[Groonga-commit] groonga/grnxx at 2d80947 [master] Add KeyCursor for DoubleArray<T>.

Back to archive index

susumu.yata null+****@clear*****
Thu Apr 18 18:35:35 JST 2013


susumu.yata	2013-04-18 18:35:35 +0900 (Thu, 18 Apr 2013)

  New Revision: 2d8094722ccb75b44dbfac6fe200e8ed2159f30e
  https://github.com/groonga/grnxx/commit/2d8094722ccb75b44dbfac6fe200e8ed2159f30e

  Message:
    Add KeyCursor for DoubleArray<T>.

  Modified files:
    lib/grnxx/alpha/map/double_array-slice.cpp
    lib/grnxx/alpha/map/double_array.cpp
    lib/grnxx/alpha/map/double_array.hpp

  Modified: lib/grnxx/alpha/map/double_array-slice.cpp (+4 -4)
===================================================================
--- lib/grnxx/alpha/map/double_array-slice.cpp    2013-04-18 17:28:26 +0900 (b76f714)
+++ lib/grnxx/alpha/map/double_array-slice.cpp    2013-04-18 18:35:35 +0900 (8edcc65)
@@ -818,8 +818,8 @@ bool DoubleArrayKeyCursor<Slice>::next_order_by_key() {
       if (options_.offset > 0) {
         --options_.offset;
       } else {
-        key_id_ = key.id();
-        key_ = key.slice();
+        this->key_id_ = key.id();
+        this->key_ = key.slice();
         ++count_;
         return true;
       }
@@ -853,8 +853,8 @@ bool DoubleArrayKeyCursor<Slice>::next_reverse_order_by_key() {
         if (options_.offset > 0) {
           --options_.offset;
         } else {
-          key_id_ = key.id();
-          key_ = key.slice();
+          this->key_id_ = key.id();
+          this->key_ = key.slice();
           ++count_;
           return true;
         }

  Modified: lib/grnxx/alpha/map/double_array.cpp (+324 -0)
===================================================================
--- lib/grnxx/alpha/map/double_array.cpp    2013-04-18 17:28:26 +0900 (3b43699)
+++ lib/grnxx/alpha/map/double_array.cpp    2013-04-18 18:35:35 +0900 (2750357)
@@ -507,6 +507,8 @@ class DoubleArrayIDCursor : public MapCursor<T> {
   void init_order_by_key(int64_t min, int64_t max);
 };
 
+constexpr uint64_t POST_ORDER_FLAG = uint64_t(1) << 63;
+
 template <typename T>
 DoubleArrayIDCursor<T>::DoubleArrayIDCursor(
     DoubleArray<T> *double_array, int64_t min, int64_t max,
@@ -624,6 +626,303 @@ void DoubleArrayIDCursor<GeoPoint>::init_order_by_key(int64_t, int64_t) {
 }
 
 template <typename T>
+class DoubleArrayKeyCursor : public MapCursor<T>{
+ public:
+  DoubleArrayKeyCursor(DoubleArray<T> *double_array, T min, T max,
+                       const MapCursorOptions &options);
+  ~DoubleArrayKeyCursor();
+
+  bool next();
+  bool remove();
+
+ private:
+  DoubleArray<T> *double_array_;
+  uint64_t cur_;
+  uint64_t count_;
+  T min_;
+  T max_;
+  MapCursorOptions options_;
+  std::vector<uint64_t> node_ids_;
+  std::vector<std::pair<int64_t, T>> keys_;
+
+  void init_order_by_id();
+  void init_order_by_key();
+  void init_reverse_order_by_key();
+
+  bool next_order_by_id();
+  bool next_order_by_key();
+  bool next_reverse_order_by_key();
+};
+
+template <typename T>
+DoubleArrayKeyCursor<T>::DoubleArrayKeyCursor(
+    DoubleArray<T> *double_array, T min, T max,
+    const MapCursorOptions &options)
+  : MapCursor<T>(), double_array_(double_array), cur_(), count_(0),
+    min_(min), max_(max), options_(options), node_ids_(), keys_() {
+  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
+      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
+    init_order_by_id();
+  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    init_order_by_key();
+  } else {
+    init_reverse_order_by_key();
+  }
+}
+
+template <typename T>
+DoubleArrayKeyCursor<T>::~DoubleArrayKeyCursor() {}
+
+template <typename T>
+bool DoubleArrayKeyCursor<T>::next() {
+  if (count_ >= options_.limit) {
+    return false;
+  }
+  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
+      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
+    return next_order_by_id();
+  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    return next_order_by_key();
+  } else {
+    return next_reverse_order_by_key();
+  }
+}
+
+template <typename T>
+bool DoubleArrayKeyCursor<T>::remove() {
+  return double_array_->unset(this->key_id_);
+}
+
+template <typename T>
+void DoubleArrayKeyCursor<T>::init_order_by_id() {
+  init_order_by_key();
+
+  while (!node_ids_.empty()) {
+    const uint64_t node_id = node_ids_.back();
+    node_ids_.pop_back();
+
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (node.sibling() != INVALID_LABEL) {
+      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+    }
+
+    if (node.is_leaf()) {
+      const T key = double_array_->keys_[node.key_id()];
+      if ((key > max_) ||
+          ((key == max_) && (options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
+        break;
+      }
+      keys_.push_back(std::make_pair(node.key_id(), key));
+      ++count_;
+    } else if (node.child() != INVALID_LABEL) {
+      node_ids_.push_back(node.offset() ^ node.child());
+    }
+  }
+
+  std::sort(keys_.begin(), keys_.end());
+  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    std::reverse(keys_.begin(), keys_.end());
+  }
+  cur_ = options_.offset;
+}
+
+template <typename T>
+void DoubleArrayKeyCursor<T>::init_order_by_key() {
+  uint8_t min_buf[sizeof(T)];
+  convert_key(min_, min_buf);
+
+  uint64_t node_id = ROOT_NODE_ID;
+  DoubleArrayNodeForOthers node;
+  for (size_t i = 0; i < sizeof(T); ++i) {
+    node = double_array_->nodes_[node_id];
+    if (node.is_leaf()) {
+      const T key = double_array_->keys_[node.key_id()];
+      if ((key > min_) ||
+          ((key == min_) && (~options_.flags & MAP_CURSOR_EXCEPT_MIN))) {
+        node_ids_.push_back(node_id);
+      } else if (node.sibling() != INVALID_LABEL) {
+        node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+      }
+      return;
+    } else if (node.sibling() != INVALID_LABEL) {
+      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+    }
+
+    node_id = node.offset() ^ min_buf[i];
+    if (double_array_->nodes_[node_id].label() != min_buf[i]) {
+      uint16_t label = node.child();
+      if (label == TERMINAL_LABEL) {
+        label = double_array_->nodes_[node.offset() ^ label].sibling();
+      }
+      while (label != INVALID_LABEL) {
+        if (label > min_buf[i]) {
+          node_ids_.push_back(node.offset() ^ label);
+          break;
+        }
+        label = double_array_->nodes_[node.offset() ^ label].sibling();
+      }
+      return;
+    }
+  }
+
+  node = double_array_->nodes_[node_id];
+  if (node.is_leaf()) {
+    if (~options_.flags & MAP_CURSOR_EXCEPT_MIN) {
+      node_ids_.push_back(node_id);
+    } else if (node.sibling() != INVALID_LABEL) {
+      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+    }
+    return;
+  } else if (node.sibling() != INVALID_LABEL) {
+    node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+  }
+
+  uint16_t label = node.child();
+  if ((label == TERMINAL_LABEL) && (options_.flags & MAP_CURSOR_EXCEPT_MIN)) {
+    label = double_array_->nodes_[node.offset() ^ label].sibling();
+  }
+  if (label != INVALID_LABEL) {
+    node_ids_.push_back(node.offset() ^ label);
+  }
+}
+
+template <typename T>
+void DoubleArrayKeyCursor<T>::init_reverse_order_by_key() {
+  uint8_t max_buf[sizeof(T)];
+  convert_key(max_, max_buf);
+
+  uint64_t node_id = ROOT_NODE_ID;
+  for (size_t i = 0; i < sizeof(T); ++i) {
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (node.is_leaf()) {
+      const T key = double_array_->keys_[node.key_id()];
+      if ((key < max_) ||
+          ((key == max_) && (~options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
+        node_ids_.push_back(node_id | POST_ORDER_FLAG);
+      }
+      return;
+    }
+
+    uint16_t label = double_array_->nodes_[node_id].child();
+    if (label == TERMINAL_LABEL) {
+      node_id = node.offset() ^ label;
+      node_ids_.push_back(node_id | POST_ORDER_FLAG);
+      label = double_array_->nodes_[node_id].sibling();
+    }
+    while (label != INVALID_LABEL) {
+      node_id = node.offset() ^ label;
+      if (label < max_buf[i]) {
+        node_ids_.push_back(node_id);
+      } else if (label > max_buf[i]) {
+        return;
+      } else {
+        break;
+      }
+      label = double_array_->nodes_[node_id].sibling();
+    }
+    if (label == INVALID_LABEL) {
+      return;
+    }
+  }
+
+  const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+  if (node.is_leaf()) {
+    if (~options_.flags & MAP_CURSOR_EXCEPT_MAX) {
+      node_ids_.push_back(node_id | POST_ORDER_FLAG);
+    }
+    return;
+  }
+
+  uint16_t label = double_array_->nodes_[node_id].child();
+  if ((label == TERMINAL_LABEL) &&
+      (~options_.flags & MAP_CURSOR_EXCEPT_MAX)) {
+    node_ids_.push_back((node.offset() ^ label) | POST_ORDER_FLAG);
+  }
+}
+
+template <typename T>
+bool DoubleArrayKeyCursor<T>::next_order_by_id() {
+  if (cur_ < keys_.size()) {
+    this->key_id_ = keys_[cur_].first;
+    this->key_ = keys_[cur_].second;
+    ++cur_;
+    ++count_;
+    return true;
+  }
+  return false;
+}
+
+template <typename T>
+bool DoubleArrayKeyCursor<T>::next_order_by_key() {
+  while (!node_ids_.empty()) {
+    const uint64_t node_id = node_ids_.back();
+    node_ids_.pop_back();
+
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (node.sibling() != INVALID_LABEL) {
+      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+    }
+
+    if (node.is_leaf()) {
+      const T key = double_array_->keys_[node.key_id()];
+      if ((key > max_) ||
+          ((key == max_) && (options_.flags & MAP_CURSOR_EXCEPT_MAX))) {
+        node_ids_.clear();
+        return false;
+      }
+      if (options_.offset > 0) {
+        --options_.offset;
+      } else {
+        this->key_id_ = node.key_id();
+        this->key_ = key;
+        ++count_;
+        return true;
+      }
+    } else if (node.child() != INVALID_LABEL) {
+      node_ids_.push_back(node.offset() ^ node.child());
+    }
+  }
+  return false;
+}
+
+template <typename T>
+bool DoubleArrayKeyCursor<T>::next_reverse_order_by_key() {
+  while (!node_ids_.empty()) {
+    const bool post_order = node_ids_.back() & POST_ORDER_FLAG;
+    const uint64_t node_id = node_ids_.back() & ~POST_ORDER_FLAG;
+
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (post_order) {
+      node_ids_.pop_back();
+      if (node.is_leaf()) {
+        const T key = double_array_->keys_[node.key_id()];
+        if ((key < min_) ||
+            ((key == min_) && (options_.flags & MAP_CURSOR_EXCEPT_MIN))) {
+          node_ids_.clear();
+          return false;
+        }
+        if (options_.offset > 0) {
+          --options_.offset;
+        } else {
+          this->key_id_ = node.key_id();
+          this->key_ = key;
+          ++count_;
+          return true;
+        }
+      }
+    } else {
+      node_ids_.back() |= POST_ORDER_FLAG;
+      uint16_t label = double_array_->nodes_[node_id].child();
+      while (label != INVALID_LABEL) {
+        node_ids_.push_back(node.offset() ^ label);
+        label = double_array_->nodes_[node.offset() ^ label].sibling();
+      }
+    }
+  }
+  return false;
+}
+
+template <typename T>
 DoubleArray<T>::~DoubleArray() {
   if (!initialized_) try {
     // Free allocated blocks if initialization failed.
@@ -893,12 +1192,37 @@ void DoubleArray<T>::truncate() {
 }
 
 template <typename T>
+MapCursor<T> *DoubleArray<T>::open_basic_cursor(
+    const MapCursorOptions &options) {
+  if ((options.flags & MAP_CURSOR_ORDER_BY_ID) ||
+      (~options.flags & MAP_CURSOR_ORDER_BY_KEY)) {
+    return open_id_cursor(-1, -1, options);
+  } else {
+    // TODO: KeyCursor should be used.
+    return open_id_cursor(-1, -1, options);
+  }
+}
+
+template <typename T>
 MapCursor<T> *DoubleArray<T>::open_id_cursor(int64_t min, int64_t max,
                                              const MapCursorOptions &options) {
   return new (std::nothrow) DoubleArrayIDCursor<T>(this, min, max, options);
 }
 
 template <typename T>
+MapCursor<T> *DoubleArray<T>::open_key_cursor(
+    T min, T max, const MapCursorOptions &options) {
+  return new (std::nothrow) DoubleArrayKeyCursor<T>(this, min, max, options);
+}
+
+template <>
+MapCursor<GeoPoint> *DoubleArray<GeoPoint>::open_key_cursor(
+    GeoPoint, GeoPoint, const MapCursorOptions &) {
+  // Not supported.
+  return nullptr;
+}
+
+template <typename T>
 DoubleArray<T>::DoubleArray()
   : pool_(),
     block_info_(nullptr),

  Modified: lib/grnxx/alpha/map/double_array.hpp (+10 -11)
===================================================================
--- lib/grnxx/alpha/map/double_array.hpp    2013-04-18 17:28:26 +0900 (bc1e5b4)
+++ lib/grnxx/alpha/map/double_array.hpp    2013-04-18 18:35:35 +0900 (0f7448e)
@@ -60,8 +60,8 @@ class DoubleArrayKeyForSlice;
 
 template <typename T>
 class DoubleArray : public Map<T> {
-  friend DoubleArrayIDCursor<T>;
-  friend DoubleArrayKeyCursor<T>;
+  friend class DoubleArrayIDCursor<T>;
+  friend class DoubleArrayKeyCursor<T>;
 
  public:
   typedef DoubleArrayHeaderForOthers DoubleArrayHeader;
@@ -97,13 +97,12 @@ class DoubleArray : public Map<T> {
 
   void truncate();
 
-  // TODO
-//  MapCursor<T> *open_basic_cursor(
-//      const MapCursorOptions &options = MapCursorOptions());
+  MapCursor<T> *open_basic_cursor(
+      const MapCursorOptions &options = MapCursorOptions());
   MapCursor<T> *open_id_cursor(int64_t min, int64_t max,
       const MapCursorOptions &options = MapCursorOptions());
-//  MapCursor<T> *open_key_cursor(T min, T max,
-//      const MapCursorOptions &options = MapCursorOptions());
+  MapCursor<T> *open_key_cursor(T min, T max,
+      const MapCursorOptions &options = MapCursorOptions());
 
   // TODO
 //  MapCursor<T> *open_bitwise_completion_cursor(
@@ -153,10 +152,10 @@ class DoubleArray : public Map<T> {
 
 template <>
 class DoubleArray<Slice> : public Map<Slice> {
-  friend DoubleArrayIDCursor<Slice>;
-  friend DoubleArrayKeyCursor<Slice>;
-  friend DoubleArrayPrefixCursor<Slice>;
-  friend DoubleArrayCompletionCursor<Slice>;
+  friend class DoubleArrayIDCursor<Slice>;
+  friend class DoubleArrayKeyCursor<Slice>;
+  friend class DoubleArrayPrefixCursor<Slice>;
+  friend class DoubleArrayCompletionCursor<Slice>;
 
  public:
   typedef DoubleArrayHeaderForSlice DoubleArrayHeader;
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index