diff --git a/sprout/algorithm/fixed/shuffle.hpp b/sprout/algorithm/fixed/shuffle.hpp index 292bb75c..75261f41 100644 --- a/sprout/algorithm/fixed/shuffle.hpp +++ b/sprout/algorithm/fixed/shuffle.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ namespace sprout { ? sprout::fixed::detail::make_shuffle_indexes_1( n, sprout::random::uniform_int_distribution(0, n - 1)(sprout::forward(g)), - sprout::fixed::iota(sprout::null_array >(), 0), + sprout::fixed::iota(sprout::pit >(), 0), 0 ) : sprout::array{{}} diff --git a/sprout/array.hpp b/sprout/array.hpp index 15820caf..484c18b8 100644 --- a/sprout/array.hpp +++ b/sprout/array.hpp @@ -43,7 +43,7 @@ namespace sprout { SPROUT_STATIC_CONSTEXPR size_type static_size = N; SPROUT_STATIC_CONSTEXPR size_type fixed_size = static_size; public: - T elems[N ? N : 1]; + value_type elems[static_size ? static_size : 1]; public: void fill(const_reference value) { std::fill_n(begin(), size(), value); @@ -114,13 +114,13 @@ namespace sprout { } // capacity: SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { - return N; + return static_size; } SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { return size(); } SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { - return N == 0; + return size() == 0; } // element access: reference operator[](size_type i) { @@ -320,18 +320,18 @@ namespace std { // get // template - T& get(sprout::array& arr) SPROUT_NOEXCEPT { + T& get(sprout::array& t) SPROUT_NOEXCEPT { static_assert(I < N, "get: index out of range"); - return arr[I]; + return t[I]; } template - SPROUT_CONSTEXPR T const& get(sprout::array const& arr) SPROUT_NOEXCEPT { + SPROUT_CONSTEXPR T const& get(sprout::array const& t) SPROUT_NOEXCEPT { static_assert(I < N, "get: index out of range"); - return arr[I]; + return t[I]; } template - T&& get(sprout::array&& arr) SPROUT_NOEXCEPT { - return std::move(std::get(arr)); + T&& get(sprout::array&& t) SPROUT_NOEXCEPT { + return std::move(std::get(t)); } } // namespace std diff --git a/sprout/checksum/sha1.hpp b/sprout/checksum/sha1.hpp new file mode 100644 index 00000000..be517e53 --- /dev/null +++ b/sprout/checksum/sha1.hpp @@ -0,0 +1,313 @@ +#ifndef SPROUT_CHECKSUM_SHA1_HPP +#define SPROUT_CHECKSUM_SHA1_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + static_assert(CHAR_BIT == 8, "CHAR_BIT == 8"); + + namespace detail { + SPROUT_CONSTEXPR inline std::uint32_t sha1_left_rotate(std::uint32_t x, std::size_t n) { + return (x << n) ^ (x >> (32 - n)); + } + } // namespace detail + + // + // sha1 + // + class sha1 { + public: + typedef sprout::array value_type; + private: + sprout::array h_; + sprout::array block_; + std::size_t block_byte_index_; + std::size_t byte_count_; + private: + SPROUT_CONSTEXPR sha1( + sprout::array const& h, + sprout::array const& block, + std::size_t block_byte_index, + std::size_t byte_count + ) + : h_(h) + , block_(block) + , block_byte_index_(block_byte_index) + , byte_count_(byte_count) + {} + SPROUT_CONSTEXPR std::uint32_t calc_w(std::size_t i) const { + return i < 16 + ? (block_[i * 4] << 24) + | (block_[i * 4 + 1] << 16) + | (block_[i * 4 + 2] << 8) + | (block_[i * 4 + 3]) + : sprout::detail::sha1_left_rotate( + calc_w(i - 3) ^ calc_w(i - 8) ^ calc_w(i - 14) ^ calc_w(i - 16), + 1 + ) + ; + } + SPROUT_CONSTEXPR sha1 process( + sprout::array const& h, + sprout::array const& block, + std::size_t block_byte_index, + std::size_t byte_count + ) const + { + return block_byte_index != 64 + ? sha1( + h, + block, + block_byte_index, + byte_count + ) + : sha1( + h, + block, + 0, + byte_count + ).process_block() + ; + } + SPROUT_CONSTEXPR sha1 process_block_2( + std::uint32_t a, + std::uint32_t b, + std::uint32_t c, + std::uint32_t d, + std::uint32_t e, + std::size_t i, + std::uint32_t f, + std::uint32_t k + ) const + { + return process_block_1( + sprout::detail::sha1_left_rotate(a, 5) + f + e + k + calc_w(i), + a, + sprout::detail::sha1_left_rotate(b, 30), + c, + d, + i + 1 + ); + } + SPROUT_CONSTEXPR sha1 process_block_1( + std::uint32_t a, + std::uint32_t b, + std::uint32_t c, + std::uint32_t d, + std::uint32_t e, + std::size_t i = 0 + ) const + { + return i < 80 + ? process_block_2( + a, + b, + c, + d, + e, + i, + i < 20 ? (b & c) | (~b & d) + : i < 40 ? b ^ c ^ d + : i < 60 ? (b & c) | (b & d) | (c & d) + : b ^ c ^ d + , + i < 20 ? 0x5A827999 + : i < 40 ? 0x6ED9EBA1 + : i < 60 ? 0x8F1BBCDC + : 0xCA62C1D6 + ) + : sha1( + sprout::array{{h_[0] + a, h_[1] + b, h_[2] + c, h_[3] + d, h_[4] + e}}, + block_, + block_byte_index_, + byte_count_ + ) + ; + } + SPROUT_CONSTEXPR sha1 process_block() const { + return process_block_1(h_[0], h_[1], h_[2], h_[3], h_[4]); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) == 64, + sha1 + >::type process_block_impl( + Iterator first, + Iterator last, + Args... args + ) const + { + return first == last ? process( + h_, + sprout::make_array(args...), + 64, + byte_count_ + 64 + ) + : process( + h_, + sprout::make_array(args...), + 64, + byte_count_ + 64 + ).process_block_impl(first, last) + ; + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) != 64, + sha1 + >::type process_block_impl( + Iterator first, + Iterator last, + Args... args + ) const + { + return first == last ? process( + h_, + sprout::get_fixed(sprout::range::fixed::copy(sprout::make_array(args...), sprout::sub(block_, block_byte_index_))), + block_byte_index_ + sizeof...(Args), + byte_count_ + sizeof...(Args) + ) + : block_byte_index_ + sizeof...(Args) == 64 ? process( + h_, + sprout::get_fixed(sprout::range::fixed::copy(sprout::make_array(args...), sprout::sub(block_, block_byte_index_))), + block_byte_index_ + sizeof...(Args), + byte_count_ + sizeof...(Args) + ).process_block_impl(first, last) + : process_block_impl(sprout::next(first), last, args..., *first) + ; + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) == 64, + sha1 + >::type process_padding( + Args... args + ) const + { + return process( + h_, + sprout::make_array(args...), + 64, + byte_count_ + 64 + ).process_padding() + ; + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) != 64, + sha1 + >::type process_padding( + Args... args + ) const + { + return block_byte_index_ + sizeof...(Args) == 56 ? process( + h_, + sprout::get_fixed(sprout::range::fixed::copy(sprout::make_array(args...), sprout::sub(block_, block_byte_index_))), + block_byte_index_ + sizeof...(Args), + byte_count_ + sizeof...(Args) + ) + : block_byte_index_ + sizeof...(Args) == 64 ? process( + h_, + sprout::get_fixed(sprout::range::fixed::copy(sprout::make_array(args...), sprout::sub(block_, block_byte_index_))), + block_byte_index_ + sizeof...(Args), + byte_count_ + sizeof...(Args) + ).process_padding() + : process_padding(args..., static_cast(0)) + ; + } + SPROUT_CONSTEXPR sha1 process_append() const { + return process( + h_, + sprout::get_fixed(sprout::range::fixed::copy( + sprout::array{{ + static_cast(0), + static_cast(0), + static_cast(0), + static_cast(0), + static_cast((byte_count_ * 8 >> 24) & 0xFF), + static_cast((byte_count_ * 8 >> 16) & 0xFF), + static_cast((byte_count_ * 8 >> 8) & 0xFF), + static_cast((byte_count_ * 8) & 0xFF) + }}, + sprout::sub(block_, block_byte_index_) + )), + block_byte_index_ + 8, + byte_count_ + 8 + ); + } + SPROUT_CONSTEXPR value_type make_value() const { + return value_type{{ + static_cast((h_[0] >> 24) & 0xFF), + static_cast((h_[0] >> 16) & 0xFF), + static_cast((h_[0] >> 8) & 0xFF), + static_cast((h_[0]) & 0xFF), + static_cast((h_[1] >> 24) & 0xFF), + static_cast((h_[1] >> 16) & 0xFF), + static_cast((h_[1] >> 8) & 0xFF), + static_cast((h_[1]) & 0xFF), + static_cast((h_[2] >> 24) & 0xFF), + static_cast((h_[2] >> 16) & 0xFF), + static_cast((h_[2] >> 8) & 0xFF), + static_cast((h_[2]) & 0xFF), + static_cast((h_[3] >> 24) & 0xFF), + static_cast((h_[3] >> 16) & 0xFF), + static_cast((h_[3] >> 8) & 0xFF), + static_cast((h_[3]) & 0xFF), + static_cast((h_[4] >> 24) & 0xFF), + static_cast((h_[4] >> 16) & 0xFF), + static_cast((h_[4] >> 8) & 0xFF), + static_cast((h_[4]) & 0xFF) + }}; + } + public: + SPROUT_CONSTEXPR sha1() + : h_{{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}} + , block_{{}} + , block_byte_index_() + , byte_count_() + {} + SPROUT_CONSTEXPR sha1 process_byte(std::uint8_t byte) const { + return process( + h_, + sprout::fixed::set(block_, block_.begin() + block_byte_index_, byte), + block_byte_index_ + 1, + byte_count_ + 1 + ); + } + template + SPROUT_CONSTEXPR sha1 process_block(Iterator bytes_begin, Iterator bytes_end) const { + return process_block_impl( + sprout::make_bytes_iterator(bytes_begin), + sprout::make_bytes_iterator(bytes_end) + ); + } + template + SPROUT_CONSTEXPR sha1 process_bytes(Iterator buffer, std::size_t byte_count) const { + return process_block(buffer, sprout::next(buffer, byte_count)); + } + template + SPROUT_CONSTEXPR sha1 process_range(Range const& bytes_range) const { + return process_block(sprout::begin(bytes_range), sprout::end(bytes_range)); + } + SPROUT_CONSTEXPR value_type checksum() const { + return process_byte(0x80).process_padding().process_append().make_value(); + } + SPROUT_CONSTEXPR value_type operator()() const { + return checksum(); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_CHECKSUM_SHA1_HPP diff --git a/sprout/detail/algorithm.hpp b/sprout/detail/algorithm.hpp index ce5f7814..5cffac09 100644 --- a/sprout/detail/algorithm.hpp +++ b/sprout/detail/algorithm.hpp @@ -126,6 +126,17 @@ namespace sprout { ? false : sprout::detail::lexicographical_compare(sprout::next(first1), last1, sprout::next(first2), last2, comp); } + + // + // find + // + template + SPROUT_CONSTEXPR Iterator find(Iterator first, Iterator last, T const& value) { + return first == last || *first == value + ? first + : sprout::detail::find(sprout::next(first), last, value) + ; + } } // namespace detail } // namespace sprout diff --git a/sprout/detail/io/ios_state.hpp b/sprout/detail/io/ios_state.hpp new file mode 100644 index 00000000..34cddeae --- /dev/null +++ b/sprout/detail/io/ios_state.hpp @@ -0,0 +1,412 @@ +#ifndef SPROUT_DETAIL_IO_IOS_STATE_HPP +#define SPROUT_DETAIL_IO_IOS_STATE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + namespace io { + class ios_flags_saver { + public: + typedef std::ios_base state_type; + typedef std::ios_base::fmtflags aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit ios_flags_saver(state_type& s) + : s_save_(s) + , a_save_(s.flags()) + {} + ios_flags_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.flags(a)) + {} + ios_flags_saver& operator=(ios_flags_saver const&) = delete; + ~ios_flags_saver() { + this->restore(); + } + void restore() { + s_save_.flags(a_save_); + } + }; + + class ios_precision_saver { + public: + typedef std::ios_base state_type; + typedef std::streamsize aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit ios_precision_saver(state_type& s) + : s_save_(s) + , a_save_(s.precision()) + {} + ios_precision_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.precision(a)) + {} + ios_precision_saver& operator=(ios_precision_saver const&) = delete; + ~ios_precision_saver() { + this->restore(); + } + void restore() { + s_save_.precision(a_save_); + } + }; + + class ios_width_saver { + public: + typedef std::ios_base state_type; + typedef std::streamsize aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit ios_width_saver(state_type& s) + : s_save_(s) + , a_save_(s.width()) + {} + ios_width_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.width(a)) + {} + ios_width_saver& operator=(ios_width_saver const&) = delete; + ~ios_width_saver() { + this->restore(); + } + void restore() { + s_save_.width(a_save_); + } + }; + + template + class basic_ios_iostate_saver { + public: + typedef std::basic_ios state_type; + typedef std::ios_base::iostate aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit basic_ios_iostate_saver(state_type& s) + : s_save_(s) + , a_save_(s.rdstate()) + {} + basic_ios_iostate_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.rdstate()) + { + s.clear(a); + } + basic_ios_iostate_saver& operator=(basic_ios_iostate_saver const&) = delete; + ~basic_ios_iostate_saver() { + this->restore(); + } + void restore() { + s_save_.clear(a_save_); + } + }; + + template + class basic_ios_exception_saver { + public: + typedef std::basic_ios state_type; + typedef std::ios_base::iostate aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit basic_ios_exception_saver(state_type& s) + : s_save_(s) + , a_save_(s.exceptions()) + {} + basic_ios_exception_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.exceptions()) + { + s.exceptions(a); + } + basic_ios_exception_saver& operator=(basic_ios_exception_saver const&) = delete; + ~basic_ios_exception_saver() { + this->restore(); + } + void restore() { + s_save_.exceptions(a_save_); + } + }; + + template + class basic_ios_tie_saver { + public: + typedef std::basic_ios state_type; + typedef std::basic_ostream* aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit basic_ios_tie_saver(state_type& s) + : s_save_(s) + , a_save_(s.tie()) + {} + basic_ios_tie_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.tie(a)) + {} + basic_ios_tie_saver& operator=(basic_ios_tie_saver const&) = delete; + ~basic_ios_tie_saver() { + this->restore(); + } + void restore() { + s_save_.tie(a_save_); + } + }; + + template + class basic_ios_rdbuf_saver { + public: + typedef std::basic_ios state_type; + typedef std::basic_streambuf* aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit basic_ios_rdbuf_saver(state_type& s) + : s_save_(s) + , a_save_(s.rdbuf()) + {} + basic_ios_rdbuf_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.rdbuf(a)) + {} + basic_ios_rdbuf_saver& operator=(basic_ios_rdbuf_saver const&) = delete; + ~basic_ios_rdbuf_saver() { + this->restore(); + } + void restore() { + s_save_.rdbuf(a_save_); + } + }; + + template + class basic_ios_fill_saver { + public: + typedef std::basic_ios state_type; + typedef typename state_type::char_type aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit basic_ios_fill_saver(state_type& s) + : s_save_(s) + , a_save_(s.fill()) + {} + basic_ios_fill_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.fill(a)) + {} + basic_ios_fill_saver& operator=(basic_ios_fill_saver const&) = delete; + ~basic_ios_fill_saver() { + this->restore(); + } + void restore() { + s_save_.fill(a_save_); + } + }; + + template + class basic_ios_locale_saver { + public: + typedef std::basic_ios state_type; + typedef std::locale aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + public: + explicit basic_ios_locale_saver(state_type& s) + : s_save_(s) + , a_save_(s.getloc()) + {} + basic_ios_locale_saver(state_type& s, aspect_type const& a) + : s_save_(s) + , a_save_(s.imbue(a)) + {} + basic_ios_locale_saver& operator=(basic_ios_locale_saver const&) = delete; + ~basic_ios_locale_saver() { + this->restore(); + } + void restore() { + s_save_.imbue(a_save_); + } + }; + + class ios_iword_saver { + public: + typedef std::ios_base state_type; + typedef int index_type; + typedef long aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + index_type const i_save_; + public: + explicit ios_iword_saver(state_type& s, index_type i) + : s_save_(s) + , a_save_(s.iword(i)) + , i_save_(i) + {} + ios_iword_saver(state_type& s, index_type i, aspect_type const& a) + : s_save_(s) + , a_save_(s.iword(i)) + , i_save_(i) + { + s.iword(i) = a; + } + ios_iword_saver& operator=(ios_iword_saver const&) = delete; + ~ios_iword_saver() { + this->restore(); + } + void restore() { + s_save_.iword(i_save_) = a_save_; + } + }; + + class ios_pword_saver { + public: + typedef std::ios_base state_type; + typedef int index_type; + typedef void* aspect_type; + private: + state_type& s_save_; + aspect_type const a_save_; + index_type const i_save_; + public: + explicit ios_pword_saver(state_type& s, index_type i) + : s_save_(s) + , a_save_(s.pword(i)) + , i_save_(i) + {} + ios_pword_saver(state_type& s, index_type i, aspect_type const& a) + : s_save_(s) + , a_save_(s.pword(i)) + , i_save_(i) + { + s.pword(i) = a; + } + ios_pword_saver& operator=(ios_pword_saver const&) = delete; + ~ios_pword_saver() { + this->restore(); + } + void restore() { + s_save_.pword(i_save_) = a_save_; + } + }; + + class ios_base_all_saver { + public: + typedef std::ios_base state_type; + private: + state_type& s_save_; + state_type::fmtflags const a1_save_; + std::streamsize const a2_save_; + std::streamsize const a3_save_; + public: + explicit ios_base_all_saver(state_type& s) + : s_save_(s) + , a1_save_(s.flags()) + , a2_save_(s.precision()) + , a3_save_(s.width()) + {} + ios_base_all_saver& operator=(ios_base_all_saver const&) = delete; + ~ios_base_all_saver() { + this->restore(); + } + void restore() { + s_save_.width(a3_save_); + s_save_.precision(a2_save_); + s_save_.flags(a1_save_); + } + }; + + template + class basic_ios_all_saver { + public: + typedef std::basic_ios state_type; + private: + state_type& s_save_; + typename state_type::fmtflags const a1_save_; + std::streamsize const a2_save_; + std::streamsize const a3_save_; + typename state_type::iostate const a4_save_; + typename state_type::iostate const a5_save_; + std::basic_ostream* const a6_save_; + std::basic_streambuf* const a7_save_; + typename state_type::char_type const a8_save_; + std::locale const a9_save_; + public: + explicit basic_ios_all_saver(state_type& s) + : s_save_(s) + , a1_save_(s.flags()) + , a2_save_(s.precision()) + , a3_save_(s.width()) + , a4_save_(s.rdstate()) + , a5_save_(s.exceptions()) + , a6_save_(s.tie()) + , a7_save_(s.rdbuf()) + , a8_save_(s.fill()) + , a9_save_(s.getloc()) + {} + basic_ios_all_saver& operator=(basic_ios_all_saver const&) = delete; + ~basic_ios_all_saver() { + this->restore(); + } + void restore() { + s_save_.imbue(a9_save_); + s_save_.fill(a8_save_); + s_save_.rdbuf(a7_save_); + s_save_.tie(a6_save_); + s_save_.exceptions(a5_save_); + s_save_.clear(a4_save_); + s_save_.width(a3_save_); + s_save_.precision(a2_save_); + s_save_.flags(a1_save_); + } + }; + + class ios_all_word_saver { + public: + typedef std::ios_base state_type; + typedef int index_type; + private: + state_type& s_save_; + index_type const i_save_; + long const a1_save_; + void* const a2_save_; + public: + ios_all_word_saver(state_type& s, index_type i) + : s_save_(s) + , i_save_(i) + , a1_save_(s.iword(i)) + , a2_save_(s.pword(i)) + {} + ios_all_word_saver& operator=(ios_all_word_saver const&) = delete; + ~ios_all_word_saver() { + this->restore(); + } + void restore() { + s_save_.pword(i_save_) = a2_save_; + s_save_.iword(i_save_) = a1_save_; + } + }; + } // namespace io + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_DETAIL_IO_IOS_STATE_HPP diff --git a/sprout/detail/io_fwd.hpp b/sprout/detail/io_fwd.hpp new file mode 100644 index 00000000..ba0a2971 --- /dev/null +++ b/sprout/detail/io_fwd.hpp @@ -0,0 +1,71 @@ +#ifndef SPROUT_DETAIL_IO_FWD_HPP +#define SPROUT_DETAIL_IO_FWD_HPP + +#include + +namespace sprout { + namespace detail { + namespace io { + class ios_flags_saver; + class ios_precision_saver; + class ios_width_saver; + class ios_base_all_saver; + + template > + class basic_ios_iostate_saver; + template > + class basic_ios_exception_saver; + template > + class basic_ios_tie_saver; + template > + class basic_ios_rdbuf_saver; + template > + class basic_ios_fill_saver; + template > + class basic_ios_locale_saver; + template > + class basic_ios_all_saver; + + typedef sprout::detail::io::basic_ios_iostate_saver ios_iostate_saver; + typedef sprout::detail::io::basic_ios_iostate_saver wios_iostate_saver; + typedef sprout::detail::io::basic_ios_iostate_saver u16ios_iostate_saver; + typedef sprout::detail::io::basic_ios_iostate_saver u32ios_iostate_saver; + + typedef sprout::detail::io::basic_ios_exception_saver ios_exception_saver; + typedef sprout::detail::io::basic_ios_exception_saver wios_exception_saver; + typedef sprout::detail::io::basic_ios_exception_saver u16ios_exception_saver; + typedef sprout::detail::io::basic_ios_exception_saver u32ios_exception_saver; + + typedef sprout::detail::io::basic_ios_tie_saver ios_tie_saver; + typedef sprout::detail::io::basic_ios_tie_saver wios_tie_saver; + typedef sprout::detail::io::basic_ios_tie_saver u16ios_tie_saver; + typedef sprout::detail::io::basic_ios_tie_saver u32ios_tie_saver; + + typedef sprout::detail::io::basic_ios_rdbuf_saver ios_rdbuf_saver; + typedef sprout::detail::io::basic_ios_rdbuf_saver wios_rdbuf_saver; + typedef sprout::detail::io::basic_ios_rdbuf_saver u16ios_rdbuf_saver; + typedef sprout::detail::io::basic_ios_rdbuf_saver u32ios_rdbuf_saver; + + typedef sprout::detail::io::basic_ios_fill_saver ios_fill_saver; + typedef sprout::detail::io::basic_ios_fill_saver wios_fill_saver; + typedef sprout::detail::io::basic_ios_fill_saver u16ios_fill_saver; + typedef sprout::detail::io::basic_ios_fill_saver u32ios_fill_saver; + + typedef sprout::detail::io::basic_ios_locale_saver ios_locale_saver; + typedef sprout::detail::io::basic_ios_locale_saver wios_locale_saver; + typedef sprout::detail::io::basic_ios_locale_saver u16ios_locale_saver; + typedef sprout::detail::io::basic_ios_locale_saver u32ios_locale_saver; + + typedef sprout::detail::io::basic_ios_all_saver ios_all_saver; + typedef sprout::detail::io::basic_ios_all_saver wios_all_saver; + typedef sprout::detail::io::basic_ios_all_saver u16ios_all_saver; + typedef sprout::detail::io::basic_ios_all_saver u32ios_all_saver; + + class ios_iword_saver; + class ios_pword_saver; + class ios_all_word_saver; + } // namespace io + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_DETAIL_IO_FWD_HPP diff --git a/sprout/endian_traits.hpp b/sprout/endian_traits.hpp new file mode 100644 index 00000000..13839d43 --- /dev/null +++ b/sprout/endian_traits.hpp @@ -0,0 +1,47 @@ +#ifndef SPROUT_ENDIAN_TRAITS_HPP +#define SPROUT_ENDIAN_TRAITS_HPP + +#include +#include +#include + +namespace sprout { + // + // big_endian_traits + // + template + class big_endian_traits { + public: + typedef T type; + public: + static SPROUT_CONSTEXPR std::size_t size() { + return sizeof(type); + } + static SPROUT_CONSTEXPR unsigned char get_byte(type const& t, std::size_t i) { + return static_cast( + (t & (UCHAR_MAX << CHAR_BIT * ((size() - 1) - i))) + >> CHAR_BIT * ((size() - 1) - i) + ); + } + }; + // + // little_endian_traits + // + template + class little_endian_traits { + public: + typedef T type; + public: + static SPROUT_CONSTEXPR std::size_t size() { + return sizeof(type); + } + static SPROUT_CONSTEXPR unsigned char get_byte(type const& t, std::size_t i) { + return static_cast( + (t & (UCHAR_MAX << CHAR_BIT * i)) + >> CHAR_BIT * i + ); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_ENDIAN_TRAITS_HPP diff --git a/sprout/functional/hash/hash.hpp b/sprout/functional/hash/hash.hpp index 85f5ccd2..93b387fd 100644 --- a/sprout/functional/hash/hash.hpp +++ b/sprout/functional/hash/hash.hpp @@ -216,7 +216,7 @@ namespace sprout { public: typedef T* argument_type; typedef std::size_t result_type; - public: \ + public: SPROUT_CONSTEXPR std::size_t operator()(T* v) const { return sprout::hash_value(v); } diff --git a/sprout/iterator/bytes_iterator.hpp b/sprout/iterator/bytes_iterator.hpp new file mode 100644 index 00000000..e091368e --- /dev/null +++ b/sprout/iterator/bytes_iterator.hpp @@ -0,0 +1,223 @@ +#ifndef SPROUT_ITERATOR_BYTES_ITERATOR_HPP +#define SPROUT_ITERATOR_BYTES_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // bytes_iterator + // + template< + typename Iterator, + typename Traits = sprout::big_endian_traits::value_type> + > + class bytes_iterator + : public std::iterator< + typename std::iterator_traits::iterator_category, + unsigned char, + std::ptrdiff_t, + void, + unsigned char + > + { + public: + typedef Iterator base_type; + typedef Traits traits_type; + private: + typedef std::iterator< + typename std::iterator_traits::iterator_category, + unsigned char, + std::ptrdiff_t, + void, + unsigned char + > iterator_type; + public: + typedef typename iterator_type::iterator_category iterator_category; + typedef typename iterator_type::value_type value_type; + typedef typename iterator_type::difference_type difference_type; + typedef typename iterator_type::pointer pointer; + typedef typename iterator_type::reference reference; + private: + struct next_tag {}; + struct prev_tag {}; + struct ra_tag {}; + private: + base_type it_; + difference_type i_; + private: + SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i) + : it_(it) + , i_(i) + {} + SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i, next_tag) + : it_(i / traits_type::size() == 0 ? it : sprout::next(it)) + , i_(i % traits_type::size()) + {} + SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i, prev_tag) + : it_((i + 1 - traits_type::size()) / traits_type::size() == 0 ? it : sprout::prev(it)) + , i_(i % traits_type::size() + traits_type::size()) + {} + SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i, ra_tag) + : it_(i >= 0 + ? sprout::next(it, i / traits_type::size()) + : sprout::next(it, (i + 1 - traits_type::size()) / traits_type::size()) + ) + , i_(i >= 0 + ? i % traits_type::size() + : i % traits_type::size() + traits_type::size() + ) + {} + public: + SPROUT_CONSTEXPR bytes_iterator() + : it_() + , i_() + {} + bytes_iterator(bytes_iterator const&) = default; + SPROUT_CONSTEXPR explicit bytes_iterator(base_type it) + : it_(it) + , i_() + {} + SPROUT_CONSTEXPR bytes_iterator next() const { + return bytes_iterator(it_, i_ + 1, next_tag()); + } + SPROUT_CONSTEXPR bytes_iterator prev() const { + return bytes_iterator(it_, i_ - 1, prev_tag()); + } + void swap(bytes_iterator& other) { + using std::swap; + swap(it_, other.it_); + swap(i_, other.i_); + } + friend SPROUT_CONSTEXPR bool operator==(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return lhs.it_ == rhs.it_ && lhs.i_ == rhs.i_; + } + friend SPROUT_CONSTEXPR bool operator!=(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return !(lhs == rhs); + } + friend bool operator<(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return lhs.it_ < rhs.it_ || lhs.it_ == rhs.it_ && lhs.i_ < rhs.i_; + } + friend bool operator>(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return rhs < lhs; + } + friend bool operator<=(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return !(rhs < lhs); + } + friend bool operator>=(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return !(lhs < rhs); + } + SPROUT_CONSTEXPR reference operator*() const { + return traits_type::get_byte(*it_, i_); + } + bytes_iterator& operator++() { + bytes_iterator temp(next()); + temp.swap(*this); + return *this; + } + bytes_iterator operator++(int) { + bytes_iterator result(*this); + ++*this; + return result; + } + bytes_iterator& operator--() { + bytes_iterator temp(prev()); + temp.swap(*this); + return *this; + } + bytes_iterator operator--(int) { + bytes_iterator result(*this); + --*this; + return result; + } + SPROUT_CONSTEXPR bytes_iterator operator+(difference_type n) const { + return bytes_iterator(it_, i_ + n, ra_tag()); + } + SPROUT_CONSTEXPR bytes_iterator operator-(difference_type n) const { + return bytes_iterator(it_, i_ - n, ra_tag()); + } + bytes_iterator& operator+=(difference_type n) { + bytes_iterator temp(it_, i_ + n, ra_tag()); + temp.swap(this); + return this; + } + bytes_iterator& operator-=(difference_type n) { + bytes_iterator temp(it_, i_ - n, ra_tag()); + temp.swap(this); + return this; + } + SPROUT_CONSTEXPR reference operator[](difference_type n) const { + return *(*this + n); + } + friend difference_type operator-(bytes_iterator const& lhs, bytes_iterator const& rhs) { + return (lhs.it_ - rhs.it_) * traits_type::size() + (lhs.i_ - rhs.i_); + } + friend SPROUT_CONSTEXPR bytes_iterator operator+(difference_type n, bytes_iterator const& it) { + return it + n; + } + }; + + // + // swap + // + template + inline void swap(sprout::bytes_iterator& lhs, sprout::bytes_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { + lhs.swap(rhs); + } + + // + // next + // + template + SPROUT_CONSTEXPR inline sprout::bytes_iterator next( + sprout::bytes_iterator const& it + ) + { + return it.next(); + } + template + SPROUT_CONSTEXPR inline sprout::bytes_iterator next( + sprout::bytes_iterator const& it, + typename sprout::bytes_iterator::difference_type n + ) + { + return it + n; + } + + // + // prev + // + template + SPROUT_CONSTEXPR inline sprout::bytes_iterator prev( + sprout::bytes_iterator const& it + ) + { + return it.prev(); + } + template + SPROUT_CONSTEXPR inline sprout::bytes_iterator prev( + sprout::bytes_iterator const& it, + typename sprout::bytes_iterator::difference_type n + ) + { + return it - n; + } + + // + // make_bytes_iterator + // + template + SPROUT_CONSTEXPR inline sprout::bytes_iterator make_bytes_iterator(Iterator it) { + return sprout::bytes_iterator(it); + } + template + SPROUT_CONSTEXPR inline sprout::bytes_iterator make_bytes_iterator(Iterator it, Traits) { + return sprout::bytes_iterator(it); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_BYTES_ITERATOR_HPP diff --git a/sprout/null_array.hpp b/sprout/pit.hpp similarity index 57% rename from sprout/null_array.hpp rename to sprout/pit.hpp index 8c1f4da0..447507c5 100644 --- a/sprout/null_array.hpp +++ b/sprout/pit.hpp @@ -1,5 +1,5 @@ -#ifndef SPROUT_NULL_ARRAY_HPP -#define SPROUT_NULL_ARRAY_HPP +#ifndef SPROUT_PIT_HPP +#define SPROUT_PIT_HPP #include #include @@ -12,13 +12,13 @@ namespace sprout { // - // null_array + // pit // template - class null_array { + class pit { public: typedef Container container_type; - typedef null_array fixed_container_type; + typedef pit fixed_container_type; typedef container_type internal_type; typedef typename sprout::fixed_container_traits::clone_type clone_type; typedef typename sprout::fixed_container_traits::value_type value_type; @@ -38,8 +38,8 @@ namespace sprout { public: value_type elem; public: - null_array() = default; - void swap(null_array& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { + pit() = default; + void swap(pit& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { using std::swap; swap(elem, other.elem); } @@ -120,14 +120,14 @@ namespace sprout { // others: void rangecheck(size_type i) const { if (i >= size()) { - throw std::out_of_range("null_array<>: index out of range"); + throw std::out_of_range("pit<>: index out of range"); } } }; template - SPROUT_CONSTEXPR typename sprout::null_array::size_type sprout::null_array::static_size; + SPROUT_CONSTEXPR typename sprout::pit::size_type sprout::pit::static_size; template - SPROUT_CONSTEXPR typename sprout::null_array::size_type sprout::null_array::fixed_size; + SPROUT_CONSTEXPR typename sprout::pit::size_type sprout::pit::fixed_size; // // operator== @@ -138,27 +138,27 @@ namespace sprout { // operator>= // template - SPROUT_CONSTEXPR inline bool operator==(sprout::null_array const& lhs, sprout::null_array const& rhs) { + SPROUT_CONSTEXPR inline bool operator==(sprout::pit const& lhs, sprout::pit const& rhs) { return lhs.front() == rhs.front(); } template - SPROUT_CONSTEXPR inline bool operator!=(sprout::null_array const& lhs, sprout::null_array const& rhs) { + SPROUT_CONSTEXPR inline bool operator!=(sprout::pit const& lhs, sprout::pit const& rhs) { return !(lhs == rhs); } template - SPROUT_CONSTEXPR inline bool operator<(sprout::null_array const& lhs, sprout::null_array const& rhs) { + SPROUT_CONSTEXPR inline bool operator<(sprout::pit const& lhs, sprout::pit const& rhs) { return lhs.front() < rhs.front(); } template - SPROUT_CONSTEXPR inline bool operator>(sprout::null_array const& lhs, sprout::null_array const& rhs) { + SPROUT_CONSTEXPR inline bool operator>(sprout::pit const& lhs, sprout::pit const& rhs) { return rhs < lhs; } template - SPROUT_CONSTEXPR inline bool operator<=(sprout::null_array const& lhs, sprout::null_array const& rhs) { + SPROUT_CONSTEXPR inline bool operator<=(sprout::pit const& lhs, sprout::pit const& rhs) { return !(rhs < lhs); } template - SPROUT_CONSTEXPR inline bool operator>=(sprout::null_array const& lhs, sprout::null_array const& rhs) { + SPROUT_CONSTEXPR inline bool operator>=(sprout::pit const& lhs, sprout::pit const& rhs) { return !(lhs < rhs); } @@ -166,7 +166,7 @@ namespace sprout { // swap // template - inline void swap(sprout::null_array& lhs, sprout::null_array& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { + inline void swap(sprout::pit& lhs, sprout::pit& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } @@ -174,15 +174,15 @@ namespace sprout { // fixed_container_traits // template - struct fixed_container_traits > - : public sprout::detail::fixed_container_traits_base > + struct fixed_container_traits > + : public sprout::detail::fixed_container_traits_base > { public: - typedef typename sprout::null_array::fixed_container_type fixed_container_type; - typedef typename sprout::null_array::internal_type internal_type; - typedef typename sprout::null_array::clone_type clone_type; + typedef typename sprout::pit::fixed_container_type fixed_container_type; + typedef typename sprout::pit::internal_type internal_type; + typedef typename sprout::pit::clone_type clone_type; public: - SPROUT_STATIC_CONSTEXPR typename sprout::detail::fixed_container_traits_base >::size_type fixed_size + SPROUT_STATIC_CONSTEXPR typename sprout::detail::fixed_container_traits_base >::size_type fixed_size = std::tuple_size::type>::value ; }; @@ -191,14 +191,14 @@ namespace sprout { // rebind_fixed_size // template - struct rebind_fixed_size > { + struct rebind_fixed_size > { public: - template >::size_type S> + template >::size_type S> struct apply { public: - typedef sprout::null_array< + typedef sprout::pit< typename sprout::rebind_fixed_size< - typename sprout::fixed_container_traits >::internal_type + typename sprout::fixed_container_traits >::internal_type >::template apply::type > type; }; @@ -208,14 +208,14 @@ namespace sprout { // clone_functor // template - struct clone_functor > { + struct clone_functor > { private: - typedef typename sprout::fixed_container_traits >::clone_type clone_type; + typedef typename sprout::fixed_container_traits >::clone_type clone_type; public: - clone_type operator()(sprout::null_array& cont) const { + clone_type operator()(sprout::pit& cont) const { return clone_type(); } - SPROUT_CONSTEXPR clone_type operator()(sprout::null_array const& cont) const { + SPROUT_CONSTEXPR clone_type operator()(sprout::pit const& cont) const { return clone_type(); } }; @@ -224,10 +224,10 @@ namespace sprout { // make_clone_functor // template - struct make_clone_functor > { + struct make_clone_functor > { private: - typedef typename sprout::fixed_container_traits >::clone_type clone_type; - typedef typename sprout::fixed_container_traits >::internal_type internal_type; + typedef typename sprout::fixed_container_traits >::clone_type clone_type; + typedef typename sprout::fixed_container_traits >::internal_type internal_type; public: template SPROUT_CONSTEXPR clone_type operator()(Args const&... args) const { @@ -239,15 +239,15 @@ namespace sprout { // remake_clone_functor // template - struct remake_clone_functor > { + struct remake_clone_functor > { private: - typedef typename sprout::fixed_container_traits >::clone_type clone_type; - typedef typename sprout::fixed_container_traits >::internal_type internal_type; + typedef typename sprout::fixed_container_traits >::clone_type clone_type; + typedef typename sprout::fixed_container_traits >::internal_type internal_type; public: template clone_type operator()( Other& other, - typename sprout::fixed_container_traits >::difference_type size, + typename sprout::fixed_container_traits >::difference_type size, Args const&... args ) const { @@ -256,7 +256,7 @@ namespace sprout { template SPROUT_CONSTEXPR clone_type operator()( Other const& other, - typename sprout::fixed_container_traits >::difference_type size, + typename sprout::fixed_container_traits >::difference_type size, Args const&... args ) const { @@ -270,9 +270,9 @@ namespace std { // tuple_size // template - struct tuple_size > { + struct tuple_size > { public: - typedef std::integral_constant >::fixed_size> type; + typedef std::integral_constant >::fixed_size> type; SPROUT_STATIC_CONSTEXPR std::size_t value = type::value; }; @@ -280,38 +280,38 @@ namespace std { // tuple_element // template - struct tuple_element > { + struct tuple_element > { public: - static_assert(I < sprout::fixed_container_traits >::fixed_size, "tuple_element<>: index out of range"); - typedef typename sprout::fixed_container_traits >::value_type type; + static_assert(I < sprout::fixed_container_traits >::fixed_size, "tuple_element<>: index out of range"); + typedef typename sprout::fixed_container_traits >::value_type type; }; // // get // template - typename sprout::fixed_container_traits >::value_type& get( - sprout::null_array& arr + typename sprout::fixed_container_traits >::value_type& get( + sprout::pit& t ) SPROUT_NOEXCEPT { - static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); - return arr[I]; + static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); + return t[I]; } template - SPROUT_CONSTEXPR typename sprout::fixed_container_traits >::value_type const& get( - sprout::null_array const& arr + SPROUT_CONSTEXPR typename sprout::fixed_container_traits >::value_type const& get( + sprout::pit const& t ) SPROUT_NOEXCEPT { - static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); - return arr[I]; + static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); + return t[I]; } template - typename sprout::fixed_container_traits >::value_type&& get( - sprout::null_array&& arr - ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(arr)))) + typename sprout::fixed_container_traits >::value_type&& get( + sprout::pit&& t + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(t)))) { - return std::move(std::get(arr)); + return std::move(std::get(t)); } } // namespace std -#endif // #ifndef SPROUT_NULL_ARRAY_HPP +#endif // #ifndef SPROUT_PIT_HPP diff --git a/sprout/string.hpp b/sprout/string.hpp index 225e4b04..1ba8af92 100644 --- a/sprout/string.hpp +++ b/sprout/string.hpp @@ -264,7 +264,7 @@ namespace sprout { return from_c_str(s, traits_type::length(s)); } public: - T elems[N + 1]; + value_type elems[static_size + 1]; size_type len; public: // construct/copy/destroy: @@ -347,7 +347,7 @@ namespace sprout { return size(); } SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { - return N; + return static_size; } void resize(size_type n, value_type c) { maxcheck(n); @@ -1071,18 +1071,18 @@ namespace std { // get // template - T& get(sprout::basic_string& arr) SPROUT_NOEXCEPT { + T& get(sprout::basic_string& t) SPROUT_NOEXCEPT { static_assert(I < N, "get: index out of range"); - return arr[I]; + return t[I]; } template - SPROUT_CONSTEXPR T const& get(sprout::basic_string const& arr) SPROUT_NOEXCEPT { + SPROUT_CONSTEXPR T const& get(sprout::basic_string const& t) SPROUT_NOEXCEPT { static_assert(I < N, "get: index out of range"); - return arr[I]; + return t[I]; } template - T&& get(sprout::basic_string&& arr) SPROUT_NOEXCEPT { - return std::move(std::get(arr)); + T&& get(sprout::basic_string&& t) SPROUT_NOEXCEPT { + return std::move(std::get(t)); } } // namespace std diff --git a/sprout/sub_array.hpp b/sprout/sub_array.hpp index 69429510..d8c2a381 100644 --- a/sprout/sub_array.hpp +++ b/sprout/sub_array.hpp @@ -945,26 +945,26 @@ namespace std { // template typename sprout::fixed_container_traits >::value_type& get( - sprout::sub_array& arr - ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(arr), I))) + sprout::sub_array& t + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(t), I))) { static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); - return *sprout::next(sprout::fixed_begin(arr), I); + return *sprout::next(sprout::fixed_begin(t), I); } template SPROUT_CONSTEXPR typename sprout::fixed_container_traits >::value_type const& get( - sprout::sub_array const& arr - ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(arr), I))) + sprout::sub_array const& t + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(t), I))) { static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); - return *sprout::next(sprout::fixed_begin(arr), I); + return *sprout::next(sprout::fixed_begin(t), I); } template typename sprout::fixed_container_traits >::value_type&& get( - sprout::sub_array&& arr - ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(arr)))) + sprout::sub_array&& t + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(t)))) { - return std::move(std::get(arr)); + return std::move(std::get(t)); } } // namespace std diff --git a/sprout/uuid.hpp b/sprout/uuid.hpp new file mode 100644 index 00000000..dc212f4b --- /dev/null +++ b/sprout/uuid.hpp @@ -0,0 +1,10 @@ +#ifndef SPROUT_UUID_HPP +#define SPROUT_UUID_HPP + +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_UUID_HPP diff --git a/sprout/uuid/detail/table.hpp b/sprout/uuid/detail/table.hpp new file mode 100644 index 00000000..7f95f637 --- /dev/null +++ b/sprout/uuid/detail/table.hpp @@ -0,0 +1,64 @@ +#ifndef SPROUT_UUID_DETAIL_TABLE_HPP +#define SPROUT_UUID_DETAIL_TABLE_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace uuids { + namespace detail { + template + struct digits {}; + + template<> + struct digits { + public: + SPROUT_STATIC_CONSTEXPR sprout::basic_string table = sprout::to_string("0123456789abcdefABCDEF"); + SPROUT_STATIC_CONSTEXPR char dash = '-'; + }; + SPROUT_CONSTEXPR sprout::basic_string sprout::uuids::detail::digits::table; + SPROUT_CONSTEXPR char sprout::uuids::detail::digits::dash; + + template<> + struct digits { + public: + SPROUT_STATIC_CONSTEXPR sprout::basic_string table = sprout::to_string(L"0123456789abcdefABCDEF"); + SPROUT_STATIC_CONSTEXPR wchar_t dash = L'-'; + }; + SPROUT_CONSTEXPR sprout::basic_string sprout::uuids::detail::digits::table; + SPROUT_CONSTEXPR wchar_t sprout::uuids::detail::digits::dash; + + template<> + struct digits { + public: + SPROUT_STATIC_CONSTEXPR sprout::basic_string table = sprout::to_string(u"0123456789abcdefABCDEF"); + SPROUT_STATIC_CONSTEXPR char16_t dash = u'-'; + }; + SPROUT_CONSTEXPR sprout::basic_string sprout::uuids::detail::digits::table; + SPROUT_CONSTEXPR char16_t sprout::uuids::detail::digits::dash; + + template<> + struct digits { + public: + SPROUT_STATIC_CONSTEXPR sprout::basic_string table = sprout::to_string(U"0123456789abcdefABCDEF"); + SPROUT_STATIC_CONSTEXPR char32_t dash = U'-'; + }; + SPROUT_CONSTEXPR sprout::basic_string sprout::uuids::detail::digits::table; + SPROUT_CONSTEXPR char32_t sprout::uuids::detail::digits::dash; + + template + struct values; + + template<> + struct values { + public: + SPROUT_STATIC_CONSTEXPR sprout::array table = sprout::array{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15}}; + }; + SPROUT_CONSTEXPR sprout::array sprout::uuids::detail::values::table; + } // namespace detail + } // namespace uuids +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_DETAIL_TABLE_HPP diff --git a/sprout/uuid/name_generator.hpp b/sprout/uuid/name_generator.hpp new file mode 100644 index 00000000..fbf16949 --- /dev/null +++ b/sprout/uuid/name_generator.hpp @@ -0,0 +1,72 @@ +#ifndef SPROUT_UUID_NAME_GENERATOR_HPP +#define SPROUT_UUID_NAME_GENERATOR_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace uuids { + // + // name_generator + // + class name_generator { + public: + typedef sprout::uuids::uuid result_type; + private: + typedef typename result_type::value_type value_type; + private: + sprout::sha1 sha_; + private: + SPROUT_CONSTEXPR result_type sha_to_uuid_1(sprout::sha1::value_type const& value) const { + return result_type{{ + value[0], + value[1], + value[2], + value[3], + value[4], + value[5], + static_cast((value[6] & 0x5F) | 0x50), + value[7], + static_cast((value[8] & 0xBF) | 0x80), + value[9], + value[10], + value[11], + value[12], + value[13], + value[14], + value[15] + }}; + } + SPROUT_CONSTEXPR result_type sha_to_uuid(sprout::sha1 const& sha) const { + return sha_to_uuid_1(sha.checksum()); + } + public: + SPROUT_CONSTEXPR name_generator() + : sha_(sprout::sha1().process_range(sprout::uuids::uuid{{0}})) + {} + SPROUT_CONSTEXPR explicit name_generator(sprout::uuids::uuid const& namespace_uuid) + : sha_(sprout::sha1().process_range(namespace_uuid)) + {} + template + SPROUT_CONSTEXPR result_type operator()(sprout::basic_string const& name) const { + return sha_to_uuid(sha_.process_range(name)); + } + SPROUT_CONSTEXPR result_type operator()(char const* name) const { + return sha_to_uuid(sha_.process_bytes(name, sprout::char_traits::length(name))); + } + SPROUT_CONSTEXPR result_type operator()(wchar_t const* name) const { + return sha_to_uuid(sha_.process_bytes(name, sprout::char_traits::length(name))); + } + SPROUT_CONSTEXPR result_type operator()(char16_t const* name) const { + return sha_to_uuid(sha_.process_bytes(name, sprout::char_traits::length(name))); + } + SPROUT_CONSTEXPR result_type operator()(char32_t const* name) const { + return sha_to_uuid(sha_.process_bytes(name, sprout::char_traits::length(name))); + } + }; + } // namespace uuids +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_NAME_GENERATOR_HPP diff --git a/sprout/uuid/nil_generator.hpp b/sprout/uuid/nil_generator.hpp new file mode 100644 index 00000000..2318db87 --- /dev/null +++ b/sprout/uuid/nil_generator.hpp @@ -0,0 +1,29 @@ +#ifndef SPROUT_UUID_NIL_GENERATOR_HPP +#define SPROUT_UUID_NIL_GENERATOR_HPP + +#include +#include + +namespace sprout { + namespace uuids { + // + // nil_generator + // + class nil_generator { + public: + typedef sprout::uuids::uuid result_type; + public: + SPROUT_CONSTEXPR result_type operator()() const { + return result_type{{0}}; + } + }; + // + // nil_uuid + // + SPROUT_CONSTEXPR inline sprout::uuids::uuid nil_uuid() { + return sprout::uuids::nil_generator()(); + } + } // namespace uuids +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_NIL_GENERATOR_HPP diff --git a/sprout/uuid/random_generator.hpp b/sprout/uuid/random_generator.hpp new file mode 100644 index 00000000..96be01cc --- /dev/null +++ b/sprout/uuid/random_generator.hpp @@ -0,0 +1,90 @@ +#ifndef SPROUT_UUID_RANDOM_GENERATOR_HPP +#define SPROUT_UUID_RANDOM_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace uuids { + // + // basic_random_generator + // + template + class basic_random_generator { + public: + typedef sprout::uuids::uuid result_type; + private: + typedef UniformRandomNumberGenerator engine_type; + typedef sprout::random::uniform_int_distribution distribution_type; + typedef typename result_type::value_type value_type; + private: + distribution_type distribution_; + private: + SPROUT_CONSTEXPR result_type random_to_uuid_1(std::uint32_t v0, std::uint32_t v1, std::uint32_t v2, std::uint32_t v3) const { + return result_type{{ + static_cast((v0 >> 24) & 0xFF), + static_cast((v0 >> 16) & 0xFF), + static_cast((v0 >> 8) & 0xFF), + static_cast((v0) & 0xFF), + static_cast((v1 >> 24) & 0xFF), + static_cast((v1 >> 16) & 0xFF), + static_cast(((v1 >> 8) & 0x4F) | 0x40), + static_cast((v1) & 0xFF), + static_cast(((v2 >> 24) & 0xBF) | 0x80), + static_cast((v2 >> 16) & 0xFF), + static_cast((v2 >> 8) & 0xFF), + static_cast((v2) & 0xFF), + static_cast((v3 >> 24) & 0xFF), + static_cast((v3 >> 16) & 0xFF), + static_cast((v3 >> 8) & 0xFF), + static_cast((v3) & 0xFF) + }}; + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) == 3, + result_type + >::type random_to_uuid(Random const& rnd, Args... args) const { + return random_to_uuid_1(args..., rnd.result()); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) != 3, + result_type + >::type random_to_uuid(Random const& rnd, Args... args) const { + return random_to_uuid(rnd(), args..., rnd.result()); + } + public: + SPROUT_CONSTEXPR basic_random_generator() + : distribution_(std::numeric_limits::min(), std::numeric_limits::max()) + {} + template + SPROUT_CONSTEXPR typename std::enable_if< + std::is_integral::value, + result_type + >::type operator()(T const& seed) const { + return operator()(engine_type(seed)); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + !std::is_integral::value, + result_type + >::type operator()(Engine const& engine) const { + return random_to_uuid(sprout::random::combine(engine, distribution_)()); + } + }; + + // + // random_generator + // + typedef sprout::uuids::basic_random_generator random_generator; + } // namespace uuids +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_RANDOM_GENERATOR_HPP diff --git a/sprout/uuid/string_generator.hpp b/sprout/uuid/string_generator.hpp new file mode 100644 index 00000000..10c7214a --- /dev/null +++ b/sprout/uuid/string_generator.hpp @@ -0,0 +1,191 @@ +#ifndef SPROUT_UUID_STRING_GENERATOR_HPP +#define SPROUT_UUID_STRING_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT_DETAIL +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT_DETAIL + +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; + Iterator first; + Iterator last; + public: + SPROUT_CONSTEXPR next_char(Iterator f, Iterator l) + : c(f != l ? *f : throw "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 "string_generator: invalid uuid string (invalid character)" + ; + } + template + SPROUT_CONSTEXPR std::uint8_t get_value(Elem c) const { + return value_at( + NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance( + sprout::uuids::detail::digits::table.begin(), + NS_SSCRISK_CEL_OR_SPROUT_DETAIL::find( + sprout::uuids::detail::digits::table.begin(), + sprout::uuids::detail::digits::table.end(), + c + ) + ) + ); + } + static SPROUT_CONSTEXPR bool is_dash(char c) { + return c == '-'; + } + static SPROUT_CONSTEXPR bool is_dash(wchar_t c) { + return c == L'-'; + } + static SPROUT_CONSTEXPR bool is_dash(char16_t c) { + return c == u'-'; + } + static SPROUT_CONSTEXPR bool is_dash(char32_t c) { + return c == U'-'; + } + static SPROUT_CONSTEXPR bool is_open_brace(char c) { + return c == '{'; + } + static SPROUT_CONSTEXPR bool is_open_brace(wchar_t c) { + return c == L'{'; + } + static SPROUT_CONSTEXPR bool is_open_brace(char16_t c) { + return c == u'{'; + } + static SPROUT_CONSTEXPR bool is_open_brace(char32_t c) { + return c == U'{'; + } + static SPROUT_CONSTEXPR bool is_close_brace(char c, char open_brace) { + return open_brace == '{' && c == '}'; + } + static SPROUT_CONSTEXPR bool is_close_brace(wchar_t c, char open_brace) { + return open_brace == L'{' && c == L'}'; + } + static SPROUT_CONSTEXPR bool is_close_brace(char16_t c, char open_brace) { + return open_brace == u'{' && c == u'}'; + } + static SPROUT_CONSTEXPR bool is_close_brace(char32_t c, char open_brace) { + return open_brace == U'{' && c == U'}'; + } + 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 "string_generator: invalid uuid string (dashes not found)" // ??? + : generate_2_2(nc, open_brace, has_dashes, args...) + : 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 has_dashes, 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 has_dashes, Args... args) const { + return !open_brace || (open_brace && is_close_brace(nc.next().c, open_brace)) + ? result_type{{args...}} + : throw "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()(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)); + } + 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)); + } + template + SPROUT_CONSTEXPR result_type operator()(Iterator first, Iterator last) const { + return generate_1(next_char(first, last)); + } + }; + } // namespace uuids +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_STRING_GENERATOR_HPP diff --git a/sprout/uuid/uuid.hpp b/sprout/uuid/uuid.hpp new file mode 100644 index 00000000..b0492af2 --- /dev/null +++ b/sprout/uuid/uuid.hpp @@ -0,0 +1,299 @@ +#ifndef SPROUT_UUID_UUID_HPP +#define SPROUT_UUID_UUID_HPP + +#include +#include +#include +#include +#include +#include +#include +#include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT_DETAIL +#if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION +# include +#endif + +namespace sprout { + namespace uuids { + namespace detail { + template + SPROUT_CONSTEXPR inline bool is_nil(InputIterator first, InputIterator last) { + return first == last ? true + : !*first && sprout::uuids::detail::is_nil(sprout::next(first), last) + ; + } + } // namespace detail + + // + // uuid + // + class uuid { + public: + typedef std::uint8_t value_type; +#if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION + typedef sprout::index_iterator iterator; + typedef sprout::index_iterator const_iterator; +#else + typedef std::uint8_t* iterator; + typedef std::uint8_t const* const_iterator; +#endif + typedef std::uint8_t& reference; + typedef std::uint8_t const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::uint8_t* pointer; + typedef std::uint8_t const* const_pointer; + typedef sprout::reverse_iterator reverse_iterator; + typedef sprout::reverse_iterator const_reverse_iterator; + public: + // + // variant_type + // + enum variant_type { + variant_ncs, + variant_rfc_4122, + variant_microsoft, + variant_future + }; + // + // version_type + // + enum version_type { + version_unknown = -1, + version_time_based = 1, + version_dce_security = 2, + version_name_based_md5 = 3, + version_random_number_based = 4, + version_name_based_sha1 = 5 + }; + public: + SPROUT_STATIC_CONSTEXPR size_type static_size = 16; + SPROUT_STATIC_CONSTEXPR size_type fixed_size = static_size; + public: + value_type elems[static_size]; + public: + void fill(const_reference value) { + std::fill_n(begin(), size(), value); + } + void swap(uuid& other) SPROUT_NOEXCEPT { + std::swap_ranges(other.begin(), other.end(), begin()); + } + // iterators: +#if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION + iterator begin() SPROUT_NOEXCEPT { + return iterator(*this, 0); + } + SPROUT_CONSTEXPR const_iterator begin() const SPROUT_NOEXCEPT { + return const_iterator(*this, 0); + } + iterator end() SPROUT_NOEXCEPT { + return iterator(*this, size()); + } + SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { + return const_iterator(*this, size()); + } +#else + iterator begin() SPROUT_NOEXCEPT { + return &elems[0]; + } + SPROUT_CONSTEXPR const_iterator begin() const SPROUT_NOEXCEPT { + return &elems[0]; + } + iterator end() SPROUT_NOEXCEPT { + return &elems[0] + size(); + } + SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { + return &elems[0] + size(); + } +#endif + reverse_iterator rbegin() SPROUT_NOEXCEPT { + return reverse_iterator(end()); + } + SPROUT_CONSTEXPR const_reverse_iterator rbegin() const SPROUT_NOEXCEPT { + return const_reverse_iterator(end()); + } + reverse_iterator rend() SPROUT_NOEXCEPT { + return reverse_iterator(begin()); + } + SPROUT_CONSTEXPR const_reverse_iterator rend() const SPROUT_NOEXCEPT { + return const_reverse_iterator(begin()); + } +#if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION + SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { + return const_iterator(*this, 0); + } + SPROUT_CONSTEXPR const_iterator cend() const SPROUT_NOEXCEPT { + return const_iterator(*this, size()); + } +#else + SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { + return &elems[0]; + } + SPROUT_CONSTEXPR const_iterator cend() const SPROUT_NOEXCEPT { + return &elems[0] + size(); + } +#endif + SPROUT_CONSTEXPR const_reverse_iterator crbegin() const SPROUT_NOEXCEPT { + return const_reverse_iterator(end()); + } + SPROUT_CONSTEXPR const_reverse_iterator crend() const SPROUT_NOEXCEPT { + return const_reverse_iterator(begin()); + } + // capacity: + SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { + return static_size; + } + SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { + return size(); + } + SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { + return size() == 0; + } + // element access: + reference operator[](size_type i) { + return elems[i]; + } + SPROUT_CONSTEXPR const_reference operator[](size_type i) const { + return elems[i]; + } + reference at(size_type i) { + rangecheck(i); + return elems[i]; + } + const_reference at(size_type i) const { + rangecheck(i); + return elems[i]; + } + reference front() { + return elems[0]; + } + SPROUT_CONSTEXPR const_reference front() const { + return elems[0]; + } + reference back() { + return elems[size() - 1]; + } + SPROUT_CONSTEXPR const_reference back() const { + return elems[size() - 1]; + } + + pointer data() SPROUT_NOEXCEPT { + return &elems[0]; + } + SPROUT_CONSTEXPR const_pointer data() const SPROUT_NOEXCEPT { + return &elems[0]; + } + + // others: + pointer c_array() SPROUT_NOEXCEPT { + return &elems[0]; + } + void assign(const_reference value) { + fill(value); + } + void rangecheck(size_type i) const { + if (i >= size()) { + throw std::out_of_range("uuid<>: index out of range"); + } + } + + SPROUT_CONSTEXPR bool is_nil() const { + return sprout::uuids::detail::is_nil(begin(), end()); + } + SPROUT_CONSTEXPR variant_type variant() const { + return (elems[8] & 0x80) == 0x00 ? variant_ncs + : (elems[8] & 0xC0) == 0x80 ? variant_rfc_4122 + : (elems[8] & 0xE0) == 0xC0 ? variant_microsoft + : variant_future + ; + } + SPROUT_CONSTEXPR version_type version() const { + return (elems[6] & 0xF0) == 0x10 ? version_time_based + : (elems[6] & 0xF0) == 0x20 ? version_dce_security + : (elems[6] & 0xF0) == 0x30 ? version_name_based_md5 + : (elems[6] & 0xF0) == 0x40 ? version_random_number_based + : (elems[6] & 0xF0) == 0x50 ? version_name_based_sha1 + : version_unknown + ; + } + }; + + // + // operator== + // operator!= + // operator< + // operator> + // operator<= + // operator>= + // + SPROUT_CONSTEXPR inline bool operator==(sprout::uuids::uuid const& lhs, sprout::uuids::uuid const& rhs) { + return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + SPROUT_CONSTEXPR inline bool operator!=(sprout::uuids::uuid const& lhs, sprout::uuids::uuid const& rhs) { + return !(lhs == rhs); + } + SPROUT_CONSTEXPR inline bool operator<(sprout::uuids::uuid const& lhs, sprout::uuids::uuid const& rhs) { + return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + } + SPROUT_CONSTEXPR inline bool operator>(sprout::uuids::uuid const& lhs, sprout::uuids::uuid const& rhs) { + return rhs < lhs; + } + SPROUT_CONSTEXPR inline bool operator<=(sprout::uuids::uuid const& lhs, sprout::uuids::uuid const& rhs) { + return !(rhs < lhs); + } + SPROUT_CONSTEXPR inline bool operator>=(sprout::uuids::uuid const& lhs, sprout::uuids::uuid const& rhs) { + return !(lhs < rhs); + } + + // + // swap + // + inline void swap(sprout::uuids::uuid& lhs, sprout::uuids::uuid& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { + lhs.swap(rhs); + } + } // namespace uuids + + using sprout::uuids::uuid; +} // namespace sprout + +namespace std { + // + // tuple_size + // + template<> + struct tuple_size { + public: + typedef std::integral_constant type; + SPROUT_STATIC_CONSTEXPR std::size_t value = type::value; + }; + + // + // tuple_element + // + template + struct tuple_element { + public: + static_assert(I < 16, "tuple_element<>: index out of range"); + typedef sprout::uuids::uuid::value_type type; + }; + + // + // get + // + template + sprout::uuids::uuid::value_type& get(sprout::uuids::uuid& t) SPROUT_NOEXCEPT { + static_assert(I < 16, "get: index out of range"); + return t[I]; + } + template + SPROUT_CONSTEXPR sprout::uuids::uuid::value_type const& get(sprout::uuids::uuid const& t) SPROUT_NOEXCEPT { + static_assert(I < 16, "get: index out of range"); + return t[I]; + } + template + sprout::uuids::uuid::value_type&& get(sprout::uuids::uuid&& t) SPROUT_NOEXCEPT { + return std::move(std::get(t)); + } +} // namespace std + +#endif // #ifndef SPROUT_UUID_UUID_HPP diff --git a/sprout/uuid/uuid_generators.hpp b/sprout/uuid/uuid_generators.hpp new file mode 100644 index 00000000..8bd675e2 --- /dev/null +++ b/sprout/uuid/uuid_generators.hpp @@ -0,0 +1,10 @@ +#ifndef SPROUT_UUID_UUID_GENERATORS_HPP +#define SPROUT_UUID_UUID_GENERATORS_HPP + +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_UUID_UUID_GENERATORS_HPP diff --git a/sprout/uuid/uuid_hash.hpp b/sprout/uuid/uuid_hash.hpp new file mode 100644 index 00000000..bdae3f09 --- /dev/null +++ b/sprout/uuid/uuid_hash.hpp @@ -0,0 +1,14 @@ +#ifndef SPROUT_UUID_UUID_HASH_HPP +#define SPROUT_UUID_UUID_HASH_HPP + +#include +#include +#include + +namespace sprout { + SPROUT_CONSTEXPR std::size_t hash_value(sprout::uuids::uuid const& v) { + return sprout::hash_range(v.begin(), v.end()); + } +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_UUID_HASH_HPP diff --git a/sprout/uuid/uuid_io.hpp b/sprout/uuid/uuid_io.hpp new file mode 100644 index 00000000..13a543de --- /dev/null +++ b/sprout/uuid/uuid_io.hpp @@ -0,0 +1,184 @@ +#ifndef SPROUT_UUID_UUID_IO_HPP +#define SPROUT_UUID_UUID_IO_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace uuids { + // + // operator>> + // + template + std::basic_istream& operator>>(std::basic_istream& lhs, sprout::uuids::uuid& rhs) { + typedef typename std::basic_ios::char_type char_type; + typename std::basic_istream::sentry const ok(lhs); + typedef std::ctype ctype_type; + if (ok) { + sprout::uuids::uuid::value_type data[16]; + ctype_type const& ctype = std::use_facet(lhs.getloc()); + char_type xdigits[16]; + { + char const szdigits[] = "0123456789ABCDEF"; + ctype.widen(szdigits, szdigits + 16, xdigits); + } + char_type const* const xdigits_end = xdigits + 16; + char_type c; + for (sprout::uuids::uuid::size_type i = 0, last = rhs.size(); i < last && lhs; ++i) { + lhs >> c; + c = ctype.toupper(c); + char_type const* f = std::find(xdigits, xdigits_end, c); + if (f == xdigits_end) { + lhs.setstate(std::ios_base::failbit); + break; + } + sprout::uuids::uuid::value_type byte = static_cast(std::distance(&xdigits[0], f)); + lhs >> c; + c = ctype.toupper(c); + f = std::find(xdigits, xdigits_end, c); + if (f == xdigits_end) { + lhs.setstate(std::ios_base::failbit); + break; + } + byte <<= 4; + byte |= static_cast(std::distance(&xdigits[0], f)); + data[i] = byte; + if (lhs) { + if (i == 3 || i == 5 || i == 7 || i == 9) { + lhs >> c; + if (c != lhs.widen('-')) { + lhs.setstate(std::ios_base::failbit); + break; + } + } + } + } + if (lhs) { + std::copy(data, data + 16, rhs.begin()); + } + } + return lhs; + } + // + // operator<< + // + template + std::basic_ostream& operator<<(std::basic_ostream& lhs, sprout::uuids::uuid const& rhs) { + sprout::detail::io::ios_flags_saver flags_saver(lhs); + sprout::detail::io::basic_ios_fill_saver fill_saver(lhs); + typename std::basic_ostream::sentry const ok(lhs); + if (ok) { + std::streamsize const width = lhs.width(0); + std::streamsize const uuid_width = 36; + std::ios_base::fmtflags const flags = lhs.flags(); + typename std::basic_ios::char_type const fill = lhs.fill(); + if (flags & (std::ios_base::right | std::ios_base::internal)) { + for (std::streamsize i = uuid_width; i < width; ++i) { + lhs << fill; + } + } + lhs << std::hex; + lhs.fill(lhs.widen('0')); + std::size_t i = 0; + for (sprout::uuids::uuid::const_iterator i_data = rhs.begin(), i_last = rhs.end(); i_data != i_last; ++i_data, ++i) { + lhs.width(2); + lhs << static_cast(*i_data); + if (i == 3 || i == 5 || i == 7 || i == 9) { + lhs << lhs.widen('-'); + } + } + if (flags & std::ios_base::left) { + for (std::streamsize i = uuid_width; i < width; ++i) { + lhs << fill; + } + } + lhs.width(0); + } + return lhs; + } + + // + // to_string_of + // + template > + SPROUT_CONSTEXPR inline sprout::basic_string to_string_of(sprout::uuids::uuid const& u) { + return sprout::basic_string{ + { + sprout::uuids::detail::digits::table[(u[0] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[0]) & 0x0F], + sprout::uuids::detail::digits::table[(u[1] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[1]) & 0x0F], + sprout::uuids::detail::digits::table[(u[2] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[2]) & 0x0F], + sprout::uuids::detail::digits::table[(u[3] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[3]) & 0x0F], + sprout::uuids::detail::digits::dash, + sprout::uuids::detail::digits::table[(u[4] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[4]) & 0x0F], + sprout::uuids::detail::digits::table[(u[5] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[5]) & 0x0F], + sprout::uuids::detail::digits::dash, + sprout::uuids::detail::digits::table[(u[6] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[6]) & 0x0F], + sprout::uuids::detail::digits::table[(u[7] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[7]) & 0x0F], + sprout::uuids::detail::digits::dash, + sprout::uuids::detail::digits::table[(u[8] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[8]) & 0x0F], + sprout::uuids::detail::digits::table[(u[9] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[9]) & 0x0F], + sprout::uuids::detail::digits::dash, + sprout::uuids::detail::digits::table[(u[10] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[10]) & 0x0F], + sprout::uuids::detail::digits::table[(u[11] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[11]) & 0x0F], + sprout::uuids::detail::digits::table[(u[12] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[12]) & 0x0F], + sprout::uuids::detail::digits::table[(u[13] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[13]) & 0x0F], + sprout::uuids::detail::digits::table[(u[14] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[14]) & 0x0F], + sprout::uuids::detail::digits::table[(u[15] >> 4) & 0x0F], + sprout::uuids::detail::digits::table[(u[15]) & 0x0F] + }, + 36 + }; + } + // + // to_string + // + SPROUT_CONSTEXPR inline sprout::basic_string to_string(sprout::uuids::uuid const& u) { + return sprout::uuids::to_string_of(u); + } + // + // to_wstring + // + SPROUT_CONSTEXPR inline sprout::basic_string to_wstring(sprout::uuids::uuid const& u) { + return sprout::uuids::to_string_of(u); + } + // + // to_u16string + // + SPROUT_CONSTEXPR inline sprout::basic_string to_u16string(sprout::uuids::uuid const& u) { + return sprout::uuids::to_string_of(u); + } + // + // to_u32string + // + SPROUT_CONSTEXPR inline sprout::basic_string to_u32string(sprout::uuids::uuid const& u) { + return sprout::uuids::to_string_of(u); + } + } // namespace uuids +} // namespace sprout + +#endif // #ifndef SPROUT_UUID_UUID_IO_HPP