[Groonga-commit] groonga/grnxx at 04fd840 [master] Add implementations of grnxx::MapCursor.

Back to archive index

susumu.yata null+****@clear*****
Mon May 27 15:46:10 JST 2013


susumu.yata	2013-05-27 15:46:10 +0900 (Mon, 27 May 2013)

  New Revision: 04fd8405a74b3c5ef66564025fd3d6b4e4fae463
  https://github.com/groonga/grnxx/commit/04fd8405a74b3c5ef66564025fd3d6b4e4fae463

  Message:
    Add implementations of grnxx::MapCursor.

  Added files:
    lib/grnxx/map/cursor_impl.cpp
    lib/grnxx/map/cursor_impl.hpp
    lib/grnxx/map_cursor.cpp
    lib/grnxx/map_cursor.hpp
    lib/grnxx/map_cursor_query.hpp
  Copied files:
    lib/grnxx/map/scanner_impl.hpp
      (from lib/grnxx/map/scanner.hpp)
  Removed files:
    lib/grnxx/map/cursor.cpp
  Modified files:
    lib/grnxx/Makefile.am
    lib/grnxx/map.cpp
    lib/grnxx/map.hpp
    lib/grnxx/map/Makefile.am
  Renamed files:
    lib/grnxx/map/scanner_impl.cpp
      (from lib/grnxx/map/scanner.cpp)
    lib/grnxx/map_scanner.cpp
      (from lib/grnxx/map/cursor.hpp)
    lib/grnxx/map_scanner.hpp
      (from lib/grnxx/map/scanner.hpp)

  Modified: lib/grnxx/Makefile.am (+5 -0)
===================================================================
--- lib/grnxx/Makefile.am    2013-05-24 20:28:33 +0900 (759da75)
+++ lib/grnxx/Makefile.am    2013-05-27 15:46:10 +0900 (7625569)
@@ -30,6 +30,8 @@ libgrnxx_la_SOURCES =			\
 	grnxx.cpp			\
 	logger.cpp			\
 	map.cpp				\
+	map_cursor.cpp			\
+	map_scanner.cpp			\
 	mutex.cpp			\
 	os.cpp				\
 	periodic_clock.cpp		\
@@ -63,6 +65,9 @@ libgrnxx_include_HEADERS =		\
 	lock.hpp			\
 	logger.hpp			\
 	map.hpp				\
+	map_cursor.hpp			\
+	map_cursor_query.hpp		\
+	map_scanner.hpp			\
 	mutex.hpp			\
 	os.hpp				\
 	periodic_clock.hpp		\

  Modified: lib/grnxx/map.cpp (+14 -45)
===================================================================
--- lib/grnxx/map.cpp    2013-05-24 20:28:33 +0900 (eaec002)
+++ lib/grnxx/map.cpp    2013-05-27 15:46:10 +0900 (e4f112d)
@@ -25,9 +25,10 @@
 #include "grnxx/storage.hpp"
 #include "grnxx/string_builder.hpp"
 #include "grnxx/map/array_map.hpp"
+#include "grnxx/map/cursor_impl.hpp"
 #include "grnxx/map/header.hpp"
 #include "grnxx/map/helper.hpp"
