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#define ICU_UTIL_DATA_FILE   0
19#define ICU_UTIL_DATA_SHARED 1
20#define ICU_UTIL_DATA_STATIC 2
21
22#define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat"
23#define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt.dll"
24#endif
25
26namespace v8 {
27
28namespace internal {
29
30#if defined(V8_I18N_SUPPORT) && (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
31namespace {
32char* g_icu_data_ptr = NULL;
33
34void free_icu_data_ptr() {
35  delete[] g_icu_data_ptr;
36}
37
38}  // namespace
39#endif
40
41bool InitializeICU(const char* icu_data_file) {
42#if !defined(V8_I18N_SUPPORT)
43  return true;
44#else
45#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED
46  // We expect to find the ICU data module alongside the current module.
47  HMODULE module = LoadLibraryA(ICU_UTIL_DATA_SHARED_MODULE_NAME);
48  if (!module) return false;
49
50  FARPROC addr = GetProcAddress(module, ICU_UTIL_DATA_SYMBOL);
51  if (!addr) return false;
52
53  UErrorCode err = U_ZERO_ERROR;
54  udata_setCommonData(reinterpret_cast<void*>(addr), &err);
55  return err == U_ZERO_ERROR;
56#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC
57  // Mac/Linux bundle the ICU data in.
58  return true;
59#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
60  if (!icu_data_file) return false;
61
62  if (g_icu_data_ptr) return true;
63
64  FILE* inf = fopen(icu_data_file, "rb");
65  if (!inf) return false;
66
67  fseek(inf, 0, SEEK_END);
68  size_t size = ftell(inf);
69  rewind(inf);
70
71  g_icu_data_ptr = new char[size];
72  if (fread(g_icu_data_ptr, 1, size, inf) != size) {
73    delete[] g_icu_data_ptr;
74    g_icu_data_ptr = NULL;
75    fclose(inf);
76    return false;
77  }
78  fclose(inf);
79
80  atexit(free_icu_data_ptr);
81
82  UErrorCode err = U_ZERO_ERROR;
83  udata_setCommonData(reinterpret_cast<void*>(g_icu_data_ptr), &err);
84  return err == U_ZERO_ERROR;
85#endif
86#endif
87}
88
89}  // namespace internal
90}  // namespace v8
91