Add libwx-perl
[pkg-perl] / deb-src / libwx-perl / libwx-perl-0.96 / cpp / streams.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        cpp/streams.cpp
3 // Purpose:     implementation for streams.h
4 // Author:      Mattia Barbon
5 // Modified by:
6 // Created:     30/03/2001
7 // RCS-ID:      $Id: streams.cpp 2698 2009-12-13 11:08:53Z mbarbon $
8 // Copyright:   (c) 2001-2002, 2004, 2006-2007, 2009 Mattia Barbon
9 // Licence:     This program is free software; you can redistribute it and/or
10 //              modify it under the same terms as Perl itself
11 /////////////////////////////////////////////////////////////////////////////
12
13 #if WXPERL_W_VERSION_GE( 2, 5, 3 )
14 typedef wxFileOffset wxPliFileOffset;
15 #else
16 typedef off_t wxPliFileOffset;
17 #endif
18
19 // thread KO
20 const char sub_read[] = "sub { read $_[0], $_[1], $_[2] }";
21 const char sub_seek[] = "sub { seek $_[0], $_[1], $_[2]; tell $_[0] }";
22 const char sub_tell[] = "sub { tell $_[0] }";
23 const char sub_write[] = "sub { print { $_[0] } $_[1] }";
24 const char sub_length[] = "sub { eval { fileno( $_[0] ) && fileno( $_[0] ) >= 0 } ? ( stat $_[0] )[7] : -1 }";
25
26 SV* sg_read;
27 SV* sg_seek;
28 SV* sg_tell;
29 SV* sg_write;
30 SV* sg_length;
31
32 class wxPliStreamInitializer
33 {
34 public:
35     wxPliStreamInitializer()
36     {
37         dTHX;
38         sg_read = eval_pv( CHAR_P sub_read, 1 );
39         sg_seek = eval_pv( CHAR_P sub_seek, 1 );
40         sg_tell = eval_pv( CHAR_P sub_tell, 1 );
41         sg_write = eval_pv( CHAR_P sub_write, 1 );
42         sg_length = eval_pv( CHAR_P sub_length, 1 );
43         SvREFCNT_inc( sg_read );
44         SvREFCNT_inc( sg_seek );
45         SvREFCNT_inc( sg_tell );
46         SvREFCNT_inc( sg_write );
47         SvREFCNT_inc( sg_length );
48     }
49
50     ~wxPliStreamInitializer()
51     {
52         // SvREFCNT_dec( sg_read );
53         // SvREFCNT_dec( sg_seek );
54         // SvREFCNT_dec( sg_tell );
55         // SvREFCNT_dec( sg_write );
56     }
57 };
58
59 wxPliStreamInitializer dummy;
60
61 // helpers
62
63 wxPliFileOffset stream_seek( wxStreamBase* stream, SV* fh, wxPliFileOffset seek, wxSeekMode mode );
64 wxPliFileOffset stream_tell( const wxStreamBase* stream, SV* fh );
65 wxPliFileOffset stream_length( const wxStreamBase* stream, SV* fh );
66
67 // input stream
68
69 wxPliInputStream* wxPliInputStream_ctor( SV* sv )
70 {
71     return new wxPliInputStream( sv );
72 }
73
74 wxPliOutputStream* wxPliOutputStream_ctor( SV* sv )
75 {
76     return new wxPliOutputStream( sv );
77 }
78
79 wxPliInputStream::wxPliInputStream( SV* fh )
80     :m_fh( fh )
81 {
82     dTHX;
83     SvREFCNT_inc( m_fh );
84 }
85
86 wxPliInputStream::wxPliInputStream( const wxPliInputStream& stream )
87     :m_fh( stream.m_fh )
88 {
89     dTHX;
90     SvREFCNT_inc( m_fh );
91 }
92
93 const wxPliInputStream& wxPliInputStream::operator =
94     ( const wxPliInputStream& stream )
95 {
96     dTHX;
97     if( m_fh ) SvREFCNT_dec( m_fh );
98     m_fh = stream.m_fh;
99     SvREFCNT_inc( m_fh );
100
101     return *this;
102 }
103
104 wxPliInputStream::~wxPliInputStream()
105 {
106     dTHX;
107     SvREFCNT_dec( m_fh );
108 }
109
110 size_t wxPliInputStream::OnSysRead( void* buffer, size_t size )
111 {
112     //FIXME// need a ( safe ) way to: create an SV, set ( NOT copy )
113     //FIXME// buffer into it, then call sg_read
114
115     dTHX;
116     dSP;
117
118     ENTER;
119     SAVETMPS;
120
121     SV* target = sv_2mortal( newSVsv( &PL_sv_undef ) );
122
123     PUSHMARK( SP );
124     XPUSHs( m_fh );
125     XPUSHs( target );
126     XPUSHs( sv_2mortal( newSVuv( size ) ) );
127     PUTBACK;
128
129     call_sv( sg_read, G_SCALAR );
130
131     SPAGAIN;
132
133     SV* sv_read_count = POPs;
134     size_t read_count = 0;
135
136     m_lasterror = wxSTREAM_NO_ERROR;
137     if( !SvOK( sv_read_count ) )
138         m_lasterror = wxSTREAM_READ_ERROR;
139     else 
140     {
141         read_count = SvOK( target ) ? SvUV( sv_read_count ) : 0;
142         if( !read_count )
143             m_lasterror = wxSTREAM_EOF;
144     }
145
146     PUTBACK;
147
148     if( read_count )
149         memcpy( buffer, SvPV_nolen( target ), read_count );
150
151     FREETMPS;
152     LEAVE;
153
154     return read_count;
155 }
156
157 wxPliFileOffset wxPliInputStream::OnSysSeek( wxPliFileOffset seek, wxSeekMode mode )
158 {
159     return stream_seek( this, m_fh, seek, mode );
160 }
161
162 wxPliFileOffset wxPliInputStream::OnSysTell() const
163 {
164     return stream_tell( this, m_fh );
165 }
166
167 wxFileOffset wxPliInputStream::GetLength() const
168 {
169     return stream_length( this, m_fh );
170 }
171
172 size_t wxPliInputStream::GetSize() const
173 {
174     return stream_length( this, m_fh );
175 }
176
177 // output stream
178
179 wxPliOutputStream::wxPliOutputStream( SV* fh )
180     :m_fh( fh )
181 {
182     dTHX;
183     SvREFCNT_inc( m_fh );
184 }
185
186 wxPliOutputStream::wxPliOutputStream( const wxPliOutputStream& stream )
187     :m_fh( stream.m_fh )
188 {
189     dTHX;
190     SvREFCNT_inc( m_fh );
191 }
192
193 const wxPliOutputStream& wxPliOutputStream::operator =
194     ( const wxPliOutputStream& stream )
195 {
196     dTHX;
197     if( m_fh ) SvREFCNT_dec( m_fh );
198     m_fh = stream.m_fh;
199     SvREFCNT_inc( m_fh );
200
201     return *this;
202 }
203
204 wxPliOutputStream::~wxPliOutputStream()
205 {
206     dTHX;
207     SvREFCNT_dec( m_fh );
208 }
209
210 size_t wxPliOutputStream::OnSysWrite( const void* buffer, size_t size )
211 {
212     //FIXME// need a ( safe ) way to: create an SV, set ( NOT copy )
213     //FIXME// buffer into it, then call sg_write
214
215     // printf( "OnSysWrite: %x %d = ", buffer, size );
216
217     dTHX;
218     dSP;
219
220     ENTER;
221     SAVETMPS;
222
223     SV* target = sv_2mortal( newSVpvn( CHAR_P ( const char*)buffer, size ) );
224
225     PUSHMARK( SP );
226     XPUSHs( m_fh );
227     XPUSHs( target );
228     XPUSHs( sv_2mortal( newSVuv( size ) ) );
229     PUTBACK;
230
231     call_sv( sg_write, G_SCALAR );
232
233     SPAGAIN;
234
235     SV* sv_write_count = POPs;
236     size_t write_count = 0;
237
238     m_lasterror = wxSTREAM_NO_ERROR;
239     if( !SvOK( sv_write_count ) )
240         m_lasterror = wxSTREAM_WRITE_ERROR;
241     else
242     {
243         write_count = SvUV( sv_write_count );
244     }
245
246     PUTBACK;
247
248     FREETMPS;
249     LEAVE;
250
251     // printf( "%d\n", write_count );fflush( stdout );
252     // OnSysSeek( 0, wxFromCurrent );
253
254     return write_count;
255 }
256
257 wxPliFileOffset wxPliOutputStream::OnSysSeek( wxPliFileOffset seek, wxSeekMode mode )
258 {
259     return stream_seek( this, m_fh, seek, mode );
260 }
261
262 wxPliFileOffset wxPliOutputStream::OnSysTell() const
263 {
264     return stream_tell( this, m_fh );
265 }
266
267 wxFileOffset wxPliOutputStream::GetLength() const
268 {
269     return stream_length( this, m_fh );
270 }
271
272 size_t wxPliOutputStream::GetSize() const
273 {
274     return stream_length( this, m_fh );
275 }
276
277 // helpers
278
279 wxPliFileOffset stream_seek( wxStreamBase* stream, SV* fh, wxPliFileOffset seek, wxSeekMode mode )
280 {
281     IV pl_act;
282
283     switch( mode )
284     {
285     case wxFromStart:
286         pl_act = 0;
287         break;
288     case wxFromCurrent:
289         pl_act = 1;
290         break;
291     case wxFromEnd:
292         pl_act = 2;
293         break;
294     default:
295         return -1;
296     }
297
298     dTHX;
299     dSP;
300
301     ENTER;
302     SAVETMPS;
303
304     PUSHMARK( SP );
305     XPUSHs( fh );
306     XPUSHs( sv_2mortal( newSViv( seek ) ) );
307     XPUSHs( sv_2mortal( newSViv( pl_act ) ) );
308     PUTBACK;
309
310     call_sv( sg_seek, G_SCALAR );
311
312     SPAGAIN;
313     IV ret = POPi;
314     PUTBACK;
315
316     FREETMPS;
317     LEAVE;
318
319     return ret;
320 }
321
322 wxPliFileOffset stream_tell( const wxStreamBase* stream, SV* fh )
323 {
324     dTHX;
325     dSP;
326
327     ENTER;
328     SAVETMPS;
329
330     PUSHMARK( SP );
331     XPUSHs( fh );
332     PUTBACK;
333
334     call_sv( sg_tell, G_SCALAR );
335
336     SPAGAIN;
337     IV ret = POPi;
338     PUTBACK;
339
340     FREETMPS;
341     LEAVE;
342
343     return ret;
344 }
345
346 wxPliFileOffset stream_length( const wxStreamBase* stream, SV* fh )
347 {
348     dTHX;
349     dSP;
350
351     ENTER;
352     SAVETMPS;
353
354     PUSHMARK( SP );
355     XPUSHs( fh );
356     PUTBACK;
357
358     call_sv( sg_length, G_SCALAR );
359
360     SPAGAIN;
361     IV ret = POPi;
362     PUTBACK;
363
364     FREETMPS;
365     LEAVE;
366
367     return ret == -1 ? ~0 : ret;
368 }