Add base for calculation sizes of structs for StructuredDataDef

This commit is contained in:
Jan 2022-03-22 14:12:48 +01:00
parent c131c58bbe
commit 77420495f6
4 changed files with 190 additions and 1 deletions

View File

@ -3,6 +3,7 @@
#include <sstream> #include <sstream>
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
#include "StructuredDataDef/Parsing/StructuredDataDefSizeCalculator.h"
namespace sdd::def_scope_sequences 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) static void SetDefSizeFromRootStruct(const StructuredDataDefParserState* state)
{ {
if (state->m_current_def->m_root_type.m_category == CommonStructuredDataTypeCategory::STRUCT if (state->m_current_def->m_root_type.m_category == CommonStructuredDataTypeCategory::STRUCT
@ -242,7 +255,7 @@ namespace sdd::def_scope_sequences
CreateDefaultStructWhenNoStructsSpecified(state); CreateDefaultStructWhenNoStructsSpecified(state);
EnsureAllUsedTypesHaveBeenDefined(state); EnsureAllUsedTypesHaveBeenDefined(state);
ReplaceUndefinedTypeReference(state); ReplaceUndefinedTypeReference(state);
// TODO: Calculate struct sizes and property offsets CalculateSizesAndOffsetsForDef(state);
SetDefSizeFromRootStruct(state); SetDefSizeFromRootStruct(state);
if (!state->m_checksum_overriden) if (!state->m_checksum_overriden)

View File

@ -0,0 +1,143 @@
#include "StructuredDataDefSizeCalculator.h"
#include <cassert>
#include <sstream>
#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<CommonStructuredDataType> m_type_stack;
std::vector<bool> m_struct_in_calculation;
std::vector<bool> m_struct_calculated;
std::vector<bool> m_indexed_array_calculated;
std::vector<bool> 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();
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <string>
#include <exception>
#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);
};
}

View File

@ -16,10 +16,16 @@
#undef _NODISCARD #undef _NODISCARD
#endif #endif
#ifdef _NORETURN
#undef _NORETURN
#endif
#if _CPP_VERSION >= 201703L #if _CPP_VERSION >= 201703L
#define _NODISCARD [[nodiscard]] #define _NODISCARD [[nodiscard]]
#define _NORETURN [[noreturn]]
#else #else
#define _NODISCARD #define _NODISCARD
#define _NORETURN
#endif #endif
template <class T> template <class T>