Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 08a3220

Browse files
committed
Add string_piece_util
Following functions are implemented for further performance optimization. * JoinStringPiece * SplitStringPiece * EqualsCaseInsensitiveASCII * ToLowerASCII To improve performance of CLParser, I will introduce above functions into include_normalize-win32.cc.
1 parent 586bb6d commit 08a3220

5 files changed

+253
-0
lines changed

configure.py

+2
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ def has_re2c():
489489
'manifest_parser',
490490
'metrics',
491491
'state',
492+
'string_piece_util',
492493
'util',
493494
'version']:
494495
objs += cxx(name)
@@ -551,6 +552,7 @@ def has_re2c():
551552
'manifest_parser_test',
552553
'ninja_test',
553554
'state_test',
555+
'string_piece_util_test',
554556
'subprocess_test',
555557
'test',
556558
'util_test']:

src/string_piece.h

+10
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ using namespace std;
2525
/// externally. It is useful for reducing the number of std::strings
2626
/// we need to allocate.
2727
struct StringPiece {
28+
typedef const char* const_iterator;
29+
2830
StringPiece() : str_(NULL), len_(0) {}
2931

3032
/// The constructors intentionally allow for implicit conversions.
@@ -46,6 +48,14 @@ struct StringPiece {
4648
return len_ ? string(str_, len_) : string();
4749
}
4850

51+
const_iterator begin() const {
52+
return str_;
53+
}
54+
55+
const_iterator end() const {
56+
return str_ + len_;
57+
}
58+
4959
const char* str_;
5060
size_t len_;
5161
};

src/string_piece_util.cc

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2017 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "string_piece_util.h"
16+
17+
#include <algorithm>
18+
#include <string>
19+
#include <vector>
20+
using namespace std;
21+
22+
vector<StringPiece> SplitStringPiece(StringPiece input, char sep) {
23+
vector<StringPiece> elems;
24+
elems.reserve(count(input.begin(), input.end(), sep) + 1);
25+
26+
StringPiece::const_iterator pos = input.begin();
27+
28+
for (;;) {
29+
const char* next_pos = find(pos, input.end(), sep);
30+
if (next_pos == input.end()) {
31+
elems.push_back(StringPiece(pos, input.end() - pos));
32+
break;
33+
}
34+
elems.push_back(StringPiece(pos, next_pos - pos));
35+
pos = next_pos + 1;
36+
}
37+
38+
return elems;
39+
}
40+
41+
string JoinStringPiece(const vector<StringPiece>& list, char sep) {
42+
if (list.size() == 0){
43+
return "";
44+
}
45+
46+
string ret;
47+
48+
{
49+
size_t cap = list.size() - 1;
50+
for (size_t i = 0; i < list.size(); ++i) {
51+
cap += list[i].len_;
52+
}
53+
ret.reserve(cap);
54+
}
55+
56+
for (size_t i = 0; i < list.size(); ++i) {
57+
if (i != 0) {
58+
ret += sep;
59+
}
60+
ret.append(list[i].str_, list[i].len_);
61+
}
62+
63+
return ret;
64+
}
65+
66+
bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) {
67+
if (a.len_ != b.len_) {
68+
return false;
69+
}
70+
71+
for (size_t i = 0; i < a.len_; ++i) {
72+
if (ToLowerASCII(a.str_[i]) != ToLowerASCII(b.str_[i])) {
73+
return false;
74+
}
75+
}
76+
77+
return true;
78+
}

src/string_piece_util.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2017 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef NINJA_STRINGPIECE_UTIL_H_
16+
#define NINJA_STRINGPIECE_UTIL_H_
17+
18+
#include <string>
19+
#include <vector>
20+
21+
#include "string_piece.h"
22+
using namespace std;
23+
24+
vector<StringPiece> SplitStringPiece(StringPiece input, char sep);
25+
26+
string JoinStringPiece(const vector<StringPiece>& list, char sep);
27+
28+
inline char ToLowerASCII(char c) {
29+
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
30+
}
31+
32+
bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b);
33+
34+
#endif // NINJA_STRINGPIECE_UTIL_H_

