Skip to content

Commit ad100c4

Browse files
committed
maybe?
Signed-off-by: Rosen Penev <[email protected]>
1 parent a7eb0f8 commit ad100c4

File tree

6 files changed

+89
-12
lines changed

6 files changed

+89
-12
lines changed

include/exiv2/basicio.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ class EXIV2API FileIo : public BasicIo {
310310
Nonzero if failure.
311311
*/
312312
int open(const std::string& mode);
313+
#ifdef _WIN32
314+
int open(const std::wstring& mode);
315+
#endif
313316
/*!
314317
@brief Open the file using the default access mode of "rb".
315318
This method can also be used to "reopen" a file which will flush
@@ -941,6 +944,9 @@ class EXIV2API CurlIo : public RemoteIo {
941944
@throw Error In case of failure.
942945
*/
943946
EXIV2API DataBuf readFile(const std::string& path);
947+
#ifdef _WIN32
948+
EXIV2API DataBuf readFile(const std::wstring& path);
949+
#endif
944950
/*!
945951
@brief Write DataBuf \em buf to file \em path.
946952
@return Return the number of bytes written.

include/exiv2/exif.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ class EXIV2API ExifThumb : public ExifThumbC {
303303
application that comes with OS X for one.) - David Harvey.
304304
*/
305305
void setJpegThumbnail(const std::string& path, URational xres, URational yres, uint16_t unit);
306+
#ifdef _WIN32
307+
void setJpegThumbnail(const std::wstring& path, URational xres, URational yres, uint16_t unit);
308+
#endif
306309
#endif
307310
/*!
308311
@brief Set the Exif thumbnail to the JPEG image pointed to by \em buf,

include/exiv2/image.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,9 @@ class EXIV2API ImageFactory {
586586
@throw Error If the image type is not supported.
587587
*/
588588
static Image::UniquePtr create(ImageType type, const std::string& path);
589+
#ifdef _WIN32
590+
static Image::UniquePtr create(ImageType type, const std::wstring& path);
591+
#endif
589592
/*!
590593
@brief Create an Image subclass of the requested type by creating a
591594
new image in memory.

src/basicio.cpp

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,11 @@ class FileIo::Impl {
7373
//! Mode of operation
7474
enum OpMode { opRead, opWrite, opSeek };
7575
// DATA
76-
fs::path path_; //!< (Standard) path
77-
std::string openMode_; //!< File open mode
78-
FILE* fp_{}; //!< File stream pointer
79-
OpMode opMode_{opSeek}; //!< File open mode
76+
fs::path path_; //!< (Standard) path
77+
std::string openMode_; //!< File open mode
78+
std::wstring wOpenMode_; //!< File open mode (wide)
79+
FILE* fp_{}; //!< File stream pointer
80+
OpMode opMode_{opSeek}; //!< File open mode
8081

8182
#if defined _WIN32
8283
HANDLE hFile_{}; //!< Duplicated fd
@@ -118,6 +119,19 @@ int FileIo::Impl::switchMode(OpMode opMode) {
118119

119120
bool reopen = true;
120121
switch (opMode) {
122+
#ifdef _WIN32
123+
case opRead:
124+
// Flush if current mode allows reading, else reopen (in mode "r+b"
125+
// as in this case we know that we can write to the file)
126+
if (wOpenMode_.front() == L'r' || wOpenMode_.at(1) == L'+')
127+
reopen = false;
128+
break;
129+
case opWrite:
130+
// Flush if current mode allows writing, else reopen
131+
if (wOpenMode_.front() != L'r' || wOpenMode_.at(1) == L'+')
132+
reopen = false;
133+
break;
134+
#else
121135
case opRead:
122136
// Flush if current mode allows reading, else reopen (in mode "r+b"
123137
// as in this case we know that we can write to the file)
@@ -129,6 +143,7 @@ int FileIo::Impl::switchMode(OpMode opMode) {
129143
if (openMode_.front() != 'r' || openMode_.at(1) == '+')
130144
reopen = false;
131145
break;
146+
#endif
132147
case opSeek:
133148
reopen = false;
134149
break;
@@ -339,7 +354,11 @@ size_t FileIo::write(BasicIo& src) {
339354

340355
void FileIo::transfer(BasicIo& src) {
341356
const bool wasOpen = (p_->fp_ != nullptr);
357+
#ifdef _WIN32
358+
const std::wstring lastMode(p_->wOpenMode_);
359+
#else
342360
const std::string lastMode(p_->openMode_);
361+
#endif
343362

344363
if (auto fileIo = dynamic_cast<FileIo*>(&src)) {
345364
// Optimization if src is another instance of FileIo
@@ -414,7 +433,7 @@ void FileIo::transfer(BasicIo& src) {
414433

415434
if (wasOpen) {
416435
if (open(lastMode) != 0) {
417-
throw Error(ErrorCode::kerFileOpenFailed, path(), lastMode, strError());
436+
throw Error(ErrorCode::kerFileOpenFailed, path(), strError());
418437
}
419438
} else
420439
close();
@@ -465,7 +484,11 @@ size_t FileIo::tell() const {
465484

466485
size_t FileIo::size() const {
467486
// Flush and commit only if the file is open for writing
487+
#ifdef _WIN32
488+
if (p_->fp_ && (p_->wOpenMode_.front() != L'r' || p_->wOpenMode_.at(1) == L'+')) {
489+
#else
468490
if (p_->fp_ && (p_->openMode_.front() != 'r' || p_->openMode_.at(1) == '+')) {
491+
#endif
469492
std::fflush(p_->fp_);
470493
#ifdef _MSC_VER
471494
// This is required on msvcrt before stat after writing to a file
@@ -481,26 +504,34 @@ size_t FileIo::size() const {
481504

482505
int FileIo::open() {
483506
// Default open is in read-only binary mode
507+
#ifdef _WIN32
508+
return open(L"rb");
509+
#else
484510
return open("rb");
511+
#endif
485512
}
486513

487514
int FileIo::open(const std::string& mode) {
488515
close();
489516
p_->openMode_ = mode;
490517
p_->opMode_ = Impl::opSeek;
491-
#ifdef _WIN32
492-
wchar_t wmode[10];
493-
MultiByteToWideChar(CP_UTF8, 0, mode.c_str(), -1, wmode, 10);
494-
if (_wfopen_s(&p_->fp_, p_->path_.c_str(), wmode))
495-
return 1;
496-
#else
497518
p_->fp_ = ::fopen(path().c_str(), mode.c_str());
498519
if (!p_->fp_)
499520
return 1;
500-
#endif
501521
return 0;
502522
}
503523

524+
#ifdef _WIN32
525+
int FileIo::open(const std::wstring& mode) {
526+
close();
527+
p_->wOpenMode_ = mode;
528+
p_->opMode_ = Impl::opSeek;
529+
if (_wfopen_s(&p_->fp_, p_->path_.c_str(), mode.c_str()))
530+
return 1;
531+
return 0;
532+
}
533+
#endif
534+
504535
bool FileIo::isopen() const {
505536
return p_->fp_ != nullptr;
506537
}
@@ -1647,6 +1678,17 @@ size_t writeFile(const DataBuf& buf, const std::string& path) {
16471678
}
16481679
return file.write(buf.c_data(), buf.size());
16491680
}
1681+
1682+
#ifdef _WIN32
1683+
DataBuf readFile(const std::wstring& path) {
1684+
FileIo file(path);
1685+
if (file.open(L"rb") != 0)
1686+
throw Error(ErrorCode::kerFileOpenFailed, "wb", strError());
1687+
DataBuf buf(static_cast<size_t>(fs::file_size(path)));
1688+
file.read(buf.data(), buf.size());
1689+
return buf;
1690+
}
1691+
#endif
16501692
#endif
16511693

16521694
#ifdef EXV_USE_CURL

src/exif.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,13 @@ void ExifThumb::setJpegThumbnail(const std::string& path, URational xres, URatio
411411
DataBuf thumb = readFile(path); // may throw
412412
setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit);
413413
}
414+
415+
#ifdef _WIN32
416+
void ExifThumb::setJpegThumbnail(const std::wstring& path, URational xres, URational yres, uint16_t unit) {
417+
DataBuf thumb = readFile(path); // may throw
418+
setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit);
419+
}
420+
#endif
414421
#endif
415422

416423
void ExifThumb::setJpegThumbnail(const byte* buf, size_t size, URational xres, URational yres, uint16_t unit) {

src/image.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,22 @@ Image::UniquePtr ImageFactory::create(ImageType type, const std::string& path) {
879879
throw Error(ErrorCode::kerUnsupportedImageType, static_cast<int>(type));
880880
return image;
881881
}
882+
883+
#ifdef _WIN32
884+
Image::UniquePtr ImageFactory::create(ImageType type, const std::wstring& path) {
885+
auto fileIo = std::make_unique<FileIo>(path);
886+
// Create or overwrite the file, then close it
887+
if (fileIo->open(L"w+b") != 0)
888+
throw Error(ErrorCode::kerFileOpenFailed, "w+b", strError());
889+
fileIo->close();
890+
891+
BasicIo::UniquePtr io(std::move(fileIo));
892+
auto image = create(type, std::move(io));
893+
if (!image)
894+
throw Error(ErrorCode::kerUnsupportedImageType, static_cast<int>(type));
895+
return image;
896+
}
897+
#endif
882898
#endif
883899

884900
Image::UniquePtr ImageFactory::create(ImageType type) {

0 commit comments

Comments
 (0)