feat: 实现Containers、Memory、Threading核心模块及单元测试
- Containers: String, Array, HashMap 容器实现及测试 - Memory: Allocator, LinearAllocator, PoolAllocator, ProxyAllocator, MemoryManager 实现及测试 - Threading: Mutex, SpinLock, ReadWriteLock, Thread, Task, TaskSystem 实现及测试 - 修复Windows平台兼容性: _aligned_malloc, std::hash特化 - 修复构建错误和测试用例问题
This commit is contained in:
327
engine/src/Containers/String.cpp
Normal file
327
engine/src/Containers/String.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
#include "Containers/String.h"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Containers {
|
||||
|
||||
String::String() : m_data(nullptr), m_length(0), m_capacity(0) {
|
||||
m_data = new char[1];
|
||||
m_data[0] = '\0';
|
||||
m_capacity = 1;
|
||||
}
|
||||
|
||||
String::String(const char* str) {
|
||||
if (str) {
|
||||
m_length = std::strlen(str);
|
||||
m_capacity = m_length + 1;
|
||||
m_data = new char[m_capacity];
|
||||
std::memcpy(m_data, str, m_length + 1);
|
||||
} else {
|
||||
m_data = new char[1];
|
||||
m_data[0] = '\0';
|
||||
m_length = 0;
|
||||
m_capacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
String::String(const char* str, SizeType len) {
|
||||
if (str && len > 0) {
|
||||
m_length = len;
|
||||
m_capacity = m_length + 1;
|
||||
m_data = new char[m_capacity];
|
||||
std::memcpy(m_data, str, m_length);
|
||||
m_data[m_length] = '\0';
|
||||
} else {
|
||||
m_data = new char[1];
|
||||
m_data[0] = '\0';
|
||||
m_length = 0;
|
||||
m_capacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
String::String(const String& other) {
|
||||
m_length = other.m_length;
|
||||
m_capacity = m_length + 1;
|
||||
m_data = new char[m_capacity];
|
||||
std::memcpy(m_data, other.m_data, m_length + 1);
|
||||
}
|
||||
|
||||
String::String(String&& other) noexcept {
|
||||
m_data = other.m_data;
|
||||
m_length = other.m_length;
|
||||
m_capacity = other.m_capacity;
|
||||
|
||||
other.m_data = nullptr;
|
||||
other.m_length = 0;
|
||||
other.m_capacity = 0;
|
||||
}
|
||||
|
||||
String::~String() {
|
||||
Deallocate();
|
||||
}
|
||||
|
||||
String& String::operator=(const String& other) {
|
||||
if (this != &other) {
|
||||
if (other.m_length + 1 > m_capacity) {
|
||||
Deallocate();
|
||||
Allocate(other.m_length + 1);
|
||||
}
|
||||
m_length = other.m_length;
|
||||
std::memcpy(m_data, other.m_data, m_length + 1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator=(String&& other) noexcept {
|
||||
if (this != &other) {
|
||||
Deallocate();
|
||||
m_data = other.m_data;
|
||||
m_length = other.m_length;
|
||||
m_capacity = other.m_capacity;
|
||||
|
||||
other.m_data = nullptr;
|
||||
other.m_length = 0;
|
||||
other.m_capacity = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator=(const char* str) {
|
||||
if (str) {
|
||||
SizeType len = std::strlen(str);
|
||||
if (len + 1 > m_capacity) {
|
||||
Deallocate();
|
||||
Allocate(len + 1);
|
||||
}
|
||||
m_length = len;
|
||||
std::memcpy(m_data, str, m_length + 1);
|
||||
} else {
|
||||
Clear();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator+=(const String& other) {
|
||||
if (other.m_length > 0) {
|
||||
SizeType newLength = m_length + other.m_length;
|
||||
if (newLength + 1 > m_capacity) {
|
||||
char* newData = new char[newLength + 1];
|
||||
std::memcpy(newData, m_data, m_length);
|
||||
delete[] m_data;
|
||||
m_data = newData;
|
||||
m_capacity = newLength + 1;
|
||||
}
|
||||
std::memcpy(m_data + m_length, other.m_data, other.m_length + 1);
|
||||
m_length = newLength;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator+=(const char* str) {
|
||||
if (str) {
|
||||
SizeType len = std::strlen(str);
|
||||
if (len > 0) {
|
||||
SizeType newLength = m_length + len;
|
||||
if (newLength + 1 > m_capacity) {
|
||||
char* newData = new char[newLength + 1];
|
||||
std::memcpy(newData, m_data, m_length);
|
||||
delete[] m_data;
|
||||
m_data = newData;
|
||||
m_capacity = newLength + 1;
|
||||
}
|
||||
std::memcpy(m_data + m_length, str, len + 1);
|
||||
m_length = newLength;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& String::operator+=(char c) {
|
||||
SizeType newLength = m_length + 1;
|
||||
if (newLength + 1 > m_capacity) {
|
||||
SizeType newCapacity = newLength * 2;
|
||||
char* newData = new char[newCapacity];
|
||||
std::memcpy(newData, m_data, m_length);
|
||||
delete[] m_data;
|
||||
m_data = newData;
|
||||
m_capacity = newCapacity;
|
||||
}
|
||||
m_data[m_length] = c;
|
||||
m_data[newLength] = '\0';
|
||||
m_length = newLength;
|
||||
return *this;
|
||||
}
|
||||
|
||||
String String::Substring(SizeType pos, SizeType len) const {
|
||||
if (pos >= m_length) {
|
||||
return String();
|
||||
}
|
||||
SizeType actualLen = (len == npos || pos + len > m_length) ? (m_length - pos) : len;
|
||||
return String(m_data + pos, actualLen);
|
||||
}
|
||||
|
||||
String String::Trim() const {
|
||||
if (m_length == 0) {
|
||||
return String();
|
||||
}
|
||||
|
||||
SizeType start = 0;
|
||||
SizeType end = m_length - 1;
|
||||
|
||||
while (start <= end && (m_data[start] == ' ' || m_data[start] == '\t' ||
|
||||
m_data[start] == '\n' || m_data[start] == '\r')) {
|
||||
start++;
|
||||
}
|
||||
|
||||
while (end >= start && (m_data[end] == ' ' || m_data[end] == '\t' ||
|
||||
m_data[end] == '\n' || m_data[end] == '\r')) {
|
||||
end--;
|
||||
}
|
||||
|
||||
if (start > end) {
|
||||
return String();
|
||||
}
|
||||
|
||||
return String(m_data + start, end - start + 1);
|
||||
}
|
||||
|
||||
String String::ToLower() const {
|
||||
String result(*this);
|
||||
for (SizeType i = 0; i < result.m_length; i++) {
|
||||
if (result.m_data[i] >= 'A' && result.m_data[i] <= 'Z') {
|
||||
result.m_data[i] = result.m_data[i] + 32;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String String::ToUpper() const {
|
||||
String result(*this);
|
||||
for (SizeType i = 0; i < result.m_length; i++) {
|
||||
if (result.m_data[i] >= 'a' && result.m_data[i] <= 'z') {
|
||||
result.m_data[i] = result.m_data[i] - 32;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String::SizeType String::Find(const char* str, String::SizeType pos) const {
|
||||
if (!str || m_length == 0) {
|
||||
return npos;
|
||||
}
|
||||
|
||||
SizeType len = std::strlen(str);
|
||||
if (len == 0 || pos >= m_length) {
|
||||
return npos;
|
||||
}
|
||||
|
||||
for (SizeType i = pos; i <= m_length - len; i++) {
|
||||
if (std::memcmp(m_data + i, str, len) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
bool String::StartsWith(const String& prefix) const {
|
||||
return StartsWith(prefix.CStr());
|
||||
}
|
||||
|
||||
bool String::StartsWith(const char* prefix) const {
|
||||
if (!prefix) {
|
||||
return false;
|
||||
}
|
||||
SizeType len = std::strlen(prefix);
|
||||
if (len > m_length) {
|
||||
return false;
|
||||
}
|
||||
return std::memcmp(m_data, prefix, len) == 0;
|
||||
}
|
||||
|
||||
bool String::EndsWith(const String& suffix) const {
|
||||
return EndsWith(suffix.CStr());
|
||||
}
|
||||
|
||||
bool String::EndsWith(const char* suffix) const {
|
||||
if (!suffix) {
|
||||
return false;
|
||||
}
|
||||
SizeType len = std::strlen(suffix);
|
||||
if (len > m_length) {
|
||||
return false;
|
||||
}
|
||||
return std::memcmp(m_data + m_length - len, suffix, len) == 0;
|
||||
}
|
||||
|
||||
void String::Clear() {
|
||||
if (m_data) {
|
||||
m_data[0] = '\0';
|
||||
}
|
||||
m_length = 0;
|
||||
}
|
||||
|
||||
void String::Reserve(SizeType capacity) {
|
||||
if (capacity > m_capacity) {
|
||||
char* newData = new char[capacity];
|
||||
std::memcpy(newData, m_data, m_length + 1);
|
||||
delete[] m_data;
|
||||
m_data = newData;
|
||||
m_capacity = capacity;
|
||||
}
|
||||
}
|
||||
|
||||
void String::Resize(SizeType newSize) {
|
||||
Resize(newSize, '\0');
|
||||
}
|
||||
|
||||
void String::Resize(SizeType newSize, char fillChar) {
|
||||
if (newSize + 1 > m_capacity) {
|
||||
Reserve(newSize + 1);
|
||||
}
|
||||
if (newSize > m_length) {
|
||||
for (SizeType i = m_length; i < newSize; i++) {
|
||||
m_data[i] = fillChar;
|
||||
}
|
||||
}
|
||||
m_data[newSize] = '\0';
|
||||
m_length = newSize;
|
||||
}
|
||||
|
||||
void String::Allocate(SizeType capacity) {
|
||||
m_capacity = capacity;
|
||||
m_data = new char[m_capacity];
|
||||
m_data[0] = '\0';
|
||||
}
|
||||
|
||||
void String::Deallocate() {
|
||||
if (m_data) {
|
||||
delete[] m_data;
|
||||
m_data = nullptr;
|
||||
}
|
||||
m_length = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
void String::CopyFrom(const char* str, SizeType len) {
|
||||
if (len + 1 > m_capacity) {
|
||||
Deallocate();
|
||||
Allocate(len + 1);
|
||||
}
|
||||
m_length = len;
|
||||
std::memcpy(m_data, str, len);
|
||||
m_data[len] = '\0';
|
||||
}
|
||||
|
||||
void String::MoveFrom(String&& other) noexcept {
|
||||
m_data = other.m_data;
|
||||
m_length = other.m_length;
|
||||
m_capacity = other.m_capacity;
|
||||
|
||||
other.m_data = nullptr;
|
||||
other.m_length = 0;
|
||||
other.m_capacity = 0;
|
||||
}
|
||||
|
||||
} // namespace Containers
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user