finditemtype works as tested.

starting to think about removing default_locale in lieu of a hierarchical system.
This commit is contained in:
Enno Rehling 2012-05-21 13:18:05 -07:00
parent 5ab1b2881a
commit 1e9c10fbe2
7 changed files with 63 additions and 49 deletions

View file

@ -56,6 +56,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
static critbit_tree inames[MAXLOCALES];
static critbit_tree cb_resources; static critbit_tree cb_resources;
static critbit_tree cb_items; static critbit_tree cb_items;
luxury_type *luxurytypes; luxury_type *luxurytypes;
@ -1100,46 +1101,49 @@ attrib_type at_showitem = {
"showitem" "showitem"
}; };
/* static local_names *inames; */ static int add_itemname_cb(const void * match, const void * key, size_t keylen, void *data)
{
struct locale * lang = (struct locale *)data;
int i = locale_index(lang);
critbit_tree * cb = inames+i;
item_type *itype;
cb_get_kv(match, &itype, sizeof(itype));
for (i = 0; i!=2;++i) {
char buffer[64];
const char * name = locale_string(lang, itype->rtype->_name[i]);
if (name && transliterate(buffer, sizeof(buffer), name)) {
size_t len = strlen(buffer);
assert(len+sizeof(itype)<sizeof(buffer));
cb_new_kv(buffer, &itype, sizeof(itype), buffer);
cb_insert(cb, buffer, len+1+sizeof(itype));
}
}
return 0;
}
const item_type *finditemtype(const char *name, const struct locale *lang) const item_type *finditemtype(const char *name, const struct locale *lang)
{ {
local_names *inames = 0; int i = locale_index(lang);
const void * matches[CB_BATCHSIZE]; critbit_tree * cb = inames+i;
local_names *in = inames; char buffer[64];
variant token;
while (in) { if (transliterate(buffer, sizeof(buffer), name)) {
if (in->lang == lang) const void * match;
break; if (!cb->root) {
in = in->next; /* first-time initialization of item names for this locale */
cb_foreach(&cb_items, "", 0, add_itemname_cb, (void *)lang);
}
if (cb_find_prefix(cb, buffer, strlen(buffer), &match, 1, 0)) {
const item_type * itype = 0;
cb_get_kv(match, (void*)&itype, sizeof(itype));
return itype;
}
} else {
log_debug("finditemtype: transliterate failed for '%s'\n", name);
} }
if (!in) { return 0;
int m, offset = 0;
in = (local_names *)calloc(1, sizeof(local_names));
in->next = inames;
in->lang = lang;
do {
m = cb_find_prefix(&cb_items, "", 0, matches, CB_BATCHSIZE, offset);
if (m) {
int i;
offset += m;
for (i=0;i!=m;++i) {
item_type *itype;
cb_get_kv(matches[i], &itype, sizeof(itype));
token.v = (void *)itype;
addtoken(&in->names, locale_string(lang, itype->rtype->_name[0]), token);
addtoken(&in->names, locale_string(lang, itype->rtype->_name[1]), token);
}
}
} while (m==CB_BATCHSIZE);
inames = in;
}
if (findtoken(in->names, name, &token) == E_TOK_NOMATCH) {
return 0;
}
return (const item_type *)token.v;
} }
static void init_resourcelimit(attrib * a) static void init_resourcelimit(attrib * a)
@ -1197,6 +1201,8 @@ int free_rtype_cb(const void * match, const void * key, size_t keylen, void *cbd
void test_clear_resources(void) void test_clear_resources(void)
{ {
int i;
memset((void *)olditemtype, 0, sizeof(olditemtype)); memset((void *)olditemtype, 0, sizeof(olditemtype));
memset((void *)oldresourcetype, 0, sizeof(oldresourcetype)); memset((void *)oldresourcetype, 0, sizeof(oldresourcetype));
memset((void *)oldpotiontype, 0, sizeof(oldpotiontype)); memset((void *)oldpotiontype, 0, sizeof(oldpotiontype));
@ -1209,7 +1215,9 @@ void test_clear_resources(void)
r_hp = r_silver = r_aura = r_permaura = r_unit = 0; r_hp = r_silver = r_aura = r_permaura = r_unit = 0;
i_silver = 0; i_silver = 0;
/* inames = 0; TODO: this is a terrible hack, the whole inames global state must die */ for (i=0; i!=MAXLOCALES; ++i) {
cb_clear(inames+i);
}
} }
#endif #endif

View file

@ -31,28 +31,34 @@ void test_resource_type(CuTest * tc)
void test_finditemtype(CuTest * tc) void test_finditemtype(CuTest * tc)
{ {
struct item_type *itype; const item_type *itype, *iresult;
const char *names[4] = { "herp" , "herp_p", "derp", "derp_p" }; const char *names[] = { "herp" , "herp_p" };
struct locale * lang = make_locale("de"); struct locale * lang = make_locale("de");
test_cleanup(); test_cleanup();
locale_setstring(lang, names[0], "Foo");
itype = test_create_itemtype(names); itype = test_create_itemtype(names);
CuAssertPtrNotNull(tc, itype); CuAssertPtrNotNull(tc, itype);
locale_setstring(lang, names[0], "Foo"); iresult = finditemtype("Foo", lang);
locale_setstring(lang, names[1], "Foos"); CuAssertPtrEquals(tc, (void*)itype, (void*)iresult);
}
#if 0
locale_setstring(lang, names[1], "Foos");
CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Foo", lang)); CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Foo", lang));
CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Foos", lang)); CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Foos", lang));
test_cleanup();
itype = test_create_itemtype(names+2); itype = test_create_itemtype(names+2);
CuAssertPtrNotNull(tc, itype); CuAssertPtrNotNull(tc, itype);
locale_setstring(lang, names[2], "Bar"); locale_setstring(lang, names[2], "Bar");
locale_setstring(lang, names[3], "Bars"); locale_setstring(lang, names[3], "Bars");
CuAssertPtrEquals(tc, (void*)0, (void*)finditemtype("Foo", lang));
CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Bar", lang)); CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Bar", lang));
CuAssertPtrEquals(tc, (void*)itype, (void*)finditemtype("Bars", lang));
} }
#endif
CuSuite *get_item_suite(void) CuSuite *get_item_suite(void)
{ {

View file

@ -330,13 +330,14 @@ int cb_erase(critbit_tree * cb, const void * key, size_t keylen)
} }
} }
void cb_new_kv(const char *key, void * value, size_t len, void * dst) size_t cb_new_kv(const char *key, void * value, size_t len, void * dst)
{ {
size_t keylen = strlen(key)+1; size_t keylen = strlen(key)+1;
if (dst!=key) { if (dst!=key) {
memcpy(dst, key, keylen); memcpy(dst, key, keylen);
} }
memcpy((char*)dst+keylen, value, len); memcpy((char*)dst+keylen, value, len);
return len+keylen;
} }
void cb_get_kv(const void *kv, void * value, size_t len) void cb_get_kv(const void *kv, void * value, size_t len)

