GLTF loading should now be a smidge faster.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6187 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-02-19 20:48:16 +00:00
parent 242dea4676
commit f99764a887
1 changed files with 93 additions and 26 deletions

View File

@ -82,7 +82,12 @@ typedef struct json_s
struct json_s *parent;
struct json_s *child;
struct json_s *sibling;
struct json_s **childlink;
union
{
struct json_s **childlink;
struct json_s **array;
};
size_t arraymax; //note that child+siblings are kinda updated with arrays too, just not orphaned cleanly...
qboolean used; //set to say when something actually read/walked it, so we can flag unsupported things gracefully
char name[1];
} json_t;
@ -93,16 +98,26 @@ static void JSON_Orphan(json_t *t)
if (t->parent)
{
json_t *p = t->parent, **l = &p->child;
while (*l)
if (p->arraymax)
{
if (*l == t)
size_t idx = atoi(t->name);
if (idx <= p->arraymax)
p->array[idx] = NULL;
//FIXME: sibling links are screwed. be careful iterrating after a removal.
}
else
{
while (*l)
{
*l = t->sibling;
if (*l)
p->childlink = l;
break;
if (*l == t)
{
*l = t->sibling;
if (*l)
p->childlink = l;
break;
}
l = &(*l)->sibling;
}
l = &(*l)->sibling;
}
t->parent = NULL;
t->sibling = NULL;
@ -112,15 +127,26 @@ static void JSON_Destroy(json_t *t)
{
if (t)
{
while(t->child)
JSON_Destroy(t->child);
if (t->arraymax)
{
size_t idx;
for (idx = 0; idx < t->arraymax; idx++)
if (t->array[idx])
JSON_Destroy(t->array[idx]);
free(t->array);
}
else
{
while(t->child)
JSON_Destroy(t->child);
}
JSON_Orphan(t);
free(t);
}
}
//node creation
static json_t *JSON_CreateNode(json_t *parent, const char *namestart, const char *nameend, const char *bodystart, const char *bodyend)
static json_t *JSON_CreateNode(json_t *parent, const char *namestart, const char *nameend, const char *bodystart, const char *bodyend, qboolean array)
{
json_t *j;
qboolean dupbody = false;
@ -139,12 +165,39 @@ static json_t *JSON_CreateNode(json_t *parent, const char *namestart, const char
j->child = NULL;
j->sibling = NULL;
j->childlink = &j->child;
j->arraymax = 0;
if (array)
{ //pre-initialise the array a bit.
j->arraymax = 32;
j->array = calloc(j->arraymax, sizeof(*j->array));
}
else
j->childlink = &j->child;
j->parent = parent;
if (parent)
{
*parent->childlink = j;
parent->childlink = &j->sibling;
if (parent->arraymax)
{
size_t idx = atoi(j->name);
if (idx >= parent->arraymax)
{
size_t oldmax = parent->arraymax;
parent->arraymax = max(idx+1, parent->arraymax*2);
parent->array = realloc(parent->array, sizeof(*parent->array)*parent->arraymax);
while (oldmax < parent->arraymax)
parent->array[oldmax++] = NULL; //make sure there's no gaps.
}
parent->array[idx] = j;
if (!idx)
parent->child = j;
else if (parent->array[idx-1])
parent->array[idx-1]->sibling = j;
}
else
{
*parent->childlink = j;
parent->childlink = &j->sibling;
}
j->used = false;
}
else
@ -343,7 +396,7 @@ static json_t *JSON_Parse(json_t *t, const char *namestart, const char *nameend,
*jsonpos+=1;
JSON_SkipWhite(json, jsonpos, jsonlen);
t = JSON_CreateNode(t, namestart, nameend, NULL, NULL);
t = JSON_CreateNode(t, namestart, nameend, NULL, NULL, false);
while (*jsonpos < jsonlen && json[*jsonpos] == '\"')
{
@ -381,7 +434,7 @@ static json_t *JSON_Parse(json_t *t, const char *namestart, const char *nameend,
*jsonpos+=1;
JSON_SkipWhite(json, jsonpos, jsonlen);
t = JSON_CreateNode(t, namestart, nameend, NULL, NULL);
t = JSON_CreateNode(t, namestart, nameend, NULL, NULL, true);
for(;;)
{
@ -409,7 +462,7 @@ static json_t *JSON_Parse(json_t *t, const char *namestart, const char *nameend,
else
{
if (JSON_ParseString(json, jsonpos, jsonlen, &childstart, &childend))
return JSON_CreateNode(t, namestart, nameend, childstart, childend);
return JSON_CreateNode(t, namestart, nameend, childstart, childend, false);
}
}
return NULL;
@ -426,17 +479,31 @@ static json_t *JSON_FindChild(json_t *t, const char *child)
nl = dot-child;
else
nl = strlen(child);
for (t = t->child; t; t = t->sibling)
if (t->arraymax)
{
if (!strncmp(t->name, child, nl) && (t->name[nl] == '.' || !t->name[nl]))
size_t idx = atoi(child);
if (idx < t->arraymax)
{
child+=nl;
t->used = true;
if (*child == '.')
return JSON_FindChild(t, child+1);
if (!*child)
return t;
break;
t = t->array[idx];
if (t)
goto found;
}
}
else
{
for (t = t->child; t; t = t->sibling)
{
if (!strncmp(t->name, child, nl) && (t->name[nl] == '.' || !t->name[nl]))
{
found:
child+=nl;
t->used = true;
if (*child == '.')
return JSON_FindChild(t, child+1);
if (!*child)
return t;
break;
}
}
}
}