├── README.md
├── guid_parse.hpp
└── uuid_parse.hpp
/README.md:
--------------------------------------------------------------------------------
1 | # constexpr-GUID-C-11-
2 | constexpr GUID parsing in C++11
3 |
4 | inspired by https://gist.github.com/AlexBAV/b58e92d7632bae5d6f5947be455f796f
5 |
6 | usage
7 |
8 |
9 | constexpr const GUID clsid = guid_parse::make_guid("{EFECF0A1-399E-40B8-A13C-ACE28DB40212}");
10 |
11 |
12 | or
13 |
14 |
15 | using namespace guid_parse::literals;
16 |
17 | constexpr const GUID clsid = "{EFECF0A1-399E-40B8-A13C-ACE28DB40212}"_guid;
18 |
19 |
20 | The file uuid_parse.hpp contains constexpr conversion-functions for boost::uuids::uuid
.
21 |
--------------------------------------------------------------------------------
/guid_parse.hpp:
--------------------------------------------------------------------------------
1 | //-------------------------------------------------------------------------------------------------------
2 | // constexpr GUID parsing
3 | // Written by Alexander Bessonov
4 | // Written by Tobias Loew
5 | //
6 | // Licensed under the MIT license.
7 | //-------------------------------------------------------------------------------------------------------
8 |
9 | #pragma once
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #if !defined(GUID_DEFINED)
16 | #define GUID_DEFINED
17 | struct GUID {
18 | uint32_t Data1;
19 | uint16_t Data2;
20 | uint16_t Data3;
21 | uint8_t Data4[8];
22 | };
23 | #endif
24 |
25 | namespace guid_parse
26 | {
27 | namespace details
28 | {
29 | constexpr const size_t short_guid_form_length = 36; // XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
30 | constexpr const size_t long_guid_form_length = 38; // {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
31 |
32 | //
33 | constexpr uint8_t parse_hex_digit(const char c)
34 | {
35 | using namespace std::string_literals;
36 | return
37 | ('0' <= c && c <= '9')
38 | ? c - '0'
39 | : ('a' <= c && c <= 'f')
40 | ? 10 + c - 'a'
41 | : ('A' <= c && c <= 'F')
42 | ? 10 + c - 'A'
43 | :
44 | throw std::domain_error{ "invalid character in GUID"s };
45 | }
46 |
47 | constexpr uint8_t parse_hex_uint8_t(const char *ptr)
48 | {
49 | return (parse_hex_digit(ptr[0]) << 4) + parse_hex_digit(ptr[1]);
50 | }
51 |
52 | constexpr uint16_t parse_hex_uint16_t(const char *ptr)
53 | {
54 | return (parse_hex_uint8_t(ptr) << 8) + parse_hex_uint8_t(ptr + 2);
55 | }
56 |
57 | constexpr uint32_t parse_hex_uint32_t(const char *ptr)
58 | {
59 | return (parse_hex_uint16_t(ptr) << 16) + parse_hex_uint16_t(ptr + 4);
60 | }
61 |
62 | constexpr GUID parse_guid(const char *begin)
63 | {
64 | return GUID{
65 | parse_hex_uint32_t(begin),
66 | parse_hex_uint16_t(begin + 8 + 1),
67 | parse_hex_uint16_t(begin + 8 + 1 + 4 + 1),
68 | {
69 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1),
70 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2),
71 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2 + 2 + 1),
72 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2 + 2 + 1 + 2),
73 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2 + 2 + 1 + 2 + 2),
74 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2 + 2 + 1 + 2 + 2 + 2),
75 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2 + 2 + 1 + 2 + 2 + 2 + 2),
76 | parse_hex_uint8_t(begin + 8 + 1 + 4 + 1 + 4 + 1 + 2 + 2 + 1 + 2 + 2 + 2 + 2 + 2)
77 | }
78 |
79 | };
80 | }
81 |
82 | constexpr GUID make_guid_helper(const char *str, size_t N)
83 | {
84 | using namespace std::string_literals;
85 | using namespace details;
86 |
87 | return (!(N == long_guid_form_length || N == short_guid_form_length))
88 | ? throw std::domain_error{ "String GUID of the form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} or XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX is expected"s }
89 | : (N == long_guid_form_length && (str[0] != '{' || str[long_guid_form_length - 1] != '}'))
90 | ? throw std::domain_error{ "Missing opening or closing brace"s }
91 |
92 | : parse_guid(str + (N == long_guid_form_length ? 1 : 0));
93 | }
94 |
95 |
96 | template
97 | constexpr GUID make_guid(const char(&str)[N])
98 | {
99 | return make_guid_helper(str, N - 1);
100 | }
101 | }
102 | using details::make_guid;
103 |
104 | namespace literals
105 | {
106 | constexpr GUID operator "" _guid(const char *str, size_t N)
107 | {
108 | using namespace details;
109 | return make_guid_helper(str, N);
110 | }
111 | }
112 | }
113 |
114 |
115 |
--------------------------------------------------------------------------------
/uuid_parse.hpp:
--------------------------------------------------------------------------------
1 | //-------------------------------------------------------------------------------------------------------
2 | // constexpr GUID parsing
3 | // Written by Alexander Bessonov
4 | // Written by Tobias Loew
5 | //
6 | // Licensed under the MIT license.
7 | //-------------------------------------------------------------------------------------------------------
8 |
9 | #pragma once
10 | #include
11 | #include "guid_parse.hpp"
12 |
13 |
14 | namespace guid_parse
15 | {
16 | namespace details {
17 |
18 | template
19 | constexpr uint8_t get_nth_byte_of(T data, size_t pos) {
20 | return ((uint8_t)((data >> (8 * pos)) & 0xff));
21 | }
22 |
23 | constexpr boost::uuids::uuid uuid_creator(GUID guid) {
24 | return
25 | boost::uuids::uuid
26 | { get_nth_byte_of(guid.Data1, 3), get_nth_byte_of(guid.Data1, 2), get_nth_byte_of(guid.Data1, 1), get_nth_byte_of(guid.Data1, 0)
27 | , get_nth_byte_of(guid.Data2, 1), get_nth_byte_of(guid.Data2, 0)
28 | , get_nth_byte_of(guid.Data3, 1), get_nth_byte_of(guid.Data3, 0)
29 | , guid.Data4[0], guid.Data4[1],guid.Data4[2],guid.Data4[3],guid.Data4[4],guid.Data4[5],guid.Data4[6],guid.Data4[7]
30 | };
31 | }
32 |
33 | constexpr boost::uuids::uuid make_uuid_helper(const char *str, size_t N)
34 | {
35 | using namespace std::string_literals;
36 | using namespace details;
37 |
38 | return
39 | uuid_creator(
40 | (!(N == long_guid_form_length || N == short_guid_form_length))
41 | ? throw std::domain_error{ "String GUID of the form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} or XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX is expected"s }
42 | : (N == long_guid_form_length && (str[0] != '{' || str[long_guid_form_length - 1] != '}'))
43 | ? throw std::domain_error{ "Missing opening or closing brace"s }
44 |
45 | : parse_guid(str + (N == long_guid_form_length ? 1 : 0))
46 | );
47 | }
48 |
49 | template
50 | constexpr boost::uuids::uuid make_uuid(const char(&str)[N])
51 | {
52 | return make_uuid_helper(str, N - 1);
53 | }
54 | }
55 |
56 | using details::make_uuid;
57 |
58 | namespace literals
59 | {
60 | constexpr boost::uuids::uuid operator "" _uuid(const char *str, size_t N)
61 | {
62 | using namespace details;
63 | return make_uuid_helper(str, N);
64 | }
65 | }
66 | }
67 |
68 |
69 |
--------------------------------------------------------------------------------