Date: Mon, 18 Aug 2014 18:13:50 GMT From: ghostmansd@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r272632 - in soc2014/ghostmansd/head/lib: libc/locale libc/string libcolldb Message-ID: <201408181813.s7IIDo7Q045267@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ghostmansd Date: Mon Aug 18 18:13:50 2014 New Revision: 272632 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272632 Log: reference counting system; revised fallbacks Added: soc2014/ghostmansd/head/lib/libcolldb/colldb.3 Modified: soc2014/ghostmansd/head/lib/libc/locale/collate.c soc2014/ghostmansd/head/lib/libc/locale/collate.h soc2014/ghostmansd/head/lib/libc/locale/xlocale.c soc2014/ghostmansd/head/lib/libc/locale/xlocale_private.h soc2014/ghostmansd/head/lib/libc/string/strcoll.c soc2014/ghostmansd/head/lib/libc/string/strxfrm.c soc2014/ghostmansd/head/lib/libc/string/wcscoll.c soc2014/ghostmansd/head/lib/libc/string/wcsxfrm.c Modified: soc2014/ghostmansd/head/lib/libc/locale/collate.c ============================================================================== --- soc2014/ghostmansd/head/lib/libc/locale/collate.c Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/locale/collate.c Mon Aug 18 18:13:50 2014 (r272632) @@ -51,6 +51,290 @@ #include "libc_private.h" +#define ROOT_COLLDB "/usr/share/locale/UTF-8/LC_COLLATE" + + +/* Collation Database. */ +struct __colldb { + uint32_t version; + void *handle; +}; + +void * +__colldb_create(const char *path, int mode) +{ + DBT key; + DBT value; + DB *db = NULL; + int error = 0; + void *colldb = NULL; + uint32_t version = 0; + int flags = (O_RDWR | O_CREAT | O_TRUNC); + + colldb = calloc(1, sizeof(struct __colldb)); + if (colldb == NULL) { + errno = ENOMEM; + return (NULL); + } + db = dbopen(path, flags, mode, DB_HASH, NULL); + if (db == NULL) { + error = errno; + free(colldb); + errno = error; + return (NULL); + } + ((struct __colldb*)colldb)->version = __COLLDB_VERSION; + + key.data = "TYPE"; + value.data = "COLLATION"; + key.size = (strlen("TYPE") + 1); + value.size = (strlen("COLLATION") + 1); + if (db->put(db, &key, &value, 0) == -1) { + error = errno; + goto failure; + } + + key.data = "VERSION"; + version = htonl(((struct __colldb*)colldb)->version); + value.data = &version; + key.size = (strlen("VERSION") + 1); + value.size = sizeof(((struct __colldb*)colldb)->version); + if (db->put(db, &key, &value, 0) == -1) { + error = errno; + goto failure; + } + + ((struct __colldb*)colldb)->handle = db; + return (colldb); + +failure: + (void) db->close(db); + free(colldb); + errno = error; + return (NULL); +} + +void * +__colldb_open(const char *path) +{ + DBT key; + DBT value; + DB *db = NULL; + int error = 0; + int state = 0; + void *colldb = NULL; + int flags = O_RDONLY; + + colldb = calloc(1, sizeof(struct __colldb)); + if (colldb == NULL) { + errno = ENOMEM; + return (NULL); + } + db = dbopen(path, flags, 0, DB_HASH, NULL); + if (db == NULL) { + error = errno; + free(colldb); + errno = error; + return (NULL); + } + + key.data = "TYPE"; + key.size = (strlen("TYPE") + 1); + state = db->get(db, &key, &value, 0); + if (state != 0) { + if (state < 0) + error = errno; + else + error = EFTYPE; + goto failure; + } + if (strcmp(value.data, "COLLATION") != 0) { + error = EFTYPE; + goto failure; + } + + key.data = "VERSION"; + key.size = (strlen("VERSION") + 1); + state = db->get(db, &key, &value, 0); + if (state != 0) { + if (state < 0) + error = errno; + else + error = EFTYPE; + goto failure; + } + ((struct __colldb*)colldb)->version = + ntohl(*(const uint32_t*)value.data); + + ((struct __colldb*)colldb)->handle = db; + return (colldb); + +failure: + (void) db->close(db); + free(colldb); + errno = error; + return (NULL); +} + +int +__colldb_close(void *colldb) +{ + DB *db = NULL; + int error = 0; + + if (colldb == NULL) { + errno = EINVAL; + return (-1); + } + db = ((struct __colldb*)colldb)->handle; + if (db == NULL) { + errno = EINVAL; + return (-1); + } + if (db->close(db) == -1) { + error = errno; + free(colldb); + errno = error; + return (-1); + } + free(colldb); + return (0); +} + +int +__colldb_sync(void *colldb) +{ + DB *db = NULL; + + if (colldb == NULL) { + errno = EINVAL; + return (-1); + } + db = ((struct __colldb*)colldb)->handle; + if (db == NULL) { + errno = EINVAL; + return (-1); + } + return db->sync(db, 0); +} + +int +__colldb_get(void *colldb, + struct __colldb_key *key, + struct __colldb_value *value) +{ + DBT dbkey; + DBT dbvalue; + DB *db = NULL; + size_t i = 0; + int error = 0; + int state = 0; + uint32_t *keybuf = NULL; + struct __colldb_weight *weights = NULL; + + if ((colldb == NULL) || (key == NULL) || (value == NULL)) { + errno = EINVAL; + return (-1); + } + db = ((struct __colldb*)colldb)->handle; + if ((db == NULL) || (key->chars == NULL) || (key->count == 0)) { + errno = EINVAL; + return (-1); + } + + keybuf = malloc(key->count * sizeof(*key->chars)); + if (keybuf == NULL) { + errno = ENOMEM; + return (-1); + } + for (i = 0; i < key->count; ++i) + keybuf[i] = htonl(key->chars[i]); + + dbkey.data = keybuf; + dbkey.size = (key->count * sizeof(*key->chars)); + state = db->get(db, &dbkey, &dbvalue, 0); + if (state != 0) { + error = errno; + free(keybuf); + errno = error; + return (state); + } + + weights = dbvalue.data; + if ((dbvalue.size / sizeof(*weights)) > value->count) { + free(keybuf); + errno = ERANGE; + return (-1); + } + value->count = (dbvalue.size / sizeof(*weights)); + for (i = 0; i < value->count; ++i) { + value->weights[i].alternate = weights[i].alternate; + value->weights[i].level1 = ntohl(weights[i].level1); + value->weights[i].level2 = ntohl(weights[i].level2); + value->weights[i].level3 = ntohl(weights[i].level3); + value->weights[i].level4 = ntohl(weights[i].level4); + } + free(dbvalue.data); + free(keybuf); + return (0); +} + +int +__colldb_put(void *colldb, + struct __colldb_key *key, + struct __colldb_value *value) +{ + DBT dbkey; + DBT dbvalue; + DB *db = NULL; + size_t i = 0; + int state = 0; + int error = 0; + uint32_t *keybuf = NULL; + struct __colldb_weight *valuebuf = NULL; + + if ((colldb == NULL) || (key == NULL) || (value == NULL)) { + errno = EINVAL; + return (-1); + } + db = ((struct __colldb*)colldb)->handle; + if ((db == NULL) || (key->chars == NULL) || (key->count == 0)) { + errno = EINVAL; + return (-1); + } + + valuebuf = value->weights; + keybuf = malloc(key->count * sizeof(*key->chars)); + valuebuf = malloc(value->count * sizeof(*value->weights)); + if ((keybuf == NULL) || (valuebuf == NULL)) { + errno = ENOMEM; + return (-1); + } + for (i = 0; i < key->count; ++i) + keybuf[i] = htonl(key->chars[i]); + for (i = 0; i < value->count; ++i) { + valuebuf[i].alternate = value->weights[i].alternate; + valuebuf[i].level1 = htonl(value->weights[i].level1); + valuebuf[i].level2 = htonl(value->weights[i].level2); + valuebuf[i].level3 = htonl(value->weights[i].level3); + valuebuf[i].level4 = htonl(value->weights[i].level4); + } + + dbkey.data = keybuf; + dbvalue.data = valuebuf; + dbkey.size = (key->count * sizeof(*key->chars)); + dbvalue.size = (value->count * sizeof(*value->weights)); + state = db->put(db, &dbkey, &dbvalue, 0); + if (state != 0) { + error = errno; + free(keybuf); + free(valuebuf); + errno = error; + } + return state; +} + + /* * To avoid modifying the original (single-threaded) code too much, we'll just * define the old globals as fields inside the table. @@ -66,11 +350,11 @@ struct xlocale_collate __xlocale_global_collate = { - {{0}, "C"}, 1, 0 + {{0}, "C"}, NULL, 1, 0 }; - struct xlocale_collate __xlocale_C_collate = { - {{0}, "C"}, 1, 0 +struct xlocale_collate __xlocale_C_collate = { + {{0}, "C"}, NULL, 1, 0 }; void __collate_err(int ex, const char *f) __dead2; @@ -84,6 +368,11 @@ struct xlocale_collate *table = t; if (__collate_chain_pri_table) { free(__collate_chain_pri_table); + __collate_chain_pri_table = NULL; + } + if (table->__colldb != NULL) { + __colldb_close(table->__colldb); + table->__colldb = NULL; } free(t); } @@ -122,6 +411,7 @@ FILE *fp; int i, saverr, chains; uint32_t u32; + void *colldb = NULL; char strbuf[STR_LEN], buf[PATH_MAX]; void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table; @@ -137,6 +427,20 @@ (void)strcat(buf, "/"); (void)strcat(buf, encoding); (void)strcat(buf, "/LC_COLLATE"); + + /* + * Try to use collation database for the given locale. + * If collation database does not exist for the given locale, + * try to use root collation database. + * If it fails too, use original collation algorithm. + */ + saverr = errno; + if ((table->__colldb = __colldb_open(buf)) == NULL) + table->__colldb = __colldb_open(ROOT_COLLDB); + if (colldb != NULL) + return (_LDP_LOADED); + errno = saverr; + if ((fp = fopen(buf, "re")) == NULL) return (_LDP_ERROR); Modified: soc2014/ghostmansd/head/lib/libc/locale/collate.h ============================================================================== --- soc2014/ghostmansd/head/lib/libc/locale/collate.h Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/locale/collate.h Mon Aug 18 18:13:50 2014 (r272632) @@ -45,6 +45,39 @@ #define COLLATE_VERSION "1.0\n" #define COLLATE_VERSION1_2 "1.2\n" + +#define __COLLDB_VERSION 0x00000001 +#define __COLLDB_WEIGHTS_MAX 16 +struct __colldb_weight { + uint8_t alternate; + uint32_t level1; + uint32_t level2; + uint32_t level3; + uint32_t level4; +}; +struct __colldb_key { + size_t count; + const uint32_t *chars; +}; +struct __colldb_value { + size_t count; + struct __colldb_weight *weights; +}; +void* __colldb_create(const char*, int mode); +void* __colldb_open(const char*); +int __colldb_close(void*); +int __colldb_sync(void*); +int __colldb_get(void*, + struct __colldb_key*, + struct __colldb_value*); +int __colldb_put(void*, + struct __colldb_key*, + struct __colldb_value*); + +size_t __ucsxfrm(uint32_t*, const uint32_t*, size_t, void*); +int __ucscoll(const uint32_t*, const uint32_t*, void*); + + struct __collate_st_char_pri { int prim, sec; }; @@ -58,6 +91,7 @@ struct xlocale_collate { struct xlocale_component header; + void *__colldb; int __collate_load_error; int __collate_substitute_nontrivial; Modified: soc2014/ghostmansd/head/lib/libc/locale/xlocale.c ============================================================================== --- soc2014/ghostmansd/head/lib/libc/locale/xlocale.c Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/locale/xlocale.c Mon Aug 18 18:13:50 2014 (r272632) @@ -43,306 +43,6 @@ #include "xlocale_private.h" -/* Collation Database. */ -static void *colldb_root_handle = NULL; -static pthread_once_t colldb_root_once = PTHREAD_ONCE_INIT; - -static void colldb_root_init(void) -{ - colldb_root_handle = - __colldb_open("/usr/share/locale/UTF-8/LC_COLLATE"); -} - -void *__colldb_root_handle(void) -{ - _once(&colldb_root_once, &colldb_root_init); - if (colldb_root_handle == NULL) { - errno = ENOSYS; - return (NULL); - } - return (colldb_root_handle); -} - -struct __colldb { - uint32_t version; - void *handle; -}; - -void * -__colldb_create(const char *path, int mode) -{ - DBT key; - DBT value; - DB *db = NULL; - int error = 0; - void *colldb = NULL; - uint32_t version = 0; - int flags = (O_RDWR | O_CREAT | O_TRUNC); - - colldb = calloc(1, sizeof(struct __colldb)); - if (colldb == NULL) { - errno = ENOMEM; - return (NULL); - } - db = dbopen(path, flags, mode, DB_HASH, NULL); - if (db == NULL) { - error = errno; - free(colldb); - errno = error; - return (NULL); - } - ((struct __colldb*)colldb)->version = __COLLDB_VERSION; - - key.data = "TYPE"; - value.data = "COLLATION"; - key.size = (strlen("TYPE") + 1); - value.size = (strlen("COLLATION") + 1); - if (db->put(db, &key, &value, 0) == -1) { - error = errno; - goto failure; - } - - key.data = "VERSION"; - version = htonl(((struct __colldb*)colldb)->version); - value.data = &version; - key.size = (strlen("VERSION") + 1); - value.size = sizeof(((struct __colldb*)colldb)->version); - if (db->put(db, &key, &value, 0) == -1) { - error = errno; - goto failure; - } - - ((struct __colldb*)colldb)->handle = db; - return (colldb); - -failure: - (void) db->close(db); - free(colldb); - errno = error; - return (NULL); -} - -void * -__colldb_open(const char *path) -{ - DBT key; - DBT value; - DB *db = NULL; - int error = 0; - int state = 0; - void *colldb = NULL; - int flags = O_RDONLY; - - colldb = calloc(1, sizeof(struct __colldb)); - if (colldb == NULL) { - errno = ENOMEM; - return (NULL); - } - db = dbopen(path, flags, 0, DB_HASH, NULL); - if (db == NULL) { - error = errno; - free(colldb); - errno = error; - return (NULL); - } - - key.data = "TYPE"; - key.size = (strlen("TYPE") + 1); - state = db->get(db, &key, &value, 0); - if (state != 0) { - if (state < 0) - error = errno; - else - error = EFTYPE; - goto failure; - } - if (strcmp(value.data, "COLLATION") != 0) { - error = EFTYPE; - goto failure; - } - - key.data = "VERSION"; - key.size = (strlen("VERSION") + 1); - state = db->get(db, &key, &value, 0); - if (state != 0) { - if (state < 0) - error = errno; - else - error = EFTYPE; - goto failure; - } - ((struct __colldb*)colldb)->version = - ntohl(*(const uint32_t*)value.data); - - ((struct __colldb*)colldb)->handle = db; - return (colldb); - -failure: - (void) db->close(db); - free(colldb); - errno = error; - return (NULL); -} - -int -__colldb_close(void *colldb) -{ - DB *db = NULL; - int error = 0; - - if (colldb == NULL) { - errno = EINVAL; - return (-1); - } - db = ((struct __colldb*)colldb)->handle; - if (db == NULL) { - errno = EINVAL; - return (-1); - } - if (db->close(db) == -1) { - error = errno; - free(colldb); - errno = error; - return (-1); - } - free(colldb); - return (0); -} - -int -__colldb_sync(void *colldb) -{ - DB *db = NULL; - - if (colldb == NULL) { - errno = EINVAL; - return (-1); - } - db = ((struct __colldb*)colldb)->handle; - if (db == NULL) { - errno = EINVAL; - return (-1); - } - return db->sync(db, 0); -} - -int -__colldb_get(void *colldb, - struct __colldb_key *key, - struct __colldb_value *value) -{ - DBT dbkey; - DBT dbvalue; - DB *db = NULL; - size_t i = 0; - int error = 0; - int state = 0; - uint32_t *keybuf = NULL; - struct __colldb_weight *weights = NULL; - - if ((colldb == NULL) || (key == NULL) || (value == NULL)) { - errno = EINVAL; - return (-1); - } - db = ((struct __colldb*)colldb)->handle; - if ((db == NULL) || (key->chars == NULL) || (key->count == 0)) { - errno = EINVAL; - return (-1); - } - - keybuf = malloc(key->count * sizeof(*key->chars)); - if (keybuf == NULL) { - errno = ENOMEM; - return (-1); - } - for (i = 0; i < key->count; ++i) - keybuf[i] = htonl(key->chars[i]); - - dbkey.data = keybuf; - dbkey.size = (key->count * sizeof(*key->chars)); - state = db->get(db, &dbkey, &dbvalue, 0); - if (state != 0) { - error = errno; - free(keybuf); - errno = error; - return (state); - } - - weights = dbvalue.data; - if ((dbvalue.size / sizeof(*weights)) > value->count) { - free(keybuf); - errno = ERANGE; - return (-1); - } - value->count = (dbvalue.size / sizeof(*weights)); - for (i = 0; i < value->count; ++i) { - value->weights[i].alternate = weights[i].alternate; - value->weights[i].level1 = ntohl(weights[i].level1); - value->weights[i].level2 = ntohl(weights[i].level2); - value->weights[i].level3 = ntohl(weights[i].level3); - value->weights[i].level4 = ntohl(weights[i].level4); - } - free(dbvalue.data); - free(keybuf); - return (0); -} - -int -__colldb_put(void *colldb, - struct __colldb_key *key, - struct __colldb_value *value) -{ - DBT dbkey; - DBT dbvalue; - DB *db = NULL; - size_t i = 0; - int state = 0; - int error = 0; - uint32_t *keybuf = NULL; - struct __colldb_weight *valuebuf = NULL; - - if ((colldb == NULL) || (key == NULL) || (value == NULL)) { - errno = EINVAL; - return (-1); - } - db = ((struct __colldb*)colldb)->handle; - if ((db == NULL) || (key->chars == NULL) || (key->count == 0)) { - errno = EINVAL; - return (-1); - } - - valuebuf = value->weights; - keybuf = malloc(key->count * sizeof(*key->chars)); - valuebuf = malloc(value->count * sizeof(*value->weights)); - if ((keybuf == NULL) || (valuebuf == NULL)) { - errno = ENOMEM; - return (-1); - } - for (i = 0; i < key->count; ++i) - keybuf[i] = htonl(key->chars[i]); - for (i = 0; i < value->count; ++i) { - valuebuf[i].alternate = value->weights[i].alternate; - valuebuf[i].level1 = htonl(value->weights[i].level1); - valuebuf[i].level2 = htonl(value->weights[i].level2); - valuebuf[i].level3 = htonl(value->weights[i].level3); - valuebuf[i].level4 = htonl(value->weights[i].level4); - } - - dbkey.data = keybuf; - dbvalue.data = valuebuf; - dbkey.size = (key->count * sizeof(*key->chars)); - dbvalue.size = (value->count * sizeof(*value->weights)); - state = db->put(db, &dbkey, &dbvalue, 0); - if (state != 0) { - error = errno; - free(keybuf); - free(valuebuf); - errno = error; - } - return state; -} - - /** * Each locale loader declares a global component. This is used by setlocale() * and also by xlocale with LC_GLOBAL_LOCALE.. Modified: soc2014/ghostmansd/head/lib/libc/locale/xlocale_private.h ============================================================================== --- soc2014/ghostmansd/head/lib/libc/locale/xlocale_private.h Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/locale/xlocale_private.h Mon Aug 18 18:13:50 2014 (r272632) @@ -52,40 +52,6 @@ #define __UC_NFKC 4 size_t __ucsnorm(uint32_t*, const uint32_t*, size_t, int); -#define __COLLDB_VERSION 0x00000001 -#define __COLLDB_WEIGHTS_MAX 16 -struct __colldb_weight { - uint8_t alternate; - uint32_t level1; - uint32_t level2; - uint32_t level3; - uint32_t level4; -}; -struct __colldb_key { - size_t count; - const uint32_t *chars; -}; -struct __colldb_value { - size_t count; - struct __colldb_weight *weights; -}; -void *__colldb_root_handle(void); -#define __colldb_root (__colldb_root_handle()) - -void* __colldb_create(const char*, int mode); -void* __colldb_open(const char*); -int __colldb_close(void*); -int __colldb_sync(void*); -int __colldb_get(void*, - struct __colldb_key*, - struct __colldb_value*); -int __colldb_put(void*, - struct __colldb_key*, - struct __colldb_value*); - -size_t __ucsxfrm(uint32_t*, const uint32_t*, size_t, void*); -int __ucscoll(const uint32_t*, const uint32_t*, void*); - enum { XLC_COLLATE = 0, @@ -132,8 +98,6 @@ struct xlocale_refcounted header; /** Components for the locale. */ struct xlocale_component *components[XLC_LAST]; - /** Collation Database handle. */ - void *colldb; /** Flag indicating if components[XLC_MONETARY] has changed since the * last call to localeconv_l() with this locale. */ int monetary_locale_changed; Modified: soc2014/ghostmansd/head/lib/libc/string/strcoll.c ============================================================================== --- soc2014/ghostmansd/head/lib/libc/string/strcoll.c Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/string/strcoll.c Mon Aug 18 18:13:50 2014 (r272632) @@ -35,13 +35,37 @@ #include <stdlib.h> #include <string.h> +#include <wchar.h> #include "collate.h" -#include <stdio.h> + +static wchar_t * +__wcsdup(const char *s) +{ + static const mbstate_t initial; + mbstate_t st = initial; + size_t len = 0; + wchar_t *wcs = NULL; + const char *cp = s; + + cp = s; + st = initial; + if ((len = mbsrtowcs(NULL, &cp, 0, &st)) == (size_t)-1) + return (NULL); + if ((wcs = malloc((len + 1) * sizeof(wchar_t))) == NULL) + return (NULL); + st = initial; + mbsrtowcs(wcs, &s, len + 1, &st); + + return (wcs); +} + int strcoll_l(const char *s, const char *s2, locale_t locale) { + wchar_t *ws = NULL; + wchar_t *ws2 = NULL; int len, len2, prim, prim2, sec, sec2, ret, ret2; const char *t, *t2; char *tt, *tt2; Modified: soc2014/ghostmansd/head/lib/libc/string/strxfrm.c ============================================================================== --- soc2014/ghostmansd/head/lib/libc/string/strxfrm.c Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/string/strxfrm.c Mon Aug 18 18:13:50 2014 (r272632) @@ -51,6 +51,8 @@ int prim, sec, l; size_t slen; char *s, *ss; + wchar_t *ws = NULL; + wchar_t *wss = NULL; FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; Modified: soc2014/ghostmansd/head/lib/libc/string/wcscoll.c ============================================================================== --- soc2014/ghostmansd/head/lib/libc/string/wcscoll.c Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/string/wcscoll.c Mon Aug 18 18:13:50 2014 (r272632) @@ -78,12 +78,6 @@ struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; - errno = 0; - diff = __ucscoll(ucs1, ucs2, locale->colldb); - if (errno != ENOSYS) - return (diff); - errno = init_error; - if (table->__collate_load_error || MB_CUR_MAX > 1) /* * Locale has no special collating order, could not be @@ -92,6 +86,9 @@ */ return (wcscmp(ws1, ws2)); + if (table->__colldb != NULL) + return __ucscoll(ucs1, ucs2, table->__colldb); + if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) { /* * Out of memory or illegal wide chars; fall back to wcscmp() Modified: soc2014/ghostmansd/head/lib/libc/string/wcsxfrm.c ============================================================================== --- soc2014/ghostmansd/head/lib/libc/string/wcsxfrm.c Mon Aug 18 17:38:50 2014 (r272631) +++ soc2014/ghostmansd/head/lib/libc/string/wcsxfrm.c Mon Aug 18 18:13:50 2014 (r272632) @@ -59,12 +59,6 @@ struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; - errno = 0; - ulen = __ucsxfrm(udst, usrc, len, locale->colldb); - if (errno != ENOSYS) - return (ulen); - errno = init_error; - if (*src == L'\0') { if (len != 0) *dest = L'\0'; @@ -84,6 +78,9 @@ return (slen); } + if (table->__colldb != NULL) + return __ucsxfrm(udst, usrc, len, table->__colldb); + mbsrc = __mbsdup(src); slen = 0; prim = sec = 0; Added: soc2014/ghostmansd/head/lib/libcolldb/colldb.3 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2014/ghostmansd/head/lib/libcolldb/colldb.3 Mon Aug 18 18:13:50 2014 (r272632) @@ -0,0 +1,130 @@ +.\"- +.\" Copyright (c) 2014 Dmitry Selyutin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" + +.Dd August 18, 2014 +.Dt COLLDB 3 +.Os +.Sh NAME +.Nm colldb_create , +.Nm colldb_open , +.Nm colldb_sync , +.Nm colldb_close , +.Nm colldb_get , +.Nm colldb_put +.Nd Collation database functions +.Sh LIBRARY +.Lb libcolldb +.Sh SYNOPSIS +.In colldb.h +.Ft void * +.Fn colldb_create "const char *path" "int mode" +.Ft void * +.Fn colldb_open "const char *path" +.Ft int +.Fn colldb_sync "void *colldb" +.Ft int +.Fn colldb_close "void *colldb" +.Ft int +.Fn colldb_get "void *colldb" "struct colldb_key *key" \ +"struct colldb_value *value" +.Ft int +.Fn colldb_put "void *colldb" "struct colldb_key *key" \ +"struct colldb_value *value" +.Sh DESCRIPTION +libcolldb provides a high-level interface for processing collation databases. +Database is a map of struct colldb_key and struct colldb_value pairs, where +each uint32_t integer is stored in network byte order. +.br +Conversion between host and network byte order is done implicitly. +.Pp +.Sh STRUCTURES +.Pp +.Bd -literal +struct colldb_weight { + uint8_t alternate; + uint32_t level1; + uint32_t level2; + uint32_t level3; + uint32_t level4; +}; +.Ed +.Pp +.Bd -literal +struct colldb_key { + size_t count; + uint32_t *chars; +}; +.Ed +.Pp +.Bd -literal +struct colldb_value { + size_t count; + struct colldb_weight *weights; +}; +.Ed +.Pp +.Fn colldb_create +creates a new collation database. +.Fa mode +argument is interpreted in the same way as in +.Fn open +call. +.Pp +.Fn colldb_open +opens existing collation database. +.Pp +.Fn colldb_sync +flushes any cached information to disk. +.Pp +.Fn colldb_close +flushes any cached information to disk, frees any allocated resources, and +closes the underlying file. +.Pp +.Fn colldb_get +accepts database, key and value. Key is converted to network byte order if +necessary. Fields of struct colldb_value must be already correctly initialized, +since value from database is written directly to it. Usually it is enough to +allocate +.Dv Va COLLDB_WEIGHTS_MAX +weights, set +.Va count +member of struct colldb_value to this number and set +.Va weights +member of struct colldb_value to point to allocated weights. However, in order +to support exotic databases, colldb_get() may return -1 and set errno to +.Er ERANGE +to indicate that struct colldb_value must allocate a larger weights buffer. +.Pp +.Fn colldb_put +accepts database, key and value. If necessary, it converts key and value into +the network byte order before writing. +.Sh ERRORS +.Fn colldb_create +and +.Fn colldb_open +return handle to collation database or NULL in case of failure. All other +functions behave exactly like their Berkley Database ancestors. Thus caller +must use return value and errno to determine what error happened.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408181813.s7IIDo7Q045267>