From 5afbc014dae84a6905f8e20e88ace3f6d9357156 Mon Sep 17 00:00:00 2001 From: dpeter99 Date: Fri, 27 May 2022 21:16:05 +0200 Subject: [PATCH] Reworked SFF parser --- projs/shadow-file-format-test/test.cpp | 188 +++++++++++++++++- projs/shadow-file-format/SFFElement.natvis | 24 +++ .../shadow-file-format.vcxproj | 6 +- .../shadow-file-format.vcxproj.filters | 24 +-- projs/shadow-file-format/src/SFFElement.ixx | 6 +- projs/shadow-file-format/src/SFFParser.ixx | 68 ++++--- 6 files changed, 259 insertions(+), 57 deletions(-) create mode 100644 projs/shadow-file-format/SFFElement.natvis diff --git a/projs/shadow-file-format-test/test.cpp b/projs/shadow-file-format-test/test.cpp index e140181..8122793 100644 --- a/projs/shadow-file-format-test/test.cpp +++ b/projs/shadow-file-format-test/test.cpp @@ -2,23 +2,197 @@ import Shadow.FileFormat; -std::string example_str = "ShadowFileFormat_1_0_0 \n\ +std::string example_empty = "ShadowFileFormat_1_0_0"; + +std::string example_simple = "ShadowFileFormat_1_0_0 \n\ Assets:{ \ - 9:textures / cube_maps / ame_ash / ashcanyon.sff, \ - 10 : textures / models / checker_board.sff, \ - 12 : shaders / skybox / skybox.sff, \ -} \ + 9:Content_9, \ + 10 : Content_10, \ + 11: Content_11, \ +}, \ +"; + +std::string example_multi_root = +"ShadowFileFormat_1_0_0 \n \ +Assets:{ \ + 9:Content_9, \ +}, \ +Texture:{ \ + texture:checker_board.png, \ +}, \ "; -TEST(TestCaseName, TestName) { +std::string example_multi_level = "ShadowFileFormat_1_0_0 \n\ +Assets:{ \ + 9: { \ + \ + }, \ +}, \ +"; +std::stringstream streamFrom(std::string str) { std::stringstream ss; - ss << example_str; + ss << str; + + return ss; +} + +TEST(EmptyFile, HasHeader) { + + std::stringstream ss = streamFrom(example_empty); auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); auto assets = a->GetChildByIndex(0); + EXPECT_EQ(assets, nullptr); +} + + +TEST(SimpleFile, SingleRoot) { + + std::stringstream ss = streamFrom(example_simple); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + EXPECT_EQ(a->children.size(), 1); + + + auto assets = a->GetChildByIndex(0); + + EXPECT_NE(assets, nullptr); EXPECT_STREQ(assets->name.c_str(), "Assets"); +} + +TEST(SimpleFile, RootByName) { + + std::stringstream ss = streamFrom(example_simple); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByName("Assets"); + + EXPECT_NE(assets, nullptr); + EXPECT_STREQ(assets->name.c_str(), "Assets"); +} + +TEST(SimpleFile, SubChildren) { + + std::stringstream ss = streamFrom(example_simple); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByIndex(0); + + EXPECT_EQ(assets->children.size(), 3); +} + +TEST(SimpleFile, SubChildrenExist) { + + std::stringstream ss = streamFrom(example_simple); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByIndex(0); + + + for (size_t i = 0; i < 3; i++) + { + auto i9 = assets->GetChildByName(std::to_string(9+i)); + EXPECT_NE(i9, nullptr); + } + +} + +TEST(SimpleFile, SubChildrenContent) { + + std::stringstream ss = streamFrom(example_simple); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByIndex(0); + + + for (size_t i = 0; i < 3; i++) + { + std::string name = std::to_string(9 + i); + auto i9 = assets->GetChildByName(name); + EXPECT_EQ(i9->value, "Content_"+ name); + } + +} + + +TEST(MultiLevel, SinlgeRootExists) { + + std::stringstream ss = streamFrom(example_multi_level); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + EXPECT_EQ(a->children.size(), 1); +} + +TEST(MultiLevel, SecondLevelExists) { + + std::stringstream ss = streamFrom(example_multi_level); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto asset = a->GetChildByIndex(0); + + EXPECT_EQ(asset->children.size(), 1); +} + +TEST(MultiLevel, BlockTagIsCorrect) { + + std::stringstream ss = streamFrom(example_multi_level); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByIndex(0); + EXPECT_EQ(assets->isBlock, true); + + auto element = assets->GetChildByIndex(0); + EXPECT_EQ(element->isBlock, true); +} + +TEST(MultiLevel, LevelsHaveCorrectName) { + + std::stringstream ss = streamFrom(example_multi_level); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByIndex(0); + EXPECT_EQ(assets->name, "Assets"); + + auto element = assets->GetChildByIndex(0); + EXPECT_EQ(element->name, "9"); +} + + +TEST(MultiRoot, RootsExist) { + + std::stringstream ss = streamFrom(example_multi_root); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + EXPECT_EQ(a->children.size(), 2); +} + +TEST(MultiRoot, RootsHaveCorrectName) { + + std::stringstream ss = streamFrom(example_multi_root); + + auto a = Shadow::SFF::SFFParser::ReadFromStream(ss); + + auto assets = a->GetChildByName("Assets"); + + EXPECT_NE(assets, nullptr); + EXPECT_EQ(assets->name, "Assets"); + + auto texture = a->GetChildByName("Texture"); + + EXPECT_NE(texture, nullptr); + EXPECT_EQ(texture->name, "Texture"); } \ No newline at end of file diff --git a/projs/shadow-file-format/SFFElement.natvis b/projs/shadow-file-format/SFFElement.natvis new file mode 100644 index 0000000..8039962 --- /dev/null +++ b/projs/shadow-file-format/SFFElement.natvis @@ -0,0 +1,24 @@ + + + + {{Name = {name} Parent={parent->name} Children={children} }} + {{Name = {name} Children={children} }} + + + + parent + name + isBlock + + + children._Mypair._Myval2._Myval2._Mysize + children._Mypair._Myval2._Myval2._Myhead->_Parent + _Left + _Right + _Myval.second,view(MapHelper) + + + + + + \ No newline at end of file diff --git a/projs/shadow-file-format/shadow-file-format.vcxproj b/projs/shadow-file-format/shadow-file-format.vcxproj index c6578f5..9287768 100644 --- a/projs/shadow-file-format/shadow-file-format.vcxproj +++ b/projs/shadow-file-format/shadow-file-format.vcxproj @@ -26,19 +26,19 @@ - - - {7b9e6056-e4fb-411b-9612-a2fd679c2b69} + + + diff --git a/projs/shadow-file-format/shadow-file-format.vcxproj.filters b/projs/shadow-file-format/shadow-file-format.vcxproj.filters index f5fb9e6..beff2f9 100644 --- a/projs/shadow-file-format/shadow-file-format.vcxproj.filters +++ b/projs/shadow-file-format/shadow-file-format.vcxproj.filters @@ -21,25 +21,18 @@ Source Files - - Source Files - Source Files Source Files - - + + + + - - Header Files - - - Header Files - Header Files @@ -55,11 +48,8 @@ Header Files - - Header Files - - - Header Files - + + + \ No newline at end of file diff --git a/projs/shadow-file-format/src/SFFElement.ixx b/projs/shadow-file-format/src/SFFElement.ixx index 85a7112..9fdbebb 100644 --- a/projs/shadow-file-format/src/SFFElement.ixx +++ b/projs/shadow-file-format/src/SFFElement.ixx @@ -20,8 +20,7 @@ import ; std::string value; typedef std::map ChildrenMap; - std::list properties_old; - std::map children; + ChildrenMap children; std::string GetStringProperty(std::string name); @@ -33,6 +32,9 @@ import ; SFFElement* GetChildByIndex(int index) { ChildrenMap::iterator it = children.begin(); + if (it == children.end()) + return nullptr; + for (size_t i = 0; i < index; i++) { it++; diff --git a/projs/shadow-file-format/src/SFFParser.ixx b/projs/shadow-file-format/src/SFFParser.ixx index 9ea2d43..b71f74a 100644 --- a/projs/shadow-file-format/src/SFFParser.ixx +++ b/projs/shadow-file-format/src/SFFParser.ixx @@ -28,12 +28,13 @@ namespace Shadow::SFF { //The current node that we are building auto* context = new SFFElement; + context->name = "root"; //Top level Element SFFElement* base = context; //The new node that will be a child of the context - auto* current = new SFFElement; + SFFElement* current = nullptr; std::string buffer; @@ -42,52 +43,63 @@ namespace Shadow::SFF { while (!stream.eof()) { stream.get(c); - if (c == ':') - { + + switch (c) { + case ':': //The stuff in the buffer is a parameter name - std::cout << "Name: " << buffer; + //std::cout << "Name: " << buffer; + current = new SFFElement; current->name = buffer; + current->parent = context; + buffer = ""; - } - else if (c == '{') - { + break; + + case '{': //Start of a new block current->isBlock = true; - current->parent = context; - context->children[current->name] = current; context = current; - current = new SFFElement; - } - else if (c == ',') - { + current = nullptr; + break; + + case ',': // End of a property - //The stuff is the value - std::cout << "Value: " << buffer << std::endl; - current->value = buffer; - current->parent = context; - current->isBlock = false; + if (!current->isBlock) { + //The stuff is the value + current->value = buffer; + current->parent = context; + current->isBlock = false; + } buffer = ""; context->children[current->name] = current; - current = new SFFElement(); - } - else if (c == '}') - { - // End of a block - context = context->parent; - } - else - { + current = nullptr; + break; + + case '}': + if (current != nullptr) { + // End of a block + current->parent = context; + context->children[current->name] = current; + } + current = context; + context = current->parent; + + break; + + default: if (std::isspace(c) == 0) { buffer += c; } + break; } + } - std::cout << "END" << std::endl; + //std::cout << "END" << std::endl; return base; }