2
0
mirror of https://github.com/boostorg/uuid.git synced 2026-01-19 04:42:16 +00:00

One can define BOOST_UUID_NO_TYPE_TRAITS to remove the dependency on Boost.TypeTraits.

Stream operator<< handles left, internal, and right manipulators.
Added to_string, to_wstring
Fixed bug in 3 uuid string in documentation


[SVN r63941]
This commit is contained in:
Andy Tompkins
2010-07-13 00:37:17 +00:00
parent db4414ffc9
commit 967a19964c
6 changed files with 231 additions and 21 deletions

View File

@@ -37,8 +37,10 @@
#include <boost/cstdint.hpp>
#include <algorithm>
#include <boost/config.hpp> // for static assert
#include <boost/mpl/bool.hpp>
#ifndef BOOST_UUID_NO_TYPE_TRAITS
#include <boost/type_traits/is_pod.hpp>
#include <boost/type_traits/integral_constant.hpp>
#endif
#if defined(_MSC_VER)
#pragma warning(push) // Save warning settings.
@@ -202,14 +204,15 @@ inline std::size_t hash_value(uuid const& u) /* throw() */
}} //namespace boost::uuids
#ifndef BOOST_UUID_NO_TYPE_TRAITS
// type traits specializations
namespace boost {
template <>
struct is_pod<uuids::uuid> : mpl::true_
{};
struct is_pod<uuids::uuid> : true_type {};
} // namespace boost
#endif
#if defined(_MSC_VER)
#pragma warning(pop) // Restore warnings to previous state.

View File

@@ -32,11 +32,20 @@ template <typename ch, typename char_traits>
std::basic_ostream<ch, char_traits>& operator<<(std::basic_ostream<ch, char_traits> &os, uuid const& u)
{
io::ios_flags_saver flags_saver(os);
io::ios_width_saver width_saver(os);
io::basic_ios_fill_saver<ch, char_traits> fill_saver(os);
const typename std::basic_ostream<ch, char_traits>::sentry ok(os);
if (ok) {
const std::streamsize width = os.width(0);
const std::streamsize uuid_width = 36;
const std::ios_base::fmtflags flags = os.flags();
const typename std::basic_ios<ch, char_traits>::char_type fill = os.fill();
if (flags & (std::ios_base::right | std::ios_base::internal)) {
for (std::streamsize i=uuid_width; i<width; i++) {
os << fill;
}
}
os << std::hex;
os.fill(os.widen('0'));
@@ -48,6 +57,14 @@ template <typename ch, typename char_traits>
os << os.widen('-');
}
}
if (flags & std::ios_base::left) {
for (std::streamsize i=uuid_width; i<width; i++) {
os << fill;
}
}
os.width(0); //used the width so reset it
}
return os;
}
@@ -110,6 +127,68 @@ template <typename ch, typename char_traits>
return is;
}
namespace detail {
inline char to_char(size_t i) {
if (i <= 9) {
return static_cast<char>('0' + i);
} else {
return static_cast<char>('a' + (i-10));
}
}
inline wchar_t to_wchar(size_t i) {
if (i <= 9) {
return static_cast<wchar_t>(L'0' + i);
} else {
return static_cast<wchar_t>(L'a' + (i-10));
}
}
} // namespace detail
inline std::string to_string(uuid const& u)
{
std::string result;
result.reserve(36);
std::size_t i=0;
for (uuid::const_iterator it_data = u.begin(); it_data!=u.end(); ++it_data, ++i) {
const size_t hi = ((*it_data) >> 4) & 0x0F;
result += detail::to_char(hi);
const size_t lo = (*it_data) & 0x0F;
result += detail::to_char(lo);
if (i == 3 || i == 5 || i == 7 || i == 9) {
result += '-';
}
}
return result;
}
#ifndef BOOST_NO_STD_WSTRING
inline std::wstring to_wstring(uuid const& u)
{
std::wstring result;
result.reserve(36);
std::size_t i=0;
for (uuid::const_iterator it_data = u.begin(); it_data!=u.end(); ++it_data, ++i) {
const size_t hi = ((*it_data) >> 4) & 0x0F;
result += detail::to_wchar(hi);
const size_t lo = (*it_data) & 0x0F;
result += detail::to_wchar(lo);
if (i == 3 || i == 5 || i == 7 || i == 9) {
result += L'-';
}
}
return result;
}
#endif
}} //namespace boost::uuids
#if defined(_MSC_VER)

