• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <new>
2 
3 #include "marisa/keyset.h"
4 
5 namespace marisa {
6 
Keyset()7 Keyset::Keyset()
8     : base_blocks_(), base_blocks_size_(0), base_blocks_capacity_(0),
9       extra_blocks_(), extra_blocks_size_(0), extra_blocks_capacity_(0),
10       key_blocks_(), key_blocks_size_(0), key_blocks_capacity_(0),
11       ptr_(NULL), avail_(0), size_(0), total_length_(0) {}
12 
push_back(const Key & key)13 void Keyset::push_back(const Key &key) {
14   MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
15 
16   char * const key_ptr = reserve(key.length());
17   for (std::size_t i = 0; i < key.length(); ++i) {
18     key_ptr[i] = key[i];
19   }
20 
21   Key &new_key = key_blocks_[size_ / KEY_BLOCK_SIZE][size_ % KEY_BLOCK_SIZE];
22   new_key.set_str(key_ptr, key.length());
23   new_key.set_id(key.id());
24   ++size_;
25   total_length_ += new_key.length();
26 }
27 
push_back(const Key & key,char end_marker)28 void Keyset::push_back(const Key &key, char end_marker) {
29   MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
30 
31   if ((size_ / KEY_BLOCK_SIZE) == key_blocks_size_) {
32     append_key_block();
33   }
34 
35   char * const key_ptr = reserve(key.length() + 1);
36   for (std::size_t i = 0; i < key.length(); ++i) {
37     key_ptr[i] = key[i];
38   }
39   key_ptr[key.length()] = end_marker;
40 
41   Key &new_key = key_blocks_[size_ / KEY_BLOCK_SIZE][size_ % KEY_BLOCK_SIZE];
42   new_key.set_str(key_ptr, key.length());
43   new_key.set_id(key.id());
44   ++size_;
45   total_length_ += new_key.length();
46 }
47 
push_back(const char * str)48 void Keyset::push_back(const char *str) {
49   MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
50   MARISA_THROW_IF(str == NULL, MARISA_NULL_ERROR);
51 
52   std::size_t length = 0;
53   while (str[length] != '\0') {
54     ++length;
55   }
56   push_back(str, length);
57 }
58 
push_back(const char * ptr,std::size_t length,float weight)59 void Keyset::push_back(const char *ptr, std::size_t length, float weight) {
60   MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
61   MARISA_THROW_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
62   MARISA_THROW_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
63 
64   char * const key_ptr = reserve(length);
65   for (std::size_t i = 0; i < length; ++i) {
66     key_ptr[i] = ptr[i];
67   }
68 
69   Key &key = key_blocks_[size_ / KEY_BLOCK_SIZE][size_ % KEY_BLOCK_SIZE];
70   key.set_str(key_ptr, length);
71   key.set_weight(weight);
72   ++size_;
73   total_length_ += length;
74 }
75 
reset()76 void Keyset::reset() {
77   base_blocks_size_ = 0;
78   extra_blocks_size_ = 0;
79   ptr_ = NULL;
80   avail_ = 0;
81   size_ = 0;
82   total_length_ = 0;
83 }
84 
clear()85 void Keyset::clear() {
86   Keyset().swap(*this);
87 }
88 
swap(Keyset & rhs)89 void Keyset::swap(Keyset &rhs) {
90   base_blocks_.swap(rhs.base_blocks_);
91   marisa::swap(base_blocks_size_, rhs.base_blocks_size_);
92   marisa::swap(base_blocks_capacity_, rhs.base_blocks_capacity_);
93   extra_blocks_.swap(rhs.extra_blocks_);
94   marisa::swap(extra_blocks_size_, rhs.extra_blocks_size_);
95   marisa::swap(extra_blocks_capacity_, rhs.extra_blocks_capacity_);
96   key_blocks_.swap(rhs.key_blocks_);
97   marisa::swap(key_blocks_size_, rhs.key_blocks_size_);
98   marisa::swap(key_blocks_capacity_, rhs.key_blocks_capacity_);
99   marisa::swap(ptr_, rhs.ptr_);
100   marisa::swap(avail_, rhs.avail_);
101   marisa::swap(size_, rhs.size_);
102   marisa::swap(total_length_, rhs.total_length_);
103 }
104 
reserve(std::size_t size)105 char *Keyset::reserve(std::size_t size) {
106   if ((size_ / KEY_BLOCK_SIZE) == key_blocks_size_) {
107     append_key_block();
108   }
109 
110   if (size > EXTRA_BLOCK_SIZE) {
111     append_extra_block(size);
112     return extra_blocks_[extra_blocks_size_ - 1].get();
113   } else {
114     if (size > avail_) {
115       append_base_block();
116     }
117     ptr_ += size;
118     avail_ -= size;
119     return ptr_ - size;
120   }
121 }
122 
append_base_block()123 void Keyset::append_base_block() {
124   if (base_blocks_size_ == base_blocks_capacity_) {
125     const std::size_t new_capacity =
126         (base_blocks_size_ != 0) ? (base_blocks_size_ * 2) : 1;
127     scoped_array<scoped_array<char> > new_blocks(
128         new (std::nothrow) scoped_array<char>[new_capacity]);
129     MARISA_THROW_IF(new_blocks.get() == NULL, MARISA_MEMORY_ERROR);
130     for (std::size_t i = 0; i < base_blocks_size_; ++i) {
131       base_blocks_[i].swap(new_blocks[i]);
132     }
133     base_blocks_.swap(new_blocks);
134     base_blocks_capacity_ = new_capacity;
135   }
136   if (base_blocks_[base_blocks_size_].get() == NULL) {
137     scoped_array<char> new_block(new (std::nothrow) char[BASE_BLOCK_SIZE]);
138     MARISA_THROW_IF(new_block.get() == NULL, MARISA_MEMORY_ERROR);
139     base_blocks_[base_blocks_size_].swap(new_block);
140   }
141   ptr_ = base_blocks_[base_blocks_size_++].get();
142   avail_ = BASE_BLOCK_SIZE;
143 }
144 
append_extra_block(std::size_t size)145 void Keyset::append_extra_block(std::size_t size) {
146   if (extra_blocks_size_ == extra_blocks_capacity_) {
147     const std::size_t new_capacity =
148         (extra_blocks_size_ != 0) ? (extra_blocks_size_ * 2) : 1;
149     scoped_array<scoped_array<char> > new_blocks(
150         new (std::nothrow) scoped_array<char>[new_capacity]);
151     MARISA_THROW_IF(new_blocks.get() == NULL, MARISA_MEMORY_ERROR);
152     for (std::size_t i = 0; i < extra_blocks_size_; ++i) {
153       extra_blocks_[i].swap(new_blocks[i]);
154     }
155     extra_blocks_.swap(new_blocks);
156     extra_blocks_capacity_ = new_capacity;
157   }
158   scoped_array<char> new_block(new (std::nothrow) char[size]);
159   MARISA_THROW_IF(new_block.get() == NULL, MARISA_MEMORY_ERROR);
160   extra_blocks_[extra_blocks_size_++].swap(new_block);
161 }
162 
append_key_block()163 void Keyset::append_key_block() {
164   if (key_blocks_size_ == key_blocks_capacity_) {
165     const std::size_t new_capacity =
166         (key_blocks_size_ != 0) ? (key_blocks_size_ * 2) : 1;
167     scoped_array<scoped_array<Key> > new_blocks(
168         new (std::nothrow) scoped_array<Key>[new_capacity]);
169     MARISA_THROW_IF(new_blocks.get() == NULL, MARISA_MEMORY_ERROR);
170     for (std::size_t i = 0; i < key_blocks_size_; ++i) {
171       key_blocks_[i].swap(new_blocks[i]);
172     }
173     key_blocks_.swap(new_blocks);
174     key_blocks_capacity_ = new_capacity;
175   }
176   scoped_array<Key> new_block(new (std::nothrow) Key[KEY_BLOCK_SIZE]);
177   MARISA_THROW_IF(new_block.get() == NULL, MARISA_MEMORY_ERROR);
178   key_blocks_[key_blocks_size_++].swap(new_block);
179 }
180 
181 }  // namespace marisa
182