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