1 // Boost string_generator.hpp header file ----------------------------------------------//
3 // Copyright 2010 Andy Tompkins.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_UUID_STRING_GENERATOR_HPP
9 #define BOOST_UUID_STRING_GENERATOR_HPP
11 #include <boost/uuid/uuid.hpp>
13 #include <cstring> // for strlen, wcslen
15 #include <algorithm> // for find
17 #include <boost/throw_exception.hpp>
19 #ifdef BOOST_NO_STDC_NAMESPACE
24 #endif //BOOST_NO_STDC_NAMESPACE
29 // generate a uuid from a string
30 // lexical_cast works fine using uuid_io.hpp
31 // but this generator should accept more forms
32 // and be more efficient
33 // would like to accept the following forms:
34 // 0123456789abcdef0123456789abcdef
35 // 01234567-89ab-cdef-0123456789abcdef
36 // {01234567-89ab-cdef-0123456789abcdef}
37 // {0123456789abcdef0123456789abcdef}
39 struct string_generator {
40 typedef uuid result_type;
42 template <typename ch, typename char_traits, typename alloc>
43 uuid operator()(std::basic_string<ch, char_traits, alloc> const& s) const {
44 return operator()(s.begin(), s.end());
47 uuid operator()(char const*const s) const {
48 return operator()(s, s+std::strlen(s));
51 uuid operator()(wchar_t const*const s) const {
52 return operator()(s, s+std::wcslen(s));
55 template <typename CharIterator>
56 uuid operator()(CharIterator begin, CharIterator end) const
58 typedef typename std::iterator_traits<CharIterator>::value_type char_type;
61 char_type c = get_next_char(begin, end);
62 bool has_open_brace = is_open_brace(c);
63 char_type open_brace_char = c;
65 c = get_next_char(begin, end);
68 bool has_dashes = false;
72 for (uuid::iterator it_byte=u.begin(); it_byte!=u.end(); ++it_byte, ++i) {
73 if (it_byte != u.begin()) {
74 c = get_next_char(begin, end);
78 has_dashes = is_dash(c);
80 c = get_next_char(begin, end);
85 if (i == 6 || i == 8 || i == 10) {
87 c = get_next_char(begin, end);
94 *it_byte = get_value(c);
96 c = get_next_char(begin, end);
98 *it_byte |= get_value(c);
102 if (has_open_brace) {
103 c = get_next_char(begin, end);
104 check_close_brace(c, open_brace_char);
111 template <typename CharIterator>
112 typename std::iterator_traits<CharIterator>::value_type
113 get_next_char(CharIterator& begin, CharIterator end) const {
120 unsigned char get_value(char c) const {
121 static char const*const digits_begin = "0123456789abcdefABCDEF";
122 static char const*const digits_end = digits_begin + 22;
124 static unsigned char const values[] =
125 { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15
126 , static_cast<unsigned char>(-1) };
128 char const* d = std::find(digits_begin, digits_end, c);
129 return values[d - digits_begin];
132 unsigned char get_value(wchar_t c) const {
133 static wchar_t const*const digits_begin = L"0123456789abcdefABCDEF";
134 static wchar_t const*const digits_end = digits_begin + 22;
136 static unsigned char const values[] =
137 { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15
138 , static_cast<unsigned char>(-1) };
140 wchar_t const* d = std::find(digits_begin, digits_end, c);
141 return values[d - digits_begin];
144 bool is_dash(char c) const {
148 bool is_dash(wchar_t c) const {
152 // return closing brace
153 bool is_open_brace(char c) const {
157 bool is_open_brace(wchar_t c) const {
161 void check_close_brace(char c, char open_brace) const {
162 if (open_brace == '{' && c == '}') {
169 void check_close_brace(wchar_t c, wchar_t open_brace) const {
170 if (open_brace == L'{' && c == L'}') {
177 void throw_invalid() const {
178 BOOST_THROW_EXCEPTION(std::runtime_error("invalid uuid string"));
182 }} // namespace boost::uuids
184 #endif //BOOST_UUID_STRING_GENERATOR_HPP