1 : /******************************************************************************
2 : * $Id: jpeg2000_vsil_io.cpp 20996 2010-10-28 18:38:15Z rouault $
3 : *
4 : * Project: JPEG-2000
5 : * Purpose: Return a stream for a VSIL file
6 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
7 : *
8 : ******************************************************************************/
9 :
10 : /* Following code is mostly derived from jas_stream.c, which is licenced */
11 : /* under the below terms */
12 :
13 : /*
14 : * Copyright (c) 1999-2000 Image Power, Inc. and the University of
15 : * British Columbia.
16 : * Copyright (c) 2001-2003 Michael David Adams.
17 : * All rights reserved.
18 : */
19 :
20 : /* __START_OF_JASPER_LICENSE__
21 : *
22 : * JasPer License Version 2.0
23 : *
24 : * Copyright (c) 2001-2006 Michael David Adams
25 : * Copyright (c) 1999-2000 Image Power, Inc.
26 : * Copyright (c) 1999-2000 The University of British Columbia
27 : *
28 : * All rights reserved.
29 : *
30 : * Permission is hereby granted, free of charge, to any person (the
31 : * "User") obtaining a copy of this software and associated documentation
32 : * files (the "Software"), to deal in the Software without restriction,
33 : * including without limitation the rights to use, copy, modify, merge,
34 : * publish, distribute, and/or sell copies of the Software, and to permit
35 : * persons to whom the Software is furnished to do so, subject to the
36 : * following conditions:
37 : *
38 : * 1. The above copyright notices and this permission notice (which
39 : * includes the disclaimer below) shall be included in all copies or
40 : * substantial portions of the Software.
41 : *
42 : * 2. The name of a copyright holder shall not be used to endorse or
43 : * promote products derived from the Software without specific prior
44 : * written permission.
45 : *
46 : * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
47 : * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
48 : * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
49 : * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
50 : * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
51 : * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
52 : * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
53 : * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
54 : * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
55 : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
56 : * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
57 : * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
58 : * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
59 : * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
60 : * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
61 : * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
62 : * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
63 : * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
64 : * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
65 : * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
66 : * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
67 : * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
68 : * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
69 : * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
70 : * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
71 : * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
72 : *
73 : * __END_OF_JASPER_LICENSE__
74 : */
75 :
76 : #include "jpeg2000_vsil_io.h"
77 : #include "cpl_vsi.h"
78 :
79 : CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 20996 2010-10-28 18:38:15Z rouault $");
80 :
81 : /*
82 : * File descriptor file object.
83 : */
84 : typedef struct {
85 : VSILFILE* fp;
86 : } jas_stream_VSIFL_t;
87 :
88 : /******************************************************************************\
89 : * File stream object.
90 : \******************************************************************************/
91 :
92 1730 : static int JPEG2000_VSIL_read(jas_stream_obj_t *obj, char *buf, int cnt)
93 : {
94 1730 : jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
95 1730 : return VSIFReadL(buf, 1, cnt, fileobj->fp);
96 : }
97 :
98 11 : static int JPEG2000_VSIL_write(jas_stream_obj_t *obj, char *buf, int cnt)
99 : {
100 11 : jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
101 11 : return VSIFWriteL(buf, 1, cnt, fileobj->fp);
102 : }
103 :
104 30 : static long JPEG2000_VSIL_seek(jas_stream_obj_t *obj, long offset, int origin)
105 : {
106 30 : jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
107 30 : if (offset < 0 && origin == SEEK_CUR)
108 : {
109 0 : origin = SEEK_SET;
110 0 : offset += VSIFTellL(fileobj->fp);
111 : }
112 30 : else if (offset < 0 && origin == SEEK_END)
113 : {
114 0 : origin = SEEK_SET;
115 0 : VSIFSeekL(fileobj->fp, 0, SEEK_END);
116 0 : offset += VSIFTellL(fileobj->fp);
117 : }
118 30 : VSIFSeekL(fileobj->fp, offset, origin);
119 30 : return VSIFTellL(fileobj->fp);
120 : }
121 :
122 53 : static int JPEG2000_VSIL_close(jas_stream_obj_t *obj)
123 : {
124 53 : jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
125 53 : VSIFCloseL(fileobj->fp);
126 53 : fileobj->fp = NULL;
127 53 : jas_free(fileobj);
128 53 : return 0;
129 : }
130 :
131 : static jas_stream_ops_t JPEG2000_VSIL_stream_fileops = {
132 : JPEG2000_VSIL_read,
133 : JPEG2000_VSIL_write,
134 : JPEG2000_VSIL_seek,
135 : JPEG2000_VSIL_close
136 : };
137 :
138 : /******************************************************************************\
139 : * Code for opening and closing streams.
140 : \******************************************************************************/
141 :
142 55 : static jas_stream_t *JPEG2000_VSIL_jas_stream_create()
143 : {
144 : jas_stream_t *stream;
145 :
146 55 : if (!(stream = (jas_stream_t*) jas_malloc(sizeof(jas_stream_t)))) {
147 0 : return 0;
148 : }
149 55 : stream->openmode_ = 0;
150 55 : stream->bufmode_ = 0;
151 55 : stream->flags_ = 0;
152 55 : stream->bufbase_ = 0;
153 55 : stream->bufstart_ = 0;
154 55 : stream->bufsize_ = 0;
155 55 : stream->ptr_ = 0;
156 55 : stream->cnt_ = 0;
157 55 : stream->ops_ = 0;
158 55 : stream->obj_ = 0;
159 55 : stream->rwcnt_ = 0;
160 55 : stream->rwlimit_ = -1;
161 :
162 55 : return stream;
163 : }
164 :
165 2 : static void JPEG2000_VSIL_jas_stream_destroy(jas_stream_t *stream)
166 : {
167 : /* If the memory for the buffer was allocated with malloc, free
168 : this memory. */
169 2 : if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
170 0 : jas_free(stream->bufbase_);
171 0 : stream->bufbase_ = 0;
172 : }
173 2 : jas_free(stream);
174 2 : }
175 :
176 :
177 : /******************************************************************************\
178 : * Buffer initialization code.
179 : \******************************************************************************/
180 :
181 53 : static void JPEG2000_VSIL_jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
182 : int bufsize)
183 : {
184 : /* If this function is being called, the buffer should not have been
185 : initialized yet. */
186 53 : assert(!stream->bufbase_);
187 :
188 53 : if (bufmode != JAS_STREAM_UNBUF) {
189 : /* The full- or line-buffered mode is being employed. */
190 53 : if (!buf) {
191 : /* The caller has not specified a buffer to employ, so allocate
192 : one. */
193 53 : if ((stream->bufbase_ = (unsigned char*)jas_malloc(JAS_STREAM_BUFSIZE +
194 : JAS_STREAM_MAXPUTBACK))) {
195 53 : stream->bufmode_ |= JAS_STREAM_FREEBUF;
196 53 : stream->bufsize_ = JAS_STREAM_BUFSIZE;
197 : } else {
198 : /* The buffer allocation has failed. Resort to unbuffered
199 : operation. */
200 0 : stream->bufbase_ = stream->tinybuf_;
201 0 : stream->bufsize_ = 1;
202 : }
203 : } else {
204 : /* The caller has specified a buffer to employ. */
205 : /* The buffer must be large enough to accommodate maximum
206 : putback. */
207 0 : assert(bufsize > JAS_STREAM_MAXPUTBACK);
208 0 : stream->bufbase_ = JAS_CAST(uchar *, buf);
209 0 : stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
210 : }
211 : } else {
212 : /* The unbuffered mode is being employed. */
213 : /* A buffer should not have been supplied by the caller. */
214 0 : assert(!buf);
215 : /* Use a trivial one-character buffer. */
216 0 : stream->bufbase_ = stream->tinybuf_;
217 0 : stream->bufsize_ = 1;
218 : }
219 53 : stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
220 53 : stream->ptr_ = stream->bufstart_;
221 53 : stream->cnt_ = 0;
222 53 : stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
223 53 : }
224 :
225 55 : static int JPEG2000_VSIL_jas_strtoopenmode(const char *s)
226 : {
227 55 : int openmode = 0;
228 231 : while (*s != '\0') {
229 121 : switch (*s) {
230 : case 'r':
231 45 : openmode |= JAS_STREAM_READ;
232 45 : break;
233 : case 'w':
234 10 : openmode |= JAS_STREAM_WRITE | JAS_STREAM_CREATE;
235 10 : break;
236 : case 'b':
237 55 : openmode |= JAS_STREAM_BINARY;
238 55 : break;
239 : case 'a':
240 0 : openmode |= JAS_STREAM_APPEND;
241 0 : break;
242 : case '+':
243 11 : openmode |= JAS_STREAM_READ | JAS_STREAM_WRITE;
244 : break;
245 : default:
246 : break;
247 : }
248 121 : ++s;
249 : }
250 55 : return openmode;
251 : }
252 :
253 55 : jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode)
254 : {
255 : jas_stream_t *stream;
256 : jas_stream_VSIFL_t *obj;
257 :
258 : /* Allocate a stream object. */
259 55 : if (!(stream = JPEG2000_VSIL_jas_stream_create())) {
260 0 : return 0;
261 : }
262 :
263 : /* Parse the mode string. */
264 55 : stream->openmode_ = JPEG2000_VSIL_jas_strtoopenmode(mode);
265 :
266 : /* Allocate space for the underlying file stream object. */
267 55 : if (!(obj = (jas_stream_VSIFL_t*) jas_malloc(sizeof(jas_stream_VSIFL_t)))) {
268 0 : JPEG2000_VSIL_jas_stream_destroy(stream);
269 0 : return 0;
270 : }
271 55 : obj->fp = NULL;
272 55 : stream->obj_ = (void *) obj;
273 :
274 : /* Select the operations for a file stream object. */
275 55 : stream->ops_ = &JPEG2000_VSIL_stream_fileops;
276 :
277 : /* Open the underlying file. */
278 55 : if ((obj->fp = VSIFOpenL(filename, mode)) == NULL) {
279 2 : JPEG2000_VSIL_jas_stream_destroy(stream);
280 2 : return 0;
281 : }
282 :
283 : /* By default, use full buffering for this type of stream. */
284 53 : JPEG2000_VSIL_jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
285 :
286 53 : return stream;
287 : }
|