1#include <algorithm>
2#include <stdexcept>
3
4#include "trie.h"
5
6namespace marisa {
7
8Trie::Trie()
9    : louds_(), labels_(), terminal_flags_(), link_flags_(), links_(),
10      trie_(), tail_(), num_first_branches_(0), num_keys_(0) {}
11
12void 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
21void Trie::map(const void *ptr, std::size_t size) {
22  Mapper mapper(ptr, size);
23  map(mapper);
24}
25
26void 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
45void Trie::load(const char *filename,
46    long offset, int whence) {
47  Reader reader;
48  reader.open(filename, offset, whence);
49  read(reader);
50}
51
52void Trie::fread(std::FILE *file) {
53  Reader reader(file);
54  read(reader);
55}
56
57void Trie::read(int fd) {
58  Reader reader(fd);
59  read(reader);
60}
61
62void Trie::read(std::istream &stream) {
63  Reader reader(&stream);
64  read(reader);
65}
66
67void 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
86void 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
93void Trie::fwrite(std::FILE *file) const {
94  Writer writer(file);
95  write(writer);
96}
97
98void Trie::write(int fd) const {
99  Writer writer(fd);
100  write(writer);
101}
102
103void Trie::write(std::ostream &stream) const {
104  Writer writer(&stream);
105  write(writer);
106}
107
108void 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
122std::size_t Trie::num_tries() const {
123  return has_trie() ? (trie_->num_tries() + 1) : (louds_.empty() ? 0 : 1);
124}
125
126std::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
137std::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
144void Trie::clear() {
145  Trie().swap(this);
146}
147
148void 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