This was vastly simplified to make the diff more readable. Differential Revision: https://phabricator.services.mozilla.com/D307365
384 lines
16 KiB
Diff
384 lines
16 KiB
Diff
diff --git a/ggml/src/gguf.cpp b/ggml/src/gguf.cpp
|
|
index 61026df1c6ab..c4b9b54290ea 100644
|
|
--- a/ggml/src/gguf.cpp
|
|
+++ b/ggml/src/gguf.cpp
|
|
@@ -91,41 +91,48 @@ struct type_to_gguf_type<double> {
|
|
static constexpr enum gguf_type value = GGUF_TYPE_FLOAT64;
|
|
};
|
|
|
|
-static const std::map<gguf_type, size_t> GGUF_TYPE_SIZE = {
|
|
- {GGUF_TYPE_UINT8, sizeof(uint8_t)},
|
|
- {GGUF_TYPE_INT8, sizeof(int8_t)},
|
|
- {GGUF_TYPE_UINT16, sizeof(uint16_t)},
|
|
- {GGUF_TYPE_INT16, sizeof(int16_t)},
|
|
- {GGUF_TYPE_UINT32, sizeof(uint32_t)},
|
|
- {GGUF_TYPE_INT32, sizeof(int32_t)},
|
|
- {GGUF_TYPE_FLOAT32, sizeof(float)},
|
|
- {GGUF_TYPE_BOOL, sizeof(int8_t)},
|
|
- {GGUF_TYPE_STRING, 0}, // undefined
|
|
- {GGUF_TYPE_ARRAY, 0}, // undefined
|
|
- {GGUF_TYPE_UINT64, sizeof(uint64_t)},
|
|
- {GGUF_TYPE_INT64, sizeof(int64_t)},
|
|
- {GGUF_TYPE_FLOAT64, sizeof(double)},
|
|
-};
|
|
-static_assert(GGUF_TYPE_COUNT == 13, "GGUF_TYPE_COUNT != 13");
|
|
-
|
|
-static const std::map<gguf_type, const char *> GGUF_TYPE_NAME = {
|
|
- {GGUF_TYPE_UINT8, "u8"},
|
|
- {GGUF_TYPE_INT8, "i8"},
|
|
- {GGUF_TYPE_UINT16, "u16"},
|
|
- {GGUF_TYPE_INT16, "i16"},
|
|
- {GGUF_TYPE_UINT32, "u32"},
|
|
- {GGUF_TYPE_INT32, "i32"},
|
|
- {GGUF_TYPE_FLOAT32, "f32"},
|
|
- {GGUF_TYPE_BOOL, "bool"},
|
|
- {GGUF_TYPE_STRING, "str"},
|
|
- {GGUF_TYPE_ARRAY, "arr"},
|
|
- {GGUF_TYPE_UINT64, "u64"},
|
|
- {GGUF_TYPE_INT64, "i64"},
|
|
- {GGUF_TYPE_FLOAT64, "f64"},
|
|
-};
|
|
-static_assert(GGUF_TYPE_COUNT == 13, "GGUF_TYPE_COUNT != 13");
|
|
+static const std::map<gguf_type, size_t> & get_gguf_type_size_map() {
|
|
+ static const std::map<gguf_type, size_t> GGUF_TYPE_SIZE = {
|
|
+ {GGUF_TYPE_UINT8, sizeof(uint8_t)},
|
|
+ {GGUF_TYPE_INT8, sizeof(int8_t)},
|
|
+ {GGUF_TYPE_UINT16, sizeof(uint16_t)},
|
|
+ {GGUF_TYPE_INT16, sizeof(int16_t)},
|
|
+ {GGUF_TYPE_UINT32, sizeof(uint32_t)},
|
|
+ {GGUF_TYPE_INT32, sizeof(int32_t)},
|
|
+ {GGUF_TYPE_FLOAT32, sizeof(float)},
|
|
+ {GGUF_TYPE_BOOL, sizeof(int8_t)},
|
|
+ {GGUF_TYPE_STRING, 0}, // undefined
|
|
+ {GGUF_TYPE_ARRAY, 0}, // undefined
|
|
+ {GGUF_TYPE_UINT64, sizeof(uint64_t)},
|
|
+ {GGUF_TYPE_INT64, sizeof(int64_t)},
|
|
+ {GGUF_TYPE_FLOAT64, sizeof(double)},
|
|
+ };
|
|
+ static_assert(GGUF_TYPE_COUNT == 13, "GGUF_TYPE_COUNT != 13");
|
|
+ return GGUF_TYPE_SIZE;
|
|
+}
|
|
+
|
|
+static const std::map<gguf_type, const char *> & get_gguf_type_name_map() {
|
|
+ static const std::map<gguf_type, const char *> GGUF_TYPE_NAME = {
|
|
+ {GGUF_TYPE_UINT8, "u8"},
|
|
+ {GGUF_TYPE_INT8, "i8"},
|
|
+ {GGUF_TYPE_UINT16, "u16"},
|
|
+ {GGUF_TYPE_INT16, "i16"},
|
|
+ {GGUF_TYPE_UINT32, "u32"},
|
|
+ {GGUF_TYPE_INT32, "i32"},
|
|
+ {GGUF_TYPE_FLOAT32, "f32"},
|
|
+ {GGUF_TYPE_BOOL, "bool"},
|
|
+ {GGUF_TYPE_STRING, "str"},
|
|
+ {GGUF_TYPE_ARRAY, "arr"},
|
|
+ {GGUF_TYPE_UINT64, "u64"},
|
|
+ {GGUF_TYPE_INT64, "i64"},
|
|
+ {GGUF_TYPE_FLOAT64, "f64"},
|
|
+ };
|
|
+ static_assert(GGUF_TYPE_COUNT == 13, "GGUF_TYPE_COUNT != 13");
|
|
+ return GGUF_TYPE_NAME;
|
|
+}
|
|
|
|
size_t gguf_type_size(enum gguf_type type) {
|
|
+ const auto & GGUF_TYPE_SIZE = get_gguf_type_size_map();
|
|
auto it = GGUF_TYPE_SIZE.find(type);
|
|
return it == GGUF_TYPE_SIZE.end() ? 0 : it->second;
|
|
}
|
|
@@ -999,6 +1006,7 @@ void gguf_free(struct gguf_context * ctx) {
|
|
}
|
|
|
|
const char * gguf_type_name(enum gguf_type type) {
|
|
+ const auto & GGUF_TYPE_NAME = get_gguf_type_name_map();
|
|
auto it = GGUF_TYPE_NAME.find(type);
|
|
return it == GGUF_TYPE_NAME.end() ? nullptr : it->second;
|
|
}
|
|
diff --git a/src/llama-arch.cpp b/src/llama-arch.cpp
|
|
index 4a52d977297c..b09fe1e25058 100644
|
|
--- a/src/llama-arch.cpp
|
|
+++ b/src/llama-arch.cpp
|
|
@@ -5,7 +5,8 @@
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
-static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = {
|
|
+static const std::map<llm_arch, const char *> & get_llm_arch_names() {
|
|
+ static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = {
|
|
{ LLM_ARCH_CLIP, "clip" }, // dummy, only used by llama-quantize
|
|
{ LLM_ARCH_LLAMA, "llama" },
|
|
{ LLM_ARCH_LLAMA4, "llama4" },
|
|
@@ -139,9 +140,12 @@ static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = {
|
|
{ LLM_ARCH_TALKIE, "talkie" },
|
|
{ LLM_ARCH_MELLUM, "mellum" },
|
|
{ LLM_ARCH_UNKNOWN, "(unknown)" },
|
|
-};
|
|
+ };
|
|
+ return LLM_ARCH_NAMES;
|
|
+}
|
|
|
|
-static const std::map<llm_kv, const char *> LLM_KV_NAMES = {
|
|
+static const std::map<llm_kv, const char *> & get_llm_kv_names() {
|
|
+ static const std::map<llm_kv, const char *> LLM_KV_NAMES = {
|
|
{ LLM_KV_GENERAL_TYPE, "general.type" },
|
|
{ LLM_KV_GENERAL_ARCHITECTURE, "general.architecture" },
|
|
{ LLM_KV_GENERAL_QUANTIZATION_VERSION, "general.quantization_version" },
|
|
@@ -354,9 +358,12 @@ static const std::map<llm_kv, const char *> LLM_KV_NAMES = {
|
|
{ LLM_KV_TOKENIZER_PREFIX_ID, "tokenizer.ggml.prefix_token_id" },
|
|
{ LLM_KV_TOKENIZER_SUFFIX_ID, "tokenizer.ggml.suffix_token_id" },
|
|
{ LLM_KV_TOKENIZER_MIDDLE_ID, "tokenizer.ggml.middle_token_id" },
|
|
-};
|
|
+ };
|
|
+ return LLM_KV_NAMES;
|
|
+}
|
|
|
|
-static const std::map<llm_tensor, const char *> LLM_TENSOR_NAMES = {
|
|
+static const std::map<llm_tensor, const char *> & get_llm_tensor_names() {
|
|
+ static const std::map<llm_tensor, const char *> LLM_TENSOR_NAMES = {
|
|
{ LLM_TENSOR_TOKEN_EMBD, "token_embd" },
|
|
{ LLM_TENSOR_OUTPUT_NORM, "output_norm" },
|
|
{ LLM_TENSOR_OUTPUT_NORM_LFM2, "token_embd_norm" }, // fix for wrong tensor name
|
|
@@ -569,7 +576,9 @@ static const std::map<llm_tensor, const char *> LLM_TENSOR_NAMES = {
|
|
{ LLM_TENSOR_MASKED_EMBD_ORDERING, "masked_embd_ordering" },
|
|
{ LLM_TENSOR_FC, "fc" },
|
|
{ LLM_TENSOR_D2T, "d2t" },
|
|
-};
|
|
+ };
|
|
+ return LLM_TENSOR_NAMES;
|
|
+}
|
|
|
|
// declare information about the model weight tensors:
|
|
// - the layer in which the tensor is going to be used. this is needed in order to assign the correct buffer type for the weight
|
|
@@ -581,7 +590,8 @@ static const std::map<llm_tensor, const char *> LLM_TENSOR_NAMES = {
|
|
// assignment of the buffer types and extra overhead during computation
|
|
// example: https://github.com/ggml-org/llama.cpp/pull/17548
|
|
//
|
|
-static const std::map<llm_tensor, llm_tensor_info> LLM_TENSOR_INFOS = {
|
|
+static const std::map<llm_tensor, llm_tensor_info> & get_llm_tensor_infos() {
|
|
+ static const std::map<llm_tensor, llm_tensor_info> LLM_TENSOR_INFOS = {
|
|
{LLM_TENSOR_TOKEN_EMBD, {LLM_TENSOR_LAYER_INPUT, GGML_OP_GET_ROWS}},
|
|
{LLM_TENSOR_POS_EMBD, {LLM_TENSOR_LAYER_INPUT, GGML_OP_GET_ROWS}},
|
|
{LLM_TENSOR_TOKEN_TYPES, {LLM_TENSOR_LAYER_INPUT, GGML_OP_GET_ROWS}},
|
|
@@ -798,12 +808,14 @@ static const std::map<llm_tensor, llm_tensor_info> LLM_TENSOR_INFOS = {
|
|
// eagle3
|
|
{LLM_TENSOR_FC, {LLM_TENSOR_LAYER_OUTPUT, GGML_OP_MUL_MAT}},
|
|
{LLM_TENSOR_D2T, {LLM_TENSOR_LAYER_OUTPUT, GGML_OP_GET_ROWS}},
|
|
-};
|
|
+ };
|
|
+ return LLM_TENSOR_INFOS;
|
|
+}
|
|
|
|
LLM_KV::LLM_KV(llm_arch arch, const char * suffix) : arch(arch), suffix(suffix) {}
|
|
|
|
std::string LLM_KV::operator()(llm_kv kv) const {
|
|
- std::string name = ::format(LLM_KV_NAMES.at(kv), LLM_ARCH_NAMES.at(arch));
|
|
+ std::string name = ::format(get_llm_kv_names().at(kv), get_llm_arch_names().at(arch));
|
|
|
|
if (suffix != nullptr) {
|
|
name += ".";
|
|
@@ -817,6 +829,7 @@ LLM_TN_IMPL::LLM_TN_IMPL(llm_arch arch, llm_tensor tensor, const char * suffix,
|
|
: arch(arch), tensor(tensor), suffix(suffix), bid(bid), xid(xid) {}
|
|
|
|
std::string LLM_TN_IMPL::str() const {
|
|
+ const auto & LLM_TENSOR_NAMES = get_llm_tensor_names();
|
|
if (LLM_TENSOR_NAMES.find(tensor) == LLM_TENSOR_NAMES.end()) {
|
|
GGML_ABORT("unknown tensor name for tensor id %d", static_cast<int>(tensor));
|
|
}
|
|
@@ -832,6 +845,7 @@ std::string LLM_TN_IMPL::str() const {
|
|
|
|
std::vector<llm_arch> llm_arch_all() {
|
|
std::vector<llm_arch> ret;
|
|
+ const auto & LLM_ARCH_NAMES = get_llm_arch_names();
|
|
ret.reserve(LLM_ARCH_NAMES.size());
|
|
for (const auto & [arch, _] : LLM_ARCH_NAMES) {
|
|
ret.push_back(arch);
|
|
@@ -840,6 +854,7 @@ std::vector<llm_arch> llm_arch_all() {
|
|
}
|
|
|
|
const char * llm_arch_name(llm_arch arch) {
|
|
+ const auto & LLM_ARCH_NAMES = get_llm_arch_names();
|
|
auto it = LLM_ARCH_NAMES.find(arch);
|
|
if (it == LLM_ARCH_NAMES.end()) {
|
|
return "unknown";
|
|
@@ -848,7 +863,7 @@ const char * llm_arch_name(llm_arch arch) {
|
|
}
|
|
|
|
llm_arch llm_arch_from_string(const std::string & name) {
|
|
- for (const auto & kv : LLM_ARCH_NAMES) { // NOLINT
|
|
+ for (const auto & kv : get_llm_arch_names()) { // NOLINT
|
|
if (kv.second == name) {
|
|
return kv.first;
|
|
}
|
|
@@ -858,7 +873,7 @@ llm_arch llm_arch_from_string(const std::string & name) {
|
|
}
|
|
|
|
const llm_tensor_info & llm_tensor_info_for(llm_tensor tensor) {
|
|
- return LLM_TENSOR_INFOS.at(tensor);
|
|
+ return get_llm_tensor_infos().at(tensor);
|
|
}
|
|
|
|
bool llm_arch_is_recurrent(const llm_arch & arch) {
|
|
diff --git a/src/llama-chat.cpp b/src/llama-chat.cpp
|
|
index d08ce353a113..6c16838fda83 100644
|
|
--- a/src/llama-chat.cpp
|
|
+++ b/src/llama-chat.cpp
|
|
@@ -27,7 +27,8 @@ static std::string trim(const std::string & str) {
|
|
return str.substr(start, end - start);
|
|
}
|
|
|
|
-static const std::map<std::string, llm_chat_template> LLM_CHAT_TEMPLATES = {
|
|
+static const std::map<std::string, llm_chat_template> & get_llm_chat_templates() {
|
|
+ static const std::map<std::string, llm_chat_template> LLM_CHAT_TEMPLATES = {
|
|
{ "chatml", LLM_CHAT_TEMPLATE_CHATML },
|
|
{ "llama2", LLM_CHAT_TEMPLATE_LLAMA_2 },
|
|
{ "llama2-sys", LLM_CHAT_TEMPLATE_LLAMA_2_SYS },
|
|
@@ -82,10 +83,12 @@ static const std::map<std::string, llm_chat_template> LLM_CHAT_TEMPLATES = {
|
|
{ "grok-2", LLM_CHAT_TEMPLATE_GROK_2 },
|
|
{ "pangu-embedded", LLM_CHAT_TEMPLATE_PANGU_EMBED },
|
|
{ "solar-open", LLM_CHAT_TEMPLATE_SOLAR_OPEN },
|
|
-};
|
|
+ };
|
|
+ return LLM_CHAT_TEMPLATES;
|
|
+}
|
|
|
|
llm_chat_template llm_chat_template_from_str(const std::string & name) {
|
|
- return LLM_CHAT_TEMPLATES.at(name);
|
|
+ return get_llm_chat_templates().at(name);
|
|
}
|
|
|
|
llm_chat_template llm_chat_detect_template(const std::string & tmpl) {
|
|
@@ -96,6 +99,7 @@ llm_chat_template llm_chat_detect_template(const std::string & tmpl) {
|
|
// ignore
|
|
}
|
|
#endif
|
|
+ const auto & LLM_CHAT_TEMPLATES = get_llm_chat_templates();
|
|
auto chat_template = LLM_CHAT_TEMPLATES.find(tmpl);
|
|
if (chat_template != LLM_CHAT_TEMPLATES.end()) {
|
|
return chat_template->second;
|
|
@@ -956,6 +960,7 @@ int32_t llm_chat_apply_template(
|
|
// public interface
|
|
|
|
int32_t llama_chat_builtin_templates(const char ** output, size_t len) {
|
|
+ const auto & LLM_CHAT_TEMPLATES = get_llm_chat_templates();
|
|
auto it = LLM_CHAT_TEMPLATES.begin();
|
|
for (size_t i = 0; i < std::min(len, LLM_CHAT_TEMPLATES.size()); i++) {
|
|
output[i] = it->first.c_str();
|
|
diff --git a/src/llama-model.cpp b/src/llama-model.cpp
|
|
index f9a1a7a446b1..201580ca9012 100644
|
|
--- a/src/llama-model.cpp
|
|
+++ b/src/llama-model.cpp
|
|
@@ -820,19 +820,22 @@ static const char * llama_expert_gating_func_name(llama_expert_gating_func_type
|
|
}
|
|
}
|
|
|
|
-static const std::map<llama_rope_scaling_type, const char *> LLAMA_ROPE_SCALING_TYPES = {
|
|
- { LLAMA_ROPE_SCALING_TYPE_NONE, "none" },
|
|
- { LLAMA_ROPE_SCALING_TYPE_LINEAR, "linear" },
|
|
- { LLAMA_ROPE_SCALING_TYPE_YARN, "yarn" },
|
|
- { LLAMA_ROPE_SCALING_TYPE_LONGROPE, "longrope" },
|
|
-};
|
|
+static const std::map<llama_rope_scaling_type, const char *> & get_llama_rope_scaling_types() {
|
|
+ static const std::map<llama_rope_scaling_type, const char *> LLAMA_ROPE_SCALING_TYPES = {
|
|
+ { LLAMA_ROPE_SCALING_TYPE_NONE, "none" },
|
|
+ { LLAMA_ROPE_SCALING_TYPE_LINEAR, "linear" },
|
|
+ { LLAMA_ROPE_SCALING_TYPE_YARN, "yarn" },
|
|
+ { LLAMA_ROPE_SCALING_TYPE_LONGROPE, "longrope" },
|
|
+ };
|
|
+ return LLAMA_ROPE_SCALING_TYPES;
|
|
+}
|
|
|
|
std::string llama_rope_scaling_type_name(llama_rope_scaling_type rope_scaling_type) {
|
|
- return LLAMA_ROPE_SCALING_TYPES.at(rope_scaling_type);
|
|
+ return get_llama_rope_scaling_types().at(rope_scaling_type);
|
|
}
|
|
|
|
static llama_rope_scaling_type llama_rope_scaling_type_from_string(const std::string & name) {
|
|
- for (const auto & kv : LLAMA_ROPE_SCALING_TYPES) {
|
|
+ for (const auto & kv : get_llama_rope_scaling_types()) {
|
|
if (kv.second == name) {
|
|
return (llama_rope_scaling_type) kv.first;
|
|
}
|
|
@@ -845,17 +848,21 @@ static llama_rope_scaling_type llama_rope_scaling_type_from_string(const std::st
|
|
// graph builders. Only gated activations that map cleanly to llm_ffn_op_type are
|
|
// listed; unrecognized values fall back to GeGLU, which matches the historical
|
|
// default for ModernBert-style architectures.
|
|
-static const std::map<std::string, llm_ffn_op_type> LLM_FFN_OP_TYPES_FROM_STRING = {
|
|
- { "gelu", LLM_FFN_GEGLU },
|
|
- { "geglu", LLM_FFN_GEGLU },
|
|
- { "silu", LLM_FFN_SWIGLU },
|
|
- { "swish", LLM_FFN_SWIGLU },
|
|
- { "swiglu", LLM_FFN_SWIGLU },
|
|
- { "relu", LLM_FFN_RELU },
|
|
- { "reglu", LLM_FFN_REGLU },
|
|
-};
|
|
+static const std::map<std::string, llm_ffn_op_type> & get_llm_ffn_op_types_from_string() {
|
|
+ static const std::map<std::string, llm_ffn_op_type> LLM_FFN_OP_TYPES_FROM_STRING = {
|
|
+ { "gelu", LLM_FFN_GEGLU },
|
|
+ { "geglu", LLM_FFN_GEGLU },
|
|
+ { "silu", LLM_FFN_SWIGLU },
|
|
+ { "swish", LLM_FFN_SWIGLU },
|
|
+ { "swiglu", LLM_FFN_SWIGLU },
|
|
+ { "relu", LLM_FFN_RELU },
|
|
+ { "reglu", LLM_FFN_REGLU },
|
|
+ };
|
|
+ return LLM_FFN_OP_TYPES_FROM_STRING;
|
|
+}
|
|
|
|
llm_ffn_op_type llm_ffn_op_type_from_string(const std::string & name, llm_ffn_op_type fallback) {
|
|
+ const auto & LLM_FFN_OP_TYPES_FROM_STRING = get_llm_ffn_op_types_from_string();
|
|
const auto it = LLM_FFN_OP_TYPES_FROM_STRING.find(name);
|
|
if (it != LLM_FFN_OP_TYPES_FROM_STRING.end()) {
|
|
return it->second;
|
|
diff --git a/src/unicode-data.cpp b/src/unicode-data.cpp
|
|
index 04dcd7fcfbce..8904adf6a115 100644
|
|
--- a/src/unicode-data.cpp
|
|
+++ b/src/unicode-data.cpp
|
|
@@ -2283,7 +2283,8 @@ const std::initializer_list<std::pair<uint32_t, uint16_t>> unicode_ranges_flags
|
|
{0x110000, 0x0000},
|
|
};
|
|
|
|
-const std::unordered_set<uint32_t> unicode_set_whitespace = {
|
|
+const std::unordered_set<uint32_t> & get_unicode_set_whitespace() {
|
|
+ static const std::unordered_set<uint32_t> unicode_set_whitespace = {
|
|
0x000009,
|
|
0x00000A,
|
|
0x00000B,
|
|
@@ -2309,7 +2310,9 @@ const std::unordered_set<uint32_t> unicode_set_whitespace = {
|
|
0x00202F,
|
|
0x00205F,
|
|
0x003000,
|
|
-};
|
|
+ };
|
|
+ return unicode_set_whitespace;
|
|
+}
|
|
|
|
// list is always in ascending order, to enable binary search
|
|
const std::initializer_list<std::pair<uint32_t, uint32_t>> unicode_map_lowercase = {
|
|
diff --git a/src/unicode-data.h b/src/unicode-data.h
|
|
index f6973ebd2e35..cafaa0064ea1 100644
|
|
--- a/src/unicode-data.h
|
|
+++ b/src/unicode-data.h
|
|
@@ -14,7 +14,11 @@ struct range_nfd {
|
|
static const uint32_t MAX_CODEPOINTS = 0x110000;
|
|
|
|
extern const std::initializer_list<std::pair<uint32_t, uint16_t>> unicode_ranges_flags;
|
|
-extern const std::unordered_set<uint32_t> unicode_set_whitespace;
|
|
+// Firefox (no static constructors): the std::unordered_set has a non-trivial
|
|
+// constructor/destructor, so expose it via a lazily-initialized accessor instead
|
|
+// of a load-time global. The initializer_list globals are constant-initialized
|
|
+// and need no such treatment.
|
|
+const std::unordered_set<uint32_t> & get_unicode_set_whitespace();
|
|
extern const std::initializer_list<std::pair<uint32_t, uint32_t>> unicode_map_lowercase;
|
|
extern const std::initializer_list<std::pair<uint32_t, uint32_t>> unicode_map_uppercase;
|
|
extern const std::initializer_list<range_nfd> unicode_ranges_nfd;
|
|
diff --git a/src/unicode.cpp b/src/unicode.cpp
|
|
index 4a2f58237548..052d0fa8c670 100644
|
|
--- a/src/unicode.cpp
|
|
+++ b/src/unicode.cpp
|
|
@@ -128,6 +128,7 @@ static std::vector<unicode_cpt_flags> unicode_cpt_flags_array() {
|
|
}
|
|
}
|
|
|
|
+ const auto & unicode_set_whitespace = get_unicode_set_whitespace();
|
|
for (auto cpt : unicode_set_whitespace) {
|
|
cpt_flags[cpt].is_whitespace = true;
|
|
}
|