| // Copyright 2019 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef dap_typeof_h |
| #define dap_typeof_h |
| |
| #include "typeinfo.h" |
| #include "types.h" |
| |
| #include "serialization.h" |
| |
| namespace dap { |
| |
| // BasicTypeInfo is an implementation of the TypeInfo interface for the simple |
| // template type T. |
| template <typename T> |
| struct BasicTypeInfo : public TypeInfo { |
| BasicTypeInfo(const std::string& name) : name_(name) {} |
| |
| // TypeInfo compliance |
| inline std::string name() const { return name_; } |
| inline size_t size() const { return sizeof(T); } |
| inline size_t alignment() const { return alignof(T); } |
| inline void construct(void* ptr) const { new (ptr) T(); } |
| inline void copyConstruct(void* dst, const void* src) const { |
| new (dst) T(*reinterpret_cast<const T*>(src)); |
| } |
| inline void destruct(void* ptr) const { reinterpret_cast<T*>(ptr)->~T(); } |
| inline bool deserialize(const Deserializer* d, void* ptr) const { |
| return d->deserialize(reinterpret_cast<T*>(ptr)); |
| } |
| inline bool serialize(Serializer* s, const void* ptr) const { |
| return s->serialize(*reinterpret_cast<const T*>(ptr)); |
| } |
| |
| private: |
| std::string name_; |
| }; |
| |
| // TypeOf has a template specialization for each DAP type, each declaring a |
| // const TypeInfo* type() static member function that describes type T. |
| template <typename T> |
| struct TypeOf {}; |
| |
| template <> |
| struct TypeOf<boolean> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <> |
| struct TypeOf<string> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <> |
| struct TypeOf<integer> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <> |
| struct TypeOf<number> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <> |
| struct TypeOf<object> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <> |
| struct TypeOf<any> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <> |
| struct TypeOf<null> { |
| static const TypeInfo* type(); |
| }; |
| |
| template <typename T> |
| struct TypeOf<array<T>> { |
| static inline const TypeInfo* type() { |
| static BasicTypeInfo<array<T>> typeinfo("array<" + |
| TypeOf<T>::type()->name() + ">"); |
| return &typeinfo; |
| } |
| }; |
| |
| template <typename T0, typename... Types> |
| struct TypeOf<variant<T0, Types...>> { |
| static inline const TypeInfo* type() { |
| static BasicTypeInfo<variant<T0, Types...>> typeinfo("variant"); |
| return &typeinfo; |
| } |
| }; |
| |
| template <typename T> |
| struct TypeOf<optional<T>> { |
| static inline const TypeInfo* type() { |
| static BasicTypeInfo<optional<T>> typeinfo("optional<" + |
| TypeOf<T>::type()->name() + ">"); |
| return &typeinfo; |
| } |
| }; |
| |
| // DAP_OFFSETOF() macro is a generalization of the offsetof() macro defined in |
| // <cstddef>. It evaluates to the offset of the given field, with fewer |
| // restrictions than offsetof(). We cast the address '32' and subtract it again, |
| // because null-dereference is undefined behavior. |
| #define DAP_OFFSETOF(s, m) \ |
| ((int)(size_t) & reinterpret_cast<const volatile char&>((((s*)32)->m)) - 32) |
| |
| // internal functionality |
| namespace detail { |
| template <class T, class M> |
| M member_type(M T::*); |
| } // namespace detail |
| |
| // DAP_TYPEOF() returns the type of the struct (s) member (m). |
| #define DAP_TYPEOF(s, m) decltype(detail::member_type(&s::m)) |
| |
| // DAP_FIELD() declares a structure field for the DAP_IMPLEMENT_STRUCT_TYPEINFO |
| // macro. |
| // FIELD is the name of the struct field. |
| // NAME is the serialized name of the field, as described by the DAP |
| // specification. |
| #define DAP_FIELD(FIELD, NAME) \ |
| dap::Field { \ |
| NAME, DAP_OFFSETOF(StructTy, FIELD), \ |
| TypeOf<DAP_TYPEOF(StructTy, FIELD)>::type(), \ |
| } |
| |
| // DAP_DECLARE_STRUCT_TYPEINFO() declares a TypeOf<> specialization for STRUCT. |
| #define DAP_DECLARE_STRUCT_TYPEINFO(STRUCT) \ |
| template <> \ |
| struct TypeOf<STRUCT> { \ |
| static constexpr bool has_custom_serialization = true; \ |
| static const TypeInfo* type(); \ |
| } |
| |
| // DAP_DECLARE_STRUCT_TYPEINFO() implements the type() member function for the |
| // TypeOf<> specialization for STRUCT. |
| // STRUCT is the structure typename. |
| // NAME is the serialized name of the structure, as described by the DAP |
| // specification. The variadic (...) parameters should be a repeated list of |
| // DAP_FIELD()s, one for each field of the struct. |
| #define DAP_IMPLEMENT_STRUCT_TYPEINFO(STRUCT, NAME, ...) \ |
| const TypeInfo* TypeOf<STRUCT>::type() { \ |
| using StructTy = STRUCT; \ |
| struct TI : BasicTypeInfo<StructTy> { \ |
| TI() : BasicTypeInfo<StructTy>(NAME) {} \ |
| bool deserialize(const Deserializer* d, void* ptr) const override { \ |
| return d->deserialize(ptr, {__VA_ARGS__}); \ |
| } \ |
| bool serialize(Serializer* s, const void* ptr) const override { \ |
| return s->serialize(ptr, {__VA_ARGS__}); \ |
| } \ |
| }; \ |
| static TI typeinfo; \ |
| return &typeinfo; \ |
| } |
| |
| // DAP_STRUCT_TYPEINFO() is a helper for declaring and implementing a TypeOf<> |
| // specialization for STRUCT in a single statement. |
| #define DAP_STRUCT_TYPEINFO(STRUCT, NAME, ...) \ |
| DAP_DECLARE_STRUCT_TYPEINFO(STRUCT); \ |
| DAP_IMPLEMENT_STRUCT_TYPEINFO(STRUCT, NAME, __VA_ARGS__) |
| |
| } // namespace dap |
| |
| #endif // dap_typeof_h |