File Coverage

darts.h
Criterion Covered Total %
statement 0 160 0.0
branch 0 162 0.0
condition n/a
subroutine n/a
pod n/a
total 0 322 0.0


line stmt bran cond sub pod time code
1             /*
2             Darts -- Double-ARray Trie System
3              
4             $Id: darts.h,v 0.10 2022/06/14 02:05:42 dankogai Exp $;
5              
6             Copyright(C) 2001-2007 Taku Kudo
7             */
8             #ifndef DARTS_H_
9             #define DARTS_H_
10              
11             #define DARTS_VERSION "0.32"
12             #include
13             #include
14             #include
15              
16             #ifdef HAVE_ZLIB_H
17             namespace zlib {
18             #include
19             }
20             #define SH(p)((unsigned short)(unsigned char)((p)[0]) | ((unsigned short)(unsigned char)((p)[1]) << 8))
21             #define LG(p)((unsigned long)(SH(p)) |((unsigned long)(SH((p)+2)) << 16))
22             #endif
23              
24             namespace Darts {
25              
26 0 0         template inline T _max(T x, T y) { return(x > y) ? x : y; }
    0          
27 0           template inline T* _resize(T* ptr, size_t n, size_t l, T v) {
28 0 0         T *tmp = new T[l];
29 0 0         for (size_t i = 0; i < n; ++i) tmp[i] = ptr[i];
    0          
30 0 0         for (size_t i = n; i < l; ++i) tmp[i] = v;
    0          
31 0 0         delete [] ptr;
    0          
32 0           return tmp;
33             }
34              
35             template
36             class Length {
37             public: size_t operator()(const T *key) const
38             { size_t i; for (i = 0; key[i] != static_cast(0); ++i) {} return i; }
39             };
40              
41             template <> class Length {
42 0           public: size_t operator()(const char *key) const
43 0           { return std::strlen(key); }
44             };
45              
46             template
47             class array_type_, class array_u_type_,
48             class length_func_ = Length >
49             class DoubleArrayImpl {
50             public:
51             typedef array_type_ value_type;
52             typedef node_type_ key_type;
53             typedef array_type_ result_type; // for compatibility
54              
55             struct result_pair_type {
56             value_type value;
57             size_t length;
58             };
59              
60 0           explicit DoubleArrayImpl(): array_(0), used_(0),
61             size_(0), alloc_size_(0),
62 0           no_delete_(0), error_(0) {}
63 0 0         virtual ~DoubleArrayImpl() { clear(); }
64              
65             void set_result(value_type *x, value_type r, size_t) const {
66             *x = r;
67             }
68              
69 0           void set_result(result_pair_type *x, value_type r, size_t l) const {
70 0           x->value = r;
71 0           x->length = l;
72 0           }
73              
74             void set_array(void *ptr, size_t size = 0) {
75             clear();
76             array_ = reinterpret_cast(ptr);
77             no_delete_ = true;
78             size_ = size;
79             }
80              
81             const void *array() const {
82             return const_cast(reinterpret_cast(array_));
83             }
84              
85 0           void clear() {
86 0 0         if (!no_delete_)
87 0 0         delete [] array_;
88 0 0         delete [] used_;
89 0           array_ = 0;
90 0           used_ = 0;
91 0           alloc_size_ = 0;
92 0           size_ = 0;
93 0           no_delete_ = false;
94 0           }
95              
96             size_t unit_size() const { return sizeof(unit_t); }
97             size_t size() const { return size_; }
98             size_t total_size() const { return size_ * sizeof(unit_t); }
99              
100             size_t nonzero_size() const {
101             size_t result = 0;
102             for (size_t i = 0; i < size_; ++i)
103             if (array_[i].check) ++result;
104             return result;
105             }
106              
107 0           int build(size_t key_size,
108             const key_type **key,
109             const size_t *length = 0,
110             const value_type *value = 0,
111             int (*progress_func)(size_t, size_t) = 0) {
112 0 0         if (!key_size || !key) return 0;
    0          
113              
114 0           progress_func_ = progress_func;
115 0           key_ = key;
116 0           length_ = length;
117 0           key_size_ = key_size;
118 0           value_ = value;
119 0           progress_ = 0;
120              
121 0 0         resize(8192);
122              
123 0           array_[0].base = 1;
124 0           next_check_pos_ = 0;
125              
126             node_t root_node;
127 0           root_node.left = 0;
128 0           root_node.right = key_size;
129 0           root_node.depth = 0;
130              
131 0 0         std::vector siblings;
    0          
132 0 0         fetch(root_node, siblings);
133 0 0         insert(siblings);
134              
135 0           size_ += (1 << 8 * sizeof(key_type)) + 1;
136 0 0         if (size_ >= alloc_size_) resize(size_);
    0          
137              
138 0 0         delete [] used_;
139 0           used_ = 0;
140              
141 0           return error_;
142             }
143              
144 0           int open(const char *file,
145             const char *mode = "rb",
146             size_t offset = 0,
147             size_t size = 0) {
148 0           std::FILE *fp = std::fopen(file, mode);
149 0 0         if (!fp) return -1;
150 0 0         if (std::fseek(fp, offset, SEEK_SET) != 0) return -1;
151              
152 0 0         if (!size) {
153 0 0         if (std::fseek(fp, 0L, SEEK_END) != 0) return -1;
154 0           size = std::ftell(fp);
155 0 0         if (std::fseek(fp, offset, SEEK_SET) != 0) return -1;
156             }
157              
158 0           clear();
159              
160 0           size_ = size;
161 0           size_ /= sizeof(unit_t);
162 0 0         array_ = new unit_t[size_];
163 0 0         if (size_ != std::fread(reinterpret_cast(array_),
164 0           sizeof(unit_t), size_, fp)) return -1;
165 0           std::fclose(fp);
166              
167 0           return 0;
168             }
169              
170             int save(const char *file,
171             const char *mode = "wb",
172             size_t offset = 0) {
173             if (!size_) return -1;
174             std::FILE *fp = std::fopen(file, mode);
175             if (!fp) return -1;
176             if (size_ != std::fwrite(reinterpret_cast(array_),
177             sizeof(unit_t), size_, fp))
178             return -1;
179             std::fclose(fp);
180             return 0;
181             }
182              
183             #ifdef HAVE_ZLIB_H
184             int gzopen(const char *file,
185             const char *mode = "rb",
186             size_t offset = 0,
187             size_t size = 0) {
188             std::FILE *fp = std::fopen(file, mode);
189             if (!fp) return -1;
190             clear();
191              
192             size_ = size;
193             if (!size_) {
194             if (-1L != static_cast(std::fseek(fp, -8, SEEK_END))) {
195             char buf[8];
196             if (std::fread(static_cast(buf),
197             1, 8, fp) != sizeof(buf)) {
198             std::fclose(fp);
199             return -1;
200             }
201             size_ = LG(buf+4);
202             size_ /= sizeof(unit_t);
203             }
204             }
205             std::fclose(fp);
206              
207             if (!size_) return -1;
208              
209             zlib::gzFile gzfp = zlib::gzopen(file, mode);
210             if (!gzfp) return -1;
211             array_ = new unit_t[size_];
212             if (zlib::gzseek(gzfp, offset, SEEK_SET) != 0) return -1;
213             zlib::gzread(gzfp, reinterpret_cast(array_),
214             sizeof(unit_t) * size_);
215             zlib::gzclose(gzfp);
216             return 0;
217             }
218              
219             int gzsave(const char *file, const char *mode = "wb",
220             size_t offset = 0) {
221             zlib::gzFile gzfp = zlib::gzopen(file, mode);
222             if (!gzfp) return -1;
223             zlib::gzwrite(gzfp, reinterpret_cast(array_),
224             sizeof(unit_t) * size_);
225             zlib::gzclose(gzfp);
226             return 0;
227             }
228             #endif
229              
230             template
231             inline void exactMatchSearch(const key_type *key,
232             T & result,
233             size_t len = 0,
234             size_t node_pos = 0) const {
235             result = exactMatchSearch (key, len, node_pos);
236             return;
237             }
238              
239             template
240             inline T exactMatchSearch(const key_type *key,
241             size_t len = 0,
242             size_t node_pos = 0) const {
243             if (!len) len = length_func_()(key);
244              
245             T result;
246             set_result(&result, -1, 0);
247              
248             register array_type_ b = array_[node_pos].base;
249             register array_u_type_ p;
250              
251             for (register size_t i = 0; i < len; ++i) {
252             p = b +(node_u_type_)(key[i]) + 1;
253             if (static_cast(b) == array_[p].check)
254             b = array_[p].base;
255             else
256             return result;
257             }
258              
259             p = b;
260             array_type_ n = array_[p].base;
261             if (static_cast(b) == array_[p].check && n < 0)
262             set_result(&result, -n-1, len);
263              
264             return result;
265             }
266              
267             template
268 0           size_t commonPrefixSearch(const key_type *key,
269             T* result,
270             size_t result_len,
271             size_t len = 0,
272             size_t node_pos = 0) const {
273 0 0         if (!len) len = length_func_()(key);
274              
275 0           register array_type_ b = array_[node_pos].base;
276 0           register size_t num = 0;
277             register array_type_ n;
278             register array_u_type_ p;
279              
280 0 0         for (register size_t i = 0; i < len; ++i) {
281 0           p = b; // + 0;
282 0           n = array_[p].base;
283 0 0         if ((array_u_type_) b == array_[p].check && n < 0) {
    0          
284             // result[num] = -n-1;
285 0 0         if (num < result_len) set_result(&result[num], -n-1, i);
286 0           ++num;
287             }
288              
289 0           p = b +(node_u_type_)(key[i]) + 1;
290 0 0         if ((array_u_type_) b == array_[p].check)
291 0           b = array_[p].base;
292             else
293 0           return num;
294             }
295              
296 0           p = b;
297 0           n = array_[p].base;
298              
299 0 0         if ((array_u_type_)b == array_[p].check && n < 0) {
    0          
300 0 0         if (num < result_len) set_result(&result[num], -n-1, len);
301 0           ++num;
302             }
303              
304 0           return num;
305             }
306              
307             value_type traverse(const key_type *key,
308             size_t &node_pos,
309             size_t &key_pos,
310             size_t len = 0) const {
311             if (!len) len = length_func_()(key);
312              
313             register array_type_ b = array_[node_pos].base;
314             register array_u_type_ p;
315              
316             for (; key_pos < len; ++key_pos) {
317             p = b + (node_u_type_)(key[key_pos]) + 1;
318             if (static_cast(b) == array_[p].check) {
319             node_pos = p;
320             b = array_[p].base;
321             } else {
322             return -2; // no node
323             }
324             }
325              
326             p = b;
327             array_type_ n = array_[p].base;
328             if (static_cast(b) == array_[p].check && n < 0)
329             return -n-1;
330              
331             return -1; // found, but no value
332             }
333              
334             private:
335             struct node_t {
336             array_u_type_ code;
337             size_t depth;
338             size_t left;
339             size_t right;
340             };
341              
342             struct unit_t {
343             array_type_ base;
344             array_u_type_ check;
345             };
346              
347             unit_t *array_;
348             unsigned char *used_;
349             size_t size_;
350             size_t alloc_size_;
351             size_t key_size_;
352             const node_type_ **key_;
353             const size_t *length_;
354             const array_type_ *value_;
355             size_t progress_;
356             size_t next_check_pos_;
357             bool no_delete_;
358             int error_;
359             int (*progress_func_)(size_t, size_t);
360              
361 0           size_t resize(const size_t new_size) {
362             unit_t tmp;
363 0           tmp.base = 0;
364 0           tmp.check = 0;
365 0 0         array_ = _resize(array_, alloc_size_, new_size, tmp);
366 0 0         used_ = _resize(used_, alloc_size_, new_size,
367             static_cast(0));
368 0           alloc_size_ = new_size;
369 0           return new_size;
370             }
371              
372 0           size_t fetch(const node_t &parent, std::vector &siblings) {
373 0 0         if (error_ < 0) return 0;
374              
375 0           array_u_type_ prev = 0;
376              
377 0 0         for (size_t i = parent.left; i < parent.right; ++i) {
378 0 0         if ((length_ ? length_[i] : length_func_()(key_[i])) < parent.depth)
    0          
    0          
379 0           continue;
380              
381 0           const node_u_type_ *tmp = reinterpret_cast(key_[i]);
382              
383 0           array_u_type_ cur = 0;
384 0 0         if ((length_ ? length_[i] : length_func_()(key_[i])) != parent.depth)
    0          
    0          
385 0           cur = (array_u_type_)tmp[parent.depth] + 1;
386              
387 0 0         if (prev > cur) {
388 0           error_ = -3;
389 0           return 0;
390             }
391              
392 0 0         if (cur != prev || siblings.empty()) {
    0          
    0          
393             node_t tmp_node;
394 0           tmp_node.depth = parent.depth + 1;
395 0           tmp_node.code = cur;
396 0           tmp_node.left = i;
397 0 0         if (!siblings.empty()) siblings[siblings.size()-1].right = i;
    0          
398              
399 0 0         siblings.push_back(tmp_node);
400             }
401              
402 0           prev = cur;
403             }
404              
405 0 0         if (!siblings.empty())
406 0           siblings[siblings.size()-1].right = parent.right;
407              
408 0           return siblings.size();
409             }
410              
411 0           size_t insert(const std::vector &siblings) {
412 0 0         if (error_ < 0) return 0;
413              
414 0           size_t begin = 0;
415 0           size_t pos = _max((size_t)siblings[0].code + 1, next_check_pos_) - 1;
416 0           size_t nonzero_num = 0;
417 0           int first = 0;
418              
419 0 0         if (alloc_size_ <= pos) resize(pos + 1);
420              
421 0           while (true) {
422             next:
423 0           ++pos;
424              
425 0 0         if (alloc_size_ <= pos) resize(pos + 1);
426              
427 0 0         if (array_[pos].check) {
428 0           ++nonzero_num;
429 0           continue;
430 0 0         } else if (!first) {
431 0           next_check_pos_ = pos;
432 0           first = 1;
433             }
434              
435 0           begin = pos - siblings[0].code;
436 0 0         if (alloc_size_ <= (begin + siblings[siblings.size()-1].code))
437 0           resize(static_cast(alloc_size_ *
438 0           _max(1.05, 1.0 * key_size_ / progress_)));
439              
440 0 0         if (used_[begin]) continue;
441              
442 0 0         for (size_t i = 1; i < siblings.size(); ++i)
443 0 0         if (array_[begin + siblings[i].code].check != 0) goto next;
444              
445 0           break;
446             }
447              
448             // -- Simple heuristics --
449             // if the percentage of non-empty contents in check between the index
450             // 'next_check_pos' and 'check' is greater than some constant
451             // value(e.g. 0.9),
452             // new 'next_check_pos' index is written by 'check'.
453 0 0         if (1.0 * nonzero_num/(pos - next_check_pos_ + 1) >= 0.95)
454 0           next_check_pos_ = pos;
455              
456 0           used_[begin] = 1;
457 0           size_ = _max(size_,
458             begin +
459 0           static_cast(siblings[siblings.size() - 1].code + 1));
460              
461 0 0         for (size_t i = 0; i < siblings.size(); ++i)
462 0           array_[begin + siblings[i].code].check = begin;
463              
464 0 0         for (size_t i = 0; i < siblings.size(); ++i) {
465 0 0         std::vector new_siblings;
466              
467 0 0         if (!fetch(siblings[i], new_siblings)) {
    0          
468 0 0         array_[begin + siblings[i].code].base =
469 0           value_ ?
470 0           static_cast(-value_[siblings[i].left]-1) :
471 0           static_cast(-siblings[i].left-1);
472              
473 0 0         if (value_ && (array_type_)(-value_[siblings[i].left]-1) >= 0) {
    0          
    0          
474 0           error_ = -2;
475 0           return 0;
476             }
477              
478 0           ++progress_;
479 0 0         if (progress_func_)(*progress_func_)(progress_, key_size_);
    0          
480              
481             } else {
482 0 0         size_t h = insert(new_siblings);
483 0 0         array_[begin + siblings[i].code].base = h;
    0          
484             }
485             }
486              
487 0           return begin;
488             }
489              
490             };
491              
492             #if 4 == 2
493             typedef Darts::DoubleArrayImpl
494             unsigned short> DoubleArray;
495             #define DARTS_ARRAY_SIZE_IS_DEFINED 1
496             #endif
497              
498             #if 4 == 4 && !defined(DARTS_ARRAY_SIZE_IS_DEFINED)
499             typedef Darts::DoubleArrayImpl
500             unsigned int> DoubleArray;
501             #define DARTS_ARRAY_SIZE_IS_DEFINED 1
502             #endif
503              
504             #if 4 == 4 && !defined(DARTS_ARRAY_SIZE_IS_DEFINED)
505             typedef Darts::DoubleArrayImpl
506             unsigned long> DoubleArray;
507             #define DARTS_ARRAY_SIZE_IS_DEFINED 1
508             #endif
509              
510             #if 4 == 8 && !defined(DARTS_ARRAY_SIZE_IS_DEFINED)
511             typedef Darts::DoubleArrayImpl
512             unsigned long long> DoubleArray;
513             #endif
514             }
515             #endif