123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- /*******************************************************************************
- The content of this file includes portions of the AUDIOKINETIC Wwise Technology
- released in source code form as part of the SDK installer package.
- Commercial License Usage
- Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
- may use this file in accordance with the end user license agreement provided
- with the software or, alternatively, in accordance with the terms contained in a
- written agreement between you and Audiokinetic Inc.
- Apache License Usage
- Alternatively, this file may be used under the Apache License, Version 2.0 (the
- "Apache License"); you may not use this file except in compliance with the
- Apache License. You may obtain a copy of the Apache License at
- http://www.apache.org/licenses/LICENSE-2.0.
- Unless required by applicable law or agreed to in writing, software distributed
- under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
- OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
- the specific language governing permissions and limitations under the License.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- #pragma once
- #include <map>
- #include <string>
- #include <vector>
- #include <utility>
- namespace AK
- {
- namespace WwiseAuthoringAPI
- {
- template<typename VariantType, typename StringType, typename StringCompareType> class AkJsonBase final
- {
- public:
- typedef std::map<StringType, AkJsonBase, StringCompareType> Map;
- typedef std::vector<AkJsonBase> Array;
- enum class Type
- {
- Map,
- Array,
- Variant,
- Empty
- };
- AkJsonBase() {}
- AkJsonBase(const VariantType& in_other)
- {
- SetVariant(in_other);
- }
- AkJsonBase(const Array& in_other)
- {
- SetArray(in_other);
- }
- AkJsonBase(const Map& in_other)
- {
- SetMap(in_other);
- }
- AkJsonBase(Type in_eType)
- {
- SetType(in_eType);
- }
- AkJsonBase(const AkJsonBase& in_other)
- {
- Copy(in_other, *this);
- }
- AkJsonBase(AkJsonBase&& in_other) noexcept
- {
- m_ptr = in_other.m_ptr;
- m_eType = in_other.m_eType;
- in_other.m_ptr = nullptr;
- in_other.m_eType = Type::Empty;
- }
- ~AkJsonBase()
- {
- Clear();
- }
- inline bool IsEmpty() const
- {
- return (m_eType == Type::Empty);
- }
- inline AkJsonBase& operator=(const AkJsonBase& in_other)
- {
- Copy(in_other, *this);
- return *this;
- }
- inline AkJsonBase& operator=(AkJsonBase&& in_other) noexcept
- {
- std::swap(this->m_eType, in_other.m_eType);
- std::swap(this->m_ptr, in_other.m_ptr);
- return *this;
- }
- void SetVariant(const VariantType& in_other)
- {
- SetType(Type::Variant);
- *m_pVariant = in_other;
- AKASSERT(*m_pVariant == in_other);
- AKASSERT(m_pVariant->GetType() == in_other.GetType());
- }
- void SetArray(const Array& in_other)
- {
- #ifdef _DEBUG
- for (const auto& element : in_other)
- {
- AKASSERT(!element.IsEmpty());
- }
- #endif
- SetType(Type::Array);
- (*m_pArray).assign(in_other.begin(), in_other.end());
- AKASSERT(m_pArray->size() == in_other.size());
- }
- void SetMap(const Map& in_other)
- {
- #ifdef _DEBUG
- for (const auto& element : in_other)
- {
- AKASSERT(!element.second.IsEmpty());
- }
- #endif
- SetType(Type::Map);
- (*m_pMap).clear();
- (*m_pMap).insert(in_other.begin(), in_other.end());
- AKASSERT(m_pMap->size() == in_other.size());
- }
- static void Copy(const AkJsonBase& in_rSrc, AkJsonBase& in_rDest)
- {
- switch (in_rSrc.GetType())
- {
- case Type::Array:
- {
- in_rDest.SetArray(in_rSrc.GetArray());
- AKASSERT(in_rDest.GetType() == Type::Array);
- break;
- }
- case Type::Map:
- {
- in_rDest.SetMap(in_rSrc.GetMap());
- AKASSERT(in_rDest.GetType() == Type::Map);
- break;
- }
- case Type::Variant:
- {
- in_rDest.SetVariant(in_rSrc.GetVariant());
- AKASSERT(in_rDest.GetType() == Type::Variant);
- break;
- }
- case Type::Empty:
- {
- in_rDest.Clear();
- AKASSERT(in_rDest.GetType() == Type::Empty);
- break;
- }
- default:
- {
- AKASSERT(!"Invalid type copied");
- in_rDest.Clear();
- AKASSERT(in_rDest.GetType() == Type::Empty);
- break;
- }
- }
- }
- void SetType(Type in_eType)
- {
- if (in_eType != m_eType)
- {
- Clear();
- AKASSERT(m_ptr == nullptr);
- m_eType = in_eType;
- switch (in_eType)
- {
- case Type::Array:
- m_pArray = new Array();
- break;
- case Type::Map:
- m_pMap = new Map();
- break;
- case Type::Variant:
- m_pVariant = new VariantType();
- break;
- case Type::Empty:
- m_eType = Type::Empty;
- AKASSERT(!L"Cannot assign type empty");
- break;
- default:
- m_eType = Type::Empty;
- AKASSERT(!L"Unknown type assigned");
- break;
- }
- }
- AKASSERT(m_eType == in_eType);
- AKASSERT(m_ptr != nullptr);
- }
- void Clear()
- {
- if (m_ptr == nullptr)
- {
- AKASSERT(m_eType == Type::Empty);
- return;
- }
- switch (m_eType)
- {
- case Type::Array:
- delete m_pArray;
- break;
- case Type::Map:
- delete m_pMap;
- break;
- case Type::Variant:
- delete m_pVariant;
- break;
- case Type::Empty:
- default:
- // Leak any value pointed to by m_ptr: unknown type
- AKASSERT(!"Empty-typed variant with non-null value");
- break;
- }
- m_eType = Type::Empty;
- m_ptr = nullptr;
- }
- inline Type GetType() const
- {
- AKASSERT(
- m_eType == Type::Map ||
- m_eType == Type::Array ||
- m_eType == Type::Variant ||
- m_eType == Type::Empty
- );
- return m_eType;
- }
- inline bool IsArray() const
- {
- return m_eType == Type::Array;
- }
- inline bool IsMap() const
- {
- return m_eType == Type::Map;
- }
- inline bool IsVariant() const
- {
- return m_eType == Type::Variant;
- }
- inline Array& GetArray() const
- {
- AKASSERT(m_eType == Type::Array);
- AKASSERT(m_pArray != nullptr);
- return *m_pArray;
- }
- inline const Map& GetMap() const
- {
- AKASSERT(m_eType == Type::Map);
- AKASSERT(m_pMap != nullptr);
- return *m_pMap;
- }
- inline const VariantType& GetVariant() const
- {
- AKASSERT(m_eType == Type::Variant);
- AKASSERT(m_pVariant != nullptr);
- return *m_pVariant;
- }
- inline Array& GetArray()
- {
- AKASSERT(m_eType == Type::Array);
- AKASSERT(m_pArray != nullptr);
- return *m_pArray;
- }
- inline Map& GetMap()
- {
- AKASSERT(m_eType == Type::Map);
- AKASSERT(m_pMap != nullptr);
- return *m_pMap;
- }
- inline VariantType& GetVariant()
- {
- AKASSERT(m_eType == Type::Variant);
- AKASSERT(m_pVariant != nullptr);
- return *m_pVariant;
- }
- inline bool HasKey(const StringType& in_key) const
- {
- if (m_eType == Type::Map)
- {
- return (GetMap().find(in_key) != GetMap().end());
- }
- else
- {
- AKASSERT(!"Calling HasKey on AkJsonBase which is NOT a map!");
- }
- return false;
- }
- const AkJsonBase& operator[](const StringType& in_key) const
- {
- if (m_eType == Type::Map)
- {
- auto it = GetMap().find(in_key);
- AKASSERT(it != GetMap().end());
- if (it != GetMap().end())
- return it->second;
- }
- else
- {
- AKASSERT(!"Calling [] operator on AkJsonBase which is NOT a map!");
- }
- static const AkJsonBase empty;
- return empty;
- }
- const AkJsonBase& operator[](const uint32_t in_index) const
- {
- if (m_eType == Type::Array)
- {
- AKASSERT(in_index < GetArray().size());
- if (in_index < GetArray().size())
- return GetArray()[in_index];
- }
- else
- {
- AKASSERT(!"Calling [] operator on AkJsonBase which is NOT an array!");
- }
- static const AkJsonBase empty;
- return empty;
- }
- // Implicit interface compatible with rapidjson. Dependency on rapidjson is not required if those functions are not used.
- template<typename RapidJsonValue, typename RapidJsonAllocator, typename RapidJsonSizeType, typename StringToValue>
- static bool ToRapidJson(const AkJsonBase& in_node, RapidJsonValue& out_rapidJson, RapidJsonAllocator& in_allocator);
- template<typename RapidJsonValue>
- static bool FromRapidJson(const RapidJsonValue& in_rapidJson, AkJsonBase& out_node);
- private:
- Type m_eType = Type::Empty;
- union
- {
- void* m_ptr{nullptr};
- Map* m_pMap;
- Array* m_pArray;
- VariantType* m_pVariant;
- };
- };
- //<rapidjson::Value>
- template<typename VariantType, typename StringType, typename StringCompareType>
- template<typename RapidJsonValue>
- bool AkJsonBase<VariantType, StringType, StringCompareType>::FromRapidJson(const RapidJsonValue& in_rapidJson, AkJsonBase& out_node)
- {
- if (in_rapidJson.IsObject())
- {
- out_node.SetType(AkJsonBase::Type::Map);
- AkJsonBase::Map& map = out_node.GetMap();
- for (auto it = in_rapidJson.MemberBegin(); it != in_rapidJson.MemberEnd(); ++it)
- {
- StringType rosName(it->name.GetString());
- map[rosName] = AkJsonBase();
- if (!FromRapidJson(it->value, map[rosName]))
- return false;
- }
- }
- else if (in_rapidJson.IsArray())
- {
- out_node.SetType(AkJsonBase::Type::Array);
- AkJsonBase::Array& array = out_node.GetArray();
- for (auto it = in_rapidJson.Begin(); it != in_rapidJson.End(); ++it)
- {
- array.push_back(AkJsonBase());
- if (!FromRapidJson(*it, array.back()))
- return false;
- }
- }
- else if (in_rapidJson.IsNull())
- {
- out_node = VariantType();
- return true;
- }
- else
- {
- out_node.SetType(AkJsonBase::Type::Variant);
- out_node.SetVariant(VariantType::template FromRapidJsonValue<decltype(in_rapidJson)>(in_rapidJson));
- return (!out_node.GetVariant().IsEmpty());
- }
- return true;
- }
- //<rapidjson::Value, rapidjson::MemoryPoolAllocator<>, rapidjson::SizeType>
- template<typename VariantType, typename StringType, typename StringCompareType>
- template<typename RapidJsonValue, typename RapidJsonAllocator, typename RapidJsonSizeType, typename StringToValue>
- bool AkJsonBase<VariantType, StringType, StringCompareType>::ToRapidJson(const AkJsonBase& in_node, RapidJsonValue& out_rapidJson, RapidJsonAllocator& in_allocator)
- {
- if (in_node.GetType() == AkJsonBase::Type::Map)
- {
- out_rapidJson.SetObject();
- const AkJsonBase::Map& map = in_node.GetMap();
- for (auto it = map.begin(); it != map.end(); ++it)
- {
- RapidJsonValue value;
- if (!ToRapidJson<RapidJsonValue, RapidJsonAllocator, RapidJsonSizeType, StringToValue>(it->second, value, in_allocator))
- return false;
- StringType name(it->first);
- RapidJsonValue key = StringToValue::Convert(name, in_allocator);
- out_rapidJson.AddMember(key, value, in_allocator);
- }
- }
- else if (in_node.GetType() == AkJsonBase::Type::Array)
- {
- out_rapidJson.SetArray();
- const AkJsonBase::Array& arr = in_node.GetArray();
- for (auto it = arr.begin(); it != arr.end(); ++it)
- {
- RapidJsonValue value;
- if (!ToRapidJson<RapidJsonValue, RapidJsonAllocator, RapidJsonSizeType, StringToValue>(*it, value, in_allocator))
- return false;
- out_rapidJson.PushBack(value, in_allocator);
- }
- }
- else if (in_node.GetType() == AkJsonBase::Type::Empty)
- {
- out_rapidJson.SetNull();
- }
- else
- {
- const VariantType& value = in_node.GetVariant();
- return value.template toRapidJsonValue<decltype(out_rapidJson), decltype(in_allocator), RapidJsonSizeType>(out_rapidJson, in_allocator);
- }
- return true;
- }
- }
- }
|