Skip to content

Commit 2ebcb09

Browse files
author
Ivan Baidakou
committed
Further optimisation
1 parent 426dbfc commit 2ebcb09

File tree

1 file changed

+69
-75
lines changed

1 file changed

+69
-75
lines changed

include/bredis/impl/protocol.ipp

Lines changed: 69 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ template <typename Iterator, typename Policy>
7171
parse_result_t<Iterator, Policy> raw_parse(const Iterator &from,
7272
const Iterator &to);
7373

74+
struct count_value_t {
75+
size_t value;
76+
size_t consumed;
77+
};
78+
79+
template <typename Iterator, typename Policy>
80+
using count_variant_t =
81+
boost::variant<count_value_t, parse_result_t<Iterator, Policy>>;
82+
7483
template <typename Iterator, typename Policy> struct markup_helper_t {
7584
using result_wrapper_t = parse_result_t<Iterator, Policy>;
7685
using positive_wrapper_t = parse_result_mapper_t<Iterator, Policy>;
@@ -172,22 +181,47 @@ struct array_helper_t<Iterator, parsing_policy::drop_result> {
172181
result_t get() { return result_t{item_t{consumed_}}; }
173182
};
174183

175-
template <typename Iterator, typename Policy> struct unwrap_error_t {
176-
using wrapped_result_t = parse_result_t<Iterator, Policy>;
184+
template <typename Iterator, typename Policy>
185+
struct unwrap_count_t
186+
: public boost::static_visitor<count_variant_t<Iterator, Policy>> {
187+
using wrapped_result_t = count_variant_t<Iterator, Policy>;
188+
using negative_result_t = parse_result_t<Iterator, Policy>;
189+
using positive_input_t =
190+
parse_result_mapper_t<Iterator, parsing_policy::keep_result>;
177191

178192
wrapped_result_t operator()(const not_enough_data_t &value) const {
179-
return value;
193+
return wrapped_result_t{negative_result_t{value}};
180194
}
181195

182196
wrapped_result_t operator()(const protocol_error_t &value) const {
183-
return value;
197+
return wrapped_result_t{negative_result_t{value}};
184198
}
185199

186-
template <typename Parser>
187-
wrapped_result_t operator()(const Parser &ignored) const {
188-
assert("non-reacheable code");
189-
return protocol_error_t{
190-
Error::make_error_code(bredis_errors::parser_error)};
200+
wrapped_result_t operator()(const positive_input_t &value) const {
201+
using string_t = markers::string_t<Iterator>;
202+
using helper = markup_helper_t<Iterator, Policy>;
203+
204+
auto &count_string_ref = boost::get<string_t>(value.result);
205+
std::string count_string{count_string_ref.from, count_string_ref.to};
206+
auto count_consumed = value.consumed;
207+
const char *count_ptr = count_string.c_str();
208+
char *count_end;
209+
210+
errno = 0;
211+
long count = strtol(count_ptr, &count_end, 10);
212+
if (errno) {
213+
return wrapped_result_t{protocol_error_t{
214+
Error::make_error_code(bredis_errors::count_conversion)}};
215+
} else if (count == -1) {
216+
return helper::markup_nil(count_consumed, count_string_ref);
217+
} else if (count < -1) {
218+
return wrapped_result_t{protocol_error_t{
219+
Error::make_error_code(bredis_errors::count_range)}};
220+
}
221+
222+
return wrapped_result_t{
223+
count_value_t{static_cast<size_t>(count), count_consumed},
224+
};
191225
}
192226
};
193227

@@ -250,57 +284,35 @@ template <typename Iterator, typename Policy> struct bulk_string_parser_t {
250284
-> parse_result_t<Iterator, Policy> {
251285

252286
using helper = markup_helper_t<Iterator, Policy>;
287+
using count_unwrapper_t = unwrap_count_t<Iterator, Policy>;
253288
using keep_policy = parsing_policy::keep_result;
254-
using wrapped_string_t = parse_result_mapper_t<Iterator, keep_policy>;
255289
using count_parser_t = string_parser_t<Iterator, keep_policy>;
256-
using count_unwrapper_t = unwrap_error_t<Iterator, Policy>;
257-
using string_t = markers::string_t<Iterator>;
258-
using array_helper = array_helper_t<Iterator, Policy>;
259-
using element_t = parse_result_mapper_t<Iterator, Policy>;
260-
261-
auto count_result = count_parser_t::apply(from, to, 0);
262-
auto *count_string_wrapped =
263-
boost::get<wrapped_string_t>(&count_result);
264-
if (!count_string_wrapped) {
265-
return boost::apply_visitor(count_unwrapper_t{}, count_result);
266-
}
267-
auto &count_string_ref =
268-
boost::get<string_t>(count_string_wrapped->result);
269-
std::string count_string{count_string_ref.from, count_string_ref.to};
270-
auto count_consumed = count_string_wrapped->consumed;
271-
const char *count_ptr = count_string.c_str();
272-
char *count_end;
273-
274-
errno = 0;
275-
long count = strtol(count_ptr, &count_end, 10);
276-
if (errno) {
277-
return protocol_error_t{
278-
Error::make_error_code(bredis_errors::count_conversion)};
279-
} else if (count == -1) {
280-
size_t consumed = count_consumed + already_consumed;
281-
return helper::markup_nil(consumed, count_string_ref);
282-
} else if (count < -1) {
283-
return protocol_error_t{
284-
Error::make_error_code(bredis_errors::count_range)};
290+
using result_t = parse_result_t<Iterator, Policy>;
291+
292+
auto count_result = count_parser_t::apply(from, to, already_consumed);
293+
auto count_int_result =
294+
boost::apply_visitor(count_unwrapper_t{}, count_result);
295+
auto *count_wrapped = boost::get<count_value_t>(&count_int_result);
296+
if (!count_wrapped) {
297+
return boost::get<result_t>(count_int_result);
285298
}
286299

287-
auto head = from + count_consumed;
300+
auto head = from + (count_wrapped->consumed - already_consumed);
288301
size_t left = std::distance(head, to);
289-
size_t ucount = static_cast<size_t>(count);
302+
size_t count = count_wrapped->value;
290303
auto terminator_size = terminator.size;
291-
if (left < ucount + terminator_size) {
304+
if (left < count + terminator_size) {
292305
return not_enough_data_t{};
293306
}
294-
auto tail = head + ucount;
307+
auto tail = head + count;
295308
auto tail_end = tail + terminator_size;
296309

297310
bool found_terminator = terminator.equal(tail, tail_end);
298311
if (!found_terminator) {
299312
return protocol_error_t{
300313
Error::make_error_code(bredis_errors::bulk_terminator)};
301314
}
302-
size_t consumed =
303-
count_consumed + ucount + terminator_size + already_consumed;
315+
size_t consumed = count_wrapped->consumed + count + terminator_size;
304316

305317
return helper::markup_string(consumed, head, tail);
306318
}
@@ -312,44 +324,26 @@ template <typename Iterator, typename Policy> struct array_parser_t {
312324
-> parse_result_t<Iterator, Policy> {
313325

314326
using helper = markup_helper_t<Iterator, Policy>;
327+
using count_unwrapper_t = unwrap_count_t<Iterator, Policy>;
328+
using result_t = parse_result_t<Iterator, Policy>;
315329
using keep_policy = parsing_policy::keep_result;
316-
using wrapped_string_t = parse_result_mapper_t<Iterator, keep_policy>;
317330
using count_parser_t = string_parser_t<Iterator, keep_policy>;
318-
using count_unwrapper_t = unwrap_error_t<Iterator, Policy>;
319-
using string_t = markers::string_t<Iterator>;
320331
using array_helper = array_helper_t<Iterator, Policy>;
321332
using element_t = parse_result_mapper_t<Iterator, Policy>;
322333

323-
auto count_result = count_parser_t::apply(from, to, 0);
324-
auto *count_string_wrapped =
325-
boost::get<wrapped_string_t>(&count_result);
326-
if (!count_string_wrapped) {
327-
return boost::apply_visitor(count_unwrapper_t{}, count_result);
328-
}
329-
auto &count_string_ref =
330-
boost::get<string_t>(count_string_wrapped->result);
331-
std::string count_string{count_string_ref.from, count_string_ref.to};
332-
auto count_consumed = count_string_wrapped->consumed;
333-
const char *count_ptr = count_string.c_str();
334-
char *count_end;
335-
336-
errno = 0;
337-
long count = strtol(count_ptr, &count_end, 10);
338-
if (errno) {
339-
return protocol_error_t{
340-
Error::make_error_code(bredis_errors::count_conversion)};
341-
} else if (count == -1) {
342-
size_t consumed = count_consumed + already_consumed;
343-
return helper::markup_nil(consumed, count_string_ref);
344-
} else if (count < -1) {
345-
return protocol_error_t{
346-
Error::make_error_code(bredis_errors::count_range)};
334+
auto count_result = count_parser_t::apply(from, to, already_consumed);
335+
auto count_int_result =
336+
boost::apply_visitor(count_unwrapper_t{}, count_result);
337+
auto *count_wrapped = boost::get<count_value_t>(&count_int_result);
338+
if (!count_wrapped) {
339+
return boost::get<result_t>(count_int_result);
347340
}
348341

349-
array_helper elements{already_consumed + count_consumed,
350-
static_cast<size_t>(count)};
342+
auto count = count_wrapped->value;
343+
array_helper elements{count_wrapped->consumed, count};
351344
long marked_elements{0};
352-
Iterator element_from = from + count_consumed;
345+
Iterator element_from =
346+
from + (count_wrapped->consumed - already_consumed);
353347
while (marked_elements < count) {
354348
auto element_result = raw_parse<Iterator, Policy>(element_from, to);
355349
auto *element = boost::get<element_t>(&element_result);

0 commit comments

Comments
 (0)