建档
This commit is contained in:
61
source/Tool/Allocator.cpp
Normal file
61
source/Tool/Allocator.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2016-2018 Kiwano - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "Tool/Allocator.h"
|
||||
|
||||
namespace memory
|
||||
{
|
||||
MemoryAllocator *current_allocator_ = nullptr;
|
||||
|
||||
MemoryAllocator *GetGlobalAllocator()
|
||||
{
|
||||
class GlobalAllocator : public MemoryAllocator
|
||||
{
|
||||
public:
|
||||
virtual void *Alloc(size_t size) override
|
||||
{
|
||||
return ::operator new(size);
|
||||
}
|
||||
|
||||
virtual void Free(void *ptr) override
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
static GlobalAllocator global_allocator;
|
||||
return &global_allocator;
|
||||
}
|
||||
|
||||
MemoryAllocator *GetAllocator()
|
||||
{
|
||||
if (!current_allocator_)
|
||||
{
|
||||
current_allocator_ = GetGlobalAllocator();
|
||||
}
|
||||
return current_allocator_;
|
||||
}
|
||||
|
||||
void SetAllocator(MemoryAllocator *allocator)
|
||||
{
|
||||
current_allocator_ = allocator;
|
||||
}
|
||||
|
||||
} // namespace memory
|
||||
151
source/Tool/Allocator.h
Normal file
151
source/Tool/Allocator.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
namespace memory
|
||||
{
|
||||
/// \~chinese
|
||||
/// @brief 内存分配器
|
||||
class MemoryAllocator
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 申请内存
|
||||
virtual void *Alloc(size_t size) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 释放内存
|
||||
virtual void Free(void *ptr) = 0;
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取当前内存分配器
|
||||
MemoryAllocator *GetAllocator();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置当前内存分配器
|
||||
void SetAllocator(MemoryAllocator *allocator);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 使用当前内存分配器分配内存
|
||||
inline void *Alloc(size_t size)
|
||||
{
|
||||
return memory::GetAllocator()->Alloc(size);
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 使用当前内存分配器释放内存
|
||||
inline void Free(void *ptr)
|
||||
{
|
||||
memory::GetAllocator()->Free(ptr);
|
||||
}
|
||||
|
||||
} // namespace memory
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 分配器
|
||||
template <typename _Ty>
|
||||
class Allocator
|
||||
{
|
||||
public:
|
||||
typedef _Ty value_type;
|
||||
typedef _Ty *pointer;
|
||||
typedef const _Ty *const_pointer;
|
||||
typedef _Ty &reference;
|
||||
typedef const _Ty &const_reference;
|
||||
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
template <class _Other>
|
||||
struct rebind
|
||||
{
|
||||
using other = Allocator<_Other>;
|
||||
};
|
||||
|
||||
Allocator() noexcept {}
|
||||
|
||||
Allocator(const Allocator &) noexcept = default;
|
||||
|
||||
template <class _Other>
|
||||
Allocator(const Allocator<_Other> &) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
inline _Ty *allocate(size_t count)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
return static_cast<_Ty *>(memory::Alloc(sizeof(_Ty) * count));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline void *allocate(size_t count, const void *)
|
||||
{
|
||||
return allocate(count);
|
||||
}
|
||||
|
||||
inline void deallocate(void *ptr, size_t count)
|
||||
{
|
||||
memory::Free(ptr /*, sizeof(_Ty) * count */);
|
||||
}
|
||||
|
||||
template <typename _UTy, typename... _Args>
|
||||
inline void construct(_UTy *const ptr, _Args &&...args)
|
||||
{
|
||||
::new (const_cast<void *>(static_cast<const volatile void *>(ptr))) _Ty(std::forward<_Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename _UTy>
|
||||
inline void destroy(_UTy *ptr)
|
||||
{
|
||||
ptr->~_UTy();
|
||||
}
|
||||
|
||||
size_t max_size() const noexcept
|
||||
{
|
||||
return std::numeric_limits<size_t>::max() / sizeof(_Ty);
|
||||
}
|
||||
|
||||
_Ty *address(_Ty &val) const noexcept
|
||||
{
|
||||
return std::addressof(val);
|
||||
}
|
||||
|
||||
const _Ty *address(const _Ty &val) const noexcept
|
||||
{
|
||||
return std::addressof(val);
|
||||
}
|
||||
};
|
||||
|
||||
// Allocator<void>
|
||||
template <>
|
||||
class Allocator<void>
|
||||
{
|
||||
public:
|
||||
using value_type = void;
|
||||
typedef void *pointer;
|
||||
typedef const void *const_pointer;
|
||||
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
template <class _Other>
|
||||
struct rebind
|
||||
{
|
||||
using other = Allocator<_Other>;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _Ty, class _Other>
|
||||
bool operator==(const Allocator<_Ty> &, const Allocator<_Other> &) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Ty, class _Other>
|
||||
bool operator!=(const Allocator<_Ty> &, const Allocator<_Other> &) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
137
source/Tool/Blob.hpp
Normal file
137
source/Tool/Blob.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
class Blob
|
||||
{
|
||||
using BYTE = unsigned char;
|
||||
|
||||
private:
|
||||
const std::vector<BYTE> m_blob;
|
||||
size_t m_offset;
|
||||
|
||||
// 检查是否有足够的剩余字节
|
||||
void checkSize(size_t required) const
|
||||
{
|
||||
if (m_offset + required > m_blob.size())
|
||||
{
|
||||
throw std::out_of_range("Insufficient data in blob");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// 构造函数,接受一个字节向量的引用
|
||||
Blob(const std::vector<BYTE> blob) : m_blob(blob), m_offset(0) {}
|
||||
|
||||
// 重置解析偏移量
|
||||
void reset() { m_offset = 0; }
|
||||
|
||||
// 获取当前偏移量
|
||||
size_t getOffset() const { return m_offset; }
|
||||
|
||||
// 设置偏移量
|
||||
void setOffset(size_t offset)
|
||||
{
|
||||
if (offset > m_blob.size())
|
||||
{
|
||||
throw std::out_of_range("Offset out of range");
|
||||
}
|
||||
m_offset = offset;
|
||||
}
|
||||
|
||||
// 获取剩余字节数
|
||||
size_t remaining() const { return m_blob.size() - m_offset; }
|
||||
|
||||
// 读取一个T类型的数据(适用于基本类型)
|
||||
template <typename T>
|
||||
T get()
|
||||
{
|
||||
checkSize(sizeof(T));
|
||||
|
||||
T value;
|
||||
std::copy(m_blob.begin() + m_offset,
|
||||
m_blob.begin() + m_offset + sizeof(T),
|
||||
reinterpret_cast<BYTE *>(&value));
|
||||
m_offset += sizeof(T);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// 读取int类型
|
||||
int32_t getInt() { return get<int32_t>(); }
|
||||
|
||||
// 读取无符号int类型
|
||||
uint32_t getUInt() { return get<uint32_t>(); }
|
||||
|
||||
// 读取short类型
|
||||
int16_t getShort() { return get<int16_t>(); }
|
||||
|
||||
// 读取无符号short类型
|
||||
uint16_t getUShort() { return get<uint16_t>(); }
|
||||
|
||||
// 读取float类型
|
||||
float getFloat() { return get<float>(); }
|
||||
|
||||
// 读取double类型
|
||||
double getDouble() { return get<double>(); }
|
||||
|
||||
BYTE getByte() { return get<BYTE>(); }
|
||||
|
||||
float get256()
|
||||
{
|
||||
BYTE buf = get<BYTE>();
|
||||
return static_cast<float>(buf);
|
||||
}
|
||||
|
||||
// 读取指定长度的字符串
|
||||
std::string getString(size_t length)
|
||||
{
|
||||
checkSize(length);
|
||||
|
||||
std::string str(reinterpret_cast<const char *>(m_blob.data() + m_offset), length);
|
||||
m_offset += length;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// 读取以null结尾的字符串
|
||||
std::string getNullTerminatedString()
|
||||
{
|
||||
size_t length = 0;
|
||||
size_t pos = m_offset;
|
||||
|
||||
// 查找null终止符
|
||||
while (pos < m_blob.size() && m_blob[pos] != '\0')
|
||||
{
|
||||
pos++;
|
||||
length++;
|
||||
}
|
||||
|
||||
// 确保找到了终止符
|
||||
if (pos >= m_blob.size())
|
||||
{
|
||||
throw std::runtime_error("Null-terminated string not found");
|
||||
}
|
||||
|
||||
// 读取字符串(不包含终止符)
|
||||
std::string str(reinterpret_cast<const char *>(m_blob.data() + m_offset), length);
|
||||
m_offset = pos + 1; // 跳过终止符
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// 读取指定数量的字节
|
||||
std::vector<BYTE> getBytes(size_t count)
|
||||
{
|
||||
checkSize(count);
|
||||
|
||||
std::vector<BYTE> bytes(m_blob.begin() + m_offset, m_blob.begin() + m_offset + count);
|
||||
m_offset += count;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
};
|
||||
262
source/Tool/Common.h
Normal file
262
source/Tool/Common.h
Normal file
@@ -0,0 +1,262 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <cstddef>
|
||||
#include <SDL.h>
|
||||
#ifdef __SWITCH__
|
||||
#include <switch/types.h>
|
||||
#else
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 不可拷贝对象
|
||||
class Noncopyable
|
||||
{
|
||||
protected:
|
||||
Noncopyable() = default;
|
||||
|
||||
private:
|
||||
Noncopyable(const Noncopyable &) = delete;
|
||||
|
||||
Noncopyable &operator=(const Noncopyable &) = delete;
|
||||
};
|
||||
|
||||
// 整数坐标向量
|
||||
typedef struct VecPos
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
// 构造函数,方便初始化
|
||||
VecPos(int x_ = 0, int y_ = 0) : x(x_), y(y_) {}
|
||||
|
||||
// 定义到 SDL_Point 的转换运算符
|
||||
operator SDL_Point() const
|
||||
{
|
||||
return {x, y}; // 直接返回包含 x、y 的 SDL_Point
|
||||
}
|
||||
// 转换为SDL_Point指针的运算符(用于指针场景)
|
||||
operator const SDL_Point *() const
|
||||
{
|
||||
// 注意:这里返回的是指向当前对象的指针,需确保对象生命周期有效
|
||||
return reinterpret_cast<const SDL_Point *>(this);
|
||||
}
|
||||
|
||||
// 加法运算符重载:两个 VecPos 相加
|
||||
VecPos operator+(const VecPos &other) const
|
||||
{
|
||||
return VecPos(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
// 减法运算符重载:两个 VecPos 相减
|
||||
VecPos operator-(const VecPos &other) const
|
||||
{
|
||||
return VecPos(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
// 等于运算符重载:判断两个 VecPos 是否相等
|
||||
bool operator==(const VecPos &other) const
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
// 复合赋值加法:当前对象加上另一个 VecPos
|
||||
VecPos &operator+=(const VecPos &other)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 复合赋值减法:当前对象减去另一个 VecPos
|
||||
VecPos &operator-=(const VecPos &other)
|
||||
{
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
} VecPos;
|
||||
|
||||
// 浮点数坐标向量
|
||||
typedef struct VecFPos
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
// 构造函数,方便初始化
|
||||
VecFPos(float x_ = 0.0f, float y_ = 0.0f) : x(x_), y(y_) {}
|
||||
VecFPos(int x_, int y_ = 0) : x(static_cast<float>(x_)), y(static_cast<float>(y_)) {}
|
||||
|
||||
// 定义到 SDL_FPoint 的转换运算符
|
||||
operator SDL_FPoint() const
|
||||
{
|
||||
return {x, y}; // 直接返回包含 x、y 的 SDL_Point
|
||||
}
|
||||
|
||||
// 加法运算符重载:两个 VecFPos 相加
|
||||
VecFPos operator+(const VecFPos &other) const
|
||||
{
|
||||
return VecFPos(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
// 减法运算符重载:两个 VecFPos 相减
|
||||
VecFPos operator-(const VecFPos &other) const
|
||||
{
|
||||
return VecFPos(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
// 乘法运算符重载:两个 VecFPos 相乘
|
||||
VecFPos operator*(const VecFPos &other) const
|
||||
{
|
||||
return VecFPos(x * other.x, y * other.y);
|
||||
}
|
||||
|
||||
// 等于运算符重载:判断两个 VecFPos 是否相等
|
||||
// 注意:浮点数比较需要考虑精度问题
|
||||
bool operator==(const VecFPos &other) const
|
||||
{
|
||||
// 使用一个小的epsilon值来比较浮点数
|
||||
const float epsilon = 0.0001f;
|
||||
return (fabs(x - other.x) < epsilon) && (fabs(y - other.y) < epsilon);
|
||||
}
|
||||
|
||||
// 复合赋值加法:当前对象加上另一个 VecFPos
|
||||
VecFPos &operator+=(const VecFPos &other)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 复合赋值减法:当前对象减去另一个 VecFPos
|
||||
VecFPos &operator-=(const VecFPos &other)
|
||||
{
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
} VecFPos;
|
||||
|
||||
// 尺寸向量
|
||||
typedef struct VecSize
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// 构造函数,方便初始化
|
||||
VecSize(int width_ = 0, int height_ = 0) : width(width_), height(height_) {}
|
||||
|
||||
// 加法运算符重载:两个 VecSize 相加
|
||||
VecSize operator+(const VecSize &other) const
|
||||
{
|
||||
return VecSize(width + other.width, height + other.height);
|
||||
}
|
||||
|
||||
// 减法运算符重载:两个 VecSize 相减
|
||||
VecSize operator-(const VecSize &other) const
|
||||
{
|
||||
return VecSize(width - other.width, height - other.height);
|
||||
}
|
||||
|
||||
// 等于运算符重载:判断两个 VecSize 是否相等
|
||||
bool operator==(const VecSize &other) const
|
||||
{
|
||||
return width == other.width && height == other.height;
|
||||
}
|
||||
|
||||
// 复合赋值加法:当前对象加上另一个 VecSize
|
||||
VecSize &operator+=(const VecSize &other)
|
||||
{
|
||||
width += other.width;
|
||||
height += other.height;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 复合赋值减法:当前对象减去另一个 VecSize
|
||||
VecSize &operator-=(const VecSize &other)
|
||||
{
|
||||
width -= other.width;
|
||||
height -= other.height;
|
||||
return *this;
|
||||
}
|
||||
} VecSize;
|
||||
|
||||
typedef struct VecPos3
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
VecPos3(int x_ = 0, int y_ = 0, int z_ = 0) : x(x_), y(y_), z(z_) {}
|
||||
|
||||
VecPos3 operator+(const VecPos3 &other) const
|
||||
{
|
||||
return VecPos3(x + other.x, y + other.y, z + other.z);
|
||||
}
|
||||
|
||||
VecPos3 operator-(const VecPos3 &other) const
|
||||
{
|
||||
return VecPos3(x - other.x, y - other.y, z - other.z);
|
||||
}
|
||||
|
||||
bool operator==(const VecPos3 &other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
|
||||
} VecPos3;
|
||||
|
||||
typedef struct VecFPos3
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
VecFPos3(float x_ = 0, float y_ = 0, float z_ = 0) : x(x_), y(y_), z(z_) {}
|
||||
|
||||
VecFPos3 operator+(const VecFPos3 &other) const
|
||||
{
|
||||
return VecFPos3(x + other.x, y + other.y, z + other.z);
|
||||
}
|
||||
|
||||
VecFPos3 operator-(const VecFPos3 &other) const
|
||||
{
|
||||
return VecFPos3(x - other.x, y - other.y, z - other.z);
|
||||
}
|
||||
|
||||
bool operator==(const VecFPos3 &other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
|
||||
} VecFPos3;
|
||||
|
||||
typedef struct VecSpeed3
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
VecSpeed3(float x_ = 0, float y_ = 0, float z_ = 0) : x(x_), y(y_), z(z_) {}
|
||||
|
||||
VecSpeed3 operator+(const VecSpeed3 &other) const
|
||||
{
|
||||
return VecSpeed3(x + other.x, y + other.y, z + other.z);
|
||||
}
|
||||
|
||||
VecSpeed3 operator-(const VecSpeed3 &other) const
|
||||
{
|
||||
return VecSpeed3(x - other.x, y - other.y, z - other.z);
|
||||
}
|
||||
|
||||
bool operator==(const VecSpeed3 &other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
} VecSpeed3;
|
||||
86
source/Tool/Ifstream_NPK.cpp
Normal file
86
source/Tool/Ifstream_NPK.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "Ifstream_NPK.h"
|
||||
|
||||
// 密钥初始化
|
||||
Ifstream_NPK::Ifstream_NPK() : Key{112, 117, 99, 104, 105, 107, 111, 110, 64, 110, 101, 111, 112, 108, 101, 32, 100, 117, 110, 103, 101, 111, 110, 32, 97, 110, 100, 32, 102, 105, 103, 104, 116, 101, 114, 32, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 0}
|
||||
{
|
||||
// 构造函数体可以为空
|
||||
}
|
||||
|
||||
// char* 转整数
|
||||
int Ifstream_NPK::CharToInt(char *Str)
|
||||
{
|
||||
return *(int *)Str;
|
||||
}
|
||||
|
||||
// char* 转Long
|
||||
long Ifstream_NPK::CharToLong(char *Str)
|
||||
{
|
||||
return *(long long *)Str;
|
||||
}
|
||||
|
||||
// 读整数
|
||||
int Ifstream_NPK::ReadInt()
|
||||
{
|
||||
char *CountBuffer = new char[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
this->get(CountBuffer[i]);
|
||||
}
|
||||
int Count = CharToInt(CountBuffer);
|
||||
delete[] CountBuffer;
|
||||
return Count;
|
||||
}
|
||||
|
||||
// 读字符串
|
||||
std::string Ifstream_NPK::ReadString()
|
||||
{
|
||||
char *CharBuffer = new char[1024];
|
||||
this->get(CharBuffer, 1024, '\0');
|
||||
std::string Str = CharBuffer;
|
||||
delete[] CharBuffer;
|
||||
this->seekg(1, std::ios::cur);
|
||||
return Str;
|
||||
}
|
||||
|
||||
// 读取信息
|
||||
std::string Ifstream_NPK::ReadInfo()
|
||||
{
|
||||
char *CharBuffer = new char[256];
|
||||
char var;
|
||||
int i = 0;
|
||||
while (i < 256)
|
||||
{
|
||||
this->get(var);
|
||||
CharBuffer[i] = var ^ Key[i];
|
||||
++i;
|
||||
}
|
||||
std::string Str = CharBuffer;
|
||||
delete[] CharBuffer;
|
||||
return Str;
|
||||
}
|
||||
|
||||
// 读LONG
|
||||
int Ifstream_NPK::ReadLong()
|
||||
{
|
||||
char *CountBuffer = new char[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
this->get(CountBuffer[i]);
|
||||
}
|
||||
long Count = CharToLong(CountBuffer);
|
||||
delete[] CountBuffer;
|
||||
return Count;
|
||||
}
|
||||
|
||||
// 读指定长度数据
|
||||
BYTE *Ifstream_NPK::ReadCustomSize(int Size)
|
||||
{
|
||||
BYTE *CharBuffer = new BYTE[Size];
|
||||
for (int j = 0; j < Size; j++)
|
||||
{
|
||||
char var;
|
||||
this->get(var);
|
||||
CharBuffer[j] = var;
|
||||
}
|
||||
return CharBuffer;
|
||||
}
|
||||
36
source/Tool/Ifstream_NPK.h
Normal file
36
source/Tool/Ifstream_NPK.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
class Ifstream_NPK : public std::ifstream
|
||||
{
|
||||
private:
|
||||
const BYTE Key[256];
|
||||
|
||||
public:
|
||||
// 构造函数
|
||||
Ifstream_NPK();
|
||||
|
||||
// char* 转整数
|
||||
int CharToInt(char *Str);
|
||||
|
||||
// char* 转Long
|
||||
long CharToLong(char *Str);
|
||||
|
||||
// 读整数
|
||||
int ReadInt();
|
||||
|
||||
// 读字符串
|
||||
std::string ReadString();
|
||||
|
||||
// 读取信息
|
||||
std::string ReadInfo();
|
||||
|
||||
// 读LONG
|
||||
int ReadLong();
|
||||
|
||||
// 读指定长度数据
|
||||
BYTE *ReadCustomSize(int Size);
|
||||
};
|
||||
35
source/Tool/Ifstream_PVF.cpp
Normal file
35
source/Tool/Ifstream_PVF.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "Ifstream_PVF.h"
|
||||
Ifstream_PVF::Ifstream_PVF(std::string fileName)
|
||||
{
|
||||
std::ifstream file(fileName, std::ios::binary | std::ios::in);
|
||||
if (file.is_open())
|
||||
{
|
||||
// 获取文件大小
|
||||
file.seekg(0, std::ios::end);
|
||||
std::streamsize length = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
// 直接调整vector大小并读取数据
|
||||
_Data.resize(static_cast<size_t>(length));
|
||||
if (file.read(_Data.data(), length))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
_Data.clear();
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "无法打开文件: %s", fileName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Ifstream_PVF::~Ifstream_PVF()
|
||||
{
|
||||
// vector会自动释放内存,无需手动操作
|
||||
}
|
||||
170
source/Tool/Ifstream_PVF.h
Normal file
170
source/Tool/Ifstream_PVF.h
Normal file
@@ -0,0 +1,170 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <SDL.h>
|
||||
#include <algorithm>
|
||||
#include "Tool/Tool_String.h"
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
// 定义宏用于注册获取不同类型值的函数
|
||||
#define REGISTER_GET_FUNCTION(Type, FunctionName) \
|
||||
Type Get##FunctionName() \
|
||||
{ \
|
||||
char buffer[sizeof(Type)]; \
|
||||
read(buffer, sizeof(Type)); \
|
||||
Type result; \
|
||||
std::memcpy(&result, buffer, sizeof(Type)); \
|
||||
return result; \
|
||||
}
|
||||
class Ifstream_PVF
|
||||
{
|
||||
public:
|
||||
// 使用vector存储数据,替代char*
|
||||
std::vector<char> _Data;
|
||||
// 当前位置
|
||||
int _CurPos = 0;
|
||||
// 上一次读取的实际大小
|
||||
int _LastReadSize = 0;
|
||||
|
||||
public:
|
||||
Ifstream_PVF(std::string fileName);
|
||||
~Ifstream_PVF();
|
||||
|
||||
public:
|
||||
int tellg()
|
||||
{
|
||||
return _CurPos;
|
||||
}
|
||||
|
||||
// 获取数据大小
|
||||
int size() const
|
||||
{
|
||||
return static_cast<int>(_Data.size());
|
||||
}
|
||||
|
||||
void read(char *ptr, int size)
|
||||
{
|
||||
// 使用vector的size()作为最大长度
|
||||
if ((size + _CurPos) > static_cast<int>(_Data.size()))
|
||||
{
|
||||
size = static_cast<int>(_Data.size()) - _CurPos;
|
||||
}
|
||||
memcpy(ptr, _Data.data() + _CurPos, size);
|
||||
_CurPos += size;
|
||||
_LastReadSize = size;
|
||||
}
|
||||
|
||||
int gcount()
|
||||
{
|
||||
return _LastReadSize;
|
||||
}
|
||||
|
||||
void seek(int _jidx)
|
||||
{
|
||||
// 确保不会越界
|
||||
_CurPos = std::clamp(_jidx, 0, static_cast<int>(_Data.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned int charPtrToInt(const char *bytes)
|
||||
{
|
||||
unsigned int result;
|
||||
std::memcpy(&result, bytes, sizeof(int));
|
||||
return result;
|
||||
}
|
||||
|
||||
void CrcDecode(const int Length, const int crc32)
|
||||
{
|
||||
int num = 0x81A79011;
|
||||
int originalPos = tellg(); // 保存初始位置
|
||||
for (int i = 0; i < Length; i += 4)
|
||||
{
|
||||
int Pos = tellg();
|
||||
char buffer[4];
|
||||
read(buffer, 4);
|
||||
unsigned int anInt = charPtrToInt(buffer);
|
||||
unsigned int val = (anInt ^ num ^ crc32);
|
||||
unsigned int jiemi = (val >> 6) | ((val << (32 - 6)) & 0xFFFFFFFF);
|
||||
|
||||
// 使用vector的data()获取数据指针
|
||||
if (Pos + 3 < static_cast<int>(_Data.size()))
|
||||
{
|
||||
_Data[Pos] = ((jiemi >> 0) & 0xFF);
|
||||
_Data[Pos + 1] = ((jiemi >> 8) & 0xFF);
|
||||
_Data[Pos + 2] = ((jiemi >> 16) & 0xFF);
|
||||
_Data[Pos + 3] = ((jiemi >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
// 重置读取位置,因为解码过程中移动了指针
|
||||
seek(originalPos + Length); // 移动到解码后的位置
|
||||
}
|
||||
|
||||
std::string tolower(std::string str)
|
||||
{
|
||||
for (size_t i = 0; i < str.length(); ++i)
|
||||
{
|
||||
str[i] = std::tolower(str[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string &str, const std::string &delimiter)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
size_t pos = 0;
|
||||
size_t found;
|
||||
while ((found = str.find(delimiter, pos)) != std::string::npos)
|
||||
{
|
||||
tokens.push_back(str.substr(pos, found - pos));
|
||||
pos = found + delimiter.length();
|
||||
}
|
||||
tokens.push_back(str.substr(pos));
|
||||
return tokens;
|
||||
}
|
||||
|
||||
public:
|
||||
REGISTER_GET_FUNCTION(int, Int);
|
||||
REGISTER_GET_FUNCTION(short, Short);
|
||||
REGISTER_GET_FUNCTION(unsigned short, UShort);
|
||||
|
||||
std::string GetString(const int size)
|
||||
{
|
||||
if (size <= 0)
|
||||
return "";
|
||||
|
||||
// 确保不会读取超出范围的数据
|
||||
int readSize = std::min(size, static_cast<int>(_Data.size()) - _CurPos);
|
||||
std::string result(_Data.data() + _CurPos, readSize);
|
||||
_CurPos += readSize;
|
||||
_LastReadSize = readSize;
|
||||
|
||||
if (readSize != size)
|
||||
{
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "未能成功读取指定字节数的数据!");
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
std::string GetStringNormal(const int size)
|
||||
{
|
||||
// 与GetString实现相同,可根据实际需求区分
|
||||
if (size <= 0)
|
||||
return "";
|
||||
|
||||
int readSize = std::min(size, static_cast<int>(_Data.size()) - _CurPos);
|
||||
std::string result(_Data.data() + _CurPos, readSize);
|
||||
_CurPos += readSize;
|
||||
_LastReadSize = readSize;
|
||||
|
||||
if (readSize != size)
|
||||
{
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "未能成功读取指定字节数的数据!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
459
source/Tool/IntrusiveList.hpp
Normal file
459
source/Tool/IntrusiveList.hpp
Normal file
@@ -0,0 +1,459 @@
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 侵入式链表
|
||||
template <typename _PtrTy>
|
||||
class IntrusiveList
|
||||
{
|
||||
public:
|
||||
using value_type = typename std::pointer_traits<_PtrTy>::pointer;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
|
||||
IntrusiveList()
|
||||
: first_(), last_()
|
||||
{
|
||||
}
|
||||
|
||||
~IntrusiveList()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取首元素
|
||||
const value_type &GetFirst() const
|
||||
{
|
||||
return first_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取首元素
|
||||
value_type &GetFirst()
|
||||
{
|
||||
return first_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取尾元素
|
||||
const value_type &GetLast() const
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取尾元素
|
||||
value_type &GetLast()
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 链表是否为空
|
||||
inline bool IsEmpty() const
|
||||
{
|
||||
return first_ == nullptr;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 在链表尾部添加对象
|
||||
void PushBack(reference child)
|
||||
{
|
||||
if (child->GetPrev())
|
||||
child->GetPrev()->GetNext() = child->GetNext();
|
||||
if (child->GetNext())
|
||||
child->GetNext()->GetPrev() = child->GetPrev();
|
||||
|
||||
child->GetPrev() = last_;
|
||||
child->GetNext() = nullptr;
|
||||
|
||||
if (first_)
|
||||
{
|
||||
last_->GetNext() = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_ = child;
|
||||
}
|
||||
|
||||
last_ = child;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 在链表头部添加对象
|
||||
void PushFront(reference child)
|
||||
{
|
||||
if (child->GetPrev())
|
||||
child->GetPrev()->GetNext() = child->GetNext();
|
||||
if (child->GetNext())
|
||||
child->GetNext()->GetPrev() = child->GetPrev();
|
||||
|
||||
child->GetPrev() = nullptr;
|
||||
child->GetNext() = first_;
|
||||
|
||||
if (first_)
|
||||
{
|
||||
first_->GetPrev() = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_ = child;
|
||||
}
|
||||
|
||||
first_ = child;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 在链表的对象前插入新对象
|
||||
void InsertBefore(reference child, reference before)
|
||||
{
|
||||
if (child->GetPrev())
|
||||
child->GetPrev()->GetNext() = child->GetNext();
|
||||
if (child->GetNext())
|
||||
child->GetNext()->GetPrev() = child->GetPrev();
|
||||
|
||||
if (before->GetPrev())
|
||||
before->GetPrev()->GetNext() = child;
|
||||
else
|
||||
first_ = child;
|
||||
|
||||
child->GetPrev() = before->GetPrev();
|
||||
child->GetNext() = before;
|
||||
before->GetPrev() = child;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 在链表的对象后插入新对象
|
||||
void InsertAfter(reference child, reference after)
|
||||
{
|
||||
if (child->GetPrev())
|
||||
child->GetPrev()->GetNext() = child->GetNext();
|
||||
if (child->GetNext())
|
||||
child->GetNext()->GetPrev() = child->GetPrev();
|
||||
|
||||
if (after->GetNext())
|
||||
after->GetNext()->GetPrev() = child;
|
||||
else
|
||||
last_ = child;
|
||||
|
||||
child->GetNext() = after->GetNext();
|
||||
child->GetPrev() = after;
|
||||
after->GetNext() = child;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除对象
|
||||
void Remove(reference child)
|
||||
{
|
||||
if (child->GetNext())
|
||||
{
|
||||
child->GetNext()->GetPrev() = child->GetPrev();
|
||||
}
|
||||
else
|
||||
{
|
||||
last_ = child->GetPrev();
|
||||
}
|
||||
|
||||
if (child->GetPrev())
|
||||
{
|
||||
child->GetPrev()->GetNext() = child->GetNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
first_ = child->GetNext();
|
||||
}
|
||||
|
||||
child->GetPrev() = nullptr;
|
||||
child->GetNext() = nullptr;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 清空所有对象
|
||||
void Clear()
|
||||
{
|
||||
value_type p = first_;
|
||||
while (p)
|
||||
{
|
||||
value_type tmp = p;
|
||||
p = p->GetNext();
|
||||
if (tmp)
|
||||
{
|
||||
tmp->GetNext() = nullptr;
|
||||
tmp->GetPrev() = nullptr;
|
||||
}
|
||||
}
|
||||
first_ = nullptr;
|
||||
last_ = nullptr;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 检查链表是否有效
|
||||
bool CheckValid()
|
||||
{
|
||||
if (!first_)
|
||||
return true;
|
||||
|
||||
int pos = 0;
|
||||
|
||||
value_type p = first_;
|
||||
value_type tmp = p;
|
||||
do
|
||||
{
|
||||
tmp = p;
|
||||
p = p->GetNext();
|
||||
++pos;
|
||||
|
||||
if (p)
|
||||
{
|
||||
if (p->GetPrev() != tmp)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmp != last_)
|
||||
return false;
|
||||
}
|
||||
} while (p);
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename _IterPtrTy>
|
||||
struct Iterator
|
||||
{
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = _IterPtrTy;
|
||||
using pointer = _IterPtrTy *;
|
||||
using reference = _IterPtrTy &;
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
inline Iterator(value_type ptr = nullptr, bool is_end = false)
|
||||
: base_(ptr), is_end_(is_end)
|
||||
{
|
||||
}
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
return const_cast<reference>(base_);
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return std::pointer_traits<pointer>::pointer_to(**this);
|
||||
}
|
||||
|
||||
inline Iterator &operator++()
|
||||
{
|
||||
value_type next = base_->GetNext();
|
||||
if (next)
|
||||
base_ = next;
|
||||
else
|
||||
is_end_ = true;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline Iterator operator++(int)
|
||||
{
|
||||
Iterator old = (*this);
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
inline Iterator &operator--()
|
||||
{
|
||||
if (is_end_)
|
||||
is_end_ = false;
|
||||
else
|
||||
base_ = base_->GetPrev();
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline Iterator operator--(int)
|
||||
{
|
||||
Iterator old = (*this);
|
||||
--(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
inline bool operator==(const Iterator &other) const
|
||||
{
|
||||
return base_ == other.base_ && is_end_ == other.is_end_;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Iterator &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
inline operator bool() const
|
||||
{
|
||||
return base_ != nullptr && !is_end_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_end_;
|
||||
|
||||
typename std::remove_const<value_type>::type base_;
|
||||
};
|
||||
|
||||
public:
|
||||
using iterator = Iterator<value_type>;
|
||||
using const_iterator = Iterator<const value_type>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
inline iterator begin()
|
||||
{
|
||||
return iterator(first_, first_ == nullptr);
|
||||
}
|
||||
|
||||
inline const_iterator begin() const
|
||||
{
|
||||
return const_iterator(first_, first_ == nullptr);
|
||||
}
|
||||
|
||||
inline const_iterator cbegin() const
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
inline iterator end()
|
||||
{
|
||||
return iterator(last_, true);
|
||||
}
|
||||
|
||||
inline const_iterator end() const
|
||||
{
|
||||
return const_iterator(last_, true);
|
||||
}
|
||||
|
||||
inline const_iterator cend() const
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
inline reverse_iterator rbegin()
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
inline const_reverse_iterator rbegin() const
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
inline const_reverse_iterator crbegin() const
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
inline reverse_iterator rend()
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
inline const_reverse_iterator rend() const
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
inline const_reverse_iterator crend() const
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
inline value_type &front()
|
||||
{
|
||||
if (IsEmpty())
|
||||
throw std::out_of_range("front() called on empty list");
|
||||
return first_;
|
||||
}
|
||||
|
||||
inline const value_type &front() const
|
||||
{
|
||||
if (IsEmpty())
|
||||
throw std::out_of_range("front() called on empty list");
|
||||
return first_;
|
||||
}
|
||||
|
||||
inline value_type &back()
|
||||
{
|
||||
if (IsEmpty())
|
||||
throw std::out_of_range("back() called on empty list");
|
||||
return last_;
|
||||
}
|
||||
|
||||
inline const value_type &back() const
|
||||
{
|
||||
if (IsEmpty())
|
||||
throw std::out_of_range("back() called on empty list");
|
||||
return last_;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type first_;
|
||||
value_type last_;
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 侵入式链表元素
|
||||
template <typename _PtrTy>
|
||||
class IntrusiveListValue
|
||||
{
|
||||
public:
|
||||
using value_type = typename std::pointer_traits<_PtrTy>::pointer;
|
||||
using reference = value_type &;
|
||||
using pointer = value_type *;
|
||||
|
||||
IntrusiveListValue()
|
||||
: prev_(nullptr), next_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
IntrusiveListValue(value_type rhs)
|
||||
: prev_(nullptr), next_(nullptr)
|
||||
{
|
||||
if (rhs)
|
||||
{
|
||||
prev_ = rhs->GetPrev();
|
||||
next_ = rhs->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取前一元素
|
||||
const value_type &GetPrev() const
|
||||
{
|
||||
return prev_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取前一元素
|
||||
value_type &GetPrev()
|
||||
{
|
||||
return prev_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取下一元素
|
||||
const value_type &GetNext() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取下一元素
|
||||
value_type &GetNext()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type prev_;
|
||||
value_type next_;
|
||||
|
||||
friend class IntrusiveList<_PtrTy>;
|
||||
};
|
||||
110
source/Tool/Logger.cpp
Normal file
110
source/Tool/Logger.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "Logger.h"
|
||||
|
||||
Logger::Logger()
|
||||
: m_logFile(nullptr)
|
||||
, m_initialized(false)
|
||||
, m_originalCallback(nullptr)
|
||||
, m_originalUserdata(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool Logger::Init()
|
||||
{
|
||||
if (m_initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取当前工作目录
|
||||
char cwd[1024];
|
||||
if (getcwd(cwd, sizeof(cwd)) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 构建日志文件路径
|
||||
std::string logPath = std::string(cwd) + "/log.txt";
|
||||
|
||||
// 打开日志文件(追加模式)
|
||||
m_logFile = fopen(logPath.c_str(), "a");
|
||||
if (!m_logFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 保存原始的SDL日志回调
|
||||
SDL_LogGetOutputFunction(&m_originalCallback, &m_originalUserdata);
|
||||
|
||||
// 设置自定义的SDL日志回调
|
||||
SDL_LogSetOutputFunction(SDLLogCallback, this);
|
||||
|
||||
m_initialized = true;
|
||||
|
||||
// 使用SDL_Log写入初始化信息(这会同时输出到文件和原始目标)
|
||||
SDL_Log("Logger initialized successfully - Log file: %s", logPath.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Logger::Close()
|
||||
{
|
||||
if (m_initialized) {
|
||||
if (m_logFile) {
|
||||
SDL_Log("Logger shutting down");
|
||||
fflush(m_logFile);
|
||||
fclose(m_logFile);
|
||||
m_logFile = nullptr;
|
||||
}
|
||||
|
||||
// 恢复原始的SDL日志回调
|
||||
if (m_originalCallback) {
|
||||
SDL_LogSetOutputFunction(m_originalCallback, m_originalUserdata);
|
||||
}
|
||||
|
||||
m_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::SDLLogCallback(void* userdata, int category, SDL_LogPriority priority, const char* message)
|
||||
{
|
||||
Logger* logger = static_cast<Logger*>(userdata);
|
||||
|
||||
// 首先调用原始回调(保持控制台输出等功能)
|
||||
if (logger->m_originalCallback) {
|
||||
logger->m_originalCallback(logger->m_originalUserdata, category, priority, message);
|
||||
}
|
||||
|
||||
// 然后写入到日志文件
|
||||
if (logger->m_initialized && logger->m_logFile) {
|
||||
std::string timestamp = logger->GetCurrentTime();
|
||||
|
||||
const char* priorityStr = "UNKNOWN";
|
||||
switch (priority) {
|
||||
case SDL_LOG_PRIORITY_VERBOSE: priorityStr = "VERBOSE"; break;
|
||||
case SDL_LOG_PRIORITY_DEBUG: priorityStr = "DEBUG"; break;
|
||||
case SDL_LOG_PRIORITY_INFO: priorityStr = "INFO"; break;
|
||||
case SDL_LOG_PRIORITY_WARN: priorityStr = "WARN"; break;
|
||||
case SDL_LOG_PRIORITY_ERROR: priorityStr = "ERROR"; break;
|
||||
case SDL_LOG_PRIORITY_CRITICAL: priorityStr = "CRITICAL"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
fprintf(logger->m_logFile, "[%s][%s] %s\n", timestamp.c_str(), priorityStr, message);
|
||||
fflush(logger->m_logFile);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Logger::GetCurrentTime()
|
||||
{
|
||||
time_t rawTime;
|
||||
struct tm* timeInfo;
|
||||
char buffer[80];
|
||||
|
||||
time(&rawTime);
|
||||
timeInfo = localtime(&rawTime);
|
||||
|
||||
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeInfo);
|
||||
return std::string(buffer);
|
||||
}
|
||||
52
source/Tool/Logger.h
Normal file
52
source/Tool/Logger.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#ifdef _SWITCH_
|
||||
#include <switch.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <SDL.h>
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
Logger(const Logger &) = delete;
|
||||
Logger &operator=(const Logger &) = delete;
|
||||
Logger(Logger &&) = delete;
|
||||
Logger &operator=(Logger &&) = delete;
|
||||
|
||||
// 全局访问点
|
||||
static Logger &GetInstance()
|
||||
{
|
||||
static Logger instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public:
|
||||
// 初始化函数 - 重定向SDL_Log到日志文件
|
||||
bool Init();
|
||||
|
||||
// 关闭日志
|
||||
void Close();
|
||||
|
||||
private:
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
// SDL日志回调函数 - 将日志同时输出到文件和原始输出
|
||||
static void SDLLogCallback(void* userdata, int category, SDL_LogPriority priority, const char* message);
|
||||
|
||||
// 获取当前时间字符串
|
||||
std::string GetCurrentTime();
|
||||
|
||||
private:
|
||||
FILE* m_logFile;
|
||||
bool m_initialized;
|
||||
SDL_LogOutputFunction m_originalCallback;
|
||||
void* m_originalUserdata;
|
||||
};
|
||||
282
source/Tool/Math.h
Normal file
282
source/Tool/Math.h
Normal file
@@ -0,0 +1,282 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
class Math
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
Math(/* args */) = default;
|
||||
~Math() = default;
|
||||
|
||||
public:
|
||||
static void InitRandomSeed()
|
||||
{
|
||||
static bool seeded = false;
|
||||
if (!seeded)
|
||||
{
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
seeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 获取X轴方向(0:目标在左侧,1:目标在右侧)
|
||||
static int getDirectionToTargetX(float objX, float x)
|
||||
{
|
||||
return (objX > x) ? 0 : 1;
|
||||
}
|
||||
|
||||
// 2. 生成[Min, Max]范围内的随机整数(左闭右闭)
|
||||
static int Rand(int Min, int Max)
|
||||
{
|
||||
InitRandomSeed(); // 确保随机数种子已初始化
|
||||
if (Min > Max)
|
||||
{
|
||||
throw std::invalid_argument("Rand: Min must be less than or equal to Max");
|
||||
}
|
||||
// 计算随机数范围:(Max - Min + 1)个可能值
|
||||
int range = Max - Min + 1;
|
||||
// rand()返回[0, RAND_MAX],通过取模和偏移实现范围映射
|
||||
return Min + (rand() % range);
|
||||
}
|
||||
|
||||
// 3. 从数组中随机获取一个元素(支持任意可索引容器)
|
||||
template <typename T>
|
||||
static T GetRandomElementFromArray(const std::vector<T> &arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
{
|
||||
throw std::invalid_argument("GetRandomElementFromArray: Array is empty");
|
||||
}
|
||||
int randomIndex = Rand(0, static_cast<int>(arr.size()) - 1);
|
||||
return arr[randomIndex];
|
||||
}
|
||||
|
||||
// 5. 根据方向计算偏移后的X坐标
|
||||
static float GetDistancePos(float startX, int direction, float offsetX)
|
||||
{
|
||||
return (direction == 0) ? (startX - offsetX) : (startX + offsetX);
|
||||
}
|
||||
|
||||
// 6. 通过两点坐标计算旋转角度(预留实现,需根据具体需求补充)
|
||||
static float getRorateAngleByCurrentPos(float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
// 示例实现:计算X-Z平面内的角度(可根据需求调整为3D角度)
|
||||
float dx = x2 - x1;
|
||||
float dz = z2 - z1;
|
||||
// atan2(dz, dx):返回与X轴正方向的夹角(弧度),范围[-π, π]
|
||||
return std::atan2(dz, dx);
|
||||
}
|
||||
|
||||
// 8. 标准抛物线计算(y = a(x - c/2)² + b,开口向下)
|
||||
static float sq_Parabola(float x, float b, float c)
|
||||
{
|
||||
if (c == 0)
|
||||
{
|
||||
throw std::invalid_argument("sq_Parabola: c cannot be zero");
|
||||
}
|
||||
// 计算抛物线系数a(确保顶点在x=c/2,y=b)
|
||||
float a = (-4.0f * b) / (c * c);
|
||||
return a * (x - c / 2.0f) * (x - c / 2.0f) + b;
|
||||
}
|
||||
|
||||
// 9. 计算2D平面两点距离(Y轴权重0.29,用于透视校正)
|
||||
static float Get2D_Distance(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float offsetX = x1 - x2;
|
||||
float offsetY = (y1 - y2) * 0.29f;
|
||||
// 勾股定理计算距离
|
||||
return std::sqrt(offsetX * offsetX + offsetY * offsetY);
|
||||
}
|
||||
|
||||
// 10. 判断角度是否在[startA, endA]形成的锐角范围内(角度单位:度)
|
||||
static bool CheckAngleIsInArea(float judge, float startA, float endA)
|
||||
{
|
||||
// 步骤1:将角度标准化到[0, 360)范围
|
||||
auto normalizeAngle = [](float angle)
|
||||
{
|
||||
angle = std::fmod(angle, 360.0f);
|
||||
return (angle < 0) ? (angle + 360.0f) : angle;
|
||||
};
|
||||
|
||||
startA = normalizeAngle(startA);
|
||||
endA = normalizeAngle(endA);
|
||||
judge = normalizeAngle(judge);
|
||||
|
||||
// 特殊情况:范围跨0度(如startA=350°,endA=10°)
|
||||
if (startA > 270.0f && startA < 360.0f && endA > 0.0f && endA < 90.0f)
|
||||
{
|
||||
return (judge >= startA && judge <= 360.0f) || (judge >= 0.0f && judge <= endA);
|
||||
}
|
||||
// 普通情况:范围不跨0度
|
||||
else
|
||||
{
|
||||
// 处理startA > endA的正常范围(如startA=30°,endA=60°)
|
||||
if (startA > endA)
|
||||
{
|
||||
std::swap(startA, endA);
|
||||
}
|
||||
return (judge >= startA && judge <= endA);
|
||||
}
|
||||
}
|
||||
|
||||
// 11. 弧度转角度
|
||||
static float toDegree(float radian)
|
||||
{
|
||||
return radian * 57.2957795f; // 180/π ≈ 57.2957795
|
||||
}
|
||||
|
||||
// 12. 角度转弧度
|
||||
static float toRadian(float degree)
|
||||
{
|
||||
return degree * 0.0174532925f; // π/180 ≈ 0.0174532925
|
||||
}
|
||||
|
||||
// 13. 判断点是否在立方体内(立方体由对角点定义)
|
||||
static bool pointIsInCubeArea(float px, float py, float pz,
|
||||
float startX, float startY, float startZ,
|
||||
float endX, float endY, float endZ)
|
||||
{
|
||||
// 计算立方体中心点和半边长
|
||||
float cubeCenterX = (startX + endX) / 2.0f;
|
||||
float cubeXLen = std::fabs(startX - endX) / 2.0f;
|
||||
|
||||
float cubeCenterY = (startY + endY) / 2.0f;
|
||||
float cubeYLen = std::fabs(startY - endY) / 2.0f;
|
||||
|
||||
float cubeCenterZ = (startZ + endZ) / 2.0f;
|
||||
float cubeZLen = std::fabs(startZ - endZ) / 2.0f;
|
||||
|
||||
// 点到各轴中心点的距离 ≤ 半边长 → 在立方体内
|
||||
return (std::fabs(px - cubeCenterX) <= cubeXLen + 1e-6f) &&
|
||||
(std::fabs(py - cubeCenterY) <= cubeYLen + 1e-6f) &&
|
||||
(std::fabs(pz - cubeCenterZ) <= cubeZLen + 1e-6f);
|
||||
}
|
||||
|
||||
// 14. 立方体与立方体碰撞检测(基于顶点和中心点判断)
|
||||
static bool CubeAndCubeCollection(float c1StartX, float c1StartY, float c1StartZ,
|
||||
float c1EndX, float c1EndY, float c1EndZ,
|
||||
float c2StartX, float c2StartY, float c2StartZ,
|
||||
float c2EndX, float c2EndY, float c2EndZ)
|
||||
{
|
||||
// 优化说明:原Squirrel代码判断过多冗余点,此处保留核心顶点+中心点判断
|
||||
const std::vector<std::tuple<float, float, float>> c1Points = {
|
||||
// 立方体1的8个顶点
|
||||
{c1StartX, c1StartY, c1StartZ},
|
||||
{c1EndX, c1StartY, c1StartZ},
|
||||
{c1StartX, c1EndY, c1StartZ},
|
||||
{c1EndX, c1EndY, c1StartZ},
|
||||
{c1StartX, c1StartY, c1EndZ},
|
||||
{c1EndX, c1StartY, c1EndZ},
|
||||
{c1StartX, c1EndY, c1EndZ},
|
||||
{c1EndX, c1EndY, c1EndZ},
|
||||
// 立方体1的中心点
|
||||
{(c1StartX + c1EndX) / 2, (c1StartY + c1EndY) / 2, (c1StartZ + c1EndZ) / 2}};
|
||||
|
||||
const std::vector<std::tuple<float, float, float>> c2Points = {
|
||||
// 立方体2的8个顶点
|
||||
{c2StartX, c2StartY, c2StartZ},
|
||||
{c2EndX, c2StartY, c2StartZ},
|
||||
{c2StartX, c2EndY, c2StartZ},
|
||||
{c2EndX, c2EndY, c2StartZ},
|
||||
{c2StartX, c2StartY, c2EndZ},
|
||||
{c2EndX, c2StartY, c2EndZ},
|
||||
{c2StartX, c2EndY, c2EndZ},
|
||||
{c2EndX, c2EndY, c2EndZ},
|
||||
// 立方体2的中心点
|
||||
{(c2StartX + c2EndX) / 2, (c2StartY + c2EndY) / 2, (c2StartZ + c2EndZ) / 2}};
|
||||
|
||||
// 检查立方体1的点是否在立方体2内
|
||||
for (const auto &[x, y, z] : c1Points)
|
||||
{
|
||||
if (pointIsInCubeArea(x, y, z, c2StartX, c2StartY, c2StartZ, c2EndX, c2EndY, c2EndZ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查立方体2的点是否在立方体1内
|
||||
for (const auto &[x, y, z] : c2Points)
|
||||
{
|
||||
if (pointIsInCubeArea(x, y, z, c1StartX, c1StartY, c1StartZ, c1EndX, c1EndY, c1EndZ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 15. 计算三角形面积(叉乘法,避免开方,效率更高)
|
||||
static float get3PointArea(float x1, float y1, float x2, float y2, float x3, float y3)
|
||||
{
|
||||
// 面积公式:0.5 * |x1(y2-y3) + x2(y3-y1) + x3(y1-y2)|
|
||||
return 0.5f * std::fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2));
|
||||
}
|
||||
|
||||
// 16. 计算四边形面积(拆分为两个三角形面积之和)
|
||||
static float get4PointArea(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
|
||||
{
|
||||
// 四边形拆分为:(x1,y1)-(x2,y2)-(x3,y3) 和 (x2,y2)-(x3,y3)-(x4,y4)
|
||||
float area1 = get3PointArea(x1, y1, x2, y2, x3, y3);
|
||||
float area2 = get3PointArea(x2, y2, x3, y3, x4, y4);
|
||||
return area1 + area2;
|
||||
}
|
||||
|
||||
// 17. 判断点是否在四边形内(面积比较法,要求四边形顶点按顺序排列)
|
||||
static bool pointIsIn4PointArea(float px, float py,
|
||||
float x1, float y1, float x2, float y2,
|
||||
float x3, float y3, float x4, float y4)
|
||||
{
|
||||
const float eps = 10.0f; // 容差(原Squirrel代码定义为10.0)
|
||||
float totalArea = get4PointArea(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
// 点与四边形各边组成的4个三角形面积之和
|
||||
float sumArea = get3PointArea(x1, y1, x2, y2, px, py) +
|
||||
get3PointArea(x2, y2, x3, y3, px, py) +
|
||||
get3PointArea(x3, y3, x4, y4, px, py) +
|
||||
get3PointArea(x4, y4, x1, y1, px, py);
|
||||
|
||||
// 面积差在容差范围内 → 点在四边形内
|
||||
return std::fabs(totalArea - sumArea) < eps;
|
||||
}
|
||||
|
||||
// 18. 判断点是否在矩形内(矩形由坐标数组定义,格式:[x, y, width, height])
|
||||
static bool PointIsInSquare(float x1, float y1, const std::vector<float> &SquareArr)
|
||||
{
|
||||
if (SquareArr.size() != 4)
|
||||
{
|
||||
throw std::invalid_argument("PointIsInSquare: SquareArr must have 4 elements (x, y, width, height)");
|
||||
}
|
||||
float sqX = SquareArr[0];
|
||||
float sqY = SquareArr[1];
|
||||
float sqWidth = SquareArr[2];
|
||||
float sqHeight = SquareArr[3];
|
||||
|
||||
// 点的X在[sqX, sqX+width],Y在[sqY, sqY+height] → 在矩形内
|
||||
return (x1 >= sqX - 1e-6f) && (x1 <= sqX + sqWidth + 1e-6f) &&
|
||||
(y1 >= sqY - 1e-6f) && (y1 <= sqY + sqHeight + 1e-6f);
|
||||
}
|
||||
|
||||
static float getUniformVelocity(float sv, float ev, float currentRate, float maxRate)
|
||||
{
|
||||
// 避免除零错误
|
||||
if (maxRate <= 0.0f)
|
||||
{
|
||||
throw std::invalid_argument("maxRate must be greater than 0");
|
||||
}
|
||||
|
||||
// 计算当前进度比例(0.0到1.0之间)
|
||||
float rate = currentRate / maxRate;
|
||||
// 限制比例在[0, 1]范围内,避免超出边界
|
||||
rate = std::clamp(rate, 0.0f, 1.0f);
|
||||
|
||||
// 计算变化量并返回当前值
|
||||
float varyValue = ev - sv;
|
||||
return sv + varyValue * rate;
|
||||
}
|
||||
};
|
||||
257
source/Tool/RefBasePtr.hpp
Normal file
257
source/Tool/RefBasePtr.hpp
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright (c) 2016-2018 Kiwano - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include "Tool/Common.h"
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 引用计数智能指针
|
||||
*/
|
||||
template <typename _Ty, typename _RefPolicy>
|
||||
class RefBasePtr : protected _RefPolicy
|
||||
{
|
||||
public:
|
||||
using value_type = _Ty;
|
||||
using pointer_type = _Ty *;
|
||||
using const_pointer_type = const _Ty *;
|
||||
using reference_type = _Ty &;
|
||||
using const_reference_type = const _Ty &;
|
||||
|
||||
RefBasePtr() noexcept
|
||||
: ptr_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
RefBasePtr(std::nullptr_t) noexcept
|
||||
: ptr_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
RefBasePtr(pointer_type p)
|
||||
: ptr_(p)
|
||||
{
|
||||
_RefPolicy::Retain(ptr_);
|
||||
}
|
||||
|
||||
RefBasePtr(const RefBasePtr &other)
|
||||
: ptr_(other.ptr_)
|
||||
{
|
||||
_RefPolicy::Retain(ptr_);
|
||||
}
|
||||
|
||||
RefBasePtr(RefBasePtr &&other) noexcept
|
||||
: ptr_(nullptr)
|
||||
{
|
||||
Swap(other);
|
||||
}
|
||||
|
||||
~RefBasePtr()
|
||||
{
|
||||
Tidy();
|
||||
}
|
||||
|
||||
template <typename _UTy, typename std::enable_if<std::is_convertible<_UTy *, _Ty *>::value, int>::type = 0>
|
||||
RefBasePtr(const RefBasePtr<_UTy, _RefPolicy> &other)
|
||||
{
|
||||
ptr_ = dynamic_cast<pointer_type>(other.Get());
|
||||
_RefPolicy::Retain(ptr_);
|
||||
}
|
||||
|
||||
inline pointer_type Get() const noexcept
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline pointer_type *GetAddressOfAndRelease()
|
||||
{
|
||||
Tidy();
|
||||
return &ptr_;
|
||||
}
|
||||
|
||||
inline void Reset(pointer_type ptr = nullptr)
|
||||
{
|
||||
if (ptr)
|
||||
RefBasePtr(ptr).Swap(*this);
|
||||
else
|
||||
Tidy();
|
||||
}
|
||||
|
||||
inline void Swap(RefBasePtr &other) noexcept
|
||||
{
|
||||
std::swap(ptr_, other.ptr_);
|
||||
}
|
||||
|
||||
inline pointer_type operator->()
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline const_pointer_type operator->() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline reference_type operator*()
|
||||
{
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
inline const_reference_type operator*() const
|
||||
{
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
inline pointer_type *operator&()
|
||||
{
|
||||
return this->GetAddressOfAndRelease();
|
||||
}
|
||||
|
||||
inline operator bool() const noexcept
|
||||
{
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
|
||||
inline bool operator!() const noexcept
|
||||
{
|
||||
return ptr_ == 0;
|
||||
}
|
||||
|
||||
inline RefBasePtr &operator=(const RefBasePtr &other)
|
||||
{
|
||||
if (other.ptr_ != ptr_)
|
||||
RefBasePtr(other).Swap(*this);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline RefBasePtr &operator=(RefBasePtr &&other) noexcept
|
||||
{
|
||||
if (other.ptr_ != ptr_)
|
||||
other.Swap(*this);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline RefBasePtr &operator=(pointer_type p)
|
||||
{
|
||||
if (p != ptr_)
|
||||
RefBasePtr(p).Swap(*this);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
template <typename _UTy, typename std::enable_if<std::is_convertible<_UTy *, _Ty *>::value, int>::type = 0>
|
||||
inline RefBasePtr &operator=(const RefBasePtr<_UTy, _RefPolicy> &other)
|
||||
{
|
||||
if (other.Get() != ptr_)
|
||||
RefBasePtr(dynamic_cast<pointer_type>(other.Get())).Swap(*this);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline RefBasePtr &operator=(std::nullptr_t)
|
||||
{
|
||||
Tidy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void Tidy()
|
||||
{
|
||||
_RefPolicy::Release(ptr_);
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
pointer_type ptr_;
|
||||
};
|
||||
|
||||
template <class _Ty, class _UTy, class _RefPolicy>
|
||||
inline bool operator==(const RefBasePtr<_Ty, _RefPolicy> &lhs, const RefBasePtr<_UTy, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return lhs.Get() == rhs.Get();
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator==(const RefBasePtr<_Ty, _RefPolicy> &lhs, _Ty *rhs) noexcept
|
||||
{
|
||||
return lhs.Get() == rhs;
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator==(_Ty *lhs, const RefBasePtr<_Ty, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return lhs == rhs.Get();
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator==(const RefBasePtr<_Ty, _RefPolicy> &lhs, std::nullptr_t) noexcept
|
||||
{
|
||||
return !static_cast<bool>(lhs);
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator==(std::nullptr_t, const RefBasePtr<_Ty, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return !static_cast<bool>(rhs);
|
||||
}
|
||||
|
||||
template <class _Ty, class _UTy, class _RefPolicy>
|
||||
inline bool operator!=(const RefBasePtr<_Ty, _RefPolicy> &lhs, const RefBasePtr<_UTy, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator!=(const RefBasePtr<_Ty, _RefPolicy> &lhs, _Ty *rhs) noexcept
|
||||
{
|
||||
return lhs.Get() != rhs;
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator!=(_Ty *lhs, const RefBasePtr<_Ty, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return lhs != rhs.Get();
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator!=(const RefBasePtr<_Ty, _RefPolicy> &lhs, std::nullptr_t) noexcept
|
||||
{
|
||||
return static_cast<bool>(lhs);
|
||||
}
|
||||
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline bool operator!=(std::nullptr_t, const RefBasePtr<_Ty, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return static_cast<bool>(rhs);
|
||||
}
|
||||
|
||||
template <class _Ty, class _UTy, class _RefPolicy>
|
||||
inline bool operator<(const RefBasePtr<_Ty, _RefPolicy> &lhs, const RefBasePtr<_UTy, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
return lhs.Get() < rhs.Get();
|
||||
}
|
||||
|
||||
// template class cannot specialize std::swap,
|
||||
// so implement a swap function in kiwano namespace
|
||||
template <class _Ty, class _RefPolicy>
|
||||
inline void swap(RefBasePtr<_Ty, _RefPolicy> &lhs, RefBasePtr<_Ty, _RefPolicy> &rhs) noexcept
|
||||
{
|
||||
lhs.Swap(rhs);
|
||||
}
|
||||
86
source/Tool/RefObject.cpp
Normal file
86
source/Tool/RefObject.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "Tool/RefObject.h"
|
||||
|
||||
RefObject::RefObject()
|
||||
: ref_count_(0) // 修正:新创建对象引用计数应为1
|
||||
{
|
||||
}
|
||||
|
||||
RefObject::~RefObject() {}
|
||||
|
||||
void RefObject::Retain()
|
||||
{
|
||||
// 修正:使用fetch_add确保原子操作
|
||||
ref_count_.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void RefObject::Release()
|
||||
{
|
||||
// 修正:使用fetch_sub确保原子操作并检查结果
|
||||
if (ref_count_.fetch_sub(1, std::memory_order_acq_rel) == 1)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RefObject::GetRefCount() const
|
||||
{
|
||||
return ref_count_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void *RefObject::operator new(size_t size)
|
||||
{
|
||||
void *ptr = memory::Alloc(size);
|
||||
if (!ptr)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void RefObject::operator delete(void *ptr)
|
||||
{
|
||||
if (ptr) // 增加空指针检查
|
||||
{
|
||||
memory::Free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// 修正:添加noexcept说明符,与声明一致
|
||||
void *RefObject::operator new(size_t size, std::nothrow_t const &) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return memory::Alloc(size);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// 修正:添加noexcept说明符,与声明一致
|
||||
void RefObject::operator delete(void *ptr, std::nothrow_t const &) noexcept
|
||||
{
|
||||
if (ptr) // 增加空指针检查
|
||||
{
|
||||
try
|
||||
{
|
||||
memory::Free(ptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// 忽略异常,符合noexcept语义
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修正:添加noexcept说明符,与声明一致
|
||||
void *RefObject::operator new(size_t size, void *ptr) noexcept
|
||||
{
|
||||
return ::operator new(size, ptr);
|
||||
}
|
||||
|
||||
void RefObject::operator delete(void *ptr, void *place) noexcept
|
||||
{
|
||||
::operator delete(ptr, place);
|
||||
}
|
||||
45
source/Tool/RefObject.h
Normal file
45
source/Tool/RefObject.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tool/Common.h"
|
||||
#include "Tool/Allocator.h"
|
||||
#include <atomic>
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 引用计数器
|
||||
*/
|
||||
class RefObject : protected Noncopyable
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 增加引用计数
|
||||
void Retain();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 减少引用计数
|
||||
void Release();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取引用计数
|
||||
uint32_t GetRefCount() const;
|
||||
|
||||
static void *operator new(size_t size);
|
||||
|
||||
static void operator delete(void *ptr);
|
||||
|
||||
static void *operator new(size_t size, std::nothrow_t const &) noexcept;
|
||||
|
||||
static void operator delete(void *ptr, std::nothrow_t const &) noexcept;
|
||||
|
||||
static void *operator new(size_t size, void *ptr) noexcept;
|
||||
|
||||
static void operator delete(void *ptr, void *place) noexcept;
|
||||
|
||||
virtual ~RefObject();
|
||||
|
||||
protected:
|
||||
RefObject();
|
||||
|
||||
private:
|
||||
std::atomic<uint32_t> ref_count_;
|
||||
};
|
||||
63
source/Tool/RefPtr.h
Normal file
63
source/Tool/RefPtr.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2016-2018 Kiwano - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Tool/RefObject.h"
|
||||
#include "Tool/RefBasePtr.hpp"
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 默认的智能指针引用计数策略
|
||||
struct DefaultRefPtrPolicy
|
||||
{
|
||||
inline void Retain(RefObject *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
ptr->Retain();
|
||||
}
|
||||
|
||||
inline void Release(RefObject *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
ptr->Release();
|
||||
}
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 引用计数对象智能指针
|
||||
template <typename _Ty>
|
||||
using RefPtr = RefBasePtr<_Ty, DefaultRefPtrPolicy>;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造引用计数对象智能指针
|
||||
template <typename _Ty, typename... _Args>
|
||||
inline RefPtr<_Ty> MakePtr(_Args &&...args)
|
||||
{
|
||||
static_assert(std::is_base_of<RefObject, _Ty>::value, "_Ty must be derived from RefObject");
|
||||
return RefPtr<_Ty>(new _Ty(std::forward<_Args>(args)...));
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造引用计数对象智能指针
|
||||
template <typename _Ty>
|
||||
inline RefPtr<_Ty> MakePtr(_Ty *ptr)
|
||||
{
|
||||
static_assert(std::is_base_of<RefObject, _Ty>::value, "_Ty must be derived from RefObject");
|
||||
return RefPtr<_Ty>(ptr);
|
||||
}
|
||||
67
source/Tool/TagGed.h
Normal file
67
source/Tool/TagGed.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
enum class Tag
|
||||
{
|
||||
NONE = 0, // 无标签
|
||||
SCENE = 1 << 0, // 场景标签
|
||||
ACTOR = 1 << 1, // 角色标签
|
||||
COMPONENT = 1 << 2, // 组件标签
|
||||
UPDATE = 1 << 3, // 更新标签
|
||||
RENDER = 1 << 4, // 渲染标签
|
||||
TRANSFORM = 1 << 5, // 变换标签
|
||||
HANDEL_EVENT = 1 << 6, // 事件处理标签
|
||||
};
|
||||
|
||||
constexpr Tag operator|(Tag a, Tag b)
|
||||
{
|
||||
using Underlying = std::underlying_type_t<Tag>;
|
||||
return static_cast<Tag>(static_cast<Underlying>(a) | static_cast<Underlying>(b));
|
||||
}
|
||||
|
||||
constexpr Tag operator&(Tag a, Tag b)
|
||||
{
|
||||
using Underlying = std::underlying_type_t<Tag>;
|
||||
return static_cast<Tag>(static_cast<Underlying>(a) & static_cast<Underlying>(b));
|
||||
}
|
||||
class TagGed
|
||||
{
|
||||
private:
|
||||
uint64_t m_tags;
|
||||
|
||||
public:
|
||||
TagGed(Tag initialTag = Tag::NONE)
|
||||
: m_tags(static_cast<uint64_t>(initialTag)) {}
|
||||
|
||||
// 添加标签
|
||||
void addTag(Tag tag)
|
||||
{
|
||||
if (!hasTag(tag))
|
||||
m_tags |= static_cast<uint64_t>(tag);
|
||||
}
|
||||
|
||||
// 移除标签
|
||||
void removeTag(Tag tag)
|
||||
{
|
||||
if (hasTag(tag))
|
||||
m_tags &= ~static_cast<uint64_t>(tag);
|
||||
}
|
||||
|
||||
// 判断是否包含指定标签
|
||||
bool hasTag(Tag tag) const
|
||||
{
|
||||
return (m_tags & static_cast<uint64_t>(tag)) != 0;
|
||||
}
|
||||
|
||||
// 判断是否包含所有指定标签
|
||||
bool hasAllTags(Tag tags) const
|
||||
{
|
||||
return (m_tags & static_cast<uint64_t>(tags)) == static_cast<uint64_t>(tags);
|
||||
}
|
||||
|
||||
// 清除所有标签
|
||||
void clearTags()
|
||||
{
|
||||
m_tags = 0;
|
||||
}
|
||||
};
|
||||
96
source/Tool/ThreadPool.cpp
Normal file
96
source/Tool/ThreadPool.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "ThreadPool.h"
|
||||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
|
||||
// 获取单例实例
|
||||
ThreadPool &ThreadPool::GetInstance()
|
||||
{
|
||||
static ThreadPool instance(3); // 固定3个工作线程
|
||||
return instance;
|
||||
}
|
||||
|
||||
ThreadPool::~ThreadPool()
|
||||
{
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void ThreadPool::shutdown()
|
||||
{
|
||||
printf("ThreadPool destroyed\n");
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(queue_mutex);
|
||||
stop = true;
|
||||
// 清空所有线程的任务队列
|
||||
for (auto &queue : threadTasks)
|
||||
{
|
||||
// 使用swap技巧清空队列
|
||||
std::queue<std::function<void()>> empty;
|
||||
std::swap(queue, empty);
|
||||
}
|
||||
}
|
||||
|
||||
// 通知所有线程
|
||||
for (auto &cond : threadConditions)
|
||||
cond->notify_all();
|
||||
|
||||
for (std::thread &worker : workers)
|
||||
if (worker.joinable())
|
||||
worker.join();
|
||||
|
||||
// 释放条件变量
|
||||
for (auto &cond : threadConditions)
|
||||
delete cond;
|
||||
}
|
||||
|
||||
// 获取线程池大小
|
||||
size_t ThreadPool::size() const
|
||||
{
|
||||
return workers.size();
|
||||
}
|
||||
|
||||
// 获取指定线程的负载(待处理任务数)
|
||||
size_t ThreadPool::getThreadLoad(int threadId) const
|
||||
{
|
||||
if (threadId < 0 || threadId >= static_cast<int>(workers.size()))
|
||||
throw std::runtime_error("Invalid thread ID");
|
||||
|
||||
std::unique_lock<std::mutex> lock(queue_mutex);
|
||||
return threadTasks.at(threadId).size();
|
||||
}
|
||||
|
||||
// 私有构造函数实现
|
||||
ThreadPool::ThreadPool(size_t numThreads) : stop(false)
|
||||
{
|
||||
// 为每个线程创建任务队列
|
||||
threadTasks.resize(numThreads);
|
||||
|
||||
// 为每个线程创建条件变量
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
threadConditions.push_back(new std::condition_variable());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
workers.emplace_back([this, i]
|
||||
{
|
||||
while(true) {
|
||||
std::function<void()> task;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
||||
this->threadConditions[i]->wait(lock, [this, i] {
|
||||
return this->stop || !this->threadTasks[i].empty();
|
||||
});
|
||||
|
||||
if(this->stop && this->threadTasks[i].empty())
|
||||
return;
|
||||
|
||||
task = std::move(this->threadTasks[i].front());
|
||||
this->threadTasks[i].pop();
|
||||
}
|
||||
|
||||
task();
|
||||
} });
|
||||
}
|
||||
}
|
||||
80
source/Tool/ThreadPool.h
Normal file
80
source/Tool/ThreadPool.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
// 获取单例实例
|
||||
static ThreadPool &GetInstance();
|
||||
|
||||
// 删除拷贝构造函数和赋值运算符
|
||||
ThreadPool(const ThreadPool &) = delete;
|
||||
ThreadPool &operator=(const ThreadPool &) = delete;
|
||||
|
||||
// 向指定线程添加任务
|
||||
template <class F, class... Args>
|
||||
void enqueueToThread(int threadId, F &&f, Args &&...args)
|
||||
{
|
||||
if (threadId < 0 || threadId >= static_cast<int>(workers.size()))
|
||||
throw std::runtime_error("Invalid thread ID");
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(queue_mutex);
|
||||
|
||||
// 不允许在停止后添加新任务
|
||||
if (stop)
|
||||
throw std::runtime_error("enqueue on stopped ThreadPool");
|
||||
|
||||
// 将任务添加到指定线程的队列
|
||||
threadTasks[threadId].emplace([=]() mutable
|
||||
{ std::invoke(f, args...); });
|
||||
}
|
||||
|
||||
// 通知指定线程
|
||||
threadConditions[threadId]->notify_one();
|
||||
}
|
||||
|
||||
// 向任意线程添加任务(负载均衡)
|
||||
template <class F, class... Args>
|
||||
void enqueue(F &&f, Args &&...args)
|
||||
{
|
||||
// 使用轮询方式选择线程
|
||||
static std::atomic<int> nextThreadId(0);
|
||||
int threadId = nextThreadId.load();
|
||||
nextThreadId = (nextThreadId + 1) % workers.size();
|
||||
|
||||
enqueueToThread(threadId, std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
~ThreadPool();
|
||||
|
||||
void shutdown();
|
||||
|
||||
// 获取线程池大小
|
||||
size_t size() const;
|
||||
|
||||
// 获取指定线程的负载(待处理任务数)
|
||||
size_t getThreadLoad(int threadId) const;
|
||||
|
||||
private:
|
||||
// 私有构造函数
|
||||
ThreadPool(size_t numThreads);
|
||||
|
||||
private:
|
||||
std::vector<std::thread> workers;
|
||||
std::vector<std::queue<std::function<void()>>> threadTasks; // 每个线程有自己的任务队列
|
||||
|
||||
mutable std::mutex queue_mutex;
|
||||
std::vector<std::condition_variable *> threadConditions; // 使用指针存储条件变量
|
||||
std::atomic<bool> stop;
|
||||
};
|
||||
82
source/Tool/Tool_Network.cpp
Normal file
82
source/Tool/Tool_Network.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "Tool/Tool_Network.h"
|
||||
|
||||
// // 定义内存管理结构体
|
||||
// struct MemoryStruct
|
||||
// {
|
||||
// char *memory;
|
||||
// size_t size;
|
||||
// };
|
||||
|
||||
// size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
// {
|
||||
// size_t realsize = size * nmemb;
|
||||
// struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
||||
|
||||
// void *ptr = realloc(mem->memory, mem->size + realsize + 1);
|
||||
// if (!ptr)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// mem->memory = (char *)ptr;
|
||||
// memcpy(&(mem->memory[mem->size]), contents, realsize);
|
||||
// mem->size += realsize;
|
||||
// mem->memory[mem->size] = '\0';
|
||||
|
||||
// return realsize;
|
||||
// }
|
||||
|
||||
// int http_get(const char *url, char **response, size_t *response_size)
|
||||
// {
|
||||
// CURL *curl;
|
||||
// CURLcode res;
|
||||
// struct MemoryStruct chunk;
|
||||
|
||||
// // 初始化内存结构
|
||||
// chunk.memory = (char *)malloc(1);
|
||||
// chunk.size = 0;
|
||||
// if (!chunk.memory)
|
||||
// {
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// curl = curl_easy_init();
|
||||
// if (curl)
|
||||
// {
|
||||
// curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
// curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
// curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||
|
||||
// // 允许重定向
|
||||
// curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
// curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L);
|
||||
|
||||
// // 执行请求
|
||||
// res = curl_easy_perform(curl);
|
||||
|
||||
// // 检查HTTP状态码
|
||||
// long response_code;
|
||||
// curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
|
||||
// if (res != CURLE_OK)
|
||||
// {
|
||||
// free(chunk.memory);
|
||||
// *response = NULL;
|
||||
// *response_size = 0;
|
||||
// curl_easy_cleanup(curl);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// // 返回结果
|
||||
// *response = chunk.memory;
|
||||
// *response_size = chunk.size;
|
||||
|
||||
// curl_easy_cleanup(curl);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// free(chunk.memory);
|
||||
// *response = NULL;
|
||||
// *response_size = 0;
|
||||
// return -1;
|
||||
// }
|
||||
16
source/Tool/Tool_Network.h
Normal file
16
source/Tool/Tool_Network.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _SWITCH_
|
||||
#include <switch.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "Tool/Logger.h"
|
||||
|
||||
// // 回调函数
|
||||
// size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp);
|
||||
|
||||
// // HTTP GET请求函数
|
||||
// int http_get(const char *url, char **response, size_t *response_size);
|
||||
88
source/Tool/Tool_String.cpp
Normal file
88
source/Tool/Tool_String.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "Tool/Tool_String.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <iconv.h>
|
||||
#include <regex>
|
||||
#include "Tool_String.h"
|
||||
std::string Tool_toLowerCase(const std::string &str)
|
||||
{
|
||||
std::string result = str;
|
||||
// 使用transform算法遍历字符串并转换为小写
|
||||
std::transform(result.begin(), result.end(), result.begin(),
|
||||
[](unsigned char c)
|
||||
{ return std::tolower(c); });
|
||||
return result;
|
||||
}
|
||||
// GBK 转 UTF-8(基于 SDL2 的 SDL_iconv)
|
||||
std::string Tool_Gbk2Utf8(const std::string &gbk_str)
|
||||
{
|
||||
iconv_t cd = iconv_open("UTF-8", "GBK");
|
||||
if (cd == (iconv_t)-1)
|
||||
{
|
||||
throw std::runtime_error("Failed to open iconv conversion descriptor");
|
||||
}
|
||||
|
||||
size_t in_bytes_left = gbk_str.size();
|
||||
char *in_buf = const_cast<char *>(gbk_str.data());
|
||||
|
||||
// 分配输出缓冲区(GBK转UTF-8后长度最多可能增长到原长的3倍)
|
||||
size_t out_bytes_left = gbk_str.size() * 3 + 1;
|
||||
std::string utf8_str(out_bytes_left, '\0');
|
||||
char *out_buf = &utf8_str[0];
|
||||
|
||||
// 执行转换
|
||||
size_t result = iconv(cd, &in_buf, &in_bytes_left, &out_buf, &out_bytes_left);
|
||||
iconv_close(cd);
|
||||
|
||||
if (result == (size_t)-1)
|
||||
{
|
||||
throw std::runtime_error("Conversion failed!");
|
||||
}
|
||||
|
||||
// 调整字符串大小以去除未使用的空间
|
||||
utf8_str.resize(utf8_str.size() - out_bytes_left);
|
||||
return utf8_str;
|
||||
}
|
||||
|
||||
std::string Tool_RegRealPath(const std::string &Path)
|
||||
{
|
||||
// 检查路径中是否包含"../"
|
||||
if (Path.find("../") == std::string::npos)
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
|
||||
// 正则表达式:匹配形如"xxx/../"的模式
|
||||
// [^/]+ 匹配非斜杠的字符序列(表示目录名)
|
||||
// /../ 匹配"/../"
|
||||
std::regex pattern("[^/]+/\\.\\./");
|
||||
|
||||
std::string processedPath = Path;
|
||||
std::smatch match;
|
||||
|
||||
// 循环处理所有匹配的模式
|
||||
while (std::regex_search(processedPath, match, pattern))
|
||||
{
|
||||
// 替换匹配到的部分(删除"xxx/../")
|
||||
processedPath = std::regex_replace(processedPath, pattern, "", std::regex_constants::format_first_only);
|
||||
}
|
||||
|
||||
return processedPath;
|
||||
}
|
||||
|
||||
std::string Tool_TruncatePath(const std::string &path)
|
||||
{
|
||||
// 查找最后一个 '/' 的位置
|
||||
size_t lastSlashPos = path.find_last_of('/');
|
||||
|
||||
// 如果找到了 '/',返回从开始到该位置(包含)的子串
|
||||
if (lastSlashPos != std::string::npos)
|
||||
{
|
||||
return path.substr(0, lastSlashPos + 1); // +1 是为了包含 '/' 本身
|
||||
}
|
||||
|
||||
// 如果没有找到 '/',返回原字符串(或根据需求返回空)
|
||||
return path;
|
||||
}
|
||||
12
source/Tool/Tool_String.h
Normal file
12
source/Tool/Tool_String.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
||||
std::string Tool_toLowerCase(const std::string &str);
|
||||
|
||||
std::string Tool_Gbk2Utf8(const std::string &gbk_str);
|
||||
|
||||
std::string Tool_RegRealPath(const std::string &Path);
|
||||
|
||||
std::string Tool_TruncatePath(const std::string &path);
|
||||
52
source/Tool/TransformT.cpp
Normal file
52
source/Tool/TransformT.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "TransformT.h"
|
||||
|
||||
TransformT::TransformT()
|
||||
: rotation(0.f), position(), scale(1.f, 1.f)
|
||||
{
|
||||
}
|
||||
|
||||
bool TransformT::IsFast() const
|
||||
{
|
||||
return scale.x == 1.f && scale.y == 1.f && rotation == 0.f;
|
||||
}
|
||||
|
||||
bool TransformT::operator==(const TransformT &rhs) const
|
||||
{
|
||||
return position == rhs.position && rotation == rhs.rotation && scale == rhs.scale;
|
||||
}
|
||||
|
||||
// -------------------------- 加法运算符实现 --------------------------
|
||||
TransformT TransformT::operator+(const TransformT &rhs) const
|
||||
{
|
||||
TransformT result;
|
||||
result.rotation = this->rotation + rhs.rotation;
|
||||
result.position = this->position + rhs.position;
|
||||
result.scale = this->scale + rhs.scale;
|
||||
return result;
|
||||
}
|
||||
|
||||
TransformT TransformT::operator-(const TransformT &rhs) const
|
||||
{
|
||||
TransformT result;
|
||||
result.rotation = this->rotation - rhs.rotation;
|
||||
result.position = this->position - rhs.position;
|
||||
result.scale = this->scale - rhs.scale;
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------- 复合赋值运算符实现 --------------------------
|
||||
TransformT &TransformT::operator+=(const TransformT &rhs)
|
||||
{
|
||||
this->rotation += rhs.rotation;
|
||||
this->position += rhs.position;
|
||||
this->scale += rhs.scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TransformT &TransformT::operator-=(const TransformT &rhs)
|
||||
{
|
||||
this->rotation -= rhs.rotation;
|
||||
this->position -= rhs.position;
|
||||
this->scale -= rhs.scale;
|
||||
return *this;
|
||||
}
|
||||
25
source/Tool/TransformT.h
Normal file
25
source/Tool/TransformT.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "Tool/Common.h"
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 二维放射变换
|
||||
*/
|
||||
class TransformT
|
||||
{
|
||||
public:
|
||||
float rotation; ///< 旋转
|
||||
VecFPos position; ///< 坐标
|
||||
VecFPos scale; ///< 缩放
|
||||
|
||||
public:
|
||||
TransformT();
|
||||
|
||||
bool IsFast() const;
|
||||
|
||||
bool operator==(const TransformT &rhs) const;
|
||||
|
||||
TransformT operator+(const TransformT &rhs) const;
|
||||
TransformT operator-(const TransformT &rhs) const;
|
||||
TransformT &operator+=(const TransformT &rhs);
|
||||
TransformT &operator-=(const TransformT &rhs);
|
||||
};
|
||||
Reference in New Issue
Block a user