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