/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/Engine/Foundation/IO/OpenDdlParser.h
227 строк
9 KB
Jan Krassnigg
Improved documentation of the Foundation library (#1664)
20 сен 2025, 19:53
Не верифицирован
20 сен 2025, 19:53
0e28096
Код
Авторство
О чём код?
#pragma once #include <Foundation/Basics.h> #include <Foundation/Containers/DynamicArray.h> #include <Foundation/Containers/HybridArray.h> #include <Foundation/IO/Stream.h> class ezLogInterface; /// \brief The primitive data types that OpenDDL supports enum class ezOpenDdlPrimitiveType { Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, // Half, // Currently not supported Float, Double, String, // Ref, // Currently not supported // Type // Currently not supported Custom }; /// \brief Low-level streaming parser for OpenDDL documents /// /// This abstract base class provides incremental parsing of OpenDDL (Open Data Description Language) format. /// Unlike ezOpenDdlReader which builds a complete in-memory tree, this parser operates in streaming mode, /// calling virtual functions as elements are encountered. This allows processing large documents with minimal /// memory usage and enables selective parsing where only certain parts are processed. /// Derived classes must override the virtual On* methods to handle parsed elements. class EZ_FOUNDATION_DLL ezOpenDdlParser { public: ezOpenDdlParser(); virtual ~ezOpenDdlParser() = default; /// \brief Whether an error occurred during parsing that resulted in cancellation of further parsing. bool HadFatalParsingError() const { return m_bHadFatalParsingError; } // [tested] protected: /// \brief Sets an ezLogInterface through which errors and warnings are reported. void SetLogInterface(ezLogInterface* pLog) { m_pLogInterface = pLog; } /// \brief Sets the internal cache size for batching primitive data callbacks /// /// Data is returned in larger chunks to reduce the number of function calls. The cache size determines /// the maximum chunk size per primitive type. Default cache size is 4 KB, allowing up to 1000 integers /// or 500 doubles per chunk. Increasing the cache size only helps when the input data contains large /// primitive arrays, otherwise it provides no benefit. void SetCacheSize(ezUInt32 uiSizeInKB); /// \brief Configures the parser to read from the given stream. This can only be called once on a parser instance. void SetInputStream(ezStreamReader& stream, ezUInt32 uiFirstLineOffset = 0); // [tested] /// \brief Parses the next portion of the document and triggers appropriate callbacks /// /// Returns false when the end of the document has been reached or a fatal parsing error occurred. /// Use this for incremental parsing where you want to control when parsing happens. bool ContinueParsing(); // [tested] /// \brief Calls ContinueParsing() in a loop until that returns false. ezResult ParseAll(); // [tested] /// \brief Skips the rest of the currently open object. No OnEndObject() call will be done for this object either. void SkipRestOfObject(); /// \brief Can be used to prevent parsing the rest of the document. void StopParsing(); /// \brief Outputs that a parsing error was detected (via OnParsingError) and stops further parsing, if bFatal is set to true. void ParsingError(ezStringView sMessage, bool bFatal); ezLogInterface* m_pLogInterface; protected: /// \brief Called when something unexpected is encountered in the document. /// /// The error message describes what was expected and what was encountered. /// If bFatal is true, the error has left the parser in an unrecoverable state and thus it will not continue parsing. /// In that case client code will need to clean up it's open state, as no further callbacks will be called. /// If bFatal is false, the document is not entirely valid, but the parser is still able to continue. virtual void OnParsingError(ezStringView sMessage, bool bFatal, ezUInt32 uiLine, ezUInt32 uiColumn) { EZ_IGNORE_UNUSED(sMessage); EZ_IGNORE_UNUSED(bFatal); EZ_IGNORE_UNUSED(uiLine); EZ_IGNORE_UNUSED(uiColumn); } /// \brief Called when a new object is encountered. virtual void OnBeginObject(ezStringView sType, ezStringView sName, bool bGlobalName) = 0; /// \brief Called when the end of an object is encountered. virtual void OnEndObject() = 0; /// \brief Called when a new primitive object is encountered. virtual void OnBeginPrimitiveList(ezOpenDdlPrimitiveType type, ezStringView sName, bool bGlobalName) = 0; /// \brief Called when the end of a primitive object is encountered. virtual void OnEndPrimitiveList() = 0; /// \todo Currently not supported // virtual void OnBeginPrimitiveArrayList(ezOpenDdlPrimitiveType type, ezUInt32 uiGroupSize) = 0; // virtual void OnEndPrimitiveArrayList() = 0; /// \brief Called when boolean primitive data is available /// /// Multiple values may be reported at once for efficiency. bThisIsAll indicates if this is the final batch /// for the current primitive list. Implementations should accumulate data if bThisIsAll is false. virtual void OnPrimitiveBool(ezUInt32 count, const bool* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveInt8(ezUInt32 count, const ezInt8* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveInt16(ezUInt32 count, const ezInt16* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveInt32(ezUInt32 count, const ezInt32* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveInt64(ezUInt32 count, const ezInt64* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveUInt8(ezUInt32 count, const ezUInt8* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveUInt16(ezUInt32 count, const ezUInt16* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveUInt32(ezUInt32 count, const ezUInt32* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveUInt64(ezUInt32 count, const ezUInt64* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveFloat(ezUInt32 count, const float* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveDouble(ezUInt32 count, const double* pData, bool bThisIsAll) = 0; /// \brief Called when data for a primitive type is available. More than one value may be reported at a time. virtual void OnPrimitiveString(ezUInt32 count, const ezStringView* pData, bool bThisIsAll) = 0; private: enum State { Finished, Idle, ReadingBool, ReadingInt8, ReadingInt16, ReadingInt32, ReadingInt64, ReadingUInt8, ReadingUInt16, ReadingUInt32, ReadingUInt64, ReadingFloat, ReadingDouble, ReadingString, }; struct DdlState { DdlState() : m_State(Idle) { } DdlState(State s) : m_State(s) { } State m_State; }; void ReadNextByte(); bool ReadCharacter(); bool ReadCharacterSkipComments(); void SkipWhitespace(); void ContinueIdle(); void ReadIdentifier(ezUInt8* szString, ezUInt32& count); void ReadString(); void ReadWord(); ezUInt64 ReadDecimalLiteral(); void PurgeCachedPrimitives(bool bThisIsAll); bool ContinuePrimitiveList(); void ContinueString(); void SkipString(); void ContinueBool(); void ContinueInt(); void ContinueFloat(); void ReadDecimalFloat(); void ReadHexString(); ezHybridArray<DdlState, 32> m_StateStack; ezStreamReader* m_pInput; ezDynamicArray<ezUInt8> m_Cache; static constexpr ezUInt32 s_uiMaxIdentifierLength = 64; ezUInt8 m_uiCurByte; ezUInt8 m_uiNextByte; ezUInt32 m_uiCurLine; ezUInt32 m_uiCurColumn; bool m_bSkippingMode; bool m_bHadFatalParsingError; ezUInt8 m_szIdentifierType[s_uiMaxIdentifierLength]; ezUInt8 m_szIdentifierName[s_uiMaxIdentifierLength]; ezDynamicArray<ezUInt8> m_TempString; ezUInt32 m_uiTempStringLength; ezUInt32 m_uiNumCachedPrimitives; bool* m_pBoolCache; ezInt8* m_pInt8Cache; ezInt16* m_pInt16Cache; ezInt32* m_pInt32Cache; ezInt64* m_pInt64Cache; ezUInt8* m_pUInt8Cache; ezUInt16* m_pUInt16Cache; ezUInt32* m_pUInt32Cache; ezUInt64* m_pUInt64Cache; float* m_pFloatCache; double* m_pDoubleCache; };