Initial commit

This commit is contained in:
InoriRus
2021-12-01 19:29:27 +10:00
parent b1e7dcdc5d
commit 43f49c8763
1843 changed files with 1111694 additions and 0 deletions
+225
View File
@@ -0,0 +1,225 @@
#ifndef INCLUDE_KYTY_CORE_ARRAYWRAPPER_H_
#define INCLUDE_KYTY_CORE_ARRAYWRAPPER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include <initializer_list> // IWYU pragma: export
namespace Kyty::Core {
template <class Type, int Num>
class Array final
{
public:
Array() = default;
~Array() = default;
KYTY_CLASS_DEFAULT_COPY(Array);
Array(std::initializer_list<Type> list) noexcept: m_ptr {}
{
int index = 0;
for (const Type& e: list)
{
(*this)[index++] = e;
}
}
const Type& operator[](int index) const
{
EXIT_IF(index < 0 || index >= Num);
return m_ptr[index];
}
Type& operator[](int index)
{
EXIT_IF(index < 0 || index >= Num);
return m_ptr[index];
}
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
operator Type const *() const { return &m_ptr[0]; }
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
operator Type*() { return &m_ptr[0]; }
[[nodiscard]] int Size() const { return Num; }
Type* GetPtr() { return m_ptr; }
[[nodiscard]] const Type* GetPtr() const { return m_ptr; }
[[nodiscard]] size_t ByteSize() const { return sizeof(Type) * Num; }
// void SetZero()
// {
// memset(m_ptr, 0, sizeof(Type) * num);
// }
//
// void Memset(int fill)
// {
// memset(m_ptr, fill, sizeof(Type) * num);
// }
using iterator = Type*;
using const_iterator = const Type*;
iterator begin() { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
iterator end() { return &m_ptr[Num]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator begin() const { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator end() const { return &m_ptr[Num]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cbegin() const { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cend() const { return &m_ptr[Num]; } // NOLINT(readability-identifier-naming)
private:
Type m_ptr[Num];
};
template <class Type, int Num1, int Num2>
class Array2 final
{
public:
Array2() = default;
~Array2() = default;
KYTY_CLASS_DEFAULT_COPY(Array2);
Array2(std::initializer_list<Array<Type, Num2>> list) noexcept: m_ptr {}
{
int index = 0;
for (const Array<Type, Num2>& e: list)
{
(*this)[index++] = e;
}
}
const Array<Type, Num2>& operator[](int index) const
{
EXIT_IF(index < 0 || index >= Num1);
return m_ptr[index];
}
Array<Type, Num2>& operator[](int index)
{
EXIT_IF(index < 0 || index >= Num1);
return m_ptr[index];
}
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
operator Type const *() const { return &m_ptr[0][0]; }
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
operator Type*() { return &m_ptr[0][0]; }
[[nodiscard]] int Size() const { return Num1; }
Array<Type, Num2>* GetPtr() { return m_ptr; }
[[nodiscard]] const Array<Type, Num2>* GetPtr() const { return m_ptr; }
[[nodiscard]] size_t ByteSize() const { return sizeof(Type) * Num1 * Num2; }
// void SetZero()
// {
// memset(m_ptr, 0, sizeof(Type) * num1 * num2);
// }
//
// void Memset(int fill)
// {
// memset(m_ptr, fill, sizeof(Type) * num1 * num2);
// }
using iterator = Array<Type, Num2>*;
using const_iterator = const Array<Type, Num2>*;
iterator begin() { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
iterator end() { return &m_ptr[Num1]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator begin() const { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator end() const { return &m_ptr[Num1]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cbegin() const { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cend() const { return &m_ptr[Num1]; } // NOLINT(readability-identifier-naming)
private:
Array<Type, Num2> m_ptr[Num1];
};
template <class Type, int Num1, int Num2, int Num3>
class Array3
{
public:
Array3() = default;
~Array3() = default;
KYTY_CLASS_DEFAULT_COPY(Array3);
Array3(std::initializer_list<Array2<Type, Num2, Num3>> list) noexcept: m_ptr {}
{
int index = 0;
for (const Array2<Type, Num2, Num3>& e: list)
{
(*this)[index++] = e;
}
}
const Array2<Type, Num2, Num3>& operator[](int index) const
{
EXIT_IF(index < 0 || index >= Num1);
return m_ptr[index];
}
Array2<Type, Num2, Num3>& operator[](int index)
{
EXIT_IF(index < 0 || index >= Num1);
return m_ptr[index];
}
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
operator Type const *() const { return &m_ptr[0][0][0]; }
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
operator Type*() { return &m_ptr[0][0][0]; }
[[nodiscard]] int Size() const { return Num1; }
Array2<Type, Num2, Num3>* GetPtr() { return m_ptr; }
[[nodiscard]] const Array2<Type, Num2, Num3>* GetPtr() const { return m_ptr; }
[[nodiscard]] size_t ByteSize() const { return sizeof(Type) * Num1 * Num2 * Num3; }
// void SetZero()
// {
// memset(m_ptr, 0, sizeof(Type) * num1 * num2 * num3);
// }
//
// void Memset(int fill)
// {
// memset(m_ptr, fill, sizeof(Type) * num1 * num2 * num3);
// }
using iterator = Array2<Type, Num2, Num3>*;
using const_iterator = const Array2<Type, Num2, Num3>*;
iterator begin() { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
iterator end() { return &m_ptr[Num1]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator begin() const { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator end() const { return &m_ptr[Num1]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cbegin() const { return &m_ptr[0]; } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cend() const { return &m_ptr[Num1]; } // NOLINT(readability-identifier-naming)
private:
Array2<Type, Num2, Num3> m_ptr[Num1];
};
} // namespace Kyty::Core
#define KYTY_ARRAY_NUM(a) ((int)(sizeof((a)) / sizeof((a)[0])))
#endif /* INCLUDE_KYTY_CORE_ARRAYWRAPPER_H_ */
+37
View File
@@ -0,0 +1,37 @@
#ifndef INCLUDE_KYTY_CORE_BYTEBUFFER_H_
#define INCLUDE_KYTY_CORE_BYTEBUFFER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Vector.h"
#include <cstddef> // IWYU pragma: export
namespace Kyty::Core {
using Byte = std::byte;
class ByteBuffer: public Vector<Byte>
{
public:
ByteBuffer() = default;
using Vector<Byte>::Vector;
ByteBuffer(std::initializer_list<uint8_t> list): ByteBuffer(static_cast<uint32_t>(list.size()), false) // @suppress("Ambiguous problem")
{
Byte* values_ptr = GetData();
for (const uint8_t& e: list)
{
*(values_ptr++) = static_cast<Byte>(e);
}
}
ByteBuffer(const void* buf, uint32_t size): ByteBuffer(size, false) // @suppress("Ambiguous problem")
{
Byte* values_ptr = GetData();
std::memcpy(values_ptr, buf, size);
}
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_BYTEBUFFER_H_ */
+64
View File
@@ -0,0 +1,64 @@
#ifndef INCLUDE_KYTY_CORE_COMMON_H_
#define INCLUDE_KYTY_CORE_COMMON_H_
#include "kyty_config.h" // IWYU pragma: export
#if KYTY_COMPILER != KYTY_COMPILER_MSVC
#if __cplusplus < 201703L
#undef __cplusplus
#define __cplusplus 201703L
#endif
#endif
#if (KYTY_COMPILER == KYTY_COMPILER_MINGW)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage,cert-dcl51-cpp,cert-dcl37-c,bugprone-reserved-identifier)
#define __USE_MINGW_ANSI_STDIO 1
#endif
// IWYU pragma: begin_exports
#include <cinttypes>
#include <cstdint>
#include <cstdio>
// IWYU pragma: end_exports
#define KYTY_FORCE_LINK_THIS(x) int force_link_##x = 0;
#define KYTY_FORCE_LINK_THAT(x) \
void force_link_function_##x() \
{ \
extern int force_link_##x; \
force_link_##x = 1; \
}
#define KYTY_CLASS_NO_COPY(name) \
public: \
name(const name&) = delete; /* NOLINT(bugprone-macro-parentheses) */ \
name& operator=(const name&) = delete; /* NOLINT(bugprone-macro-parentheses) */ \
name(name&&) noexcept = delete; /* NOLINT(bugprone-macro-parentheses) */ \
name& operator=(name&&) noexcept = delete; /* NOLINT(bugprone-macro-parentheses) */
#define KYTY_CLASS_DEFAULT_COPY(name) \
public: \
name(const name&) = default; /* NOLINT(bugprone-macro-parentheses) */ \
name& operator=(const name&) = default; /* NOLINT(bugprone-macro-parentheses) */ \
name(name&&) noexcept = default; /* NOLINT(bugprone-macro-parentheses) */ \
name& operator=(name&&) noexcept = default; /* NOLINT(bugprone-macro-parentheses) */
#if (KYTY_COMPILER == KYTY_COMPILER_MINGW || KYTY_COMPILER == KYTY_COMPILER_GCC)
#define KYTY_FORMAT_PRINTF(a, b) __attribute__((format(gnu_printf, a, b)))
#elif KYTY_COMPILER == KYTY_COMPILER_CLANG
#define KYTY_FORMAT_PRINTF(a, b) __attribute__((format(printf, a, b)))
#else
#define KYTY_FORMAT_PRINTF(a, b)
#endif
#if KYTY_PLATFORM == KYTY_PLATFORM_ANDROID
#include <android/log.h> // IWYU pragma: export
#define KYTY_LOG_TAG "KYTY_Tag"
#define KYTY_LOGI(...) __android_log_print(ANDROID_LOG_INFO, KYTY_LOG_TAG, __VA_ARGS__)
#define KYTY_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, KYTY_LOG_TAG, __VA_ARGS__)
#else
#define KYTY_LOGI printf
#define KYTY_LOGE printf
#endif
#endif /* INCLUDE_KYTY_CORE_COMMON_H_ */
+147
View File
@@ -0,0 +1,147 @@
#ifndef INCLUDE_KYTY_CORE_COMPRESSION_H_
#define INCLUDE_KYTY_CORE_COMPRESSION_H_
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DateTime.h"
#include "Kyty/Core/String.h"
namespace Kyty::Core {
using ZipCompressLevel = int;
using ZstdCompressLevel = int;
constexpr ZipCompressLevel ZIP_NO_COMPRESSION = 0;
constexpr ZipCompressLevel ZIP_BEST_SPEED = 1;
constexpr ZipCompressLevel ZIP_DEFAULT_LEVEL = 6;
constexpr ZipCompressLevel ZIP_BEST_COMPRESSION = 9;
constexpr ZstdCompressLevel ZSTD_BEST_SPEED = 1;
constexpr ZstdCompressLevel ZSTD_DEFAULT_LEVEL = 3;
constexpr ZstdCompressLevel ZSTD_BEST_COMPRESSION = 22;
ByteBuffer CompressZstd(const uint8_t* buf, uint32_t length, int level = ZSTD_DEFAULT_LEVEL);
ByteBuffer CompressZstd(const ByteBuffer& buf, int level = ZSTD_DEFAULT_LEVEL);
ByteBuffer CompressZstd(const String& str, int level = ZSTD_DEFAULT_LEVEL);
ByteBuffer DecompressZstd(const uint8_t* buf, uint32_t length);
ByteBuffer DecompressZstd(const ByteBuffer& buf);
String DecompressZstdStr(const uint8_t* buf, uint32_t length);
String DecompressZstdStr(const ByteBuffer& buf);
ByteBuffer CompressLzma(const uint8_t* buf, uint32_t length);
ByteBuffer CompressLzma(const ByteBuffer& buf);
ByteBuffer CompressLzma(const String& str);
ByteBuffer DecompressLzma(const uint8_t* buf, uint32_t length);
ByteBuffer DecompressLzma(const ByteBuffer& buf);
String DecompressLzmaStr(const uint8_t* buf, uint32_t length);
String DecompressLzmaStr(const ByteBuffer& buf);
ByteBuffer CompressZip(const uint8_t* buf, uint32_t length, ZipCompressLevel level = ZIP_DEFAULT_LEVEL);
ByteBuffer CompressZip(const ByteBuffer& buf, ZipCompressLevel level = ZIP_DEFAULT_LEVEL);
ByteBuffer CompressZip(const String& str, ZipCompressLevel level = ZIP_DEFAULT_LEVEL);
ByteBuffer DecompressZip(const uint8_t* buf, uint32_t length);
ByteBuffer DecompressZip(const ByteBuffer& buf);
String DecompressZipStr(const uint8_t* buf, uint32_t length);
String DecompressZipStr(const ByteBuffer& buf);
ByteBuffer CompressLzf(const uint8_t* buf, uint32_t length);
ByteBuffer CompressLzf(const ByteBuffer& buf);
ByteBuffer CompressLzf(const String& str);
ByteBuffer DecompressLzf(const uint8_t* buf, uint32_t length);
ByteBuffer DecompressLzf(const ByteBuffer& buf);
String DecompressLzfStr(const uint8_t* buf, uint32_t length);
String DecompressLzfStr(const ByteBuffer& buf);
struct ZipFileStat
{
uint32_t m_file_index;
// uint32_t m_central_dir_ofs;
// uint16_t m_version_made_by;
// uint16_t m_version_needed;
// uint16_t m_bit_flag;
// uint16_t m_method;
DateTime m_time;
uint32_t m_crc32;
uint64_t m_comp_size;
uint64_t m_uncomp_size;
// uint16_t m_internal_attr;
// uint32_t m_external_attr;
// uint64_t m_local_header_ofs;
// uint32_t m_comment_size;
String m_filename;
String m_comment;
};
struct ZipPrivate;
class ZipReader
{
public:
ZipReader() = default;
virtual ~ZipReader();
bool Open(const String& file_name);
bool Open(const ByteBuffer& buf);
bool Open(uint8_t* mem, uint32_t size);
void Close();
// Returns the total number of files in the archive.
int GetNumFiles();
// Returns detailed information about an archive file entry.
bool GetFileStat(int file_index, ZipFileStat* out_stat);
// Determines if an archive file entry is a directory entry.
bool IsFileDirectory(int file_index);
bool IsFileEncrypted(int file_index);
// Retrieves the filename of an archive file entry.
String GetFileName(int file_index);
// Attempts to locates a file in the archive's central directory.
// Returns -1 if the file cannot be found.
int FindFile(const String& name, const String& comment = U"");
// Extracts a archive file to a memory buffer
ByteBuffer ExtractFile(int file_index);
ByteBuffer ExtractFile(const String& name);
friend class ZipWriter;
KYTY_CLASS_NO_COPY(ZipReader);
private:
ZipPrivate* m_p = nullptr;
};
class ZipWriter
{
public:
ZipWriter() = default;
virtual ~ZipWriter();
bool Create(const String& file_name);
void Close();
bool AddFile(const String& file_name, const ByteBuffer& buf, ZipCompressLevel level = ZIP_DEFAULT_LEVEL);
bool AddFile(const String& file_name, const uint8_t* buf, uint32_t size, ZipCompressLevel level = ZIP_DEFAULT_LEVEL);
bool AddFileFromFile(const String& file_name, const String& from_file, ZipCompressLevel level = ZIP_DEFAULT_LEVEL);
bool AddFileFromReader(const String& file_name, ZipReader* from_reader, int file_index);
bool AddDir(const String& dir_name);
KYTY_CLASS_NO_COPY(ZipWriter);
private:
ZipPrivate* m_p = nullptr;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_COMPRESSION_H_ */
+12
View File
@@ -0,0 +1,12 @@
#ifndef INCLUDE_KYTY_CORE_CORE_H_
#define INCLUDE_KYTY_CORE_CORE_H_
#include "Kyty/Core/Subsystems.h"
namespace Kyty::Core {
KYTY_SUBSYSTEM_DEFINE(Core);
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_CORE_H_ */
+164
View File
@@ -0,0 +1,164 @@
#ifndef INCLUDE_KYTY_CORE_DATABASE_H_
#define INCLUDE_KYTY_CORE_DATABASE_H_
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Vector.h"
namespace Kyty::Core::Database {
struct StatementPrivate;
struct ConnectionPrivate;
void Init();
class Statement
{
public:
enum class State
{
Done,
Row,
Error
};
enum class Type
{
Integer,
Float,
Text,
Blob,
Null
};
State Step();
void Reset();
void ClearBindings();
void BindBlob(const char* name, const ByteBuffer& blob) { BindBlob(GetIndex(name), blob); }
void BindBlob(const String& name, const ByteBuffer& blob) { BindBlob(GetIndex(name), blob); }
void BindBlob(int index, const ByteBuffer& blob);
void BindDouble(const char* name, double d) { BindDouble(GetIndex(name), d); }
void BindDouble(const String& name, double d) { BindDouble(GetIndex(name), d); }
void BindDouble(int index, double d);
void BindInt(const char* name, int i) { BindInt(GetIndex(name), i); }
void BindInt(const String& name, int i) { BindInt(GetIndex(name), i); }
void BindInt(int index, int i);
void BindInt64(const char* name, int64_t i) { BindInt64(GetIndex(name), i); }
void BindInt64(const String& name, int64_t i) { BindInt64(GetIndex(name), i); }
void BindInt64(int index, int64_t i);
void BindString(const char* name, const String& str) { BindString(GetIndex(name), str); }
void BindString(const String& name, const String& str) { BindString(GetIndex(name), str); }
void BindString(int index, const String& str);
void BindString(const char* name, const char* str) { BindString(GetIndex(name), str); }
void BindString(const String& name, const char* str) { BindString(GetIndex(name), str); }
void BindString(int index, const char* str);
void BindNull(const char* name) { BindNull(GetIndex(name)); }
void BindNull(const String& name) { BindNull(GetIndex(name)); }
void BindNull(int index);
int GetIndex(const char* name);
int GetIndex(const String& name);
int GetColumnCount();
const char* GetColumnName(int index);
const char* GetColumnNameDatabase(int index);
const char* GetColumnNameTable(int index);
const char* GetColumnNameField(int index);
ByteBuffer GetColumnBlob(int index);
double GetColumnDouble(int index);
int GetColumnInt(int index);
int64_t GetColumnInt64(int index);
String GetColumnString(int index);
Type GetColumnType(int index);
void DbgTest();
KYTY_CLASS_NO_COPY(Statement);
friend class Connection;
protected:
virtual ~Statement();
explicit Statement(ConnectionPrivate* c);
private:
StatementPrivate* m_p;
};
class Connection
{
public:
enum class Mode
{
ReadOnly,
ReadWrite
};
struct ExecRow
{
StringList names;
StringList values;
};
class ExecResult: public Vector<ExecRow>
{
public:
using Vector<ExecRow>::Vector;
using Vector<ExecRow>::At;
[[nodiscard]] bool CheckSize(uint32_t columns_num, uint32_t rows_num) const
{
return Size() == rows_num && (rows_num != 0u ? At(0).values.Size() == columns_num : false);
}
[[nodiscard]] const String& At(uint32_t column, uint32_t row) const { return At(row).values.At(column); }
};
Connection();
virtual ~Connection();
bool CreateInMemory();
bool Create(const String& file_name);
bool Open(const String& file_name, Mode mode);
void Close();
void CopyTo(Connection* db);
void SetPassword(const String& password, int legacy);
[[nodiscard]] ByteBuffer GetSalt() const;
[[nodiscard]] ByteBuffer GetKey() const;
void SetKey(const ByteBuffer& key);
[[nodiscard]] bool IsInvalid() const;
[[nodiscard]] bool IsError() const { return m_error; }
[[nodiscard]] int GetErrorCode() const { return m_error_code; }
[[nodiscard]] const String& GetErrorMsg() const { return m_error_msg; }
[[nodiscard]] int GetExtErrorCode() const { return m_ext_error_code; }
Statement* Prepare(const char* sql_text);
Statement* Prepare(const String& sql_text) { return Prepare(sql_text.C_Str()); }
void CloseAllStatements();
ExecResult Exec(const char* sql_text);
ExecResult Exec(const String& sql_text) { return Exec(sql_text.C_Str()); }
void BeginTransaction();
void EndTransaction();
void Vacuum();
int64_t GetLastInsertRowid();
int Changes();
KYTY_CLASS_NO_COPY(Connection);
friend struct ConnectionPrivate;
private:
bool m_error {false};
int m_error_code {};
int m_ext_error_code {};
String m_error_msg;
ConnectionPrivate* m_p {nullptr};
};
} // namespace Kyty::Core::Database
#endif /* INCLUDE_KYTY_CORE_DATABASE_H_ */
+198
View File
@@ -0,0 +1,198 @@
#ifndef INCLUDE_KYTY_CORE_DATETIME_H_
#define INCLUDE_KYTY_CORE_DATETIME_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Language.h"
#include "Kyty/Core/String.h"
namespace Kyty::Core {
using jd_t = int32_t;
constexpr jd_t DATE_JD_INVALID = (INT32_MIN);
constexpr int TIME_MS_INVALID = (-1);
constexpr int TIME_MS_IN_DAY = (24 * 3600 * 1000);
constexpr int MONTH_JANUARY = 1;
constexpr int MONTH_FEBRUARY = 2;
constexpr int MONTH_MARCH = 3;
constexpr int MONTH_APRIL = 4;
constexpr int MONTH_MAY = 5;
constexpr int MONTH_JUNE = 6;
constexpr int MONTH_JULY = 7;
constexpr int MONTH_AUGUST = 8;
constexpr int MONTH_SEPTEMBER = 9;
constexpr int MONTH_OCTOBER = 10;
constexpr int MONTH_NOVEMBER = 11;
constexpr int MONTH_DECEMBER = 12;
class Date final
{
public:
Date() = default;
explicit Date(jd_t d): m_jd(d) {}
Date(const Date& d) = default;
Date(Date&& d) noexcept = default;
Date(int year, int month, int day); // month in [1...12], day in [1...31]
~Date() = default;
static Date FromSystem();
static Date FromSystemUTC();
static Date FromMacros(const String& date);
void Set(int year, int month, int day);
void Set(jd_t jd) { this->m_jd = jd; }
void Get(int* year, int* month, int* day) const;
[[nodiscard]] bool IsInvalid() const { return m_jd == DATE_JD_INVALID; }
[[nodiscard]] int DaysInMonth() const;
[[nodiscard]] int DaysInYear() const;
[[nodiscard]] bool IsLeapYear() const;
[[nodiscard]] int Year() const;
[[nodiscard]] int Month() const;
[[nodiscard]] int Day() const;
[[nodiscard]] jd_t JulianDay() const { return m_jd; }
[[nodiscard]] int DayOfWeek() const;
[[nodiscard]] int DayOfYear() const;
[[nodiscard]] int QuarterOfYear() const;
String ToString(const char* format = "YYYY.MM.DD", LanguageId lang_id = LanguageId::English) const;
static bool IsValid(int year, int month, int day);
static int DaysInMonth(int month);
static int DaysInYear(int year);
static bool IsLeapYear(int year);
bool operator==(const Date& other) const { return m_jd == other.m_jd; }
bool operator!=(const Date& other) const { return m_jd != other.m_jd; }
bool operator<(const Date& other) const { return m_jd < other.m_jd; }
bool operator<=(const Date& other) const { return m_jd <= other.m_jd; }
bool operator>(const Date& other) const { return m_jd > other.m_jd; }
bool operator>=(const Date& other) const { return m_jd >= other.m_jd; }
Date& operator=(const Date& other) = default;
Date& operator=(Date&& other) noexcept = default;
Date operator+(int days) const { return Date(m_jd + days); }
Date operator-(int days) const { return Date(m_jd - days); }
Date operator+=(int days)
{
m_jd += days;
return *this;
}
Date operator-=(int days)
{
m_jd -= days;
return *this;
}
private:
jd_t m_jd {DATE_JD_INVALID};
};
class Time final
{
public:
Time() = default;
explicit Time(int msec): m_ms(msec)
{
if (m_ms < 0 || m_ms >= TIME_MS_IN_DAY)
{
m_ms = TIME_MS_INVALID;
}
}
Time(const Time& t) = default;
Time(Time&& t) noexcept = default;
Time(int hour24, int minute, int second, int msec = 0);
~Time() = default;
static Time FromSystem();
static Time FromSystemUTC();
void Set(int hour24, int minute, int second, int msec = 0);
void Set(int msec) { m_ms = msec; }
void Get(int* hour24, int* minute, int* second, int* msec = nullptr) const;
[[nodiscard]] bool IsInvalid() const { return m_ms < 0 || m_ms >= TIME_MS_IN_DAY; }
[[nodiscard]] int Hour12() const;
[[nodiscard]] int Hour24() const;
[[nodiscard]] bool IsAM() const;
[[nodiscard]] bool IsPM() const;
[[nodiscard]] int Minute() const;
[[nodiscard]] int Second() const;
[[nodiscard]] int Msec() const;
[[nodiscard]] int MsecTotal() const { return m_ms; }
String ToString(const char* format = "HH24:MI:SS") const;
static bool IsValid(int hour, int minute, int second, int msec = 0);
bool operator==(const Time& other) const { return m_ms == other.m_ms; }
bool operator!=(const Time& other) const { return m_ms != other.m_ms; }
bool operator<(const Time& other) const { return m_ms < other.m_ms; }
bool operator<=(const Time& other) const { return m_ms <= other.m_ms; }
bool operator>(const Time& other) const { return m_ms > other.m_ms; }
bool operator>=(const Time& other) const { return m_ms >= other.m_ms; }
Time& operator=(const Time& other) = default;
Time& operator=(Time&& other) noexcept = default;
Time operator+(int secs) const;
Time operator-(int secs) const;
Time operator+=(int secs);
Time operator-=(int secs);
private:
int m_ms {TIME_MS_INVALID};
};
class DateTime final
{
public:
DateTime() = default;
explicit DateTime(const Date& d): m_date(d) {}
explicit DateTime(const Time& t): m_time(t) {}
DateTime(const Date& d, const Time& t): m_date(d), m_time(t) {}
DateTime(const Time& t, const Date& d): m_date(d), m_time(t) {}
DateTime(const DateTime& dt) = default;
DateTime(DateTime&& dt) noexcept = default;
~DateTime() = default;
static DateTime FromSystem();
static DateTime FromSystemUTC();
static DateTime FromSQLiteJulian(double jd);
[[nodiscard]] double ToSQLiteJulian() const;
[[nodiscard]] int64_t ToSQLiteJulianInt64() const;
static DateTime FromUnix(double seconds);
[[nodiscard]] double ToUnix() const;
[[nodiscard]] uint64_t DistanceMs(const DateTime& other) const;
[[nodiscard]] bool IsInvalid() const { return m_date.IsInvalid() || m_time.IsInvalid(); }
void SetDate(const Date& d) { m_date = d; }
void SetTime(const Time& t) { m_time = t; }
Date& GetDate() { return m_date; }
Time& GetTime() { return m_time; }
[[nodiscard]] const Date& GetDate() const { return m_date; }
[[nodiscard]] const Time& GetTime() const { return m_time; }
String ToString(const char* format = "YYYY.MM.DD HH24:MI:SS", LanguageId lang_id = LanguageId::English) const;
DateTime& operator=(const DateTime& other) = default;
DateTime& operator=(DateTime&& other) noexcept = default;
bool operator==(const DateTime& other) const { return m_date == other.m_date && m_time == other.m_time; }
bool operator!=(const DateTime& other) const { return !(*this == other); }
bool operator<(const DateTime& other) const { return m_date < other.m_date || (m_date == other.m_date && m_time < other.m_time); }
bool operator<=(const DateTime& other) const { return !(other < *this); }
bool operator>(const DateTime& other) const { return other < *this; }
bool operator>=(const DateTime& other) const { return !(*this < other); }
private:
Date m_date;
Time m_time;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_DATETIME_H_ */
+74
View File
@@ -0,0 +1,74 @@
#ifndef INCLUDE_KYTY_CORE_DBGASSERT_H_
#define INCLUDE_KYTY_CORE_DBGASSERT_H_
#include "Kyty/Core/Common.h"
#include <cstdlib> // IWYU pragma: keep
#ifndef KYTY_FINAL
#define ASSERT_ENABLED
#endif
namespace Kyty::Core {
#ifdef __clang__
int dbg_exit_handler(char const* file, int line, const char* f, ...) KYTY_FORMAT_PRINTF(3, 4) __attribute__((analyzer_noreturn));
int dbg_assert_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn));
int dbg_exit_if_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn));
int dbg_not_implemented_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn));
#else
int dbg_exit_handler(char const* file, int line, const char* f, ...) KYTY_FORMAT_PRINTF(3, 4);
int dbg_assert_handler(char const* expr, char const* file, int line);
int dbg_exit_if_handler(char const* expr, char const* file, int line);
int dbg_not_implemented_handler(char const* expr, char const* file, int line);
#endif
bool dbg_is_debugger_present();
} // namespace Kyty::Core
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#define ASSERT_HALT() \
(Kyty::Core::dbg_is_debugger_present() ? (::fflush(nullptr), *(reinterpret_cast<volatile int*>(1)) = 0) : (std::_Exit(321), 1))
#else
#define ASSERT_HALT() (std::_Exit(321), 1)
#endif
//#define UNUSED(x) ((void)sizeof(x))
#ifdef ASSERT_ENABLED
#define ASSERT(x) ((void)(!(x) && Kyty::Core::dbg_assert_handler(#x, __FILE__, __LINE__) != 0 && (ASSERT_HALT(), 1) != 0))
#define EXIT_IF(x) ((void)((x) && Kyty::Core::dbg_exit_if_handler(#x, __FILE__, __LINE__) != 0 && (ASSERT_HALT(), 1) != 0))
#else
//#define ASSERT(x) ((void)sizeof(x))
//#define EXIT_IF(x) ((void)sizeof(x))
#define ASSERT(x) \
do \
{ \
constexpr bool __emp_assert_tmp = false && (x); \
(void)__emp_assert_tmp; \
} while (0)
#define EXIT_IF(x) \
do \
{ \
constexpr bool __emp_assert_tmp = false && (x); \
(void)__emp_assert_tmp; \
} while (0)
#endif
#if KYTY_COMPILER == KYTY_COMPILER_MSVC
#define EXIT(f, ...) \
{ \
((void)(Kyty::Core::dbg_exit_handler(__FILE__, __LINE__, f, __VA_ARGS__) && (ASSERT_HALT(), 1))); \
}
#else
#define EXIT(f, s...) \
{ \
((void)(Kyty::Core::dbg_exit_handler(__FILE__, __LINE__, f, ##s) && (ASSERT_HALT(), 1))); \
}
#endif
#define EXIT_NOT_IMPLEMENTED(x) \
((void)((x) && Kyty::Core::dbg_not_implemented_handler(#x, __FILE__, __LINE__) != 0 && (ASSERT_HALT(), 1) != 0))
#define KYTY_NOT_IMPLEMENTED EXIT_NOT_IMPLEMENTED(true)
#endif /* INCLUDE_KYTY_CORE_DBGASSERT_H_ */
+71
View File
@@ -0,0 +1,71 @@
#ifndef INCLUDE_KYTY_CORE_DEBUG_H_
#define INCLUDE_KYTY_CORE_DEBUG_H_
#include "Kyty/Core/ArrayWrapper.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
namespace Kyty::Core {
void core_debug_init(const char* app_name);
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && KYTY_BUILD == KYTY_BUILD_DEBUG && KYTY_COMPILER == KYTY_COMPILER_CLANG
constexpr int DEBUG_MAX_STACK_DEPTH = 20;
#else
constexpr int DEBUG_MAX_STACK_DEPTH = 15;
#endif
struct DebugMapPrivate;
namespace Debug {
String GetCompiler();
String GetLinker();
String GetBitness();
} // namespace Debug
class DebugMap
{
public:
DebugMap();
virtual ~DebugMap();
void LoadMap();
void LoadCsv();
void LoadMsvcLink(const String& name, int mode);
void LoadGnuLd(const String& name, int bitness);
void LoadLlvmLld(const String& name, int bitness);
void LoadCsv(const String& name);
void DumpMap(const String& name);
friend struct DebugMapPrivate;
KYTY_CLASS_NO_COPY(DebugMap);
private:
DebugMapPrivate* m_p;
};
struct DebugStack
{
int depth {0};
Array<void*, DEBUG_MAX_STACK_DEPTH> stack {};
[[nodiscard]] uintptr_t GetAddr(int i) const { return reinterpret_cast<uintptr_t>(stack[i]); }
void Print(int from, bool with_name = true) const;
void PrintAndroid(int from, bool with_name = true) const;
void CopyTo(DebugStack* s) const
{
std::memcpy(s->stack, stack, sizeof(void*) * depth);
s->depth = depth;
}
static void Trace(DebugStack* stack);
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_DEBUG_H_ */
+161
View File
@@ -0,0 +1,161 @@
#ifndef INCLUDE_KYTY_CORE_FILE_H_
#define INCLUDE_KYTY_CORE_FILE_H_
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DateTime.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Vector.h"
struct SDL_RWops;
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#ifdef CreateDirectory
#undef CreateDirectory
#endif
#ifdef DeleteFile
#undef DeleteFile
#endif
#ifdef CopyFile
#undef CopyFile
#endif
#ifdef MoveFile
#undef MoveFile
#endif
#endif
namespace Kyty::Core {
// SUBSYSTEM_DEFINE(File);
void core_file_init();
class File
{
public:
enum class Encoding
{
Unknown,
Utf8,
Utf16BE,
Utf16LE,
Utf32BE,
Utf32LE
};
enum class Mode
{
Read,
Write,
ReadWrite,
WriteRead
};
struct FindInfo
{
String path_with_name;
String rel_path_with_name;
DateTime last_access_time;
DateTime last_write_time;
uint64_t size;
};
struct DirEntry
{
String name;
bool is_file;
};
File();
explicit File(const String& name);
File(const String& name, Mode mode);
virtual ~File();
bool Create(const String& name);
bool Open(const String& name, Mode mode);
bool OpenInMem(void* buf, uint32_t buf_size);
bool OpenInMem(ByteBuffer& buf); // NOLINT(google-runtime-references)
bool CreateInMem();
void Close();
bool Flush();
[[nodiscard]] uint64_t Size() const;
[[nodiscard]] uint64_t Remaining() const;
bool Seek(uint64_t offset);
[[nodiscard]] uint64_t Tell() const;
bool Truncate(uint64_t size);
[[nodiscard]] bool IsInvalid() const;
[[nodiscard]] bool IsEOF() const { return Tell() >= Size(); }
void GetLastAccessAndWriteTimeUTC(DateTime* access, DateTime* write);
void Read(void* data, uint32_t size, uint32_t* bytes_read = nullptr);
ByteBuffer Read(uint32_t size);
void Write(const void* data, uint32_t size, uint32_t* bytes_written = nullptr);
void Write(const ByteBuffer& buf, uint32_t* bytes_written = nullptr);
void ReadR(void* data, uint32_t size);
void WriteR(const void* data, uint32_t size);
void Write(const String& str, uint32_t* bytes_written = nullptr);
void WriteBOM();
String ReadLine();
String ReadWholeString();
[[nodiscard]] Encoding GetEncoding() const;
void SetEncoding(Encoding e);
void DetectEncoding();
void Printf(const char* format, ...) KYTY_FORMAT_PRINTF(2, 3);
void PrintfLF(const char* format, ...) KYTY_FORMAT_PRINTF(2, 3);
ByteBuffer ReadWholeBuffer();
static uint64_t Size(const String& name);
static String Read(const String& name, Encoding e);
static bool IsDirectoryExisting(const String& path);
static bool IsFileExisting(const String& name);
static bool IsAssetFileExisting(const String& name);
static bool CreateDirectory(const String& path);
static bool CreateDirectories(const String& path);
static bool DeleteDirectory(const String& path);
static bool DeleteDirectories(const String& path);
static bool DeleteFile(const String& name);
static DateTime GetLastAccessTimeUTC(const String& name);
static DateTime GetLastWriteTimeUTC(const String& name);
static void GetLastAccessAndWriteTimeUTC(const String& name, DateTime* access, DateTime* write);
static bool SetLastAccessTimeUTC(const String& name, const DateTime& dt);
static bool SetLastWriteTimeUTC(const String& name, const DateTime& dt);
static bool SetLastAccessAndWriteTimeUTC(const String& name, const DateTime& access, const DateTime& write);
static Vector<FindInfo> FindFiles(const String& path);
static Vector<DirEntry> GetDirEntries(const String& path);
static bool CopyFile(const String& src, const String& dst);
static bool MoveFile(const String& src, const String& dst);
static void RemoveReadonly(const String& name);
static void SyncDirectories(const String& src_dir, const String& dst_dir, bool del_dst = true);
static void SetAssetsDir(const String& dir);
static String GetAssetsDir();
static void SetAssetsSubDir(const String& dir);
static String GetAssetsSubDir();
SDL_RWops* CreateSdlRWops();
KYTY_CLASS_NO_COPY(File);
private:
struct FilePrivate;
String m_file_name;
FilePrivate* m_p;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_FILE_H_ */
+164
View File
@@ -0,0 +1,164 @@
#ifndef INCLUDE_KYTY_CORE_HASH_H_
#define INCLUDE_KYTY_CORE_HASH_H_
#include "Kyty/Core/Common.h"
namespace Kyty::Core {
inline uint32_t hash(const void *key, uint32_t key_len)
{
uint32_t hash = 0;
const auto *ptr = static_cast<const uint8_t*>(key);
while(key_len >= 4)
{
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[2];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[3];
hash += (hash << 10u);
hash ^= (hash >> 6u);
key_len -= 4;
ptr += 4;
}
switch(key_len)
{
case 3:
hash += ptr[2];
hash += (hash << 10u);
hash ^= (hash >> 6u);
[[fallthrough]];
case 2:
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
[[fallthrough]];
case 1:
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
[[fallthrough]];
default:
break;
}
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash8(uint8_t key)
{
uint32_t hash = 0;
uint8_t *ptr = &key;
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash16(uint16_t key)
{
uint32_t hash = 0;
auto *ptr = reinterpret_cast<uint8_t *>(&key);
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash32(uint32_t key)
{
uint32_t hash = 0;
auto *ptr = reinterpret_cast<uint8_t *>(&key);
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[2];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[3];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash64(uint64_t key)
{
uint32_t hash = 0;
auto *ptr = reinterpret_cast<uint8_t *>(&key);
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[2];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[3];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[4];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[5];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[6];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[7];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_HASH_H_ */
+182
View File
@@ -0,0 +1,182 @@
#ifndef INCLUDE_KYTY_CORE_HASHMAP_H_
#define INCLUDE_KYTY_CORE_HASHMAP_H_
#include "Kyty/Core/Common.h"
#include <new>
namespace Kyty::Core {
class HashmapPrivate;
//#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
//#define HASH_CALL __stdcall
//#else
#define KYTY_HASH_CALL
//#endif
#define KYTY_HASH_DEFINE_CALC(type) \
template <> \
uint32_t KYTY_HASH_CALL hash_calc<>(type const* key)
#define KYTY_HASH_DEFINE_EQUALS(type) \
template <> \
bool KYTY_HASH_CALL hash_key_equals(type const* key_a, type const* key_b)
#define KYTY_HASH_CALLBACK(name, K, V, arg) \
static void KYTY_HASH_CALL name(K* key, V* value, void* arg) /* NOLINT(bugprone-macro-parentheses) */
template <class T>
uint32_t KYTY_HASH_CALL hash_calc(const T* key);
template <class T>
bool KYTY_HASH_CALL hash_key_equals(const T* key_a, const T* key_b);
template <class T>
void KYTY_HASH_CALL hash_key_copy(T* key_dst, const T* key_src)
{
new (key_dst) T(*key_src);
}
template <class T>
void KYTY_HASH_CALL hash_value_copy(T* value_dst, const T* value_src)
{
new (value_dst) T(*value_src);
}
template <class T>
void KYTY_HASH_CALL hash_key_free(T* key)
{
key->~T();
}
template <class T>
void KYTY_HASH_CALL hash_value_free(T* value)
{
value->~T();
}
using hash_calc_func_t = uint32_t (*)(const void*);
using hash_key_equals_func_t = bool (*)(const void*, const void*);
using hash_key_copy_func_t = void (*)(void*, const void*);
using hash_value_copy_func_t = void (*)(void*, const void*);
using hash_key_free_func_t = void (*)(void*);
using hash_value_free_func_t = void (*)(void*);
using hash_callback_func_t = bool (*)(const void*, const void*, void*);
class HashmapBase
{
public:
HashmapBase(uint32_t key_size, uint32_t value_size, hash_calc_func_t hash, hash_key_equals_func_t equals, hash_key_copy_func_t key_copy,
hash_value_copy_func_t value_copy, hash_key_free_func_t key_free, hash_value_free_func_t value_free);
virtual ~HashmapBase();
void Clear();
[[nodiscard]] uint32_t Size() const;
void Put(const void* key, const void* value);
const void* Get(const void* key) const;
void Remove(const void* key);
void* OperatorSquareBrackets(const void* key, const void* default_value);
void Start() const;
[[nodiscard]] bool End() const;
void Next() const;
[[nodiscard]] const void* Value() const;
[[nodiscard]] const void* Key() const;
void ForEach(hash_callback_func_t callback, void* arg) const;
[[nodiscard]] uint32_t CollisionsCount() const;
KYTY_CLASS_NO_COPY(HashmapBase);
private:
HashmapPrivate* m_p;
};
template <class K, class V>
class Hashmap
{
public:
Hashmap()
: m_b(sizeof(K), sizeof(V), // NOLINT(bugprone-sizeof-expression)
reinterpret_cast<hash_calc_func_t>(hash_calc<K>), reinterpret_cast<hash_key_equals_func_t>(hash_key_equals<K>),
reinterpret_cast<hash_key_copy_func_t>(hash_key_copy<K>), reinterpret_cast<hash_value_copy_func_t>(hash_value_copy<V>),
reinterpret_cast<hash_key_free_func_t>(hash_key_free<K>), reinterpret_cast<hash_value_free_func_t>(hash_value_free<V>))
{
}
virtual ~Hashmap() = default;
void Clear() { m_b.Clear(); }
[[nodiscard]] uint32_t Size() const { return m_b.Size(); }
V& operator[](const K& key)
{
V def;
return *(static_cast<V*>(m_b.OperatorSquareBrackets(&key, &def)));
}
V& GetOrPutDef(const K& key, const V& def) { return *(static_cast<V*>(m_b.OperatorSquareBrackets(&key, &def))); }
void Put(const K& key, const V& value) { m_b.Put(&key, &value); }
[[nodiscard]] V Get(const K& key, const V& default_value = V()) const
{
const V* v = static_cast<const V*>(m_b.Get(&key));
return (v ? *v : default_value);
}
[[nodiscard]] const V* Find(const K& key) const { return static_cast<const V*>(m_b.Get(&key)); }
[[nodiscard]] bool Contains(const K& key) const { return m_b.Get(&key); }
void Remove(const K& key) { m_b.Remove(&key); }
void Start() const { m_b.Start(); }
[[nodiscard]] bool End() const { return m_b.End(); }
void Next() const { m_b.Next(); }
[[nodiscard]] const V& Value() const { return *(static_cast<const V*>(m_b.Value())); }
[[nodiscard]] const K& Key() const { return *(static_cast<const K*>(m_b.Key())); }
void ForEach(bool(KYTY_HASH_CALL* callback)(const K* key, const V* value, void* context), void* arg) const
{
m_b.ForEach(reinterpret_cast<hash_callback_func_t>(callback), arg);
}
uint32_t CollisionsCount() { return m_b.CollisionsCount(); }
bool operator==(const Hashmap<K, V>& other) const
{
if (Size() != other.Size())
{
return false;
}
bool ok = true;
auto callback = [&ok, &other](const K* key, const V* value) {
if (!(other.Find(*key) && other.Get(*key) == *value))
{
ok = false;
return false;
}
return true;
};
ForEach([](const K* key, const V* value, void* func) { return (*static_cast<decltype(callback)*>(func))(key, value); }, &callback);
return ok;
}
bool operator!=(const Hashmap<K, V>& other) const { return !(*this == other); }
KYTY_CLASS_NO_COPY(Hashmap);
private:
HashmapBase m_b;
};
#define FOR_HASH(h) for ((h).Start(); !(h).End(); (h).Next()) /*NOLINT(cppcoreguidelines-macro-usage)*/
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_HASHMAP_H_ */
+80
View File
@@ -0,0 +1,80 @@
#ifndef INCLUDE_KYTY_CORE_JSONREADER_H_
#define INCLUDE_KYTY_CORE_JSONREADER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Vector.h"
namespace Kyty::Core {
enum JsonType
{
JsonBool,
JsonNULL,
JsonNumber,
JsonString,
JsonArray,
JsonObject,
};
class Json
{
public:
using ListType = Vector<const Json*>;
virtual ~Json();
static void Init();
static const Json* Create(const String& str);
static String GetError();
// const Json* GetItem(const String &string) const;
// String GetString(const String &name, const String &default_value) const;
// double GetFloat(const String &name, double default_value) const;
// int64_t GetInt(const String &name, int64_t default_value) const;
const Json* GetItem(const char* string) const;
String GetString(const char* name, const String& default_value) const;
String GetString(const char* name) const;
double GetFloat(const char* name, double default_value) const;
int64_t GetInt(const char* name, int64_t default_value) const;
bool GetBool(const char* name, bool default_value) const;
[[nodiscard]] String GetName() const { return m_name; }
[[nodiscard]] JsonType GetType() const { return m_type; }
[[nodiscard]] bool IsNull() const { return m_type == JsonNULL; }
[[nodiscard]] bool IsNumber() const { return m_type == JsonNumber; }
[[nodiscard]] bool IsString() const { return m_type == JsonString; }
[[nodiscard]] bool IsObject() const { return m_type == JsonObject; }
[[nodiscard]] bool IsArray() const { return m_type == JsonArray; }
[[nodiscard]] bool IsBool() const { return m_type == JsonBool; }
[[nodiscard]] String ToString() const { return m_value_string; }
[[nodiscard]] double ToFloat() const { return m_value_double; }
[[nodiscard]] int64_t ToInt() const { return m_value_int; }
[[nodiscard]] int64_t ToBool() const { return static_cast<int64_t>(m_value_bool); }
[[nodiscard]] const ListType& ToArray() const { return m_list; }
[[nodiscard]] StringList DbgCheckList(const StringList& required, const StringList& optional) const;
KYTY_CLASS_NO_COPY(Json);
private:
Json() = default;
const char32_t* parse_value(const char32_t* value);
const char32_t* parse_array(const char32_t* value);
const char32_t* parse_object(const char32_t* value);
const char32_t* parse_string(const char32_t* str);
const char32_t* parse_number(const char32_t* value);
ListType m_list;
JsonType m_type = JsonNULL;
String m_value_string;
int64_t m_value_int = 0;
double m_value_double = 0.0;
bool m_value_bool = false;
String m_name;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_JSONREADER_H_ */
+46
View File
@@ -0,0 +1,46 @@
#ifndef INCLUDE_KYTY_CORE_LANGUAGE_H_
#define INCLUDE_KYTY_CORE_LANGUAGE_H_
#include "Kyty/Core/String.h"
namespace Kyty::Core {
// SUBSYSTEM_DEFINE(Language);
enum class LanguageId
{
Unknown,
// Arabic,
// Chinese,
German,
English,
French,
// Hindi,
Italian,
// Japanese,
// Korean,
Portuguese,
Russian,
Spanish
};
namespace Language {
void Init();
StringList GetLanguages();
LanguageId GetId(const String& id);
String GetCharList(const String& id);
String GetLettersList(const String& id);
String GetLettersList(LanguageId lang_id);
String GetNumericList(const String& id);
String GetPunctuationList(const String& id);
String GetCharListAll();
String GetNameOfMonth(int month, LanguageId lang_id);
String GetNameOfMonthShort(int month, LanguageId lang_id);
String GetNameOfDay(int day, LanguageId lang_id);
String GetNameOfDayShort(int day, LanguageId lang_id);
} // namespace Language
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_LANGUAGE_H_ */
+317
View File
@@ -0,0 +1,317 @@
#ifndef INCLUDE_KYTY_CORE_LINKLIST_H_
#define INCLUDE_KYTY_CORE_LINKLIST_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/SafeDelete.h"
#include <type_traits>
namespace Kyty::Core {
template <typename T>
class List;
// typedef struct {void *p;} ListIndex;
using ListIndex = struct
{
void* p;
};
#define FOR_LIST(index, list) /*NOLINT(cppcoreguidelines-macro-usage)*/ \
for (Core::ListIndex index = (list).First(); (list).IndexValid(index); \
index = (list).Next(index)) /* NOLINT(bugprone-macro-parentheses) */
#define FOR_LIST_R(index, list) /*NOLINT(cppcoreguidelines-macro-usage)*/ \
for (Core::ListIndex index = (list).Last(); (list).IndexValid(index); \
index = (list).Prev(index)) /* NOLINT(bugprone-macro-parentheses) */
template <typename T>
class ListNode
{
/*private:*/
friend class List<T>;
explicit ListNode(const T& v): m_value(v), m_next(this), m_prev(this) {}
virtual ~ListNode() { Remove(); }
void Remove()
{
m_prev->m_next = m_next;
m_next->m_prev = m_prev;
m_next = this;
m_prev = this;
}
void InsertBefore(ListNode<T>* node)
{
m_next = node;
m_prev = node->m_prev;
node->m_prev = this;
m_prev->m_next = this;
}
[[nodiscard]] ListNode<T>* PrevNode() const { return m_prev; }
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDelete)
[[nodiscard]] ListNode<T>* NextNode() const { return m_next; }
T& Value() { return m_value; }
T m_value;
ListNode<T>* m_next;
ListNode<T>* m_prev;
KYTY_CLASS_NO_COPY(ListNode);
};
template <typename T>
class List
{
/*private:*/
template <typename T2>
using IsNotListType = typename std::enable_if<!std::is_same<typename std::remove_reference<T2>::type, T>::value>::type;
public:
using Index = ListIndex;
List() = default;
List(const List<T>& list) { (*this) = list; }
List(List<T>&& list) noexcept { (*this) = list; }
virtual ~List() { Clear(); }
[[nodiscard]] uint32_t Size() const { return m_size; }
void Clear()
{
if (m_head)
{
while (m_head->NextNode() != m_head)
{
delete m_head->NextNode();
}
DeleteProtected(m_head);
}
m_head = nullptr;
m_size = 0;
}
virtual Index Add(const T& v) { return add(v); }
[[nodiscard]] bool IndexValid(Index index) const { return !(index.p == nullptr); }
[[nodiscard]] Index First() const
{
Index ret = {m_head};
return ret;
}
[[nodiscard]] Index Last() const
{
Index ret = {m_head ? m_head->PrevNode() : nullptr};
return ret;
}
[[nodiscard]] Index Next(Index index) const
{
auto* node = static_cast<ListNode<T>*>(index.p);
if (node)
{
node = node->NextNode();
if (node == m_head)
{
node = nullptr;
}
}
Index ret = {node};
return ret;
}
[[nodiscard]] Index Prev(Index index) const
{
auto* node = static_cast<ListNode<T>*>(index.p);
if (node)
{
node = node->PrevNode();
if (node->NextNode() == m_head)
{
node = nullptr;
}
}
Index ret = {node};
return ret;
}
T& operator[](Index index)
{
EXIT_IF(!IndexValid(index));
auto* node = static_cast<ListNode<T>*>(index.p);
return node->Value();
}
const T& operator[](Index index) const
{
EXIT_IF(!IndexValid(index));
auto* node = static_cast<ListNode<T>*>(index.p);
return node->Value();
}
[[nodiscard]] const T& At(Index index) const
{
EXIT_IF(!IndexValid(index));
auto* node = static_cast<ListNode<T>*>(index.p);
return node->Value();
}
[[nodiscard]] Index Find(const T& value) const
{
FOR_LIST(index, (*this))
{
if ((*this)[index] == value)
{
return index;
}
}
Index ret = {nullptr};
return ret;
}
template <typename T2, typename OP>
[[nodiscard]] Index Find(const T2& t, OP&& op_eq) const
{
FOR_LIST(index, (*this))
{
if (op_eq((*this)[index], t))
{
return index;
}
}
Index ret = {nullptr};
return ret;
}
template <typename T2, typename T3, typename OP>
[[nodiscard]] Index Find(const T2& t2, const T3& t3, OP&& op_eq) const
{
FOR_LIST(index, (*this))
{
if (op_eq((*this)[index], t2, t3))
{
return index;
}
}
Index ret = {nullptr};
return ret;
}
[[nodiscard]] bool Contains(const T& value) const { return IndexValid(Find(value)); }
Index Remove(const T& value)
{
Index index = Find(value);
return Remove(index);
}
Index Remove(Index index)
{
if (!IndexValid(index))
{
Index ret = {nullptr};
return ret;
}
auto* node = static_cast<ListNode<T>*>(index.p);
auto* next = static_cast<ListNode<T>*>(Next(index).p);
if (node == m_head)
{
if (next == nullptr)
{
DeleteProtected(m_head);
m_head = nullptr;
m_size = 0;
Index ret = {nullptr};
return ret;
}
m_head = next;
}
DeleteProtected(node);
m_size--;
Index ret = {next};
return ret;
}
// NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
List<T>& operator=(const List<T>& list)
{
if (this != &list)
{
Clear();
FOR_LIST(index, list) { add(list[index]); }
}
return *this;
}
List<T>& operator=(List<T>&& list) noexcept
{
*this = list;
return *this;
}
private:
Index add(const T& v)
{
auto* node = new ListNode<T>(v);
if (m_head)
{
node->InsertBefore(m_head);
} else
{
m_head = node;
}
m_size++;
Index ret = {node};
return ret;
}
ListNode<T>* m_head = {nullptr};
uint32_t m_size = {0};
};
template <typename T>
class ListSet: public List<T>
{
public:
typename List<T>::Index Add(const T& v) override
{
typename List<T>::Index index = this->Find(v);
if (!this->IndexValid(index))
{
return List<T>::Add(v);
}
return index;
}
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_LINKLIST_H_ */
+41
View File
@@ -0,0 +1,41 @@
#ifndef INCLUDE_KYTY_CORE_MAGICENUM_H_
#define INCLUDE_KYTY_CORE_MAGICENUM_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "magic_enum.hpp" // IWYU pragma: export
namespace Kyty::Core {
template <typename E>
inline String EnumName(E v)
{
auto str = magic_enum::enum_name(v);
return String::FromUtf8(str.data(), static_cast<uint32_t>(str.length()));
}
template <typename E>
inline E EnumValue(const String& str, E default_value)
{
auto v = magic_enum::enum_cast<E>(str.C_Str());
if (v.has_value())
{
return v.value();
}
return default_value;
}
#define KYTY_ENUM_RANGE(e, mx, mn) \
namespace magic_enum::customize { \
template <> \
struct enum_range<e> \
{ \
static constexpr int min = (mx); \
static constexpr int max = (mn); \
}; \
}
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_MAGICENUM_H_ */
+35
View File
@@ -0,0 +1,35 @@
#ifndef INCLUDE_KYTY_CORE_MEMORYALLOC_H_
#define INCLUDE_KYTY_CORE_MEMORYALLOC_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Core {
// SUBSYSTEM_DEFINE(Memory);
void core_memory_init();
struct MemStats
{
int state;
size_t total_allocated;
uint32_t blocks_num;
};
void* mem_alloc(size_t size);
void* mem_realloc(void* ptr, size_t size);
void mem_free(void* ptr);
void mem_print(int from_state);
void mem_get_stat(MemStats* s);
void mem_set_max_size(size_t size);
int mem_new_state();
bool mem_tracker_enabled();
void mem_tracker_enable();
void mem_tracker_disable();
bool mem_check(const void* ptr);
#define KYTY_MEM_CHECK(ptr) EXIT_IF(!mem_check(ptr))
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_MEMORYALLOC_H_ */
+86
View File
@@ -0,0 +1,86 @@
#ifndef INCLUDE_KYTY_CORE_REFCOUNTER_H_
#define INCLUDE_KYTY_CORE_REFCOUNTER_H_
#include "Kyty/Core/Common.h"
namespace Kyty::Core {
template <class MutexPolicy>
class RefCounter
{
public:
RefCounter() = default;
virtual ~RefCounter() = default;
void Release() const
{
Lock();
if (DecRef() == 0)
{
Unlock();
delete this;
} else
{
Unlock();
}
}
template <class PtrType>
void CopyPtr(PtrType** dst, PtrType* src) const
{
Lock();
*dst = src;
AddRef();
Unlock();
}
template <class PtrType>
void CopyOnWrite(PtrType** data) const
{
Lock();
if (Refs() > 1)
{
if (DecRef() == 0)
{
Unlock();
delete this;
} else
{
Unlock();
}
*data = new PtrType(**data);
} else
{
Unlock();
}
}
KYTY_CLASS_NO_COPY(RefCounter);
private:
uint32_t AddRef() const { return ++m_refs; }
uint32_t Refs() const { return m_refs; }
uint32_t DecRef() const
{
EXIT_IF(m_refs == 0);
uint32_t ret = --m_refs;
return ret;
}
void Lock() const { m_mutex.Lock(); }
void Unlock() const { m_mutex.Unlock(); }
mutable uint32_t m_refs = {1};
mutable MutexPolicy m_mutex;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_REFCOUNTER_H_ */
+12
View File
@@ -0,0 +1,12 @@
#ifndef INCLUDE_KYTY_GAME_SDLSUBSYSTEM_H_
#define INCLUDE_KYTY_GAME_SDLSUBSYSTEM_H_
#include "Kyty/Core/Subsystems.h"
namespace Kyty::Core {
KYTY_SUBSYSTEM_DEFINE(SDL);
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_GAME_SDLSUBSYSTEM_H_ */
+75
View File
@@ -0,0 +1,75 @@
#ifndef INCLUDE_KYTY_CORE_SAFEDELETE_H_
#define INCLUDE_KYTY_CORE_SAFEDELETE_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include <cstring>
namespace Kyty {
#define KYTY_CORE_SAFE_DELETE_DEADBEEF (reinterpret_cast<void*>((uintptr_t)0x01))
#define DeleteProtected(p) /* NOLINT(cppcoreguidelines-macro-usage) */ \
{ \
if (!(p)) \
{ \
EXIT("delete null\n"); \
} \
void* dddd = KYTY_CORE_SAFE_DELETE_DEADBEEF; \
if (std::memcmp(&(p), &dddd, sizeof(void*)) == 0) \
{ \
EXIT("already deleted\n"); \
} \
delete (p); \
std::memcpy(&(p), &dddd, sizeof(void*)); \
}
#define DeleteProtectedArray(p) /* NOLINT(cppcoreguidelines-macro-usage) */ \
{ \
if (!(p)) \
{ \
EXIT("delete null\n"); \
} \
void* dddd = KYTY_CORE_SAFE_DELETE_DEADBEEF; \
if (std::memcmp(&(p), &dddd, sizeof(void*)) == 0) \
{ \
EXIT("already deleted\n"); \
} \
delete[](p); \
std::memcpy(&(p), &dddd, sizeof(void*)); \
}
template <class T>
void Delete(T*& p)
{
if (!p)
{
EXIT("delete null\n");
}
if (p == static_cast<T*>(KYTY_CORE_SAFE_DELETE_DEADBEEF))
{
EXIT("already deleted\n");
}
delete p;
p = static_cast<T*>(KYTY_CORE_SAFE_DELETE_DEADBEEF);
}
template <class T>
void DeleteArray(T*& p)
{
if (!p)
{
EXIT("delete null\n");
}
if (p == static_cast<T*>(KYTY_CORE_SAFE_DELETE_DEADBEEF))
{
EXIT("already deleted\n");
}
delete[] p;
p = static_cast<T*>(KYTY_CORE_SAFE_DELETE_DEADBEEF);
}
} // namespace Kyty
#endif /* INCLUDE_KYTY_CORE_SAFEDELETE_H_ */
+647
View File
@@ -0,0 +1,647 @@
#ifndef INCLUDE_KYTY_CORE_SIMPLEARRAY_H_
#define INCLUDE_KYTY_CORE_SIMPLEARRAY_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Hash.h"
#include "Kyty/Core/MemoryAlloc.h"
#include "Kyty/Core/RefCounter.h"
#include "Kyty/Core/Threads.h"
// IWYU pragma: begin_exports
#include <cstring>
#include <functional>
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>
// IWYU pragma: end_exports
// IWYU pragma: private
namespace Kyty::Core {
#define KYTY_ARRAY_DEFINE_SWAP(name, type) \
void name(type* array, int32_t i, int32_t j, [[maybe_unused]] void* arg) /* NOLINT(bugprone-macro-parentheses) */
template <typename T, typename R>
using IsTriviallyCopyable = typename std::enable_if<std::is_trivially_copyable<T>::value, R>::type;
template <typename T, typename R>
using IsNotTriviallyCopyable = typename std::enable_if<!std::is_trivially_copyable<T>::value, R>::type;
template <typename T>
class SimpleArray: public RefCounter<Mutex>
{
public:
using ValueType = T;
using ArrayType = SimpleArray<T>;
using SortSwapFunc = void (*)(T*, int32_t, int32_t, void*);
using SortCompareFunc = bool (*)(const T&, const T&);
static constexpr size_t SIZEOF_T = sizeof(T); // NOLINT(bugprone-sizeof-expression)
SimpleArray() = default;
SimpleArray(const ArrayType& src) { copy(src); }
SimpleArray(ArrayType&& src) = delete;
explicit SimpleArray(uint32_t size, bool ctor = true)
: m_values_num(size), m_values_limit(size), m_values(static_cast<T*>(mem_alloc(m_values_limit * SIZEOF_T)))
{
if (ctor)
{
for (uint32_t index = 0; index < m_values_num; index++)
{
new (m_values + index) T();
}
}
}
SimpleArray(std::initializer_list<T> list): SimpleArray(static_cast<uint32_t>(list.size()))
{
T* values_ptr = m_values;
for (const T& e: list)
{
*(values_ptr++) = e;
}
}
~SimpleArray() override { Free(); }
uint32_t Size() const { return m_values_num; }
uint32_t Capacity() const { return m_values_limit; }
uint32_t Hash() { return hash(); } // @suppress("Ambiguous problem")
void Clear()
{
for (uint32_t index = 0; index < m_values_num; index++)
{
m_values[index].~T();
}
m_values_num = 0;
m_hash = 0;
}
void Free()
{
Clear();
if (m_values)
{
mem_free(m_values);
}
m_values_limit = 0;
m_values = nullptr;
}
// NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
SimpleArray<T>& operator=(const ArrayType& src)
{
if (this != &src)
{
Free();
copy(src);
}
return *this;
}
ArrayType& operator=(ArrayType&& src) = delete;
bool operator==(const ArrayType& s) const
{
if (m_values_num != s.m_values_num)
{
return false;
}
for (uint32_t index = 0; index < m_values_num; index++)
{
if (!(m_values[index] == s.m_values[index]))
{
return false;
}
}
return true;
}
void Expand(uint32_t num) { expand(num); } // @suppress("Ambiguous problem")
void Add(const T& val)
{
uint32_t values_i = m_values_num;
expand(1); // @suppress("Ambiguous problem")
m_values_num = values_i + 1;
new (m_values + values_i) T(val);
m_hash = 0;
}
void Add(T&& val)
{
uint32_t values_i = m_values_num;
expand(1); // @suppress("Ambiguous problem")
m_values_num = values_i + 1;
new (m_values + values_i) T(std::forward<T>(val));
m_hash = 0;
}
void Add(const T* val, uint32_t num)
{
uint32_t values_i = m_values_num;
expand(num); // @suppress("Ambiguous problem")
m_values_num = values_i + num;
for (uint32_t i = 0; i < num; i++)
{
new (m_values + values_i + i) T(val[i]);
}
m_hash = 0;
}
void InsertAt(uint32_t index, const T& val)
{
Add(val);
if (IndexValid(index))
{
for (uint32_t last_index = m_values_num - 1; last_index != index; last_index--)
{
std::swap(m_values[last_index], m_values[last_index - 1]);
}
}
}
void InsertAt(uint32_t index, T&& val)
{
Add(std::forward<T>(val));
if (IndexValid(index))
{
for (uint32_t last_index = m_values_num - 1; last_index != index; last_index--)
{
std::swap(m_values[last_index], m_values[last_index - 1]);
}
}
}
uint32_t Find(const T& t) const
{
for (uint32_t index = 0; index < m_values_num; index++)
{
if (m_values[index] == t)
{
return index;
}
}
return uint32_t(-1);
}
template <typename OP>
uint32_t Find(const T& t, OP&& op_eq) const
{
for (uint32_t index = 0; index < m_values_num; index++)
{
if (op_eq(m_values[index], t))
{
return index;
}
}
return uint32_t(-1);
}
template <typename T2, typename OP>
uint32_t Find(const T2& t, OP&& op_eq) const
{
for (uint32_t index = 0; index < m_values_num; index++)
{
if (op_eq(m_values[index], t))
{
return index;
}
}
return uint32_t(-1);
}
template <typename T2, typename OP, typename V>
void FindAll(const T2& t, OP&& op_eq, V* ret) const
{
for (uint32_t index = 0; index < m_values_num; index++)
{
if (op_eq(m_values[index], t))
{
ret->Add(index);
}
}
}
template <typename T2, typename T3, typename OP>
uint32_t Find(const T2& t2, const T3& t3, OP&& op_eq) const
{
for (uint32_t index = 0; index < m_values_num; index++)
{
if (op_eq(m_values[index], t2, t3))
{
return index;
}
}
return uint32_t(-1);
}
bool Remove(const T& t)
{
uint32_t index = Find(t);
if (index == uint32_t(-1))
{
return false;
}
return RemoveAt(index);
}
bool RemoveAt(uint32_t index, uint32_t count = 1) { return remove_at(index, count); } // @suppress("Ambiguous problem")
[[nodiscard]] bool IndexValid(uint32_t index) const { return index < m_values_num; }
T& operator[](uint32_t index)
{
m_hash = 0;
if (index >= m_values_num)
{
EXIT_IF(index >= m_values_num);
}
return m_values[index];
}
const T& operator[](uint32_t index) const
{
EXIT_IF(index >= m_values_num);
return m_values[index];
}
const T& At(uint32_t index) const
{
if (index >= m_values_num)
{
EXIT_IF(index >= m_values_num);
}
return m_values[index];
}
T* GetData()
{
m_hash = 0;
return m_values;
}
const T* GetData() const { return m_values; }
const T* GetDataConst() const { return m_values; }
void Memset(int c)
{
m_hash = 0;
memset(m_values, c, m_values_num * SIZEOF_T);
}
void Sort()
{
if (m_values_num == 0)
{
return;
}
sort(0, m_values_num - 1, 0);
m_hash = 0;
}
void Sort(SortCompareFunc comp_func)
{
if (m_values_num == 0)
{
return;
}
sort_with_compare_func(0, m_values_num - 1, 0, comp_func);
m_hash = 0;
}
void Sort(SortSwapFunc swap_func, void* swap_arg)
{
if (m_values_num == 0)
{
return;
}
sort_with_swap_func(0, m_values_num - 1, 0, swap_func, swap_arg);
m_hash = 0;
}
template <typename OP>
void Sort(OP&& comp_func)
{
if (m_values_num == 0)
{
return;
}
sort_with_compare_func(0, m_values_num - 1, 0, comp_func);
m_hash = 0;
}
using iterator = T*;
using const_iterator = const T*;
iterator begin() // NOLINT(readability-identifier-naming)
{
m_hash = 0;
return m_values;
}
iterator end() // NOLINT(readability-identifier-naming)
{
m_hash = 0;
return m_values + m_values_num;
}
const_iterator begin() const { return m_values; } // NOLINT(readability-identifier-naming)
const_iterator end() const { return m_values + m_values_num; } // NOLINT(readability-identifier-naming)
const_iterator cbegin() const { return m_values; } // NOLINT(readability-identifier-naming)
const_iterator cend() const { return m_values + m_values_num; } // NOLINT(readability-identifier-naming)
private:
template <typename U = T>
IsNotTriviallyCopyable<U, void> copy(const ArrayType& src)
{
m_values_num = src.m_values_num;
m_values_limit = src.m_values_limit;
m_hash = src.m_hash;
if (src.m_values)
{
m_values = static_cast<T*>(mem_alloc(m_values_limit * SIZEOF_T));
for (uint32_t index = 0; index < m_values_num; index++)
{
new (m_values + index) T(src.m_values[index]);
}
} else
{
m_values = nullptr;
}
}
template <typename U = T>
IsTriviallyCopyable<U, void> copy(const ArrayType& src)
{
m_values_num = src.m_values_num;
m_values_limit = src.m_values_limit;
m_hash = src.m_hash;
if (src.m_values)
{
m_values = static_cast<T*>(mem_alloc(m_values_limit * SIZEOF_T));
std::memcpy(m_values, src.m_values, m_values_num * SIZEOF_T);
} else
{
m_values = nullptr;
}
}
template <typename U = T>
IsNotTriviallyCopyable<U, void> expand(uint32_t add_num)
{
uint32_t values_i = m_values_num;
uint32_t new_values_num = values_i + add_num;
if (new_values_num >= m_values_limit)
{
m_values_limit = static_cast<uint32_t>((m_values_limit * 3) / 2 + new_values_num - m_values_limit + 1);
T* old_values = m_values;
m_values = static_cast<T*>(mem_alloc(m_values_limit * SIZEOF_T));
for (uint32_t index = 0; index < values_i; index++)
{
new (m_values + index) T(old_values[index]);
old_values[index].~T();
}
mem_free(old_values);
}
}
template <typename U = T>
IsTriviallyCopyable<U, void> expand(uint32_t add_num)
{
uint32_t values_i = m_values_num;
uint32_t new_values_num = values_i + add_num;
if (new_values_num >= m_values_limit)
{
m_values_limit = static_cast<uint32_t>((m_values_limit * 3) / 2 + new_values_num - m_values_limit + 1);
m_values = static_cast<T*>(mem_realloc(m_values, m_values_limit * SIZEOF_T));
}
}
void sort(int32_t low, int32_t high, uint32_t depth)
{
EXIT_IF(depth >= 64);
EXIT_IF(low < 0 || high < 0);
int32_t i = low;
int32_t j = high;
const T m = m_values[static_cast<uint32_t>(i + j) >> 1u];
do
{
while (m_values[i] < m)
{
i++;
}
while (m < m_values[j])
{
j--;
}
if (i <= j)
{
const T tmp = m_values[i];
m_values[i] = m_values[j];
m_values[j] = tmp;
i++;
j--;
}
} while (i <= j);
if (low < j)
{
sort(low, j, depth + 1);
}
if (i < high)
{
sort(i, high, depth + 1);
}
}
template <typename OP>
void sort_with_compare_func(int32_t low, int32_t high, uint32_t depth, OP&& comp_func)
{
EXIT_IF(depth >= 64);
EXIT_IF(low < 0 || high < 0);
int32_t i = low;
int32_t j = high;
const T m = m_values[static_cast<uint32_t>(i + j) >> 1u];
do
{
while (comp_func(m_values[i], m))
{
i++;
}
while (comp_func(m, m_values[j]))
{
j--;
}
if (i <= j)
{
const T tmp = m_values[i];
m_values[i] = m_values[j];
m_values[j] = tmp;
i++;
j--;
}
} while (i <= j);
if (low < j)
{
sort_with_compare_func(low, j, depth + 1, comp_func);
}
if (i < high)
{
sort_with_compare_func(i, high, depth + 1, comp_func);
}
}
void sort_with_swap_func(int32_t low, int32_t high, uint32_t depth, SortSwapFunc swap_func, void* arg)
{
EXIT_IF(depth >= 64);
EXIT_IF(low < 0 || high < 0);
int32_t i = low;
int32_t j = high;
const T m = m_values[static_cast<uint32_t>(i + j) >> 1u];
do
{
while (m_values[i] < m)
{
i++;
}
while (m < m_values[j])
{
j--;
}
if (i <= j)
{
swap_func(m_values, i, j, arg);
i++;
j--;
}
} while (i <= j);
if (low < j)
{
sort_with_swap_func(low, j, depth + 1, swap_func, arg);
}
if (i < high)
{
sort_with_swap_func(i, high, depth + 1, swap_func, arg);
}
}
template <typename U = T>
IsNotTriviallyCopyable<U, uint32_t> hash()
{
if (m_hash == 0)
{
EXIT_IF(true);
}
return m_hash;
}
template <typename U = T>
IsTriviallyCopyable<U, uint32_t> hash()
{
if (m_hash == 0)
{
m_hash = Core::hash(m_values, SIZEOF_T * m_values_num);
}
return m_hash;
}
template <typename U = T>
IsNotTriviallyCopyable<U, bool> remove_at(uint32_t index, uint32_t count = 1)
{
uint32_t size = m_values_num;
if (index >= size)
{
return false;
}
if (index + count > size)
{
count = size - index;
}
m_values_num = size - count;
uint32_t mc = size - (index + count);
for (uint32_t i = 0; i < mc; i++)
{
m_values[index + i] = m_values[index + i + count];
}
for (uint32_t i = 0; i < count; i++)
{
m_values[m_values_num + i].~T();
}
m_hash = 0;
return true;
}
template <typename U = T>
IsTriviallyCopyable<U, bool> remove_at(uint32_t index, uint32_t count = 1)
{
uint32_t size = m_values_num;
if (index >= size)
{
return false;
}
if (index + count > size)
{
count = size - index;
}
m_values_num = size - count;
std::memmove(m_values + index, (m_values + index + count), (size - (index + count)) * SIZEOF_T);
for (uint32_t i = 0; i < count; i++)
{
m_values[m_values_num + i].~T();
}
m_hash = 0;
return true;
}
uint32_t m_values_num {0};
uint32_t m_values_limit {0};
T* m_values {nullptr};
uint32_t m_hash {0};
};
#define FOR(index, array) /* NOLINT(cppcoreguidelines-macro-usage)*/ \
uint32_t array##_size_ = (array).Size(); \
for (uint32_t index = 0; index < array##_size_; index++) /* NOLINT(bugprone-macro-parentheses) */
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_SIMPLEARRAY_H_ */
+39
View File
@@ -0,0 +1,39 @@
#ifndef INCLUDE_KYTY_CORE_SINGLETON_H_
#define INCLUDE_KYTY_CORE_SINGLETON_H_
#include <cstdlib>
#include <new>
namespace Kyty::Core {
template <class T>
class Singleton
{
public:
static T* Instance()
{
if (!g_m_instance)
{
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
g_m_instance = static_cast<T*>(std::malloc(sizeof(T)));
new (g_m_instance) T;
}
return g_m_instance;
}
KYTY_CLASS_NO_COPY(Singleton);
protected:
Singleton();
~Singleton();
private:
static inline T* g_m_instance = nullptr;
};
// template<class T> T* Singleton<T>::instance = 0;
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_SINGLETON_H_ */
+312
View File
@@ -0,0 +1,312 @@
#ifndef CORE_KYTYSTRING_H_
#define CORE_KYTYSTRING_H_
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/SimpleArray.h" // IWYU pragma: export
#include "Kyty/Core/Vector.h"
#include <cstdarg> // IWYU pragma: export
namespace Kyty::Core {
constexpr uint32_t STRING_INVALID_INDEX = static_cast<uint32_t>(-1);
class StringList;
#define C_Str utf8_str().GetData /* NOLINT(cppcoreguidelines-macro-usage) */
#define Ru_Str cp866_str().GetData /* NOLINT(cppcoreguidelines-macro-usage) */
#define Win_Str cp1251_str().GetData /* NOLINT(cppcoreguidelines-macro-usage) */
struct CharProperty
{
int decimal : 1;
int alpha : 1;
int lower : 1;
int upper : 1;
int space : 1;
int hex : 1;
int hex_data : 5;
int case_offset : 21;
};
class Char
{
public:
static int ToCp866(char32_t src, uint8_t* dst);
static int ToCp1251(char32_t src, uint8_t* dst);
static int ToUtf8(char32_t src, uint8_t* dst);
static int ToUtf16(char32_t src, char16_t* dst);
static int ToUtf32(char32_t src, char32_t* dst);
static bool IsDecimal(char32_t ucs4);
static bool IsAlpha(char32_t ucs4);
static bool IsAlphaNum(char32_t ucs4);
static bool IsLower(char32_t ucs4);
static bool IsUpper(char32_t ucs4);
static bool IsSpace(char32_t ucs4);
static bool IsHex(char32_t ucs4);
static int HexDigit(char32_t ucs4);
static int DecimalDigit(char32_t ucs4);
static char32_t ToLower(char32_t ucs4);
static char32_t ToUpper(char32_t ucs4);
static char32_t ReadCp866(const uint8_t** str);
static char32_t ReadCp1251(const uint8_t** str);
static char32_t ReadUtf8(const uint8_t** str);
static char32_t ReadUtf16(const char16_t** str);
static char32_t ReadUtf32(const char32_t** str);
static bool EqualAscii(const char32_t* utf32_str, const char* ascii_str);
static bool EqualAsciiNoCase(const char32_t* utf32_str, const char* ascii_str);
static bool EqualAsciiN(const char32_t* utf32_str, const char* ascii_str, int n);
static bool EqualAsciiNoCaseN(const char32_t* utf32_str, const char* ascii_str, int n);
};
class String
{
public:
using DataType = SimpleArray<char32_t>;
using Utf8 = Vector<char>;
using Cp866 = Vector<char>;
using Cp1251 = Vector<char>;
using Utf16 = Vector<char16_t>;
using Utf32 = Vector<char32_t>;
enum class Case
{
Insensitive = 0,
Sensitive = 1
};
enum class SplitType
{
WithEmptyParts,
SplitNoEmptyParts
};
String();
String(const String& src);
String(String&& src) noexcept;
String(char32_t ch, uint32_t repeat = 1); // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
String(const char32_t* str); // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
explicit String(const Utf8& utf8);
virtual ~String();
[[nodiscard]] uint32_t Size() const;
[[nodiscard]] bool IsEmpty() const;
[[nodiscard]] bool IsInvalid() const;
void Clear();
char32_t& operator[](uint32_t index);
const char32_t& operator[](uint32_t index) const;
[[nodiscard]] const char32_t& At(uint32_t index) const;
char32_t* GetData();
[[nodiscard]] const char32_t* GetData() const;
[[nodiscard]] const char32_t* GetDataConst() const;
[[nodiscard]] Utf8 utf8_str() const; // NOLINT(readability-identifier-naming)
[[nodiscard]] Utf16 utf16_str() const; // NOLINT(readability-identifier-naming)
[[nodiscard]] Utf32 utf32_str() const; // NOLINT(readability-identifier-naming)
[[nodiscard]] Cp866 cp866_str() const; // NOLINT(readability-identifier-naming)
[[nodiscard]] Cp1251 cp1251_str() const; // NOLINT(readability-identifier-naming)
String& operator=(const String& src);
String& operator=(String&& src) noexcept;
String& operator=(char32_t ch);
String& operator=(const char32_t* utf32_str);
String& operator=(const char* utf8_str);
String& operator=(const char16_t* utf16_str);
String& operator+=(const String& src);
String& operator+=(char32_t ch);
String& operator+=(const char32_t* utf32_str);
String& operator+=(const char* utf8_str);
String& operator+=(const char16_t* utf16_str);
friend String operator+(const String& str1, const String& str2);
friend String operator+(const char* utf8_str1, const String& str2);
friend String operator+(const String& str1, const char* utf8_str2);
friend String operator+(const char32_t* utf32_str1, const String& str2);
friend String operator+(const String& str1, const char32_t* utf32_str2);
friend String operator+(char32_t ch, const String& str2);
friend String operator+(const String& str1, char32_t ch);
[[nodiscard]] bool Equal(const String& src) const;
[[nodiscard]] bool Equal(char32_t ch) const;
bool Equal(const char32_t* utf32_str) const;
bool Equal(const char* utf8_str) const;
[[nodiscard]] bool EqualNoCase(const String& src) const;
[[nodiscard]] bool EqualNoCase(char32_t ch) const;
bool EqualNoCase(const char32_t* utf32_str) const;
bool EqualNoCase(const char* utf8_str) const;
friend bool operator==(const String& str1, const String& str2) { return str2.Equal(str1); }
friend bool operator==(const char* utf8_str1, const String& str2) { return str2.Equal(utf8_str1); }
friend bool operator==(const String& str1, const char* utf8_str2) { return str1.Equal(utf8_str2); }
friend bool operator==(const char32_t* utf32_str1, const String& str2) { return str2.Equal(utf32_str1); }
friend bool operator==(const String& str1, const char32_t* utf32_str2) { return str1.Equal(utf32_str2); }
friend bool operator==(char32_t ch, const String& str2) { return str2.Equal(ch); }
friend bool operator==(const String& str1, char32_t ch) { return str1.Equal(ch); }
friend bool operator!=(const String& str1, const String& str2) { return !str2.Equal(str1); }
friend bool operator!=(const char* utf8_str1, const String& str2) { return !str2.Equal(utf8_str1); }
friend bool operator!=(const String& str1, const char* utf8_str2) { return !str1.Equal(utf8_str2); }
friend bool operator!=(const char32_t* utf32_str1, const String& str2) { return !str2.Equal(utf32_str1); }
friend bool operator!=(const String& str1, const char32_t* utf32_str2) { return !str1.Equal(utf32_str2); }
friend bool operator!=(char32_t ch, const String& str2) { return !str2.Equal(ch); }
friend bool operator!=(const String& str1, char32_t ch) { return !str1.Equal(ch); }
[[nodiscard]] String Mid(uint32_t first, uint32_t count) const;
[[nodiscard]] String Mid(uint32_t first) const;
[[nodiscard]] String Left(uint32_t count) const;
[[nodiscard]] String Right(uint32_t count) const;
[[nodiscard]] String ToUpper() const;
[[nodiscard]] String ToLower() const;
[[nodiscard]] String TrimRight() const;
[[nodiscard]] String TrimLeft() const;
[[nodiscard]] String Trim() const;
[[nodiscard]] String Simplify() const;
[[nodiscard]] String ReplaceChar(char32_t old_char, char32_t new_char, Case cs = Case::Sensitive) const;
[[nodiscard]] String ReplaceStr(const String& old_str, const String& new_str, Case cs = Case::Sensitive) const;
[[nodiscard]] String RemoveAt(uint32_t index, uint32_t count = 1) const;
[[nodiscard]] String RemoveChar(char32_t ch, Case cs = Case::Sensitive) const;
[[nodiscard]] String RemoveStr(const String& str, Case cs = Case::Sensitive) const;
[[nodiscard]] String RemoveLast(uint32_t num) const;
[[nodiscard]] String RemoveFirst(uint32_t num) const;
[[nodiscard]] String InsertAt(uint32_t index, const String& str) const;
[[nodiscard]] String SafeLua() const;
[[nodiscard]] String SafeCsv() const;
[[nodiscard]] uint32_t FindIndex(const String& str, uint32_t from = 0, Case cs = Case::Sensitive) const;
[[nodiscard]] uint32_t FindLastIndex(const String& str, uint32_t from = STRING_INVALID_INDEX, Case cs = Case::Sensitive) const;
[[nodiscard]] uint32_t FindIndex(char32_t chr, uint32_t from = 0, Case cs = Case::Sensitive) const;
[[nodiscard]] bool IndexValid(uint32_t index) const;
[[nodiscard]] uint32_t FindLastIndex(char32_t chr, uint32_t from = STRING_INVALID_INDEX, Case cs = Case::Sensitive) const;
[[nodiscard]] bool ContainsStr(const String& str, Case cs = Case::Sensitive) const;
[[nodiscard]] bool ContainsAnyStr(const StringList& list, Case cs = Case::Sensitive) const;
[[nodiscard]] bool ContainsAllStr(const StringList& list, Case cs = Case::Sensitive) const;
[[nodiscard]] bool ContainsChar(char32_t chr, Case cs = Case::Sensitive) const;
[[nodiscard]] bool ContainsAnyChar(const String& list, Case cs = Case::Sensitive) const;
[[nodiscard]] bool ContainsAllChar(const String& list, Case cs = Case::Sensitive) const;
[[nodiscard]] bool EndsWith(const String& str, Case cs = Case::Sensitive) const;
[[nodiscard]] bool StartsWith(const String& str, Case cs = Case::Sensitive) const;
[[nodiscard]] bool EndsWith(char32_t chr, Case cs = Case::Sensitive) const;
[[nodiscard]] bool StartsWith(char32_t chr, Case cs = Case::Sensitive) const;
[[nodiscard]] String DirectoryWithoutFilename() const;
[[nodiscard]] String FilenameWithoutDirectory() const;
[[nodiscard]] String FilenameWithoutExtension() const;
[[nodiscard]] String ExtensionWithoutFilename() const;
[[nodiscard]] String FixFilenameSlash() const;
[[nodiscard]] String FixDirectorySlash() const;
bool Printf(const char* format, va_list args);
bool Printf(const char* format, ...) KYTY_FORMAT_PRINTF(2, 3);
static String FromPrintf(const char* format, ...) KYTY_FORMAT_PRINTF(1, 2);
[[nodiscard]] StringList Split(const String& sep, SplitType type = SplitType::SplitNoEmptyParts, Case cs = Case::Sensitive) const;
[[nodiscard]] StringList Split(char32_t sep, SplitType type = SplitType::SplitNoEmptyParts, Case cs = Case::Sensitive) const;
[[nodiscard]] uint32_t ToUint32(int base = 10) const;
[[nodiscard]] uint64_t ToUint64(int base = 10) const;
[[nodiscard]] int32_t ToInt32(int base = 10) const;
[[nodiscard]] int64_t ToInt64(int base = 10) const;
[[nodiscard]] double ToDouble() const;
[[nodiscard]] float ToFloat() const;
[[nodiscard]] uint32_t Hash() const;
[[nodiscard]] ByteBuffer HexToBin() const;
static String HexFromBin(const ByteBuffer& bin);
bool EqualAscii(const char* ascii_str) const;
bool EqualAsciiNoCase(const char* ascii_str) const;
[[nodiscard]] bool IsAlpha() const;
static String FromCp866(const char* utf8_str) { return String(reinterpret_cast<const uint8_t*>(utf8_str), Char::ReadCp866); }
static String FromCp1251(const char* utf8_str) { return String(reinterpret_cast<const uint8_t*>(utf8_str), Char::ReadCp1251); }
static String FromUtf8(const char* utf8_str) { return String(reinterpret_cast<const uint8_t*>(utf8_str), Char::ReadUtf8); }
static String FromUtf8(const char* utf8_str, uint32_t size)
{
return String(reinterpret_cast<const uint8_t*>(utf8_str), Char::ReadUtf8, size, true);
}
static String FromUtf16(const char16_t* utf16_str) { return String(utf16_str, Char::ReadUtf16); }
static String FromUtf32(const char32_t* utf32_str) { return String(utf32_str, Char::ReadUtf32); }
[[nodiscard]] String SortChars() const;
using iterator = char32_t*;
using const_iterator = const char32_t*;
iterator begin() { return GetData(); } // NOLINT(readability-identifier-naming)
iterator end() { return GetData() + Size(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator begin() const { return GetDataConst(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator end() const { return GetDataConst() + Size(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cbegin() const { return GetDataConst(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cend() const { return GetDataConst() + Size(); } // NOLINT(readability-identifier-naming)
private:
String(const char32_t* array, uint32_t size);
// String(const uint8_t *utf8_str);
// String(const char16_t *utf16_str);
template <class T, class OP>
String(const T* str, OP&& read, uint32_t size = 0, bool with_size = false): m_data(new DataType)
{
if (str == nullptr)
{
m_data->Add(U'\0');
} else
{
// const T *ptr = (const T*)str;
const auto* ptr = str;
for (;;)
{
if (with_size && ptr - str >= size)
{
m_data->Add(U'\0');
break;
}
char32_t u = read(&ptr);
m_data->Add(u);
if (u == U'\0')
{
break;
}
}
}
}
DataType* m_data;
};
class StringList: public Vector<String>
{
public:
using Vector<String>::Vector;
// StringList(): Vector<String>() {};
// StringList(std::initializer_list<String> list): Vector<String>(list) {};
// virtual ~StringList() {};
[[nodiscard]] bool Contains(const String& str, String::Case cs = String::Case::Sensitive) const;
[[nodiscard]] String Concat(const String& str) const;
[[nodiscard]] String Concat(char32_t chr) const;
[[nodiscard]] bool Equal(const StringList& str) const;
[[nodiscard]] bool EqualNoCase(const StringList& str) const;
bool operator==(const StringList& str) const { return this->Equal(str); }
bool operator!=(const StringList& str) const { return !(*this == str); }
};
} // namespace Kyty::Core
namespace Kyty {
using String = Core::String;
} // namespace Kyty
#endif /* CORE_KYTYSTRING_H_ */
+102
View File
@@ -0,0 +1,102 @@
#ifndef INCLUDE_KYTY_CORE_SUBSYSTEMS_H_
#define INCLUDE_KYTY_CORE_SUBSYSTEMS_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Singleton.h"
#include <initializer_list>
namespace Kyty::Core {
class Subsystem;
class SubsystemsListPrivate;
class SubsystemPrivate;
class SubsystemsList
{
public:
SubsystemsList();
virtual ~SubsystemsList();
void SetArgs(int argc, char* argv[]);
// void Add(Subsystem* s, const char* name, ...);
void Add(Subsystem* s, std::initializer_list<Subsystem*> deps);
bool InitAll(bool print_msg = false);
void DestroyAll(bool print_msg = false);
int* GetArgc();
char** GetArgv();
[[nodiscard]] const char* GetFailName() const;
[[nodiscard]] const char* GetFailMsg() const;
void ShutdownAll();
static SubsystemsList* Instance() { return Core::Singleton<SubsystemsList>::Instance(); }
KYTY_CLASS_NO_COPY(SubsystemsList);
private:
SubsystemsListPrivate* m_p;
};
using SubsystemsListSingleton = Kyty::Core::Singleton<SubsystemsList>;
class Subsystem
{
public:
Subsystem();
virtual ~Subsystem();
virtual const char* Id() = 0;
virtual void Init(SubsystemsList* parent) = 0;
virtual void Destroy(SubsystemsList* parent) = 0;
virtual void UnexpectedShutdown(SubsystemsList* parent) = 0;
friend class SubsystemsListPrivate;
KYTY_CLASS_NO_COPY(Subsystem);
protected:
void Fail(const char* format, ...) KYTY_FORMAT_PRINTF(2, 3);
private:
SubsystemPrivate* m_p;
};
#define KYTY_SUBSYSTEM_DEFINE(s) \
class s##Subsystem: public Core::Subsystem \
{ \
public: \
static Subsystem* Instance() { return Core::Singleton<s##Subsystem>::Instance(); } \
const char* Id() { return #s; } \
void Init(Core::SubsystemsList* parent); \
void Destroy(Core::SubsystemsList* parent); \
void UnexpectedShutdown(Core::SubsystemsList* parent); \
}; \
typedef Core::Singleton<s##Subsystem> s##SubsystemSingleton;
#define KYTY_SUBSYSTEM_INIT(s) void s##Subsystem::Init([[maybe_unused]] Core::SubsystemsList* parent)
#define KYTY_SUBSYSTEM_DESTROY(s) void s##Subsystem::Destroy([[maybe_unused]] Core::SubsystemsList* parent)
#define KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(s) void s##Subsystem::UnexpectedShutdown([[maybe_unused]] Core::SubsystemsList* parent)
#define KYTY_SUBSYSTEM_ARGC parent->GetArgc()
#define KYTY_SUBSYSTEM_ARGV parent->GetArgv()
#if KYTY_COMPILER == KYTY_COMPILER_MSVC
#define KYTY_SUBSYSTEM_FAIL(f, ...) \
this->Fail(f, __VA_ARGS__); \
return;
#else
#define KYTY_SUBSYSTEM_FAIL(f, s...) \
this->Fail(f, ##s); \
return;
#endif
//#define KYTY_SUBSYSTEM_ADD(list, s, ...) list.Add(s##SubsystemSingleton::Instance(), #s, __VA_ARGS__);
//#define KYTY_SUBSYSTEM_ADD2(list, ...) list.Add2(s##SubsystemSingleton::Instance(), __VA_ARGS__);
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_SUBSYSTEMS_H_ */
+121
View File
@@ -0,0 +1,121 @@
#ifndef INCLUDE_KYTY_CORE_THREADS_H_
#define INCLUDE_KYTY_CORE_THREADS_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Subsystems.h"
namespace Kyty::Core {
KYTY_SUBSYSTEM_DEFINE(Threads);
using thread_func_t = void (*)(void*);
// struct ThreadPrivate;
class String;
class Thread
{
public:
Thread(thread_func_t func, void* arg);
virtual ~Thread();
void Join();
void Detach();
// Once a thread has finished, the id may be reused by another thread.
[[nodiscard]] String GetId() const;
static void Sleep(uint32_t millis);
static void SleepMicro(uint32_t micros);
static void SleepNano(uint64_t nanos);
static bool IsMainThread();
// Get current thread id
// Once a thread has finished, the id may be reused by another thread.
static String GetThreadId();
// Get current thread id
// The id is unique and can't be reused by another thread.
static int GetThreadIdUnique();
KYTY_CLASS_NO_COPY(Thread);
private:
struct ThreadPrivate;
ThreadPrivate* m_thread;
};
class Mutex
{
public:
Mutex();
virtual ~Mutex();
void Lock();
void Unlock();
bool TryLock();
friend class CondVar;
KYTY_CLASS_NO_COPY(Mutex);
private:
struct MutexPrivate;
MutexPrivate* m_mutex;
};
class DummyMutex final
{
public:
DummyMutex() = default;
~DummyMutex() = default;
void Lock() {}
void Unlock() {}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
bool TryLock() { return false; }
friend class CondVar;
KYTY_CLASS_NO_COPY(DummyMutex);
private:
};
class CondVar
{
public:
CondVar();
virtual ~CondVar();
void Wait(Mutex* mutex);
void WaitFor(Mutex* mutex, uint32_t micros);
void Signal();
void SignalAll();
KYTY_CLASS_NO_COPY(CondVar);
private:
struct CondVarPrivate;
CondVarPrivate* m_cond_var;
};
class LockGuard
{
public:
using mutex_type = Mutex;
explicit LockGuard(mutex_type& m): m_mutex(m) { m_mutex.Lock(); }
~LockGuard() { m_mutex.Unlock(); }
KYTY_CLASS_NO_COPY(LockGuard);
private:
mutex_type& m_mutex;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_THREADS_H_ */
+48
View File
@@ -0,0 +1,48 @@
#ifndef INCLUDE_KYTY_CORE_TIMER_H_
#define INCLUDE_KYTY_CORE_TIMER_H_
#include "Kyty/Core/Common.h"
namespace Kyty::Core {
class Timer final
{
public:
Timer() noexcept;
~Timer() = default;
void Start();
void Pause();
void Resume();
[[nodiscard]] bool IsPaused() const;
// return time in milliseconds
[[nodiscard]] double GetTimeMs() const;
// return time in seconds
[[nodiscard]] double GetTimeS() const;
// return time in ticks
[[nodiscard]] uint64_t GetTicks() const;
// return ticks frequency
[[nodiscard]] uint64_t GetFrequency() const;
KYTY_CLASS_NO_COPY(Timer);
[[nodiscard]] static uint64_t QueryPerformanceFrequency();
[[nodiscard]] static uint64_t QueryPerformanceCounter();
private:
bool m_is_paused = true;
uint64_t m_Frequency = 0;
uint64_t m_StartTime = 0;
uint64_t m_PauseTime = 0;
};
} // namespace Kyty::Core
#endif /* INCLUDE_KYTY_CORE_TIMER_H_ */
+279
View File
@@ -0,0 +1,279 @@
#ifndef INCLUDE_KYTY_CORE_VECTOR_H_
#define INCLUDE_KYTY_CORE_VECTOR_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/SimpleArray.h" // IWYU pragma: export
namespace Kyty::Core {
template <typename T>
class SimpleArray;
template <typename T, class A>
class VectorBase
{
public:
using DataType = A;
using VectorType = VectorBase<T, A>;
using SortSwapFunc = typename A::SortSwapFunc;
using SortCompareFunc = typename A::SortCompareFunc;
VectorBase(): m_data(new DataType) {}
VectorBase(const VectorType& src) { src.m_data->CopyPtr(&m_data, src.m_data); }
VectorBase(VectorType&& src) noexcept: m_data(src.m_data) { src.m_data = nullptr; }
explicit VectorBase(uint32_t size, bool ctor = true): m_data(size != 0u ? new DataType(size, ctor) : new DataType) {}
VectorBase(std::initializer_list<T> list): m_data(new DataType(list)) {}
virtual ~VectorBase()
{
if (m_data)
{
m_data->Release();
}
}
[[nodiscard]] uint32_t Size() const { return m_data->Size(); }
[[nodiscard]] uint32_t Capacity() const { return m_data->Capacity(); }
void Clear()
{
copy_on_write();
m_data->Clear();
}
void Free()
{
copy_on_write();
m_data->Free();
}
// NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
VectorBase<T, A>& operator=(const VectorType& src)
{
if (m_data != src.m_data)
{
if (m_data)
{
m_data->Release();
}
src.m_data->CopyPtr(&m_data, src.m_data);
}
return *this;
}
VectorBase<T, A>& operator=(VectorType&& src) noexcept
{
if (m_data != src.m_data)
{
if (m_data)
{
m_data->Release();
}
m_data = src.m_data;
src.m_data = nullptr;
}
return *this;
}
bool operator==(const VectorType& s) const { return *m_data == *s.m_data; }
bool operator!=(const VectorType& s) const { return !(*m_data == *s.m_data); }
void Expand(uint32_t num)
{
copy_on_write();
m_data->Expand(num);
}
void Add(const T& val)
{
copy_on_write();
m_data->Add(val);
}
void Add(T&& val)
{
copy_on_write();
m_data->Add(std::forward<T>(val));
}
void Add(const T* val, uint32_t num)
{
copy_on_write();
m_data->Add(val, num);
}
void Add(const VectorType& v)
{
if (this == &v)
{
VectorType v2(v);
copy_on_write();
m_data->Add(v2.GetData(), v2.Size());
} else
{
copy_on_write();
m_data->Add(v.GetData(), v.Size());
}
}
void InsertAt(uint32_t index, const T& val)
{
copy_on_write();
m_data->InsertAt(index, val);
}
void InsertAt(uint32_t index, T&& val)
{
copy_on_write();
m_data->InsertAt(index, std::forward<T>(val));
}
[[nodiscard]] uint32_t Find(const T& t) const { return m_data->Find(t); }
template <typename OP>
uint32_t Find(const T& t, OP&& op_eq) const
{
return m_data->Find(t, op_eq);
}
template <typename T2, typename OP>
uint32_t Find(const T2& t, OP&& op_eq) const
{
return m_data->Find(t, op_eq);
}
template <typename T2, typename OP, typename V>
void FindAll(const T2& t, OP&& op_eq, V* out) const
{
m_data->FindAll(t, op_eq, out);
}
template <typename T2, typename T3, typename OP>
uint32_t Find(const T2& t2, const T3& t3, OP&& op_eq) const
{
return m_data->Find(t2, t3, op_eq);
}
[[nodiscard]] bool Contains(const T& t) const { return Find(t) != uint32_t(-1); }
template <typename T2, typename OP>
bool Contains(const T2& t, OP&& op_eq) const
{
return Find(t, op_eq) != uint32_t(-1);
}
bool Remove(const T& t)
{
copy_on_write();
return m_data->Remove(t);
}
bool RemoveAt(uint32_t index, uint32_t count = 1)
{
copy_on_write();
return m_data->RemoveAt(index, count);
}
[[nodiscard]] bool IndexValid(uint32_t index) const { return m_data->IndexValid(index); }
T& operator[](uint32_t index)
{
copy_on_write();
return m_data->operator[](index);
}
const T& operator[](uint32_t index) const { return m_data->At(index); }
[[nodiscard]] const T& At(uint32_t index) const { return m_data->At(index); }
T* GetData()
{
copy_on_write();
return m_data->GetData();
}
[[nodiscard]] const T* GetData() const { return m_data->GetDataConst(); }
[[nodiscard]] const T* GetDataConst() const { return m_data->GetDataConst(); }
void Memset(int c)
{
copy_on_write();
m_data->Memset(c);
}
void Sort()
{
copy_on_write();
m_data->Sort();
}
void Sort(SortCompareFunc comp_func)
{
copy_on_write();
m_data->Sort(comp_func);
}
void Sort(SortSwapFunc swap_func, void* swap_arg = nullptr)
{
copy_on_write();
m_data->Sort(swap_func, swap_arg);
}
template <typename OP>
void Sort(OP&& comp_func)
{
copy_on_write();
m_data->Sort(comp_func);
}
[[nodiscard]] bool IsEmpty() const { return Size() == 0; }
using iterator = T*;
using const_iterator = const T*;
iterator begin() // NOLINT(readability-identifier-naming)
{
copy_on_write();
return m_data->begin();
}
iterator end() // NOLINT(readability-identifier-naming)
{
copy_on_write();
return m_data->end();
}
[[nodiscard]] const_iterator begin() const { return m_data->cbegin(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator end() const { return m_data->cend(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cbegin() const { return m_data->cbegin(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cend() const { return m_data->cend(); } // NOLINT(readability-identifier-naming)
private:
void copy_on_write() { m_data->CopyOnWrite(&m_data); }
DataType* m_data;
};
} // namespace Kyty::Core
namespace Kyty {
template <typename T>
class Vector: public Core::VectorBase<T, Core::SimpleArray<T>>
{
public:
using Core::VectorBase<T, Core::SimpleArray<T>>::VectorBase;
};
} // namespace Kyty
#endif /* INCLUDE_KYTY_CORE_VECTOR_H_ */
+54
View File
@@ -0,0 +1,54 @@
#ifndef INCLUDE_KYTY_MATH_CRYPTO_H_
#define INCLUDE_KYTY_MATH_CRYPTO_H_
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
namespace Kyty::Math {
namespace AES {
enum class Mode
{
Cbc256Pkcs7Padding,
Cbc256ZeroPadding
};
Core::ByteBuffer Encrypt(const uint8_t* buf, uint32_t length, const uint8_t* key, const uint8_t* iv, Mode mode);
Core::ByteBuffer Encrypt(const Core::ByteBuffer& buf, const uint8_t* key, const uint8_t* iv, Mode mode);
Core::ByteBuffer EncryptStr(const String& str, const uint8_t* key, const uint8_t* iv, Mode mode);
Core::ByteBuffer Decrypt(const uint8_t* buf, uint32_t length, const uint8_t* key, const uint8_t* iv, Mode mode);
Core::ByteBuffer Decrypt(const Core::ByteBuffer& buf, const uint8_t* key, const uint8_t* iv, Mode mode);
String DecryptStr(const uint8_t* buf, uint32_t length, const uint8_t* key, const uint8_t* iv, Mode mode);
String DecryptStr(const Core::ByteBuffer& buf, const uint8_t* key, const uint8_t* iv, Mode mode);
} // namespace AES
namespace MD5 {
/* MD5 context. */
struct CTX
{
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
uint8_t buffer[64]; /* input buffer */
};
void Init(CTX* context);
void Update(CTX* context, const uint8_t* input, uint32_t input_len);
void Final(uint8_t digest[16], CTX* context);
Core::ByteBuffer Hash(const uint8_t* buf, uint32_t length);
Core::ByteBuffer Hash(const Core::ByteBuffer& buf);
Core::ByteBuffer Hash(const String& str);
} // namespace MD5
namespace CRC32 {
uint32_t Hash(const uint8_t* buf, uint32_t length);
uint32_t Hash(const Core::ByteBuffer& buf);
uint32_t Hash(const String& str);
} // namespace CRC32
} // namespace Kyty::Math
#endif /* INCLUDE_KYTY_MATH_CRYPTO_H_ */
+240
View File
@@ -0,0 +1,240 @@
#ifndef INCLUDE_KYTY_MATH_MAT2IMPL_H_
#define INCLUDE_KYTY_MATH_MAT2IMPL_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Math::m {
// MAT2_DECL mat2::mat2() = default;
//
// MAT2_DECL mat2::mat2(const mat2 &m)
//{
// data[0].x = m.data[0].x; data[0].y = m.data[0].y;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y;
//}
//
// MAT2_DECL mat2::mat2(mat2 &&m) noexcept
//{
// data[0].x = m.data[0].x; data[0].y = m.data[0].y;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y;
//}
MAT2_DECL mat2::mat2(const mat3& m) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = m.data[0].x;
data[0].y = m.data[0].y;
data[1].x = m.data[1].x;
data[1].y = m.data[1].y;
}
MAT2_DECL mat2::mat2(const mat4& m) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = m.data[0].x;
data[0].y = m.data[0].y;
data[1].x = m.data[1].x;
data[1].y = m.data[1].y;
}
MAT2_DECL mat2::mat2(float x) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = x;
data[0].y = 0;
data[1].x = 0;
data[1].y = x;
}
MAT2_DECL mat2::mat2(float x1, float y1, // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
float x2, float y2) noexcept
{
data[0].x = x1;
data[0].y = y1;
data[1].x = x2;
data[1].y = y2;
}
MAT2_DECL mat2::mat2(const vec2& v1, const vec2& v2) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = v1.x;
data[0].y = v1.y;
data[1].x = v2.x;
data[1].y = v2.y;
}
MAT2_DECL vec2& mat2::operator[](int i)
{
EXIT_IF(!(i >= 0 && i < 2));
return data[i];
}
MAT2_DECL const vec2& mat2::operator[](int i) const
{
EXIT_IF(!(i >= 0 && i < 2));
return data[i];
}
// MAT2_DECL mat2 &mat2::operator = (const mat2 &m)
//{
// if (this != &m)
// {
// data[0].x = m.data[0].x; data[0].y = m.data[0].y;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y;
// }
// return *this;
//}
//
// MAT2_DECL mat2 &mat2::operator = (mat2 &&m) noexcept
//{
// *this = m;
// return *this;
//}
MAT2_DECL mat2& mat2::operator+=(float s)
{
data[0].x += s;
data[0].y += s;
data[1].x += s;
data[1].y += s;
return *this;
}
MAT2_DECL mat2& mat2::operator+=(const mat2& m)
{
data[0].x += m.data[0].x;
data[0].y += m.data[0].y;
data[1].x += m.data[1].x;
data[1].y += m.data[1].y;
return *this;
}
MAT2_DECL mat2& mat2::operator-=(float s)
{
data[0].x -= s;
data[0].y -= s;
data[1].x -= s;
data[1].y -= s;
return *this;
}
MAT2_DECL mat2& mat2::operator-=(const mat2& m)
{
data[0].x -= m.data[0].x;
data[0].y -= m.data[0].y;
data[1].x -= m.data[1].x;
data[1].y -= m.data[1].y;
return *this;
}
MAT2_DECL mat2& mat2::operator*=(float s)
{
data[0].x *= s;
data[0].y *= s;
data[1].x *= s;
data[1].y *= s;
return *this;
}
MAT2_DECL mat2& mat2::operator*=(const mat2& m)
{
*this = *this * m;
return *this;
}
MAT2_DECL mat2& mat2::operator/=(float s)
{
data[0].x /= s;
data[0].y /= s;
data[1].x /= s;
data[1].y /= s;
return *this;
}
MAT2_DECL mat2 operator+(const mat2& m, float s)
{
return mat2(m.data[0].x + s, m.data[0].y + s, m.data[1].x + s, m.data[1].y + s);
}
MAT2_DECL mat2 operator+(float s, const mat2& m)
{
return mat2(m.data[0].x + s, m.data[0].y + s, m.data[1].x + s, m.data[1].y + s);
}
MAT2_DECL mat2 operator+(const mat2& m1, const mat2& m2)
{
return mat2(m1.data[0].x + m2.data[0].x, m1.data[0].y + m2.data[0].y, m1.data[1].x + m2.data[1].x, m1.data[1].y + m2.data[1].y);
}
MAT2_DECL mat2 operator-(const mat2& m, float s)
{
return mat2(m.data[0].x - s, m.data[0].y - s, m.data[1].x - s, m.data[1].y - s);
}
MAT2_DECL mat2 operator-(float s, const mat2& m)
{
return mat2(s - m.data[0].x, s - m.data[0].y, s - m.data[1].x, s - m.data[1].y);
}
MAT2_DECL mat2 operator-(const mat2& m1, const mat2& m2)
{
return mat2(m1.data[0].x - m2.data[0].x, m1.data[0].y - m2.data[0].y, m1.data[1].x - m2.data[1].x, m1.data[1].y - m2.data[1].y);
}
MAT2_DECL mat2 operator*(const mat2& m, float s)
{
return mat2(m.data[0].x * s, m.data[0].y * s, m.data[1].x * s, m.data[1].y * s);
}
MAT2_DECL mat2 operator*(float s, const mat2& m)
{
return mat2(m.data[0].x * s, m.data[0].y * s, m.data[1].x * s, m.data[1].y * s);
}
MAT2_DECL mat2 operator*(const mat2& m1, const mat2& m2)
{
/*#define MUL2(i, j) */ auto mul = [&m1, &m2](auto i, auto j) {
return (m1.data[0].data[(j)] * m2.data[(i)].data[0] + m1.data[1].data[(j)] * m2.data[(i)].data[1]);
};
return mat2(mul(0, 0), mul(0, 1), mul(1, 0), mul(1, 1));
//#undef MUL2
}
MAT2_DECL vec2 operator*(const mat2& m, const vec2& v)
{
return vec2(m.data[0].x * v.x + m.data[1].x * v.y, m.data[0].y * v.x + m.data[1].y * v.y);
}
MAT2_DECL vec2 operator*(const vec2& v, const mat2& m)
{
return vec2(m.data[0].x * v.x + m.data[0].y * v.y, m.data[1].x * v.x + m.data[1].y * v.y);
}
MAT2_DECL mat2 operator/(const mat2& m, float s)
{
return mat2(m.data[0].x / s, m.data[0].y / s, m.data[1].x / s, m.data[1].y / s);
}
MAT2_DECL mat2 operator/(float s, const mat2& m)
{
return mat2(s / m.data[0].x, s / m.data[0].y, s / m.data[1].x, s / m.data[1].y);
}
MAT2_DECL bool operator==(const mat2& m1, const mat2& m2)
{
return (m1.data[0].x == m2.data[0].x) && (m1.data[0].y == m2.data[0].y) && (m1.data[1].x == m2.data[1].x) &&
(m1.data[1].y == m2.data[1].y);
}
MAT2_DECL bool operator!=(const mat2& m1, const mat2& m2)
{
return (m1.data[0].x != m2.data[0].x) || (m1.data[0].y != m2.data[0].y) || (m1.data[1].x != m2.data[1].x) ||
(m1.data[1].y != m2.data[1].y);
}
} // namespace Kyty::Math::m
#endif /* INCLUDE_KYTY_MATH_MAT2IMPL_H_ */
+303
View File
@@ -0,0 +1,303 @@
#ifndef INCLUDE_KYTY_MATH_MAT3IMPL_H_
#define INCLUDE_KYTY_MATH_MAT3IMPL_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Math::m {
// MAT3_DECL mat3::mat3() = default;
//
// MAT3_DECL mat3::mat3(const mat3 &m)
//{
// data[0].x = m.data[0].x; data[0].y = m.data[0].y; data[0].z = m.data[0].z;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y; data[1].z = m.data[1].z;
// data[2].x = m.data[2].x; data[2].y = m.data[2].y; data[2].z = m.data[2].z;
//}
//
// MAT3_DECL mat3::mat3(mat3 &&m) noexcept
//{
// data[0].x = m.data[0].x; data[0].y = m.data[0].y; data[0].z = m.data[0].z;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y; data[1].z = m.data[1].z;
// data[2].x = m.data[2].x; data[2].y = m.data[2].y; data[2].z = m.data[2].z;
//}
MAT3_DECL mat3::mat3(const mat4& m) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = m.data[0].x;
data[0].y = m.data[0].y;
data[0].z = m.data[0].z;
data[1].x = m.data[1].x;
data[1].y = m.data[1].y;
data[1].z = m.data[1].z;
data[2].x = m.data[2].x;
data[2].y = m.data[2].y;
data[2].z = m.data[2].z;
}
MAT3_DECL mat3::mat3(float x) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = x;
data[0].y = 0;
data[0].z = 0;
data[1].x = 0;
data[1].y = x;
data[1].z = 0;
data[2].x = 0;
data[2].y = 0;
data[2].z = x;
}
MAT3_DECL mat3::mat3(float x1, float y1, float z1, // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
float x2, float y2, float z2, float x3, float y3, float z3) noexcept
{
data[0].x = x1;
data[0].y = y1;
data[0].z = z1;
data[1].x = x2;
data[1].y = y2;
data[1].z = z2;
data[2].x = x3;
data[2].y = y3;
data[2].z = z3;
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
MAT3_DECL mat3::mat3(const vec3& v1, const vec3& v2, const vec3& v3) noexcept
{
data[0].x = v1.x;
data[0].y = v1.y;
data[0].z = v1.z;
data[1].x = v2.x;
data[1].y = v2.y;
data[1].z = v2.z;
data[2].x = v3.x;
data[2].y = v3.y;
data[2].z = v3.z;
}
MAT3_DECL vec3& mat3::operator[](int i)
{
EXIT_IF(!(i >= 0 && i < 3));
return data[i];
}
MAT3_DECL const vec3& mat3::operator[](int i) const
{
EXIT_IF(!(i >= 0 && i < 3));
return data[i];
}
// MAT3_DECL mat3 &mat3::operator = (const mat3 &m)
//{
// if (this != &m)
// {
// data[0].x = m.data[0].x; data[0].y = m.data[0].y; data[0].z = m.data[0].z;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y; data[1].z = m.data[1].z;
// data[2].x = m.data[2].x; data[2].y = m.data[2].y; data[2].z = m.data[2].z;
// }
// return *this;
//}
//
// MAT3_DECL mat3 &mat3::operator = (mat3 &&m) noexcept
//{
// *this = m;
// return *this;
//}
MAT3_DECL mat3& mat3::operator+=(float s)
{
data[0].x += s;
data[0].y += s;
data[0].z += s;
data[1].x += s;
data[1].y += s;
data[1].z += s;
data[2].x += s;
data[2].y += s;
data[2].z += s;
return *this;
}
MAT3_DECL mat3& mat3::operator+=(const mat3& m)
{
data[0].x += m.data[0].x;
data[0].y += m.data[0].y;
data[0].z += m.data[0].z;
data[1].x += m.data[1].x;
data[1].y += m.data[1].y;
data[1].z += m.data[1].z;
data[2].x += m.data[2].x;
data[2].y += m.data[2].y;
data[2].z += m.data[2].z;
return *this;
}
MAT3_DECL mat3& mat3::operator-=(float s)
{
data[0].x -= s;
data[0].y -= s;
data[0].z -= s;
data[1].x -= s;
data[1].y -= s;
data[1].z -= s;
data[2].x -= s;
data[2].y -= s;
data[2].z -= s;
return *this;
}
MAT3_DECL mat3& mat3::operator-=(const mat3& m)
{
data[0].x -= m.data[0].x;
data[0].y -= m.data[0].y;
data[0].z -= m.data[0].z;
data[1].x -= m.data[1].x;
data[1].y -= m.data[1].y;
data[1].z -= m.data[1].z;
data[2].x -= m.data[2].x;
data[2].y -= m.data[2].y;
data[2].z -= m.data[2].z;
return *this;
}
MAT3_DECL mat3& mat3::operator*=(float s)
{
data[0].x *= s;
data[0].y *= s;
data[0].z *= s;
data[1].x *= s;
data[1].y *= s;
data[1].z *= s;
data[2].x *= s;
data[2].y *= s;
data[2].z *= s;
return *this;
}
MAT3_DECL mat3& mat3::operator*=(const mat3& m)
{
*this = *this * m;
return *this;
}
MAT3_DECL mat3& mat3::operator/=(float s)
{
data[0].x /= s;
data[0].y /= s;
data[0].z /= s;
data[1].x /= s;
data[1].y /= s;
data[1].z /= s;
data[2].x /= s;
data[2].y /= s;
data[2].z /= s;
return *this;
}
MAT3_DECL mat3 operator+(const mat3& m, float s)
{
return mat3(m.data[0].x + s, m.data[0].y + s, m.data[0].z + s, m.data[1].x + s, m.data[1].y + s, m.data[1].z + s, m.data[2].x + s,
m.data[2].y + s, m.data[2].z + s);
}
MAT3_DECL mat3 operator+(float s, const mat3& m)
{
return mat3(m.data[0].x + s, m.data[0].y + s, m.data[0].z + s, m.data[1].x + s, m.data[1].y + s, m.data[1].z + s, m.data[2].x + s,
m.data[2].y + s, m.data[2].z + s);
}
MAT3_DECL mat3 operator+(const mat3& m1, const mat3& m2)
{
return mat3(m1.data[0].x + m2.data[0].x, m1.data[0].y + m2.data[0].y, m1.data[0].z + m2.data[0].z, m1.data[1].x + m2.data[1].x,
m1.data[1].y + m2.data[1].y, m1.data[1].z + m2.data[1].z, m1.data[2].x + m2.data[2].x, m1.data[2].y + m2.data[2].y,
m1.data[2].z + m2.data[2].z);
}
MAT3_DECL mat3 operator-(const mat3& m, float s)
{
return mat3(m.data[0].x - s, m.data[0].y - s, m.data[0].z - s, m.data[1].x - s, m.data[1].y - s, m.data[1].z - s, m.data[2].x - s,
m.data[2].y - s, m.data[2].z - s);
}
MAT3_DECL mat3 operator-(float s, const mat3& m)
{
return mat3(s - m.data[0].x, s - m.data[0].y, s - m.data[0].z, s - m.data[1].x, s - m.data[1].y, s - m.data[1].z, s - m.data[2].x,
s - m.data[2].y, s - m.data[2].z);
}
MAT3_DECL mat3 operator-(const mat3& m1, const mat3& m2)
{
return mat3(m1.data[0].x - m2.data[0].x, m1.data[0].y - m2.data[0].y, m1.data[0].z - m2.data[0].z, m1.data[1].x - m2.data[1].x,
m1.data[1].y - m2.data[1].y, m1.data[1].z - m2.data[1].z, m1.data[2].x - m2.data[2].x, m1.data[2].y - m2.data[2].y,
m1.data[2].z - m2.data[2].z);
}
MAT3_DECL mat3 operator*(const mat3& m, float s)
{
return mat3(m.data[0].x * s, m.data[0].y * s, m.data[0].z * s, m.data[1].x * s, m.data[1].y * s, m.data[1].z * s, m.data[2].x * s,
m.data[2].y * s, m.data[2].z * s);
}
MAT3_DECL mat3 operator*(float s, const mat3& m)
{
return mat3(m.data[0].x * s, m.data[0].y * s, m.data[0].z * s, m.data[1].x * s, m.data[1].y * s, m.data[1].z * s, m.data[2].x * s,
m.data[2].y * s, m.data[2].z * s);
}
MAT3_DECL mat3 operator*(const mat3& m1, const mat3& m2)
{
/*#define MUL3(i, j) */ auto mul3 = [&](auto i, auto j) {
return (m1.data[0].data[(j)] * m2.data[(i)].data[0] + m1.data[1].data[(j)] * m2.data[(i)].data[1] +
m1.data[2].data[(j)] * m2.data[(i)].data[2]);
};
return mat3(mul3(0, 0), mul3(0, 1), mul3(0, 2), mul3(1, 0), mul3(1, 1), mul3(1, 2), mul3(2, 0), mul3(2, 1), mul3(2, 2));
//#undef MUL3
}
MAT3_DECL vec3 operator*(const mat3& m, const vec3& v)
{
return vec3(m.data[0].x * v.x + m.data[1].x * v.y + m.data[2].x * v.z, m.data[0].y * v.x + m.data[1].y * v.y + m.data[2].y * v.z,
m.data[0].z * v.x + m.data[1].z * v.y + m.data[2].z * v.z);
}
MAT3_DECL vec3 operator*(const vec3& v, const mat3& m)
{
return vec3(m.data[0].x * v.x + m.data[0].y * v.y + m.data[0].z * v.z, m.data[1].x * v.x + m.data[1].y * v.y + m.data[1].z * v.z,
m.data[2].x * v.x + m.data[2].y * v.y + m.data[2].z * v.z);
}
MAT3_DECL mat3 operator/(const mat3& m, float s)
{
return mat3(m.data[0].x / s, m.data[0].y / s, m.data[0].z / s, m.data[1].x / s, m.data[1].y / s, m.data[1].z / s, m.data[2].x / s,
m.data[2].y / s, m.data[2].z / s);
}
MAT3_DECL mat3 operator/(float s, const mat3& m)
{
return mat3(s / m.data[0].x, s / m.data[0].y, s / m.data[0].z, s / m.data[1].x, s / m.data[1].y, s / m.data[1].z, s / m.data[2].x,
s / m.data[2].y, s / m.data[2].z);
}
MAT3_DECL bool operator==(const mat3& m1, const mat3& m2)
{
return (m1.data[0].x == m2.data[0].x) && (m1.data[0].y == m2.data[0].y) && (m1.data[0].z == m2.data[0].z) &&
(m1.data[1].x == m2.data[1].x) && (m1.data[1].y == m2.data[1].y) && (m1.data[1].z == m2.data[1].z) &&
(m1.data[2].x == m2.data[2].x) && (m1.data[2].y == m2.data[2].y) && (m1.data[2].z == m2.data[2].z);
}
MAT3_DECL bool operator!=(const mat3& m1, const mat3& m2)
{
return (m1.data[0].x != m2.data[0].x) || (m1.data[0].y != m2.data[0].y) || (m1.data[0].z != m2.data[0].z) ||
(m1.data[1].x != m2.data[1].x) || (m1.data[1].y != m2.data[1].y) || (m1.data[1].z != m2.data[1].z) ||
(m1.data[2].x != m2.data[2].x) || (m1.data[2].y != m2.data[2].y) || (m1.data[2].z != m2.data[2].z);
}
} // namespace Kyty::Math::m
#endif /* INCLUDE_KYTY_MATH_MAT3IMPL_H_ */
+389
View File
@@ -0,0 +1,389 @@
#ifndef INCLUDE_KYTY_MATH_MAT4IMPL_H_
#define INCLUDE_KYTY_MATH_MAT4IMPL_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Math::m {
// MAT4_DECL mat4::mat4() = default;
//
// MAT4_DECL mat4::mat4(const mat4 &m)
//{
// data[0].x = m.data[0].x; data[0].y = m.data[0].y; data[0].z = m.data[0].z; data[0].w = m.data[0].w;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y; data[1].z = m.data[1].z; data[1].w = m.data[1].w;
// data[2].x = m.data[2].x; data[2].y = m.data[2].y; data[2].z = m.data[2].z; data[2].w = m.data[2].w;
// data[3].x = m.data[3].x; data[3].y = m.data[3].y; data[3].z = m.data[3].z; data[3].w = m.data[3].w;
//}
//
// MAT4_DECL mat4::mat4(mat4 &&m) noexcept
//{
// data[0].x = m.data[0].x; data[0].y = m.data[0].y; data[0].z = m.data[0].z; data[0].w = m.data[0].w;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y; data[1].z = m.data[1].z; data[1].w = m.data[1].w;
// data[2].x = m.data[2].x; data[2].y = m.data[2].y; data[2].z = m.data[2].z; data[2].w = m.data[2].w;
// data[3].x = m.data[3].x; data[3].y = m.data[3].y; data[3].z = m.data[3].z; data[3].w = m.data[3].w;
//}
MAT4_DECL mat4::mat4(float x) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
{
data[0].x = x;
data[0].y = 0;
data[0].z = 0;
data[0].w = 0;
data[1].x = 0;
data[1].y = x;
data[1].z = 0;
data[1].w = 0;
data[2].x = 0;
data[2].y = 0;
data[2].z = x;
data[2].w = 0;
data[3].x = 0;
data[3].y = 0;
data[3].z = 0;
data[3].w = x;
}
MAT4_DECL mat4::mat4(float x1, float y1, float z1, float w1, // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
float x2, float y2, float z2, float w2, float x3, float y3, float z3, float w3, float x4, float y4, float z4,
float w4) noexcept
{
data[0].x = x1;
data[0].y = y1;
data[0].z = z1;
data[0].w = w1;
data[1].x = x2;
data[1].y = y2;
data[1].z = z2;
data[1].w = w2;
data[2].x = x3;
data[2].y = y3;
data[2].z = z3;
data[2].w = w3;
data[3].x = x4;
data[3].y = y4;
data[3].z = z4;
data[3].w = w4;
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
MAT4_DECL mat4::mat4(const vec4& v1, const vec4& v2, const vec4& v3, const vec4& v4) noexcept
{
data[0].x = v1.x;
data[0].y = v1.y;
data[0].z = v1.z;
data[0].w = v1.w;
data[1].x = v2.x;
data[1].y = v2.y;
data[1].z = v2.z;
data[1].w = v2.w;
data[2].x = v3.x;
data[2].y = v3.y;
data[2].z = v3.z;
data[2].w = v3.w;
data[3].x = v4.x;
data[3].y = v4.y;
data[3].z = v4.z;
data[3].w = v4.w;
}
MAT4_DECL vec4& mat4::operator[](int i)
{
EXIT_IF(!(i >= 0 && i < 4));
return data[i];
}
MAT4_DECL const vec4& mat4::operator[](int i) const
{
EXIT_IF(!(i >= 0 && i < 4));
return data[i];
}
// MAT4_DECL mat4 &mat4::operator = (const mat4 &m)
//{
// if (this != &m)
// {
// data[0].x = m.data[0].x; data[0].y = m.data[0].y; data[0].z = m.data[0].z; data[0].w = m.data[0].w;
// data[1].x = m.data[1].x; data[1].y = m.data[1].y; data[1].z = m.data[1].z; data[1].w = m.data[1].w;
// data[2].x = m.data[2].x; data[2].y = m.data[2].y; data[2].z = m.data[2].z; data[2].w = m.data[2].w;
// data[3].x = m.data[3].x; data[3].y = m.data[3].y; data[3].z = m.data[3].z; data[3].w = m.data[3].w;
// }
// return *this;
//}
//
// MAT4_DECL mat4 &mat4::operator = (mat4 &&m) noexcept
//{
// *this = m;
// return *this;
//}
MAT4_DECL mat4& mat4::operator+=(float s)
{
data[0].x += s;
data[0].y += s;
data[0].z += s;
data[0].w += s;
data[1].x += s;
data[1].y += s;
data[1].z += s;
data[1].w += s;
data[2].x += s;
data[2].y += s;
data[2].z += s;
data[2].w += s;
data[3].x += s;
data[3].y += s;
data[3].z += s;
data[3].w += s;
return *this;
}
MAT4_DECL mat4& mat4::operator+=(const mat4& m)
{
data[0].x += m.data[0].x;
data[0].y += m.data[0].y;
data[0].z += m.data[0].z;
data[0].w += m.data[0].w;
data[1].x += m.data[1].x;
data[1].y += m.data[1].y;
data[1].z += m.data[1].z;
data[1].w += m.data[1].w;
data[2].x += m.data[2].x;
data[2].y += m.data[2].y;
data[2].z += m.data[2].z;
data[2].w += m.data[2].w;
data[3].x += m.data[3].x;
data[3].y += m.data[3].y;
data[3].z += m.data[3].z;
data[3].w += m.data[3].w;
return *this;
}
MAT4_DECL mat4& mat4::operator-=(float s)
{
data[0].x -= s;
data[0].y -= s;
data[0].z -= s;
data[0].w -= s;
data[1].x -= s;
data[1].y -= s;
data[1].z -= s;
data[1].w -= s;
data[2].x -= s;
data[2].y -= s;
data[2].z -= s;
data[2].w -= s;
data[3].x -= s;
data[3].y -= s;
data[3].z -= s;
data[3].w -= s;
return *this;
}
MAT4_DECL mat4& mat4::operator-=(const mat4& m)
{
data[0].x -= m.data[0].x;
data[0].y -= m.data[0].y;
data[0].z -= m.data[0].z;
data[0].w -= m.data[0].w;
data[1].x -= m.data[1].x;
data[1].y -= m.data[1].y;
data[1].z -= m.data[1].z;
data[1].w -= m.data[1].w;
data[2].x -= m.data[2].x;
data[2].y -= m.data[2].y;
data[2].z -= m.data[2].z;
data[2].w -= m.data[2].w;
data[3].x -= m.data[3].x;
data[3].y -= m.data[3].y;
data[3].z -= m.data[3].z;
data[3].w -= m.data[3].w;
return *this;
}
MAT4_DECL mat4& mat4::operator*=(float s)
{
data[0].x *= s;
data[0].y *= s;
data[0].z *= s;
data[0].w *= s;
data[1].x *= s;
data[1].y *= s;
data[1].z *= s;
data[1].w *= s;
data[2].x *= s;
data[2].y *= s;
data[2].z *= s;
data[2].w *= s;
data[3].x *= s;
data[3].y *= s;
data[3].z *= s;
data[3].w *= s;
return *this;
}
MAT4_DECL mat4& mat4::operator*=(const mat4& m)
{
*this = *this * m;
return *this;
}
MAT4_DECL mat4& mat4::operator/=(float s)
{
data[0].x /= s;
data[0].y /= s;
data[0].z /= s;
data[0].w /= s;
data[1].x /= s;
data[1].y /= s;
data[1].z /= s;
data[1].w /= s;
data[2].x /= s;
data[2].y /= s;
data[2].z /= s;
data[2].w /= s;
data[3].x /= s;
data[3].y /= s;
data[3].z /= s;
data[3].w /= s;
return *this;
}
MAT4_DECL mat4 operator+(const mat4& m, float s)
{
return mat4(m.data[0].x + s, m.data[0].y + s, m.data[0].z + s, m.data[0].w + s, m.data[1].x + s, m.data[1].y + s, m.data[1].z + s,
m.data[1].w + s, m.data[2].x + s, m.data[2].y + s, m.data[2].z + s, m.data[2].w + s, m.data[3].x + s, m.data[3].y + s,
m.data[3].z + s, m.data[3].w + s);
}
MAT4_DECL mat4 operator+(float s, const mat4& m)
{
return mat4(m.data[0].x + s, m.data[0].y + s, m.data[0].z + s, m.data[0].w + s, m.data[1].x + s, m.data[1].y + s, m.data[1].z + s,
m.data[1].w + s, m.data[2].x + s, m.data[2].y + s, m.data[2].z + s, m.data[2].w + s, m.data[3].x + s, m.data[3].y + s,
m.data[3].z + s, m.data[3].w + s);
}
MAT4_DECL mat4 operator+(const mat4& m1, const mat4& m2)
{
return mat4(m1.data[0].x + m2.data[0].x, m1.data[0].y + m2.data[0].y, m1.data[0].z + m2.data[0].z, m1.data[0].w + m2.data[0].w,
m1.data[1].x + m2.data[1].x, m1.data[1].y + m2.data[1].y, m1.data[1].z + m2.data[1].z, m1.data[1].w + m2.data[1].w,
m1.data[2].x + m2.data[2].x, m1.data[2].y + m2.data[2].y, m1.data[2].z + m2.data[2].z, m1.data[2].w + m2.data[2].w,
m1.data[3].x + m2.data[3].x, m1.data[3].y + m2.data[3].y, m1.data[3].z + m2.data[3].z, m1.data[3].w + m2.data[3].w);
}
MAT4_DECL mat4 operator-(const mat4& m, float s)
{
return mat4(m.data[0].x - s, m.data[0].y - s, m.data[0].z - s, m.data[0].w - s, m.data[1].x - s, m.data[1].y - s, m.data[1].z - s,
m.data[1].w - s, m.data[2].x - s, m.data[2].y - s, m.data[2].z - s, m.data[2].w - s, m.data[3].x - s, m.data[3].y - s,
m.data[3].z - s, m.data[3].w - s);
}
MAT4_DECL mat4 operator-(float s, const mat4& m)
{
return mat4(s - m.data[0].x, s - m.data[0].y, s - m.data[0].z, s - m.data[0].w, s - m.data[1].x, s - m.data[1].y, s - m.data[1].z,
s - m.data[1].w, s - m.data[2].x, s - m.data[2].y, s - m.data[2].z, s - m.data[2].w, s - m.data[3].x, s - m.data[3].y,
s - m.data[3].z, s - m.data[3].w);
}
MAT4_DECL mat4 operator-(const mat4& m1, const mat4& m2)
{
return mat4(m1.data[0].x - m2.data[0].x, m1.data[0].y - m2.data[0].y, m1.data[0].z - m2.data[0].z, m1.data[0].w - m2.data[0].w,
m1.data[1].x - m2.data[1].x, m1.data[1].y - m2.data[1].y, m1.data[1].z - m2.data[1].z, m1.data[1].w - m2.data[1].w,
m1.data[2].x - m2.data[2].x, m1.data[2].y - m2.data[2].y, m1.data[2].z - m2.data[2].z, m1.data[2].w - m2.data[2].w,
m1.data[3].x - m2.data[3].x, m1.data[3].y - m2.data[3].y, m1.data[3].z - m2.data[3].z, m1.data[3].w - m2.data[3].w);
}
MAT4_DECL mat4 operator*(const mat4& m, float s)
{
return mat4(m.data[0].x * s, m.data[0].y * s, m.data[0].z * s, m.data[0].w * s, m.data[1].x * s, m.data[1].y * s, m.data[1].z * s,
m.data[1].w * s, m.data[2].x * s, m.data[2].y * s, m.data[2].z * s, m.data[2].w * s, m.data[3].x * s, m.data[3].y * s,
m.data[3].z * s, m.data[3].w * s);
}
MAT4_DECL mat4 operator*(float s, const mat4& m)
{
return mat4(m.data[0].x * s, m.data[0].y * s, m.data[0].z * s, m.data[0].w * s, m.data[1].x * s, m.data[1].y * s, m.data[1].z * s,
m.data[1].w * s, m.data[2].x * s, m.data[2].y * s, m.data[2].z * s, m.data[2].w * s, m.data[3].x * s, m.data[3].y * s,
m.data[3].z * s, m.data[3].w * s);
}
MAT4_DECL mat4 operator*(const mat4& m1, const mat4& m2)
{
/*#define MUL4(i, j)*/ auto mul4 = [&](auto i, auto j) {
return (m1.data[0].data[(j)] * m2.data[(i)].data[0] + m1.data[1].data[(j)] * m2.data[(i)].data[1] +
m1.data[2].data[(j)] * m2.data[(i)].data[2] + m1.data[3].data[(j)] * m2.data[(i)].data[3]);
};
return mat4(mul4(0, 0), mul4(0, 1), mul4(0, 2), mul4(0, 3), mul4(1, 0), mul4(1, 1), mul4(1, 2), mul4(1, 3), mul4(2, 0), mul4(2, 1),
mul4(2, 2), mul4(2, 3), mul4(3, 0), mul4(3, 1), mul4(3, 2), mul4(3, 3));
//#undef MUL4
}
MAT4_DECL vec4 operator*(const mat4& m, const vec4& v)
{
float x1 = m.data[0].x * v.x + m.data[1].x * v.y;
float x2 = m.data[2].x * v.z + m.data[3].x * v.w;
float y1 = m.data[0].y * v.x + m.data[1].y * v.y;
float y2 = m.data[2].y * v.z + m.data[3].y * v.w;
float z1 = m.data[0].z * v.x + m.data[1].z * v.y;
float z2 = m.data[2].z * v.z + m.data[3].z * v.w;
float w1 = m.data[0].w * v.x + m.data[1].w * v.y;
float w2 = m.data[2].w * v.z + m.data[3].w * v.w;
return vec4(x1 + x2, y1 + y2, z1 + z2, w1 + w2);
// return vec4(m.data[0].x * v.x + m.data[1].x * v.y + m.data[2].x * v.z + m.data[3].x * v.w,
// m.data[0].y * v.x + m.data[1].y * v.y + m.data[2].y * v.z + m.data[3].y * v.w,
// m.data[0].z * v.x + m.data[1].z * v.y + m.data[2].z * v.z + m.data[3].z * v.w,
// m.data[0].w * v.x + m.data[1].w * v.y + m.data[2].w * v.z + m.data[3].w * v.w);
}
MAT4_DECL vec4 operator*(const vec4& v, const mat4& m)
{
return vec4(m.data[0].x * v.x + m.data[0].y * v.y + m.data[0].z * v.z + m.data[0].w * v.w,
m.data[1].x * v.x + m.data[1].y * v.y + m.data[1].z * v.z + m.data[1].w * v.w,
m.data[2].x * v.x + m.data[2].y * v.y + m.data[2].z * v.z + m.data[2].w * v.w,
m.data[3].x * v.x + m.data[3].y * v.y + m.data[3].z * v.z + m.data[3].w * v.w);
}
MAT4_DECL mat4 operator/(const mat4& m, float s)
{
return mat4(m.data[0].x / s, m.data[0].y / s, m.data[0].z / s, m.data[0].w / s, m.data[1].x / s, m.data[1].y / s, m.data[1].z / s,
m.data[1].w / s, m.data[2].x / s, m.data[2].y / s, m.data[2].z / s, m.data[2].w / s, m.data[3].x / s, m.data[3].y / s,
m.data[3].z / s, m.data[3].w / s);
}
MAT4_DECL mat4 operator/(float s, const mat4& m)
{
return mat4(s / m.data[0].x, s / m.data[0].y, s / m.data[0].z, s / m.data[0].w, s / m.data[1].x, s / m.data[1].y, s / m.data[1].z,
s / m.data[1].w, s / m.data[2].x, s / m.data[2].y, s / m.data[2].z, s / m.data[2].w, s / m.data[3].x, s / m.data[3].y,
s / m.data[3].z, s / m.data[3].w);
}
MAT4_DECL bool operator==(const mat4& m1, const mat4& m2)
{
return (m1.data[0].x == m2.data[0].x) && (m1.data[0].y == m2.data[0].y) && (m1.data[0].z == m2.data[0].z) &&
(m1.data[0].w == m2.data[0].w) && (m1.data[1].x == m2.data[1].x) && (m1.data[1].y == m2.data[1].y) &&
(m1.data[1].z == m2.data[1].z) && (m1.data[1].w == m2.data[1].w) && (m1.data[2].x == m2.data[2].x) &&
(m1.data[2].y == m2.data[2].y) && (m1.data[2].z == m2.data[2].z) && (m1.data[2].w == m2.data[2].w) &&
(m1.data[3].x == m2.data[3].x) && (m1.data[3].y == m2.data[3].y) && (m1.data[3].z == m2.data[3].z) &&
(m1.data[3].w == m2.data[3].w);
}
MAT4_DECL bool operator!=(const mat4& m1, const mat4& m2)
{
return (m1.data[0].x != m2.data[0].x) || (m1.data[0].y != m2.data[0].y) || (m1.data[0].z != m2.data[0].z) ||
(m1.data[0].w != m2.data[0].w) || (m1.data[1].x != m2.data[1].x) || (m1.data[1].y != m2.data[1].y) ||
(m1.data[1].z != m2.data[1].z) || (m1.data[1].w != m2.data[1].w) || (m1.data[2].x != m2.data[2].x) ||
(m1.data[2].y != m2.data[2].y) || (m1.data[2].z != m2.data[2].z) || (m1.data[2].w != m2.data[2].w) ||
(m1.data[3].x != m2.data[3].x) || (m1.data[3].y != m2.data[3].y) || (m1.data[3].z != m2.data[3].z) ||
(m1.data[3].w != m2.data[3].w);
}
} // namespace Kyty::Math::m
#endif /* INCLUDE_KYTY_MATH_MAT4IMPL_H_ */
+522
View File
@@ -0,0 +1,522 @@
#ifndef INCLUDE_KYTY_MATH_MATHALL_H_
#define INCLUDE_KYTY_MATH_MATHALL_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/Subsystems.h"
//#define KYTY_MATH_GLM
#ifdef KYTY_MATH_GLM
#include "Kyty/KytyGlmInc.h" // IWYU pragma: export
typedef glm::mat2 mat2;
typedef glm::mat3 mat3;
typedef glm::mat4 mat4;
typedef glm::vec2 vec2;
typedef glm::vec3 vec3;
typedef glm::vec4 vec4;
#else
#include "Kyty/Math/VectorAndMatrix.h" // IWYU pragma: export
using mat2 = Kyty::Math::m::mat2;
using mat3 = Kyty::Math::m::mat3;
using mat4 = Kyty::Math::m::mat4;
using vec2 = Kyty::Math::m::vec2;
using vec3 = Kyty::Math::m::vec3;
using vec4 = Kyty::Math::m::vec4;
#endif
namespace Kyty::Math {
namespace Double {
constexpr double E = 2.7182818284590452354; /* e */
constexpr double LOG2E = 1.4426950408889634074; /* log 2e */
constexpr double LOG10E = 0.43429448190325182765; /* log 10e */
constexpr double LN2 = 0.69314718055994530942; /* log e2 */
constexpr double LN10 = 2.30258509299404568402; /* log e10 */
constexpr double PI = 3.14159265358979323846; /* pi */
constexpr double PI_2 = 1.57079632679489661923; /* pi/2 */
constexpr double PI_4 = 0.78539816339744830962; /* pi/4 */
constexpr double C_1_PI = 0.31830988618379067154; /* 1/pi */
constexpr double C_2_PI = 0.63661977236758134308; /* 2/pi */
constexpr double C_2_SQRTPI = 1.12837916709551257390; /* 2/sqrt(pi) */
constexpr double SQRT2 = 1.41421356237309504880; /* sqrt(2) */
constexpr double SQRT1_2 = 0.70710678118654752440; /* 1/sqrt(2) */
} // namespace Double
namespace Float {
constexpr float E = 2.7182818284590452354f; /* e */
constexpr float LOG2E = 1.4426950408889634074f; /* log 2e */
constexpr float LOG10E = 0.43429448190325182765f; /* log 10e */
constexpr float LN2 = 0.69314718055994530942f; /* log e2 */
constexpr float LN10 = 2.30258509299404568402f; /* log e10 */
constexpr float PI = 3.14159265358979323846f; /* pi */
constexpr float PI_2 = 1.57079632679489661923f; /* pi/2 */
constexpr float PI_4 = 0.78539816339744830962f; /* pi/4 */
constexpr float C_1_PI = 0.31830988618379067154f; /* 1/pi */
constexpr float C_2_PI = 0.63661977236758134308f; /* 2/pi */
constexpr float C_2_SQRTPI = 1.12837916709551257390f; /* 2/sqrt(pi) */
constexpr float SQRT2 = 1.41421356237309504880f; /* sqrt(2) */
constexpr float SQRT1_2 = 0.70710678118654752440f; /* 1/sqrt(2) */
} // namespace Float
KYTY_SUBSYSTEM_DEFINE(Math);
inline vec3& xyz(vec4& v) // NOLINT(google-runtime-references)
{
#ifdef KYTY_MATH_GLM
return *(vec3*)glm::value_ptr(v);
#else
return *reinterpret_cast<vec3*>(m::value_ptr(v));
#endif
}
inline const vec3& xyz(const vec4& v)
{
#ifdef KYTY_MATH_GLM
return *(const vec3*)glm::value_ptr(v);
#else
return *reinterpret_cast<const vec3*>(m::value_ptr(v));
#endif
}
inline vec2& xy(vec4& v) // NOLINT(google-runtime-references)
{
#ifdef KYTY_MATH_GLM
return *(vec2*)glm::value_ptr(v);
#else
return *reinterpret_cast<vec2*>(m::value_ptr(v));
#endif
}
inline vec2& xy(vec3& v) // NOLINT(google-runtime-references)
{
#ifdef KYTY_MATH_GLM
return *(vec2*)glm::value_ptr(v);
#else
return *reinterpret_cast<vec2*>(m::value_ptr(v));
#endif
}
inline uint32_t nod(uint32_t a, uint32_t b)
{
while ((a != 0u) && (b != 0u))
{
a > b ? a %= b : b %= a;
}
return a + b;
}
struct Size
{
Size() = default;
Size(uint32_t w, uint32_t h): width(w), height(h) {}
bool operator==(const Size& s) const { return width == s.width && height == s.height; }
uint32_t width {0};
uint32_t height {0};
};
struct Rect
{
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
};
inline mat4 mat_translate(const vec3& v)
{
return mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, v.x, v.y, v.z, 1.0f);
}
inline mat4 mat_translate(const vec2& v)
{
return mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, v.x, v.y, 0.0f, 1.0f);
}
inline mat4 mat_translate(float z)
{
return mat4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, z, 1.0f);
}
inline void mat_translate_upd(mat4& m, const vec3& v) // NOLINT(google-runtime-references)
{
m[3][0] = v.x;
m[3][1] = v.y;
m[3][2] = v.z;
}
inline void mat_translate_upd(mat4& m, const vec2& v) // NOLINT(google-runtime-references)
{
m[3][0] = v.x;
m[3][1] = v.y;
}
inline void mat_translate_upd(mat4& m, float z) // NOLINT(google-runtime-references)
{
m[3][2] = z;
}
inline mat4 mat_scale(const vec3& v)
{
return mat4(v.x, 0.0f, 0.0f, 0.0f, 0.0f, v.y, 0.0f, 0.0f, 0.0f, 0.0f, v.z, 0.0f, 0.0f, 0.0f, 0.0, 1.0f);
}
inline mat4 mat_scale(const vec2& v)
{
return mat4(v.x, 0.0f, 0.0f, 0.0f, 0.0f, v.y, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0, 1.0f);
}
inline void mat_scale_upd(mat4& m, const vec3& v) // NOLINT(google-runtime-references)
{
m[0][0] = v.x;
m[1][1] = v.y;
m[2][2] = v.z;
}
inline void mat_scale_upd(mat4& m, const vec2& v) // NOLINT(google-runtime-references)
{
m[0][0] = v.x;
m[1][1] = v.y;
}
inline mat4 mat_rotate(float angle, const vec3& v)
{
#ifdef KYTY_MATH_GLM
return glm::rotate(mat4(1.0f), angle, v);
#else
return m::rotate(angle, v);
#endif
}
inline mat4 mat_rotate(float angle)
{
float c = cosf(angle);
float s = sinf(angle);
return mat4(c, s, 0.0f, 0.0f, -s, c, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0, 1.0f);
}
inline void mat_rotate_upd(mat4& m, float angle, const vec3& v) // NOLINT(google-runtime-references)
{
#ifdef KYTY_MATH_GLM
m = glm::rotate(mat4(1.0f), angle, v);
#else
m = m::rotate(angle, v);
#endif
}
inline void mat_rotate_upd(mat4& m, float angle) // NOLINT(google-runtime-references)
{
float c = cosf(angle);
float s = sinf(angle);
m[0][0] = c;
m[1][1] = c;
m[1][0] = -s;
m[0][1] = s;
}
inline vec2 vec_reciprocal(const vec2& v)
{
EXIT_IF(v.x == 0.0f || v.y == 0.0f);
return vec2(1.0f / v.x, 1.0f / v.y);
}
inline vec3 vec_reciprocal(const vec3& v)
{
EXIT_IF(v.x == 0.0f || v.y == 0.0f || v.z == 0.0f);
return vec3(1.0f / v.x, 1.0f / v.y, 1.0f / v.z);
}
inline vec4 vec_reciprocal(const vec4& v)
{
EXIT_IF(v.x == 0.0f || v.y == 0.0f || v.z == 0.0f || v.w == 0.0f);
return vec4(1.0f / v.x, 1.0f / v.y, 1.0f / v.z, 1.0f / v.w);
}
struct PosUV
{
vec2 pos {};
vec2 uv {};
};
struct RectUV
{
PosUV p1 {};
PosUV p2 {};
float z {};
};
template <class T>
inline T floordiv(T a, T b)
{
if (b < 0)
{
if (a < 0)
{
return a / b;
};
b = -b;
a = -a;
}
return (a - (a < 0 ? b - 1 : 0)) / b;
}
inline mat4 mat_lookAt(const vec3& eye, const vec3& center, const vec3& up)
{
#ifdef KYTY_MATH_GLM
return glm::lookAt(eye, center, up);
#else
return m::lookAt(eye, center, up);
#endif
}
inline mat4 mat_perspective(float f, float a, float nr, float fr)
{
#ifdef KYTY_MATH_GLM
return glm::perspective(f, a, nr, fr);
#else
return m::perspective(f, a, nr, fr);
#endif
}
inline mat4 mat_ortho(float left, float right, float bottom, float top, float z_near, float z_far)
{
#ifdef KYTY_MATH_GLM
return glm::ortho(left, right, bottom, top, z_near, z_far);
#else
return m::ortho(left, right, bottom, top, z_near, z_far);
#endif
}
inline mat4 mat_inverse_transpose(const mat4& m)
{
#ifdef KYTY_MATH_GLM
return glm::inverseTranspose(m);
#else
return m::inverseTranspose(m);
#endif
}
inline mat4 mat_transpose(const mat4& m)
{
#ifdef KYTY_MATH_GLM
return glm::transpose(m);
#else
return m::transpose(m);
#endif
}
inline mat4 mat_inverse(const mat4& m)
{
#ifdef KYTY_MATH_GLM
return glm::inverse(m);
#else
return m::inverse(m);
#endif
}
inline mat3 mat_transpose(const mat3& m)
{
#ifdef KYTY_MATH_GLM
return glm::transpose(m);
#else
return m::transpose(m);
#endif
}
inline mat3 mat_inverse(const mat3& m)
{
#ifdef KYTY_MATH_GLM
return glm::inverse(m);
#else
return m::inverse(m);
#endif
}
inline mat4 make_mat4(const float* f)
{
#ifdef KYTY_MATH_GLM
return glm::make_mat4(f);
#else
return m::make_mat4(f);
#endif
}
inline float math_radians(float a)
{
#ifdef KYTY_MATH_GLM
return glm::radians(a);
#else
return m::radians(a);
#endif
}
inline float math_round(float a)
{
#ifdef KYTY_MATH_GLM
return glm::round(a);
#else
return m::round(a);
#endif
}
inline vec4 math_round(const vec4& a)
{
#ifdef KYTY_MATH_GLM
return glm::round(a);
#else
return m::round(a);
#endif
}
inline float math_max(float a, float b)
{
#ifdef KYTY_MATH_GLM
return glm::max(a, b);
#else
return m::max(a, b);
#endif
}
inline vec2 math_max(const vec2& a, const vec2& b)
{
#ifdef KYTY_MATH_GLM
return glm::max(a, b);
#else
return m::max(a, b);
#endif
}
inline vec3 math_max(const vec3& a, const vec3& b)
{
#ifdef KYTY_MATH_GLM
return glm::max(a, b);
#else
return m::max(a, b);
#endif
}
inline vec4 math_max(const vec4& a, const vec4& b)
{
#ifdef KYTY_MATH_GLM
return glm::max(a, b);
#else
return m::max(a, b);
#endif
}
inline float math_min(float a, float b)
{
#ifdef KYTY_MATH_GLM
return glm::min(a, b);
#else
return m::min(a, b);
#endif
}
inline vec2 math_min(const vec2& a, const vec2& b)
{
#ifdef KYTY_MATH_GLM
return glm::min(a, b);
#else
return m::min(a, b);
#endif
}
inline vec3 math_min(const vec3& a, const vec3& b)
{
#ifdef KYTY_MATH_GLM
return glm::min(a, b);
#else
return m::min(a, b);
#endif
}
inline vec4 math_min(const vec4& a, const vec4& b)
{
#ifdef KYTY_MATH_GLM
return glm::min(a, b);
#else
return m::min(a, b);
#endif
}
inline float math_clamp(float v, float a, float b)
{
#ifdef KYTY_MATH_GLM
return glm::clamp(v, a, b);
#else
return m::clamp(v, a, b);
#endif
}
inline vec3 math_clamp(const vec3& v, float a, float b)
{
#ifdef KYTY_MATH_GLM
return glm::clamp(v, a, b);
#else
return m::clamp(v, a, b);
#endif
}
inline float math_abs(float v)
{
#ifdef KYTY_MATH_GLM
return glm::abs(v);
#else
return m::abs(v);
#endif
}
inline vec2 math_abs(const vec2& v)
{
#ifdef KYTY_MATH_GLM
return glm::abs(v);
#else
return m::abs(v);
#endif
}
inline float math_dot(const vec2& x, const vec2& y)
{
#ifdef KYTY_MATH_GLM
return glm::dot(x, y);
#else
return m::dot(x, y);
#endif
}
inline int math_nod(int a, int b)
{
while ((a != 0) && (b != 0))
{
a > b ? a %= b : b %= a;
}
return a + b;
}
inline int math_nod(int a, int b, int c)
{
return static_cast<int>(nod(nod(a, b), c));
}
inline int math_nod(int* a, int n)
{
int d = a[0];
for (int i = 1; i < n; i++)
{
d = static_cast<int>(nod(d, a[i]));
}
return d;
}
} // namespace Kyty::Math
#endif /* INCLUDE_KYTY_MATH_MATHALL_H_ */
+62
View File
@@ -0,0 +1,62 @@
#ifndef INCLUDE_KYTY_MATH_RAND_H_
#define INCLUDE_KYTY_MATH_RAND_H_
#include "Kyty/Core/Common.h"
#include <random> // IWYU pragma: export
namespace Kyty::Math {
class Rand
{
public:
static void Init();
// random in range [0, 4294967295]
static uint32_t Uint();
// random in range [-2147483648, 2147483647]
static int32_t Int();
// random in range [0.0, 1.0]
static double DoubleInclusive();
// random in range [0.0, 1.0)
static double Double();
// random in range [from, to]
static double DoubleInclusiveRange(double from_incl, double to_incl);
// random in range [from, to)
static double DoubleRange(double from_incl, double to_excl);
// random in range [0.0, 1.0]
static float FloatInclusive();
// random in range [0.0, 1.0)
static float Float();
// random in range [from, to]
static float FloatInclusiveRange(float from_incl, float to_incl);
// random in range [from, to)
static float FloatRange(float from_incl, float to_excl);
// random in range [from, to]
static uint32_t UintInclusiveRange(uint32_t from_incl, uint32_t to_incl);
// random in range [from, to]
static int32_t IntInclusiveRange(int32_t from_incl, int32_t to_incl);
static void Seed(unsigned int s);
static void SeedBySystemTime();
static std::mt19937 GetRandomEngine();
};
// using Rand = Math::Rand;
} // namespace Kyty::Math
#endif /* INCLUDE_KYTY_MATH_RAND_H_ */
+181
View File
@@ -0,0 +1,181 @@
#ifndef INCLUDE_KYTY_MATH_VEC2IMPL_H_
#define INCLUDE_KYTY_MATH_VEC2IMPL_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Math::m {
// VEC2_DECL vec2::vec2() {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
// VEC2_DECL vec2::vec2(const vec2 &v): x(v.x), y(v.y) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
// VEC2_DECL vec2::vec2(vec2 &&v) noexcept: x(v.x), y(v.y) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC2_DECL vec2::vec2(const vec3& v) noexcept: x(v.x), y(v.y) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC2_DECL vec2::vec2(const vec4& v) noexcept: x(v.x), y(v.y) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC2_DECL vec2::vec2(float s) noexcept: x(s), y(s) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC2_DECL vec2::vec2(float s1, float s2) noexcept: x(s1), y(s2) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC2_DECL float& vec2::operator[](int i)
{
EXIT_IF(!(i >= 0 && i < 2));
return data[i];
}
VEC2_DECL float const& vec2::operator[](int i) const
{
EXIT_IF(!(i >= 0 && i < 2));
return data[i];
}
// VEC2_DECL vec2 &vec2::operator = (const vec2 &v)
//{
// if (this != &v)
// {
// x = v.x;
// y = v.y;
// }
// return *this;
//}
//
// VEC2_DECL vec2 &vec2::operator = (vec2 &&v) noexcept
//{
// *this = v;
// return *this;
//}
VEC2_DECL vec2& vec2::operator+=(float s)
{
x += s;
y += s;
return *this;
}
VEC2_DECL vec2& vec2::operator+=(const vec2& v)
{
x += v.x;
y += v.y;
return *this;
}
VEC2_DECL vec2& vec2::operator-=(float s)
{
x -= s;
y -= s;
return *this;
}
VEC2_DECL vec2& vec2::operator-=(const vec2& v)
{
x -= v.x;
y -= v.y;
return *this;
}
VEC2_DECL vec2& vec2::operator*=(float s)
{
x *= s;
y *= s;
return *this;
}
VEC2_DECL vec2& vec2::operator*=(const vec2& v)
{
x *= v.x;
y *= v.y;
return *this;
}
VEC2_DECL vec2& vec2::operator/=(float s)
{
x /= s;
y /= s;
return *this;
}
VEC2_DECL vec2& vec2::operator/=(const vec2& v)
{
x /= v.x;
y /= v.y;
return *this;
}
VEC2_DECL vec2 vec2::operator-() const
{
return vec2(-x, -y);
}
VEC2_DECL vec2 operator+(const vec2& v, float s)
{
return vec2(v.x + s, v.y + s);
}
VEC2_DECL vec2 operator+(float s, const vec2& v)
{
return vec2(v.x + s, v.y + s);
}
VEC2_DECL vec2 operator+(const vec2& v1, const vec2& v2)
{
return vec2(v1.x + v2.x, v1.y + v2.y);
}
VEC2_DECL vec2 operator-(const vec2& v, float s)
{
return vec2(v.x - s, v.y - s);
}
VEC2_DECL vec2 operator-(float s, const vec2& v)
{
return vec2(s - v.x, s - v.y);
}
VEC2_DECL vec2 operator-(const vec2& v1, const vec2& v2)
{
return vec2(v1.x - v2.x, v1.y - v2.y);
}
VEC2_DECL vec2 operator*(const vec2& v, float s)
{
return vec2(v.x * s, v.y * s);
}
VEC2_DECL vec2 operator*(float s, const vec2& v)
{
return vec2(v.x * s, v.y * s);
}
VEC2_DECL vec2 operator*(const vec2& v1, const vec2& v2)
{
return vec2(v1.x * v2.x, v1.y * v2.y);
}
VEC2_DECL vec2 operator/(const vec2& v, float s)
{
return vec2(v.x / s, v.y / s);
}
VEC2_DECL vec2 operator/(float s, const vec2& v)
{
return vec2(s / v.x, s / v.y);
}
VEC2_DECL vec2 operator/(const vec2& v1, const vec2& v2)
{
return vec2(v1.x / v2.x, v1.y / v2.y);
}
VEC2_DECL bool operator==(const vec2& v1, const vec2& v2)
{
return (v1.x == v2.x) && (v1.y == v2.y);
}
VEC2_DECL bool operator!=(const vec2& v1, const vec2& v2)
{
return (v1.x != v2.x) || (v1.y != v2.y);
}
} // namespace Kyty::Math::m
#endif /* INCLUDE_KYTY_MATH_VEC2IMPL_H_ */
+191
View File
@@ -0,0 +1,191 @@
#ifndef INCLUDE_KYTY_MATH_VEC3IMPL_H_
#define INCLUDE_KYTY_MATH_VEC3IMPL_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Math::m {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC3_DECL vec3::vec3(const vec4& v) noexcept: x(v.x), y(v.y), z(v.z) {}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC3_DECL vec3::vec3(float s) noexcept: x(s), y(s), z(s) {}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC3_DECL vec3::vec3(float s1, float s2, float s3) noexcept: x(s1), y(s2), z(s3) {}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC3_DECL vec3::vec3(const vec2& v, float s3) noexcept: x(v.x), y(v.y), z(s3) {}
VEC3_DECL float& vec3::operator[](int i)
{
EXIT_IF(!(i >= 0 && i < 3));
return data[i];
}
VEC3_DECL float const& vec3::operator[](int i) const
{
EXIT_IF(!(i >= 0 && i < 3));
return data[i];
}
// VEC3_DECL vec3 &vec3::operator = (const vec3 &v)
//{
// if (this != &v)
// {
// x = v.x;
// y = v.y;
// z = v.z;
// }
// return *this;
//}
//
// VEC3_DECL vec3 &vec3::operator = (vec3 &&v) noexcept
//{
// *this = v;
// return *this;
//}
VEC3_DECL vec3& vec3::operator+=(float s)
{
x += s;
y += s;
z += s;
return *this;
}
VEC3_DECL vec3& vec3::operator+=(const vec3& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
VEC3_DECL vec3& vec3::operator-=(float s)
{
x -= s;
y -= s;
z -= s;
return *this;
}
VEC3_DECL vec3& vec3::operator-=(const vec3& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
VEC3_DECL vec3& vec3::operator*=(float s)
{
x *= s;
y *= s;
z *= s;
return *this;
}
VEC3_DECL vec3& vec3::operator*=(const vec3& v)
{
x *= v.x;
y *= v.y;
z *= v.z;
return *this;
}
VEC3_DECL vec3& vec3::operator/=(float s)
{
x /= s;
y /= s;
z /= s;
return *this;
}
VEC3_DECL vec3& vec3::operator/=(const vec3& v)
{
x /= v.x;
y /= v.y;
z /= v.z;
return *this;
}
VEC3_DECL vec3 vec3::operator-() const
{
return vec3(-x, -y, -z);
}
VEC3_DECL vec3 operator+(const vec3& v, float s)
{
return vec3(v.x + s, v.y + s, v.z + s);
}
VEC3_DECL vec3 operator+(float s, const vec3& v)
{
return vec3(v.x + s, v.y + s, v.z + s);
}
VEC3_DECL vec3 operator+(const vec3& v1, const vec3& v2)
{
return vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
VEC3_DECL vec3 operator-(const vec3& v, float s)
{
return vec3(v.x - s, v.y - s, v.z - s);
}
VEC3_DECL vec3 operator-(float s, const vec3& v)
{
return vec3(s - v.x, s - v.y, s - v.z);
}
VEC3_DECL vec3 operator-(const vec3& v1, const vec3& v2)
{
return vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
VEC3_DECL vec3 operator*(const vec3& v, float s)
{
return vec3(v.x * s, v.y * s, v.z * s);
}
VEC3_DECL vec3 operator*(float s, const vec3& v)
{
return vec3(v.x * s, v.y * s, v.z * s);
}
VEC3_DECL vec3 operator*(const vec3& v1, const vec3& v2)
{
return vec3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
}
VEC3_DECL vec3 operator/(const vec3& v, float s)
{
return vec3(v.x / s, v.y / s, v.z / s);
}
VEC3_DECL vec3 operator/(float s, const vec3& v)
{
return vec3(s / v.x, s / v.y, s / v.z);
}
VEC3_DECL vec3 operator/(const vec3& v1, const vec3& v2)
{
return vec3(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z);
}
VEC3_DECL bool operator==(const vec3& v1, const vec3& v2)
{
return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z);
}
VEC3_DECL bool operator!=(const vec3& v1, const vec3& v2)
{
return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z);
}
} // namespace Kyty::Math::m
#endif /* INCLUDE_KYTY_MATH_VEC3IMPL_H_ */
+198
View File
@@ -0,0 +1,198 @@
#ifndef INCLUDE_KYTY_MATH_VEC4IMPL_H_
#define INCLUDE_KYTY_MATH_VEC4IMPL_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
namespace Kyty::Math::m {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC4_DECL vec4::vec4(float s) noexcept: x(s), y(s), z(s), w(s) {}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC4_DECL vec4::vec4(float s1, float s2, float s3, float s4) noexcept: x(s1), y(s2), z(s3), w(s4) {}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
VEC4_DECL vec4::vec4(const vec3& v, float s4) noexcept: x(v.x), y(v.y), z(v.z), w(s4) {}
VEC4_DECL float& vec4::operator[](int i)
{
EXIT_IF(!(i >= 0 && i < 4));
return data[i];
}
VEC4_DECL float const& vec4::operator[](int i) const
{
EXIT_IF(!(i >= 0 && i < 4));
return data[i];
}
// VEC4_DECL vec4 &vec4::operator = (const vec4 &v)
//{
// if (this != &v)
// {
// x = v.x;
// y = v.y;
// z = v.z;
// w = v.w;
// }
// return *this;
//}
//
// VEC4_DECL vec4 &vec4::operator = (vec4 &&v) noexcept
//{
// *this = v;
// return *this;
//}
VEC4_DECL vec4& vec4::operator+=(float s)
{
x += s;
y += s;
z += s;
w += s;
return *this;
}
VEC4_DECL vec4& vec4::operator+=(const vec4& v)
{
x += v.x;
y += v.y;
z += v.z;
w += v.w;
return *this;
}
VEC4_DECL vec4& vec4::operator-=(float s)
{
x -= s;
y -= s;
z -= s;
w -= s;
return *this;
}
VEC4_DECL vec4& vec4::operator-=(const vec4& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
w -= v.w;
return *this;
}
VEC4_DECL vec4& vec4::operator*=(float s)
{
x *= s;
y *= s;
z *= s;
w *= s;
return *this;
}
VEC4_DECL vec4& vec4::operator*=(const vec4& v)
{
x *= v.x;
y *= v.y;
z *= v.z;
w *= v.w;
return *this;
}
VEC4_DECL vec4& vec4::operator/=(float s)
{
x /= s;
y /= s;
z /= s;
w /= s;
return *this;
}
VEC4_DECL vec4& vec4::operator/=(const vec4& v)
{
x /= v.x;
y /= v.y;
z /= v.z;
w /= v.w;
return *this;
}
VEC4_DECL vec4 vec4::operator-() const
{
return vec4(-x, -y, -z, -w);
}
VEC4_DECL vec4 operator+(const vec4& v, float s)
{
return vec4(v.x + s, v.y + s, v.z + s, v.w + s);
}
VEC4_DECL vec4 operator+(float s, const vec4& v)
{
return vec4(v.x + s, v.y + s, v.z + s, v.w + s);
}
VEC4_DECL vec4 operator+(const vec4& v1, const vec4& v2)
{
return vec4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
}
VEC4_DECL vec4 operator-(const vec4& v, float s)
{
return vec4(v.x - s, v.y - s, v.z - s, v.w - s);
}
VEC4_DECL vec4 operator-(float s, const vec4& v)
{
return vec4(s - v.x, s - v.y, s - v.z, s - v.w);
}
VEC4_DECL vec4 operator-(const vec4& v1, const vec4& v2)
{
return vec4(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);
}
VEC4_DECL vec4 operator*(const vec4& v, float s)
{
return vec4(v.x * s, v.y * s, v.z * s, v.w * s);
}
VEC4_DECL vec4 operator*(float s, const vec4& v)
{
return vec4(v.x * s, v.y * s, v.z * s, v.w * s);
}
VEC4_DECL vec4 operator*(const vec4& v1, const vec4& v2)
{
return vec4(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w);
}
VEC4_DECL vec4 operator/(const vec4& v, float s)
{
return vec4(v.x / s, v.y / s, v.z / s, v.w / s);
}
VEC4_DECL vec4 operator/(float s, const vec4& v)
{
return vec4(s / v.x, s / v.y, s / v.z, s / v.w);
}
VEC4_DECL vec4 operator/(const vec4& v1, const vec4& v2)
{
return vec4(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w);
}
VEC4_DECL bool operator==(const vec4& v1, const vec4& v2)
{
return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z) && (v1.w == v2.w);
}
VEC4_DECL bool operator!=(const vec4& v1, const vec4& v2)
{
return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z) || (v1.w != v2.w);
}
} // namespace Kyty::Math::m
#endif /* INCLUDE_KYTY_MATH_VEC4IMPL_H_ */
+868
View File
@@ -0,0 +1,868 @@
#ifndef INCLUDE_KYTY_MATH_VECTORANDMATRIX_H_
#define INCLUDE_KYTY_MATH_VECTORANDMATRIX_H_
// IWYU pragma: private
#include "Kyty/Core/Common.h"
#include <cmath> // IWYU pragma: export
namespace Kyty::Math::m {
class vec3;
class vec4;
// NOLINTNEXTLINE(readability-identifier-naming)
class vec2 final
{
public:
vec2() noexcept = default;
~vec2() = default;
vec2(const vec2& v) noexcept = default;
vec2(vec2&& v) noexcept = default;
explicit vec2(const vec3& v) noexcept;
explicit vec2(const vec4& v) noexcept;
explicit vec2(float s) noexcept;
explicit vec2(float s1, float s2) noexcept;
float& operator[](int i);
float const& operator[](int i) const;
vec2& operator=(const vec2& v) = default;
vec2& operator=(vec2&& v) noexcept = default;
vec2& operator+=(float s);
vec2& operator+=(const vec2& v);
vec2& operator-=(float s);
vec2& operator-=(const vec2& v);
vec2& operator*=(float s);
vec2& operator*=(const vec2& v);
vec2& operator/=(float s);
vec2& operator/=(const vec2& v);
vec2 operator-() const;
friend vec2 operator+(const vec2& v, float s);
friend vec2 operator+(float s, const vec2& v);
friend vec2 operator+(const vec2& v1, const vec2& v2);
friend vec2 operator-(const vec2& v, float s);
friend vec2 operator-(float s, const vec2& v);
friend vec2 operator-(const vec2& v1, const vec2& v2);
friend vec2 operator*(const vec2& v, float s);
friend vec2 operator*(float s, const vec2& v);
friend vec2 operator*(const vec2& v1, const vec2& v2);
friend vec2 operator/(const vec2& v, float s);
friend vec2 operator/(float s, const vec2& v);
friend vec2 operator/(const vec2& v1, const vec2& v2);
friend bool operator==(const vec2& v1, const vec2& v2);
friend bool operator!=(const vec2& v1, const vec2& v2);
union
{
struct
{
union
{
float x, r;
};
union
{
float y, g;
};
};
float data[2];
};
};
// NOLINTNEXTLINE(readability-identifier-naming)
class vec3 final
{
public:
vec3() noexcept = default;
vec3(const vec3& v) noexcept = default;
vec3(vec3&& v) noexcept = default;
~vec3() = default;
explicit vec3(const vec4& v) noexcept;
explicit vec3(float s) noexcept;
explicit vec3(float s1, float s2, float s3) noexcept;
explicit vec3(const vec2& v, float s3) noexcept;
float& operator[](int i);
float const& operator[](int i) const;
[[nodiscard]] vec2 Xy() const { return vec2(x, y); }
[[nodiscard]] vec2 Rg() const { return vec2(r, g); }
vec3& operator=(const vec3& v) = default;
vec3& operator=(vec3&& v) noexcept = default;
vec3& operator+=(float s);
vec3& operator+=(const vec3& v);
vec3& operator-=(float s);
vec3& operator-=(const vec3& v);
vec3& operator*=(float s);
vec3& operator*=(const vec3& v);
vec3& operator/=(float s);
vec3& operator/=(const vec3& v);
vec3 operator-() const;
friend vec3 operator+(const vec3& v, float s);
friend vec3 operator+(float s, const vec3& v);
friend vec3 operator+(const vec3& v1, const vec3& v2);
friend vec3 operator-(const vec3& v, float s);
friend vec3 operator-(float s, const vec3& v);
friend vec3 operator-(const vec3& v1, const vec3& v2);
friend vec3 operator*(const vec3& v, float s);
friend vec3 operator*(float s, const vec3& v);
friend vec3 operator*(const vec3& v1, const vec3& v2);
friend vec3 operator/(const vec3& v, float s);
friend vec3 operator/(float s, const vec3& v);
friend vec3 operator/(const vec3& v1, const vec3& v2);
friend bool operator==(const vec3& v1, const vec3& v2);
friend bool operator!=(const vec3& v1, const vec3& v2);
union
{
struct
{
union
{
float x, r;
};
union
{
float y, g;
};
union
{
float z, b;
};
};
float data[3];
};
};
// NOLINTNEXTLINE(readability-identifier-naming)
class vec4 final
{
public:
vec4() noexcept = default;
vec4(const vec4& v) noexcept = default;
vec4(vec4&& v) noexcept = default;
~vec4() = default;
explicit vec4(float s) noexcept;
explicit vec4(float s1, float s2, float s3, float s4) noexcept;
explicit vec4(const vec3& v, float s4) noexcept;
float& operator[](int i);
float const& operator[](int i) const;
[[nodiscard]] vec2 Xy() const { return vec2(x, y); }
[[nodiscard]] vec2 Rg() const { return vec2(r, g); }
[[nodiscard]] vec3 Xyz() const { return vec3(x, y, z); }
[[nodiscard]] vec3 Rgb() const { return vec3(r, g, b); }
vec4& operator=(const vec4& v) = default;
vec4& operator=(vec4&& v) noexcept = default;
vec4& operator+=(float s);
vec4& operator+=(const vec4& v);
vec4& operator-=(float s);
vec4& operator-=(const vec4& v);
vec4& operator*=(float s);
vec4& operator*=(const vec4& v);
vec4& operator/=(float s);
vec4& operator/=(const vec4& v);
vec4 operator-() const;
friend vec4 operator+(const vec4& v, float s);
friend vec4 operator+(float s, const vec4& v);
friend vec4 operator+(const vec4& v1, const vec4& v2);
friend vec4 operator-(const vec4& v, float s);
friend vec4 operator-(float s, const vec4& v);
friend vec4 operator-(const vec4& v1, const vec4& v2);
friend vec4 operator*(const vec4& v, float s);
friend vec4 operator*(float s, const vec4& v);
friend vec4 operator*(const vec4& v1, const vec4& v2);
friend vec4 operator/(const vec4& v, float s);
friend vec4 operator/(float s, const vec4& v);
friend vec4 operator/(const vec4& v1, const vec4& v2);
friend bool operator==(const vec4& v1, const vec4& v2);
friend bool operator!=(const vec4& v1, const vec4& v2);
union
{
struct
{
union
{
float x;
float r;
};
union
{
float y, g;
};
union
{
float z, b;
};
union
{
float w, a;
};
};
float data[4];
};
};
class mat3;
class mat4;
// NOLINTNEXTLINE(readability-identifier-naming)
class mat2 final
{
public:
mat2() noexcept = default;
mat2(const mat2& m) noexcept = default;
mat2(mat2&& m) noexcept = default;
~mat2() = default;
explicit mat2(const mat3& m) noexcept;
explicit mat2(const mat4& m) noexcept;
explicit mat2(float x) noexcept;
explicit mat2(float x1, float y1, float x2, float y2) noexcept;
explicit mat2(const vec2& v1, const vec2& v2) noexcept;
vec2& operator[](int i);
const vec2& operator[](int i) const;
mat2& operator=(const mat2& m) = default;
mat2& operator=(mat2&& m) noexcept = default;
mat2& operator+=(float s);
mat2& operator+=(const mat2& m);
mat2& operator-=(float s);
mat2& operator-=(const mat2& m);
mat2& operator*=(float s);
mat2& operator*=(const mat2& m);
mat2& operator/=(float s);
friend mat2 operator+(const mat2& m, float s);
friend mat2 operator+(float s, const mat2& m);
friend mat2 operator+(const mat2& m1, const mat2& m2);
friend mat2 operator-(const mat2& m, float s);
friend mat2 operator-(float s, const mat2& m);
friend mat2 operator-(const mat2& m1, const mat2& m2);
friend mat2 operator*(const mat2& m, float s);
friend mat2 operator*(float s, const mat2& m);
friend mat2 operator*(const mat2& m1, const mat2& m2);
friend vec2 operator*(const mat2& m, const vec2& v);
friend vec2 operator*(const vec2& v, const mat2& m);
friend mat2 operator/(const mat2& m, float s);
friend mat2 operator/(float s, const mat2& m);
friend bool operator==(const mat2& m1, const mat2& m2);
friend bool operator!=(const mat2& m1, const mat2& m2);
vec2 data[2];
};
// NOLINTNEXTLINE(readability-identifier-naming)
class mat3 final
{
public:
mat3() noexcept = default;
~mat3() = default;
mat3(const mat3& m) noexcept = default;
mat3(mat3&& m) noexcept = default;
explicit mat3(const mat4& m) noexcept;
explicit mat3(float x) noexcept;
explicit mat3(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) noexcept;
explicit mat3(const vec3& v1, const vec3& v2, const vec3& v3) noexcept;
vec3& operator[](int i);
const vec3& operator[](int i) const;
mat3& operator=(const mat3& m) = default;
mat3& operator=(mat3&& m) noexcept = default;
mat3& operator+=(float s);
mat3& operator+=(const mat3& m);
mat3& operator-=(float s);
mat3& operator-=(const mat3& m);
mat3& operator*=(float s);
mat3& operator*=(const mat3& m);
mat3& operator/=(float s);
friend mat3 operator+(const mat3& m, float s);
friend mat3 operator+(float s, const mat3& m);
friend mat3 operator+(const mat3& m1, const mat3& m2);
friend mat3 operator-(const mat3& m, float s);
friend mat3 operator-(float s, const mat3& m);
friend mat3 operator-(const mat3& m1, const mat3& m2);
friend mat3 operator*(const mat3& m, float s);
friend mat3 operator*(float s, const mat3& m);
friend mat3 operator*(const mat3& m1, const mat3& m2);
friend vec3 operator*(const mat3& m, const vec3& v);
friend vec3 operator*(const vec3& v, const mat3& m);
friend mat3 operator/(const mat3& m, float s);
friend mat3 operator/(float s, const mat3& m);
friend bool operator==(const mat3& m1, const mat3& m2);
friend bool operator!=(const mat3& m1, const mat3& m2);
vec3 data[3];
};
// NOLINTNEXTLINE(readability-identifier-naming)
class mat4 final
{
public:
mat4() noexcept = default;
~mat4() = default;
mat4(const mat4& m) noexcept = default;
mat4(mat4&& m) noexcept = default;
explicit mat4(float x) noexcept;
explicit mat4(float x1, float y1, float z1, float w1, float x2, float y2, float z2, float w2, float x3, float y3, float z3, float w3,
float x4, float y4, float z4, float w4) noexcept;
explicit mat4(const vec4& v1, const vec4& v2, const vec4& v3, const vec4& v4) noexcept;
vec4& operator[](int i);
const vec4& operator[](int i) const;
mat4& operator=(const mat4& m) = default;
mat4& operator=(mat4&& m) noexcept = default;
mat4& operator+=(float s);
mat4& operator+=(const mat4& m);
mat4& operator-=(float s);
mat4& operator-=(const mat4& m);
mat4& operator*=(float s);
mat4& operator*=(const mat4& m);
mat4& operator/=(float s);
friend mat4 operator+(const mat4& m, float s);
friend mat4 operator+(float s, const mat4& m);
friend mat4 operator+(const mat4& m1, const mat4& m2);
friend mat4 operator-(const mat4& m, float s);
friend mat4 operator-(float s, const mat4& m);
friend mat4 operator-(const mat4& m1, const mat4& m2);
friend mat4 operator*(const mat4& m, float s);
friend mat4 operator*(float s, const mat4& m);
friend mat4 operator*(const mat4& m1, const mat4& m2);
friend vec4 operator*(const mat4& m, const vec4& v);
friend vec4 operator*(const vec4& v, const mat4& m);
friend mat4 operator/(const mat4& m, float s);
friend mat4 operator/(float s, const mat4& m);
friend bool operator==(const mat4& m1, const mat4& m2);
friend bool operator!=(const mat4& m1, const mat4& m2);
vec4 data[4];
};
inline float* value_ptr(vec2& v) // NOLINT(google-runtime-references)
{
return &v.x;
}
inline float* value_ptr(vec3& v) // NOLINT(google-runtime-references)
{
return &v.x;
}
inline float* value_ptr(vec4& v) // NOLINT(google-runtime-references)
{
return &v.x;
}
inline float* value_ptr(mat2& v) // NOLINT(google-runtime-references)
{
return &v.data[0].x;
}
inline float* value_ptr(mat3& v) // NOLINT(google-runtime-references)
{
return &v.data[0].x;
}
inline float* value_ptr(mat4& v) // NOLINT(google-runtime-references)
{
return &v.data[0].x;
}
inline const float* value_ptr(const vec2& v)
{
return &v.x;
}
inline const float* value_ptr(const vec3& v)
{
return &v.x;
}
inline const float* value_ptr(const vec4& v)
{
return &v.x;
}
inline const float* value_ptr(const mat2& v)
{
return &v.data[0].x;
}
inline const float* value_ptr(const mat3& v)
{
return &v.data[0].x;
}
inline const float* value_ptr(const mat4& v)
{
return &v.data[0].x;
}
inline float round(float n)
{
if (n < 0.0f)
{
return ceilf(n - 0.5f);
}
return floorf(n + 0.5f);
}
inline vec2 round(const vec2& v)
{
return vec2(round(v.x), round(v.y));
}
inline vec3 round(const vec3& v)
{
return vec3(round(v.x), round(v.y), round(v.z));
}
inline vec4 round(const vec4& v)
{
return vec4(round(v.x), round(v.y), round(v.z), round(v.w));
}
inline float abs(float n)
{
return fabsf(n);
}
inline vec2 abs(const vec2& v)
{
return vec2(abs(v.x), abs(v.y));
}
inline vec3 abs(const vec3& v)
{
return vec3(abs(v.x), abs(v.y), abs(v.z));
}
inline vec4 abs(const vec4& v)
{
return vec4(abs(v.x), abs(v.y), abs(v.z), abs(v.w));
}
inline vec2 normalize(const vec2& v)
{
return v / sqrtf(v.x * v.x + v.y * v.y);
}
inline vec3 normalize(const vec3& v)
{
return v / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}
inline vec4 normalize(const vec4& v)
{
return v / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
}
inline float dot(const vec2& v1, const vec2& v2)
{
return v1.x * v2.x + v1.y * v2.y;
}
inline float dot(const vec3& v1, const vec3& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
inline float dot(const vec4& v1, const vec4& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
}
inline vec3 cross(const vec3& x, const vec3& y)
{
return vec3(x.y * y.z - y.y * x.z, x.z * y.x - y.z * x.x, x.x * y.y - y.x * x.y);
}
inline mat4 rotate(float a, const vec3& v)
{
float c = cosf(a);
float s = sinf(a);
float t = 1.0f - c;
vec3 u = normalize(v);
float tx = t * u.x;
float ty = t * u.y;
float tz = t * u.z;
float sx = s * u.x;
float sy = s * u.y;
float sz = s * u.z;
float m1 = c + u.x * tx;
float m2 = u.y * tx - sz;
float m3 = u.z * tx + sy;
float m4 = u.y * tx + sz;
float m5 = c + u.y * ty;
float m6 = u.y * tz - sx;
float m7 = u.z * tx - sy;
float m8 = u.z * ty + sx;
float m9 = c + u.z * tz;
return mat4(m1, m4, m7, 0, m2, m5, m8, 0, m3, m6, m9, 0, 0, 0, 0, 1);
}
inline mat4 lookAt(const vec3& eye, const vec3& center, const vec3& up)
{
vec3 f(normalize(center - eye));
vec3 s(normalize(cross(f, up)));
vec3 u(cross(s, f));
mat4 r {};
r.data[0].x = s.x;
r.data[0].y = u.x;
r.data[0].z = -f.x;
r.data[0].w = 0.0f;
r.data[1].x = s.y;
r.data[1].y = u.y;
r.data[1].z = -f.y;
r.data[1].w = 0.0f;
r.data[2].x = s.z;
r.data[2].y = u.z;
r.data[2].z = -f.z;
r.data[2].w = 0.0f;
r.data[3].x = -dot(s, eye);
r.data[3].y = -dot(u, eye);
r.data[3].z = dot(f, eye);
r.data[3].w = 1.0f;
return r;
}
inline mat4 perspective(float fovy, float aspect, float z_near, float z_far)
{
float t = tanf(fovy / 2.0f);
mat4 r {};
r.data[0].x = 1.0f / (aspect * t);
r.data[0].y = 0.0f;
r.data[0].z = 0.0f;
r.data[0].w = 0.0f;
r.data[1].x = 0.0f;
r.data[1].y = 1.0f / (t);
r.data[1].z = 0.0f;
r.data[1].w = 0.0f;
r.data[2].x = 0.0f;
r.data[2].y = 0.0f;
r.data[2].z = -(z_far + z_near) / (z_far - z_near);
r.data[2].w = -1.0f;
r.data[3].x = 0.0f;
r.data[3].y = 0.0f;
r.data[3].z = -(2.0f * z_far * z_near) / (z_far - z_near);
r.data[3].w = 0.0f;
return r;
}
inline mat4 ortho(float left, float right, float bottom, float top, float z_near, float z_far)
{
mat4 r {};
r.data[0].x = 2.0f / (right - left);
r.data[0].y = 0.0f;
r.data[0].z = 0.0f;
r.data[0].w = 0.0f;
r.data[1].x = 0.0f;
r.data[1].y = 2.0f / (top - bottom);
r.data[1].z = 0.0f;
r.data[1].w = 0.0f;
r.data[2].x = 0.0f;
r.data[2].y = 0.0f;
r.data[2].z = -2.0f / (z_far - z_near);
r.data[2].w = 0.0f;
r.data[3].x = -(right + left) / (right - left);
r.data[3].y = -(top + bottom) / (top - bottom);
r.data[3].z = -(z_far + z_near) / (z_far - z_near);
r.data[3].w = 1.0f;
return r;
}
inline float determinant(const mat2& m)
{
return m.data[0].x * m.data[1].y - m.data[0].y * m.data[1].x;
}
inline float determinant(const mat3& m)
{
return m.data[0].x * determinant(mat2(m.data[1].y, m.data[1].z, m.data[2].y, m.data[2].z)) -
m.data[0].y * determinant(mat2(m.data[1].x, m.data[1].z, m.data[2].x, m.data[2].z)) +
m.data[0].z * determinant(mat2(m.data[1].x, m.data[1].y, m.data[2].x, m.data[2].y));
}
inline float determinant(const mat4& m)
{
return m.data[0].x * determinant(mat3(m.data[1].y, m.data[1].z, m.data[1].w, m.data[2].y, m.data[2].z, m.data[2].w, m.data[3].y,
m.data[3].z, m.data[3].w)) -
m.data[0].y * determinant(mat3(m.data[1].x, m.data[1].z, m.data[1].w, m.data[2].x, m.data[2].z, m.data[2].w, m.data[3].x,
m.data[3].z, m.data[3].w)) +
m.data[0].z * determinant(mat3(m.data[1].x, m.data[1].y, m.data[1].w, m.data[2].x, m.data[2].y, m.data[2].w, m.data[3].x,
m.data[3].y, m.data[3].w)) -
m.data[0].w * determinant(mat3(m.data[1].x, m.data[1].y, m.data[1].z, m.data[2].x, m.data[2].y, m.data[2].z, m.data[3].x,
m.data[3].y, m.data[3].z));
}
inline mat2 inverseTranspose(const mat2& m)
{
float x1 = m.data[1].y;
float y1 = m.data[1].x;
float x2 = m.data[0].y;
float y2 = m.data[0].x;
return mat2(x1, -y1, -x2, y2) / determinant(m);
}
inline mat3 inverseTranspose(const mat3& m)
{
float x1 = determinant(mat2(m.data[1].y, m.data[1].z, m.data[2].y, m.data[2].z));
float y1 = determinant(mat2(m.data[1].x, m.data[1].z, m.data[2].x, m.data[2].z));
float z1 = determinant(mat2(m.data[1].x, m.data[1].y, m.data[2].x, m.data[2].y));
float x2 = determinant(mat2(m.data[0].y, m.data[0].z, m.data[2].y, m.data[2].z));
float y2 = determinant(mat2(m.data[0].x, m.data[0].z, m.data[2].x, m.data[2].z));
float z2 = determinant(mat2(m.data[0].x, m.data[0].y, m.data[2].x, m.data[2].y));
float x3 = determinant(mat2(m.data[0].y, m.data[0].z, m.data[1].y, m.data[1].z));
float y3 = determinant(mat2(m.data[0].x, m.data[0].z, m.data[1].x, m.data[1].z));
float z3 = determinant(mat2(m.data[0].x, m.data[0].y, m.data[1].x, m.data[1].y));
return mat3(x1, -y1, z1, -x2, y2, -z2, x3, -y3, z3) / determinant(m);
}
inline mat4 inverseTranspose(const mat4& m)
{
float x1 = determinant(
mat3(m.data[1].y, m.data[1].z, m.data[1].w, m.data[2].y, m.data[2].z, m.data[2].w, m.data[3].y, m.data[3].z, m.data[3].w));
float y1 = determinant(
mat3(m.data[1].x, m.data[1].z, m.data[1].w, m.data[2].x, m.data[2].z, m.data[2].w, m.data[3].x, m.data[3].z, m.data[3].w));
float z1 = determinant(
mat3(m.data[1].x, m.data[1].y, m.data[1].w, m.data[2].x, m.data[2].y, m.data[2].w, m.data[3].x, m.data[3].y, m.data[3].w));
float w1 = determinant(
mat3(m.data[1].x, m.data[1].y, m.data[1].z, m.data[2].x, m.data[2].y, m.data[2].z, m.data[3].x, m.data[3].y, m.data[3].z));
float x2 = determinant(
mat3(m.data[0].y, m.data[0].z, m.data[0].w, m.data[2].y, m.data[2].z, m.data[2].w, m.data[3].y, m.data[3].z, m.data[3].w));
float y2 = determinant(
mat3(m.data[0].x, m.data[0].z, m.data[0].w, m.data[2].x, m.data[2].z, m.data[2].w, m.data[3].x, m.data[3].z, m.data[3].w));
float z2 = determinant(
mat3(m.data[0].x, m.data[0].y, m.data[0].w, m.data[2].x, m.data[2].y, m.data[2].w, m.data[3].x, m.data[3].y, m.data[3].w));
float w2 = determinant(
mat3(m.data[0].x, m.data[0].y, m.data[0].z, m.data[2].x, m.data[2].y, m.data[2].z, m.data[3].x, m.data[3].y, m.data[3].z));
float x3 = determinant(
mat3(m.data[0].y, m.data[0].z, m.data[0].w, m.data[1].y, m.data[1].z, m.data[1].w, m.data[3].y, m.data[3].z, m.data[3].w));
float y3 = determinant(
mat3(m.data[0].x, m.data[0].z, m.data[0].w, m.data[1].x, m.data[1].z, m.data[1].w, m.data[3].x, m.data[3].z, m.data[3].w));
float z3 = determinant(
mat3(m.data[0].x, m.data[0].y, m.data[0].w, m.data[1].x, m.data[1].y, m.data[1].w, m.data[3].x, m.data[3].y, m.data[3].w));
float w3 = determinant(
mat3(m.data[0].x, m.data[0].y, m.data[0].z, m.data[1].x, m.data[1].y, m.data[1].z, m.data[3].x, m.data[3].y, m.data[3].z));
float x4 = determinant(
mat3(m.data[0].y, m.data[0].z, m.data[0].w, m.data[1].y, m.data[1].z, m.data[1].w, m.data[2].y, m.data[2].z, m.data[2].w));
float y4 = determinant(
mat3(m.data[0].x, m.data[0].z, m.data[0].w, m.data[1].x, m.data[1].z, m.data[1].w, m.data[2].x, m.data[2].z, m.data[2].w));
float z4 = determinant(
mat3(m.data[0].x, m.data[0].y, m.data[0].w, m.data[1].x, m.data[1].y, m.data[1].w, m.data[2].x, m.data[2].y, m.data[2].w));
float w4 = determinant(
mat3(m.data[0].x, m.data[0].y, m.data[0].z, m.data[1].x, m.data[1].y, m.data[1].z, m.data[2].x, m.data[2].y, m.data[2].z));
return mat4(x1, -y1, z1, -w1, -x2, y2, -z2, w2, x3, -y3, z3, -w3, -x4, y4, -z4, w4) / determinant(m);
}
inline mat2 transpose(const mat2& m)
{
return mat2(m.data[0].x, m.data[1].x, m.data[0].y, m.data[1].y);
}
inline mat3 transpose(const mat3& m)
{
return mat3(m.data[0].x, m.data[1].x, m.data[2].x, m.data[0].y, m.data[1].y, m.data[2].y, m.data[0].z, m.data[1].z, m.data[2].z);
}
inline mat4 transpose(const mat4& m)
{
return mat4(m.data[0].x, m.data[1].x, m.data[2].x, m.data[3].x, m.data[0].y, m.data[1].y, m.data[2].y, m.data[3].y, m.data[0].z,
m.data[1].z, m.data[2].z, m.data[3].z, m.data[0].w, m.data[1].w, m.data[2].w, m.data[3].w);
}
inline mat2 inverse(const mat2& m)
{
return transpose(inverseTranspose(m));
}
inline mat3 inverse(const mat3& m)
{
return transpose(inverseTranspose(m));
}
inline mat4 inverse(const mat4& m)
{
return transpose(inverseTranspose(m));
}
inline mat2 make_mat2(const float* m)
{
return mat2(m[0], m[1], m[2], m[3]);
}
inline mat3 make_mat3(const float* m)
{
return mat3(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
}
inline mat4 make_mat4(const float* m)
{
return mat4(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
}
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#endif
inline float max(float a, float b)
{
return a > b ? a : b;
}
inline vec2 max(const vec2& a, const vec2& b)
{
return vec2(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y);
}
inline vec3 max(const vec3& a, const vec3& b)
{
return vec3(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z);
}
inline vec4 max(const vec4& a, const vec4& b)
{
return vec4(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z, a.w > b.w ? a.w : b.w);
}
inline vec2 max(const vec2& a, float b)
{
return max(a, vec2(b));
}
inline vec3 max(const vec3& a, float b)
{
return max(a, vec3(b));
}
inline vec4 max(const vec4& a, float b)
{
return max(a, vec4(b));
}
inline float min(float a, float b)
{
return a < b ? a : b;
}
inline vec2 min(const vec2& a, const vec2& b)
{
return vec2(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y);
}
inline vec3 min(const vec3& a, const vec3& b)
{
return vec3(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z);
}
inline vec4 min(const vec4& a, const vec4& b)
{
return vec4(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z, a.w < b.w ? a.w : b.w);
}
inline vec2 min(const vec2& a, float b)
{
return min(a, vec2(b));
}
inline vec3 min(const vec3& a, float b)
{
return min(a, vec3(b));
}
inline vec4 min(const vec4& a, float b)
{
return min(a, vec4(b));
}
inline float clamp(float x, float min_val, float max_val)
{
return min(max(x, min_val), max_val);
}
inline vec2 clamp(const vec2& x, float min_val, float max_val)
{
return min(max(x, min_val), max_val);
}
inline vec3 clamp(const vec3& x, float min_val, float max_val)
{
return min(max(x, min_val), max_val);
}
inline vec4 clamp(const vec4& x, float min_val, float max_val)
{
return min(max(x, min_val), max_val);
}
inline float radians(float degrees)
{
return degrees * (0.01745329251994329576923690768489f);
}
} // namespace Kyty::Math::m
#define VEC2_DECL inline /*NOLINT(cppcoreguidelines-macro-usage)*/
#define VEC3_DECL inline /*NOLINT(cppcoreguidelines-macro-usage)*/
#define VEC4_DECL inline /*NOLINT(cppcoreguidelines-macro-usage)*/
#define MAT2_DECL inline /*NOLINT(cppcoreguidelines-macro-usage)*/
#define MAT3_DECL inline /*NOLINT(cppcoreguidelines-macro-usage)*/
#define MAT4_DECL inline /*NOLINT(cppcoreguidelines-macro-usage)*/
// IWYU pragma: begin_exports
#include "Kyty/Math/Mat2Impl.h"
#include "Kyty/Math/Mat3Impl.h"
#include "Kyty/Math/Mat4Impl.h"
#include "Kyty/Math/Vec2Impl.h"
#include "Kyty/Math/Vec3Impl.h"
#include "Kyty/Math/Vec4Impl.h"
// IWYU pragma: end_exports
#endif /* INCLUDE_KYTY_MATH_VECTORANDMATRIX_H_ */
+12
View File
@@ -0,0 +1,12 @@
#ifndef INCLUDE_KYTY_SCRIPTS_BUILDTOOLS_H_
#define INCLUDE_KYTY_SCRIPTS_BUILDTOOLS_H_
#include "Kyty/Core/Subsystems.h"
namespace Kyty::BuildTools {
KYTY_SUBSYSTEM_DEFINE(BuildTools);
} // namespace Kyty::BuildTools
#endif /* INCLUDE_KYTY_SCRIPTS_BUILDTOOLS_H_ */
+24
View File
@@ -0,0 +1,24 @@
#ifndef INCLUDE_KYTY_SCRIPTS_LUACPP_H_
#define INCLUDE_KYTY_SCRIPTS_LUACPP_H_
#include "Kyty/Core/Common.h"
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
//#define LUA_BUILD_AS_DLL
//#define LUA_USE_WINDOWS
#else
#define LUA_USE_LINUX
#endif
// IWYU pragma: begin_exports
extern "C" {
#include "lua.h"
//
#include "lualib.h"
//
#include "lauxlib.h"
//
}
// IWYU pragma: end_exports
#endif /* INCLUDE_KYTY_SCRIPTS_LUACPP_H_ */
+220
View File
@@ -0,0 +1,220 @@
#ifndef INCLUDE_KYTY_SCRIPTS_SCRIPTS_H_
#define INCLUDE_KYTY_SCRIPTS_SCRIPTS_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Subsystems.h"
#include "Kyty/Core/Vector.h"
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
//#include <string.h>
#endif
#define KYTY_LUA_5_2 1
#define KYTY_LUA_5_3 2
#define KYTY_LUA_VER KYTY_LUA_5_2
namespace Kyty::Scripts {
using LuaState = void;
KYTY_SUBSYSTEM_DEFINE(Scripts);
enum class ScriptError
{
Ok,
SyntaxError,
FileError,
RunError,
UnknownError
};
using script_func_t = int (*)(LuaState*);
using help_func_t = void (*)();
#define KYTY_SCRIPT_NAME(name) name([[maybe_unused]] Kyty::Scripts::LuaState* LS)
//#define STATIC_SCRIPT_FUNC(name) static int SCRIPT_NAME(name)
#define KYTY_SCRIPT_FUNC(name) int KYTY_SCRIPT_NAME(name)
#define KYTY_STATIC_SCRIPT_FUNC(name) \
static int name##_private([[maybe_unused]] Kyty::Scripts::LuaState* LS, [[maybe_unused]] Scripts::ScriptFuncResult* script_result); \
static int name(Kyty::Scripts::LuaState* LS) \
{ \
Scripts::ScriptFuncResult script_result; \
int r = name##_private(LS, &script_result); \
script_result.ThrowError(); \
return r; \
} \
static int name##_private([[maybe_unused]] Kyty::Scripts::LuaState* LS, [[maybe_unused]] Scripts::ScriptFuncResult* script_result)
ScriptError RunFile(const String& file_name);
ScriptError RunString(const String& source);
const String& GetErrMsg();
void SetErrMsg(const String& msg);
void ResetErrMsg();
void PushString(const String& str);
void PushDouble(double d);
#if KYTY_LUA_VER == KYTY_LUA_5_3
void PushInteger(int64_t i);
#else
void PushInteger(int32_t i);
#endif
void RegisterFunc(const char* name, script_func_t func, help_func_t help);
void RegisterSystemFunc(const char* name, script_func_t func);
void UnregisterFunc(const char* name);
int ArgGetVarCount();
void ArgDbgDump();
void PrintHelp();
class ScriptVar;
class ScriptPair final
{
public:
ScriptPair(const ScriptVar& key, const ScriptVar& value);
~ScriptPair();
ScriptPair(const ScriptPair& src);
ScriptPair& operator=(const ScriptPair&) = delete;
ScriptPair(ScriptPair&&) noexcept = delete;
ScriptPair& operator=(ScriptPair&&) noexcept = delete;
[[nodiscard]] const ScriptVar& GetKey() const { return *m_key; }
[[nodiscard]] const ScriptVar& GetValue() const { return *m_value; }
private:
ScriptVar* m_key;
ScriptVar* m_value;
};
class ScriptTable final
{
public:
using List = Vector<ScriptPair>;
void Add(const ScriptVar& k, const ScriptVar& v);
void DbgPrint(int depth) const;
#if KYTY_LUA_VER == KYTY_LUA_5_3
ScriptVar At(int64_t m_key) const;
#endif
[[nodiscard]] ScriptVar At(const String& key) const;
[[nodiscard]] ScriptVar At(double key) const;
[[nodiscard]] uint32_t Count() const { return m_pairs.Size(); }
[[nodiscard]] ScriptVar GetKey(uint32_t index) const;
[[nodiscard]] ScriptVar GetValue(uint32_t index) const;
[[nodiscard]] const List& GetList() const { return m_pairs; }
private:
List m_pairs;
};
class ScriptFunction final
{
public:
void LoadFromStack();
[[nodiscard]] String ToDbgString() const;
private:
static int LuaWriter(LuaState* ls, const void* p, size_t sz, void* ud);
Vector<uint8_t> m_dump;
};
class ScriptVar
{
public:
ScriptVar();
virtual ~ScriptVar();
ScriptVar(const ScriptVar& src);
ScriptVar(ScriptVar&& src) noexcept;
ScriptVar& operator=(const ScriptVar& src);
ScriptVar& operator=(ScriptVar&& src) noexcept;
void DbgPrint(int depth) const;
static ScriptVar ReadVar(int index, bool with_metatable_index);
[[nodiscard]] bool IsTable() const;
[[nodiscard]] bool IsNil() const;
[[nodiscard]] bool IsFunction() const;
[[nodiscard]] bool IsCFunction() const;
[[nodiscard]] bool IsDouble() const;
#if KYTY_LUA_VER == KYTY_LUA_5_3
bool IsInteger() const;
#else
[[nodiscard]] bool IsInteger() const;
#endif
[[nodiscard]] bool IsString() const;
[[nodiscard]] bool IsUserdata() const;
#if KYTY_LUA_VER == KYTY_LUA_5_3
int64_t ToInteger() const;
#else
[[nodiscard]] int32_t ToInteger() const;
#endif
[[nodiscard]] double ToDouble() const;
[[nodiscard]] float ToFloat() const;
[[nodiscard]] bool ToBool() const;
[[nodiscard]] String ToString() const;
[[nodiscard]] void* ToUserdata() const;
[[nodiscard]] const ScriptTable& ToTable() const;
[[nodiscard]] const ScriptTable::List& GetPairs() const;
[[nodiscard]] ScriptVar At(int64_t key) const;
[[nodiscard]] ScriptVar At(const String& key) const;
[[nodiscard]] ScriptVar At(const char* key) const;
[[nodiscard]] ScriptVar At(double key) const;
[[nodiscard]] uint32_t Count() const;
[[nodiscard]] uint32_t Size() const;
[[nodiscard]] ScriptVar GetKey(uint32_t index) const;
[[nodiscard]] ScriptVar GetValue(uint32_t index) const;
private:
class ScriptVarPrivate;
ScriptVarPrivate* m_p = {nullptr};
};
ScriptVar GlobalGetVar(const String& var_name);
ScriptVar GlobalGetVarWithParent(const String& var_name);
ScriptVar ArgGetVar(int index);
ScriptVar ArgGetVarWithParent(int index);
constexpr size_t SCRIPT_FUNC_ERR_SIZE = 1024;
class ScriptFuncResult
{
public:
ScriptFuncResult() = default;
void SetError(const String& msg);
void ThrowError();
private:
bool m_ok = {true};
char m_msg[SCRIPT_FUNC_ERR_SIZE + 1] = {0};
};
#define KYTY_SCRIPT_FUNC_BEGIN() [[maybe_unused]] auto* L = static_cast<struct lua_State*>(LS);
#define KYTY_SCRIPT_THROW_ERROR(msg) \
{ \
script_result->SetError(msg); \
return 0; \
}
} // namespace Kyty::Scripts
#endif /* INCLUDE_KYTY_SCRIPTS_SCRIPTS_H_ */
@@ -0,0 +1,15 @@
#ifndef INCLUDE_KYTY_SCRIPTS_SCRIPTSLOADER_H_
#define INCLUDE_KYTY_SCRIPTS_SCRIPTSLOADER_H_
#include "Kyty/Core/String.h"
namespace Kyty::Scripts {
void SetLoadError(const String& err);
String GetLoadError();
void ResetLoadError();
bool RunScript(const String& lua_file_name);
} // namespace Kyty::Scripts
#endif /* INCLUDE_KYTY_SCRIPTS_SCRIPTSLOADER_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSDBG_H_
#define INCLUDE_KYTY_SYS_SYSDBG_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxDbg.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsDbg.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSDBG_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSFILEIO_H_
#define INCLUDE_KYTY_SYS_SYSFILEIO_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxFileIO.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsFileIO.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSFILEIO_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSHEAP_H_
#define INCLUDE_KYTY_SYS_SYSHEAP_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxHeap.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsHeap.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSHEAP_H_ */
+34
View File
@@ -0,0 +1,34 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSDBG_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSDBG_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
namespace Kyty {
struct sys_dbg_stack_info_t
{
uintptr_t code_addr;
uintptr_t addr;
uintptr_t commited_addr;
size_t commited_size;
size_t total_size;
size_t code_size;
};
using exception_filter_func_t = void (*)(void* addr);
void sys_stack_walk(void** stack, int* depth);
void sys_stack_usage(sys_dbg_stack_info_t& s);
void sys_stack_usage_print(sys_dbg_stack_info_t& stack);
void sys_get_code_info(uintptr_t* addr, size_t* size);
void sys_set_exception_filter(exception_filter_func_t func);
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSDBG_H_ */
+104
View File
@@ -0,0 +1,104 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSFILEIO_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSFILEIO_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include "Kyty/Core/String.h"
#include "Kyty/Sys/SysLinuxTimer.h"
namespace Kyty {
enum sys_file_type_t
{
SYS_FILE_ERROR,
SYS_FILE_MEMORY_STAT,
SYS_FILE_FILE,
SYS_FILE_MEMORY_DYN
};
enum sys_file_cache_type_t
{
SYS_FILE_CACHE_AUTO = 0,
SYS_FILE_CACHE_RANDOM_ACCESS = 1,
SYS_FILE_CACHE_SEQUENTIAL_SCAN = 2
};
struct sys_file_mem_buf_t
{
uint8_t* base;
uint8_t* ptr;
uint32_t size;
};
struct sys_file_t
{
sys_file_type_t type;
union
{
FILE* f;
sys_file_mem_buf_t* buf;
};
};
struct sys_file_find_t
{
String path_with_name;
SysFileTimeStruct last_access_time;
SysFileTimeStruct last_write_time;
uint64_t size;
};
struct sys_dir_entry_t
{
String name;
bool is_file;
};
void sys_file_read(void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_read = 0);
void sys_file_write(const void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_written = 0);
void sys_file_read_r(void* data, uint32_t size, sys_file_t& f);
void sys_file_write_r(const void* data, uint32_t size, sys_file_t& f);
sys_file_t* sys_file_create(const String& file_name);
sys_file_t* sys_file_open_r(const String& file_name, sys_file_cache_type_t cache_type = SYS_FILE_CACHE_AUTO);
sys_file_t* sys_file_open_w(const String& file_name, sys_file_cache_type_t cache_type = SYS_FILE_CACHE_AUTO);
sys_file_t* sys_file_open(uint8_t* buf, uint32_t buf_size);
sys_file_t* sys_file_create();
sys_file_t* sys_file_open_rw(const String& file_name, sys_file_cache_type_t cache_type = SYS_FILE_CACHE_AUTO);
void sys_file_close(sys_file_t* f);
uint64_t sys_file_size(sys_file_t& f);
bool sys_file_seek(sys_file_t& f, uint64_t offset);
uint64_t sys_file_tell(sys_file_t& f);
bool sys_file_truncate(sys_file_t& f, uint64_t size);
void sys_file_write(uint32_t n, sys_file_t& f);
void sys_file_write_r(uint32_t n, sys_file_t& f);
uint64_t sys_file_size(const String& file_name);
bool sys_file_is_error(sys_file_t& f);
bool sys_file_io_init();
bool sys_file_is_directory_existing(const String& path);
bool sys_file_is_file_existing(const String& name);
bool sys_file_create_directory(const String& path);
bool sys_file_delete_directory(const String& path);
bool sys_file_delete_file(const String& name);
bool sys_file_flush(sys_file_t& f);
SysFileTimeStruct sys_file_get_last_access_time_utc(const String& name);
SysFileTimeStruct sys_file_get_last_write_time_utc(const String& name);
void sys_file_get_last_access_and_write_time_utc(const String& name, SysFileTimeStruct& a, SysFileTimeStruct& w);
void sys_file_get_last_access_and_write_time_utc(sys_file_t& f, SysFileTimeStruct& a, SysFileTimeStruct& w);
bool sys_file_set_last_access_time_utc(const String& name, SysFileTimeStruct& access);
bool sys_file_set_last_write_time_utc(const String& name, SysFileTimeStruct& write);
bool sys_file_set_last_access_and_write_time_utc(const String& name, SysFileTimeStruct& access, SysFileTimeStruct& write);
void sys_file_find_files(const String& path, Kyty::Vector<sys_file_find_t>& out);
void sys_file_get_dents(const String& path, Kyty::Vector<sys_dir_entry_t>& out);
bool sys_file_copy_file(const String& src, const String& dst);
bool sys_file_move_file(const String& src, const String& dst);
void sys_file_remove_readonly(const String& name);
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSFILEIO_H_ */
+98
View File
@@ -0,0 +1,98 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include "Kyty/Sys/SysLinuxSync.h"
namespace Kyty {
typedef SysCS* sys_heap_id_t;
inline sys_heap_id_t sys_heap_create()
{
return 0;
}
inline sys_heap_id_t sys_heap_deafult()
{
return 0;
}
inline void* sys_heap_alloc(sys_heap_id_t heap_id, size_t size)
{
void* m = malloc(size);
EXIT_IF(m == 0);
return m;
}
inline void* sys_heap_realloc(sys_heap_id_t heap_id, void* p, size_t size)
{
void* m = p ? realloc(p, size) : malloc(size);
if (m == 0)
{
EXIT_IF(m == 0);
}
return m;
}
inline void sys_heap_free(sys_heap_id_t heap_id, void* p)
{
free(p);
}
inline sys_heap_id_t sys_heap_create_s()
{
SysCS* cs = new SysCS;
cs->Init();
return cs;
}
inline void* sys_heap_alloc_s(sys_heap_id_t heap_id, size_t size)
{
heap_id->Enter();
void* m = malloc(size);
heap_id->Leave();
EXIT_IF(m == 0);
return m;
}
inline void* sys_heap_realloc_s(sys_heap_id_t heap_id, void* p, size_t size)
{
heap_id->Enter();
void* m = p ? realloc(p, size) : malloc(size);
heap_id->Leave();
EXIT_IF(m == 0);
return m;
}
inline void sys_heap_free_s(sys_heap_id_t heap_id, void* p)
{
heap_id->Enter();
free(p);
heap_id->Leave();
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSHEAP_H_ */
+34
View File
@@ -0,0 +1,34 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSSTDIO_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSSTDIO_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
//#include <stdio.h>
namespace Kyty {
inline uint32_t sys_vscprintf(const char* format, va_list argptr)
{
int len;
va_list argcopy;
va_copy(argcopy, argptr);
len = vsnprintf(0, 0, format, argcopy);
va_end(argcopy);
return len < 0 ? 0 : len;
}
inline uint32_t sys_vsnprintf(char* Dest, size_t Count, const char* Format, va_list Args)
{
int len = vsnprintf(Dest, Count + 1, Format, Args);
return len < 0 ? 0 : len;
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSSTDIO_H_ */
+55
View File
@@ -0,0 +1,55 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSSTDLIB_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSSTDLIB_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
namespace Kyty {
inline float sys_strtof(const char* nptr, char** endptr)
{
return strtof(nptr, endptr);
}
inline double sys_strtod(const char* nptr, char** endptr)
{
return strtod(nptr, endptr);
}
inline int32_t sys_strtoi32(const char* nptr, char** endptr, int base)
{
long r = strtol(nptr, endptr, base);
if (r >= static_cast<long>(INT32_MAX))
{
return INT32_MAX;
}
if (r <= static_cast<long>(INT32_MIN))
{
return INT32_MIN;
}
return static_cast<int32_t>(r);
}
inline uint32_t sys_strtoui32(const char* nptr, char** endptr, int base)
{
return strtoul(nptr, endptr, base);
}
inline int64_t sys_strtoi64(const char* nptr, char** endptr, int base)
{
return strtoll(nptr, endptr, base);
}
inline uint64_t sys_strtoui64(const char* nptr, char** endptr, int base)
{
return strtoull(nptr, endptr, base);
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSSTDLIB_H_ */
+82
View File
@@ -0,0 +1,82 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSSYNC_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSSYNC_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include <pthread.h>
#include <unistd.h>
namespace Kyty {
class SysCS
{
public:
SysCS() { check_ptr = 0; }
void Init()
{
EXIT_IF(check_ptr != 0);
check_ptr = this;
pthread_mutexattr_t attr;
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&m, &attr);
pthread_mutexattr_destroy(&attr);
}
void Delete()
{
EXIT_IF(check_ptr != this);
check_ptr = 0;
pthread_mutex_destroy(&m);
}
~SysCS() { EXIT_IF(check_ptr != 0); }
void Enter()
{
EXIT_IF(check_ptr != this);
pthread_mutex_lock(&m);
}
bool TryEnter()
{
EXIT_IF(check_ptr != this);
return pthread_mutex_trylock(&m) == 0;
}
void Leave()
{
EXIT_IF(check_ptr != this);
pthread_mutex_unlock(&m);
}
KYTY_CLASS_NO_COPY(SysCS);
private:
SysCS* check_ptr;
pthread_mutex_t m;
};
inline void sys_sleep(uint32_t ms)
{
struct timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000;
nanosleep(&ts, 0);
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSSYNC_H_ */
+147
View File
@@ -0,0 +1,147 @@
#ifndef SYS_LINUX_INCLUDE_KYTY_SYSTIMER_H_
#define SYS_LINUX_INCLUDE_KYTY_SYSTIMER_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
//#error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
#else
#include <ctime>
namespace Kyty {
struct SysTimeStruct
{
uint16_t Year;
uint16_t Month;
uint16_t Day;
uint16_t Hour;
uint16_t Minute;
uint16_t Second;
uint16_t Milliseconds;
bool is_invalid;
};
struct SysFileTimeStruct
{
time_t time;
bool is_invalid;
};
inline void sys_file_to_system_time_utc(const SysFileTimeStruct& f, SysTimeStruct& t)
{
struct tm i;
if (f.is_invalid || !gmtime_r(&f.time, &i))
{
t.is_invalid = true;
return;
}
t.is_invalid = false;
t.Year = i.tm_year + 1900;
t.Month = i.tm_mon + 1;
t.Day = i.tm_mday;
t.Hour = i.tm_hour;
t.Minute = i.tm_min;
t.Second = (i.tm_sec == 60 ? 59 : i.tm_sec);
t.Milliseconds = 0;
}
inline void sys_time_t_to_system(time_t t, SysTimeStruct& s)
{
SysFileTimeStruct ft;
ft.time = t;
ft.is_invalid = false;
sys_file_to_system_time_utc(ft, s);
}
inline time_t sys_timegm(struct tm* tm)
{
return timegm(tm);
// time_t t = mktime(tm);
// return t == (time_t)-1 ? (time_t)-1 : t + localtime(&t)->tm_gmtoff;
}
inline void sys_system_to_file_time_utc(const SysTimeStruct& f, SysFileTimeStruct& t)
{
struct tm i;
i.tm_year = f.Year - 1900;
i.tm_mon = f.Month - 1;
i.tm_mday = f.Day;
i.tm_hour = f.Hour;
i.tm_min = f.Minute;
i.tm_sec = f.Second;
if (f.is_invalid || (t.time = sys_timegm(&i)) == (time_t)-1)
{
t.is_invalid = true;
} else
{
t.is_invalid = false;
}
}
// Retrieves the current local date and time
inline void sys_get_system_time(SysTimeStruct& t)
{
time_t st;
struct tm i;
if (time(&st) == (time_t)-1 || !localtime_r(&st, &i))
{
t.is_invalid = true;
return;
}
t.is_invalid = false;
t.Year = i.tm_year + 1900;
t.Month = i.tm_mon + 1;
t.Day = i.tm_mday;
t.Hour = i.tm_hour;
t.Minute = i.tm_min;
t.Second = (i.tm_sec == 60 ? 59 : i.tm_sec);
t.Milliseconds = 0;
}
// Retrieves the current system date and time in Coordinated Universal Time (UTC).
inline void sys_get_system_time_utc(SysTimeStruct& t)
{
time_t st;
struct tm i;
if (time(&st) == (time_t)-1 || !gmtime_r(&st, &i))
{
t.is_invalid = true;
return;
}
t.is_invalid = false;
t.Year = i.tm_year + 1900;
t.Month = i.tm_mon + 1;
t.Day = i.tm_mday;
t.Hour = i.tm_hour;
t.Minute = i.tm_min;
t.Second = (i.tm_sec == 60 ? 59 : i.tm_sec);
t.Milliseconds = 0;
}
inline void sys_query_performance_frequency(uint64_t* freq)
{
*freq = 1000000000LL;
}
inline void sys_query_performance_counter(uint64_t* counter)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
*counter = now.tv_sec * 1000000000LL + now.tv_nsec;
}
} // namespace Kyty
#endif
#endif /* SYS_LINUX_INCLUDE_KYTY_SYSTIMER_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSSTDIO_H_
#define INCLUDE_KYTY_SYS_SYSSTDIO_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxStdio.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsStdio.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSSTDIO_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSSTDLIB_H_
#define INCLUDE_KYTY_SYS_SYSSTDLIB_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxStdlib.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsStdlib.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSSTDLIB_H_ */
@@ -0,0 +1,91 @@
#ifndef INCLUDE_KYTY_SYS_SYSSWAPBYTEORDER_H_
#define INCLUDE_KYTY_SYS_SYSSWAPBYTEORDER_H_
#include "Kyty/Core/Common.h"
#include <type_traits>
namespace Kyty {
inline uint16_t SwapByteOrder16(uint16_t value)
{
#if KYTY_COMPILER == KYTY_COMPILER_MSVC
return _byteswap_ushort(value);
#else
uint16_t hi = value << 8u;
uint16_t lo = value >> 8u;
return hi | lo;
#endif
}
inline uint32_t SwapByteOrder32(uint32_t value)
{
#if KYTY_COMPILER == KYTY_COMPILER_CLANG
return __builtin_bswap32(value);
#elif KYTY_COMPILER == KYTY_COMPILER_MSVC
return _byteswap_ulong(value);
#else
uint32_t Byte0 = value & 0x000000FFu;
uint32_t Byte1 = value & 0x0000FF00u;
uint32_t Byte2 = value & 0x00FF0000u;
uint32_t Byte3 = value & 0xFF000000u;
return (Byte0 << 24u) | (Byte1 << 8u) | (Byte2 >> 8u) | (Byte3 >> 24u);
#endif
}
inline uint64_t SwapByteOrder64(uint64_t value)
{
#if KYTY_COMPILER == KYTY_COMPILER_CLANG
return __builtin_bswap64(value);
#elif KYTY_COMPILER == KYTY_COMPILER_MSVC
return _byteswap_uint64(value);
#else
uint64_t Hi = SwapByteOrder32(uint32_t(value));
uint32_t Lo = SwapByteOrder32(uint32_t(value >> 32u));
return (Hi << 32u) | Lo;
#endif
}
template <typename T>
inline void SwapByteOrder(T& x)
{
if (sizeof(x) == 2)
{
if (std::is_signed_v<T>)
{
x = std::make_signed_t<T>(SwapByteOrder16(std::make_unsigned_t<uint16_t>(x)));
} else
{
x = SwapByteOrder16(x);
}
}
if (sizeof(x) == 4)
{
if (std::is_signed_v<T>)
{
x = std::make_signed_t<T>(SwapByteOrder32(std::make_unsigned_t<uint32_t>(x)));
} else
{
x = SwapByteOrder32(x);
}
}
if (sizeof(x) == 8)
{
if (std::is_signed_v<T>)
{
x = std::make_signed_t<T>(SwapByteOrder64(std::make_unsigned_t<uint64_t>(x)));
} else
{
x = SwapByteOrder64(x);
}
}
}
template <typename T>
inline void NoSwapByteOrder(T& x)
{
}
} // namespace Kyty
#endif /* INCLUDE_KYTY_SYS_SYSSWAPBYTEORDER_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSSYNC_H_
#define INCLUDE_KYTY_SYS_SYSSYNC_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxSync.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsSync.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSSYNC_H_ */
+9
View File
@@ -0,0 +1,9 @@
#ifndef INCLUDE_KYTY_SYS_SYSTIMER_H_
#define INCLUDE_KYTY_SYS_SYSTIMER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Sys/SysLinuxTimer.h" // IWYU pragma: export
#include "Kyty/Sys/SysWindowsTimer.h" // IWYU pragma: export
#endif /* INCLUDE_KYTY_SYS_SYSTIMER_H_ */
+41
View File
@@ -0,0 +1,41 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSDBG_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSDBG_H_
// IWYU pragma: private
#include "Kyty/Core/Common.h"
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
namespace Kyty {
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_dbg_stack_info_t
{
uintptr_t addr;
uintptr_t reserved_addr;
size_t reserved_size;
uintptr_t guard_addr;
size_t guard_size;
uintptr_t commited_addr;
size_t commited_size;
size_t total_size;
};
using exception_filter_func_t = void (*)(void* addr);
void sys_stack_walk(void** stack, int* depth);
void sys_stack_usage(sys_dbg_stack_info_t& s); // NOLINT(google-runtime-references)
void sys_stack_usage_print(sys_dbg_stack_info_t& stack); // NOLINT(google-runtime-references)
void sys_get_code_info(uintptr_t* addr, size_t* size);
void sys_set_exception_filter(exception_filter_func_t func);
} // namespace Kyty
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSDBG_H_ */
+123
View File
@@ -0,0 +1,123 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSFILEIO_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSFILEIO_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Sys/SysTimer.h"
namespace Kyty {
using KYTY_HANDLE = void*;
template <typename T>
class Vector;
// NOLINTNEXTLINE(readability-identifier-naming)
enum sys_file_type_t
{
SYS_FILE_ERROR, // NOLINT(readability-identifier-naming)
SYS_FILE_MEMORY_STAT, // NOLINT(readability-identifier-naming)
SYS_FILE_FILE, // NOLINT(readability-identifier-naming)
SYS_FILE_MEMORY_DYN // NOLINT(readability-identifier-naming)
};
// NOLINTNEXTLINE(readability-identifier-naming)
enum sys_file_cache_type_t
{
SYS_FILE_CACHE_AUTO = 0, // NOLINT(readability-identifier-naming)
SYS_FILE_CACHE_RANDOM_ACCESS = 1, // NOLINT(readability-identifier-naming)
SYS_FILE_CACHE_SEQUENTIAL_SCAN = 2 // NOLINT(readability-identifier-naming)
};
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_file_mem_buf_t
{
uint8_t* base;
uint8_t* ptr;
uint32_t size;
};
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_file_t
{
sys_file_type_t type;
union
{
KYTY_HANDLE handle;
sys_file_mem_buf_t* buf;
};
};
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_file_find_t
{
String path_with_name;
SysFileTimeStruct last_access_time;
SysFileTimeStruct last_write_time;
uint64_t size;
};
// NOLINTNEXTLINE(readability-identifier-naming)
struct sys_dir_entry_t
{
String name;
bool is_file;
};
void sys_file_read(void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_read = nullptr); // NOLINT(google-runtime-references)
void sys_file_write(const void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_written = nullptr); // NOLINT(google-runtime-references)
void sys_file_read_r(void* data, uint32_t size, sys_file_t& f); // NOLINT(google-runtime-references)
void sys_file_write_r(const void* data, uint32_t size, sys_file_t& f); // NOLINT(google-runtime-references)
sys_file_t* sys_file_create(const String& file_name);
sys_file_t* sys_file_open_r(const String& file_name, sys_file_cache_type_t cache_type = SYS_FILE_CACHE_AUTO);
sys_file_t* sys_file_open_w(const String& file_name, sys_file_cache_type_t cache_type = SYS_FILE_CACHE_AUTO);
sys_file_t* sys_file_open(uint8_t* buf, uint32_t buf_size);
sys_file_t* sys_file_create();
sys_file_t* sys_file_open_rw(const String& file_name, sys_file_cache_type_t cache_type = SYS_FILE_CACHE_AUTO);
void sys_file_close(sys_file_t* f);
uint64_t sys_file_size(sys_file_t& f); // NOLINT(google-runtime-references)
bool sys_file_seek(sys_file_t& f, uint64_t offset); // NOLINT(google-runtime-references)
uint64_t sys_file_tell(sys_file_t& f); // NOLINT(google-runtime-references)
bool sys_file_truncate(sys_file_t& f, uint64_t size); // NOLINT(google-runtime-references)
void sys_file_write(uint32_t n, sys_file_t& f); // NOLINT(google-runtime-references)
void sys_file_write_r(uint32_t n, sys_file_t& f); // NOLINT(google-runtime-references)
uint64_t sys_file_size(const String& file_name);
bool sys_file_is_error(sys_file_t& f); // NOLINT(google-runtime-references)
bool sys_file_io_init();
bool sys_file_is_directory_existing(const String& path);
bool sys_file_is_file_existing(const String& name);
bool sys_file_create_directory(const String& path);
bool sys_file_delete_directory(const String& path);
bool sys_file_delete_file(const String& name);
bool sys_file_flush(sys_file_t& f); // NOLINT(google-runtime-references)
SysFileTimeStruct sys_file_get_last_access_time_utc(const String& name);
SysFileTimeStruct sys_file_get_last_write_time_utc(const String& name);
// NOLINTNEXTLINE(google-runtime-references)
void sys_file_get_last_access_and_write_time_utc(const String& name, SysFileTimeStruct& a, SysFileTimeStruct& w);
// NOLINTNEXTLINE(google-runtime-references)
void sys_file_get_last_access_and_write_time_utc(sys_file_t& f, SysFileTimeStruct& a, SysFileTimeStruct& w);
// NOLINTNEXTLINE(google-runtime-references)
bool sys_file_set_last_access_time_utc(const String& name, SysFileTimeStruct& access);
// NOLINTNEXTLINE(google-runtime-references)
bool sys_file_set_last_write_time_utc(const String& name, SysFileTimeStruct& write);
// NOLINTNEXTLINE(google-runtime-references)
bool sys_file_set_last_access_and_write_time_utc(const String& name, SysFileTimeStruct& access, SysFileTimeStruct& write);
// NOLINTNEXTLINE(google-runtime-references)
void sys_file_find_files(const String& path, Kyty::Vector<sys_file_find_t>& out);
// NOLINTNEXTLINE(google-runtime-references)
void sys_file_get_dents(const String& path, Kyty::Vector<sys_dir_entry_t>& out);
bool sys_file_copy_file(const String& src, const String& dst);
bool sys_file_move_file(const String& src, const String& dst);
void sys_file_remove_readonly(const String& name);
} // namespace Kyty
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSFILEIO_H_ */
+206
View File
@@ -0,0 +1,206 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSHEAP_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSHEAP_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
#if 0
#include <windows.h>
namespace Kyty {
typedef HANDLE sys_heap_id_t;
inline sys_heap_id_t sys_heap_create()
{
HANDLE h = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
EXIT_IF(h == NULL);
return h;
}
inline sys_heap_id_t sys_heap_deafult()
{
HANDLE h = GetProcessHeap();
EXIT_IF(h == NULL);
return h;
}
inline void* sys_heap_alloc(sys_heap_id_t heap_id, size_t size)
{
void *m = HeapAlloc(heap_id, HEAP_NO_SERIALIZE, size);
EXIT_IF(m == 0);
return m;
}
inline void* sys_heap_realloc(sys_heap_id_t heap_id, void *p, size_t size)
{
void *m = p ? HeapReAlloc(heap_id, HEAP_NO_SERIALIZE, p, size)
: HeapAlloc(heap_id, HEAP_NO_SERIALIZE, size);
if (m == 0)
{
EXIT_IF(m == 0);
}
return m;
}
inline void sys_heap_free(sys_heap_id_t heap_id, void *p)
{
bool r = HeapFree(heap_id, HEAP_NO_SERIALIZE, p);
if (!r)
{
printf("%" PRIx64"\n", uint64_t(p));
EXIT_IF(!r);
}
}
inline sys_heap_id_t sys_heap_create_s()
{
HANDLE h = HeapCreate(0, 0, 0);
EXIT_IF(h == NULL);
return h;
}
inline void* sys_heap_alloc_s(sys_heap_id_t heap_id, size_t size)
{
void *m = HeapAlloc(heap_id, 0, size);
EXIT_IF(m == 0);
return m;
}
inline void* sys_heap_realloc_s(sys_heap_id_t heap_id, void *p, size_t size)
{
void *m = HeapReAlloc(heap_id, 0, p, size);
EXIT_IF(m == 0);
return m;
}
inline void sys_heap_free_s(sys_heap_id_t heap_id, void *p)
{
bool r = HeapFree(heap_id, 0, p);
EXIT_IF(!r);
}
} // namespace Kyty
#else
#include "Kyty/Sys/SysSync.h"
namespace Kyty {
using sys_heap_id_t = SysCS *;
inline sys_heap_id_t sys_heap_create()
{
return nullptr;
}
inline sys_heap_id_t sys_heap_deafult()
{
return nullptr;
}
inline void* sys_heap_alloc(sys_heap_id_t /*heap_id*/, size_t size)
{
//NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void *m = malloc(size);
EXIT_IF(m == nullptr);
return m;
}
inline void* sys_heap_realloc(sys_heap_id_t /*heap_id*/, void *p, size_t size)
{
//NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void *m = p != nullptr ? realloc(p, size) : malloc(size);
if (m == nullptr)
{
EXIT_IF(m == nullptr);
}
return m;
}
inline void sys_heap_free(sys_heap_id_t /*heap_id*/, void *p)
{
//NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
free(p);
}
inline sys_heap_id_t sys_heap_create_s()
{
auto *cs = new SysCS;
cs->Init();
return cs;
}
inline void* sys_heap_alloc_s(sys_heap_id_t heap_id, size_t size)
{
heap_id->Enter();
//NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void *m = malloc(size);
heap_id->Leave();
EXIT_IF(m == nullptr);
return m;
}
inline void* sys_heap_realloc_s(sys_heap_id_t heap_id, void *p, size_t size)
{
heap_id->Enter();
//NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
void *m = p != nullptr ? realloc(p, size) : malloc(size);
heap_id->Leave();
EXIT_IF(m == nullptr);
return m;
}
inline void sys_heap_free_s(sys_heap_id_t heap_id, void *p)
{
heap_id->Enter();
//NOLINTNEXTLINE(cppcoreguidelines-no-malloc,hicpp-no-malloc)
free(p);
heap_id->Leave();
}
} // namespace Kyty
#endif
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSHEAP_H_ */
+30
View File
@@ -0,0 +1,30 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSSTDIO_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSSTDIO_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
//#include <stdio.h>
namespace Kyty {
inline uint32_t sys_vscprintf(const char *format, va_list argptr)
{
int len = _vscprintf(format, argptr);
return len < 0 ? 0 : len;
}
inline uint32_t sys_vsnprintf(char *dest, size_t count, const char *format, va_list args)
{
int len = _vsnprintf_s(dest, count+1, count, format, args);
return len < 0 ? 0 : len;
}
} // namespace Kyty
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSSTDIO_H_ */
@@ -0,0 +1,46 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSSTDLIB_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSSTDLIB_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
namespace Kyty {
inline float sys_strtof(const char *nptr, char **endptr)
{
return strtof(nptr, endptr); // @suppress("Invalid arguments")
}
inline double sys_strtod(const char *nptr, char **endptr)
{
return strtod(nptr, endptr); // @suppress("Invalid arguments")
}
inline int32_t sys_strtoi32(const char *nptr, char **endptr, int base)
{
return strtol(nptr, endptr, base); // @suppress("Invalid arguments")
}
inline uint32_t sys_strtoui32(const char *nptr, char **endptr, int base)
{
return strtoul(nptr, endptr, base); // @suppress("Invalid arguments")
}
inline int64_t sys_strtoi64(const char *nptr, char **endptr, int base)
{
return _strtoi64(nptr, endptr, base); // @suppress("Invalid arguments")
}
inline uint64_t sys_strtoui64(const char *nptr, char **endptr, int base)
{
return _strtoui64(nptr, endptr, base); // @suppress("Invalid arguments")
}
} // namespace Kyty
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSSTDLIB_H_ */
+78
View File
@@ -0,0 +1,78 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSSYNC_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSSYNC_H_
// IWYU pragma: private
#include "Kyty/Core/DbgAssert.h"
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
#include <windows.h>
namespace Kyty {
constexpr DWORD SYS_CS_SPIN_COUNT = 16;
class SysCS
{
public:
SysCS() = default;
void Init()
{
EXIT_IF(m_check_ptr != nullptr);
m_check_ptr = this;
InitializeCriticalSectionAndSpinCount(&m_cs, SYS_CS_SPIN_COUNT);
}
void Delete()
{
EXIT_IF(m_check_ptr != this);
m_check_ptr = nullptr;
DeleteCriticalSection(&m_cs);
}
~SysCS() { EXIT_IF(m_check_ptr != nullptr); }
void Enter()
{
EXIT_IF(m_check_ptr != this);
EnterCriticalSection(&m_cs);
}
bool TryEnter()
{
EXIT_IF(m_check_ptr != this);
return TryEnterCriticalSection(&m_cs) != 0;
}
void Leave()
{
EXIT_IF(m_check_ptr != this);
LeaveCriticalSection(&m_cs);
}
KYTY_CLASS_NO_COPY(SysCS);
private:
SysCS* m_check_ptr = nullptr;
CRITICAL_SECTION m_cs {};
};
inline void sys_sleep(uint32_t ms)
{
Sleep(ms);
}
} // namespace Kyty
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSSYNC_H_ */
+132
View File
@@ -0,0 +1,132 @@
#ifndef SYS_WIN32_INCLUDE_KYTY_SYSTIMER_H_
#define SYS_WIN32_INCLUDE_KYTY_SYSTIMER_H_
// IWYU pragma: private
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
//#error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else
#include <windows.h>
namespace Kyty {
struct SysTimeStruct
{
uint16_t Year; // NOLINT(readability-identifier-naming)
uint16_t Month; // NOLINT(readability-identifier-naming)
uint16_t Day; // NOLINT(readability-identifier-naming)
uint16_t Hour; // NOLINT(readability-identifier-naming)
uint16_t Minute; // NOLINT(readability-identifier-naming)
uint16_t Second; // NOLINT(readability-identifier-naming)
uint16_t Milliseconds; // NOLINT(readability-identifier-naming)
bool is_invalid; // NOLINT(readability-identifier-naming)
};
struct SysFileTimeStruct
{
FILETIME time;
bool is_invalid;
};
// NOLINTNEXTLINE(google-runtime-references)
inline void sys_file_to_system_time_utc(const SysFileTimeStruct& f, SysTimeStruct& t)
{
SYSTEMTIME s;
if (f.is_invalid || (FileTimeToSystemTime(&f.time, &s) == 0))
{
t.is_invalid = true;
return;
}
t.is_invalid = false;
t.Year = s.wYear;
t.Month = s.wMonth;
t.Day = s.wDay;
t.Hour = s.wHour;
t.Minute = s.wMinute;
t.Second = (s.wSecond == 60 ? 59 : s.wSecond);
t.Milliseconds = s.wMilliseconds;
}
// NOLINTNEXTLINE(google-runtime-references)
inline void sys_time_t_to_system(time_t t, SysTimeStruct& s)
{
SysFileTimeStruct ft {};
LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
ft.time.dwLowDateTime = static_cast<DWORD>(ll);
ft.time.dwHighDateTime = static_cast<DWORD>(static_cast<uint64_t>(ll) >> 32u);
ft.is_invalid = false;
sys_file_to_system_time_utc(ft, s);
}
// NOLINTNEXTLINE(google-runtime-references)
inline void sys_system_to_file_time_utc(const SysTimeStruct& f, SysFileTimeStruct& t)
{
SYSTEMTIME s;
s.wYear = f.Year;
s.wMonth = f.Month;
s.wDay = f.Day;
s.wHour = f.Hour;
s.wMinute = f.Minute;
s.wSecond = f.Second;
s.wMilliseconds = f.Milliseconds;
t.is_invalid = (f.is_invalid || (SystemTimeToFileTime(&s, &t.time) == 0));
}
// Retrieves the current local date and time
// NOLINTNEXTLINE(google-runtime-references)
inline void sys_get_system_time(SysTimeStruct& t)
{
SYSTEMTIME s;
GetLocalTime(&s);
t.is_invalid = false;
t.Year = s.wYear;
t.Month = s.wMonth;
t.Day = s.wDay;
t.Hour = s.wHour;
t.Minute = s.wMinute;
t.Second = (s.wSecond == 60 ? 59 : s.wSecond);
t.Milliseconds = s.wMilliseconds;
}
// Retrieves the current system date and time in Coordinated Universal Time (UTC).
// NOLINTNEXTLINE(google-runtime-references)
inline void sys_get_system_time_utc(SysTimeStruct& t)
{
SYSTEMTIME s;
GetSystemTime(&s);
t.is_invalid = false;
t.Year = s.wYear;
t.Month = s.wMonth;
t.Day = s.wDay;
t.Hour = s.wHour;
t.Minute = s.wMinute;
t.Second = (s.wSecond == 60 ? 59 : s.wSecond);
t.Milliseconds = s.wMilliseconds;
}
inline void sys_query_performance_frequency(uint64_t* freq)
{
LARGE_INTEGER f;
QueryPerformanceFrequency(&f);
*freq = f.QuadPart;
}
inline void sys_query_performance_counter(uint64_t* counter)
{
LARGE_INTEGER c;
QueryPerformanceCounter(&c);
*counter = c.QuadPart;
}
} // namespace Kyty
#endif
#endif /* SYS_WIN32_INCLUDE_KYTY_SYSTIMER_H_ */
+49
View File
@@ -0,0 +1,49 @@
#ifndef INCLUDE_KYTY_CONFIG_H_
#define INCLUDE_KYTY_CONFIG_H_
#define KYTY_PLATFORM_WINDOWS 1
#define KYTY_PLATFORM_ANDROID 2
#define KYTY_PLATFORM_OSX 3
#define KYTY_PLATFORM_IOS 4
#define KYTY_PLATFORM_LINUX 5
#define KYTY_COMPILER_MINGW 1
#define KYTY_COMPILER_MSVC 2
#define KYTY_COMPILER_GCC 3
#define KYTY_COMPILER_CLANG 4
#define KYTY_LINKER_LINK 1
#define KYTY_LINKER_LD 2
#define KYTY_LINKER_LLD 3
#define KYTY_LINKER_LLD_LINK 4
#define KYTY_BUILD_DEBUG 1
#define KYTY_BUILD_RELEASE 2
#define KYTY_ENDIAN_BIG 1
#define KYTY_ENDIAN_LITTLE 2
#define KYTY_ABI_ARMEABI 1
#define KYTY_ABI_ARMEABI_V7A 2
#define KYTY_ABI_ARM64_V8A 3
#define KYTY_ABI_X86 4
#define KYTY_ABI_X86_64 5
#define KYTY_ABI_MIPS 6
#define KYTY_ABI_MIPS64 7
#define KYTY_ARM_FLOAT_SOFT 1
#define KYTY_ARM_FLOAT_HARD 2
#define KYTY_PROJECT_EMPTY 0
#define KYTY_PROJECT_EMULATOR 1
#define KYTY_PROJECT_BUILD_TOOLS 2
#include "cmake_config.h"
#if KYTY_BITNESS == 32
#define KYTY_ABI KYTY_ABI_X86
#else
#define KYTY_ABI KYTY_ABI_X86_64
#endif
#endif /* INCLUDE_KYTY_CONFIG_H_ */