]> git.saurik.com Git - wxWidgets.git/blame - src/common/execcmn.cpp
don't crash when streaming out a wxString into an std::ostream, just set the failbit...
[wxWidgets.git] / src / common / execcmn.cpp
CommitLineData
79066131
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: common/wxexec.cpp
3// Purpose: defines wxStreamTempInputBuffer which is used by Unix and MSW
4// implementations of wxExecute; this file is only used by the
5// library and never by the user code
6// Author: Vadim Zeitlin
7// Modified by:
8// Created: 20.08.02
9// RCS-ID: $Id$
10// Copyright: (c) 2002 Vadim Zeitlin <vadim@wxwindows.org>
65571936 11// Licence: wxWindows licence
79066131
VZ
12///////////////////////////////////////////////////////////////////////////////
13
14#ifndef _WX_WXEXEC_CPP_
15#define _WX_WXEXEC_CPP_
16
17// this file should never be compiled directly, just included by other code
18#ifndef _WX_USED_BY_WXEXECUTE_
29343d04 19 #error "You should never directly build this file!"
79066131
VZ
20#endif
21
22// ----------------------------------------------------------------------------
23// wxStreamTempInputBuffer
24// ----------------------------------------------------------------------------
25
26/*
27 wxStreamTempInputBuffer is a hack which we need to solve the problem of
28 executing a child process synchronously with IO redirecting: when we do
29 this, the child writes to a pipe we open to it but when the pipe buffer
30 (which has finite capacity, e.g. commonly just 4Kb) becomes full we have to
31 read data from it because the child blocks in its write() until then and if
32 it blocks we are never going to return from wxExecute() so we dead lock.
33
34 So here is the fix: we now read the output as soon as it appears into a temp
35 buffer (wxStreamTempInputBuffer object) and later just stuff it back into
36 the stream when the process terminates. See supporting code in wxExecute()
37 itself as well.
38
39 Note that this is horribly inefficient for large amounts of output (count
40 the number of times we copy the data around) and so a better API is badly
41 needed! However it's not easy to devise a way to do this keeping backwards
42 compatibility with the existing wxExecute(wxEXEC_SYNC)...
43*/
44
45class wxStreamTempInputBuffer
46{
47public:
48 wxStreamTempInputBuffer();
49
50 // call to associate a stream with this buffer, otherwise nothing happens
51 // at all
52 void Init(wxPipeInputStream *stream);
53
54 // check for input on our stream and cache it in our buffer if any
4d425dee
VZ
55 //
56 // return true if anything was done
57 bool Update();
79066131
VZ
58
59 ~wxStreamTempInputBuffer();
60
61private:
62 // the stream we're buffering, if NULL we don't do anything at all
63 wxPipeInputStream *m_stream;
64
65 // the buffer of size m_size (NULL if m_size == 0)
66 void *m_buffer;
67
68 // the size of the buffer
69 size_t m_size;
22f3361e
VZ
70
71 DECLARE_NO_COPY_CLASS(wxStreamTempInputBuffer)
79066131
VZ
72};
73
74inline wxStreamTempInputBuffer::wxStreamTempInputBuffer()
75{
76 m_stream = NULL;
77 m_buffer = NULL;
78 m_size = 0;
79}
80
81inline void wxStreamTempInputBuffer::Init(wxPipeInputStream *stream)
82{
83 m_stream = stream;
84}
85
2887179b 86inline
4d425dee 87bool wxStreamTempInputBuffer::Update()
79066131 88{
4d425dee
VZ
89 if ( !m_stream || !m_stream->CanRead() )
90 return false;
91
92 // realloc in blocks of 4Kb: this is the default (and minimal) buffer
93 // size of the Unix pipes so it should be the optimal step
94 //
95 // NB: don't use "static int" in this inline function, some compilers
96 // (e.g. IBM xlC) don't like it
97 enum { incSize = 4096 };
98
99 void *buf = realloc(m_buffer, m_size + incSize);
100 if ( !buf )
79066131 101 {
4d425dee
VZ
102 // don't read any more, we don't have enough memory to do it
103 m_stream = NULL;
79066131 104 }
4d425dee
VZ
105 else // got memory for the buffer
106 {
107 m_buffer = buf;
108 m_stream->Read((char *)m_buffer + m_size, incSize);
109 m_size += m_stream->LastRead();
110 }
111
112 return true;
79066131
VZ
113}
114
2887179b 115inline
79066131
VZ
116wxStreamTempInputBuffer::~wxStreamTempInputBuffer()
117{
118 if ( m_buffer )
119 {
120 m_stream->Ungetch(m_buffer, m_size);
121 free(m_buffer);
122 }
123}
124
79066131
VZ
125#endif // _WX_WXEXEC_CPP_
126