• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // Copyright 2019 Google LLC.
2  // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3  
4  #include "SkLoadICU.h"
5  
6  #if defined(_WIN32) && defined(SK_USING_THIRD_PARTY_ICU)
7  
8  #ifndef WIN32_LEAN_AND_MEAN
9  #define WIN32_LEAN_AND_MEAN
10  #endif
11  #include <windows.h>
12  #include <io.h>
13  
14  #include <cstdio>
15  #include <cstring>
16  #include <mutex>
17  #include <string>
18  
19  #include "unicode/udata.h"
20  
win_mmap(const char * dataFile)21  static void* win_mmap(const char* dataFile) {
22      if (!dataFile) {
23          return nullptr;
24      }
25      struct FCloseWrapper { void operator()(FILE* f) { fclose(f); } };
26      std::unique_ptr<FILE, FCloseWrapper> stream(fopen(dataFile, "rb"));
27      if (!stream) {
28          fprintf(stderr, "SkIcuLoader: datafile missing.\n");
29          return nullptr;
30      }
31      int fileno = _fileno(stream.get());
32      if (fileno < 0) {
33          fprintf(stderr, "SkIcuLoader: datafile fileno error.\n");
34          return nullptr;
35      }
36      HANDLE file = (HANDLE)_get_osfhandle(fileno);
37      if ((HANDLE)INVALID_HANDLE_VALUE == file) {
38          fprintf(stderr, "SkIcuLoader: datafile handle error.\n");
39          return nullptr;
40      }
41      struct CloseHandleWrapper { void operator()(HANDLE h) { CloseHandle(h); } };
42      std::unique_ptr<void, CloseHandleWrapper> mmapHandle(
43          CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
44      if (!mmapHandle) {
45          fprintf(stderr, "SkIcuLoader: datafile mmap error.\n");
46          return nullptr;
47      }
48      void* addr = MapViewOfFile(mmapHandle.get(), FILE_MAP_READ, 0, 0, 0);
49      if (nullptr == addr) {
50          fprintf(stderr, "SkIcuLoader: datafile view error.\n");
51          return nullptr;
52      }
53      return addr;
54  }
55  
init_icu(void * addr)56  static bool init_icu(void* addr) {
57      UErrorCode err = U_ZERO_ERROR;
58      udata_setCommonData(addr, &err);
59      if (err != U_ZERO_ERROR) {
60          fprintf(stderr, "udata_setCommonData() returned %d.\n", (int)err);
61          return false;
62      }
63      udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
64      if (err != U_ZERO_ERROR) {
65          fprintf(stderr, "udata_setFileAccess() returned %d.\n", (int)err);
66          return false;
67      }
68      return true;
69  }
70  
executable_directory()71  static std::string executable_directory() {
72      HMODULE hModule = GetModuleHandleA(NULL);
73      char path[MAX_PATH];
74      GetModuleFileNameA(hModule, path, MAX_PATH);
75      const char* end = strrchr(path, '\\');
76      return end ? std::string(path, end - path) : std::string();
77  }
78  
SkLoadICU()79  bool SkLoadICU() {
80      static bool good = false;
81      static std::once_flag flag;
82      std::call_once(flag, []() {
83          std::string sPath = executable_directory();
84          sPath += "\\icudtl.dat";
85          if (void* addr = win_mmap(sPath.c_str())) {
86              if (init_icu(addr)) {
87                  good = true;
88              }
89          }
90      });
91      return good;
92  }
93  
94  #endif  // defined(_WIN32) && defined(SK_USING_THIRD_PARTY_ICU)
95