/*============================================================================= Copyright (c) 2011-2016 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_UUID_STRING_GENERATOR_HPP #define SPROUT_UUID_STRING_GENERATOR_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace uuids { // // string_generator // class string_generator { public: typedef sprout::uuids::uuid result_type; private: template struct next_char { public: typedef typename std::iterator_traits::value_type char_type; public: char_type c; ForwardIterator first; ForwardIterator last; public: SPROUT_CONSTEXPR next_char(ForwardIterator f, ForwardIterator l) : c(f != l ? *f : throw std::runtime_error("string_generator: invalid uuid string (out of range)") ) , first(sprout::next(f)) , last(l) {} SPROUT_CONSTEXPR next_char next() const { return next_char(first, last); } }; private: SPROUT_CONSTEXPR std::uint8_t value_at(std::size_t i) const { return i < 22 ? sprout::uuids::detail::values::table[i] : throw std::runtime_error("string_generator: invalid uuid string (invalid character)") ; } template SPROUT_CONSTEXPR std::uint8_t get_value(Elem c) const { return value_at( sprout::distance( sprout::uuids::detail::digits::value.begin(), sprout::find( sprout::uuids::detail::digits::value.begin(), sprout::uuids::detail::digits::value.end(), c ) ) ); } template static SPROUT_CONSTEXPR bool is_dash(Elem c) { return c == sprout::uuids::detail::dash::value; } template static SPROUT_CONSTEXPR bool is_open_brace(Elem c) { return c == sprout::uuids::detail::lbrace::value; } template static SPROUT_CONSTEXPR bool is_close_brace(Elem c) { return c == sprout::uuids::detail::rbrace::value; } template static SPROUT_CONSTEXPR bool is_close_brace(Elem c, Elem open_brace) { return is_open_brace(open_brace) && is_close_brace(c); } template SPROUT_CONSTEXPR result_type generate_2_3(next_char nc, Char open_brace, bool has_dashes, std::uint8_t byte, Args... args) const { return generate_2(nc, open_brace, has_dashes, args..., static_cast((byte << 4) | get_value(nc.c))); } template SPROUT_CONSTEXPR result_type generate_2_2(next_char nc, Char open_brace, bool has_dashes, Args... args) const { return generate_2_3(nc.next(), open_brace, has_dashes, get_value(nc.c), args...); } template SPROUT_CONSTEXPR typename std::enable_if< sizeof...(Args) == 6 || sizeof...(Args) == 8 || sizeof...(Args) == 10, result_type >::type generate_2_1(next_char nc, Char open_brace, bool has_dashes, Args... args) const { return has_dashes ? is_dash(nc.c) ? generate_2_2(nc.next(), open_brace, has_dashes, args...) : throw std::runtime_error("string_generator: invalid uuid string (dashes not found)") : generate_2_2(nc, open_brace, has_dashes, args...) ; } template SPROUT_CONSTEXPR typename std::enable_if< sizeof...(Args) == 4, result_type >::type generate_2_1(next_char nc, Char open_brace, bool, Args... args) const { return is_dash(nc.c) ? generate_2_2(nc.next(), open_brace, true, args...) : generate_2_2(nc, open_brace, false, args...) ; } template SPROUT_CONSTEXPR typename std::enable_if< sizeof...(Args) != 4 && sizeof...(Args) != 6 && sizeof...(Args) != 8 && sizeof...(Args) != 10, result_type >::type generate_2_1(next_char nc, Char open_brace, bool has_dashes, Args... args) const { return generate_2_2(nc, open_brace, has_dashes, args...); } template SPROUT_CONSTEXPR typename std::enable_if< sizeof...(Args) == 16, result_type >::type generate_2(next_char nc, Char open_brace, bool, Args... args) const { return !open_brace || (open_brace && is_close_brace(nc.next().c, open_brace)) ? result_type{{args...}} : throw std::runtime_error("string_generator: invalid uuid string (brace not closed)") ; } template SPROUT_CONSTEXPR typename std::enable_if< sizeof...(Args) == 0, result_type >::type generate_2(next_char nc, Char open_brace, bool has_dashes, Args... args) const { return generate_2_2(nc, open_brace, has_dashes, args...); } template SPROUT_CONSTEXPR typename std::enable_if< sizeof...(Args) != 0 && sizeof...(Args) != 16, result_type >::type generate_2(next_char nc, Char open_brace, bool has_dashes, Args... args) const { return generate_2_1(nc.next(), open_brace, has_dashes, args...); } template SPROUT_CONSTEXPR result_type generate_1(next_char nc) const { return is_open_brace(nc.c) ? generate_2(nc.next(), nc.c, false) : generate_2(nc, typename next_char::char_type(), false) ; } public: template SPROUT_CONSTEXPR result_type operator()(ForwardIterator first, ForwardIterator last) const { return generate_1(next_char(first, last)); } template SPROUT_CONSTEXPR result_type operator()(sprout::basic_string const& s) const { return operator()(s.begin(), s.end()); } SPROUT_CONSTEXPR result_type operator()(char const* s) const { return operator()(s, s + sprout::char_traits::length(s)); } SPROUT_CONSTEXPR result_type operator()(wchar_t const* s) const { return operator()(s, s + sprout::char_traits::length(s)); } #if SPROUT_USE_UNICODE_LITERALS SPROUT_CONSTEXPR result_type operator()(char16_t const* s) const { return operator()(s, s + sprout::char_traits::length(s)); } SPROUT_CONSTEXPR result_type operator()(char32_t const* s) const { return operator()(s, s + sprout::char_traits::length(s)); } #endif }; // // make_uuid // template inline SPROUT_CONSTEXPR sprout::uuids::uuid make_uuid(ForwardIterator first, ForwardIterator last) { return sprout::uuids::string_generator()(first, last); } template inline SPROUT_CONSTEXPR sprout::uuids::uuid make_uuid(sprout::basic_string const& s) { return sprout::uuids::string_generator()(s); } inline SPROUT_CONSTEXPR sprout::uuids::uuid make_uuid(char const* s) { return sprout::uuids::string_generator()(s); } inline SPROUT_CONSTEXPR sprout::uuids::uuid make_uuid(wchar_t const* s) { return sprout::uuids::string_generator()(s); } #if SPROUT_USE_UNICODE_LITERALS inline SPROUT_CONSTEXPR sprout::uuids::uuid make_uuid(char16_t const* s) { return sprout::uuids::string_generator()(s); } inline SPROUT_CONSTEXPR sprout::uuids::uuid make_uuid(char32_t const* s) { return sprout::uuids::string_generator()(s); } #endif } // namespace uuids } // namespace sprout #endif // #ifndef SPROUT_UUID_STRING_GENERATOR_HPP