Skip to content

Commit

Permalink
Merge pull request #59 from matyalatte/noexcept
Browse files Browse the repository at this point in the history
Fix memory leak on Linux
  • Loading branch information
matyalatte authored Nov 23, 2024
2 parents ffbad17 + 5b10369 commit 49cb123
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 173 deletions.
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

0 comments on commit 49cb123

Please sign in to comment.