mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-20 01:11:18 +00:00
add dynamic (freeable but unchangeable) strings
This is an imperfect revision of history.
This commit is contained in:
parent
ff47490c48
commit
2a36c74120
4 changed files with 150 additions and 53 deletions
|
@ -583,9 +583,9 @@ PF_sprintf (progs_t *pr)
|
|||
dstring_t *dstr;
|
||||
int str;
|
||||
|
||||
str = PR_NewString (pr);
|
||||
dstr = PR_GetDString (pr, str);
|
||||
PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args);
|
||||
str = PR_NewMutableString (pr);
|
||||
dstr = PR_GetMutableString (pr, str);
|
||||
PR_Sprintf (pr, dstr, "PF_sprintf", fmt, count, args);
|
||||
PR_MakeTempString (pr, str);
|
||||
R_STRING (pr) = str;
|
||||
}
|
||||
|
|
|
@ -46,11 +46,22 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/hash.h"
|
||||
#include "QF/progs.h"
|
||||
|
||||
typedef enum {
|
||||
str_static,
|
||||
str_dynamic,
|
||||
str_mutable,
|
||||
str_temp,
|
||||
str_return,
|
||||
} str_e;
|
||||
|
||||
struct strref_s {
|
||||
strref_t *next;
|
||||
char *string;
|
||||
dstring_t *dstring;
|
||||
int count;
|
||||
strref_t **prev;
|
||||
str_e type;
|
||||
union {
|
||||
char *string;
|
||||
dstring_t *dstring;
|
||||
} s;
|
||||
};
|
||||
|
||||
// format adjustments
|
||||
|
@ -126,8 +137,8 @@ new_string_ref (progs_t *pr)
|
|||
static void
|
||||
free_string_ref (progs_t *pr, strref_t *sr)
|
||||
{
|
||||
sr->string = 0;
|
||||
sr->dstring = 0;
|
||||
if (sr->prev)
|
||||
*sr->prev = sr->next;
|
||||
sr->next = pr->free_string_refs;
|
||||
pr->free_string_refs = sr;
|
||||
}
|
||||
|
@ -139,9 +150,9 @@ string_index (progs_t *pr, strref_t *sr)
|
|||
unsigned int i;
|
||||
|
||||
if (o >= 0 && o < pr->num_strings)
|
||||
return sr->string - pr->pr_strings;
|
||||
return sr->s.string - pr->pr_strings;
|
||||
for (i = 0; i < pr->dyn_str_size; i++) {
|
||||
int d = sr - pr->dynamic_strings[i];
|
||||
int d = sr - pr->string_map[i];
|
||||
if (d >= 0 && d < 1024)
|
||||
return ~(i * 1024 + d);
|
||||
}
|
||||
|
@ -153,7 +164,8 @@ strref_get_key (void *_sr, void *notused)
|
|||
{
|
||||
strref_t *sr = (strref_t*)_sr;
|
||||
|
||||
return sr->string;
|
||||
// only static strings will ever be in the hash table
|
||||
return sr->s.string;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -244,9 +256,16 @@ get_string (progs_t *pr, int num)
|
|||
strref_t *ref = get_strref (pr, num);
|
||||
if (!ref)
|
||||
return 0;
|
||||
if (ref->dstring)
|
||||
return ref->dstring->str;
|
||||
return ref->string;
|
||||
switch (ref->type) {
|
||||
case str_static:
|
||||
case str_temp:
|
||||
case str_dynamic:
|
||||
case str_return:
|
||||
return ref->s.string;
|
||||
case str_mutable:
|
||||
return ref->s.dstring->str;
|
||||
}
|
||||
PR_Error (pr, "internal string error");
|
||||
} else {
|
||||
if (num >= pr->pr_stringsize)
|
||||
return 0;
|
||||
|
@ -272,12 +291,12 @@ PR_GetString (progs_t *pr, int num)
|
|||
}
|
||||
|
||||
dstring_t *
|
||||
PR_GetDString (progs_t *pr, int num)
|
||||
PR_GetMutableString (progs_t *pr, int num)
|
||||
{
|
||||
strref_t *ref = get_strref (pr, num);
|
||||
if (ref) {
|
||||
if (ref->dstring)
|
||||
return ref->dstring;
|
||||
if (ref->type == str_mutable)
|
||||
return ref->s.dstring;
|
||||
PR_RunError (pr, "not a dstring: %d", num);
|
||||
}
|
||||
PR_RunError (pr, "Invalid string offset: %d", num);
|
||||
|
@ -298,8 +317,7 @@ pr_strfree (progs_t *pr, char *s)
|
|||
static inline char *
|
||||
pr_strdup (progs_t *pr, const char *s)
|
||||
{
|
||||
size_t len = strlen (s) + 1;
|
||||
char *new = PR_Zone_Malloc (pr, len);
|
||||
char *new = pr_stralloc (pr, strlen (s));
|
||||
strcpy (new, s);
|
||||
return new;
|
||||
}
|
||||
|
@ -315,8 +333,8 @@ PR_SetString (progs_t *pr, const char *s)
|
|||
|
||||
if (!sr) {
|
||||
sr = new_string_ref (pr);
|
||||
sr->string = pr_strdup(pr, s);
|
||||
sr->count = 0;
|
||||
sr->type = str_static;
|
||||
sr->s.string = pr_strdup(pr, s);
|
||||
Hash_Add (pr->strref_hash, sr);
|
||||
}
|
||||
return string_index (pr, sr);
|
||||
|
@ -346,13 +364,14 @@ PR_SetReturnString (progs_t *pr, const char *s)
|
|||
}
|
||||
|
||||
if ((sr = pr->return_strings[pr->rs_slot])) {
|
||||
if (sr->string)
|
||||
PR_Zone_Free (pr, sr->string);
|
||||
if (sr->type != str_return)
|
||||
PR_Error (pr, "internal string error");
|
||||
pr_strfree (pr, sr->s.string);
|
||||
} else {
|
||||
sr = new_string_ref (pr);
|
||||
}
|
||||
sr->string = pr_strdup(pr, s);
|
||||
sr->count = 0;
|
||||
sr->type = str_return;
|
||||
sr->s.string = pr_strdup(pr, s);
|
||||
|
||||
pr->return_strings[pr->rs_slot++] = sr;
|
||||
pr->rs_slot %= PR_RS_SLOTS;
|
||||
|
@ -396,11 +415,28 @@ PR_SetTempString (progs_t *pr, const char *s)
|
|||
if (!s)
|
||||
return PR_SetString (pr, "");
|
||||
|
||||
if ((sr = Hash_Find (pr->strref_hash, s))) {
|
||||
return string_index (pr, sr);
|
||||
}
|
||||
|
||||
return pr_settempstring (pr, pr_strdup (pr, s));
|
||||
}
|
||||
|
||||
int
|
||||
PR_SetDynamicString (progs_t *pr, const char *s)
|
||||
{
|
||||
strref_t *sr;
|
||||
|
||||
if (!s)
|
||||
return PR_SetString (pr, "");
|
||||
|
||||
if ((sr = Hash_Find (pr->strref_hash, s))) {
|
||||
return string_index (pr, sr);
|
||||
}
|
||||
|
||||
sr = new_string_ref (pr);
|
||||
sr->string = pr_strdup(pr, s);
|
||||
sr->count = 0;
|
||||
sr->next = pr->pr_xtstr;
|
||||
pr->pr_xtstr = sr;
|
||||
sr->type = str_dynamic;
|
||||
sr->s.string = pr_strdup (pr, s);
|
||||
return string_index (pr, sr);
|
||||
}
|
||||
|
||||
|
@ -411,23 +447,26 @@ PR_MakeTempString (progs_t *pr, int str)
|
|||
|
||||
if (!sr)
|
||||
PR_RunError (pr, "invalid string %d", str);
|
||||
if (sr->dstring) {
|
||||
if (sr->dstring->str)
|
||||
sr->string = sr->dstring->str;
|
||||
PR_Zone_Free (pr, sr->dstring);
|
||||
if (sr->type != str_mutable)
|
||||
PR_RunError (pr, "not a dstring: %d", str);
|
||||
if (sr->s.dstring->str) {
|
||||
sr->s.string = dstring_freeze (sr->s.dstring);
|
||||
} else {
|
||||
dstring_delete (sr->s.dstring);
|
||||
}
|
||||
if (!sr->string)
|
||||
sr->string = pr_strdup (pr, "");
|
||||
sr->count = 0;
|
||||
if (!sr->s.string)
|
||||
sr->s.string = pr_strdup (pr, "");
|
||||
sr->type = str_temp;
|
||||
sr->next = pr->pr_xtstr;
|
||||
pr->pr_xtstr = sr;
|
||||
}
|
||||
|
||||
int
|
||||
PR_NewString (progs_t *pr)
|
||||
PR_NewMutableString (progs_t *pr)
|
||||
{
|
||||
strref_t *sr = new_string_ref (pr);
|
||||
sr->dstring = _dstring_newstr (pr->ds_mem);
|
||||
sr->type = str_mutable;
|
||||
sr->s.dstring = _dstring_newstr (pr->ds_mem);
|
||||
return string_index (pr, sr);
|
||||
}
|
||||
|
||||
|
@ -437,14 +476,25 @@ PR_FreeString (progs_t *pr, int str)
|
|||
strref_t *sr = get_strref (pr, str);
|
||||
|
||||
if (sr) {
|
||||
if (sr->dstring)
|
||||
dstring_delete (sr->dstring);
|
||||
else
|
||||
PR_Zone_Free (pr, sr->string);
|
||||
switch (sr->type) {
|
||||
case str_static:
|
||||
case str_temp:
|
||||
return;
|
||||
case str_mutable:
|
||||
dstring_delete (sr->s.dstring);
|
||||
break;
|
||||
case str_dynamic:
|
||||
pr_strfree (pr, sr->s.string);
|
||||
break;
|
||||
case str_return:
|
||||
default:
|
||||
PR_Error (pr, "internal string error");
|
||||
}
|
||||
free_string_ref (pr, sr);
|
||||
return;
|
||||
}
|
||||
PR_RunError (pr, "attempt to free invalid string %d", str);
|
||||
if (!get_string (pr, str))
|
||||
PR_RunError (pr, "attempt to free invalid string %d", str);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -454,7 +504,9 @@ PR_FreeTempStrings (progs_t *pr)
|
|||
|
||||
for (sr = pr->pr_xtstr; sr; sr = t) {
|
||||
t = sr->next;
|
||||
PR_Zone_Free (pr, sr->string);
|
||||
if (sr->type != str_temp)
|
||||
PR_Error (pr, "internal string error");
|
||||
pr_strfree (pr, sr->s.string);
|
||||
free_string_ref (pr, sr);
|
||||
}
|
||||
pr->pr_xtstr = 0;
|
||||
|
@ -512,14 +564,18 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting)
|
|||
PRINT (string);
|
||||
break;
|
||||
case 'i':
|
||||
dstring_appendstr (tmp, "ld");
|
||||
dstring_appendstr (tmp, "d");
|
||||
PRINT (integer);
|
||||
break;
|
||||
case 'x':
|
||||
dstring_appendstr (tmp, "x");
|
||||
PRINT (integer);
|
||||
break;
|
||||
case 'u':
|
||||
if (current->flags & FMT_HEX)
|
||||
dstring_appendstr (tmp, "lx");
|
||||
dstring_appendstr (tmp, "x");
|
||||
else
|
||||
dstring_appendstr (tmp, "lu");
|
||||
dstring_appendstr (tmp, "u");
|
||||
PRINT (uinteger);
|
||||
break;
|
||||
case 'f':
|
||||
|
|
|
@ -50,7 +50,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
static void
|
||||
bi_str_new (progs_t *pr)
|
||||
{
|
||||
R_STRING (pr) = PR_NewString (pr);
|
||||
R_STRING (pr) = PR_NewMutableString (pr);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -78,11 +78,53 @@ bi_str_clear (progs_t *pr)
|
|||
R_STRING (pr) = P_STRING (pr, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_str_mid (progs_t *pr)
|
||||
{
|
||||
const char *str = P_GSTRING (pr, 0);
|
||||
int pos = P_INT (pr, 1);
|
||||
int end = P_INT (pr, 2);
|
||||
int size = strlen (str);
|
||||
char *temp;
|
||||
|
||||
if (pr->pr_argc == 2)
|
||||
end = size;
|
||||
|
||||
R_STRING (pr) = 0;
|
||||
if (pos < 0)
|
||||
pos += size;
|
||||
if (end < 0)
|
||||
end += size;
|
||||
if (end > size)
|
||||
end = size;
|
||||
if (pos < 0 || pos >= size || end <= pos)
|
||||
return;
|
||||
temp = alloca (end - pos + 1);
|
||||
strncpy (temp, str + pos, end - pos);
|
||||
temp[end - pos] = 0;
|
||||
RETURN_STRING (pr, temp);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_str_str (progs_t *pr)
|
||||
{
|
||||
const char *haystack = P_GSTRING (pr, 0);
|
||||
const char *needle = P_GSTRING (pr, 1);
|
||||
char *res = strstr (haystack, needle);
|
||||
|
||||
R_STRING (pr) = 0;
|
||||
if (res)
|
||||
R_STRING (pr) = res - pr->pr_strings;
|
||||
}
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"str_new", bi_str_new, -1},
|
||||
{"str_free", bi_str_free, -1},
|
||||
{"str_copy", bi_str_copy, -1},
|
||||
{"str_clear", bi_str_clear, -1},
|
||||
{"str_mid|*i", bi_str_mid, -1},
|
||||
{"str_mid|*ii", bi_str_mid, -1},
|
||||
{"str_str", bi_str_str, -1},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ PF_substr (progs_t * pr)
|
|||
|
||||
tmp = Hunk_TempAlloc (len);
|
||||
strncpy (tmp, s, len - 1);
|
||||
tmp[len] = 0;
|
||||
tmp[len - 1] = 0;
|
||||
|
||||
RETURN_STRING (pr, tmp);
|
||||
}
|
||||
|
@ -238,8 +238,7 @@ PF_str2short (progs_t * pr)
|
|||
PF_newstr
|
||||
|
||||
string newstr (string str [, float size])
|
||||
|
||||
ignores size (there for compatability with qwe)
|
||||
The new string will be at least as big as size, if given.
|
||||
*/
|
||||
static void
|
||||
PF_newstr (progs_t * pr)
|
||||
|
@ -250,8 +249,8 @@ PF_newstr (progs_t * pr)
|
|||
|
||||
s = P_GSTRING (pr, 0);
|
||||
|
||||
i = PR_NewString (pr);
|
||||
dstr = PR_GetDString (pr, i);
|
||||
i = PR_NewMutableString (pr);
|
||||
dstr = PR_GetMutableString (pr, i);
|
||||
|
||||
dstring_copystr (dstr, s);
|
||||
|
||||
|
|
Loading…
Reference in a new issue