libc/locale: Add __collate_equiv_value functionality
authorJohn Marino <draco@marino.st>
Thu, 6 Aug 2015 21:21:14 +0000 (23:21 +0200)
committerJohn Marino <draco@marino.st>
Thu, 6 Aug 2015 22:05:41 +0000 (00:05 +0200)
This function is required for TRE bracket equivalence support.

lib/libc/locale/Symbol.map
lib/libc/locale/collate.c
lib/libc/locale/collate.h

index 376cd7d..454c89c 100644 (file)
@@ -205,6 +205,7 @@ DF402.0 {
 
 DFprivate_1.0 {
     __detect_path_locale;
+    __collate_equiv_value;
     __collate_load;
     __collate_load_tables;
     __collate_range_cmp;
index 4df1ce4..1b89cf8 100644 (file)
@@ -643,3 +643,56 @@ fail:
                free(tr);
        return ((size_t)(-1));
 }
+
+/*
+ * __collate_equiv_value returns the primary collation value for the given
+ * collating symbol specified by str and len.  Zero or negative is returned
+ * if the collating symbol was not found.  This function is used by bracket
+ * code in the TRE regex library.
+ */
+int
+__collate_equiv_value(locale_t locale, const wchar_t *str, size_t len)
+{
+       int32_t e;
+
+       if (len < 1 || len >= COLLATE_STR_LEN)
+               return (-1);
+
+       FIX_LOCALE(locale);
+       struct xlocale_collate *table =
+               (struct xlocale_collate*)locale->components[XLC_COLLATE];
+
+       if (table->__collate_load_error)
+               return ((len == 1 && *str <= UCHAR_MAX) ? *str : -1);
+
+       if (len == 1) {
+               e = -1;
+               if (*str <= UCHAR_MAX)
+                       e = table->char_pri_table[*str].pri[0];
+               else if (table->info->large_count > 0) {
+                       collate_large_t *match_large;
+                       match_large = largesearch(table, *str);
+                       if (match_large)
+                               e = match_large->pri.pri[0];
+               }
+               if (e == 0)
+                       return (1);
+               return (e > 0 ? e : 0);
+       }
+       if (table->info->chain_count > 0) {
+               wchar_t name[COLLATE_STR_LEN];
+               collate_chain_t *match_chain;
+               int clen;
+
+               wcsncpy (name, str, len);
+               name[len] = 0;
+               match_chain = chainsearch(table, name, &clen);
+               if (match_chain) {
+                       e = match_chain->pri[0];
+                       if (e == 0)
+                               return (1);
+                       return (e < 0 ? -e : e);
+               }
+       }
+       return (0);
+}
index 149750e..082a77d 100644 (file)
@@ -125,6 +125,7 @@ struct xlocale_collate {
 
 __BEGIN_DECLS
 int    __collate_load_tables(const char *);
+int    __collate_equiv_value(locale_t, const wchar_t *, size_t);
 void   _collate_lookup(struct xlocale_collate *,const wchar_t *, int *, int *,
        int, const int **);
 int    __collate_range_cmp(struct xlocale_collate *, wchar_t, wchar_t);