susumu.yata
null+****@clear*****
Tue Feb 12 22:44:52 JST 2013
susumu.yata 2013-02-12 22:44:52 +0900 (Tue, 12 Feb 2013) New Revision: 0bb9e8394edcb15545cfa8361b4e20b0fad9770d https://github.com/groonga/grnxx/commit/0bb9e8394edcb15545cfa8361b4e20b0fad9770d Log: Add grnxx::Slice. Added files: lib/slice.hpp test/test_slice.cpp Modified files: lib/Makefile.am test/Makefile.am Modified: lib/Makefile.am (+1 -0) =================================================================== --- lib/Makefile.am 2013-02-08 16:11:46 +0900 (fa60014) +++ lib/Makefile.am 2013-02-12 22:44:52 +0900 (24c43ef) @@ -39,6 +39,7 @@ libgrnxx_include_HEADERS = \ mutex.hpp \ os.hpp \ recycler.hpp \ + slice.hpp \ string.hpp \ string_builder.hpp \ string_format.hpp \ Added: lib/slice.hpp (+119 -0) 100644 =================================================================== --- /dev/null +++ lib/slice.hpp 2013-02-12 22:44:52 +0900 (d897a87) @@ -0,0 +1,119 @@ +/* + 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_SLICE_HPP +#define GRNXX_SLICE_HPP + +#include "basic.hpp" + +namespace grnxx { + +class Slice { + public: + // Create an empty (zero-size) slice. + Slice() : ptr_(nullptr), size_(0) {} + // Create a slice that refers to a zero-terminated string. + Slice(const char *str) : ptr_(str), size_(std::strlen(str)) {} + // Create a slice. + Slice(const char *ptr, size_t size) : ptr_(ptr), size_(size) {} + + // Return true iff *this" is not empty. + explicit operator bool() const { + return size_ != 0; + } + + // Make "*this" empty. + void clear() { + ptr_ = nullptr; + size_ = 0; + } + + // Create a slice for the first "n" bytes. + Slice prefix(size_t size) const { + return Slice(ptr_, size); + } + // Create a slice for the last "n" bytes. + Slice suffix(size_t size) const { + return Slice(ptr_ + size_ - size, size); + } + // Create a subslice. + Slice subslice(size_t offset, size_t size) const { + return Slice(ptr_ + offset, size); + } + + // Ignore the first "n" bytes of "*this". + void remove_prefix(size_t n) { + ptr_ += n; + size_ -= n; + } + // Ignore the last "n" bytes of "*this". + void remove_suffix(size_t n) { + size_ -= n; + } + + // Compare "*this" and "s". Return a negative value if "*this" < "s", zero if + // "*this" == "s", or a positive value otherwise (if "*this" > "s"). + int compare(const Slice &s) const { + const size_t min_size = (size_ < s.size_) ? size_ : s.size_; + int result = std::memcmp(ptr_, s.ptr_, min_size); + if (result != 0) { + return result; + } + return (size_ < s.size_) ? -1 : (size_ > s.size_); + } + + // Return true iff "s" is a prefix of "*this". + bool starts_with(const Slice &s) const { + return (size_ >= s.size_) && (std::memcmp(ptr_, s.ptr_, s.size_) == 0); + } + // Return true iff "s" is a suffix of "*this". + bool ends_with(const Slice &s) const { + return (size_ >= s.size_) && + (std::memcmp(ptr_ + size_ - s.size_, s.ptr_, s.size_) == 0); + } + + // Return the "n"-th byte of "*this". + char operator[](size_t i) const { + return ptr_[i]; + } + + // Return the starting address of "*this". + const char *ptr() const { + return ptr_; + } + // Returns the size of "*this". + size_t size() const { + return size_; + } + + private: + const char *ptr_; + size_t size_; +}; + +inline bool operator==(const Slice &lhs, const Slice &rhs) { + return (lhs.size() == rhs.size()) && + (std::memcmp(lhs.ptr(), rhs.ptr(), lhs.size()) == 0); +} + +inline bool operator!=(const Slice &lhs, const Slice &rhs) { + return !(lhs == rhs); +} + +} // namespace grnxx + +#endif // GRNXX_SLICE_HPP Modified: test/Makefile.am (+4 -0) =================================================================== --- test/Makefile.am 2013-02-08 16:11:46 +0900 (f996a6d) +++ test/Makefile.am 2013-02-12 22:44:52 +0900 (ba11422) @@ -22,6 +22,7 @@ TESTS = \ test_mutex \ test_os \ test_recycler \ + test_slice \ test_string \ test_string_builder \ test_string_format \ @@ -93,6 +94,9 @@ test_os_LDADD = ../lib/libgrnxx.la test_recycler_SOURCES = test_recycler.cpp test_recycler_LDADD = ../lib/libgrnxx.la +test_slice_SOURCES = test_slice.cpp +test_slice_LDADD = ../lib/libgrnxx.la + test_string_SOURCES = test_string.cpp test_string_LDADD = ../lib/libgrnxx.la Added: test/test_slice.cpp (+186 -0) 100644 =================================================================== --- /dev/null +++ test/test_slice.cpp 2013-02-12 22:44:52 +0900 (b3410fb) @@ -0,0 +1,186 @@ +/* + 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 <cassert> + +#include "logger.hpp" +#include "slice.hpp" + +void test_constructors() { + grnxx::Slice slice; + + assert(!slice); + assert(!slice.ptr()); + assert(slice.size() == 0); + + const char *empty_str = ""; + slice = grnxx::Slice(empty_str); + + assert(!slice); + assert(slice.ptr() == empty_str); + assert(slice.size() == 0); + + const char *digits = "0123456789"; + slice = grnxx::Slice(digits); + + assert(slice); + assert(slice.ptr() == digits); + assert(slice.size() == 10); + + slice = grnxx::Slice(digits + 3, 5); + + assert(slice); + assert(slice.ptr() == digits + 3); + assert(slice.size() == 5); +} + +void test_prefix() { + grnxx::Slice slice("0123456789"); + grnxx::Slice prefix = slice.prefix(0); + + assert(!prefix); + assert(prefix.ptr() == slice.ptr()); + assert(prefix.size() == 0); + + prefix = slice.prefix(5); + + assert(prefix); + assert(prefix.ptr() == slice.ptr()); + assert(prefix.size() == 5); +} + +void test_suffix() { + grnxx::Slice slice("0123456789"); + grnxx::Slice suffix = slice.suffix(0); + + assert(!suffix); + assert(suffix.ptr() == (slice.ptr() + 10)); + assert(suffix.size() == 0); + + suffix = slice.suffix(5); + + assert(suffix); + assert(suffix.ptr() == (slice.ptr() + 5)); + assert(suffix.size() == 5); +} + +void test_subslice() { + grnxx::Slice slice("0123456789"); + grnxx::Slice subslice = slice.subslice(5, 0); + + assert(!subslice); + assert(subslice.ptr() == (slice.ptr() + 5)); + assert(subslice.size() == 0); + + subslice = slice.subslice(3, 5); + + assert(subslice); + assert(subslice.ptr() == (slice.ptr() + 3)); + assert(subslice.size() == 5); +} + +void test_remove_prefix() { + grnxx::Slice slice("0123456789"); + grnxx::Slice suffix = slice; + + suffix.remove_prefix(0); + assert(suffix == slice); + + suffix.remove_prefix(3); + assert(suffix == slice.suffix(7)); + + suffix.remove_prefix(5); + assert(suffix == slice.suffix(2)); + + suffix.remove_prefix(2); + assert(suffix == slice.suffix(0)); +} + +void test_remove_suffix() { + grnxx::Slice slice("0123456789"); + grnxx::Slice prefix = slice; + + prefix.remove_suffix(0); + assert(prefix == slice); + + prefix.remove_suffix(3); + assert(prefix == slice.prefix(7)); + + prefix.remove_suffix(5); + assert(prefix == slice.prefix(2)); + + prefix.remove_suffix(2); + assert(prefix == slice.prefix(0)); +} + +void test_compare() { + grnxx::Slice abc("abc"); + grnxx::Slice abcde("abcde"); + grnxx::Slice cde("cde"); + + assert(abc.compare(abc) == 0); + assert(abc.compare(abcde) < 0); + assert(abc.compare(cde) < 0); + + assert(abcde.compare(abc) > 0); + assert(abcde.compare(abcde) == 0); + assert(abcde.compare(cde) < 0); + + assert(cde.compare(abc) > 0); + assert(cde.compare(abcde) > 0); + assert(cde.compare(cde) == 0); +} + +void test_starts_with() { + grnxx::Slice slice("cde"); + + assert(slice.starts_with("")); + assert(slice.starts_with("c")); + assert(slice.starts_with("cd")); + assert(slice.starts_with("cde")); + assert(!slice.starts_with("cdef")); + assert(!slice.starts_with("abc")); +} + +void test_ends_with() { + grnxx::Slice slice("cde"); + + assert(slice.ends_with("")); + assert(slice.ends_with("e")); + assert(slice.ends_with("de")); + assert(slice.ends_with("cde")); + assert(!slice.ends_with("bcde")); + assert(!slice.ends_with("abc")); +} + +int main() { + grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL | + grnxx::LOGGER_ENABLE_COUT); + grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER); + + test_constructors(); + test_prefix(); + test_suffix(); + test_subslice(); + test_remove_prefix(); + test_remove_suffix(); + test_compare(); + test_starts_with(); + test_ends_with(); + + return 0; +} -------------- next part -------------- HTML����������������������������...ダウンロード