Skip to content

Commit

Permalink
Support UTF-8 paths on Windows
Browse files Browse the repository at this point in the history
Faceplates aren't loading if the RACK_USER_DIR has non-ASCII
characters in it. See:
https://community.vcvrack.com/t/rarebreeds-eugene-not-working/20266

Resolves issue #4.
  • Loading branch information
RareBreeds committed Jul 30, 2023
1 parent 1aece7e commit 2ee3855
Showing 1 changed file with 56 additions and 11 deletions.
67 changes: 56 additions & 11 deletions src/OrbitsConfig.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,55 @@
#include <fstream>

#include "OrbitsConfig.hpp"
#include "plugin.hpp"

static json_t *orbits_json_load_file(const char *path, size_t flags, json_error_t *error)
{
FILE *fp = std::fopen(path, "rb");
json_t *json = json_loadf(fp, flags, error);
if (fp)
{
std::fclose(fp);
}
return json;
}

static std::string read_file_contents(const std::string& filename)
{
// Read a file into a string without using ifstream.
// MINGW doesn't have an ifstream that supports being constructed
// from a wide string, which is required on Windows for opening
// paths containing UTF8 characters.
FILE* file = std::fopen(filename.c_str(), "rb");
if (file == NULL)
{
return "";
}

fseek(file, 0, SEEK_END);
long ftell_result = ftell(file);
fseek(file, 0, SEEK_SET);

if (ftell_result <= 0)
{
std::fclose(file);
return "";
}

size_t file_size = (size_t) ftell_result;
std::vector<char> buffer(file_size + 1);
size_t bytes_read = fread(buffer.data(), 1, file_size, file);

std::fclose(file);

if (bytes_read != static_cast<size_t>(file_size))
{
return "";
}

buffer[file_size] = '\0';

return std::string(buffer.data());
}

OrbitsConfig::OrbitsConfig(std::string path)
{
m_path = path;
Expand Down Expand Up @@ -33,7 +80,7 @@ std::string OrbitsConfig::getSvg(std::string component, int theme)
{
json_error_t error;
std::string path = asset::plugin(pluginInstance, m_path);
json_t *root = json_load_file(path.c_str(), 0, &error);
json_t *root = orbits_json_load_file(path.c_str(), 0, &error);
json_t *themes = json_object_get(root, "themes");
json_t *entry = json_array_get(themes, theme);
json_t *obj = json_object_get(entry, component.c_str());
Expand All @@ -50,8 +97,7 @@ std::string OrbitsConfig::getSvg(std::string component)

Vec OrbitsConfig::getPos(std::string component)
{
std::ifstream ifs(getSvg("panel"));
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
std::string content = read_file_contents(getSvg("panel"));
size_t search = content.find("inkscape:label=\"components\"");
if(search == std::string::npos)
{
Expand All @@ -73,8 +119,7 @@ Vec OrbitsConfig::getPos(std::string component)

Vec OrbitsConfig::getSize(std::string component)
{
std::ifstream ifs(getSvg("panel"));
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
std::string content = read_file_contents(getSvg("panel"));
size_t search = content.find("inkscape:label=\"components\"");
search = content.find("inkscape:label=\"" + component, search);
float w = rFindFloatAttribute(content, "width", search);
Expand All @@ -86,7 +131,7 @@ std::string OrbitsConfig::getThemeName(int theme)
{
json_error_t error;
std::string path = asset::plugin(pluginInstance, m_path);
json_t *root = json_load_file(path.c_str(), 0, &error);
json_t *root = orbits_json_load_file(path.c_str(), 0, &error);
json_t *themes = json_object_get(root, "themes");
json_t *entry = json_array_get(themes, theme);
json_t *name = json_object_get(entry, "name");
Expand All @@ -106,7 +151,7 @@ int OrbitsConfig::getDefaultThemeId()
int default_theme_id = 0;
json_error_t error;
std::string path = asset::plugin(pluginInstance, m_path);
json_t *root = json_load_file(path.c_str(), 0, &error);
json_t *root = orbits_json_load_file(path.c_str(), 0, &error);
json_t *def = json_object_get(root, "default");
const char *default_name = json_string_value(def);
json_t *themes = json_object_get(root, "themes");
Expand All @@ -131,7 +176,7 @@ size_t OrbitsConfig::numThemes()
{
json_error_t error;
std::string path = asset::plugin(pluginInstance, m_path);
json_t *root = json_load_file(path.c_str(), 0, &error);
json_t *root = orbits_json_load_file(path.c_str(), 0, &error);
json_t *themes = json_object_get(root, "themes");
size_t count = json_array_size(themes);
json_decref(root);
Expand All @@ -142,7 +187,7 @@ std::array<uint8_t, 3> OrbitsConfig::getColour(std::string component, int theme)
{
json_error_t error;
std::string path = asset::plugin(pluginInstance, m_path);
json_t *root = json_load_file(path.c_str(), 0, &error);
json_t *root = orbits_json_load_file(path.c_str(), 0, &error);
json_t *themes = json_object_get(root, "themes");
json_t *entry = json_array_get(themes, theme);
json_t *obj = json_object_get(entry, component.c_str());
Expand Down

0 comments on commit 2ee3855

Please sign in to comment.