-#include "grnxx/map/scanner.hpp"
+#include "grnxx/map/scanner_impl.hpp"
 
 namespace grnxx {
 
@@ -53,33 +54,6 @@ StringBuilder &operator<<(StringBuilder &builder, MapType type) {
 
 MapOptions::MapOptions() {}
 
-MapCursorOptions::MapCursorOptions()
-    : flags(MAP_CURSOR_DEFAULT),
-      offset(0),
-      limit(std::numeric_limits<uint64_t>::max()) {}
-
-template <typename T>
-MapCursor<T>::MapCursor() : key_id_(MAP_INVALID_KEY_ID), key_() {}
-
-template <typename T>
-MapCursor<T>::~MapCursor() {}
-
-template <typename T>
-bool MapCursor<T>::remove() {
-  GRNXX_ERROR() << "invalid operation";
-  return false;
-}
-
-template <typename T>
-MapScanner<T>::MapScanner()
-    : offset_(0),
-      size_(0),
-      key_id_(MAP_INVALID_KEY_ID),
-      key_() {}
-
-template <typename T>
-MapScanner<T>::~MapScanner() {}
-
 template <typename T>
 Map<T>::Map() {}
 
@@ -273,14 +247,23 @@ bool Map<T>::truncate() {
 }
 
 template <typename T>
-MapCursor<T> *Map<T>::create_cursor(const MapCursorOptions &) {
+MapCursor<T> *Map<T>::create_cursor(MapCursorAll<T>,
+                                    const MapCursorOptions &) {
+  // TODO: Give a naive implementation.
+  GRNXX_ERROR() << "invalid operation";
+  return nullptr;
+}
+
+template <typename T>
+MapCursor<T> *Map<T>::create_cursor(const MapCursorKeyIDRange<T> &,
+                                    const MapCursorOptions &) {
   // TODO: Give a naive implementation.
   GRNXX_ERROR() << "invalid operation";
   return nullptr;
 }
 
 template <typename T>
-MapCursor<T> *Map<T>::create_cursor(const map::CursorQuery<T> &,
+MapCursor<T> *Map<T>::create_cursor(const MapCursorKeyRange<T> &,
                                     const MapCursorOptions &) {
   // TODO: Give a naive implementation.
   GRNXX_ERROR() << "invalid operation";
@@ -296,23 +279,9 @@ MapScanner<T> *Map<T>::create_scanner(KeyArg, const Charset *) {
 template <>
 MapScanner<Bytes> *Map<Bytes>::create_scanner(KeyArg query,
                                               const Charset *charset) {
-  return map::Scanner<Bytes>::create(this, query, charset);
+  return map::ScannerImpl<Bytes>::create(this, query, charset);
 }
 
-template class MapCursor<int8_t>;
-template class MapCursor<uint8_t>;
-template class MapCursor<int16_t>;
-template class MapCursor<uint16_t>;
-template class MapCursor<int32_t>;
-template class MapCursor<uint32_t>;
-template class MapCursor<int64_t>;
-template class MapCursor<uint64_t>;
-template class MapCursor<double>;
-template class MapCursor<GeoPoint>;
-template class MapCursor<Bytes>;
-
-template class MapScanner<Bytes>;
-
 template class Map<int8_t>;
 template class Map<uint8_t>;
 template class Map<int16_t>;

  Modified: lib/grnxx/map.hpp (+25 -114)
===================================================================
--- lib/grnxx/map.hpp    2013-05-24 20:28:33 +0900 (9281bc4)
+++ lib/grnxx/map.hpp    2013-05-27 15:46:10 +0900 (e99fada)
@@ -18,36 +18,30 @@
 #ifndef GRNXX_MAP_HPP
 #define GRNXX_MAP_HPP
 
+#include "grnxx/features.hpp"
+
 #include "grnxx/flags_impl.hpp"
+#include "grnxx/map_cursor.hpp"
+#include "grnxx/map_cursor_query.hpp"
+#include "grnxx/map_scanner.hpp"
 #include "grnxx/traits.hpp"
 #include "grnxx/types.hpp"
 
 namespace grnxx {
-namespace map {
-
-template <typename T> class DummyKeyID;
-template <typename T> class DummyKey;
-template <typename T> class CursorQuery;
-
-}  // namespace map
 
-class StringBuilder;
-
-class Storage;
 class Charset;
-
-template <typename T> class Map;
+class Storage;
+class StringBuilder;
 
 constexpr int64_t MAP_MIN_KEY_ID     = 0;
 constexpr int64_t MAP_MAX_KEY_ID     = (1LL << 40) - 2;
 constexpr int64_t MAP_INVALID_KEY_ID = MAP_MAX_KEY_ID + 1;
 
 enum MapType : uint32_t {
-  MAP_UNKNOWN      = 0,
-  MAP_ARRAY        = 1,  // Array-based implementation.
-  MAP_DOUBLE_ARRAY = 2,  // TODO: DoubleArray-based implementation.
-  MAP_PATRICIA     = 3,  // TODO: Patricia-based implementation.
-  MAP_HASH_TABLE   = 4   // TODO: HashTable-based implementation.
+  MAP_ARRAY        = 0,  // Array-based implementation.
+  MAP_DOUBLE_ARRAY = 1,  // TODO: DoubleArray-based implementation.
+  MAP_PATRICIA     = 2,  // TODO: Patricia-based implementation.
+  MAP_HASH_TABLE   = 3   // TODO: HashTable-based implementation.
 };
 
 StringBuilder &operator<<(StringBuilder &builder, MapType type);
@@ -57,103 +51,11 @@ struct MapOptions {
   MapOptions();
 };
 
-// TODO: How to implement NEAR cursor.
-struct MapCursorFlagsIdentifier;
-using MapCursorFlags = FlagsImpl<MapCursorFlagsIdentifier>;
-
-// Use the default settings.
-constexpr MapCursorFlags MAP_CURSOR_DEFAULT       =
-    MapCursorFlags::define(0x000);
-// Sort keys by ID.
-constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_ID   =
-    MapCursorFlags::define(0x001);
-// Sort keys by key.
-constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_KEY  =
-    MapCursorFlags::define(0x002);
-// Access keys in reverse order.
-constexpr MapCursorFlags MAP_CURSOR_REVERSE_ORDER =
-    MapCursorFlags::define(0x010);
-
-struct MapCursorOptions {
-  MapCursorFlags flags;
-  uint64_t offset;
-  uint64_t limit;
-
-  // Initialize the members.
-  MapCursorOptions();
-};
-
-template <typename T>
-class MapCursor {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  MapCursor();
-  virtual ~MapCursor();
-
-  // Move the cursor to the next key and return true on success.
-  virtual bool next() = 0;
-  // Remove the current key and return true on success.
-  virtual bool remove();
-
-  // Return the ID of the current key.
-  int64_t key_id() const {
-    return key_id_;
-  }
-  // Return the current key.
-  const Key &key() const {
-    return key_;
-  }
-
- protected:
-  int64_t key_id_;
-  Key key_;
-};
-
-template <typename T>
-class MapScanner {
- public:
-  using Key = typename Traits<T>::Type;
-  using KeyArg = typename Traits<T>::ArgumentType;
-
-  MapScanner();
-  virtual ~MapScanner();
-
-  // Find the next key from the rest of the query and return true on success.
-  virtual bool next() = 0;
-
-  // Return the start position of the found key.
-  uint64_t offset() const {
-    return offset_;
-  }
-  // Return the size of the found key.
-  uint64_t size() const {
-    return size_;
-  }
-  // Return the ID of the found key.
-  int64_t key_id() const {
-    return key_id_;
-  }
-  // Return the found key.
-  const Key &key() const {
-    return key_;
-  }
-
- protected:
-  uint64_t offset_;
-  uint64_t size_;
-  int64_t key_id_;
-  Key key_;
-};
-
 template <typename T>
 class Map {
  public:
   using Key = typename Traits<T>::Type;
   using KeyArg = typename Traits<T>::ArgumentType;
-  using DummyKeyID = map::DummyKeyID<T>;
-  using DummyKey = map::DummyKey<T>;
   using Cursor = MapCursor<T>;
   using Scanner = MapScanner<T>;
 
@@ -227,20 +129,29 @@ class Map {
 
   // TODO: Not yet fixed.
   // Return a reference to create a cursor query.
-  const DummyKeyID &key_id() const {
-    return *static_cast<const DummyKeyID *>(nullptr);
+  MapCursorAll<T> all() const {
+    return MapCursorAll<T>();
   }
   // Return a reference to create a cursor query.
-  const DummyKey &key() const {
-    return *static_cast<const DummyKey *>(nullptr);
+  MapCursorKeyID<T> key_id() const {
+    return MapCursorKeyID<T>();
+  }
+  // Return a reference to create a cursor query.
+  MapCursorKey<T> key() const {
+    return MapCursorKey<T>();
   }
 
   // Create a cursor for accessing all the keys.
   virtual Cursor *create_cursor(
+      MapCursorAll<T> query,
+      const MapCursorOptions &options = MapCursorOptions());
+  // Create a cursor for accessing keys that satisfy "query".
+  virtual Cursor *create_cursor(
+      const MapCursorKeyIDRange<T> &query,
       const MapCursorOptions &options = MapCursorOptions());
   // Create a cursor for accessing keys that satisfy "query".
   virtual Cursor *create_cursor(
-      const map::CursorQuery<T> &query,
+      const MapCursorKeyRange<T> &query,
       const MapCursorOptions &options = MapCursorOptions());
 
   // Create a MapScanner object to find keys in "query".

  Modified: lib/grnxx/map/Makefile.am (+4 -4)
===================================================================
--- lib/grnxx/map/Makefile.am    2013-05-24 20:28:33 +0900 (d430696)
+++ lib/grnxx/map/Makefile.am    2013-05-27 15:46:10 +0900 (76179d5)
@@ -5,14 +5,14 @@ libgrnxx_map_la_LDFLAGS = @AM_LTLDFLAGS@
 libgrnxx_map_la_SOURCES =	\
 	array_map.cpp		\
 	bytes_store.cpp		\
-	cursor.cpp		\
-	scanner.cpp
+	cursor_impl.cpp		\
+	scanner_impl.cpp
 
 libgrnxx_map_includedir = ${includedir}/grnxx/map
 libgrnxx_map_include_HEADERS =	\
 	array_map.hpp		\
 	bytes_store.hpp		\
-	cursor.hpp		\
+	cursor_impl.hpp		\
 	header.hpp		\
 	helper.hpp		\
-	scanner.hpp
+	scanner_impl.hpp

  Deleted: lib/grnxx/map/cursor.cpp (+0 -24) 100644
===================================================================
--- lib/grnxx/map/cursor.cpp    2013-05-24 20:28:33 +0900 (6e6c0d9)
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-  Copyright (C) 2013  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  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-1301  USA
-*/
-#include "grnxx/map/cursor.hpp"
-
-namespace grnxx {
-namespace map {
-
-}  // namespace map
-}  // namespace grnxx

  Added: lib/grnxx/map/cursor_impl.cpp (+269 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/map/cursor_impl.cpp    2013-05-27 15:46:10 +0900 (ed981c4)
@@ -0,0 +1,269 @@
+/*
+  Copyright (C) 2013  Brazil, Inc.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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-1301  USA
+*/
+#include "grnxx/map/cursor_impl.hpp"
+
+#include <memory>
+#include <new>
+
+#include "grnxx/bytes.hpp"
+#include "grnxx/geo_point.hpp"
+#include "grnxx/logger.hpp"
+#include "grnxx/map.hpp"
+
+namespace grnxx {
+namespace map {
+
+template <typename T>
+KeyIDRangeCursor<T>::KeyIDRangeCursor()
+    : MapCursor<T>(), map_(), cur_(), end_(), step_(), count_(0),
+      query_(), options_() {}
+
+template <typename T>
+KeyIDRangeCursor<T>::~KeyIDRangeCursor() {}
+
+template <typename T>
+KeyIDRangeCursor<T> *KeyIDRangeCursor<T>::create(
+    Map<T> *map,
+    const MapCursorKeyIDRange<T> &query,
+    const MapCursorOptions &options) {
+  std::unique_ptr<KeyIDRangeCursor<T>> cursor(
+      new (std::nothrow) KeyIDRangeCursor<T>);
+  if (!cursor) {
+    GRNXX_ERROR() << "new grnxx::map::KeyIDRangeCursor<T> failed";
+    return nullptr;
+  }
+  if (!cursor->init(map, query, options)) {
+    return nullptr;
+  }
+  return cursor.release();
+}
+
+template <typename T>
+bool KeyIDRangeCursor<T>::next() {
+  if (count_ >= options_.limit) {
+    return false;
+  }
+  while (cur_ != end_) {
+    cur_ += step_;
+    if (map_->get(cur_, &this->key_)) {
+      this->key_id_ = cur_;
+      ++count_;
+      return true;
+    }
+  }
+  return false;
+}
+
+template <typename T>
+bool KeyIDRangeCursor<T>::remove() {
+  return map_->unset(this->key_id_);
+}
+
+template <typename T>
+bool KeyIDRangeCursor<T>::init(Map<T> *map,
+                               const MapCursorKeyIDRange<T> &query,
+                               const MapCursorOptions &options) {
+  map_ = map;
+  query_ = query;
+  options_ = options;
+  options_.flags = MAP_CURSOR_ORDER_BY_ID;
+  if (options.flags & MAP_CURSOR_REVERSE_ORDER) {
+    options_.flags |= MAP_CURSOR_REVERSE_ORDER;
+  }
+
+  int64_t min;
+  if (query.flags & MAP_CURSOR_KEY_ID_GREATER) {
+    min = query_.min + 1;
+  } else if (query.flags & MAP_CURSOR_KEY_ID_GREATER_EQUAL) {
+    min = query_.min;
+  } else {
+    min = map->min_key_id();
+  }
+
+  int64_t max;
+  if (query.flags & MAP_CURSOR_KEY_ID_LESS) {
+    max = query_.max + 1;
+  } else if (query.flags & MAP_CURSOR_KEY_ID_LESS_EQUAL) {
+    max = query_.max;
+  } else {
+    max = map->max_key_id();
+  }
+
+  if (min > max) {
+    // There are no keys in the range [min, max].
+    cur_ = end_ = 0;
+    return true;
+  }
+
+  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    cur_ = max + 1;
+    end_ = min;
+    step_ = -1;
+  } else {
+    cur_ = min - 1;
+    end_ = max;
+    step_ = 1;
+  }
+
+  // Skip the first "options_.offset" keys in range.
+  for (uint64_t count = 0; (count < options_.offset) && (cur_ != end_); ) {
+    cur_ += step_;
+    if (map_->get(cur_)) {
+      ++count;
+    }
+  }
+  return true;
+}
+
+template <typename T>
+KeyFilterCursor<T>::KeyFilterCursor()
+    : MapCursor<T>(), map_(), cur_(), end_(), step_(), count_(0), options_() {}
+
+template <typename T>
+KeyFilterCursor<T>::~KeyFilterCursor() {}
+
+template <typename T>
+bool KeyFilterCursor<T>::next() {
+  if (count_ >= options_.limit) {
+    return false;
+  }
+  while (cur_ != end_) {
+    cur_ += step_;
+    if (map_->get(cur_, &this->key_)) {
+      if (filter(this->key_)) {
+        this->key_id_ = cur_;
+        ++count_;
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+template <typename T>
+bool KeyFilterCursor<T>::remove() {
+  return map_->unset(this->key_id_);
+}
+
+template <typename T>
+bool KeyFilterCursor<T>::init(Map<T> *map, const MapCursorOptions &options) {
+  map_ = map;
+  options_ = options;
+  options_.flags = MAP_CURSOR_ORDER_BY_ID;
+  if (options.flags & MAP_CURSOR_REVERSE_ORDER) {
+    options_.flags |= MAP_CURSOR_REVERSE_ORDER;
+  }
+
+  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    cur_ = map_->max_key_id() + 1;
+    end_ = 0;
+    step_ = -1;
+  } else {
+    cur_ = -1;
+    end_ = map_->max_key_id();
+    step_ = 1;
+  }
+
+  // Skip the first "options_.offset" keys in range.
+  for (uint64_t count = 0; (count < options_.offset) && (cur_ != end_); ) {
+    cur_ += step_;
+    if (map_->get(cur_, &this->key_)) {
+      if (filter(this->key_)) {
+        ++count;
+      }
+    }
+  }
+  return true;
+}
+
+template <typename T>
+KeyRangeCursor<T>::KeyRangeCursor() : KeyFilterCursor<T>(), query_() {}
+
+template <typename T>
+KeyRangeCursor<T>::~KeyRangeCursor() {}
+
+template <typename T>
+KeyRangeCursor<T> *KeyRangeCursor<T>::create(
+    Map<T> *map,
+    const MapCursorKeyRange<T> &query,
+    const MapCursorOptions &options) {
+  std::unique_ptr<KeyRangeCursor<T>> cursor(
+      new (std::nothrow) KeyRangeCursor<T>);
+  if (!cursor) {
+    GRNXX_ERROR() << "new grnxx::map::KeyRangeCursor<T> failed";
+    return nullptr;
+  }
+  query_ = query;
+  if (!cursor->init(map, options)) {
+    return nullptr;
+  }
+  return cursor.release();
+}
+
+template <typename T>
+bool KeyRangeCursor<T>::filter(KeyArg key) const {
+  if (query_.flags & MAP_CURSOR_KEY_LESS) {
+    if (key >= query_.min) {
+      return false;
+    }
+  } else if (query_.flags & MAP_CURSOR_KEY_LESS_EQUAL) {
+    if (key > query_.min) {
+      return false;
+    }
+  }
+  if (query_.flags & MAP_CURSOR_KEY_GREATER) {
+    if (key <= query_.min) {
+      return false;
+    }
+  } else if (query_.flags & MAP_CURSOR_KEY_GREATER_EQUAL) {
+    if (key < query_.min) {
+      return false;
+    }
+  }
+  return true;
+}
+
+template class KeyIDRangeCursor<int8_t>;
+template class KeyIDRangeCursor<int16_t>;
+template class KeyIDRangeCursor<int32_t>;
+template class KeyIDRangeCursor<int64_t>;
+template class KeyIDRangeCursor<uint8_t>;
+template class KeyIDRangeCursor<uint16_t>;
+template class KeyIDRangeCursor<uint32_t>;
+template class KeyIDRangeCursor<uint64_t>;
+template class KeyIDRangeCursor<double>;
+template class KeyIDRangeCursor<GeoPoint>;
+// TODO: To be enabled.
+//template class KeyIDRangeCursor<Bytes>;
+
+template class KeyRangeCursor<int8_t>;
+template class KeyRangeCursor<int16_t>;
+template class KeyRangeCursor<int32_t>;
+template class KeyRangeCursor<int64_t>;
+template class KeyRangeCursor<uint8_t>;
+template class KeyRangeCursor<uint16_t>;
+template class KeyRangeCursor<uint32_t>;
+template class KeyRangeCursor<uint64_t>;
+template class KeyRangeCursor<double>;
+// GeoPoint does not support comparison operators (<, <=, >, >=).
+//template class KeyRangeCursor<GeoPoint>;
+// TODO: To be enabled.
+//template class KeyRangeCursor<Bytes>;
+
+}  // namespace map
+}  // namespace grnxx

  Added: lib/grnxx/map/cursor_impl.hpp (+108 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/map/cursor_impl.hpp    2013-05-27 15:46:10 +0900 (c72155d)
@@ -0,0 +1,108 @@
+/*
+  Copyright (C) 2013  Brazil, Inc.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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-1301  USA
+*/
+#ifndef GRNXX_MAP_CURSOR_IMPL_HPP
+#define GRNXX_MAP_CURSOR_IMPL_HPP
+
+#include "grnxx/features.hpp"
+
+#include "grnxx/map_cursor.hpp"
+#include "grnxx/map_cursor_query.hpp"
+#include "grnxx/traits.hpp"
+#include "grnxx/types.hpp"
+
+namespace grnxx {
+namespace map {
+
+template <typename T>
+class KeyIDRangeCursor : public MapCursor<T> {
+ public:
+  using Key = typename Traits<T>::Type;
+  using KeyArg = typename Traits<T>::ArgumentType;
+
+  KeyIDRangeCursor();
+  ~KeyIDRangeCursor();
+
+  static KeyIDRangeCursor *create(Map<T> *map,
+                                  const MapCursorKeyIDRange<T> &query,
+                                  const MapCursorOptions &options);
+
+  bool next();
+  bool remove();
+
+ private:
+  Map<T> *map_;
+  int64_t cur_;
+  int64_t end_;
+  int64_t step_;
+  uint64_t count_;
+  MapCursorKeyIDRange<T> query_;
+  MapCursorOptions options_;
+
+  bool init(Map<T> *map,
+            const MapCursorKeyIDRange<T> &query,
+            const MapCursorOptions &options);
+};
+
+template <typename T>
+class KeyFilterCursor : public MapCursor<T> {
+ public:
+  using Key = typename Traits<T>::Type;
+  using KeyArg = typename Traits<T>::ArgumentType;
+
+  KeyFilterCursor();
+  virtual ~KeyFilterCursor();
+
+  bool next();
+  bool remove();
+
+ protected:
+  Map<T> *map_;
+  int64_t cur_;
+  int64_t end_;
+  int64_t step_;
+  uint64_t count_;
+  MapCursorOptions options_;
+
+  bool init(Map<T> *map, const MapCursorOptions &options);
+
+  // Return true if "key" satisfies the query.
+  virtual bool filter(KeyArg key) const = 0;
+};
+
+template <typename T>
+class KeyRangeCursor : public KeyFilterCursor<T> {
+ public:
+  using Key = typename Traits<T>::Type;
+  using KeyArg = typename Traits<T>::ArgumentType;
+
+  KeyRangeCursor();
+  ~KeyRangeCursor();
+
+  KeyRangeCursor *create(Map<T> *map, const MapCursorKeyRange<T> &query,
+                         const MapCursorOptions &options);
+
+ private:
+  MapCursorKeyRange<T> query_;
+
+  bool filter(KeyArg key) const;
+};
+
+}  // namespace map
+}  // namespace grnxx
+
+#endif  // GRNXX_MAP_CURSOR_IMPL_HPP

  Renamed: lib/grnxx/map/scanner_impl.cpp (+10 -9) 78%
===================================================================
--- lib/grnxx/map/scanner.cpp    2013-05-24 20:28:33 +0900 (2a6db90)
+++ lib/grnxx/map/scanner_impl.cpp    2013-05-27 15:46:10 +0900 (c12d1f3)
@@ -15,7 +15,7 @@
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
-#include "grnxx/map/scanner.hpp"
+#include "grnxx/map/scanner_impl.hpp"
 
 #include <memory>
 #include <new>
@@ -23,6 +23,7 @@
 #include "grnxx/bytes.hpp"
 #include "grnxx/charset.hpp"
 #include "grnxx/logger.hpp"
+#include "grnxx/map.hpp"
 
 // TODO: To be removed in future.
 #include "grnxx/slice.hpp"
@@ -31,17 +32,17 @@ namespace grnxx {
 namespace map {
 
 template <typename T>
-Scanner<T>::Scanner() : map_(), query_(), charset_() {}
+ScannerImpl<T>::ScannerImpl() : map_(), query_(), charset_() {}
 
 template <typename T>
-Scanner<T>::~Scanner() {}
+ScannerImpl<T>::~ScannerImpl() {}
 
 template <typename T>
-Scanner<T> *Scanner<T>::create(Map<T> *map, KeyArg query,
-                               const Charset *charset) {
-  std::unique_ptr<Scanner> scanner(new (std::nothrow) Scanner);
+ScannerImpl<T> *ScannerImpl<T>::create(Map<T> *map, KeyArg query,
+                                       const Charset *charset) {
+  std::unique_ptr<ScannerImpl> scanner(new (std::nothrow) ScannerImpl);
   if (!scanner) {
-    GRNXX_ERROR() << "new grnxx::map::Scanner failed";
+    GRNXX_ERROR() << "new grnxx::map::ScannerImpl failed";
     return nullptr;
   }
   scanner->map_ = map;
@@ -51,7 +52,7 @@ Scanner<T> *Scanner<T>::create(Map<T> *map, KeyArg query,
 }
 
 template <typename T>
-bool Scanner<T>::next() {
+bool ScannerImpl<T>::next() {
   this->offset_ += this->size_;
   while (this->offset_ < query_.size()) {
     const T rest = query_.except_prefix(this->offset_);
@@ -71,7 +72,7 @@ bool Scanner<T>::next() {
   return false;
 }
 
-template class Scanner<Bytes>;
+template class ScannerImpl<Bytes>;
 
 }  // namespace map
 }  // namespace grnxx

  Copied: lib/grnxx/map/scanner_impl.hpp (+10 -8) 75%
===================================================================
--- lib/grnxx/map/scanner.hpp    2013-05-24 20:28:33 +0900 (a62b08b)
+++ lib/grnxx/map/scanner_impl.hpp    2013-05-27 15:46:10 +0900 (3d23ce2)
@@ -15,29 +15,31 @@
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
-#ifndef GRNXX_MAP_SCANNER_HPP
-#define GRNXX_MAP_SCANNER_HPP
+#ifndef GRNXX_MAP_SCANNER_IMPL_HPP
+#define GRNXX_MAP_SCANNER_IMPL_HPP
 
 #include "grnxx/features.hpp"
 
-#include "grnxx/map.hpp"
+#include "grnxx/map_scanner.hpp"
 
 namespace grnxx {
 
 class Charset;
+template <typename T> class Map;
 
 namespace map {
 
 template <typename T>
-class Scanner : public MapScanner<T> {
+class ScannerImpl : public MapScanner<T> {
  public:
   using Key = typename MapScanner<T>::Key;
   using KeyArg = typename MapScanner<T>::KeyArg;
 
-  Scanner();
-  ~Scanner();
+  ScannerImpl();
+  ~ScannerImpl();
 
-  static Scanner *create(Map<T> *map, KeyArg query, const Charset *charset);
+  static ScannerImpl *create(Map<T> *map, KeyArg query,
+                             const Charset *charset);
 
   bool next();
 
@@ -50,4 +52,4 @@ class Scanner : public MapScanner<T> {
 }  // namespace map
 }  // namespace grnxx
 
-#endif  // GRNXX_MAP_SCANNER_HPP
+#endif  // GRNXX_MAP_SCANNER_IMPL_HPP

  Added: lib/grnxx/map_cursor.cpp (+78 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/map_cursor.cpp    2013-05-27 15:46:10 +0900 (4e06734)
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2013  Brazil, Inc.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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-1301  USA
+*/
+#include "grnxx/map_cursor.hpp"
+
+#include "grnxx/bytes.hpp"
+#include "grnxx/geo_point.hpp"
+#include "grnxx/logger.hpp"
+#include "grnxx/map.hpp"
+#include "grnxx/string_builder.hpp"
+
+namespace grnxx {
+
+#define GRNXX_FLAGS_WRITE(flag) do { \
+  if (flags & flag) { \
+    if (!is_first) { \
+      builder << " | "; \
+    } \
+    builder << #flag; \
+    is_first = false; \
+  } \
+} while (false)
+
+StringBuilder &operator<<(StringBuilder &builder, MapCursorFlags flags) {
+  bool is_first = true;
+  GRNXX_FLAGS_WRITE(MAP_CURSOR_ORDER_BY_ID);
+  GRNXX_FLAGS_WRITE(MAP_CURSOR_ORDER_BY_KEY);
+  GRNXX_FLAGS_WRITE(MAP_CURSOR_REVERSE_ORDER);
+  if (is_first) {
+    builder << "MAP_CURSOR_DEFAULT";
+  }
+  return builder;
+}
+
+MapCursorOptions::MapCursorOptions()
+    : flags(MAP_CURSOR_DEFAULT),
+      offset(0),
+      limit(std::numeric_limits<uint64_t>::max()) {}
+
+template <typename T>
+MapCursor<T>::MapCursor() : key_id_(MAP_INVALID_KEY_ID), key_() {}
+
+template <typename T>
+MapCursor<T>::~MapCursor() {}
+
+template <typename T>
+bool MapCursor<T>::remove() {
+  GRNXX_ERROR() << "invalid operation";
+  return false;
+}
+
+template class MapCursor<int8_t>;
+template class MapCursor<uint8_t>;
+template class MapCursor<int16_t>;
+template class MapCursor<uint16_t>;
+template class MapCursor<int32_t>;
+template class MapCursor<uint32_t>;
+template class MapCursor<int64_t>;
+template class MapCursor<uint64_t>;
+template class MapCursor<double>;
+template class MapCursor<GeoPoint>;
+template class MapCursor<Bytes>;
+
+}  // namespace grnxx

  Added: lib/grnxx/map_cursor.hpp (+91 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/map_cursor.hpp    2013-05-27 15:46:10 +0900 (9297eba)
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2013  Brazil, Inc.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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-1301  USA
+*/
+#ifndef GRNXX_MAP_CURSOR_HPP
+#define GRNXX_MAP_CURSOR_HPP
+
+#include "grnxx/features.hpp"
+
+#include "grnxx/flags_impl.hpp"
+#include "grnxx/traits.hpp"
+#include "grnxx/types.hpp"
+
+namespace grnxx {
+
+class StringBuilder;
+
+template <typename T> class Map;
+
+// TODO: How to implement NEAR cursor.
+struct MapCursorFlagsIdentifier;
+using MapCursorFlags = FlagsImpl<MapCursorFlagsIdentifier>;
+
+// Use the default settings.
+constexpr MapCursorFlags MAP_CURSOR_DEFAULT       =
+    MapCursorFlags::define(0x00);
+// Sort keys by ID.
+constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_ID   =
+    MapCursorFlags::define(0x01);
+// Sort keys by key.
+constexpr MapCursorFlags MAP_CURSOR_ORDER_BY_KEY  =
+    MapCursorFlags::define(0x02);
+// Access keys in reverse order.
+constexpr MapCursorFlags MAP_CURSOR_REVERSE_ORDER =
+    MapCursorFlags::define(0x10);
+
+StringBuilder &operator<<(StringBuilder &builder, MapCursorFlags flags);
+
+struct MapCursorOptions {
+  MapCursorFlags flags;
+  uint64_t offset;
+  uint64_t limit;
+
+  // Initialize the members.
+  MapCursorOptions();
+};
+
+template <typename T>
+class MapCursor {
+ public:
+  using Key = typename Traits<T>::Type;
+  using KeyArg = typename Traits<T>::ArgumentType;
+
+  MapCursor();
+  virtual ~MapCursor();
+
+  // Move the cursor to the next key and return true on success.
+  virtual bool next() = 0;
+  // Remove the current key and return true on success.
+  virtual bool remove();
+
+  // Return the ID of the current key.
+  int64_t key_id() const {
+    return key_id_;
+  }
+  // Return the current key.
+  const Key &key() const {
+    return key_;
+  }
+
+ protected:
+  int64_t key_id_;
+  Key key_;
+};
+
+}  // namespace grnxx
+
+#endif  // GRNXX_MAP_CURSOR_HPP

  Added: lib/grnxx/map_cursor_query.hpp (+326 -0) 100644
===================================================================
--- /dev/null
+++ lib/grnxx/map_cursor_query.hpp    2013-05-27 15:46:10 +0900 (7e86ef8)
@@ -0,0 +1,326 @@
+/*
+  Copyright (C) 2013  Brazil, Inc.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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-1301  USA
+*/
+#ifndef GRNXX_MAP_CURSOR_QUERY_HPP
+#define GRNXX_MAP_CURSOR_QUERY_HPP
+
+#include "grnxx/features.hpp"
+
+#include "grnxx/flags_impl.hpp"
+#include "grnxx/types.hpp"
+
+namespace grnxx {
+
+// MapCursorAll.
+
+template <typename T> struct MapCursorAll {};
+
+// MapCursorKeyID
+
+template <typename T> struct MapCursorKeyID {};
+
+struct MapCursorKeyIDFlagsIdentifier;
+using MapCursorKeyIDFlags = FlagsImpl<MapCursorKeyIDFlagsIdentifier>;
+
+constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_LESS          =
+    MapCursorKeyIDFlags::define(0x01);
+constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_LESS_EQUAL    =
+    MapCursorKeyIDFlags::define(0x02);
+constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_GREATER       =
+    MapCursorKeyIDFlags::define(0x04);
+constexpr MapCursorKeyIDFlags MAP_CURSOR_KEY_ID_GREATER_EQUAL =
+    MapCursorKeyIDFlags::define(0x08);
+
+template <typename T>
+struct MapCursorKeyIDRange {
+  MapCursorKeyIDFlags flags;
+  int64_t min;
+  int64_t max;
+};
+
+template <typename T>
+struct MapCursorKeyIDLess {
+  int64_t max;
+  constexpr MapCursorKeyIDFlags flags() {
+    return MAP_CURSOR_KEY_ID_LESS;
+  }
+  operator MapCursorKeyIDRange<T>() const {
+    return MapCursorKeyIDRange<T>{ flags(), 0, max };
+  }
+};
+
+template <typename T>
+struct MapCursorKeyIDLessEqual {
+  int64_t max;
+  constexpr MapCursorKeyIDFlags flags() {
+    return MAP_CURSOR_KEY_ID_LESS_EQUAL;
+  }
+  operator MapCursorKeyIDRange<T>() const {
+    return MapCursorKeyIDRange<T>{ flags(), 0, max };
+  };
+};
+
+template <typename T>
+struct MapCursorKeyIDGreater {
+  int64_t min;
+  constexpr MapCursorKeyIDFlags flags() {
+    return MAP_CURSOR_KEY_ID_GREATER;
+  }
+  operator MapCursorKeyIDRange<T>() const {
+    return MapCursorKeyIDRange<T>{ flags(), min, 0 };
+  }
+};
+
+template <typename T>
+struct MapCursorKeyIDGreaterEqual {
+  int64_t min;
+  constexpr MapCursorKeyIDFlags flags() {
+    return MAP_CURSOR_KEY_ID_GREATER_EQUAL;
+  }
+  operator MapCursorKeyIDRange<T>() const {
+    return MapCursorKeyIDRange<T>{ flags(), min };
+  }
+};
+
+template <typename T>
+MapCursorKeyIDLess<T> operator<(MapCursorKeyID<T>, int64_t max) {
+  return MapCursorKeyIDLess<T>{ max };
+}
+template <typename T>
+MapCursorKeyIDLessEqual<T> operator<=(MapCursorKeyID<T>, int64_t max) {
+  return MapCursorKeyIDLessEqual<T>{ max };
+}
+template <typename T>
+MapCursorKeyIDGreater<T> operator>(MapCursorKeyID<T>, int64_t min) {
+  return MapCursorKeyIDGreater<T>{ min };
+}
+template <typename T>
+MapCursorKeyIDGreaterEqual<T> operator>=(MapCursorKeyID<T>, int64_t min) {
+  return MapCursorKeyIDGreaterEqual<T>{ min };
+}
+
+template <typename T>
+MapCursorKeyIDGreater<T> operator<(int64_t min, MapCursorKeyID<T>) {
+  return MapCursorKeyIDGreater<T>{ min };
+}
+template <typename T>
+MapCursorKeyIDGreaterEqual<T> operator<=(int64_t min, MapCursorKeyID<T>) {
+  return MapCursorKeyIDGreaterEqual<T>{ min };
+}
+template <typename T>
+MapCursorKeyIDLess<T> operator>(int64_t max, MapCursorKeyID<T>) {
+  return MapCursorKeyIDLess<T>{ max };
+}
+template <typename T>
+MapCursorKeyIDLessEqual<T> operator>=(int64_t max, MapCursorKeyID<T>) {
+  return MapCursorKeyIDLessEqual<T>{ max };
+}
+
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLess<T> less,
+                                  MapCursorKeyIDGreater<T> greater) {
+  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
+                                 greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLess<T> less,
+                                  MapCursorKeyIDGreaterEqual<T> greater) {
+  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
+                                 greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLessEqual<T> less,
+                                  MapCursorKeyIDGreater<T> greater) {
+  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
+                                 greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDLessEqual<T> less,
+                                  MapCursorKeyIDGreaterEqual<T> greater) {
+  return MapCursorKeyIDRange<T>{ less.flags() | greater.flags(),
+                                 greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreater<T> greater,
+                                  MapCursorKeyIDLess<T> less) {
+  return less && greater;
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreater<T> greater,
+                                  MapCursorKeyIDLessEqual<T> less) {
+  return less && greater;
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreaterEqual<T> greater,
+                                  MapCursorKeyIDLess<T> less) {
+  return less && greater;
+}
+template <typename T>
+MapCursorKeyIDRange<T> operator&&(MapCursorKeyIDGreaterEqual<T> greater,
+                                  MapCursorKeyIDLessEqual<T> less) {
+  return less && greater;
+}
+
+// MapCursorKey
+
+template <typename T> struct MapCursorKey {};
+
+struct MapCursorKeyFlagsIdentifier;
+using MapCursorKeyFlags = FlagsImpl<MapCursorKeyFlagsIdentifier>;
+
+constexpr MapCursorKeyFlags MAP_CURSOR_KEY_LESS          =
+    MapCursorKeyFlags::define(0x01);
+constexpr MapCursorKeyFlags MAP_CURSOR_KEY_LESS_EQUAL    =
+    MapCursorKeyFlags::define(0x02);
+constexpr MapCursorKeyFlags MAP_CURSOR_KEY_GREATER       =
+    MapCursorKeyFlags::define(0x04);
+constexpr MapCursorKeyFlags MAP_CURSOR_KEY_GREATER_EQUAL =
+    MapCursorKeyFlags::define(0x08);
+
+template <typename T>
+struct MapCursorKeyRange {
+  MapCursorKeyFlags flags;
+  T min;
+  T max;
+};
+
+template <typename T>
+struct MapCursorKeyLess {
+  T max;
+  constexpr MapCursorKeyFlags flags() {
+    return MAP_CURSOR_KEY_LESS;
+  }
+  operator MapCursorKeyRange<T>() const {
+    return MapCursorKeyRange<T>{ flags(), T(), max };
+  }
+};
+
+template <typename T>
+struct MapCursorKeyLessEqual {
+  T max;
+  constexpr MapCursorKeyFlags flags() {
+    return MAP_CURSOR_KEY_LESS_EQUAL;
+  }
+  operator MapCursorKeyRange<T>() const {
+    return MapCursorKeyRange<T>{ flags(), T(), max };
+  }
+};
+
+template <typename T>
+struct MapCursorKeyGreater {
+  T min;
+  constexpr MapCursorKeyFlags flags() {
+    return MAP_CURSOR_KEY_GREATER;
+  }
+  operator MapCursorKeyRange<T>() const {
+    return MapCursorKeyRange<T>{ flags(), min, T() };
+  }
+};
+
+template <typename T>
+struct MapCursorKeyGreaterEqual {
+  T min;
+  constexpr MapCursorKeyFlags flags() {
+    return MAP_CURSOR_KEY_GREATER_EQUAL;
+  }
+  operator MapCursorKeyRange<T>() const {
+    return MapCursorKeyRange<T>{ flags(), min, T() };
+  }
+};
+
+template <typename T>
+MapCursorKeyLess<T> operator<(MapCursorKey<T>, T max) {
+  return MapCursorKeyLess<T>{ max };
+}
+template <typename T>
+MapCursorKeyLessEqual<T> operator<=(MapCursorKey<T>, T max) {
+  return MapCursorKeyLessEqual<T>{ max };
+}
+template <typename T>
+MapCursorKeyGreater<T> operator>(MapCursorKey<T>, T min) {
+  return MapCursorKeyGreater<T>{ min };
+}
+template <typename T>
+MapCursorKeyGreaterEqual<T> operator>=(MapCursorKey<T>, T min) {
+  return MapCursorKeyGreaterEqual<T>{ min };
+}
+
+template <typename T>
+MapCursorKeyGreater<T> operator<(T min, MapCursorKey<T>) {
+  return MapCursorKeyGreater<T>{ min };
+}
+template <typename T>
+MapCursorKeyGreaterEqual<T> operator<=(T min, MapCursorKey<T>) {
+  return MapCursorKeyGreaterEqual<T>{ min };
+}
+template <typename T>
+MapCursorKeyLess<T> operator>(T max, MapCursorKey<T>) {
+  return MapCursorKeyLess<T>{ max };
+}
+template <typename T>
+MapCursorKeyLessEqual<T> operator>=(T max, MapCursorKey<T>) {
+  return MapCursorKeyLessEqual<T>{ max };
+}
+
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyLess<T> less,
+                                MapCursorKeyGreater<T> greater) {
+  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
+                               greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyLess<T> less,
+                                MapCursorKeyGreaterEqual<T> greater) {
+  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
+                               greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyLessEqual<T> less,
+                                MapCursorKeyGreater<T> greater) {
+  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
+                               greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyLessEqual<T> less,
+                                MapCursorKeyGreaterEqual<T> greater) {
+  return MapCursorKeyRange<T>{ less.flags() | greater.flags(),
+                               greater.min, less.max };
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyGreater<T> greater,
+                                MapCursorKeyLess<T> less) {
+  return less && greater;
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyGreater<T> greater,
+                                MapCursorKeyLessEqual<T> less) {
+  return less && greater;
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyGreaterEqual<T> greater,
+                                MapCursorKeyLess<T> less) {
+  return less && greater;
+}
+template <typename T>
+MapCursorKeyRange<T> operator&&(MapCursorKeyGreaterEqual<T> greater,
+                                MapCursorKeyLessEqual<T> less) {
+  return less && greater;
+}
+
+}  // namespace grnxx
+
+#endif  // GRNXX_MAP_CURSOR_QUERY_HPP

  Renamed: lib/grnxx/map_scanner.cpp (+15 -7) 72%
===================================================================
--- lib/grnxx/map/cursor.hpp    2013-05-24 20:28:33 +0900 (5ac9df5)
+++ lib/grnxx/map_scanner.cpp    2013-05-27 15:46:10 +0900 (8814983)
@@ -15,15 +15,23 @@
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
-#ifndef GRNXX_MAP_CURSOR_HPP
-#define GRNXX_MAP_CURSOR_HPP
+#include "grnxx/map_scanner.hpp"
 
-#include "grnxx/features.hpp"
+#include "grnxx/bytes.hpp"
+#include "grnxx/map.hpp"
 
 namespace grnxx {
-namespace map {
 
-}  // namespace map
-}  // namespace grnxx
+template <typename T>
+MapScanner<T>::MapScanner()
+    : offset_(0),
+      size_(0),
+      key_id_(MAP_INVALID_KEY_ID),
+      key_() {}
+
+template <typename T>
+MapScanner<T>::~MapScanner() {}
 
-#endif  // GRNXX_MAP_CURSOR_HPP
+template class MapScanner<Bytes>;
+
+}  // namespace grnxx

  Renamed: lib/grnxx/map_scanner.hpp (+31 -14) 56%
===================================================================
--- lib/grnxx/map/scanner.hpp    2013-05-24 20:28:33 +0900 (a62b08b)
+++ lib/grnxx/map_scanner.hpp    2013-05-27 15:46:10 +0900 (b28af1c)
@@ -20,34 +20,51 @@
 
 #include "grnxx/features.hpp"
 
-#include "grnxx/map.hpp"
+#include "grnxx/flags_impl.hpp"
+#include "grnxx/traits.hpp"
+#include "grnxx/types.hpp"
 
 namespace grnxx {
 
 class Charset;
-
-namespace map {
+class Storage;
 
 template <typename T>
-class Scanner : public MapScanner<T> {
+class MapScanner {
  public:
-  using Key = typename MapScanner<T>::Key;
-  using KeyArg = typename MapScanner<T>::KeyArg;
+  using Key = typename Traits<T>::Type;
+  using KeyArg = typename Traits<T>::ArgumentType;
 
-  Scanner();
-  ~Scanner();
+  MapScanner();
+  virtual ~MapScanner();
 
-  static Scanner *create(Map<T> *map, KeyArg query, const Charset *charset);
+  // Find the next key from the rest of the query and return true on success.
+  virtual bool next() = 0;
 
-  bool next();
+  // Return the start position of the found key.
+  uint64_t offset() const {
+    return offset_;
+  }
+  // Return the size of the found key.
+  uint64_t size() const {
+    return size_;
+  }
+  // Return the ID of the found key.
+  int64_t key_id() const {
+    return key_id_;
+  }
+  // Return the found key.
+  const Key &key() const {
+    return key_;
+  }
 
  protected:
-  Map<T> *map_;
-  Key query_;
-  const Charset *charset_;
+  uint64_t offset_;
+  uint64_t size_;
+  int64_t key_id_;
+  Key key_;
 };
 
-}  // namespace map
 }  // namespace grnxx
 
 #endif  // GRNXX_MAP_SCANNER_HPP
-------------- next part --------------
HTML����������������������������...
Download 



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