View File

@@ -8,6 +8,7 @@ import testing ;
test-suite uuid :
# make sure each header file is self-contained
[ compile compile_uuid.cpp ]
[ compile compile_uuid.cpp : <define>BOOST_UUID_NO_TYPE_TRAITS : compile_uuid_no_type_traits ]
[ compile compile_uuid_io.cpp ]
[ compile compile_uuid_serialize.cpp ]
[ compile compile_uuid_generators.cpp ]
@@ -40,8 +41,7 @@ test-suite uuid :
[ run test_uuid_class.cpp ]
# test serializing uuids
[ run test_serialization.cpp ../../serialization/build//boost_serialization
]
[ run test_serialization.cpp ../../serialization/build//boost_serialization ]
# TODO - This test fails to like with boost_wserialization
#[ run test_wserialization.cpp
# ../../serialization/build//boost_serialization

View File

@@ -7,7 +7,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Purpose to make sure that a translation unit consisting of just the contents
// Purpose to make sure that a translation unit consisting of just the contents
// of the header file will compile successfully.
#include <boost/uuid/uuid.hpp>

View File

@@ -15,6 +15,20 @@
#include <boost/lexical_cast.hpp>
#include <string>
#include <sstream>
#include <iomanip>
#ifndef BOOST_NO_STD_WSTRING
namespace std {
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& os, std::wstring const& s) {
// convert to string
std::string temp(s.begin(), s.end());
os << temp;
return os;
}
} // namespace std
#endif
int main(int, char*[])
{
@@ -36,8 +50,48 @@ int main(int, char*[])
std::stringstream ss3;
ss3 << u3;
BOOST_TEST_EQ(ss3.str(), "12345678-90ab-cdef-1234-567890abcdef");
std::stringstream ss4;
ss4 << std::uppercase << u3;
BOOST_TEST_EQ(ss4.str(), "12345678-90AB-CDEF-1234-567890ABCDEF");
std::stringstream ss5;
ss5 << 'a' << std::right << std::setfill('*') << std::setw(40) << u1 << 'a';
BOOST_TEST_EQ(ss5.str(), "a****00000000-0000-0000-0000-000000000000a");
std::stringstream ss6;
ss6 << std::left << std::setfill('*') << std::setw(45) << u1;
BOOST_TEST_EQ(ss6.str(), "00000000-0000-0000-0000-000000000000*********");
}
#ifndef BOOST_NO_STD_WSTRING
{ // test insert/extract operators
std::wstringstream ss1;
ss1 << u1;
BOOST_TEST_EQ(ss1.str(), L"00000000-0000-0000-0000-000000000000");
std::wstringstream ss2;
ss2 << u2;
BOOST_TEST_EQ(ss2.str(), L"00010203-0405-0607-0809-0a0b0c0d0e0f");
std::wstringstream ss3;
ss3 << u3;
BOOST_TEST_EQ(ss3.str(), L"12345678-90ab-cdef-1234-567890abcdef");
std::wstringstream ss4;
ss4 << std::uppercase << u3;
BOOST_TEST_EQ(ss4.str(), L"12345678-90AB-CDEF-1234-567890ABCDEF");
std::wstringstream ss5;
ss5 << L'a' << std::right << std::setfill(L'*') << std::setw(40) << u1 << L'a';
BOOST_TEST_EQ(ss5.str(), L"a****00000000-0000-0000-0000-000000000000a");
std::wstringstream ss6;
ss6 << std::left << std::setfill(L'*') << std::setw(45) << u1;
BOOST_TEST_EQ(ss6.str(), L"00000000-0000-0000-0000-000000000000*********");
}
#endif
{
uuid u;
@@ -51,6 +105,21 @@ int main(int, char*[])
BOOST_TEST_EQ(u, u3);
}
#ifndef BOOST_NO_STD_WSTRING
{
uuid u;
std::wstringstream ss;
ss << L"00000000-0000-0000-0000-000000000000";
ss >> u;
BOOST_TEST_EQ(u, u1);
ss << L"12345678-90ab-cdef-1234-567890abcdef";
ss >> u;
BOOST_TEST_EQ(u, u3);
}
#endif
{ // test with lexical_cast
BOOST_TEST_EQ(boost::lexical_cast<std::string>(u1), std::string("00000000-0000-0000-0000-000000000000"));
BOOST_TEST_EQ(boost::lexical_cast<uuid>("00000000-0000-0000-0000-000000000000"), u1);
@@ -59,5 +128,27 @@ int main(int, char*[])
BOOST_TEST_EQ(boost::lexical_cast<uuid>("12345678-90ab-cdef-1234-567890abcdef"), u3);
}
return boost::report_errors();
#ifndef BOOST_NO_STD_WSTRING
{ // test with lexical_cast
BOOST_TEST_EQ(boost::lexical_cast<std::wstring>(u1), std::wstring(L"00000000-0000-0000-0000-000000000000"));
BOOST_TEST_EQ(boost::lexical_cast<uuid>(L"00000000-0000-0000-0000-000000000000"), u1);
BOOST_TEST_EQ(boost::lexical_cast<std::wstring>(u3), std::wstring(L"12345678-90ab-cdef-1234-567890abcdef"));
BOOST_TEST_EQ(boost::lexical_cast<uuid>(L"12345678-90ab-cdef-1234-567890abcdef"), u3);
}
#endif
{ // test to_string
BOOST_TEST_EQ(to_string(u1), std::string("00000000-0000-0000-0000-000000000000"));
BOOST_TEST_EQ(to_string(u3), std::string("12345678-90ab-cdef-1234-567890abcdef"));
}
#ifndef BOOST_NO_STD_WSTRING
{ // test to_wstring
BOOST_TEST_EQ(to_wstring(u1), std::wstring(L"00000000-0000-0000-0000-000000000000"));
BOOST_TEST_EQ(to_wstring(u3), std::wstring(L"12345678-90ab-cdef-1234-567890abcdef"));
}
#endif
return boost::report_errors();
}

