1  
//
1  
//
2  
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP
10  
#ifndef BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP
11  
#define BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP
11  
#define BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP
12  

12  

13  
#include <boost/url/detail/config.hpp>
13  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/grammar/detail/charset.hpp>
14  
#include <boost/url/grammar/detail/charset.hpp>
15  

15  

16  
namespace boost {
16  
namespace boost {
17  
namespace urls {
17  
namespace urls {
18  
namespace grammar {
18  
namespace grammar {
19  
namespace implementation_defined {
19  
namespace implementation_defined {
20  
struct hexdig_chars_t
20  
struct hexdig_chars_t
21  
{
21  
{
22  
    /** Determine if a character is a hexadecimal digit
22  
    /** Determine if a character is a hexadecimal digit
23  

23  

24  
        @param c The character to test
24  
        @param c The character to test
25  
        @return `true` if `c` is a hexadecimal digit.
25  
        @return `true` if `c` is a hexadecimal digit.
26  
    */
26  
    */
27  
    constexpr
27  
    constexpr
28  
    bool
28  
    bool
29  
    operator()(char c) const noexcept
29  
    operator()(char c) const noexcept
30  
    {
30  
    {
31  
        return
31  
        return
32  
            (c >= '0' && c <= '9') ||
32  
            (c >= '0' && c <= '9') ||
33  
            (c >= 'A' && c <= 'F') ||
33  
            (c >= 'A' && c <= 'F') ||
34  
            (c >= 'a' && c <= 'f');
34  
            (c >= 'a' && c <= 'f');
35  
    }
35  
    }
36  

36  

37  
#ifdef BOOST_URL_USE_SSE2
37  
#ifdef BOOST_URL_USE_SSE2
38  
    char const*
38  
    char const*
39  
    find_if(
39  
    find_if(
40  
        char const* first,
40  
        char const* first,
41  
        char const* last) const noexcept
41  
        char const* last) const noexcept
42  
    {
42  
    {
43  
        return detail::find_if_pred(
43  
        return detail::find_if_pred(
44  
            *this, first, last);
44  
            *this, first, last);
45  
    }
45  
    }
46  

46  

47  
    char const*
47  
    char const*
48  
    find_if_not(
48  
    find_if_not(
49  
        char const* first,
49  
        char const* first,
50  
        char const* last) const noexcept
50  
        char const* last) const noexcept
51  
    {
51  
    {
52  
        return detail::find_if_not_pred(
52  
        return detail::find_if_not_pred(
53  
            *this, first, last);
53  
            *this, first, last);
54  
    }
54  
    }
55  
#endif
55  
#endif
56  
};
56  
};
57  
}
57  
}
58  

58  

59  
/** The set of hexadecimal digits
59  
/** The set of hexadecimal digits
60  

60  

61  
    @par Example
61  
    @par Example
62  
    Character sets are used with rules and the
62  
    Character sets are used with rules and the
63  
    functions @ref find_if and @ref find_if_not.
63  
    functions @ref find_if and @ref find_if_not.
64  
    @code
64  
    @code
65  
    system::result< core::string_view > rv = parse( "8086FC19", token_rule( hexdig_chars ) );
65  
    system::result< core::string_view > rv = parse( "8086FC19", token_rule( hexdig_chars ) );
66  
    @endcode
66  
    @endcode
67  

67  

68  
    @par BNF
68  
    @par BNF
69  
    @code
69  
    @code
70  
    HEXDIG      = DIGIT
70  
    HEXDIG      = DIGIT
71  
                / "A" / "B" / "C" / "D" / "E" / "F"
71  
                / "A" / "B" / "C" / "D" / "E" / "F"
72  
                / "a" / "b" / "c" / "d" / "e" / "f"
72  
                / "a" / "b" / "c" / "d" / "e" / "f"
73  
    @endcode
73  
    @endcode
74  

74  

75  
    @note The RFCs are inconsistent on the case
75  
    @note The RFCs are inconsistent on the case
76  
    sensitivity of hexadecimal digits. Existing
76  
    sensitivity of hexadecimal digits. Existing
77  
    uses suggest case-insensitivity is a de-facto
77  
    uses suggest case-insensitivity is a de-facto
78  
    standard.
78  
    standard.
79  

79  

80  
    @par Specification
80  
    @par Specification
81  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
81  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1"
82  
        >B.1. Core Rules (rfc5234)</a>
82  
        >B.1. Core Rules (rfc5234)</a>
83  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc7230#section-1.2"
83  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc7230#section-1.2"
84  
        >1.2. Syntax Notation (rfc7230)</a>
84  
        >1.2. Syntax Notation (rfc7230)</a>
85  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-2.3"
85  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-2.3"
86  
        >2.3. Uppercase or Lowercase (rfc5952)</a>
86  
        >2.3. Uppercase or Lowercase (rfc5952)</a>
87  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-4.3"
87  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-4.3"
88  
        >4.3. Lowercase (rfc5952)</a>
88  
        >4.3. Lowercase (rfc5952)</a>
89  

89  

90  
    @see
90  
    @see
91  
        @ref find_if,
91  
        @ref find_if,
92  
        @ref find_if_not,
92  
        @ref find_if_not,
93  
        @ref hexdig_value,
93  
        @ref hexdig_value,
94  
        @ref parse,
94  
        @ref parse,
95  
        @ref token_rule.
95  
        @ref token_rule.
96  
*/
96  
*/
97  
constexpr implementation_defined::hexdig_chars_t hexdig_chars{};
97  
constexpr implementation_defined::hexdig_chars_t hexdig_chars{};
98  

98  

99  
/** Return the decimal value of a hex character
99  
/** Return the decimal value of a hex character
100  

100  

101  
    This function returns the decimal
101  
    This function returns the decimal
102  
    value of a hexadecimal character,
102  
    value of a hexadecimal character,
103  
    or -1 if the argument is not a
103  
    or -1 if the argument is not a
104  
    valid hexadecimal digit.
104  
    valid hexadecimal digit.
105  

105  

106  
    @par BNF
106  
    @par BNF
107  
    @code
107  
    @code
108  
    HEXDIG      = DIGIT
108  
    HEXDIG      = DIGIT
109  
                / "A" / "B" / "C" / "D" / "E" / "F"
109  
                / "A" / "B" / "C" / "D" / "E" / "F"
110  
                / "a" / "b" / "c" / "d" / "e" / "f"
110  
                / "a" / "b" / "c" / "d" / "e" / "f"
111  
    @endcode
111  
    @endcode
112  

112  

113  
    @param ch The character to check
113  
    @param ch The character to check
114  

114  

115  
    @return The decimal value or -1
115  
    @return The decimal value or -1
116  
*/
116  
*/
117  
inline
117  
inline
118  
signed char
118  
signed char
119  
hexdig_value(char ch) noexcept
119  
hexdig_value(char ch) noexcept
120  
{
120  
{
121  
    // Idea for a switch statement to
121  
    // Idea for a switch statement to
122  
    // minimize emitted assembly from
122  
    // minimize emitted assembly from
123  
    // Glen Fernandes
123  
    // Glen Fernandes
124  
    signed char res;
124  
    signed char res;
125  
    switch(ch)
125  
    switch(ch)
126  
    {
126  
    {
127  
    default:            res = -1; break;
127  
    default:            res = -1; break;
128  
    case '0':           res =  0; break;
128  
    case '0':           res =  0; break;
129  
    case '1':           res =  1; break;
129  
    case '1':           res =  1; break;
130  
    case '2':           res =  2; break;
130  
    case '2':           res =  2; break;
131  
    case '3':           res =  3; break;
131  
    case '3':           res =  3; break;
132  
    case '4':           res =  4; break;
132  
    case '4':           res =  4; break;
133  
    case '5':           res =  5; break;
133  
    case '5':           res =  5; break;
134  
    case '6':           res =  6; break;
134  
    case '6':           res =  6; break;
135  
    case '7':           res =  7; break;
135  
    case '7':           res =  7; break;
136  
    case '8':           res =  8; break;
136  
    case '8':           res =  8; break;
137  
    case '9':           res =  9; break;
137  
    case '9':           res =  9; break;
138  
    case 'a': case 'A': res = 10; break;
138  
    case 'a': case 'A': res = 10; break;
139  
    case 'b': case 'B': res = 11; break;
139  
    case 'b': case 'B': res = 11; break;
140  
    case 'c': case 'C': res = 12; break;
140  
    case 'c': case 'C': res = 12; break;
141  
    case 'd': case 'D': res = 13; break;
141  
    case 'd': case 'D': res = 13; break;
142  
    case 'e': case 'E': res = 14; break;
142  
    case 'e': case 'E': res = 14; break;
143  
    case 'f': case 'F': res = 15; break;
143  
    case 'f': case 'F': res = 15; break;
144  
    }
144  
    }
145  
    return res;
145  
    return res;
146  
}
146  
}
147  

147  

148  
} // grammar
148  
} // grammar
149  
} // urls
149  
} // urls
150  
} // boost
150  
} // boost
151  

151  

152  
#endif
152  
#endif