You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp

194 lines
5.5 KiB
C++

/*
* 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<char>*& 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<const StringIdPoolIndex*>(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<StringIdPoolIndex*>(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<size_t>(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<size_t>(stream.Write(bytesToWrite, reinterpret_cast<const void*>(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<const StringIdPoolIndex*>(lhs) == *static_cast<const StringIdPoolIndex*>(rhs);
}
};
void StringIdPoolIndex::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (!serializeContext)
{
return;
}
serializeContext->Class<StringIdPoolIndex>()
->Version(1)
->Serializer<StringIdPoolIndexSerializer>()
;
}
} // namespace MCore