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. 35namespace flatbuffers { 36 37// Retrieve ::back() from a string in a way that is compatible with pre C++11 38// STLs (e.g stlport). 39inline 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). 45template <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 51template <typename T> inline const T *vector_data( 52 const std::vector<T> &vector) { 53 return &(*vector.begin()); 54} 55 56template <typename T, typename V> 57inline 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: 79 static unsigned long long min() { return 0ULL; } 80 static unsigned long long max() { return ~0ULL; } 81 }; 82 83 template <> class numeric_limits<long long> { 84 public: 85 static long long min() { 86 return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1)); 87 } 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: 129 unique_ptr() {} 130 explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {} 131 unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(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 154 unique_ptr() : ptr_(nullptr) {} 155 explicit unique_ptr(T* p) : ptr_(p) {} 156 unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); } 157 unique_ptr(const unique_ptr& u) : ptr_(nullptr) { 158 reset(const_cast<unique_ptr*>(&u)->release()); 159 } 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_; } 179 T* get() const noexcept { return ptr_; } 180 explicit operator bool() const { return ptr_ != nullptr; } 181 182 // modifiers 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 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