3 * Copyright (c) 1998 New Generation Software (NGS) Oy
5 * Author: Markku Rossi <mtr@ngs.fi>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/src/iostream.c,v $
33 * Types and definitions.
36 #define DEFAULT_BUFFER_SIZE 4096
47 stream
= js_calloc (NULL
, 1, sizeof (*stream
));
51 stream
->buflen
= DEFAULT_BUFFER_SIZE
;
52 stream
->buffer
= js_malloc (NULL
, stream
->buflen
);
53 if (stream
->buffer
== NULL
)
63 /* The `FILE *' stream. */
66 file_read (void *context
, unsigned char *buffer
, unsigned int todo
,
72 got
= fread (buffer
, 1, todo
, (FILE *) context
);
73 *error_return
= errno
;
80 file_write (void *context
, unsigned char *buffer
, unsigned int todo
,
86 wrote
= fwrite (buffer
, 1, todo
, (FILE *) context
);
87 *error_return
= errno
;
94 file_seek (void *context
, long offset
, int whence
)
96 return fseek ((FILE *) context
, offset
, whence
);
101 file_get_position (void *context
)
103 return ftell ((FILE *) context
);
108 file_get_length (void *context
)
110 FILE *fp
= (FILE *) context
;
114 /* Save current position. */
118 /* Seek to the end of the file. */
119 if (fseek (fp
, 0, SEEK_END
) >= 0)
125 if (fseek (fp
, cpos
, SEEK_SET
) < 0)
126 /* Couldn't revert the fp to the original position. */
136 file_close (void *context
)
138 fclose ((FILE *) context
);
143 js_iostream_file (FILE *fp
, int readp
, int writep
, int do_close
)
150 stream
= js_iostream_new ();
155 stream
->read
= file_read
;
157 stream
->write
= file_write
;
159 stream
->seek
= file_seek
;
160 stream
->get_position
= file_get_position
;
161 stream
->get_length
= file_get_length
;
164 stream
->close
= file_close
;
166 stream
->context
= fp
;
173 close_pipe (void *context
)
175 pclose ((FILE *) context
);
180 js_iostream_pipe (FILE *fp
, int readp
)
187 stream
= js_iostream_new ();
193 stream
->read
= file_read
;
195 stream
->write
= file_write
;
197 stream
->seek
= file_seek
;
198 stream
->get_position
= file_get_position
;
199 stream
->get_length
= file_get_length
;
200 stream
->close
= close_pipe
;
201 stream
->context
= fp
;
208 js_iostream_read (JSIOStream
*stream
, void *ptr
, size_t size
)
215 /* We have buffered output data. */
216 if (js_iostream_flush (stream
) == EOF
)
219 assert (stream
->writep
== 0);
224 /* First, take everything from the buffer. */
225 if (stream
->bufpos
< stream
->data_in_buf
)
227 got
= stream
->data_in_buf
- stream
->bufpos
;
232 memcpy (ptr
, stream
->buffer
+ stream
->bufpos
, got
);
234 stream
->bufpos
+= got
;
236 (unsigned char *) ptr
+= got
;
242 /* EOF seen, can't read more. */
245 js_iostream_fill_buffer (stream
);
254 js_iostream_write (JSIOStream
*stream
, void *ptr
, size_t size
)
259 if (stream
->write
== NULL
)
261 stream
->error
= EBADF
;
265 if (!stream
->writep
&& stream
->bufpos
< stream
->data_in_buf
)
268 * We have some buffered data in the stream => the actual stream
269 * position in stream->context is not in sync with stream->bufpos.
273 if ((*stream
->seek
) (stream
->context
, SEEK_CUR
,
274 stream
->bufpos
- stream
->data_in_buf
) < 0)
275 /* XXX Error value. */
279 stream
->data_in_buf
= 0;
284 space
= stream
->buflen
- stream
->data_in_buf
;
288 /* Append data to the buffer. */
289 memcpy (stream
->buffer
+ stream
->data_in_buf
, ptr
, space
);
290 stream
->data_in_buf
+= space
;
293 (unsigned char *) ptr
+= space
;
295 /* Now the buffer contains buffered write data. */
300 /* Still some data left. Must flush */
301 if (js_iostream_flush (stream
) == EOF
)
307 if (stream
->autoflush
&& stream
->writep
)
308 if (js_iostream_flush (stream
) == EOF
)
309 /* Failed. Just return something smaller than <size> */
310 return total
- stream
->data_in_buf
;
317 js_iostream_flush (JSIOStream
*stream
)
319 if (stream
== NULL
|| stream
->write
== NULL
|| !stream
->writep
)
323 assert (stream
->bufpos
== 0);
325 if (stream
->data_in_buf
> 0)
327 int to_write
= stream
->data_in_buf
;
329 stream
->data_in_buf
= 0;
330 if ((*stream
->write
) (stream
->context
, stream
->buffer
,
331 to_write
, &stream
->error
) < to_write
)
333 stream
->error
= errno
;
343 js_iostream_unget (JSIOStream
*stream
, int byte
)
347 /* We have buffered output data. */
348 if (js_iostream_flush (stream
) == EOF
)
351 assert (stream
->writep
== 0);
354 if (stream
->bufpos
> 0)
357 stream
->buffer
[--stream
->bufpos
] = byte
;
359 else if (stream
->data_in_buf
< stream
->buflen
)
362 memmove (stream
->buffer
+ 1, stream
->buffer
, stream
->data_in_buf
);
363 stream
->data_in_buf
++;
364 stream
->buffer
[0] = byte
;
368 /* Allocate a bigger buffer. */
369 unsigned char *new_buffer
= js_realloc (NULL
, stream
->buffer
,
371 if (new_buffer
== NULL
)
373 stream
->error
= errno
;
378 stream
->buffer
= new_buffer
;
382 /* Upon successful completion, we must return the byte. */
388 js_iostream_close (JSIOStream
*stream
)
395 if (js_iostream_flush (stream
) == EOF
)
399 (*stream
->close
) (stream
->context
);
401 js_free (stream
->buffer
);
409 js_iostream_seek (JSIOStream
*stream
, long offset
, int whence
)
413 if (js_iostream_flush (stream
) == EOF
)
416 result
= (*stream
->seek
) (stream
->context
, offset
, whence
);
418 /* Successful. Clear the eof flag. */
426 js_iostream_get_position (JSIOStream
*stream
)
430 /* Flush the possible buffered output. */
431 if (js_iostream_flush (stream
) == EOF
)
434 pos
= (*stream
->get_position
) (stream
->context
);
439 * The logical position if at <bufpos>, the context's idea is at
440 * <data_in_buf>. Adjust.
442 return pos
- (stream
->data_in_buf
- stream
->bufpos
);
447 js_iostream_get_length (JSIOStream
*stream
)
449 /* Flush the possible buffered output. */
450 if (js_iostream_flush (stream
) == EOF
)
453 return (*stream
->get_length
) (stream
->context
);
458 js_iostream_fill_buffer (JSIOStream
*stream
)
460 if (stream
->read
== NULL
)
466 stream
->data_in_buf
= (*stream
->read
) (stream
->context
, stream
->buffer
,
467 stream
->buflen
, &stream
->error
);
469 if (stream
->data_in_buf
== 0)