@@ -71,6 +71,15 @@ template <typename Iterator, typename Policy>
7171parse_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+
7483template <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