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

View file

@ -82,7 +82,12 @@ typedef struct json_s
struct json_s *parent; struct json_s *parent;
struct json_s *child; struct json_s *child;
struct json_s *sibling; 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 qboolean used; //set to say when something actually read/walked it, so we can flag unsupported things gracefully
char name[1]; char name[1];
} json_t; } json_t;
@ -93,16 +98,26 @@ static void JSON_Orphan(json_t *t)
if (t->parent) if (t->parent)
{ {
json_t *p = t->parent, **l = &p->child; 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 == t)
if (*l) {
p->childlink = l; *l = t->sibling;
break; if (*l)
p->childlink = l;
break;
}
l = &(*l)->sibling;
} }
l = &(*l)->sibling;
} }
t->parent = NULL; t->parent = NULL;
t->sibling = NULL; t->sibling = NULL;
@ -112,15 +127,26 @@ static void JSON_Destroy(json_t *t)
{ {
if (t) if (t)
{ {
while(t->child) if (t->arraymax)
JSON_Destroy(t->child); {
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); JSON_Orphan(t);
free(t); free(t);
} }
} }
//node creation //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; json_t *j;
qboolean dupbody = false; qboolean dupbody = false;
@ -139,12 +165,39 @@ static json_t *JSON_CreateNode(json_t *parent, const char *namestart, const char
j->child = NULL; j->child = NULL;
j->sibling = 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; j->parent = parent;
if (parent) if (parent)
{ {
*parent->childlink = j; if (parent->arraymax)
parent->childlink = &j->sibling; {
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; j->used = false;
} }
else else
@ -343,7 +396,7 @@ static json_t *JSON_Parse(json_t *t, const char *namestart, const char *nameend,
*jsonpos+=1; *jsonpos+=1;
JSON_SkipWhite(json, jsonpos, jsonlen); 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] == '\"') 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; *jsonpos+=1;
JSON_SkipWhite(json, jsonpos, jsonlen); JSON_SkipWhite(json, jsonpos, jsonlen);
t = JSON_CreateNode(t, namestart, nameend, NULL, NULL); t = JSON_CreateNode(t, namestart, nameend, NULL, NULL, true);
for(;;) for(;;)
{ {
@ -409,7 +462,7 @@ static json_t *JSON_Parse(json_t *t, const char *namestart, const char *nameend,
else else
{ {
if (JSON_ParseString(json, jsonpos, jsonlen, &childstart, &childend)) 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; return NULL;
@ -426,17 +479,31 @@ static json_t *JSON_FindChild(json_t *t, const char *child)
nl = dot-child; nl = dot-child;
else else
nl = strlen(child); 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 = t->array[idx];
t->used = true; if (t)
if (*child == '.') goto found;
return JSON_FindChild(t, child+1); }
if (!*child) }
return t; else
break; {
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;
}
} }
} }
} }