2 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
4 * Copyright (c) 2001-2003 Michael David Adams.
8 /* __START_OF_JASPER_LICENSE__
10 * JasPer License Version 2.0
12 * Copyright (c) 2001-2006 Michael David Adams
13 * Copyright (c) 1999-2000 Image Power, Inc.
14 * Copyright (c) 1999-2000 The University of British Columbia
16 * All rights reserved.
18 * Permission is hereby granted, free of charge, to any person (the
19 * "User") obtaining a copy of this software and associated documentation
20 * files (the "Software"), to deal in the Software without restriction,
21 * including without limitation the rights to use, copy, modify, merge,
22 * publish, distribute, and/or sell copies of the Software, and to permit
23 * persons to whom the Software is furnished to do so, subject to the
24 * following conditions:
26 * 1. The above copyright notices and this permission notice (which
27 * includes the disclaimer below) shall be included in all copies or
28 * substantial portions of the Software.
30 * 2. The name of a copyright holder shall not be used to endorse or
31 * promote products derived from the Software without specific prior
34 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
35 * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
36 * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
37 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
39 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
40 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
41 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
42 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
43 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
44 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
45 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
46 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
47 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
48 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
49 * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
50 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
51 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
52 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
53 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
54 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
55 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
56 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
57 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
58 * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
59 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
61 * __END_OF_JASPER_LICENSE__
67 * $Id: jas_stream.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
70 /******************************************************************************\
72 \******************************************************************************/
75 #if defined(HAVE_FCNTL_H)
82 #if defined(HAVE_UNISTD_H)
85 #if defined(WIN32) || defined(HAVE_IO_H)
89 #include "jasper/jas_types.h"
90 #include "jasper/jas_stream.h"
91 #include "jasper/jas_malloc.h"
92 #include "jasper/jas_math.h"
94 /******************************************************************************\
95 * Local function prototypes.
96 \******************************************************************************/
98 static int jas_strtoopenmode(const char *s);
99 static void jas_stream_destroy(jas_stream_t *stream);
100 static jas_stream_t *jas_stream_create(void);
101 static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
104 static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt);
105 static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt);
106 static long mem_seek(jas_stream_obj_t *obj, long offset, int origin);
107 static int mem_close(jas_stream_obj_t *obj);
109 static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt);
110 static int sfile_write(jas_stream_obj_t *obj, char *buf, int cnt);
111 static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin);
112 static int sfile_close(jas_stream_obj_t *obj);
114 static int file_read(jas_stream_obj_t *obj, char *buf, int cnt);
115 static int file_write(jas_stream_obj_t *obj, char *buf, int cnt);
116 static long file_seek(jas_stream_obj_t *obj, long offset, int origin);
117 static int file_close(jas_stream_obj_t *obj);
119 /******************************************************************************\
121 \******************************************************************************/
123 static jas_stream_ops_t jas_stream_fileops = {
130 static jas_stream_ops_t jas_stream_sfileops = {
137 static jas_stream_ops_t jas_stream_memops = {
144 /******************************************************************************\
145 * Code for opening and closing streams.
146 \******************************************************************************/
148 static jas_stream_t *jas_stream_create()
150 jas_stream_t *stream;
152 if (!(stream = jas_malloc(sizeof(jas_stream_t)))) {
155 stream->openmode_ = 0;
156 stream->bufmode_ = 0;
158 stream->bufbase_ = 0;
159 stream->bufstart_ = 0;
160 stream->bufsize_ = 0;
166 stream->rwlimit_ = -1;
171 jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
173 jas_stream_t *stream;
174 jas_stream_memobj_t *obj;
176 if (!(stream = jas_stream_create())) {
180 /* A stream associated with a memory buffer is always opened
181 for both reading and writing in binary mode. */
182 stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
184 /* Since the stream data is already resident in memory, buffering
186 /* But... It still may be faster to use buffering anyways. */
187 jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
189 /* Select the operations for a memory stream. */
190 stream->ops_ = &jas_stream_memops;
192 /* Allocate memory for the underlying memory stream object. */
193 if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) {
194 jas_stream_destroy(stream);
197 stream->obj_ = (void *) obj;
199 /* Initialize a few important members of the memory stream object. */
203 /* If the buffer size specified is nonpositive, then the buffer
204 is allocated internally and automatically grown as needed. */
206 obj->bufsize_ = 1024;
209 obj->bufsize_ = bufsize;
213 obj->buf_ = (unsigned char *) buf;
215 obj->buf_ = jas_malloc(obj->bufsize_);
219 jas_stream_close(stream);
223 if (bufsize > 0 && buf) {
224 /* If a buffer was supplied by the caller and its length is positive,
225 make the associated buffer data appear in the stream initially. */
228 /* The stream is initially empty. */
236 jas_stream_t *jas_stream_fopen(const char *filename, const char *mode)
238 jas_stream_t *stream;
239 jas_stream_fileobj_t *obj;
242 /* Allocate a stream object. */
243 if (!(stream = jas_stream_create())) {
247 /* Parse the mode string. */
248 stream->openmode_ = jas_strtoopenmode(mode);
250 /* Determine the correct flags to use for opening the file. */
251 if ((stream->openmode_ & JAS_STREAM_READ) &&
252 (stream->openmode_ & JAS_STREAM_WRITE)) {
254 } else if (stream->openmode_ & JAS_STREAM_READ) {
255 openflags = O_RDONLY;
256 } else if (stream->openmode_ & JAS_STREAM_WRITE) {
257 openflags = O_WRONLY;
261 if (stream->openmode_ & JAS_STREAM_APPEND) {
262 openflags |= O_APPEND;
264 if (stream->openmode_ & JAS_STREAM_BINARY) {
265 openflags |= O_BINARY;
267 if (stream->openmode_ & JAS_STREAM_CREATE) {
268 openflags |= O_CREAT | O_TRUNC;
271 /* Allocate space for the underlying file stream object. */
272 if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
273 jas_stream_destroy(stream);
278 obj->pathname[0] = '\0';
279 stream->obj_ = (void *) obj;
281 /* Select the operations for a file stream object. */
282 stream->ops_ = &jas_stream_fileops;
284 /* Open the underlying file. */
285 if ((obj->fd = open(filename, openflags, JAS_STREAM_PERMS)) < 0) {
286 jas_stream_destroy(stream);
290 /* By default, use full buffering for this type of stream. */
291 jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
296 jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp)
298 jas_stream_t *stream;
301 /* Eliminate compiler warning about unused variable. */
304 /* Allocate a stream object. */
305 if (!(stream = jas_stream_create())) {
309 /* Parse the mode string. */
310 stream->openmode_ = jas_strtoopenmode(mode);
312 /* Determine the correct flags to use for opening the file. */
313 if ((stream->openmode_ & JAS_STREAM_READ) &&
314 (stream->openmode_ & JAS_STREAM_WRITE)) {
316 } else if (stream->openmode_ & JAS_STREAM_READ) {
317 openflags = O_RDONLY;
318 } else if (stream->openmode_ & JAS_STREAM_WRITE) {
319 openflags = O_WRONLY;
323 if (stream->openmode_ & JAS_STREAM_APPEND) {
324 openflags |= O_APPEND;
326 if (stream->openmode_ & JAS_STREAM_BINARY) {
327 openflags |= O_BINARY;
329 if (stream->openmode_ & JAS_STREAM_CREATE) {
330 openflags |= O_CREAT | O_TRUNC;
333 stream->obj_ = JAS_CAST(void *, fp);
335 /* Select the operations for a file stream object. */
336 stream->ops_ = &jas_stream_sfileops;
338 /* By default, use full buffering for this type of stream. */
339 jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
344 jas_stream_t *jas_stream_tmpfile()
346 jas_stream_t *stream;
347 jas_stream_fileobj_t *obj;
349 if (!(stream = jas_stream_create())) {
353 /* A temporary file stream is always opened for both reading and
354 writing in binary mode. */
355 stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
357 /* Allocate memory for the underlying temporary file object. */
358 if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
359 jas_stream_destroy(stream);
367 /* Choose a file name. */
368 tmpnam(obj->pathname);
370 /* Open the underlying file. */
371 if ((obj->fd = open(obj->pathname, O_CREAT | O_EXCL | O_RDWR | O_TRUNC | O_BINARY,
372 JAS_STREAM_PERMS)) < 0) {
373 jas_stream_destroy(stream);
377 /* Choose a file name. */
378 snprintf(obj->pathname, L_tmpnam, "%s/tmp.XXXXXXXXXX", P_tmpdir);
380 /* Open the underlying file. */
381 if ((obj->fd = mkstemp(obj->pathname)) < 0) {
382 jas_stream_destroy(stream);
387 /* Unlink the file so that it will disappear if the program
388 terminates abnormally. */
389 if (unlink(obj->pathname)) {
390 jas_stream_destroy(stream);
394 /* Use full buffering. */
395 jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
397 stream->ops_ = &jas_stream_fileops;
402 jas_stream_t *jas_stream_fdopen(int fd, const char *mode)
404 jas_stream_t *stream;
405 jas_stream_fileobj_t *obj;
407 /* Allocate a stream object. */
408 if (!(stream = jas_stream_create())) {
412 /* Parse the mode string. */
413 stream->openmode_ = jas_strtoopenmode(mode);
416 /* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the
417 greatest depths of purgatory! */
418 /* Ensure that the file descriptor is in binary mode, if the caller
419 has specified the binary mode flag. Arguably, the caller ought to
420 take care of this, but text mode is a ugly wart anyways, so we save
421 the caller some grief by handling this within the stream library. */
422 /* This ugliness is mainly for the benefit of those who run the
423 JasPer software under Windows from shells that insist on opening
424 files in text mode. For example, in the Cygwin environment,
425 shells often open files in text mode when I/O redirection is
427 if (stream->openmode_ & JAS_STREAM_BINARY) {
428 setmode(fd, O_BINARY);
432 /* Allocate space for the underlying file stream object. */
433 if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
434 jas_stream_destroy(stream);
439 obj->pathname[0] = '\0';
440 stream->obj_ = (void *) obj;
442 /* Do not close the underlying file descriptor when the stream is
444 obj->flags |= JAS_STREAM_FILEOBJ_NOCLOSE;
446 /* By default, use full buffering for this type of stream. */
447 jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
449 /* Select the operations for a file stream object. */
450 stream->ops_ = &jas_stream_fileops;
455 static void jas_stream_destroy(jas_stream_t *stream)
457 /* If the memory for the buffer was allocated with malloc, free
459 if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
460 jas_free(stream->bufbase_);
461 stream->bufbase_ = 0;
466 int jas_stream_close(jas_stream_t *stream)
468 /* Flush buffer if necessary. */
469 jas_stream_flush(stream);
471 /* Close the underlying stream object. */
472 (*stream->ops_->close_)(stream->obj_);
474 jas_stream_destroy(stream);
479 /******************************************************************************\
480 * Code for reading and writing streams.
481 \******************************************************************************/
483 int jas_stream_getc_func(jas_stream_t *stream)
485 assert(stream->ptr_ - stream->bufbase_ <= stream->bufsize_ +
486 JAS_STREAM_MAXPUTBACK);
487 return jas_stream_getc_macro(stream);
490 int jas_stream_putc_func(jas_stream_t *stream, int c)
492 assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_);
493 return jas_stream_putc_macro(stream, c);
496 int jas_stream_ungetc(jas_stream_t *stream, int c)
498 if (!stream->ptr_ || stream->ptr_ == stream->bufbase_) {
502 /* Reset the EOF indicator (since we now have at least one character
504 stream->flags_ &= ~JAS_STREAM_EOF;
513 int jas_stream_read(jas_stream_t *stream, void *buf, int cnt)
523 if ((c = jas_stream_getc(stream)) == EOF) {
533 int jas_stream_write(jas_stream_t *stream, const void *buf, int cnt)
542 if (jas_stream_putc(stream, *bufptr) == EOF) {
552 /* Note: This function uses a fixed size buffer. Therefore, it cannot
553 handle invocations that will produce more output than can be held
555 int jas_stream_printf(jas_stream_t *stream, const char *fmt, ...)
562 ret = vsnprintf(buf, sizeof buf, fmt, ap);
563 jas_stream_puts(stream, buf);
568 int jas_stream_puts(jas_stream_t *stream, const char *s)
571 if (jas_stream_putc_macro(stream, *s) == EOF) {
579 char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize)
586 while (bufsize > 1) {
587 if ((c = jas_stream_getc(stream)) == EOF) {
600 int jas_stream_gobble(jas_stream_t *stream, int n)
604 for (m = n; m > 0; --m) {
605 if (jas_stream_getc(stream) == EOF) {
612 int jas_stream_pad(jas_stream_t *stream, int n, int c)
616 for (m = n; m > 0; --m) {
617 if (jas_stream_putc(stream, c) == EOF)
623 /******************************************************************************\
624 * Code for getting and setting the stream position.
625 \******************************************************************************/
627 int jas_stream_isseekable(jas_stream_t *stream)
629 if (stream->ops_ == &jas_stream_memops) {
631 } else if (stream->ops_ == &jas_stream_fileops) {
632 if ((*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR) < 0) {
641 int jas_stream_rewind(jas_stream_t *stream)
643 return jas_stream_seek(stream, 0, SEEK_SET);
646 long jas_stream_seek(jas_stream_t *stream, long offset, int origin)
650 /* The buffer cannot be in use for both reading and writing. */
651 assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ &
654 /* Reset the EOF indicator (since we may not be at the EOF anymore). */
655 stream->flags_ &= ~JAS_STREAM_EOF;
657 if (stream->bufmode_ & JAS_STREAM_RDBUF) {
658 if (origin == SEEK_CUR) {
659 offset -= stream->cnt_;
661 } else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
662 if (jas_stream_flush(stream)) {
667 stream->ptr_ = stream->bufstart_;
668 stream->bufmode_ &= ~(JAS_STREAM_RDBUF | JAS_STREAM_WRBUF);
670 if ((newpos = (*stream->ops_->seek_)(stream->obj_, offset, origin))
678 long jas_stream_tell(jas_stream_t *stream)
683 if (stream->bufmode_ & JAS_STREAM_RDBUF) {
684 adjust = -stream->cnt_;
685 } else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
686 adjust = stream->ptr_ - stream->bufstart_;
691 if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) {
695 return offset + adjust;
698 /******************************************************************************\
699 * Buffer initialization code.
700 \******************************************************************************/
702 static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
705 /* If this function is being called, the buffer should not have been
707 assert(!stream->bufbase_);
709 if (bufmode != JAS_STREAM_UNBUF) {
710 /* The full- or line-buffered mode is being employed. */
712 /* The caller has not specified a buffer to employ, so allocate
714 if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE +
715 JAS_STREAM_MAXPUTBACK))) {
716 stream->bufmode_ |= JAS_STREAM_FREEBUF;
717 stream->bufsize_ = JAS_STREAM_BUFSIZE;
719 /* The buffer allocation has failed. Resort to unbuffered
721 stream->bufbase_ = stream->tinybuf_;
722 stream->bufsize_ = 1;
725 /* The caller has specified a buffer to employ. */
726 /* The buffer must be large enough to accommodate maximum
728 assert(bufsize > JAS_STREAM_MAXPUTBACK);
729 stream->bufbase_ = JAS_CAST(uchar *, buf);
730 stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
733 /* The unbuffered mode is being employed. */
734 /* A buffer should not have been supplied by the caller. */
736 /* Use a trivial one-character buffer. */
737 stream->bufbase_ = stream->tinybuf_;
738 stream->bufsize_ = 1;
740 stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
741 stream->ptr_ = stream->bufstart_;
743 stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
746 /******************************************************************************\
747 * Buffer filling and flushing code.
748 \******************************************************************************/
750 int jas_stream_flush(jas_stream_t *stream)
752 if (stream->bufmode_ & JAS_STREAM_RDBUF) {
755 return jas_stream_flushbuf(stream, EOF);
758 int jas_stream_fillbuf(jas_stream_t *stream, int getflag)
762 /* The stream must not be in an error or EOF state. */
763 if ((stream->flags_ & (JAS_STREAM_ERRMASK)) != 0) {
767 /* The stream must be open for reading. */
768 if ((stream->openmode_ & JAS_STREAM_READ) == 0) {
772 /* Make a half-hearted attempt to confirm that the buffer is not
773 currently being used for writing. This check is not intended
775 assert((stream->bufmode_ & JAS_STREAM_WRBUF) == 0);
777 assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_);
779 /* Mark the buffer as being used for reading. */
780 stream->bufmode_ |= JAS_STREAM_RDBUF;
782 /* Read new data into the buffer. */
783 stream->ptr_ = stream->bufstart_;
784 if ((stream->cnt_ = (*stream->ops_->read_)(stream->obj_,
785 (char *) stream->bufstart_, stream->bufsize_)) <= 0) {
786 if (stream->cnt_ < 0) {
787 stream->flags_ |= JAS_STREAM_ERR;
789 stream->flags_ |= JAS_STREAM_EOF;
795 assert(stream->cnt_ > 0);
796 /* Get or peek at the first character in the buffer. */
797 c = (getflag) ? jas_stream_getc2(stream) : (*stream->ptr_);
802 int jas_stream_flushbuf(jas_stream_t *stream, int c)
807 /* The stream should not be in an error or EOF state. */
808 if ((stream->flags_ & (JAS_STREAM_ERRMASK)) != 0) {
812 /* The stream must be open for writing. */
813 if ((stream->openmode_ & (JAS_STREAM_WRITE | JAS_STREAM_APPEND)) == 0) {
817 /* The buffer should not currently be in use for reading. */
818 assert(!(stream->bufmode_ & JAS_STREAM_RDBUF));
820 /* Note: Do not use the quantity stream->cnt to determine the number
821 of characters in the buffer! Depending on how this function was
822 called, the stream->cnt value may be "off-by-one". */
823 len = stream->ptr_ - stream->bufstart_;
825 n = (*stream->ops_->write_)(stream->obj_, (char *)
826 stream->bufstart_, len);
828 stream->flags_ |= JAS_STREAM_ERR;
832 stream->cnt_ = stream->bufsize_;
833 stream->ptr_ = stream->bufstart_;
835 stream->bufmode_ |= JAS_STREAM_WRBUF;
838 assert(stream->cnt_ > 0);
839 return jas_stream_putc2(stream, c);
845 /******************************************************************************\
846 * Miscellaneous code.
847 \******************************************************************************/
849 static int jas_strtoopenmode(const char *s)
855 openmode |= JAS_STREAM_READ;
858 openmode |= JAS_STREAM_WRITE | JAS_STREAM_CREATE;
861 openmode |= JAS_STREAM_BINARY;
864 openmode |= JAS_STREAM_APPEND;
867 openmode |= JAS_STREAM_READ | JAS_STREAM_WRITE;
877 int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n)
883 all = (n < 0) ? 1 : 0;
886 while (all || m > 0) {
887 if ((c = jas_stream_getc_macro(in)) == EOF) {
888 /* The next character of input could not be read. */
889 /* Return with an error if an I/O error occured
890 (not including EOF) or if an explicit copy count
892 return (!all || jas_stream_error(in)) ? (-1) : 0;
894 if (jas_stream_putc_macro(out, c) == EOF) {
902 long jas_stream_setrwcount(jas_stream_t *stream, long rwcnt)
906 old = stream->rwcnt_;
907 stream->rwcnt_ = rwcnt;
911 int jas_stream_display(jas_stream_t *stream, FILE *fp, int n)
913 unsigned char buf[16];
924 for (i = 0; i < n; i += 16) {
925 if (n > 16 && i > 0) {
926 display = (i >= cnt) ? 1 : 0;
929 fprintf(fp, "%08x:", i);
931 m = JAS_MIN(n - i, 16);
932 for (j = 0; j < m; ++j) {
933 if ((c = jas_stream_getc(stream)) == EOF) {
940 for (j = 0; j < m; ++j) {
941 fprintf(fp, " %02x", buf[j]);
944 for (; j < 16; ++j) {
947 for (j = 0; j < m; ++j) {
948 if (isprint(buf[j])) {
962 long jas_stream_length(jas_stream_t *stream)
966 if ((oldpos = jas_stream_tell(stream)) < 0) {
969 if (jas_stream_seek(stream, 0, SEEK_END) < 0) {
972 if ((pos = jas_stream_tell(stream)) < 0) {
975 if (jas_stream_seek(stream, oldpos, SEEK_SET) < 0) {
981 /******************************************************************************\
982 * Memory stream object.
983 \******************************************************************************/
985 static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt)
988 jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
989 n = m->len_ - m->pos_;
990 cnt = JAS_MIN(n, cnt);
991 memcpy(buf, &m->buf_[m->pos_], cnt);
996 static int mem_resize(jas_stream_memobj_t *m, int bufsize)
1001 if (!(buf = jas_realloc(m->buf_, bufsize))) {
1005 m->bufsize_ = bufsize;
1009 static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
1013 jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1017 newpos = m->pos_ + cnt;
1018 if (newpos > m->bufsize_ && m->growable_) {
1019 newbufsize = m->bufsize_;
1020 while (newbufsize < newpos) {
1022 assert(newbufsize >= 0);
1024 if (mem_resize(m, newbufsize)) {
1028 if (m->pos_ > m->len_) {
1029 /* The current position is beyond the end of the file, so
1030 pad the file to the current position with zeros. */
1031 n = JAS_MIN(m->pos_, m->bufsize_) - m->len_;
1033 memset(&m->buf_[m->len_], 0, n);
1036 if (m->pos_ != m->len_) {
1037 /* The buffer is not big enough. */
1041 n = m->bufsize_ - m->pos_;
1042 ret = JAS_MIN(n, cnt);
1044 memcpy(&m->buf_[m->pos_], buf, ret);
1047 if (m->pos_ > m->len_) {
1054 static long mem_seek(jas_stream_obj_t *obj, long offset, int origin)
1056 jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1064 newpos = m->len_ - offset;
1067 newpos = m->pos_ + offset;
1081 static int mem_close(jas_stream_obj_t *obj)
1083 jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1084 if (m->myalloc_ && m->buf_) {
1092 /******************************************************************************\
1093 * File stream object.
1094 \******************************************************************************/
1096 static int file_read(jas_stream_obj_t *obj, char *buf, int cnt)
1098 jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1099 return read(fileobj->fd, buf, cnt);
1102 static int file_write(jas_stream_obj_t *obj, char *buf, int cnt)
1104 jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1105 return write(fileobj->fd, buf, cnt);
1108 static long file_seek(jas_stream_obj_t *obj, long offset, int origin)
1110 jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1111 return lseek(fileobj->fd, offset, origin);
1114 static int file_close(jas_stream_obj_t *obj)
1116 jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1118 ret = close(fileobj->fd);
1119 if (fileobj->flags & JAS_STREAM_FILEOBJ_DELONCLOSE) {
1120 unlink(fileobj->pathname);
1126 /******************************************************************************\
1127 * Stdio file stream object.
1128 \******************************************************************************/
1130 static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt)
1133 fp = JAS_CAST(FILE *, obj);
1134 return fread(buf, 1, cnt, fp);
1137 static int sfile_write(jas_stream_obj_t *obj, char *buf, int cnt)
1140 fp = JAS_CAST(FILE *, obj);
1141 return fwrite(buf, 1, cnt, fp);
1144 static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin)
1147 fp = JAS_CAST(FILE *, obj);
1148 return fseek(fp, offset, origin);
1151 static int sfile_close(jas_stream_obj_t *obj)
1154 fp = JAS_CAST(FILE *, obj);