Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:30:44

0001 #ifndef BOOST_UUID_STRING_GENERATOR_HPP_INCLUDED
0002 #define BOOST_UUID_STRING_GENERATOR_HPP_INCLUDED
0003 
0004 // Copyright 2010 Andy Tompkins
0005 // Copyright 2024 Peter Dimov
0006 // Distributed under the Boost Software License, Version 1.0.
0007 // https://www.boost.org/LICENSE_1_0.txt
0008 
0009 #include <boost/uuid/uuid.hpp>
0010 #include <boost/throw_exception.hpp>
0011 #include <boost/config.hpp>
0012 #include <string>
0013 #include <iterator>
0014 #include <algorithm> // for find
0015 #include <stdexcept>
0016 #include <cstring> // for strlen, wcslen
0017 #include <cstdio>
0018 
0019 namespace boost {
0020 namespace uuids {
0021 
0022 // Generates a UUID from a string
0023 //
0024 // Accepts the following forms:
0025 //
0026 // 0123456789abcdef0123456789abcdef
0027 // 01234567-89ab-cdef-0123-456789abcdef
0028 // {01234567-89ab-cdef-0123-456789abcdef}
0029 // {0123456789abcdef0123456789abcdef}
0030 
0031 struct string_generator
0032 {
0033     using result_type = uuid;
0034 
0035     template<class Ch, class Traits, class Alloc>
0036     uuid operator()( std::basic_string<Ch, Traits, Alloc> const& s ) const
0037     {
0038         return operator()(s.begin(), s.end());
0039     }
0040 
0041     uuid operator()( char const* s ) const
0042     {
0043         return operator()( s, s + std::strlen( s ) );
0044     }
0045 
0046     uuid operator()( wchar_t const* s ) const
0047     {
0048         return operator()( s, s + std::wcslen( s ) );
0049     }
0050 
0051     template<class CharIterator>
0052     uuid operator()( CharIterator begin, CharIterator end ) const
0053     {
0054         using char_type = typename std::iterator_traits<CharIterator>::value_type;
0055 
0056         int ipos = 0;
0057 
0058         // check open brace
0059         char_type c = get_next_char( begin, end, ipos );
0060 
0061         bool has_open_brace = is_open_brace( c );
0062 
0063         char_type open_brace_char = c;
0064 
0065         if( has_open_brace )
0066         {
0067             c = get_next_char( begin, end, ipos );
0068         }
0069 
0070         bool has_dashes = false;
0071 
0072         uuid u;
0073 
0074         int i = 0;
0075 
0076         for( uuid::iterator it_byte = u.begin(); it_byte != u.end(); ++it_byte, ++i )
0077         {
0078             if( it_byte != u.begin() )
0079             {
0080                 c = get_next_char( begin, end, ipos );
0081             }
0082 
0083             if( i == 4 )
0084             {
0085                 has_dashes = is_dash( c );
0086 
0087                 if( has_dashes )
0088                 {
0089                     c = get_next_char( begin, end, ipos );
0090                 }
0091             }
0092             else if( i == 6 || i == 8 || i == 10 )
0093             {
0094                 // if there are dashes, they must be in every slot
0095                 if( has_dashes )
0096                 {
0097                     if( is_dash( c ) )
0098                     {
0099                         c = get_next_char( begin, end, ipos );
0100                     }
0101                     else
0102                     {
0103                         throw_invalid( ipos - 1, "dash expected" );
0104                     }
0105                 }
0106             }
0107 
0108             *it_byte = get_value( c, ipos - 1 );
0109 
0110             c = get_next_char( begin, end, ipos );
0111 
0112             *it_byte <<= 4;
0113             *it_byte |= get_value( c, ipos - 1 );
0114         }
0115 
0116         // check close brace
0117         if( has_open_brace )
0118         {
0119             c = get_next_char( begin, end, ipos );
0120             check_close_brace( c, open_brace_char, ipos - 1 );
0121         }
0122 
0123         // check end of string - any additional data is an invalid uuid
0124         if( begin != end )
0125         {
0126             throw_invalid( ipos, "unexpected extra input" );
0127         }
0128 
0129         return u;
0130     }
0131 
0132 private:
0133 
0134     BOOST_NORETURN void throw_invalid( int ipos, char const* error ) const
0135     {
0136         char buffer[ 16 ];
0137         std::snprintf( buffer, sizeof( buffer ), "%d", ipos );
0138 
0139         BOOST_THROW_EXCEPTION( std::runtime_error( std::string( "Invalid UUID string at position " ) + buffer + ": " + error ) );
0140     }
0141 
0142     template <typename CharIterator>
0143     typename std::iterator_traits<CharIterator>::value_type
0144     get_next_char( CharIterator& begin, CharIterator end, int& ipos ) const
0145     {
0146         if( begin == end )
0147         {
0148             throw_invalid( ipos, "unexpected end of input" );
0149         }
0150 
0151         ++ipos;
0152         return *begin++;
0153     }
0154 
0155     unsigned char get_value( char c, int ipos ) const
0156     {
0157         static char const digits_begin[] = "0123456789abcdefABCDEF";
0158         static size_t digits_len = (sizeof(digits_begin) / sizeof(char)) - 1;
0159         static char const* const digits_end = digits_begin + digits_len;
0160 
0161         static unsigned char const values[] =
0162             { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15 };
0163 
0164         size_t pos = std::find( digits_begin, digits_end, c ) - digits_begin;
0165 
0166         if( pos >= digits_len )
0167         {
0168             throw_invalid( ipos, "hex digit expected" );
0169         }
0170 
0171         return values[ pos ];
0172     }
0173 
0174     unsigned char get_value( wchar_t c, int ipos ) const
0175     {
0176         static wchar_t const digits_begin[] = L"0123456789abcdefABCDEF";
0177         static size_t digits_len = (sizeof(digits_begin) / sizeof(wchar_t)) - 1;
0178         static wchar_t const* const digits_end = digits_begin + digits_len;
0179 
0180         static unsigned char const values[] =
0181             { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11,12,13,14,15 };
0182 
0183         size_t pos = std::find( digits_begin, digits_end, c ) - digits_begin;
0184 
0185         if( pos >= digits_len )
0186         {
0187             throw_invalid( ipos, "hex digit expected" );
0188         }
0189 
0190         return values[ pos ];
0191     }
0192 
0193     bool is_dash( char c ) const
0194     {
0195         return c == '-';
0196     }
0197 
0198     bool is_dash( wchar_t c ) const
0199     {
0200         return c == L'-';
0201     }
0202 
0203     // return closing brace
0204     bool is_open_brace( char c ) const
0205     {
0206         return c == '{';
0207     }
0208 
0209     bool is_open_brace( wchar_t c ) const
0210     {
0211         return c == L'{';
0212     }
0213 
0214     void check_close_brace( char c, char open_brace, int ipos ) const
0215     {
0216         if( open_brace == '{' && c == '}' )
0217         {
0218             //great
0219         }
0220         else
0221         {
0222             throw_invalid( ipos, "closing brace expected" );
0223         }
0224     }
0225 
0226     void check_close_brace( wchar_t c, wchar_t open_brace, int ipos ) const
0227     {
0228         if( open_brace == L'{' && c == L'}' )
0229         {
0230             // great
0231         }
0232         else
0233         {
0234             throw_invalid( ipos, "closing brace expected" );
0235         }
0236     }
0237 };
0238 
0239 }} // namespace boost::uuids
0240 
0241 #endif // BOOST_UUID_STRING_GENERATOR_HPP_INCLUDED