| // This file is part of the ustl library, an STL implementation. |
| // |
| // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net> |
| // This file is free software, distributed under the MIT License. |
| // |
| // uspecial.h |
| // |
| // Template specializations for uSTL classes. |
| // |
| |
| #ifndef USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 |
| #define USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 |
| |
| #include "uassert.h" |
| #include "uvector.h" |
| #include "ustring.h" |
| #include "uset.h" |
| #include "umultiset.h" |
| #include "ubitset.h" |
| #include "ulaalgo.h" |
| #include "uctralgo.h" |
| #include "ufunction.h" |
| #include "uctrstrm.h" |
| #include "sistream.h" |
| #include <ctype.h> |
| |
| namespace ustl { |
| |
| //---------------------------------------------------------------------- |
| // Alogrithm specializations not in use by the library code. |
| //---------------------------------------------------------------------- |
| |
| template <> inline void swap (cmemlink& a, cmemlink& b) { a.swap (b); } |
| template <> inline void swap (memlink& a, memlink& b) { a.swap (b); } |
| template <> inline void swap (memblock& a, memblock& b) { a.swap (b); } |
| template <> inline void swap (string& a, string& b) { a.swap (b); } |
| #define TEMPLATE_SWAP_PSPEC(type, template_decl) \ |
| template_decl inline void swap (type& a, type& b) { a.swap (b); } |
| TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) |
| TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (set,T), TEMPLATE_DECL1 (T)) |
| TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (multiset,T), TEMPLATE_DECL1 (T)) |
| TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE2 (tuple,N,T), TEMPLATE_FULL_DECL2 (size_t,N,typename,T)) |
| |
| //---------------------------------------------------------------------- |
| // Streamable definitions. Not used in the library and require streams. |
| //---------------------------------------------------------------------- |
| |
| //----{ pair }---------------------------------------------------------- |
| |
| /// \brief Reads pair \p p from stream \p is. |
| template <typename T1, typename T2> |
| istream& operator>> (istream& is, pair<T1,T2>& p) |
| { |
| is >> p.first; |
| is.align (alignof(T2())); |
| is >> p.second; |
| is.align (alignof(T1())); |
| return (is); |
| } |
| |
| /// Writes pair \p p to stream \p os. |
| template <typename T1, typename T2> |
| ostream& operator<< (ostream& os, const pair<T1,T2>& p) |
| { |
| os << p.first; |
| os.align (alignof(T2())); |
| os << p.second; |
| os.align (alignof(T1())); |
| return (os); |
| } |
| |
| /// Writes pair \p p to stream \p os. |
| template <typename T1, typename T2> |
| ostringstream& operator<< (ostringstream& os, const pair<T1,T2>& p) |
| { |
| os << '(' << p.first << ',' << p.second << ')'; |
| return (os); |
| } |
| |
| /// Returns the written size of the object. |
| template <typename T1, typename T2> |
| inline size_t stream_size_of (const pair<T1,T2>& v) |
| { |
| return (Align (stream_size_of(v.first), alignof(T2())) + |
| Align (stream_size_of(v.second), alignof(T1()))); |
| } |
| |
| /// \brief Takes a pair and returns pair.first |
| /// This is an extension, available in uSTL and the SGI STL. |
| template <typename Pair> struct select1st : public unary_function<Pair,typename Pair::first_type> { |
| typedef typename Pair::first_type result_type; |
| inline const result_type& operator()(const Pair& a) const { return (a.first); } |
| inline result_type& operator()(Pair& a) const { return (a.first); } |
| }; |
| |
| /// \brief Takes a pair and returns pair.second |
| /// This is an extension, available in uSTL and the SGI STL. |
| template <typename Pair> struct select2nd : public unary_function<Pair,typename Pair::second_type> { |
| typedef typename Pair::second_type result_type; |
| inline const result_type& operator()(const Pair& a) const { return (a.second); } |
| inline result_type& operator()(Pair& a) const { return (a.second); } |
| }; |
| |
| /// \brief Converts a const_iterator pair into an iterator pair |
| /// Useful for converting pair ranges returned by equal_range, for instance. |
| /// This is an extension, available in uSTL. |
| template <typename Container> |
| inline pair<typename Container::iterator, typename Container::iterator> |
| unconst (const pair<typename Container::const_iterator, typename Container::const_iterator>& i, Container& ctr) |
| { |
| assert (i.first >= ctr.begin() && i.first <= ctr.end() && "unconst algorithm must be given iterators from the argument container"); |
| pair<typename Container::iterator, typename Container::iterator> result; |
| result.first = ctr.begin() + (i.first - ctr.begin()); |
| result.second = ctr.begin() + (i.second - ctr.begin()); |
| return (result); |
| } |
| |
| //----{ vector }-------------------------------------------------------- |
| |
| STD_TEMPLATE_CTR_STREAMABLE (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) |
| |
| template <typename T> |
| inline size_t alignof (const vector<T>&) |
| { |
| typedef typename vector<T>::written_size_type written_size_type; |
| return (alignof (written_size_type())); |
| } |
| |
| //----{ bitset }-------------------------------------------------------- |
| |
| /// Reads bitset \p v from stream \p is. |
| template <size_t Size> |
| inline istream& operator>> (istream& is, bitset<Size>& v) |
| { |
| return (nr_container_read (is, v)); |
| } |
| |
| /// Writes bitset \p v into stream \p os. |
| template <size_t Size> |
| inline ostream& operator<< (ostream& os, const bitset<Size>& v) |
| { |
| return (nr_container_write (os, v)); |
| } |
| |
| /// Writes bitset \p v into stream \p os. |
| template <size_t Size> |
| inline ostringstream& operator<< (ostringstream& os, const bitset<Size>& v) |
| { |
| return (os << v.to_string()); |
| } |
| |
| /// Writes bitset \p v into stream \p os. |
| template <size_t Size> |
| istringstream& operator>> (istringstream& is, bitset<Size>& v) |
| { |
| char c; |
| for (int i = Size; --i >= 0 && (is >> c).good();) |
| v.set (i, c == '1'); |
| return (is); |
| } |
| |
| /// Returns the number of bytes necessary to write this object to a stream |
| template <size_t Size> |
| inline size_t stream_size_of (const bitset<Size>& v) |
| { |
| return (v.capacity() / CHAR_BIT); |
| } |
| |
| //----{ tuple }--------------------------------------------------------- |
| |
| STD_TEMPLATE_NR_CTR_STREAMABLE ( |
| TEMPLATE_TYPE2 (tuple,N,T), |
| TEMPLATE_FULL_DECL2 (size_t,N,typename,T) |
| ) |
| |
| template <size_t N, typename T> |
| struct numeric_limits<tuple<N,T> > { |
| typedef numeric_limits<T> value_limits; |
| static inline tuple<N,T> min (void) { tuple<N,T> v; fill (v, value_limits::min()); return (v); } |
| static inline tuple<N,T> max (void) { tuple<N,T> v; fill (v, value_limits::max()); return (v); } |
| static const bool is_signed = value_limits::is_signed; |
| static const bool is_integer = value_limits::is_integer; |
| static const bool is_integral = value_limits::is_integral; |
| }; |
| |
| template <size_t N, typename T> |
| inline size_t alignof (const tuple<N,T>&) { return (alignof (T())); } |
| |
| template <typename T, typename IntT> |
| inline ostringstream& chartype_text_write (ostringstream& os, const T& v) |
| { |
| if (isprint(v)) |
| os << '\'' << v << '\''; |
| else |
| os << (IntT)(v); |
| return (os); |
| } |
| |
| template <> |
| inline ostringstream& container_element_text_write (ostringstream& os, const uint8_t& v) |
| { return (chartype_text_write<uint8_t, unsigned int> (os, v)); } |
| template <> |
| inline ostringstream& container_element_text_write (ostringstream& os, const int8_t& v) |
| { return (chartype_text_write<int8_t, int> (os, v)); } |
| |
| //----{ matrix }-------------------------------------------------------- |
| |
| /// Writes tuple \p v into stream \p os. |
| template <size_t NX, size_t NY, typename T> |
| ostringstream& operator<< (ostringstream& os, const matrix<NX,NY,T>& v) |
| { |
| os << '('; |
| for (uoff_t row = 0; row < NY; ++ row) { |
| os << '('; |
| for (uoff_t column = 0; column < NX; ++ column) { |
| os << v[row][column]; |
| if (column < NX - 1) |
| os << ','; |
| } |
| os << ')'; |
| } |
| os << ')'; |
| return (os); |
| } |
| |
| //---------------------------------------------------------------------- |
| |
| #ifndef DOXYGEN_SHOULD_SKIP_THIS |
| #ifndef WITHOUT_LIBSTDCPP |
| |
| /// \todo Need a better solution to getting the hash value. |
| inline hashvalue_t hash_value (const string::const_pointer& v) |
| { |
| string::const_pointer first (v), last (v + strlen(v)); |
| hashvalue_t h = 0; |
| // This has the bits flowing into each other from both sides of the number |
| for (; first < last; ++ first) |
| h = *first + ((h << 7) | (h >> BitsInType(hashvalue_t) - 7)); |
| return (h); |
| } |
| |
| #endif |
| #endif |
| |
| //---------------------------------------------------------------------- |
| |
| } // namespace ustl |
| |
| // This is here because there really is no other place to put it. |
| #if SIZE_OF_BOOL != SIZE_OF_CHAR |
| // bool is a big type on some machines (like DEC Alpha), so it's written as a byte. |
| ALIGNOF(bool, sizeof(uint8_t)) |
| #endif |
| STD_STREAMABLE(cmemlink) |
| STD_STREAMABLE(istream) |
| STD_STREAMABLE(ostream) |
| STD_STREAMABLE(string) |
| STD_STREAMABLE(exception) |
| STD_STREAMABLE(CBacktrace) |
| TEXT_STREAMABLE(cmemlink) |
| TEXT_STREAMABLE(istream) |
| TEXT_STREAMABLE(ostream) |
| TEXT_STREAMABLE(exception) |
| TEXT_STREAMABLE(CBacktrace) |
| |
| #endif |
| |