diff --git a/src/ObjLoading/StructuredDataDef/Parsing/Sequence/StructuredDataDefScopeSequences.cpp b/src/ObjLoading/StructuredDataDef/Parsing/Sequence/StructuredDataDefScopeSequences.cpp index e532c204..a9a6c1e7 100644 --- a/src/ObjLoading/StructuredDataDef/Parsing/Sequence/StructuredDataDefScopeSequences.cpp +++ b/src/ObjLoading/StructuredDataDef/Parsing/Sequence/StructuredDataDefScopeSequences.cpp @@ -3,6 +3,7 @@ #include #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.h" namespace sdd::def_scope_sequences { @@ -223,6 +224,18 @@ namespace sdd::def_scope_sequences } } + static void CalculateSizesAndOffsetsForDef(const StructuredDataDefParserState* state) + { + try + { + StructuredDataDefSizeCalculator::CalculateSizesAndOffsetsForDef(*state->m_current_def); + } + catch(SizeCalculationException& e) + { + throw ParsingException(TokenPos(), e.Message()); + } + } + static void SetDefSizeFromRootStruct(const StructuredDataDefParserState* state) { if (state->m_current_def->m_root_type.m_category == CommonStructuredDataTypeCategory::STRUCT @@ -242,7 +255,7 @@ namespace sdd::def_scope_sequences CreateDefaultStructWhenNoStructsSpecified(state); EnsureAllUsedTypesHaveBeenDefined(state); ReplaceUndefinedTypeReference(state); - // TODO: Calculate struct sizes and property offsets + CalculateSizesAndOffsetsForDef(state); SetDefSizeFromRootStruct(state); if (!state->m_checksum_overriden) diff --git a/src/ObjLoading/StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.cpp b/src/ObjLoading/StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.cpp new file mode 100644 index 00000000..552849dd --- /dev/null +++ b/src/ObjLoading/StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.cpp @@ -0,0 +1,143 @@ +#include "StructuredDataDefSizeCalculator.h" + +#include +#include + +#include "Utils/ClassUtils.h" + +using namespace sdd; + +SizeCalculationException::SizeCalculationException(std::string message) + : m_message(std::move(message)) +{ +} + +const std::string& SizeCalculationException::Message() const +{ + return m_message; +} + +char const* SizeCalculationException::what() const +{ + return m_message.c_str(); +} + +class StructuredDataDefSizeCalculatorInternal +{ + CommonStructuredDataDef& m_def; + std::vector m_type_stack; + std::vector m_struct_in_calculation; + std::vector m_struct_calculated; + std::vector m_indexed_array_calculated; + std::vector m_enumed_array_calculated; + + _NORETURN void ThrowCircularDependencyException(const size_t structIndex) const + { + assert(structIndex < m_def.m_structs.size()); + + std::ostringstream ss; + + ss << "Circular dependencies detected: "; + + auto foundDependencyChainStart = false; + for(const auto& type : m_type_stack) + { + if(foundDependencyChainStart) + { + if(type.m_category == CommonStructuredDataTypeCategory::STRUCT) + { + assert(type.m_info.type_index < m_def.m_structs.size()); + ss << " -> " << m_def.m_structs[type.m_info.type_index]->m_name; + } + } + else if (type.m_category == CommonStructuredDataTypeCategory::STRUCT && type.m_info.type_index == structIndex) + { + foundDependencyChainStart = true; + ss << m_def.m_structs[structIndex]->m_name; + } + } + + ss << " -> " << m_def.m_structs[structIndex]->m_name; + + throw SizeCalculationException(ss.str()); + } + + void CalculateForStruct(const size_t index, CommonStructuredDataStruct& _struct) + { + if (m_struct_calculated[index]) + return; + + if (m_struct_in_calculation[index]) + ThrowCircularDependencyException(index); + m_struct_in_calculation[index] = true; + + m_type_stack.emplace_back(CommonStructuredDataTypeCategory::STRUCT, index); + + // TODO: Actually calculate stuff + + m_struct_calculated[index] = true; + m_type_stack.pop_back(); + } + + void CalculateForIndexedArray(size_t index, CommonStructuredDataIndexedArray& indexedArray) + { + // TODO: Actually calculate stuff + } + + void CalculateForEnumedArray(size_t index, CommonStructuredDataEnumedArray& enumedArray) + { + // TODO: Actually calculate stuff + } + + void CalculateForType(const CommonStructuredDataType type) + { + switch (type.m_category) + { + case CommonStructuredDataTypeCategory::STRUCT: + assert(type.m_info.type_index < m_def.m_structs.size()); + CalculateForStruct(type.m_info.type_index, *m_def.m_structs[type.m_info.type_index]); + break; + case CommonStructuredDataTypeCategory::INDEXED_ARRAY: + assert(type.m_info.type_index < m_def.m_indexed_arrays.size()); + CalculateForIndexedArray(type.m_info.type_index, m_def.m_indexed_arrays[type.m_info.type_index]); + break; + case CommonStructuredDataTypeCategory::ENUM_ARRAY: + assert(type.m_info.type_index < m_def.m_enumed_arrays.size()); + CalculateForEnumedArray(type.m_info.type_index, m_def.m_enumed_arrays[type.m_info.type_index]); + break; + default: + break; + } + } + +public: + explicit StructuredDataDefSizeCalculatorInternal(CommonStructuredDataDef& def) + : m_def(def), + m_struct_in_calculation(def.m_structs.size()), + m_struct_calculated(def.m_structs.size()), + m_indexed_array_calculated(def.m_indexed_arrays.size()), + m_enumed_array_calculated(def.m_enumed_arrays.size()) + { + } + + void CalculateSizesAndOffsets() + { + auto index = 0u; + for (auto& _struct : m_def.m_structs) + CalculateForStruct(index++, *_struct); + + index = 0u; + for (auto& indexedArray : m_def.m_indexed_arrays) + CalculateForIndexedArray(index++, indexedArray); + + index = 0u; + for (auto& enumedArray : m_def.m_enumed_arrays) + CalculateForEnumedArray(index++, enumedArray); + } +}; + +void StructuredDataDefSizeCalculator::CalculateSizesAndOffsetsForDef(CommonStructuredDataDef& def) +{ + StructuredDataDefSizeCalculatorInternal calculator(def); + calculator.CalculateSizesAndOffsets(); +} diff --git a/src/ObjLoading/StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.h b/src/ObjLoading/StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.h new file mode 100644 index 00000000..b3721cf8 --- /dev/null +++ b/src/ObjLoading/StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include "Utils/ClassUtils.h" +#include "StructuredDataDef/CommonStructuredDataDef.h" + +namespace sdd +{ + class SizeCalculationException final : std::exception + { + std::string m_message; + + public: + explicit SizeCalculationException(std::string message); + + _NODISCARD const std::string& Message() const; + _NODISCARD char const* what() const override; + }; + + class StructuredDataDefSizeCalculator + { + public: + static void CalculateSizesAndOffsetsForDef(CommonStructuredDataDef& def); + }; +} diff --git a/src/Utils/Utils/ClassUtils.h b/src/Utils/Utils/ClassUtils.h index 4216d4a0..8fd50645 100644 --- a/src/Utils/Utils/ClassUtils.h +++ b/src/Utils/Utils/ClassUtils.h @@ -16,10 +16,16 @@ #undef _NODISCARD #endif +#ifdef _NORETURN +#undef _NORETURN +#endif + #if _CPP_VERSION >= 201703L #define _NODISCARD [[nodiscard]] +#define _NORETURN [[noreturn]] #else #define _NODISCARD +#define _NORETURN #endif template