[Groonga-commit] groonga/groonga [master] added grn::dat::String and changed cursors' interfaces.

Back to archive index

null+****@clear***** null+****@clear*****
2011年 7月 2日 (土) 14:19:25 JST


Susumu Yata	2011-07-02 05:19:25 +0000 (Sat, 02 Jul 2011)

  New Revision: 893c35296ff77e2eb43da21a0a3ef34564911cb5

  Log:
    added grn::dat::String and changed cursors' interfaces.

  Added files:
    lib/dat/string.hpp
  Modified files:
    lib/dat.cpp
    lib/dat/Makefile.am
    lib/dat/common-prefix-cursor.cpp
    lib/dat/common-prefix-cursor.hpp
    lib/dat/cursor-factory.cpp
    lib/dat/cursor-factory.hpp
    lib/dat/cursor.hpp
    lib/dat/id-cursor.cpp
    lib/dat/id-cursor.hpp
    lib/dat/key-cursor.cpp
    lib/dat/key-cursor.hpp
    lib/dat/key.hpp
    lib/dat/memory-mapped-file-impl.cpp
    lib/dat/memory-mapped-file-impl.hpp
    lib/dat/memory-mapped-file.cpp
    lib/dat/memory-mapped-file.hpp
    lib/dat/predictive-cursor.cpp
    lib/dat/predictive-cursor.hpp
    lib/dat/vector.hpp

  Modified: lib/dat.cpp (+3 -3)
===================================================================
--- lib/dat.cpp    2011-07-01 08:33:11 +0000 (445f777)
+++ lib/dat.cpp    2011-07-02 05:19:25 +0000 (91cb51c)
@@ -259,7 +259,7 @@ grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk)
       grn::dat::Trie *trie = static_cast<grn::dat::Trie *>(dat->handle);
       trie->ith_key(id, &k);
       len = k.length();
-      const char *key = k.ptr();
+      const char *key = static_cast<const char *>(k.ptr());
       if (bulk->header.impl_flags & GRN_OBJ_REFER) {
         bulk->u.b.head = (char *)key;
         bulk->u.b.curr = (char *)key + len;
@@ -308,7 +308,7 @@ grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat,
             grn::dat::Trie *trie = static_cast<grn::dat::Trie *>(dat->handle);
             grn::dat::CommonPrefixCursor *cursor;
             cursor = new grn::dat::CommonPrefixCursor;
-            cursor->open(*trie, max, min_size, max_size, offset, limit);
+            cursor->open(*trie, grn::dat::String(max, max_size), min_size, offset, limit);
             dc->cursor = cursor;
           } else {
             /* todo: near */
@@ -423,7 +423,7 @@ _grn_dat_key(grn_ctx *ctx, grn_dat *dat, grn_id id, uint32_t *key_size)
       grn::dat::Trie *trie = static_cast<grn::dat::Trie *>(dat->handle);
       trie->ith_key(id, &k);
       *key_size = k.length();
-      key = k.ptr();
+      key = static_cast<const char *>(k.ptr());
     } catch (const grn::dat::Exception &ex) {
       key = NULL;
     }

  Modified: lib/dat/Makefile.am (+1 -0)
===================================================================
--- lib/dat/Makefile.am    2011-07-01 08:33:11 +0000 (93a1b85)
+++ lib/dat/Makefile.am    2011-07-02 05:19:25 +0000 (8217637)
@@ -30,6 +30,7 @@ noinst_HEADERS =				\
 	memory-mapped-file.hpp			\
 	node.hpp				\
 	predictive-cursor.hpp			\
+	string.hpp				\
 	timer.hpp				\
 	trie.hpp				\
 	usage.hpp				\

  Modified: lib/dat/common-prefix-cursor.cpp (+29 -32)
===================================================================
--- lib/dat/common-prefix-cursor.cpp    2011-07-01 08:33:11 +0000 (2fb913b)
+++ lib/dat/common-prefix-cursor.cpp    2011-07-02 05:19:25 +0000 (417b3a7)
@@ -1,7 +1,6 @@
 #include "common-prefix-cursor.hpp"
 
 #include <algorithm>
-#include <cstring>
 
 #include "trie.hpp"
 
@@ -20,18 +19,17 @@ CommonPrefixCursor::CommonPrefixCursor()
 CommonPrefixCursor::~CommonPrefixCursor() {}
 
 void CommonPrefixCursor::open(const Trie &trie,
-                              const void *ptr,
+                              const String &str,
                               UInt32 min_length,
-                              UInt32 max_length,
                               UInt32 offset,
                               UInt32 limit,
                               UInt32 flags) {
-  GRN_DAT_THROW_IF(PARAM_ERROR, (ptr == NULL) && (max_length != 0));
-  GRN_DAT_THROW_IF(PARAM_ERROR, min_length > max_length);
+  GRN_DAT_THROW_IF(PARAM_ERROR, (str.ptr() == NULL) && (str.length() != 0));
+  GRN_DAT_THROW_IF(PARAM_ERROR, min_length > str.length());
 
   flags = fix_flags(flags);
   CommonPrefixCursor new_cursor(trie, offset, limit, flags);
-  new_cursor.init(static_cast<const UInt8 *>(ptr), min_length, max_length);
+  new_cursor.init(str, min_length);
   new_cursor.swap(this);
 }
 
@@ -52,6 +50,18 @@ bool CommonPrefixCursor::next(Key *key) {
   return true;
 }
 
+CommonPrefixCursor::CommonPrefixCursor(const Trie &trie,
+                                       UInt32 offset,
+                                       UInt32 limit,
+                                       UInt32 flags)
+    : trie_(&trie),
+      offset_(offset),
+      limit_(limit),
+      flags_(flags),
+      buf_(),
+      cur_(0),
+      end_(0) {}
+
 UInt32 CommonPrefixCursor::fix_flags(UInt32 flags) const {
   const UInt32 cursor_type = flags & CURSOR_TYPE_MASK;
   GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) &&
@@ -72,35 +82,22 @@ UInt32 CommonPrefixCursor::fix_flags(UInt32 flags) const {
   return flags;
 }
 
