stl_emulation.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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. #ifndef FLATBUFFERS_STL_EMULATION_H_
  17. #define FLATBUFFERS_STL_EMULATION_H_
  18. // clang-format off
  19. #include "flatbuffers/base.h"
  20. #include <string>
  21. #include <type_traits>
  22. #include <vector>
  23. #include <memory>
  24. #include <limits>
  25. // Detect C++17 compatible compiler.
  26. // __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
  27. #if defined(FLATBUFFERS_USE_STD_OPTIONAL) \
  28. || (defined(__cplusplus) && __cplusplus >= 201703L) \
  29. || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
  30. #include <optional>
  31. #ifndef FLATBUFFERS_USE_STD_OPTIONAL
  32. #define FLATBUFFERS_USE_STD_OPTIONAL
  33. #endif
  34. #endif
  35. #if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
  36. #define FLATBUFFERS_CPP98_STL
  37. #endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
  38. #if defined(FLATBUFFERS_CPP98_STL)
  39. #include <cctype>
  40. #endif // defined(FLATBUFFERS_CPP98_STL)
  41. // This header provides backwards compatibility for C++98 STLs like stlport.
  42. namespace flatbuffers {
  43. // Retrieve ::back() from a string in a way that is compatible with pre C++11
  44. // STLs (e.g stlport).
  45. inline char& string_back(std::string &value) {
  46. return value[value.length() - 1];
  47. }
  48. inline char string_back(const std::string &value) {
  49. return value[value.length() - 1];
  50. }
  51. // Helper method that retrieves ::data() from a vector in a way that is
  52. // compatible with pre C++11 STLs (e.g stlport).
  53. template <typename T> inline T *vector_data(std::vector<T> &vector) {
  54. // In some debug environments, operator[] does bounds checking, so &vector[0]
  55. // can't be used.
  56. return vector.empty() ? nullptr : &vector[0];
  57. }
  58. template <typename T> inline const T *vector_data(
  59. const std::vector<T> &vector) {
  60. return vector.empty() ? nullptr : &vector[0];
  61. }
  62. template <typename T, typename V>
  63. inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
  64. #if defined(FLATBUFFERS_CPP98_STL)
  65. vector->push_back(data);
  66. #else
  67. vector->emplace_back(std::forward<V>(data));
  68. #endif // defined(FLATBUFFERS_CPP98_STL)
  69. }
  70. #ifndef FLATBUFFERS_CPP98_STL
  71. #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
  72. template <typename T>
  73. using numeric_limits = std::numeric_limits<T>;
  74. #else
  75. template <typename T> class numeric_limits :
  76. public std::numeric_limits<T> {};
  77. #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
  78. #else
  79. template <typename T> class numeric_limits :
  80. public std::numeric_limits<T> {
  81. public:
  82. // Android NDK fix.
  83. static T lowest() {
  84. return std::numeric_limits<T>::min();
  85. }
  86. };
  87. template <> class numeric_limits<float> :
  88. public std::numeric_limits<float> {
  89. public:
  90. static float lowest() { return -FLT_MAX; }
  91. };
  92. template <> class numeric_limits<double> :
  93. public std::numeric_limits<double> {
  94. public:
  95. static double lowest() { return -DBL_MAX; }
  96. };
  97. template <> class numeric_limits<unsigned long long> {
  98. public:
  99. static unsigned long long min() { return 0ULL; }
  100. static unsigned long long max() { return ~0ULL; }
  101. static unsigned long long lowest() {
  102. return numeric_limits<unsigned long long>::min();
  103. }
  104. };
  105. template <> class numeric_limits<long long> {
  106. public:
  107. static long long min() {
  108. return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
  109. }
  110. static long long max() {
  111. return static_cast<long long>(
  112. (1ULL << ((sizeof(long long) << 3) - 1)) - 1);
  113. }
  114. static long long lowest() {
  115. return numeric_limits<long long>::min();
  116. }
  117. };
  118. #endif // FLATBUFFERS_CPP98_STL
  119. #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
  120. #ifndef FLATBUFFERS_CPP98_STL
  121. template <typename T> using is_scalar = std::is_scalar<T>;
  122. template <typename T, typename U> using is_same = std::is_same<T,U>;
  123. template <typename T> using is_floating_point = std::is_floating_point<T>;
  124. template <typename T> using is_unsigned = std::is_unsigned<T>;
  125. template <typename T> using is_enum = std::is_enum<T>;
  126. template <typename T> using make_unsigned = std::make_unsigned<T>;
  127. template<bool B, class T, class F>
  128. using conditional = std::conditional<B, T, F>;
  129. template<class T, T v>
  130. using integral_constant = std::integral_constant<T, v>;
  131. #else
  132. // Map C++ TR1 templates defined by stlport.
  133. template <typename T> using is_scalar = std::tr1::is_scalar<T>;
  134. template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
  135. template <typename T> using is_floating_point =
  136. std::tr1::is_floating_point<T>;
  137. template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
  138. template <typename T> using is_enum = std::tr1::is_enum<T>;
  139. // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
  140. template<typename T> struct make_unsigned {
  141. static_assert(is_unsigned<T>::value, "Specialization not implemented!");
  142. using type = T;
  143. };
  144. template<> struct make_unsigned<char> { using type = unsigned char; };
  145. template<> struct make_unsigned<short> { using type = unsigned short; };
  146. template<> struct make_unsigned<int> { using type = unsigned int; };
  147. template<> struct make_unsigned<long> { using type = unsigned long; };
  148. template<>
  149. struct make_unsigned<long long> { using type = unsigned long long; };
  150. template<bool B, class T, class F>
  151. using conditional = std::tr1::conditional<B, T, F>;
  152. template<class T, T v>
  153. using integral_constant = std::tr1::integral_constant<T, v>;
  154. #endif // !FLATBUFFERS_CPP98_STL
  155. #else
  156. // MSVC 2010 doesn't support C++11 aliases.
  157. template <typename T> struct is_scalar : public std::is_scalar<T> {};
  158. template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
  159. template <typename T> struct is_floating_point :
  160. public std::is_floating_point<T> {};
  161. template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
  162. template <typename T> struct is_enum : public std::is_enum<T> {};
  163. template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
  164. template<bool B, class T, class F>
  165. struct conditional : public std::conditional<B, T, F> {};
  166. template<class T, T v>
  167. struct integral_constant : public std::integral_constant<T, v> {};
  168. #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
  169. #ifndef FLATBUFFERS_CPP98_STL
  170. #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
  171. template <class T> using unique_ptr = std::unique_ptr<T>;
  172. #else
  173. // MSVC 2010 doesn't support C++11 aliases.
  174. // We're manually "aliasing" the class here as we want to bring unique_ptr
  175. // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
  176. // namespace we have a completely independent implementation (see below)
  177. // for C++98 STL implementations.
  178. template <class T> class unique_ptr : public std::unique_ptr<T> {
  179. public:
  180. unique_ptr() {}
  181. explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
  182. unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
  183. unique_ptr(unique_ptr&& u) { *this = std::move(u); }
  184. unique_ptr& operator=(std::unique_ptr<T>&& u) {
  185. std::unique_ptr<T>::reset(u.release());
  186. return *this;
  187. }
  188. unique_ptr& operator=(unique_ptr&& u) {
  189. std::unique_ptr<T>::reset(u.release());
  190. return *this;
  191. }
  192. unique_ptr& operator=(T* p) {
  193. return std::unique_ptr<T>::operator=(p);
  194. }
  195. };
  196. #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
  197. #else
  198. // Very limited implementation of unique_ptr.
  199. // This is provided simply to allow the C++ code generated from the default
  200. // settings to function in C++98 environments with no modifications.
  201. template <class T> class unique_ptr {
  202. public:
  203. typedef T element_type;
  204. unique_ptr() : ptr_(nullptr) {}
  205. explicit unique_ptr(T* p) : ptr_(p) {}
  206. unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
  207. unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
  208. reset(const_cast<unique_ptr*>(&u)->release());
  209. }
  210. ~unique_ptr() { reset(); }
  211. unique_ptr& operator=(const unique_ptr& u) {
  212. reset(const_cast<unique_ptr*>(&u)->release());
  213. return *this;
  214. }
  215. unique_ptr& operator=(unique_ptr&& u) {
  216. reset(u.release());
  217. return *this;
  218. }
  219. unique_ptr& operator=(T* p) {
  220. reset(p);
  221. return *this;
  222. }
  223. const T& operator*() const { return *ptr_; }
  224. T* operator->() const { return ptr_; }
  225. T* get() const noexcept { return ptr_; }
  226. explicit operator bool() const { return ptr_ != nullptr; }
  227. // modifiers
  228. T* release() {
  229. T* value = ptr_;
  230. ptr_ = nullptr;
  231. return value;
  232. }
  233. void reset(T* p = nullptr) {
  234. T* value = ptr_;
  235. ptr_ = p;
  236. if (value) delete value;
  237. }
  238. void swap(unique_ptr& u) {
  239. T* temp_ptr = ptr_;
  240. ptr_ = u.ptr_;
  241. u.ptr_ = temp_ptr;
  242. }
  243. private:
  244. T* ptr_;
  245. };
  246. template <class T> bool operator==(const unique_ptr<T>& x,
  247. const unique_ptr<T>& y) {
  248. return x.get() == y.get();
  249. }
  250. template <class T, class D> bool operator==(const unique_ptr<T>& x,
  251. const D* y) {
  252. return static_cast<D*>(x.get()) == y;
  253. }
  254. template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
  255. return reinterpret_cast<intptr_t>(x.get()) == y;
  256. }
  257. template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
  258. return !!x;
  259. }
  260. template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
  261. return !!x;
  262. }
  263. template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
  264. return !x;
  265. }
  266. template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
  267. return !x;
  268. }
  269. #endif // !FLATBUFFERS_CPP98_STL
  270. #ifdef FLATBUFFERS_USE_STD_OPTIONAL
  271. template<class T>
  272. using Optional = std::optional<T>;
  273. using nullopt_t = std::nullopt_t;
  274. inline constexpr nullopt_t nullopt = std::nullopt;
  275. #else
  276. // Limited implementation of Optional<T> type for a scalar T.
  277. // This implementation limited by trivial types compatible with
  278. // std::is_arithmetic<T> or std::is_enum<T> type traits.
  279. // A tag to indicate an empty flatbuffers::optional<T>.
  280. struct nullopt_t {
  281. explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {}
  282. };
  283. #if defined(FLATBUFFERS_CONSTEXPR_DEFINED)
  284. namespace internal {
  285. template <class> struct nullopt_holder {
  286. static constexpr nullopt_t instance_ = nullopt_t(0);
  287. };
  288. template<class Dummy>
  289. constexpr nullopt_t nullopt_holder<Dummy>::instance_;
  290. }
  291. static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
  292. #else
  293. namespace internal {
  294. template <class> struct nullopt_holder {
  295. static const nullopt_t instance_;
  296. };
  297. template<class Dummy>
  298. const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0);
  299. }
  300. static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
  301. #endif
  302. template<class T>
  303. class Optional FLATBUFFERS_FINAL_CLASS {
  304. // Non-scalar 'T' would extremely complicated Optional<T>.
  305. // Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
  306. // isn't implemented.
  307. static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T");
  308. public:
  309. ~Optional() {}
  310. FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT
  311. : value_(), has_value_(false) {}
  312. FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT
  313. : value_(), has_value_(false) {}
  314. FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT
  315. : value_(val), has_value_(true) {}
  316. FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT
  317. : value_(other.value_), has_value_(other.has_value_) {}
  318. FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT {
  319. value_ = other.value_;
  320. has_value_ = other.has_value_;
  321. return *this;
  322. }
  323. FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT {
  324. value_ = T();
  325. has_value_ = false;
  326. return *this;
  327. }
  328. FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT {
  329. value_ = val;
  330. has_value_ = true;
  331. return *this;
  332. }
  333. void reset() FLATBUFFERS_NOEXCEPT {
  334. *this = nullopt;
  335. }
  336. void swap(Optional &other) FLATBUFFERS_NOEXCEPT {
  337. std::swap(value_, other.value_);
  338. std::swap(has_value_, other.has_value_);
  339. }
  340. FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT {
  341. return has_value_;
  342. }
  343. FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT {
  344. return has_value_;
  345. }
  346. FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT {
  347. return value_;
  348. }
  349. const T& value() const {
  350. FLATBUFFERS_ASSERT(has_value());
  351. return value_;
  352. }
  353. T value_or(T default_value) const FLATBUFFERS_NOEXCEPT {
  354. return has_value() ? value_ : default_value;
  355. }
  356. private:
  357. T value_;
  358. bool has_value_;
  359. };
  360. template<class T>
  361. FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT {
  362. return !opt;
  363. }
  364. template<class T>
  365. FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT {
  366. return !opt;
  367. }
  368. template<class T, class U>
  369. FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT {
  370. return static_cast<bool>(lhs) && (*lhs == rhs);
  371. }
  372. template<class T, class U>
  373. FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
  374. return static_cast<bool>(rhs) && (lhs == *rhs);
  375. }
  376. template<class T, class U>
  377. FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
  378. return static_cast<bool>(lhs) != static_cast<bool>(rhs)
  379. ? false
  380. : !static_cast<bool>(lhs) ? false : (*lhs == *rhs);
  381. }
  382. #endif // FLATBUFFERS_USE_STD_OPTIONAL
  383. } // namespace flatbuffers
  384. #endif // FLATBUFFERS_STL_EMULATION_H_