1 //******************************************************************
3 // Copyright 2014 Intel Corporation All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #ifndef __INTEL_OCPROPERTIES_H_20140708
22 #define __INTEL_OCPROPERTIES_H_20140708
36 #include <type_traits>
38 #include "OCException.h"
40 namespace OC { namespace OCReflect {
42 enum class property_type : uint8_t {
53 enum class property_attribute : uint8_t {
59 struct property_signature
61 OC::OCReflect::property_type type;
62 OC::OCReflect::property_attribute attribute;
66 : type(OC::OCReflect::property_type::nil),
67 attribute(OC::OCReflect::property_attribute::rw)
70 property_signature(const OC::OCReflect::property_type& type_)
72 attribute(OC::OCReflect::property_attribute::rw)
75 property_signature(const OC::OCReflect::property_type type_, const OC::OCReflect::property_attribute attribute_)
81 typedef std::vector<property_type> property_type_vector;
83 typedef std::vector<property_signature> property_signature_vector;
85 typedef std::vector<char> property_data;
87 typedef std::tuple<std::string, property_signature> named_property_binding;
88 typedef std::vector<named_property_binding> named_property_binding_vector;
90 typedef std::tuple<named_property_binding, property_data> property;
91 typedef std::tuple<property_signature, property_data> tagged_property; // eg. a return value
93 typedef std::vector<property> property_vector;
95 typedef std::function<property(property_vector)> bound_function;
99 // Great name, huh? Must be late in the day:
100 inline property_signature_vector typev2signaturev(const property_type_vector& ptv, const property_attribute pa = property_attribute::rw)
102 property_signature_vector psv(ptv.size());
104 std::transform(std::begin(ptv), std::end(ptv), std::back_inserter(psv),
105 [&pa](const property_type& pt) -> property_signature { return property_signature(pt, pa); });
114 // Helper for constructing sequences (like vector<property>) from a parameter pack:
115 template <typename SeqT, typename T>
116 SeqT make_seq(const T& x)
121 template <typename SeqT, typename T, typename ...TS>
122 SeqT make_seq(const T& x, const TS&... xs)
126 auto vs = make_seq<SeqT>(xs...);
128 s.insert(s.end(), std::make_move_iterator(vs.begin()), std::make_move_iterator(vs.end()));
133 } // namespace OC::OCReflect::detail
135 }} // namespace OC::OCReflect
138 namespace OC { namespace OCReflect {
140 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_type& pt);
141 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_attribute& pa);
142 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_signature& ps);
143 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property& p);
145 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_type_vector& pv);
146 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_vector& p);
148 std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb);
150 }} // namespace OC::OCReflect
152 /* JFW: I wonder if I can do this...
153 constexpr OC::OCReflect::property_type map_property_type(bool)
155 return OC::OCReflect::property_type::boolean;
159 // Map concerete to property type enumerations:
160 namespace OC { namespace OCReflect {
162 template <typename T>
163 struct map_property_type
165 static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::INVALID);
169 struct map_property_type<bool>
171 static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::boolean);
175 struct map_property_type<int64_t>
177 static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::integer);
181 struct map_property_type<double>
183 static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::rational);
187 struct map_property_type<std::string>
189 static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
193 struct map_property_type<const char *>
195 static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
198 }} // namespace OC::OCReflect
201 // Sequence containers:
203 struct map_property_type< template <class T, class A> >
205 static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
209 struct map_property_type<std::vector>
211 static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
215 struct map_property_type<std::list>
217 static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
221 struct map_property_type<std::forward_list>
223 static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
227 struct map_property_type<std::deque>
229 static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
233 namespace OC { namespace OCReflect { namespace to_property {
235 OC::OCReflect::tagged_property convert(const bool& in);
236 OC::OCReflect::tagged_property convert(const int& in);
237 OC::OCReflect::tagged_property convert(const int64_t& in);
238 OC::OCReflect::tagged_property convert(const double& in);
239 OC::OCReflect::tagged_property convert(const std::string& in);
241 }}} // namespace OC::OCReflect::to_property
243 typedef std::tuple<OC::OCReflect::property_data::const_iterator, OC::OCReflect::property_data::const_iterator> pd_iter_tuple;
245 pd_iter_tuple consume_typecheck(const OC::OCReflect::property_type expected_pt, const OC::OCReflect::property_data& in);
247 namespace OC { namespace OCReflect { namespace from_property {
249 typedef OC::OCReflect::property_data::const_iterator pdci;
250 typedef std::tuple<pdci, pdci> pd_iter_pair;
252 /* We need to use a struct to get around the fact that we can't partially specialize against a
253 free function's signature-- nothing else special happening here: */
256 static void convert(const pd_iter_pair& in, bool& out)
258 out = static_cast<bool>(static_cast<int>(*(std::get<0>(in))));
261 static void convert(const pd_iter_pair& in, int64_t& out)
263 std::copy(std::get<0>(in), std::get<1>(in), reinterpret_cast<char *>(&out));
266 static void convert(const pd_iter_pair& in, double& out)
268 std::copy(std::get<0>(in), std::get<1>(in), reinterpret_cast<char *>(&out));
271 static void convert(const pd_iter_pair& in, std::string& out)
273 out.assign(std::get<0>(in), std::get<1>(in));
277 template <template <class T, class AllocT> class SeqT>
278 static void convert(const pd_iter_pair& in, SeqT& out)
280 std::copy(std::get<0>(in), std::get<1>(in), std::back_inserter(out));
286 }}} // namespace OC::OCReflect::from_property
288 namespace OC { namespace OCReflect {
290 inline OC::OCReflect::named_property_binding make_named_property_binding(const std::string& name, const OC::OCReflect::property_type pt, const OC::OCReflect::property_attribute pa = OC::OCReflect::property_attribute::rw)
292 return OC::OCReflect::named_property_binding { name, { pt, pa } };
295 }} // namespace OC::OCReflect
297 // ...probably not-so-efficent, but we want it "working" for now:
298 namespace OC { namespace OCReflect {
300 // ...a class just to facilitate the usual ADL trick:
301 struct make_property {
303 // ...work around array->bool conversion:
304 static OC::OCReflect::property apply(const char *in, const std::string& name)
306 return apply(std::string(in), name);
310 static OC::OCReflect::property apply(const InT& in, const std::string& name)
313 static_assert(property_valid(InT, OC::OCReflect::property_type::INVALID),
314 "invalid input type for make_property()");
317 OC::OCReflect::tagged_property tp { OC::OCReflect::to_property::convert(in) };
318 OC::OCReflect::named_property_binding npb { name, { std::get<0>(tp) } };
320 OC::OCReflect::property_data& tp_data = std::get<1>(tp);
322 // Encode the type, followed by the data:
323 OC::OCReflect::property_data encoded_data;
325 encoded_data.push_back(OC::OCReflect::map_property_type<InT>::value);
326 std::copy(std::begin(tp_data), std::end(tp_data), std::back_inserter(encoded_data));
328 return OC::OCReflect::property(npb, encoded_data);
332 // Pretend you didn't see this, and I won't tell anyone where you hide the bodies:
334 make_property(const InT& in, const std::string& name, OC::OCReflect::property& out)
336 out = detail::make_property::apply(in, name, out);
340 }; // struct make_property
342 }} // namespace OC::OCReflect
344 namespace OC { namespace OCReflect {
346 template <class OutT>
347 OutT concretize(const OC::OCReflect::property_data& pd)
351 OC::OCReflect::from_property::conversion::convert(
353 static_cast<OC::OCReflect::property_type>(
354 OC::OCReflect::map_property_type<OutT>::value), pd), ret);
359 template <class OutT>
360 OutT concretize(const OC::OCReflect::tagged_property& tp)
362 return concretize<OutT>(std::get<1>(tp));
365 template <class OutT>
366 OutT concretize(const OC::OCReflect::property& p)
368 return concretize<OutT>(std::get<1>(p));
371 }} // namespace OC::OCReflect
373 namespace OC { namespace OCReflect {
375 // Runtime dynamic cast from entities to concrete types:
376 template <class OutT>
377 OutT narrow(const entity& e)
379 return OutT(); // placeholder
382 struct method_signature
384 property_signature ret_signature;
385 property_signature_vector param_signatures;
388 method_signature(const property_type& return_type, const property_signature_vector& param_types_)
389 : ret_signature(return_type, OC::OCReflect::property_attribute::r),
390 param_signatures(param_types_)
393 method_signature(const property_type& return_type, const property_type_vector& param_types_)
394 : ret_signature(return_type, OC::OCReflect::property_attribute::r),
395 param_signatures(detail::typev2signaturev(param_types_))
398 template <typename ...ParameterT>
399 method_signature(const property_type& return_type, const ParameterT& ...params_)
400 : ret_signature(return_type, OC::OCReflect::property_attribute::r),
401 param_signatures { detail::make_seq<property_signature_vector>(params_...) }
405 }} // namespace OC::OCReflect
407 namespace OC { namespace OCReflect {
409 struct method_binding
411 friend std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb);
416 method_signature signature;
419 static unsigned long long anon;
423 : name("__ANONYMOUS__"),
424 signature { property_type::nil, {{ property_type::nil, property_attribute::r }} }
427 method_binding(bound_function& f,
428 method_signature& signature_)
429 : signature(signature_)
432 method_binding(const std::string& name_, bound_function& f_,
433 const property_type& return_type_, const property_type_vector& param_types_)
436 signature { return_type_, param_types_ }
439 method_binding(const std::string& name_, bound_function& f_,
440 const method_signature& signature_)
443 signature(signature_)
447 struct property_binding
449 template <typename PropertyT>
450 property_binding(PropertyT& property, const named_property_binding& pb)
455 }} // namespace OC::OCReflect