/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/Engine/Foundation/IO/Implementation/OpenDdlReader.cpp
383 строки
11 KB
C-Core
Re-enabled security relevant warnings (#1339)
25 июн 2024, 12:03
Не верифицирован
25 июн 2024, 12:03
7083663
Код
Авторство
О чём код?
#include <Foundation/FoundationPCH.h> #include <Foundation/IO/OpenDdlReader.h> ezOpenDdlReader::ezOpenDdlReader() { m_pCurrentChunk = nullptr; m_uiBytesInChunkLeft = 0; } ezOpenDdlReader::~ezOpenDdlReader() { ClearDataChunks(); } ezResult ezOpenDdlReader::ParseDocument(ezStreamReader& inout_stream, ezUInt32 uiFirstLineOffset, ezLogInterface* pLog, ezUInt32 uiCacheSizeInKB) { EZ_ASSERT_DEBUG(m_ObjectStack.IsEmpty(), "A reader can only be used once."); SetLogInterface(pLog); SetCacheSize(uiCacheSizeInKB); SetInputStream(inout_stream, uiFirstLineOffset); m_TempCache.Reserve(s_uiChunkSize); ezOpenDdlReaderElement* pElement = &m_Elements.ExpandAndGetRef(); pElement->m_pFirstChild = nullptr; pElement->m_pLastChild = nullptr; pElement->m_PrimitiveType = ezOpenDdlPrimitiveType::Custom; pElement->m_pSiblingElement = nullptr; pElement->m_sCustomType = CopyString("root"); pElement->m_sName = nullptr; pElement->m_uiNumChildElements = 0; m_ObjectStack.PushBack(pElement); return ParseAll(); } const ezOpenDdlReaderElement* ezOpenDdlReader::GetRootElement() const { EZ_ASSERT_DEBUG(!m_ObjectStack.IsEmpty(), "The reader has not parsed any document yet or an error occurred during parsing."); return m_ObjectStack[0]; } const ezOpenDdlReaderElement* ezOpenDdlReader::FindElement(ezStringView sGlobalName) const { return m_GlobalNames.GetValueOrDefault(sGlobalName, nullptr); } ezStringView ezOpenDdlReader::CopyString(const ezStringView& string) { if (string.IsEmpty()) return {}; // no idea how to make this more efficient without running into lots of other problems m_Strings.PushBack(string); return m_Strings.PeekBack(); } ezOpenDdlReaderElement* ezOpenDdlReader::CreateElement(ezOpenDdlPrimitiveType type, ezStringView sType, ezStringView sName, bool bGlobalName) { ezOpenDdlReaderElement* pElement = &m_Elements.ExpandAndGetRef(); pElement->m_pFirstChild = nullptr; pElement->m_pLastChild = nullptr; pElement->m_PrimitiveType = type; pElement->m_pSiblingElement = nullptr; pElement->m_sCustomType = sType; pElement->m_sName = CopyString(sName); pElement->m_uiNumChildElements = 0; if (bGlobalName) { pElement->m_uiNumChildElements = EZ_BIT(31); } if (bGlobalName && !sName.IsEmpty()) { m_GlobalNames[sName] = pElement; } ezOpenDdlReaderElement* pParent = m_ObjectStack.PeekBack(); pParent->m_uiNumChildElements++; if (pParent->m_pFirstChild == nullptr) { pParent->m_pFirstChild = pElement; pParent->m_pLastChild = pElement; } else { ((ezOpenDdlReaderElement*)pParent->m_pLastChild)->m_pSiblingElement = pElement; pParent->m_pLastChild = pElement; } m_ObjectStack.PushBack(pElement); return pElement; } void ezOpenDdlReader::OnBeginObject(ezStringView sType, ezStringView sName, bool bGlobalName) { CreateElement(ezOpenDdlPrimitiveType::Custom, CopyString(sType), sName, bGlobalName); } void ezOpenDdlReader::OnEndObject() { m_ObjectStack.PopBack(); } void ezOpenDdlReader::OnBeginPrimitiveList(ezOpenDdlPrimitiveType type, ezStringView sName, bool bGlobalName) { CreateElement(type, nullptr, sName, bGlobalName); m_TempCache.Clear(); } void ezOpenDdlReader::OnEndPrimitiveList() { // if we had to temporarily store the primitive data, copy it into a new destination if (!m_TempCache.IsEmpty()) { ezUInt8* pTarget = AllocateBytes(m_TempCache.GetCount()); m_ObjectStack.PeekBack()->m_pFirstChild = pTarget; ezMemoryUtils::Copy(pTarget, m_TempCache.GetData(), m_TempCache.GetCount()); } m_ObjectStack.PopBack(); } void ezOpenDdlReader::StorePrimitiveData(bool bThisIsAll, ezUInt32 bytecount, const ezUInt8* pData) { ezUInt8* pTarget = nullptr; if (!bThisIsAll || !m_TempCache.IsEmpty()) { // if this is not all, accumulate the data in a temp buffer ezUInt32 offset = m_TempCache.GetCount(); m_TempCache.SetCountUninitialized(m_TempCache.GetCount() + bytecount); pTarget = &m_TempCache[offset]; // have to index m_TempCache after the resize, otherwise it could be empty and not like it } else { // otherwise, allocate the final storage immediately pTarget = AllocateBytes(bytecount); m_ObjectStack.PeekBack()->m_pFirstChild = pTarget; } ezMemoryUtils::Copy(pTarget, pData, bytecount); } void ezOpenDdlReader::OnPrimitiveBool(ezUInt32 count, const bool* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(bool) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveInt8(ezUInt32 count, const ezInt8* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezInt8) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveInt16(ezUInt32 count, const ezInt16* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezInt16) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveInt32(ezUInt32 count, const ezInt32* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezInt32) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveInt64(ezUInt32 count, const ezInt64* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezInt64) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveUInt8(ezUInt32 count, const ezUInt8* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezUInt8) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveUInt16(ezUInt32 count, const ezUInt16* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezUInt16) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveUInt32(ezUInt32 count, const ezUInt32* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezUInt32) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveUInt64(ezUInt32 count, const ezUInt64* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(ezUInt64) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveFloat(ezUInt32 count, const float* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(float) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveDouble(ezUInt32 count, const double* pData, bool bThisIsAll) { StorePrimitiveData(bThisIsAll, sizeof(double) * count, (const ezUInt8*)pData); m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnPrimitiveString(ezUInt32 count, const ezStringView* pData, bool bThisIsAll) { EZ_IGNORE_UNUSED(bThisIsAll); const ezUInt32 uiDataSize = count * sizeof(ezStringView); const ezUInt32 offset = m_TempCache.GetCount(); m_TempCache.SetCountUninitialized(m_TempCache.GetCount() + uiDataSize); ezStringView* pTarget = (ezStringView*)&m_TempCache[offset]; for (ezUInt32 i = 0; i < count; ++i) { pTarget[i] = CopyString(pData[i]); } m_ObjectStack.PeekBack()->m_uiNumChildElements += count; } void ezOpenDdlReader::OnParsingError(ezStringView sMessage, bool bFatal, ezUInt32 uiLine, ezUInt32 uiColumn) { EZ_IGNORE_UNUSED(sMessage); EZ_IGNORE_UNUSED(uiLine); EZ_IGNORE_UNUSED(uiColumn); if (bFatal) { m_ObjectStack.Clear(); m_GlobalNames.Clear(); m_Elements.Clear(); ClearDataChunks(); } } ////////////////////////////////////////////////////////////////////////// void ezOpenDdlReader::ClearDataChunks() { for (ezUInt32 i = 0; i < m_DataChunks.GetCount(); ++i) { EZ_DEFAULT_DELETE(m_DataChunks[i]); } m_DataChunks.Clear(); } ezUInt8* ezOpenDdlReader::AllocateBytes(ezUInt32 uiNumBytes) { uiNumBytes = ezMemoryUtils::AlignSize(uiNumBytes, static_cast<ezUInt32>(EZ_ALIGNMENT_MINIMUM)); // if the requested data is very large, just allocate it as an individual chunk if (uiNumBytes > s_uiChunkSize / 2) { ezUInt8* pResult = EZ_DEFAULT_NEW_ARRAY(ezUInt8, uiNumBytes).GetPtr(); m_DataChunks.PushBack(pResult); return pResult; } // if our current chunk is too small, discard the remaining free bytes and just allocate a new chunk if (m_uiBytesInChunkLeft < uiNumBytes) { m_pCurrentChunk = EZ_DEFAULT_NEW_ARRAY(ezUInt8, s_uiChunkSize).GetPtr(); m_uiBytesInChunkLeft = s_uiChunkSize; m_DataChunks.PushBack(m_pCurrentChunk); } // no fulfill the request from the current chunk ezUInt8* pResult = m_pCurrentChunk; m_pCurrentChunk += uiNumBytes; m_uiBytesInChunkLeft -= uiNumBytes; return pResult; } ////////////////////////////////////////////////////////////////////////// ezUInt32 ezOpenDdlReaderElement::GetNumChildObjects() const { if (m_PrimitiveType != ezOpenDdlPrimitiveType::Custom) return 0; return m_uiNumChildElements & (~EZ_BIT(31)); // Bit 31 stores whether the name is global } ezUInt32 ezOpenDdlReaderElement::GetNumPrimitives() const { if (m_PrimitiveType == ezOpenDdlPrimitiveType::Custom) return 0; return m_uiNumChildElements & (~EZ_BIT(31)); // Bit 31 stores whether the name is global } bool ezOpenDdlReaderElement::HasPrimitives(ezOpenDdlPrimitiveType type, ezUInt32 uiMinNumberOfPrimitives /*= 1*/) const { /// \test This is new if (m_PrimitiveType != type) return false; return m_uiNumChildElements >= uiMinNumberOfPrimitives; } const ezOpenDdlReaderElement* ezOpenDdlReaderElement::FindChild(ezStringView sName) const { EZ_ASSERT_DEBUG(m_PrimitiveType == ezOpenDdlPrimitiveType::Custom, "Cannot search for a child object in a primitives list"); const ezOpenDdlReaderElement* pChild = static_cast<const ezOpenDdlReaderElement*>(m_pFirstChild); while (pChild) { if (pChild->GetName() == sName) { return pChild; } pChild = pChild->GetSibling(); } return nullptr; } const ezOpenDdlReaderElement* ezOpenDdlReaderElement::FindChildOfType(ezOpenDdlPrimitiveType type, ezStringView sName, ezUInt32 uiMinNumberOfPrimitives /* = 1*/) const { /// \test This is new EZ_ASSERT_DEBUG(m_PrimitiveType == ezOpenDdlPrimitiveType::Custom, "Cannot search for a child object in a primitives list"); const ezOpenDdlReaderElement* pChild = static_cast<const ezOpenDdlReaderElement*>(m_pFirstChild); while (pChild) { if (pChild->GetPrimitivesType() == type && pChild->GetName() == sName) { if (type == ezOpenDdlPrimitiveType::Custom || pChild->GetNumPrimitives() >= uiMinNumberOfPrimitives) return pChild; } pChild = pChild->GetSibling(); } return nullptr; } const ezOpenDdlReaderElement* ezOpenDdlReaderElement::FindChildOfType(ezStringView sType, ezStringView sName /*= {}*/) const { const ezOpenDdlReaderElement* pChild = static_cast<const ezOpenDdlReaderElement*>(m_pFirstChild); while (pChild) { if (pChild->GetPrimitivesType() == ezOpenDdlPrimitiveType::Custom && pChild->GetCustomType() == sType && (sName.IsEmpty() || pChild->GetName() == sName)) { return pChild; } pChild = pChild->GetSibling(); } return nullptr; }