/* * Copyright 2010-2013 Various Authors * Copyright 2010 Johannes Weißl * * based on gunicollate.c from glib * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include "u_collate.h" #include "uchar.h" #include "xmalloc.h" #include "ui_curses.h" /* using_utf8, charset */ #include "convert.h" #include #include #include int u_strcoll(const char *str1, const char *str2) { int result; if (using_utf8) { result = strcoll(str1, str2); } else { char *str1_locale = NULL, *str2_locale = NULL; convert(str1, -1, &str1_locale, -1, charset, "UTF-8"); convert(str2, -1, &str2_locale, -1, charset, "UTF-8"); if (str1_locale && str2_locale) result = strcoll(str1_locale, str2_locale); else result = strcmp(str1, str2); if (str2_locale) free(str2_locale); if (str1_locale) free(str1_locale); } return result; } int u_strcasecoll(const char *str1, const char *str2) { char *cf_a, *cf_b; int res; cf_a = u_casefold(str1); cf_b = u_casefold(str2); res = u_strcoll(cf_a, cf_b); free(cf_b); free(cf_a); return res; } int u_strcasecoll0(const char *str1, const char *str2) { if (!str1) return str2 ? -1 : 0; if (!str2) return 1; return u_strcasecoll(str1, str2); } char *u_strcoll_key(const char *str) { char *result = NULL; if (using_utf8) { size_t xfrm_len = strxfrm(NULL, str, 0); if ((ssize_t) xfrm_len >= 0 && xfrm_len < INT_MAX - 2) { result = xnew(char, xfrm_len + 1); strxfrm(result, str, xfrm_len + 1); } } if (!result) { char *str_locale = NULL; convert(str, -1, &str_locale, -1, charset, "UTF-8"); if (str_locale) { size_t xfrm_len = strxfrm(NULL, str_locale, 0); if ((ssize_t) xfrm_len >= 0 && xfrm_len < INT_MAX - 2) { result = xnew(char, xfrm_len + 2); result[0] = 'A'; strxfrm(result + 1, str_locale, xfrm_len + 1); } free(str_locale); } } if (!result) { size_t xfrm_len = strlen(str); result = xmalloc(xfrm_len + 2); result[0] = 'B'; memcpy(result + 1, str, xfrm_len); result[xfrm_len+1] = '\0'; } return result; } char *u_strcasecoll_key(const char *str) { char *key, *cf_str; cf_str = u_casefold(str); key = u_strcoll_key(cf_str); free(cf_str); return key; } char *u_strcasecoll_key0(const char *str) { return str ? u_strcasecoll_key(str) : NULL; }