Add utility classes (Slice, Fd, Status, etc)
Test: as follows
- built
- flashed
- bootedt log
- netdutils_test passes
- unsubmitted NFLogListenerTest passes
Bug: 28806131
Change-Id: I17846a0dee1edca55df10e5464e607109d978cb5
diff --git a/libnetdutils/include/netdutils/StatusOr.h b/libnetdutils/include/netdutils/StatusOr.h
new file mode 100644
index 0000000..6afbfcb
--- /dev/null
+++ b/libnetdutils/include/netdutils/StatusOr.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETUTILS_STATUSOR_H
+#define NETUTILS_STATUSOR_H
+
+#include <cassert>
+#include "netdutils/Status.h"
+
+namespace android {
+namespace netdutils {
+
+// Wrapper around a combination of Status and application value type.
+// T may be any copyable or movable type.
+template <typename T>
+class StatusOr {
+ public:
+ StatusOr() = default;
+ StatusOr(const Status status) : mStatus(status) { assert(!isOk(status)); }
+ StatusOr(const T& value) : mStatus(status::ok), mValue(value) {}
+ StatusOr(T&& value) : mStatus(status::ok), mValue(std::move(value)) {}
+
+ // Move constructor ok (if T supports move)
+ StatusOr(StatusOr&&) = default;
+ // Move assignment ok (if T supports move)
+ StatusOr& operator=(StatusOr&&) = default;
+ // Copy constructor ok (if T supports copy)
+ StatusOr(const StatusOr&) = default;
+ // Copy assignment ok (if T supports copy)
+ StatusOr& operator=(const StatusOr&) = default;
+
+ // Return const references to wrapped type
+ // It is an error to call value() when !isOk(status())
+ const T& value() const & { return mValue; }
+ const T&& value() const && { return mValue; }
+
+ // Return rvalue references to wrapped type
+ // It is an error to call value() when !isOk(status())
+ T& value() & { return mValue; }
+ T&& value() && { return mValue; }
+
+ // Return status assigned in constructor
+ const Status status() const { return mStatus; }
+
+ // Implict cast to Status
+ operator Status() const { return status(); }
+
+ private:
+ Status mStatus = status::undefined;
+ T mValue;
+};
+
+template <typename T>
+inline std::ostream& operator<<(std::ostream& os, const StatusOr<T>& s) {
+ os << "StatusOr[status: " << s.status();
+ if (isOk(s)) {
+ os << ", value: " << s.value();
+ }
+ return os << "]";
+}
+
+#define ASSIGN_OR_RETURN_IMPL(tmp, lhs, stmt) \
+ auto tmp = (stmt); \
+ RETURN_IF_NOT_OK(tmp); \
+ lhs = std::move(tmp.value());
+
+#define ASSIGN_OR_RETURN_CONCAT(line, lhs, stmt) \
+ ASSIGN_OR_RETURN_IMPL(__CONCAT(_status_or_, line), lhs, stmt)
+
+// Macro to allow exception-like handling of error return values.
+//
+// If the evaluation of stmt results in an error, return that error
+// from the current function. Otherwise, assign the result to lhs.
+//
+// This macro supports both move and copy assignment operators. lhs
+// may be either a new local variable or an existing non-const
+// variable accessible in the current scope.
+//
+// Example usage:
+// StatusOr<MyType> foo() { ... }
+//
+// ASSIGN_OR_RETURN(auto myVar, foo());
+// ASSIGN_OR_RETURN(myExistingVar, foo());
+// ASSIGN_OR_RETURN(myMemberVar, foo());
+#define ASSIGN_OR_RETURN(lhs, stmt) ASSIGN_OR_RETURN_CONCAT(__LINE__, lhs, stmt)
+
+} // namespace netdutils
+} // namespace android
+
+#endif /* NETUTILS_STATUSOR_H */