]> git.saurik.com Git - wxWidgets.git/blame - src/common/sstream.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / sstream.cpp
CommitLineData
121fa06a 1///////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/common/sstream.cpp
121fa06a
VZ
3// Purpose: string-based streams implementation
4// Author: Vadim Zeitlin
c5d99d7b 5// Modified by: Ryan Norton (UTF8 UNICODE)
121fa06a
VZ
6// Created: 2004-09-19
7// RCS-ID: $Id$
8// Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_STREAMS
28
29#include "wx/sstream.h"
30
31// ============================================================================
32// wxStringInputStream implementation
33// ============================================================================
34
c5d99d7b
RN
35// ----------------------------------------------------------------------------
36// construction/destruction
37// ----------------------------------------------------------------------------
38
cb28cc9e 39// TODO: Do we want to include the null char in the stream? If so then
03647350 40// just add +1 to m_len in the ctor
86501081 41wxStringInputStream::wxStringInputStream(const wxString& s)
c5d99d7b 42#if wxUSE_UNICODE
86501081
VS
43 // FIXME-UTF8: use wxCharBufferWithLength if we have it
44 : m_str(s), m_buf(s.utf8_str()), m_len(strlen(m_buf))
c5d99d7b 45#else
86501081 46 : m_str(s), m_buf(s.mb_str()), m_len(s.length())
c5d99d7b
RN
47#endif
48{
49#if wxUSE_UNICODE
9a83f860 50 wxASSERT_MSG(m_buf.data() != NULL, wxT("Could not convert string to UTF8!"));
c5d99d7b
RN
51#endif
52 m_pos = 0;
53}
54
c5d99d7b
RN
55// ----------------------------------------------------------------------------
56// getlength
57// ----------------------------------------------------------------------------
58
03647350
VZ
59wxFileOffset wxStringInputStream::GetLength() const
60{
61 return m_len;
c5d99d7b
RN
62}
63
121fa06a
VZ
64// ----------------------------------------------------------------------------
65// seek/tell
66// ----------------------------------------------------------------------------
67
4004775e 68wxFileOffset wxStringInputStream::OnSysSeek(wxFileOffset ofs, wxSeekMode mode)
121fa06a
VZ
69{
70 switch ( mode )
71 {
72 case wxFromStart:
73 // nothing to do, ofs already ok
74 break;
75
76 case wxFromEnd:
c5d99d7b 77 ofs += m_len;
121fa06a
VZ
78 break;
79
80 case wxFromCurrent:
81 ofs += m_pos;
82 break;
83
84 default:
9a83f860 85 wxFAIL_MSG( wxT("invalid seek mode") );
121fa06a
VZ
86 return wxInvalidOffset;
87 }
88
5c33522f 89 if ( ofs < 0 || ofs > static_cast<wxFileOffset>(m_len) )
5a4c7f71
VZ
90 return wxInvalidOffset;
91
c781c316
VZ
92 // FIXME: this can't be right
93 m_pos = wx_truncate_cast(size_t, ofs);
121fa06a
VZ
94
95 return ofs;
96}
97
4004775e 98wxFileOffset wxStringInputStream::OnSysTell() const
121fa06a 99{
5c33522f 100 return static_cast<wxFileOffset>(m_pos);
121fa06a
VZ
101}
102
103// ----------------------------------------------------------------------------
104// actual IO
105// ----------------------------------------------------------------------------
106
107size_t wxStringInputStream::OnSysRead(void *buffer, size_t size)
108{
c5d99d7b 109 const size_t sizeMax = m_len - m_pos;
121fa06a
VZ
110
111 if ( size >= sizeMax )
112 {
113 if ( sizeMax == 0 )
114 {
115 m_lasterror = wxSTREAM_EOF;
116 return 0;
117 }
118
119 size = sizeMax;
120 }
121
86501081 122 memcpy(buffer, m_buf.data() + m_pos, size);
121fa06a
VZ
123 m_pos += size;
124
125 return size;
126}
127
128// ============================================================================
129// wxStringOutputStream implementation
130// ============================================================================
131
a5ea75bc
VZ
132// ----------------------------------------------------------------------------
133// seek/tell
134// ----------------------------------------------------------------------------
135
4004775e 136wxFileOffset wxStringOutputStream::OnSysTell() const
a5ea75bc 137{
5c33522f 138 return static_cast<wxFileOffset>(m_pos);
a5ea75bc
VZ
139}
140
121fa06a
VZ
141// ----------------------------------------------------------------------------
142// actual IO
143// ----------------------------------------------------------------------------
144
145size_t wxStringOutputStream::OnSysWrite(const void *buffer, size_t size)
146{
5c33522f 147 const char *p = static_cast<const char *>(buffer);
121fa06a 148
ff8a5f3d 149#if wxUSE_UNICODE
2c17722e
VZ
150 // the part of the string we have here may be incomplete, i.e. it can stop
151 // in the middle of an UTF-8 character and so converting it would fail; if
152 // this is the case, accumulate the part which we failed to convert until
153 // we get the rest (and also take into account the part which we might have
154 // left unconverted before)
155 const char *src;
156 size_t srcLen;
157 if ( m_unconv.GetDataLen() )
158 {
159 // append the new data to the data remaining since the last time
160 m_unconv.AppendData(p, size);
161 src = m_unconv;
162 srcLen = m_unconv.GetDataLen();
163 }
164 else // no unconverted data left, avoid extra copy
165 {
166 src = p;
167 srcLen = size;
168 }
169
a7b9ab62
VZ
170 size_t wlen;
171 wxWCharBuffer wbuf(m_conv.cMB2WC(src, srcLen, &wlen));
2c17722e
VZ
172 if ( wbuf )
173 {
174 // conversion succeeded, clear the unconverted buffer
175 m_unconv = wxMemoryBuffer(0);
176
a7b9ab62 177 m_str->append(wbuf, wlen);
2c17722e
VZ
178 }
179 else // conversion failed
180 {
181 // remember unconverted data if there had been none before (otherwise
182 // we've already got it in the buffer)
183 if ( src == p )
184 m_unconv.AppendData(src, srcLen);
185
186 // pretend that we wrote the data anyhow, otherwise the caller would
187 // believe there was an error and this might not be the case, but do
188 // not update m_pos as m_str hasn't changed
189 return size;
190 }
ff8a5f3d
VZ
191#else // !wxUSE_UNICODE
192 // no recoding necessary
2c17722e 193 m_str->append(p, size);
ff8a5f3d 194#endif // wxUSE_UNICODE/!wxUSE_UNICODE
121fa06a 195
cb28cc9e 196 // update position
c5d99d7b 197 m_pos += size;
a5ea75bc 198
cb28cc9e 199 // return number of bytes actually written
c5d99d7b 200 return size;
121fa06a
VZ
201}
202
203#endif // wxUSE_STREAMS
204