| #include <algorithm> |
| #include <stdexcept> |
| |
| #include "trie.h" |
| |
| namespace marisa { |
| |
| Trie::Trie() |
| : louds_(), labels_(), terminal_flags_(), link_flags_(), links_(), |
| trie_(), tail_(), num_first_branches_(0), num_keys_(0) {} |
| |
| void Trie::mmap(Mapper *mapper, const char *filename, |
| long offset, int whence) { |
| MARISA_THROW_IF(mapper == NULL, MARISA_PARAM_ERROR); |
| Mapper temp_mapper; |
| temp_mapper.open(filename, offset, whence); |
| map(temp_mapper); |
| temp_mapper.swap(mapper); |
| } |
| |
| void Trie::map(const void *ptr, std::size_t size) { |
| Mapper mapper(ptr, size); |
| map(mapper); |
| } |
| |
| void Trie::map(Mapper &mapper) { |
| Trie temp; |
| temp.louds_.map(mapper); |
| temp.labels_.map(mapper); |
| temp.terminal_flags_.map(mapper); |
| temp.link_flags_.map(mapper); |
| temp.links_.map(mapper); |
| temp.tail_.map(mapper); |
| mapper.map(&temp.num_first_branches_); |
| mapper.map(&temp.num_keys_); |
| |
| if (temp.has_link() && !temp.has_tail()) { |
| temp.trie_.reset(new (std::nothrow) Trie); |
| MARISA_THROW_IF(!temp.has_trie(), MARISA_MEMORY_ERROR); |
| temp.trie_->map(mapper); |
| } |
| temp.swap(this); |
| } |
| |
| void Trie::load(const char *filename, |
| long offset, int whence) { |
| Reader reader; |
| reader.open(filename, offset, whence); |
| read(reader); |
| } |
| |
| void Trie::fread(std::FILE *file) { |
| Reader reader(file); |
| read(reader); |
| } |
| |
| void Trie::read(int fd) { |
| Reader reader(fd); |
| read(reader); |
| } |
| |
| void Trie::read(std::istream &stream) { |
| Reader reader(&stream); |
| read(reader); |
| } |
| |
| void Trie::read(Reader &reader) { |
| Trie temp; |
| temp.louds_.read(reader); |
| temp.labels_.read(reader); |
| temp.terminal_flags_.read(reader); |
| temp.link_flags_.read(reader); |
| temp.links_.read(reader); |
| temp.tail_.read(reader); |
| reader.read(&temp.num_first_branches_); |
| reader.read(&temp.num_keys_); |
| |
| if (temp.has_link() && !temp.has_tail()) { |
| temp.trie_.reset(new (std::nothrow) Trie); |
| MARISA_THROW_IF(!temp.has_trie(), MARISA_MEMORY_ERROR); |
| temp.trie_->read(reader); |
| } |
| temp.swap(this); |
| } |
| |
| void Trie::save(const char *filename, bool trunc_flag, |
| long offset, int whence) const { |
| Writer writer; |
| writer.open(filename, trunc_flag, offset, whence); |
| write(writer); |
| } |
| |
| void Trie::fwrite(std::FILE *file) const { |
| Writer writer(file); |
| write(writer); |
| } |
| |
| void Trie::write(int fd) const { |
| Writer writer(fd); |
| write(writer); |
| } |
| |
| void Trie::write(std::ostream &stream) const { |
| Writer writer(&stream); |
| write(writer); |
| } |
| |
| void Trie::write(Writer &writer) const { |
| louds_.write(writer); |
| labels_.write(writer); |
| terminal_flags_.write(writer); |
| link_flags_.write(writer); |
| links_.write(writer); |
| tail_.write(writer); |
| writer.write(num_first_branches_); |
| writer.write(num_keys_); |
| if (has_trie()) { |
| trie_->write(writer); |
| } |
| } |
| |
| std::size_t Trie::num_tries() const { |
| return has_trie() ? (trie_->num_tries() + 1) : (louds_.empty() ? 0 : 1); |
| } |
| |
| std::size_t Trie::num_nodes() const { |
| if (louds_.empty()) { |
| return 0; |
| } |
| std::size_t num_nodes = (louds_.size() / 2) - 1; |
| if (has_trie()) { |
| num_nodes += trie_->num_nodes(); |
| } |
| return num_nodes; |
| } |
| |
| std::size_t Trie::total_size() const { |
| return louds_.total_size() + labels_.total_size() |
| + terminal_flags_.total_size() + link_flags_.total_size() |
| + links_.total_size() + (has_trie() ? trie_->total_size() : 0) |
| + tail_.total_size() + sizeof(num_first_branches_) + sizeof(num_keys_); |
| } |
| |
| void Trie::clear() { |
| Trie().swap(this); |
| } |
| |
| void Trie::swap(Trie *rhs) { |
| MARISA_THROW_IF(rhs == NULL, MARISA_PARAM_ERROR); |
| louds_.swap(&rhs->louds_); |
| labels_.swap(&rhs->labels_); |
| terminal_flags_.swap(&rhs->terminal_flags_); |
| link_flags_.swap(&rhs->link_flags_); |
| links_.swap(&rhs->links_); |
| Swap(&trie_, &rhs->trie_); |
| tail_.swap(&rhs->tail_); |
| Swap(&num_first_branches_, &rhs->num_first_branches_); |
| Swap(&num_keys_, &rhs->num_keys_); |
| } |
| |
| } // namespace marisa |