mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[gamecode] Add support for holding ephemeral strings
PR_HoldString converts ephemeral (temp and return) strings to dynamic strings. This makes dealing with strings in progs a little easier.
This commit is contained in:
parent
b4874f7d9b
commit
ec82d6b027
2 changed files with 46 additions and 2 deletions
|
@ -1344,6 +1344,18 @@ string_t PR_NewMutableString (progs_t *pr);
|
|||
*/
|
||||
string_t PR_SetDynamicString (progs_t *pr, const char *s);
|
||||
|
||||
/** Convert an ephemeral string to a dynamic string.
|
||||
|
||||
Valid strings that are not ephemeral (static, dynamic, mutable) will not
|
||||
be affected, but temp and return strings will be marked dynamic, requiring
|
||||
a call to PR_FreeString to return their memory.
|
||||
|
||||
\param pr pointer to ::progs_t VM struct
|
||||
\param str The string to be "held" (made non-ephemeral). Safe to call
|
||||
on any valid string, but affects only ephemeral strings.
|
||||
*/
|
||||
void PR_HoldString (progs_t *pr, string_t str);
|
||||
|
||||
/** Destroy a mutable, dynamic or temporary string.
|
||||
\param pr pointer to ::progs_t VM struct
|
||||
\param str string index of the string to be destroyed
|
||||
|
|
|
@ -449,8 +449,8 @@ PR_SetReturnString (progs_t *pr, const char *s)
|
|||
}
|
||||
|
||||
// grab the string ref from the oldest slot, or make a new one if the
|
||||
// slot is empty
|
||||
if ((sr = res->rs_slot->strref)) {
|
||||
// slot is empty or the string has been held
|
||||
if ((sr = res->rs_slot->strref) && sr->type != str_dynamic) {
|
||||
if (sr->type != str_return || sr->rs_slot != res->rs_slot) {
|
||||
PR_Error (pr, "internal string error: %d", __LINE__);
|
||||
}
|
||||
|
@ -592,6 +592,33 @@ PR_NewMutableString (progs_t *pr)
|
|||
return string_index (res, sr);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_HoldString (progs_t *pr, string_t str)
|
||||
{
|
||||
prstr_resources_t *res = pr->pr_string_resources;
|
||||
strref_t *sr = get_strref (res, str);
|
||||
|
||||
if (sr) {
|
||||
switch (sr->type) {
|
||||
case str_temp:
|
||||
case str_return:
|
||||
break;
|
||||
case str_static:
|
||||
case str_mutable:
|
||||
case str_dynamic:
|
||||
// non-ephemeral string, no-op
|
||||
return;
|
||||
default:
|
||||
PR_Error (pr, "internal string error: %d", __LINE__);
|
||||
}
|
||||
sr->type = str_dynamic;
|
||||
return;
|
||||
}
|
||||
if (!PR_StringValid (pr, str)) {
|
||||
PR_RunError (pr, "attempt to hold invalid string %d", str);
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_FreeString (progs_t *pr, string_t str)
|
||||
{
|
||||
|
@ -629,6 +656,11 @@ PR_FreeTempStrings (progs_t *pr)
|
|||
|
||||
for (sr = pr->pr_xtstr; sr; sr = t) {
|
||||
t = sr->next;
|
||||
if (sr->type == str_dynamic) {
|
||||
// the string has been held, so simply remove the ref from the
|
||||
// queue
|
||||
continue;
|
||||
}
|
||||
if (sr->type != str_temp)
|
||||
PR_Error (pr, "internal string error: %d", __LINE__);
|
||||
if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr)
|
||||
|
|
Loading…
Reference in a new issue