fmtlib provides compile time checking of format strings that we're not
currently using. This change makes Errorf() and ErrnoErrorf() into
macros such that we can take advantage of this capability.
Test: build successfully normally
Test: fail the build if using an invalid format string
Change-Id: Icb8ba8cb973bbd1fa4755a62e7598bdbb0113757
Init had some pretty horrid Error() << StringPrintf(...) calls that
are all much better replaced by Errorf(...) now.
Test: build, check that keyword_map errors look correct
Change-Id: I572588c7541b928c72ae1bf140b814acdef1cd60
Now that Result<T> is actually expected<T, ...>, and the expected
proposal states expected<void, ...> as the way to indicate an expected
object that returns either successfully with no object or an error,
let's move init's Result<Success> to the preferred Result<void>.
Bug: 132145659
Test: boot, init unit tests
Change-Id: Ib2f98396d8e6e274f95a496fcdfd8341f77585ee
The Result, Error, ErrnoError are quite generic. Moving them from init
to libbase so that they can be used from other places.
Bug: 132145659
Test: libbase_test
Change-Id: Id774a587f74380fadd7a0fc88c0aa892c3d9a489
Android-base has an implementation of the future std::expected<>.
This provides the same baseline functionality as Result<>, so use it
instead of our own version.
Bug: 132145659
Test: boot, init unit tests
Change-Id: I11e61bcb5719b262a6420483ed51a762826a9e23
It's better to either check these results or explicitly ignore them.
Only a few callers weren't already doing this, so it's relatively
trivial to enforce.
Test: build
Change-Id: I44cdc342e46128f66cac914aaa0b9b4559cacd8c
Result<T> currently has two problems,
1) A failing Result<T> cannot be easily constructed from a Result<U>'s
error.
2) errno is lost when passing .error() through multiple Result<T>'s
This change fixes both problems having Result<T>::error() return a
ResultError class that contains the std::string error message and int
errno.
It additionally has ostream operators to continue to allow printing
the error string directly to an ostream and also to pass the errno
through to another Result<T> class via Error() creation.
Lastly, it provides a new constructor for Result<T> for ResultError,
such that a Result<T> can be constructed from Result<U>::error().
Test: boot bullhead, init unit tests
Change-Id: Id9614b727cdabd2f5498b0da0e598e9aff7d9ae0
init tries to propagate error information up to build context before
logging errors. This is a good thing, however too often init has the
overly verbose paradigm for error handling, below:
bool CalculateResult(const T& input, U* output, std::string* err)
bool CalculateAndUseResult(const T& input, std::string* err) {
U output;
std::string calculate_result_err;
if (!CalculateResult(input, &output, &calculate_result_err)) {
*err = "CalculateResult " + input + " failed: " +
calculate_result_err;
return false;
}
UseResult(output);
return true;
}
Even more common are functions that return only true/false but also
require passing a std::string* err in order to see the error message.
This change introduces a Result<T> that is use to either hold a
successful return value of type T or to hold an error message as a
std::string. If the functional only returns success or a failure with
an error message, Result<Success> may be used. The classes Error and
ErrnoError are used to indicate a failed Result<T>.
A successful Result<T> is constructed implicitly from any type that
can be implicitly converted to T or from the constructor arguments for
T. This allows you to return a type T directly from a function that
returns Result<T>.
Error and ErrnoError are used to construct a Result<T> has
failed. Each of these classes take an ostream as an input and are
implicitly cast to a Result<T> containing that failure. ErrnoError()
additionally appends ": " + strerror(errno) to the end of the failure
string to aid in interacting with C APIs.
The end result is that the above code snippet is turned into the much
clearer example below:
Result<U> CalculateResult(const T& input);
Result<Success> CalculateAndUseResult(const T& input) {
auto output = CalculateResult(input);
if (!output) {
return Error() << "CalculateResult " << input << " failed: "
<< output.error();
}
UseResult(*output);
return Success();
}
This change also makes this conversion for some of the util.cpp
functions that used the old paradigm.
Test: boot bullhead, init unit tests
Merged-In: I1e7d3a8820a79362245041251057fbeed2f7979b
Change-Id: I1e7d3a8820a79362245041251057fbeed2f7979b