summaryrefslogtreecommitdiffstats
path: root/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp')
-rw-r--r--storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp b/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp
new file mode 100644
index 00000000..de969839
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp
@@ -0,0 +1,184 @@
+/* -*- c-basic-offset: 2 -*- */
+/* Copyright(C) 2011 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+*/
+
+#include "id-cursor.hpp"
+
+#include <algorithm>
+
+#include "trie.hpp"
+
+namespace grn {
+namespace dat {
+
+IdCursor::IdCursor()
+ : trie_(NULL),
+ offset_(0),
+ limit_(MAX_UINT32),
+ flags_(ID_RANGE_CURSOR),
+ cur_(INVALID_KEY_ID),
+ end_(INVALID_KEY_ID),
+ count_(0) {}
+
+IdCursor::~IdCursor() {}
+
+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);
+}
+
+void IdCursor::open(const Trie &trie,
+ UInt32 min_id,
+ UInt32 max_id,
+ UInt32 offset,
+ UInt32 limit,
+ UInt32 flags) {
+ flags = fix_flags(flags);
+
+ IdCursor new_cursor(trie, offset, limit, flags);
+ new_cursor.init(min_id, max_id);
+ new_cursor.swap(this);
+}
+
+void IdCursor::close() {
+ IdCursor new_cursor;
+ new_cursor.swap(this);
+}
+
+const Key &IdCursor::next() {
+ if (count_ >= limit_) {
+ return Key::invalid_key();
+ }
+ while (cur_ != end_) {
+ const Key &key = trie_->ith_key(cur_);
+ if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) {
+ ++cur_;
+ } else {
+ --cur_;
+ }
+ if (key.is_valid()) {
+ ++count_;
+ return key;
+ }
+ }
+ return Key::invalid_key();
+}
+
+IdCursor::IdCursor(const Trie &trie,
+ UInt32 offset,
+ UInt32 limit,
+ UInt32 flags)
+ : trie_(&trie),
+ offset_(offset),
+ limit_(limit),
+ flags_(flags),
+ cur_(INVALID_KEY_ID),
+ end_(INVALID_KEY_ID),
+ count_(0) {}
+
+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 IdCursor::init(UInt32 min_id, UInt32 max_id) {
+ if (min_id == INVALID_KEY_ID) {
+ min_id = trie_->min_key_id();
+ } else if ((flags_ & EXCEPT_LOWER_BOUND) == EXCEPT_LOWER_BOUND) {
+ ++min_id;
+ }
+
+ if (max_id == INVALID_KEY_ID) {
+ max_id = trie_->max_key_id();
+ } else if ((flags_ & EXCEPT_UPPER_BOUND) == EXCEPT_UPPER_BOUND) {
+ --max_id;
+ }
+
+ if ((max_id < min_id) || ((max_id - min_id) < offset_)) {
+ return;
+ }
+
+ if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) {
+ cur_ = min_id;
+ end_ = max_id + 1;
+ for (UInt32 i = 0; (i < offset_) && (cur_ != end_); ++i) {
+ while (cur_ != end_) {
+ if (trie_->ith_key(cur_++).is_valid()) {
+ break;
+ }
+ }
+ }
+ } else {
+ cur_ = max_id;
+ end_ = min_id - 1;
+ for (UInt32 i = 0; (i < offset_) && (cur_ != end_); ++i) {
+ while (cur_ != end_) {
+ if (trie_->ith_key(cur_--).is_valid()) {
+ break;
+ }
+ }
+ }
+ }
+}
+
+void IdCursor::swap(IdCursor *cursor) {
+ std::swap(trie_, cursor->trie_);
+ std::swap(offset_, cursor->offset_);
+ std::swap(limit_, cursor->limit_);
+ std::swap(flags_, cursor->flags_);
+ std::swap(cur_, cursor->cur_);
+ std::swap(end_, cursor->end_);
+ std::swap(count_, cursor->count_);
+}
+
+} // namespace dat
+} // namespace grn