RESTinio
Loading...
Searching...
No Matches
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
22namespace restinio
23{
24
25namespace http_field_parsers
26{
27
28using namespace restinio::easy_parser;
29
30namespace meta = restinio::utils::metaprogramming;
31
33{
34
35//! A type to hold a qvalue.
37
38//! The maximal allowed value for a qvalue.
39constexpr underlying_uint_t maximum = 1000u;
40//! The minimal allowed value for a qvalue.
41constexpr 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.
45enum class extremum_min_t { v };
46enum class extremum_max_t { v };
47
48//! A helper wrapper to indicate that value is already checked and
49//! shouldn't be checked again.
51{
53
54public :
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.
64{
66
67public :
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 */
136{
137public :
138 //! The type of underlying small integer.
140 //! The type that doesn't check a value to be used for qvalue.
142 //! The type that checks a value to be used for qvalue.
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.
153
154private :
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 {
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
186public :
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
200 {}
201
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]]
221inline bool
222operator==( const qvalue_t & a, const qvalue_t & b ) noexcept
223{
224 return a.as_uint() == b.as_uint();
225}
226
227[[nodiscard]]
228inline bool
229operator!=( const qvalue_t & a, const qvalue_t & b ) noexcept
230{
231 return a.as_uint() != b.as_uint();
232}
233
234[[nodiscard]]
235inline bool
236operator<( const qvalue_t & a, const qvalue_t & b ) noexcept
237{
238 return a.as_uint() < b.as_uint();
239}
240
241[[nodiscard]]
242inline bool
243operator<=( const qvalue_t & a, const qvalue_t & b ) noexcept
244{
245 return a.as_uint() <= b.as_uint();
246}
247
248namespace impl
249{
250
251using 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]]
264inline constexpr bool
265is_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]]
320inline constexpr bool
321is_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]]
356inline constexpr bool
357is_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]]
379inline constexpr bool
380is_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]]
401inline constexpr bool
402is_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 */
483class ows_producer_t : public producer_tag< std::optional<char> >
484{
485public :
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 >
528 try_parse_value( source_t & from, std::string & accumulator )
529 {
531
532 do
533 {
534 const auto ch = from.getch();
535 if( ch.m_eof )
536 {
538 break;
539 }
540
541 if( !is_token_char(ch.m_ch) )
542 {
543 from.putback();
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 {
565 }
566
567public :
568 [[nodiscard]]
570 try_parse( source_t & from ) const
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 >
598 try_parse_value( source_t & from, std::string & accumulator )
599 {
601
602 bool second_quote_extracted{ false };
603 do
604 {
605 const auto ch = from.getch();
606 if( ch.m_eof )
607 {
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 {
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 {
631 from.putback();
632 break;
633 }
634 }
635 else if( is_qdtext( ch.m_ch ) )
636 accumulator += ch.m_ch;
637 else
638 {
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
652public :
653 [[nodiscard]]
655 try_parse( source_t & from ) const
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(),
679 } );
680 }
681 }
682 else
683 return make_unexpected( parse_error_t{
684 consumer.started_at(),
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 */
704{
705public :
706 [[nodiscard]]
708 try_parse( source_t & from ) const
709 {
710 source_t::content_consumer_t consumer{ from };
711
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
731 }
732 }
733 else
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
755comment = "(" *( ctext / quoted-pair / comment ) ")"
756ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text
757quoted-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{
766public :
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]]
789inline 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]]
811inline 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]]
833inline 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]]
855inline 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]]
881inline 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]]
910inline auto
911ows_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]]
940inline auto
941ows() 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]]
958inline auto
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]]
986inline auto
987token_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]]
1013inline 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]]
1039inline auto
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]]
1074inline auto
1075expected_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]]
1113inline auto
1114expected_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
1121namespace 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().
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
1192public :
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]]
1251inline auto
1252qvalue_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]]
1278inline auto
1279weight_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
1291namespace 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
13031#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 */
1315template<
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
1326public :
1327 using typename producer_tag< Container >::result_type;
1328
1330 Element_Producer && element )
1331 : m_element{ std::move(element) }
1332 {}
1333
1334 [[nodiscard]]
1337 {
1338 Container tmp_value;
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 */
1379template<
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
1390public :
1391 using typename producer_tag< Container >::result_type;
1392
1394 Element_Producer && element )
1395 : m_element{ std::move(element) }
1396 {}
1397
1398 [[nodiscard]]
1401 {
1402 Container tmp_value;
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
14321#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 */
1454template<
1455 typename Container,
1456 typename Element_Producer >
1457[[nodiscard]]
1458auto
1459non_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
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 */
1500template<
1501 typename Container,
1502 typename Element_Producer >
1503[[nodiscard]]
1504auto
1505maybe_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
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 */
1523using parameter_with_mandatory_value_t = std::pair< std::string, std::string >;
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 */
1544struct 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]]
1571 const parameter_with_mandatory_value_container_t & where,
1572 string_view_t what )
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
1584namespace 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]]
1600inline 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{
1639
1642
1643public :
1645
1646 [[nodiscard]]
1647 auto
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
1664T := *( 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]]
1687params_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 */
1698 std::pair< std::string, std::optional<std::string> >;
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]]
1741 const parameter_with_optional_value_container_t & where,
1742 string_view_t what )
1743{
1744 const auto it = std::find_if( where.begin(), where.end(),
1745 [&what]( const auto & pair ) {
1746 return restinio::impl::is_equal_caseless( pair.first, what );
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
1760namespace 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]]
1776inline 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{
1817
1820
1821public :
1823
1824 [[nodiscard]]
1825 auto
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
1842T := *( 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]]
1866
1867} /* namespace http_field_parser */
1868
1869} /* namespace restinio */
A helper class to automatically return acquired content back to the input stream.
void commit() noexcept
Consume all acquired content.
The class that implements "input stream".
void putback() noexcept
Return one character back to the input stream.
character_t getch() noexcept
Get the next character from the input stream.
Information about parsing error.
Exception class for all exceptions thrown by RESTinio.
Definition exception.hpp:26
exception_t(const char *err)
Definition exception.hpp:29
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition basics.hpp:1129
A template for a producer that handles possibly empty list of comma-separated values.
Definition basics.hpp:1384
expected_t< result_type, parse_error_t > try_parse(source_t &from)
Definition basics.hpp:1400
A template for a producer that handles non-empty list of comma-separated values.
Definition basics.hpp:1320
expected_t< result_type, parse_error_t > try_parse(source_t &from)
Definition basics.hpp:1336
expected_t< result_type, parse_error_t > try_parse(source_t &from) const noexcept
Definition basics.hpp:488
A type of producer that produces instances of parameter_with_optional_value_container.
Definition basics.hpp:1814
A type of producer that produces instances of parameter_with_mandatory_value_container.
Definition basics.hpp:1636
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition basics.hpp:708
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition basics.hpp:655
static std::optional< parse_error_t > try_parse_value(source_t &from, std::string &accumulator)
Definition basics.hpp:598
A helper class to be used to accumulate actual integer while when the next digit is extracted from th...
Definition basics.hpp:1176
void consume(zero_initialized_unit_t &dest, char &&digit)
Definition basics.hpp:1185
An implementation of producer of qvalue.
Definition basics.hpp:1166
expected_t< result_type, parse_error_t > try_parse(source_t &from) const noexcept
Definition basics.hpp:1195
expected_t< result_type, parse_error_t > try_parse(source_t &from) const
Definition basics.hpp:570
static std::optional< parse_error_t > try_parse_value(source_t &from, std::string &accumulator)
Definition basics.hpp:528
static constexpr bool is_token_char(const char ch) noexcept
Definition basics.hpp:562
A helper wrapper to indicate that value is already checked and shouldn't be checked again.
Definition basics.hpp:51
constexpr trusted(underlying_uint_t value) noexcept
Definition basics.hpp:56
A helper wrapper to indicate that value hasn't been checked yet and should be checked in the construc...
Definition basics.hpp:64
A class for holding the parsed value of qvalue from RFC7231.
Definition basics.hpp:136
qvalue_details::untrusted untrusted
The type that checks a value to be used for qvalue.
Definition basics.hpp:143
constexpr qvalue_t(qvalue_details::extremum_min_t) noexcept
Definition basics.hpp:198
constexpr auto as_uint() const noexcept
Definition basics.hpp:206
std::array< char, 6 > underlying_char_array_t
Definition basics.hpp:156
qvalue_details::trusted trusted
The type that doesn't check a value to be used for qvalue.
Definition basics.hpp:141
underlying_char_array_t make_char_array() const noexcept
Definition basics.hpp:161
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 qvalue_t(trusted val) noexcept
Definition basics.hpp:194
constexpr qvalue_t(qvalue_details::extremum_max_t) noexcept
Definition basics.hpp:202
qvalue_t(untrusted val) noexcept
Definition basics.hpp:190
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
constexpr char HTAB
A constant for Horizontal Tab value.
constexpr char SP
A constant for SPACE value.
constexpr bool is_space(const char ch) noexcept
If a character a space character?
constexpr bool is_digit(const char ch) noexcept
Is a character a decimal digit?
auto to_container()
A factory function to create a to_container_consumer.
error_reason_t
Reason of parsing error.
@ unexpected_eof
Unexpected end of input is encontered when some character expected.
@ unexpected_character
Unexpected character is found in the input.
@ pattern_not_found
Required pattern is not found in the input.
auto make_parser()
Helper function that creates an instance of producer of parameter_with_optional_value_container.
Definition basics.hpp:1777
auto make_parser()
Helper function that creates an instance of producer of parameter_with_mandatory_value_container.
Definition basics.hpp:1601
constexpr bool is_qdtext(const char ch) noexcept
Is a character a qdtext?
Definition basics.hpp:380
constexpr bool is_ctext(const char ch) noexcept
Is a character a ctext?
Definition basics.hpp:402
constexpr bool is_obs_text(const char ch) noexcept
Is a character an obs_text?
Definition basics.hpp:357
constexpr bool is_vchar(const char ch) noexcept
Is a character a VCHAR?
Definition basics.hpp:321
constexpr bool is_alpha(const char ch) noexcept
Is a character an ALPHA?
Definition basics.hpp:265
constexpr underlying_uint_t zero
The minimal allowed value for a qvalue.
Definition basics.hpp:41
constexpr underlying_uint_t maximum
The maximal allowed value for a qvalue.
Definition basics.hpp:39
impl::params_with_value_producer_t params_with_value_p()
A factory of producer of parameter_with_mandatory_value_container.
Definition basics.hpp:1687
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
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
auto vchar_symbol_p()
A factory for producer of VCHAR symbols.
Definition basics.hpp:834
auto qvalue_p() noexcept
A factory function to create a qvalue_producer.
Definition basics.hpp:1252
auto ows_p() noexcept
A factory function to create an ows_producer.
Definition basics.hpp:911
auto token_p() noexcept
A factory function to create a token_producer.
Definition basics.hpp:987
auto ctext_symbol_p()
A factory for producer of ctext symbols.
Definition basics.hpp:856
bool operator==(const qvalue_t &a, const qvalue_t &b) noexcept
Definition basics.hpp:222
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 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
auto alpha_symbol_p()
A factory for producer of ALPHA symbols.
Definition basics.hpp:790
auto token_symbol_p() noexcept
A factory for producer of symbols than can be used in tokens.
Definition basics.hpp:959
bool operator!=(const qvalue_t &a, const qvalue_t &b) noexcept
Definition basics.hpp:229
std::pair< std::string, std::optional< std::string > > parameter_with_optional_value_t
A type that describes a parameter with optional value.
Definition basics.hpp:1697
auto alphanum_symbol_p()
A factory for producer of symbol that an ALPHA or DIGIT.
Definition basics.hpp:812
bool operator<=(const qvalue_t &a, const qvalue_t &b) noexcept
Definition basics.hpp:243
auto weight_p() noexcept
A factory function to create a producer for weight parameter.
Definition basics.hpp:1279
auto ows() noexcept
A factory function to create an OWS clause.
Definition basics.hpp:941
std::pair< std::string, std::string > parameter_with_mandatory_value_t
A type that describes a parameter with mandatory value.
Definition basics.hpp:1523
auto quoted_pair_p() noexcept
A factory function to create a quoted_pair_producer.
Definition basics.hpp:1040
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
bool operator<(const qvalue_t &a, const qvalue_t &b) noexcept
Definition basics.hpp:236
auto quoted_string_p() noexcept
A factory function to create a quoted_string_producer.
Definition basics.hpp:1014
auto comment_p()
A factory for producer of comment token.
Definition basics.hpp:882
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
One character extracted from the input stream.
A special base class to be used with consumers.
A special base class to be used with producers.
A preducate for symbol_producer_template that checks that a symbol is an alpha.
Definition basics.hpp:281
bool operator()(const char actual) const noexcept
Definition basics.hpp:284
A preducate for symbol_producer_template that checks that a symbol is an alpha or numeric.
Definition basics.hpp:300
bool operator()(const char actual) const noexcept
Definition basics.hpp:303
A preducate for symbol_producer_template that checks that a symbol is a ctext.
Definition basics.hpp:422
bool operator()(const char actual) const noexcept
Definition basics.hpp:425
A predicate for symbol_producer_template that checks that a symbol can be used inside a token.
Definition basics.hpp:439
static constexpr bool is_token_char(const char ch) noexcept
Definition basics.hpp:442
bool operator()(const char actual) const noexcept
Definition basics.hpp:464
A preducate for symbol_producer_template that checks that a symbol is a VCHAR.
Definition basics.hpp:336
bool operator()(const char actual) const noexcept
Definition basics.hpp:339
An empty type to be used as indicator of negative search result.
Definition basics.hpp:1544