Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encode to/from utf8 when storing/loading path from json #82

Merged
merged 2 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/core/fileutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,63 @@ static bool getFileMTime(const std::string& path, std::chrono::system_clock::tim
return getFileMTime(path.c_str(), tp);
}

#ifdef WIN32
// for now we use ANSI paths on windows, so we have to convert ANSI -> UTF8
static std::string pathToUTF8(const std::string& s)
{
std::wstring wbuf;
std::string res;
// ansi -> wstring
int wlen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, NULL, 0);
if (wlen < 1) // error
return res;
wbuf.resize(wlen); // resize to incl NUL, since the implicit NUL can not be written
wlen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wbuf.data(), wbuf.size());
if (wlen < 1) // error
return res;
wbuf.resize(wlen - 1); // cut terminating NUL
// wstring -> utf8
int len = WideCharToMultiByte(CP_UTF8, 0, wbuf.c_str(), -1, NULL, 0, NULL, NULL);
if (len < 1) // error
return res;
res.resize(len);
len = WideCharToMultiByte(CP_UTF8, 0, wbuf.c_str(), -1, res.data(), res.size(), NULL, NULL);
if (len < 1) // error
res.resize(0);
else
res.resize(len - 1); // cut terminating NUL
return res;
}

static std::string pathFromUTF8(const std::string& s)
{
std::wstring wbuf;
std::string res;
// utf8 -> wstring
int wlen = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0);
if (wlen < 1) // error
return res;
wbuf.resize(wlen); // resize to incl NUL, since the implicit NUL can not be written
wlen = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, wbuf.data(), wbuf.size());
if (wlen < 1) // error
return res;
wbuf.resize(wlen - 1); // cut terminating NUL
// wstring -> ansi
int len = WideCharToMultiByte(CP_ACP, 0, wbuf.c_str(), -1, NULL, 0, NULL, NULL);
if (len < 1) // error
return res;
res.resize(len);
len = WideCharToMultiByte(CP_ACP, 0, wbuf.c_str(), -1, res.data(), res.size(), NULL, NULL);
if (len < 1) // error
res.resize(0);
else
res.resize(len - 1); // cut terminating NUL
return res;
}
#else // non-WIN32
// on non-windows paths are expected to be UTF8
#define pathToUTF8(s) (s)
#define pathFromUTF8(s) (s)
#endif

#endif // _CORE_FILEUTIL_H
15 changes: 10 additions & 5 deletions src/core/statemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ bool StateManager::saveState(Tracker* tracker, ScriptHost*,
}
state["ui_hints"] = jUiHints;
state["pack"] = {
{ "path", pack->getPath() },
{ "path", pathToUTF8(pack->getPath()) },
{ "uid", pack->getUID() },
{ "variant", pack->getVariant() },
{ "version", pack->getVersion() },
Expand All @@ -77,10 +77,15 @@ bool StateManager::saveState(Tracker* tracker, ScriptHost*,
}
printf("Saving state \"%s\" to file %s...\n",
external ? "export" : name.c_str(), filename.c_str());
std::string new_state = state.dump();
std::string old_state;
if (!readFile(filename, old_state) || old_state != new_state)
return writeFile(filename, new_state);
try {
std::string new_state = state.dump();
std::string old_state;
if (!readFile(filename, old_state) || old_state != new_state)
return writeFile(filename, new_state);
} catch (std::exception& ex) {
fprintf(stderr, "error saving: %s\n", ex.what());
return false;
}
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ int main(int argc, char** argv)
// argc/argv should be empty here. we pass everything through json args
json args = json::object();
if (packPath) {
args["pack"] = { {"path", packPath} };
args["pack"] = { {"path", pathToUTF8(packPath)} };
} else if (loadPack) {
args["pack"] = { {"uid", loadPack} };
}
Expand Down
18 changes: 9 additions & 9 deletions src/poptracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ PopTracker::PopTracker(int argc, char** argv, bool cli, const json& args)
_config["software_fps_limit"] = DEFAULT_SOFTWARE_FPS_LIMIT;

if (_config["export_file"].is_string() && _config["export_uid"].is_string()) {
_exportFile = _config["export_file"];
_exportFile = pathFromUTF8(_config["export_file"]);
_exportUID = _config["export_uid"];
}

if (_config["export_dir"].is_string())
_exportDir = _config["export_dir"];
_exportDir = pathFromUTF8(_config["export_dir"]);

if (_config["at_uri"].is_string())
_atUri = _config["at_uri"];
Expand Down Expand Up @@ -349,9 +349,9 @@ bool PopTracker::start()
if (pos.top <= -1 * size.height)
pos.top = 0;
}
auto jPack = _args.contains("pack") ? _args["pack"] : _config["pack"];
auto& jPack = _args.contains("pack") ? _args["pack"] : _config["pack"];
if (jPack.type() == json::value_t::object) {
std::string path = to_string(jPack["path"],"");
std::string path = pathFromUTF8(to_string(jPack["path"],""));
std::string variant = to_string(jPack["variant"],"");
if (!scheduleLoadTracker(path,variant))
{
Expand Down Expand Up @@ -502,7 +502,7 @@ bool PopTracker::start()
json extra = { { "at_uri", _atUri }, {"at_slot", _atSlot } };
if (StateManager::saveState(_tracker, _scriptHost, _win->getHints(), extra, true, filename, true))
{
_exportFile = filename;
_exportFile = filename; // this is local encoding for fopen
_exportUID = _pack->getUID();
_exportDir = os_dirname(_exportFile);
}
Expand All @@ -518,7 +518,7 @@ bool PopTracker::start()
std::string filename;
if (!Dlg::OpenFile("Load State", lastName.c_str(), {{"JSON Files",{"*.json"}}}, filename)) return;
if (filename != _exportFile) {
_exportFile = filename;
_exportFile = filename; // this is local encoding for fopen
_exportDir = os_dirname(_exportFile);
_exportUID.clear();
}
Expand Down Expand Up @@ -731,7 +731,7 @@ bool PopTracker::frame()
_config["format_version"] = 1;
if (_pack)
_config["pack"] = {
{"path",_pack->getPath()},
{"path",pathToUTF8(_pack->getPath())},
{"variant",_pack->getVariant()},
{"uid",_pack->getUID()},
{"version",_pack->getVersion()}
Expand All @@ -744,9 +744,9 @@ bool PopTracker::frame()
{"display_name", _win->getDisplayName()},
{"display_pos", {disppos.left,disppos.top}}
};
_config["export_file"] = _exportFile;
_config["export_file"] = pathToUTF8(_exportFile);
_config["export_uid"] = _exportUID;
_config["export_dir"] = _exportDir;
_config["export_dir"] = pathToUTF8(_exportDir);
saveConfig();
}

Expand Down