blob: 0b87a5462f6fc360b75e33ab6a09b86d2d7753fd [file] [log] [blame]
// 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