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.)
pull/33/merge
whitequark 2016-10-09 19:58:44 +00:00
parent fb87431ba5
commit d12bf047b4
7 changed files with 46 additions and 42 deletions

View File

@ -702,16 +702,16 @@ void DxfFileWriter::FinishAndCloseFile() {
interface.writer = this; interface.writer = this;
interface.dxf = &dxf; interface.dxf = &dxf;
std::fstream stream = ssfstream(filename, std::ios_base::out); std::stringstream stream;
if(!stream.good()) {
Error("Couldn't write to '%s'", filename.c_str());
return;
}
dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false); dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false);
paths.clear(); paths.clear();
constraint = NULL; constraint = NULL;
if(!WriteFile(filename, stream.str())) {
Error("Couldn't write to '%s'", filename.c_str());
return;
}
if(!interface.messages.empty()) { if(!interface.messages.empty()) {
std::string text = "Some aspects of the drawing have no DXF equivalent and " std::string text = "Some aspects of the drawing have no DXF equivalent and "
"were not exported:\n"; "were not exported:\n";

View File

@ -903,13 +903,14 @@ void ImportDxf(const std::string &filename) {
DxfReadInterface interface; DxfReadInterface interface;
interface.clearBlockTransform(); interface.clearBlockTransform();
std::fstream stream = ssfstream(filename, std::ios_base::in); std::string data;
if(!stream.good()) { if(!ReadFile(filename, &data)) {
Error("Couldn't read from '%s'", filename.c_str()); Error("Couldn't read from '%s'", filename.c_str());
return; return;
} }
SS.UndoRemember(); SS.UndoRemember();
std::stringstream stream(data);
if(!dxfRW().read(stream, &interface, /*ext=*/false)) { if(!dxfRW().read(stream, &interface, /*ext=*/false)) {
Error("Corrupted DXF file."); Error("Corrupted DXF file.");
} }
@ -924,13 +925,14 @@ void ImportDwg(const std::string &filename) {
DxfReadInterface interface; DxfReadInterface interface;
interface.clearBlockTransform(); interface.clearBlockTransform();
std::fstream stream = ssfstream(filename, std::ios_base::in); std::string data;
if(!stream.good()) { if(!ReadFile(filename, &data)) {
Error("Couldn't read from '%s'", filename.c_str()); Error("Couldn't read from '%s'", filename.c_str());
return; return;
} }
SS.UndoRemember(); SS.UndoRemember();
std::stringstream stream(data);
if(!dwgR().read(stream, &interface, /*ext=*/false)) { if(!dwgR().read(stream, &interface, /*ext=*/false)) {
Error("Corrupted DWG file."); Error("Corrupted DWG file.");
} }

View File

@ -82,13 +82,6 @@ FILE *ssfopen(const std::string &filename, const char *mode)
return fopen(filename.c_str(), 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) void ssremove(const std::string &filename)
{ {
ssassert(filename.length() == strlen(filename.c_str()), ssassert(filename.length() == strlen(filename.c_str()),

View File

@ -136,14 +136,6 @@ FILE *ssfopen(const std::string &filename, const char *mode)
return _wfopen(Widen(MakeUNCFilename(filename)).c_str(), Widen(mode).c_str()); 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) void ssremove(const std::string &filename)
{ {
ssassert(filename.length() == strlen(filename.c_str()), ssassert(filename.length() == strlen(filename.c_str()),

View File

@ -29,7 +29,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include <chrono> #include <chrono>
#include <fstream> #include <sstream>
// We declare these in advance instead of simply using FT_Library // We declare these in advance instead of simply using FT_Library
// (defined as typedef FT_LibraryRec_* FT_Library) because including // (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); double a41, double a42, double a43, double a44);
std::string MakeAcceleratorLabel(int accel); std::string MakeAcceleratorLabel(int accel);
bool FilenameHasExtension(const std::string &str, const char *ext); 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 Message(const char *str, ...);
void Error(const char *str, ...); void Error(const char *str, ...);
void CnfFreezeBool(bool v, const std::string &name); void CnfFreezeBool(bool v, const std::string &name);

View File

@ -61,6 +61,33 @@ bool SolveSpace::FilenameHasExtension(const std::string &str, const char *ext)
return true; 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() int64_t SolveSpace::GetMilliseconds()
{ {
auto timestamp = std::chrono::steady_clock::now().time_since_epoch(); auto timestamp = std::chrono::steady_clock::now().time_since_epoch();

View File

@ -95,19 +95,6 @@ static std::string Colorize(Color color, std::string input) {
return 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 // 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 // behavior, so if we want to compare savefiles byte-by-byte, we need to do something
// to get rid of irrelevant differences in LSB. // 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())); ssprintf("saving file '%s'", refPath.c_str()));
return false; return false;
} else { } else {
std::string refData = PrepareSavefile(ReadFile(refPath)), std::string refData, outData;
outData = PrepareSavefile(ReadFile(outPath)); ReadFile(refPath, &refData);
if(!RecordCheck(refData == outData)) { ReadFile(outPath, &outData);
if(!RecordCheck(PrepareSavefile(refData) == PrepareSavefile(outData))) {
PrintFailure(file, line, "savefile doesn't match reference"); PrintFailure(file, line, "savefile doesn't match reference");
return false; return false;
} }