|
4 | 4 |
|
5 | 5 | #include "flutter/fml/icu_util.h" |
6 | 6 |
|
| 7 | +#include <memory> |
7 | 8 | #include <mutex> |
8 | 9 |
|
| 10 | +#include "flutter/fml/build_config.h" |
9 | 11 | #include "flutter/fml/logging.h" |
| 12 | +#include "flutter/fml/mapping.h" |
| 13 | +#include "flutter/fml/native_library.h" |
| 14 | +#include "flutter/fml/paths.h" |
10 | 15 | #include "third_party/icu/source/common/unicode/udata.h" |
11 | 16 |
|
12 | 17 | namespace fml { |
13 | 18 | namespace icu { |
14 | 19 |
|
15 | | -void InitializeICU(std::unique_ptr<const Mapping> mapping) { |
16 | | - if (mapping == nullptr || mapping->GetSize() == 0) { |
17 | | - return; |
| 20 | +class ICUContext { |
| 21 | + public: |
| 22 | + ICUContext(const std::string& icu_data_path) : valid_(false) { |
| 23 | + valid_ = SetupMapping(icu_data_path) && SetupICU(); |
18 | 24 | } |
19 | | - static std::once_flag g_icu_init_flag; |
20 | | - std::call_once(g_icu_init_flag, [mapping = std::move(mapping)]() mutable { |
21 | | - static auto icu_mapping = std::move(mapping); |
| 25 | + |
| 26 | + ICUContext(std::unique_ptr<Mapping> mapping) : mapping_(std::move(mapping)) { |
| 27 | + valid_ = SetupICU(); |
| 28 | + } |
| 29 | + |
| 30 | + ~ICUContext() = default; |
| 31 | + |
| 32 | + bool SetupMapping(const std::string& icu_data_path) { |
| 33 | + // Check if the path exists and it readable directly. |
| 34 | + auto fd = |
| 35 | + fml::OpenFile(icu_data_path.c_str(), false, fml::FilePermission::kRead); |
| 36 | + |
| 37 | + // Check the path relative to the current executable. |
| 38 | + if (!fd.is_valid()) { |
| 39 | + auto directory = fml::paths::GetExecutableDirectoryPath(); |
| 40 | + |
| 41 | + if (!directory.first) { |
| 42 | + return false; |
| 43 | + } |
| 44 | + |
| 45 | + std::string path_relative_to_executable = |
| 46 | + paths::JoinPaths({directory.second, icu_data_path}); |
| 47 | + |
| 48 | + fd = fml::OpenFile(path_relative_to_executable.c_str(), false, |
| 49 | + fml::FilePermission::kRead); |
| 50 | + } |
| 51 | + |
| 52 | + if (!fd.is_valid()) { |
| 53 | + return false; |
| 54 | + } |
| 55 | + |
| 56 | + std::initializer_list<FileMapping::Protection> protection = { |
| 57 | + fml::FileMapping::Protection::kRead}; |
| 58 | + |
| 59 | + auto file_mapping = |
| 60 | + std::make_unique<FileMapping>(fd, std::move(protection)); |
| 61 | + |
| 62 | + if (file_mapping->GetSize() != 0) { |
| 63 | + mapping_ = std::move(file_mapping); |
| 64 | + return true; |
| 65 | + } |
| 66 | + |
| 67 | + return false; |
| 68 | + } |
| 69 | + |
| 70 | + bool SetupICU() { |
| 71 | + if (GetSize() == 0) { |
| 72 | + return false; |
| 73 | + } |
| 74 | + |
22 | 75 | UErrorCode err_code = U_ZERO_ERROR; |
23 | | - udata_setCommonData(icu_mapping->GetMapping(), &err_code); |
24 | | - FML_CHECK(err_code == U_ZERO_ERROR) << "Must be able to initialize ICU."; |
| 76 | + udata_setCommonData(GetMapping(), &err_code); |
| 77 | + return (err_code == U_ZERO_ERROR); |
| 78 | + } |
| 79 | + |
| 80 | + const uint8_t* GetMapping() const { |
| 81 | + return mapping_ ? mapping_->GetMapping() : nullptr; |
| 82 | + } |
| 83 | + |
| 84 | + size_t GetSize() const { return mapping_ ? mapping_->GetSize() : 0; } |
| 85 | + |
| 86 | + bool IsValid() const { return valid_; } |
| 87 | + |
| 88 | + private: |
| 89 | + bool valid_; |
| 90 | + std::unique_ptr<Mapping> mapping_; |
| 91 | + |
| 92 | + FML_DISALLOW_COPY_AND_ASSIGN(ICUContext); |
| 93 | +}; |
| 94 | + |
| 95 | +void InitializeICUOnce(const std::string& icu_data_path) { |
| 96 | + static ICUContext* context = new ICUContext(icu_data_path); |
| 97 | + FML_CHECK(context->IsValid()) |
| 98 | + << "Must be able to initialize the ICU context. Tried: " << icu_data_path; |
| 99 | +} |
| 100 | + |
| 101 | +std::once_flag g_icu_init_flag; |
| 102 | +void InitializeICU(const std::string& icu_data_path) { |
| 103 | + std::call_once(g_icu_init_flag, |
| 104 | + [&icu_data_path]() { InitializeICUOnce(icu_data_path); }); |
| 105 | +} |
| 106 | + |
| 107 | +void InitializeICUFromMappingOnce(std::unique_ptr<Mapping> mapping) { |
| 108 | + static ICUContext* context = new ICUContext(std::move(mapping)); |
| 109 | + FML_CHECK(context->IsValid()) |
| 110 | + << "Unable to initialize the ICU context from a mapping."; |
| 111 | +} |
| 112 | + |
| 113 | +void InitializeICUFromMapping(std::unique_ptr<Mapping> mapping) { |
| 114 | + std::call_once(g_icu_init_flag, [mapping = std::move(mapping)]() mutable { |
| 115 | + InitializeICUFromMappingOnce(std::move(mapping)); |
25 | 116 | }); |
26 | 117 | } |
27 | 118 |
|
|
0 commit comments