├── 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 | --------------------------------------------------------------------------------