Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add locale argument to collation_key

  • Loading branch information...
commit 997ba3bfd17b9425d59d72839dbad5bcc9533429 1 parent 36fa52a
Nikolai Weibull authored
View
2  ext/u/rb_u_string.c
@@ -364,7 +364,7 @@ Init_u_string(VALUE mU)
rb_define_method(rb_cUString, "<=>", rb_u_string_collate, -1); /* in ext/u/rb_u_string_collate.c */
rb_define_method(rb_cUString, "casecmp", rb_u_string_casecmp, -1); /* in ext/u/rb_u_string_casecmp.c */
- rb_define_method(rb_cUString, "collation_key", rb_u_string_collation_key, 0); /* in ext/u/rb_u_string_collation_key.c */
+ rb_define_method(rb_cUString, "collation_key", rb_u_string_collation_key, -1); /* in ext/u/rb_u_string_collation_key.c */
rb_define_method(rb_cUString, "combining_class", rb_u_string_combining_class, 0); /* in ext/u/rb_u_string_combining_class.c */
rb_define_method(rb_cUString, "general_category", rb_u_string_general_category, 0); /* in ext/u/rb_u_string_general_category.c */
View
2  ext/u/rb_u_string.h
@@ -80,7 +80,7 @@ VALUE rb_u_string_chop(VALUE self);
VALUE rb_u_string_chr(VALUE self);
VALUE rb_u_string_cntrl(VALUE self);
VALUE rb_u_string_collate(int argc, VALUE *argv, VALUE self);
-VALUE rb_u_string_collation_key(VALUE self);
+VALUE rb_u_string_collation_key(int argc, VALUE *argv, VALUE self);
VALUE rb_u_string_combining_class(VALUE self);
VALUE rb_u_string_count(int argc, VALUE *argv, VALUE self);
VALUE rb_u_string_defined(VALUE self);
View
25 ext/u/rb_u_string_collation_key.c
@@ -1,18 +1,17 @@
#include "rb_includes.h"
-/* @return [U::String] The locale-dependent collation key of the receiver,
- * inheriting any taint and untrust
- * @note Use the collation key when comparing U::Strings to each other
- * repeatedly, as occurs when, for example, sorting a list of U::Strings. */
+/* @overload collation_key(locale = ENV['LC_COLLATE'])
+ *
+ * @return [U::String] The locale-dependent collation key of the receiver in
+ * LOCALE, inheriting any taint and untrust
+ * @note Use the collation key when comparing U::Strings to each other
+ * repeatedly, as occurs when, for example, sorting a list of
+ * U::Strings.
+ * @note The LOCALE must be given as a language, region, and encoding, for
+ * example, “en_US.UTF-8”. */
VALUE
-rb_u_string_collation_key(VALUE self)
+rb_u_string_collation_key(int argc, VALUE *argv, VALUE self)
{
- const struct rb_u_string *string = RVAL2USTRING(self);
-
- size_t length;
- char *collation_key = u_collation_key_n(USTRING_STR(string),
- USTRING_LENGTH(string),
- &length);
-
- return rb_u_string_new_c_own(self, collation_key, length);
+ return _rb_u_string_case_in_locale(argc, argv, self,
+ u_collation_key_in_locale_n);
}
View
2  ext/u/u.h
@@ -375,6 +375,8 @@ U_PURE int u_collate_n(const char *a, size_t a_n, const char *b, size_t b_n);
U_PURE int u_collate_in_locale_n(const char *a, size_t a_n, const char *b, size_t b_n, const char *locale);
char *u_collation_key(const char *str);
char *u_collation_key_n(const char *str, size_t n, size_t *new_n);
+char *u_collation_key_in_locale_n(const char *str, size_t n, const char *locale,
+ size_t *new_n);
U_PURE size_t u_char_index(const char *str, uint32_t c);
U_PURE size_t u_char_index_n(const char *str, uint32_t c, size_t n);
View
33 ext/u/u_collation_key.c
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <wchar.h>
+#include <xlocale.h>
#include "u.h"
#include "utf8.h"
@@ -52,13 +53,21 @@ utf8_encode(char *buf, wchar_t c)
return retval;
}
+static size_t
+key(wchar_t *result, const wchar_t *string, size_t n, locale_t locale)
+{
+ return locale != NULL ?
+ wcsxfrm_l(result, string, n, locale) :
+ wcsxfrm(result, string, n);
+}
/* {{{1
* Generate a collation key from a string which can be compared with other
* collation keys using str_compare().
*/
static char *
-u_collation_key_impl(const char *str, size_t n, bool use_n, size_t *new_n)
+u_collation_key_impl(const char *str, size_t n, bool use_n, const char *locale,
+ size_t *new_n)
{
assert(str != NULL);
@@ -76,9 +85,13 @@ u_collation_key_impl(const char *str, size_t n, bool use_n, size_t *new_n)
}
*q = '\0';
- size_t xfrm_n = wcsxfrm(NULL, (wchar_t *)str_norm, 0);
- wchar_t result_wc[xfrm_n + 1];
- wcsxfrm(result_wc, (wchar_t *)str_norm, xfrm_n + 1);
+ locale_t l = NULL;
+ if (locale != NULL)
+ l = newlocale(LC_COLLATE_MASK, locale, NULL);
+
+ size_t xfrm_n = key(NULL, (wchar_t *)str_norm, 0, l);
+ wchar_t *result_wc = malloc(sizeof(wchar_t) * (xfrm_n + 1));
+ key(result_wc, (wchar_t *)str_norm, xfrm_n + 1, l);
int result_n = 0;
for (size_t i = 0; i < xfrm_n; i++)
@@ -90,6 +103,7 @@ u_collation_key_impl(const char *str, size_t n, bool use_n, size_t *new_n)
result_n += utf8_encode(result + result_n, result_wc[i]);
result[result_n] = '\0';
+ free(result_wc);
free(str_norm);
if (new_n != NULL)
@@ -106,7 +120,7 @@ u_collation_key_impl(const char *str, size_t n, bool use_n, size_t *new_n)
char *
u_collation_key(const char *str)
{
- return u_collation_key_impl(str, 0, false, NULL);
+ return u_collation_key_impl(str, 0, false, NULL, NULL);
}
@@ -117,5 +131,12 @@ u_collation_key(const char *str)
char *
u_collation_key_n(const char *str, size_t n, size_t *new_n)
{
- return u_collation_key_impl(str, n, true, new_n);
+ return u_collation_key_impl(str, n, true, NULL, new_n);
+}
+
+char *
+u_collation_key_in_locale_n(const char *str, size_t n, const char *locale,
+ size_t *new_n)
+{
+ return u_collation_key_impl(str, n, true, locale, new_n);
}
Please sign in to comment.
Something went wrong with that request. Please try again.