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
75da0bec
Commit
75da0bec
authored
Apr 16, 2019
by
zhujiashun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support_kv_pair_splitter: add basic features
parent
1ebba7f7
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
152 additions
and
72 deletions
+152
-72
uri.cpp
src/brpc/uri.cpp
+0
-13
uri.h
src/brpc/uri.h
+10
-59
string_splitter.h
src/butil/string_splitter.h
+77
-0
string_splitter_inl.h
src/butil/string_splitter_inl.h
+13
-0
string_splitter_unittest.cpp
test/string_splitter_unittest.cpp
+52
-0
No files found.
src/brpc/uri.cpp
View file @
75da0bec
...
...
@@ -407,19 +407,6 @@ void URI::SetH2Path(const char* h2_path) {
}
}
void
QuerySplitter
::
split
()
{
butil
::
StringPiece
query_pair
(
_sp
.
field
(),
_sp
.
length
());
const
size_t
pos
=
query_pair
.
find
(
'='
);
if
(
pos
==
butil
::
StringPiece
::
npos
)
{
_key
=
query_pair
;
_value
.
clear
();
}
else
{
_key
=
query_pair
.
substr
(
0
,
pos
);
_value
=
query_pair
.
substr
(
pos
+
1
);
}
_is_split
=
true
;
}
QueryRemover
::
QueryRemover
(
const
std
::
string
*
str
)
:
_query
(
str
)
,
_qs
(
str
->
data
(),
str
->
data
()
+
str
->
size
())
...
...
src/brpc/uri.h
View file @
75da0bec
...
...
@@ -195,68 +195,19 @@ inline std::ostream& operator<<(std::ostream& os, const URI& uri) {
}
// Split query in the format of "key1=value1&key2&key3=value3"
// This class can also handle some exceptional cases, such as
// consecutive ampersand, only equal sign, only key and so on.
class
QuerySplitter
{
class
QuerySplitter
:
public
butil
::
KeyValuePairsSplitter
{
public
:
QuerySplitter
(
const
char
*
str_begin
,
const
char
*
str_end
)
:
_sp
(
str_begin
,
str_end
,
'&'
)
,
_is_split
(
false
)
{
}
QuerySplitter
(
const
char
*
str_begin
)
:
_sp
(
str_begin
,
'&'
)
,
_is_split
(
false
)
{
}
inline
QuerySplitter
(
const
char
*
str_begin
,
const
char
*
str_end
)
:
KeyValuePairsSplitter
(
str_begin
,
str_end
,
'='
,
'&'
)
{}
QuerySplitter
(
const
butil
::
StringPiece
&
sp
)
:
_sp
(
sp
.
begin
(),
sp
.
end
(),
'&'
)
,
_is_split
(
false
)
{
}
inline
QuerySplitter
(
const
char
*
str_begin
)
:
KeyValuePairsSplitter
(
str_begin
,
'='
,
'&'
)
{}
const
butil
::
StringPiece
&
key
()
{
if
(
!
_is_split
)
{
split
();
}
return
_key
;
}
const
butil
::
StringPiece
&
value
()
{
if
(
!
_is_split
)
{
split
();
}
return
_value
;
}
// Get the current value of key and value
// in the format of "key=value"
butil
::
StringPiece
key_and_value
(){
return
butil
::
StringPiece
(
_sp
.
field
(),
_sp
.
length
());
}
// Move splitter forward.
QuerySplitter
&
operator
++
()
{
++
_sp
;
_is_split
=
false
;
return
*
this
;
}
QuerySplitter
operator
++
(
int
)
{
QuerySplitter
tmp
=
*
this
;
operator
++
();
return
tmp
;
}
operator
const
void
*
()
const
{
return
_sp
;
}
private
:
void
split
();
private
:
butil
::
StringSplitter
_sp
;
butil
::
StringPiece
_key
;
butil
::
StringPiece
_value
;
bool
_is_split
;
inline
QuerySplitter
(
const
butil
::
StringPiece
&
sp
)
:
KeyValuePairsSplitter
(
sp
,
'='
,
'&'
)
{}
};
// A class to remove some specific keys in a query string,
...
...
src/butil/string_splitter.h
View file @
75da0bec
...
...
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stdint.h>
#include "butil/strings/string_piece.h"
// It's common to encode data into strings separated by special characters
// and decode them back, but functions such as `split_string' has to modify
...
...
@@ -159,6 +160,82 @@ private:
const
EmptyFieldAction
_empty_field_action
;
};
// 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.
class
KeyValuePairsSplitter
{
public
:
inline
KeyValuePairsSplitter
(
const
char
*
str_begin
,
const
char
*
str_end
,
char
key_value_delimiter
,
char
key_value_pair_delimiter
)
:
_sp
(
str_begin
,
str_end
,
key_value_pair_delimiter
)
,
_is_split
(
false
)
,
_key_value_delimiter
(
key_value_delimiter
)
{
}
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
)
{
}
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
)
{
}
inline
const
StringPiece
&
key
()
{
if
(
!
_is_split
)
{
split
();
}
return
_key
;
}
inline
const
StringPiece
&
value
()
{
if
(
!
_is_split
)
{
split
();
}
return
_value
;
}
// Get the current value of key and value
// in the format of "key=value"
inline
StringPiece
key_and_value
(){
return
StringPiece
(
_sp
.
field
(),
_sp
.
length
());
}
// Move splitter forward.
inline
KeyValuePairsSplitter
&
operator
++
()
{
++
_sp
;
_is_split
=
false
;
return
*
this
;
}
inline
KeyValuePairsSplitter
operator
++
(
int
)
{
KeyValuePairsSplitter
tmp
=
*
this
;
operator
++
();
return
tmp
;
}
inline
operator
const
void
*
()
const
{
return
_sp
;
}
private
:
inline
void
split
();
private
:
StringSplitter
_sp
;
StringPiece
_key
;
StringPiece
_value
;
bool
_is_split
;
const
char
_key_value_delimiter
;
};
}
// namespace butil
#include "butil/string_splitter_inl.h"
...
...
src/butil/string_splitter_inl.h
View file @
75da0bec
...
...
@@ -309,6 +309,19 @@ 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
);
}
_is_split
=
true
;
}
}
// namespace butil
#endif // BUTIL_STRING_SPLITTER_INL_H
test/string_splitter_unittest.cpp
View file @
75da0bec
...
...
@@ -321,4 +321,56 @@ TEST_F(StringSplitterTest, split_limit_len) {
ASSERT_FALSE
(
ss2
);
}
TEST_F
(
StringSplitterTest
,
key_value_pairs_splitter_sanity
)
{
std
::
string
kvstr
=
"key1=value1&key2=value2&key3=value3"
;
{
butil
::
KeyValuePairsSplitter
splitter
(
kvstr
,
'='
,
'&'
);
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key1"
);
ASSERT_EQ
(
splitter
.
value
(),
"value1"
);
++
splitter
;
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key2"
);
ASSERT_EQ
(
splitter
.
value
(),
"value2"
);
++
splitter
;
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key3"
);
ASSERT_EQ
(
splitter
.
value
(),
"value3"
);
++
splitter
;
ASSERT_FALSE
(
splitter
);
}
{
butil
::
KeyValuePairsSplitter
splitter
(
kvstr
.
data
(),
kvstr
.
data
()
+
kvstr
.
size
(),
'='
,
'&'
);
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key1"
);
ASSERT_EQ
(
splitter
.
value
(),
"value1"
);
++
splitter
;
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key2"
);
ASSERT_EQ
(
splitter
.
value
(),
"value2"
);
++
splitter
;
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key3"
);
ASSERT_EQ
(
splitter
.
value
(),
"value3"
);
++
splitter
;
ASSERT_FALSE
(
splitter
);
}
{
butil
::
KeyValuePairsSplitter
splitter
(
kvstr
.
c_str
(),
'='
,
'&'
);
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key1"
);
ASSERT_EQ
(
splitter
.
value
(),
"value1"
);
++
splitter
;
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key2"
);
ASSERT_EQ
(
splitter
.
value
(),
"value2"
);
++
splitter
;
ASSERT_TRUE
(
splitter
);
ASSERT_EQ
(
splitter
.
key
(),
"key3"
);
ASSERT_EQ
(
splitter
.
value
(),
"value3"
);
++
splitter
;
ASSERT_FALSE
(
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