]> git.saurik.com Git - wxWidgets.git/blame - src/common/stdstream.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / stdstream.cpp
CommitLineData
72a7c559 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/common/stdstream.cpp
72a7c559
VZ
3// Purpose: Implementation of std::istream and std::ostream derived
4// wrappers for wxInputStream and wxOutputStream
5// Author: Jonathan Liu <net147@gmail.com>
6// Created: 2009-05-02
7// RCS-ID: $Id$
8// Copyright: (c) 2009 Jonathan Liu
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ==========================================================================
13// Declarations
14// ==========================================================================
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
e5805c0f 23#if wxUSE_STREAMS && wxUSE_STD_IOSTREAM
72a7c559
VZ
24
25#ifndef WX_PRECOMP
26#endif
27
28#include "wx/stdstream.h"
29
30#include <ios>
31#include <istream>
32#include <ostream>
33#include <streambuf>
34
35// ==========================================================================
36// Helpers
37// ==========================================================================
38
39namespace
40{
41
5c4f18cc 42bool
72a7c559
VZ
43IosSeekDirToWxSeekMode(std::ios_base::seekdir way,
44 wxSeekMode& seekMode)
45{
46 switch ( way )
47 {
48 case std::ios_base::beg:
49 seekMode = wxFromStart;
50 break;
51 case std::ios_base::cur:
52 seekMode = wxFromCurrent;
53 break;
54 case std::ios_base::end:
55 seekMode = wxFromEnd;
56 break;
57 default:
58 return false;
59 }
60
61 return true;
62}
63
64} // anonymous namespace
65
66// ==========================================================================
67// wxStdInputStreamBuffer
68// ==========================================================================
69
70wxStdInputStreamBuffer::wxStdInputStreamBuffer(wxInputStream& stream) :
71 m_stream(stream), m_lastChar(EOF)
72{
73}
74
75std::streambuf *
76wxStdInputStreamBuffer::setbuf(char *WXUNUSED(s),
77 std::streamsize WXUNUSED(n))
78{
79 return NULL;
80}
81
82std::streampos
83wxStdInputStreamBuffer::seekoff(std::streamoff off,
84 std::ios_base::seekdir way,
85 std::ios_base::openmode which)
86{
87 wxSeekMode seekMode;
88
89 if ( !IosSeekDirToWxSeekMode(way, seekMode) )
90 return -1;
91 if ( !(which & std::ios_base::in) )
92 return -1;
93
94 off_t newPos = m_stream.SeekI((off_t) off, seekMode);
95
96 if ( newPos != wxInvalidOffset )
97 return (std::streampos) newPos;
98 else
99 return -1;
100}
101
102std::streampos
103wxStdInputStreamBuffer::seekpos(std::streampos sp,
104 std::ios_base::openmode which)
105{
106 if ( !(which & std::ios_base::in) )
107 return -1;
108
109 off_t newPos = m_stream.SeekI((off_t) sp);
110
111 if ( newPos != wxInvalidOffset )
112 return (std::streampos) newPos;
113 else
114 return -1;
115}
116
117std::streamsize
118wxStdInputStreamBuffer::showmanyc()
119{
120 if ( m_stream.CanRead() && (off_t) m_stream.GetSize() > m_stream.TellI() )
121 return m_stream.GetSize() - m_stream.TellI();
122 else
123 return 0;
124}
125
126std::streamsize
127wxStdInputStreamBuffer::xsgetn(char *s, std::streamsize n)
128{
129 m_stream.Read((void *) s, (size_t) n);
130
131 std::streamsize read = m_stream.LastRead();
132
133 if ( read > 0 )
134 m_lastChar = (unsigned char) s[read - 1];
135
136 return read;
137}
138
139int
140wxStdInputStreamBuffer::underflow()
141{
142 int ch = m_stream.GetC();
143
144 if ( m_stream.LastRead() == 1 )
145 {
146 m_stream.Ungetch((char) ch);
147 return ch;
148 }
149 else
150 {
151 return EOF;
152 }
153}
154
155int
156wxStdInputStreamBuffer::uflow()
157{
158 int ch = m_stream.GetC();
159
160 if ( m_stream.LastRead() == 1 )
161 {
162 m_lastChar = ch;
163 return ch;
164 }
165 else
166 {
167 return EOF;
168 }
169}
170
171int
172wxStdInputStreamBuffer::pbackfail(int c)
173{
174 if ( c == EOF )
175 {
176 if ( m_lastChar == EOF )
177 return EOF;
178
179 c = m_lastChar;
180 m_lastChar = EOF;
181 }
182
183 return m_stream.Ungetch((char) c) ? c : EOF;
184}
185
72a7c559
VZ
186// ==========================================================================
187// wxStdOutputStreamBuffer
188// ==========================================================================
189
190wxStdOutputStreamBuffer::wxStdOutputStreamBuffer(wxOutputStream& stream) :
191 m_stream(stream)
192{
193}
194
195std::streambuf *
196wxStdOutputStreamBuffer::setbuf(char *WXUNUSED(s),
197 std::streamsize WXUNUSED(n))
198{
199 return NULL;
200}
201
202std::streampos
203wxStdOutputStreamBuffer::seekoff(std::streamoff off,
204 std::ios_base::seekdir way,
205 std::ios_base::openmode which)
206{
207 wxSeekMode seekMode;
208
209 if ( !IosSeekDirToWxSeekMode(way, seekMode) )
210 return -1;
211 if ( !(which & std::ios_base::out) )
212 return -1;
213
214 off_t newPos = m_stream.SeekO((off_t) off, seekMode);
215
216 if ( newPos != wxInvalidOffset )
217 return (std::streampos) newPos;
218 else
219 return -1;
220}
221
222std::streampos
223wxStdOutputStreamBuffer::seekpos(std::streampos sp,
224 std::ios_base::openmode which)
225{
226 if ( !(which & std::ios_base::out) )
227 return -1;
228
229 off_t newPos = m_stream.SeekO((off_t) sp);
230
231 if ( newPos != wxInvalidOffset )
232 return (std::streampos) newPos;
233 else
234 return -1;
235}
236
237std::streamsize
238wxStdOutputStreamBuffer::xsputn(const char *s,
239 std::streamsize n)
240{
241 m_stream.Write((const void *) s, (size_t) n);
242 return (std::streamsize) m_stream.LastWrite();
243}
244
245int
246wxStdOutputStreamBuffer::overflow(int c)
247{
248 m_stream.PutC(c);
249 return m_stream.IsOk() ? c : EOF;
250}
251
252// ==========================================================================
9dfe9a1a 253// wxStdInputStream and wxStdOutputStream
72a7c559
VZ
254// ==========================================================================
255
9dfe9a1a
VZ
256// FIXME-VC6: it is impossible to call basic_ios<char>::init() with this
257// compiler, it complains about invalid call to non-static member
258// function so use a suspicious (as it uses a pointer to not yet
259// constructed streambuf) but working workaround
260//
261// It also doesn't like using istream in the ctor initializer list
262// and we must spell it out as basic_istream<char>.
263#ifdef __VISUALC6__
264
265wxStdInputStream::wxStdInputStream(wxInputStream& stream)
266 : std::basic_istream<char, std::char_traits<char> >(&m_streamBuffer),
267 m_streamBuffer(stream)
268{
269}
270
271wxStdOutputStream::wxStdOutputStream(wxOutputStream& stream)
272 : std::basic_ostream<char, std::char_traits<char> >(&m_streamBuffer),
273 m_streamBuffer(stream)
274{
275}
276
277#else // !VC6
278
279wxStdInputStream::wxStdInputStream(wxInputStream& stream) :
280 std::istream(NULL), m_streamBuffer(stream)
281{
282 std::ios::init(&m_streamBuffer);
283}
284
72a7c559
VZ
285wxStdOutputStream::wxStdOutputStream(wxOutputStream& stream) :
286 std::ostream(NULL), m_streamBuffer(stream)
287{
288 std::ios::init(&m_streamBuffer);
289}
290
9dfe9a1a
VZ
291#endif // VC6/!VC6
292
e5805c0f 293#endif // wxUSE_STREAMS && wxUSE_STD_IOSTREAM