From d12bf047b4802501a6a65feaee70bba8524fd400 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 9 Oct 2016 19:58:44 +0000 Subject: [PATCH] Update 58db06d8 to not even try to use std::fstream with Unicode paths. Unfortunately there is no portable way to open an Unicode path with std::fstream. On *nix, it is enough to call the const char* constructor. On MSVC, it is enough to call a nonstandard const wchar_t* constructor. However, on MinGW, there is no way at all to construct an std::fstream with a wide path, not even using undocumented APIs. (There used to be a const wchar_t* overload added back in libstdc++ 4.7, but it got removed for a reason that I was not able to find out.) --- src/exportvector.cpp | 12 ++++++------ src/importdxf.cpp | 10 ++++++---- src/platform/unixutil.cpp | 7 ------- src/platform/w32util.cpp | 8 -------- src/solvespace.h | 4 +++- src/util.cpp | 27 +++++++++++++++++++++++++++ test/harness.cpp | 20 ++++---------------- 7 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/exportvector.cpp b/src/exportvector.cpp index ebf71b17..594816dd 100644 --- a/src/exportvector.cpp +++ b/src/exportvector.cpp @@ -702,16 +702,16 @@ void DxfFileWriter::FinishAndCloseFile() { interface.writer = this; interface.dxf = &dxf; - std::fstream stream = ssfstream(filename, std::ios_base::out); - if(!stream.good()) { - Error("Couldn't write to '%s'", filename.c_str()); - return; - } - + std::stringstream stream; dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false); paths.clear(); constraint = NULL; + if(!WriteFile(filename, stream.str())) { + Error("Couldn't write to '%s'", filename.c_str()); + return; + } + if(!interface.messages.empty()) { std::string text = "Some aspects of the drawing have no DXF equivalent and " "were not exported:\n"; diff --git a/src/importdxf.cpp b/src/importdxf.cpp index 048537b8..c5be3aa5 100644 --- a/src/importdxf.cpp +++ b/src/importdxf.cpp @@ -903,13 +903,14 @@ void ImportDxf(const std::string &filename) { DxfReadInterface interface; interface.clearBlockTransform(); - std::fstream stream = ssfstream(filename, std::ios_base::in); - if(!stream.good()) { + std::string data; + if(!ReadFile(filename, &data)) { Error("Couldn't read from '%s'", filename.c_str()); return; } SS.UndoRemember(); + std::stringstream stream(data); if(!dxfRW().read(stream, &interface, /*ext=*/false)) { Error("Corrupted DXF file."); } @@ -924,13 +925,14 @@ void ImportDwg(const std::string &filename) { DxfReadInterface interface; interface.clearBlockTransform(); - std::fstream stream = ssfstream(filename, std::ios_base::in); - if(!stream.good()) { + std::string data; + if(!ReadFile(filename, &data)) { Error("Couldn't read from '%s'", filename.c_str()); return; } SS.UndoRemember(); + std::stringstream stream(data); if(!dwgR().read(stream, &interface, /*ext=*/false)) { Error("Corrupted DWG file."); } diff --git a/src/platform/unixutil.cpp b/src/platform/unixutil.cpp index 812e519d..f076cc99 100644 --- a/src/platform/unixutil.cpp +++ b/src/platform/unixutil.cpp @@ -82,13 +82,6 @@ FILE *ssfopen(const std::string &filename, const char *mode) return fopen(filename.c_str(), mode); } -std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode) -{ - ssassert(filename.length() == strlen(filename.c_str()), - "Unexpected null byte in middle of a path"); - return std::fstream(filename, mode); -} - void ssremove(const std::string &filename) { ssassert(filename.length() == strlen(filename.c_str()), diff --git a/src/platform/w32util.cpp b/src/platform/w32util.cpp index 65423601..3e08a897 100644 --- a/src/platform/w32util.cpp +++ b/src/platform/w32util.cpp @@ -136,14 +136,6 @@ FILE *ssfopen(const std::string &filename, const char *mode) return _wfopen(Widen(MakeUNCFilename(filename)).c_str(), Widen(mode).c_str()); } -std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode) -{ - std::string uncFilename = MakeUNCFilename(filename); - ssassert(filename.length() == strlen(filename.c_str()), - "Unexpected null byte in middle of a path"); - return std::fstream(Widen(MakeUNCFilename(filename)).c_str(), mode); -} - void ssremove(const std::string &filename) { ssassert(filename.length() == strlen(filename.c_str()), diff --git a/src/solvespace.h b/src/solvespace.h index 0fabf053..9b8a10f1 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include // We declare these in advance instead of simply using FT_Library // (defined as typedef FT_LibraryRec_* FT_Library) because including @@ -367,6 +367,8 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, double a41, double a42, double a43, double a44); std::string MakeAcceleratorLabel(int accel); bool FilenameHasExtension(const std::string &str, const char *ext); +bool ReadFile(const std::string &filename, std::string *data); +bool WriteFile(const std::string &filename, const std::string &data); void Message(const char *str, ...); void Error(const char *str, ...); void CnfFreezeBool(bool v, const std::string &name); diff --git a/src/util.cpp b/src/util.cpp index 34c14ba1..95ea2e52 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -61,6 +61,33 @@ bool SolveSpace::FilenameHasExtension(const std::string &str, const char *ext) return true; } +bool SolveSpace::ReadFile(const std::string &filename, std::string *data) +{ + FILE *f = ssfopen(filename.c_str(), "rb"); + if(f == NULL) + return false; + + fseek(f, 0, SEEK_END); + data->resize(ftell(f)); + fseek(f, 0, SEEK_SET); + fread(&(*data)[0], 1, data->size(), f); + fclose(f); + + return true; +} + +bool SolveSpace::WriteFile(const std::string &filename, const std::string &data) +{ + FILE *f = ssfopen(filename.c_str(), "wb"); + if(f == NULL) + return false; + + fwrite(&data[0], 1, data.size(), f); + fclose(f); + + return true; +} + int64_t SolveSpace::GetMilliseconds() { auto timestamp = std::chrono::steady_clock::now().time_since_epoch(); diff --git a/test/harness.cpp b/test/harness.cpp index 5df55dc6..3585c088 100644 --- a/test/harness.cpp +++ b/test/harness.cpp @@ -95,19 +95,6 @@ static std::string Colorize(Color color, std::string input) { return input; } -static std::string ReadFile(std::string path) { - std::string data; - FILE *f = ssfopen(path.c_str(), "rb"); - if(f) { - fseek(f, 0, SEEK_END); - data.resize(ftell(f)); - fseek(f, 0, SEEK_SET); - fread(&data[0], 1, data.size(), f); - fclose(f); - } - return data; -} - // Normalizes a savefile. Different platforms have slightly different floating-point // behavior, so if we want to compare savefiles byte-by-byte, we need to do something // to get rid of irrelevant differences in LSB. @@ -211,9 +198,10 @@ bool Test::Helper::CheckSave(const char *file, int line, const char *reference) ssprintf("saving file '%s'", refPath.c_str())); return false; } else { - std::string refData = PrepareSavefile(ReadFile(refPath)), - outData = PrepareSavefile(ReadFile(outPath)); - if(!RecordCheck(refData == outData)) { + std::string refData, outData; + ReadFile(refPath, &refData); + ReadFile(outPath, &outData); + if(!RecordCheck(PrepareSavefile(refData) == PrepareSavefile(outData))) { PrintFailure(file, line, "savefile doesn't match reference"); return false; }