1// This file is part of the ustl library, an STL implementation. 2// 3// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net> 4// This file is free software, distributed under the MIT License. 5// 6// uspecial.h 7// 8// Template specializations for uSTL classes. 9// 10 11#ifndef USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 12#define USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 13 14#include "uassert.h" 15#include "uvector.h" 16#include "ustring.h" 17#include "uset.h" 18#include "umultiset.h" 19#include "ubitset.h" 20#include "ulaalgo.h" 21#include "uctralgo.h" 22#include "ufunction.h" 23#include "uctrstrm.h" 24#include "sistream.h" 25#include <ctype.h> 26 27namespace ustl { 28 29//---------------------------------------------------------------------- 30// Alogrithm specializations not in use by the library code. 31//---------------------------------------------------------------------- 32 33template <> inline void swap (cmemlink& a, cmemlink& b) { a.swap (b); } 34template <> inline void swap (memlink& a, memlink& b) { a.swap (b); } 35template <> inline void swap (memblock& a, memblock& b) { a.swap (b); } 36template <> inline void swap (string& a, string& b) { a.swap (b); } 37#define TEMPLATE_SWAP_PSPEC(type, template_decl) \ 38template_decl inline void swap (type& a, type& b) { a.swap (b); } 39TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) 40TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (set,T), TEMPLATE_DECL1 (T)) 41TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (multiset,T), TEMPLATE_DECL1 (T)) 42TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE2 (tuple,N,T), TEMPLATE_FULL_DECL2 (size_t,N,typename,T)) 43 44//---------------------------------------------------------------------- 45// Streamable definitions. Not used in the library and require streams. 46//---------------------------------------------------------------------- 47 48//----{ pair }---------------------------------------------------------- 49 50/// \brief Reads pair \p p from stream \p is. 51template <typename T1, typename T2> 52istream& operator>> (istream& is, pair<T1,T2>& p) 53{ 54 is >> p.first; 55 is.align (alignof(T2())); 56 is >> p.second; 57 is.align (alignof(T1())); 58 return (is); 59} 60 61/// Writes pair \p p to stream \p os. 62template <typename T1, typename T2> 63ostream& operator<< (ostream& os, const pair<T1,T2>& p) 64{ 65 os << p.first; 66 os.align (alignof(T2())); 67 os << p.second; 68 os.align (alignof(T1())); 69 return (os); 70} 71 72/// Writes pair \p p to stream \p os. 73template <typename T1, typename T2> 74ostringstream& operator<< (ostringstream& os, const pair<T1,T2>& p) 75{ 76 os << '(' << p.first << ',' << p.second << ')'; 77 return (os); 78} 79 80/// Returns the written size of the object. 81template <typename T1, typename T2> 82inline size_t stream_size_of (const pair<T1,T2>& v) 83{ 84 return (Align (stream_size_of(v.first), alignof(T2())) + 85 Align (stream_size_of(v.second), alignof(T1()))); 86} 87 88/// \brief Takes a pair and returns pair.first 89/// This is an extension, available in uSTL and the SGI STL. 90template <typename Pair> struct select1st : public unary_function<Pair,typename Pair::first_type> { 91 typedef typename Pair::first_type result_type; 92 inline const result_type& operator()(const Pair& a) const { return (a.first); } 93 inline result_type& operator()(Pair& a) const { return (a.first); } 94}; 95 96/// \brief Takes a pair and returns pair.second 97/// This is an extension, available in uSTL and the SGI STL. 98template <typename Pair> struct select2nd : public unary_function<Pair,typename Pair::second_type> { 99 typedef typename Pair::second_type result_type; 100 inline const result_type& operator()(const Pair& a) const { return (a.second); } 101 inline result_type& operator()(Pair& a) const { return (a.second); } 102}; 103 104/// \brief Converts a const_iterator pair into an iterator pair 105/// Useful for converting pair ranges returned by equal_range, for instance. 106/// This is an extension, available in uSTL. 107template <typename Container> 108inline pair<typename Container::iterator, typename Container::iterator> 109unconst (const pair<typename Container::const_iterator, typename Container::const_iterator>& i, Container& ctr) 110{ 111 assert (i.first >= ctr.begin() && i.first <= ctr.end() && "unconst algorithm must be given iterators from the argument container"); 112 pair<typename Container::iterator, typename Container::iterator> result; 113 result.first = ctr.begin() + (i.first - ctr.begin()); 114 result.second = ctr.begin() + (i.second - ctr.begin()); 115 return (result); 116} 117 118//----{ vector }-------------------------------------------------------- 119 120STD_TEMPLATE_CTR_STREAMABLE (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) 121 122template <typename T> 123inline size_t alignof (const vector<T>&) 124{ 125 typedef typename vector<T>::written_size_type written_size_type; 126 return (alignof (written_size_type())); 127} 128 129//----{ bitset }-------------------------------------------------------- 130 131/// Reads bitset \p v from stream \p is. 132template <size_t Size> 133inline istream& operator>> (istream& is, bitset<Size>& v) 134{ 135 return (nr_container_read (is, v)); 136} 137 138/// Writes bitset \p v into stream \p os. 139template <size_t Size> 140inline ostream& operator<< (ostream& os, const bitset<Size>& v) 141{ 142 return (nr_container_write (os, v)); 143} 144 145/// Writes bitset \p v into stream \p os. 146template <size_t Size> 147inline ostringstream& operator<< (ostringstream& os, const bitset<Size>& v) 148{ 149 return (os << v.to_string()); 150} 151 152/// Writes bitset \p v into stream \p os. 153template <size_t Size> 154istringstream& operator>> (istringstream& is, bitset<Size>& v) 155{ 156 char c; 157 for (int i = Size; --i >= 0 && (is >> c).good();) 158 v.set (i, c == '1'); 159 return (is); 160} 161 162/// Returns the number of bytes necessary to write this object to a stream 163template <size_t Size> 164inline size_t stream_size_of (const bitset<Size>& v) 165{ 166 return (v.capacity() / CHAR_BIT); 167} 168 169//----{ tuple }--------------------------------------------------------- 170 171STD_TEMPLATE_NR_CTR_STREAMABLE ( 172 TEMPLATE_TYPE2 (tuple,N,T), 173 TEMPLATE_FULL_DECL2 (size_t,N,typename,T) 174) 175 176template <size_t N, typename T> 177struct numeric_limits<tuple<N,T> > { 178 typedef numeric_limits<T> value_limits; 179 static inline tuple<N,T> min (void) { tuple<N,T> v; fill (v, value_limits::min()); return (v); } 180 static inline tuple<N,T> max (void) { tuple<N,T> v; fill (v, value_limits::max()); return (v); } 181 static const bool is_signed = value_limits::is_signed; 182 static const bool is_integer = value_limits::is_integer; 183 static const bool is_integral = value_limits::is_integral; 184}; 185 186template <size_t N, typename T> 187inline size_t alignof (const tuple<N,T>&) { return (alignof (T())); } 188 189template <typename T, typename IntT> 190inline ostringstream& chartype_text_write (ostringstream& os, const T& v) 191{ 192 if (isprint(v)) 193 os << '\'' << v << '\''; 194 else 195 os << (IntT)(v); 196 return (os); 197} 198 199template <> 200inline ostringstream& container_element_text_write (ostringstream& os, const uint8_t& v) 201{ return (chartype_text_write<uint8_t, unsigned int> (os, v)); } 202template <> 203inline ostringstream& container_element_text_write (ostringstream& os, const int8_t& v) 204{ return (chartype_text_write<int8_t, int> (os, v)); } 205 206//----{ matrix }-------------------------------------------------------- 207 208/// Writes tuple \p v into stream \p os. 209template <size_t NX, size_t NY, typename T> 210ostringstream& operator<< (ostringstream& os, const matrix<NX,NY,T>& v) 211{ 212 os << '('; 213 for (uoff_t row = 0; row < NY; ++ row) { 214 os << '('; 215 for (uoff_t column = 0; column < NX; ++ column) { 216 os << v[row][column]; 217 if (column < NX - 1) 218 os << ','; 219 } 220 os << ')'; 221 } 222 os << ')'; 223 return (os); 224} 225 226//---------------------------------------------------------------------- 227 228#ifndef DOXYGEN_SHOULD_SKIP_THIS 229#ifndef WITHOUT_LIBSTDCPP 230 231/// \todo Need a better solution to getting the hash value. 232inline hashvalue_t hash_value (const string::const_pointer& v) 233{ 234 string::const_pointer first (v), last (v + strlen(v)); 235 hashvalue_t h = 0; 236 // This has the bits flowing into each other from both sides of the number 237 for (; first < last; ++ first) 238 h = *first + ((h << 7) | (h >> BitsInType(hashvalue_t) - 7)); 239 return (h); 240} 241 242#endif 243#endif 244 245//---------------------------------------------------------------------- 246 247} // namespace ustl 248 249// This is here because there really is no other place to put it. 250#if SIZE_OF_BOOL != SIZE_OF_CHAR 251// bool is a big type on some machines (like DEC Alpha), so it's written as a byte. 252ALIGNOF(bool, sizeof(uint8_t)) 253#endif 254STD_STREAMABLE(cmemlink) 255STD_STREAMABLE(istream) 256STD_STREAMABLE(ostream) 257STD_STREAMABLE(string) 258STD_STREAMABLE(exception) 259STD_STREAMABLE(CBacktrace) 260TEXT_STREAMABLE(cmemlink) 261TEXT_STREAMABLE(istream) 262TEXT_STREAMABLE(ostream) 263TEXT_STREAMABLE(exception) 264TEXT_STREAMABLE(CBacktrace) 265 266#endif 267 268