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 #ifndef MOSTREAM_H_24A8C5397E0848216573E5670930FC9A
9 #define MOSTREAM_H_24A8C5397E0848216573E5670930FC9A
12 #include "uexception.h"
15 #ifdef WANT_STREAM_BOUNDS_CHECKING
24 /// \class ostream mostream.h ustl.h
25 /// \ingroup BinaryStreams
27 /// \brief Helper class to write packed binary streams.
29 /// This class contains a set of functions to write integral types into an
30 /// unstructured memory block. Packing binary file data can be done this
31 /// way, for instance. aligning the data is your responsibility, and can
32 /// be accomplished by proper ordering of writes and by calling \ref ostream::align.
33 /// Unaligned access is usually slower by orders of magnitude and,
34 /// on some architectures, such as PowerPC, can cause your program to crash.
35 /// Therefore, all write functions have asserts to check alignment.
36 /// See \ref istream documentation for rules on designing your data format.
37 /// Overwriting 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.
46 /// os << boolVar << ios::talign<int>();
47 /// os << intVar << floatVar;
48 /// os.write (binaryData, binaryDataSize);
50 /// b.resize (os.pos());
51 /// b.write_file ("test.file");
54 class ostream
: public memlink
, public ios_base
{
57 ostream (void* p
, size_type n
);
58 explicit ostream (const memlink
& source
);
59 inline iterator
end (void) { return (memlink::end()); }
60 inline const_iterator
end (void) const { return (memlink::end()); }
61 inline void seek (uoff_t newPos
);
62 inline void iseek (const_iterator newPos
);
63 inline void skip (size_type nBytes
);
64 inline uoff_t
pos (void) const { return (m_Pos
); }
65 inline iterator
ipos (void) { return (begin() + pos()); }
66 inline const_iterator
ipos (void) const { return (begin() + pos()); }
67 inline size_type
remaining (void) const;
68 inline bool aligned (size_type grain
= c_DefaultAlignment
) const;
69 void verify_remaining (const char* op
, const char* type
, size_t n
) const;
70 inline size_type
align_size (size_type grain
= c_DefaultAlignment
) const;
71 void align (size_type grain
= c_DefaultAlignment
);
72 void write (const void* buffer
, size_type size
);
73 inline void write (const cmemlink
& buf
);
74 void write_strz (const char* str
);
75 void read (istream
& is
);
76 inline void write (ostream
& os
) const { os
.write (begin(), pos()); }
77 void text_write (ostringstream
& os
) const;
78 inline size_t stream_size (void) const { return (pos()); }
79 void insert (iterator start
, size_type size
);
80 void erase (iterator start
, size_type size
);
81 void swap (ostream
& os
);
83 inline void iwrite (const T
& v
);
84 inline virtual size_type
overflow (size_type
= 1){ return (remaining()); }
85 virtual void unlink (void) throw();
86 inline void link (void* p
, size_type n
) { memlink::link (p
, n
); }
87 inline void link (memlink
& l
) { memlink::link (l
.data(), l
.writable_size()); }
88 inline void link (void* f
, void* l
) { memlink::link (f
, l
); }
89 inline void relink (void* p
, size_type n
) { memlink::relink (p
, n
); m_Pos
= 0; }
90 inline void relink (memlink
& l
) { relink (l
.data(), l
.writable_size()); }
91 inline void seekp (off_t p
, seekdir d
= beg
);
92 inline off_t
tellp (void) const { return (pos()); }
94 inline void SetPos (uoff_t newPos
) { m_Pos
= newPos
; }
96 uoff_t m_Pos
; ///< Current write position.
99 //----------------------------------------------------------------------
101 /// \class ostream_iterator mostream.h ustl.h
102 /// \ingroup BinaryStreamIterators
104 /// \brief An iterator over an ostream to use with uSTL algorithms.
106 template <typename T
, typename Stream
= ostream
>
107 class ostream_iterator
{
109 typedef T value_type
;
110 typedef ptrdiff_t difference_type
;
111 typedef value_type
* pointer
;
112 typedef value_type
& reference
;
113 typedef ostream::size_type size_type
;
115 inline explicit ostream_iterator (Stream
& os
)
117 inline ostream_iterator (const ostream_iterator
& iter
)
118 : m_Os (iter
.m_Os
) {}
119 /// Writes \p v into the stream.
120 inline ostream_iterator
& operator= (const T
& v
)
121 { m_Os
<< v
; return (*this); }
122 inline ostream_iterator
& operator* (void) { return (*this); }
123 inline ostream_iterator
& operator++ (void) { return (*this); }
124 inline ostream_iterator
operator++ (int) { return (*this); }
125 inline ostream_iterator
& operator+= (size_type n
) { m_Os
.skip (n
); return (*this); }
126 inline bool operator== (const ostream_iterator
& i
) const
127 { return (m_Os
.pos() == i
.m_Os
.pos()); }
128 inline bool operator< (const ostream_iterator
& i
) const
129 { return (m_Os
.pos() < i
.m_Os
.pos()); }
134 //----------------------------------------------------------------------
136 typedef ostream_iterator
<utf8subchar_t
> ostream_iterator_for_utf8
;
137 typedef utf8out_iterator
<ostream_iterator_for_utf8
> utf8ostream_iterator
;
139 /// Returns a UTF-8 adaptor writing to \p os.
140 inline utf8ostream_iterator
utf8out (ostream
& os
)
142 ostream_iterator_for_utf8
si (os
);
143 return (utf8ostream_iterator (si
));
146 //----------------------------------------------------------------------
148 /// Move the write pointer to \p newPos
149 inline void ostream::seek (uoff_t newPos
)
151 #ifdef WANT_STREAM_BOUNDS_CHECKING
153 throw stream_bounds_exception ("seekp", "byte", pos(), newPos
- pos(), size());
155 assert (newPos
<= size());
160 /// Sets the current write position to \p newPos
161 inline void ostream::iseek (const_iterator newPos
)
163 seek (distance (begin(), const_cast<iterator
>(newPos
)));
166 /// Sets the current write position to \p p based on \p d.
167 inline void ostream::seekp (off_t p
, seekdir d
)
170 case beg
: seek (p
); break;
171 case cur
: seek (pos() + p
); break;
172 case ios_base::end
: seek (size() - p
); break;
176 /// Skips \p nBytes without writing anything.
177 inline void ostream::skip (size_type nBytes
)
179 seek (pos() + nBytes
);
182 /// Returns number of bytes remaining in the write buffer.
183 inline ostream::size_type
ostream::remaining (void) const
185 return (size() - pos());
188 /// Returns \c true if the write pointer is aligned on \p grain
189 inline bool ostream::aligned (size_type grain
) const
191 assert (uintptr_t(begin()) % grain
== 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors.");
192 return (pos() % grain
== 0);
195 /// Returns the number of bytes to skip to be aligned on \p grain.
196 inline ostream::size_type
ostream::align_size (size_type grain
) const
198 return (Align (pos(), grain
) - pos());
201 /// Writes the contents of \p buf into the stream as a raw dump.
202 inline void ostream::write (const cmemlink
& buf
)
204 write (buf
.begin(), buf
.size());
207 /// Writes type T into the stream via a direct pointer cast.
208 template <typename T
>
209 inline void ostream::iwrite (const T
& v
)
211 assert (aligned (alignof (v
)));
212 #ifdef WANT_STREAM_BOUNDS_CHECKING
213 verify_remaining ("write", typeid(v
).name(), sizeof(T
));
215 assert (remaining() >= sizeof(T
));
217 *reinterpret_cast<T
*>(ipos()) = v
;
218 SetPos (pos() + sizeof(T
));
221 //----------------------------------------------------------------------
223 template <typename T
> struct object_writer
{
224 inline void operator()(ostream
& os
, const T
& v
) const { v
.write (os
); }
226 template <typename T
> struct integral_object_writer
{
227 inline void operator()(ostream
& os
, const T
& v
) const { os
.iwrite (v
); }
229 template <typename T
>
230 inline ostream
& operator<< (ostream
& os
, const T
& v
) {
231 typedef typename
tm::Select
<numeric_limits
<T
>::is_integral
,
232 integral_object_writer
<T
>, object_writer
<T
> >::Result object_writer_t
;
233 object_writer_t()(os
, v
);
237 //----------------------------------------------------------------------