/src/LibRaw/libraw/libraw_datastream.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- C -*- |
2 | | * File: libraw_datastream.h |
3 | | * Copyright 2008-2024 LibRaw LLC (info@libraw.org) |
4 | | * Created: Sun Jan 18 13:07:35 2009 |
5 | | * |
6 | | * LibRaw Data stream interface |
7 | | |
8 | | LibRaw is free software; you can redistribute it and/or modify |
9 | | it under the terms of the one of two licenses as you choose: |
10 | | |
11 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
12 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
13 | | |
14 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
15 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
16 | | |
17 | | */ |
18 | | |
19 | | #ifndef __LIBRAW_DATASTREAM_H |
20 | | #define __LIBRAW_DATASTREAM_H |
21 | | |
22 | | #include <stdio.h> |
23 | | #include <sys/types.h> |
24 | | #include <errno.h> |
25 | | #include <string.h> |
26 | | |
27 | | #ifndef __cplusplus |
28 | | |
29 | | #else /* __cplusplus */ |
30 | | #if defined _WIN32 |
31 | | #ifndef LIBRAW_NO_WINSOCK2 |
32 | | #ifdef NOMINMAX |
33 | | #define LIBRAW_NO_UNDEF_NOMINMAX |
34 | | #else |
35 | | #define NOMINMAX |
36 | | #endif |
37 | | |
38 | | #include <winsock2.h> |
39 | | |
40 | | #ifndef LIBRAW_NO_UNDEF_NOMINMAX |
41 | | #undef NOMINMAX /* restore previous mode*/ |
42 | | #endif |
43 | | #undef LIBRAW_NO_UNDEF_NOMINMAX |
44 | | #endif |
45 | | #endif |
46 | | /* No unique_ptr on Apple ?? */ |
47 | | #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) || \ |
48 | | (defined(_MSC_VER) && _MSVC_LANG >= 201103L) |
49 | | /* OK - use unique_ptr unless LIBRAW_USE_AUTOPTR defined externally*/ |
50 | | #else |
51 | | /* Force to use auto_ptr */ |
52 | | #ifndef LIBRAW_USE_AUTOPTR |
53 | | #define LIBRAW_USE_AUTOPTR |
54 | | #endif |
55 | | #endif |
56 | | |
57 | | #include "libraw_const.h" |
58 | | #include "libraw_types.h" |
59 | | #include <fstream> |
60 | | #include <memory> |
61 | | #include <vector> |
62 | | |
63 | | #if defined(_WIN32) && (_MSC_VER) >= 1500 |
64 | | #define WIN32SECURECALLS |
65 | | #endif |
66 | | |
67 | | #ifdef USE_DNGSDK |
68 | | |
69 | | #if defined LIBRAW_WIN32_CALLS |
70 | | #define qWinOS 1 |
71 | | #define qMacOS 0 |
72 | | #elif defined(__APPLE__) |
73 | | #define qWinOS 0 |
74 | | #define qMacOS 1 |
75 | | #else |
76 | | /* define OS types for DNG here */ |
77 | | #endif |
78 | | #define qDNGXMPDocOps 0 |
79 | | #define qDNGUseLibJPEG 1 |
80 | | #define qDNGXMPFiles 0 |
81 | | #define qDNGExperimental 1 |
82 | | #define qDNGThreadSafe 1 |
83 | | #include "dng_stream.h" |
84 | | #endif /* DNGSDK */ |
85 | | |
86 | | #define IOERROR() \ |
87 | | do \ |
88 | | { \ |
89 | | throw LIBRAW_EXCEPTION_IO_EOF; \ |
90 | | } while (0) |
91 | | |
92 | | class LibRaw_buffer_datastream; |
93 | | class LibRaw_bit_buffer; |
94 | | |
95 | | class DllDef LibRaw_abstract_datastream |
96 | | { |
97 | | public: |
98 | 25.6k | LibRaw_abstract_datastream() { }; |
99 | 25.6k | virtual ~LibRaw_abstract_datastream(void) { } |
100 | | virtual int valid() = 0; |
101 | | virtual int read(void *, size_t, size_t) = 0; |
102 | | virtual int seek(INT64, int) = 0; |
103 | | virtual INT64 tell() = 0; |
104 | | virtual INT64 size() = 0; |
105 | | virtual int get_char() = 0; |
106 | | virtual char *gets(char *, int) = 0; |
107 | | virtual int scanf_one(const char *, void *) = 0; |
108 | | virtual int eof() = 0; |
109 | | virtual int jpeg_src(void *); |
110 | 0 | virtual void buffering_off() {} |
111 | 0 | virtual void buffering_on() {} |
112 | 0 | virtual bool is_buffered() { return false; } |
113 | | /* reimplement in subclass to use parallel access in xtrans_load_raw() if |
114 | | * OpenMP is not used */ |
115 | 1.74k | virtual int lock() { return 1; } /* success */ |
116 | 1.74k | virtual void unlock() {} |
117 | 1.74k | virtual const char *fname() { return NULL; }; |
118 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
119 | | virtual const wchar_t *wfname() { return NULL; }; |
120 | | #endif |
121 | | }; |
122 | | |
123 | | #ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM |
124 | | |
125 | | #ifdef LIBRAW_WIN32_DLLDEFS |
126 | | #ifdef LIBRAW_USE_AUTOPTR |
127 | | template class DllDef std::auto_ptr<std::streambuf>; |
128 | | #else |
129 | | template class DllDef std::unique_ptr<std::streambuf>; |
130 | | #endif |
131 | | #endif |
132 | | |
133 | | class DllDef LibRaw_file_datastream : public LibRaw_abstract_datastream |
134 | | { |
135 | | protected: |
136 | | #ifdef LIBRAW_USE_AUTOPTR |
137 | | std::auto_ptr<std::streambuf> f; /* will close() automatically through dtor */ |
138 | | #else |
139 | | std::unique_ptr<std::streambuf> f; |
140 | | #endif |
141 | | std::string filename; |
142 | | INT64 _fsize; |
143 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
144 | | std::wstring wfilename; |
145 | | #endif |
146 | | |
147 | | public: |
148 | | virtual ~LibRaw_file_datastream(); |
149 | | LibRaw_file_datastream(const char *fname); |
150 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
151 | | LibRaw_file_datastream(const wchar_t *fname); |
152 | | #endif |
153 | | virtual int valid(); |
154 | | virtual int read(void *ptr, size_t size, size_t nmemb); |
155 | | virtual int eof(); |
156 | | virtual int seek(INT64 o, int whence); |
157 | | virtual INT64 tell(); |
158 | | virtual INT64 size() { return _fsize; } |
159 | | virtual int get_char() {return f->sbumpc();} |
160 | | virtual char *gets(char *str, int sz); |
161 | | virtual int scanf_one(const char *fmt, void *val); |
162 | | virtual const char *fname(); |
163 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
164 | | virtual const wchar_t *wfname(); |
165 | | #endif |
166 | | }; |
167 | | #endif |
168 | | |
169 | | #if defined (LIBRAW_NO_IOSTREAMS_DATASTREAM) && defined (LIBRAW_WIN32_CALLS) |
170 | | |
171 | | struct DllDef LibRaw_bufio_params |
172 | | { |
173 | | static int bufsize; |
174 | | static void set_bufsize(int bs); |
175 | | }; |
176 | | |
177 | | class buffer_t : public std::vector<unsigned char> |
178 | | { |
179 | | public: |
180 | | INT64 _bstart, _bend; |
181 | | buffer_t() : std::vector<unsigned char>(LibRaw_bufio_params::bufsize), _bstart(0), _bend(0) {} |
182 | | int charOReof(INT64 _fpos) |
183 | | { |
184 | | if (_bstart < 0LL || _bend < 0LL || _bend < _bstart || _fpos < 0LL) |
185 | | return -1; |
186 | | if ((_bend - _bstart) > (INT64)size()) |
187 | | return -1; |
188 | | if (_fpos >= _bstart && _fpos < _bend) |
189 | | return data()[_fpos - _bstart]; |
190 | | return -1; |
191 | | } |
192 | | bool contains(INT64 _fpos, INT64& contains) |
193 | | { |
194 | | if (_bstart < 0LL || _bend < 0LL || _bend < _bstart || _fpos < 0LL) |
195 | | { |
196 | | contains = 0; |
197 | | return false; |
198 | | } |
199 | | if ((_bend - _bstart) > (INT64)size()) |
200 | | { |
201 | | contains = 0; |
202 | | return false; |
203 | | } |
204 | | if (_fpos >= _bstart && _fpos < _bend) |
205 | | { |
206 | | contains = _bend - _fpos; |
207 | | return true; |
208 | | } |
209 | | contains = 0; |
210 | | return false; |
211 | | } |
212 | | }; |
213 | | |
214 | | |
215 | | class DllDef LibRaw_bigfile_buffered_datastream : public LibRaw_abstract_datastream |
216 | | { |
217 | | public: |
218 | | LibRaw_bigfile_buffered_datastream(const char *fname); |
219 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
220 | | LibRaw_bigfile_buffered_datastream(const wchar_t *fname); |
221 | | #endif |
222 | | virtual ~LibRaw_bigfile_buffered_datastream(); |
223 | | virtual int valid(); |
224 | | virtual void buffering_off() { buffered = 0; } |
225 | | virtual void buffering_on() { buffered = 1; } |
226 | | virtual bool is_buffered() { return buffered; } |
227 | | virtual int read(void *ptr, size_t size, size_t nmemb); |
228 | | virtual int eof(); |
229 | | virtual int seek(INT64 o, int whence); |
230 | | virtual INT64 tell(); |
231 | | virtual INT64 size() { return _fsize; } |
232 | | virtual char *gets(char *str, int sz); |
233 | | virtual int scanf_one(const char *fmt, void *val); |
234 | | virtual const char *fname(); |
235 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
236 | | virtual const wchar_t *wfname(); |
237 | | #endif |
238 | | virtual int get_char() |
239 | | { |
240 | | int r = iobuffers[0].charOReof(_fpos); |
241 | | if (r >= 0) |
242 | | { |
243 | | _fpos++; |
244 | | return r; |
245 | | } |
246 | | unsigned char c; |
247 | | r = read(&c, 1, 1); |
248 | | return r > 0 ? c : r; |
249 | | } |
250 | | |
251 | | protected: |
252 | | INT64 readAt(void *ptr, size_t size, INT64 off); |
253 | | bool fillBufferAt(int buf, INT64 off); |
254 | | int selectStringBuffer(INT64 len, INT64& contains); |
255 | | HANDLE fhandle; |
256 | | INT64 _fsize; |
257 | | INT64 _fpos; /* current file position; current buffer start position */ |
258 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
259 | | std::wstring wfilename; |
260 | | #endif |
261 | | std::string filename; |
262 | | buffer_t iobuffers[2]; |
263 | | int buffered; |
264 | | }; |
265 | | |
266 | | #endif |
267 | | |
268 | | class DllDef LibRaw_buffer_datastream : public LibRaw_abstract_datastream |
269 | | { |
270 | | public: |
271 | | LibRaw_buffer_datastream(const void *buffer, size_t bsize); |
272 | | virtual ~LibRaw_buffer_datastream(); |
273 | | virtual int valid(); |
274 | | virtual int jpeg_src(void *jpegdata); |
275 | | virtual int read(void *ptr, size_t sz, size_t nmemb); |
276 | | virtual int eof(); |
277 | | virtual int seek(INT64 o, int whence); |
278 | | virtual INT64 tell(); |
279 | 0 | virtual INT64 size() { return streamsize; } |
280 | | virtual char *gets(char *s, int sz); |
281 | | virtual int scanf_one(const char *fmt, void *val); |
282 | | virtual int get_char() |
283 | 0 | { |
284 | 0 | if (streampos >= streamsize) return -1; |
285 | 0 | return buf[streampos++]; |
286 | 0 | } |
287 | | |
288 | | private: |
289 | | unsigned char *buf; |
290 | | size_t streampos, streamsize; |
291 | | }; |
292 | | |
293 | | class DllDef LibRaw_bigfile_datastream : public LibRaw_abstract_datastream |
294 | | { |
295 | | public: |
296 | | LibRaw_bigfile_datastream(const char *fname); |
297 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
298 | | LibRaw_bigfile_datastream(const wchar_t *fname); |
299 | | #endif |
300 | | virtual ~LibRaw_bigfile_datastream(); |
301 | | virtual int valid(); |
302 | | virtual int read(void *ptr, size_t size, size_t nmemb); |
303 | | virtual int eof(); |
304 | | virtual int seek(INT64 o, int whence); |
305 | | virtual INT64 tell(); |
306 | 0 | virtual INT64 size() { return _fsize; } |
307 | | virtual char *gets(char *str, int sz); |
308 | | virtual int scanf_one(const char *fmt, void *val); |
309 | | virtual const char *fname(); |
310 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
311 | | virtual const wchar_t *wfname(); |
312 | | #endif |
313 | | virtual int get_char() |
314 | 0 | { |
315 | 0 | #ifndef LIBRAW_WIN32_CALLS |
316 | 0 | return getc_unlocked(f); |
317 | | #else |
318 | | return fgetc(f); |
319 | | #endif |
320 | 0 | } |
321 | | |
322 | | protected: |
323 | | FILE *f; |
324 | | std::string filename; |
325 | | INT64 _fsize; |
326 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
327 | | std::wstring wfilename; |
328 | | #endif |
329 | | }; |
330 | | |
331 | | #ifdef LIBRAW_WIN32_CALLS |
332 | | class DllDef LibRaw_windows_datastream : public LibRaw_buffer_datastream |
333 | | { |
334 | | public: |
335 | | /* ctor: high level constructor opens a file by name */ |
336 | | LibRaw_windows_datastream(const TCHAR *sFile); |
337 | | /* ctor: construct with a file handle - caller is responsible for closing the |
338 | | * file handle */ |
339 | | LibRaw_windows_datastream(HANDLE hFile); |
340 | | /* dtor: unmap and close the mapping handle */ |
341 | | virtual ~LibRaw_windows_datastream(); |
342 | | virtual INT64 size() { return cbView_; } |
343 | | |
344 | | protected: |
345 | | void Open(HANDLE hFile); |
346 | | inline void reconstruct_base() |
347 | | { |
348 | | /* this subterfuge is to overcome the private-ness of |
349 | | * LibRaw_buffer_datastream */ |
350 | | (LibRaw_buffer_datastream &)*this = |
351 | | LibRaw_buffer_datastream(pView_, (size_t)cbView_); |
352 | | } |
353 | | |
354 | | HANDLE hMap_; /* handle of the file mapping */ |
355 | | void *pView_; /* pointer to the mapped memory */ |
356 | | __int64 cbView_; /* size of the mapping in bytes */ |
357 | | }; |
358 | | |
359 | | #endif |
360 | | |
361 | | #ifdef USE_DNGSDK |
362 | | |
363 | | class libraw_dng_stream : public dng_stream |
364 | | { |
365 | | public: |
366 | | libraw_dng_stream(LibRaw_abstract_datastream *p) |
367 | | : dng_stream((dng_abort_sniffer *)NULL, kBigBufferSize, 0), |
368 | | parent_stream(p) |
369 | | { |
370 | | if (parent_stream) |
371 | | { |
372 | | parent_buffered = parent_stream->is_buffered(); |
373 | | parent_stream->buffering_off(); |
374 | | off = parent_stream->tell(); |
375 | | parent_stream->seek(0UL, SEEK_SET); /* seek to start */ |
376 | | } |
377 | | } |
378 | | ~libraw_dng_stream() |
379 | | { |
380 | | if (parent_stream) |
381 | | { |
382 | | if (parent_buffered) |
383 | | parent_stream->buffering_on(); |
384 | | parent_stream->seek(off, SEEK_SET); |
385 | | } |
386 | | } |
387 | | virtual uint64 DoGetLength() |
388 | | { |
389 | | if (parent_stream) |
390 | | return parent_stream->size(); |
391 | | return 0; |
392 | | } |
393 | | virtual void DoRead(void *data, uint32 count, uint64 offset) |
394 | | { |
395 | | if (parent_stream) |
396 | | { |
397 | | parent_stream->seek(offset, SEEK_SET); |
398 | | parent_stream->read(data, 1, count); |
399 | | } |
400 | | } |
401 | | |
402 | | private: |
403 | | libraw_dng_stream(const libraw_dng_stream &stream); |
404 | | libraw_dng_stream &operator=(const libraw_dng_stream &stream); |
405 | | LibRaw_abstract_datastream *parent_stream; |
406 | | INT64 off; |
407 | | bool parent_buffered; |
408 | | }; |
409 | | |
410 | | #endif |
411 | | |
412 | | #endif /* cplusplus */ |
413 | | |
414 | | #endif |