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