1 // This file is part of the ustl library, an STL implementation.
3 // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
8 // Template specializations for uSTL classes.
11 #ifndef USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0
12 #define USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0
17 #include "umultiset.h"
21 #include "ufunction.h"
28 //----------------------------------------------------------------------
29 // Alogrithm specializations not in use by the library code.
30 //----------------------------------------------------------------------
32 template <> inline void swap (cmemlink
& a
, cmemlink
& b
) { a
.swap (b
); }
33 template <> inline void swap (memlink
& a
, memlink
& b
) { a
.swap (b
); }
34 template <> inline void swap (memblock
& a
, memblock
& b
) { a
.swap (b
); }
35 template <> inline void swap (string
& a
, string
& b
) { a
.swap (b
); }
36 #define TEMPLATE_SWAP_PSPEC(type, template_decl) \
37 template_decl inline void swap (type& a, type& b) { a.swap (b); }
38 TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (vector
,T
), TEMPLATE_DECL1 (T
))
39 TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (set
,T
), TEMPLATE_DECL1 (T
))
40 TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (multiset
,T
), TEMPLATE_DECL1 (T
))
41 TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE2 (tuple
,N
,T
), TEMPLATE_FULL_DECL2 (size_t,N
,typename
,T
))
43 //----------------------------------------------------------------------
44 // Streamable definitions. Not used in the library and require streams.
45 //----------------------------------------------------------------------
47 //----{ pair }----------------------------------------------------------
49 /// \brief Reads pair \p p from stream \p is.
50 template <typename T1
, typename T2
>
51 istream
& operator>> (istream
& is
, pair
<T1
,T2
>& p
)
54 is
.align (alignof(p
.second
));
56 is
.align (alignof(p
.first
));
60 /// Writes pair \p p to stream \p os.
61 template <typename T1
, typename T2
>
62 ostream
& operator<< (ostream
& os
, const pair
<T1
,T2
>& p
)
65 os
.align (alignof(p
.second
));
67 os
.align (alignof(p
.first
));
71 /// Writes pair \p p to stream \p os.
72 template <typename T1
, typename T2
>
73 ostringstream
& operator<< (ostringstream
& os
, const pair
<T1
,T2
>& p
)
75 os
<< '(' << p
.first
<< ',' << p
.second
<< ')';
79 /// Returns the written size of the object.
80 template <typename T1
, typename T2
>
81 struct object_stream_size
<pair
<T1
,T2
> > {
82 inline size_t operator()(const pair
<T1
,T2
>& v
) const
84 return (Align (stream_size_of(v
.first
), alignof(v
.second
)) +
85 Align (stream_size_of(v
.second
), alignof(v
.first
)));
89 /// \brief Takes a pair and returns pair.first
90 /// This is an extension, available in uSTL and the SGI STL.
91 template <typename Pair
> struct select1st
: public unary_function
<Pair
,typename
Pair::first_type
> {
92 typedef typename
Pair::first_type result_type
;
93 inline const result_type
& operator()(const Pair
& a
) const { return (a
.first
); }
94 inline result_type
& operator()(Pair
& a
) const { return (a
.first
); }
97 /// \brief Takes a pair and returns pair.second
98 /// This is an extension, available in uSTL and the SGI STL.
99 template <typename Pair
> struct select2nd
: public unary_function
<Pair
,typename
Pair::second_type
> {
100 typedef typename
Pair::second_type result_type
;
101 inline const result_type
& operator()(const Pair
& a
) const { return (a
.second
); }
102 inline result_type
& operator()(Pair
& a
) const { return (a
.second
); }
105 /// \brief Converts a const_iterator pair into an iterator pair
106 /// Useful for converting pair ranges returned by equal_range, for instance.
107 /// This is an extension, available in uSTL.
108 template <typename Container
>
109 inline pair
<typename
Container::iterator
, typename
Container::iterator
>
110 unconst (const pair
<typename
Container::const_iterator
, typename
Container::const_iterator
>& i
, Container
&)
112 typedef pair
<typename
Container::iterator
, typename
Container::iterator
> unconst_pair_t
;
113 return (*noalias_cast
<unconst_pair_t
*>(&i
));
116 //----{ vector }--------------------------------------------------------
118 template <typename T
>
119 inline size_t alignof (const vector
<T
>&)
121 typedef typename vector
<T
>::written_size_type written_size_type
;
122 return (alignof (written_size_type()));
125 //----{ bitset }--------------------------------------------------------
127 /// Writes bitset \p v into stream \p os.
128 template <size_t Size
>
129 istringstream
& operator>> (istringstream
& is
, bitset
<Size
>& v
)
132 for (int i
= Size
; --i
>= 0 && (is
>> c
).good();)
137 //----{ tuple }---------------------------------------------------------
139 template <size_t N
, typename T
>
140 inline istream
& operator>> (istream
& is
, tuple
<N
,T
>& v
)
141 { v
.read (is
); return (is
); }
142 template <size_t N
, typename T
>
143 inline ostream
& operator<< (ostream
& os
, const tuple
<N
,T
>& v
)
144 { v
.write (os
); return (os
); }
145 template <size_t N
, typename T
>
146 inline ostringstream
& operator<< (ostringstream
& os
, const tuple
<N
,T
>& v
)
147 { v
.text_write (os
); return (os
); }
149 template <size_t N
, typename T
>
150 struct numeric_limits
<tuple
<N
,T
> > {
151 typedef numeric_limits
<T
> value_limits
;
152 static inline tuple
<N
,T
> min (void) { tuple
<N
,T
> v
; fill (v
, value_limits::min()); return (v
); }
153 static inline tuple
<N
,T
> max (void) { tuple
<N
,T
> v
; fill (v
, value_limits::max()); return (v
); }
154 static const bool is_signed
= value_limits::is_signed
;
155 static const bool is_integer
= value_limits::is_integer
;
156 static const bool is_integral
= value_limits::is_integral
;
159 template <size_t N
, typename T
>
160 inline size_t alignof (const tuple
<N
,T
>&) { return (alignof (NullValue
<T
>())); }
162 template <typename T
, typename IntT
>
163 inline ostringstream
& chartype_text_write (ostringstream
& os
, const T
& v
)
165 os
.format (_FmtPrtChr
[!isprint(v
)], v
);
170 inline ostringstream
& container_element_text_write (ostringstream
& os
, const uint8_t& v
)
171 { return (chartype_text_write
<uint8_t, unsigned int> (os
, v
)); }
173 inline ostringstream
& container_element_text_write (ostringstream
& os
, const int8_t& v
)
174 { return (chartype_text_write
<int8_t, int> (os
, v
)); }
176 //----{ matrix }--------------------------------------------------------
178 /// Writes tuple \p v into stream \p os.
179 template <size_t NX
, size_t NY
, typename T
>
180 ostringstream
& operator<< (ostringstream
& os
, const matrix
<NX
,NY
,T
>& v
)
183 for (uoff_t row
= 0; row
< NY
; ++ row
) {
185 for (uoff_t column
= 0; column
< NX
; ++column
)
186 os
<< v
[row
][column
] << ",)"[column
== NX
-1];
192 //----{ long4grain }----------------------------------------------------
194 #if SIZE_OF_LONG == 8 && HAVE_INT64_T
195 // Helper class for long4grain and ptr4grain wrappers.
198 inline _long4grain (uint64_t v
) : m_v (v
) {}
200 inline void read (istream
& is
)
202 assert (is
.aligned(4));
203 #ifdef WANT_STREAM_BOUNDS_CHECKING
204 is
.verify_remaining ("read", "long4grain", sizeof(m_v
));
206 assert (is
.remaining() >= sizeof(m_v
));
208 m_v
= *reinterpret_cast<const uint64_t*>(is
.ipos());
209 is
.skip (sizeof(m_v
));
211 inline void write (ostream
& os
) const
213 assert (os
.aligned(4));
214 #ifdef WANT_STREAM_BOUNDS_CHECKING
215 os
.verify_remaining ("write", "long4grain", sizeof(m_v
));
217 assert (os
.remaining() >= sizeof(m_v
));
219 *reinterpret_cast<uint64_t*>(os
.ipos()) = m_v
;
220 os
.skip (sizeof(m_v
));
222 #elif USTL_BYTE_ORDER == USTL_BIG_ENDIAN
223 inline void read (istream
& is
) { uint32_t vl
, vh
; is
>> vh
>> vl
; m_v
= (uint64_t(vh
) << 32) | uint64_t(vl
); }
224 inline void write (ostream
& os
) const { os
<< uint32_t(m_v
>> 32) << uint32_t(m_v
); }
226 inline void read (istream
& is
) { uint32_t vl
, vh
; is
>> vl
>> vh
; m_v
= (uint64_t(vh
) << 32) | uint64_t(vl
); }
227 inline void write (ostream
& os
) const { os
<< uint32_t(m_v
) << uint32_t(m_v
>> 32); }
229 inline size_t stream_size (void) const { return (stream_size_of(m_v
)); }
234 /// Wrap long values to allow writing them on 4-grain even on 64bit platforms.
235 inline _long4grain
& long4grain (unsigned long& v
) { asm("":"+m"(v
)); return (*noalias_cast
<_long4grain
*>(&v
)); }
236 /// Wrap long values to allow writing them on 4-grain even on 64bit platforms.
237 inline const _long4grain
long4grain (const unsigned long& v
) { return (_long4grain(v
)); }
238 /// Wrap pointer values to allow writing them on 4-grain even on 64bit platforms.
239 template <typename T
>
240 inline _long4grain
& ptr4grain (T
*& p
) { asm("":"+m"(p
)); return (*noalias_cast
<_long4grain
*>(&p
)); }
241 /// Wrap pointer values to allow writing them on 4-grain even on 64bit platforms.
242 template <typename T
>
243 inline const _long4grain
ptr4grain (const T
* const& p
) { return (_long4grain(uintptr_t(p
))); }
244 #else // if not SIZE_OF_LONG == 8 && HAVE_INT64_T
245 inline unsigned long& long4grain (unsigned long& v
) { return (v
); }
246 inline const unsigned long& long4grain (const unsigned long& v
) { return (v
); }
247 template <typename T
> inline T
*& ptr4grain (T
*& p
) { return (p
); }
248 template <typename T
> inline const T
* const& ptr4grain (const T
* const& p
) { return (p
); }
249 #endif // SIZE_OF_LONG == 8
251 //----------------------------------------------------------------------
253 #ifndef DOXYGEN_SHOULD_SKIP_THIS
254 #ifndef WITHOUT_LIBSTDCPP
256 /// \todo Need a better solution to getting the hash value.
257 inline hashvalue_t
hash_value (const string::const_pointer
& v
)
259 string::const_pointer
first (v
), last (v
+ strlen(v
));
261 // This has the bits flowing into each other from both sides of the number
262 for (; first
< last
; ++ first
)
263 h
= *first
+ ((h
<< 7) | (h
>> BitsInType(hashvalue_t
) - 7));
270 //----------------------------------------------------------------------
274 // This is here because there really is no other place to put it.
275 #if SIZE_OF_BOOL != SIZE_OF_CHAR
276 // bool is a big type on some machines (like DEC Alpha), so it's written as a byte.
277 ALIGNOF(bool, sizeof(uint8_t))
278 CAST_STREAMABLE(bool, uint8_t)
280 #if SIZE_OF_LONG == 8 && HAVE_INT64_T
281 ALIGNOF (_long4grain
, 4)