more bsdstring removal, str_replace, unit tests.

This commit is contained in:
Enno Rehling 2017-12-11 18:20:21 +01:00
parent 691dde5960
commit 9f391039b5
16 changed files with 121 additions and 59 deletions

View file

@ -7337,8 +7337,8 @@
</string> </string>
<string name="a_road_percent"> <string name="a_road_percent">
<text locale="de">eine zu %d%% vollendete Straße</text> <text locale="de">eine zu $percent%% vollendete Straße</text>
<text locale="en">a road that is %d%% complete</text> <text locale="en">a road that is $percent% complete</text>
</string> </string>
<string name="a_road_connection"> <string name="a_road_connection">

View file

@ -189,7 +189,7 @@ static char *sidename(side * s)
static char sidename_buf[4][SIDENAMEBUFLEN]; /* STATIC_RESULT: used for return, not across calls */ static char sidename_buf[4][SIDENAMEBUFLEN]; /* STATIC_RESULT: used for return, not across calls */
bufno = bufno % 4; bufno = bufno % 4;
strlcpy(sidename_buf[bufno], factionname(s->stealthfaction ? s->stealthfaction : s->faction), SIDENAMEBUFLEN); strncpy(sidename_buf[bufno], factionname(s->stealthfaction ? s->stealthfaction : s->faction), SIDENAMEBUFLEN);
return sidename_buf[bufno++]; return sidename_buf[bufno++];
} }
@ -2886,10 +2886,10 @@ static void print_header(battle * b)
for (df = s->fighters; df; df = df->next) { for (df = s->fighters; df; df = df->next) {
if (is_attacker(df)) { if (is_attacker(df)) {
if (first) { if (first) {
bufp = STRLCPY(bufp, ", ", size); strlcpy(bufp, ", ", size);
} }
if (lastf) { if (lastf) {
bufp = STRLCPY(bufp, lastf, size); strlcpy(bufp, lastf, size);
first = true; first = true;
} }
if (seematrix(f, s)) if (seematrix(f, s))
@ -3579,7 +3579,7 @@ static int battle_report(battle * b)
if (komma) { if (komma) {
bufp = STRLCPY(bufp, ", ", size); bufp = STRLCPY(bufp, ", ", size);
} }
slprintf(buffer, sizeof(buffer), "%s %2d(%s): ", snprintf(buffer, sizeof(buffer), "%s %2d(%s): ",
loc_army, army_index(s), abbrev); loc_army, army_index(s), abbrev);
bufp = STRLCPY(bufp, buffer, size); bufp = STRLCPY(bufp, buffer, size);

View file

@ -516,7 +516,7 @@ static void report_crtypes(FILE * F, const struct locale *lang)
assert(hash > 0); assert(hash > 0);
fprintf(F, "MESSAGETYPE %u\n", hash); fprintf(F, "MESSAGETYPE %u\n", hash);
fputc('\"', F); fputc('\"', F);
fputs(escape_string(nrt_string(nrt), buffer, sizeof(buffer)), F); fputs(str_escape(nrt_string(nrt), buffer, sizeof(buffer)), F);
fputs("\";text\n", F); fputs("\";text\n", F);
fprintf(F, "\"%s\";section\n", nrt_section(nrt)); fprintf(F, "\"%s\";section\n", nrt_section(nrt));
} }
@ -1067,7 +1067,7 @@ static void cr_reportspell(FILE * F, spell * sp, int level, const struct locale
const char *name = const char *name =
translate(mkname("spell", sp->sname), spell_name(sp, lang)); translate(mkname("spell", sp->sname), spell_name(sp, lang));
fprintf(F, "ZAUBER %d\n", hashstring(sp->sname)); fprintf(F, "ZAUBER %d\n", str_hash(sp->sname));
fprintf(F, "\"%s\";name\n", name); fprintf(F, "\"%s\";name\n", name);
fprintf(F, "%d;level\n", level); fprintf(F, "%d;level\n", level);
fprintf(F, "%d;rank\n", sp->rank); fprintf(F, "%d;rank\n", sp->rank);
@ -1115,7 +1115,7 @@ static char *cr_output_resource(char *buf, const resource_type *rtype,
assert(rtype); assert(rtype);
name = resourcename(rtype, NMF_PLURAL); name = resourcename(rtype, NMF_PLURAL);
assert(name); assert(name);
buf += sprintf(buf, "RESOURCE %u\n", hashstring(rtype->_name)); buf += sprintf(buf, "RESOURCE %u\n", str_hash(rtype->_name));
tname = LOC(loc, name); tname = LOC(loc, name);
assert(tname); assert(tname);
tname = translate(name, tname); tname = translate(name, tname);
@ -1663,7 +1663,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
if (ptype == NULL) if (ptype == NULL)
continue; continue;
ch = resourcename(ptype->itype->rtype, 0); ch = resourcename(ptype->itype->rtype, 0);
fprintf(F, "TRANK %d\n", hashstring(ch)); fprintf(F, "TRANK %d\n", str_hash(ch));
fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch))); fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch)));
fprintf(F, "%d;Stufe\n", ptype->level); fprintf(F, "%d;Stufe\n", ptype->level);

