1 | // Boost uuid_io.hpp header file ----------------------------------------------// |
2 | |
3 | // Copyright 2009 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) |
7 | |
8 | // Revision History |
9 | // 20 Mar 2009 - Initial Revision |
10 | // 28 Nov 2009 - disabled deprecated warnings for MSVC |
11 | |
12 | #ifndef BOOST_UUID_IO_HPP |
13 | #define BOOST_UUID_IO_HPP |
14 | |
15 | #include <boost/uuid/uuid.hpp> |
16 | #include <ios> |
17 | #include <ostream> |
18 | #include <istream> |
19 | #include <boost/io/ios_state.hpp> |
20 | #include <locale> |
21 | #include <algorithm> |
22 | |
23 | #if defined(_MSC_VER) |
24 | #pragma warning(push) // Save warning settings. |
25 | #pragma warning(disable : 4996) // Disable deprecated std::ctype<char>::widen, std::copy |
26 | #endif |
27 | |
28 | namespace boost { |
29 | namespace uuids { |
30 | |
31 | template <typename ch, typename char_traits> |
32 | std::basic_ostream<ch, char_traits>& operator<<(std::basic_ostream<ch, char_traits> &os, uuid const& u) |
33 | { |
34 | io::ios_flags_saver flags_saver(os); |
35 | io::basic_ios_fill_saver<ch, char_traits> fill_saver(os); |
36 | |
37 | const typename std::basic_ostream<ch, char_traits>::sentry ok(os); |
38 | if (ok) { |
39 | const std::streamsize width = os.width(0); |
40 | const std::streamsize uuid_width = 36; |
41 | const std::ios_base::fmtflags flags = os.flags(); |
42 | const typename std::basic_ios<ch, char_traits>::char_type fill = os.fill(); |
43 | if (flags & (std::ios_base::right | std::ios_base::internal)) { |
44 | for (std::streamsize i=uuid_width; i<width; i++) { |
45 | os << fill; |
46 | } |
47 | } |
48 | |
49 | os << std::hex; |
50 | os.fill(os.widen('0')); |
51 | |
52 | std::size_t i=0; |
53 | for (uuid::const_iterator i_data = u.begin(); i_data!=u.end(); ++i_data, ++i) { |
54 | os.width(2); |
55 | os << static_cast<unsigned int>(*i_data); |
56 | if (i == 3 || i == 5 || i == 7 || i == 9) { |
57 | os << os.widen('-'); |
58 | } |
59 | } |
60 | |
61 | if (flags & std::ios_base::left) { |
62 | for (std::streamsize s=uuid_width; s<width; s++) { |
63 | os << fill; |
64 | } |
65 | } |
66 | |
67 | os.width(0); //used the width so reset it |
68 | } |
69 | return os; |
70 | } |
71 | |
72 | template <typename ch, typename char_traits> |
73 | std::basic_istream<ch, char_traits>& operator>>(std::basic_istream<ch, char_traits> &is, uuid &u) |
74 | { |
75 | const typename std::basic_istream<ch, char_traits>::sentry ok(is); |
76 | if (ok) { |
77 | unsigned char data[16]; |
78 | |
79 | typedef std::ctype<ch> ctype_t; |
80 | ctype_t const& ctype = std::use_facet<ctype_t>(is.getloc()); |
81 | |
82 | ch xdigits[16]; |
83 | { |
84 | char szdigits[] = "0123456789ABCDEF" ; |
85 | ctype.widen(szdigits, szdigits+16, xdigits); |
86 | } |
87 | ch*const xdigits_end = xdigits+16; |
88 | |
89 | ch c; |
90 | for (std::size_t i=0; i<u.size() && is; ++i) { |
91 | is >> c; |
92 | c = ctype.toupper(c); |
93 | |
94 | ch* f = std::find(xdigits, xdigits_end, c); |
95 | if (f == xdigits_end) { |
96 | is.setstate(std::ios_base::failbit); |
97 | break; |
98 | } |
99 | |
100 | unsigned char byte = static_cast<unsigned char>(std::distance(&xdigits[0], f)); |
101 | |
102 | is >> c; |
103 | c = ctype.toupper(c); |
104 | f = std::find(xdigits, xdigits_end, c); |
105 | if (f == xdigits_end) { |
106 | is.setstate(std::ios_base::failbit); |
107 | break; |
108 | } |
109 | |
110 | byte <<= 4; |
111 | byte |= static_cast<unsigned char>(std::distance(&xdigits[0], f)); |
112 | |
113 | data[i] = byte; |
114 | |
115 | if (is) { |
116 | if (i == 3 || i == 5 || i == 7 || i == 9) { |
117 | is >> c; |
118 | if (c != is.widen('-')) is.setstate(std::ios_base::failbit); |
119 | } |
120 | } |
121 | } |
122 | |
123 | if (is) { |
124 | std::copy(data, data+16, u.begin()); |
125 | } |
126 | } |
127 | return is; |
128 | } |
129 | |
130 | namespace detail { |
131 | inline char to_char(size_t i) { |
132 | if (i <= 9) { |
133 | return static_cast<char>('0' + i); |
134 | } else { |
135 | return static_cast<char>('a' + (i-10)); |
136 | } |
137 | } |
138 | |
139 | inline wchar_t to_wchar(size_t i) { |
140 | if (i <= 9) { |
141 | return static_cast<wchar_t>(L'0' + i); |
142 | } else { |
143 | return static_cast<wchar_t>(L'a' + (i-10)); |
144 | } |
145 | } |
146 | |
147 | } // namespace detail |
148 | |
149 | inline std::string to_string(uuid const& u) |
150 | { |
151 | std::string result; |
152 | result.reserve(36); |
153 | |
154 | std::size_t i=0; |
155 | for (uuid::const_iterator it_data = u.begin(); it_data!=u.end(); ++it_data, ++i) { |
156 | const size_t hi = ((*it_data) >> 4) & 0x0F; |
157 | result += detail::to_char(hi); |
158 | |
159 | const size_t lo = (*it_data) & 0x0F; |
160 | result += detail::to_char(lo); |
161 | |
162 | if (i == 3 || i == 5 || i == 7 || i == 9) { |
163 | result += '-'; |
164 | } |
165 | } |
166 | return result; |
167 | } |
168 | |
169 | #ifndef BOOST_NO_STD_WSTRING |
170 | inline std::wstring to_wstring(uuid const& u) |
171 | { |
172 | std::wstring result; |
173 | result.reserve(36); |
174 | |
175 | std::size_t i=0; |
176 | for (uuid::const_iterator it_data = u.begin(); it_data!=u.end(); ++it_data, ++i) { |
177 | const size_t hi = ((*it_data) >> 4) & 0x0F; |
178 | result += detail::to_wchar(hi); |
179 | |
180 | const size_t lo = (*it_data) & 0x0F; |
181 | result += detail::to_wchar(lo); |
182 | |
183 | if (i == 3 || i == 5 || i == 7 || i == 9) { |
184 | result += L'-'; |
185 | } |
186 | } |
187 | return result; |
188 | } |
189 | |
190 | #endif |
191 | |
192 | }} //namespace boost::uuids |
193 | |
194 | #if defined(_MSC_VER) |
195 | #pragma warning(pop) // Restore warnings to previous state. |
196 | #endif |
197 | |
198 | #endif // BOOST_UUID_IO_HPP |
199 | |