RESTinio
basics.hpp
Go to the documentation of this file.
1 /*
2  * RESTinio
3  */
4 
5 /*!
6  * @file
7  * @brief Utilities for parsing values of http-fields
8  *
9  * @since v.0.6.1
10  */
11 
12 #pragma once
13 
14 #include <restinio/impl/string_caseless_compare.hpp>
15 
16 #include <restinio/helpers/easy_parser.hpp>
17 
18 #include <restinio/expected.hpp>
19 
20 #include <algorithm>
21 
22 namespace restinio
23 {
24 
25 namespace http_field_parsers
26 {
27 
28 using namespace restinio::easy_parser;
29 
30 namespace meta = restinio::utils::metaprogramming;
31 
32 namespace qvalue_details
33 {
34 
35 //! A type to hold a qvalue.
37 
38 //! The maximal allowed value for a qvalue.
39 constexpr underlying_uint_t maximum = 1000u;
40 //! The minimal allowed value for a qvalue.
41 constexpr underlying_uint_t zero = 0u;
42 
43 // A part of workaround for problem with static constexpr members
44 // detected after release of v.0.6.1.
45 enum class extremum_min_t { v };
46 enum class extremum_max_t { v };
47 
48 //! A helper wrapper to indicate that value is already checked and
49 //! shouldn't be checked again.
50 class trusted
51 {
53 
54 public :
55  explicit constexpr
56  trusted( underlying_uint_t value ) noexcept : m_value{ value } {}
57 
58  constexpr auto get() const noexcept { return m_value; }
59 };
60 
61 //! A helper wrapper to indicate that value hasn't been checked yet
62 //! and should be checked in the constructor of qvalue.
63 class untrusted
64 {
66 
67 public :
68  explicit
69  untrusted( underlying_uint_t value ) : m_value{ value }
70  {
71  if( m_value > maximum )
72  throw exception_t( "invalid value for "
73  "http_field_parser::rfc::qvalue_t" );
74  }
75 
76  auto get() const noexcept { return m_value; }
77 };
78 
79 } /* namespace qvalue_details */
80 
81 //
82 // qvalue_t
83 //
84 /*!
85  * @brief A class for holding the parsed value of qvalue from RFC7231.
86  *
87  * An important note: qvalue in RFC7231 is defined as a number with
88  * fractional point. This number can have no more that three digits
89  * after a point. And the non-factional part can only be 0 or 1. If
90  * non-frational part is 1 then fractional part can only be 0. It means
91  * that qvalue can be in the range [0.000, 1.000].
92  *
93  * To simplify work with qvalue RESTinio holds qvalue as a small integer
94  * in the range [0, 1000] where 0 corresponds to 0.000 and 1000 corresponds
95  * to 1.000. In means, for example, that value 0.05 will be represented and 50,
96  * and the value 0.001 will be represented as 1, and the value 0.901 will
97  * be represented as 901.
98  *
99  * The integer representation of qvalue can be obtained via as_uint()
100  * method.
101  *
102  * Method as_string() returns std::string with number with fractional
103  * part inside. It means:
104  * @code
105  * assert("1.000" == qvalue_t{qvalue_t::maximum}.as_string());
106  * assert("0.901" == qvalue_t{qvalue_t::untrusted{901}}.as_string());
107  * @endcode
108  * Such representation is also used in `operator<<` for std::ostream.
109  *
110  * Instances of qvalue_t can be compared, operations `==`, `!=`, `<` and `<=`
111  * are supported.
112  *
113  * There are two ways to construct a new qvalue object.
114  *
115  * The first and recommended way is intended for cases when the source
116  * value for a new qvalue object isn't known at the compile-time and
117  * produced somehow at the run-time. It's the usage of qvalue_t::untrusted
118  * wrapper:
119  * @code
120  * qvalue_t weight{qvalue_t::untrusted{config.default_weigh() * 10}};
121  * @endcode
122  * In that case the value of `untrusted` will be checked in
123  * qvalue_t::untrusted's constructor and an exception will be thrown if that
124  * value isn't in [0, 1000] range.
125  *
126  * The second way is intended to be used with compile-time constants:
127  * @code
128  * qvalue_t weight{qvalue_t::trusted{250}};
129  * @endcode
130  * In the case of `trusted` the value is not checked in qvalue_t's
131  * constructor. Therefore that way should be used with additional care.
132  *
133  * @since v.0.6.1
134  */
135 class qvalue_t
136 {
137 public :
138  //! The type of underlying small integer.
140  //! The type that doesn't check a value to be used for qvalue.
141  using trusted = qvalue_details::trusted;
142  //! The type that checks a value to be used for qvalue.
143  using untrusted = qvalue_details::untrusted;
144 
145  //! The indicator that tells that new qvalue object should have
146  //! the maximal allowed value.
149  //! The indicator that tells that new qvalue object should have
150  //! the minimal allowed value.
151  static constexpr qvalue_details::extremum_min_t zero =
153 
154 private :
155  // Note: with the terminal 0-symbol.
156  using underlying_char_array_t = std::array<char, 6>;
157 
159 
161  make_char_array() const noexcept
162  {
163  underlying_char_array_t result;
164  if( qvalue_details::maximum == m_value )
165  {
166  static constexpr char fixed_value[]{ "1.000" };
167  std::copy( std::begin(fixed_value), std::end(fixed_value),
168  std::begin(result) );
169  }
170  else
171  {
172  result[0] = '0';
173  result[1] = '.';
174 
175  result[2] = '0' + static_cast<char>(m_value / 100u);
176  const auto d2 = m_value % 100u;
177  result[3] = '0' + static_cast<char>(d2 / 10u);
178  const auto d3 = d2 % 10u;
179  result[4] = '0' + static_cast<char>(d3);
180  result[5] = 0;
181  }
182 
183  return result;
184  }
185 
186 public :
187 
188  constexpr qvalue_t() = default;
189 
190  qvalue_t( untrusted val ) noexcept
191  : m_value{ val.get() }
192  {}
193 
194  constexpr qvalue_t( trusted val ) noexcept
195  : m_value{ val.get() }
196  {}
197 
198  constexpr qvalue_t( qvalue_details::extremum_min_t ) noexcept
200  {}
201 
202  constexpr qvalue_t( qvalue_details::extremum_max_t ) noexcept
204  {}
205 
206  constexpr auto as_uint() const noexcept { return m_value; }
207 
208  auto as_string() const
209  {
210  return std::string{ &make_char_array().front() };
211  }
212 
213  friend std::ostream &
214  operator<<( std::ostream & to, const qvalue_t & what )
215  {
216  return (to << &what.make_char_array().front());
217  }
218 };
219 
220 [[nodiscard]]
221 inline bool
222 operator==( const qvalue_t & a, const qvalue_t & b ) noexcept
223 {
224  return a.as_uint() == b.as_uint();
225 }
226 
227 [[nodiscard]]
228 inline bool
229 operator!=( const qvalue_t & a, const qvalue_t & b ) noexcept
230 {
231  return a.as_uint() != b.as_uint();
232 }
233 
234 [[nodiscard]]
235 inline bool
236 operator<( const qvalue_t & a, const qvalue_t & b ) noexcept
237 {
238  return a.as_uint() < b.as_uint();
239 }
240 
241 [[nodiscard]]
242 inline bool
243 operator<=( const qvalue_t & a, const qvalue_t & b ) noexcept
244 {
245  return a.as_uint() <= b.as_uint();
246 }
247 
248 namespace impl
249 {
250 
251 using namespace restinio::easy_parser::impl;
252 
253 //
254 // is_alpha
255 //
256 /*!
257  * @brief Is a character an ALPHA?
258  *
259  * See: https://tools.ietf.org/html/rfc5234#appendix-B.1
260  *
261  * @since v.0.6.1
262  */
263 [[nodiscard]]
264 inline constexpr bool
265 is_alpha( const char ch ) noexcept
266 {
267  return (ch >= '\x41' && ch <= '\x5A') ||
268  (ch >= '\x61' && ch <= '\x7A');
269 }
270 
271 //
272 // is_alpha_predicate_t
273 //
274 /*!
275  * @brief A preducate for symbol_producer_template that checks that
276  * a symbol is an alpha.
277  *
278  * @since v.0.6.2
279  */
281 {
282  [[nodiscard]]
283  bool
284  operator()( const char actual ) const noexcept
285  {
286  return is_alpha(actual);
287  }
288 };
289 
290 //
291 // is_alphanum_predicate_t
292 //
293 /*!
294  * @brief A preducate for symbol_producer_template that checks that
295  * a symbol is an alpha or numeric.
296  *
297  * @since v.0.6.2
298  */
300 {
301  [[nodiscard]]
302  bool
303  operator()( const char actual ) const noexcept
304  {
305  return is_alpha(actual) || is_digit(actual);
306  }
307 };
308 
309 //
310 // is_vchar
311 //
312 /*!
313  * @brief Is a character a VCHAR?
314  *
315  * See: https://tools.ietf.org/html/rfc5234#appendix-B.1
316  *
317  * @since v.0.6.1
318  */
319 [[nodiscard]]
320 inline constexpr bool
321 is_vchar( const char ch ) noexcept
322 {
323  return (ch >= '\x21' && ch <= '\x7E');
324 }
325 
326 //
327 // is_vchar_predicate_t
328 //
329 /*!
330  * @brief A preducate for symbol_producer_template that checks that
331  * a symbol is a VCHAR.
332  *
333  * @since v.0.6.2
334  */
336 {
337  [[nodiscard]]
338  bool
339  operator()( const char actual ) const noexcept
340  {
341  return is_vchar(actual);
342  }
343 };
344 
345 //
346 // is_obs_text
347 //
348 /*!
349  * @brief Is a character an obs_text?
350  *
351  * See: https://tools.ietf.org/html/rfc7230
352  *
353  * @since v.0.6.1
354  */
355 [[nodiscard]]
356 inline constexpr bool
357 is_obs_text( const char ch ) noexcept
358 {
359  constexpr unsigned short left = 0x80u;
360  constexpr unsigned short right = 0xFFu;
361 
362  const unsigned short t = static_cast<unsigned short>(
363  static_cast<unsigned char>(ch));
364 
365  return (t >= left && t <= right);
366 }
367 
368 //
369 // is_qdtext
370 //
371 /*!
372  * @brief Is a character a qdtext?
373  *
374  * See: https://tools.ietf.org/html/rfc7230
375  *
376  * @since v.0.6.1
377  */
378 [[nodiscard]]
379 inline constexpr bool
380 is_qdtext( const char ch ) noexcept
381 {
382  return ch == SP ||
383  ch == HTAB ||
384  ch == '!' ||
385  (ch >= '\x23' && ch <= '\x5B') ||
386  (ch >= '\x5D' && ch <= '\x7E') ||
387  is_obs_text( ch );
388 }
389 
390 //
391 // is_ctext
392 //
393 /*!
394  * @brief Is a character a ctext?
395  *
396  * See: https://tools.ietf.org/html/rfc7230
397  *
398  * @since v.0.6.4
399  */
400 [[nodiscard]]
401 inline constexpr bool
402 is_ctext( const char ch ) noexcept
403 {
404  return ch == SP ||
405  ch == HTAB ||
406  (ch >= '\x21' && ch <= '\x27') ||
407  (ch >= '\x2A' && ch <= '\x5B') ||
408  (ch >= '\x5D' && ch <= '\x7E') ||
409  is_obs_text( ch );
410 }
411 
412 //
413 // is_ctext_predicate_t
414 //
415 /*!
416  * @brief A preducate for symbol_producer_template that checks that
417  * a symbol is a ctext.
418  *
419  * @since v.0.6.4
420  */
422 {
423  [[nodiscard]]
424  bool
425  operator()( const char actual ) const noexcept
426  {
427  return is_ctext(actual);
428  }
429 };
430 
431 //
432 // is_token_char_predicate_t
433 //
434 /*!
435  * @brief A predicate for symbol_producer_template that checks that
436  * a symbol can be used inside a token.
437  */
439 {
440  [[nodiscard]]
441  static constexpr bool
442  is_token_char( const char ch ) noexcept
443  {
444  return is_alpha(ch) || is_digit(ch) ||
445  ch == '!' ||
446  ch == '#' ||
447  ch == '$' ||
448  ch == '%' ||
449  ch == '&' ||
450  ch == '\'' ||
451  ch == '*' ||
452  ch == '+' ||
453  ch == '-' ||
454  ch == '.' ||
455  ch == '^' ||
456  ch == '_' ||
457  ch == '`' ||
458  ch == '|' ||
459  ch == '~';
460  }
461 
462  [[nodiscard]]
463  bool
464  operator()( const char actual ) const noexcept
465  {
466  return is_token_char(actual);
467  }
468 };
469 
470 //
471 // ows_producer_t
472 //
473 /*!
474  * @brief A producer for OWS.
475  *
476  * If an OWS found in the input stream it produces non-empty
477  * std::optional<char> with SP as the value.
478  *
479  * See: https://tools.ietf.org/html/rfc7230
480  *
481  * @since v.0.6.1
482  */
483 class ows_producer_t : public producer_tag< std::optional<char> >
484 {
485 public :
486  [[nodiscard]]
489  source_t & from ) const noexcept
490  {
491  std::size_t extracted_spaces{};
492  character_t ch;
493  for( ch = from.getch();
494  !ch.m_eof && is_space(ch.m_ch);
495  ch = from.getch() )
496  {
497  ++extracted_spaces;
498  }
499 
500  if( !ch.m_eof )
501  // The first non-space char should be returned back.
502  from.putback();
503 
504  if( extracted_spaces > 0u )
505  return result_type{ ' ' };
506 
507  return result_type{ std::nullopt };
508  }
509 };
510 
511 //
512 // token_producer_t
513 //
514 /*!
515  * @brief A producer for token.
516  *
517  * If a token is found in the input stream it produces std::string
518  * with the value of that token.
519  *
520  * See: https://tools.ietf.org/html/rfc7230
521  *
522  * @since v.0.6.1
523  */
525 {
526  [[nodiscard]]
527  static std::optional< parse_error_t >
529  {
530  error_reason_t reason = error_reason_t::pattern_not_found;
531 
532  do
533  {
534  const auto ch = from.getch();
535  if( ch.m_eof )
536  {
537  reason = error_reason_t::unexpected_eof;
538  break;
539  }
540 
541  if( !is_token_char(ch.m_ch) )
542  {
543  from.putback();
544  reason = error_reason_t::unexpected_character;
545  break;
546  }
547 
548  accumulator += ch.m_ch;
549  }
550  while( true );
551 
552  if( accumulator.empty() )
553  {
554  return parse_error_t{ from.current_position(), reason };
555  }
556 
557  return std::nullopt;
558  }
559 
560  [[nodiscard]]
561  static constexpr bool
562  is_token_char( const char ch ) noexcept
563  {
564  return is_token_char_predicate_t::is_token_char( ch );
565  }
566 
567 public :
568  [[nodiscard]]
571  {
572  std::string value;
573  const auto try_result = try_parse_value( from, value );
574  if( !try_result )
575  return { std::move(value) };
576  else
577  return make_unexpected( *try_result );
578  }
579 };
580 
581 //
582 // quoted_string_producer_t
583 //
584 /*!
585  * @brief A producer for quoted_string.
586  *
587  * If a quoted_string is found in the input stream it produces std::string
588  * with the value of that token.
589  *
590  * See: https://tools.ietf.org/html/rfc7230
591  *
592  * @since v.0.6.1
593  */
595 {
596  [[nodiscard]]
597  static std::optional< parse_error_t >
599  {
600  error_reason_t reason = error_reason_t::pattern_not_found;
601 
602  bool second_quote_extracted{ false };
603  do
604  {
605  const auto ch = from.getch();
606  if( ch.m_eof )
607  {
608  reason = error_reason_t::unexpected_eof;
609  break;
610  }
611 
612  if( '"' == ch.m_ch )
613  second_quote_extracted = true;
614  else if( '\\' == ch.m_ch )
615  {
616  const auto next = from.getch();
617  if( next.m_eof )
618  {
619  reason = error_reason_t::unexpected_eof;
620  break;
621  }
622  else if( SP == next.m_ch || HTAB == next.m_ch ||
623  is_vchar( next.m_ch ) ||
624  is_obs_text( next.m_ch ) )
625  {
626  accumulator += next.m_ch;
627  }
628  else
629  {
630  reason = error_reason_t::unexpected_character;
631  from.putback();
632  break;
633  }
634  }
635  else if( is_qdtext( ch.m_ch ) )
636  accumulator += ch.m_ch;
637  else
638  {
639  reason = error_reason_t::unexpected_character;
640  from.putback();
641  break;
642  }
643  }
644  while( !second_quote_extracted );
645 
646  if( !second_quote_extracted )
647  return parse_error_t{ from.current_position(), reason };
648  else
649  return std::nullopt;
650  }
651 
652 public :
653  [[nodiscard]]
656  {
657  source_t::content_consumer_t consumer{ from };
658 
659  const auto ch = from.getch();
660  if( !ch.m_eof )
661  {
662  if( '"' == ch.m_ch )
663  {
664  std::string value;
665  const auto try_result = try_parse_value( from, value );
666  if( !try_result )
667  {
668  consumer.commit();
669  return { std::move(value) };
670  }
671  else
672  return make_unexpected( *try_result );
673  }
674  else
675  {
676  return make_unexpected( parse_error_t{
677  consumer.started_at(),
678  error_reason_t::unexpected_character
679  } );
680  }
681  }
682  else
683  return make_unexpected( parse_error_t{
684  consumer.started_at(),
685  error_reason_t::unexpected_eof
686  } );
687  }
688 };
689 
690 //
691 // quoted_pair_producer_t
692 //
693 /*!
694  * @brief A producer for quoted_pair.
695  *
696  * If a quoted_pair is found in the input stream it produces char
697  * with the value of that token.
698  *
699  * See: https://tools.ietf.org/html/rfc7230
700  *
701  * @since v.0.6.4
702  */
703 class quoted_pair_producer_t : public producer_tag< char >
704 {
705 public :
706  [[nodiscard]]
709  {
710  source_t::content_consumer_t consumer{ from };
711 
712  error_reason_t reason = error_reason_t::unexpected_eof;
713 
714  const auto ch = from.getch();
715  if( !ch.m_eof )
716  {
717  if( '\\' == ch.m_ch )
718  {
719  const auto next = from.getch();
720  if( !next.m_eof )
721  {
722  if( SP == next.m_ch || HTAB == next.m_ch ||
723  is_vchar( next.m_ch ) ||
724  is_obs_text( next.m_ch ) )
725  {
726  consumer.commit();
727  return next.m_ch;
728  }
729 
730  reason = error_reason_t::unexpected_character;
731  }
732  }
733  else
734  reason = error_reason_t::unexpected_character;
735  }
736 
737  return make_unexpected( parse_error_t{
738  from.current_position(),
739  reason
740  } );
741  }
742 };
743 
744 //
745 // comment_producer_t
746 //
747 /*!
748  * @brief A producer for comment.
749  *
750  * If a comment is found in the input stream it produces std::string
751  * with the value of that token.
752  *
753  * Comment is defined that way:
754 @verbatim
755 comment = "(" *( ctext / quoted-pair / comment ) ")"
756 ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text
757 quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
758 @endverbatim
759  *
760  * See: https://tools.ietf.org/html/rfc7230
761  *
762  * @since v.0.6.4
763  */
765 {
766 public :
767  [[nodiscard]]
769  try_parse( source_t & from ) const; // NOTE: implementation below.
770 };
771 
772 } /* namespace impl */
773 
774 //
775 // alpha_symbol_producer
776 //
777 /*!
778  * @brief A factory for producer of ALPHA symbols.
779  *
780  * Usage example:
781  * @code
782  produce<std::string>(
783  repeat(1, 20, alpha_symbol_p() >> to_container());
784  * @endcode
785  *
786  * @since v.0.6.2
787  */
788 [[nodiscard]]
789 inline auto
791 {
792  return restinio::easy_parser::impl::symbol_producer_template_t<
793  impl::is_alpha_predicate_t >{};
794 }
795 
796 //
797 // alphanum_symbol_producer
798 //
799 /*!
800  * @brief A factory for producer of symbol that an ALPHA or DIGIT.
801  *
802  * Usage example:
803  * @code
804  produce<std::string>(
805  repeat(1, 20, alphanum_symbol_p() >> to_container());
806  * @endcode
807  *
808  * @since v.0.6.2
809  */
810 [[nodiscard]]
811 inline auto
813 {
814  return restinio::easy_parser::impl::symbol_producer_template_t<
815  impl::is_alphanum_predicate_t >{};
816 }
817 
818 //
819 // vchar_symbol_producer
820 //
821 /*!
822  * @brief A factory for producer of VCHAR symbols.
823  *
824  * Usage example:
825  * @code
826  produce<std::string>(
827  repeat(1, 20, vchar_symbol_p() >> to_container());
828  * @endcode
829  *
830  * @since v.0.6.2
831  */
832 [[nodiscard]]
833 inline auto
835 {
836  return restinio::easy_parser::impl::symbol_producer_template_t<
837  impl::is_vchar_predicate_t >{};
838 }
839 
840 //
841 // ctext_symbol_producer
842 //
843 /*!
844  * @brief A factory for producer of ctext symbols.
845  *
846  * Usage example:
847  * @code
848  produce<std::string>(
849  repeat(1, 20, ctext_symbol_p() >> to_container());
850  * @endcode
851  *
852  * @since v.0.6.4
853  */
854 [[nodiscard]]
855 inline auto
857 {
858  return restinio::easy_parser::impl::symbol_producer_template_t<
859  impl::is_ctext_predicate_t >{};
860 }
861 
862 //
863 // comment_producer
864 //
865 /*!
866  * @brief A factory for producer of comment token.
867  *
868  * Usage example:
869  * @code
870  produce<std::string>(
871  alternatives(
872  token_p() >> as_result(),
873  comment_p() >> as_result()
874  )
875  );
876  * @endcode
877  *
878  * @since v.0.6.4
879  */
880 [[nodiscard]]
881 inline auto
883 {
884  return impl::comment_producer_t{};
885 }
886 
887 //
888 // ows_producer
889 //
890 /*!
891  * @brief A factory function to create an ows_producer.
892  *
893  * Usage example:
894  * @code
895  * produce<std::string>(
896  * ows_p() >> skip(),
897  * symbol('v'),
898  * symbol('='),
899  * ows_p() >> skip(),
900  * token_p() >> as_result()
901  * );
902  * @endcode
903  *
904  * @note
905  * Factory function ows() can be used instead of expression `ows_p() >> skip()`.
906  *
907  * @since v.0.6.1
908  */
909 [[nodiscard]]
910 inline auto
911 ows_p() noexcept { return impl::ows_producer_t{}; }
912 
913 //
914 // ows
915 //
916 /*!
917  * @brief A factory function to create an OWS clause.
918  *
919  * This clause handles an optional sequence of spaces in the input stream and
920  * skips the value of that sequence.
921  *
922  * Usage example:
923  * @code
924  * produce<std::string>(
925  * ows(),
926  * symbol('v'),
927  * symbol('='),
928  * ows(),
929  * token_p() >> as_result()
930  * );
931  * @endcode
932  * This expression corresponds the following rule:
933  @verbatim
934  T := OWS 'v' '=' OWS token
935  @endverbatim
936  *
937  * @since v.0.6.1
938  */
939 [[nodiscard]]
940 inline auto
941 ows() noexcept { return ows_p() >> skip(); }
942 
943 //
944 // token_symbol_producer
945 //
946 /*!
947  * @brief A factory for producer of symbols than can be used in tokens.
948  *
949  * Usage example:
950  * @code
951  produce<std::string>(
952  repeat(1, 20, token_symbol_p() >> to_container());
953  * @endcode
954  *
955  * @since v.0.6.9
956  */
957 [[nodiscard]]
958 inline auto
959 token_symbol_p() noexcept
960 {
961  return restinio::easy_parser::impl::symbol_producer_template_t<
962  impl::is_token_char_predicate_t >{};
963 }
964 
965 //
966 // token_producer
967 //
968 /*!
969  * @brief A factory function to create a token_producer.
970  *
971  * Usage example:
972  * @code
973  * using parameter = std::pair<std::string, std::string>;
974  * produce<parameter>(
975  * ows(),
976  * token_p() >> &parameter::first,
977  * symbol('='),
978  * ows(),
979  * token_p() >> &parameter::second
980  * );
981  * @endcode
982  *
983  * @since v.0.6.1
984  */
985 [[nodiscard]]
986 inline auto
987 token_p() noexcept { return impl::token_producer_t{}; }
988 
989 //
990 // quoted_string_producer
991 //
992 /*!
993  * @brief A factory function to create a quoted_string_producer.
994  *
995  * Usage example:
996  * @code
997  * using parameter = std::pair<std::string, std::string>;
998  * produce<parameter>(
999  * ows(),
1000  * token_p() >> &parameter::first,
1001  * symbol('='),
1002  * ows(),
1003  * alternatives(
1004  * token_p() >> &parameter::second,
1005  * quoted_string_p() >> &parameter::second
1006  * )
1007  * );
1008  * @endcode
1009  *
1010  * @since v.0.6.1
1011  */
1012 [[nodiscard]]
1013 inline auto
1015 {
1016  return impl::quoted_string_producer_t{};
1017 }
1018 
1019 //
1020 // quoted_pair_producer
1021 //
1022 /*!
1023  * @brief A factory function to create a quoted_pair_producer.
1024  *
1025  * Usage example:
1026  * @code
1027  * produce<std::string>(
1028  * repeat(1, N,
1029  * alternatives(
1030  * ctext_symbol_p() >> to_container(),
1031  * quoted_pair_p() >> to_container()
1032  * )
1033  * );
1034  * @endcode
1035  *
1036  * @since v.0.6.4
1037  */
1038 [[nodiscard]]
1039 inline auto
1040 quoted_pair_p() noexcept
1041 {
1042  return impl::quoted_pair_producer_t{};
1043 }
1044 
1045 //
1046 // expected_token_p
1047 //
1048 /*!
1049  * @brief A factory function to create a producer that expect a
1050  * token with specific value.
1051  *
1052  * If the expected token is successfully parsed then boolean value
1053  * is produced.
1054  *
1055  * Usage example:
1056  * @code
1057  * enum class compression { zlib, bz2, xz };
1058  * produce<compression>(
1059  * expected_token_p("compression") >> skip(),
1060  * ows(),
1061  * symbol('='),
1062  * ows(),
1063  * alternatives(
1064  * expected_token_p("zlib") >> just_result(compression::zlib),
1065  * expected_token_p("bz2") >> just_result(compression::bz2),
1066  * expected_token_p("xz") >> just_result(compression::xz)
1067  * )
1068  * );
1069  * @endcode
1070  *
1071  * @since v.0.6.9
1072  */
1073 [[nodiscard]]
1074 inline auto
1075 expected_token_p( string_view_t token )
1076 {
1077  return produce< bool >(
1078  exact_p( token ) >> as_result(),
1079  not_clause( token_symbol_p() >> skip() ) );
1080 }
1081 
1082 //
1083 // expected_caseless_token_p
1084 //
1085 /*!
1086  * @brief A factory function to create a producer that expect a
1087  * token with specific value.
1088  *
1089  * This processer uses case-insensitive comparison.
1090  *
1091  * If the expected token is successfully parsed then boolean value
1092  * is produced.
1093  *
1094  * Usage example:
1095  * @code
1096  * enum class compression { zlib, bz2, xz };
1097  * produce<compression>(
1098  * caseless_expected_token_p("Compression") >> skip(),
1099  * ows(),
1100  * symbol('='),
1101  * ows(),
1102  * alternatives(
1103  * caseless_expected_token_p("ZLib") >> just_result(compression::zlib),
1104  * caseless_expected_token_p("BZ2") >> just_result(compression::bz2),
1105  * caseless_expected_token_p("xz") >> just_result(compression::xz)
1106  * )
1107  * );
1108  * @endcode
1109  *
1110  * @since v.0.6.9
1111  */
1112 [[nodiscard]]
1113 inline auto
1114 expected_caseless_token_p( string_view_t token )
1115 {
1116  return produce< bool >(
1117  caseless_exact_p( token ) >> as_result(),
1118  not_clause( token_symbol_p() >> skip() ) );
1119 }
1120 
1121 namespace impl
1122 {
1123 
1124 //
1125 // comment_producer_t implementation
1126 //
1127 [[nodiscard]]
1130 {
1131  return produce< std::string >(
1132  sequence(
1133  symbol('('),
1134  repeat(0, N,
1135  alternatives(
1136  ctext_symbol_p() >> to_container(),
1137  quoted_pair_p() >> to_container(),
1138  comment_p() >> custom_consumer(
1139  []( std::string & dest, std::string && what ) {
1140  dest += what;
1141  } )
1142  ) ),
1143  symbol(')') )
1144  ).try_parse( from );
1145 }
1146 
1147 //
1148 // qvalue_producer_t
1149 //
1150 /*!
1151  * @brief An implementation of producer of qvalue.
1152  *
1153  * Handles the following rule:
1154  @verbatim
1155  qvalue = ( "0" [ "." 0*3DIGIT ] )
1156  / ( "1" [ "." 0*3("0") ] )
1157  @endverbatim
1158  * and produces an instance of qvalue_t.
1159  *
1160  * See: https://tools.ietf.org/html/rfc7231
1161  *
1162  * @since v.0.6.1
1163  */
1165  : public producer_tag< qvalue_t >
1166 {
1167  // This type has to be used as type parameter for produce().
1169  {
1171  };
1172 
1173  //! A helper class to be used to accumulate actual integer
1174  //! while when the next digit is extracted from the input stream.
1176  {
1178 
1179  public :
1180  constexpr digit_consumer_t( qvalue_t::underlying_uint_t m )
1181  : m_multiplier{ m }
1182  {}
1183 
1184  void
1185  consume( zero_initialized_unit_t & dest, char && digit )
1186  {
1187  dest.m_value += m_multiplier *
1188  static_cast< qvalue_t::underlying_uint_t >(digit - '0');
1189  }
1190  };
1191 
1192 public :
1193  [[nodiscard]]
1195  try_parse( source_t & from ) const noexcept
1196  {
1197  const auto parse_result = produce< zero_initialized_unit_t >(
1198  alternatives(
1199  sequence(
1200  symbol('0'),
1201  maybe(
1202  symbol('.'),
1203  maybe( digit_p() >> digit_consumer_t{100},
1204  maybe( digit_p() >> digit_consumer_t{10},
1205  maybe( digit_p() >> digit_consumer_t{1} )
1206  )
1207  )
1208  )
1209  ),
1210  sequence(
1211  symbol_p('1') >> digit_consumer_t{1000},
1212  maybe(
1213  symbol('.'),
1214  maybe( symbol('0'),
1215  maybe( symbol('0'),
1216  maybe( symbol('0') )
1217  )
1218  )
1219  )
1220  )
1221  )
1222  ).try_parse( from );
1223 
1224  if( parse_result )
1225  return qvalue_t{ qvalue_t::trusted{ parse_result->m_value } };
1226  else
1227  return make_unexpected( parse_result.error() );
1228  }
1229 };
1230 
1231 } /* namespace impl */
1232 
1233 //
1234 // qvalue_producer
1235 //
1236 /*!
1237  * @brief A factory function to create a qvalue_producer.
1238  *
1239  * Usage example:
1240  * @code
1241  * produce<qvalue_t>(
1242  * alternatives(symbol('r'), symbol('R')),
1243  * symbol('='),
1244  * qvalue_p() >> as_result()
1245  * );
1246  * @endcode
1247  *
1248  * @since v.0.6.1
1249  */
1250 [[nodiscard]]
1251 inline auto
1252 qvalue_p() noexcept
1253 {
1254  return impl::qvalue_producer_t{};
1255 }
1256 
1257 //
1258 // weight_producer
1259 //
1260 /*!
1261  * @brief A factory function to create a producer for weight parameter.
1262  *
1263  * Returns a producer that handles the following rules:
1264  @verbatim
1265  weight = OWS ';' OWS ('q' / 'Q') '=' qvalue
1266 
1267  qvalue = ( "0" [ "." 0*3DIGIT ] )
1268  / ( "1" [ "." 0*3("0") ] )
1269  @endverbatim
1270  *
1271  * See: https://tools.ietf.org/html/rfc7231
1272  *
1273  * That producer produces a value of type qvalue_t.
1274  *
1275  * @since v.0.6.1
1276  */
1277 [[nodiscard]]
1278 inline auto
1279 weight_p() noexcept
1280 {
1281  return produce< qvalue_t >(
1282  ows(),
1283  symbol(';'),
1284  ows(),
1285  caseless_symbol('q'),
1286  symbol('='),
1287  qvalue_p() >> as_result()
1288  );
1289 }
1290 
1291 namespace impl
1292 {
1293 
1294 //
1295 // non_empty_comma_separated_list_producer_t
1296 //
1297 /*!
1298  * @brief A template for a producer that handles non-empty list of
1299  * comma-separated values.
1300  *
1301  * That producer handles the following rule:
1302 @verbatim
1303 1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )
1304 @endverbatim
1305  *
1306  * See: https://tools.ietf.org/html/rfc7230
1307  * (section "7. ABNF List Extension: #rule")
1308  *
1309  * @tparam Container the type of container to be produced.
1310  *
1311  * @tparam Element_Producer the type of the producer of a single item.
1312  *
1313  * @since v.0.6.1
1314  */
1315 template<
1316  typename Container,
1317  typename Element_Producer >
1319  : public producer_tag< Container >
1320 {
1321  static_assert( impl::is_producer_v<Element_Producer>,
1322  "Element_Producer should be a value producer type" );
1323 
1324  Element_Producer m_element;
1325 
1326 public :
1327  using typename producer_tag< Container >::result_type;
1328 
1330  Element_Producer && element )
1331  : m_element{ std::move(element) }
1332  {}
1333 
1334  [[nodiscard]]
1337  {
1339 
1340  const auto appender = to_container();
1341 
1342  const auto process_result = sequence(
1343  repeat( 0, N, symbol(','), ows() ),
1344  m_element >> appender,
1345  repeat( 0, N,
1346  ows(), symbol(','),
1347  maybe( ows(), m_element >> appender )
1348  )
1349  ).try_process( from, tmp_value );
1350 
1351  if( !process_result )
1352  return { std::move(tmp_value) };
1353  else
1354  return make_unexpected( *process_result );
1355  }
1356 };
1357 
1358 //
1359 // maybe_empty_comma_separated_list_producer_t
1360 //
1361 /*!
1362  * @brief A template for a producer that handles possibly empty list of
1363  * comma-separated values.
1364  *
1365  * That producer handles the following rule:
1366 @verbatim
1367 #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
1368 @endverbatim
1369  *
1370  * See: https://tools.ietf.org/html/rfc7230
1371  * (section "7. ABNF List Extension: #rule")
1372  *
1373  * @tparam Container the type of container to be produced.
1374  *
1375  * @tparam Element_Producer the type of the producer of a single item.
1376  *
1377  * @since v.0.6.1
1378  */
1379 template<
1380  typename Container,
1381  typename Element_Producer >
1383  : public producer_tag< Container >
1384 {
1385  static_assert( impl::is_producer_v<Element_Producer>,
1386  "Element_Producer should be a value producer type" );
1387 
1388  Element_Producer m_element;
1389 
1390 public :
1391  using typename producer_tag< Container >::result_type;
1392 
1394  Element_Producer && element )
1395  : m_element{ std::move(element) }
1396  {}
1397 
1398  [[nodiscard]]
1401  {
1403 
1404  const auto appender = to_container();
1405 
1406  const auto process_result = maybe(
1407  alternatives( symbol(','), m_element >> appender ),
1408  repeat( 0, N,
1409  ows(), symbol(','),
1410  maybe( ows(), m_element >> appender )
1411  )
1412  ).try_process( from, tmp_value );
1413 
1414  if( !process_result )
1415  return { std::move(tmp_value) };
1416  else
1417  return make_unexpected( *process_result );
1418  }
1419 };
1420 
1421 } /* namespace impl */
1422 
1423 //
1424 // non_empty_comma_separated_list_producer
1425 //
1426 /*!
1427  * @brief A factory for a producer that handles non-empty list of
1428  * comma-separated values.
1429  *
1430  * That producer handles the following rule:
1431 @verbatim
1432 1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )
1433 @endverbatim
1434  *
1435  * See: https://tools.ietf.org/html/rfc7230
1436  * (section "7. ABNF List Extension: #rule")
1437  *
1438  * Usage example:
1439  * @code
1440  auto parse = produce< byte_ranges_data >(
1441  make_bytes_prefix_parser(),
1442  non_empty_comma_separated_list_p< std::vector< byte_range > >(
1443  make_byte_range_parser()
1444  ) >> &byte_ranges_data::ranges
1445  );
1446  * @endcode
1447  *
1448  * @tparam Container the type of container to be produced.
1449  *
1450  * @tparam Element_Producer the type of the producer of a single item.
1451  *
1452  * @since v.0.6.1
1453  */
1454 template<
1455  typename Container,
1456  typename Element_Producer >
1457 [[nodiscard]]
1458 auto
1459 non_empty_comma_separated_list_p( Element_Producer element )
1460 {
1461  static_assert( impl::is_producer_v<Element_Producer>,
1462  "Element_Producer should be a value producer type" );
1463 
1464  return impl::non_empty_comma_separated_list_producer_t<
1465  Container,
1466  Element_Producer >{ std::move(element) };
1467 }
1468 
1469 //
1470 // maybe_empty_comma_separated_list_producer
1471 //
1472 /*!
1473  * @brief A factory for a producer that handles possibly empty list of
1474  * comma-separated values.
1475  *
1476  * That producer handles the following rule:
1477 @verbatim
1478 #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
1479 @endverbatim
1480  *
1481  * See: https://tools.ietf.org/html/rfc7230
1482  * (section "7. ABNF List Extension: #rule")
1483  *
1484  * Usage example:
1485  * @code
1486  auto parse = produce< byte_ranges_data >(
1487  make_bytes_prefix_parser(),
1488  maybe_empty_comma_separated_list_p< std::vector< byte_range > >(
1489  make_byte_range_parser()
1490  ) >> &byte_ranges_data::ranges
1491  );
1492  * @endcode
1493  *
1494  * @tparam Container the type of container to be produced.
1495  *
1496  * @tparam Element_Producer the type of the producer of a single item.
1497  *
1498  * @since v.0.6.1
1499  */
1500 template<
1501  typename Container,
1502  typename Element_Producer >
1503 [[nodiscard]]
1504 auto
1505 maybe_empty_comma_separated_list_p( Element_Producer element )
1506 {
1507  static_assert( impl::is_producer_v<Element_Producer>,
1508  "Element_Producer should be a value producer type" );
1509 
1510  return impl::maybe_empty_comma_separated_list_producer_t<
1511  Container,
1512  Element_Producer >{ std::move(element) };
1513 }
1514 
1515 //
1516 // parameter_with_mandatory_value_t
1517 //
1518 /*!
1519  * @brief A type that describes a parameter with mandatory value.
1520  *
1521  * @since v.0.6.1
1522  */
1524 
1525 //
1526 // parameter_with_mandatory_value_container_t
1527 //
1528 /*!
1529  * @brief A type of container for parameters with mandatory values.
1530  *
1531  * @since v.0.6.1
1532  */
1535 
1536 //
1537 // not_found_t
1538 //
1539 /*!
1540  * @brief An empty type to be used as indicator of negative search result.
1541  *
1542  * @since v.0.6.1
1543  */
1544 struct not_found_t {};
1545 
1546 //
1547 // find_first
1548 //
1549 /*!
1550  * @brief A helper function to find the first occurence of a parameter
1551  * with the specified value.
1552  *
1553  * @note
1554  * The caseless (case-insentive) search is used. It means that
1555  * search with value "charset" will returns items "CharSet", "charset",
1556  * "CHARSET" and so on.
1557  *
1558  * Usage example:
1559  * @code
1560  * const auto charset = find_first(content_type_params, "charset");
1561  * if(charset) {
1562  * ... // Handle the value of charset parameter.
1563  * }
1564  * @endcode
1565  *
1566  * @since v.0.6.1
1567  */
1568 [[nodiscard]]
1573 {
1574  const auto it = std::find_if( where.begin(), where.end(),
1575  [&what]( const auto & pair ) {
1576  return restinio::impl::is_equal_caseless( pair.first, what );
1577  } );
1578  if( it != where.end() )
1579  return string_view_t{ it->second };
1580  else
1581  return make_unexpected( not_found_t{} );
1582 }
1583 
1584 namespace impl
1585 {
1586 
1588 {
1589 
1590 //
1591 // make_parser
1592 //
1593 /*!
1594  * @brief Helper function that creates an instance of producer
1595  * of parameter_with_mandatory_value_container.
1596  *
1597  * @since v.0.6.1
1598  */
1599 [[nodiscard]]
1600 inline auto
1602 {
1603  return produce< parameter_with_mandatory_value_container_t >(
1604  repeat( 0, N,
1605  produce< parameter_with_mandatory_value_t >(
1606  ows(),
1607  symbol(';'),
1608  ows(),
1609  token_p() >> to_lower()
1610  >> &parameter_with_mandatory_value_t::first,
1611  symbol('='),
1612  alternatives(
1613  token_p()
1614  >> &parameter_with_mandatory_value_t::second,
1615  quoted_string_p()
1616  >> &parameter_with_mandatory_value_t::second
1617  )
1618  ) >> to_container()
1619  )
1620  );
1621 }
1622 
1623 } /* namespace params_with_value_producer_details */
1624 
1625 //
1626 // params_with_value_producer_t
1627 //
1628 /*!
1629  * @brief A type of producer that produces instances of
1630  * parameter_with_mandatory_value_container.
1631  *
1632  * @since v.0.6.1
1633  */
1636 {
1637  using actual_producer_t = std::decay_t<
1639 
1642 
1643 public :
1644  params_with_value_producer_t() = default;
1645 
1646  [[nodiscard]]
1647  auto
1648  try_parse( source_t & from )
1649  {
1650  return m_producer.try_parse( from );
1651  }
1652 };
1653 
1654 } /* namespace impl */
1655 
1656 //
1657 // params_with_value_producer
1658 //
1659 /*!
1660  * @brief A factory of producer of parameter_with_mandatory_value_container.
1661  *
1662  * Creates a produces that handles the following rule:
1663 @verbatim
1664 T := *( OWS ';' OWS token '=' OWS (token / quoted_string))
1665 @endverbatim
1666  *
1667  * Usage example:
1668  * @code
1669  * struct my_field {
1670  * std::string value;
1671  * parameter_with_mandatory_value_container_t params;
1672  * };
1673  * produce<my_field>(
1674  * token_p() >> to_lower() >> &my_field::value,
1675  * params_with_value_p() >> &my_field::params
1676  * );
1677  * @endcode
1678  *
1679  * @note
1680  * Parameters names are converted to lower case. Parameters' values
1681  * are not changed and stored as they are.
1682  *
1683  * @since v.0.6.1
1684  */
1685 [[nodiscard]]
1687 params_with_value_p() { return {}; }
1688 
1689 //
1690 // parameter_with_optional_value_t
1691 //
1692 /*!
1693  * @brief A type that describes a parameter with optional value.
1694  *
1695  * @since v.0.6.1
1696  */
1699 
1700 //
1701 // parameter_with_optional_value_container_t
1702 //
1703 /*!
1704  * @brief A type of container for parameters with optional values.
1705  *
1706  * @since v.0.6.1
1707  */
1710 
1711 //
1712 // find_first
1713 //
1714 /*!
1715  * @brief A helper function to find the first occurence of a parameter
1716  * with the specified value.
1717  *
1718  * @note
1719  * The caseless (case-insentive) search is used. It means that
1720  * search with value "charset" will returns items "CharSet", "charset",
1721  * "CHARSET" and so on.
1722  *
1723  * Usage example:
1724  * @code
1725  * const auto max_age = find_first(cache_control_params, "max-age");
1726  * if(max_age) {
1727  * if(*max_age) {
1728  * ... // Handle the value of max-age parameter.
1729  * }
1730  * else {
1731  * ... // Handle the case where max-age specified but without a value.
1732  * }
1733  * }
1734  * @endcode
1735  *
1736  * @since v.0.6.1
1737  */
1738 [[nodiscard]]
1743 {
1744  const auto it = std::find_if( where.begin(), where.end(),
1745  [&what]( const auto & pair ) {
1747  } );
1748  if( it != where.end() )
1749  {
1750  const auto opt = it->second;
1751  if( opt )
1752  return string_view_t{ *opt };
1753  else
1754  return std::optional< string_view_t >{ std::nullopt };
1755  }
1756  else
1757  return make_unexpected( not_found_t{} );
1758 }
1759 
1760 namespace impl
1761 {
1762 
1764 {
1765 
1766 //
1767 // make_parser
1768 //
1769 /*!
1770  * @brief Helper function that creates an instance of producer
1771  * of parameter_with_optional_value_container.
1772  *
1773  * @since v.0.6.1
1774  */
1775 [[nodiscard]]
1776 inline auto
1778 {
1779  return produce< parameter_with_optional_value_container_t >(
1780  repeat( 0, N,
1781  produce< parameter_with_optional_value_t >(
1782  ows(),
1783  symbol(';'),
1784  ows(),
1785  token_p() >> to_lower()
1786  >> &parameter_with_optional_value_t::first,
1787  maybe(
1788  symbol('='),
1789  alternatives(
1790  token_p()
1791  >> &parameter_with_optional_value_t::second,
1792  quoted_string_p()
1793  >> &parameter_with_optional_value_t::second
1794  )
1795  )
1796  ) >> to_container()
1797  )
1798  );
1799 }
1800 
1801 } /* namespace params_with_opt_value_producer_details */
1802 
1803 //
1804 // params_with_opt_value_producer_t
1805 //
1806 /*!
1807  * @brief A type of producer that produces instances of
1808  * parameter_with_optional_value_container.
1809  *
1810  * @since v.0.6.1
1811  */
1814 {
1815  using actual_producer_t = std::decay_t<
1817 
1820 
1821 public :
1823 
1824  [[nodiscard]]
1825  auto
1826  try_parse( source_t & from )
1827  {
1828  return m_producer.try_parse( from );
1829  }
1830 };
1831 
1832 } /* namespace impl */
1833 
1834 //
1835 // params_with_opt_value_producer
1836 //
1837 /*!
1838  * @brief A factory of producer of parameter_with_optional_value_container.
1839  *
1840  * Creates a produces that handles the following rule:
1841 @verbatim
1842 T := *( OWS ';' OWS token ['=' OWS (token / quoted_string)] )
1843 @endverbatim
1844  *
1845  * Usage example:
1846  * @code
1847  * struct my_field {
1848  * std::string value;
1849  * parameter_with_optional_value_container_t params;
1850  * };
1851  * produce<my_field>(
1852  * token_p() >> to_lower() >> &my_field::value,
1853  * params_with_opt_value_p() >> &my_field::params
1854  * );
1855  * @endcode
1856  *
1857  * @note
1858  * Parameters names are converted to lower case. Parameters' values
1859  * are not changed and stored as they are.
1860  *
1861  * @since v.0.6.1
1862  */
1863 [[nodiscard]]
1865 params_with_opt_value_p() { return {}; }
1866 
1867 } /* namespace http_field_parser */
1868 
1869 } /* namespace restinio */
expected_t< result_type, parse_error_t > try_parse(source_t &from) const noexcept
Definition: basics.hpp:1195
expected_t< std::optional< string_view_t >, not_found_t > find_first(const parameter_with_optional_value_container_t &where, string_view_t what)
A helper function to find the first occurence of a parameter with the specified value.
Definition: basics.hpp:1740
auto vchar_symbol_p()
A factory for producer of VCHAR symbols.
Definition: basics.hpp:834
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition: basics.hpp:708
auto ctext_symbol_p()
A factory for producer of ctext symbols.
Definition: basics.hpp:856
auto make_parser()
Helper function that creates an instance of producer of parameter_with_optional_value_container.
Definition: basics.hpp:1777
constexpr bool is_qdtext(const char ch) noexcept
Is a character a qdtext?
Definition: basics.hpp:380
bool operator()(const char actual) const noexcept
Definition: basics.hpp:425
A helper wrapper to indicate that value hasn&#39;t been checked yet and should be checked in the construc...
Definition: basics.hpp:63
constexpr underlying_uint_t zero
The minimal allowed value for a qvalue.
Definition: basics.hpp:41
auto comment_p()
A factory for producer of comment token.
Definition: basics.hpp:882
constexpr bool is_obs_text(const char ch) noexcept
Is a character an obs_text?
Definition: basics.hpp:357
auto quoted_string_p() noexcept
A factory function to create a quoted_string_producer.
Definition: basics.hpp:1014
impl::params_with_opt_value_producer_t params_with_opt_value_p()
A factory of producer of parameter_with_optional_value_container.
Definition: basics.hpp:1865
constexpr underlying_uint_t maximum
The maximal allowed value for a qvalue.
Definition: basics.hpp:39
bool operator()(const char actual) const noexcept
Definition: basics.hpp:303
bool operator()(const char actual) const noexcept
Definition: basics.hpp:339
bool operator<(const qvalue_t &a, const qvalue_t &b) noexcept
Definition: basics.hpp:236
A preducate for symbol_producer_template that checks that a symbol is an alpha.
Definition: basics.hpp:280
auto non_empty_comma_separated_list_p(Element_Producer element)
A factory for a producer that handles non-empty list of comma-separated values.
Definition: basics.hpp:1459
static constexpr bool is_token_char(const char ch) noexcept
Definition: basics.hpp:562
constexpr bool is_ctext(const char ch) noexcept
Is a character a ctext?
Definition: basics.hpp:402
A class for holding the parsed value of qvalue from RFC7231.
Definition: basics.hpp:135
bool operator!=(const qvalue_t &a, const qvalue_t &b) noexcept
Definition: basics.hpp:229
An implementation of producer of qvalue.
Definition: basics.hpp:1164
auto qvalue_p() noexcept
A factory function to create a qvalue_producer.
Definition: basics.hpp:1252
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
A preducate for symbol_producer_template that checks that a symbol is a ctext.
Definition: basics.hpp:421
static std::optional< parse_error_t > try_parse_value(source_t &from, std::string &accumulator)
Definition: basics.hpp:528
constexpr trusted(underlying_uint_t value) noexcept
Definition: basics.hpp:56
constexpr qvalue_t(trusted val) noexcept
Definition: basics.hpp:194
constexpr bool is_alpha(const char ch) noexcept
Is a character an ALPHA?
Definition: basics.hpp:265
auto maybe_empty_comma_separated_list_p(Element_Producer element)
A factory for a producer that handles possibly empty list of comma-separated values.
Definition: basics.hpp:1505
auto expected_caseless_token_p(string_view_t token)
A factory function to create a producer that expect a token with specific value.
Definition: basics.hpp:1114
auto token_symbol_p() noexcept
A factory for producer of symbols than can be used in tokens.
Definition: basics.hpp:959
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition: basics.hpp:570
static constexpr qvalue_details::extremum_max_t maximum
The indicator that tells that new qvalue object should have the maximal allowed value.
Definition: basics.hpp:147
A template for a producer that handles non-empty list of comma-separated values.
Definition: basics.hpp:1318
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition: basics.hpp:655
A preducate for symbol_producer_template that checks that a symbol is a VCHAR.
Definition: basics.hpp:335
constexpr qvalue_t(qvalue_details::extremum_min_t) noexcept
Definition: basics.hpp:198
static constexpr bool is_token_char(const char ch) noexcept
Definition: basics.hpp:442
auto alphanum_symbol_p()
A factory for producer of symbol that an ALPHA or DIGIT.
Definition: basics.hpp:812
A type of producer that produces instances of parameter_with_optional_value_container.
Definition: basics.hpp:1812
auto make_parser()
Helper function that creates an instance of producer of parameter_with_mandatory_value_container.
Definition: basics.hpp:1601
expected_t< result_type, parse_error_t > try_parse(source_t &from)
Definition: basics.hpp:1336
A predicate for symbol_producer_template that checks that a symbol can be used inside a token...
Definition: basics.hpp:438
impl::params_with_value_producer_t params_with_value_p()
A factory of producer of parameter_with_mandatory_value_container.
Definition: basics.hpp:1687
A template for a producer that handles possibly empty list of comma-separated values.
Definition: basics.hpp:1382
expected_t< string_view_t, not_found_t > find_first(const parameter_with_mandatory_value_container_t &where, string_view_t what)
A helper function to find the first occurence of a parameter with the specified value.
Definition: basics.hpp:1570
A helper class to be used to accumulate actual integer while when the next digit is extracted from th...
Definition: basics.hpp:1175
qvalue_t(untrusted val) noexcept
Definition: basics.hpp:190
constexpr qvalue_t(qvalue_details::extremum_max_t) noexcept
Definition: basics.hpp:202
friend std::ostream & operator<<(std::ostream &to, const qvalue_t &what)
Definition: basics.hpp:214
auto quoted_pair_p() noexcept
A factory function to create a quoted_pair_producer.
Definition: basics.hpp:1040
auto ows() noexcept
A factory function to create an OWS clause.
Definition: basics.hpp:941
constexpr bool is_vchar(const char ch) noexcept
Is a character a VCHAR?
Definition: basics.hpp:321
auto ows_p() noexcept
A factory function to create an ows_producer.
Definition: basics.hpp:911
bool operator()(const char actual) const noexcept
Definition: basics.hpp:464
underlying_char_array_t make_char_array() const noexcept
Definition: basics.hpp:161
An empty type to be used as indicator of negative search result.
Definition: basics.hpp:1544
A type of producer that produces instances of parameter_with_mandatory_value_container.
Definition: basics.hpp:1634
auto weight_p() noexcept
A factory function to create a producer for weight parameter.
Definition: basics.hpp:1279
expected_t< result_type, parse_error_t > try_parse(source_t &from) const noexcept
Definition: basics.hpp:488
auto token_p() noexcept
A factory function to create a token_producer.
Definition: basics.hpp:987
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition: basics.hpp:1129
A preducate for symbol_producer_template that checks that a symbol is an alpha or numeric...
Definition: basics.hpp:299
bool operator()(const char actual) const noexcept
Definition: basics.hpp:284
void consume(zero_initialized_unit_t &dest, char &&digit)
Definition: basics.hpp:1185
static constexpr qvalue_details::extremum_min_t zero
The indicator that tells that new qvalue object should have the minimal allowed value.
Definition: basics.hpp:151
constexpr auto as_uint() const noexcept
Definition: basics.hpp:206
auto expected_token_p(string_view_t token)
A factory function to create a producer that expect a token with specific value.
Definition: basics.hpp:1075
auto alpha_symbol_p()
A factory for producer of ALPHA symbols.
Definition: basics.hpp:790
expected_t< result_type, parse_error_t > try_parse(source_t &from)
Definition: basics.hpp:1400
A helper wrapper to indicate that value is already checked and shouldn&#39;t be checked again...
Definition: basics.hpp:50
bool operator<=(const qvalue_t &a, const qvalue_t &b) noexcept
Definition: basics.hpp:243
bool operator==(const qvalue_t &a, const qvalue_t &b) noexcept
Definition: basics.hpp:222
static std::optional< parse_error_t > try_parse_value(source_t &from, std::string &accumulator)
Definition: basics.hpp:598