Reworked SFF parser
This commit is contained in:
parent
10625e731a
commit
5afbc014da
|
@ -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");
|
||||||
}
|
}
|
24
projs/shadow-file-format/SFFElement.natvis
Normal file
24
projs/shadow-file-format/SFFElement.natvis
Normal 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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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++;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user