Skip to content

Commit 1b6a4f4

Browse files
AndreyTokmakovgittiver
authored andcommitted
Get rid of unnecessary string copies in the the keys() method
1 parent 4fbd9b4 commit 1b6a4f4

File tree

3 files changed

+62
-11
lines changed

3 files changed

+62
-11
lines changed

include/crow/query_string.h

+16-11
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ inline size_t qs_parse(char* qs, char* qs_kv[], size_t qs_kv_size, bool parse_ur
138138
#endif
139139

140140
return i;
141-
}
141+
}
142142

143143

144144
inline int qs_decode(char * qs)
@@ -295,9 +295,7 @@ namespace crow
295295
public:
296296
static const int MAX_KEY_VALUE_PAIRS_COUNT = 256;
297297

298-
query_string()
299-
{
300-
}
298+
query_string() = default;
301299

302300
query_string(const query_string& qs):
303301
url_(qs.url_)
@@ -319,7 +317,7 @@ namespace crow
319317
return *this;
320318
}
321319

322-
query_string& operator=(query_string&& qs)
320+
query_string& operator=(query_string&& qs) noexcept
323321
{
324322
key_value_pairs_ = std::move(qs.key_value_pairs_);
325323
char* old_data = (char*)qs.url_.c_str();
@@ -339,9 +337,10 @@ namespace crow
339337
return;
340338

341339
key_value_pairs_.resize(MAX_KEY_VALUE_PAIRS_COUNT);
342-
343340
size_t count = qs_parse(&url_[0], &key_value_pairs_[0], MAX_KEY_VALUE_PAIRS_COUNT, url);
341+
344342
key_value_pairs_.resize(count);
343+
key_value_pairs_.shrink_to_fit();
345344
}
346345

347346
void clear()
@@ -472,13 +471,19 @@ namespace crow
472471

473472
std::vector<std::string> keys() const
474473
{
475-
std::vector<std::string> ret;
476-
for (auto element : key_value_pairs_)
474+
std::vector<std::string> keys;
475+
keys.reserve(key_value_pairs_.size());
476+
477+
for (const char* const element : key_value_pairs_)
477478
{
478-
std::string str_element(element);
479-
ret.emplace_back(str_element.substr(0, str_element.find('=')));
479+
const char* delimiter = strchr(element, '=');
480+
if (delimiter)
481+
keys.emplace_back(element, delimiter);
482+
else
483+
keys.emplace_back(element);
480484
}
481-
return ret;
485+
486+
return keys;
482487
}
483488

484489
private:

tests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ enable_testing()
77

88
set(TEST_SRCS
99
unittest.cpp
10+
query_string_tests.cpp
1011
)
1112

1213
add_executable(unittest ${TEST_SRCS})

tests/query_string_tests.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
#include <iostream>
3+
#include <vector>
4+
5+
#include "catch.hpp"
6+
#include "crow/query_string.h"
7+
8+
namespace
9+
{
10+
std::string buildQueryStr(const std::vector<std::pair<std::string, std::string>>& paramList)
11+
{
12+
std::string paramsStr{};
13+
for (const auto& param : paramList)
14+
paramsStr.append(param.first).append(1, '=').append(param.second).append(1, '&');
15+
if (!paramsStr.empty())
16+
paramsStr.resize(paramsStr.size() - 1);
17+
return paramsStr;
18+
}
19+
}
20+
21+
TEST_CASE( "empty query params" )
22+
{
23+
const crow::query_string query_params("");
24+
const std::vector<std::string> keys = query_params.keys();
25+
26+
REQUIRE(keys.empty() == true);
27+
}
28+
29+
TEST_CASE( "query string keys" )
30+
{
31+
const std::vector<std::pair<std::string, std::string>> params {
32+
{"foo", "bar"}, {"mode", "night"}, {"page", "2"},
33+
{"tag", "js"}, {"name", "John Smith"}, {"age", "25"},
34+
};
35+
36+
const crow::query_string query_params("params?" + buildQueryStr(params));
37+
const std::vector<std::string> keys = query_params.keys();
38+
39+
for (const auto& entry: params)
40+
{
41+
const bool exist = std::any_of(keys.cbegin(), keys.cend(), [&](const std::string& key) {
42+
return key == entry.first;});
43+
REQUIRE(exist == true);
44+
}
45+
}

0 commit comments

Comments
 (0)