14 #include <sys/types.h> 31 #include <string_view> 34 #include <fcitx-utils/macros.h> 35 #include "naivevector.h" 42 template <
typename value_type>
45 value_type result_value;
49 int32_t decodeValue(V raw) {
50 DecoderUnion<V> decoder;
51 decoder.result_value = raw;
52 return decoder.result;
57 static int32_t NO_VALUE() {
return -1; };
58 static int32_t NO_PATH() {
return -2; }
64 int32_t noValue = decodeValue(std::nanf(
"1"));
65 int32_t noPath = decodeValue(std::nanf(
"2"));
66 return (noValue != noPath);
70 struct NanValue<float> {
71 static_assert(std::numeric_limits<float>::has_quiet_NaN,
72 "Require support for quiet NaN.");
73 static int32_t NO_VALUE() {
74 return isGoodNanf() ? decodeValue(std::nanf(
"1")) : 0x7fc00001;
76 static int32_t NO_PATH() {
77 return isGoodNanf() ? decodeValue(std::nanf(
"2")) : 0x7fc00002;
82 constexpr T decodeImpl(int32_t raw) {
83 typename DATriePrivate<T>::decoder_type d;
85 return d.result_value;
94 using vector_impl = naivevector<T>;
96 template <
typename V,
bool ORDERED,
int MAX_TRIAL>
100 using value_type =
typename base_type::value_type;
101 using position_type =
typename base_type::position_type;
102 using updater_type =
typename base_type::updater_type;
103 using callback_type =
typename base_type::callback_type;
104 using decoder_type = DecoderUnion<V>;
106 static inline const int32_t CEDAR_NO_VALUE = NanValue<V>::NO_VALUE();
107 static inline const int32_t CEDAR_NO_PATH = NanValue<V>::NO_PATH();
109 static constexpr
size_t MAX_ALLOC_SIZE = 1
111 using result_type = value_type;
112 using uchar = uint8_t;
113 static_assert(
sizeof(value_type) <=
sizeof(int32_t),
114 "value size need to be same as int32_t");
121 node(
const int32_t base_ = 0,
const int32_t check_ = 0)
122 : base(base_), check(check_) {}
124 node(std::istream &in) : base(0), check(0) {
125 throw_if_io_fail(unmarshall(in, base));
126 throw_if_io_fail(unmarshall(in, check));
129 FCITX_INLINE_DEFINE_DEFAULT_DTOR_AND_COPY(
node);
131 friend std::ostream &operator<<(std::ostream &out,
const node &n) {
132 marshall(out, n.base) && marshall(out, n.check);
141 npos_t() : offset(0), index(0) {}
143 explicit npos_t(position_type i) {
145 index = i & 0xffffffffULL;
148 operator bool() {
return offset != 0 && index != 0; }
150 bool operator==(
const npos_t &other)
const {
151 return offset == other.offset && index == other.index;
154 bool operator!=(
const npos_t &other)
const {
155 return !operator==(other);
158 position_type toInt() {
159 return (static_cast<position_type>(offset) << 32) | index;
169 block() : prev(0), next(0), num(256), reject(257), trial(0), ehead(0) {}
172 throw_if_io_fail(unmarshall(in, prev));
173 throw_if_io_fail(unmarshall(in, next));
174 throw_if_io_fail(unmarshall(in, num));
175 throw_if_io_fail(unmarshall(in, reject));
176 throw_if_io_fail(unmarshall(in, trial));
177 throw_if_io_fail(unmarshall(in, ehead));
180 friend std::ostream &operator<<(std::ostream &out,
const block &b) {
181 marshall(out, b.prev) && marshall(out, b.next) &&
182 marshall(out, b.num) && marshall(out, b.reject) &&
183 marshall(out, b.trial) && marshall(out, b.ehead);
190 ninfo() : sibling(0), child(0) {}
192 ninfo(std::istream &in) {
193 throw_if_io_fail(unmarshall(in, sibling));
194 throw_if_io_fail(unmarshall(in, child));
197 friend std::ostream &operator<<(std::ostream &out,
const ninfo &n) {
198 marshall(out, n.sibling) && marshall(out, n.child);
212 std::array<int, 257> m_reject;
217 size_t size()
const {
return m_ninfo.size(); }
219 size_t capacity()
const {
return m_array.size(); }
223 m_array.shrink_to_fit();
224 m_block.shrink_to_fit();
225 m_tail.shrink_to_fit();
226 m_ninfo.shrink_to_fit();
227 m_tail0.shrink_to_fit();
230 size_t num_keys()
const {
232 for (
auto to = 0; to < static_cast<int>(size()); ++to) {
233 const node &n = m_array[to];
234 if (n.check >= 0 && (m_array[n.check].base == to || n.base < 0)) {
241 void open(std::istream &fin) {
244 throw_if_io_fail(unmarshall(fin, len));
245 throw_if_io_fail(unmarshall(fin, size_));
247 const size_t length_ =
static_cast<size_t>(len);
249 m_tail.resize(length_);
251 m_array.reserve(size_);
253 m_ninfo.reserve(size_);
255 m_block.reserve(size_ >> 8);
258 throw_if_io_fail(fin.read(reinterpret_cast<char *>(m_tail.data()),
259 sizeof(
char) * length_));
261 for (
auto i = 0U; i < size_; i++) {
262 m_array.emplace_back(fin);
264 m_array.resize(size_);
266 throw_if_io_fail(unmarshall(fin, m_bheadF));
267 throw_if_io_fail(unmarshall(fin, m_bheadC));
268 throw_if_io_fail(unmarshall(fin, m_bheadO));
270 for (
auto i = 0U; i < size_; i++) {
271 m_ninfo.emplace_back(fin);
274 for (
auto i = 0U, end = size_ >> 8; i < end; i++) {
275 m_block.emplace_back(fin);
279 void save(std::ostream &fout) {
282 const uint32_t length = m_tail.size();
283 const uint32_t size_ = size();
285 assert(m_block.size() << 8 == m_ninfo.size());
286 throw_if_io_fail(marshall(fout, length));
287 throw_if_io_fail(marshall(fout, size_));
288 throw_if_io_fail(fout.write(reinterpret_cast<char *>(m_tail.data()),
289 sizeof(
char) * length));
292 for (
auto &n : m_array) {
293 throw_if_io_fail(fout << n);
299 throw_if_io_fail(marshall(fout, m_bheadF));
300 throw_if_io_fail(marshall(fout, m_bheadC));
301 throw_if_io_fail(marshall(fout, m_bheadO));
303 for (
auto &n : m_ninfo) {
304 throw_if_io_fail(fout << n);
307 for (
auto &b : m_block) {
308 throw_if_io_fail(fout << b);
313 m_bheadF = m_bheadC = m_bheadO = 0;
316 m_array[0] =
node(0, -1);
318 for (
int i = 1; i < 256; ++i) {
320 node(i == 1 ? -255 : -(i - 1), i == 255 ? -1 : -(i + 1));
329 m_block[0].ehead = 1;
333 m_tail.resize(
sizeof(int32_t));
335 for (
auto i = 0; i <= 256; ++i) {
340 void suffix(std::string &key,
size_t len,
npos_t pos)
const {
345 if (
const int offset = pos.offset) {
346 size_t len_tail = std::strlen(&m_tail[-m_array[to].base]);
347 if (len > len_tail) {
353 std::copy(&m_tail[static_cast<size_t>(offset) - len_tail],
354 &m_tail[static_cast<size_t>(offset)], key.begin() + len);
357 const int from = m_array[to].check;
359 static_cast<char>(m_array[from].base ^
static_cast<int>(to));
364 template <
typename U>
365 void update(
const char *key,
const U &callback) {
366 update(key, std::strlen(key), callback);
369 template <
typename U>
370 void update(
const char *key,
size_t len,
const U &callback) {
373 update(key, from, pos, len, callback);
376 template <
typename U>
377 void update(
const char *key,
npos_t &from,
size_t &pos,
size_t len,
379 update(key, from, pos, len, callback, [](
const int,
const int) {});
382 template <
typename U,
typename T>
383 void update(
const char *key,
npos_t &npos,
size_t &pos,
size_t len,
384 const U &callback,
const T &cf) {
386 throw std::invalid_argument(
"failed to insert zero-length key");
389 auto &from = npos.index;
390 auto offset = npos.offset;
392 for (
const uchar *
const key_ = reinterpret_cast<const uchar *>(key);
393 m_array[from].base >= 0; ++pos) {
395 const auto to = _follow(from, 0, cf);
396 m_array[to].value = callback(m_array[to].value);
399 from =
static_cast<size_t>(_follow(from, key_[pos], cf));
401 offset = -m_array[from].base;
403 if (offset >=
sizeof(int32_t)) {
404 const size_t pos_orig = pos;
405 char *
const tail = m_tail.data() + offset - pos;
406 while (pos < len && key[pos] == tail[pos]) {
410 if (pos == len && tail[pos] ==
'\0') {
411 if (
const ssize_t moved =
413 npos.offset = offset + moved;
415 char *
const data = &tail[len + 1];
416 storeDWord(data, callback(loadDWord<value_type>(data)));
422 for (
auto offset_ = static_cast<size_t>(-m_array[from].base);
424 from =
static_cast<size_t>(
425 _follow(from, static_cast<uchar>(m_tail[offset_]), cf));
429 for (
size_t pos_ = pos_orig; pos_ < pos; ++pos_) {
430 from =
static_cast<size_t>(
431 _follow(from, static_cast<uchar>(key[pos_]), cf));
439 ssize_t moved = pos - pos_orig;
442 _follow(from, static_cast<uchar>(tail[pos]), cf);
443 m_array[to_].base = -
static_cast<int>(offset + ++moved);
444 moved -= 1 +
sizeof(value_type);
447 for (ssize_t i = offset; i <= moved; i += 1 +
sizeof(value_type)) {
448 if (m_tail0.capacity() == m_tail0.size()) {
450 m_tail0.capacity() + (m_tail0.size() >= MAX_ALLOC_SIZE
453 m_tail0.reserve(quota);
455 m_tail0.push_back(i);
457 if (pos == len || tail[pos] ==
'\0') {
458 const int to = _follow(from, 0, cf);
460 m_array[to].value = callback(m_array[to].value);
466 m_array[to].value = loadDWord<value_type>(&tail[pos + 1]);
468 from =
static_cast<size_t>(
469 _follow(from, static_cast<uchar>(key[pos]), cf));
472 const auto needed = len - pos + 1 +
sizeof(value_type);
473 if (pos == len && !m_tail0.empty()) {
474 const int offset0 = *m_tail0.rbegin();
475 m_tail[offset0] =
'\0';
476 m_array[from].base = -offset0;
478 char *
const data = &m_tail[offset0 + 1];
479 storeDWord(data, callback(0));
482 if (m_tail.capacity() < m_tail.size() + needed) {
485 std::max(needed, std::min(MAX_ALLOC_SIZE, m_tail.size()));
486 m_tail.reserve(quota);
488 m_array[from].base = -m_tail.size();
489 const size_t pos_orig = pos;
490 auto old_length = m_tail.size();
491 m_tail.resize(m_tail.size() + needed);
492 char *
const tail = &m_tail[old_length] - pos;
495 tail[pos] = key[pos];
496 }
while (++pos < len);
497 npos.offset = old_length + len - pos_orig;
499 char *
const data = &tail[len + 1];
500 storeDWord(data, callback(loadDWord<value_type>(data)));
504 int erase(
const char *key) {
return erase(key, std::strlen(key)); }
505 int erase(
const char *key,
size_t len,
npos_t npos =
npos_t()) {
507 auto &from = npos.index;
508 const auto i = _find(key, npos, pos, len);
509 if (i == CEDAR_NO_PATH || i == CEDAR_NO_VALUE) {
515 bool flag = m_array[from].base < 0;
516 int e = flag ?
static_cast<int>(from) : m_array[from].base ^ 0;
517 from = m_array[e].check;
519 const node &n = m_array[from];
520 flag = m_ninfo[n.base ^ m_ninfo[from].child].sibling;
522 _pop_sibling(from, n.base, static_cast<uchar>(n.base ^ e));
525 e =
static_cast<int>(from);
526 from =
static_cast<size_t>(m_array[from].check);
531 bool foreach(
const callback_type &callback,
npos_t root =
npos_t())
const {
535 for (resultRaw = begin(from, p); resultRaw != CEDAR_NO_PATH;
536 resultRaw = next(from, p, root)) {
537 if (resultRaw != CEDAR_NO_VALUE &&
538 !callback(decodeImpl<V>(resultRaw), p, from.toInt())) {
545 template <
typename T>
546 void dump(T *result,
const size_t result_len)
const {
548 foreach([result, result_len, &num](value_type value,
size_t len,
550 if (num < result_len) {
551 _set_result(&result[num++], value, len,
npos_t(pos));
559 const size_t length_ =
560 static_cast<size_t>(m_tail.size()) -
561 (static_cast<size_t>(m_tail0.size()) * (1 +
sizeof(value_type)));
564 t.resize(
sizeof(int32_t));
566 for (
int to = 0; to < static_cast<int>(size()); ++to) {
567 node &n = m_array[to];
568 if (n.check >= 0 && m_array[n.check].base != to && n.base < 0) {
569 char *
const tail_(&m_tail[-n.base]);
570 n.base = -
static_cast<int32_t
>(t.size());
573 t.push_back(tail_[i]);
574 }
while (tail_[i++]);
575 t.resize(t.size() +
sizeof(value_type));
576 storeDWord(&t[t.size() -
sizeof(value_type)],
577 loadDWord<value_type>(&tail_[i]));
583 m_tail0.shrink_to_fit();
587 int32_t begin(
npos_t &npos,
size_t &len)
const {
588 auto &from = npos.index;
590 npos.offset ? -
static_cast<int>(npos.offset) : m_array[from].base;
592 uchar c = m_ninfo[from].child;
594 c = m_ninfo[base ^ c].sibling;
596 return CEDAR_NO_PATH;
599 for (; c && base >= 0; ++len) {
600 from =
static_cast<size_t>(base) ^ c;
601 base = m_array[from].base;
602 c = m_ninfo[from].child;
605 return m_array[base ^ c].base;
608 const size_t len_ = std::strlen(&m_tail[-base]);
609 npos.offset =
static_cast<size_t>(-base) + len_;
611 return loadDWord<int32_t>(&m_tail[-base] + len_ + 1);
614 int32_t next(
npos_t &npos,
size_t &len,
617 auto &from = npos.index;
618 if (
const int offset = npos.offset) {
620 return CEDAR_NO_PATH;
623 len -=
static_cast<size_t>(offset - (-m_array[from].base));
625 c = m_ninfo[m_array[from].base].sibling;
627 for (; !c && npos != root; --len) {
628 c = m_ninfo[from].sibling;
629 from =
static_cast<size_t>(m_array[from].check);
632 return CEDAR_NO_PATH;
634 from =
static_cast<size_t>(m_array[from].base) ^ c;
635 return begin(npos, ++len);
638 template <
typename T>
639 int _follow(uint32_t &from,
const uchar label,
const T &cf) {
641 const int base = m_array[from].base;
642 if (base < 0 || m_array[base ^ label].check < 0) {
643 to = _pop_enode(base, label, static_cast<int>(from));
644 _push_sibling(from, to ^ label, label, base >= 0);
645 }
else if (m_array[base ^ label].check != static_cast<int>(from)) {
646 to = _resolve(from, base, label, cf);
654 int32_t _find(
const char *key,
npos_t &npos,
size_t &pos,
655 const size_t len)
const {
656 auto &from = npos.index;
657 auto offset = npos.offset;
659 for (
const uchar *
const key_ = reinterpret_cast<const uchar *>(key);
660 m_array[from].base >= 0;) {
662 const node &n = m_array[m_array[from].base ^ 0];
663 if (n.check != static_cast<int>(from)) {
664 return CEDAR_NO_VALUE;
668 size_t to =
static_cast<size_t>(m_array[from].base);
670 if (m_array[to].check != static_cast<int>(from)) {
671 return CEDAR_NO_PATH;
676 offset = -m_array[from].base;
679 const size_t pos_orig = pos;
680 const char *
const tail = &m_tail[offset] - pos;
683 if (key[pos] != tail[pos]) {
686 }
while (++pos < len);
687 if (
const int moved = pos - pos_orig) {
688 npos.offset = offset + moved;
691 return CEDAR_NO_PATH;
695 return CEDAR_NO_VALUE;
697 return loadDWord<int32_t>(&tail[len + 1]);
703 return m_block[m_bheadC].ehead;
706 return m_block[m_bheadO].ehead;
708 return _add_block() << 8;
710 int _find_place(
const uchar *
const first,
const uchar *
const last) {
711 if (
auto bi = m_bheadO) {
712 const auto bz = m_block[m_bheadO].prev;
713 const auto nc = std::distance(first, last);
715 block &b = m_block[bi];
716 if (b.num >= nc && nc < b.reject) {
717 for (
int e = b.ehead;;) {
718 const int base = e ^ *first;
719 for (
const uchar *p = first;
720 m_array[base ^ *++p].check < 0;) {
726 e = -m_array[e].check;
733 if (b.reject < m_reject[b.num]) {
734 m_reject[b.num] = b.reject;
736 const int bi_ = b.next;
737 if (++b.trial == MAX_TRIAL) {
738 _transfer_block(bi, m_bheadO, m_bheadC);
746 return _add_block() << 8;
749 static void _set_result(result_type *x, value_type r,
size_t = 0,
753 static void _set_result(std::tuple<value_type, size_t, position_type> *x,
754 value_type r,
size_t len,
npos_t npos) {
755 *x = std::make_tuple<>(r, len, npos.toInt());
757 void _pop_block(
const int bi,
int &head_in,
const bool last) {
761 const block &b = m_block[bi];
762 m_block[b.prev].next = b.next;
763 m_block[b.next].prev = b.prev;
769 void _push_block(
const int bi,
int &head_out,
const bool empty) {
770 block &b = m_block[bi];
772 head_out = b.prev = b.next = bi;
774 int &tail_out = m_block[head_out].prev;
777 head_out = tail_out = m_block[tail_out].next = bi;
782 if (size() == capacity()) {
785 (size() >= MAX_ALLOC_SIZE ? MAX_ALLOC_SIZE : size());
786 m_array.reserve(new_capacity);
787 m_array.resize(new_capacity);
788 m_ninfo.reserve(new_capacity);
789 m_block.reserve(new_capacity >> 8);
790 m_block.resize(size() >> 8);
792 assert(m_block.size() == size() >> 8);
793 m_block.resize(m_block.size() + 1);
794 m_block[size() >> 8].ehead = size();
796 assert(m_array.size() >= size() + 256);
797 m_array[size()] =
node(-(size() + 255), -(size() + 1));
798 for (
auto i = size() + 1; i < size() + 255; ++i) {
799 m_array[i] =
node(-(i - 1), -(i + 1));
801 m_array[size() + 255] =
node(-(size() + 254), -size());
802 _push_block(size() >> 8, m_bheadO, !m_bheadO);
803 m_ninfo.resize(size() + 256);
804 return (size() >> 8) - 1;
807 void _transfer_block(
const int bi,
int &head_in,
int &head_out) {
808 _pop_block(bi, head_in, bi == m_block[bi].next);
809 _push_block(bi, head_out, !head_out && m_block[bi].num);
812 int _pop_enode(
const int base,
const uchar label,
const int from) {
813 const int e = base < 0 ? _find_place() : base ^ label;
814 const int bi = e >> 8;
815 node &n = m_array[e];
816 block &b = m_block[bi];
819 _transfer_block(bi, m_bheadC, m_bheadF);
822 m_array[-n.base].check = n.check;
823 m_array[-n.check].base = n.base;
827 if (bi && b.num == 1 && b.trial != MAX_TRIAL) {
829 _transfer_block(bi, m_bheadO, m_bheadC);
836 n.value = value_type(0);
840 m_array[from].base = e ^ label;
845 void _push_enode(
const int e) {
846 const int bi = e >> 8;
847 block &b = m_block[bi];
850 m_array[e] =
node(-e, -e);
852 _transfer_block(bi, m_bheadF, m_bheadC);
855 const int prev = b.ehead;
856 const int next = -m_array[prev].check;
857 m_array[e] =
node(-prev, -next);
858 m_array[prev].check = m_array[next].base = -e;
859 if (b.num == 2 || b.trial == MAX_TRIAL) {
861 _transfer_block(bi, m_bheadC, m_bheadO);
866 if (b.reject < m_reject[b.num]) {
867 b.reject = m_reject[b.num];
869 m_ninfo[e] =
ninfo();
872 void _push_sibling(
const int32_t from,
const int base,
const uchar label,
873 const bool flag =
true) {
874 uchar *c = &m_ninfo[from].child;
875 if (flag && (ORDERED ? label > *c : !*c)) {
877 c = &m_ninfo[base ^ *c].sibling;
878 }
while (ORDERED && *c && *c < label);
880 m_ninfo[base ^ label].sibling = *c, *c = label;
883 void _pop_sibling(
const int32_t from,
const int base,
const uchar label) {
884 uchar *c = &m_ninfo[from].child;
885 while (*c != label) {
886 c = &m_ninfo[base ^ *c].sibling;
888 *c = m_ninfo[base ^ label].sibling;
891 bool _consult(
const int base_n,
const int base_p, uchar c_n,
894 c_n = m_ninfo[base_n ^ c_n].sibling;
895 c_p = m_ninfo[base_p ^ c_p].sibling;
896 }
while (c_n && c_p);
900 uchar *_set_child(uchar *p,
const int base, uchar c,
901 const std::optional<uchar> label = std::nullopt) {
905 c = m_ninfo[base ^ c].sibling;
907 if (ORDERED && label.has_value()) {
908 while (c && c < *label) {
911 c = m_ninfo[base ^ c].sibling;
914 if (label.has_value()) {
921 c = m_ninfo[base ^ c].sibling;
926 template <
typename T>
927 int _resolve(uint32_t &from_n,
const int base_n,
const uchar label_n,
930 const int to_pn = base_n ^ label_n;
931 const int from_p = m_array[to_pn].check;
932 const int base_p = m_array[from_p].base;
934 = _consult(base_n, base_p, m_ninfo[from_n].child,
935 m_ninfo[from_p].child);
937 uchar *
const first = child;
939 flag ? _set_child(first, base_n, m_ninfo[from_n].child, label_n)
940 : _set_child(first, base_p, m_ninfo[from_p].child);
941 assert(first < last);
943 (first + 1 == last ? _find_place() : _find_place(first, last)) ^
946 const int from = flag ?
static_cast<int>(from_n) : from_p;
947 const int base_ = flag ? base_n : base_p;
948 if (flag && *first == label_n) {
949 m_ninfo[from].child = label_n;
951 m_array[from].base = base;
952 for (
const uchar *p = first; p < last; ++p) {
953 const int to = _pop_enode(base, *p, from);
954 const int to_ = base_ ^ *p;
955 m_ninfo[to].sibling = (p + 1 == last) ? 0 : *(p + 1);
956 if (flag && to_ == to_pn) {
960 node &n = m_array[to];
961 node &n_ = m_array[to_];
963 if (n.base > 0 && *p) {
964 uchar c = m_ninfo[to].child = m_ninfo[to_].child;
966 m_array[n.base ^ c].check = to;
967 }
while ((c = m_ninfo[n.base ^ c].sibling));
969 if (!flag && to_ == static_cast<int>(from_n)) {
971 from_n =
static_cast<size_t>(to);
973 if (!flag && to_ == to_pn) {
974 _push_sibling(from_n, to_pn ^ label_n, label_n);
975 m_ninfo[to_].child = 0;
979 n_.value = value_type(0);
981 n_.check =
static_cast<int>(from_n);
986 return flag ? base ^ label_n : to_pn;
990 template <
typename T>
993 template <
typename T>
995 std::ifstream fin(filename, std::ios::in | std::ios::binary);
996 throw_if_io_fail(fin);
1000 template <
typename T>
1005 template <
typename T>
1008 template <
typename T>
1011 template <
typename T>
1015 template <
typename T>
1018 template <
typename T>
1020 if (
this == &other) {
1027 d = std::make_unique<DATriePrivate<T>>(*other.d);
1032 template <
typename T>
1038 template <
typename T>
1040 std::ofstream fout(filename, std::ios::out | std::ios::binary);
1041 throw_if_io_fail(fout);
1045 template <
typename T>
1050 template <
typename T>
1051 void DATrie<T>::set(
const char *key,
size_t len, value_type val) {
1052 d->update(key, len, [val](value_type) {
return val; });
1055 template <
typename T>
1057 DATrie<T>::updater_type updater) {
1058 d->update(key, len, updater);
1061 template <
typename T>
1063 return d->num_keys();
1066 template <
typename T>
1068 return d->foreach([](value_type,
size_t, position_type) {
return false; });
1071 template <
typename T>
1073 position_type _pos)
const {
1076 if (d->_find(prefix, from, pos, size) ==
1081 return d->foreach(func, from);
1084 template <
typename T>
1087 return d->foreach(func, from);
1090 template <
typename T>
1095 template <
typename T>
1097 d->dump(data, size);
1100 template <
typename T>
1101 void DATrie<T>::dump(std::vector<
typename DATrie<T>::value_type> &data)
const {
1102 data.resize(size());
1103 d->dump(data.data(), data.size());
1106 template <
typename T>
1108 std::vector<std::tuple<
typename DATrie<T>::value_type,
size_t,
1109 typename DATrie<T>::position_type>> &data)
const {
1110 data.resize(size());
1111 d->dump(data.data(), data.size());
1114 template <
typename T>
1119 template <
typename T>
1124 template <
typename T>
1127 return decodeImpl<T>(exactMatchSearchRaw(key, len));
1130 template <
typename T>
1134 auto resultRaw = d->_find(key, npos, pos, len);
1141 template <
typename T>
1143 return isValid(exactMatchSearch(key));
1146 template <
typename T>
1148 position_type &from)
const {
1149 return decodeImpl<T>(traverseRaw(key, len, from));
1152 template <
typename T>
1154 position_type &from)
const {
1157 auto result = d->_find(key, npos, pos, len);
1158 from = npos.toInt();
1162 template <
typename T>
1167 template <
typename T>
1172 template <
typename T>
1174 typename DATriePrivate<T>::decoder_type d;
1176 return isNoPathRaw(d.result);
1179 template <
typename T>
1181 typename DATriePrivate<T>::decoder_type d;
1183 return isNoValueRaw(d.result);
1186 template <
typename T>
1188 typename DATriePrivate<T>::decoder_type d;
1190 return isValidRaw(d.result);
1193 template <
typename T>
1198 template <
typename T>
1203 template <
typename T>
1205 return !(isNoPathRaw(v) || isNoValueRaw(v));
1208 template <
typename T>
1213 template <
typename T>
1218 template <
typename T>
1220 return decodeImpl<T>(raw);
1223 template <
typename T>
1236 return d->m_tail.size() + (d->m_tail0.size() *
sizeof(int)) +
1237 (
sizeof(
typename decltype(d->m_array)::value_type) *
1238 d->m_array.size()) +
1239 (
sizeof(
typename decltype(d->m_block)::value_type) *
1240 d->m_block.size()) +
1241 (
sizeof(
typename decltype(d->m_ninfo)::value_type) *
Provide a DATrie implementation.
This is a trie based on cedar<www.tkl.iis.u-tokyo.ac.jp/~ynaga/cedar/>.