View file

@ -50,7 +50,6 @@
#include <util/lists.h> #include <util/lists.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <storage.h> #include <storage.h>
#include <lua.h> #include <lua.h>
@ -58,6 +57,7 @@
#include <assert.h> #include <assert.h>
#include <locale.h> #include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
static int g_quit; static int g_quit;
@ -1228,7 +1228,7 @@ static void handlekey(state * st, int c)
else if (findmode == 'F') { else if (findmode == 'F') {
faction *f = select_faction(st); faction *f = select_faction(st);
if (f != NULL) { if (f != NULL) {
strlcpy(locate, itoa36(f->no), sizeof(locate)); itoab_r(f->no, 36, locate, sizeof(locate));
findmode = 'f'; findmode = 'f';
} }
else { else {
@ -1254,7 +1254,7 @@ static void handlekey(state * st, int c)
region *first = (mr && mr->r && mr->r->next) ? mr->r->next : regions; region *first = (mr && mr->r && mr->r->next) ? mr->r->next : regions;
if (findmode == 'f') { if (findmode == 'f') {
slprintf(sbuffer, sizeof(sbuffer), "find-faction: %s", locate); snprintf(sbuffer, sizeof(sbuffer), "find-faction: %s", locate);
statusline(st->wnd_status->handle, sbuffer); statusline(st->wnd_status->handle, sbuffer);
f = findfaction(atoi36(locate)); f = findfaction(atoi36(locate));
if (f == NULL) { if (f == NULL) {

View file

@ -28,7 +28,6 @@ without prior permission by the authors of Eressea.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/language.h> #include <util/language.h>
#include <util/parser.h> #include <util/parser.h>
#include <util/rng.h> #include <util/rng.h>
@ -40,6 +39,7 @@ without prior permission by the authors of Eressea.
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
alliance *alliances = NULL; alliance *alliances = NULL;
@ -422,7 +422,7 @@ const char *alliancename(const alliance * al)
char *ibuf = idbuf[(++nextbuf) % 8]; char *ibuf = idbuf[(++nextbuf) % 8];
if (al && al->name) { if (al && al->name) {
slprintf(ibuf, sizeof(idbuf[0]), "%s (%s)", al->name, itoa36(al->id)); snprintf(ibuf, sizeof(idbuf[0]), "%s (%s)", al->name, itoa36(al->id));
} }
else { else {
return NULL; return NULL;

View file

@ -38,7 +38,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/functions.h> #include <util/functions.h>
#include <util/gamedata.h> #include <util/gamedata.h>
@ -54,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@ -372,7 +372,7 @@ building *new_building(const struct building_type * btype, region * r,
bname = parameters[P_GEBAEUDE]; bname = parameters[P_GEBAEUDE];
} }
assert(bname); assert(bname);
slprintf(buffer, sizeof(buffer), "%s %s", bname, itoa36(b->no)); snprintf(buffer, sizeof(buffer), "%s %s", bname, itoa36(b->no));
b->name = strdup(bname); b->name = strdup(bname);
return b; return b;
} }
@ -489,7 +489,7 @@ int bt_effsize(const building_type * btype, const building * b, int bsize)
const char *write_buildingname(const building * b, char *ibuf, size_t size) const char *write_buildingname(const building * b, char *ibuf, size_t size)
{ {
slprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no)); snprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no));
return ibuf; return ibuf;
} }

View file

@ -25,19 +25,21 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "unit.h" #include "unit.h"
#include <util/attrib.h> #include <util/attrib.h>
#include <util/bsdstring.h> #include <util/base36.h>
#include <util/gamedata.h> #include <util/gamedata.h>
#include <util/language.h> #include <util/language.h>
#include <util/log.h> #include <util/log.h>
#include <selist.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/strings.h>
#include <selist.h>
#include <storage.h> #include <storage.h>
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int nextborder = 0; int nextborder = 0;
@ -514,8 +516,8 @@ static const char *b_nameroad(const connection * b, const region * r,
else { else {
int percent = MAX(1, 100 * local / r->terrain->max_road); int percent = MAX(1, 100 * local / r->terrain->max_road);
if (local) { if (local) {
slprintf(buffer, sizeof(buffer), LOC(f->locale, mkname("border", const char *temp = LOC(f->locale, mkname("border", "a_road_percent"));
"a_road_percent")), percent); str_replace(buffer, sizeof(buffer), temp, "$percent", itoa10(percent));
} }
else { else {
return LOC(f->locale, mkname("border", "a_road_connection")); return LOC(f->locale, mkname("border", "a_road_connection"));

View file

@ -170,7 +170,7 @@ int stream_order(struct stream *out, const struct order *ord, const struct local
char obuf[1024]; char obuf[1024];
swrite(" ", 1, 1, out); swrite(" ", 1, 1, out);
if (escape) { if (escape) {
text = escape_string(text, obuf, sizeof(obuf)); text = str_escape(text, obuf, sizeof(obuf));
} }
swrite(text, 1, strlen(text), out); swrite(text, 1, strlen(text), out);
} }

View file

@ -51,7 +51,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/gamedata.h> #include <util/gamedata.h>
#include <util/strings.h> #include <util/strings.h>
@ -1458,9 +1457,7 @@ void default_name(const unit *u, char name[], int len) {
else { else {
result = parameters[P_UNIT]; result = parameters[P_UNIT];
} }
strlcpy(name, result, len); snprintf(name, len, "%s %s", result, itoa36(u->no));
strlcat(name, " ", len);
strlcat(name, itoa36(u->no), len);
} }
void name_unit(unit * u) void name_unit(unit * u)
@ -1874,7 +1871,7 @@ static int nextbuf = 0;
char *write_unitname(const unit * u, char *buffer, size_t size) char *write_unitname(const unit * u, char *buffer, size_t size)
{ {
const char * name = unit_getname(u); const char * name = unit_getname(u);
slprintf(buffer, size, "%s (%s)", name, itoa36(u->no)); snprintf(buffer, size, "%s (%s)", name, itoa36(u->no));
buffer[size - 1] = 0; buffer[size - 1] = 0;
return buffer; return buffer;
} }

View file

@ -52,16 +52,14 @@ int atoi36(const char *str)
return i * sign; return i * sign;
} }
const char *itoab(int i, int base) const char *itoab_r(int i, int base, char *s, size_t len)
{ {
static char sstr[80]; char *dst;
char *s, *dst;
static int index = 0; /* STATIC_XCALL: used across calls */ static int index = 0; /* STATIC_XCALL: used across calls */
s = sstr + (index * 20); assert(len > 2);
index = (index + 1) & 3; /* quick for % 4 */ dst = s + len - 2;
dst = s + 19; *dst = 0;
(*dst--) = 0;
if (i != 0) { if (i != 0) {
int neg = 0; int neg = 0;
@ -101,6 +99,18 @@ const char *itoab(int i, int base)
return dst; return dst;
} }
const char *itoab(int i, int base)
{
static char sstr[80];
char *s;
static int index = 0; /* STATIC_XCALL: used across calls */
s = sstr + (index * 20);
index = (index + 1) & 3; /* quick for % 4 */
return itoab_r(i, base, s, 20);
}
const char *itoa36(int i) const char *itoa36(int i)
{ {
return itoab(i, 36); return itoab(i, 36);

View file

@ -18,15 +18,19 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_UTIL_BASE36 #ifndef H_UTIL_BASE36
#define H_UTIL_BASE36 #define H_UTIL_BASE36
#include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
const char *itoab_r(int i, int base, char *result, size_t len);
const char *itoab(int i, int base);
const char *itoa36(int i);
const char *itoa10(int i);
extern int atoi36(const char *s); extern int atoi36(const char *s);
extern const char *itoab(int i, int base); int i10toi36(int i);
extern const char *itoa36(int i);
extern const char *itoa10(int i);
extern int i10toi36(int i);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -56,7 +56,7 @@ unsigned int locale_index(const locale * lang)
locale *get_locale(const char *name) locale *get_locale(const char *name)
{ {
unsigned int hkey = hashstring(name); unsigned int hkey = str_hash(name);
locale *l = locales; locale *l = locales;
while (l && l->hashkey != hkey) while (l && l->hashkey != hkey)
l = l->next; l = l->next;
@ -68,7 +68,7 @@ static unsigned int nextlocaleindex = 0;
locale *get_or_create_locale(const char *name) locale *get_or_create_locale(const char *name)
{ {
locale *l; locale *l;
unsigned int hkey = hashstring(name); unsigned int hkey = str_hash(name);
locale **lp = &locales; locale **lp = &locales;
if (!locales) { if (!locales) {
@ -120,7 +120,7 @@ void make_locales(const char *str)
const char *locale_getstring(const locale * lang, const char *key) const char *locale_getstring(const locale * lang, const char *key)
{ {
unsigned int hkey = hashstring(key); unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1); unsigned int id = hkey & (SMAXHASH - 1);
const struct locale_str *find; const struct locale_str *find;
@ -150,7 +150,7 @@ const char *locale_string(const locale * lang, const char *key, bool warn)
assert(key); assert(key);
if (key != NULL) { if (key != NULL) {
unsigned int hkey = hashstring(key); unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1); unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find; struct locale_str *find;
@ -188,7 +188,7 @@ const char *locale_string(const locale * lang, const char *key, bool warn)
void locale_setstring(locale * lang, const char *key, const char *value) void locale_setstring(locale * lang, const char *key, const char *value)
{ {
unsigned int hkey = hashstring(key); unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1); unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find; struct locale_str *find;
if (!lang) { if (!lang) {

View file

@ -192,7 +192,7 @@ void mt_clear(void) {
const message_type *mt_find(const char *name) const message_type *mt_find(const char *name)
{ {
unsigned int hash = hashstring(name) % MT_MAXHASH; unsigned int hash = str_hash(name) % MT_MAXHASH;
selist *ql = messagetypes[hash]; selist *ql = messagetypes[hash];
int qi; int qi;
@ -218,7 +218,7 @@ static unsigned int mt_id(const message_type * mtype)
const message_type *mt_register(message_type * type) const message_type *mt_register(message_type * type)
{ {
unsigned int hash = hashstring(type->name) % MT_MAXHASH; unsigned int hash = str_hash(type->name) % MT_MAXHASH;
selist **qlp = messagetypes + hash; selist **qlp = messagetypes + hash;
if (selist_set_insert(qlp, type, NULL)) { if (selist_set_insert(qlp, type, NULL)) {

View file

@ -45,7 +45,40 @@ char *set_string(char **s, const char *neu)
return *s; return *s;
} }
unsigned int hashstring(const char *s) void str_replace(char *buffer, size_t size, const char *tmpl, const char *var, const char *value)
{
size_t val_len = strlen(value);
size_t var_len = strlen(var);
char *s = buffer;
while (buffer + size > s) {
char *p = strstr(tmpl, var);
size_t len;
if (p) {
len = p - tmpl;
}
else {
len = strlen(tmpl);
}
if (len < size) {
memmove(s, tmpl, len);
tmpl += len;
s += len;
size -= len;
if (p && val_len < size) {
tmpl += var_len;
memmove(s, value, val_len);
s += val_len;
size -= val_len;
}
}
if (!p) {
break;
}
}
*s = 0;
}
unsigned int str_hash(const char *s)
{ {
unsigned int key = 0; unsigned int key = 0;
assert(s); assert(s);
@ -55,7 +88,7 @@ unsigned int hashstring(const char *s)
return key & 0x7FFFFFFF; return key & 0x7FFFFFFF;
} }
const char *escape_string(const char *str, char *buffer, const char *str_escape(const char *str, char *buffer,
size_t len) size_t len)
{ {
const char *start = strchr(str, '\"'); const char *start = strchr(str, '\"');

View file

@ -25,9 +25,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" { extern "C" {
#endif #endif
void str_replace(char *buffer, size_t size, const char *tmpl, const char *var, const char *value);
const char *str_escape(const char *str, char *buffer, size_t len);
char *set_string(char **s, const char *neu); char *set_string(char **s, const char *neu);
unsigned int hashstring(const char *s); unsigned int str_hash(const char *s);
const char *escape_string(const char *str, char *buffer, size_t len);
unsigned int jenkins_hash(unsigned int a); unsigned int jenkins_hash(unsigned int a);
unsigned int wang_hash(unsigned int a); unsigned int wang_hash(unsigned int a);

View file

@ -4,21 +4,36 @@
#include <string.h> #include <string.h>
#include "strings.h" #include "strings.h"
static void test_escape_string(CuTest * tc) static void test_str_escape(CuTest * tc)
{ {
char scratch[64]; char scratch[64];
CuAssertStrEquals(tc, "12345678901234567890", escape_string("12345678901234567890", scratch, 16)); CuAssertStrEquals(tc, "12345678901234567890", str_escape("12345678901234567890", scratch, 16));
CuAssertStrEquals(tc, "123456789\\\"12345", escape_string("123456789\"1234567890", scratch, 16)); CuAssertStrEquals(tc, "123456789\\\"12345", str_escape("123456789\"1234567890", scratch, 16));
CuAssertStrEquals(tc, "1234567890123456", escape_string("1234567890123456\"890", scratch, 16)); CuAssertStrEquals(tc, "1234567890123456", str_escape("1234567890123456\"890", scratch, 16));
CuAssertStrEquals(tc, "hello world", escape_string("hello world", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "hello world", str_escape("hello world", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "hello \\\"world\\\"", escape_string("hello \"world\"", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "hello \\\"world\\\"", str_escape("hello \"world\"", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "\\\"\\\\", escape_string("\"\\", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "\\\"\\\\", str_escape("\"\\", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "\\\\", escape_string("\\", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "\\\\", str_escape("\\", scratch, sizeof(scratch)));
}
static void test_str_replace(CuTest * tc)
{
char result[64];
str_replace(result, sizeof(result), "Hello $who!", "$who", "World");
CuAssertStrEquals(tc, "Hello World!", result);
}
static void test_str_hash(CuTest * tc)
{
CuAssertIntEquals(tc, 0, str_hash(""));
CuAssertIntEquals(tc, 140703196, str_hash("Hodor"));
} }
CuSuite *get_strings_suite(void) CuSuite *get_strings_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_escape_string); SUITE_ADD_TEST(suite, test_str_hash);
SUITE_ADD_TEST(suite, test_str_escape);
SUITE_ADD_TEST(suite, test_str_replace);
return suite; return suite;
} }