-CommonPrefixCursor::CommonPrefixCursor(const Trie &trie,
-                                        UInt32 offset,
-                                        UInt32 limit,
-                                        UInt32 flags)
-    : trie_(&trie),
-      offset_(offset),
-      limit_(limit),
-      flags_(flags),
-      buf_(),
-      cur_(0),
-      end_(0) {}
-
-void CommonPrefixCursor::init(const UInt8 *ptr,
-                              UInt32 min_length,
-                              UInt32 max_length) {
-  if ((limit_ == 0) || (offset_ > (max_length - min_length))) {
+void CommonPrefixCursor::init(const String &str,
+                              UInt32 min_length) {
+  if ((limit_ == 0) || (offset_ > (str.length() - min_length))) {
     return;
   }
 
   UInt32 node_id = ROOT_NODE_ID;
   UInt32 i;
-  for (i = 0; i < max_length; ++i) {
+  for (i = 0; i < str.length(); ++i) {
     const Base base = trie_->ith_node(node_id).base();
     if (base.is_terminal()) {
       Key key;
       trie_->ith_key(base.key_id(), &key);
-      if ((key.length() >= min_length) && (key.length() <= max_length) &&
-          (std::memcmp(ptr + i, key.ptr() + i, key.length() - i) == 0) &&
-          ((key.length() < max_length) ||
+      if ((key.length() >= min_length) && (key.length() <= str.length()) &&
+          (str.substr(0, key.length()).compare(key.str(), i) == 0) &&
+          ((key.length() < str.length()) ||
            ((flags_ & EXCEPT_EXACT_MATCH) != EXCEPT_EXACT_MATCH))) {
         GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(key.id()));
       }
@@ -114,26 +111,26 @@ void CommonPrefixCursor::init(const UInt8 *ptr,
                        !buf_.push_back(trie_->ith_node(terminal).key_id()));
     }
 
-    node_id = base.offset() ^ ptr[i];
-    if (trie_->ith_node(node_id).label() != ptr[i]) {
+    node_id = base.offset() ^ str[i];
+    if (trie_->ith_node(node_id).label() != str[i]) {
       break;
     }
   }
 
-  if ((i == max_length) &&
+  if ((i == str.length()) &&
       (flags_ & EXCEPT_EXACT_MATCH) != EXCEPT_EXACT_MATCH) {
     const Base base = trie_->ith_node(node_id).base();
     if (base.is_terminal()) {
       Key key;
       trie_->ith_key(base.key_id(), &key);
-      if ((key.length() >= min_length) && (key.length() <= max_length)) {
+      if ((key.length() >= min_length) && (key.length() <= str.length())) {
         GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(key.id()));
       }
     } else if (trie_->ith_node(node_id).child() == TERMINAL_LABEL) {
       const UInt32 terminal = base.offset() ^ TERMINAL_LABEL;
       Key key;
       trie_->ith_key(trie_->ith_node(terminal).key_id(), &key);
-      if ((key.length() >= min_length) && (key.length() <= max_length)) {
+      if ((key.length() >= min_length) && (key.length() <= str.length())) {
         GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(key.id()));
       }
     }
@@ -162,5 +159,5 @@ void CommonPrefixCursor::swap(CommonPrefixCursor *cursor) {
   std::swap(end_, cursor->end_);
 }
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/common-prefix-cursor.hpp (+8 -8)
===================================================================
--- lib/dat/common-prefix-cursor.hpp    2011-07-01 08:33:11 +0000 (27cd3da)
+++ lib/dat/common-prefix-cursor.hpp    2011-07-02 05:19:25 +0000 (91acf13)
@@ -1,5 +1,5 @@
-#ifndef GRN_DAT_COMMON_PREFIX_CURSOR_H
-#define GRN_DAT_COMMON_PREFIX_CURSOR_H
+#ifndef GRN_DAT_COMMON_PREFIX_CURSOR_HPP_
+#define GRN_DAT_COMMON_PREFIX_CURSOR_HPP_
 
 #include "cursor.hpp"
 #include "vector.hpp"
@@ -15,9 +15,8 @@ class CommonPrefixCursor : public Cursor {
   ~CommonPrefixCursor();
 
   void open(const Trie &trie,
-            const void *ptr,
+            const String &str,
             UInt32 min_length,
-            UInt32 max_length,
             UInt32 offset = 0,
             UInt32 limit = UINT32_MAX,
             UInt32 flags = 0);
@@ -46,10 +45,11 @@ class CommonPrefixCursor : public Cursor {
   UInt32 cur_;
   UInt32 end_;
 
-  UInt32 fix_flags(UInt32 flags) const;
   CommonPrefixCursor(const Trie &trie,
                      UInt32 offset, UInt32 limit, UInt32 flags);
-  void init(const UInt8 *ptr, UInt32 min_length, UInt32 max_length);
+
+  UInt32 fix_flags(UInt32 flags) const;
+  void init(const String &str, UInt32 min_length);
   void swap(CommonPrefixCursor *cursor);
 
   // Disallows copy and assignment.
@@ -57,7 +57,7 @@ class CommonPrefixCursor : public Cursor {
   CommonPrefixCursor &operator=(const CommonPrefixCursor &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
-#endif  // GRN_DAT_COMMON_PREFIX_CURSOR_H
+#endif  // GRN_DAT_COMMON_PREFIX_CURSOR_HPP_

  Modified: lib/dat/cursor-factory.cpp (+7 -7)
===================================================================
--- lib/dat/cursor-factory.cpp    2011-07-01 08:33:11 +0000 (a89f3a0)
+++ lib/dat/cursor-factory.cpp    2011-07-02 05:19:25 +0000 (1bcb5e2)
@@ -21,8 +21,8 @@ Cursor *CursorFactory::open(const Trie &trie,
       IdCursor *cursor = new (std::nothrow) IdCursor;
       GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL);
       try {
-        cursor->open(trie, min_ptr, min_length, max_ptr, max_length,
-                     offset, limit, flags);
+        cursor->open(trie, String(min_ptr, min_length),
+                     String(max_ptr, max_length), offset, limit, flags);
       } catch (...) {
         delete cursor;
         throw;
@@ -33,8 +33,8 @@ Cursor *CursorFactory::open(const Trie &trie,
       KeyCursor *cursor = new (std::nothrow) KeyCursor;
       GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL);
       try {
-        cursor->open(trie, min_ptr, min_length, max_ptr, max_length,
-                     offset, limit, flags);
+        cursor->open(trie, String(min_ptr, min_length),
+                     String(max_ptr, max_length), offset, limit, flags);
       } catch (...) {
         delete cursor;
         throw;
@@ -45,7 +45,7 @@ Cursor *CursorFactory::open(const Trie &trie,
       CommonPrefixCursor *cursor = new (std::nothrow) CommonPrefixCursor;
       GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL);
       try {
-        cursor->open(trie, max_ptr, min_length, max_length,
+        cursor->open(trie, String(max_ptr, max_length), min_length,
                      offset, limit, flags);
       } catch (...) {
         delete cursor;
@@ -57,7 +57,7 @@ Cursor *CursorFactory::open(const Trie &trie,
       PredictiveCursor *cursor = new (std::nothrow) PredictiveCursor;
       GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL);
       try {
-        cursor->open(trie, min_ptr, min_length,
+        cursor->open(trie, String(min_ptr, min_length),
                      offset, limit, flags);
       } catch (...) {
         delete cursor;
@@ -71,5 +71,5 @@ Cursor *CursorFactory::open(const Trie &trie,
   }
 }
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/cursor-factory.hpp (+4 -4)
===================================================================
--- lib/dat/cursor-factory.hpp    2011-07-01 08:33:11 +0000 (6db5012)
+++ lib/dat/cursor-factory.hpp    2011-07-02 05:19:25 +0000 (d50a1cc)
@@ -1,5 +1,5 @@
-#ifndef GRN_DAT_CURSOR_FACTORY_H
-#define GRN_DAT_CURSOR_FACTORY_H
+#ifndef GRN_DAT_CURSOR_FACTORY_HPP_
+#define GRN_DAT_CURSOR_FACTORY_HPP_
 
 #include "cursor.hpp"
 
@@ -23,7 +23,7 @@ class CursorFactory {
   CursorFactory &operator=(const CursorFactory &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
-#endif  // GRN_DAT_CURSOR_FACTORY_H
+#endif  // GRN_DAT_CURSOR_FACTORY_HPP_

  Modified: lib/dat/cursor.hpp (+4 -4)
===================================================================
--- lib/dat/cursor.hpp    2011-07-01 08:33:11 +0000 (ae11dc2)
+++ lib/dat/cursor.hpp    2011-07-02 05:19:25 +0000 (ae5e428)
@@ -1,5 +1,5 @@
-#ifndef GRN_DAT_CURSOR_H
-#define GRN_DAT_CURSOR_H
+#ifndef GRN_DAT_CURSOR_HPP_
+#define GRN_DAT_CURSOR_HPP_
 
 #include "key.hpp"
 
@@ -25,7 +25,7 @@ class Cursor {
   Cursor &operator=(const Cursor &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
-#endif  // GRN_DAT_CURSOR_H
+#endif  // GRN_DAT_CURSOR_HPP_

  Modified: lib/dat/id-cursor.cpp (+18 -19)
===================================================================
--- lib/dat/id-cursor.cpp    2011-07-01 08:33:11 +0000 (312602b)
+++ lib/dat/id-cursor.cpp    2011-07-02 05:19:25 +0000 (67e620b)
@@ -18,25 +18,24 @@ IdCursor::IdCursor()
 IdCursor::~IdCursor() {}
 
 void IdCursor::open(const Trie &trie,
-                    const void *min_ptr, UInt32 min_length,
-                    const void *max_ptr, UInt32 max_length,
+                    const String &min_str,
+                    const String &max_str,
                     UInt32 offset,
                     UInt32 limit,
                     UInt32 flags) {
-  GRN_DAT_THROW_IF(PARAM_ERROR, (min_ptr == NULL) && (min_length != 0));
-  GRN_DAT_THROW_IF(PARAM_ERROR, (max_ptr == NULL) && (max_length != 0));
-
   UInt32 min_id = INVALID_KEY_ID;
-  if (min_ptr != NULL) {
+  if (min_str.ptr() != NULL) {
     Key key;
-    GRN_DAT_THROW_IF(PARAM_ERROR, !trie.search(min_ptr, min_length, &key));
+    GRN_DAT_THROW_IF(PARAM_ERROR,
+                     !trie.search(min_str.ptr(), min_str.length(), &key));
     min_id = key.id();
   }
 
   UInt32 max_id = INVALID_KEY_ID;
-  if (max_ptr != NULL) {
+  if (max_str.ptr() != NULL) {
     Key key;
-    GRN_DAT_THROW_IF(PARAM_ERROR, !trie.search(max_ptr, max_length, &key));
+    GRN_DAT_THROW_IF(PARAM_ERROR,
+                     !trie.search(max_str.ptr(), max_str.length(), &key));
     max_id = key.id();
   }
 
@@ -74,6 +73,15 @@ bool IdCursor::next(Key *key) {
   return true;
 }
 
+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) {}
+
 UInt32 IdCursor::fix_flags(UInt32 flags) const {
   const UInt32 cursor_type = flags & CURSOR_TYPE_MASK;
   GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) &&
@@ -95,15 +103,6 @@ UInt32 IdCursor::fix_flags(UInt32 flags) const {
   return flags;
 }
 
-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) {}
-
 void IdCursor::init(UInt32 min_id, UInt32 max_id) {
   if (min_id == INVALID_KEY_ID) {
     min_id = trie_->min_key_id();
@@ -154,5 +153,5 @@ void IdCursor::swap(IdCursor *cursor) {
   std::swap(end_, cursor->end_);
 }
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/id-cursor.hpp (+8 -7)
===================================================================
--- lib/dat/id-cursor.hpp    2011-07-01 08:33:11 +0000 (83a4b1d)
+++ lib/dat/id-cursor.hpp    2011-07-02 05:19:25 +0000 (fe836d8)
@@ -1,5 +1,5 @@
-#ifndef GRN_DAT_ID_CURSOR_H
-#define GRN_DAT_ID_CURSOR_H
+#ifndef GRN_DAT_ID_CURSOR_HPP_
+#define GRN_DAT_ID_CURSOR_HPP_
 
 #include "cursor.hpp"
 
@@ -14,8 +14,8 @@ class IdCursor : public Cursor {
   ~IdCursor();
 
   void open(const Trie &trie,
-            const void *min_ptr, UInt32 min_length,
-            const void *max_ptr, UInt32 max_length,
+            const String &min_str,
+            const String &max_str,
             UInt32 offset = 0,
             UInt32 limit = UINT32_MAX,
             UInt32 flags = 0);
@@ -50,8 +50,9 @@ class IdCursor : public Cursor {
   UInt32 cur_;
   UInt32 end_;
 
-  UInt32 fix_flags(UInt32 flags) const;
   IdCursor(const Trie &trie, UInt32 offset, UInt32 limit, UInt32 flags);
+
+  UInt32 fix_flags(UInt32 flags) const;
   void init(UInt32 min_id, UInt32 max_id);
   void swap(IdCursor *cursor);
 
@@ -60,7 +61,7 @@ class IdCursor : public Cursor {
   IdCursor &operator=(const IdCursor &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
-#endif  // GRN_DAT_ID_CURSOR_H
+#endif  // GRN_DAT_ID_CURSOR_HPP_

  Modified: lib/dat/key-cursor.cpp (+64 -84)
===================================================================
--- lib/dat/key-cursor.cpp    2011-07-01 08:33:11 +0000 (75e52b2)
+++ lib/dat/key-cursor.cpp    2011-07-02 05:19:25 +0000 (fac4e34)
@@ -16,29 +16,30 @@ KeyCursor::KeyCursor()
       buf_(),
       count_(0),
       max_count_(0),
-      end_(false),
-      end_ptr_(NULL),
-      end_length_(0) {}
+      finished_(false),
+      end_buf_(NULL),
+      end_str_() {}
 
 KeyCursor::~KeyCursor() {
-  if ((end_ptr_ != NULL) && (end_length_ != 0)) {
-    delete [] end_ptr_;
+  if (end_buf_ != NULL) {
+    delete [] end_buf_;
   }
 }
 
 void KeyCursor::open(const Trie &trie,
-                     const void *min_ptr, UInt32 min_length,
-                     const void *max_ptr, UInt32 max_length,
+                     const String &min_str,
+                     const String &max_str,
                      UInt32 offset,
                      UInt32 limit,
                      UInt32 flags) {
-  GRN_DAT_THROW_IF(PARAM_ERROR, (min_ptr == NULL) && (min_length != 0));
-  GRN_DAT_THROW_IF(PARAM_ERROR, (max_ptr == NULL) && (max_length != 0));
+  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(static_cast<const UInt8 *>(min_ptr), min_length,
-                  static_cast<const UInt8 *>(max_ptr), max_length);
+  new_cursor.init(min_str, max_str);
   new_cursor.swap(this);
 }
 
@@ -48,7 +49,7 @@ void KeyCursor::close() {
 }
 
 bool KeyCursor::next(Key *key) {
-  if (end_ || (count_ >= max_count_)) {
+  if (finished_ || (count_ >= max_count_)) {
     return false;
   }
 
@@ -59,6 +60,19 @@ bool KeyCursor::next(Key *key) {
   }
 }
 
+KeyCursor::KeyCursor(const Trie &trie,
+                     UInt32 offset, UInt32 limit, UInt32 flags)
+    : trie_(&trie),
+      offset_(offset),
+      limit_(limit),
+      flags_(flags),
+      buf_(),
+      count_(0),
+      max_count_(0),
+      finished_(false),
+      end_buf_(NULL),
+      end_str_() {}
+
 UInt32 KeyCursor::fix_flags(UInt32 flags) const {
   const UInt32 cursor_type = flags & CURSOR_TYPE_MASK;
   GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) &&
@@ -80,21 +94,7 @@ UInt32 KeyCursor::fix_flags(UInt32 flags) const {
   return flags;
 }
 
-KeyCursor::KeyCursor(const Trie &trie,
-                     UInt32 offset, UInt32 limit, UInt32 flags)
-    : trie_(&trie),
-      offset_(offset),
-      limit_(limit),
-      flags_(flags),
-      buf_(),
-      count_(0),
-      max_count_(0),
-      end_(false),
-      end_ptr_(NULL),
-      end_length_(0) {}
-
-void KeyCursor::init(const UInt8 *min_ptr, UInt32 min_length,
-                     const UInt8 *max_ptr, UInt32 max_length) {
+void KeyCursor::init(const String &min_str, const String &max_str) {
   if (offset_ > (UINT32_MAX - limit_)) {
     max_count_ = UINT32_MAX;
   } else {
@@ -106,31 +106,28 @@ void KeyCursor::init(const UInt8 *min_ptr, UInt32 min_length,
   }
 
   if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) {
-    ascending_init(min_ptr, min_length, max_ptr, max_length);
+    ascending_init(min_str, max_str);
   } else {
-    descending_init(min_ptr, min_length, max_ptr, max_length);
+    descending_init(min_str, max_str);
   }
 }
 
-void KeyCursor::ascending_init(const UInt8 *min_ptr, UInt32 min_length,
-                               const UInt8 *max_ptr, UInt32 max_length) {
-  if (max_ptr != NULL) {
-    if (max_length != 0) {
-      end_ptr_ = new UInt8[max_length];
-      std::memcpy(end_ptr_, max_ptr, max_length);
-    } else {
-      end_ptr_ = reinterpret_cast<UInt8 *>(const_cast<char *>(""));
+void KeyCursor::ascending_init(const String &min_str, const String &max_str) {
+  if (max_str.ptr() != NULL) {
+    if (max_str.length() != 0) {
+      end_buf_ = new UInt8[max_str.length()];
+      std::memcpy(end_buf_, max_str.ptr(), max_str.length());
+      end_str_.assign(end_buf_, max_str.length());
     }
   }
-  end_length_ = max_length;
 
   UInt32 node_id = ROOT_NODE_ID;
   Node node = trie_->ith_node(node_id);
-  for (UInt32 i = 0; i < min_length; ++i) {
+  for (UInt32 i = 0; i < min_str.length(); ++i) {
     if (node.is_terminal()) {
       Key key;
       trie_->ith_key(node.key_id(), &key);
-      const int result = compare(key, min_ptr, min_length, i);
+      const int result = key.str().compare(min_str, i);
       if ((result > 0) || ((result == 0) &&
           ((flags_ & EXCEPT_LOWER_BOUND) != EXCEPT_LOWER_BOUND))) {
         GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id));
@@ -138,14 +135,14 @@ void KeyCursor::ascending_init(const UInt8 *min_ptr, UInt32 min_length,
       return;
     }
 
-    node_id = node.offset() ^ min_ptr[i];
-    if (trie_->ith_node(node_id).label() != min_ptr[i]) {
+    node_id = node.offset() ^ min_str[i];
+    if (trie_->ith_node(node_id).label() != min_str[i]) {
       UInt16 label = node.child();
       if (label == TERMINAL_LABEL) {
         label = trie_->ith_node(node.offset() ^ label).sibling();
       }
       while (label != INVALID_LABEL) {
-        if (label > min_ptr[i]) {
+        if (label > min_str[i]) {
           GRN_DAT_THROW_IF(MEMORY_ERROR,
                            !buf_.push_back(node.offset() ^ label));
           break;
@@ -158,7 +155,7 @@ void KeyCursor::ascending_init(const UInt8 *min_ptr, UInt32 min_length,
     node = trie_->ith_node(node_id);
     if (node.sibling() != INVALID_LABEL) {
       GRN_DAT_THROW_IF(MEMORY_ERROR,
-                       !buf_.push_back(node_id ^ min_ptr[i] ^ node.sibling()));
+                       !buf_.push_back(node_id ^ min_str[i] ^ node.sibling()));
     }
   }
 
@@ -166,7 +163,7 @@ void KeyCursor::ascending_init(const UInt8 *min_ptr, UInt32 min_length,
   if (base.is_terminal()) {
     Key key;
     trie_->ith_key(base.key_id(), &key);
-    if ((key.length() != min_length) ||
+    if ((key.length() != min_str.length()) ||
         ((flags_ & EXCEPT_LOWER_BOUND) != EXCEPT_LOWER_BOUND)) {
       GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id));
     }
@@ -183,25 +180,22 @@ void KeyCursor::ascending_init(const UInt8 *min_ptr, UInt32 min_length,
   }
 }
 
-void KeyCursor::descending_init(const UInt8 *min_ptr, UInt32 min_length,
-                                const UInt8 *max_ptr, UInt32 max_length) {
-  if (min_ptr != NULL) {
-    if (min_length != 0) {
-      end_ptr_ = new UInt8[min_length];
-      std::memcpy(end_ptr_, min_ptr, min_length);
-    } else {
-      end_ptr_ = reinterpret_cast<UInt8 *>(const_cast<char *>(""));
+void KeyCursor::descending_init(const String &min_str, const String &max_str) {
+  if (min_str.ptr() != NULL) {
+    if (min_str.length() != 0) {
+      end_buf_ = new UInt8[min_str.length()];
+      std::memcpy(end_buf_, min_str.ptr(), min_str.length());
+      end_str_.assign(end_buf_, min_str.length());
     }
   }
-  end_length_ = min_length;
 
   UInt32 node_id = ROOT_NODE_ID;
-  for (UInt32 i = 0; i < max_length; ++i) {
+  for (UInt32 i = 0; i < max_str.length(); ++i) {
     const Base base = trie_->ith_node(node_id).base();
     if (base.is_terminal()) {
       Key key;
       trie_->ith_key(base.key_id(), &key);
-      const int result = compare(key, max_ptr, max_length, i);
+      const int result = key.str().compare(max_str, i);
       if ((result < 0) || ((result == 0) &&
           ((flags_ & EXCEPT_UPPER_BOUND) != EXCEPT_UPPER_BOUND))) {
         GRN_DAT_THROW_IF(MEMORY_ERROR,
@@ -219,9 +213,9 @@ void KeyCursor::descending_init(const UInt8 *min_ptr, UInt32 min_length,
     }
     while (label != INVALID_LABEL) {
       node_id = base.offset() ^ label;
-      if (label < max_ptr[i]) {
+      if (label < max_str[i]) {
         GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id));
-      } else if (label > max_ptr[i]) {
+      } else if (label > max_str[i]) {
         return;
       } else {
         break;
@@ -237,7 +231,7 @@ void KeyCursor::descending_init(const UInt8 *min_ptr, UInt32 min_length,
   if (base.is_terminal()) {
     Key key;
     trie_->ith_key(base.key_id(), &key);
-    if ((key.length() == max_length) &&
+    if ((key.length() == max_str.length()) &&
         ((flags_ & EXCEPT_UPPER_BOUND) != EXCEPT_UPPER_BOUND)) {
       GRN_DAT_THROW_IF(MEMORY_ERROR,
                        !buf_.push_back(node_id | POST_ORDER_FLAG));
@@ -261,9 +255,9 @@ void KeyCursor::swap(KeyCursor *cursor) {
   buf_.swap(&cursor->buf_);
   std::swap(count_, cursor->count_);
   std::swap(max_count_, cursor->max_count_);
-  std::swap(end_, cursor->end_);
-  std::swap(end_ptr_, cursor->end_ptr_);
-  std::swap(end_length_, cursor->end_length_);
+  std::swap(finished_, cursor->finished_);
+  std::swap(end_buf_, cursor->end_buf_);
+  end_str_.swap(&cursor->end_str_);
 }
 
 bool KeyCursor::ascending_next(Key *key) {
@@ -285,11 +279,11 @@ bool KeyCursor::ascending_next(Key *key) {
     if (node.is_terminal()) {
       Key temp_key;
       trie_->ith_key(node.key_id(), &temp_key);
-      if (end_ptr_ != NULL) {
-        const int result = compare(temp_key, end_ptr_, end_length_, 0);
+      if (end_buf_ != NULL) {
+        const int result = temp_key.str().compare(end_str_);
         if ((result > 0) || ((result == 0) &&
             ((flags_ & EXCEPT_UPPER_BOUND) == EXCEPT_UPPER_BOUND))) {
-          end_ = true;
+          finished_ = true;
           return false;
         }
       }
@@ -313,11 +307,12 @@ bool KeyCursor::descending_next(Key *key) {
       if (base.is_terminal()) {
         Key temp_key;
         trie_->ith_key(base.key_id(), &temp_key);
-        if (end_ptr_ != NULL) {
-          const int result = compare(temp_key, end_ptr_, end_length_, 0);
+        if (end_buf_ != NULL) {
+          const int result =
+              temp_key.str().compare(end_str_);
           if ((result < 0) || ((result == 0) &&
               ((flags_ & EXCEPT_LOWER_BOUND) == EXCEPT_LOWER_BOUND))) {
-            end_ = true;
+            finished_ = true;
             return false;
           }
         }
@@ -338,20 +333,5 @@ bool KeyCursor::descending_next(Key *key) {
   return false;
 }
 
-int KeyCursor::compare(const Key &key,
-                       const UInt8 *ptr, UInt32 length,
-                       UInt32 offset) const {
-  const UInt32 min_length = (key.length() < length) ? key.length() : length;
-  for (UInt32 i = offset; i < min_length; ++i) {
-    if (static_cast<UInt8>(key[i]) != ptr[i]) {
-      return static_cast<UInt8>(key[i]) - ptr[i];
-    }
-  }
-  if (key.length() < length) {
-    return -1;
-  }
-  return (key.length() > length) ? 1 : 0;
-}
-
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/key-cursor.hpp (+12 -18)
===================================================================
--- lib/dat/key-cursor.hpp    2011-07-01 08:33:11 +0000 (4825a63)
+++ lib/dat/key-cursor.hpp    2011-07-02 05:19:25 +0000 (34c8f21)
@@ -15,8 +15,8 @@ class KeyCursor : public Cursor {
   ~KeyCursor();
 
   void open(const Trie &trie,
-            const void *min_ptr, UInt32 min_length,
-            const void *max_ptr, UInt32 max_length,
+            const String &min_str,
+            const String &max_str,
             UInt32 offset = 0,
             UInt32 limit = UINT32_MAX,
             UInt32 flags = 0);
@@ -44,28 +44,22 @@ class KeyCursor : public Cursor {
   Vector<UInt32> buf_;
   UInt32 count_;
   UInt32 max_count_;
-  bool end_;
-  UInt8 *end_ptr_;
-  UInt32 end_length_;
+  bool finished_;
+  UInt8 *end_buf_;
+  String end_str_;
 
-  UInt32 fix_flags(UInt32 flags) const;
   KeyCursor(const Trie &trie,
-                         UInt32 offset, UInt32 limit, UInt32 flags);
-  void init(const UInt8 *min_ptr, UInt32 min_length,
-            const UInt8 *max_ptr, UInt32 max_length);
-  void ascending_init(const UInt8 *min_ptr, UInt32 min_length,
-                      const UInt8 *max_ptr, UInt32 max_length);
-  void descending_init(const UInt8 *min_ptr, UInt32 min_length,
-                       const UInt8 *max_ptr, UInt32 max_length);
+            UInt32 offset, UInt32 limit, UInt32 flags);
+
+  UInt32 fix_flags(UInt32 flags) const;
+  void init(const String &min_str, const String &max_str);
+  void ascending_init(const String &min_str, const String &max_str);
+  void descending_init(const String &min_str, const String &max_str);
   void swap(KeyCursor *cursor);
 
   bool ascending_next(Key *key);
   bool descending_next(Key *key);
 
-  int compare(const Key &key,
-              const UInt8 *ptr, UInt32 length,
-              UInt32 offset) const;
-
   static const UInt32 POST_ORDER_FLAG = 0x80000000U;
 
   // Disallows copy and assignment.
@@ -73,7 +67,7 @@ class KeyCursor : public Cursor {
   KeyCursor &operator=(const KeyCursor &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
 #endif  // GRN_DAT_KEY_CURSOR_HPP_

  Modified: lib/dat/key.hpp (+21 -12)
===================================================================
--- lib/dat/key.hpp    2011-07-01 08:33:11 +0000 (a0c5c10)
+++ lib/dat/key.hpp    2011-07-02 05:19:25 +0000 (ab0927a)
@@ -1,41 +1,50 @@
 #ifndef GRN_DAT_KEY_HPP_
 #define GRN_DAT_KEY_HPP_
 
-#include "dat.hpp"
+#include "string.hpp"
 
 namespace grn {
 namespace dat {
 
 class Key {
  public:
-  const char &operator[](UInt32 i) const {
-    GRN_DAT_DEBUG_THROW_IF(i > length_);
-    return ptr_[i];
+  Key()
+      : str_(),
+        id_(INVALID_KEY_ID) {}
+
+  const UInt8 &operator[](UInt32 i) const {
+    GRN_DAT_DEBUG_THROW_IF(i >= str_.length());
+    return str_[i];
   }
 
-  const char *ptr() const {
-    return ptr_;
+  const String &str() const {
+    return str_;
+  }
+  const void *ptr() const {
+    return str_.ptr();
   }
   UInt32 length() const {
-    return length_;
+    return str_.length();
   }
   UInt32 id() const {
     return id_;
   }
 
-  void set_ptr(const char *x) {
-    ptr_ = x;
+  void set_str(const void *ptr, UInt32 length) {
+    str_.assign(ptr, length);
+  }
+  void set_ptr(const void *x) {
+    str_.set_ptr(x);
   }
   void set_length(UInt32 x) {
-    length_ = x;
+    str_.set_length(x);
   }
   void set_id(UInt32 x) {
     id_ = x;
   }
 
  private:
-  const char *ptr_;
-  UInt32 length_;
+  String str_;
   UInt32 id_;
 };
 

  Modified: lib/dat/memory-mapped-file-impl.cpp (+1 -1)
===================================================================
--- lib/dat/memory-mapped-file-impl.cpp    2011-07-01 08:33:11 +0000 (a80c596)
+++ lib/dat/memory-mapped-file-impl.cpp    2011-07-02 05:19:25 +0000 (5646bef)
@@ -212,5 +212,5 @@ void MemoryMappedFileImpl::open_(const char *path) {
 
 #endif  // WIN32
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/memory-mapped-file-impl.hpp (+1 -1)
===================================================================
--- lib/dat/memory-mapped-file-impl.hpp    2011-07-01 08:33:11 +0000 (aa6cf0c)
+++ lib/dat/memory-mapped-file-impl.hpp    2011-07-02 05:19:25 +0000 (66164ff)
@@ -50,7 +50,7 @@ class MemoryMappedFileImpl {
   MemoryMappedFileImpl &operator=(const MemoryMappedFileImpl &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
 #endif  // GRN_DAT_MEMORY_MAPPED_FILE_IMPL_HPP_

  Modified: lib/dat/memory-mapped-file.cpp (+1 -1)
===================================================================
--- lib/dat/memory-mapped-file.cpp    2011-07-01 08:33:11 +0000 (9c76ef5)
+++ lib/dat/memory-mapped-file.cpp    2011-07-02 05:19:25 +0000 (973bb17)
@@ -58,5 +58,5 @@ void MemoryMappedFile::swap(MemoryMappedFile *rhs) {
   rhs->impl_ = temp;
 }
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/memory-mapped-file.hpp (+1 -1)
===================================================================
--- lib/dat/memory-mapped-file.hpp    2011-07-01 08:33:11 +0000 (7d85f6b)
+++ lib/dat/memory-mapped-file.hpp    2011-07-02 05:19:25 +0000 (4baedc2)
@@ -30,7 +30,7 @@ class MemoryMappedFile {
   MemoryMappedFile &operator=(const MemoryMappedFile &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
 #endif  // GRN_DAT_MEMORY_MAPPED_FILE_HPP_

  Modified: lib/dat/predictive-cursor.cpp (+22 -25)
===================================================================
--- lib/dat/predictive-cursor.cpp    2011-07-01 08:33:11 +0000 (58d31c3)
+++ lib/dat/predictive-cursor.cpp    2011-07-02 05:19:25 +0000 (f5e755f)
@@ -21,16 +21,15 @@ PredictiveCursor::PredictiveCursor()
 PredictiveCursor::~PredictiveCursor() {}
 
 void PredictiveCursor::open(const Trie &trie,
-                            const void *ptr,
-                            UInt32 length,
+                            const String &str,
                             UInt32 offset,
                             UInt32 limit,
                             UInt32 flags) {
-  GRN_DAT_THROW_IF(PARAM_ERROR, (ptr == NULL) && (length != 0));
+  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(static_cast<const UInt8 *>(ptr), length);
+  new_cursor.init(str);
   new_cursor.swap(this);
 }
 
@@ -51,6 +50,17 @@ bool PredictiveCursor::next(Key *key) {
   }
 }
 
+PredictiveCursor::PredictiveCursor(const Trie &trie,
+                                   UInt32 offset, UInt32 limit, UInt32 flags)
+    : trie_(&trie),
+      offset_(offset),
+      limit_(limit),
+      flags_(flags),
+      buf_(),
+      cur_(0),
+      end_(0),
+      min_length_(0) {}
+
 UInt32 PredictiveCursor::fix_flags(UInt32 flags) const {
   const UInt32 cursor_type = flags & CURSOR_TYPE_MASK;
   GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) &&
@@ -71,47 +81,34 @@ UInt32 PredictiveCursor::fix_flags(UInt32 flags) const {
   return flags;
 }
 
-PredictiveCursor::PredictiveCursor(const Trie &trie,
-                                   UInt32 offset,
-                                   UInt32 limit,
-                                   UInt32 flags)
-    : trie_(&trie),
-      offset_(offset),
-      limit_(limit),
-      flags_(flags),
-      buf_(),
-      cur_(0),
-      end_(0),
-      min_length_(0) {}
-
-void PredictiveCursor::init(const UInt8 *ptr, UInt32 length) {
+void PredictiveCursor::init(const String &str) {
   if (limit_ == 0) {
     return;
   }
 
-  min_length_ = length;
+  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 < length; ++i) {
+  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() >= length) &&
-            (std::memcmp(ptr + i, key.ptr() + i, length - i) == 0)) {
+        if ((key.length() >= str.length()) &&
+            (key.str().substr(0, str.length()).compare(str, i) == 0)) {
           GRN_DAT_THROW_IF(MEMORY_ERROR, !buf_.push_back(node_id));
         }
       }
       return;
     }
 
-    node_id = base.offset() ^ ptr[i];
-    if (trie_->ith_node(node_id).label() != ptr[i]) {
+    node_id = base.offset() ^ str[i];
+    if (trie_->ith_node(node_id).label() != str[i]) {
       return;
     }
   }
@@ -187,5 +184,5 @@ bool PredictiveCursor::descending_next(Key *key) {
   return false;
 }
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn

  Modified: lib/dat/predictive-cursor.hpp (+5 -5)
===================================================================
--- lib/dat/predictive-cursor.hpp    2011-07-01 08:33:11 +0000 (2caa671)
+++ lib/dat/predictive-cursor.hpp    2011-07-02 05:19:25 +0000 (fa3e7b4)
@@ -15,8 +15,7 @@ class PredictiveCursor : public Cursor {
   ~PredictiveCursor();
 
   void open(const Trie &trie,
-            const void *ptr,
-            UInt32 length,
+            const String &str,
             UInt32 offset = 0,
             UInt32 limit = UINT32_MAX,
             UInt32 flags = 0);
@@ -46,10 +45,11 @@ class PredictiveCursor : public Cursor {
   UInt32 end_;
   UInt32 min_length_;
 
-  UInt32 fix_flags(UInt32 flags) const;
   PredictiveCursor(const Trie &trie,
                    UInt32 offset, UInt32 limit, UInt32 flags);
-  void init(const UInt8 *ptr, UInt32 length);
+
+  UInt32 fix_flags(UInt32 flags) const;
+  void init(const String &str);
   void swap(PredictiveCursor *cursor);
 
   bool ascending_next(Key *key);
@@ -62,7 +62,7 @@ class PredictiveCursor : public Cursor {
   PredictiveCursor &operator=(const PredictiveCursor &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
 #endif  // GRN_DAT_PREDICTIVE_CURSOR_HPP_

  Added: lib/dat/string.hpp (+155 -0) 100644
===================================================================
--- /dev/null
+++ lib/dat/string.hpp    2011-07-02 05:19:25 +0000 (bd137fa)
@@ -0,0 +1,155 @@
+#ifndef GRN_DAT_STRING_HPP_
+#define GRN_DAT_STRING_HPP_
+
+#include "dat.hpp"
+
+namespace grn {
+namespace dat {
+
+class String {
+ public:
+  String()
+      : ptr_(NULL),
+        length_(0) {}
+  String(const void *ptr, UInt32 length)
+      : ptr_(static_cast<const UInt8 *>(ptr)),
+        length_(length) {}
+  String(const String &rhs)
+      : ptr_(rhs.ptr_),
+        length_(rhs.length_) {}
+
+  String &operator=(const String &rhs) {
+    set_ptr(rhs.ptr());
+    set_length(rhs.length());
+    return *this;
+  }
+
+  const UInt8 &operator[](UInt32 i) const {
+    GRN_DAT_DEBUG_THROW_IF(i >= length_);
+    return ptr_[i];
+  }
+
+  const void *ptr() const {
+    return ptr_;
+  }
+  UInt32 length() const {
+    return length_;
+  }
+
+  void set_ptr(const void *x) {
+    ptr_ = static_cast<const UInt8 *>(x);
+  }
+  void set_length(UInt32 x) {
+    length_ = x;
+  }
+
+  void assign(const void *ptr, UInt32 length) {
+    set_ptr(ptr);
+    set_length(length);
+  }
+
+  String substr(UInt32 offset = 0) const {
+    return String(ptr_ + offset, length_ - offset);
+  }
+  String substr(UInt32 offset, UInt32 length) const {
+    return String(ptr_ + offset, length);
+  }
+
+  // This function returns an integer as follows:
+  // - a negative value if *this < rhs,
+  // - zero if *this == rhs,
+  // - a positive value if *this > rhs,
+  // but if the offset is too large, the result is undefined.
+  int compare(const String &rhs, UInt32 offset = 0) const {
+    GRN_DAT_DEBUG_THROW_IF(offset > length());
+    GRN_DAT_DEBUG_THROW_IF(offset > rhs.length());
+
+    UInt32 i;
+    for (i = offset; i < length(); ++i) {
+      if (i >= rhs.length()) {
+        return 1;
+      } else if ((*this)[i] != rhs[i]) {
+        return (*this)[i] - rhs[i];
+      }
+    }
+    return (i == rhs.length()) ? 0 : -1;
+  }
+
+  bool starts_with(const String &str) const {
+    if (length() < str.length()) {
+      return false;
+    }
+    for (UInt32 i = 0; i < str.length(); ++i) {
+      if ((*this)[i] != str[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  bool ends_with(const String &str) const {
+    if (length() < str.length()) {
+      return false;
+    }
+    UInt32 offset = length() - str.length();
+    for (UInt32 i = 0; i < str.length(); ++i) {
+      if ((*this)[offset + i] != str[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void swap(String *rhs) {
+    const UInt8 * const ptr_temp = ptr_;
+    ptr_ = rhs->ptr_;
+    rhs->ptr_ = ptr_temp;
+
+    const UInt32 length_temp = length_;
+    length_ = rhs->length_;
+    rhs->length_ = length_temp;
+  }
+
+ private:
+  const UInt8 *ptr_;
+  UInt32 length_;
+};
+
+inline bool operator==(const String &lhs, const String &rhs) {
+  if (lhs.length() != rhs.length()) {
+    return false;
+  } else if (lhs.ptr() == rhs.ptr()) {
+    return true;
+  }
+  for (UInt32 i = 0; i < lhs.length(); ++i) {
+    if (lhs[i] != rhs[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+inline bool operator!=(const String &lhs, const String &rhs) {
+  return !(lhs == rhs);
+}
+
+inline bool operator<(const String &lhs, const String &rhs) {
+  return lhs.compare(rhs) < 0;
+}
+
+inline bool operator>(const String &lhs, const String &rhs) {
+  return rhs < lhs;
+}
+
+inline bool operator<=(const String &lhs, const String &rhs) {
+  return !(lhs > rhs);
+}
+
+inline bool operator>=(const String &lhs, const String &rhs) {
+  return !(lhs < rhs);
+}
+
+}  // namespace dat
+}  // namespace grn
+
+#endif  // GRN_DAT_STRING_HPP_

  Modified: lib/dat/vector.hpp (+1 -1)
===================================================================
--- lib/dat/vector.hpp    2011-07-01 08:33:11 +0000 (e77a932)
+++ lib/dat/vector.hpp    2011-07-02 05:19:25 +0000 (8f9f1d3)
@@ -60,7 +60,7 @@ class Vector {
   Vector &operator=(const Vector &);
 };
 
-}  // namespace grn
 }  // namespace dat
+}  // namespace grn
 
 #endif  // GRN_DAT_VECTOR_HPP_




Groonga-commit メーリングリストの案内
Back to archive index