| // 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. |
| |
| #include "dap/typeof.h" |
| |
| #include <atomic> |
| #include <memory> |
| #include <vector> |
| |
| namespace { |
| |
| // TypeInfos owns all the dap::TypeInfo instances. |
| struct TypeInfos { |
| // get() returns the TypeInfos singleton pointer. |
| // TypeInfos is constructed with an internal reference count of 1. |
| static TypeInfos* get(); |
| |
| // reference() increments the TypeInfos reference count. |
| inline void reference() { |
| assert(refcount.load() > 0); |
| refcount++; |
| } |
| |
| // release() decrements the TypeInfos reference count. |
| // If the reference count becomes 0, then the TypeInfos is destructed. |
| inline void release() { |
| if (--refcount == 0) { |
| this->~TypeInfos(); |
| } |
| } |
| |
| struct NullTI : public dap::TypeInfo { |
| using null = dap::null; |
| inline std::string name() const override { return "null"; } |
| inline size_t size() const override { return sizeof(null); } |
| inline size_t alignment() const override { return alignof(null); } |
| inline void construct(void* ptr) const override { new (ptr) null(); } |
| inline void copyConstruct(void* dst, const void* src) const override { |
| new (dst) null(*reinterpret_cast<const null*>(src)); |
| } |
| inline void destruct(void* ptr) const override { |
| reinterpret_cast<null*>(ptr)->~null(); |
| } |
| inline bool deserialize(const dap::Deserializer*, void*) const override { |
| return true; |
| } |
| inline bool serialize(dap::Serializer*, const void*) const override { |
| return true; |
| } |
| }; |
| |
| dap::BasicTypeInfo<dap::boolean> boolean = {"boolean"}; |
| dap::BasicTypeInfo<dap::string> string = {"string"}; |
| dap::BasicTypeInfo<dap::integer> integer = {"integer"}; |
| dap::BasicTypeInfo<dap::number> number = {"number"}; |
| dap::BasicTypeInfo<dap::object> object = {"object"}; |
| dap::BasicTypeInfo<dap::any> any = {"any"}; |
| NullTI null; |
| std::vector<std::unique_ptr<dap::TypeInfo>> types; |
| |
| private: |
| TypeInfos() = default; |
| ~TypeInfos() = default; |
| std::atomic<uint64_t> refcount = {1}; |
| }; |
| |
| // aligned_storage() is a replacement for std::aligned_storage that isn't busted |
| // on older versions of MSVC. |
| template <size_t SIZE, size_t ALIGNMENT> |
| struct aligned_storage { |
| struct alignas(ALIGNMENT) type { |
| unsigned char data[SIZE]; |
| }; |
| }; |
| |
| TypeInfos* TypeInfos::get() { |
| static aligned_storage<sizeof(TypeInfos), alignof(TypeInfos)>::type memory; |
| |
| struct Instance { |
| TypeInfos* ptr() { return reinterpret_cast<TypeInfos*>(memory.data); } |
| Instance() { new (ptr()) TypeInfos(); } |
| ~Instance() { ptr()->release(); } |
| }; |
| |
| static Instance instance; |
| return instance.ptr(); |
| } |
| |
| } // namespace |
| |
| namespace dap { |
| |
| const TypeInfo* TypeOf<boolean>::type() { |
| return &TypeInfos::get()->boolean; |
| } |
| |
| const TypeInfo* TypeOf<string>::type() { |
| return &TypeInfos::get()->string; |
| } |
| |
| const TypeInfo* TypeOf<integer>::type() { |
| return &TypeInfos::get()->integer; |
| } |
| |
| const TypeInfo* TypeOf<number>::type() { |
| return &TypeInfos::get()->number; |
| } |
| |
| const TypeInfo* TypeOf<object>::type() { |
| return &TypeInfos::get()->object; |
| } |
| |
| const TypeInfo* TypeOf<any>::type() { |
| return &TypeInfos::get()->any; |
| } |
| |
| const TypeInfo* TypeOf<null>::type() { |
| return &TypeInfos::get()->null; |
| } |
| |
| void TypeInfo::deleteOnExit(TypeInfo* ti) { |
| TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti)); |
| } |
| |
| void initialize() { |
| TypeInfos::get()->reference(); |
| } |
| |
| void terminate() { |
| TypeInfos::get()->release(); |
| } |
| |
| } // namespace dap |