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;
union
{
struct json_s **childlink; 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,6 +98,15 @@ 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;
if (p->arraymax)
{
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) while (*l)
{ {
if (*l == t) if (*l == t)
@ -104,6 +118,7 @@ static void JSON_Orphan(json_t *t)
} }
l = &(*l)->sibling; l = &(*l)->sibling;
} }
}
t->parent = NULL; t->parent = NULL;
t->sibling = NULL; t->sibling = NULL;
} }
@ -111,16 +126,27 @@ static void JSON_Orphan(json_t *t)
static void JSON_Destroy(json_t *t) static void JSON_Destroy(json_t *t)
{ {
if (t) if (t)
{
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) while(t->child)
JSON_Destroy(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->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->childlink = &j->child;
j->parent = parent; j->parent = parent;
if (parent) if (parent)
{
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;
parent->childlink = &j->sibling; 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,10 +479,23 @@ 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);
if (t->arraymax)
{
size_t idx = atoi(child);
if (idx < t->arraymax)
{
t = t->array[idx];
if (t)
goto found;
}
}
else
{
for (t = t->child; t; t = t->sibling) for (t = t->child; t; t = t->sibling)
{ {
if (!strncmp(t->name, child, nl) && (t->name[nl] == '.' || !t->name[nl])) if (!strncmp(t->name, child, nl) && (t->name[nl] == '.' || !t->name[nl]))
{ {
found:
child+=nl; child+=nl;
t->used = true; t->used = true;
if (*child == '.') if (*child == '.')
@ -440,6 +506,7 @@ static json_t *JSON_FindChild(json_t *t, const char *child)
} }
} }
} }
}
return NULL; return NULL;
} }
static json_t *JSON_FindIndexedChild(json_t *t, const char *child, unsigned int idx) static json_t *JSON_FindIndexedChild(json_t *t, const char *child, unsigned int idx)