1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/i18n/icu_util.h" 6 7 #include "build/build_config.h" 8 9 #if defined(OS_WIN) 10 #include <windows.h> 11 #endif 12 13 #include <string> 14 15 #include "base/file_path.h" 16 #include "base/file_util.h" 17 #include "base/logging.h" 18 #include "base/path_service.h" 19 #include "base/string_util.h" 20 #include "base/sys_string_conversions.h" 21 #include "unicode/putil.h" 22 #include "unicode/udata.h" 23 24 #define ICU_UTIL_DATA_FILE 0 25 #define ICU_UTIL_DATA_SHARED 1 26 #define ICU_UTIL_DATA_STATIC 2 27 28 #ifndef ICU_UTIL_DATA_IMPL 29 30 #if defined(OS_WIN) 31 #define ICU_UTIL_DATA_IMPL ICU_UTIL_DATA_SHARED 32 #elif defined(OS_MACOSX) 33 #define ICU_UTIL_DATA_IMPL ICU_UTIL_DATA_STATIC 34 #elif defined(OS_POSIX) 35 #define ICU_UTIL_DATA_IMPL ICU_UTIL_DATA_FILE 36 #endif 37 38 #endif // ICU_UTIL_DATA_IMPL 39 40 #if defined(OS_WIN) 41 #define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat" 42 #define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt" U_ICU_VERSION_SHORT ".dll" 43 #endif 44 45 namespace icu_util { 46 Initialize()47bool Initialize() { 48 #ifndef NDEBUG 49 // Assert that we are not called more than once. Even though calling this 50 // function isn't harmful (ICU can handle it), being called twice probably 51 // indicates a programming error. 52 static bool called_once = false; 53 DCHECK(!called_once); 54 called_once = true; 55 #endif 56 57 #if (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED) 58 // We expect to find the ICU data module alongside the current module. 59 FilePath data_path; 60 PathService::Get(base::DIR_MODULE, &data_path); 61 data_path = data_path.AppendASCII(ICU_UTIL_DATA_SHARED_MODULE_NAME); 62 63 HMODULE module = LoadLibrary(data_path.value().c_str()); 64 if (!module) { 65 LOG(ERROR) << "Failed to load " << ICU_UTIL_DATA_SHARED_MODULE_NAME; 66 return false; 67 } 68 69 FARPROC addr = GetProcAddress(module, ICU_UTIL_DATA_SYMBOL); 70 if (!addr) { 71 LOG(ERROR) << ICU_UTIL_DATA_SYMBOL << ": not found in " 72 << ICU_UTIL_DATA_SHARED_MODULE_NAME; 73 return false; 74 } 75 76 UErrorCode err = U_ZERO_ERROR; 77 udata_setCommonData(reinterpret_cast<void*>(addr), &err); 78 return err == U_ZERO_ERROR; 79 #elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC) 80 // Mac bundles the ICU data in. 81 return true; 82 #elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE) 83 // For now, expect the data file to be alongside the executable. 84 // This is sufficient while we work on unit tests, but will eventually 85 // likely live in a data directory. 86 FilePath data_path; 87 bool path_ok = PathService::Get(base::DIR_EXE, &data_path); 88 DCHECK(path_ok); 89 u_setDataDirectory(data_path.value().c_str()); 90 // Only look for the packaged data file; 91 // the default behavior is to look for individual files. 92 UErrorCode err = U_ZERO_ERROR; 93 udata_setFileAccess(UDATA_ONLY_PACKAGES, &err); 94 return err == U_ZERO_ERROR; 95 #endif 96 } 97 98 } // namespace icu_util 99