// 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 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(src)); } inline void destruct(void* ptr) const { reinterpret_cast(ptr)->~T(); } inline bool deserialize(const Deserializer* d, void* ptr) const { return d->deserialize(reinterpret_cast(ptr)); } inline bool serialize(Serializer* s, const void* ptr) const { return s->serialize(*reinterpret_cast(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 struct TypeOf {}; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template <> struct TypeOf { static const TypeInfo* type(); }; template struct TypeOf> { static inline const TypeInfo* type() { static BasicTypeInfo> typeinfo("array<" + TypeOf::type()->name() + ">"); return &typeinfo; } }; template struct TypeOf> { static inline const TypeInfo* type() { static BasicTypeInfo> typeinfo("variant"); return &typeinfo; } }; template struct TypeOf> { static inline const TypeInfo* type() { static BasicTypeInfo> typeinfo("optional<" + TypeOf::type()->name() + ">"); return &typeinfo; } }; // DAP_OFFSETOF() macro is a generalization of the offsetof() macro defined in // . 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((((s*)32)->m)) - 32) // internal functionality namespace detail { template 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::type(), \ } // DAP_DECLARE_STRUCT_TYPEINFO() declares a TypeOf<> specialization for STRUCT. #define DAP_DECLARE_STRUCT_TYPEINFO(STRUCT) \ template <> \ struct TypeOf { \ 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::type() { \ using StructTy = STRUCT; \ struct TI : BasicTypeInfo { \ TI() : BasicTypeInfo(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->fields(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