📄 jas_stream.c
字号:
writing in binary mode. */ stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY; /* Allocate memory for the underlying temporary file object. */ if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { jas_stream_destroy(stream); return 0; } obj->fd = -1; obj->flags = 0; obj->pathname[0] = '\0'; stream->obj_ = obj; /* Choose a file name. */ tmpnam(obj->pathname); /* Open the underlying file. */ if ((obj->fd = open(obj->pathname, O_CREAT | O_EXCL | O_RDWR | O_TRUNC | O_BINARY, JAS_STREAM_PERMS)) < 0) { jas_stream_destroy(stream); return 0; } /* Unlink the file so that it will disappear if the program terminates abnormally. */ /* Under UNIX, one can unlink an open file and continue to do I/O on it. Not all operating systems support this functionality, however. For example, under Microsoft Windows the unlink operation will fail, since the file is open. */ if (unlink(obj->pathname)) { /* We will try unlinking the file again after it is closed. */ obj->flags |= JAS_STREAM_FILEOBJ_DELONCLOSE; } /* Use full buffering. */ jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); stream->ops_ = &jas_stream_fileops; return stream;}jas_stream_t *jas_stream_fdopen(int fd, const char *mode){ jas_stream_t *stream; jas_stream_fileobj_t *obj; /* Allocate a stream object. */ if (!(stream = jas_stream_create())) { return 0; } /* Parse the mode string. */ stream->openmode_ = jas_strtoopenmode(mode);#if defined(WIN32) /* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the greatest depths of purgatory! */ /* Ensure that the file descriptor is in binary mode, if the caller has specified the binary mode flag. Arguably, the caller ought to take care of this, but text mode is a ugly wart anyways, so we save the caller some grief by handling this within the stream library. */ /* This ugliness is mainly for the benefit of those who run the JasPer software under Windows from shells that insist on opening files in text mode. For example, in the Cygwin environment, shells often open files in text mode when I/O redirection is used. Grr... */ if (stream->openmode_ & JAS_STREAM_BINARY) { setmode(fd, O_BINARY); }#endif /* Allocate space for the underlying file stream object. */ if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { jas_stream_destroy(stream); return 0; } obj->fd = fd; obj->flags = 0; obj->pathname[0] = '\0'; stream->obj_ = (void *) obj; /* Do not close the underlying file descriptor when the stream is closed. */ obj->flags |= JAS_STREAM_FILEOBJ_NOCLOSE; /* By default, use full buffering for this type of stream. */ jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); /* Select the operations for a file stream object. */ stream->ops_ = &jas_stream_fileops; return stream;}static void jas_stream_destroy(jas_stream_t *stream){ /* If the memory for the buffer was allocated with malloc, free this memory. */ if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { jas_free(stream->bufbase_); stream->bufbase_ = 0; } jas_free(stream);}int jas_stream_close(jas_stream_t *stream){ /* Flush buffer if necessary. */ jas_stream_flush(stream); /* Close the underlying stream object. */ (*stream->ops_->close_)(stream->obj_); jas_stream_destroy(stream); return 0;}/******************************************************************************\* Code for reading and writing streams.\******************************************************************************/int jas_stream_getc_func(jas_stream_t *stream){ assert(stream->ptr_ - stream->bufbase_ <= stream->bufsize_ + JAS_STREAM_MAXPUTBACK); return jas_stream_getc_macro(stream);}int jas_stream_putc_func(jas_stream_t *stream, int c){ assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_); return jas_stream_putc_macro(stream, c);}int jas_stream_ungetc(jas_stream_t *stream, int c){ if (!stream->ptr_ || stream->ptr_ == stream->bufbase_) { return -1; } /* Reset the EOF indicator (since we now have at least one character to read). */ stream->flags_ &= ~JAS_STREAM_EOF; --stream->rwcnt_; --stream->ptr_; ++stream->cnt_; *stream->ptr_ = c; return 0;}int jas_stream_read(jas_stream_t *stream, void *buf, int cnt){ int n; int c; char *bufptr; bufptr = buf; n = 0; while (n < cnt) { if ((c = jas_stream_getc(stream)) == EOF) { return n; } *bufptr++ = c; ++n; } return n;}int jas_stream_write(jas_stream_t *stream, const void *buf, int cnt){ int n; const char *bufptr; bufptr = buf; n = 0; while (n < cnt) { if (jas_stream_putc(stream, *bufptr) == EOF) { return n; } ++bufptr; ++n; } return n;}/* Note: This function uses a fixed size buffer. Therefore, it cannot handle invocations that will produce more output than can be held by the buffer. */int jas_stream_printf(jas_stream_t *stream, const char *fmt, ...){ va_list ap; char buf[4096]; int ret; va_start(ap, fmt); ret = vsprintf(buf, fmt, ap); jas_stream_puts(stream, buf); va_end(ap); return ret;}int jas_stream_puts(jas_stream_t *stream, const char *s){ while (*s != '\0') { if (jas_stream_putc_macro(stream, *s) == EOF) { return -1; } ++s; } return 0;}char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize){ int c; char *bufptr; assert(bufsize > 0); bufptr = buf; while (bufsize > 1) { if ((c = jas_stream_getc(stream)) == EOF) { break; } *bufptr++ = c; --bufsize; if (c == '\n') { break; } } *bufptr = '\0'; return buf;}int jas_stream_gobble(jas_stream_t *stream, int n){ int m; m = n; for (m = n; m > 0; --m) { if (jas_stream_getc(stream) == EOF) { return n - m; } } return n;}int jas_stream_pad(jas_stream_t *stream, int n, int c){ int m; m = n; for (m = n; m > 0; --m) { if (jas_stream_putc(stream, c) == EOF) return n - m; } return n;}/******************************************************************************\* Code for getting and setting the stream position.\******************************************************************************/int jas_stream_isseekable(jas_stream_t *stream){ if (stream->ops_ == &jas_stream_memops) { return 1; } else if (stream->ops_ == &jas_stream_fileops) { if ((*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR) < 0) { return 0; } return 1; } else { return 0; }}int jas_stream_rewind(jas_stream_t *stream){ return jas_stream_seek(stream, 0, SEEK_SET);}long jas_stream_seek(jas_stream_t *stream, long offset, int origin){ long newpos; /* The buffer cannot be in use for both reading and writing. */ assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ & JAS_STREAM_WRBUF))); /* Reset the EOF indicator (since we may not be at the EOF anymore). */ stream->flags_ &= ~JAS_STREAM_EOF; if (stream->bufmode_ & JAS_STREAM_RDBUF) { if (origin == SEEK_CUR) { offset -= stream->cnt_; } } else if (stream->bufmode_ & JAS_STREAM_WRBUF) { if (jas_stream_flush(stream)) { return -1; } } stream->cnt_ = 0; stream->ptr_ = stream->bufstart_; stream->bufmode_ &= ~(JAS_STREAM_RDBUF | JAS_STREAM_WRBUF); if ((newpos = (*stream->ops_->seek_)(stream->obj_, offset, origin)) < 0) { return -1; } return newpos;}long jas_stream_tell(jas_stream_t *stream){ int adjust; int offset; if (stream->bufmode_ & JAS_STREAM_RDBUF) { adjust = -stream->cnt_; } else if (stream->bufmode_ & JAS_STREAM_WRBUF) { adjust = stream->ptr_ - stream->bufstart_; } else { adjust = 0; } if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) { return -1; } return offset + adjust;}/******************************************************************************\* Buffer initialization code.\******************************************************************************/static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, int bufsize){ /* If this function is being called, the buffer should not have been initialized yet. */ assert(!stream->bufbase_); if (bufmode != JAS_STREAM_UNBUF) { /* The full- or line-buffered mode is being employed. */ if (!buf) { /* The caller has not specified a buffer to employ, so allocate one. */ if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE + JAS_STREAM_MAXPUTBACK))) { stream->bufmode_ |= JAS_STREAM_FREEBUF; stream->bufsize_ = JAS_STREAM_BUFSIZE; } else { /* The buffer allocation has failed. Resort to unbuffered operation. */ stream->bufbase_ = stream->tinybuf_; stream->bufsize_ = 1; } } else { /* The caller has specified a buffer to employ. */ /* The buffer must be large enough to accommodate maximum putback. */ assert(bufsize > JAS_STREAM_MAXPUTBACK); stream->bufbase_ = JAS_CAST(uchar *, buf); stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK; } } else { /* The unbuffered mode is being employed. */ /* A buffer should not have been supplied by the caller. */ assert(!buf); /* Use a trivial one-character buffer. */ stream->bufbase_ = stream->tinybuf_; stream->bufsize_ = 1; } stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK]; stream->ptr_ = stream->bufstart_; stream->cnt_ = 0; stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;}/******************************************************************************\* Buffer filling and flushing code.\******************************************************************************/int jas_stream_flush(jas_stream_t *stream){ if (stream->bufmode_ & JAS_STREAM_RDBUF) { return 0; } return jas_stream_flushbuf(stream, EOF);}int jas_stream_fillbuf(jas_stream_t *stream, int getflag){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -