bool PredictiveCursor::ascending_next(Key *key) { while (!buf_.empty()) { const bool is_root = (buf_.back() & IS_ROOT_FLAG) == IS_ROOT_FLAG; const UInt32 node_id = buf_.back() & ~IS_ROOT_FLAG; buf_.pop_back(); const Node node = trie_->ith_node(node_id); if (!is_root && (node.sibling() != INVALID_LABEL)) { GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id ^ node.label() ^ node.sibling())); } if (node.is_terminal()) { Key temp_key; trie_->ith_key(node.key_id(), &temp_key); if (temp_key.length() >= min_length_) { if (cur_++ >= offset_) { *key = temp_key; return true; } } } else if (node.child() != INVALID_LABEL) { GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node.offset() ^ node.child())); } } return false; }
void reserve(UInt32 new_capacity) { if (new_capacity <= capacity()) { return; } else if ((new_capacity / 2) < capacity()) { if (capacity() < (MAX_UINT32 / 2)) { new_capacity = capacity() * 2; } else { new_capacity = MAX_UINT32; } } T *new_buf = reinterpret_cast<T *>( new (std::nothrow) char[sizeof(new_capacity) * new_capacity]); GRN_DAT_THROW_IF(MEMORY_ERROR, new_buf == NULL); for (UInt32 i = 0; i < size(); ++i) { new (&new_buf[i]) T(buf_[i]); } for (UInt32 i = 0; i < size(); ++i) { buf_[i].~T(); } T *old_buf = buf_; buf_ = new_buf; delete [] reinterpret_cast<char *>(old_buf); capacity_ = new_capacity; }
bool PredictiveCursor::descending_next(Key *key) { while (!buf_.empty()) { const bool post_order = (buf_.back() & POST_ORDER_FLAG) == POST_ORDER_FLAG; const UInt32 node_id = buf_.back() & ~POST_ORDER_FLAG; const Base base = trie_->ith_node(node_id).base(); if (post_order) { buf_.pop_back(); if (base.is_terminal()) { Key temp_key; trie_->ith_key(base.key_id(), &temp_key); if (temp_key.length() >= min_length_) { if (cur_++ >= offset_) { *key = temp_key; return true; } } } } else { buf_.back() |= POST_ORDER_FLAG; UInt16 label = trie_->ith_node(node_id).child(); while (label != INVALID_LABEL) { GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(base.offset() ^ label)); label = trie_->ith_node(base.offset() ^ label).sibling(); } } } return false; }
void KeyCursor::open(const Trie &trie, const String &min_str, const String &max_str, UInt32 offset, UInt32 limit, UInt32 flags) { GRN_DAT_THROW_IF(PARAM_ERROR, (min_str.ptr() == NULL) && (min_str.length() != 0)); GRN_DAT_THROW_IF(PARAM_ERROR, (max_str.ptr() == NULL) && (max_str.length() != 0)); flags = fix_flags(flags); KeyCursor new_cursor(trie, offset, limit, flags); new_cursor.init(min_str, max_str); new_cursor.swap(this); }
UInt32 PredictiveCursor::fix_flags(UInt32 flags) const { const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) && (cursor_type != PREDICTIVE_CURSOR)); flags |= PREDICTIVE_CURSOR; const UInt32 cursor_order = flags & CURSOR_ORDER_MASK; GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_order != 0) && (cursor_order != ASCENDING_CURSOR) && (cursor_order != DESCENDING_CURSOR)); if (cursor_order == 0) { flags |= ASCENDING_CURSOR; } const UInt32 cursor_options = flags & CURSOR_OPTIONS_MASK; GRN_DAT_THROW_IF(PARAM_ERROR, cursor_options & ~(EXCEPT_EXACT_MATCH)); return flags; }
UInt32 IdCursor::fix_flags(UInt32 flags) const { const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) && (cursor_type != ID_RANGE_CURSOR)); flags |= ID_RANGE_CURSOR; const UInt32 cursor_order = flags & CURSOR_ORDER_MASK; GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_order != 0) && (cursor_order != ASCENDING_CURSOR) && (cursor_order != DESCENDING_CURSOR)); if (cursor_order == 0) { flags |= ASCENDING_CURSOR; } const UInt32 cursor_options = flags & CURSOR_OPTIONS_MASK; GRN_DAT_THROW_IF(PARAM_ERROR, cursor_options & ~(EXCEPT_LOWER_BOUND | EXCEPT_UPPER_BOUND)); return flags; }
void PredictiveCursor::open(const Trie &trie, const String &str, UInt32 offset, UInt32 limit, UInt32 flags) { GRN_DAT_THROW_IF(PARAM_ERROR, (str.ptr() == NULL) && (str.length() != 0)); flags = fix_flags(flags); PredictiveCursor new_cursor(trie, offset, limit, flags); new_cursor.init(str); new_cursor.swap(this); }
void PredictiveCursor::init(const String &str) { if (limit_ == 0) { return; } min_length_ = str.length(); if ((flags_ & EXCEPT_EXACT_MATCH) == EXCEPT_EXACT_MATCH) { ++min_length_; } end_ = (offset_ > (UINT32_MAX - limit_)) ? UINT32_MAX : (offset_ + limit_); UInt32 node_id = ROOT_NODE_ID; for (UInt32 i = 0; i < str.length(); ++i) { const Base base = trie_->ith_node(node_id).base(); if (base.is_terminal()) { if (offset_ == 0) { Key key; trie_->ith_key(base.key_id(), &key); if ((key.length() >= str.length()) && (key.str().substr(0, str.length()).compare(str, i) == 0)) { if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { node_id |= IS_ROOT_FLAG; } GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id)); } } return; } node_id = base.offset() ^ str[i]; if (trie_->ith_node(node_id).label() != str[i]) { return; } } if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { node_id |= IS_ROOT_FLAG; } GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id)); }
void IdCursor::open(const Trie &trie, const String &min_str, const String &max_str, UInt32 offset, UInt32 limit, UInt32 flags) { UInt32 min_id = INVALID_KEY_ID; if (min_str.ptr() != NULL) { UInt32 key_pos; GRN_DAT_THROW_IF(PARAM_ERROR, !trie.search(min_str.ptr(), min_str.length(), &key_pos)); min_id = trie.get_key(key_pos).id(); } UInt32 max_id = INVALID_KEY_ID; if (max_str.ptr() != NULL) { UInt32 key_pos; GRN_DAT_THROW_IF(PARAM_ERROR, !trie.search(max_str.ptr(), max_str.length(), &key_pos)); max_id = trie.get_key(key_pos).id(); } open(trie, min_id, max_id, offset, limit, flags); }
Cursor *CursorFactory::open(const Trie &trie, const void *min_ptr, UInt32 min_length, const void *max_ptr, UInt32 max_length, UInt32 offset, UInt32 limit, UInt32 flags) { GRN_DAT_THROW_IF(PARAM_ERROR, &trie == NULL); const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; switch (cursor_type) { case ID_RANGE_CURSOR: { IdCursor *cursor = new (std::nothrow) IdCursor; GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); try { cursor->open(trie, String(min_ptr, min_length), String(max_ptr, max_length), offset, limit, flags); } catch (...) { delete cursor; throw; } return cursor; } case KEY_RANGE_CURSOR: { KeyCursor *cursor = new (std::nothrow) KeyCursor; GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); try { cursor->open(trie, String(min_ptr, min_length), String(max_ptr, max_length), offset, limit, flags); } catch (...) { delete cursor; throw; } return cursor; } case PREFIX_CURSOR: { PrefixCursor *cursor = new (std::nothrow) PrefixCursor; GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); try { cursor->open(trie, String(max_ptr, max_length), min_length, offset, limit, flags); } catch (...) { delete cursor; throw; } return cursor; } case PREDICTIVE_CURSOR: { PredictiveCursor *cursor = new (std::nothrow) PredictiveCursor; GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); try { cursor->open(trie, String(min_ptr, min_length), offset, limit, flags); } catch (...) { delete cursor; throw; } return cursor; } default: { GRN_DAT_THROW(PARAM_ERROR, "unknown cursor type"); } } }