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