OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [language/] [cxx/] [ustl/] [current/] [include/] [ustl/] [mistream.h] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
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 MISTREAM_H_103AEF1F266C04AA1A817D38705983DA
7
#define MISTREAM_H_103AEF1F266C04AA1A817D38705983DA
8
 
9
#include "memlink.h"
10
#include "uexception.h"
11
#include "strmsize.h"
12
#include "utf8.h"
13
#include "uios.h"
14
#include "config.h"
15
#if WANT_STREAM_BOUNDS_CHECKING
16
    #include <typeinfo>
17
#endif
18
 
19
namespace ustl {
20
 
21
class ostream;
22
class memlink;
23
class string;
24
 
25
/// \class istream mistream.h ustl.h
26
/// \ingroup BinaryStreams
27
///
28
/// \brief Helper class to read packed binary streams.
29
/// 
30
/// This class contains a set of functions to read integral types from an
31
/// unstructured memory block. Unpacking binary file data can be done this
32
/// way, for instance. aligning the data is your responsibility, and can
33
/// be accomplished by proper ordering of reads and by calling the align()
34
/// function. Unaligned access is usually slower by orders of magnitude and,
35
/// on some architectures, such as PowerPC, can cause your program to crash.
36
/// Therefore, all read functions have asserts to check alignment.
37
/// Overreading the end of the stream will also cause a crash (an assert in
38
/// debug builds). Oh, and don't be intimidated by the size of the inlines
39
/// here. In the assembly code the compiler will usually chop everything down
40
/// to five instructions each.
41
/// 
42
/// Alignment rules for your objects:
43
///     - Assume your writes start off 4-byte aligned.
44
///     - After completion, \ref istream::align the stream to at least 4.
45
///     - If data portability between 32bit and 64bit platforms is important
46
///     (it often is not, in config files and the like), ensure you are always
47
///     using fixed-size types and are aligning to a fixed grain. Avoid writing
48
///     8-byte types, and if you do, manually align before doing so.
49
///     - Non-default alignment is allowed if you plan to frequently write this
50
///     object in array form and alignment would be costly. For example, an
51
///     array of uint16_t-sized objects may leave the stream uint16_t aligned
52
///     as long as you know about it and will default-align the stream after
53
///     writing the array (note: \ref vector will already do this for you)
54
/// 
55
/// Example code:
56
/// \code
57
///     memblock b;
58
///     b.read_file ("test.file");
59
///     ostream is (b);
60
///     is >> boolVar >> ios::talign<int>();
61
///     is >> intVar >> floatVar;
62
///     is.read (binaryData, binaryDataSize);
63
///     is.align();
64
/// \endcode
65
///
66
class istream : public cmemlink, public ios_base {
67
public:
68
    inline              istream (void);
69
    inline              istream (const void* p, streamsize n);
70
    inline explicit     istream (const cmemlink& source);
71
    explicit            istream (const ostream& source);
72
    inline iterator     end (void) const                        { return (cmemlink::end()); }
73
    inline void         link (const void* p, streamsize n)      { cmemlink::link (p, n); }
74
    inline void         link (const cmemlink& l)                { cmemlink::link (l.cdata(), l.readable_size()); }
75
    inline void         link (const void* f, const void* l)     { cmemlink::link (f, l); }
76
    inline void         relink (const void* p, streamsize n)    { cmemlink::relink (p, n); m_Pos = 0; }
77
    inline void         relink (const cmemlink& l)              { relink (l.cdata(), l.readable_size()); }
78
    virtual void        unlink (void) throw();
79
    inline virtual streamsize   underflow (streamsize = 1)      { return (remaining()); }
80
    inline uoff_t       pos (void) const        { return (m_Pos); }
81
    inline const_iterator ipos (void) const     { return (begin() + pos()); }
82
    inline streamsize   remaining (void) const  { return (size() - pos()); }
83
    inline void         seek (uoff_t newPos);
84
    inline void         iseek (const_iterator newPos);
85
    inline void         skip (streamsize nBytes);
86
    inline bool         aligned (streamsize grain = c_DefaultAlignment) const;
87
    inline bool         verify_remaining (const char* op, const char* type, streamsize n);
88
    inline streamsize   align_size (streamsize grain = c_DefaultAlignment) const;
89
    inline void         align (streamsize grain = c_DefaultAlignment);
90
    inline void         swap (istream& is);
91
    inline void         read (void* buffer, streamsize size);
92
    inline void         read (memlink& buf)     { read (buf.begin(), buf.writable_size()); }
93
    void                read_strz (string& str);
94
    streamsize          readsome (void* s, streamsize n);
95
    inline void         read (istream&)                 { }
96
    void                write (ostream& os) const;
97
    void                text_write (ostringstream& os) const;
98
    inline streamsize   stream_size (void) const        { return (remaining()); }
99
    template <typename T>
100
    inline void         iread (T& v);
101
    inline void         ungetc (void)           { seek (pos() - 1); }
102
    inline off_t        tellg (void) const      { return (pos()); }
103
    inline void         seekg (off_t p, seekdir d = beg);
104
private:
105
    streamoff           m_Pos;          ///< The current read position.
106
};
107
 
108
//----------------------------------------------------------------------
109
 
110
template <typename T, typename Stream>
111
inline streamsize required_stream_size (T, const Stream&) { return (1); }
112
template <typename T>
113
inline streamsize required_stream_size (T v, const istream&) { return (stream_size_of(v)); }
114
 
115
template <typename Stream>
116
inline bool stream_at_eof (const Stream& stm)   { return (stm.eof()); }
117
template <>
118
inline bool stream_at_eof (const istream&)      { return (false); }
119
 
120
/// \class istream_iterator
121
/// \ingroup BinaryStreamIterators
122
///
123
/// \brief An iterator over an istream to use with uSTL algorithms.
124
///
125
template <typename T, typename Stream = istream>
126
class istream_iterator {
127
public:
128
    typedef T                   value_type;
129
    typedef ptrdiff_t           difference_type;
130
    typedef const value_type*   pointer;
131
    typedef const value_type&   reference;
132
    typedef typename Stream::size_type  size_type;
133
public:
134
                                istream_iterator (void)         : m_pis (NULL), m_v() {}
135
    explicit                    istream_iterator (Stream& is)   : m_pis (&is), m_v() { Read(); }
136
                                istream_iterator (const istream_iterator& i)    : m_pis (i.m_pis), m_v (i.m_v) {}
137
    /// Reads and returns the next value.
138
    inline const T&             operator* (void)        { return (m_v); }
139
    inline istream_iterator&    operator++ (void)       { Read(); return (*this); }
140
    inline istream_iterator&    operator-- (void)       { m_pis->seek (m_pis->pos() - 2 * stream_size_of(m_v)); return (operator++()); }
141
    inline istream_iterator     operator++ (int)        { istream_iterator old (*this); operator++(); return (old); }
142
    inline istream_iterator     operator-- (int)        { istream_iterator old (*this); operator--(); return (old); }
143
    inline istream_iterator&    operator+= (streamsize n)       { while (n--) operator++(); return (*this); }
144
    inline istream_iterator&    operator-= (streamsize n)       { m_pis->seek (m_pis->pos() - (n + 1) * stream_size_of(m_v)); return (operator++()); }
145
    inline istream_iterator     operator- (streamoff n) const                   { istream_iterator result (*this); return (result -= n); }
146
    inline difference_type      operator- (const istream_iterator& i) const     { return (distance (i.m_pis->pos(), m_pis->pos()) / stream_size_of(m_v)); }
147
    inline bool                 operator== (const istream_iterator& i) const    { return ((!m_pis && !i.m_pis) || (m_pis && i.m_pis && m_pis->pos() == i.m_pis->pos())); }
148
    inline bool                 operator< (const istream_iterator& i) const     { return (!i.m_pis || (m_pis && m_pis->pos() < i.m_pis->pos())); }
149
private:
150
    void Read (void)
151
    {
152
        if (!m_pis)
153
            return;
154
        const streamsize rs (required_stream_size (m_v, *m_pis));
155
        if (m_pis->remaining() < rs && m_pis->underflow (rs) < rs) {
156
            m_pis = NULL;
157
            return;
158
        }
159
        *m_pis >> m_v;
160
        if (stream_at_eof (*m_pis))
161
            m_pis = NULL;
162
    }
163
private:
164
    Stream*     m_pis;          ///< The host stream.
165
    T           m_v;            ///< Last read value; cached to be returnable as a const reference.
166
};
167
 
168
//----------------------------------------------------------------------
169
 
170
/// \brief Constructs a stream attached to nothing.
171
/// A stream attached to nothing is not usable. Call Link() functions
172
/// inherited from cmemlink to attach to some memory block.
173
///
174
inline istream::istream (void)
175
: cmemlink (),
176
  m_Pos (0)
177
{
178
}
179
 
180
/// Attaches the stream to a block at \p p of size \p n.
181
inline istream::istream (const void* p, streamsize n)
182
: cmemlink (p, n),
183
  m_Pos (0)
184
{
185
}
186
 
187
/// Attaches to the block pointed to by \p source.
188
inline istream::istream (const cmemlink& source)
189
: cmemlink (source),
190
  m_Pos (0)
191
{
192
}
193
 
194
/// Checks that \p n bytes are available in the stream, or else throws.
195
inline bool istream::verify_remaining (const char* op, const char* type, streamsize n)
196
{
197
    const streamsize rem = remaining();
198
    bool enough = n <= rem;
199
    if (!enough) overrun (op, type, n, pos(), rem);
200
    return (enough);
201
}
202
 
203
/// Sets the current read position to \p newPos
204
inline void istream::seek (uoff_t newPos)
205
{
206
#if WANT_STREAM_BOUNDS_CHECKING
207
    if (newPos > size())
208
        USTL_THROW(stream_bounds_exception ("seekg", "byte", pos(), newPos - pos(), size()));
209
#else
210
    assert (newPos <= size());
211
#endif
212
    m_Pos = newPos;
213
}
214
 
215
/// Sets the current read position to \p newPos
216
inline void istream::iseek (const_iterator newPos)
217
{
218
    seek (distance (begin(), newPos));
219
}
220
 
221
/// Sets the current write position to \p p based on \p d.
222
inline void istream::seekg (off_t p, seekdir d)
223
{
224
    switch (d) {
225
        case beg:       seek (p); break;
226
        case cur:       seek (pos() + p); break;
227
        case ios_base::end:     seek (size() - p); break;
228
    }
229
}
230
 
231
/// Skips \p nBytes without reading them.
232
inline void istream::skip (streamsize nBytes)
233
{
234
    seek (pos() + nBytes);
235
}
236
 
237
/// Returns the number of bytes to skip to be aligned on \p grain.
238
inline streamsize istream::align_size (streamsize grain) const
239
{
240
    return (Align (pos(), grain) - pos());
241
}
242
 
243
/// Returns \c true if the read position is aligned on \p grain
244
inline bool istream::aligned (streamsize grain) const
245
{
246
    assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors.");
247
    return (pos() % grain == 0);
248
}
249
 
250
/// aligns the read position on \p grain
251
inline void istream::align (streamsize grain)
252
{
253
    seek (Align (pos(), grain));
254
}
255
 
256
/// Reads type T from the stream via a direct pointer cast.
257
template <typename T>
258
inline void istream::iread (T& v)
259
{
260
    assert (aligned (alignof (v)));
261
#if WANT_STREAM_BOUNDS_CHECKING
262
    if (!verify_remaining ("read", USTL_TYPENAME(v), sizeof(T)))
263
        return;
264
#else
265
    assert (remaining() >= sizeof(T));
266
#endif
267
    v = *reinterpret_cast<const T*>(ipos());
268
    m_Pos += sizeof(T);
269
}
270
 
271
/// Swaps contents with \p is
272
inline void istream::swap (istream& is)
273
{
274
    cmemlink::swap (is);
275
    ::ustl::swap (m_Pos, is.m_Pos);
276
}
277
 
278
/// Reads \p n bytes into \p buffer.
279
inline void istream::read (void* buffer, size_type n)
280
{
281
#if WANT_STREAM_BOUNDS_CHECKING
282
    if (!verify_remaining ("read", "binary data", n))
283
        return;
284
#else
285
    assert (remaining() >= n && "Reading past end of buffer. Make sure you are reading the right format.");
286
#endif
287
    memcpy (reinterpret_cast<value_type*>(buffer), ipos(), n);
288
    m_Pos += n;
289
}
290
 
291
//----------------------------------------------------------------------
292
 
293
template <typename T> struct object_reader {
294
    inline void operator()(istream& is, T& v) const { v.read (is); }
295
};
296
template <typename T> struct integral_object_reader {
297
    inline void operator()(istream& is, T& v) const { is.iread (v); }
298
};
299
template <typename T>
300
inline istream& operator>> (istream& is, T& v) {
301
    typedef typename tm::Select <numeric_limits<T>::is_integral,
302
        integral_object_reader<T>, object_reader<T> >::Result object_reader_t;
303
    object_reader_t()(is, v);
304
    return (is);
305
}
306
template <typename T>
307
inline istream& operator>> (istream& is, const T& v) { v.read (is); return (is); }
308
 
309
//----------------------------------------------------------------------
310
 
311
typedef istream_iterator<utf8subchar_t> istream_iterator_for_utf8;
312
typedef utf8in_iterator<istream_iterator_for_utf8> utf8istream_iterator;
313
 
314
/// Returns a UTF-8 adaptor reading from \p is.
315
inline utf8istream_iterator utf8in (istream& is)
316
{
317
    istream_iterator_for_utf8 si (is);
318
    return (utf8istream_iterator (si));
319
}
320
 
321
//----------------------------------------------------------------------
322
 
323
} // namespace ustl
324
 
325
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.