View file

@ -47,7 +47,7 @@ void cb_clear(critbit_tree * cb);
#define cb_find_prefix_str(cb, key, results, numresults, offset) \ #define cb_find_prefix_str(cb, key, results, numresults, offset) \
cb_find_prefix(cb, (void *)key, strlen(key), results, numresults, offset) cb_find_prefix(cb, (void *)key, strlen(key), results, numresults, offset)
void cb_new_kv(const char *key, void * value, size_t len, void * dst); size_t cb_new_kv(const char *key, void * value, size_t len, void * dst);
void cb_get_kv(const void *kv, void * value, size_t len); void cb_get_kv(const void *kv, void * value, size_t len);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -127,7 +127,7 @@ const char *locale_getstring(const locale * lang, const char *key)
const char *locale_string(const locale * lang, const char *key) const char *locale_string(const locale * lang, const char *key)
{ {
assert(lang != 0); assert(lang);
if (key != NULL) { if (key != NULL) {
unsigned int hkey = hashstring(key); unsigned int hkey = hashstring(key);
@ -136,8 +136,6 @@ const char *locale_string(const locale * lang, const char *key)
if (*key == 0) if (*key == 0)
return NULL; return NULL;
if (lang == NULL)
return key;
find = lang->strings[id]; find = lang->strings[id];
while (find) { while (find) {
if (find->hashkey == hkey) { if (find->hashkey == hkey) {
@ -153,8 +151,8 @@ const char *locale_string(const locale * lang, const char *key)
} }
if (!find) { if (!find) {
log_warning("missing translation for \"%s\" in locale %s\n", key, lang->name); log_warning("missing translation for \"%s\" in locale %s\n", key, lang->name);
if (lang != default_locale) { if (lang->fallback) {
return locale_string(default_locale, key); return locale_string(lang->fallback, key);
} }
return 0; return 0;
} }

View file

@ -19,6 +19,7 @@ typedef struct locale {
unsigned int hashkey; unsigned int hashkey;
const char *name; const char *name;
struct locale_str *strings[SMAXHASH]; struct locale_str *strings[SMAXHASH];
struct locale *fallback;
} locale; } locale;
extern locale *default_locale; extern locale *default_locale;

View file

@ -125,7 +125,7 @@ void addtoken(void ** root, const char *str, variant id)
0, ""} 0, ""}
}; };
assert(root); assert(root && str);
if (!*root) { if (!*root) {
tk = *root = calloc(1, sizeof(tnode)); tk = *root = calloc(1, sizeof(tnode));
} else { } else {