View File

@@ -60,7 +60,8 @@
<li><a href="#boost/uuid/uuid_io.hpp">boost/uuid/uuid_io.hpp</a></li>
<ul>
<li><a href="#Synopsis_io">Synopsis</a></li>
<li><a href="#Input and Output">Input and Output</a></li>
<li><a href="#Stream_operators">Stream Operators</a></li>
<li><a href="#to_string">To String</a></li>
</ul>
<li><a href="#boost/uuid/uuid_serialize.hpp">boost/uuid/uuid_serialize.hpp</a></li>
<ul>
@@ -84,7 +85,7 @@ to identify rows or records in order to ensure that they are unique across
different databases, or for publication/subscription services. Network messages
may be identified with a UUID to ensure that different parts of a message are put
back together again. Distributed computing may use UUIDs to identify a remote
procedure call. Transactions and classes involved in serialization may be
procedure call. Transactions and classes involved in serialization may be
identified by UUIDs. Microsoft's component object model (COM) uses UUIDs to
distinguish different software component interfaces. UUIDs are inserted into
documents from Microsoft Office programs. UUIDs identify audio or
@@ -167,6 +168,11 @@ initialize it to a value generated by one of the defined
mechanisms. But a class based on a UUID can be defined
that does initialize itself to a value generated by one of
the defined mechanisms.
<p>
Note that <tt>boost::is_pod</tt> is specialized for <tt>boost::uuids::uuid</tt>
and depends on <a href="http://www.boost.org/libs/type_traits">Boost.TypeTraits</a>.
Define <tt>BOOST_UUID_NO_TYPE_TRAITS</tt> before including <a href="./../../boost/uuid/uuid.hpp"><tt>boost/uuid/uuid.hpp</tt></a>
to remove the dependency on <a href="http://www.boost.org/libs/type_traits">Boost.TypeTraits</a>.
<pre>
// example using memcpy and aggregate initializers
// example of a class uuid see <a href="./test/test_uuid_class.cpp"><tt>boost/libs/uuid/test/test_uuid_class.cpp</tt></a>
@@ -441,10 +447,10 @@ struct string_generator {
<p>The <tt>boost::uuids::string_generator</tt> class generates a <b>uuid</b> from a string.
<pre>
boost::uuids::string_generator gen;
boost::uuids::uuid u1 = gen("{01234567-89ab-cdef-0123456789abcdef}");
boost::uuids::uuid u2 = gen(L"01234567-89ab-cdef-0123456789abcdef");
boost::uuids::uuid u1 = gen("{01234567-89ab-cdef-0123-456789abcdef}");
boost::uuids::uuid u2 = gen(L"01234567-89ab-cdef-0123-456789abcdef");
boost::uuids::uuid u3 = gen(std::string("0123456789abcdef0123456789abcdef"));
boost::uuids::uuid u4 = gen(std::wstring(L"01234567-89ab-cdef-0123456789abcdef"));
boost::uuids::uuid u4 = gen(std::wstring(L"01234567-89ab-cdef-0123-456789abcdef"));
</pre>
<h3><a name="boost/uuid/name_generator.hpp" href="./../../boost/uuid/name_generator.hpp">boost/uuid/name_generator.hpp</a></h3>
@@ -538,22 +544,53 @@ template &lt;typename ch, typename char_traits&gt;
template &lt;typename ch, typename char_traits&gt;
std::basic_istream&lt;ch, char_traits&gt;&amp; operator&gt;&gt;(std::basic_istream&lt;ch, char_traits&gt; &amp;is, uuid &amp;u);
std::string to_string(uuid const&amp; u);
std::wstring to_wstring(uuid const&amp; u);
}} // namespace boost::uuids
</pre>
<h4><a name="Input and Output">Input and Output</a></h4>
<h4><a name="Stream_operators">Stream Operators</a></h4>
<p>
Input and output stream operators <tt>&lt;&lt;</tt> and <tt>&gt;&gt;</tt>
are provided by including <a href="../../boost/uuid/uuid_io.hpp"><tt>boost/uuid/uuid_io.hpp</tt></a>.
The external representation of a <b>uuid</b> is a string of
hexidecimal digits of the following form: <tt>hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh</tt>
The standard input and output stream operators <tt>&lt;&lt;</tt> and <tt>&gt;&gt;</tt>
are provided by including <a href="../../boost/uuid/uuid_io.hpp"><tt>boost/uuid/uuid_io.hpp</tt></a>.
The string representation of a <b>uuid</b> is <tt>hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh</tt>
where <tt>h</tt> is a hexidecimal digit.
<pre>
boost::uuids::uuid u;
boost::uuids::uuid u1; // initialize uuid
std::stringstream ss;
ss &lt;&lt; u;
ss &gt;&gt; u;
ss &lt;&lt; u1;
boost::uuids::uuid u2;
ss &gt;&gt; u2;
assert(u1, u2);
</pre>
<p>
One can also use <a href="http://www.boost.org/libs/conversion/lexical_cast.htm"><tt>boost::lexical_cast</tt></a>.
<pre>
boost::uuids::uuid u1; // initialize uuid
std::string s = boost::lexical_cast&lt;std::string&gt;(u);
boost::uuids::uuid u2 = boost::lexical_cast&lt;boost::uuids::uuid&gt;(s);
assert(u1 == u2);
</pre>
<h4><a name="to_string">To String</a></h4>
<p>
The functions <tt>to_string</tt> and <tt>to_wstring</tt> are provided as a
convenience to convert a <b>uuid</b> to a string. They are also likely faster than
the stream operators or using <a href="http://www.boost.org/libs/conversion/lexical_cast.htm"><tt>boost::lexical_cast</tt></a>.
<pre>
boost::uuids::uuid u; // initialize uuid
std::string s1 = to_string(u);
std::wstring s2 = to_wstring(u);
</pre>
<h3><a name="boost/uuid/uuid_serialize.hpp" href="./../../boost/uuid/uuid_serialize.hpp">boost/uuid/uuid_serialize.hpp</a></h3>