mirror of
				https://github.com/Laupetin/OpenAssetTools.git
				synced 2025-10-30 18:17:15 +00:00 
			
		
		
		
	When parsing StructuredDataDefs accept undefined types
This commit is contained in:
		| @@ -31,7 +31,9 @@ namespace sdd::def_scope_sequences | ||||
|         { | ||||
|             assert(state->m_current_def); | ||||
|  | ||||
|             auto newEnum = std::make_unique<CommonStructuredDataEnum>(result.NextCapture(CAPTURE_NAME).IdentifierValue()); | ||||
|             const auto& nameToken = result.NextCapture(CAPTURE_NAME); | ||||
|             auto newEnum = std::make_unique<CommonStructuredDataEnum>(nameToken.IdentifierValue()); | ||||
|             const auto newEnumIndex = state->m_current_def->m_enums.size(); | ||||
|             if (result.HasNextCapture(CAPTURE_RESERVED_COUNT)) | ||||
|             { | ||||
|                 const auto& reservedCountToken = result.NextCapture(CAPTURE_RESERVED_COUNT); | ||||
| @@ -41,8 +43,18 @@ namespace sdd::def_scope_sequences | ||||
|                     throw ParsingException(reservedCountToken.GetPos(), "Reserved enum entry count must be greater than zero"); | ||||
|             } | ||||
|  | ||||
|             const auto existingType = state->m_def_types_by_name.find(newEnum->m_name); | ||||
|             if (existingType != state->m_def_types_by_name.end()) | ||||
|             { | ||||
|                 if (existingType->second.m_category == CommonStructuredDataTypeCategory::UNKNOWN) | ||||
|                     existingType->second = CommonStructuredDataType(CommonStructuredDataTypeCategory::ENUM, newEnumIndex); | ||||
|                 else | ||||
|                     throw ParsingException(nameToken.GetPos(), "Type with this name has already been defined"); | ||||
|             } | ||||
|             else | ||||
|                 state->m_def_types_by_name.emplace(newEnum->m_name, CommonStructuredDataType(CommonStructuredDataTypeCategory::ENUM, newEnumIndex)); | ||||
|  | ||||
|             state->m_current_enum = newEnum.get(); | ||||
|             state->m_def_types_by_name.emplace(newEnum->m_name, CommonStructuredDataType(CommonStructuredDataTypeCategory::ENUM, state->m_current_def->m_enums.size())); | ||||
|             state->m_current_def->m_enums.emplace_back(std::move(newEnum)); | ||||
|         } | ||||
|     }; | ||||
| @@ -68,22 +80,33 @@ namespace sdd::def_scope_sequences | ||||
|         { | ||||
|             assert(state->m_current_def); | ||||
|  | ||||
|             auto newStruct = std::make_unique<CommonStructuredDataStruct>(result.NextCapture(CAPTURE_NAME).IdentifierValue()); | ||||
|             const auto& nameToken = result.NextCapture(CAPTURE_NAME); | ||||
|             auto newStruct = std::make_unique<CommonStructuredDataStruct>(nameToken.IdentifierValue()); | ||||
|             auto* newStructPtr = newStruct.get(); | ||||
|             const auto newStructIndex = state->m_current_def->m_structs.size(); | ||||
|  | ||||
|             const auto existingType = state->m_def_types_by_name.find(newStruct->m_name); | ||||
|             if (existingType != state->m_def_types_by_name.end()) | ||||
|             { | ||||
|                 if (existingType->second.m_category == CommonStructuredDataTypeCategory::UNKNOWN) | ||||
|                     existingType->second = CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, newStructIndex); | ||||
|                 else | ||||
|                     throw ParsingException(nameToken.GetPos(), "Type with this name has already been defined"); | ||||
|             } | ||||
|             else | ||||
|                 state->m_def_types_by_name.emplace(newStruct->m_name, CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, newStructIndex)); | ||||
|  | ||||
|             state->m_current_struct = newStructPtr; | ||||
|             state->m_def_types_by_name.emplace(newStruct->m_name, CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, newStructIndex)); | ||||
|             state->m_current_def->m_structs.emplace_back(std::move(newStruct)); | ||||
|             state->m_current_struct_offset_in_bits = 0; | ||||
|             state->m_current_struct_padding_offset = 0; | ||||
|  | ||||
|             if (newStructPtr->m_name == "root") | ||||
|             { | ||||
|                 state->m_current_struct_offset_in_bits = 64u; | ||||
|                 state->m_current_struct_padding_offset = 64u; | ||||
|                 state->m_current_def->m_root_type = CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, newStructIndex); | ||||
|             } | ||||
|             else | ||||
|                 state->m_current_struct_offset_in_bits = 0; | ||||
|                 state->m_current_struct_padding_offset = 0; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -154,9 +177,11 @@ namespace sdd::def_scope_sequences | ||||
|             assert(state->m_current_struct == nullptr); | ||||
|  | ||||
|             CreateDefaultStructWhenNoStructsSpecified(state); | ||||
|             // TODO: Replace all unknown type references | ||||
|             // TODO: Calculate struct sizes and property offsets | ||||
|             SetDefSizeFromRootStruct(state); | ||||
|  | ||||
|             if(!state->m_checksum_overriden) | ||||
|             if (!state->m_checksum_overriden) | ||||
|                 state->m_current_def->m_checksum = state->m_current_def->CalculateChecksum(); | ||||
|             else | ||||
|                 state->m_current_def->m_checksum = state->m_checksum_override_value; | ||||
| @@ -175,7 +200,7 @@ using namespace sdd; | ||||
| using namespace def_scope_sequences; | ||||
|  | ||||
| StructuredDataDefScopeSequences::StructuredDataDefScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, | ||||
|                                                                        std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences) | ||||
|                                                                  std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences) | ||||
|     : AbstractScopeSequenceHolder(allSequences, scopeSequences) | ||||
| { | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include <algorithm> | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
| #include "Utils/Alignment.h" | ||||
|  | ||||
| namespace sdd::struct_scope_sequences | ||||
| { | ||||
| @@ -65,69 +66,45 @@ namespace sdd::struct_scope_sequences | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         static CommonStructuredDataType ProcessType(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result, size_t& currentSize, size_t& currentBitAlign) | ||||
|         static CommonStructuredDataType ProcessType(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) | ||||
|         { | ||||
|             const auto typeTag = result.NextTag(); | ||||
|  | ||||
|             switch (typeTag) | ||||
|             { | ||||
|             case TAG_TYPE_INT: | ||||
|                 currentSize = 32; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::INT); | ||||
|             case TAG_TYPE_BYTE: | ||||
|                 currentSize = 8; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::BYTE); | ||||
|             case TAG_TYPE_BOOL: | ||||
|                 currentSize = 1; | ||||
|                 currentBitAlign = 0; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::BOOL); | ||||
|             case TAG_TYPE_FLOAT: | ||||
|                 currentSize = 32; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::FLOAT); | ||||
|             case TAG_TYPE_SHORT: | ||||
|                 currentSize = 16; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::SHORT); | ||||
|             case TAG_TYPE_STRING: | ||||
|                 { | ||||
|                     currentBitAlign = 8; | ||||
|                     const auto& stringLengthToken = result.NextCapture(CAPTURE_STRING_LENGTH); | ||||
|                     const auto stringLength = stringLengthToken.IntegerValue(); | ||||
|  | ||||
|                     if (stringLength <= 0) | ||||
|                         throw ParsingException(stringLengthToken.GetPos(), "String length must be greater than zero"); | ||||
|  | ||||
|                     currentSize = stringLength * 8; | ||||
|                     return {CommonStructuredDataTypeCategory::STRING, static_cast<size_t>(stringLength)}; | ||||
|                 } | ||||
|             case TAG_TYPE_NAMED: | ||||
|                 { | ||||
|                     currentBitAlign = 8; | ||||
|                     const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE_NAME); | ||||
|                     const auto typeName = typeNameToken.IdentifierValue(); | ||||
|  | ||||
|                     const auto existingType = state->m_def_types_by_name.find(typeName); | ||||
|                     if (existingType == state->m_def_types_by_name.end()) | ||||
|                         throw ParsingException(typeNameToken.GetPos(), "No type defined under this name"); | ||||
|  | ||||
|                     if (existingType->second.m_category == CommonStructuredDataTypeCategory::STRUCT) | ||||
|                     { | ||||
|                         assert(existingType->second.m_info.type_index < state->m_current_def->m_structs.size()); | ||||
|                         const auto* _struct = state->m_current_def->m_structs[existingType->second.m_info.type_index].get(); | ||||
|                         currentSize = _struct->m_size_in_byte * 8; | ||||
|                     } | ||||
|                     else if (existingType->second.m_category == CommonStructuredDataTypeCategory::ENUM) | ||||
|                     { | ||||
|                         assert(existingType->second.m_info.type_index < state->m_current_def->m_enums.size()); | ||||
|                         currentSize = 16; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         assert(false); | ||||
|                         currentSize = 0; | ||||
|                         const auto undefinedTypeIndex = state->m_undefined_types.size(); | ||||
|                         const CommonStructuredDataType undefinedType(CommonStructuredDataTypeCategory::UNKNOWN, undefinedTypeIndex); | ||||
|                         state->m_undefined_types.emplace_back(typeName, typeNameToken.GetPos()); | ||||
|                         state->m_def_types_by_name.emplace(std::make_pair(typeName, undefinedType)); | ||||
|                         return undefinedType; | ||||
|                     } | ||||
|  | ||||
|                     return existingType->second; | ||||
| @@ -137,11 +114,8 @@ namespace sdd::struct_scope_sequences | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static CommonStructuredDataType ProcessArray(StructuredDataDefParserState* state, const SimpleParserValue& arrayToken, const CommonStructuredDataType currentType, | ||||
|                                                      size_t& currentSize, size_t& currentBitAlign) | ||||
|         static CommonStructuredDataType ProcessArray(StructuredDataDefParserState* state, const SimpleParserValue& arrayToken, const CommonStructuredDataType currentType) | ||||
|         { | ||||
|             currentBitAlign = 8; | ||||
|  | ||||
|             if (arrayToken.m_type == SimpleParserValueType::INTEGER) | ||||
|             { | ||||
|                 const auto arrayElementCount = arrayToken.IntegerValue(); | ||||
| @@ -149,8 +123,6 @@ namespace sdd::struct_scope_sequences | ||||
|                 if (arrayElementCount <= 0) | ||||
|                     throw ParsingException(arrayToken.GetPos(), "Array size must be greater than zero"); | ||||
|  | ||||
|                 currentSize *= arrayElementCount; | ||||
|  | ||||
|                 const CommonStructuredDataIndexedArray indexedArray(currentType, arrayElementCount); | ||||
|  | ||||
|                 const auto existingIndexedArray = state->m_def_indexed_arrays.find(indexedArray); | ||||
| @@ -177,7 +149,6 @@ namespace sdd::struct_scope_sequences | ||||
|  | ||||
|                 const auto enumElementCount = _enum->ElementCount(); | ||||
|                 assert(enumElementCount > 0); | ||||
|                 currentSize *= enumElementCount; | ||||
|  | ||||
|                 const CommonStructuredDataEnumedArray enumedArray(currentType, existingType->second.m_info.type_index); | ||||
|  | ||||
| @@ -199,22 +170,16 @@ namespace sdd::struct_scope_sequences | ||||
|             assert(state->m_current_def != nullptr); | ||||
|             assert(state->m_current_struct != nullptr); | ||||
|  | ||||
|             size_t currentSize = 0; | ||||
|             size_t currentAlign = 0; | ||||
|             auto currentType = ProcessType(state, result, currentSize, currentAlign); | ||||
|             auto currentType = ProcessType(state, result); | ||||
|  | ||||
|             std::vector<std::reference_wrapper<const SimpleParserValue>> arrayTokens; | ||||
|             while (result.HasNextCapture(CAPTURE_ARRAY_SIZE)) | ||||
|                 arrayTokens.emplace_back(result.NextCapture(CAPTURE_ARRAY_SIZE)); | ||||
|  | ||||
|             for (auto i = arrayTokens.rbegin(); i != arrayTokens.rend(); ++i) | ||||
|                 currentType = ProcessArray(state, i->get(), currentType, currentSize, currentAlign); | ||||
|                 currentType = ProcessArray(state, i->get(), currentType); | ||||
|  | ||||
|             if (currentAlign > 0) | ||||
|                 state->m_current_struct_offset_in_bits = (state->m_current_struct_offset_in_bits + currentAlign - 1) / currentAlign * currentAlign; | ||||
|  | ||||
|             state->m_current_struct->m_properties.emplace_back(result.NextCapture(CAPTURE_ENTRY_NAME).IdentifierValue(), currentType, state->m_current_struct_offset_in_bits); | ||||
|             state->m_current_struct_offset_in_bits += currentSize; | ||||
|             state->m_current_struct->m_properties.emplace_back(result.NextCapture(CAPTURE_ENTRY_NAME).IdentifierValue(), currentType, state->m_current_struct_padding_offset); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -245,11 +210,7 @@ namespace sdd::struct_scope_sequences | ||||
|             if (paddingValue <= 0) | ||||
|                 throw ParsingException(paddingValueToken.GetPos(), "Padding value must be greater than 0"); | ||||
|  | ||||
|             // Align to next byte | ||||
|             state->m_current_struct_offset_in_bits = (state->m_current_struct_offset_in_bits + 7) / 8 * 8; | ||||
|  | ||||
|             // Add padding value to current size | ||||
|             state->m_current_struct_offset_in_bits += static_cast<size_t>(paddingValue); | ||||
|             state->m_current_struct_padding_offset += paddingValue * 8; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -271,20 +232,11 @@ namespace sdd::struct_scope_sequences | ||||
|         { | ||||
|             assert(state->m_current_struct != nullptr); | ||||
|  | ||||
|             // Set the size of the finalized struct | ||||
|             if (!state->m_current_struct->m_properties.empty()) | ||||
|                 state->m_current_struct->m_size_in_byte = (state->m_current_struct_offset_in_bits + 7) / 8; | ||||
|             else | ||||
|                 state->m_current_struct->m_size_in_byte = 0u; | ||||
|  | ||||
|             state->m_current_struct_offset_in_bits = 0u; | ||||
|             state->m_current_struct->m_size_in_byte = utils::Align(state->m_current_struct_padding_offset, 8u) / 8; | ||||
|             state->m_current_struct_padding_offset = 0u; | ||||
|  | ||||
|             // Sort the entries of the struct alphabetically | ||||
|             std::sort(state->m_current_struct->m_properties.begin(), state->m_current_struct->m_properties.end(), | ||||
|                       [](const CommonStructuredDataStructProperty& e1, const CommonStructuredDataStructProperty& e2) | ||||
|                       { | ||||
|                           return e1.m_name < e2.m_name; | ||||
|                       }); | ||||
|             state->m_current_struct->SortPropertiesByName(); | ||||
|             state->m_current_struct = nullptr; | ||||
|         } | ||||
|     }; | ||||
|   | ||||
| @@ -2,11 +2,20 @@ | ||||
|  | ||||
| using namespace sdd; | ||||
|  | ||||
| UndefinedType::UndefinedType() | ||||
| = default; | ||||
|  | ||||
| UndefinedType::UndefinedType(std::string name, const TokenPos firstUsagePos) | ||||
|     : m_name(std::move(name)), | ||||
|       m_first_usage_pos(firstUsagePos) | ||||
| { | ||||
| } | ||||
|  | ||||
| StructuredDataDefParserState::StructuredDataDefParserState() | ||||
|     : m_current_def(nullptr), | ||||
|       m_current_enum(nullptr), | ||||
|       m_current_struct(nullptr), | ||||
|       m_current_struct_offset_in_bits(0u), | ||||
|       m_current_struct_padding_offset(0u), | ||||
|       m_checksum_override_value(0u), | ||||
|       m_checksum_overriden(false) | ||||
| { | ||||
|   | ||||
| @@ -4,11 +4,24 @@ | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <cstddef> | ||||
| #include <string> | ||||
|  | ||||
| #include "Parsing/TokenPos.h" | ||||
| #include "StructuredDataDef/CommonStructuredDataDef.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class UndefinedType | ||||
|     { | ||||
|     public: | ||||
|         std::string m_name; | ||||
|         TokenPos m_first_usage_pos; | ||||
|         CommonStructuredDataType m_mapped_type; | ||||
|  | ||||
|         UndefinedType(); | ||||
|         UndefinedType(std::string name, TokenPos firstUsagePos); | ||||
|     }; | ||||
|  | ||||
|     class StructuredDataDefParserState | ||||
|     { | ||||
|     public: | ||||
| @@ -17,7 +30,8 @@ namespace sdd | ||||
|         CommonStructuredDataDef* m_current_def; | ||||
|         CommonStructuredDataEnum* m_current_enum; | ||||
|         CommonStructuredDataStruct* m_current_struct; | ||||
|         size_t m_current_struct_offset_in_bits; | ||||
|  | ||||
|         size_t m_current_struct_padding_offset; | ||||
|  | ||||
|         size_t m_checksum_override_value; | ||||
|         bool m_checksum_overriden; | ||||
| @@ -25,6 +39,7 @@ namespace sdd | ||||
|         std::map<std::string, CommonStructuredDataType> m_def_types_by_name; | ||||
|         std::map<CommonStructuredDataIndexedArray, size_t> m_def_indexed_arrays; | ||||
|         std::map<CommonStructuredDataEnumedArray, size_t> m_def_enumed_arrays; | ||||
|         std::vector<UndefinedType> m_undefined_types; | ||||
|  | ||||
|         StructuredDataDefParserState(); | ||||
|     }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user