Skip to content

Commit

Permalink
Merge pull request #49 from matyalatte/dev
Browse files Browse the repository at this point in the history
v0.7.2 update
  • Loading branch information
matyalatte authored Oct 12, 2024
2 parents b8eca6f + bc823b2 commit edff353
Show file tree
Hide file tree
Showing 21 changed files with 195 additions and 98 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
with:
python-version: '3.x'
- run: |
pip3 install cpplint codespell
pip3 install cpplint==1.6.1 codespell
cpplint --recursive --quiet .
codespell -S subprojects
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ver 0.7.2
- Added "optional" to ignore some options when a text box is empty.
- Added "prefix" and "suffix" options to append strings to user inputs.
- Removed unused functions from release builds.
Expand Down
2 changes: 1 addition & 1 deletion examples/all_keys/gui_definition.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"recommended": "0.7.1",
"recommended": "0.7.2",
"minimum_required": "0.7.1",
"gui": [
{
Expand Down
3 changes: 0 additions & 3 deletions examples/comp_options/affix/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Affixes

> [!WARNING]
> Released builds do not support this feature yet.
`prefix` and `suffix` can append strings to user inputs.

![Affix](https://github.com/user-attachments/assets/15910d56-26b5-4f90-8294-602bec9383d3)
Expand Down
3 changes: 0 additions & 3 deletions examples/comp_options/optional/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Optional Components

> [!WARNING]
> Released builds do not support this feature yet.
`optional` is an option to ignore `"add_quotes"`, `"prefix"`, `"suffix"`, and `"validator"` when a text box is empty.

![optional](https://github.com/user-attachments/assets/a7c94cc7-cb84-4ca9-a1a1-ed1e6babc18e)
Expand Down
10 changes: 10 additions & 0 deletions include/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ inline std::string envuStr(char *cstr) {

uint32_t Fnv1Hash32(const std::string& str);

// Efficient way to concat two or three char* strings.
// str2 can be int, size_t, or uint32_t as well. It will be converted to string internally.
template<typename T>
std::string ConcatCStrings(const char* str1, T str2, const char* str3);

template<typename T>
inline std::string ConcatCStrings(const char* str1, T str2) {
return ConcatCStrings(str1, str2, nullptr);
}

#ifdef _WIN32
std::string UTF16toUTF8(const wchar_t* str);
std::wstring UTF8toUTF16(const char* str);
Expand Down
4 changes: 2 additions & 2 deletions include/tuw_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace tuw_constants {
" CLI tools\n";
constexpr char TOOL_NAME[] = "Tuw";
constexpr char AUTHOR[] = "matyalatte";
constexpr char VERSION[] = "0.7.1";
constexpr int VERSION_INT = 701;
constexpr char VERSION[] = "0.7.2";
constexpr int VERSION_INT = 702;

#ifdef _WIN32
#define TUW_CONSTANTS_OS "win"
Expand Down
3 changes: 2 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if tuw_OS == 'windows'
# but the built binary only supports Windows10 or later.
tuw_link_args += ['/NODEFAULTLIB:libucrt.lib', '/DEFAULTLIB:ucrt.lib']
endif
if meson.version().version_compare('<1.4.0')
if meson.version().version_compare('!=1.4.0')
tuw_link_args += ['/MANIFEST:NO']
endif

Expand Down Expand Up @@ -137,6 +137,7 @@ if get_option('build_exe')
dependencies : tuw_dependencies,
cpp_args: tuw_cpp_args,
link_args: tuw_link_args,
gnu_symbol_visibility: 'hidden',
include_directories: include_directories('include'),
install : false)
endif
Expand Down
6 changes: 3 additions & 3 deletions src/component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Component::Component(const rapidjson::Value& j) {
m_id = json_utils::GetString(j, "id", "");
if (m_id.empty()) {
uint32_t hash = Fnv1Hash32(j["label"].GetString());
m_id = "_" + std::to_string(hash);
m_id = ConcatCStrings("_", hash);
}
m_add_quotes = json_utils::GetBool(j, "add_quotes", false);
if (j.HasMember("validator"))
Expand All @@ -47,8 +47,8 @@ std::string Component::GetString() {
if (m_optional && str.empty())
return "";
if (m_add_quotes)
str = "\"" + str + "\"";
return m_prefix + str + m_suffix;
str = ConcatCStrings("\"", str.c_str(), "\"");
return ConcatCStrings(m_prefix.c_str(), str.c_str(), m_suffix.c_str());
}

bool Component::Validate(bool* redraw_flag) {
Expand Down
25 changes: 13 additions & 12 deletions src/exe_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,22 @@ json_utils::JsonResult ExeContainer::Read(const std::string& exe_path) {
m_exe_size = end_off + ReadUint32(file_io);
if (EXE_SIZE_MAX <= m_exe_size || end_off < m_exe_size) {
fclose(file_io);
return { false, "Unexpected exe size. (" + std::to_string(m_exe_size) + ")" };
return { false, ConcatCStrings("Unexpected exe size. (", m_exe_size, ")") };
}
fseek(file_io, m_exe_size, SEEK_SET);

// Read a header for json data
ReadMagic(file_io, magic);
if (strcmp(magic, "JSON") != 0) {
fclose(file_io);
return { false, std::string("Invalid magic. (") + magic + ")" };
return { false, ConcatCStrings("Invalid magic. (", magic, ")") };
}

uint32_t json_size = ReadUint32(file_io);
uint32_t stored_hash = ReadUint32(file_io);
if (JSON_SIZE_MAX <= json_size || end_off < m_exe_size + json_size + 20) {
fclose(file_io);
return { false, "Unexpected json size. (" + std::to_string(json_size) + ")" };
return { false, ConcatCStrings("Unexpected json size. (", json_size, ")") };
}

// Read json data
Expand All @@ -125,15 +125,15 @@ json_utils::JsonResult ExeContainer::Read(const std::string& exe_path) {
return { false, "Unexpected char detected." };

if (stored_hash != Fnv1Hash32(json_str))
return { false, "Invalid JSON hash. (" + std::to_string(stored_hash) + ")" };
return { false, ConcatCStrings("Invalid JSON hash. (", stored_hash, ")") };

rapidjson::ParseResult ok = m_json.Parse(json_str.c_str());
if (!ok) {
return {
false,
std::string("Failed to parse JSON: ") +
rapidjson::GetParseError_En(ok.Code()) +
" (offset: " + std::to_string(ok.Offset()) + ")"
ConcatCStrings("Failed to parse JSON: ",
rapidjson::GetParseError_En(ok.Code()),
ConcatCStrings(" (offset: ", ok.Offset(), ")").c_str())
};
}

Expand All @@ -148,24 +148,25 @@ json_utils::JsonResult ExeContainer::Write(const std::string& exe_path) {

uint32_t json_size = static_cast<uint32_t>(json_str.length());
if (JSON_SIZE_MAX <= json_size)
return { false, "Unexpected json size. (" + std::to_string(json_size) + ")" };
return { false, ConcatCStrings("Unexpected json size. (", json_size, ")") };

FILE* old_io = fopen(m_exe_path.c_str(), "rb");
if (!old_io)
return { false, "Failed to open a file. (" + m_exe_path + ")" };
return { false, ConcatCStrings("Failed to open a file. (", m_exe_path.c_str(), ")") };

FILE* new_io = fopen(exe_path.c_str(), "wb");
if (!new_io) {
fclose(old_io);
return { false, "Failed to open a file. (" + exe_path + ")" };
return { false, ConcatCStrings("Failed to open a file. (", exe_path.c_str(), ")") };
}
m_exe_path = exe_path;

bool ok = CopyBinary(old_io, new_io, m_exe_size);
if (!ok) {
fclose(old_io);
fclose(new_io);
return { false, "Failed to copy the original executable (" + m_exe_path + ")" };
return { false, ConcatCStrings("Failed to copy the original executable (",
m_exe_path.c_str(), ")") };
}

uint32_t pos = ftell(old_io);
Expand All @@ -175,7 +176,7 @@ json_utils::JsonResult ExeContainer::Write(const std::string& exe_path) {
if (strcmp(magic, "JSON") != 0) {
fclose(old_io);
fclose(new_io);
return { false, std::string("Invalid magic. (") + magic + ")" };
return { false, ConcatCStrings("Invalid magic. (", magic, ")") };
}
}

Expand Down
40 changes: 20 additions & 20 deletions src/json_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "rapidjson/error/en.h"

#include "tuw_constants.h"
#include "string_utils.h"

namespace json_utils {

Expand Down Expand Up @@ -46,8 +47,8 @@ namespace json_utils {

if (!ok) {
std::string msg("Failed to parse JSON: ");
msg += std::string(rapidjson::GetParseError_En(ok.Code()))
+ " (offset: " + std::to_string(ok.Offset()) + ")";
msg += rapidjson::GetParseError_En(ok.Code()) +
ConcatCStrings(" (offset: ", ok.Offset(), ")");
return { false, msg };
}
if (!json.IsObject())
Expand All @@ -59,7 +60,7 @@ namespace json_utils {
JsonResult SaveJson(rapidjson::Document& json, const std::string& file) {
FILE* fp = fopen(file.c_str(), "wb");
if (!fp)
return { false, "Failed to open " + file + "." };
return { false, ConcatCStrings("Failed to open ", file.c_str(), ".") };

char writeBuffer[JSON_SIZE_MAX];
rapidjson::FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer));
Expand All @@ -73,7 +74,7 @@ namespace json_utils {
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
json.Accept(writer);
return std::string(buffer.GetString());
return buffer.GetString();
}

const char* GetString(const rapidjson::Value& json, const char* key, const char* def) {
Expand Down Expand Up @@ -101,12 +102,11 @@ namespace json_utils {
}

static std::string GetLabel(const char* label, const char* key) {
std::string msg = "['";
std::string msg;
if (*label != '\0') {
msg += std::string(label) + "']['";
msg = ConcatCStrings("['", label, "']");
}
msg += key;
msg += "']";
msg += ConcatCStrings("['", key, "']");
return msg;
}

Expand Down Expand Up @@ -185,7 +185,7 @@ namespace json_utils {
}
if (!valid) {
result.ok = false;
result.msg = GetLabel(label, key) + " should be " + type_name + ".";
result.msg = GetLabel(label, key) + ConcatCStrings(" should be ", type_name, ".");
}
}

Expand Down Expand Up @@ -251,9 +251,9 @@ namespace json_utils {
for (size_t j = i + 1; j < size; j++) {
if (str == component_ids[j]) {
result.ok = false;
result.msg = "[components][id]"
" should not be duplicated in a gui definition. ("
+ str + ")";
result.msg = ConcatCStrings("[components][id]"
" should not be duplicated in a gui definition. (",
str.c_str(), ")");
return;
}
}
Expand Down Expand Up @@ -322,7 +322,7 @@ namespace json_utils {
if (j >= comp_size)
cmd_str += "__comp???__";
else if (j >= 0)
cmd_str += "__comp" + std::to_string(j) + "__";
cmd_str += ConcatCStrings("__comp", j, "__");
}
if (cmd_ids.size() < splitted_cmd.size())
cmd_str += splitted_cmd.back();
Expand All @@ -337,8 +337,8 @@ namespace json_utils {
if (id.GetInt() == j) { found = true; break; }
if (!found) {
result.ok = false;
result.msg = "[\"components\"][" + std::to_string(j)
+ "] is unused in the command; " + cmd_str;
result.msg = ConcatCStrings("[\"components\"][", j,
"] is unused in the command; ") + cmd_str;
if (!comp_ids[j].empty())
result.msg = "The ID of " + result.msg;
return;
Expand Down Expand Up @@ -427,7 +427,7 @@ namespace json_utils {
if (strcmp(codepage, "utf8") != 0 && strcmp(codepage, "utf-8") != 0 &&
strcmp(codepage, "default") != 0) {
result.ok = false;
result.msg = std::string("Unknown codepage: ") + codepage;
result.msg = ConcatCStrings("Unknown codepage: ", codepage);
return;
}
}
Expand Down Expand Up @@ -513,7 +513,7 @@ namespace json_utils {
break;
case COMP_UNKNOWN:
result.ok = false;
result.msg = std::string("Unknown component type: ") + type_str;
result.msg = ConcatCStrings("Unknown component type: ", type_str);
break;
}
if (!result.ok) return;
Expand Down Expand Up @@ -606,7 +606,7 @@ namespace json_utils {
for (const std::string& str : version_strings) {
if (str.length() == 0 || str.length() > 2) {
result.ok = false;
result.msg = std::string("Can NOT convert '") + string + "' to int.";
result.msg = ConcatCStrings("Can NOT convert '", string, "' to int.");
return 0;
}
if (str.length() == 1) {
Expand Down Expand Up @@ -641,7 +641,7 @@ namespace json_utils {
int required_int = VersionStringToInt(result, required);
if (tuw_constants::VERSION_INT < required_int) {
result.ok = false;
result.msg = std::string("Version ") + required + " is required.";
result.msg = ConcatCStrings("Version ", required, " is required.");
}
}
}
Expand Down Expand Up @@ -675,7 +675,7 @@ namespace json_utils {
CheckJsonType(result, h, "path", JsonType::STRING);
} else {
result.ok = false;
result.msg = std::string("Unsupported help type: ") + type;
result.msg = ConcatCStrings("Unsupported help type: ", type);
return;
}
}
Expand Down
18 changes: 10 additions & 8 deletions src/main_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ MainFrame::MainFrame(const rapidjson::Document& definition, const rapidjson::Doc
#endif

if (ignore_external_json) {
std::string msg = std::string("WARNING: Using embedded JSON. ") +
json_path + " was ignored.\n";
std::string msg = ConcatCStrings("WARNING: Using embedded JSON. ",
json_path, " was ignored.\n");
PrintFmt("[LoadDefinition] %s", msg.c_str());
ShowSuccessDialog(msg, "Warning");
}
Expand Down Expand Up @@ -239,13 +239,15 @@ void MainFrame::OpenURL(int id) {
std::string scheme = url.substr(0, pos);
// scheme should be http or https
if (scheme == "file") {
std::string msg = "Use 'file' type for a path, not 'url' type. (" + url + ")";
std::string msg = ConcatCStrings("Use 'file' type for a path, not 'url' type. (",
url.c_str(), ")");
PrintFmt("%sError: %s\n", tag, msg.c_str());
ShowErrorDialog(msg);
return;
} else if (scheme != "https" && scheme != "http") {
std::string msg = "Unsupported scheme detected. "
"It should be http or https. (" + scheme + ")";
std::string msg = ConcatCStrings(
"Unsupported scheme detected. "
"It should be http or https. (", scheme.c_str(), ")");
PrintFmt("%sError: %s\n", tag, msg.c_str());
ShowErrorDialog(msg);
return;
Expand All @@ -261,7 +263,7 @@ void MainFrame::OpenURL(int id) {
tag = "[OpenFile] ";

if (!exists) {
std::string msg = "File does not exist. (" + url + ")";
std::string msg = ConcatCStrings("File does not exist. (", url.c_str(), ")");
PrintFmt("%sError: %s\n", tag, msg.c_str());
ShowErrorDialog(msg);
return;
Expand Down Expand Up @@ -291,7 +293,7 @@ void MainFrame::OpenURL(int id) {
} else {
ExecuteResult result = LaunchDefaultApp(url);
if (result.exit_code != 0) {
std::string msg = std::string("Failed to open a ") + type + " by an unexpected error.";
std::string msg = ConcatCStrings("Failed to open a ", type, " by an unexpected error.");
PrintFmt("%sError: %s\n", tag, msg.c_str());
ShowErrorDialog(msg.c_str());
}
Expand Down Expand Up @@ -487,7 +489,7 @@ void MainFrame::RunCommand() {
if (show_last_line)
err_msg = result.last_line;
else
err_msg = "Invalid exit code (" + std::to_string(result.exit_code) + ")";
err_msg = ConcatCStrings("Invalid exit code (", result.exit_code, ")");
PrintFmt("[RunCommand] Error: %s\n", err_msg.c_str());
ShowErrorDialog(err_msg);
return;
Expand Down
Loading

0 comments on commit edff353

Please sign in to comment.