File indexing completed on 2025-01-05 03:57:11

0001 /* -*- C++ -*-
0002  * File: libraw_datastream.cpp
0003  * Copyright 2008-2021 LibRaw LLC (info@libraw.org)
0004  *
0005  * LibRaw C++ interface (implementation)
0006 
0007  LibRaw is free software; you can redistribute it and/or modify
0008  it under the terms of the one of two licenses as you choose:
0009 
0010 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0011    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0012 
0013 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0014    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0015 
0016 */
0017 
0018 #ifdef _WIN32
0019 #ifdef __MINGW32__
0020 #define _WIN32_WINNT 0x0500
0021 #include <stdexcept>
0022 #endif
0023 #endif
0024 
0025 #define LIBRAW_LIBRARY_BUILD
0026 #include "libraw/libraw.h"
0027 #include "libraw/libraw_types.h"
0028 #include "libraw/libraw_datastream.h"
0029 #include <sys/stat.h>
0030 #ifdef USE_JASPER
0031 #include <jasper/jasper.h> /* Decode RED camera movies */
0032 #else
0033 #define NO_JASPER
0034 #endif
0035 #ifdef USE_JPEG
0036 #include <jpeglib.h>
0037 #include <jerror.h>
0038 #else
0039 #define NO_JPEG
0040 #endif
0041 
0042 #ifdef USE_JPEG
0043 
0044 typedef struct
0045 {
0046     struct jpeg_source_mgr pub; /* public fields */
0047     LibRaw_abstract_datastream *instream;            /* source stream */
0048     JOCTET *buffer;             /* start of buffer */
0049     boolean start_of_file;      /* have we gotten any data yet? */
0050 } lr_jpg_source_mgr;
0051 
0052 typedef lr_jpg_source_mgr *lr_jpg_src_ptr;
0053 
0054 #define LR_JPEG_INPUT_BUF_SIZE 16384 
0055 
0056 static void f_init_source(j_decompress_ptr cinfo)
0057 {
0058     lr_jpg_src_ptr src = (lr_jpg_src_ptr)cinfo->src;
0059     src->start_of_file = TRUE;
0060 }
0061 
0062 #ifdef ERREXIT
0063 #undef ERREXIT
0064 #endif
0065 
0066 #define ERREXIT(cinfo, code)                                                   \
0067   ((cinfo)->err->msg_code = (code),                                            \
0068    (*(cinfo)->err->error_exit)((j_common_ptr)(cinfo)))
0069 
0070 static boolean lr_fill_input_buffer(j_decompress_ptr cinfo)
0071 {
0072     lr_jpg_src_ptr src = (lr_jpg_src_ptr)cinfo->src;
0073     size_t nbytes;
0074 
0075     nbytes = src->instream->read((void*)src->buffer, 1, LR_JPEG_INPUT_BUF_SIZE);
0076 
0077     if (nbytes <= 0)
0078     {
0079         if (src->start_of_file) /* Treat empty input file as fatal error */
0080             ERREXIT(cinfo, JERR_INPUT_EMPTY);
0081         WARNMS(cinfo, JWRN_JPEG_EOF);
0082         /* Insert a fake EOI marker */
0083         src->buffer[0] = (JOCTET)0xFF;
0084         src->buffer[1] = (JOCTET)JPEG_EOI;
0085         nbytes = 2;
0086     }
0087 
0088     src->pub.next_input_byte = src->buffer;
0089     src->pub.bytes_in_buffer = nbytes;
0090     src->start_of_file = FALSE;
0091     return TRUE;
0092 }
0093 
0094 static void lr_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
0095 {
0096     struct jpeg_source_mgr *src = cinfo->src;
0097     if (num_bytes > 0)
0098     {
0099         while (num_bytes > (long)src->bytes_in_buffer)
0100         {
0101             num_bytes -= (long)src->bytes_in_buffer;
0102             (void)(*src->fill_input_buffer)(cinfo);
0103             /* note we assume that fill_input_buffer will never return FALSE,
0104              * so suspension need not be handled.
0105              */
0106         }
0107         src->next_input_byte += (size_t)num_bytes;
0108         src->bytes_in_buffer -= (size_t)num_bytes;
0109     }
0110 }
0111 
0112 static void lr_term_source(j_decompress_ptr /*cinfo*/) {}
0113 
0114 static void lr_jpeg_src(j_decompress_ptr cinfo, LibRaw_abstract_datastream *inf)
0115 {
0116     lr_jpg_src_ptr src;
0117     if (cinfo->src == NULL)
0118     { /* first time for this JPEG object? */
0119         cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)(
0120             (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(lr_jpg_source_mgr));
0121         src = (lr_jpg_src_ptr)cinfo->src;
0122         src->buffer = (JOCTET *)(*cinfo->mem->alloc_small)(
0123             (j_common_ptr)cinfo, JPOOL_PERMANENT,
0124             LR_JPEG_INPUT_BUF_SIZE * sizeof(JOCTET));
0125     }
0126     else if (cinfo->src->init_source != f_init_source)
0127     {
0128         ERREXIT(cinfo, JERR_BUFFER_SIZE);
0129     }
0130 
0131     src = (lr_jpg_src_ptr)cinfo->src;
0132     src->pub.init_source = f_init_source;
0133     src->pub.fill_input_buffer = lr_fill_input_buffer;
0134     src->pub.skip_input_data = lr_skip_input_data;
0135     src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
0136     src->pub.term_source = lr_term_source;
0137     src->instream = inf;
0138     src->pub.bytes_in_buffer = 0;    /* forces fill_input_buffer on first read */
0139     src->pub.next_input_byte = NULL; /* until buffer loaded */
0140 }
0141 #endif
0142 
0143 int LibRaw_abstract_datastream::jpeg_src(void *jpegdata)
0144 {
0145 #ifdef NO_JPEG
0146     return -1;
0147 #else
0148     j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata;
0149     buffering_off();
0150     lr_jpeg_src(cinfo, this);
0151     return 0; // OK
0152 #endif
0153 }
0154 
0155 
0156 #ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
0157 // == LibRaw_file_datastream ==
0158 
0159 LibRaw_file_datastream::~LibRaw_file_datastream()
0160 {
0161   if (jas_file)
0162     fclose(jas_file);
0163 }
0164 
0165 LibRaw_file_datastream::LibRaw_file_datastream(const char *fname)
0166     : filename(fname), _fsize(0)
0167 #ifdef LIBRAW_WIN32_UNICODEPATHS
0168       ,
0169       wfilename()
0170 #endif
0171       ,
0172       jas_file(NULL)
0173 {
0174   if (filename.size() > 0)
0175   {
0176 #ifndef LIBRAW_WIN32_CALLS
0177     struct stat st;
0178     if (!stat(filename.c_str(), &st))
0179       _fsize = st.st_size;
0180 #else
0181     struct _stati64 st;
0182     if (!_stati64(filename.c_str(), &st))
0183       _fsize = st.st_size;
0184 #endif
0185 #ifdef LIBRAW_USE_AUTOPTR
0186     std::auto_ptr<std::filebuf> buf(new std::filebuf());
0187 #else
0188     std::unique_ptr<std::filebuf> buf(new std::filebuf());
0189 #endif
0190     buf->open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
0191     if (buf->is_open())
0192     {
0193 #ifdef LIBRAW_USE_AUTOPTR
0194       f = buf;
0195 #else
0196       f = std::move(buf);
0197 #endif
0198     }
0199   }
0200 }
0201 #ifdef LIBRAW_WIN32_UNICODEPATHS
0202 LibRaw_file_datastream::LibRaw_file_datastream(const wchar_t *fname)
0203     : filename(), wfilename(fname), jas_file(NULL), _fsize(0)
0204 {
0205   if (wfilename.size() > 0)
0206   {
0207     struct _stati64 st;
0208     if (!_wstati64(wfilename.c_str(), &st))
0209       _fsize = st.st_size;
0210 #ifdef LIBRAW_USE_AUTOPTR
0211     std::auto_ptr<std::filebuf> buf(new std::filebuf());
0212 #else
0213     std::unique_ptr<std::filebuf> buf(new std::filebuf());
0214 #endif
0215     buf->open(wfilename.c_str(), std::ios_base::in | std::ios_base::binary);
0216     if (buf->is_open())
0217     {
0218 #ifdef LIBRAW_USE_AUTOPTR
0219       f = buf;
0220 #else
0221       f = std::move(buf);
0222 #endif
0223     }
0224   }
0225 }
0226 const wchar_t *LibRaw_file_datastream::wfname()
0227 {
0228   return wfilename.size() > 0 ? wfilename.c_str() : NULL;
0229 }
0230 #endif
0231 
0232 int LibRaw_file_datastream::valid() { return f.get() ? 1 : 0; }
0233 
0234 #define LR_STREAM_CHK()                                                        \
0235   do                                                                           \
0236   {                                                                            \
0237     if (!f.get())                                                              \
0238       throw LIBRAW_EXCEPTION_IO_EOF;                                           \
0239   } while (0)
0240 
0241 int LibRaw_file_datastream::read(void *ptr, size_t size, size_t nmemb)
0242 {
0243 /* Visual Studio 2008 marks sgetn as insecure, but VS2010 does not. */
0244 #if defined(WIN32SECURECALLS) && (_MSC_VER < 1600)
0245   LR_STREAM_CHK();
0246   return int(f->_Sgetn_s(static_cast<char *>(ptr), nmemb * size, nmemb * size) /
0247              (size > 0 ? size : 1));
0248 #else
0249   LR_STREAM_CHK();
0250   return int(f->sgetn(static_cast<char *>(ptr), std::streamsize(nmemb * size)) /
0251              (size > 0 ? size : 1));
0252 #endif
0253 }
0254 
0255 int LibRaw_file_datastream::eof()
0256 {
0257   LR_STREAM_CHK();
0258   return f->sgetc() == EOF;
0259 }
0260 
0261 int LibRaw_file_datastream::seek(INT64 o, int whence)
0262 {
0263   LR_STREAM_CHK();
0264   std::ios_base::seekdir dir;
0265   switch (whence)
0266   {
0267   case SEEK_SET:
0268     dir = std::ios_base::beg;
0269     break;
0270   case SEEK_CUR:
0271     dir = std::ios_base::cur;
0272     break;
0273   case SEEK_END:
0274     dir = std::ios_base::end;
0275     break;
0276   default:
0277     dir = std::ios_base::beg;
0278   }
0279   return f->pubseekoff((long)o, dir) < 0;
0280 }
0281 
0282 INT64 LibRaw_file_datastream::tell()
0283 {
0284   LR_STREAM_CHK();
0285   return f->pubseekoff(0, std::ios_base::cur);
0286 }
0287 
0288 char *LibRaw_file_datastream::gets(char *str, int sz)
0289 {
0290   if(sz<1) return NULL;
0291   LR_STREAM_CHK();
0292   std::istream is(f.get());
0293   is.getline(str, sz);
0294   if (is.fail())
0295     return 0;
0296   return str;
0297 }
0298 
0299 int LibRaw_file_datastream::scanf_one(const char *fmt, void *val)
0300 {
0301   LR_STREAM_CHK();
0302 
0303   std::istream is(f.get());
0304 
0305   /* HUGE ASSUMPTION: *fmt is either "%d" or "%f" */
0306   if (strcmp(fmt, "%d") == 0)
0307   {
0308     int d;
0309     is >> d;
0310     if (is.fail())
0311       return EOF;
0312     *(static_cast<int *>(val)) = d;
0313   }
0314   else
0315   {
0316     float f;
0317     is >> f;
0318     if (is.fail())
0319       return EOF;
0320     *(static_cast<float *>(val)) = f;
0321   }
0322 
0323   return 1;
0324 }
0325 
0326 const char *LibRaw_file_datastream::fname()
0327 {
0328   return filename.size() > 0 ? filename.c_str() : NULL;
0329 }
0330 
0331 #undef LR_STREAM_CHK
0332 
0333 #ifdef LIBRAW_OLD_VIDEO_SUPPORT
0334 void *LibRaw_file_datastream::make_jas_stream()
0335 {
0336 #ifdef NO_JASPER
0337   return NULL;
0338 #else
0339 #ifdef LIBRAW_WIN32_UNICODEPATHS
0340   if (wfname())
0341   {
0342     jas_file = _wfopen(wfname(), L"rb");
0343     return jas_stream_fdopen(fileno(jas_file), "rb");
0344   }
0345   else
0346 #endif
0347   {
0348     return jas_stream_fopen(fname(), "rb");
0349   }
0350 #endif
0351 }
0352 #endif
0353 #endif
0354 
0355 // == LibRaw_buffer_datastream
0356 LibRaw_buffer_datastream::LibRaw_buffer_datastream(const void *buffer, size_t bsize)
0357 {
0358   buf = (unsigned char *)buffer;
0359   streampos = 0;
0360   streamsize = bsize;
0361 }
0362 
0363 LibRaw_buffer_datastream::~LibRaw_buffer_datastream() {}
0364 
0365 int LibRaw_buffer_datastream::read(void *ptr, size_t sz, size_t nmemb)
0366 {
0367   size_t to_read = sz * nmemb;
0368   if (to_read > streamsize - streampos)
0369     to_read = streamsize - streampos;
0370   if (to_read < 1)
0371     return 0;
0372   memmove(ptr, buf + streampos, to_read);
0373   streampos += to_read;
0374   return int((to_read + sz - 1) / (sz > 0 ? sz : 1));
0375 }
0376 
0377 int LibRaw_buffer_datastream::seek(INT64 o, int whence)
0378 {
0379   switch (whence)
0380   {
0381   case SEEK_SET:
0382     if (o < 0)
0383       streampos = 0;
0384     else if (size_t(o) > streamsize)
0385       streampos = streamsize;
0386     else
0387       streampos = size_t(o);
0388     return 0;
0389   case SEEK_CUR:
0390     if (o < 0)
0391     {
0392       if (size_t(-o) >= streampos)
0393         streampos = 0;
0394       else
0395         streampos += (size_t)o;
0396     }
0397     else if (o > 0)
0398     {
0399       if (o + streampos > streamsize)
0400         streampos = streamsize;
0401       else
0402         streampos += (size_t)o;
0403     }
0404     return 0;
0405   case SEEK_END:
0406     if (o > 0)
0407       streampos = streamsize;
0408     else if (size_t(-o) > streamsize)
0409       streampos = 0;
0410     else
0411       streampos = streamsize + (size_t)o;
0412     return 0;
0413   default:
0414     return 0;
0415   }
0416 }
0417 
0418 INT64 LibRaw_buffer_datastream::tell()
0419 {
0420   return INT64(streampos);
0421 }
0422 
0423 char *LibRaw_buffer_datastream::gets(char *s, int sz)
0424 {
0425   if(sz<1) return NULL;
0426   unsigned char *psrc, *pdest, *str;
0427   str = (unsigned char *)s;
0428   psrc = buf + streampos;
0429   pdest = str;
0430   if(streampos >= streamsize) return NULL;
0431   while ((size_t(psrc - buf) < streamsize) && ((pdest - str) < (sz-1)))
0432   {
0433     *pdest = *psrc;
0434     if (*psrc == '\n')
0435       break;
0436     psrc++;
0437     pdest++;
0438   }
0439   if (size_t(psrc - buf) < streamsize)
0440     psrc++;
0441   if ((pdest - str) < sz-1)
0442     *(++pdest) = 0;
0443   else
0444     s[sz - 1] = 0; // ensure trailing zero
0445 
0446   streampos = psrc - buf;
0447   return s;
0448 }
0449 
0450 int LibRaw_buffer_datastream::scanf_one(const char *fmt, void *val)
0451 {
0452   int scanf_res;
0453   if (streampos > streamsize)
0454     return 0;
0455 #ifndef WIN32SECURECALLS
0456   scanf_res = sscanf((char *)(buf + streampos), fmt, val);
0457 #else
0458   scanf_res = sscanf_s((char *)(buf + streampos), fmt, val);
0459 #endif
0460   if (scanf_res > 0)
0461   {
0462     int xcnt = 0;
0463     while (streampos < streamsize-1)
0464     {
0465       streampos++;
0466       xcnt++;
0467       if (buf[streampos] == 0 || buf[streampos] == ' ' ||
0468           buf[streampos] == '\t' || buf[streampos] == '\n' || xcnt > 24)
0469         break;
0470     }
0471   }
0472   return scanf_res;
0473 }
0474 
0475 int LibRaw_buffer_datastream::eof()
0476 {
0477   return streampos >= streamsize;
0478 }
0479 int LibRaw_buffer_datastream::valid() { return buf ? 1 : 0; }
0480 
0481 #ifdef LIBRAW_OLD_VIDEO_SUPPORT
0482 void *LibRaw_buffer_datastream::make_jas_stream()
0483 {
0484 #ifdef NO_JASPER
0485   return NULL;
0486 #else
0487   return jas_stream_memopen((char *)buf + streampos, streamsize - streampos);
0488 #endif
0489 }
0490 #endif
0491 
0492 int LibRaw_buffer_datastream::jpeg_src(void *jpegdata)
0493 {
0494 #if defined(NO_JPEG) || !defined(USE_JPEG)
0495   return -1;
0496 #else
0497   j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata;
0498   jpeg_mem_src(cinfo, (unsigned char *)buf + streampos,(unsigned long)(streamsize - streampos));
0499   return 0;
0500 #endif
0501 }
0502 
0503 // int LibRaw_buffer_datastream
0504 
0505 // == LibRaw_bigfile_datastream
0506 LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const char *fname)
0507     : filename(fname)
0508 #ifdef LIBRAW_WIN32_UNICODEPATHS
0509       ,
0510       wfilename()
0511 #endif
0512 {
0513   if (filename.size() > 0)
0514   {
0515 #ifndef LIBRAW_WIN32_CALLS
0516     struct stat st;
0517     if (!stat(filename.c_str(), &st))
0518       _fsize = st.st_size;
0519 #else
0520     struct _stati64 st;
0521     if (!_stati64(filename.c_str(), &st))
0522       _fsize = st.st_size;
0523 #endif
0524 
0525 #ifndef WIN32SECURECALLS
0526     f = fopen(fname, "rb");
0527 #else
0528     if (fopen_s(&f, fname, "rb"))
0529       f = 0;
0530 #endif
0531   }
0532   else
0533   {
0534     filename = std::string();
0535     f = 0;
0536   }
0537 }
0538 
0539 #ifdef LIBRAW_WIN32_UNICODEPATHS
0540 LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const wchar_t *fname)
0541     : filename(), wfilename(fname)
0542 {
0543   if (wfilename.size() > 0)
0544   {
0545     struct _stati64 st;
0546     if (!_wstati64(wfilename.c_str(), &st))
0547       _fsize = st.st_size;
0548 #ifndef WIN32SECURECALLS
0549     f = _wfopen(wfilename.c_str(), L"rb");
0550 #else
0551     if (_wfopen_s(&f, fname, L"rb"))
0552       f = 0;
0553 #endif
0554   }
0555   else
0556   {
0557     wfilename = std::wstring();
0558     f = 0;
0559   }
0560 }
0561 const wchar_t *LibRaw_bigfile_datastream::wfname()
0562 {
0563   return wfilename.size() > 0 ? wfilename.c_str() : NULL;
0564 }
0565 #endif
0566 
0567 LibRaw_bigfile_datastream::~LibRaw_bigfile_datastream()
0568 {
0569   if (f)
0570     fclose(f);
0571 }
0572 int LibRaw_bigfile_datastream::valid() { return f ? 1 : 0; }
0573 
0574 #define LR_BF_CHK()                                                            \
0575   do                                                                           \
0576   {                                                                            \
0577     if (!f)                                                                    \
0578       throw LIBRAW_EXCEPTION_IO_EOF;                                           \
0579   } while (0)
0580 
0581 int LibRaw_bigfile_datastream::read(void *ptr, size_t size, size_t nmemb)
0582 {
0583   LR_BF_CHK();
0584   return int(fread(ptr, size, nmemb, f));
0585 }
0586 
0587 int LibRaw_bigfile_datastream::eof()
0588 {
0589   LR_BF_CHK();
0590   return feof(f);
0591 }
0592 
0593 int LibRaw_bigfile_datastream::seek(INT64 o, int whence)
0594 {
0595   LR_BF_CHK();
0596 #if defined(_WIN32)
0597 #ifdef WIN32SECURECALLS
0598   return _fseeki64(f, o, whence);
0599 #else
0600   return fseek(f, (long)o, whence);
0601 #endif
0602 #else
0603   return fseeko(f, o, whence);
0604 #endif
0605 }
0606 
0607 INT64 LibRaw_bigfile_datastream::tell()
0608 {
0609   LR_BF_CHK();
0610 #if defined(_WIN32)
0611 #ifdef WIN32SECURECALLS
0612   return _ftelli64(f);
0613 #else
0614   return ftell(f);
0615 #endif
0616 #else
0617   return ftello(f);
0618 #endif
0619 }
0620 
0621 char *LibRaw_bigfile_datastream::gets(char *str, int sz)
0622 {
0623   if(sz<1) return NULL;
0624   LR_BF_CHK();
0625   return fgets(str, sz, f);
0626 }
0627 
0628 int LibRaw_bigfile_datastream::scanf_one(const char *fmt, void *val)
0629 {
0630   LR_BF_CHK();
0631   return 
0632 #ifndef WIN32SECURECALLS
0633                    fscanf(f, fmt, val)
0634 #else
0635                    fscanf_s(f, fmt, val)
0636 #endif
0637       ;
0638 }
0639 
0640 const char *LibRaw_bigfile_datastream::fname()
0641 {
0642   return filename.size() > 0 ? filename.c_str() : NULL;
0643 }
0644 
0645 #ifdef LIBRAW_OLD_VIDEO_SUPPORT
0646 void *LibRaw_bigfile_datastream::make_jas_stream()
0647 {
0648 #ifdef NO_JASPER
0649   return NULL;
0650 #else
0651   return jas_stream_fdopen(fileno(f), "rb");
0652 #endif
0653 }
0654 #endif
0655 
0656 // == LibRaw_windows_datastream
0657 #ifdef LIBRAW_WIN32_CALLS
0658 
0659 LibRaw_windows_datastream::LibRaw_windows_datastream(const TCHAR *sFile)
0660     : LibRaw_buffer_datastream(NULL, 0), hMap_(0), pView_(NULL)
0661 {
0662 #if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_APP) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
0663     HANDLE hFile = CreateFile2(sFile, GENERIC_READ, 0, OPEN_EXISTING, 0);
0664 #else
0665   HANDLE hFile = CreateFile(sFile, GENERIC_READ, 0, 0, OPEN_EXISTING,
0666                             FILE_ATTRIBUTE_NORMAL, 0);
0667 #endif
0668   if (hFile == INVALID_HANDLE_VALUE)
0669     throw std::runtime_error("failed to open the file");
0670 
0671   try
0672   {
0673     Open(hFile);
0674   }
0675   catch (...)
0676   {
0677     CloseHandle(hFile);
0678     throw;
0679   }
0680 
0681   CloseHandle(hFile); // windows will defer the actual closing of this handle
0682                       // until the hMap_ is closed
0683   reconstruct_base();
0684 }
0685 
0686 // ctor: construct with a file handle - caller is responsible for closing the
0687 // file handle
0688 LibRaw_windows_datastream::LibRaw_windows_datastream(HANDLE hFile)
0689     : LibRaw_buffer_datastream(NULL, 0), hMap_(0), pView_(NULL)
0690 {
0691   Open(hFile);
0692   reconstruct_base();
0693 }
0694 
0695 // dtor: unmap and close the mapping handle
0696 LibRaw_windows_datastream::~LibRaw_windows_datastream()
0697 {
0698   if (pView_ != NULL)
0699     ::UnmapViewOfFile(pView_);
0700 
0701   if (hMap_ != 0)
0702     ::CloseHandle(hMap_);
0703 }
0704 
0705 void LibRaw_windows_datastream::Open(HANDLE hFile)
0706 {
0707   // create a file mapping handle on the file handle
0708   hMap_ = ::CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0);
0709   if (hMap_ == NULL)
0710     throw std::runtime_error("failed to create file mapping");
0711 
0712   // now map the whole file base view
0713   if (!::GetFileSizeEx(hFile, (PLARGE_INTEGER)&cbView_))
0714     throw std::runtime_error("failed to get the file size");
0715 
0716   pView_ = ::MapViewOfFile(hMap_, FILE_MAP_READ, 0, 0, (size_t)cbView_);
0717   if (pView_ == NULL)
0718     throw std::runtime_error("failed to map the file");
0719 }
0720 
0721 #endif
0722 
0723 #if defined (LIBRAW_NO_IOSTREAMS_DATASTREAM)  && defined (LIBRAW_WIN32_CALLS)
0724 
0725 /* LibRaw_bigfile_buffered_datastream: copypasted from LibRaw_bigfile_datastream + extra cache on read */
0726 
0727 #undef LR_BF_CHK
0728 #define LR_BF_CHK()                                                    \
0729   do                                                                    \
0730   {                                                                     \
0731      if (fhandle ==0 || fhandle == INVALID_HANDLE_VALUE)                \
0732          throw LIBRAW_EXCEPTION_IO_EOF;                                 \
0733   } while (0)
0734 
0735 #define LIBRAW_BUFFER_ALIGN 4096
0736 
0737 int LibRaw_bufio_params::bufsize = 16384;
0738 
0739 void LibRaw_bufio_params::set_bufsize(int bs)
0740 {
0741     if (bs > 0)
0742         bufsize = bs;
0743 }
0744 
0745 
0746 LibRaw_bigfile_buffered_datastream::LibRaw_bigfile_buffered_datastream(const char *fname)
0747     : filename(fname), _fsize(0), _fpos(0)
0748 #ifdef LIBRAW_WIN32_UNICODEPATHS
0749     , wfilename()
0750 #endif
0751     , iobuffers(), buffered(1)
0752 {
0753     if (filename.size() > 0)
0754     {
0755         std::string fn(fname);
0756         std::wstring fpath(fn.begin(), fn.end());
0757 #if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_APP) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
0758         if ((fhandle = CreateFile2(fpath.c_str(), GENERIC_READ, 0, OPEN_EXISTING, 0)) != INVALID_HANDLE_VALUE)
0759 #else
0760         if ((fhandle = CreateFileW(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0,
0761             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
0762 #endif
0763         {
0764             LARGE_INTEGER fs;
0765             if (GetFileSizeEx(fhandle, &fs))
0766                 _fsize = fs.QuadPart;
0767         }
0768     }
0769     else
0770     {
0771         filename = std::string();
0772         fhandle = INVALID_HANDLE_VALUE;
0773     }
0774 }
0775 
0776 #ifdef LIBRAW_WIN32_UNICODEPATHS
0777 LibRaw_bigfile_buffered_datastream::LibRaw_bigfile_buffered_datastream(const wchar_t *fname)
0778     : filename(), _fsize(0), _fpos(0),
0779     wfilename(fname), iobuffers(), buffered(1)
0780 {
0781     if (wfilename.size() > 0)
0782     {
0783 #if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_APP) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
0784         if ((fhandle = CreateFile2(wfilename.c_str(), GENERIC_READ, 0, OPEN_EXISTING, 0)) != INVALID_HANDLE_VALUE)
0785 #else
0786         if ((fhandle = CreateFileW(wfilename.c_str(), GENERIC_READ, FILE_SHARE_READ, 0,
0787             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
0788 #endif
0789         {
0790             LARGE_INTEGER fs;
0791             if (GetFileSizeEx(fhandle, &fs))
0792                 _fsize = fs.QuadPart;
0793         }
0794 
0795     }
0796     else
0797     {
0798         wfilename = std::wstring();
0799         fhandle = INVALID_HANDLE_VALUE;
0800     }
0801 }
0802 
0803 const wchar_t *LibRaw_bigfile_buffered_datastream::wfname()
0804 {
0805     return wfilename.size() > 0 ? wfilename.c_str() : NULL;
0806 }
0807 #endif
0808 
0809 LibRaw_bigfile_buffered_datastream::~LibRaw_bigfile_buffered_datastream()
0810 {
0811     if (valid())
0812         CloseHandle(fhandle);
0813 }
0814 int LibRaw_bigfile_buffered_datastream::valid() {
0815     return (fhandle != NULL) && (fhandle != INVALID_HANDLE_VALUE);
0816 }
0817 
0818 const char *LibRaw_bigfile_buffered_datastream::fname()
0819 {
0820     return filename.size() > 0 ? filename.c_str() : NULL;
0821 }
0822 
0823 #ifdef LIBRAW_OLD_VIDEO_SUPPORT
0824 void *LibRaw_bigfile_buffered_datastream::make_jas_stream()
0825 {
0826 #ifdef NO_JASPER
0827     return NULL;
0828 #else
0829     return NULL;
0830 #endif
0831 }
0832 #endif
0833 
0834 INT64 LibRaw_bigfile_buffered_datastream::readAt(void *ptr, size_t size, INT64 off)
0835 {
0836     LR_BF_CHK();
0837     DWORD NumberOfBytesRead;
0838     DWORD nNumberOfBytesToRead = (DWORD)size;
0839     struct _OVERLAPPED olap;
0840     memset(&olap, 0, sizeof(olap));
0841     olap.Offset = off & 0xffffffff;
0842     olap.OffsetHigh = off >> 32;
0843     if (ReadFile(fhandle, ptr, nNumberOfBytesToRead, &NumberOfBytesRead, &olap))
0844         return NumberOfBytesRead;
0845     else
0846         return 0;
0847 }
0848 
0849 #define MAX(a, b) ((a) > (b) ? (a) : (b))
0850 #define MIN(a, b) ((a) < (b) ? (a) : (b))
0851 
0852 #ifdef _MSC_VER
0853 #pragma intrinsic(memcpy)
0854 #endif
0855 
0856 int LibRaw_bigfile_buffered_datastream::read(void *data, size_t size, size_t nmemb)
0857 {
0858     if (size < 1 || nmemb < 1)
0859         return 0;
0860     LR_BF_CHK();
0861     INT64 count = size * nmemb;
0862     INT64 partbytes = 0;
0863     if (!buffered)
0864     {
0865         INT64 r = readAt(data, count, _fpos);
0866         _fpos += r;
0867         return int(r / size);
0868     }
0869 
0870     unsigned char *fBuffer = (unsigned char*)iobuffers[0].data();
0871     while (count)
0872     {
0873         INT64 inbuffer = 0;
0874         // See if the request is totally inside buffer.
0875         if (iobuffers[0].contains(_fpos, inbuffer))
0876         {
0877             if (inbuffer >= count)
0878             {
0879                 memcpy(data, fBuffer + (unsigned)(_fpos - iobuffers[0]._bstart), count);
0880                 _fpos += count;
0881                 return int((count + partbytes) / size);
0882             }
0883             memcpy(data, fBuffer + (_fpos - iobuffers[0]._bstart), inbuffer);
0884             partbytes += inbuffer;
0885             count -= inbuffer;
0886             data = (void *)(((char *)data) + inbuffer);
0887             _fpos += inbuffer;
0888         }
0889         if (count > (INT64) iobuffers[0].size())
0890         {
0891         fallback:
0892             if (_fpos + count > _fsize)
0893                 count = MAX(0, _fsize - _fpos);
0894             if (count > 0)
0895             {
0896                 INT64 r = readAt(data, count, _fpos);
0897                 _fpos += r;
0898                 return int((r + partbytes) / size);
0899             }
0900             else
0901                 return 0;
0902         }
0903 
0904         if (!fillBufferAt(0, _fpos))
0905             goto fallback;
0906     }
0907     return 0;
0908 }
0909 
0910 bool LibRaw_bigfile_buffered_datastream::fillBufferAt(int bi, INT64 off)
0911 {
0912     if (off < 0LL) return false;
0913     iobuffers[bi]._bstart = off;
0914     if (iobuffers[bi].size() >= LIBRAW_BUFFER_ALIGN * 2)// Align to a file block.
0915         iobuffers[bi]._bstart &= (INT64)~((INT64)(LIBRAW_BUFFER_ALIGN - 1));
0916 
0917     iobuffers[bi]._bend = MIN(iobuffers[bi]._bstart + (INT64)iobuffers[bi].size(), _fsize);
0918     if (iobuffers[bi]._bend <= off) // Buffer alignment problem, fallback
0919         return false;
0920     INT64 rr = readAt(iobuffers[bi].data(), (uint32_t)(iobuffers[bi]._bend - iobuffers[bi]._bstart), iobuffers[bi]._bstart);
0921     if (rr > 0)
0922     {
0923         iobuffers[bi]._bend = iobuffers[bi]._bstart + rr;
0924         return true;
0925     }
0926     return false;
0927 }
0928 
0929 
0930 int LibRaw_bigfile_buffered_datastream::eof()
0931 {
0932     LR_BF_CHK();
0933     return _fpos >= _fsize;
0934 }
0935 
0936 int LibRaw_bigfile_buffered_datastream::seek(INT64 o, int whence)
0937 {
0938     LR_BF_CHK();
0939     if (whence == SEEK_SET) _fpos = o;
0940     else if (whence == SEEK_END) _fpos = o > 0 ? _fsize : _fsize + o;
0941     else if (whence == SEEK_CUR) _fpos += o;
0942     return 0;
0943 }
0944 
0945 INT64 LibRaw_bigfile_buffered_datastream::tell()
0946 {
0947     LR_BF_CHK();
0948     return _fpos;
0949 }
0950 
0951 char *LibRaw_bigfile_buffered_datastream::gets(char *s, int sz)
0952 {
0953     if (sz < 1)
0954         return NULL;
0955     else if (sz < 2)
0956     {
0957         s[0] = 0;
0958         return s;
0959     }
0960 
0961     LR_BF_CHK();
0962     INT64 contains;
0963     int bufindex = selectStringBuffer(sz, contains);
0964     if (bufindex < 0) return NULL;
0965     if (contains >= sz)
0966     {
0967         unsigned char *buf = iobuffers[bufindex].data() + (_fpos - iobuffers[bufindex]._bstart);
0968         int streampos = 0;
0969         int streamsize = contains;
0970         unsigned char *str = (unsigned char *)s;
0971         unsigned char *psrc, *pdest;
0972         psrc = buf + streampos;
0973         pdest = str;
0974 
0975         while ((size_t(psrc - buf) < streamsize) && ((pdest - str) < sz-1)) // sz-1: to append \0
0976         {
0977             *pdest = *psrc;
0978             if (*psrc == '\n')
0979                 break;
0980             psrc++;
0981             pdest++;
0982         }
0983         if (size_t(psrc - buf) < streamsize)
0984             psrc++;
0985         if ((pdest - str) < sz - 1)
0986             *(++pdest) = 0;
0987         else
0988             s[sz - 1] = 0; // ensure trailing zero
0989         streampos = psrc - buf;
0990         _fpos += streampos;
0991         return s;
0992     }
0993     return NULL;
0994 }
0995 
0996 int LibRaw_bigfile_buffered_datastream::selectStringBuffer(INT64 len, INT64& contains)
0997 {
0998     if (iobuffers[0].contains(_fpos, contains) && contains >= len)
0999         return 0;
1000 
1001     if (iobuffers[1].contains(_fpos, contains) && contains >= len)
1002         return 1;
1003 
1004     fillBufferAt(1, _fpos);
1005     if (iobuffers[1].contains(_fpos, contains) && contains >= len)
1006         return 1;
1007     return -1;
1008 }
1009 
1010 int LibRaw_bigfile_buffered_datastream::scanf_one(const char *fmt, void *val)
1011 {
1012     LR_BF_CHK();
1013     INT64 contains = 0;
1014     int bufindex = selectStringBuffer(24, contains);
1015     if (bufindex < 0) return -1;
1016     if (contains >= 24)
1017     {
1018         unsigned char *bstart = iobuffers[bufindex].data() + (_fpos - iobuffers[bufindex]._bstart);
1019         int streampos = 0;
1020         int streamsize = contains;
1021         int
1022 #ifndef WIN32SECURECALLS
1023             scanf_res = sscanf((char *)(bstart), fmt, val);
1024 #else
1025             scanf_res = sscanf_s((char *)(bstart), fmt, val);
1026 #endif
1027         if (scanf_res > 0)
1028         {
1029             int xcnt = 0;
1030             while (streampos < streamsize)
1031             {
1032                 streampos++;
1033                 xcnt++;
1034                 if (bstart[streampos] == 0 || bstart[streampos] == ' ' ||
1035                     bstart[streampos] == '\t' || bstart[streampos] == '\n' || xcnt > 24)
1036                     break;
1037             }
1038             _fpos += streampos;
1039             return scanf_res;
1040         }
1041     }
1042     return -1;
1043 }
1044 
1045 #endif
1046