Build XML tree from XML tokeniser, print xml tree
This commit is contained in:
parent
a1ff789485
commit
2c1d3f9593
@ -84,37 +84,76 @@ INTERNAL void rendererInit(GameState *state, v2 windowSize)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct XmlAttribute
|
||||||
|
{
|
||||||
|
b32 init;
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
struct XmlAttribute *next;
|
||||||
|
} XmlAttribute;
|
||||||
|
|
||||||
typedef struct XmlNode
|
typedef struct XmlNode
|
||||||
{
|
{
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
|
XmlAttribute attribute;
|
||||||
|
|
||||||
char **fieldName;
|
// NOTE(doyle): Track if node has more children
|
||||||
char **fieldValue;
|
b32 isClosed;
|
||||||
i32 numFields;
|
|
||||||
|
|
||||||
struct XmlNode **children;
|
// NOTE(doyle): Direct child/parent
|
||||||
|
struct XmlNode *parent;
|
||||||
|
struct XmlNode *child;
|
||||||
|
|
||||||
|
// NOTE(doyle): Else all other nodes
|
||||||
|
struct XmlNode *next;
|
||||||
} XmlNode;
|
} XmlNode;
|
||||||
|
|
||||||
enum TokenType
|
enum XmlTokenType
|
||||||
{
|
{
|
||||||
tokentype_unknown,
|
xmltokentype_unknown,
|
||||||
tokentype_openArrow,
|
xmltokentype_openArrow,
|
||||||
tokentype_closeArrow,
|
xmltokentype_closeArrow,
|
||||||
tokentype_string,
|
xmltokentype_name,
|
||||||
tokentype_equals,
|
xmltokentype_value,
|
||||||
tokentype_quotes,
|
xmltokentype_equals,
|
||||||
tokentype_backslash,
|
xmltokentype_quotes,
|
||||||
tokentype_count,
|
xmltokentype_backslash,
|
||||||
|
xmltokentype_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Token
|
typedef struct XmlToken
|
||||||
{
|
{
|
||||||
// TODO(doyle): Dynamic size string in tokens maybe.
|
// TODO(doyle): Dynamic size string in tokens maybe.
|
||||||
enum TokenType type;
|
enum XmlTokenType type;
|
||||||
char string[128];
|
char string[128];
|
||||||
i32 len;
|
i32 len;
|
||||||
} Token;
|
} XmlToken;
|
||||||
|
|
||||||
|
INTERNAL void debug_recursivePrintXmlTree(XmlNode *root)
|
||||||
|
{
|
||||||
|
if (!root)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%s ", root->name);
|
||||||
|
|
||||||
|
XmlAttribute *attribute = &root->attribute;
|
||||||
|
printf("| %s = %s", attribute->name, attribute->value);
|
||||||
|
|
||||||
|
while (attribute->next)
|
||||||
|
{
|
||||||
|
attribute = attribute->next;
|
||||||
|
printf("| %s = %04s", attribute->name, attribute->value);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
debug_recursivePrintXmlTree(root->child);
|
||||||
|
debug_recursivePrintXmlTree(root->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INTERNAL void assetInit(GameState *state)
|
INTERNAL void assetInit(GameState *state)
|
||||||
{
|
{
|
||||||
@ -137,7 +176,7 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
arena, "data/textures/WorldTraveller/ClaudeSpriteSheet.xml",
|
arena, "data/textures/WorldTraveller/ClaudeSpriteSheet.xml",
|
||||||
&xmlFileRead);
|
&xmlFileRead);
|
||||||
|
|
||||||
Token *tokens = PLATFORM_MEM_ALLOC(arena, 8192, Token);
|
XmlToken *xmlTokens = PLATFORM_MEM_ALLOC(arena, 8192, XmlToken);
|
||||||
i32 tokenIndex = 0;
|
i32 tokenIndex = 0;
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@ -156,33 +195,33 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
case '/':
|
case '/':
|
||||||
{
|
{
|
||||||
|
|
||||||
enum TokenType type = tokentype_unknown;
|
enum XmlTokenType type = xmltokentype_unknown;
|
||||||
if (c == '<')
|
if (c == '<')
|
||||||
{
|
{
|
||||||
type = tokentype_openArrow;
|
type = xmltokentype_openArrow;
|
||||||
}
|
}
|
||||||
else if (c == '>')
|
else if (c == '>')
|
||||||
{
|
{
|
||||||
type = tokentype_closeArrow;
|
type = xmltokentype_closeArrow;
|
||||||
}
|
}
|
||||||
else if (c == '=')
|
else if (c == '=')
|
||||||
{
|
{
|
||||||
type = tokentype_equals;
|
type = xmltokentype_equals;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type = tokentype_backslash;
|
type = xmltokentype_backslash;
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens[tokenIndex].type = type;
|
xmlTokens[tokenIndex].type = type;
|
||||||
tokens[tokenIndex].len = 1;
|
xmlTokens[tokenIndex].len = 1;
|
||||||
tokenIndex++;
|
tokenIndex++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '"':
|
case '"':
|
||||||
{
|
{
|
||||||
tokens[tokenIndex].type = tokentype_string;
|
xmlTokens[tokenIndex].type = xmltokentype_value;
|
||||||
for (i32 j = i + 1; j < xmlFileRead.size; j++)
|
for (i32 j = i + 1; j < xmlFileRead.size; j++)
|
||||||
{
|
{
|
||||||
char c = (CAST(char *) xmlFileRead.buffer)[j];
|
char c = (CAST(char *) xmlFileRead.buffer)[j];
|
||||||
@ -193,16 +232,17 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tokens[tokenIndex].string[tokens[tokenIndex].len++] = c;
|
xmlTokens[tokenIndex]
|
||||||
|
.string[xmlTokens[tokenIndex].len++] = c;
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(tokens[tokenIndex].len <
|
ASSERT(xmlTokens[tokenIndex].len <
|
||||||
ARRAY_COUNT(tokens[tokenIndex].string));
|
ARRAY_COUNT(xmlTokens[tokenIndex].string));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(doyle): +1 to skip the closing quotes
|
// NOTE(doyle): +1 to skip the closing quotes
|
||||||
i += (tokens[tokenIndex].len + 1);
|
i += (xmlTokens[tokenIndex].len + 1);
|
||||||
tokenIndex++;
|
tokenIndex++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -211,7 +251,7 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
{
|
{
|
||||||
if ((c >= 'a' && c <= 'z') || c >= 'A' && c <= 'Z')
|
if ((c >= 'a' && c <= 'z') || c >= 'A' && c <= 'Z')
|
||||||
{
|
{
|
||||||
tokens[tokenIndex].type = tokentype_string;
|
xmlTokens[tokenIndex].type = xmltokentype_name;
|
||||||
for (i32 j = i; j < xmlFileRead.size; j++)
|
for (i32 j = i; j < xmlFileRead.size; j++)
|
||||||
{
|
{
|
||||||
char c = (CAST(char *) xmlFileRead.buffer)[j];
|
char c = (CAST(char *) xmlFileRead.buffer)[j];
|
||||||
@ -222,15 +262,15 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tokens[tokenIndex]
|
xmlTokens[tokenIndex]
|
||||||
.string[tokens[tokenIndex].len++] = c;
|
.string[xmlTokens[tokenIndex].len++] = c;
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(tokens[tokenIndex].len <
|
ASSERT(xmlTokens[tokenIndex].len <
|
||||||
ARRAY_COUNT(tokens[tokenIndex].string));
|
ARRAY_COUNT(xmlTokens[tokenIndex].string));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += tokens[tokenIndex].len;
|
i += xmlTokens[tokenIndex].len;
|
||||||
tokenIndex++;
|
tokenIndex++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -239,6 +279,99 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XmlNode root = {0};
|
||||||
|
XmlNode *node = &root;
|
||||||
|
node->parent = node;
|
||||||
|
for (i32 i = 0; i < tokenIndex; i++)
|
||||||
|
{
|
||||||
|
XmlToken *token = &xmlTokens[i];
|
||||||
|
switch (token->type)
|
||||||
|
{
|
||||||
|
|
||||||
|
case xmltokentype_openArrow:
|
||||||
|
{
|
||||||
|
/* Open arrows are followed by the node name */
|
||||||
|
token = &xmlTokens[++i];
|
||||||
|
node->name = token->string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case xmltokentype_name:
|
||||||
|
{
|
||||||
|
// TODO(doyle): Store latest attribute pointer so we aren't always
|
||||||
|
// chasing the linked list each iteration. Do the same for children
|
||||||
|
// node
|
||||||
|
|
||||||
|
/* Xml Attributes are a linked list, get first free entry */
|
||||||
|
XmlAttribute *attribute = &node->attribute;
|
||||||
|
if (attribute->init)
|
||||||
|
{
|
||||||
|
while (attribute->next)
|
||||||
|
attribute = attribute->next;
|
||||||
|
|
||||||
|
attribute->next = PLATFORM_MEM_ALLOC(arena, 1, XmlAttribute);
|
||||||
|
attribute = attribute->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just plain text is a node attribute name */
|
||||||
|
attribute->name = token->string;
|
||||||
|
|
||||||
|
/* Followed by the value */
|
||||||
|
token = &xmlTokens[++i];
|
||||||
|
attribute->value = token->string;
|
||||||
|
attribute->init = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case xmltokentype_closeArrow:
|
||||||
|
{
|
||||||
|
XmlToken prevToken = xmlTokens[i - 1];
|
||||||
|
|
||||||
|
/* Closed node means we can return to parent */
|
||||||
|
if (prevToken.type == xmltokentype_backslash)
|
||||||
|
{
|
||||||
|
node->isClosed = TRUE;
|
||||||
|
node = node->parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node->isClosed)
|
||||||
|
{
|
||||||
|
/* Unclosed node means next fields will be children of node */
|
||||||
|
|
||||||
|
/* If the first child is free allocate, otherwise we have to
|
||||||
|
* iterate through the child's next node(s) */
|
||||||
|
if (!node->child)
|
||||||
|
{
|
||||||
|
node->child = PLATFORM_MEM_ALLOC(arena, 1, XmlNode);
|
||||||
|
node->child->parent = node;
|
||||||
|
node = node->child;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XmlNode *nodeToCheck = node->child;
|
||||||
|
while (nodeToCheck->next)
|
||||||
|
nodeToCheck = nodeToCheck->next;
|
||||||
|
|
||||||
|
nodeToCheck->next = PLATFORM_MEM_ALLOC(arena, 1, XmlNode);
|
||||||
|
nodeToCheck->next->parent = node;
|
||||||
|
node = nodeToCheck->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_recursivePrintXmlTree(&root);
|
||||||
|
|
||||||
/* Load textures */
|
/* Load textures */
|
||||||
asset_loadTextureImage(assetManager,
|
asset_loadTextureImage(assetManager,
|
||||||
"data/textures/WorldTraveller/TerraSprite1024.png",
|
"data/textures/WorldTraveller/TerraSprite1024.png",
|
||||||
|
@ -35,5 +35,6 @@ char *common_memset(char *const ptr, const i32 value, const i32 numBytes);
|
|||||||
|
|
||||||
// Max buffer size should be 11 for 32 bit integers
|
// Max buffer size should be 11 for 32 bit integers
|
||||||
void common_itoa(i32 value, char *buf, i32 bufSize);
|
void common_itoa(i32 value, char *buf, i32 bufSize);
|
||||||
|
i32 common_atoi(char *buf, i32 bufSize);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user