| @ -0,0 +1,186 @@ | |||
| // Copyright (C) 2011 Google Inc. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||
| // you may not use this file except in compliance with the License. | |||
| // You may obtain a copy of the License at | |||
| // | |||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||
| // | |||
| // Unless required by applicable law or agreed to in writing, software | |||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| // See the License for the specific language governing permissions and | |||
| // limitations under the License. | |||
| // Author: Philippe Liard | |||
| #include <cassert> | |||
| #include <cstring> | |||
| #include <sstream> | |||
| #include "stringutil.h" | |||
| namespace i18n { | |||
| namespace phonenumbers { | |||
| using std::stringstream; | |||
| string operator+(const string& s, int n) { | |||
| stringstream ss; | |||
| ss << s << n; | |||
| string result; | |||
| ss >> result; | |||
| return result; | |||
| } | |||
| string SimpleItoa(int n) { | |||
| stringstream ss; | |||
| ss << n; | |||
| string result; | |||
| ss >> result; | |||
| return result; | |||
| } | |||
| bool TryStripPrefixString(const string& in, const string& prefix, string* out) { | |||
| assert(out); | |||
| const bool has_prefix = in.compare(0, prefix.length(), prefix) == 0; | |||
| out->assign(has_prefix ? in.substr(prefix.length()) : in); | |||
| return has_prefix; | |||
| } | |||
| bool HasSuffixString(const string& s, const string& suffix) { | |||
| if (s.length() < suffix.length()) { | |||
| return false; | |||
| } | |||
| return s.compare(s.length() - suffix.length(), suffix.length(), suffix) == 0; | |||
| } | |||
| // StringHolder class | |||
| StringHolder::StringHolder(const string& s) : | |||
| string_(&s), | |||
| cstring_(NULL), | |||
| len_(s.size()) | |||
| {} | |||
| StringHolder::StringHolder(const char* s) : | |||
| string_(NULL), | |||
| cstring_(s), | |||
| len_(std::strlen(s)) | |||
| {} | |||
| StringHolder::~StringHolder() {} | |||
| // StrCat | |||
| // Implement s += sh; (s: string, sh: StringHolder) | |||
| string& operator+=(string& lhs, const StringHolder& rhs) { | |||
| const string* const s = rhs.GetString(); | |||
| if (s) { | |||
| lhs += *s; | |||
| } else { | |||
| const char* const cs = rhs.GetCString(); | |||
| if (cs) | |||
| lhs.append(cs, rhs.Length()); | |||
| } | |||
| return lhs; | |||
| } | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2) { | |||
| string result; | |||
| result.reserve(s1.Length() + s2.Length() + 1); | |||
| result += s1; | |||
| result += s2; | |||
| return result; | |||
| } | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3) { | |||
| string result; | |||
| result.reserve(s1.Length() + s2.Length() + s3.Length() + 1); | |||
| result += s1; | |||
| result += s2; | |||
| result += s3; | |||
| return result; | |||
| } | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4) { | |||
| string result; | |||
| result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() + 1); | |||
| result += s1; | |||
| result += s2; | |||
| result += s3; | |||
| result += s4; | |||
| return result; | |||
| } | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4, | |||
| const StringHolder& s5) { | |||
| string result; | |||
| result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() + | |||
| s5.Length() + 1); | |||
| result += s1; | |||
| result += s2; | |||
| result += s3; | |||
| result += s4; | |||
| result += s5; | |||
| return result; | |||
| } | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4, | |||
| const StringHolder& s5, const StringHolder& s6) { | |||
| string result; | |||
| result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() + | |||
| s5.Length() + s6.Length() + 1); | |||
| result += s1; | |||
| result += s2; | |||
| result += s3; | |||
| result += s4; | |||
| result += s5; | |||
| result += s6; | |||
| return result; | |||
| } | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4, | |||
| const StringHolder& s5, const StringHolder& s6, | |||
| const StringHolder& s7, const StringHolder& s8, | |||
| const StringHolder& s9, const StringHolder& s10, | |||
| const StringHolder& s11) { | |||
| string result; | |||
| result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() + | |||
| s5.Length() + s6.Length() + s7.Length() + s8.Length() + | |||
| s9.Length() + s10.Length() + s11.Length()); | |||
| result += s1; | |||
| result += s2; | |||
| result += s3; | |||
| result += s4; | |||
| result += s5; | |||
| result += s6; | |||
| result += s7; | |||
| result += s8; | |||
| result += s9; | |||
| result += s10; | |||
| result += s11; | |||
| return result; | |||
| } | |||
| } // namespace phonenumbers | |||
| } // namespace i18n | |||
| @ -0,0 +1,100 @@ | |||
| // Copyright (C) 2011 Google Inc. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||
| // you may not use this file except in compliance with the License. | |||
| // You may obtain a copy of the License at | |||
| // | |||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||
| // | |||
| // Unless required by applicable law or agreed to in writing, software | |||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| // See the License for the specific language governing permissions and | |||
| // limitations under the License. | |||
| // Author: Philippe Liard | |||
| #ifndef I18N_PHONENUMBERS_STRINGUTIL_H_ | |||
| #define I18N_PHONENUMBERS_STRINGUTIL_H_ | |||
| #include <cstddef> | |||
| #include <string> | |||
| namespace i18n { | |||
| namespace phonenumbers { | |||
| using std::string; | |||
| // Support string("hello") + 10 | |||
| string operator+(const string& s, int n); | |||
| // Convert integer into string | |||
| string SimpleItoa(int n); | |||
| // Return true if 'in' starts with 'prefix' and write into 'out' | |||
| // 'in' minus 'prefix' | |||
| bool TryStripPrefixString(const string& in, const string& prefix, string* out); | |||
| // Return true if 's' ends with 'suffix' | |||
| bool HasSuffixString(const string& s, const string& suffix); | |||
| // Hold a reference to a std::string or C string. | |||
| class StringHolder { | |||
| public: | |||
| // Don't make the constructors explicit to make the StrCat usage convenient. | |||
| StringHolder(const string& s); | |||
| StringHolder(const char* s); | |||
| ~StringHolder(); | |||
| const string* GetString() const { | |||
| return string_; | |||
| } | |||
| const char* GetCString() const { | |||
| return cstring_; | |||
| } | |||
| size_t Length() const { | |||
| return len_; | |||
| } | |||
| private: | |||
| const string* const string_; | |||
| const char* const cstring_; | |||
| const size_t len_; | |||
| }; | |||
| string& operator+=(string& lhs, const StringHolder& rhs); | |||
| // Efficient string concatenation | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2); | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3); | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4); | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4, | |||
| const StringHolder& s5); | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4, | |||
| const StringHolder& s5, const StringHolder& s6); | |||
| string StrCat(const StringHolder& s1, const StringHolder& s2, | |||
| const StringHolder& s3, const StringHolder& s4, | |||
| const StringHolder& s5, const StringHolder& s6, | |||
| const StringHolder& s7, const StringHolder& s8, | |||
| const StringHolder& s9, const StringHolder& s10, | |||
| const StringHolder& s11); | |||
| } // namespace phonenumbers | |||
| } // namespace i18n | |||
| #endif // I18N_PHONENUMBERS_STRINGUTIL_H_ | |||
| @ -0,0 +1,130 @@ | |||
| // Copyright (C) 2011 Google Inc. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||
| // you may not use this file except in compliance with the License. | |||
| // You may obtain a copy of the License at | |||
| // | |||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||
| // | |||
| // Unless required by applicable law or agreed to in writing, software | |||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| // See the License for the specific language governing permissions and | |||
| // limitations under the License. | |||
| // Author: Philippe Liard | |||
| #include <gtest/gtest.h> | |||
| #include "stringutil.h" | |||
| namespace i18n { | |||
| namespace phonenumbers { | |||
| // Test operator+(const string&, int) | |||
| TEST(StringUtilTest, OperatorPlus) { | |||
| EXPECT_EQ("hello10", string("hello") + 10); | |||
| } | |||
| // Test SimpleItoa implementation | |||
| TEST(StringUtilTest, SimpleItoa) { | |||
| EXPECT_EQ("10", SimpleItoa(10)); | |||
| } | |||
| // Test TryStripPrefixString | |||
| TEST(StringUtilTest, TryStripPrefixString) { | |||
| string s; | |||
| EXPECT_TRUE(TryStripPrefixString("hello world", "hello", &s)); | |||
| EXPECT_EQ(" world", s); | |||
| s.clear(); | |||
| EXPECT_FALSE(TryStripPrefixString("hello world", "helloa", &s)); | |||
| s.clear(); | |||
| EXPECT_TRUE(TryStripPrefixString("hello world", "", &s)); | |||
| EXPECT_EQ("hello world", s); | |||
| s.clear(); | |||
| EXPECT_FALSE(TryStripPrefixString("", "hello", &s)); | |||
| s.clear(); | |||
| } | |||
| // Test HasSuffixString | |||
| TEST(StringUtilTest, HasSuffixString) { | |||
| EXPECT_TRUE(HasSuffixString("hello world", "hello world")); | |||
| EXPECT_TRUE(HasSuffixString("hello world", "world")); | |||
| EXPECT_FALSE(HasSuffixString("hello world", "world!")); | |||
| EXPECT_TRUE(HasSuffixString("hello world", "")); | |||
| EXPECT_FALSE(HasSuffixString("", "hello")); | |||
| } | |||
| // Test the StringHolder class | |||
| TEST(StringUtilTest, StringHolder) { | |||
| // Test with C string | |||
| static const char cstring[] = "aaa"; | |||
| StringHolder sh1(cstring); | |||
| EXPECT_EQ(cstring, sh1.GetCString()); | |||
| EXPECT_EQ(NULL, sh1.GetString()); | |||
| // Test with std::string | |||
| string s = "bbb"; | |||
| StringHolder sh2(s); | |||
| EXPECT_EQ(NULL, sh2.GetCString()); | |||
| EXPECT_EQ(&s, sh2.GetString()); | |||
| // Test GetLength() | |||
| string s2 = "hello"; | |||
| StringHolder sh3(s2); | |||
| EXPECT_EQ(5, sh3.Length()); | |||
| } | |||
| // Test the operator+=(string& lhs, const StringHolder& rhs) implementation | |||
| TEST(StringUtilTest, OperatorPlusEquals) { | |||
| // Test with a const char* string to append | |||
| string s = "h"; | |||
| static const char append1[] = "ello"; | |||
| s += StringHolder(append1); // force StringHolder usage | |||
| EXPECT_EQ("hello", s); | |||
| // Test with a std::string to append | |||
| s = "h"; | |||
| string append2 = "ello"; | |||
| s += StringHolder(append2); // force StringHolder usage | |||
| EXPECT_EQ("hello", s); | |||
| } | |||
| // Test the StrCat implementations | |||
| TEST(StringUtilTest, StrCat) { | |||
| string s; | |||
| // Test with 2 arguments | |||
| s = StrCat("a", "b"); | |||
| EXPECT_EQ("ab", s); | |||
| // Test with 3 arguments | |||
| s = StrCat("a", "b", "c"); | |||
| EXPECT_EQ("abc", s); | |||
| // Test with 4 arguments | |||
| s = StrCat("a", "b", "c", "d"); | |||
| EXPECT_EQ("abcd", s); | |||
| // Test with 5 arguments | |||
| s = StrCat("a", "b", "c", "d", "e"); | |||
| EXPECT_EQ("abcde", s); | |||
| // Test with 6 arguments | |||
| s = StrCat("a", "b", "c", "d", "e", "f"); | |||
| EXPECT_EQ("abcdef", s); | |||
| // Test with 11 arguments | |||
| s = StrCat("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"); | |||
| EXPECT_EQ("abcdefghijk", s); | |||
| } | |||
| } // namespace phonenumbers | |||
| } // namespace i18n | |||