forked from github/server
Merge pull request #602 from ennorehling/2245-unicode
BUG 2245: Make sure that names are printable
This commit is contained in:
commit
8bbd0e9e44
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
||||||
Katja Zedel <katze@felidae.kn-bremen.de
|
Katja Zedel <katze@felidae.kn-bremen.de
|
||||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
|
@ -69,6 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <util/resolve.h>
|
#include <util/resolve.h>
|
||||||
#include <util/rng.h>
|
#include <util/rng.h>
|
||||||
#include <util/umlaut.h>
|
#include <util/umlaut.h>
|
||||||
|
#include <util/unicode.h>
|
||||||
|
|
||||||
#include <quicklist.h>
|
#include <quicklist.h>
|
||||||
#include <stream.h>
|
#include <stream.h>
|
||||||
|
@ -747,12 +748,18 @@ unit *read_unit(struct gamedata *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_STR(data->store, obuf, sizeof(obuf));
|
READ_STR(data->store, obuf, sizeof(obuf));
|
||||||
|
if (unicode_utf8_trim(obuf)!=0) {
|
||||||
|
log_warning("trim unit %s name to '%s'", itoa36(u->no), obuf);
|
||||||
|
}
|
||||||
u->_name = obuf[0] ? _strdup(obuf) : 0;
|
u->_name = obuf[0] ? _strdup(obuf) : 0;
|
||||||
if (lomem) {
|
if (lomem) {
|
||||||
READ_STR(data->store, NULL, 0);
|
READ_STR(data->store, NULL, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
READ_STR(data->store, obuf, sizeof(obuf));
|
READ_STR(data->store, obuf, sizeof(obuf));
|
||||||
|
if (unicode_utf8_trim(obuf)!=0) {
|
||||||
|
log_warning("trim unit %s info to '%s'", itoa36(u->no), obuf);
|
||||||
|
}
|
||||||
u->display = obuf[0] ? _strdup(obuf) : 0;
|
u->display = obuf[0] ? _strdup(obuf) : 0;
|
||||||
}
|
}
|
||||||
READ_INT(data->store, &number);
|
READ_INT(data->store, &number);
|
||||||
|
@ -986,6 +993,9 @@ static region *readregion(struct gamedata *data, int x, int y)
|
||||||
else {
|
else {
|
||||||
char info[DISPLAYSIZE];
|
char info[DISPLAYSIZE];
|
||||||
READ_STR(data->store, info, sizeof(info));
|
READ_STR(data->store, info, sizeof(info));
|
||||||
|
if (unicode_utf8_trim(info)!=0) {
|
||||||
|
log_warning("trim region %d info to '%s'", uid, info);
|
||||||
|
};
|
||||||
region_setinfo(r, info);
|
region_setinfo(r, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,6 +1013,9 @@ static region *readregion(struct gamedata *data, int x, int y)
|
||||||
if (fval(r->terrain, LAND_REGION)) {
|
if (fval(r->terrain, LAND_REGION)) {
|
||||||
r->land = calloc(1, sizeof(land_region));
|
r->land = calloc(1, sizeof(land_region));
|
||||||
READ_STR(data->store, name, sizeof(name));
|
READ_STR(data->store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim region %d name to '%s'", uid, name);
|
||||||
|
};
|
||||||
r->land->name = _strdup(name);
|
r->land->name = _strdup(name);
|
||||||
}
|
}
|
||||||
if (r->land) {
|
if (r->land) {
|
||||||
|
@ -1112,6 +1125,17 @@ static region *readregion(struct gamedata *data, int x, int y)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
region *read_region(gamedata *data)
|
||||||
|
{
|
||||||
|
storage *store = data->store;
|
||||||
|
region *r;
|
||||||
|
int x, y;
|
||||||
|
READ_INT(store, &x);
|
||||||
|
READ_INT(store, &y);
|
||||||
|
r = readregion(data, x, y);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void writeregion(struct gamedata *data, const region * r)
|
void writeregion(struct gamedata *data, const region * r)
|
||||||
{
|
{
|
||||||
assert(r);
|
assert(r);
|
||||||
|
@ -1176,6 +1200,14 @@ void writeregion(struct gamedata *data, const region * r)
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_region(gamedata *data, const region *r)
|
||||||
|
{
|
||||||
|
storage *store = data->store;
|
||||||
|
WRITE_INT(store, r->x);
|
||||||
|
WRITE_INT(store, r->y);
|
||||||
|
writeregion(data, r);
|
||||||
|
}
|
||||||
|
|
||||||
static ally **addally(const faction * f, ally ** sfp, int aid, int state)
|
static ally **addally(const faction * f, ally ** sfp, int aid, int state)
|
||||||
{
|
{
|
||||||
struct faction *af = findfaction(aid);
|
struct faction *af = findfaction(aid);
|
||||||
|
@ -1331,11 +1363,7 @@ void _test_write_password(gamedata *data, const faction *f) {
|
||||||
write_password(data, f);
|
write_password(data, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reads a faction from a file.
|
faction *read_faction(struct gamedata * data)
|
||||||
* This function requires no context, can be called in any state. The
|
|
||||||
* faction may not already exist, however.
|
|
||||||
*/
|
|
||||||
faction *readfaction(struct gamedata * data)
|
|
||||||
{
|
{
|
||||||
ally **sfp;
|
ally **sfp;
|
||||||
int planes, n;
|
int planes, n;
|
||||||
|
@ -1350,9 +1378,10 @@ faction *readfaction(struct gamedata * data)
|
||||||
f->no = n;
|
f->no = n;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
f->allies = NULL; /* mem leak */
|
f->allies = NULL; /* FIXME: mem leak */
|
||||||
while (f->attribs)
|
while (f->attribs) {
|
||||||
a_remove(&f->attribs, f->attribs);
|
a_remove(&f->attribs, f->attribs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
READ_INT(data->store, &f->subscription);
|
READ_INT(data->store, &f->subscription);
|
||||||
|
|
||||||
|
@ -1386,8 +1415,14 @@ faction *readfaction(struct gamedata * data)
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_STR(data->store, name, sizeof(name));
|
READ_STR(data->store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim faction %s name to '%s'", itoa36(f->no), name);
|
||||||
|
};
|
||||||
f->name = _strdup(name);
|
f->name = _strdup(name);
|
||||||
READ_STR(data->store, name, sizeof(name));
|
READ_STR(data->store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim faction %s banner to '%s'", itoa36(f->no), name);
|
||||||
|
};
|
||||||
f->banner = _strdup(name);
|
f->banner = _strdup(name);
|
||||||
|
|
||||||
log_debug(" - Lese Partei %s (%s)", f->name, factionid(f));
|
log_debug(" - Lese Partei %s (%s)", f->name, factionid(f));
|
||||||
|
@ -1480,7 +1515,7 @@ faction *readfaction(struct gamedata * data)
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writefaction(struct gamedata *data, const faction * f)
|
void write_faction(struct gamedata *data, const faction * f)
|
||||||
{
|
{
|
||||||
ally *sf;
|
ally *sf;
|
||||||
ursprung *ur;
|
ursprung *ur;
|
||||||
|
@ -1606,17 +1641,131 @@ int readgame(const char *filename, bool backup)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_game(gamedata *data) {
|
void write_building(gamedata *data, const building *b)
|
||||||
|
{
|
||||||
|
storage *store = data->store;
|
||||||
|
|
||||||
|
write_building_reference(b, store);
|
||||||
|
WRITE_STR(store, b->name);
|
||||||
|
WRITE_STR(store, b->display ? b->display : "");
|
||||||
|
WRITE_INT(store, b->size);
|
||||||
|
WRITE_TOK(store, b->type->_name);
|
||||||
|
write_attribs(store, b->attribs, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct building *read_building(gamedata *data) {
|
||||||
char name[DISPLAYSIZE];
|
char name[DISPLAYSIZE];
|
||||||
int n, p, nread;
|
building *b;
|
||||||
|
storage * store = data->store;
|
||||||
|
|
||||||
|
b = (building *)calloc(1, sizeof(building));
|
||||||
|
READ_INT(store, &b->no);
|
||||||
|
bhash(b);
|
||||||
|
READ_STR(store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim building %s name to '%s'", itoa36(b->no), name);
|
||||||
|
}
|
||||||
|
b->name = _strdup(name);
|
||||||
|
if (lomem) {
|
||||||
|
READ_STR(store, NULL, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
READ_STR(store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim building %s info to '%s'", itoa36(b->no), name);
|
||||||
|
}
|
||||||
|
b->display = _strdup(name);
|
||||||
|
}
|
||||||
|
READ_INT(store, &b->size);
|
||||||
|
READ_STR(store, name, sizeof(name));
|
||||||
|
b->type = bt_find(name);
|
||||||
|
read_attribs(data, &b->attribs, b);
|
||||||
|
|
||||||
|
// repairs, bug 2221:
|
||||||
|
if (b->type->maxsize>0 && b->size>b->type->maxsize) {
|
||||||
|
log_error("building too big: %s (%s size %d of %d), fixing.", buildingname(b), b->type->_name, b->size, b->type->maxsize);
|
||||||
|
b->size = b->type->maxsize;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_ship(gamedata *data, const ship *sh)
|
||||||
|
{
|
||||||
|
storage *store = data->store;
|
||||||
|
write_ship_reference(sh, store);
|
||||||
|
WRITE_STR(store, (const char *)sh->name);
|
||||||
|
WRITE_STR(store, sh->display ? (const char *)sh->display : "");
|
||||||
|
WRITE_TOK(store, sh->type->_name);
|
||||||
|
WRITE_INT(store, sh->size);
|
||||||
|
WRITE_INT(store, sh->damage);
|
||||||
|
WRITE_INT(store, sh->flags & SFL_SAVEMASK);
|
||||||
|
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
|
||||||
|
WRITE_INT(store, sh->coast);
|
||||||
|
write_attribs(store, sh->attribs, sh);
|
||||||
|
}
|
||||||
|
|
||||||
|
ship *read_ship(struct gamedata *data)
|
||||||
|
{
|
||||||
|
char name[DISPLAYSIZE];
|
||||||
|
ship *sh;
|
||||||
|
int n;
|
||||||
|
storage *store = data->store;
|
||||||
|
|
||||||
|
sh = (ship *)calloc(1, sizeof(ship));
|
||||||
|
READ_INT(store, &sh->no);
|
||||||
|
shash(sh);
|
||||||
|
READ_STR(store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim ship %s name to '%s'", itoa36(sh->no), name);
|
||||||
|
}
|
||||||
|
sh->name = _strdup(name);
|
||||||
|
if (lomem) {
|
||||||
|
READ_STR(store, NULL, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
READ_STR(store, name, sizeof(name));
|
||||||
|
if (unicode_utf8_trim(name)!=0) {
|
||||||
|
log_warning("trim ship %s info to '%s'", itoa36(sh->no), name);
|
||||||
|
}
|
||||||
|
sh->display = _strdup(name);
|
||||||
|
}
|
||||||
|
READ_STR(store, name, sizeof(name));
|
||||||
|
sh->type = st_find(name);
|
||||||
|
if (sh->type == NULL) {
|
||||||
|
/* old datafiles */
|
||||||
|
sh->type = st_find((const char *)LOC(default_locale, name));
|
||||||
|
}
|
||||||
|
assert(sh->type || !"ship_type not registered!");
|
||||||
|
|
||||||
|
READ_INT(store, &sh->size);
|
||||||
|
READ_INT(store, &sh->damage);
|
||||||
|
if (data->version >= FOSS_VERSION) {
|
||||||
|
READ_INT(store, &sh->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attribute rekursiv einlesen */
|
||||||
|
|
||||||
|
READ_INT(store, &n);
|
||||||
|
sh->coast = (direction_t)n;
|
||||||
|
if (sh->type->flags & SFL_NOCOAST) {
|
||||||
|
sh->coast = NODIRECTION;
|
||||||
|
}
|
||||||
|
read_attribs(data, &sh->attribs, sh);
|
||||||
|
return sh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_game(gamedata *data) {
|
||||||
|
int p, nread;
|
||||||
faction *f, **fp;
|
faction *f, **fp;
|
||||||
region *r;
|
region *r;
|
||||||
building *b, **bp;
|
building **bp;
|
||||||
ship **shp;
|
ship **shp;
|
||||||
unit *u;
|
unit *u;
|
||||||
int rmax = maxregions;
|
int rmax = maxregions;
|
||||||
const struct building_type *bt_lighthouse = bt_find("lighthouse");
|
|
||||||
storage * store = data->store;
|
storage * store = data->store;
|
||||||
|
const struct building_type *bt_lighthouse = bt_find("lighthouse");
|
||||||
|
|
||||||
if (data->version >= SAVEGAMEID_VERSION) {
|
if (data->version >= SAVEGAMEID_VERSION) {
|
||||||
int gameid;
|
int gameid;
|
||||||
|
|
||||||
|
@ -1648,11 +1797,12 @@ int read_game(gamedata *data) {
|
||||||
READ_INT(store, &nread);
|
READ_INT(store, &nread);
|
||||||
log_debug(" - Einzulesende Parteien: %d\n", nread);
|
log_debug(" - Einzulesende Parteien: %d\n", nread);
|
||||||
fp = &factions;
|
fp = &factions;
|
||||||
while (*fp)
|
while (*fp) {
|
||||||
fp = &(*fp)->next;
|
fp = &(*fp)->next;
|
||||||
|
}
|
||||||
|
|
||||||
while (--nread >= 0) {
|
while (--nread >= 0) {
|
||||||
faction *f = readfaction(data);
|
faction *f = read_faction(data);
|
||||||
|
|
||||||
*fp = f;
|
*fp = f;
|
||||||
fp = &f->next;
|
fp = &f->next;
|
||||||
|
@ -1668,53 +1818,23 @@ int read_game(gamedata *data) {
|
||||||
rmax = nread;
|
rmax = nread;
|
||||||
}
|
}
|
||||||
log_debug(" - Einzulesende Regionen: %d/%d\r", rmax, nread);
|
log_debug(" - Einzulesende Regionen: %d/%d\r", rmax, nread);
|
||||||
|
|
||||||
while (--nread >= 0) {
|
while (--nread >= 0) {
|
||||||
unit **up;
|
unit **up;
|
||||||
int x, y;
|
|
||||||
READ_INT(store, &x);
|
|
||||||
READ_INT(store, &y);
|
|
||||||
|
|
||||||
if ((nread & 0x3FF) == 0) { /* das spart extrem Zeit */
|
r = read_region(data);
|
||||||
log_debug(" - Einzulesende Regionen: %d/%d * %d,%d \r", rmax, nread, x, y);
|
|
||||||
}
|
|
||||||
--rmax;
|
|
||||||
|
|
||||||
r = readregion(data, x, y);
|
|
||||||
|
|
||||||
/* Burgen */
|
/* Burgen */
|
||||||
READ_INT(store, &p);
|
READ_INT(store, &p);
|
||||||
bp = &r->buildings;
|
bp = &r->buildings;
|
||||||
|
|
||||||
while (--p >= 0) {
|
while (--p >= 0) {
|
||||||
|
building *b = *bp = read_building(data);
|
||||||
b = (building *)calloc(1, sizeof(building));
|
|
||||||
READ_INT(store, &b->no);
|
|
||||||
*bp = b;
|
|
||||||
bp = &b->next;
|
|
||||||
bhash(b);
|
|
||||||
READ_STR(store, name, sizeof(name));
|
|
||||||
b->name = _strdup(name);
|
|
||||||
if (lomem) {
|
|
||||||
READ_STR(store, NULL, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
READ_STR(store, name, sizeof(name));
|
|
||||||
b->display = _strdup(name);
|
|
||||||
}
|
|
||||||
READ_INT(store, &b->size);
|
|
||||||
READ_STR(store, name, sizeof(name));
|
|
||||||
b->type = bt_find(name);
|
|
||||||
b->region = r;
|
|
||||||
read_attribs(data, &b->attribs, b);
|
|
||||||
if (b->type == bt_lighthouse) {
|
if (b->type == bt_lighthouse) {
|
||||||
r->flags |= RF_LIGHTHOUSE;
|
r->flags |= RF_LIGHTHOUSE;
|
||||||
}
|
}
|
||||||
|
b->region = r;
|
||||||
// repairs, bug 2221:
|
bp = &b->next;
|
||||||
if (b->type->maxsize>0 && b->size>b->type->maxsize) {
|
|
||||||
log_error("building too big: %s (%s size %d of %d), fixing.", buildingname(b), b->type->_name, b->size, b->type->maxsize);
|
|
||||||
b->size = b->type->maxsize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Schiffe */
|
/* Schiffe */
|
||||||
|
|
||||||
|
@ -1722,43 +1842,9 @@ int read_game(gamedata *data) {
|
||||||
shp = &r->ships;
|
shp = &r->ships;
|
||||||
|
|
||||||
while (--p >= 0) {
|
while (--p >= 0) {
|
||||||
ship *sh = (ship *)calloc(1, sizeof(ship));
|
ship *sh = *shp = read_ship(data);
|
||||||
sh->region = r;
|
sh->region = r;
|
||||||
READ_INT(store, &sh->no);
|
|
||||||
*shp = sh;
|
|
||||||
shp = &sh->next;
|
shp = &sh->next;
|
||||||
shash(sh);
|
|
||||||
READ_STR(store, name, sizeof(name));
|
|
||||||
sh->name = _strdup(name);
|
|
||||||
if (lomem) {
|
|
||||||
READ_STR(store, NULL, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
READ_STR(store, name, sizeof(name));
|
|
||||||
sh->display = _strdup(name);
|
|
||||||
}
|
|
||||||
READ_STR(store, name, sizeof(name));
|
|
||||||
sh->type = st_find(name);
|
|
||||||
if (sh->type == NULL) {
|
|
||||||
/* old datafiles */
|
|
||||||
sh->type = st_find((const char *)LOC(default_locale, name));
|
|
||||||
}
|
|
||||||
assert(sh->type || !"ship_type not registered!");
|
|
||||||
|
|
||||||
READ_INT(store, &sh->size);
|
|
||||||
READ_INT(store, &sh->damage);
|
|
||||||
if (data->version >= FOSS_VERSION) {
|
|
||||||
READ_INT(store, &sh->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attribute rekursiv einlesen */
|
|
||||||
|
|
||||||
READ_INT(store, &n);
|
|
||||||
sh->coast = (direction_t)n;
|
|
||||||
if (sh->type->flags & SFL_NOCOAST) {
|
|
||||||
sh->coast = NODIRECTION;
|
|
||||||
}
|
|
||||||
read_attribs(data, &sh->attribs, sh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*shp = 0;
|
*shp = 0;
|
||||||
|
@ -1783,8 +1869,13 @@ int read_game(gamedata *data) {
|
||||||
*up = u;
|
*up = u;
|
||||||
up = &u->next;
|
up = &u->next;
|
||||||
|
|
||||||
update_interval(u->faction, u->region);
|
update_interval(u->faction, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((nread & 0x3FF) == 0) { /* das spart extrem Zeit */
|
||||||
|
log_debug(" - Einzulesende Regionen: %d/%d * %d,%d \r", rmax, nread, r->x, r->y);
|
||||||
|
}
|
||||||
|
--rmax;
|
||||||
}
|
}
|
||||||
read_borders(data);
|
read_borders(data);
|
||||||
|
|
||||||
|
@ -1934,7 +2025,7 @@ int write_game(gamedata *data) {
|
||||||
if (fval(f, FFL_NPC)) {
|
if (fval(f, FFL_NPC)) {
|
||||||
clear_npc_orders(f);
|
clear_npc_orders(f);
|
||||||
}
|
}
|
||||||
writefaction(data, f);
|
write_faction(data, f);
|
||||||
WRITE_SECTION(store);
|
WRITE_SECTION(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1954,44 +2045,26 @@ int write_game(gamedata *data) {
|
||||||
log_debug(" - Schreibe Regionen: %d", n);
|
log_debug(" - Schreibe Regionen: %d", n);
|
||||||
}
|
}
|
||||||
WRITE_SECTION(store);
|
WRITE_SECTION(store);
|
||||||
WRITE_INT(store, r->x);
|
write_region(data, r);
|
||||||
WRITE_INT(store, r->y);
|
|
||||||
writeregion(data, r);
|
|
||||||
|
|
||||||
WRITE_INT(store, listlen(r->buildings));
|
WRITE_INT(store, listlen(r->buildings));
|
||||||
WRITE_SECTION(store);
|
WRITE_SECTION(store);
|
||||||
for (b = r->buildings; b; b = b->next) {
|
for (b = r->buildings; b; b = b->next) {
|
||||||
write_building_reference(b, store);
|
assert(b->region == r);
|
||||||
WRITE_STR(store, b->name);
|
write_building(data, b);
|
||||||
WRITE_STR(store, b->display ? b->display : "");
|
|
||||||
WRITE_INT(store, b->size);
|
|
||||||
WRITE_TOK(store, b->type->_name);
|
|
||||||
WRITE_SECTION(store);
|
|
||||||
write_attribs(store, b->attribs, b);
|
|
||||||
WRITE_SECTION(store);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_INT(store, listlen(r->ships));
|
WRITE_INT(store, listlen(r->ships));
|
||||||
WRITE_SECTION(store);
|
WRITE_SECTION(store);
|
||||||
for (sh = r->ships; sh; sh = sh->next) {
|
for (sh = r->ships; sh; sh = sh->next) {
|
||||||
assert(sh->region == r);
|
assert(sh->region == r);
|
||||||
write_ship_reference(sh, store);
|
write_ship(data, sh);
|
||||||
WRITE_STR(store, (const char *)sh->name);
|
|
||||||
WRITE_STR(store, sh->display ? (const char *)sh->display : "");
|
|
||||||
WRITE_TOK(store, sh->type->_name);
|
|
||||||
WRITE_INT(store, sh->size);
|
|
||||||
WRITE_INT(store, sh->damage);
|
|
||||||
WRITE_INT(store, sh->flags & SFL_SAVEMASK);
|
|
||||||
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
|
|
||||||
WRITE_INT(store, sh->coast);
|
|
||||||
WRITE_SECTION(store);
|
|
||||||
write_attribs(store, sh->attribs, sh);
|
|
||||||
WRITE_SECTION(store);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_INT(store, listlen(r->units));
|
WRITE_INT(store, listlen(r->units));
|
||||||
WRITE_SECTION(store);
|
WRITE_SECTION(store);
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
|
assert(u->region == r);
|
||||||
write_unit(data, u);
|
write_unit(data, u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ extern "C" {
|
||||||
struct spell;
|
struct spell;
|
||||||
struct spellbook;
|
struct spellbook;
|
||||||
struct unit;
|
struct unit;
|
||||||
|
struct building;
|
||||||
|
struct ship;
|
||||||
struct gamedata;
|
struct gamedata;
|
||||||
|
|
||||||
#define MAX_INPUT_SIZE DISPLAYSIZE*2
|
#define MAX_INPUT_SIZE DISPLAYSIZE*2
|
||||||
|
@ -57,6 +59,18 @@ extern "C" {
|
||||||
|
|
||||||
void write_unit(struct gamedata *data, const struct unit *u);
|
void write_unit(struct gamedata *data, const struct unit *u);
|
||||||
struct unit *read_unit(struct gamedata *data);
|
struct unit *read_unit(struct gamedata *data);
|
||||||
|
|
||||||
|
void write_faction(struct gamedata *data, const struct faction *f);
|
||||||
|
struct faction *read_faction(struct gamedata *data);
|
||||||
|
|
||||||
|
void write_region(struct gamedata *data, const struct region *r);
|
||||||
|
struct region *read_region(struct gamedata *data);
|
||||||
|
|
||||||
|
void write_building(struct gamedata *data, const struct building *b);
|
||||||
|
struct building *read_building(struct gamedata *data);
|
||||||
|
|
||||||
|
void write_ship(struct gamedata *data, const struct ship *sh);
|
||||||
|
struct ship *read_ship(struct gamedata *data);
|
||||||
|
|
||||||
int a_readint(struct attrib *a, void *owner, struct gamedata *);
|
int a_readint(struct attrib *a, void *owner, struct gamedata *);
|
||||||
void a_writeint(const struct attrib *a, const void *owner,
|
void a_writeint(const struct attrib *a, const void *owner,
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "save.h"
|
#include "save.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "building.h"
|
||||||
|
#include "ship.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "ally.h"
|
#include "ally.h"
|
||||||
|
@ -27,6 +29,7 @@
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
static void test_readwrite_data(CuTest * tc)
|
static void test_readwrite_data(CuTest * tc)
|
||||||
|
@ -55,7 +58,8 @@ static void test_readwrite_unit(CuTest * tc)
|
||||||
f = test_create_faction(0);
|
f = test_create_faction(0);
|
||||||
fno = f->no;
|
fno = f->no;
|
||||||
u = test_create_unit(f, r);
|
u = test_create_unit(f, r);
|
||||||
|
unit_setname(u, " Hodor ");
|
||||||
|
CuAssertStrEquals(tc, " Hodor ", u->_name);
|
||||||
mstream_init(&data.strm);
|
mstream_init(&data.strm);
|
||||||
gamedata_init(&data, &store, RELEASE_VERSION);
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
write_unit(&data, u);
|
write_unit(&data, u);
|
||||||
|
@ -69,6 +73,7 @@ static void test_readwrite_unit(CuTest * tc)
|
||||||
u = read_unit(&data);
|
u = read_unit(&data);
|
||||||
CuAssertPtrNotNull(tc, u);
|
CuAssertPtrNotNull(tc, u);
|
||||||
CuAssertPtrEquals(tc, f, u->faction);
|
CuAssertPtrEquals(tc, f, u->faction);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", u->_name);
|
||||||
CuAssertPtrEquals(tc, 0, u->region);
|
CuAssertPtrEquals(tc, 0, u->region);
|
||||||
|
|
||||||
mstream_done(&data.strm);
|
mstream_done(&data.strm);
|
||||||
|
@ -77,6 +82,129 @@ static void test_readwrite_unit(CuTest * tc)
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_faction(CuTest * tc)
|
||||||
|
{
|
||||||
|
gamedata data;
|
||||||
|
storage store;
|
||||||
|
faction *f;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
f = test_create_faction(0);
|
||||||
|
free(f->name);
|
||||||
|
f->name = _strdup(" Hodor ");
|
||||||
|
CuAssertStrEquals(tc, " Hodor ", f->name);
|
||||||
|
mstream_init(&data.strm);
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
write_faction(&data, f);
|
||||||
|
|
||||||
|
data.strm.api->rewind(data.strm.handle);
|
||||||
|
free_gamedata();
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
f = read_faction(&data);
|
||||||
|
CuAssertPtrNotNull(tc, f);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", f->name);
|
||||||
|
CuAssertPtrEquals(tc, 0, f->units);
|
||||||
|
factions = f;
|
||||||
|
|
||||||
|
mstream_done(&data.strm);
|
||||||
|
gamedata_done(&data);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_region(CuTest * tc)
|
||||||
|
{
|
||||||
|
gamedata data;
|
||||||
|
storage store;
|
||||||
|
region *r;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
free(r->land->name);
|
||||||
|
r->land->name = _strdup(" Hodor ");
|
||||||
|
CuAssertStrEquals(tc, " Hodor ", r->land->name);
|
||||||
|
mstream_init(&data.strm);
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
write_region(&data, r);
|
||||||
|
|
||||||
|
data.strm.api->rewind(data.strm.handle);
|
||||||
|
free_gamedata();
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
r = read_region(&data);
|
||||||
|
CuAssertPtrNotNull(tc, r);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", r->land->name);
|
||||||
|
regions = r;
|
||||||
|
|
||||||
|
mstream_done(&data.strm);
|
||||||
|
gamedata_done(&data);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_building(CuTest * tc)
|
||||||
|
{
|
||||||
|
gamedata data;
|
||||||
|
storage store;
|
||||||
|
building *b;
|
||||||
|
region *r;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
b = test_create_building(r, 0);
|
||||||
|
free(b->name);
|
||||||
|
b->name = _strdup(" Hodor ");
|
||||||
|
CuAssertStrEquals(tc, " Hodor ", b->name);
|
||||||
|
mstream_init(&data.strm);
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
write_building(&data, b);
|
||||||
|
|
||||||
|
data.strm.api->rewind(data.strm.handle);
|
||||||
|
free_gamedata();
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
b = read_building(&data);
|
||||||
|
CuAssertPtrNotNull(tc, b);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", b->name);
|
||||||
|
CuAssertPtrEquals(tc, 0, b->region);
|
||||||
|
b->region = r;
|
||||||
|
r->buildings = b;
|
||||||
|
|
||||||
|
mstream_done(&data.strm);
|
||||||
|
gamedata_done(&data);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_readwrite_ship(CuTest * tc)
|
||||||
|
{
|
||||||
|
gamedata data;
|
||||||
|
storage store;
|
||||||
|
ship *sh;
|
||||||
|
region *r;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
sh = test_create_ship(r, 0);
|
||||||
|
free(sh->name);
|
||||||
|
sh->name = _strdup(" Hodor ");
|
||||||
|
CuAssertStrEquals(tc, " Hodor ", sh->name);
|
||||||
|
mstream_init(&data.strm);
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
write_ship(&data, sh);
|
||||||
|
|
||||||
|
data.strm.api->rewind(data.strm.handle);
|
||||||
|
free_gamedata();
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||||
|
sh = read_ship(&data);
|
||||||
|
CuAssertPtrNotNull(tc, sh);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", sh->name);
|
||||||
|
CuAssertPtrEquals(tc, 0, sh->region);
|
||||||
|
sh->region = r;
|
||||||
|
r->ships = sh;
|
||||||
|
|
||||||
|
mstream_done(&data.strm);
|
||||||
|
gamedata_done(&data);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_readwrite_attrib(CuTest *tc) {
|
static void test_readwrite_attrib(CuTest *tc) {
|
||||||
gamedata data;
|
gamedata data;
|
||||||
storage store;
|
storage store;
|
||||||
|
@ -326,6 +454,10 @@ CuSuite *get_save_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_attrib);
|
SUITE_ADD_TEST(suite, test_readwrite_attrib);
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_data);
|
SUITE_ADD_TEST(suite, test_readwrite_data);
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_unit);
|
SUITE_ADD_TEST(suite, test_readwrite_unit);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_faction);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_region);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_building);
|
||||||
|
SUITE_ADD_TEST(suite, test_readwrite_ship);
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_createunit);
|
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_createunit);
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_changefaction);
|
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_changefaction);
|
||||||
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_regionowner);
|
SUITE_ADD_TEST(suite, test_readwrite_dead_faction_regionowner);
|
||||||
|
|
14
src/laws.c
14
src/laws.c
|
@ -79,17 +79,17 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <util/language.h>
|
#include <util/language.h>
|
||||||
#include <util/lists.h>
|
#include <util/lists.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
|
#include <util/message.h>
|
||||||
#include <util/parser.h>
|
#include <util/parser.h>
|
||||||
#include <util/password.h>
|
#include <util/password.h>
|
||||||
#include <quicklist.h>
|
|
||||||
#include <util/rand.h>
|
#include <util/rand.h>
|
||||||
#include <util/rng.h>
|
#include <util/rng.h>
|
||||||
#include <util/umlaut.h>
|
#include <util/umlaut.h>
|
||||||
#include <util/message.h>
|
#include <util/unicode.h>
|
||||||
#include <util/rng.h>
|
|
||||||
|
|
||||||
#include <attributes/otherfaction.h>
|
#include <attributes/otherfaction.h>
|
||||||
|
|
||||||
|
#include <quicklist.h>
|
||||||
#include <iniparser.h>
|
#include <iniparser.h>
|
||||||
/* libc includes */
|
/* libc includes */
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -1627,6 +1627,7 @@ bool renamed_building(const building * b)
|
||||||
|
|
||||||
static int rename_cmd(unit * u, order * ord, char **s, const char *s2)
|
static int rename_cmd(unit * u, order * ord, char **s, const char *s2)
|
||||||
{
|
{
|
||||||
|
char name[NAMESIZE];
|
||||||
assert(s2);
|
assert(s2);
|
||||||
if (!s2[0]) {
|
if (!s2[0]) {
|
||||||
cmistake(u, ord, 84, MSG_EVENT);
|
cmistake(u, ord, 84, MSG_EVENT);
|
||||||
|
@ -1635,12 +1636,11 @@ static int rename_cmd(unit * u, order * ord, char **s, const char *s2)
|
||||||
|
|
||||||
/* TODO: Validate to make sure people don't have illegal characters in
|
/* TODO: Validate to make sure people don't have illegal characters in
|
||||||
* names, phishing-style? () come to mind. */
|
* names, phishing-style? () come to mind. */
|
||||||
|
strlcpy(name, s2, sizeof(name));
|
||||||
|
unicode_utf8_trim(name);
|
||||||
|
|
||||||
free(*s);
|
free(*s);
|
||||||
*s = _strdup(s2);
|
*s = _strdup(name);
|
||||||
if (strlen(s2) >= NAMESIZE) {
|
|
||||||
(*s)[NAMESIZE] = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1024,7 +1024,7 @@ static void test_ally_cmd_errors(CuTest *tc) {
|
||||||
int fid;
|
int fid;
|
||||||
order *ord;
|
order *ord;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
fid = u->faction->no + 1;
|
fid = u->faction->no + 1;
|
||||||
CuAssertPtrEquals(tc, 0, findfaction(fid));
|
CuAssertPtrEquals(tc, 0, findfaction(fid));
|
||||||
|
@ -1037,12 +1037,50 @@ static void test_ally_cmd_errors(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_name_cmd(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
faction *f;
|
||||||
|
order *ord;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
u = test_create_unit(f = test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
|
|
||||||
|
ord = create_order(K_NAME, f->locale, "%s ' Ho\tdor '", LOC(f->locale, parameters[P_UNIT]));
|
||||||
|
name_cmd(u, ord);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", u->_name);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_NAME, f->locale, "%s ' Ho\tdor '", LOC(f->locale, parameters[P_FACTION]));
|
||||||
|
name_cmd(u, ord);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", f->name);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_NAME, f->locale, "%s ' Ho\tdor '", LOC(f->locale, parameters[P_SHIP]));
|
||||||
|
u->ship = test_create_ship(u->region, 0);
|
||||||
|
name_cmd(u, ord);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", u->ship->name);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_NAME, f->locale, "%s ' Ho\tdor '", LOC(f->locale, parameters[P_BUILDING]));
|
||||||
|
u->building = test_create_building(u->region, 0);
|
||||||
|
name_cmd(u, ord);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", u->building->name);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_NAME, f->locale, "%s ' Ho\tdor '", LOC(f->locale, parameters[P_REGION]));
|
||||||
|
name_cmd(u, ord);
|
||||||
|
CuAssertStrEquals(tc, "Hodor", u->region->land->name);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_ally_cmd(CuTest *tc) {
|
static void test_ally_cmd(CuTest *tc) {
|
||||||
unit *u;
|
unit *u;
|
||||||
faction * f;
|
faction * f;
|
||||||
order *ord;
|
order *ord;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
f = test_create_faction(0);
|
f = test_create_faction(0);
|
||||||
|
|
||||||
|
@ -1444,6 +1482,7 @@ CuSuite *get_laws_suite(void)
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_nmr_warnings);
|
SUITE_ADD_TEST(suite, test_nmr_warnings);
|
||||||
SUITE_ADD_TEST(suite, test_ally_cmd);
|
SUITE_ADD_TEST(suite, test_ally_cmd);
|
||||||
|
SUITE_ADD_TEST(suite, test_name_cmd);
|
||||||
SUITE_ADD_TEST(suite, test_ally_cmd_errors);
|
SUITE_ADD_TEST(suite, test_ally_cmd_errors);
|
||||||
SUITE_ADD_TEST(suite, test_long_order_normal);
|
SUITE_ADD_TEST(suite, test_long_order_normal);
|
||||||
SUITE_ADD_TEST(suite, test_long_order_none);
|
SUITE_ADD_TEST(suite, test_long_order_none);
|
||||||
|
|
|
@ -217,7 +217,9 @@ test_create_terrain(const char * name, unsigned int flags)
|
||||||
|
|
||||||
building * test_create_building(region * r, const building_type * btype)
|
building * test_create_building(region * r, const building_type * btype)
|
||||||
{
|
{
|
||||||
building * b = new_building(btype ? btype : test_create_buildingtype("castle"), r, default_locale);
|
building * b;
|
||||||
|
assert(r);
|
||||||
|
b = new_building(btype ? btype : test_create_buildingtype("castle"), r, default_locale);
|
||||||
b->size = b->type->maxsize > 0 ? b->type->maxsize : 1;
|
b->size = b->type->maxsize > 0 ? b->type->maxsize : 1;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#define B00000000 0x00
|
#define B00000000 0x00
|
||||||
#define B10000000 0x80
|
#define B10000000 0x80
|
||||||
|
@ -31,6 +32,84 @@
|
||||||
#define B00000011 0x03
|
#define B00000011 0x03
|
||||||
#define B00000001 0x01
|
#define B00000001 0x01
|
||||||
|
|
||||||
|
int unicode_utf8_trim(utf8_t *buf)
|
||||||
|
{
|
||||||
|
int result = 0, ts = 0;
|
||||||
|
utf8_t *op = buf, *ip = buf, *lc = buf;
|
||||||
|
while (*ip) {
|
||||||
|
ucs4_t ucs = *ip;
|
||||||
|
size_t size = 1;
|
||||||
|
if (ucs & 0x80) {
|
||||||
|
int ret = unicode_utf8_to_ucs4(&ucs, ip, &size);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (op == buf && iswspace(ucs)) {
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
else if (iswprint(ucs)) {
|
||||||
|
if (op != ip) {
|
||||||
|
memcpy(op, ip, size);
|
||||||
|
}
|
||||||
|
op += size;
|
||||||
|
if (iswspace(ucs)) ++ts;
|
||||||
|
else {
|
||||||
|
lc = op;
|
||||||
|
ts = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
ip += size;
|
||||||
|
}
|
||||||
|
*lc = '\0';
|
||||||
|
return result + ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unicode_utf8_mkname(utf8_t * op, size_t outlen, const utf8_t * ip)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
bool iss = true;
|
||||||
|
while (*ip) {
|
||||||
|
size_t size = 1;
|
||||||
|
bool isp = false;
|
||||||
|
do {
|
||||||
|
ucs4_t ucs = *ip;
|
||||||
|
if (ucs & 0x80) {
|
||||||
|
ret = unicode_utf8_to_ucs4(&ucs, ip, &size);
|
||||||
|
if (ret !=0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
isp = iswprint(ucs);
|
||||||
|
iss &= !!iswspace(ucs);
|
||||||
|
} else {
|
||||||
|
isp = isprint(ucs);
|
||||||
|
iss &= !!isspace(ucs);
|
||||||
|
}
|
||||||
|
if (iss) {
|
||||||
|
ip += size;
|
||||||
|
}
|
||||||
|
} while (iss);
|
||||||
|
if (size > outlen) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
if (isp) {
|
||||||
|
memcpy(op, ip, size);
|
||||||
|
op += size;
|
||||||
|
outlen -= size;
|
||||||
|
} else {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
ip += size;
|
||||||
|
}
|
||||||
|
if (outlen <= 0) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
*op = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int unicode_utf8_tolower(utf8_t * op, size_t outlen, const utf8_t * ip)
|
int unicode_utf8_tolower(utf8_t * op, size_t outlen, const utf8_t * ip)
|
||||||
{
|
{
|
||||||
while (*ip) {
|
while (*ip) {
|
||||||
|
|
|
@ -41,8 +41,9 @@ extern "C" {
|
||||||
int unicode_utf8_strcasecmp(const utf8_t * a, const utf8_t * b);
|
int unicode_utf8_strcasecmp(const utf8_t * a, const utf8_t * b);
|
||||||
int unicode_latin1_to_utf8(utf8_t * out, size_t * outlen,
|
int unicode_latin1_to_utf8(utf8_t * out, size_t * outlen,
|
||||||
const char *in, size_t * inlen);
|
const char *in, size_t * inlen);
|
||||||
int unicode_utf8_tolower(utf8_t * out, size_t outlen,
|
int unicode_utf8_tolower(utf8_t *op, size_t outlen, const utf8_t *ip);
|
||||||
const utf8_t * in);
|
int unicode_utf8_mkname(utf8_t *op, size_t outlen, const utf8_t *ip);
|
||||||
|
int unicode_utf8_trim(utf8_t *ip);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,46 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
static void test_unicode_trim(CuTest * tc)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
|
||||||
|
strcpy(buffer, "Hello Word");
|
||||||
|
CuAssertIntEquals(tc, 0, unicode_utf8_trim(buffer));
|
||||||
|
CuAssertStrEquals(tc, "Hello Word", buffer);
|
||||||
|
|
||||||
|
strcpy(buffer, " Hello Word ");
|
||||||
|
CuAssertIntEquals(tc, 4, unicode_utf8_trim(buffer));
|
||||||
|
CuAssertStrEquals(tc, "Hello Word", buffer);
|
||||||
|
|
||||||
|
strcpy(buffer, "Hello Word\n");
|
||||||
|
CuAssertIntEquals(tc, 1, unicode_utf8_trim(buffer));
|
||||||
|
CuAssertStrEquals(tc, "Hello Word", buffer);
|
||||||
|
|
||||||
|
strcpy(buffer, " Hello Word\t\n");
|
||||||
|
CuAssertIntEquals(tc, 4, unicode_utf8_trim(buffer));
|
||||||
|
CuAssertStrEquals(tc, "Hello Word", buffer);
|
||||||
|
|
||||||
|
strcpy(buffer, " \t Hello Word");
|
||||||
|
CuAssertIntEquals(tc, 3, unicode_utf8_trim(buffer));
|
||||||
|
CuAssertStrEquals(tc, "Hello Word", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_unicode_mkname(CuTest * tc)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
CuAssertIntEquals(tc, 0, unicode_utf8_mkname(buffer, sizeof(buffer), " HeLlO W0Rld"));
|
||||||
|
CuAssertStrEquals(tc, "HeLlO W0Rld", buffer);
|
||||||
|
CuAssertIntEquals(tc, 0, unicode_utf8_mkname(buffer, sizeof(buffer), "HeLlO W0Rld"));
|
||||||
|
CuAssertStrEquals(tc, "HeLlO W0Rld", buffer);
|
||||||
|
CuAssertIntEquals(tc, 1, unicode_utf8_mkname(buffer, sizeof(buffer), "HeLlO\nW0Rld"));
|
||||||
|
CuAssertStrEquals(tc, "HeLlOW0Rld", buffer);
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
buffer[5] = 'X';
|
||||||
|
CuAssertIntEquals(tc, ENOMEM, unicode_utf8_mkname(buffer, 5, "HeLl\n W0Rld"));
|
||||||
|
CuAssertStrEquals(tc, "HeLl X", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_unicode_tolower(CuTest * tc)
|
static void test_unicode_tolower(CuTest * tc)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
|
@ -66,6 +106,8 @@ CuSuite *get_unicode_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_unicode_tolower);
|
SUITE_ADD_TEST(suite, test_unicode_tolower);
|
||||||
|
SUITE_ADD_TEST(suite, test_unicode_mkname);
|
||||||
|
SUITE_ADD_TEST(suite, test_unicode_trim);
|
||||||
SUITE_ADD_TEST(suite, test_unicode_utf8_to_other);
|
SUITE_ADD_TEST(suite, test_unicode_utf8_to_other);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue