/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ // include the required headers #include "StringIdPool.h" #include "LogManager.h" namespace MCore { StringIdPool::StringIdPool() { Reserve(10000); GenerateIdForString(""); } StringIdPool::~StringIdPool() { Clear(); } void StringIdPool::Clear() { Lock(); for (AZStd::basic_string*& string : m_strings) { delete string; } m_strings.clear(); m_stringToIndex.clear(); Unlock(); } AZ::u32 StringIdPool::GenerateIdForStringWithoutLock(const AZStd::string& objectName) { // Try to insert it, if we hit a collision, we have the element. auto iterator = m_stringToIndex.emplace(objectName, aznumeric_caster(m_strings.size())); if (!iterator.second) { // could not insert, we have the element return iterator.first->second; } // Create the new string object and push it to the string list. AZStd::string* newString = new AZStd::string(objectName); m_strings.push_back(newString); // The string was already added to the hashmap return iterator.first->second; } AZ::u32 StringIdPool::GenerateIdForString(const AZStd::string& objectName) { Lock(); const AZ::u32 result = GenerateIdForStringWithoutLock(objectName); Unlock(); return result; } const AZStd::string& StringIdPool::GetName(AZ::u32 id) { Lock(); MCORE_ASSERT(id != InvalidIndex32); const AZStd::string* stringAddress = m_strings[id]; Unlock(); return *stringAddress; } void StringIdPool::Reserve(size_t numStrings) { Lock(); m_strings.reserve(numStrings); Unlock(); } // Wait with execution until we can set the lock. void StringIdPool::Lock() { m_mutex.Lock(); } // Release the lock again. void StringIdPool::Unlock() { m_mutex.Unlock(); } void StringIdPool::Log(bool includeEntries) { AZ_Printf("EMotionFX", "StringIdPool: NumEntries=%d\n", m_strings.size()); if (includeEntries) { const size_t numStrings = m_strings.size(); for (size_t i = 0; i < numStrings; ++i) { AZ_Printf("EMotionFX", " #%d: String='%s', Id=%d\n", i, m_strings[i]->c_str(), GenerateIdForString(m_strings[i]->c_str())); } } } class StringIdPoolIndexSerializer : public AZ::SerializeContext::IDataSerializer { public: /// Store the class data into a stream. size_t Save(const void* classPtr, AZ::IO::GenericStream& stream, bool /*isDataBigEndian = false*/) { // Look up the string to save const AZ::u32 index = static_cast(classPtr)->m_index; if (index == InvalidIndex32) { return 0; } const AZStd::string& string = MCore::GetStringIdPool().GetName(index); return stream.Write(string.size(), string.c_str()); } /// Load the class data from a stream. bool Load(void* classPtr, AZ::IO::GenericStream& stream, unsigned int /*version*/, bool /*isDataBigEndian = false*/) { AZStd::string string; size_t textLen = stream.GetLength(); string.resize(textLen); stream.Read(textLen, string.data()); static_cast(classPtr)->m_index = MCore::GetStringIdPool().GenerateIdForString(string); return true; } /// Convert binary data to text. size_t DataToText(AZ::IO::GenericStream& in, AZ::IO::GenericStream& out, bool /*isDataBigEndian = false*/) { AZ::u64 dataSize = in.GetLength(); AZStd::string outText; outText.resize(dataSize); in.Read(dataSize, outText.data()); return static_cast(out.Write(outText.size(), outText.c_str())); } /// Convert text data to binary, to support loading old version // formats. We must respect text version if the text->binary format has // changed! size_t TextToData(const char* text, unsigned int /*textVersion*/, AZ::IO::GenericStream& stream, bool /*isDataBigEndian = false*/) { size_t bytesToWrite = strlen(text); return static_cast(stream.Write(bytesToWrite, reinterpret_cast(text))); } /// Compares two instances of the type. /// \return true if they match. /// Note: Input pointers are assumed to point to valid instances of the class. bool CompareValueData(const void* lhs, const void* rhs) { return *static_cast(lhs) == *static_cast(rhs); } }; void StringIdPoolIndex::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); if (!serializeContext) { return; } serializeContext->Class() ->Version(1) ->Serializer() ; } } // namespace MCore