]> git.saurik.com Git - wxWidgets.git/blame - include/wx/private/streamtempinput.h
Fix wxPropertyGrid::GetPropertyRect when the last item is collapsed.
[wxWidgets.git] / include / wx / private / streamtempinput.h
CommitLineData
79066131 1///////////////////////////////////////////////////////////////////////////////
9b70925d 2// Name: wx/private/streamtempinput.h
79066131
VZ
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
9b70925d
VZ
7// Modified by: Rob Bresalier
8// Created: 2013-05-04
79066131 9// Copyright: (c) 2002 Vadim Zeitlin <vadim@wxwindows.org>
65571936 10// Licence: wxWindows licence
79066131
VZ
11///////////////////////////////////////////////////////////////////////////////
12
9b70925d
VZ
13#ifndef _WX_PRIVATE_STREAMTEMPINPUT_H
14#define _WX_PRIVATE_STREAMTEMPINPUT_H
79066131 15
9b70925d 16#include "wx/private/pipestream.h"
79066131
VZ
17
18// ----------------------------------------------------------------------------
19// wxStreamTempInputBuffer
20// ----------------------------------------------------------------------------
21
22/*
23 wxStreamTempInputBuffer is a hack which we need to solve the problem of
24 executing a child process synchronously with IO redirecting: when we do
25 this, the child writes to a pipe we open to it but when the pipe buffer
26 (which has finite capacity, e.g. commonly just 4Kb) becomes full we have to
27 read data from it because the child blocks in its write() until then and if
28 it blocks we are never going to return from wxExecute() so we dead lock.
29
30 So here is the fix: we now read the output as soon as it appears into a temp
31 buffer (wxStreamTempInputBuffer object) and later just stuff it back into
32 the stream when the process terminates. See supporting code in wxExecute()
33 itself as well.
34
35 Note that this is horribly inefficient for large amounts of output (count
36 the number of times we copy the data around) and so a better API is badly
37 needed! However it's not easy to devise a way to do this keeping backwards
38 compatibility with the existing wxExecute(wxEXEC_SYNC)...
39*/
79066131
VZ
40class wxStreamTempInputBuffer
41{
42public:
9b70925d
VZ
43 wxStreamTempInputBuffer()
44 {
45 m_stream = NULL;
46 m_buffer = NULL;
47 m_size = 0;
48 }
79066131
VZ
49
50 // call to associate a stream with this buffer, otherwise nothing happens
51 // at all
9b70925d
VZ
52 void Init(wxPipeInputStream *stream)
53 {
54 wxASSERT_MSG( !m_stream, wxS("Can only initialize once") );
55
56 m_stream = stream;
57 }
79066131
VZ
58
59 // check for input on our stream and cache it in our buffer if any
4d425dee
VZ
60 //
61 // return true if anything was done
9b70925d
VZ
62 bool Update()
63 {
64 if ( !m_stream || !m_stream->CanRead() )
65 return false;
66
67 // realloc in blocks of 4Kb: this is the default (and minimal) buffer
68 // size of the Unix pipes so it should be the optimal step
69 //
70 // NB: don't use "static int" in this inline function, some compilers
71 // (e.g. IBM xlC) don't like it
72 enum { incSize = 4096 };
73
74 void *buf = realloc(m_buffer, m_size + incSize);
75 if ( !buf )
76 return false;
77
78 m_buffer = buf;
79 m_stream->Read((char *)m_buffer + m_size, incSize);
80 m_size += m_stream->LastRead();
81
82 return true;
83 }
84
85 // check if can continue reading from the stream, this is used to disable
86 // the callback once we can't read anything more
87 bool Eof() const
88 {
89 // If we have no stream, always return true as we can't read any more.
90 return !m_stream || m_stream->Eof();
91 }
92
cda5c26a
VZ
93 // read everything remaining until the EOF, this should only be called once
94 // the child process terminates and we know that no more data is coming
95 bool ReadAll()
96 {
97 while ( !Eof() )
98 {
99 if ( !Update() )
100 return false;
101 }
102
103 return true;
104 }
105
9b70925d
VZ
106 // dtor puts the data buffered during this object lifetime into the
107 // associated stream
108 ~wxStreamTempInputBuffer()
109 {
110 if ( m_buffer )
111 {
112 m_stream->Ungetch(m_buffer, m_size);
113 free(m_buffer);
114 }
115 }
116
117 const void *GetBuffer() const { return m_buffer; }
79066131 118
9b70925d 119 size_t GetSize() const { return m_size; }
79066131
VZ
120
121private:
122 // the stream we're buffering, if NULL we don't do anything at all
123 wxPipeInputStream *m_stream;
124
125 // the buffer of size m_size (NULL if m_size == 0)
126 void *m_buffer;
127
128 // the size of the buffer
129 size_t m_size;
22f3361e 130
c0c133e1 131 wxDECLARE_NO_COPY_CLASS(wxStreamTempInputBuffer);
79066131
VZ
132};
133
9b70925d 134#endif // _WX_PRIVATE_STREAMTEMPINPUT_H