// 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 #include #include 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(src)); } inline void destruct(void* ptr) const override { reinterpret_cast(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 boolean = {"boolean"}; dap::BasicTypeInfo string = {"string"}; dap::BasicTypeInfo integer = {"integer"}; dap::BasicTypeInfo number = {"number"}; dap::BasicTypeInfo object = {"object"}; dap::BasicTypeInfo any = {"any"}; NullTI null; std::vector> types; private: TypeInfos() = default; ~TypeInfos() = default; std::atomic refcount = {1}; }; // aligned_storage() is a replacement for std::aligned_storage that isn't busted // on older versions of MSVC. template struct aligned_storage { struct alignas(ALIGNMENT) type { unsigned char data[SIZE]; }; }; TypeInfos* TypeInfos::get() { static aligned_storage::type memory; struct Instance { TypeInfos* ptr() { return reinterpret_cast(memory.data); } Instance() { new (ptr()) TypeInfos(); } ~Instance() { ptr()->release(); } }; static Instance instance; return instance.ptr(); } } // namespace namespace dap { const TypeInfo* TypeOf::type() { return &TypeInfos::get()->boolean; } const TypeInfo* TypeOf::type() { return &TypeInfos::get()->string; } const TypeInfo* TypeOf::type() { return &TypeInfos::get()->integer; } const TypeInfo* TypeOf::type() { return &TypeInfos::get()->number; } const TypeInfo* TypeOf::type() { return &TypeInfos::get()->object; } const TypeInfo* TypeOf::type() { return &TypeInfos::get()->any; } const TypeInfo* TypeOf::type() { return &TypeInfos::get()->null; } void TypeInfo::deleteOnExit(TypeInfo* ti) { TypeInfos::get()->types.emplace_back(std::unique_ptr(ti)); } void initialize() { TypeInfos::get()->reference(); } void terminate() { TypeInfos::get()->release(); } } // namespace dap