socsvn commit: r272632 - in soc2014/ghostmansd/head/lib: libc/locale libc/string libcolldb
ghostmansd at FreeBSD.org
ghostmansd at FreeBSD.org
Mon Aug 18 18:13:54 UTC 2014
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.
More information about the svn-soc-all
mailing list