提交 44dc9705 编写于 作者: Y Yi Wang

Finish StringPiece and unit tests

上级 cd91722a
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
#include "paddle/strings/stringpiece.h" #include "paddle/strings/stringpiece.h"
#include <stddef.h> // #include <stddef.h>
#include <string.h>
#include <algorithm> #include <algorithm>
#include <iosfwd> #include <iosfwd>
...@@ -72,12 +74,14 @@ bool HasSuffix(StringPiece s, StringPiece x) { ...@@ -72,12 +74,14 @@ bool HasSuffix(StringPiece s, StringPiece x) {
} }
StringPiece SkipPrefix(StringPiece s, size_t n) { StringPiece SkipPrefix(StringPiece s, size_t n) {
assert(n <= s.len()); if (n > s.len())
throw std::invalid_argument("Skip distance larger than StringPiece length");
return StringPiece(s.data() + n, s.len() - n); return StringPiece(s.data() + n, s.len() - n);
} }
StringPiece SkipSuffix(StringPiece s, size_t n) { StringPiece SkipSuffix(StringPiece s, size_t n) {
assert(size_ >= n); if (n > s.len())
throw std::invalid_argument("Skip distance larger than StringPiece length");
return StringPiece(s.data(), s.len() - n); return StringPiece(s.data(), s.len() - n);
} }
...@@ -124,4 +128,8 @@ StringPiece SubStr(StringPiece s, size_t pos, size_t n) { ...@@ -124,4 +128,8 @@ StringPiece SubStr(StringPiece s, size_t pos, size_t n) {
return StringPiece(s.data() + pos, n); return StringPiece(s.data() + pos, n);
} }
std::ostream& operator<<(std::ostream& o, StringPiece piece) {
return o << piece.ToString();
}
} // namespace paddle } // namespace paddle
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#pragma once #pragma once
#include <assert.h> #include <assert.h>
#include <string.h>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
...@@ -26,7 +25,11 @@ namespace paddle { ...@@ -26,7 +25,11 @@ namespace paddle {
// StringPiece points into a std::string object but doesn't own the // StringPiece points into a std::string object but doesn't own the
// string. It is for efficient access to strings. Like Go's string // string. It is for efficient access to strings. Like Go's string
// type. StringPiece is not thread-safe. // type. Not that StringPiece doesn't mutate the underlying string,
// so it is thread-safe given that the underlying string doesn't
// change. Because StringPiece contains a little data members, and
// its syntax is simple as it doesn't own/manage the string, it is
// cheap to construct StringPieces and pass them around.
class StringPiece { class StringPiece {
public: public:
static const size_t npos = static_cast<size_t>(-1); static const size_t npos = static_cast<size_t>(-1);
...@@ -37,7 +40,7 @@ public: ...@@ -37,7 +40,7 @@ public:
// size_ is 0. // size_ is 0.
StringPiece(); StringPiece();
StringPiece(const char* d, size_t n); StringPiece(const char* d, size_t n);
StringPiece(const char* s); StringPiece(const char* d);
StringPiece(const std::string& s); StringPiece(const std::string& s);
const char* data() const { return data_; } const char* data() const { return data_; }
...@@ -55,10 +58,6 @@ public: ...@@ -55,10 +58,6 @@ public:
iterator begin() const { return data_; } iterator begin() const { return data_; }
iterator end() const { return data_ + size_; } iterator end() const { return data_ + size_; }
struct Hasher {
size_t operator()(StringPiece arg) const;
};
// Return a string that contains the copy of the referenced data. // Return a string that contains the copy of the referenced data.
std::string ToString() const { return std::string(data_, size_); } std::string ToString() const { return std::string(data_, size_); }
...@@ -69,12 +68,6 @@ private: ...@@ -69,12 +68,6 @@ private:
// Intentionally copyable // Intentionally copyable
}; };
// Because StringPiece contains a little data members, and without the
// ownership, it is so cheap to pass StringPieces around, we don't
// need to define parrameters of the following operations to be
// references. Also, it is cheap to construct new StringPieces, so we
// don't define mutative operations as member functions.
int Compare(StringPiece a, StringPiece b); int Compare(StringPiece a, StringPiece b);
bool operator==(StringPiece x, StringPiece y); bool operator==(StringPiece x, StringPiece y);
...@@ -94,9 +87,13 @@ StringPiece SkipSuffix(StringPiece s, size_t n); ...@@ -94,9 +87,13 @@ StringPiece SkipSuffix(StringPiece s, size_t n);
StringPiece TrimPrefix(StringPiece s, StringPiece prefix); StringPiece TrimPrefix(StringPiece s, StringPiece prefix);
StringPiece TrimSuffix(StringPiece s, StringPiece suffix); StringPiece TrimSuffix(StringPiece s, StringPiece suffix);
// Returns if s contains sub. Any s except for empty s contains an
// empty sub.
bool Contains(StringPiece s, StringPiece sub); bool Contains(StringPiece s, StringPiece sub);
// Return the first occurrence of sub in s, or npos. // Return the first occurrence of sub in s, or npos. If both s and
// sub is empty, it returns npos; otherwise, if only sub is empty, it
// returns 0.
size_t Index(StringPiece s, StringPiece sub); size_t Index(StringPiece s, StringPiece sub);
// Return the first occurrence of c in s[pos:end], or npos. // Return the first occurrence of c in s[pos:end], or npos.
...@@ -108,6 +105,6 @@ size_t RFind(StringPiece s, char c, size_t pos); ...@@ -108,6 +105,6 @@ size_t RFind(StringPiece s, char c, size_t pos);
StringPiece SubStr(StringPiece s, size_t pos, size_t n); StringPiece SubStr(StringPiece s, size_t pos, size_t n);
// allow StringPiece to be logged // allow StringPiece to be logged
extern std::ostream& operator<<(std::ostream& o, StringPiece piece); std::ostream& operator<<(std::ostream& o, StringPiece piece);
} // namespace paddle } // namespace paddle
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
*/ */
#include "paddle/strings/stringpiece.h" #include "paddle/strings/stringpiece.h"
#include <sstream>
#include "gtest/gtest.h" #include "gtest/gtest.h"
TEST(StringPiece, Construct) { TEST(StringPiece, Construct) {
...@@ -23,10 +26,7 @@ TEST(StringPiece, Construct) { ...@@ -23,10 +26,7 @@ TEST(StringPiece, Construct) {
EXPECT_EQ(NULL, s.data()); EXPECT_EQ(NULL, s.data());
EXPECT_EQ(0U, s.len()); EXPECT_EQ(0U, s.len());
} }
{ { EXPECT_THROW(paddle::StringPiece s(NULL, 10000U), std::invalid_argument); }
EXPECT_THROW([] { paddle::StringPiece s(NULL, 10000U); }(),
std::invalid_argument);
}
{ {
paddle::StringPiece s(NULL); paddle::StringPiece s(NULL);
EXPECT_EQ(0U, s.len()); EXPECT_EQ(0U, s.len());
...@@ -54,7 +54,7 @@ TEST(StringPiece, CopyAndAssign) { ...@@ -54,7 +54,7 @@ TEST(StringPiece, CopyAndAssign) {
EXPECT_NE(a.data(), c.data()); EXPECT_NE(a.data(), c.data());
} }
TEST(StringPiece, Comparison) { TEST(StringPiece, Compare) {
{ {
paddle::StringPiece a("hello"); paddle::StringPiece a("hello");
paddle::StringPiece b("world"); paddle::StringPiece b("world");
...@@ -64,6 +64,8 @@ TEST(StringPiece, Comparison) { ...@@ -64,6 +64,8 @@ TEST(StringPiece, Comparison) {
EXPECT_TRUE(a <= b); EXPECT_TRUE(a <= b);
EXPECT_FALSE(a > b); EXPECT_FALSE(a > b);
EXPECT_FALSE(a >= b); EXPECT_FALSE(a >= b);
EXPECT_LT(Compare(a, b), 0);
EXPECT_GT(Compare(b, a), 0);
} }
{ {
paddle::StringPiece a, b; paddle::StringPiece a, b;
...@@ -73,5 +75,219 @@ TEST(StringPiece, Comparison) { ...@@ -73,5 +75,219 @@ TEST(StringPiece, Comparison) {
EXPECT_FALSE(a > b); EXPECT_FALSE(a > b);
EXPECT_TRUE(a <= b); EXPECT_TRUE(a <= b);
EXPECT_TRUE(a >= b); EXPECT_TRUE(a >= b);
EXPECT_EQ(0, Compare(a, b));
EXPECT_EQ(0, Compare(b, a));
}
}
TEST(StringPiece, ToString) {
{
paddle::StringPiece s;
EXPECT_EQ(std::string(""), s.ToString());
}
{
paddle::StringPiece s(NULL);
EXPECT_EQ(std::string(""), s.ToString());
}
{
paddle::StringPiece s("hello");
EXPECT_EQ(std::string("hello"), s.ToString());
}
}
TEST(StringPiece, HasPrefixSuffix) {
using paddle::HasPrefix;
using paddle::HasSuffix;
{
paddle::StringPiece s;
EXPECT_FALSE(HasPrefix(s, "something"));
EXPECT_TRUE(HasPrefix(s, ""));
EXPECT_FALSE(HasSuffix(s, "something"));
EXPECT_TRUE(HasSuffix(s, ""));
}
{
paddle::StringPiece s("app");
EXPECT_TRUE(HasPrefix(s, ""));
EXPECT_TRUE(HasPrefix(s, "a"));
EXPECT_TRUE(HasPrefix(s, "ap"));
EXPECT_TRUE(HasPrefix(s, "app"));
EXPECT_TRUE(HasSuffix(s, ""));
EXPECT_TRUE(HasSuffix(s, "p"));
EXPECT_TRUE(HasSuffix(s, "pp"));
EXPECT_TRUE(HasSuffix(s, "app"));
} }
} }
TEST(StringPiece, SkipPrefixSuffix) {
using paddle::SkipPrefix;
using paddle::SkipSuffix;
{
paddle::StringPiece s;
EXPECT_EQ("", SkipPrefix(s, 0));
EXPECT_THROW(SkipPrefix(s, 1), std::invalid_argument);
EXPECT_EQ("", SkipSuffix(s, 0));
EXPECT_THROW(SkipSuffix(s, 1), std::invalid_argument);
}
{
paddle::StringPiece s("app");
EXPECT_EQ("app", SkipPrefix(s, 0));
EXPECT_EQ("pp", SkipPrefix(s, 1));
EXPECT_EQ("p", SkipPrefix(s, 2));
EXPECT_EQ("", SkipPrefix(s, 3));
EXPECT_THROW(SkipPrefix(s, 4), std::invalid_argument);
EXPECT_EQ("app", SkipSuffix(s, 0));
EXPECT_EQ("ap", SkipSuffix(s, 1));
EXPECT_EQ("a", SkipSuffix(s, 2));
EXPECT_EQ("", SkipSuffix(s, 3));
EXPECT_THROW(SkipSuffix(s, 4), std::invalid_argument);
}
}
TEST(StringPiece, TrimPrefixSuffix) {
using paddle::TrimPrefix;
using paddle::TrimSuffix;
{
paddle::StringPiece s;
EXPECT_EQ("", TrimPrefix(s, ""));
EXPECT_EQ("", TrimPrefix(s, "something"));
EXPECT_EQ("", TrimSuffix(s, ""));
EXPECT_EQ("", TrimSuffix(s, "something"));
}
{
paddle::StringPiece s("app");
EXPECT_EQ("app", TrimPrefix(s, ""));
EXPECT_EQ("pp", TrimPrefix(s, "a"));
EXPECT_EQ("p", TrimPrefix(s, "ap"));
EXPECT_EQ("", TrimPrefix(s, "app"));
EXPECT_EQ("app", TrimPrefix(s, "something"));
EXPECT_EQ("app", TrimSuffix(s, ""));
EXPECT_EQ("ap", TrimSuffix(s, "p"));
EXPECT_EQ("a", TrimSuffix(s, "pp"));
EXPECT_EQ("", TrimSuffix(s, "app"));
EXPECT_EQ("app", TrimSuffix(s, "something"));
}
}
TEST(StringPiece, Contains) {
using paddle::Contains;
{
paddle::StringPiece s;
EXPECT_FALSE(Contains(s, ""));
EXPECT_FALSE(Contains(s, "something"));
}
{
paddle::StringPiece s("app");
EXPECT_TRUE(Contains(s, ""));
EXPECT_TRUE(Contains(s, "a"));
EXPECT_TRUE(Contains(s, "p"));
EXPECT_TRUE(Contains(s, "ap"));
EXPECT_TRUE(Contains(s, "pp"));
EXPECT_TRUE(Contains(s, "app"));
EXPECT_FALSE(Contains(s, "something"));
}
}
TEST(StringPiece, Index) {
using paddle::Index;
auto npos = paddle::StringPiece::npos;
{
paddle::StringPiece s;
EXPECT_EQ(npos, Index(s, ""));
EXPECT_EQ(npos, Index(s, "something"));
}
{
paddle::StringPiece s("app");
EXPECT_EQ(0U, Index(s, ""));
EXPECT_EQ(0U, Index(s, "a"));
EXPECT_EQ(1U, Index(s, "p"));
EXPECT_EQ(0U, Index(s, "ap"));
EXPECT_EQ(1U, Index(s, "pp"));
EXPECT_EQ(0U, Index(s, "app"));
EXPECT_EQ(npos, Index(s, "something"));
}
}
TEST(StringPiece, Find) {
using paddle::Find;
auto npos = paddle::StringPiece::npos;
{
paddle::StringPiece s;
EXPECT_EQ(npos, Find(s, 'a', 0U));
}
{
paddle::StringPiece s("app");
EXPECT_EQ(0U, Find(s, 'a', 0U));
EXPECT_EQ(1U, Find(s, 'p', 0U));
EXPECT_EQ(1U, Find(s, 'p', 1U));
EXPECT_EQ(2U, Find(s, 'p', 2U));
EXPECT_EQ(npos, Find(s, 'z', 2U));
}
}
TEST(StringPiece, RFind) {
using paddle::RFind;
auto npos = paddle::StringPiece::npos;
{
paddle::StringPiece s;
EXPECT_EQ(npos, RFind(s, 'a', 0U));
}
{
paddle::StringPiece s("app");
EXPECT_EQ(2U, RFind(s, 'p', 2U));
EXPECT_EQ(0U, RFind(s, 'a', 2U));
EXPECT_EQ(1U, RFind(s, 'p', 1U));
EXPECT_EQ(0U, RFind(s, 'a', 0));
EXPECT_EQ(npos, RFind(s, 'z', 2U));
}
}
TEST(StringPiece, SubStr) {
using paddle::SubStr;
{
paddle::StringPiece s;
EXPECT_EQ("", SubStr(s, 0, 0));
EXPECT_EQ("", SubStr(s, 0, 1));
EXPECT_EQ("", SubStr(s, 1, 0));
}
{
paddle::StringPiece s("app");
EXPECT_EQ("", SubStr(s, 0, 0));
EXPECT_EQ("", SubStr(s, 1, 0));
EXPECT_EQ("", SubStr(s, 2, 0));
EXPECT_EQ("", SubStr(s, 3, 0));
EXPECT_EQ("a", SubStr(s, 0, 1));
EXPECT_EQ("p", SubStr(s, 1, 1));
EXPECT_EQ("p", SubStr(s, 2, 1));
EXPECT_EQ("", SubStr(s, 3, 1));
EXPECT_EQ("ap", SubStr(s, 0, 2));
EXPECT_EQ("pp", SubStr(s, 1, 2));
EXPECT_EQ("p", SubStr(s, 2, 2));
EXPECT_EQ("", SubStr(s, 3, 2));
EXPECT_EQ("app", SubStr(s, 0, 3));
EXPECT_EQ("pp", SubStr(s, 1, 3));
EXPECT_EQ("p", SubStr(s, 2, 3));
EXPECT_EQ("", SubStr(s, 3, 3));
}
}
TEST(StringPiece, StreamOutput) {
using paddle::StringPiece;
std::stringstream o;
o << StringPiece();
EXPECT_EQ("", o.str());
o << StringPiece("hello");
EXPECT_EQ("hello", o.str());
o << StringPiece();
EXPECT_EQ("hello", o.str());
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册