Home | History | Annotate | Download | only in flatbuffers
      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