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