Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:08

0001 // Boost string_generator.hpp header file  ----------------------------------------------//
0002 
0003 // Copyright 2010 Andy Tompkins.
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // https://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_UUID_STRING_GENERATOR_HPP
0009 #define BOOST_UUID_STRING_GENERATOR_HPP
0010 
0011 #include <boost/uuid/uuid.hpp>
0012 #include <string>
0013 #include <cstring> // for strlen, wcslen
0014 #include <iterator>
0015 #include <algorithm> // for find
0016 #include <stdexcept>
0017 #include <boost/throw_exception.hpp>
0018 #include <boost/config.hpp>
0019 
0020 #ifdef BOOST_NO_STDC_NAMESPACE
0021 namespace std {
0022     using ::strlen;
0023     using ::wcslen;
0024 } //namespace std
0025 #endif //BOOST_NO_STDC_NAMESPACE
0026 
0027 namespace boost {
0028 namespace uuids {
0029 
0030 // generate a uuid from a string
0031 // lexical_cast works fine using uuid_io.hpp
0032 // but this generator should accept more forms
0033 // and be more efficient
0034 // would like to accept the following forms:
0035 // 0123456789abcdef0123456789abcdef
0036 // 01234567-89ab-cdef-0123-456789abcdef
0037 // {01234567-89ab-cdef-0123-456789abcdef}
0038 // {0123456789abcdef0123456789abcdef}
0039 // others?
0040 struct string_generator {
0041     typedef uuid result_type;
0042     
0043     template <typename ch, typename char_traits, typename alloc>
0044     uuid operator()(std::basic_string<ch, char_traits, alloc> const& s) const {
0045         return operator()(s.begin(), s.end());
0046     }
0047 
0048     uuid operator()(char const*const s) const {
0049         return operator()(s, s+std::strlen(s));
0050     }
0051 
0052     uuid operator()(wchar_t const*const s) const {
0053         return operator()(s, s+std::wcslen(s));
0054     }
0055 
0056     template <typename CharIterator>
0057     uuid operator()(CharIterator begin, CharIterator end) const
0058     {
0059         typedef typename std::iterator_traits<CharIterator>::value_type char_type;
0060 
0061         // check open brace
0062         char_type c = get_next_char(begin, end);
0063         bool has_open_brace = is_open_brace(c);
0064         char_type open_brace_char = c;
0065         if (has_open_brace) {
0066             c = get_next_char(begin, end);
0067         }
0068 
0069         bool has_dashes = false;
0070 
0071         uuid u;
0072         int i=0;
0073         for (uuid::iterator it_byte=u.begin(); it_byte!=u.end(); ++it_byte, ++i) {
0074             if (it_byte != u.begin()) {
0075                 c = get_next_char(begin, end);
0076             }
0077             
0078             if (i == 4) {
0079                 has_dashes = is_dash(c);
0080                 if (has_dashes) {
0081                     c = get_next_char(begin, end);
0082                 }
0083             }
0084             
0085             // if there are dashes, they must be in every slot
0086             else if (i == 6 || i == 8 || i == 10) {
0087                 if (has_dashes == true) {
0088                     if (is_dash(c)) {
0089                         c = get_next_char(begin, end);
0090                     } else {
0091                         throw_invalid();
0092                     }
0093                 }
0094             }
0095                 
0096 
0097             *it_byte = get_value(c);
0098 
0099             c = get_next_char(begin, end);
0100             *it_byte <<= 4;
0101             *it_byte |= get_value(c);
0102         }
0103 
0104         // check close brace
0105         if (has_open_brace) {
0106             c = get_next_char(begin, end);
0107             check_close_brace(c, open_brace_char);
0108         }
0109 
0110         // check end of string - any additional data is an invalid uuid
0111         if (begin != end) {
0112             throw_invalid();
0113         }
0114         
0115         return u;
0116     }
0117     
0118 private:
0119     template <typename CharIterator>
0120     typename std::iterator_traits<CharIterator>::value_type
0121     get_next_char(CharIterator& begin, CharIterator end) const {
0122         if (begin == end) {
0123             throw_invalid();
0124         }
0125         return *begin++;
0126     }
0127 
0128     unsigned char get_value(char c) const {
0129         static char const digits_begin[] = "0123456789abcdefABCDEF";
0130         static size_t digits_len = (sizeof(digits_begin) / sizeof(char)) - 1;
0131         static char const*const digits_end = digits_begin + digits_len;
0132 
0133         static unsigned char const values[] =
0134             { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15 };
0135 
0136         size_t pos = std::find(digits_begin, digits_end, c) - digits_begin;
0137         if (pos >= digits_len) {
0138             throw_invalid();
0139         }
0140         return values[pos];
0141     }
0142 
0143     unsigned char get_value(wchar_t c) const {
0144         static wchar_t const digits_begin[] = L"0123456789abcdefABCDEF";
0145         static size_t digits_len = (sizeof(digits_begin) / sizeof(wchar_t)) - 1;
0146         static wchar_t const*const digits_end = digits_begin + digits_len;
0147         
0148         static unsigned char const values[] =
0149             { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15 };
0150 
0151         size_t pos = std::find(digits_begin, digits_end, c) - digits_begin;
0152         if (pos >= digits_len) {
0153             throw_invalid();
0154         }
0155         return values[pos];
0156     }
0157 
0158     bool is_dash(char c) const {
0159         return c == '-';
0160     }
0161     
0162     bool is_dash(wchar_t c) const {
0163         return c == L'-';
0164     }
0165     
0166     // return closing brace
0167     bool is_open_brace(char c) const {
0168         return (c == '{');
0169     }
0170     
0171     bool is_open_brace(wchar_t c) const {
0172         return (c == L'{');
0173     }
0174     
0175     void check_close_brace(char c, char open_brace) const {
0176         if (open_brace == '{' && c == '}') {
0177             //great
0178         } else {
0179             throw_invalid();
0180         }
0181     }
0182     
0183     void check_close_brace(wchar_t c, wchar_t open_brace) const {
0184         if (open_brace == L'{' && c == L'}') {
0185             // great
0186         } else {
0187             throw_invalid();
0188         }
0189     }
0190     
0191     BOOST_NORETURN void throw_invalid() const {
0192         BOOST_THROW_EXCEPTION(std::runtime_error("invalid uuid string"));
0193     }
0194 };
0195 
0196 }} // namespace boost::uuids
0197 
0198 #endif //BOOST_UUID_STRING_GENERATOR_HPP
0199