1 /*
2  * Copyright (C) 2016 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 UTIL_CHRE_OPTIONAL_IMPL_H_
18 #define UTIL_CHRE_OPTIONAL_IMPL_H_
19 
20 #include <new>
21 #include <utility>
22 
23 #include "chre/util/optional.h"
24 
25 namespace chre {
26 
27 template<typename ObjectType>
Optional(const ObjectType & object)28 Optional<ObjectType>::Optional(const ObjectType& object) {
29   new (objectAddr()) ObjectType(object);
30   mHasValue = true;
31 }
32 
33 template<typename ObjectType>
Optional(ObjectType && object)34 Optional<ObjectType>::Optional(ObjectType&& object) {
35   new (objectAddr()) ObjectType(std::move(object));
36   mHasValue = true;
37 }
38 
39 template<typename ObjectType>
~Optional()40 Optional<ObjectType>::~Optional() {
41   reset();
42 }
43 
44 template<typename ObjectType>
has_value()45 bool Optional<ObjectType>::has_value() const {
46   return mHasValue;
47 }
48 
49 template<typename ObjectType>
reset()50 void Optional<ObjectType>::reset() {
51   if (mHasValue) {
52     object().~ObjectType();
53     mHasValue = false;
54   }
55 }
56 
57 template<typename ObjectType>
value()58 ObjectType& Optional<ObjectType>::value() {
59   return object();
60 }
61 
62 template<typename ObjectType>
value()63 const ObjectType& Optional<ObjectType>::value() const {
64   return object();
65 }
66 
67 template<typename ObjectType>
68 Optional<ObjectType>& Optional<ObjectType>::operator=(ObjectType&& other) {
69   if (mHasValue) {
70     object() = std::move(other);
71   } else {
72     new (objectAddr()) ObjectType(std::move(other));
73   }
74 
75   mHasValue = true;
76   return *this;
77 }
78 
79 template<typename ObjectType>
80 Optional<ObjectType>& Optional<ObjectType>::operator=(
81     Optional<ObjectType>&& other) {
82   if (mHasValue) {
83     if (other.mHasValue) {
84       object() = std::move(other.object());
85     } else {
86       reset();
87     }
88   } else if (other.mHasValue) {
89     new (objectAddr()) ObjectType(std::move(other.object()));
90   }
91 
92   mHasValue = other.mHasValue;
93   return *this;
94 }
95 
96 template<typename ObjectType>
97 Optional<ObjectType>& Optional<ObjectType>::operator=(const ObjectType& other) {
98   if (mHasValue) {
99     object() = std::move(other);
100   } else {
101     new (objectAddr()) ObjectType(other);
102   }
103 
104   mHasValue = true;
105   return *this;
106 }
107 
108 template<typename ObjectType>
109 Optional<ObjectType>& Optional<ObjectType>::operator=(
110     const Optional<ObjectType>& other) {
111   if (mHasValue) {
112     if (other.mHasValue) {
113       object() = other.object();
114     } else {
115       reset();
116     }
117   } else if (other.mHasValue) {
118     new (objectAddr()) ObjectType(other.object());
119   }
120 
121   mHasValue = other.mHasValue;
122   return *this;
123 }
124 
125 template<typename ObjectType>
126 ObjectType& Optional<ObjectType>::operator*() {
127   return object();
128 }
129 
130 template<typename ObjectType>
131 const ObjectType& Optional<ObjectType>::operator*() const {
132   return object();
133 }
134 
135 template<typename ObjectType>
136 ObjectType *Optional<ObjectType>::operator->() {
137   return objectAddr();
138 }
139 
140 template<typename ObjectType>
141 const ObjectType *Optional<ObjectType>::operator->() const {
142   return objectAddr();
143 }
144 
145 template<typename ObjectType>
object()146 ObjectType& Optional<ObjectType>::object() {
147   return *objectAddr();
148 }
149 
150 template<typename ObjectType>
object()151 const ObjectType& Optional<ObjectType>::object() const {
152   return *objectAddr();
153 }
154 
155 template<typename ObjectType>
objectAddr()156 ObjectType *Optional<ObjectType>::objectAddr() {
157   return reinterpret_cast<ObjectType *>(&mObject);
158 }
159 
160 template<typename ObjectType>
objectAddr()161 const ObjectType *Optional<ObjectType>::objectAddr() const {
162   return reinterpret_cast<const ObjectType *>(&mObject);
163 }
164 
165 }  // namespace chre
166 
167 #endif  // UTIL_CHRE_OPTIONAL_IMPL_H_
168