uuid_io.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #ifndef BOOST_UUID_UUID_IO_HPP_INCLUDED
  2. #define BOOST_UUID_UUID_IO_HPP_INCLUDED
  3. // Copyright 2009 Andy Tompkins
  4. // Copyright 2024 Peter Dimov
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // https://www.boost.org/LICENSE_1_0.txt
  7. #include <boost/uuid/uuid.hpp>
  8. #include <boost/uuid/detail/to_chars.hpp>
  9. #include <boost/uuid/detail/static_assert.hpp>
  10. #include <boost/config.hpp>
  11. #include <iosfwd>
  12. #include <istream>
  13. #include <locale>
  14. #include <algorithm>
  15. #include <string>
  16. #include <cstddef>
  17. #if defined(_MSC_VER)
  18. #pragma warning(push) // Save warning settings.
  19. #pragma warning(disable : 4996) // Disable deprecated std::ctype<char>::widen, std::copy
  20. #endif
  21. namespace boost {
  22. namespace uuids {
  23. // to_chars
  24. template<class OutputIterator>
  25. OutputIterator to_chars( uuid const& u, OutputIterator out )
  26. {
  27. char tmp[ 36 ];
  28. detail::to_chars( u, tmp );
  29. return std::copy_n( tmp, 36, out );
  30. }
  31. template<class Ch>
  32. inline bool to_chars( uuid const& u, Ch* first, Ch* last ) noexcept
  33. {
  34. if( last - first < 36 )
  35. {
  36. return false;
  37. }
  38. detail::to_chars( u, first );
  39. return true;
  40. }
  41. template<class Ch, std::size_t N>
  42. inline Ch* to_chars( uuid const& u, Ch (&buffer)[ N ] ) noexcept
  43. {
  44. BOOST_UUID_STATIC_ASSERT( N >= 37 );
  45. detail::to_chars( u, buffer + 0 );
  46. buffer[ 36 ] = 0;
  47. return buffer + 36;
  48. }
  49. // only provided for compatibility; deprecated
  50. template<class Ch>
  51. BOOST_DEPRECATED( "Use Ch[37] instead of Ch[36] to allow for the null terminator" )
  52. inline Ch* to_chars( uuid const& u, Ch (&buffer)[ 36 ] ) noexcept
  53. {
  54. detail::to_chars( u, buffer + 0 );
  55. return buffer + 36;
  56. }
  57. // operator<<
  58. template<class Ch, class Traits>
  59. std::basic_ostream<Ch, Traits>& operator<<( std::basic_ostream<Ch, Traits>& os, uuid const& u )
  60. {
  61. char tmp[ 37 ];
  62. to_chars( u, tmp );
  63. os << tmp;
  64. return os;
  65. }
  66. // operator>>
  67. template<class Ch, class Traits>
  68. std::basic_istream<Ch, Traits>& operator>>( std::basic_istream<Ch, Traits>& is, uuid& u )
  69. {
  70. Ch tmp[ 37 ] = {};
  71. is.width( 37 ); // required for pre-C++20
  72. if( is >> tmp )
  73. {
  74. u = {};
  75. using ctype_t = std::ctype<Ch>;
  76. ctype_t const& ctype = std::use_facet<ctype_t>( is.getloc() );
  77. Ch xdigits[ 17 ];
  78. {
  79. char szdigits[] = "0123456789ABCDEF-";
  80. ctype.widen( szdigits, szdigits + 17, xdigits );
  81. }
  82. Ch* const xdigits_end = xdigits + 16;
  83. ctype.toupper( tmp, tmp + 36 );
  84. int j = 0;
  85. for( std::size_t i = 0; i < 16; ++i )
  86. {
  87. Ch* f = std::find( xdigits, xdigits_end, tmp[ j++ ] );
  88. if( f == xdigits_end )
  89. {
  90. is.setstate( std::ios_base::failbit );
  91. return is;
  92. }
  93. unsigned char byte = static_cast<unsigned char>( f - xdigits );
  94. f = std::find( xdigits, xdigits_end, tmp[ j++ ] );
  95. if( f == xdigits_end )
  96. {
  97. is.setstate( std::ios_base::failbit );
  98. return is;
  99. }
  100. byte <<= 4;
  101. byte |= static_cast<unsigned char>( f - xdigits );
  102. u.data()[ i ] = byte;
  103. if( i == 3 || i == 5 || i == 7 || i == 9 )
  104. {
  105. if( tmp[ j++ ] != xdigits[ 16 ] )
  106. {
  107. is.setstate( std::ios_base::failbit );
  108. return is;
  109. }
  110. }
  111. }
  112. }
  113. return is;
  114. }
  115. // to_string
  116. inline std::string to_string( uuid const& u )
  117. {
  118. std::string result( 36, char() );
  119. // string::data() returns const char* before C++17
  120. detail::to_chars( u, &result[0] );
  121. return result;
  122. }
  123. inline std::wstring to_wstring( uuid const& u )
  124. {
  125. std::wstring result( 36, wchar_t() );
  126. detail::to_chars( u, &result[0] );
  127. return result;
  128. }
  129. }} //namespace boost::uuids
  130. #if defined(_MSC_VER)
  131. #pragma warning(pop) // Restore warnings to previous state.
  132. #endif
  133. #endif // BOOST_UUID_UUID_IO_HPP_INCLUDED