diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml
index ea4acf758..b06ff0445 100644
--- a/res/core/de/strings.xml
+++ b/res/core/de/strings.xml
@@ -7337,8 +7337,8 @@
- eine zu %d%% vollendete Straße
- a road that is %d%% complete
+ eine zu $percent%% vollendete Straße
+ a road that is $percent% complete
diff --git a/src/battle.c b/src/battle.c
index a58b0ab63..c12e6d46e 100644
--- a/src/battle.c
+++ b/src/battle.c
@@ -189,7 +189,7 @@ static char *sidename(side * s)
static char sidename_buf[4][SIDENAMEBUFLEN]; /* STATIC_RESULT: used for return, not across calls */
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++];
}
@@ -2886,10 +2886,10 @@ static void print_header(battle * b)
for (df = s->fighters; df; df = df->next) {
if (is_attacker(df)) {
if (first) {
- bufp = STRLCPY(bufp, ", ", size);
+ strlcpy(bufp, ", ", size);
}
if (lastf) {
- bufp = STRLCPY(bufp, lastf, size);
+ strlcpy(bufp, lastf, size);
first = true;
}
if (seematrix(f, s))
@@ -3579,7 +3579,7 @@ static int battle_report(battle * b)
if (komma) {
bufp = STRLCPY(bufp, ", ", size);
}
- slprintf(buffer, sizeof(buffer), "%s %2d(%s): ",
+ snprintf(buffer, sizeof(buffer), "%s %2d(%s): ",
loc_army, army_index(s), abbrev);
bufp = STRLCPY(bufp, buffer, size);
diff --git a/src/creport.c b/src/creport.c
index 89cf4c9ce..3f3e1bfb8 100644
--- a/src/creport.c
+++ b/src/creport.c
@@ -516,7 +516,7 @@ static void report_crtypes(FILE * F, const struct locale *lang)
assert(hash > 0);
fprintf(F, "MESSAGETYPE %u\n", hash);
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);
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 =
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, "%d;level\n", level);
fprintf(F, "%d;rank\n", sp->rank);
@@ -1115,7 +1115,7 @@ static char *cr_output_resource(char *buf, const resource_type *rtype,
assert(rtype);
name = resourcename(rtype, NMF_PLURAL);
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);
assert(tname);
tname = translate(name, tname);
@@ -1663,7 +1663,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
if (ptype == NULL)
continue;
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, "%d;Stufe\n", ptype->level);
diff --git a/src/gmtool.c b/src/gmtool.c
index fcb8cff8b..1fba47be6 100644
--- a/src/gmtool.c
+++ b/src/gmtool.c
@@ -50,7 +50,6 @@
#include
#include
#include
-#include
#include
#include
@@ -58,6 +57,7 @@
#include
#include
#include
+#include
#include
static int g_quit;
@@ -1228,7 +1228,7 @@ static void handlekey(state * st, int c)
else if (findmode == 'F') {
faction *f = select_faction(st);
if (f != NULL) {
- strlcpy(locate, itoa36(f->no), sizeof(locate));
+ itoab_r(f->no, 36, locate, sizeof(locate));
findmode = 'f';
}
else {
@@ -1254,7 +1254,7 @@ static void handlekey(state * st, int c)
region *first = (mr && mr->r && mr->r->next) ? mr->r->next : regions;
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);
f = findfaction(atoi36(locate));
if (f == NULL) {
diff --git a/src/kernel/alliance.c b/src/kernel/alliance.c
index f0cdf3bbd..ba3929f1f 100644
--- a/src/kernel/alliance.c
+++ b/src/kernel/alliance.c
@@ -28,7 +28,6 @@ without prior permission by the authors of Eressea.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -40,6 +39,7 @@ without prior permission by the authors of Eressea.
#include
#include
#include
+#include
alliance *alliances = NULL;
@@ -422,7 +422,7 @@ const char *alliancename(const alliance * al)
char *ibuf = idbuf[(++nextbuf) % 8];
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 {
return NULL;
diff --git a/src/kernel/building.c b/src/kernel/building.c
index ea01fe665..26d261e97 100644
--- a/src/kernel/building.c
+++ b/src/kernel/building.c
@@ -38,7 +38,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -54,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */
#include
#include
+#include
#include
#include
@@ -372,7 +372,7 @@ building *new_building(const struct building_type * btype, region * r,
bname = parameters[P_GEBAEUDE];
}
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);
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)
{
- slprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no));
+ snprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no));
return ibuf;
}
diff --git a/src/kernel/connection.c b/src/kernel/connection.c
index b630429fe..2cae4ec8f 100644
--- a/src/kernel/connection.c
+++ b/src/kernel/connection.c
@@ -25,19 +25,21 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "unit.h"
#include
-#include
+#include
#include
#include
#include
-#include
#include
+#include
+#include
#include
/* libc includes */
#include
#include
#include
+#include
#include
int nextborder = 0;
@@ -514,8 +516,8 @@ static const char *b_nameroad(const connection * b, const region * r,
else {
int percent = MAX(1, 100 * local / r->terrain->max_road);
if (local) {
- slprintf(buffer, sizeof(buffer), LOC(f->locale, mkname("border",
- "a_road_percent")), percent);
+ const char *temp = LOC(f->locale, mkname("border", "a_road_percent"));
+ str_replace(buffer, sizeof(buffer), temp, "$percent", itoa10(percent));
}
else {
return LOC(f->locale, mkname("border", "a_road_connection"));
diff --git a/src/kernel/order.c b/src/kernel/order.c
index baf26f615..605f44be9 100644
--- a/src/kernel/order.c
+++ b/src/kernel/order.c
@@ -170,7 +170,7 @@ int stream_order(struct stream *out, const struct order *ord, const struct local
char obuf[1024];
swrite(" ", 1, 1, out);
if (escape) {
- text = escape_string(text, obuf, sizeof(obuf));
+ text = str_escape(text, obuf, sizeof(obuf));
}
swrite(text, 1, strlen(text), out);
}
diff --git a/src/kernel/unit.c b/src/kernel/unit.c
index ee4da958c..87ccd5944 100644
--- a/src/kernel/unit.c
+++ b/src/kernel/unit.c
@@ -51,7 +51,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include
#include
-#include
#include
#include
#include
@@ -1458,9 +1457,7 @@ void default_name(const unit *u, char name[], int len) {
else {
result = parameters[P_UNIT];
}
- strlcpy(name, result, len);
- strlcat(name, " ", len);
- strlcat(name, itoa36(u->no), len);
+ snprintf(name, len, "%s %s", result, itoa36(u->no));
}
void name_unit(unit * u)
@@ -1874,7 +1871,7 @@ static int nextbuf = 0;
char *write_unitname(const unit * u, char *buffer, size_t size)
{
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;
return buffer;
}
diff --git a/src/util/base36.c b/src/util/base36.c
index 221ece870..ef7c38371 100644
--- a/src/util/base36.c
+++ b/src/util/base36.c
@@ -52,16 +52,14 @@ int atoi36(const char *str)
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 *s, *dst;
+ char *dst;
static int index = 0; /* STATIC_XCALL: used across calls */
- s = sstr + (index * 20);
- index = (index + 1) & 3; /* quick for % 4 */
- dst = s + 19;
- (*dst--) = 0;
+ assert(len > 2);
+ dst = s + len - 2;
+ *dst = 0;
if (i != 0) {
int neg = 0;
@@ -101,6 +99,18 @@ const char *itoab(int i, int base)
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)
{
return itoab(i, 36);
diff --git a/src/util/base36.h b/src/util/base36.h
index 650538219..804952ab7 100644
--- a/src/util/base36.h
+++ b/src/util/base36.h
@@ -18,15 +18,19 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_UTIL_BASE36
#define H_UTIL_BASE36
+
+#include
+
#ifdef __cplusplus
extern "C" {
#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 const char *itoab(int i, int base);
- extern const char *itoa36(int i);
- extern const char *itoa10(int i);
- extern int i10toi36(int i);
+ int i10toi36(int i);
#ifdef __cplusplus
}
diff --git a/src/util/language.c b/src/util/language.c
index a1cda4d2f..8cd6188d2 100644
--- a/src/util/language.c
+++ b/src/util/language.c
@@ -56,7 +56,7 @@ unsigned int locale_index(const locale * lang)
locale *get_locale(const char *name)
{
- unsigned int hkey = hashstring(name);
+ unsigned int hkey = str_hash(name);
locale *l = locales;
while (l && l->hashkey != hkey)
l = l->next;
@@ -68,7 +68,7 @@ static unsigned int nextlocaleindex = 0;
locale *get_or_create_locale(const char *name)
{
locale *l;
- unsigned int hkey = hashstring(name);
+ unsigned int hkey = str_hash(name);
locale **lp = &locales;
if (!locales) {
@@ -120,7 +120,7 @@ void make_locales(const char *str)
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);
const struct locale_str *find;
@@ -150,7 +150,7 @@ const char *locale_string(const locale * lang, const char *key, bool warn)
assert(key);
if (key != NULL) {
- unsigned int hkey = hashstring(key);
+ unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1);
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)
{
- unsigned int hkey = hashstring(key);
+ unsigned int hkey = str_hash(key);
unsigned int id = hkey & (SMAXHASH - 1);
struct locale_str *find;
if (!lang) {
diff --git a/src/util/message.c b/src/util/message.c
index e53010093..239863bd1 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -192,7 +192,7 @@ void mt_clear(void) {
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];
int qi;
@@ -218,7 +218,7 @@ static unsigned int mt_id(const message_type * mtype)
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;
if (selist_set_insert(qlp, type, NULL)) {
diff --git a/src/util/strings.c b/src/util/strings.c
index 4e7e17aa4..55d4ca5fb 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -45,7 +45,40 @@ char *set_string(char **s, const char *neu)
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;
assert(s);
@@ -55,7 +88,7 @@ unsigned int hashstring(const char *s)
return key & 0x7FFFFFFF;
}
-const char *escape_string(const char *str, char *buffer,
+const char *str_escape(const char *str, char *buffer,
size_t len)
{
const char *start = strchr(str, '\"');
diff --git a/src/util/strings.h b/src/util/strings.h
index 05a435e2c..f63299d93 100644
--- a/src/util/strings.h
+++ b/src/util/strings.h
@@ -25,9 +25,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" {
#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);
- unsigned int hashstring(const char *s);
- const char *escape_string(const char *str, char *buffer, size_t len);
+ unsigned int str_hash(const char *s);
unsigned int jenkins_hash(unsigned int a);
unsigned int wang_hash(unsigned int a);
diff --git a/src/util/strings.test.c b/src/util/strings.test.c
index bcee29e47..60a0b5d37 100644
--- a/src/util/strings.test.c
+++ b/src/util/strings.test.c
@@ -4,21 +4,36 @@
#include
#include "strings.h"
-static void test_escape_string(CuTest * tc)
+static void test_str_escape(CuTest * tc)
{
char scratch[64];
- CuAssertStrEquals(tc, "12345678901234567890", escape_string("12345678901234567890", scratch, 16));
- CuAssertStrEquals(tc, "123456789\\\"12345", escape_string("123456789\"1234567890", scratch, 16));
- CuAssertStrEquals(tc, "1234567890123456", escape_string("1234567890123456\"890", scratch, 16));
- CuAssertStrEquals(tc, "hello world", escape_string("hello world", scratch, sizeof(scratch)));
- CuAssertStrEquals(tc, "hello \\\"world\\\"", escape_string("hello \"world\"", scratch, sizeof(scratch)));
- CuAssertStrEquals(tc, "\\\"\\\\", escape_string("\"\\", scratch, sizeof(scratch)));
- CuAssertStrEquals(tc, "\\\\", escape_string("\\", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "12345678901234567890", str_escape("12345678901234567890", scratch, 16));
+ CuAssertStrEquals(tc, "123456789\\\"12345", str_escape("123456789\"1234567890", scratch, 16));
+ CuAssertStrEquals(tc, "1234567890123456", str_escape("1234567890123456\"890", scratch, 16));
+ CuAssertStrEquals(tc, "hello world", str_escape("hello world", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "hello \\\"world\\\"", str_escape("hello \"world\"", scratch, sizeof(scratch)));
+ CuAssertStrEquals(tc, "\\\"\\\\", str_escape("\"\\", 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 *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;
}