1// Copyright 2013 the V8 project 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 "src/icu_util.h" 6 7#if defined(_WIN32) 8#include <windows.h> 9#endif 10 11#if defined(V8_I18N_SUPPORT) 12#include <stdio.h> 13#include <stdlib.h> 14 15#include "unicode/putil.h" 16#include "unicode/udata.h" 17 18#include "src/base/build_config.h" 19#include "src/base/file-utils.h" 20 21#define ICU_UTIL_DATA_FILE 0 22#define ICU_UTIL_DATA_SHARED 1 23#define ICU_UTIL_DATA_STATIC 2 24 25#define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat" 26#define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt.dll" 27#endif 28 29namespace v8 { 30 31namespace internal { 32 33#if defined(V8_I18N_SUPPORT) && (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE) 34namespace { 35char* g_icu_data_ptr = NULL; 36 37void free_icu_data_ptr() { 38 delete[] g_icu_data_ptr; 39} 40 41} // namespace 42#endif 43 44bool InitializeICUDefaultLocation(const char* exec_path, 45 const char* icu_data_file) { 46#if !defined(V8_I18N_SUPPORT) 47 return true; 48#else 49#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE 50 if (icu_data_file) { 51 return InitializeICU(icu_data_file); 52 } 53 char* icu_data_file_default; 54#if defined(V8_TARGET_LITTLE_ENDIAN) 55 base::RelativePath(&icu_data_file_default, exec_path, "icudtl.dat"); 56#elif defined(V8_TARGET_BIG_ENDIAN) 57 base::RelativePath(&icu_data_file_default, exec_path, "icudtb.dat"); 58#else 59#error Unknown byte ordering 60#endif 61 bool result = InitializeICU(icu_data_file_default); 62 free(icu_data_file_default); 63 return result; 64#else 65 return InitializeICU(NULL); 66#endif 67#endif 68} 69 70bool InitializeICU(const char* icu_data_file) { 71#if !defined(V8_I18N_SUPPORT) 72 return true; 73#else 74#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED 75 // We expect to find the ICU data module alongside the current module. 76 HMODULE module = LoadLibraryA(ICU_UTIL_DATA_SHARED_MODULE_NAME); 77 if (!module) return false; 78 79 FARPROC addr = GetProcAddress(module, ICU_UTIL_DATA_SYMBOL); 80 if (!addr) return false; 81 82 UErrorCode err = U_ZERO_ERROR; 83 udata_setCommonData(reinterpret_cast<void*>(addr), &err); 84 return err == U_ZERO_ERROR; 85#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC 86 // Mac/Linux bundle the ICU data in. 87 return true; 88#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE 89 if (!icu_data_file) return false; 90 91 if (g_icu_data_ptr) return true; 92 93 FILE* inf = fopen(icu_data_file, "rb"); 94 if (!inf) return false; 95 96 fseek(inf, 0, SEEK_END); 97 size_t size = ftell(inf); 98 rewind(inf); 99 100 g_icu_data_ptr = new char[size]; 101 if (fread(g_icu_data_ptr, 1, size, inf) != size) { 102 delete[] g_icu_data_ptr; 103 g_icu_data_ptr = NULL; 104 fclose(inf); 105 return false; 106 } 107 fclose(inf); 108 109 atexit(free_icu_data_ptr); 110 111 UErrorCode err = U_ZERO_ERROR; 112 udata_setCommonData(reinterpret_cast<void*>(g_icu_data_ptr), &err); 113 return err == U_ZERO_ERROR; 114#endif 115#endif 116} 117 118} // namespace internal 119} // namespace v8 120