ChaiScript / ChaiScript
1
// This file is distributed under the BSD License.
2
// See "license.txt" for details.
3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5
// http://www.chaiscript.com
6

7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9

10

11
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
12
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
13

14
#include <memory>
15
#include <type_traits>
16

17
#include "boxed_value.hpp"
18
#include "type_info.hpp"
19

20

21
namespace chaiscript 
22
{
23
  class Type_Conversions_State;
24

25
  namespace detail
26
  {
27
    // Cast_Helper_Inner helper classes
28

29
    template<typename T>
30 1
      constexpr T* throw_if_null(T *t)
31
      {
32 1
        if (t) { return t; }
33 1
        throw std::runtime_error("Attempted to dereference null Boxed_Value");
34
      }
35

36
    template<typename T>
37 1
    static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
38 1
      if (ob.get_type_info() == ti) {
39 1
        return ptr;
40
      } else {
41 1
        throw chaiscript::detail::exception::bad_any_cast();
42
      }
43
    }
44

45
    template<typename T>
46 1
    static T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
47 1
      if (!ob.is_const() && ob.get_type_info() == ti) {
48 1
        return ptr;
49
      } else {
50 1
        throw chaiscript::detail::exception::bad_any_cast();
51
      }
52
    }
53

54

55
    template<typename T>
56 1
    static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
57 1
      if (ob.get_type_info().bare_equal_type_info(ti)) {
58 1
        return throw_if_null(ptr);
59
      } else {
60 1
        throw chaiscript::detail::exception::bad_any_cast();
61
      }
62
    }
63

64
    template<typename T>
65 1
    static T *verify_type(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
66 1
      if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) {
67 1
        return throw_if_null(ptr);
68
      } else {
69 1
        throw chaiscript::detail::exception::bad_any_cast();
70
      }
71
    }
72

73
    /// Generic Cast_Helper_Inner, for casting to any type
74
    template<typename Result>
75
      struct Cast_Helper_Inner
76
      {
77 1
        static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
78
        {
79 1
          return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
80
        }
81
      };
82

83
    template<typename Result>
84
      struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
85
      {
86
      };
87

88

89
    /// Cast_Helper_Inner for casting to a const * type
90
    template<typename Result>
91
      struct Cast_Helper_Inner<const Result *>
92
      {
93 1
        static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
94
        {
95 1
          return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
96
        }
97
      };
98

99
    /// Cast_Helper_Inner for casting to a * type
100
    template<typename Result>
101
      struct Cast_Helper_Inner<Result *>
102
      {
103 1
        static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
104
        {
105 1
          return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
106
        }
107
      };
108

109
    template<typename Result>
110
    struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
111
    {
112
    };
113

114
    template<typename Result>
115
    struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
116
    {
117
    };
118

119

120
    /// Cast_Helper_Inner for casting to a & type
121
    template<typename Result>
122
      struct Cast_Helper_Inner<const Result &>
123
      {
124 1
        static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
125
        {
126 1
          return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
127
        }
128
      };
129

130

131

132
    /// Cast_Helper_Inner for casting to a & type
133
    template<typename Result>
134
      struct Cast_Helper_Inner<Result &>
135
      {
136 1
        static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
137
        {
138 1
          return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
139
        }
140
      };
141

142
    /// Cast_Helper_Inner for casting to a && type
143
    template<typename Result>
144
      struct Cast_Helper_Inner<Result &&>
145
      {
146 0
        static Result&& cast(const Boxed_Value &ob, const Type_Conversions_State *)
147
        {
148 0
          return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
149
        }
150
      };
151

152
    /// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
153
    /// \todo Fix the fact that this has to be in a shared_ptr for now
154
    template<typename Result>
155
      struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
156
      {
157 1
        static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *)
158
        {
159 1
          return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
160
        }
161
      };
162

163
    /// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
164
    /// \todo Fix the fact that this has to be in a shared_ptr for now
165
    template<typename Result>
166
      struct Cast_Helper_Inner<std::unique_ptr<Result> &>
167
      {
168 1
        static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
169
        {
170 1
          return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
171
        }
172
      };
173

174
    /// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
175
    /// \todo Fix the fact that this has to be in a shared_ptr for now
176
    template<typename Result>
177
      struct Cast_Helper_Inner<const std::unique_ptr<Result> &>
178
      {
179 1
        static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
180
        {
181 1
          return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
182
        }
183
      };
184

185

186
    /// Cast_Helper_Inner for casting to a std::shared_ptr<> type
187
    template<typename Result>
188
      struct Cast_Helper_Inner<std::shared_ptr<Result> >
189
      {
190 1
        static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
191
        {
192 1
          return ob.get().cast<std::shared_ptr<Result> >();
193
        }
194
      };
195

196
    /// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
197
    template<typename Result>
198
      struct Cast_Helper_Inner<std::shared_ptr<const Result> >
199
      {
200 1
        static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
201
        {
202 1
          if (!ob.get_type_info().is_const())
203
          {
204 1
            return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
205
          } else {
206 1
            return ob.get().cast<std::shared_ptr<const Result> >();
207
          }
208
        }
209
      };
210

211
    /// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
212
    template<typename Result>
213
      struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
214
      {
215
      };
216

217
    template<typename Result>
218
      struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
219
      {
220
      };
221

222
    template<typename Result>
223
      struct Cast_Helper_Inner<std::shared_ptr<Result> &>
224
      {
225
        static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
226 1
        static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
227
        {
228 1
          std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
229 1
          return ob.pointer_sentinel(res);
230
        }
231
      };
232

233

234
    /// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
235
    template<typename Result>
236
      struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
237
      {
238
      };
239

240
    template<typename Result>
241
      struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
242
      {
243
      };
244

245

246
    /// Cast_Helper_Inner for casting to a Boxed_Value type
247
    template<>
248
      struct Cast_Helper_Inner<Boxed_Value>
249
      {
250 1
        static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
251
        {
252 1
          return ob;
253
        }
254
      };
255

256
    /// Cast_Helper_Inner for casting to a Boxed_Value & type
257
    template<>
258
      struct Cast_Helper_Inner<Boxed_Value &>
259
      {
260 1
        static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
261
        {
262 1
          return std::ref(const_cast<Boxed_Value &>(ob));
263
        }
264
      };
265

266

267
    /// Cast_Helper_Inner for casting to a const Boxed_Value & type
268
    template<>
269
      struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
270
      {
271
      };
272

273
    template<>
274
      struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
275
      {
276
      };
277

278

279
    /// Cast_Helper_Inner for casting to a std::reference_wrapper type
280
    template<typename Result>
281
      struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
282
      {
283
      };
284

285
    template<typename Result>
286
      struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
287
      {
288
      };
289

290
    template<typename Result>
291
      struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
292
      {
293
      };
294

295
    template<typename Result>
296
      struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
297
      {
298
      };
299

300
    template<typename Result>
301
      struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
302
      {
303
      };
304

305
    template<typename Result>
306
      struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
307
      {
308
      };
309

310
    /// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
311
    template<typename T>
312
      struct Cast_Helper
313
      {
314
        static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
315
        {
316
          return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
317
        }
318
      };
319
  }
320
  
321
}
322

323
#endif

Read our documentation on viewing source code .

Loading