add dynamic (freeable but unchangeable) strings

This is an imperfect revision of history.
This commit is contained in:
Bill Currie 2004-11-11 09:40:00 +00:00 committed by Jeff Teunissen
parent ff47490c48
commit 2a36c74120
4 changed files with 150 additions and 53 deletions

View file

@ -583,9 +583,9 @@ PF_sprintf (progs_t *pr)
dstring_t *dstr; dstring_t *dstr;
int str; int str;
str = PR_NewString (pr); str = PR_NewMutableString (pr);
dstr = PR_GetDString (pr, str); dstr = PR_GetMutableString (pr, str);
PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); PR_Sprintf (pr, dstr, "PF_sprintf", fmt, count, args);
PR_MakeTempString (pr, str); PR_MakeTempString (pr, str);
R_STRING (pr) = str; R_STRING (pr) = str;
} }

View file

@ -46,11 +46,22 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "QF/hash.h" #include "QF/hash.h"
#include "QF/progs.h" #include "QF/progs.h"
typedef enum {
str_static,
str_dynamic,
str_mutable,
str_temp,
str_return,
} str_e;
struct strref_s { struct strref_s {
strref_t *next; strref_t *next;
char *string; strref_t **prev;
dstring_t *dstring; str_e type;
int count; union {
char *string;
dstring_t *dstring;
} s;
}; };
// format adjustments // format adjustments
@ -126,8 +137,8 @@ new_string_ref (progs_t *pr)
static void static void
free_string_ref (progs_t *pr, strref_t *sr) free_string_ref (progs_t *pr, strref_t *sr)
{ {
sr->string = 0; if (sr->prev)
sr->dstring = 0; *sr->prev = sr->next;
sr->next = pr->free_string_refs; sr->next = pr->free_string_refs;
pr->free_string_refs = sr; pr->free_string_refs = sr;
} }
@ -139,9 +150,9 @@ string_index (progs_t *pr, strref_t *sr)
unsigned int i; unsigned int i;
if (o >= 0 && o < pr->num_strings) 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++) { 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) if (d >= 0 && d < 1024)
return ~(i * 1024 + d); return ~(i * 1024 + d);
} }
@ -153,7 +164,8 @@ strref_get_key (void *_sr, void *notused)
{ {
strref_t *sr = (strref_t*)_sr; 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 static void
@ -244,9 +256,16 @@ get_string (progs_t *pr, int num)
strref_t *ref = get_strref (pr, num); strref_t *ref = get_strref (pr, num);
if (!ref) if (!ref)
return 0; return 0;
if (ref->dstring) switch (ref->type) {
return ref->dstring->str; case str_static:
return ref->string; 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 { } else {
if (num >= pr->pr_stringsize) if (num >= pr->pr_stringsize)
return 0; return 0;
@ -272,12 +291,12 @@ PR_GetString (progs_t *pr, int num)
} }
dstring_t * dstring_t *
PR_GetDString (progs_t *pr, int num) PR_GetMutableString (progs_t *pr, int num)
{ {
strref_t *ref = get_strref (pr, num); strref_t *ref = get_strref (pr, num);
if (ref) { if (ref) {
if (ref->dstring) if (ref->type == str_mutable)
return ref->dstring; return ref->s.dstring;
PR_RunError (pr, "not a dstring: %d", num); PR_RunError (pr, "not a dstring: %d", num);
} }
PR_RunError (pr, "Invalid string offset: %d", num); PR_RunError (pr, "Invalid string offset: %d", num);
@ -298,8 +317,7 @@ pr_strfree (progs_t *pr, char *s)
static inline char * static inline char *
pr_strdup (progs_t *pr, const char *s) pr_strdup (progs_t *pr, const char *s)
{ {
size_t len = strlen (s) + 1; char *new = pr_stralloc (pr, strlen (s));
char *new = PR_Zone_Malloc (pr, len);
strcpy (new, s); strcpy (new, s);
return new; return new;
} }
@ -315,8 +333,8 @@ PR_SetString (progs_t *pr, const char *s)
if (!sr) { if (!sr) {
sr = new_string_ref (pr); sr = new_string_ref (pr);
sr->string = pr_strdup(pr, s); sr->type = str_static;
sr->count = 0; sr->s.string = pr_strdup(pr, s);
Hash_Add (pr->strref_hash, sr); Hash_Add (pr->strref_hash, sr);
} }
return string_index (pr, 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 = pr->return_strings[pr->rs_slot])) {
if (sr->string) if (sr->type != str_return)
PR_Zone_Free (pr, sr->string); PR_Error (pr, "internal string error");
pr_strfree (pr, sr->s.string);
} else { } else {
sr = new_string_ref (pr); sr = new_string_ref (pr);
} }
sr->string = pr_strdup(pr, s); sr->type = str_return;
sr->count = 0; sr->s.string = pr_strdup(pr, s);
pr->return_strings[pr->rs_slot++] = sr; pr->return_strings[pr->rs_slot++] = sr;
pr->rs_slot %= PR_RS_SLOTS; pr->rs_slot %= PR_RS_SLOTS;
@ -396,11 +415,28 @@ PR_SetTempString (progs_t *pr, const char *s)
if (!s) if (!s)
return PR_SetString (pr, ""); 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 = new_string_ref (pr);
sr->string = pr_strdup(pr, s); sr->type = str_dynamic;
sr->count = 0; sr->s.string = pr_strdup (pr, s);
sr->next = pr->pr_xtstr;
pr->pr_xtstr = sr;
return string_index (pr, sr); return string_index (pr, sr);
} }
@ -411,23 +447,26 @@ PR_MakeTempString (progs_t *pr, int str)
if (!sr) if (!sr)
PR_RunError (pr, "invalid string %d", str); PR_RunError (pr, "invalid string %d", str);
if (sr->dstring) { if (sr->type != str_mutable)
if (sr->dstring->str) PR_RunError (pr, "not a dstring: %d", str);
sr->string = sr->dstring->str; if (sr->s.dstring->str) {
PR_Zone_Free (pr, sr->dstring); sr->s.string = dstring_freeze (sr->s.dstring);
} else {
dstring_delete (sr->s.dstring);
} }
if (!sr->string) if (!sr->s.string)
sr->string = pr_strdup (pr, ""); sr->s.string = pr_strdup (pr, "");
sr->count = 0; sr->type = str_temp;
sr->next = pr->pr_xtstr; sr->next = pr->pr_xtstr;
pr->pr_xtstr = sr; pr->pr_xtstr = sr;
} }
int int
PR_NewString (progs_t *pr) PR_NewMutableString (progs_t *pr)
{ {
strref_t *sr = new_string_ref (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); return string_index (pr, sr);
} }
@ -437,14 +476,25 @@ PR_FreeString (progs_t *pr, int str)
strref_t *sr = get_strref (pr, str); strref_t *sr = get_strref (pr, str);
if (sr) { if (sr) {
if (sr->dstring) switch (sr->type) {
dstring_delete (sr->dstring); case str_static:
else case str_temp:
PR_Zone_Free (pr, sr->string); 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); free_string_ref (pr, sr);
return; 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 void
@ -454,7 +504,9 @@ PR_FreeTempStrings (progs_t *pr)
for (sr = pr->pr_xtstr; sr; sr = t) { for (sr = pr->pr_xtstr; sr; sr = t) {
t = sr->next; 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); free_string_ref (pr, sr);
} }
pr->pr_xtstr = 0; pr->pr_xtstr = 0;
@ -512,14 +564,18 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting)
PRINT (string); PRINT (string);
break; break;
case 'i': case 'i':
dstring_appendstr (tmp, "ld"); dstring_appendstr (tmp, "d");
PRINT (integer);
break;
case 'x':
dstring_appendstr (tmp, "x");
PRINT (integer); PRINT (integer);
break; break;
case 'u': case 'u':
if (current->flags & FMT_HEX) if (current->flags & FMT_HEX)
dstring_appendstr (tmp, "lx"); dstring_appendstr (tmp, "x");
else else
dstring_appendstr (tmp, "lu"); dstring_appendstr (tmp, "u");
PRINT (uinteger); PRINT (uinteger);
break; break;
case 'f': case 'f':

