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