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