View file

@ -50,7 +50,7 @@ static __attribute__ ((unused)) const char rcsid[] =
static void static void
bi_str_new (progs_t *pr) bi_str_new (progs_t *pr)
{ {
R_STRING (pr) = PR_NewString (pr); R_STRING (pr) = PR_NewMutableString (pr);
} }
static void static void
@ -78,11 +78,53 @@ bi_str_clear (progs_t *pr)
R_STRING (pr) = P_STRING (pr, 0); 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[] = { static builtin_t builtins[] = {
{"str_new", bi_str_new, -1}, {"str_new", bi_str_new, -1},
{"str_free", bi_str_free, -1}, {"str_free", bi_str_free, -1},
{"str_copy", bi_str_copy, -1}, {"str_copy", bi_str_copy, -1},
{"str_clear", bi_str_clear, -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} {0}
}; };

View file

@ -178,7 +178,7 @@ PF_substr (progs_t * pr)
tmp = Hunk_TempAlloc (len); tmp = Hunk_TempAlloc (len);
strncpy (tmp, s, len - 1); strncpy (tmp, s, len - 1);
tmp[len] = 0; tmp[len - 1] = 0;
RETURN_STRING (pr, tmp); RETURN_STRING (pr, tmp);
} }
@ -238,8 +238,7 @@ PF_str2short (progs_t * pr)
PF_newstr PF_newstr
string newstr (string str [, float size]) string newstr (string str [, float size])
The new string will be at least as big as size, if given.
ignores size (there for compatability with qwe)
*/ */
static void static void
PF_newstr (progs_t * pr) PF_newstr (progs_t * pr)
@ -250,8 +249,8 @@ PF_newstr (progs_t * pr)
s = P_GSTRING (pr, 0); s = P_GSTRING (pr, 0);
i = PR_NewString (pr); i = PR_NewMutableString (pr);
dstr = PR_GetDString (pr, i); dstr = PR_GetMutableString (pr, i);
dstring_copystr (dstr, s); dstring_copystr (dstr, s);