1 #include <algorithm>
2 #include <stdexcept>
3
4 #include "trie.h"
5
6 namespace marisa {
7
Trie()8 Trie::Trie()
9 : louds_(), labels_(), terminal_flags_(), link_flags_(), links_(),
10 trie_(), tail_(), num_first_branches_(0), num_keys_(0) {}
11
mmap(Mapper * mapper,const char * filename,long offset,int whence)12 void Trie::mmap(Mapper *mapper, const char *filename,
13 long offset, int whence) {
14 MARISA_THROW_IF(mapper == NULL, MARISA_PARAM_ERROR);
15 Mapper temp_mapper;
16 temp_mapper.open(filename, offset, whence);
17 map(temp_mapper);
18 temp_mapper.swap(mapper);
19 }
20
map(const void * ptr,std::size_t size)21 void Trie::map(const void *ptr, std::size_t size) {
22 Mapper mapper(ptr, size);
23 map(mapper);
24 }
25
map(Mapper & mapper)26 void Trie::map(Mapper &mapper) {
27 Trie temp;
28 temp.louds_.map(mapper);
29 temp.labels_.map(mapper);
30 temp.terminal_flags_.map(mapper);
31 temp.link_flags_.map(mapper);
32 temp.links_.map(mapper);
33 temp.tail_.map(mapper);
34 mapper.map(&temp.num_first_branches_);
35 mapper.map(&temp.num_keys_);
36
37 if (temp.has_link() && !temp.has_tail()) {
38 temp.trie_.reset(new (std::nothrow) Trie);
39 MARISA_THROW_IF(!temp.has_trie(), MARISA_MEMORY_ERROR);
40 temp.trie_->map(mapper);
41 }
42 temp.swap(this);
43 }
44
load(const char * filename,long offset,int whence)45 void Trie::load(const char *filename,
46 long offset, int whence) {
47 Reader reader;
48 reader.open(filename, offset, whence);
49 read(reader);
50 }
51
fread(std::FILE * file)52 void Trie::fread(std::FILE *file) {
53 Reader reader(file);
54 read(reader);
55 }
56
read(int fd)57 void Trie::read(int fd) {
58 Reader reader(fd);
59 read(reader);
60 }
61
read(std::istream & stream)62 void Trie::read(std::istream &stream) {
63 Reader reader(&stream);
64 read(reader);
65 }
66
read(Reader & reader)67 void Trie::read(Reader &reader) {
68 Trie temp;
69 temp.louds_.read(reader);
70 temp.labels_.read(reader);
71 temp.terminal_flags_.read(reader);
72 temp.link_flags_.read(reader);
73 temp.links_.read(reader);
74 temp.tail_.read(reader);
75 reader.read(&temp.num_first_branches_);
76 reader.read(&temp.num_keys_);
77
78 if (temp.has_link() && !temp.has_tail()) {
79 temp.trie_.reset(new (std::nothrow) Trie);
80 MARISA_THROW_IF(!temp.has_trie(), MARISA_MEMORY_ERROR);
81 temp.trie_->read(reader);
82 }
83 temp.swap(this);
84 }
85
save(const char * filename,bool trunc_flag,long offset,int whence) const86 void Trie::save(const char *filename, bool trunc_flag,
87 long offset, int whence) const {
88 Writer writer;
89 writer.open(filename, trunc_flag, offset, whence);
90 write(writer);
91 }
92
fwrite(std::FILE * file) const93 void Trie::fwrite(std::FILE *file) const {
94 Writer writer(file);
95 write(writer);
96 }
97
write(int fd) const98 void Trie::write(int fd) const {
99 Writer writer(fd);
100 write(writer);
101 }
102
write(std::ostream & stream) const103 void Trie::write(std::ostream &stream) const {
104 Writer writer(&stream);
105 write(writer);
106 }
107
write(Writer & writer) const108 void Trie::write(Writer &writer) const {
109 louds_.write(writer);
110 labels_.write(writer);
111 terminal_flags_.write(writer);
112 link_flags_.write(writer);
113 links_.write(writer);
114 tail_.write(writer);
115 writer.write(num_first_branches_);
116 writer.write(num_keys_);
117 if (has_trie()) {
118 trie_->write(writer);
119 }
120 }
121
num_tries() const122 std::size_t Trie::num_tries() const {
123 return has_trie() ? (trie_->num_tries() + 1) : (louds_.empty() ? 0 : 1);
124 }
125
num_nodes() const126 std::size_t Trie::num_nodes() const {
127 if (louds_.empty()) {
128 return 0;
129 }
130 std::size_t num_nodes = (louds_.size() / 2) - 1;
131 if (has_trie()) {
132 num_nodes += trie_->num_nodes();
133 }
134 return num_nodes;
135 }
136
total_size() const137 std::size_t Trie::total_size() const {
138 return louds_.total_size() + labels_.total_size()
139 + terminal_flags_.total_size() + link_flags_.total_size()
140 + links_.total_size() + (has_trie() ? trie_->total_size() : 0)
141 + tail_.total_size() + sizeof(num_first_branches_) + sizeof(num_keys_);
142 }
143
clear()144 void Trie::clear() {
145 Trie().swap(this);
146 }
147
swap(Trie * rhs)148 void Trie::swap(Trie *rhs) {
149 MARISA_THROW_IF(rhs == NULL, MARISA_PARAM_ERROR);
150 louds_.swap(&rhs->louds_);
151 labels_.swap(&rhs->labels_);
152 terminal_flags_.swap(&rhs->terminal_flags_);
153 link_flags_.swap(&rhs->link_flags_);
154 links_.swap(&rhs->links_);
155 Swap(&trie_, &rhs->trie_);
156 tail_.swap(&rhs->tail_);
157 Swap(&num_first_branches_, &rhs->num_first_branches_);
158 Swap(&num_keys_, &rhs->num_keys_);
159 }
160
161 } // namespace marisa
162