Reworked SFF parser

This commit is contained in:
dpeter99 2022-05-27 21:16:05 +02:00
parent 10625e731a
commit 5afbc014da
6 changed files with 259 additions and 57 deletions

View File

@ -2,23 +2,197 @@
import Shadow.FileFormat; 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:{ \ Assets:{ \
9:textures / cube_maps / ame_ash / ashcanyon.sff, \ 9:Content_9, \
10 : textures / models / checker_board.sff, \ 10 : Content_10, \
12 : shaders / skybox / skybox.sff, \ 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; 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 a = Shadow::SFF::SFFParser::ReadFromStream(ss);
auto assets = a->GetChildByIndex(0); 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"); 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");
} }

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="Shadow::SFF::SFFElement">
<DisplayString Condition="parent != 0">{{Name = {name} Parent={parent->name} Children={children} }}</DisplayString>
<DisplayString>{{Name = {name} Children={children} }}</DisplayString>
<Expand>
<Item Name="Parent" Condition="parent != 0">parent</Item>
<Item Name="Name">name</Item>
<Item Name="Block">isBlock</Item>
<TreeItems>
<Size>children._Mypair._Myval2._Myval2._Mysize</Size>
<HeadPointer>children._Mypair._Myval2._Myval2._Myhead->_Parent</HeadPointer>
<LeftPointer>_Left</LeftPointer>
<RightPointer>_Right</RightPointer>
<ValueNode Condition="_Isnil == 0" Name="[{_Myval.first}]">_Myval.second,view(MapHelper)</ValueNode>
</TreeItems>
</Expand>
</Type>
</AutoVisualizer>

View File

@ -26,19 +26,19 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="src/SFFElement.cpp" /> <ClCompile Include="src/SFFElement.cpp" />
<ClCompile Include="src/SFFParser.cpp" /> <ClCompile Include="src/SFFParser.cpp" />
<ClCompile Include="src/SFFElement.ixx" /> <ClCompile Include="src/SFFElement.ixx" />
<ClCompile Include="src/Shadow.FileFormat.ixx" /> <ClCompile Include="src/Shadow.FileFormat.ixx" />
<ClCompile Include="src/SFFParser.ixx" /> <ClCompile Include="src/SFFParser.ixx" />
<ClCompile Include="src/SFFVersion.ixx" /> <ClCompile Include="src/SFFVersion.ixx" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\shadow-utility\shadow-utility.vcxproj"> <ProjectReference Include="..\shadow-utility\shadow-utility.vcxproj">
<Project>{7b9e6056-e4fb-411b-9612-a2fd679c2b69}</Project> <Project>{7b9e6056-e4fb-411b-9612-a2fd679c2b69}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Natvis Include="SFFElement.natvis" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

View File

@ -21,25 +21,18 @@
<ClCompile Include="src/**/*.cpp"> <ClCompile Include="src/**/*.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src/**/*.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src/SFFElement.cpp"> <ClCompile Include="src/SFFElement.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src/SFFParser.cpp"> <ClCompile Include="src/SFFParser.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="SFFElement.ixx" /> <ClCompile Include="src/SFFElement.ixx" />
<ClCompile Include="Shadow.FileFormat.ixx" /> <ClCompile Include="src/Shadow.FileFormat.ixx" />
<ClCompile Include="src/SFFParser.ixx" />
<ClCompile Include="src/SFFVersion.ixx" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\SFFParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\SFFVersion.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src/**/*.h"> <ClInclude Include="src/**/*.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -55,11 +48,8 @@
<ClInclude Include="src/**/*.h"> <ClInclude Include="src/**/*.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src/SFFParser.h"> </ItemGroup>
<Filter>Header Files</Filter> <ItemGroup>
</ClInclude> <Natvis Include="SFFElement.natvis" />
<ClInclude Include="src/SFFVersion.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -20,8 +20,7 @@ import <list>;
std::string value; std::string value;
typedef std::map<std::string, SFFElement*> ChildrenMap; typedef std::map<std::string, SFFElement*> ChildrenMap;
std::list<SFFElement*> properties_old; ChildrenMap children;
std::map<std::string, SFFElement*> children;
std::string GetStringProperty(std::string name); std::string GetStringProperty(std::string name);
@ -33,6 +32,9 @@ import <list>;
SFFElement* GetChildByIndex(int index) SFFElement* GetChildByIndex(int index)
{ {
ChildrenMap::iterator it = children.begin(); ChildrenMap::iterator it = children.begin();
if (it == children.end())
return nullptr;
for (size_t i = 0; i < index; i++) for (size_t i = 0; i < index; i++)
{ {
it++; it++;

View File

@ -28,12 +28,13 @@ namespace Shadow::SFF {
//The current node that we are building //The current node that we are building
auto* context = new SFFElement; auto* context = new SFFElement;
context->name = "root";
//Top level Element //Top level Element
SFFElement* base = context; SFFElement* base = context;
//The new node that will be a child of the context //The new node that will be a child of the context
auto* current = new SFFElement; SFFElement* current = nullptr;
std::string buffer; std::string buffer;
@ -42,52 +43,63 @@ namespace Shadow::SFF {
while (!stream.eof()) while (!stream.eof())
{ {
stream.get(c); stream.get(c);
if (c == ':')
{ switch (c) {
case ':':
//The stuff in the buffer is a parameter name //The stuff in the buffer is a parameter name
std::cout << "Name: " << buffer; //std::cout << "Name: " << buffer;
current = new SFFElement;
current->name = buffer; current->name = buffer;
current->parent = context;
buffer = ""; buffer = "";
} break;
else if (c == '{')
{ case '{':
//Start of a new block //Start of a new block
current->isBlock = true; current->isBlock = true;
current->parent = context;
context->children[current->name] = current;
context = current; context = current;
current = new SFFElement; current = nullptr;
} break;
else if (c == ',')
{ case ',':
// End of a property // End of a property
//The stuff is the value if (!current->isBlock) {
std::cout << "Value: " << buffer << std::endl; //The stuff is the value
current->value = buffer; current->value = buffer;
current->parent = context; current->parent = context;
current->isBlock = false; current->isBlock = false;
}
buffer = ""; buffer = "";
context->children[current->name] = current; context->children[current->name] = current;
current = new SFFElement(); current = nullptr;
} break;
else if (c == '}')
{ case '}':
// End of a block if (current != nullptr) {
context = context->parent; // End of a block
} current->parent = context;
else context->children[current->name] = current;
{ }
current = context;
context = current->parent;
break;
default:
if (std::isspace(c) == 0) if (std::isspace(c) == 0)
{ {
buffer += c; buffer += c;
} }
break;
} }
} }
std::cout << "END" << std::endl; //std::cout << "END" << std::endl;
return base; return base;
} }