• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef OBOE_RESULT_WITH_VALUE_H
18 #define OBOE_RESULT_WITH_VALUE_H
19 
20 #include "oboe/Definitions.h"
21 #include <iostream>
22 #include <sstream>
23 
24 namespace oboe {
25 
26 /**
27  * A ResultWithValue can store both the result of an operation (either OK or an error) and a value.
28  *
29  * It has been designed for cases where the caller needs to know whether an operation succeeded and,
30  * if it did, a value which was obtained during the operation.
31  *
32  * For example, when reading from a stream the caller needs to know the result of the read operation
33  * and, if it was successful, how many frames were read. Note that ResultWithValue can be evaluated
34  * as a boolean so it's simple to check whether the result is OK.
35  *
36  * <code>
37  * ResultWithValue<int32_t> resultOfRead = myStream.read(&buffer, numFrames, timeoutNanoseconds);
38  *
39  * if (resultOfRead) {
40  *     LOGD("Frames read: %d", resultOfRead.value());
41  * } else {
42  *     LOGD("Error reading from stream: %s", resultOfRead.error());
43  * }
44  * </code>
45  */
46 template <typename T>
47 class ResultWithValue {
48 public:
49 
50     /**
51      * Construct a ResultWithValue containing an error result.
52      *
53      * @param error The error
54      */
ResultWithValue(oboe::Result error)55     ResultWithValue(oboe::Result error)
56             : mValue{}
57             , mError(error) {}
58 
59     /**
60      * Construct a ResultWithValue containing an OK result and a value.
61      *
62      * @param value the value to store
63      */
ResultWithValue(T value)64     explicit ResultWithValue(T value)
65             : mValue(value)
66             , mError(oboe::Result::OK) {}
67 
68     /**
69      * Get the result.
70      *
71      * @return the result
72      */
error()73     oboe::Result error() const {
74         return mError;
75     }
76 
77     /**
78      * Get the value
79      * @return
80      */
value()81     T value() const {
82         return mValue;
83     }
84 
85     /**
86      * @return true if OK
87      */
88     explicit operator bool() const { return mError == oboe::Result::OK; }
89 
90     /**
91      * Quick way to check for an error.
92      *
93      * The caller could write something like this:
94      * <code>
95      *     if (!result) { printf("Got error %s\n", convertToText(result.error())); }
96      * </code>
97      *
98      * @return true if an error occurred
99      */
100     bool operator !() const { return mError != oboe::Result::OK; }
101 
102     /**
103      * Implicitly convert to a Result. This enables easy comparison with Result values. Example:
104      *
105      * <code>
106      *     ResultWithValue result = openStream();
107      *     if (result == Result::ErrorNoMemory){ // tell user they're out of memory }
108      * </code>
109      */
Result()110     operator Result() const {
111         return mError;
112     }
113 
114     /**
115      * Create a ResultWithValue from a number. If the number is positive the ResultWithValue will
116      * have a result of Result::OK and the value will contain the number. If the number is negative
117      * the result will be obtained from the negative number (numeric error codes can be found in
118      * AAudio.h) and the value will be null.
119      *
120      */
createBasedOnSign(T numericResult)121     static ResultWithValue<T> createBasedOnSign(T numericResult){
122 
123         // Ensure that the type is either an integer or float
124         static_assert(std::is_arithmetic<T>::value,
125                       "createBasedOnSign can only be called for numeric types (int or float)");
126 
127         if (numericResult >= 0){
128             return ResultWithValue<T>(numericResult);
129         } else {
130             return ResultWithValue<T>(static_cast<Result>(numericResult));
131         }
132     }
133 
134 private:
135     const T             mValue;
136     const oboe::Result  mError;
137 };
138 
139 /**
140  * If the result is `OK` then return the value, otherwise return a human-readable error message.
141  */
142 template <typename T>
143 std::ostream& operator<<(std::ostream &strm, const ResultWithValue<T> &result) {
144     if (!result) {
145         strm << convertToText(result.error());
146     } else {
147         strm << result.value();
148     }
149    return strm;
150 }
151 
152 } // namespace oboe
153 
154 
155 #endif //OBOE_RESULT_WITH_VALUE_H
156