src/string_piece_util_test.cc

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright 2017 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "string_piece_util.h"
16+
17+
#include "test.h"
18+
19+
TEST(StringPieceUtilTest, SplitStringPiece) {
20+
{
21+
string input("a:b:c");
22+
vector<StringPiece> list = SplitStringPiece(input, ':');
23+
24+
EXPECT_EQ(list.size(), 3);
25+
26+
EXPECT_EQ(list[0], "a");
27+
EXPECT_EQ(list[1], "b");
28+
EXPECT_EQ(list[2], "c");
29+
}
30+
31+
{
32+
string empty("");
33+
vector<StringPiece> list = SplitStringPiece(empty, ':');
34+
35+
EXPECT_EQ(list.size(), 1);
36+
37+
EXPECT_EQ(list[0], "");
38+
}
39+
40+
{
41+
string one("a");
42+
vector<StringPiece> list = SplitStringPiece(one, ':');
43+
44+
EXPECT_EQ(list.size(), 1);
45+
46+
EXPECT_EQ(list[0], "a");
47+
}
48+
49+
{
50+
string sep_only(":");
51+
vector<StringPiece> list = SplitStringPiece(sep_only, ':');
52+
53+
EXPECT_EQ(list.size(), 2);
54+
55+
EXPECT_EQ(list[0], "");
56+
EXPECT_EQ(list[1], "");
57+
}
58+
59+
{
60+
string sep(":a:b:c:");
61+
vector<StringPiece> list = SplitStringPiece(sep, ':');
62+
63+
EXPECT_EQ(list.size(), 5);
64+
65+
EXPECT_EQ(list[0], "");
66+
EXPECT_EQ(list[1], "a");
67+
EXPECT_EQ(list[2], "b");
68+
EXPECT_EQ(list[3], "c");
69+
EXPECT_EQ(list[4], "");
70+
}
71+
}
72+
73+
TEST(StringPieceUtilTest, JoinStringPiece) {
74+
{
75+
string input("a:b:c");
76+
vector<StringPiece> list = SplitStringPiece(input, ':');
77+
78+
EXPECT_EQ("a:b:c", JoinStringPiece(list, ':'));
79+
EXPECT_EQ("a/b/c", JoinStringPiece(list, '/'));
80+
}
81+
82+
{
83+
string empty("");
84+
vector<StringPiece> list = SplitStringPiece(empty, ':');
85+
86+
EXPECT_EQ("", JoinStringPiece(list, ':'));
87+
}
88+
89+
{
90+
vector<StringPiece> empty_list;
91+
92+
EXPECT_EQ("", JoinStringPiece(empty_list, ':'));
93+
}
94+
95+
{
96+
string one("a");
97+
vector<StringPiece> single_list = SplitStringPiece(one, ':');
98+
99+
EXPECT_EQ("a", JoinStringPiece(single_list, ':'));
100+
}
101+
102+
{
103+
string sep(":a:b:c:");
104+
vector<StringPiece> list = SplitStringPiece(sep, ':');
105+
106+
EXPECT_EQ(":a:b:c:", JoinStringPiece(list, ':'));
107+
}
108+
}
109+
110+
TEST(StringPieceUtilTest, ToLowerASCII) {
111+
EXPECT_EQ('a', ToLowerASCII('A'));
112+
EXPECT_EQ('z', ToLowerASCII('Z'));
113+
EXPECT_EQ('a', ToLowerASCII('a'));
114+
EXPECT_EQ('z', ToLowerASCII('z'));
115+
EXPECT_EQ('/', ToLowerASCII('/'));
116+
EXPECT_EQ('1', ToLowerASCII('1'));
117+
}
118+
119+
TEST(StringPieceUtilTest, EqualsCaseInsensitiveASCII) {
120+
EXPECT_TRUE(EqualsCaseInsensitiveASCII("abc", "abc"));
121+
EXPECT_TRUE(EqualsCaseInsensitiveASCII("abc", "ABC"));
122+
EXPECT_TRUE(EqualsCaseInsensitiveASCII("abc", "aBc"));
123+
EXPECT_TRUE(EqualsCaseInsensitiveASCII("AbC", "aBc"));
124+
EXPECT_TRUE(EqualsCaseInsensitiveASCII("", ""));
125+
126+
EXPECT_FALSE(EqualsCaseInsensitiveASCII("a", "ac"));
127+
EXPECT_FALSE(EqualsCaseInsensitiveASCII("/", "\\"));
128+
EXPECT_FALSE(EqualsCaseInsensitiveASCII("1", "10"));
129+
}

0 commit comments

Comments
 (0)