Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
c43d848c
Commit
c43d848c
authored
Apr 16, 2019
by
zhujiashun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support_kv_pair_splitter: refactor key()/value() in StringSplitter && add comments
parent
75da0bec
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
65 additions
and
47 deletions
+65
-47
string_splitter.h
src/butil/string_splitter.h
+27
-27
string_splitter_inl.h
src/butil/string_splitter_inl.h
+21
-19
string_splitter_unittest.cpp
test/string_splitter_unittest.cpp
+17
-1
No files found.
src/butil/string_splitter.h
View file @
c43d848c
...
...
@@ -66,7 +66,10 @@ public:
// if str_end is not NULL.
inline
StringSplitter
(
const
char
*
str_begin
,
const
char
*
str_end
,
char
separator
,
EmptyFieldAction
=
SKIP_EMPTY_FIELD
);
EmptyFieldAction
action
=
SKIP_EMPTY_FIELD
);
// Allows containing embedded '\0' characters and separator can be '\0',
inline
StringSplitter
(
const
StringPiece
&
input
,
char
separator
,
EmptyFieldAction
action
=
SKIP_EMPTY_FIELD
);
// Move splitter forward.
inline
StringSplitter
&
operator
++
();
...
...
@@ -79,6 +82,7 @@ public:
// not be '\0' because we don't modify `input'.
inline
const
char
*
field
()
const
;
inline
size_t
length
()
const
;
inline
StringPiece
field_sp
()
const
;
// Cast field to specific type, and write the value into `pv'.
// Returns 0 on success, -1 otherwise.
...
...
@@ -133,6 +137,7 @@ public:
// not be '\0' because we don't modify `input'.
inline
const
char
*
field
()
const
;
inline
size_t
length
()
const
;
inline
StringPiece
field_sp
()
const
;
// Cast field to specific type, and write the value into `pv'.
// Returns 0 on success, -1 otherwise.
...
...
@@ -161,8 +166,14 @@ private:
};
// Split query in the format according to the given delimiters.
// This class can also handle some exceptional cases, such as
// consecutive ampersand, only equal sign, only key and so on.
// This class can also handle some exceptional cases.
// 1. consecutive key_value_pair_delimiter are omitted, for example,
// suppose key_value_delimiter is '=' and key_value_pair_delimiter
// is '&', then k1=v1&&&k2=v2 is normalized to k1=k2&k2=v2.
// 2. key or value can be empty or both can be empty
// 3. consecutive key_value_delimiter are not omitted, for example,
// suppose input is k1===v2 and key_value_delimiter is '=', then
// key() returns 'k1', value() returns '==v2'.
class
KeyValuePairsSplitter
{
public
:
inline
KeyValuePairsSplitter
(
const
char
*
str_begin
,
...
...
@@ -170,38 +181,29 @@ public:
char
key_value_delimiter
,
char
key_value_pair_delimiter
)
:
_sp
(
str_begin
,
str_end
,
key_value_pair_delimiter
)
,
_
is_split
(
false
)
,
_
deli_pos
(
StringPiece
::
npos
)
,
_key_value_delimiter
(
key_value_delimiter
)
{
UpdateDelimiterPos
();
}
inline
KeyValuePairsSplitter
(
const
char
*
str_begin
,
char
key_value_delimiter
,
char
key_value_pair_delimiter
)
:
_sp
(
str_begin
,
key_value_pair_delimiter
)
,
_is_split
(
false
)
,
_key_value_delimiter
(
key_value_delimiter
)
{
}
:
KeyValuePairsSplitter
(
str_begin
,
NULL
,
key_value_delimiter
,
key_value_pair_delimiter
)
{}
inline
KeyValuePairsSplitter
(
const
StringPiece
&
sp
,
char
key_value_delimiter
,
char
key_value_pair_delimiter
)
:
_sp
(
sp
.
begin
(),
sp
.
end
(),
key_value_pair_delimiter
)
,
_is_split
(
false
)
,
_key_value_delimiter
(
key_value_delimiter
)
{
}
:
KeyValuePairsSplitter
(
sp
.
begin
(),
sp
.
end
(),
key_value_delimiter
,
key_value_pair_delimiter
)
{}
inline
const
StringPiece
&
key
()
{
if
(
!
_is_split
)
{
split
();
}
return
_key
;
inline
StringPiece
key
()
{
return
StringPiece
(
_sp
.
field
(),
_sp
.
length
()).
substr
(
0
,
_deli_pos
);
}
inline
const
StringPiece
&
value
()
{
if
(
!
_is_split
)
{
split
();
}
return
_value
;
inline
StringPiece
value
()
{
return
StringPiece
(
_sp
.
field
(),
_sp
.
length
()).
substr
(
_deli_pos
+
1
);
}
// Get the current value of key and value
...
...
@@ -213,7 +215,7 @@ public:
// Move splitter forward.
inline
KeyValuePairsSplitter
&
operator
++
()
{
++
_sp
;
_is_split
=
false
;
UpdateDelimiterPos
()
;
return
*
this
;
}
...
...
@@ -226,13 +228,11 @@ public:
inline
operator
const
void
*
()
const
{
return
_sp
;
}
private
:
inline
void
split
();
inline
void
UpdateDelimiterPos
();
private
:
StringSplitter
_sp
;
StringPiece
_key
;
StringPiece
_value
;
bool
_is_split
;
StringPiece
::
size_type
_deli_pos
;
const
char
_key_value_delimiter
;
};
...
...
src/butil/string_splitter_inl.h
View file @
c43d848c
...
...
@@ -22,15 +22,6 @@
namespace
butil
{
StringSplitter
::
StringSplitter
(
const
char
*
str
,
char
sep
,
EmptyFieldAction
action
)
:
_head
(
str
)
,
_str_tail
(
NULL
)
,
_sep
(
sep
)
,
_empty_field_action
(
action
)
{
init
();
}
StringSplitter
::
StringSplitter
(
const
char
*
str_begin
,
const
char
*
str_end
,
const
char
sep
,
...
...
@@ -42,6 +33,14 @@ StringSplitter::StringSplitter(const char* str_begin,
init
();
}
StringSplitter
::
StringSplitter
(
const
char
*
str
,
char
sep
,
EmptyFieldAction
action
)
:
StringSplitter
(
str
,
NULL
,
sep
,
action
)
{}
StringSplitter
::
StringSplitter
(
const
StringPiece
&
input
,
char
sep
,
EmptyFieldAction
action
)
:
StringSplitter
(
input
.
data
(),
input
.
data
()
+
input
.
length
(),
sep
,
action
)
{}
void
StringSplitter
::
init
()
{
// Find the starting _head and _tail.
if
(
__builtin_expect
(
_head
!=
NULL
,
1
))
{
...
...
@@ -86,6 +85,10 @@ size_t StringSplitter::length() const {
return
static_cast
<
size_t
>
(
_tail
-
_head
);
}
StringPiece
StringSplitter
::
field_sp
()
const
{
return
StringPiece
(
field
(),
length
());
}
bool
StringSplitter
::
not_end
(
const
char
*
p
)
const
{
return
(
_str_tail
==
NULL
)
?
*
p
:
(
p
!=
_str_tail
);
}
...
...
@@ -233,6 +236,10 @@ size_t StringMultiSplitter::length() const {
return
static_cast
<
size_t
>
(
_tail
-
_head
);
}
StringPiece
StringMultiSplitter
::
field_sp
()
const
{
return
StringPiece
(
field
(),
length
());
}
bool
StringMultiSplitter
::
not_end
(
const
char
*
p
)
const
{
return
(
_str_tail
==
NULL
)
?
*
p
:
(
p
!=
_str_tail
);
}
...
...
@@ -309,17 +316,12 @@ int StringMultiSplitter::to_double(double* pv) const {
return
(
endptr
==
field
()
+
length
())
?
0
:
-
1
;
}
void
KeyValuePairsSplitter
::
split
()
{
StringPiece
query_pair
(
_sp
.
field
(),
_sp
.
length
());
const
size_t
pos
=
query_pair
.
find
(
'='
);
if
(
pos
==
StringPiece
::
npos
)
{
_key
=
query_pair
;
_value
.
clear
();
}
else
{
_key
=
query_pair
.
substr
(
0
,
pos
);
_value
=
query_pair
.
substr
(
pos
+
1
);
void
KeyValuePairsSplitter
::
UpdateDelimiterPos
()
{
StringPiece
key_value_pair
(
_sp
.
field
(),
_sp
.
length
());
_deli_pos
=
key_value_pair
.
find
(
_key_value_delimiter
);
if
(
_deli_pos
==
StringPiece
::
npos
)
{
_deli_pos
=
key_value_pair
.
length
();
}
_is_split
=
true
;
}
}
// namespace butil
...
...
test/string_splitter_unittest.cpp
View file @
c43d848c
...
...
@@ -319,10 +319,26 @@ TEST_F(StringSplitterTest, split_limit_len) {
++
ss2
;
ASSERT_FALSE
(
ss2
);
butil
::
StringPiece
sp
(
str
,
5
);
// Allows using '\0' as separator
butil
::
StringSplitter
ss3
(
sp
,
'\0'
);
ASSERT_TRUE
(
ss3
);
ASSERT_EQ
(
3ul
,
ss3
.
length
());
ASSERT_FALSE
(
strncmp
(
ss3
.
field
(),
"1
\t
1"
,
ss3
.
length
()));
++
ss3
;
ASSERT_TRUE
(
ss3
);
ASSERT_EQ
(
1ul
,
ss3
.
length
());
ASSERT_FALSE
(
strncmp
(
ss3
.
field
(),
"3"
,
ss3
.
length
()));
++
ss3
;
ASSERT_FALSE
(
ss3
);
}
TEST_F
(
StringSplitterTest
,
key_value_pairs_splitter_sanity
)
{
std
::
string
kvstr
=
"key1=value1&key2=value2&key3=value3"
;
std
::
string
kvstr
=
"key1=value1&
&&
key2=value2&key3=value3"
;
{
butil
::
KeyValuePairsSplitter
splitter
(
kvstr
,
'='
,
'&'
);
ASSERT_TRUE
(
splitter
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment