1 /*
2 * Copyright 2017 Google Inc. All rights reserved.
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 FLATBUFFERS_STL_EMULATION_H_
18 #define FLATBUFFERS_STL_EMULATION_H_
19
20 #include <string>
21 #include <type_traits>
22 #include <vector>
23 #include <memory>
24 #include <limits>
25
26 #if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
27 #define FLATBUFFERS_CPP98_STL
28 #endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
29
30 #if defined(FLATBUFFERS_CPP98_STL)
31 #include <cctype>
32 #endif // defined(FLATBUFFERS_CPP98_STL)
33
34 // This header provides backwards compatibility for C++98 STLs like stlport.
35 namespace flatbuffers {
36
37 // Retrieve ::back() from a string in a way that is compatible with pre C++11
38 // STLs (e.g stlport).
string_back(const std::string & value)39 inline char string_back(const std::string &value) {
40 return value[value.length() - 1];
41 }
42
43 // Helper method that retrieves ::data() from a vector in a way that is
44 // compatible with pre C++11 STLs (e.g stlport).
vector_data(std::vector<T> & vector)45 template <typename T> inline T *vector_data(std::vector<T> &vector) {
46 // In some debug environments, operator[] does bounds checking, so &vector[0]
47 // can't be used.
48 return &(*vector.begin());
49 }
50
vector_data(const std::vector<T> & vector)51 template <typename T> inline const T *vector_data(
52 const std::vector<T> &vector) {
53 return &(*vector.begin());
54 }
55
56 template <typename T, typename V>
vector_emplace_back(std::vector<T> * vector,V && data)57 inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
58 #if defined(FLATBUFFERS_CPP98_STL)
59 vector->push_back(data);
60 #else
61 vector->emplace_back(std::forward<V>(data));
62 #endif // defined(FLATBUFFERS_CPP98_STL)
63 }
64
65 #ifndef FLATBUFFERS_CPP98_STL
66 #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
67 template <typename T>
68 using numeric_limits = std::numeric_limits<T>;
69 #else
70 template <typename T> class numeric_limits :
71 public std::numeric_limits<T> {};
72 #endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
73 #else
74 template <typename T> class numeric_limits :
75 public std::numeric_limits<T> {};
76
77 template <> class numeric_limits<unsigned long long> {
78 public:
min()79 static unsigned long long min() { return 0ULL; }
max()80 static unsigned long long max() { return ~0ULL; }
81 };
82
83 template <> class numeric_limits<long long> {
84 public:
min()85 static long long min() {
86 return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
87 }
max()88 static long long max() {
89 return static_cast<long long>(
90 (1ULL << ((sizeof(long long) << 3) - 1)) - 1);
91 }
92 };
93 #endif // FLATBUFFERS_CPP98_STL
94
95 #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
96 #ifndef FLATBUFFERS_CPP98_STL
97 template <typename T> using is_scalar = std::is_scalar<T>;
98 template <typename T, typename U> using is_same = std::is_same<T,U>;
99 template <typename T> using is_floating_point = std::is_floating_point<T>;
100 template <typename T> using is_unsigned = std::is_unsigned<T>;
101 #else
102 // Map C++ TR1 templates defined by stlport.
103 template <typename T> using is_scalar = std::tr1::is_scalar<T>;
104 template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
105 template <typename T> using is_floating_point =
106 std::tr1::is_floating_point<T>;
107 template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
108 #endif // !FLATBUFFERS_CPP98_STL
109 #else
110 // MSVC 2010 doesn't support C++11 aliases.
111 template <typename T> struct is_scalar : public std::is_scalar<T> {};
112 template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
113 template <typename T> struct is_floating_point :
114 public std::is_floating_point<T> {};
115 template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
116 #endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
117
118 #ifndef FLATBUFFERS_CPP98_STL
119 #if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
120 template <class T> using unique_ptr = std::unique_ptr<T>;
121 #else
122 // MSVC 2010 doesn't support C++11 aliases.
123 // We're manually "aliasing" the class here as we want to bring unique_ptr
124 // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
125 // namespace we have a completely independent implemenation (see below)
126 // for C++98 STL implementations.
127 template <class T> class unique_ptr : public std::unique_ptr<T> {
128 public:
unique_ptr()129 unique_ptr() {}
unique_ptr(T * p)130 explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
unique_ptr(std::unique_ptr<T> && u)131 unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
unique_ptr(unique_ptr && u)132 unique_ptr(unique_ptr&& u) { *this = std::move(u); }
133 unique_ptr& operator=(std::unique_ptr<T>&& u) {
134 std::unique_ptr<T>::reset(u.release());
135 return *this;
136 }
137 unique_ptr& operator=(unique_ptr&& u) {
138 std::unique_ptr<T>::reset(u.release());
139 return *this;
140 }
141 unique_ptr& operator=(T* p) {
142 return std::unique_ptr<T>::operator=(p);
143 }
144 };
145 #endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
146 #else
147 // Very limited implementation of unique_ptr.
148 // This is provided simply to allow the C++ code generated from the default
149 // settings to function in C++98 environments with no modifications.
150 template <class T> class unique_ptr {
151 public:
152 typedef T element_type;
153
unique_ptr()154 unique_ptr() : ptr_(nullptr) {}
unique_ptr(T * p)155 explicit unique_ptr(T* p) : ptr_(p) {}
unique_ptr(unique_ptr && u)156 unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
unique_ptr(const unique_ptr & u)157 unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
158 reset(const_cast<unique_ptr*>(&u)->release());
159 }
~unique_ptr()160 ~unique_ptr() { reset(); }
161
162 unique_ptr& operator=(const unique_ptr& u) {
163 reset(const_cast<unique_ptr*>(&u)->release());
164 return *this;
165 }
166
167 unique_ptr& operator=(unique_ptr&& u) {
168 reset(u.release());
169 return *this;
170 }
171
172 unique_ptr& operator=(T* p) {
173 reset(p);
174 return *this;
175 }
176
177 const T& operator*() const { return *ptr_; }
178 T* operator->() const { return ptr_; }
get()179 T* get() const noexcept { return ptr_; }
180 explicit operator bool() const { return ptr_ != nullptr; }
181
182 // modifiers
release()183 T* release() {
184 T* value = ptr_;
185 ptr_ = nullptr;
186 return value;
187 }
188
189 void reset(T* p = nullptr) {
190 T* value = ptr_;
191 ptr_ = p;
192 if (value) delete value;
193 }
194
swap(unique_ptr & u)195 void swap(unique_ptr& u) {
196 T* temp_ptr = ptr_;
197 ptr_ = u.ptr_;
198 u.ptr_ = temp_ptr;
199 }
200
201 private:
202 T* ptr_;
203 };
204
205 template <class T> bool operator==(const unique_ptr<T>& x,
206 const unique_ptr<T>& y) {
207 return x.get() == y.get();
208 }
209
210 template <class T, class D> bool operator==(const unique_ptr<T>& x,
211 const D* y) {
212 return static_cast<D*>(x.get()) == y;
213 }
214
215 template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
216 return reinterpret_cast<intptr_t>(x.get()) == y;
217 }
218 #endif // !FLATBUFFERS_CPP98_STL
219
220 } // namespace flatbuffers
221
222 #endif // FLATBUFFERS_STL_EMULATION_H_
223