@delali/narsil-react-native 0.3.1-next.154 → 0.3.1-next.156
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +144 -0
- package/NarsilReactNative.podspec +2 -2
- package/android/CMakeLists.txt +1 -1
- package/cpp/HybridNarsilCoreAnalysis.cpp +277 -0
- package/cpp/HybridNarsilCoreImpl.hpp +43 -0
- package/cpp/HybridNarsilCoreKeyword.cpp +253 -0
- package/cpp/HybridNarsilCoreMath.cpp +47 -0
- package/cpp/core/include/narsil_analysis.h +86 -0
- package/cpp/core/include/narsil_core.h +1 -1
- package/cpp/core/include/narsil_keyword.h +110 -0
- package/cpp/core/include/narsil_math.h +36 -0
- package/cpp/core/src/analysis/analyse.c +281 -0
- package/cpp/core/src/analysis/analyser.h +49 -0
- package/cpp/core/src/analysis/languages.c +79 -0
- package/cpp/core/src/analysis/languages.h +42 -0
- package/cpp/core/src/analysis/normalise.c +242 -0
- package/cpp/core/src/analysis/normalise.h +28 -0
- package/cpp/core/src/analysis/split.c +183 -0
- package/cpp/core/src/analysis/split.h +27 -0
- package/cpp/core/src/analysis/stop_words.c +82 -0
- package/cpp/core/src/analysis/stop_words.h +19 -0
- package/cpp/core/src/analysis/term_cache.c +88 -0
- package/cpp/core/src/analysis/term_cache.h +36 -0
- package/cpp/core/src/analysis/text.c +161 -0
- package/cpp/core/src/analysis/text.h +45 -0
- package/cpp/core/src/analysis/transform.c +103 -0
- package/cpp/core/src/analysis/unicode.c +252 -0
- package/cpp/core/src/analysis/unicode.h +54 -0
- package/cpp/core/src/internal.h +4 -0
- package/cpp/core/src/keyword/pass.h +117 -0
- package/cpp/core/src/keyword/prune.c +324 -0
- package/cpp/core/src/keyword/request.c +179 -0
- package/cpp/core/src/keyword/rows.c +83 -0
- package/cpp/core/src/keyword/rows.h +18 -0
- package/cpp/core/src/keyword/score.c +257 -0
- package/cpp/core/src/keyword/score.h +17 -0
- package/cpp/core/src/keyword/scratch.c +226 -0
- package/cpp/core/src/keyword/scratch.h +55 -0
- package/cpp/core/src/keyword/select.c +155 -0
- package/cpp/core/src/keyword/select.h +17 -0
- package/cpp/core/src/languages/bulgarian_stemmer.c +114 -0
- package/cpp/core/src/languages/data/albanian.c +54 -0
- package/cpp/core/src/languages/data/amharic.c +93 -0
- package/cpp/core/src/languages/data/arabic.c +146 -0
- package/cpp/core/src/languages/data/armenian.c +46 -0
- package/cpp/core/src/languages/data/azerbaijani.c +68 -0
- package/cpp/core/src/languages/data/bambara.c +48 -0
- package/cpp/core/src/languages/data/basque.c +62 -0
- package/cpp/core/src/languages/data/belarusian.c +56 -0
- package/cpp/core/src/languages/data/bengali.c +63 -0
- package/cpp/core/src/languages/data/bosnian.c +73 -0
- package/cpp/core/src/languages/data/breton.c +52 -0
- package/cpp/core/src/languages/data/bulgarian.c +144 -0
- package/cpp/core/src/languages/data/burmese.c +48 -0
- package/cpp/core/src/languages/data/catalan.c +84 -0
- package/cpp/core/src/languages/data/chinese.c +70 -0
- package/cpp/core/src/languages/data/croatian.c +72 -0
- package/cpp/core/src/languages/data/czech.c +72 -0
- package/cpp/core/src/languages/data/dagbani.c +88 -0
- package/cpp/core/src/languages/data/danish.c +56 -0
- package/cpp/core/src/languages/data/declarations.h +114 -0
- package/cpp/core/src/languages/data/dutch.c +58 -0
- package/cpp/core/src/languages/data/english.c +172 -0
- package/cpp/core/src/languages/data/esperanto.c +71 -0
- package/cpp/core/src/languages/data/estonian.c +417 -0
- package/cpp/core/src/languages/data/ewe.c +89 -0
- package/cpp/core/src/languages/data/faroese.c +54 -0
- package/cpp/core/src/languages/data/fijian.c +44 -0
- package/cpp/core/src/languages/data/finnish.c +100 -0
- package/cpp/core/src/languages/data/french.c +74 -0
- package/cpp/core/src/languages/data/ga.c +83 -0
- package/cpp/core/src/languages/data/galician.c +70 -0
- package/cpp/core/src/languages/data/georgian.c +57 -0
- package/cpp/core/src/languages/data/german.c +96 -0
- package/cpp/core/src/languages/data/greek.c +202 -0
- package/cpp/core/src/languages/data/guarani.c +110 -0
- package/cpp/core/src/languages/data/gujarati.c +90 -0
- package/cpp/core/src/languages/data/haitian-creole.c +54 -0
- package/cpp/core/src/languages/data/hausa.c +85 -0
- package/cpp/core/src/languages/data/hawaiian.c +50 -0
- package/cpp/core/src/languages/data/hebrew.c +85 -0
- package/cpp/core/src/languages/data/hindi.c +91 -0
- package/cpp/core/src/languages/data/hungarian.c +98 -0
- package/cpp/core/src/languages/data/icelandic.c +73 -0
- package/cpp/core/src/languages/data/igbo.c +90 -0
- package/cpp/core/src/languages/data/indonesian.c +296 -0
- package/cpp/core/src/languages/data/irish.c +60 -0
- package/cpp/core/src/languages/data/italian.c +107 -0
- package/cpp/core/src/languages/data/japanese.c +52 -0
- package/cpp/core/src/languages/data/kannada.c +60 -0
- package/cpp/core/src/languages/data/kazakh.c +57 -0
- package/cpp/core/src/languages/data/khmer.c +71 -0
- package/cpp/core/src/languages/data/kinyarwanda.c +54 -0
- package/cpp/core/src/languages/data/kirundi.c +53 -0
- package/cpp/core/src/languages/data/korean.c +74 -0
- package/cpp/core/src/languages/data/kurmanji.c +43 -0
- package/cpp/core/src/languages/data/kyrgyz.c +65 -0
- package/cpp/core/src/languages/data/lao.c +46 -0
- package/cpp/core/src/languages/data/latin.c +46 -0
- package/cpp/core/src/languages/data/latvian.c +75 -0
- package/cpp/core/src/languages/data/lingala.c +88 -0
- package/cpp/core/src/languages/data/lithuanian.c +65 -0
- package/cpp/core/src/languages/data/luxembourgish.c +80 -0
- package/cpp/core/src/languages/data/macedonian.c +286 -0
- package/cpp/core/src/languages/data/malagasy.c +51 -0
- package/cpp/core/src/languages/data/malay.c +184 -0
- package/cpp/core/src/languages/data/malayalam.c +64 -0
- package/cpp/core/src/languages/data/maltese.c +102 -0
- package/cpp/core/src/languages/data/maori.c +52 -0
- package/cpp/core/src/languages/data/marathi.c +62 -0
- package/cpp/core/src/languages/data/nepali.c +72 -0
- package/cpp/core/src/languages/data/norwegian.c +74 -0
- package/cpp/core/src/languages/data/oromo.c +51 -0
- package/cpp/core/src/languages/data/persian.c +150 -0
- package/cpp/core/src/languages/data/polish.c +111 -0
- package/cpp/core/src/languages/data/portuguese.c +91 -0
- package/cpp/core/src/languages/data/punjabi.c +80 -0
- package/cpp/core/src/languages/data/registry.c +116 -0
- package/cpp/core/src/languages/data/romanian.c +93 -0
- package/cpp/core/src/languages/data/russian.c +76 -0
- package/cpp/core/src/languages/data/samoan.c +47 -0
- package/cpp/core/src/languages/data/sanskrit.c +53 -0
- package/cpp/core/src/languages/data/scottish-gaelic.c +119 -0
- package/cpp/core/src/languages/data/serbian.c +84 -0
- package/cpp/core/src/languages/data/shona.c +55 -0
- package/cpp/core/src/languages/data/sinhala.c +78 -0
- package/cpp/core/src/languages/data/slovak.c +135 -0
- package/cpp/core/src/languages/data/slovenian.c +139 -0
- package/cpp/core/src/languages/data/sorani.c +55 -0
- package/cpp/core/src/languages/data/spanish.c +84 -0
- package/cpp/core/src/languages/data/swahili.c +59 -0
- package/cpp/core/src/languages/data/swedish.c +60 -0
- package/cpp/core/src/languages/data/tagalog.c +75 -0
- package/cpp/core/src/languages/data/tamil.c +69 -0
- package/cpp/core/src/languages/data/tatar.c +548 -0
- package/cpp/core/src/languages/data/telugu.c +54 -0
- package/cpp/core/src/languages/data/thai.c +46 -0
- package/cpp/core/src/languages/data/tibetan.c +55 -0
- package/cpp/core/src/languages/data/tigrinya.c +73 -0
- package/cpp/core/src/languages/data/tongan.c +47 -0
- package/cpp/core/src/languages/data/turkish.c +100 -0
- package/cpp/core/src/languages/data/twi.c +88 -0
- package/cpp/core/src/languages/data/ukrainian.c +99 -0
- package/cpp/core/src/languages/data/urdu.c +174 -0
- package/cpp/core/src/languages/data/vietnamese.c +88 -0
- package/cpp/core/src/languages/data/welsh.c +143 -0
- package/cpp/core/src/languages/data/wolof.c +51 -0
- package/cpp/core/src/languages/data/xhosa.c +56 -0
- package/cpp/core/src/languages/data/yoruba.c +93 -0
- package/cpp/core/src/languages/data/zulu.c +58 -0
- package/cpp/core/src/languages/marks.c +64 -0
- package/cpp/core/src/languages/rules.c +63 -0
- package/cpp/core/src/languages/rules.h +68 -0
- package/cpp/core/src/languages/sanskrit_stemmer.c +50 -0
- package/cpp/core/src/languages/scripts.c +143 -0
- package/cpp/core/src/languages/slovenian_stemmer.c +46 -0
- package/cpp/core/src/languages/snowball/api.c +52 -0
- package/cpp/core/src/languages/snowball/api.h +43 -0
- package/cpp/core/src/languages/snowball/arabic_stemmer.c +1506 -0
- package/cpp/core/src/languages/snowball/arabic_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/armenian_stemmer.c +523 -0
- package/cpp/core/src/languages/snowball/armenian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/basque_stemmer.c +1089 -0
- package/cpp/core/src/languages/snowball/basque_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/catalan_stemmer.c +1380 -0
- package/cpp/core/src/languages/snowball/catalan_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/czech_stemmer.c +582 -0
- package/cpp/core/src/languages/snowball/czech_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/danish_stemmer.c +352 -0
- package/cpp/core/src/languages/snowball/danish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/dutch_stemmer.c +1657 -0
- package/cpp/core/src/languages/snowball/dutch_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/english_stemmer.c +1019 -0
- package/cpp/core/src/languages/snowball/english_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/esperanto_stemmer.c +716 -0
- package/cpp/core/src/languages/snowball/esperanto_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/estonian_stemmer.c +1361 -0
- package/cpp/core/src/languages/snowball/estonian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/finnish_stemmer.c +800 -0
- package/cpp/core/src/languages/snowball/finnish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/french_stemmer.c +1217 -0
- package/cpp/core/src/languages/snowball/french_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/german_stemmer.c +567 -0
- package/cpp/core/src/languages/snowball/german_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/greek_stemmer.c +3450 -0
- package/cpp/core/src/languages/snowball/greek_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/hindi_stemmer.c +325 -0
- package/cpp/core/src/languages/snowball/hindi_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/hungarian_stemmer.c +742 -0
- package/cpp/core/src/languages/snowball/hungarian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/indonesian_stemmer.c +443 -0
- package/cpp/core/src/languages/snowball/indonesian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/irish_stemmer.c +428 -0
- package/cpp/core/src/languages/snowball/irish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/italian_stemmer.c +983 -0
- package/cpp/core/src/languages/snowball/italian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/lithuanian_stemmer.c +794 -0
- package/cpp/core/src/languages/snowball/lithuanian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/nepali_stemmer.c +361 -0
- package/cpp/core/src/languages/snowball/nepali_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/norwegian_stemmer.c +332 -0
- package/cpp/core/src/languages/snowball/norwegian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/persian_stemmer.c +538 -0
- package/cpp/core/src/languages/snowball/persian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/polish_stemmer.c +501 -0
- package/cpp/core/src/languages/snowball/polish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/portuguese_stemmer.c +866 -0
- package/cpp/core/src/languages/snowball/portuguese_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/romanian_stemmer.c +940 -0
- package/cpp/core/src/languages/snowball/romanian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/russian_stemmer.c +598 -0
- package/cpp/core/src/languages/snowball/russian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/serbian_stemmer.c +6765 -0
- package/cpp/core/src/languages/snowball/serbian_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/snowball_runtime.h +122 -0
- package/cpp/core/src/languages/snowball/spanish_stemmer.c +955 -0
- package/cpp/core/src/languages/snowball/spanish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/swedish_stemmer.c +364 -0
- package/cpp/core/src/languages/snowball/swedish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/tamil_stemmer.c +1305 -0
- package/cpp/core/src/languages/snowball/tamil_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/turkish_stemmer.c +1700 -0
- package/cpp/core/src/languages/snowball/turkish_stemmer.h +24 -0
- package/cpp/core/src/languages/snowball/utilities.c +716 -0
- package/cpp/core/src/languages/substitutions.c +131 -0
- package/cpp/core/src/languages/swahili_stemmer.c +85 -0
- package/cpp/core/src/languages/ukrainian_stemmer.c +168 -0
- package/cpp/core/src/locks.c +2 -15
- package/cpp/core/src/math/apply.c +44 -0
- package/cpp/core/src/math/fdlibm.h +16 -0
- package/cpp/core/src/math/inverse.c +242 -0
- package/cpp/core/src/math/log.c +90 -0
- package/cpp/core/src/math/reduce.c +325 -0
- package/cpp/core/src/math/trig.c +188 -0
- package/cpp/core/src/math/words.h +45 -0
- package/cpp/core/src/thread_yield.h +18 -0
- package/cpp/core/src/unicode/decompositions.c +310 -0
- package/cpp/core/src/unicode/lowercase.c +172 -0
- package/cpp/core/src/unicode/properties.c +214 -0
- package/cpp/core/src/workspace.c +5 -1
- package/lib/engine/analysis.d.ts +3 -0
- package/lib/engine/analysis.js +76 -0
- package/lib/engine/core.js +5 -0
- package/lib/engine/keyword.d.ts +3 -0
- package/lib/engine/keyword.js +25 -0
- package/lib/specs/core.nitro.d.ts +1 -0
- package/nitrogen/generated/shared/c++/HybridNarsilCoreSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridNarsilCoreSpec.hpp +1 -0
- package/package.json +4 -3
- package/src/engine/analysis.ts +87 -0
- package/src/engine/core.ts +6 -0
- package/src/engine/keyword.ts +26 -0
- package/src/specs/core.nitro.ts +1 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#include "normalise.h"
|
|
2
|
+
|
|
3
|
+
#include "../../include/narsil_core.h"
|
|
4
|
+
#include "text.h"
|
|
5
|
+
#include "unicode.h"
|
|
6
|
+
|
|
7
|
+
#include <stddef.h>
|
|
8
|
+
#include <stdint.h>
|
|
9
|
+
|
|
10
|
+
#define CAPITAL_SIGMA 0x3A3U
|
|
11
|
+
#define SMALL_FINAL_SIGMA 0x3C2U
|
|
12
|
+
#define ASCII_CAPITAL_A 0x41U
|
|
13
|
+
#define ASCII_CAPITAL_Z 0x5AU
|
|
14
|
+
#define ASCII_CASE_OFFSET 0x20U
|
|
15
|
+
#define APOSTROPHE 0x27U
|
|
16
|
+
#define LATIN_SMALL_I 0x69U
|
|
17
|
+
#define COMBINING_DOT_ABOVE 0x307U
|
|
18
|
+
#define DOTTED_CAPITAL_I 0x130U
|
|
19
|
+
#define ARMENIAN_MARKS_FIRST 0x55BU
|
|
20
|
+
#define ARMENIAN_MARKS_LAST 0x55FU
|
|
21
|
+
#define LEFT_SINGLE_QUOTE 0x2018U
|
|
22
|
+
#define RIGHT_SINGLE_QUOTE 0x2019U
|
|
23
|
+
#define MODIFIER_APOSTROPHE 0x2BCU
|
|
24
|
+
#define MODIFIER_TURNED_COMMA 0x2BBU
|
|
25
|
+
#define FULLWIDTH_ASCII_FIRST 0xFF01U
|
|
26
|
+
#define FULLWIDTH_ASCII_LAST 0xFF5EU
|
|
27
|
+
#define FULLWIDTH_ASCII_OFFSET 0xFEE0U
|
|
28
|
+
#define HALFWIDTH_KANA_FIRST 0xFF61U
|
|
29
|
+
#define HALFWIDTH_KANA_LAST 0xFF9DU
|
|
30
|
+
#define HALFWIDTH_VOICED_MARK 0xFF9EU
|
|
31
|
+
#define HALFWIDTH_SEMI_VOICED_MARK 0xFF9FU
|
|
32
|
+
#define COMBINING_VOICED_MARK 0x3099U
|
|
33
|
+
#define COMBINING_SEMI_VOICED_MARK 0x309AU
|
|
34
|
+
#define COMBINING_DIACRITICS_FIRST 0x300U
|
|
35
|
+
#define COMBINING_DIACRITICS_LAST 0x36FU
|
|
36
|
+
#define NON_STARTER_BEFORE_ANY_STARTER 256U
|
|
37
|
+
|
|
38
|
+
static const uint16_t halfwidth_kana_targets[HALFWIDTH_KANA_LAST - HALFWIDTH_KANA_FIRST + 1] = {
|
|
39
|
+
0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5,
|
|
40
|
+
0x30E7, 0x30C3, 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3,
|
|
41
|
+
0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC,
|
|
42
|
+
0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4,
|
|
43
|
+
0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
void narsil_normalise_scratch_release(narsil_normalise_scratch *scratch) {
|
|
47
|
+
narsil_text_release(&scratch->first);
|
|
48
|
+
narsil_text_release(&scratch->second);
|
|
49
|
+
narsil_code_points_release(&scratch->points);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static void reorder_canonically(uint32_t *values, size_t length) {
|
|
53
|
+
for (size_t i = 1; i < length; i++) {
|
|
54
|
+
uint32_t value = values[i];
|
|
55
|
+
uint32_t value_class = narsil_unicode_combining_class(value);
|
|
56
|
+
if (value_class == 0) { continue; }
|
|
57
|
+
size_t position = i;
|
|
58
|
+
while (position > 0) {
|
|
59
|
+
uint32_t before_class = narsil_unicode_combining_class(values[position - 1]);
|
|
60
|
+
if (before_class <= value_class) { break; }
|
|
61
|
+
values[position] = values[position - 1];
|
|
62
|
+
position--;
|
|
63
|
+
}
|
|
64
|
+
values[position] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static int decompose_text(const uint16_t *units, size_t length, narsil_code_points *points) {
|
|
69
|
+
points->length = 0;
|
|
70
|
+
int status = narsil_code_points_reserve(points, length);
|
|
71
|
+
if (status != NARSIL_OK) { return status; }
|
|
72
|
+
uint32_t parts[NARSIL_UNICODE_MAX_DECOMPOSITION];
|
|
73
|
+
size_t index = 0;
|
|
74
|
+
while (index < length) {
|
|
75
|
+
uint32_t count = narsil_unicode_decompose(narsil_decode_next(units, length, &index), parts);
|
|
76
|
+
for (uint32_t part = 0; part < count; part++) {
|
|
77
|
+
status = narsil_code_points_push(points, parts[part]);
|
|
78
|
+
if (status != NARSIL_OK) { return status; }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
reorder_canonically(points->values, points->length);
|
|
82
|
+
return NARSIL_OK;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static size_t compose_in_place(uint32_t *values, size_t length) {
|
|
86
|
+
if (length == 0) { return 0; }
|
|
87
|
+
size_t starter_position = 0;
|
|
88
|
+
uint32_t starter = values[0];
|
|
89
|
+
uint32_t last_class = narsil_unicode_combining_class(starter);
|
|
90
|
+
if (last_class != 0) { last_class = NON_STARTER_BEFORE_ANY_STARTER; }
|
|
91
|
+
size_t kept = 1;
|
|
92
|
+
for (size_t i = 1; i < length; i++) {
|
|
93
|
+
uint32_t value = values[i];
|
|
94
|
+
uint32_t value_class = narsil_unicode_combining_class(value);
|
|
95
|
+
uint32_t composite = narsil_unicode_compose(starter, value);
|
|
96
|
+
if (composite != NARSIL_UNICODE_NO_COMPOSITE && (last_class < value_class || last_class == 0)) {
|
|
97
|
+
values[starter_position] = composite;
|
|
98
|
+
starter = composite;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (value_class == 0) {
|
|
102
|
+
starter_position = kept;
|
|
103
|
+
starter = value;
|
|
104
|
+
}
|
|
105
|
+
last_class = value_class;
|
|
106
|
+
values[kept++] = value;
|
|
107
|
+
}
|
|
108
|
+
return kept;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static int encode_points(const uint32_t *values, size_t length, narsil_text *out) {
|
|
112
|
+
out->length = 0;
|
|
113
|
+
int status = narsil_text_reserve(out, length);
|
|
114
|
+
for (size_t i = 0; i < length && status == NARSIL_OK; i++) { status = narsil_text_push_code_point(out, values[i]); }
|
|
115
|
+
return status;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
int narsil_nfd(const uint16_t *units, size_t length, narsil_text *out, narsil_code_points *points) {
|
|
119
|
+
int status = decompose_text(units, length, points);
|
|
120
|
+
if (status != NARSIL_OK) { return status; }
|
|
121
|
+
return encode_points(points->values, points->length, out);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
int narsil_nfc(const uint16_t *units, size_t length, narsil_text *out, narsil_code_points *points) {
|
|
125
|
+
int status = decompose_text(units, length, points);
|
|
126
|
+
if (status != NARSIL_OK) { return status; }
|
|
127
|
+
points->length = compose_in_place(points->values, points->length);
|
|
128
|
+
return encode_points(points->values, points->length, out);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static int cased_letter_beside(const uint16_t *units, size_t length, size_t index, int forward) {
|
|
132
|
+
while (forward ? index < length : index > 0) {
|
|
133
|
+
uint32_t code_point = forward ? narsil_decode_next(units, length, &index) : narsil_decode_previous(units, &index);
|
|
134
|
+
uint32_t properties = narsil_unicode_properties(code_point);
|
|
135
|
+
if ((properties & NARSIL_UNICODE_CASE_IGNORABLE) != 0) { continue; }
|
|
136
|
+
return (properties & NARSIL_UNICODE_CASED) != 0;
|
|
137
|
+
}
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
int narsil_lowercase(const uint16_t *units, size_t length, narsil_text *out) {
|
|
142
|
+
out->length = 0;
|
|
143
|
+
int status = narsil_text_reserve(out, length);
|
|
144
|
+
size_t index = 0;
|
|
145
|
+
while (index < length && status == NARSIL_OK) {
|
|
146
|
+
size_t start = index;
|
|
147
|
+
uint32_t code_point = narsil_decode_next(units, length, &index);
|
|
148
|
+
if (code_point == CAPITAL_SIGMA && cased_letter_beside(units, length, start, 0) &&
|
|
149
|
+
!cased_letter_beside(units, length, index, 1)) {
|
|
150
|
+
status = narsil_text_push(out, SMALL_FINAL_SIGMA);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
uint32_t second = 0;
|
|
154
|
+
uint32_t lower = narsil_unicode_lowercase_of(code_point, &second);
|
|
155
|
+
status = narsil_text_push_code_point(out, lower);
|
|
156
|
+
if (status == NARSIL_OK && second != 0) { status = narsil_text_push_code_point(out, second); }
|
|
157
|
+
}
|
|
158
|
+
return status;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static uint16_t fold_width(uint16_t unit) {
|
|
162
|
+
if (unit >= FULLWIDTH_ASCII_FIRST && unit <= FULLWIDTH_ASCII_LAST) {
|
|
163
|
+
return (uint16_t)(unit - FULLWIDTH_ASCII_OFFSET);
|
|
164
|
+
}
|
|
165
|
+
if (unit >= HALFWIDTH_KANA_FIRST && unit <= HALFWIDTH_KANA_LAST) {
|
|
166
|
+
return halfwidth_kana_targets[unit - HALFWIDTH_KANA_FIRST];
|
|
167
|
+
}
|
|
168
|
+
if (unit == HALFWIDTH_VOICED_MARK) { return COMBINING_VOICED_MARK; }
|
|
169
|
+
if (unit == HALFWIDTH_SEMI_VOICED_MARK) { return COMBINING_SEMI_VOICED_MARK; }
|
|
170
|
+
return unit;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static int fold_forms(const narsil_text *source, narsil_text *out) {
|
|
174
|
+
out->length = 0;
|
|
175
|
+
int status = narsil_text_reserve(out, source->length);
|
|
176
|
+
for (size_t i = 0; i < source->length && status == NARSIL_OK; i++) {
|
|
177
|
+
uint16_t unit = source->units[i];
|
|
178
|
+
if (unit == COMBINING_DOT_ABOVE || (unit >= ARMENIAN_MARKS_FIRST && unit <= ARMENIAN_MARKS_LAST)) { continue; }
|
|
179
|
+
if (unit == DOTTED_CAPITAL_I) {
|
|
180
|
+
status = narsil_text_push(out, LATIN_SMALL_I);
|
|
181
|
+
} else if (unit == LEFT_SINGLE_QUOTE || unit == RIGHT_SINGLE_QUOTE || unit == MODIFIER_APOSTROPHE ||
|
|
182
|
+
unit == MODIFIER_TURNED_COMMA) {
|
|
183
|
+
status = narsil_text_push(out, APOSTROPHE);
|
|
184
|
+
} else {
|
|
185
|
+
status = narsil_text_push(out, unit);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return status;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
int narsil_fold_for_splitting(const uint16_t *units, size_t length, narsil_text *out,
|
|
192
|
+
narsil_normalise_scratch *scratch) {
|
|
193
|
+
if (narsil_units_are_ascii(units, length)) {
|
|
194
|
+
out->length = 0;
|
|
195
|
+
int status = narsil_text_reserve(out, length);
|
|
196
|
+
if (status != NARSIL_OK) { return status; }
|
|
197
|
+
for (size_t i = 0; i < length; i++) {
|
|
198
|
+
uint16_t unit = units[i];
|
|
199
|
+
out->units[i] = unit >= ASCII_CAPITAL_A && unit <= ASCII_CAPITAL_Z ? (uint16_t)(unit + ASCII_CASE_OFFSET) : unit;
|
|
200
|
+
}
|
|
201
|
+
out->length = length;
|
|
202
|
+
return NARSIL_OK;
|
|
203
|
+
}
|
|
204
|
+
scratch->first.length = 0;
|
|
205
|
+
int status = narsil_text_reserve(&scratch->first, length);
|
|
206
|
+
if (status != NARSIL_OK) { return status; }
|
|
207
|
+
for (size_t i = 0; i < length; i++) { scratch->first.units[i] = fold_width(units[i]); }
|
|
208
|
+
scratch->first.length = length;
|
|
209
|
+
status = narsil_nfc(scratch->first.units, scratch->first.length, &scratch->second, &scratch->points);
|
|
210
|
+
if (status == NARSIL_OK) { status = fold_forms(&scratch->second, &scratch->first); }
|
|
211
|
+
if (status == NARSIL_OK) { status = narsil_lowercase(scratch->first.units, scratch->first.length, out); }
|
|
212
|
+
return status;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static int is_combining_diacritic(uint32_t code_point) {
|
|
216
|
+
return code_point >= COMBINING_DIACRITICS_FIRST && code_point <= COMBINING_DIACRITICS_LAST;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
int narsil_strip_diacritics(const uint16_t *units, size_t length, narsil_text *out, narsil_code_points *points) {
|
|
220
|
+
int status = decompose_text(units, length, points);
|
|
221
|
+
if (status != NARSIL_OK) { return status; }
|
|
222
|
+
size_t kept = 0;
|
|
223
|
+
for (size_t i = 0; i < points->length; i++) {
|
|
224
|
+
if (!is_combining_diacritic(points->values[i])) { points->values[kept++] = points->values[i]; }
|
|
225
|
+
}
|
|
226
|
+
return encode_points(points->values, kept, out);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
int narsil_remove_marks(const uint16_t *units, size_t length, narsil_mark_test is_removed, narsil_text *out,
|
|
230
|
+
narsil_normalise_scratch *scratch) {
|
|
231
|
+
if (narsil_units_are_ascii(units, length)) { return narsil_text_assign(out, units, length); }
|
|
232
|
+
int status = decompose_text(units, length, &scratch->points);
|
|
233
|
+
if (status != NARSIL_OK) { return status; }
|
|
234
|
+
size_t kept = 0;
|
|
235
|
+
for (size_t i = 0; i < scratch->points.length; i++) {
|
|
236
|
+
if (!is_removed(scratch->points.values[i])) { scratch->points.values[kept++] = scratch->points.values[i]; }
|
|
237
|
+
}
|
|
238
|
+
if (kept == scratch->points.length) { return narsil_text_assign(out, units, length); }
|
|
239
|
+
status = encode_points(scratch->points.values, kept, &scratch->first);
|
|
240
|
+
if (status != NARSIL_OK) { return status; }
|
|
241
|
+
return narsil_nfc(scratch->first.units, scratch->first.length, out, &scratch->points);
|
|
242
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#ifndef NARSIL_ANALYSIS_NORMALISE_H
|
|
2
|
+
#define NARSIL_ANALYSIS_NORMALISE_H
|
|
3
|
+
|
|
4
|
+
#include "text.h"
|
|
5
|
+
|
|
6
|
+
#include <stddef.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
|
|
9
|
+
typedef struct {
|
|
10
|
+
narsil_text first;
|
|
11
|
+
narsil_text second;
|
|
12
|
+
narsil_code_points points;
|
|
13
|
+
} narsil_normalise_scratch;
|
|
14
|
+
|
|
15
|
+
typedef int (*narsil_mark_test)(uint32_t code_point);
|
|
16
|
+
|
|
17
|
+
void narsil_normalise_scratch_release(narsil_normalise_scratch *scratch);
|
|
18
|
+
|
|
19
|
+
int narsil_nfd(const uint16_t *units, size_t length, narsil_text *out, narsil_code_points *points);
|
|
20
|
+
int narsil_nfc(const uint16_t *units, size_t length, narsil_text *out, narsil_code_points *points);
|
|
21
|
+
int narsil_lowercase(const uint16_t *units, size_t length, narsil_text *out);
|
|
22
|
+
int narsil_fold_for_splitting(const uint16_t *units, size_t length, narsil_text *out,
|
|
23
|
+
narsil_normalise_scratch *scratch);
|
|
24
|
+
int narsil_strip_diacritics(const uint16_t *units, size_t length, narsil_text *out, narsil_code_points *points);
|
|
25
|
+
int narsil_remove_marks(const uint16_t *units, size_t length, narsil_mark_test is_removed, narsil_text *out,
|
|
26
|
+
narsil_normalise_scratch *scratch);
|
|
27
|
+
|
|
28
|
+
#endif
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#include "split.h"
|
|
2
|
+
|
|
3
|
+
#include "../../include/narsil_core.h"
|
|
4
|
+
#include "languages.h"
|
|
5
|
+
#include "text.h"
|
|
6
|
+
#include "unicode.h"
|
|
7
|
+
|
|
8
|
+
#include <stddef.h>
|
|
9
|
+
#include <stdint.h>
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
|
|
12
|
+
#define MIN_SPANS 16U
|
|
13
|
+
|
|
14
|
+
#define PROLONGED_SOUND_MARK 0x30FCU
|
|
15
|
+
#define IDEOGRAPHIC_ITERATION_MARK 0x3005U
|
|
16
|
+
#define LOWEST_NGRAM_CODE_POINT 0x0E00U
|
|
17
|
+
#define LOWEST_MARK_CODE_POINT 0x0300U
|
|
18
|
+
#define THAI_BLOCK_END 0x0E7FU
|
|
19
|
+
#define LAO_BLOCK_END 0x0EFFU
|
|
20
|
+
#define MYANMAR_BLOCK_START 0x1000U
|
|
21
|
+
#define MYANMAR_BLOCK_END 0x109FU
|
|
22
|
+
#define KHMER_BLOCK_START 0x1780U
|
|
23
|
+
#define KHMER_BLOCK_END 0x19FFU
|
|
24
|
+
#define SOUTHEAST_ASIAN_BLOCKS_END 0x1A00U
|
|
25
|
+
#define HIRAGANA_BLOCK_START 0x3040U
|
|
26
|
+
#define HIRAGANA_BLOCK_END 0x309FU
|
|
27
|
+
#define COMBINING_VOICED_MARK 0x3099U
|
|
28
|
+
#define COMBINING_SEMI_VOICED_MARK 0x309AU
|
|
29
|
+
#define KATAKANA_BLOCK_START 0x30A0U
|
|
30
|
+
#define KATAKANA_BLOCK_END 0x30FFU
|
|
31
|
+
#define HAN_EXTENSION_A_START 0x3400U
|
|
32
|
+
#define HAN_EXTENSION_A_END 0x4DBFU
|
|
33
|
+
#define HAN_UNIFIED_START 0x4E00U
|
|
34
|
+
#define HAN_UNIFIED_END 0x9FFFU
|
|
35
|
+
#define HANGUL_SYLLABLE_START 0xAC00U
|
|
36
|
+
#define HANGUL_SYLLABLE_END 0xD7A3U
|
|
37
|
+
#define HAN_COMPATIBILITY_START 0xF900U
|
|
38
|
+
#define HAN_COMPATIBILITY_END 0xFAFFU
|
|
39
|
+
|
|
40
|
+
int narsil_spans_push(narsil_spans *spans, narsil_span span) {
|
|
41
|
+
if (spans->length >= spans->capacity) {
|
|
42
|
+
size_t capacity = spans->capacity < MIN_SPANS ? MIN_SPANS : spans->capacity;
|
|
43
|
+
while (capacity <= spans->length) {
|
|
44
|
+
if (capacity > (SIZE_MAX / sizeof(narsil_span)) / 2) { return NARSIL_OUT_OF_MEMORY; }
|
|
45
|
+
capacity *= 2;
|
|
46
|
+
}
|
|
47
|
+
narsil_span *grown = realloc(spans->spans, capacity * sizeof(narsil_span));
|
|
48
|
+
if (grown == NULL) { return NARSIL_OUT_OF_MEMORY; }
|
|
49
|
+
spans->spans = grown;
|
|
50
|
+
spans->capacity = capacity;
|
|
51
|
+
}
|
|
52
|
+
spans->spans[spans->length] = span;
|
|
53
|
+
spans->length++;
|
|
54
|
+
return NARSIL_OK;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static narsil_span span_of(size_t begin, size_t end) {
|
|
58
|
+
narsil_span span = {(uint32_t)begin, (uint32_t)(end - begin)};
|
|
59
|
+
return span;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void narsil_spans_release(narsil_spans *spans) {
|
|
63
|
+
free(spans->spans);
|
|
64
|
+
spans->spans = NULL;
|
|
65
|
+
spans->length = 0;
|
|
66
|
+
spans->capacity = 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static uint32_t next_split_unit(const narsil_language *language, const uint16_t *units, uint32_t length,
|
|
70
|
+
size_t *index) {
|
|
71
|
+
if (language->splits_code_points) { return narsil_decode_next(units, length, index); }
|
|
72
|
+
return units[(*index)++];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
int narsil_split(const narsil_language *language, const uint16_t *units, uint32_t length, narsil_spans *parts) {
|
|
76
|
+
parts->length = 0;
|
|
77
|
+
size_t start = 0;
|
|
78
|
+
size_t index = 0;
|
|
79
|
+
while (index < length) {
|
|
80
|
+
size_t separator = index;
|
|
81
|
+
if (narsil_language_keeps(language, next_split_unit(language, units, length, &index))) { continue; }
|
|
82
|
+
int status = narsil_spans_push(parts, span_of(start, separator));
|
|
83
|
+
if (status != NARSIL_OK) { return status; }
|
|
84
|
+
for (;;) {
|
|
85
|
+
size_t before = index;
|
|
86
|
+
if (index >= length || narsil_language_keeps(language, next_split_unit(language, units, length, &index))) {
|
|
87
|
+
index = before;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
start = index;
|
|
92
|
+
}
|
|
93
|
+
return narsil_spans_push(parts, span_of(start, length));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static int is_mark(uint32_t code_point) {
|
|
97
|
+
if (code_point < LOWEST_MARK_CODE_POINT) { return 0; }
|
|
98
|
+
if (code_point >= HAN_UNIFIED_START && code_point <= HAN_UNIFIED_END) { return 0; }
|
|
99
|
+
if (code_point >= HIRAGANA_BLOCK_START && code_point <= KATAKANA_BLOCK_END) {
|
|
100
|
+
return code_point == COMBINING_VOICED_MARK || code_point == COMBINING_SEMI_VOICED_MARK;
|
|
101
|
+
}
|
|
102
|
+
if (code_point >= HANGUL_SYLLABLE_START && code_point <= HANGUL_SYLLABLE_END) { return 0; }
|
|
103
|
+
if (code_point >= HAN_EXTENSION_A_START && code_point <= HAN_EXTENSION_A_END) { return 0; }
|
|
104
|
+
return (narsil_unicode_properties(code_point) & NARSIL_UNICODE_MARK) != 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static uint32_t script_in_block(uint32_t code_point, uint32_t block_script) {
|
|
108
|
+
return narsil_unicode_script(code_point) == block_script ? block_script : NARSIL_UNICODE_SCRIPT_OTHER;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static uint32_t classify_southeast_asian(uint32_t code_point) {
|
|
112
|
+
if (code_point <= THAI_BLOCK_END) { return script_in_block(code_point, NARSIL_UNICODE_SCRIPT_THAI); }
|
|
113
|
+
if (code_point <= LAO_BLOCK_END) { return script_in_block(code_point, NARSIL_UNICODE_SCRIPT_LAO); }
|
|
114
|
+
if (code_point >= MYANMAR_BLOCK_START && code_point <= MYANMAR_BLOCK_END) {
|
|
115
|
+
return script_in_block(code_point, NARSIL_UNICODE_SCRIPT_MYANMAR);
|
|
116
|
+
}
|
|
117
|
+
if (code_point >= KHMER_BLOCK_START && code_point <= KHMER_BLOCK_END) {
|
|
118
|
+
return script_in_block(code_point, NARSIL_UNICODE_SCRIPT_KHMER);
|
|
119
|
+
}
|
|
120
|
+
return narsil_unicode_script(code_point);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static uint32_t prolonged_sound_kind(uint32_t current) {
|
|
124
|
+
return current == NARSIL_UNICODE_SCRIPT_HIRAGANA ? NARSIL_UNICODE_SCRIPT_HIRAGANA : NARSIL_UNICODE_SCRIPT_KATAKANA;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static uint32_t classify(uint32_t code_point) {
|
|
128
|
+
if (code_point < LOWEST_NGRAM_CODE_POINT) { return NARSIL_UNICODE_SCRIPT_OTHER; }
|
|
129
|
+
if (code_point < SOUTHEAST_ASIAN_BLOCKS_END) { return classify_southeast_asian(code_point); }
|
|
130
|
+
if (code_point >= HIRAGANA_BLOCK_START && code_point <= HIRAGANA_BLOCK_END) { return NARSIL_UNICODE_SCRIPT_HIRAGANA; }
|
|
131
|
+
if (code_point >= KATAKANA_BLOCK_START && code_point <= KATAKANA_BLOCK_END) { return NARSIL_UNICODE_SCRIPT_KATAKANA; }
|
|
132
|
+
if (code_point >= HAN_UNIFIED_START && code_point <= HAN_UNIFIED_END) { return NARSIL_UNICODE_SCRIPT_HAN; }
|
|
133
|
+
if (code_point >= HAN_EXTENSION_A_START && code_point <= HAN_EXTENSION_A_END) { return NARSIL_UNICODE_SCRIPT_HAN; }
|
|
134
|
+
if (code_point >= HANGUL_SYLLABLE_START && code_point <= HANGUL_SYLLABLE_END) { return NARSIL_UNICODE_SCRIPT_HANGUL; }
|
|
135
|
+
if (code_point >= HAN_COMPATIBILITY_START && code_point <= HAN_COMPATIBILITY_END) {
|
|
136
|
+
return NARSIL_UNICODE_SCRIPT_HAN;
|
|
137
|
+
}
|
|
138
|
+
if (code_point == IDEOGRAPHIC_ITERATION_MARK) { return NARSIL_UNICODE_SCRIPT_HAN; }
|
|
139
|
+
return narsil_unicode_script(code_point);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static int emit_run(narsil_span part, const narsil_code_points *offsets, uint32_t kind, uint32_t size,
|
|
143
|
+
narsil_spans *out) {
|
|
144
|
+
if (offsets->length < 2) { return NARSIL_OK; }
|
|
145
|
+
size_t count = offsets->length - 1;
|
|
146
|
+
const uint32_t *boundaries = offsets->values;
|
|
147
|
+
if (kind == NARSIL_UNICODE_SCRIPT_OTHER || count <= size) {
|
|
148
|
+
return narsil_spans_push(out, span_of((size_t)part.start + boundaries[0], (size_t)part.start + boundaries[count]));
|
|
149
|
+
}
|
|
150
|
+
for (size_t first = 0; first + size <= count; first++) {
|
|
151
|
+
int status = narsil_spans_push(
|
|
152
|
+
out, span_of((size_t)part.start + boundaries[first], (size_t)part.start + boundaries[first + size]));
|
|
153
|
+
if (status != NARSIL_OK) { return status; }
|
|
154
|
+
}
|
|
155
|
+
return NARSIL_OK;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
int narsil_expand_ngrams(const uint16_t *units, narsil_span part, uint32_t size, narsil_spans *out,
|
|
159
|
+
narsil_code_points *offsets) {
|
|
160
|
+
const uint16_t *text = units + part.start;
|
|
161
|
+
size_t length = part.length;
|
|
162
|
+
offsets->length = 0;
|
|
163
|
+
if (length == 0) { return NARSIL_OK; }
|
|
164
|
+
uint32_t kind = NARSIL_UNICODE_SCRIPT_OTHER;
|
|
165
|
+
size_t index = 0;
|
|
166
|
+
int status = NARSIL_OK;
|
|
167
|
+
while (index < length && status == NARSIL_OK) {
|
|
168
|
+
size_t start = index;
|
|
169
|
+
uint32_t code_point = narsil_decode_next(text, length, &index);
|
|
170
|
+
if (offsets->length > 0 && is_mark(code_point)) { continue; }
|
|
171
|
+
uint32_t next = code_point == PROLONGED_SOUND_MARK ? prolonged_sound_kind(kind) : classify(code_point);
|
|
172
|
+
if (offsets->length > 0 && next != kind) {
|
|
173
|
+
status = narsil_code_points_push(offsets, (uint32_t)start);
|
|
174
|
+
if (status == NARSIL_OK) { status = emit_run(part, offsets, kind, size, out); }
|
|
175
|
+
offsets->length = 0;
|
|
176
|
+
}
|
|
177
|
+
kind = next;
|
|
178
|
+
if (status == NARSIL_OK) { status = narsil_code_points_push(offsets, (uint32_t)start); }
|
|
179
|
+
}
|
|
180
|
+
if (status == NARSIL_OK) { status = narsil_code_points_push(offsets, (uint32_t)length); }
|
|
181
|
+
if (status == NARSIL_OK) { status = emit_run(part, offsets, kind, size, out); }
|
|
182
|
+
return status;
|
|
183
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#ifndef NARSIL_ANALYSIS_SPLIT_H
|
|
2
|
+
#define NARSIL_ANALYSIS_SPLIT_H
|
|
3
|
+
|
|
4
|
+
#include "languages.h"
|
|
5
|
+
|
|
6
|
+
#include <stddef.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
|
|
9
|
+
typedef struct {
|
|
10
|
+
uint32_t start;
|
|
11
|
+
uint32_t length;
|
|
12
|
+
} narsil_span;
|
|
13
|
+
|
|
14
|
+
typedef struct {
|
|
15
|
+
narsil_span *spans;
|
|
16
|
+
size_t length;
|
|
17
|
+
size_t capacity;
|
|
18
|
+
} narsil_spans;
|
|
19
|
+
|
|
20
|
+
int narsil_spans_push(narsil_spans *spans, narsil_span span);
|
|
21
|
+
void narsil_spans_release(narsil_spans *spans);
|
|
22
|
+
|
|
23
|
+
int narsil_split(const narsil_language *language, const uint16_t *units, uint32_t length, narsil_spans *parts);
|
|
24
|
+
int narsil_expand_ngrams(const uint16_t *units, narsil_span part, uint32_t size, narsil_spans *out,
|
|
25
|
+
narsil_code_points *offsets);
|
|
26
|
+
|
|
27
|
+
#endif
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#include "stop_words.h"
|
|
2
|
+
|
|
3
|
+
#include "../../include/narsil_core.h"
|
|
4
|
+
#include "text.h"
|
|
5
|
+
|
|
6
|
+
#include <stddef.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <string.h>
|
|
10
|
+
|
|
11
|
+
#define FNV_OFFSET_BASIS 2166136261U
|
|
12
|
+
#define FNV_PRIME 16777619U
|
|
13
|
+
#define MIN_SLOTS 8U
|
|
14
|
+
#define MAX_STOP_WORDS (1U << 28)
|
|
15
|
+
#define EMPTY_SLOT 0U
|
|
16
|
+
|
|
17
|
+
static uint32_t hash_units(const uint16_t *units, size_t length) {
|
|
18
|
+
uint32_t hash = FNV_OFFSET_BASIS;
|
|
19
|
+
for (size_t i = 0; i < length; i++) {
|
|
20
|
+
hash ^= units[i];
|
|
21
|
+
hash *= FNV_PRIME;
|
|
22
|
+
}
|
|
23
|
+
return hash;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static uint32_t word_length(const narsil_stop_words *set, uint32_t word) {
|
|
27
|
+
return set->offsets[word + 1] - set->offsets[word];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static int slot_holds(const narsil_stop_words *set, uint32_t slot, const uint16_t *units, size_t length) {
|
|
31
|
+
uint32_t word = set->slots[slot] - 1;
|
|
32
|
+
return narsil_units_equal(set->units + set->offsets[word], word_length(set, word), units, length);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void narsil_stop_words_release(narsil_stop_words *set) {
|
|
36
|
+
free(set->units);
|
|
37
|
+
free(set->offsets);
|
|
38
|
+
free(set->slots);
|
|
39
|
+
memset(set, 0, sizeof(*set));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
int narsil_stop_words_build(narsil_stop_words *set, const uint16_t *units, const uint32_t *offsets, uint32_t count) {
|
|
43
|
+
memset(set, 0, sizeof(*set));
|
|
44
|
+
if (count > MAX_STOP_WORDS) { return NARSIL_INVALID_ARGUMENT; }
|
|
45
|
+
for (uint32_t word = 0; word < count; word++) {
|
|
46
|
+
if (offsets[word + 1] < offsets[word]) { return NARSIL_INVALID_ARGUMENT; }
|
|
47
|
+
}
|
|
48
|
+
size_t total = offsets[count];
|
|
49
|
+
uint32_t slots = MIN_SLOTS;
|
|
50
|
+
while (slots < count * 2U) { slots *= 2U; }
|
|
51
|
+
set->units = malloc((total == 0 ? 1 : total) * sizeof(uint16_t));
|
|
52
|
+
set->offsets = malloc(((size_t)count + 1) * sizeof(uint32_t));
|
|
53
|
+
set->slots = calloc(slots, sizeof(uint32_t));
|
|
54
|
+
if (set->units == NULL || set->offsets == NULL || set->slots == NULL) {
|
|
55
|
+
narsil_stop_words_release(set);
|
|
56
|
+
return NARSIL_OUT_OF_MEMORY;
|
|
57
|
+
}
|
|
58
|
+
if (total > 0) { memcpy(set->units, units, total * sizeof(uint16_t)); }
|
|
59
|
+
memcpy(set->offsets, offsets, ((size_t)count + 1) * sizeof(uint32_t));
|
|
60
|
+
set->count = count;
|
|
61
|
+
set->slot_mask = slots - 1U;
|
|
62
|
+
for (uint32_t word = 0; word < count; word++) {
|
|
63
|
+
const uint16_t *word_units = set->units + offsets[word];
|
|
64
|
+
uint32_t length = word_length(set, word);
|
|
65
|
+
uint32_t slot = hash_units(word_units, length) & set->slot_mask;
|
|
66
|
+
while (set->slots[slot] != EMPTY_SLOT && !slot_holds(set, slot, word_units, length)) {
|
|
67
|
+
slot = (slot + 1U) & set->slot_mask;
|
|
68
|
+
}
|
|
69
|
+
set->slots[slot] = word + 1U;
|
|
70
|
+
}
|
|
71
|
+
return NARSIL_OK;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
int narsil_stop_words_contains(const narsil_stop_words *set, const uint16_t *units, size_t length) {
|
|
75
|
+
if (set->slots == NULL) { return 0; }
|
|
76
|
+
uint32_t slot = hash_units(units, length) & set->slot_mask;
|
|
77
|
+
while (set->slots[slot] != EMPTY_SLOT) {
|
|
78
|
+
if (slot_holds(set, slot, units, length)) { return 1; }
|
|
79
|
+
slot = (slot + 1U) & set->slot_mask;
|
|
80
|
+
}
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#ifndef NARSIL_ANALYSIS_STOP_WORDS_H
|
|
2
|
+
#define NARSIL_ANALYSIS_STOP_WORDS_H
|
|
3
|
+
|
|
4
|
+
#include <stddef.h>
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
|
|
7
|
+
typedef struct {
|
|
8
|
+
uint16_t *units;
|
|
9
|
+
uint32_t *offsets;
|
|
10
|
+
uint32_t count;
|
|
11
|
+
uint32_t *slots;
|
|
12
|
+
uint32_t slot_mask;
|
|
13
|
+
} narsil_stop_words;
|
|
14
|
+
|
|
15
|
+
int narsil_stop_words_build(narsil_stop_words *set, const uint16_t *units, const uint32_t *offsets, uint32_t count);
|
|
16
|
+
int narsil_stop_words_contains(const narsil_stop_words *set, const uint16_t *units, size_t length);
|
|
17
|
+
void narsil_stop_words_release(narsil_stop_words *set);
|
|
18
|
+
|
|
19
|
+
#endif
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#include "term_cache.h"
|
|
2
|
+
|
|
3
|
+
#include <stddef.h>
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
#include <string.h>
|
|
7
|
+
|
|
8
|
+
#define TERM_CACHE_SLOTS 16384U
|
|
9
|
+
#define TERM_CACHE_WAYS 8U
|
|
10
|
+
#define TERM_CACHE_SETS (TERM_CACHE_SLOTS / TERM_CACHE_WAYS)
|
|
11
|
+
#define TERM_CACHE_SET_MASK (TERM_CACHE_SETS - 1U)
|
|
12
|
+
#define TERM_FNV_OFFSET_BASIS 2166136261U
|
|
13
|
+
#define TERM_FNV_PRIME 16777619U
|
|
14
|
+
#define TERM_TAG_LANGUAGE_SHIFT 8U
|
|
15
|
+
#define TERM_TAG_EMPTY 0U
|
|
16
|
+
|
|
17
|
+
static uint32_t tag_of(const narsil_term_key *key) {
|
|
18
|
+
return ((key->language_index + 1U) << TERM_TAG_LANGUAGE_SHIFT) | key->flags;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static int holds(const narsil_term_slot *slot, uint32_t tag, const narsil_term_key *key) {
|
|
22
|
+
return slot->tag == tag && slot->key_length == key->length &&
|
|
23
|
+
memcmp(slot->key, key->units, key->length * sizeof *key->units) == 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static int prepared(narsil_term_cache *cache) {
|
|
27
|
+
if (cache->slots != NULL) { return 1; }
|
|
28
|
+
if (cache->unavailable) { return 0; }
|
|
29
|
+
cache->slots = calloc(TERM_CACHE_SLOTS, sizeof *cache->slots);
|
|
30
|
+
cache->next_victim = calloc(TERM_CACHE_SETS, sizeof *cache->next_victim);
|
|
31
|
+
if (cache->slots == NULL || cache->next_victim == NULL) {
|
|
32
|
+
free(cache->slots);
|
|
33
|
+
free(cache->next_victim);
|
|
34
|
+
cache->slots = NULL;
|
|
35
|
+
cache->next_victim = NULL;
|
|
36
|
+
cache->unavailable = 1;
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
narsil_term_slot *narsil_term_cache_find(narsil_term_cache *cache, const narsil_term_key *key,
|
|
43
|
+
narsil_term_slot **victim) {
|
|
44
|
+
*victim = NULL;
|
|
45
|
+
if (key->length == 0 || key->length > NARSIL_TERM_CACHE_UNITS || !prepared(cache)) { return NULL; }
|
|
46
|
+
uint32_t tag = tag_of(key);
|
|
47
|
+
uint32_t hash = (TERM_FNV_OFFSET_BASIS ^ tag) * TERM_FNV_PRIME;
|
|
48
|
+
for (size_t unit = 0; unit < key->length; unit++) {
|
|
49
|
+
hash ^= key->units[unit];
|
|
50
|
+
hash *= TERM_FNV_PRIME;
|
|
51
|
+
}
|
|
52
|
+
uint32_t set = hash & TERM_CACHE_SET_MASK;
|
|
53
|
+
narsil_term_slot *ways = &cache->slots[(size_t)set * TERM_CACHE_WAYS];
|
|
54
|
+
narsil_term_slot *empty = NULL;
|
|
55
|
+
for (uint32_t way = 0; way < TERM_CACHE_WAYS; way++) {
|
|
56
|
+
if (holds(&ways[way], tag, key)) { return &ways[way]; }
|
|
57
|
+
if (empty == NULL && ways[way].tag == TERM_TAG_EMPTY) { empty = &ways[way]; }
|
|
58
|
+
}
|
|
59
|
+
if (empty == NULL) {
|
|
60
|
+
uint8_t *next = &cache->next_victim[set];
|
|
61
|
+
empty = &ways[*next];
|
|
62
|
+
*next = (uint8_t)((*next + 1U) % TERM_CACHE_WAYS);
|
|
63
|
+
}
|
|
64
|
+
*victim = empty;
|
|
65
|
+
return NULL;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int narsil_term_cache_store(narsil_term_slot *slot, const narsil_term_key *key, const uint16_t *value, size_t length) {
|
|
69
|
+
if (length == 0 || length > NARSIL_TERM_CACHE_UNITS) { return 0; }
|
|
70
|
+
slot->tag = tag_of(key);
|
|
71
|
+
slot->key_length = (uint16_t)key->length;
|
|
72
|
+
memcpy(slot->key, key->units, key->length * sizeof *key->units);
|
|
73
|
+
slot->value_length = (uint16_t)length;
|
|
74
|
+
memcpy(slot->value, value, length * sizeof *value);
|
|
75
|
+
return 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
uint32_t narsil_term_cache_index(const narsil_term_cache *cache, const narsil_term_slot *slot) {
|
|
79
|
+
return (uint32_t)(slot - cache->slots);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
void narsil_term_cache_release(narsil_term_cache *cache) {
|
|
83
|
+
free(cache->slots);
|
|
84
|
+
free(cache->next_victim);
|
|
85
|
+
cache->slots = NULL;
|
|
86
|
+
cache->next_victim = NULL;
|
|
87
|
+
cache->unavailable = 0;
|
|
88
|
+
}
|