Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/libjasper/jas_stream.c
16337 views
1
/*
2
* Copyright (c) 1999-2000 Image Power, Inc. and the University of
3
* British Columbia.
4
* Copyright (c) 2001-2003 Michael David Adams.
5
* All rights reserved.
6
*/
7
8
/* __START_OF_JASPER_LICENSE__
9
*
10
* JasPer License Version 2.0
11
*
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
15
*
16
* All rights reserved.
17
*
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:
25
*
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.
29
*
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
32
* written permission.
33
*
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.
60
*
61
* __END_OF_JASPER_LICENSE__
62
*/
63
64
/*
65
* I/O Stream Library
66
*
67
* $Id: jas_stream.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
68
*/
69
70
/******************************************************************************\
71
* Includes.
72
\******************************************************************************/
73
74
#include <assert.h>
75
#if defined(HAVE_FCNTL_H)
76
#include <fcntl.h>
77
#endif
78
#include <stdlib.h>
79
#include <stdarg.h>
80
#include <stdio.h>
81
#include <ctype.h>
82
#if defined(HAVE_UNISTD_H)
83
#include <unistd.h>
84
#endif
85
#if defined(WIN32) || defined(HAVE_IO_H)
86
#include <io.h>
87
#endif
88
89
#include "jasper/jas_types.h"
90
#include "jasper/jas_stream.h"
91
#include "jasper/jas_malloc.h"
92
#include "jasper/jas_math.h"
93
94
/******************************************************************************\
95
* Local function prototypes.
96
\******************************************************************************/
97
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,
102
int bufsize);
103
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);
108
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);
113
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);
118
119
/******************************************************************************\
120
* Local data.
121
\******************************************************************************/
122
123
static jas_stream_ops_t jas_stream_fileops = {
124
file_read,
125
file_write,
126
file_seek,
127
file_close
128
};
129
130
static jas_stream_ops_t jas_stream_sfileops = {
131
sfile_read,
132
sfile_write,
133
sfile_seek,
134
sfile_close
135
};
136
137
static jas_stream_ops_t jas_stream_memops = {
138
mem_read,
139
mem_write,
140
mem_seek,
141
mem_close
142
};
143
144
/******************************************************************************\
145
* Code for opening and closing streams.
146
\******************************************************************************/
147
148
static jas_stream_t *jas_stream_create()
149
{
150
jas_stream_t *stream;
151
152
if (!(stream = jas_malloc(sizeof(jas_stream_t)))) {
153
return 0;
154
}
155
stream->openmode_ = 0;
156
stream->bufmode_ = 0;
157
stream->flags_ = 0;
158
stream->bufbase_ = 0;
159
stream->bufstart_ = 0;
160
stream->bufsize_ = 0;
161
stream->ptr_ = 0;
162
stream->cnt_ = 0;
163
stream->ops_ = 0;
164
stream->obj_ = 0;
165
stream->rwcnt_ = 0;
166
stream->rwlimit_ = -1;
167
168
return stream;
169
}
170
171
jas_stream_t *jas_stream_memopen(char *buf, int bufsize)
172
{
173
jas_stream_t *stream;
174
jas_stream_memobj_t *obj;
175
176
if (!(stream = jas_stream_create())) {
177
return 0;
178
}
179
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;
183
184
/* Since the stream data is already resident in memory, buffering
185
is not necessary. */
186
/* But... It still may be faster to use buffering anyways. */
187
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
188
189
/* Select the operations for a memory stream. */
190
stream->ops_ = &jas_stream_memops;
191
192
/* Allocate memory for the underlying memory stream object. */
193
if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) {
194
jas_stream_destroy(stream);
195
return 0;
196
}
197
stream->obj_ = (void *) obj;
198
199
/* Initialize a few important members of the memory stream object. */
200
obj->myalloc_ = 0;
201
obj->buf_ = 0;
202
203
/* If the buffer size specified is nonpositive, then the buffer
204
is allocated internally and automatically grown as needed. */
205
if (bufsize <= 0) {
206
obj->bufsize_ = 1024;
207
obj->growable_ = 1;
208
} else {
209
obj->bufsize_ = bufsize;
210
obj->growable_ = 0;
211
}
212
if (buf) {
213
obj->buf_ = (unsigned char *) buf;
214
} else {
215
obj->buf_ = jas_malloc(obj->bufsize_);
216
obj->myalloc_ = 1;
217
}
218
if (!obj->buf_) {
219
jas_stream_close(stream);
220
return 0;
221
}
222
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. */
226
obj->len_ = bufsize;
227
} else {
228
/* The stream is initially empty. */
229
obj->len_ = 0;
230
}
231
obj->pos_ = 0;
232
233
return stream;
234
}
235
236
jas_stream_t *jas_stream_fopen(const char *filename, const char *mode)
237
{
238
jas_stream_t *stream;
239
jas_stream_fileobj_t *obj;
240
int openflags;
241
242
/* Allocate a stream object. */
243
if (!(stream = jas_stream_create())) {
244
return 0;
245
}
246
247
/* Parse the mode string. */
248
stream->openmode_ = jas_strtoopenmode(mode);
249
250
/* Determine the correct flags to use for opening the file. */
251
if ((stream->openmode_ & JAS_STREAM_READ) &&
252
(stream->openmode_ & JAS_STREAM_WRITE)) {
253
openflags = O_RDWR;
254
} else if (stream->openmode_ & JAS_STREAM_READ) {
255
openflags = O_RDONLY;
256
} else if (stream->openmode_ & JAS_STREAM_WRITE) {
257
openflags = O_WRONLY;
258
} else {
259
openflags = 0;
260
}
261
if (stream->openmode_ & JAS_STREAM_APPEND) {
262
openflags |= O_APPEND;
263
}
264
if (stream->openmode_ & JAS_STREAM_BINARY) {
265
openflags |= O_BINARY;
266
}
267
if (stream->openmode_ & JAS_STREAM_CREATE) {
268
openflags |= O_CREAT | O_TRUNC;
269
}
270
271
/* Allocate space for the underlying file stream object. */
272
if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
273
jas_stream_destroy(stream);
274
return 0;
275
}
276
obj->fd = -1;
277
obj->flags = 0;
278
obj->pathname[0] = '\0';
279
stream->obj_ = (void *) obj;
280
281
/* Select the operations for a file stream object. */
282
stream->ops_ = &jas_stream_fileops;
283
284
/* Open the underlying file. */
285
if ((obj->fd = open(filename, openflags, JAS_STREAM_PERMS)) < 0) {
286
jas_stream_destroy(stream);
287
return 0;
288
}
289
290
/* By default, use full buffering for this type of stream. */
291
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
292
293
return stream;
294
}
295
296
jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp)
297
{
298
jas_stream_t *stream;
299
int openflags;
300
301
/* Eliminate compiler warning about unused variable. */
302
path = 0;
303
304
/* Allocate a stream object. */
305
if (!(stream = jas_stream_create())) {
306
return 0;
307
}
308
309
/* Parse the mode string. */
310
stream->openmode_ = jas_strtoopenmode(mode);
311
312
/* Determine the correct flags to use for opening the file. */
313
if ((stream->openmode_ & JAS_STREAM_READ) &&
314
(stream->openmode_ & JAS_STREAM_WRITE)) {
315
openflags = O_RDWR;
316
} else if (stream->openmode_ & JAS_STREAM_READ) {
317
openflags = O_RDONLY;
318
} else if (stream->openmode_ & JAS_STREAM_WRITE) {
319
openflags = O_WRONLY;
320
} else {
321
openflags = 0;
322
}
323
if (stream->openmode_ & JAS_STREAM_APPEND) {
324
openflags |= O_APPEND;
325
}
326
if (stream->openmode_ & JAS_STREAM_BINARY) {
327
openflags |= O_BINARY;
328
}
329
if (stream->openmode_ & JAS_STREAM_CREATE) {
330
openflags |= O_CREAT | O_TRUNC;
331
}
332
333
stream->obj_ = JAS_CAST(void *, fp);
334
335
/* Select the operations for a file stream object. */
336
stream->ops_ = &jas_stream_sfileops;
337
338
/* By default, use full buffering for this type of stream. */
339
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
340
341
return stream;
342
}
343
344
jas_stream_t *jas_stream_tmpfile()
345
{
346
jas_stream_t *stream;
347
jas_stream_fileobj_t *obj;
348
char *tmpname;
349
350
if (!(stream = jas_stream_create())) {
351
return 0;
352
}
353
354
/* A temporary file stream is always opened for both reading and
355
writing in binary mode. */
356
stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
357
358
/* Allocate memory for the underlying temporary file object. */
359
if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
360
jas_stream_destroy(stream);
361
return 0;
362
}
363
obj->fd = -1;
364
obj->flags = 0;
365
stream->obj_ = obj;
366
367
#ifdef _WIN32
368
/* Choose a file name. */
369
tmpname = tempnam(NULL, NULL);
370
strcpy(obj->pathname, tmpname);
371
free(tmpname);
372
373
/* Open the underlying file. */
374
if ((obj->fd = open(obj->pathname, O_CREAT | O_EXCL | O_RDWR | O_TRUNC | O_BINARY | O_TEMPORARY | _O_SHORT_LIVED,
375
JAS_STREAM_PERMS)) < 0) {
376
jas_stream_destroy(stream);
377
return 0;
378
}
379
#else
380
/* Choose a file name. */
381
snprintf(obj->pathname, L_tmpnam, "%s/tmp.XXXXXXXXXX", P_tmpdir);
382
383
/* Open the underlying file. */
384
if ((obj->fd = mkstemp(obj->pathname)) < 0) {
385
jas_stream_destroy(stream);
386
return 0;
387
}
388
#endif
389
390
/* Unlink the file so that it will disappear if the program
391
terminates abnormally. */
392
if (unlink(obj->pathname)) {
393
jas_stream_destroy(stream);
394
return 0;
395
}
396
397
/* Use full buffering. */
398
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
399
400
stream->ops_ = &jas_stream_fileops;
401
402
return stream;
403
}
404
405
jas_stream_t *jas_stream_fdopen(int fd, const char *mode)
406
{
407
jas_stream_t *stream;
408
jas_stream_fileobj_t *obj;
409
410
/* Allocate a stream object. */
411
if (!(stream = jas_stream_create())) {
412
return 0;
413
}
414
415
/* Parse the mode string. */
416
stream->openmode_ = jas_strtoopenmode(mode);
417
418
#if defined(WIN32)
419
/* Argh!!! Someone ought to banish text mode (i.e., O_TEXT) to the
420
greatest depths of purgatory! */
421
/* Ensure that the file descriptor is in binary mode, if the caller
422
has specified the binary mode flag. Arguably, the caller ought to
423
take care of this, but text mode is a ugly wart anyways, so we save
424
the caller some grief by handling this within the stream library. */
425
/* This ugliness is mainly for the benefit of those who run the
426
JasPer software under Windows from shells that insist on opening
427
files in text mode. For example, in the Cygwin environment,
428
shells often open files in text mode when I/O redirection is
429
used. Grr... */
430
if (stream->openmode_ & JAS_STREAM_BINARY) {
431
setmode(fd, O_BINARY);
432
}
433
#endif
434
435
/* Allocate space for the underlying file stream object. */
436
if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) {
437
jas_stream_destroy(stream);
438
return 0;
439
}
440
obj->fd = fd;
441
obj->flags = 0;
442
obj->pathname[0] = '\0';
443
stream->obj_ = (void *) obj;
444
445
/* Do not close the underlying file descriptor when the stream is
446
closed. */
447
obj->flags |= JAS_STREAM_FILEOBJ_NOCLOSE;
448
449
/* By default, use full buffering for this type of stream. */
450
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
451
452
/* Select the operations for a file stream object. */
453
stream->ops_ = &jas_stream_fileops;
454
455
return stream;
456
}
457
458
static void jas_stream_destroy(jas_stream_t *stream)
459
{
460
/* If the memory for the buffer was allocated with malloc, free
461
this memory. */
462
if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
463
jas_free(stream->bufbase_);
464
stream->bufbase_ = 0;
465
}
466
jas_free(stream);
467
}
468
469
int jas_stream_close(jas_stream_t *stream)
470
{
471
/* Flush buffer if necessary. */
472
jas_stream_flush(stream);
473
474
/* Close the underlying stream object. */
475
(*stream->ops_->close_)(stream->obj_);
476
477
jas_stream_destroy(stream);
478
479
return 0;
480
}
481
482
/******************************************************************************\
483
* Code for reading and writing streams.
484
\******************************************************************************/
485
486
int jas_stream_getc_func(jas_stream_t *stream)
487
{
488
assert(stream->ptr_ - stream->bufbase_ <= stream->bufsize_ +
489
JAS_STREAM_MAXPUTBACK);
490
return jas_stream_getc_macro(stream);
491
}
492
493
int jas_stream_putc_func(jas_stream_t *stream, int c)
494
{
495
assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_);
496
return jas_stream_putc_macro(stream, c);
497
}
498
499
int jas_stream_ungetc(jas_stream_t *stream, int c)
500
{
501
if (!stream->ptr_ || stream->ptr_ == stream->bufbase_) {
502
return -1;
503
}
504
505
/* Reset the EOF indicator (since we now have at least one character
506
to read). */
507
stream->flags_ &= ~JAS_STREAM_EOF;
508
509
--stream->rwcnt_;
510
--stream->ptr_;
511
++stream->cnt_;
512
*stream->ptr_ = c;
513
return 0;
514
}
515
516
int jas_stream_read(jas_stream_t *stream, void *buf, int cnt)
517
{
518
int n;
519
int c;
520
char *bufptr;
521
522
bufptr = buf;
523
524
n = 0;
525
while (n < cnt) {
526
if ((c = jas_stream_getc(stream)) == EOF) {
527
return n;
528
}
529
*bufptr++ = c;
530
++n;
531
}
532
533
return n;
534
}
535
536
int jas_stream_write(jas_stream_t *stream, const void *buf, int cnt)
537
{
538
int n;
539
const char *bufptr;
540
541
bufptr = buf;
542
543
n = 0;
544
while (n < cnt) {
545
if (jas_stream_putc(stream, *bufptr) == EOF) {
546
return n;
547
}
548
++bufptr;
549
++n;
550
}
551
552
return n;
553
}
554
555
/* Note: This function uses a fixed size buffer. Therefore, it cannot
556
handle invocations that will produce more output than can be held
557
by the buffer. */
558
int jas_stream_printf(jas_stream_t *stream, const char *fmt, ...)
559
{
560
va_list ap;
561
char buf[4096];
562
int ret;
563
564
va_start(ap, fmt);
565
ret = vsnprintf(buf, sizeof buf, fmt, ap);
566
jas_stream_puts(stream, buf);
567
va_end(ap);
568
return ret;
569
}
570
571
int jas_stream_puts(jas_stream_t *stream, const char *s)
572
{
573
while (*s != '\0') {
574
if (jas_stream_putc_macro(stream, *s) == EOF) {
575
return -1;
576
}
577
++s;
578
}
579
return 0;
580
}
581
582
char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize)
583
{
584
int c;
585
char *bufptr;
586
assert(bufsize > 0);
587
588
bufptr = buf;
589
while (bufsize > 1) {
590
if ((c = jas_stream_getc(stream)) == EOF) {
591
break;
592
}
593
*bufptr++ = c;
594
--bufsize;
595
if (c == '\n') {
596
break;
597
}
598
}
599
*bufptr = '\0';
600
return buf;
601
}
602
603
int jas_stream_gobble(jas_stream_t *stream, int n)
604
{
605
int m;
606
m = n;
607
for (m = n; m > 0; --m) {
608
if (jas_stream_getc(stream) == EOF) {
609
return n - m;
610
}
611
}
612
return n;
613
}
614
615
int jas_stream_pad(jas_stream_t *stream, int n, int c)
616
{
617
int m;
618
m = n;
619
for (m = n; m > 0; --m) {
620
if (jas_stream_putc(stream, c) == EOF)
621
return n - m;
622
}
623
return n;
624
}
625
626
/******************************************************************************\
627
* Code for getting and setting the stream position.
628
\******************************************************************************/
629
630
int jas_stream_isseekable(jas_stream_t *stream)
631
{
632
if (stream->ops_ == &jas_stream_memops) {
633
return 1;
634
} else if (stream->ops_ == &jas_stream_fileops) {
635
if ((*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR) < 0) {
636
return 0;
637
}
638
return 1;
639
} else {
640
return 0;
641
}
642
}
643
644
int jas_stream_rewind(jas_stream_t *stream)
645
{
646
return jas_stream_seek(stream, 0, SEEK_SET);
647
}
648
649
long jas_stream_seek(jas_stream_t *stream, long offset, int origin)
650
{
651
long newpos;
652
653
/* The buffer cannot be in use for both reading and writing. */
654
assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ &
655
JAS_STREAM_WRBUF)));
656
657
/* Reset the EOF indicator (since we may not be at the EOF anymore). */
658
stream->flags_ &= ~JAS_STREAM_EOF;
659
660
if (stream->bufmode_ & JAS_STREAM_RDBUF) {
661
if (origin == SEEK_CUR) {
662
offset -= stream->cnt_;
663
}
664
} else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
665
if (jas_stream_flush(stream)) {
666
return -1;
667
}
668
}
669
stream->cnt_ = 0;
670
stream->ptr_ = stream->bufstart_;
671
stream->bufmode_ &= ~(JAS_STREAM_RDBUF | JAS_STREAM_WRBUF);
672
673
if ((newpos = (*stream->ops_->seek_)(stream->obj_, offset, origin))
674
< 0) {
675
return -1;
676
}
677
678
return newpos;
679
}
680
681
long jas_stream_tell(jas_stream_t *stream)
682
{
683
int adjust;
684
int offset;
685
686
if (stream->bufmode_ & JAS_STREAM_RDBUF) {
687
adjust = -stream->cnt_;
688
} else if (stream->bufmode_ & JAS_STREAM_WRBUF) {
689
adjust = stream->ptr_ - stream->bufstart_;
690
} else {
691
adjust = 0;
692
}
693
694
if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) {
695
return -1;
696
}
697
698
return offset + adjust;
699
}
700
701
/******************************************************************************\
702
* Buffer initialization code.
703
\******************************************************************************/
704
705
static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
706
int bufsize)
707
{
708
/* If this function is being called, the buffer should not have been
709
initialized yet. */
710
assert(!stream->bufbase_);
711
712
if (bufmode != JAS_STREAM_UNBUF) {
713
/* The full- or line-buffered mode is being employed. */
714
if (!buf) {
715
/* The caller has not specified a buffer to employ, so allocate
716
one. */
717
if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE +
718
JAS_STREAM_MAXPUTBACK))) {
719
stream->bufmode_ |= JAS_STREAM_FREEBUF;
720
stream->bufsize_ = JAS_STREAM_BUFSIZE;
721
} else {
722
/* The buffer allocation has failed. Resort to unbuffered
723
operation. */
724
stream->bufbase_ = stream->tinybuf_;
725
stream->bufsize_ = 1;
726
}
727
} else {
728
/* The caller has specified a buffer to employ. */
729
/* The buffer must be large enough to accommodate maximum
730
putback. */
731
assert(bufsize > JAS_STREAM_MAXPUTBACK);
732
stream->bufbase_ = JAS_CAST(uchar *, buf);
733
stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
734
}
735
} else {
736
/* The unbuffered mode is being employed. */
737
/* A buffer should not have been supplied by the caller. */
738
assert(!buf);
739
/* Use a trivial one-character buffer. */
740
stream->bufbase_ = stream->tinybuf_;
741
stream->bufsize_ = 1;
742
}
743
stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
744
stream->ptr_ = stream->bufstart_;
745
stream->cnt_ = 0;
746
stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
747
}
748
749
/******************************************************************************\
750
* Buffer filling and flushing code.
751
\******************************************************************************/
752
753
int jas_stream_flush(jas_stream_t *stream)
754
{
755
if (stream->bufmode_ & JAS_STREAM_RDBUF) {
756
return 0;
757
}
758
return jas_stream_flushbuf(stream, EOF);
759
}
760
761
int jas_stream_fillbuf(jas_stream_t *stream, int getflag)
762
{
763
int c;
764
765
/* The stream must not be in an error or EOF state. */
766
if ((stream->flags_ & (JAS_STREAM_ERRMASK)) != 0) {
767
return EOF;
768
}
769
770
/* The stream must be open for reading. */
771
if ((stream->openmode_ & JAS_STREAM_READ) == 0) {
772
return EOF;
773
}
774
775
/* Make a half-hearted attempt to confirm that the buffer is not
776
currently being used for writing. This check is not intended
777
to be foolproof! */
778
assert((stream->bufmode_ & JAS_STREAM_WRBUF) == 0);
779
780
assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_);
781
782
/* Mark the buffer as being used for reading. */
783
stream->bufmode_ |= JAS_STREAM_RDBUF;
784
785
/* Read new data into the buffer. */
786
stream->ptr_ = stream->bufstart_;
787
if ((stream->cnt_ = (*stream->ops_->read_)(stream->obj_,
788
(char *) stream->bufstart_, stream->bufsize_)) <= 0) {
789
if (stream->cnt_ < 0) {
790
stream->flags_ |= JAS_STREAM_ERR;
791
} else {
792
stream->flags_ |= JAS_STREAM_EOF;
793
}
794
stream->cnt_ = 0;
795
return EOF;
796
}
797
798
assert(stream->cnt_ > 0);
799
/* Get or peek at the first character in the buffer. */
800
c = (getflag) ? jas_stream_getc2(stream) : (*stream->ptr_);
801
802
return c;
803
}
804
805
int jas_stream_flushbuf(jas_stream_t *stream, int c)
806
{
807
int len;
808
int n;
809
810
/* The stream should not be in an error or EOF state. */
811
if ((stream->flags_ & (JAS_STREAM_ERRMASK)) != 0) {
812
return EOF;
813
}
814
815
/* The stream must be open for writing. */
816
if ((stream->openmode_ & (JAS_STREAM_WRITE | JAS_STREAM_APPEND)) == 0) {
817
return EOF;
818
}
819
820
/* The buffer should not currently be in use for reading. */
821
assert(!(stream->bufmode_ & JAS_STREAM_RDBUF));
822
823
/* Note: Do not use the quantity stream->cnt to determine the number
824
of characters in the buffer! Depending on how this function was
825
called, the stream->cnt value may be "off-by-one". */
826
len = stream->ptr_ - stream->bufstart_;
827
if (len > 0) {
828
n = (*stream->ops_->write_)(stream->obj_, (char *)
829
stream->bufstart_, len);
830
if (n != len) {
831
stream->flags_ |= JAS_STREAM_ERR;
832
return EOF;
833
}
834
}
835
stream->cnt_ = stream->bufsize_;
836
stream->ptr_ = stream->bufstart_;
837
838
stream->bufmode_ |= JAS_STREAM_WRBUF;
839
840
if (c != EOF) {
841
assert(stream->cnt_ > 0);
842
return jas_stream_putc2(stream, c);
843
}
844
845
return 0;
846
}
847
848
/******************************************************************************\
849
* Miscellaneous code.
850
\******************************************************************************/
851
852
static int jas_strtoopenmode(const char *s)
853
{
854
int openmode = 0;
855
while (*s != '\0') {
856
switch (*s) {
857
case 'r':
858
openmode |= JAS_STREAM_READ;
859
break;
860
case 'w':
861
openmode |= JAS_STREAM_WRITE | JAS_STREAM_CREATE;
862
break;
863
case 'b':
864
openmode |= JAS_STREAM_BINARY;
865
break;
866
case 'a':
867
openmode |= JAS_STREAM_APPEND;
868
break;
869
case '+':
870
openmode |= JAS_STREAM_READ | JAS_STREAM_WRITE;
871
break;
872
default:
873
break;
874
}
875
++s;
876
}
877
return openmode;
878
}
879
880
int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n)
881
{
882
int all;
883
int c;
884
int m;
885
886
all = (n < 0) ? 1 : 0;
887
888
m = n;
889
while (all || m > 0) {
890
if ((c = jas_stream_getc_macro(in)) == EOF) {
891
/* The next character of input could not be read. */
892
/* Return with an error if an I/O error occured
893
(not including EOF) or if an explicit copy count
894
was specified. */
895
return (!all || jas_stream_error(in)) ? (-1) : 0;
896
}
897
if (jas_stream_putc_macro(out, c) == EOF) {
898
return -1;
899
}
900
--m;
901
}
902
return 0;
903
}
904
905
long jas_stream_setrwcount(jas_stream_t *stream, long rwcnt)
906
{
907
int old;
908
909
old = stream->rwcnt_;
910
stream->rwcnt_ = rwcnt;
911
return old;
912
}
913
914
int jas_stream_display(jas_stream_t *stream, FILE *fp, int n)
915
{
916
unsigned char buf[16];
917
int i;
918
int j;
919
int m;
920
int c;
921
int display;
922
int cnt;
923
924
cnt = n - (n % 16);
925
display = 1;
926
927
for (i = 0; i < n; i += 16) {
928
if (n > 16 && i > 0) {
929
display = (i >= cnt) ? 1 : 0;
930
}
931
if (display) {
932
fprintf(fp, "%08x:", i);
933
}
934
m = JAS_MIN(n - i, 16);
935
for (j = 0; j < m; ++j) {
936
if ((c = jas_stream_getc(stream)) == EOF) {
937
abort();
938
return -1;
939
}
940
buf[j] = c;
941
}
942
if (display) {
943
for (j = 0; j < m; ++j) {
944
fprintf(fp, " %02x", buf[j]);
945
}
946
fputc(' ', fp);
947
for (; j < 16; ++j) {
948
fprintf(fp, " ");
949
}
950
for (j = 0; j < m; ++j) {
951
if (isprint(buf[j])) {
952
fputc(buf[j], fp);
953
} else {
954
fputc(' ', fp);
955
}
956
}
957
fprintf(fp, "\n");
958
}
959
960
961
}
962
return 0;
963
}
964
965
long jas_stream_length(jas_stream_t *stream)
966
{
967
long oldpos;
968
long pos;
969
if ((oldpos = jas_stream_tell(stream)) < 0) {
970
return -1;
971
}
972
if (jas_stream_seek(stream, 0, SEEK_END) < 0) {
973
return -1;
974
}
975
if ((pos = jas_stream_tell(stream)) < 0) {
976
return -1;
977
}
978
if (jas_stream_seek(stream, oldpos, SEEK_SET) < 0) {
979
return -1;
980
}
981
return pos;
982
}
983
984
/******************************************************************************\
985
* Memory stream object.
986
\******************************************************************************/
987
988
static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt)
989
{
990
int n;
991
jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
992
n = m->len_ - m->pos_;
993
cnt = JAS_MIN(n, cnt);
994
memcpy(buf, &m->buf_[m->pos_], cnt);
995
m->pos_ += cnt;
996
return cnt;
997
}
998
999
static int mem_resize(jas_stream_memobj_t *m, int bufsize)
1000
{
1001
unsigned char *buf;
1002
1003
assert(m->buf_);
1004
if (!(buf = jas_realloc(m->buf_, bufsize))) {
1005
return -1;
1006
}
1007
m->buf_ = buf;
1008
m->bufsize_ = bufsize;
1009
return 0;
1010
}
1011
1012
static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
1013
{
1014
int n;
1015
int ret;
1016
jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1017
long newbufsize;
1018
long newpos;
1019
1020
newpos = m->pos_ + cnt;
1021
if (newpos > m->bufsize_ && m->growable_) {
1022
newbufsize = m->bufsize_;
1023
while (newbufsize < newpos) {
1024
newbufsize <<= 1;
1025
assert(newbufsize >= 0);
1026
}
1027
if (mem_resize(m, newbufsize)) {
1028
return -1;
1029
}
1030
}
1031
if (m->pos_ > m->len_) {
1032
/* The current position is beyond the end of the file, so
1033
pad the file to the current position with zeros. */
1034
n = JAS_MIN(m->pos_, m->bufsize_) - m->len_;
1035
if (n > 0) {
1036
memset(&m->buf_[m->len_], 0, n);
1037
m->len_ += n;
1038
}
1039
if (m->pos_ != m->len_) {
1040
/* The buffer is not big enough. */
1041
return 0;
1042
}
1043
}
1044
n = m->bufsize_ - m->pos_;
1045
ret = JAS_MIN(n, cnt);
1046
if (ret > 0) {
1047
memcpy(&m->buf_[m->pos_], buf, ret);
1048
m->pos_ += ret;
1049
}
1050
if (m->pos_ > m->len_) {
1051
m->len_ = m->pos_;
1052
}
1053
assert(ret == cnt);
1054
return ret;
1055
}
1056
1057
static long mem_seek(jas_stream_obj_t *obj, long offset, int origin)
1058
{
1059
jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1060
long newpos;
1061
1062
switch (origin) {
1063
case SEEK_SET:
1064
newpos = offset;
1065
break;
1066
case SEEK_END:
1067
newpos = m->len_ - offset;
1068
break;
1069
case SEEK_CUR:
1070
newpos = m->pos_ + offset;
1071
break;
1072
default:
1073
abort();
1074
break;
1075
}
1076
if (newpos < 0) {
1077
return -1;
1078
}
1079
m->pos_ = newpos;
1080
1081
return m->pos_;
1082
}
1083
1084
static int mem_close(jas_stream_obj_t *obj)
1085
{
1086
jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
1087
if (m->myalloc_ && m->buf_) {
1088
jas_free(m->buf_);
1089
m->buf_ = 0;
1090
}
1091
jas_free(obj);
1092
return 0;
1093
}
1094
1095
/******************************************************************************\
1096
* File stream object.
1097
\******************************************************************************/
1098
1099
static int file_read(jas_stream_obj_t *obj, char *buf, int cnt)
1100
{
1101
jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1102
return read(fileobj->fd, buf, cnt);
1103
}
1104
1105
static int file_write(jas_stream_obj_t *obj, char *buf, int cnt)
1106
{
1107
jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1108
return write(fileobj->fd, buf, cnt);
1109
}
1110
1111
static long file_seek(jas_stream_obj_t *obj, long offset, int origin)
1112
{
1113
jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1114
return lseek(fileobj->fd, offset, origin);
1115
}
1116
1117
static int file_close(jas_stream_obj_t *obj)
1118
{
1119
jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
1120
int ret;
1121
ret = close(fileobj->fd);
1122
if (fileobj->flags & JAS_STREAM_FILEOBJ_DELONCLOSE) {
1123
unlink(fileobj->pathname);
1124
}
1125
jas_free(fileobj);
1126
return ret;
1127
}
1128
1129
/******************************************************************************\
1130
* Stdio file stream object.
1131
\******************************************************************************/
1132
1133
static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt)
1134
{
1135
FILE *fp;
1136
fp = JAS_CAST(FILE *, obj);
1137
return fread(buf, 1, cnt, fp);
1138
}
1139
1140
static int sfile_write(jas_stream_obj_t *obj, char *buf, int cnt)
1141
{
1142
FILE *fp;
1143
fp = JAS_CAST(FILE *, obj);
1144
return fwrite(buf, 1, cnt, fp);
1145
}
1146
1147
static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin)
1148
{
1149
FILE *fp;
1150
fp = JAS_CAST(FILE *, obj);
1151
return fseek(fp, offset, origin);
1152
}
1153
1154
static int sfile_close(jas_stream_obj_t *obj)
1155
{
1156
FILE *fp;
1157
fp = JAS_CAST(FILE *, obj);
1158
return fclose(fp);
1159
}
1160
1161