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

Fix memory leak on Linux #59

Merged
merged 2 commits into from
Nov 23, 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
23 changes: 17 additions & 6 deletions include/exe_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,23 @@ class ExeContainer {
m_json() {
m_json.SetObject();
}
json_utils::JsonResult Read(const tuwString& exe_path);
json_utils::JsonResult Write(const tuwString& exe_path);
bool HasJson() { return m_json.IsObject() && !m_json.ObjectEmpty(); }
void GetJson(rapidjson::Document& json) { json.CopyFrom(m_json, json.GetAllocator()); }
void SetJson(rapidjson::Document& json) { m_json.CopyFrom(json, m_json.GetAllocator()); }
void RemoveJson() {

json_utils::JsonResult Read(const tuwString& exe_path) noexcept;
json_utils::JsonResult Write(const tuwString& exe_path) noexcept;

bool HasJson() noexcept {
return m_json.IsObject() && !m_json.ObjectEmpty();
}

void GetJson(rapidjson::Document& json) noexcept {
json.CopyFrom(m_json, json.GetAllocator());
}

void SetJson(rapidjson::Document& json) noexcept {
m_json.CopyFrom(json, m_json.GetAllocator());
}

void RemoveJson() noexcept {
rapidjson::Document doc;
doc.SetObject();
SetJson(doc);
Expand Down
5 changes: 3 additions & 2 deletions include/exec.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ struct ExecuteResult {

// When use_utf8_on_windows is true,
// Tuw converts output strings from UTF-8 to UTF-16 on Windows.
ExecuteResult Execute(const tuwString& cmd, bool use_utf8_on_windows = false);
ExecuteResult LaunchDefaultApp(const tuwString& url);
ExecuteResult Execute(const tuwString& cmd,
bool use_utf8_on_windows = false) noexcept;
ExecuteResult LaunchDefaultApp(const tuwString& url) noexcept;
16 changes: 8 additions & 8 deletions include/json_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,21 @@ struct JsonResult {
// Max binary size for JSON files.
#define JSON_SIZE_MAX 128 * 1024

JsonResult LoadJson(const tuwString& file, rapidjson::Document& json);
JsonResult SaveJson(rapidjson::Document& json, const tuwString& file);
tuwString JsonToString(rapidjson::Document& json);
JsonResult LoadJson(const tuwString& file, rapidjson::Document& json) noexcept;
JsonResult SaveJson(rapidjson::Document& json, const tuwString& file) noexcept;
tuwString JsonToString(rapidjson::Document& json) noexcept;

const char* GetString(const rapidjson::Value& json, const char* key, const char* def);
bool GetBool(const rapidjson::Value& json, const char* key, bool def);
int GetInt(const rapidjson::Value& json, const char* key, int def);
double GetDouble(const rapidjson::Value& json, const char* key, double def);
const char* GetString(const rapidjson::Value& json, const char* key, const char* def) noexcept;
bool GetBool(const rapidjson::Value& json, const char* key, bool def) noexcept;
int GetInt(const rapidjson::Value& json, const char* key, int def) noexcept;
double GetDouble(const rapidjson::Value& json, const char* key, double def) noexcept;

void GetDefaultDefinition(rapidjson::Document& definition);
void CheckVersion(JsonResult& result, rapidjson::Document& definition);
void CheckDefinition(JsonResult& result, rapidjson::Document& definition);
void CheckSubDefinition(JsonResult& result, rapidjson::Value& sub_definition,
int index,
rapidjson::Document::AllocatorType& alloc);
void CheckHelpURLs(JsonResult& result, rapidjson::Document& definition);
void CheckHelpURLs(JsonResult& result, rapidjson::Document& definition) noexcept;

} // namespace json_utils
120 changes: 62 additions & 58 deletions include/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ enum StringError : int {
};

// Returns the error status for tuwString.
StringError GetStringError();
StringError GetStringError() noexcept;

// Set STR_OK to the error status.
void ClearStringError();
void ClearStringError() noexcept;

// String class that doesn't raise std errors.
// It works without any crashes even when it got a memory allocation error.
Expand All @@ -24,147 +24,151 @@ class tuwString {
private:
char* m_str;
size_t m_size;
void alloc_cstr(const char* str, size_t size);
void append(const char* str, size_t size);
void alloc_cstr(const char* str, size_t size) noexcept;
void append(const char* str, size_t size) noexcept;

public:
tuwString() : m_str(nullptr), m_size(0) {}
tuwString(const char* str); // NOLINT(runtime/explicit)
tuwString(const char* str, size_t size);
tuwString(const tuwString& str);
tuwString(tuwString&& str);
tuwString() noexcept : m_str(nullptr), m_size(0) {}
tuwString(const char* str) noexcept; // NOLINT(runtime/explicit)
tuwString(const char* str, size_t size) noexcept;
tuwString(const tuwString& str) noexcept;
tuwString(tuwString&& str) noexcept;

// This allocates null bytes to use them as a buffer.
explicit tuwString(size_t size);
explicit tuwString(size_t size) noexcept;

~tuwString() { clear(); }
size_t length() const { return m_size; }
size_t size() const { return m_size; }
~tuwString() noexcept { clear(); }
size_t length() const noexcept { return m_size; }
size_t size() const noexcept { return m_size; }

bool empty() const { return !m_str || m_str[0] == '\0' || m_size == 0; }
bool empty() const noexcept {
return !m_str || m_str[0] == '\0' || m_size == 0;
}

// Returns an immutable C string. This can't be null.
const char* c_str() const {
const char* c_str() const noexcept {
if (m_str)
return m_str;
return "";
}

// Returns a pointer to the actual buffer.
char* data() const { return m_str; }
char* data() const noexcept { return m_str; }

void clear() {
void clear() noexcept {
if (m_str)
free(m_str);
m_str = nullptr;
m_size = 0;
}

const char& operator[](size_t id) const;
const char& operator[](size_t id) const noexcept;

tuwString& operator=(const char* str);
tuwString& operator=(const tuwString& str);
tuwString& operator=(tuwString&& str);
tuwString& operator=(const char* str) noexcept;
tuwString& operator=(const tuwString& str) noexcept;
tuwString& operator=(tuwString&& str) noexcept;

tuwString& operator+=(const char* str);
tuwString& operator+=(const tuwString& str);
tuwString& operator+=(const char* str) noexcept;
tuwString& operator+=(const tuwString& str) noexcept;

tuwString operator+(const char* str) const;
tuwString operator+(const tuwString& str) const;
tuwString operator+(const char* str) const noexcept;
tuwString operator+(const tuwString& str) const noexcept;

// You can append numbers as strings
tuwString operator+(int num) const;
tuwString operator+(size_t num) const;
tuwString operator+(uint32_t num) const;
tuwString operator+(int num) const noexcept;
tuwString operator+(size_t num) const noexcept;
tuwString operator+(uint32_t num) const noexcept;

bool operator==(const char* str) const;
bool operator==(const tuwString& str) const;
inline bool operator!=(const char* str) const {
bool operator==(const char* str) const noexcept;
bool operator==(const tuwString& str) const noexcept;
inline bool operator!=(const char* str) const noexcept {
return !(*this == str);
}
inline bool operator!=(const tuwString& str) const {
inline bool operator!=(const tuwString& str) const noexcept {
return !(*this == str);
}

const char* begin() const {
const char* begin() const noexcept {
return c_str();
}

const char* end() const {
const char* end() const noexcept {
return c_str() + m_size;
}

static const size_t npos;
size_t find(const char c) const;
size_t find(const char* str) const;
inline size_t find(const tuwString& str) const {
size_t find(const char c) const noexcept;
size_t find(const char* str) const noexcept;
inline size_t find(const tuwString& str) const noexcept {
return find(str.c_str());
}

void push_back(const char c) {
void push_back(const char c) noexcept {
this->append(&c, 1);
}

tuwString substr(size_t start, size_t size) const;
tuwString substr(size_t start, size_t size) const noexcept;
};

tuwString operator+(const char* str1, const tuwString& str2);
tuwString operator+(const char* str1, const tuwString& str2) noexcept;

inline bool operator==(const char* str1, const tuwString& str2) {
inline bool operator==(const char* str1, const tuwString& str2) noexcept {
return str2 == str1;
}

inline bool operator!=(const char* str1, const tuwString& str2) {
inline bool operator!=(const char* str1, const tuwString& str2) noexcept {
return str2 != str1;
}

// Returns only the last line and removes trailing line feeds (\n and \r.)
tuwString GetLastLine(const tuwString& str);
tuwString GetLastLine(const tuwString& str) noexcept;

class tuwWstring {
private:
wchar_t* m_str;
size_t m_size;

public:
tuwWstring(const wchar_t* str); // NOLINT(runtime/explicit)
~tuwWstring() { clear(); }
size_t length() const { return m_size; }
size_t size() const { return m_size; }
bool empty() const { return !m_str || m_str[0] == L'\0' || m_size == 0; }
tuwWstring(const wchar_t* str) noexcept; // NOLINT(runtime/explicit)
~tuwWstring() noexcept { clear(); }
size_t length() const noexcept { return m_size; }
size_t size() const noexcept { return m_size; }
bool empty() const noexcept {
return !m_str || m_str[0] == L'\0' || m_size == 0;
}

const wchar_t* c_str() const {
const wchar_t* c_str() const noexcept {
if (m_str)
return m_str;
return L"";
}

void clear() {
void clear() noexcept {
if (m_str)
free(m_str);
m_str = nullptr;
m_size = 0;
}
};

inline tuwString envuStr(char *cstr) {
inline tuwString envuStr(char *cstr) noexcept {
if (cstr == NULL)
return "";
tuwString str = cstr;
envuFree(cstr);
return str;
}

uint32_t Fnv1Hash32(const tuwString& str);
uint32_t Fnv1Hash32(const tuwString& str) noexcept;

#ifdef _WIN32
tuwString UTF16toUTF8(const wchar_t* str);
tuwWstring UTF8toUTF16(const char* str);
void FprintFmt(FILE* out, const char* fmt, ...);
void EnableCSI();
tuwString UTF16toUTF8(const wchar_t* str) noexcept;
tuwWstring UTF8toUTF16(const char* str) noexcept;
void FprintFmt(FILE* out, const char* fmt, ...) noexcept;
void EnableCSI() noexcept;
#elif defined(__TUW_UNIX__)
void SetLogEntry(void* log_entry);
void FprintFmt(FILE* out, const char* fmt, ...);
void SetLogEntry(void* log_entry) noexcept;
void FprintFmt(FILE* out, const char* fmt, ...) noexcept;
#else
#define FprintFmt(...) fprintf(__VA_ARGS__)
#endif
Expand Down
6 changes: 3 additions & 3 deletions include/validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Validator {
m_not_empty(false), m_exist(false),
m_error_msg("") {}
~Validator() {}
void Initialize(const rapidjson::Value& j);
bool Validate(const tuwString& str);
const tuwString& GetError() const { return m_error_msg; }
void Initialize(const rapidjson::Value& j) noexcept;
bool Validate(const tuwString& str) noexcept;
const tuwString& GetError() const noexcept { return m_error_msg; }
};
18 changes: 9 additions & 9 deletions src/exe_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

#include "string_utils.h"

static uint32_t ReadUint32(FILE* io) {
static uint32_t ReadUint32(FILE* io) noexcept {
unsigned char int_as_bin[4];
if (fread(int_as_bin, 1, 4, io) != 4)
return 0;
return static_cast<uint32_t>(int_as_bin[0]) | static_cast<uint32_t>(int_as_bin[1] << 8) |
static_cast<uint32_t>(int_as_bin[2] << 16) | static_cast<uint32_t>(int_as_bin[3] << 24);
}

static void WriteUint32(FILE* io, const uint32_t& num) {
static void WriteUint32(FILE* io, const uint32_t& num) noexcept {
unsigned char int_as_bin[4] = {
static_cast<unsigned char>(num & 0xFF),
static_cast<unsigned char>((num >> 8) & 0xFF),
Expand All @@ -28,14 +28,14 @@ static void WriteUint32(FILE* io, const uint32_t& num) {
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
#define BUF_SIZE 1024

static tuwString ReadStr(FILE* io, const uint32_t& size) {
static tuwString ReadStr(FILE* io, const uint32_t& size) noexcept {
tuwString str(size);
if (fread(str.data(), 1, size, io) != size)
return "";
return str;
}

static void WriteStr(FILE* io, const tuwString& str) {
static void WriteStr(FILE* io, const tuwString& str) noexcept {
fwrite(str.data(), 1, str.size(), io);

// Zero padding
Expand All @@ -44,7 +44,7 @@ static void WriteStr(FILE* io, const tuwString& str) {
fwrite(padding_bytes, 1, padding, io);
}

static bool CopyBinary(FILE* reader, FILE* writer, uint32_t size) {
static bool CopyBinary(FILE* reader, FILE* writer, uint32_t size) noexcept {
char buff[BUF_SIZE];
while (size > 0) {
size_t copy_size = MIN(BUF_SIZE, size);
Expand All @@ -57,14 +57,14 @@ static bool CopyBinary(FILE* reader, FILE* writer, uint32_t size) {
return true;
}

static void ReadMagic(FILE* io, char* magic) {
static void ReadMagic(FILE* io, char* magic) noexcept {
magic[4] = '\0';
if (fread(magic, 1, 4, io) != 4)
memset(magic, 0, sizeof(char) * 4);
return;
}

static uint32_t Length(FILE* io) {
static uint32_t Length(FILE* io) noexcept {
uint32_t cur = ftell(io);
fseek(io, 0, SEEK_END);
uint32_t len = ftell(io);
Expand All @@ -74,7 +74,7 @@ static uint32_t Length(FILE* io) {

static const uint32_t EXE_SIZE_MAX = 20000000; // Allowed size of exe

json_utils::JsonResult ExeContainer::Read(const tuwString& exe_path) {
json_utils::JsonResult ExeContainer::Read(const tuwString& exe_path) noexcept {
if (GetStringError() != STR_OK) {
// Reject the operation as the exe_path might have an unexpected value.
return { false, "Fatal error has occurred while editing strings." };
Expand Down Expand Up @@ -145,7 +145,7 @@ json_utils::JsonResult ExeContainer::Read(const tuwString& exe_path) {
return JSON_RESULT_OK;
}

json_utils::JsonResult ExeContainer::Write(const tuwString& exe_path) {
json_utils::JsonResult ExeContainer::Write(const tuwString& exe_path) noexcept {
if (GetStringError() != STR_OK) {
// Reject the operation as the exe_path might have an unexpected value.
return { false, "Fatal error has occurred while editing strings." };
Expand Down
Loading
Loading