/* * libslp-db-util * * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: Hakjoo Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include #include #include #include #include #include "collation.h" #include "db-util-debug.h" #define DB_UTIL_RETV_IF(cond,ret) \ do {\ if(cond) {\ DB_UTIL_TRACE_WARNING("\x1b[33m[%s()][RET_IF]\x1b[0m",__FUNCTION__);\ return ret;\ }\ }while(0) #define DB_UTIL_RET_IF(cond) \ do {\ if(cond) {\ DB_UTIL_TRACE_WARNING("\x1b[33m[%s()][RET_IF]\x1b[0m",__FUNCTION__);\ return;\ }\ }while(0) #define DB_UTIL_ERR_COL_FUNC_RET DB_UTIL_ERROR enum { DB_UTIL_ERR_DLOPEN = -10, DB_UTIL_ERR_DLSYM, DB_UTIL_ERR_ENV, DB_UTIL_ERR_ICU, DB_UTIL_ERR_PARAM }; enum { DB_UTIL_CMP_SC, /* Loop comparison */ DB_UTIL_CMP_LC }; #define ICU_FUNC_CNT 8 typedef UCollator* (*ICU_UCOL_OPEN)(const char *, UErrorCode *); typedef void (*ICU_UCOL_CLOSE)(UCollator *); typedef void (*ICU_UCOL_SETSTRENGTH)(UCollator *, UCollationStrength); typedef UCollationResult (*ICU_UCOL_STRCOLL)(const UCollator *, const UChar *, int32_t, const UChar *, int32_t); typedef UCollationResult (*ICU_UCOL_STRCOLLITER)(const UCollator *, UCharIterator *, UCharIterator *, UErrorCode *); typedef void (*ICU_UITER_SETUTF8)(UCharIterator *, const char *, int32_t); typedef void (*ICU_ULOC_SETDEFAULT)(const char* localeID, UErrorCode* status); typedef const char* (*ICU_ULOC_GETDEFAULT)(void); typedef struct { ICU_UCOL_OPEN icu_ucol_open; ICU_UCOL_CLOSE icu_ucol_close; ICU_UCOL_STRCOLL icu_ucol_strcoll; ICU_UCOL_STRCOLLITER icu_ucol_strcollIter; ICU_UCOL_SETSTRENGTH icu_ucol_setStrength; ICU_UITER_SETUTF8 icu_uiter_setUTF8; ICU_ULOC_SETDEFAULT icu_uloc_setDefault; ICU_ULOC_GETDEFAULT icu_uloc_getDefault; } db_util_icu_func_t; db_util_icu_func_t icu_symbol; void *g_dl_icu_handle = NULL; #ifdef DB_UTIL_ENABLE_DEVDEBUG static char *strtoutf8(const UChar * unichars, int len); #endif static int __db_util_dl_load_icu() { void *handle = NULL; void *icu_handle[ICU_FUNC_CNT] = { 0 }; char *dl_error; int i = 0; const char *ICU_API[] = { "ucol_open", "ucol_close", "ucol_strcoll", "ucol_strcollIter", "ucol_setStrength", "uiter_setUTF8", "uloc_setDefault", "uloc_getDefault" }; if(g_dl_icu_handle == NULL) { g_dl_icu_handle = dlopen("libicui18n.so", RTLD_LAZY | RTLD_GLOBAL); if(g_dl_icu_handle == NULL) { DB_UTIL_TRACE_WARNING("dlopen icu so fail"); return DB_UTIL_ERR_DLOPEN; } } for (i = 0; i < ICU_FUNC_CNT; i++) { handle = dlsym(g_dl_icu_handle, ICU_API[i]); if ((dl_error = dlerror()) != NULL) { DB_UTIL_TRACE_WARNING("dlsym(%s) is failed for %s", dl_error, ICU_API[i]); return DB_UTIL_ERR_DLSYM; } icu_handle[i] = handle; } memcpy((void*)&icu_symbol, (const void*)icu_handle, sizeof(icu_handle)); return DB_UTIL_OK; } /* The collating function must return an integer that is negative, zero or positive */ static int __db_util_collate_icu_16(void *ucol, int str1_len, const void *str1, int str2_len, const void *str2) { #ifdef DB_UTIL_ENABLE_DEVDEBUG DB_UTIL_TRACE_DEBUG("__db_util_collate_icu_16 func start \n"); UChar* tmp_v1 = (UChar *)str1; UChar* tmp_v2 = (UChar *)str2; char* utf8_v1 = strtoutf8(tmp_v1, str1_len); char* utf8_v2 = strtoutf8(tmp_v2, str2_len); DB_UTIL_TRACE_DEBUG("v1(%d) : %s\n", str1_len, utf8_v1); DB_UTIL_TRACE_DEBUG("v2(%d) : %s\n", str2_len, utf8_v2); #endif DB_UTIL_RETV_IF(icu_symbol.icu_ucol_strcoll == NULL, DB_UTIL_ERR_COL_FUNC_RET); UCollationResult result = icu_symbol.icu_ucol_strcoll( (UCollator *) ucol, (const UChar *) str1, str1_len, (const UChar *) str2, str2_len); #ifdef DB_UTIL_ENABLE_DEVDEBUG if(utf8_v1) free(utf8_v1); if(utf8_v2) free(utf8_v2); if (result == UCOL_LESS) { DB_UTIL_TRACE_DEBUG("less \n"); } else if (result == UCOL_GREATER) { DB_UTIL_TRACE_DEBUG("greater \n"); } else { DB_UTIL_TRACE_DEBUG("equal \n"); } #endif return result; } /* The collating function must return an integer that is negative, zero or positive */ static int __db_util_collate_icu_16_lc(void *ucol, int str1_len, const void *str1, int str2_len, const void *str2) { #ifdef DB_UTIL_ENABLE_DEVDEBUG DB_UTIL_TRACE_DEBUG("__db_util_collate_icu_16_lc func start \n"); UChar* tmp_v1 = (UChar *)str1; UChar* tmp_v2 = (UChar *)str2; char* utf8_v1 = strtoutf8(tmp_v1, str1_len); char* utf8_v2 = strtoutf8(tmp_v2, str2_len); DB_UTIL_TRACE_DEBUG("v1(%d) : %s\n", str1_len, utf8_v1); DB_UTIL_TRACE_DEBUG("v2(%d) : %s\n", str2_len, utf8_v2); if(utf8_v1) free(utf8_v1); if(utf8_v2) free(utf8_v2); #endif UCollationResult result = 0; UChar* str_to = (UChar *)str1; UChar* str_from = (UChar *)str1; int i; DB_UTIL_RETV_IF(icu_symbol.icu_ucol_strcoll == NULL, DB_UTIL_ERR_COL_FUNC_RET); if(str1_len> str2_len) { for(i=0;i v2_char_len) { for(i=0;i