]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/sstream.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / sstream.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/sstream.cpp
3// Purpose: string-based streams implementation
4// Author: Vadim Zeitlin
5// Modified by: Ryan Norton (UTF8 UNICODE)
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
35// ----------------------------------------------------------------------------
36// construction/destruction
37// ----------------------------------------------------------------------------
38
39// TODO: Do we want to include the null char in the stream? If so then
40// just add +1 to m_len in the ctor
41wxStringInputStream::wxStringInputStream(const wxString& s)
42#if wxUSE_UNICODE
43 // FIXME-UTF8: use wxCharBufferWithLength if we have it
44 : m_str(s), m_buf(s.utf8_str()), m_len(strlen(m_buf))
45#else
46 : m_str(s), m_buf(s.mb_str()), m_len(s.length())
47#endif
48{
49#if wxUSE_UNICODE
50 wxASSERT_MSG(m_buf.data() != NULL, wxT("Could not convert string to UTF8!"));
51#endif
52 m_pos = 0;
53}
54
55// ----------------------------------------------------------------------------
56// getlength
57// ----------------------------------------------------------------------------
58
59wxFileOffset wxStringInputStream::GetLength() const
60{
61 return m_len;
62}
63
64// ----------------------------------------------------------------------------
65// seek/tell
66// ----------------------------------------------------------------------------
67
68wxFileOffset wxStringInputStream::OnSysSeek(wxFileOffset ofs, wxSeekMode mode)
69{
70 switch ( mode )
71 {
72 case wxFromStart:
73 // nothing to do, ofs already ok
74 break;
75
76 case wxFromEnd:
77 ofs += m_len;
78 break;
79
80 case wxFromCurrent:
81 ofs += m_pos;
82 break;
83
84 default:
85 wxFAIL_MSG( wxT("invalid seek mode") );
86 return wxInvalidOffset;
87 }
88
89 if ( ofs < 0 || ofs > static_cast<wxFileOffset>(m_len) )
90 return wxInvalidOffset;
91
92 // FIXME: this can't be right
93 m_pos = wx_truncate_cast(size_t, ofs);
94
95 return ofs;
96}
97
98wxFileOffset wxStringInputStream::OnSysTell() const
99{
100 return static_cast<wxFileOffset>(m_pos);
101}
102
103// ----------------------------------------------------------------------------
104// actual IO
105// ----------------------------------------------------------------------------
106
107size_t wxStringInputStream::OnSysRead(void *buffer, size_t size)
108{
109 const size_t sizeMax = m_len - m_pos;
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
122 memcpy(buffer, m_buf.data() + m_pos, size);
123 m_pos += size;
124
125 return size;
126}
127
128// ============================================================================
129// wxStringOutputStream implementation
130// ============================================================================
131
132// ----------------------------------------------------------------------------
133// seek/tell
134// ----------------------------------------------------------------------------
135
136wxFileOffset wxStringOutputStream::OnSysTell() const
137{
138 return static_cast<wxFileOffset>(m_pos);
139}
140
141// ----------------------------------------------------------------------------
142// actual IO
143// ----------------------------------------------------------------------------
144
145size_t wxStringOutputStream::OnSysWrite(const void *buffer, size_t size)
146{
147 const char *p = static_cast<const char *>(buffer);
148
149#if wxUSE_UNICODE
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
170 size_t wlen;
171 wxWCharBuffer wbuf(m_conv.cMB2WC(src, srcLen, &wlen));
172 if ( wbuf )
173 {
174 // conversion succeeded, clear the unconverted buffer
175 m_unconv = wxMemoryBuffer(0);
176
177 m_str->append(wbuf, wlen);
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 }
191#else // !wxUSE_UNICODE
192 // no recoding necessary
193 m_str->append(p, size);
194#endif // wxUSE_UNICODE/!wxUSE_UNICODE
195
196 // update position
197 m_pos += size;
198
199 // return number of bytes actually written
200 return size;
201}
202
203#endif // wxUSE_STREAMS
204