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 // clang-format off 21 22 #include <string> 23 #include <type_traits> 24 #include <vector> 25 #include <memory> 26 #include <limits> 27 28 #if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) 29 #define FLATBUFFERS_CPP98_STL 30 #endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) 31 32 #if defined(FLATBUFFERS_CPP98_STL) 33 #include <cctype> 34 #endif // defined(FLATBUFFERS_CPP98_STL) 35 36 // Check if we can use template aliases 37 // Not possible if Microsoft Compiler before 2012 38 // Possible is the language feature __cpp_alias_templates is defined well 39 // Or possible if the C++ std is C+11 or newer 40 #if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ 41 || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ 42 || (defined(__cplusplus) && __cplusplus >= 201103L) 43 #define FLATBUFFERS_TEMPLATES_ALIASES 44 #endif 45 46 // This header provides backwards compatibility for C++98 STLs like stlport. 47 namespace flatbuffers { 48 49 // Retrieve ::back() from a string in a way that is compatible with pre C++11 50 // STLs (e.g stlport). 51 inline char& string_back(std::string &value) { 52 return value[value.length() - 1]; 53 } 54 55 inline char string_back(const std::string &value) { 56 return value[value.length() - 1]; 57 } 58 59 // Helper method that retrieves ::data() from a vector in a way that is 60 // compatible with pre C++11 STLs (e.g stlport). 61 template <typename T> inline T *vector_data(std::vector<T> &vector) { 62 // In some debug environments, operator[] does bounds checking, so &vector[0] 63 // can't be used. 64 return vector.empty() ? nullptr : &vector[0]; 65 } 66 67 template <typename T> inline const T *vector_data( 68 const std::vector<T> &vector) { 69 return vector.empty() ? nullptr : &vector[0]; 70 } 71 72 template <typename T, typename V> 73 inline void vector_emplace_back(std::vector<T> *vector, V &&data) { 74 #if defined(FLATBUFFERS_CPP98_STL) 75 vector->push_back(data); 76 #else 77 vector->emplace_back(std::forward<V>(data)); 78 #endif // defined(FLATBUFFERS_CPP98_STL) 79 } 80 81 #ifndef FLATBUFFERS_CPP98_STL 82 #if defined(FLATBUFFERS_TEMPLATES_ALIASES) 83 template <typename T> 84 using numeric_limits = std::numeric_limits<T>; 85 #else 86 template <typename T> class numeric_limits : 87 public std::numeric_limits<T> {}; 88 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) 89 #else 90 template <typename T> class numeric_limits : 91 public std::numeric_limits<T> { 92 public: 93 // Android NDK fix. 94 static T lowest() { 95 return std::numeric_limits<T>::min(); 96 } 97 }; 98 99 template <> class numeric_limits<float> : 100 public std::numeric_limits<float> { 101 public: 102 static float lowest() { return -FLT_MAX; } 103 }; 104 105 template <> class numeric_limits<double> : 106 public std::numeric_limits<double> { 107 public: 108 static double lowest() { return -DBL_MAX; } 109 }; 110 111 template <> class numeric_limits<unsigned long long> { 112 public: 113 static unsigned long long min() { return 0ULL; } 114 static unsigned long long max() { return ~0ULL; } 115 static unsigned long long lowest() { 116 return numeric_limits<unsigned long long>::min(); 117 } 118 }; 119 120 template <> class numeric_limits<long long> { 121 public: 122 static long long min() { 123 return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1)); 124 } 125 static long long max() { 126 return static_cast<long long>( 127 (1ULL << ((sizeof(long long) << 3) - 1)) - 1); 128 } 129 static long long lowest() { 130 return numeric_limits<long long>::min(); 131 } 132 }; 133 #endif // FLATBUFFERS_CPP98_STL 134 135 #if defined(FLATBUFFERS_TEMPLATES_ALIASES) 136 #ifndef FLATBUFFERS_CPP98_STL 137 template <typename T> using is_scalar = std::is_scalar<T>; 138 template <typename T, typename U> using is_same = std::is_same<T,U>; 139 template <typename T> using is_floating_point = std::is_floating_point<T>; 140 template <typename T> using is_unsigned = std::is_unsigned<T>; 141 template <typename T> using make_unsigned = std::make_unsigned<T>; 142 #else 143 // Map C++ TR1 templates defined by stlport. 144 template <typename T> using is_scalar = std::tr1::is_scalar<T>; 145 template <typename T, typename U> using is_same = std::tr1::is_same<T,U>; 146 template <typename T> using is_floating_point = 147 std::tr1::is_floating_point<T>; 148 template <typename T> using is_unsigned = std::tr1::is_unsigned<T>; 149 // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned. 150 template<typename T> struct make_unsigned { 151 static_assert(is_unsigned<T>::value, "Specialization not implemented!"); 152 using type = T; 153 }; 154 template<> struct make_unsigned<char> { using type = unsigned char; }; 155 template<> struct make_unsigned<short> { using type = unsigned short; }; 156 template<> struct make_unsigned<int> { using type = unsigned int; }; 157 template<> struct make_unsigned<long> { using type = unsigned long; }; 158 template<> 159 struct make_unsigned<long long> { using type = unsigned long long; }; 160 #endif // !FLATBUFFERS_CPP98_STL 161 #else 162 // MSVC 2010 doesn't support C++11 aliases. 163 template <typename T> struct is_scalar : public std::is_scalar<T> {}; 164 template <typename T, typename U> struct is_same : public std::is_same<T,U> {}; 165 template <typename T> struct is_floating_point : 166 public std::is_floating_point<T> {}; 167 template <typename T> struct is_unsigned : public std::is_unsigned<T> {}; 168 template <typename T> struct make_unsigned : public std::make_unsigned<T> {}; 169 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) 170 171 #ifndef FLATBUFFERS_CPP98_STL 172 #if defined(FLATBUFFERS_TEMPLATES_ALIASES) 173 template <class T> using unique_ptr = std::unique_ptr<T>; 174 #else 175 // MSVC 2010 doesn't support C++11 aliases. 176 // We're manually "aliasing" the class here as we want to bring unique_ptr 177 // into the flatbuffers namespace. We have unique_ptr in the flatbuffers 178 // namespace we have a completely independent implemenation (see below) 179 // for C++98 STL implementations. 180 template <class T> class unique_ptr : public std::unique_ptr<T> { 181 public: 182 unique_ptr() {} 183 explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {} 184 unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); } 185 unique_ptr(unique_ptr&& u) { *this = std::move(u); } 186 unique_ptr& operator=(std::unique_ptr<T>&& u) { 187 std::unique_ptr<T>::reset(u.release()); 188 return *this; 189 } 190 unique_ptr& operator=(unique_ptr&& u) { 191 std::unique_ptr<T>::reset(u.release()); 192 return *this; 193 } 194 unique_ptr& operator=(T* p) { 195 return std::unique_ptr<T>::operator=(p); 196 } 197 }; 198 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) 199 #else 200 // Very limited implementation of unique_ptr. 201 // This is provided simply to allow the C++ code generated from the default 202 // settings to function in C++98 environments with no modifications. 203 template <class T> class unique_ptr { 204 public: 205 typedef T element_type; 206 207 unique_ptr() : ptr_(nullptr) {} 208 explicit unique_ptr(T* p) : ptr_(p) {} 209 unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); } 210 unique_ptr(const unique_ptr& u) : ptr_(nullptr) { 211 reset(const_cast<unique_ptr*>(&u)->release()); 212 } 213 ~unique_ptr() { reset(); } 214 215 unique_ptr& operator=(const unique_ptr& u) { 216 reset(const_cast<unique_ptr*>(&u)->release()); 217 return *this; 218 } 219 220 unique_ptr& operator=(unique_ptr&& u) { 221 reset(u.release()); 222 return *this; 223 } 224 225 unique_ptr& operator=(T* p) { 226 reset(p); 227 return *this; 228 } 229 230 const T& operator*() const { return *ptr_; } 231 T* operator->() const { return ptr_; } 232 T* get() const noexcept { return ptr_; } 233 explicit operator bool() const { return ptr_ != nullptr; } 234 235 // modifiers 236 T* release() { 237 T* value = ptr_; 238 ptr_ = nullptr; 239 return value; 240 } 241 242 void reset(T* p = nullptr) { 243 T* value = ptr_; 244 ptr_ = p; 245 if (value) delete value; 246 } 247 248 void swap(unique_ptr& u) { 249 T* temp_ptr = ptr_; 250 ptr_ = u.ptr_; 251 u.ptr_ = temp_ptr; 252 } 253 254 private: 255 T* ptr_; 256 }; 257 258 template <class T> bool operator==(const unique_ptr<T>& x, 259 const unique_ptr<T>& y) { 260 return x.get() == y.get(); 261 } 262 263 template <class T, class D> bool operator==(const unique_ptr<T>& x, 264 const D* y) { 265 return static_cast<D*>(x.get()) == y; 266 } 267 268 template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) { 269 return reinterpret_cast<intptr_t>(x.get()) == y; 270 } 271 #endif // !FLATBUFFERS_CPP98_STL 272 273 } // namespace flatbuffers 274 275 #endif // FLATBUFFERS_STL_EMULATION_H_ 276