V0.1
This commit is contained in:
parent
524dc412af
commit
597c394120
66
CC_SDK_VS/CCMutex.cpp
Executable file
66
CC_SDK_VS/CCMutex.cpp
Executable file
@ -0,0 +1,66 @@
|
||||
#include "CCMutex.h"
|
||||
|
||||
CTL::AutoLock::AutoLock(Mutex& mutex_t)
|
||||
{
|
||||
this->Mutex_M = &mutex_t;
|
||||
if (this->Mutex_M)
|
||||
{
|
||||
this->Mutex_M->lock();
|
||||
}
|
||||
}
|
||||
|
||||
CTL::AutoLock::~AutoLock()
|
||||
{
|
||||
if (this->Mutex_M)
|
||||
{
|
||||
this->Mutex_M->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
CTL::AutoLock& CTL::AutoLock::operator=(AutoLock&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
CTL::Mutex::Mutex()
|
||||
{
|
||||
g_Mutex = ::CreateMutex(NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
CTL::Mutex::~Mutex()
|
||||
{
|
||||
if (g_Mutex)
|
||||
{
|
||||
CloseHandle(g_Mutex);
|
||||
}
|
||||
g_Mutex = nullptr;
|
||||
}
|
||||
|
||||
bool CTL::Mutex::lock()
|
||||
{
|
||||
TryLock_M = true;
|
||||
if (g_Mutex)
|
||||
{
|
||||
return WaitForSingleObject(g_Mutex, INFINITE) == WAIT_OBJECT_0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTL::Mutex::unlock()
|
||||
{
|
||||
TryLock_M = false;
|
||||
if (g_Mutex)
|
||||
{
|
||||
ReleaseMutex(g_Mutex);
|
||||
}
|
||||
}
|
||||
|
||||
bool CTL::Mutex::try_lock()
|
||||
{
|
||||
if (g_Mutex)
|
||||
{
|
||||
return WaitForSingleObject(g_Mutex, 0) == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
26
CC_SDK_VS/CCMutex.h
Executable file
26
CC_SDK_VS/CCMutex.h
Executable file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "Windows.h"
|
||||
|
||||
namespace CTL {
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
bool lock();
|
||||
void unlock();
|
||||
bool try_lock();
|
||||
private:
|
||||
HANDLE g_Mutex;
|
||||
bool TryLock_M = false;
|
||||
};
|
||||
class AutoLock
|
||||
{
|
||||
public:
|
||||
AutoLock(Mutex& mutex_t);
|
||||
~AutoLock();
|
||||
private:
|
||||
Mutex* Mutex_M;
|
||||
AutoLock& operator = (AutoLock&);
|
||||
};
|
||||
}
|
||||
89
CC_SDK_VS/CCThread.cpp
Executable file
89
CC_SDK_VS/CCThread.cpp
Executable file
@ -0,0 +1,89 @@
|
||||
#include "CCThread.h"
|
||||
|
||||
CTL::Thread::Thread()
|
||||
{
|
||||
}
|
||||
|
||||
// ÒÆ³ýÁËÒÆ¶¯¹¹Ô캯Êý
|
||||
// CTL::Thread::Thread(Thread&& other)
|
||||
// {
|
||||
// ...
|
||||
// }
|
||||
|
||||
CTL::Thread::~Thread()
|
||||
{
|
||||
}
|
||||
|
||||
DWORD CTL::Thread::GetThreadId() const
|
||||
{
|
||||
return this->dwThreadId;
|
||||
}
|
||||
|
||||
void CTL::Thread::Wait()
|
||||
{
|
||||
Mode = 0;
|
||||
hThread = CreateThread(
|
||||
NULL,
|
||||
0,
|
||||
MyThreadFunction,
|
||||
this,
|
||||
0,
|
||||
&dwThreadId
|
||||
);
|
||||
if (hThread)
|
||||
{
|
||||
::WaitForSingleObject(hThread, INFINITE);
|
||||
}
|
||||
while (!this->IsStop)
|
||||
{
|
||||
Thread::SleepMS(50);
|
||||
}
|
||||
}
|
||||
|
||||
void CTL::Thread::Start()
|
||||
{
|
||||
Mode = 1;
|
||||
hThread = CreateThread(
|
||||
NULL,
|
||||
0,
|
||||
MyThreadFunction,
|
||||
this,
|
||||
0,
|
||||
&dwThreadId
|
||||
);
|
||||
}
|
||||
|
||||
void CTL::Thread::StartDetch()
|
||||
{
|
||||
Start();
|
||||
Mode = 2;
|
||||
CloseHandle(hThread);
|
||||
hThread = nullptr;
|
||||
}
|
||||
|
||||
void CTL::Thread::SleepMS(int ms)
|
||||
{
|
||||
::Sleep(ms);
|
||||
}
|
||||
|
||||
DWORD __stdcall CTL::Thread::MyThreadFunction(LPVOID lpParam)
|
||||
{
|
||||
Thread* pThread = (Thread*)lpParam;
|
||||
if (pThread && pThread->task_Fun)
|
||||
{
|
||||
pThread->IsStop = false;
|
||||
try
|
||||
{
|
||||
pThread->task_Fun();
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
if (pThread->hThread && (pThread->Mode == 0 || pThread->Mode == 1))
|
||||
{
|
||||
CloseHandle(pThread->hThread);
|
||||
}
|
||||
pThread->IsStop = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
41
CC_SDK_VS/CCThread.h
Executable file
41
CC_SDK_VS/CCThread.h
Executable file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "Windows.h"
|
||||
#include <functional>
|
||||
|
||||
namespace CTL {
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
Thread();
|
||||
template<typename FUN, typename... ARGS>
|
||||
Thread(FUN&& fun, ARGS&& ...Args);
|
||||
~Thread();
|
||||
DWORD GetThreadId() const;
|
||||
template<typename FUN, typename... ARGS>
|
||||
bool SetThread(FUN&& fun, ARGS&& ...Args);
|
||||
void Wait();
|
||||
void Start();
|
||||
void StartDetch();
|
||||
static void SleepMS(int ms);
|
||||
private:
|
||||
static DWORD WINAPI MyThreadFunction(LPVOID lpParam);
|
||||
int Mode = 0;
|
||||
bool IsStop = false;
|
||||
public:
|
||||
private:
|
||||
HANDLE hThread;
|
||||
DWORD dwThreadId;
|
||||
std::function<void()> task_Fun;
|
||||
};
|
||||
template<typename FUN, typename ...ARGS>
|
||||
inline Thread::Thread(FUN&& fun, ARGS && ...Args)
|
||||
{
|
||||
SetThread(fun, Args...);
|
||||
}
|
||||
template<typename FUN, typename ...ARGS>
|
||||
inline bool Thread::SetThread(FUN&& fun, ARGS && ...Args)
|
||||
{
|
||||
task_Fun = std::bind(std::forward<FUN>(fun), std::forward<ARGS>(Args)...);
|
||||
return task_Fun ? true : false;
|
||||
}
|
||||
}
|
||||
78
CC_SDK_VS/CCThreadPool.cpp
Executable file
78
CC_SDK_VS/CCThreadPool.cpp
Executable file
@ -0,0 +1,78 @@
|
||||
#include "CCThreadPool.h"
|
||||
|
||||
CTL::ThreadPool::ThreadPool()
|
||||
{
|
||||
}
|
||||
|
||||
CTL::ThreadPool::~ThreadPool()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool CTL::ThreadPool::InitStart(int Core)
|
||||
{
|
||||
this->M_Core = Core;
|
||||
isRunning = true;
|
||||
for (size_t i = 0; i < M_Core; i++)
|
||||
{
|
||||
auto TB = new TaskBase();
|
||||
TB->ID = i;
|
||||
TB->IsRunning = true;
|
||||
TB->thread_t = new Thread(&ThreadPool::Worker, this, i);
|
||||
m_Threads.push_back(TB);
|
||||
TB->thread_t->Start();
|
||||
}
|
||||
return true; // ÒÆ³öÑ»·
|
||||
}
|
||||
|
||||
void CTL::ThreadPool::Stop()
|
||||
{
|
||||
if (!isRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isRunning = false;
|
||||
for (size_t i = 0; i < this->M_Core; i++)
|
||||
{
|
||||
auto thread_ = m_Threads[i];
|
||||
if (thread_ && thread_->thread_t)
|
||||
{
|
||||
thread_->thread_t->Wait();
|
||||
delete thread_->thread_t;
|
||||
thread_->thread_t = nullptr;
|
||||
delete thread_;
|
||||
thread_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTL::ThreadPool::Worker(int ID)
|
||||
{
|
||||
std::cout << "ThreadPool::Worker Start -> " << ID << std::endl;
|
||||
while (isRunning)
|
||||
{
|
||||
Fun_Type task = nullptr;
|
||||
{
|
||||
CTL::AutoLock lock(m_Mutex);
|
||||
if (m_TaskQueue.empty())
|
||||
{
|
||||
Thread::SleepMS(5);
|
||||
continue;
|
||||
}
|
||||
task = m_TaskQueue.front();
|
||||
m_TaskQueue.pop();
|
||||
}
|
||||
if (task)
|
||||
{
|
||||
try
|
||||
{
|
||||
task();
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
task = nullptr;
|
||||
}
|
||||
}
|
||||
std::cout << "ThreadPool::Worker End -> " << ID << std::endl;
|
||||
}
|
||||
42
CC_SDK_VS/CCThreadPool.h
Executable file
42
CC_SDK_VS/CCThreadPool.h
Executable file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "CCThread.h"
|
||||
#include "CCMutex.h"
|
||||
#include "vector"
|
||||
#include "queue"
|
||||
#include "iostream"
|
||||
#include <functional> // Ìí¼Ó´ËÐÐ
|
||||
|
||||
namespace CTL {
|
||||
class ThreadPool
|
||||
{
|
||||
using Fun_Type = std::function<void()>; // ÐèҪȷ±£std::function¿ÉÓÃ
|
||||
struct TaskBase
|
||||
{
|
||||
int ID = -1;
|
||||
bool IsRunning = false;
|
||||
Thread* thread_t = nullptr;
|
||||
};
|
||||
public:
|
||||
ThreadPool();
|
||||
~ThreadPool();
|
||||
bool InitStart(int Core);
|
||||
void Stop();
|
||||
template<typename FUN, typename... ARGS>
|
||||
void AddTask(FUN&& fun, ARGS&& ...Args);
|
||||
private:
|
||||
std::queue<Fun_Type> m_TaskQueue{};
|
||||
std::vector<TaskBase*> m_Threads{};
|
||||
CTL::Mutex m_Mutex;
|
||||
bool isRunning = true;
|
||||
int M_Core = 10;
|
||||
void Worker(int ID);
|
||||
};
|
||||
|
||||
template<typename FUN, typename ...ARGS>
|
||||
inline void ThreadPool::AddTask(FUN&& fun, ARGS&& ...Args)
|
||||
{
|
||||
CTL::AutoLock lock(m_Mutex);
|
||||
auto task = std::bind(std::forward<FUN>(fun), std::forward<ARGS>(Args)...);
|
||||
m_TaskQueue.push(task);
|
||||
}
|
||||
}
|
||||
164
CC_SDK_VS/Socket/CCClientSocket.cpp
Normal file
164
CC_SDK_VS/Socket/CCClientSocket.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include "CCClientSocket.h"
|
||||
#include "../CCThread.h"
|
||||
|
||||
CTL::SocketInputStream::SocketInputStream(Socket *sock) {
|
||||
this->socket = sock;
|
||||
}
|
||||
|
||||
int CTL::SocketInputStream::read(char *buffer, const size_t length) const {
|
||||
if (this->socket) {
|
||||
return this->socket->RecvData(buffer, length);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CTL::SocketInputStream::read() const {
|
||||
char buffer[1] = {};
|
||||
const int ret = read(buffer, 1);
|
||||
if (ret > 0) {
|
||||
return buffer[0];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CTL::SocketInputStream::read(ByteArray &buffer, const size_t length) const {
|
||||
if (this->socket) {
|
||||
buffer.resize(length);
|
||||
const auto ret = this->socket->RecvData(buffer.buffer(), length);
|
||||
return ret > 0 ? ret : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool CTL::SocketInputStream::available() const {
|
||||
if (this->socket) {
|
||||
return this->socket->isDataAvailable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CTL::SocketOutputStream::SocketOutputStream(Socket *sock) {
|
||||
this->socket = sock;
|
||||
}
|
||||
|
||||
int CTL::SocketOutputStream::write(const void *buffer, const size_t length) const {
|
||||
if (this->socket) {
|
||||
while (!CTL::Socket::IsSocketWritable(socket->Socketbit)) {
|
||||
CTL::Thread::SleepMS(5);
|
||||
}
|
||||
int ret = 0;
|
||||
this->socket->SendByte(static_cast<const char *>(buffer),length,&ret);
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTL::SocketOutputStream::write(ByteArray &buffer) const {
|
||||
if (this->socket) {
|
||||
return this->socket->SendByte(buffer.buffer(),buffer.size());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTL::SocketOutputStream::write(const std::string &str) const {
|
||||
if (this->socket) {
|
||||
return this->socket->SendByte(str.data(),str.size());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CTL::ClientSocket::ClientSocket(){
|
||||
socket = new Socket();
|
||||
this->isConnect_t = true;
|
||||
this->isClosed_t = false;
|
||||
IP_x = IPVX::IPV4;
|
||||
inputStream = NULL;
|
||||
outputStream = NULL;
|
||||
Port = 0;
|
||||
}
|
||||
|
||||
CTL::ClientSocket::~ClientSocket() {
|
||||
if (inputStream) {
|
||||
delete inputStream;
|
||||
inputStream = NULL;
|
||||
}
|
||||
if (outputStream) {
|
||||
delete outputStream;
|
||||
inputStream = NULL;
|
||||
}
|
||||
if (socket) {
|
||||
delete socket;
|
||||
socket = NULL;
|
||||
}
|
||||
this->isConnect_t = false;
|
||||
this->isClosed_t = true;
|
||||
}
|
||||
|
||||
CTL::ClientSocket::ClientSocket(const InetAddress &address, const int Port) {
|
||||
socket = new Socket();
|
||||
connect(address, Port);
|
||||
}
|
||||
|
||||
CTL::ClientSocket::ClientSocket(Socket *sock) {
|
||||
this->socket = sock;
|
||||
this->inputStream = new SocketInputStream(this->socket);
|
||||
this->outputStream = new SocketOutputStream(this->socket);
|
||||
this->isConnect_t = true;
|
||||
this->isClosed_t = false;
|
||||
const auto addr = socket->GetClientHost();
|
||||
this->hostAddress = addr.IPAddress;
|
||||
this->Port = addr.Port;
|
||||
}
|
||||
|
||||
bool CTL::ClientSocket::connect(const InetAddress &address, const int Port) {
|
||||
if (socket) {
|
||||
this->IP_x = address.getIPx();
|
||||
this->Port = Port;
|
||||
this->hostAddress = address.getHostAddress();
|
||||
socket->Init(IP_x, TORU::TCP, TYPE::STREAM);
|
||||
this->isConnect_t = socket->Connect(hostAddress.c_str(), Port);
|
||||
if (this->isConnect_t) {
|
||||
this->isClosed_t = false;
|
||||
this->inputStream = new SocketInputStream(this->socket);
|
||||
this->outputStream = new SocketOutputStream(this->socket);
|
||||
}
|
||||
return this->isConnect_t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTL::ClientSocket::close() {
|
||||
if (socket) {
|
||||
this->isClosed_t = true;
|
||||
this->isConnect_t = false;
|
||||
socket->Close();
|
||||
}
|
||||
}
|
||||
|
||||
bool CTL::ClientSocket::isConnect() const {
|
||||
return this->isConnect_t;
|
||||
}
|
||||
|
||||
bool CTL::ClientSocket::isClosed() const {
|
||||
return this->isClosed_t;
|
||||
}
|
||||
|
||||
CTL::SocketInputStream * CTL::ClientSocket::getInputStream() const {
|
||||
return this->inputStream;
|
||||
}
|
||||
|
||||
CTL::SocketOutputStream * CTL::ClientSocket::getOutputStream() const {
|
||||
return this->outputStream;
|
||||
}
|
||||
|
||||
CTL::Socket * CTL::ClientSocket::getSocket() const {
|
||||
return this->socket;
|
||||
}
|
||||
|
||||
int CTL::ClientSocket::getPort() const {
|
||||
return this->Port;
|
||||
}
|
||||
|
||||
CTL::InetAddress CTL::ClientSocket::getHostAddress() const {
|
||||
return InetAddress(hostAddress);
|
||||
}
|
||||
52
CC_SDK_VS/Socket/CCClientSocket.h
Normal file
52
CC_SDK_VS/Socket/CCClientSocket.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef CLIENT_SOCKET_H
|
||||
#define CLIENT_SOCKET_H
|
||||
|
||||
#include "CCSocket.h"
|
||||
#include "../base/CCByteArray.h"
|
||||
|
||||
namespace CTL {
|
||||
class SocketInputStream {
|
||||
Socket* socket;
|
||||
public:
|
||||
explicit SocketInputStream(Socket* sock);
|
||||
int read(char* buffer, size_t length) const;
|
||||
int read() const;
|
||||
int read(ByteArray& buffer, size_t length) const;
|
||||
bool available() const;
|
||||
};
|
||||
class SocketOutputStream {
|
||||
Socket* socket;
|
||||
public:
|
||||
explicit SocketOutputStream(Socket* sock);
|
||||
int write(const void* buffer, size_t length) const;
|
||||
bool write(ByteArray& buffer) const;
|
||||
bool write(const std::string& str) const;
|
||||
};
|
||||
class ClientSocket {
|
||||
Socket* socket;
|
||||
SocketInputStream* inputStream;
|
||||
SocketOutputStream* outputStream;
|
||||
IPVX IP_x;
|
||||
std::string hostAddress;
|
||||
bool isClosed_t, isConnect_t;
|
||||
int Port;
|
||||
public:
|
||||
private:
|
||||
public:
|
||||
ClientSocket();
|
||||
~ClientSocket();
|
||||
ClientSocket(const InetAddress& address,int Port);
|
||||
explicit ClientSocket(Socket* sock);
|
||||
bool connect(const InetAddress& address,int Port);
|
||||
void close();
|
||||
bool isConnect() const;
|
||||
bool isClosed() const;
|
||||
SocketInputStream* getInputStream() const;
|
||||
SocketOutputStream* getOutputStream() const;
|
||||
Socket* getSocket() const;
|
||||
int getPort() const;
|
||||
InetAddress getHostAddress() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
195
CC_SDK_VS/Socket/CCDatagramSocket.cpp
Normal file
195
CC_SDK_VS/Socket/CCDatagramSocket.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
#include "CCDatagramSocket.h"
|
||||
|
||||
CTL::DatagramPacket::DatagramPacket() {
|
||||
dataBuffer.resize(1440);
|
||||
}
|
||||
|
||||
CTL::DatagramPacket::DatagramPacket(const size_t length) {
|
||||
dataBuffer.resize(length);
|
||||
}
|
||||
|
||||
CTL::DatagramPacket::DatagramPacket(const char *data, const size_t length, const InetAddress &addr, const int portNum) {
|
||||
dataBuffer.resize(length);
|
||||
packetLength = length;
|
||||
address = addr;
|
||||
port = portNum;
|
||||
std::memcpy(dataBuffer.buffer(), data, length);
|
||||
}
|
||||
|
||||
const char* CTL::DatagramPacket::getData() const {
|
||||
return dataBuffer.buffer();
|
||||
}
|
||||
|
||||
size_t CTL::DatagramPacket::getLength() const {
|
||||
return packetLength;
|
||||
}
|
||||
|
||||
void CTL::DatagramPacket::setLength(const size_t length) {
|
||||
if (length <= dataBuffer.size()) {
|
||||
packetLength = length;
|
||||
}
|
||||
}
|
||||
|
||||
size_t CTL::DatagramPacket::getCapacity() const {
|
||||
return dataBuffer.size();
|
||||
}
|
||||
|
||||
CTL::InetAddress CTL::DatagramPacket::getAddress() const {
|
||||
return address;
|
||||
}
|
||||
|
||||
void CTL::DatagramPacket::setAddress(const InetAddress &addr) {
|
||||
address = addr;
|
||||
}
|
||||
|
||||
int CTL::DatagramPacket::getPort() const {
|
||||
return port;
|
||||
}
|
||||
|
||||
void CTL::DatagramPacket::setPort(const int portNum) {
|
||||
port = portNum;
|
||||
}
|
||||
|
||||
void CTL::DatagramPacket::setData(const char *data, const size_t length) {
|
||||
if (length > dataBuffer.size()) {
|
||||
dataBuffer.resize(length);
|
||||
}
|
||||
std::memcpy(dataBuffer.buffer(), data, length);
|
||||
packetLength = length;
|
||||
}
|
||||
|
||||
void CTL::DatagramPacket::setData(const ByteArray &data) {
|
||||
if (data.size() > dataBuffer.size()) {
|
||||
dataBuffer.resize(data.size());
|
||||
}
|
||||
dataBuffer = data;
|
||||
packetLength = data.size();
|
||||
}
|
||||
|
||||
void CTL::DatagramPacket::reset() {
|
||||
packetLength = 0;
|
||||
port = 0;
|
||||
address = InetAddress();
|
||||
}
|
||||
|
||||
std::string CTL::DatagramPacket::getDataAsString() const {
|
||||
return dataBuffer.toString();
|
||||
}
|
||||
|
||||
CTL::ByteArray CTL::DatagramPacket::getDataAsByteArray() const {
|
||||
return dataBuffer;
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::Init(const int Port, const InetAddress &address) {
|
||||
socket = new Socket();
|
||||
return bind(Port,address);
|
||||
}
|
||||
|
||||
CTL::DatagramSocket::DatagramSocket() {
|
||||
socket = new Socket();
|
||||
IP_x = IPV4;
|
||||
isClosed_t = true;
|
||||
isBound_t = false;
|
||||
Port = 0;
|
||||
}
|
||||
|
||||
CTL::DatagramSocket::DatagramSocket(const int Port, const InetAddress &address) {
|
||||
Init(Port,address);
|
||||
}
|
||||
|
||||
CTL::DatagramSocket::~DatagramSocket() {
|
||||
socket->Close();
|
||||
delete socket;
|
||||
socket = NULL;
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::bind(const int Port, const InetAddress &address) {
|
||||
if (socket) {
|
||||
this->IP_x = address.getIPx();
|
||||
this->Port = Port;
|
||||
this->hostAddress = address.getHostAddress();
|
||||
socket->Init(IP_x, TORU::UDP, TYPE::DGRAM);
|
||||
this->isBound_t = socket->Bind(hostAddress.c_str(), Port);
|
||||
if (this->isBound_t) {
|
||||
this->isClosed_t = false;
|
||||
}
|
||||
return this->isBound_t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::send(const DatagramPacket &packet) const {
|
||||
const auto buffer = packet.getDataAsByteArray();
|
||||
const auto size = packet.getLength();
|
||||
const auto addr = packet.getAddress();
|
||||
const auto port = packet.getPort();
|
||||
return socket->UDPSendByte(buffer.buffer(),size,addr.getHostName().c_str(),port);
|
||||
}
|
||||
|
||||
void CTL::DatagramSocket::receive(DatagramPacket &packet) const {
|
||||
if (socket) {
|
||||
ByteArray buffer;
|
||||
const auto size = packet.getCapacity();
|
||||
buffer.resize(size);
|
||||
CCHostInfo info;
|
||||
const auto len = socket->UDPRecvData(buffer.buffer(),size,&info);
|
||||
if (len > 0) {
|
||||
const InetAddress address(info.IPAddress);
|
||||
packet.setAddress(address);
|
||||
packet.setPort(info.Port);
|
||||
packet.setData(buffer.subBuffer(0,len));
|
||||
packet.setLength(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTL::DatagramSocket::close() {
|
||||
if (socket) {
|
||||
this->isClosed_t = true;
|
||||
this->isBound_t = false;
|
||||
socket->Close();
|
||||
}
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::isBound() const {
|
||||
return this->isBound_t;
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::isClosed() const {
|
||||
return this->isClosed_t;
|
||||
}
|
||||
|
||||
int CTL::DatagramSocket::getLocalPort() const {
|
||||
return this->Port;
|
||||
}
|
||||
|
||||
CTL::InetAddress CTL::DatagramSocket::getLocalAddress() const {
|
||||
InetAddress address(this->IP_x, this->hostAddress);
|
||||
return address;
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::available() const {
|
||||
if (socket) {
|
||||
return socket->isDataAvailable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CTL::Socket * CTL::DatagramSocket::getSocket() const {
|
||||
return socket;
|
||||
}
|
||||
|
||||
void CTL::DatagramSocket::broadcast(const DatagramPacket& packet) const{
|
||||
if (socket){
|
||||
sockaddr_in serverAddr = {};
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(packet.getPort());
|
||||
serverAddr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
socket->SendData(packet.getData(),packet.getLength(),serverAddr);
|
||||
}
|
||||
}
|
||||
|
||||
bool CTL::DatagramSocket::setSockOpt(const CCOpt opt) const {
|
||||
return socket->SetSockOpt(opt);
|
||||
}
|
||||
|
||||
92
CC_SDK_VS/Socket/CCDatagramSocket.h
Normal file
92
CC_SDK_VS/Socket/CCDatagramSocket.h
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef DATAGRAM_SOCKET_H
|
||||
#define DATAGRAM_SOCKET_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "CCSocket.h"
|
||||
#include "../base/CCByteArray.h"
|
||||
|
||||
namespace CTL {
|
||||
class DatagramPacket {
|
||||
ByteArray dataBuffer;
|
||||
size_t packetLength = 0;
|
||||
InetAddress address;
|
||||
int port = 0;
|
||||
public:
|
||||
// 构造函数:创建用于接收数据包的对象
|
||||
DatagramPacket();
|
||||
// 构造函数:创建用于接收数据包的对象
|
||||
explicit DatagramPacket(size_t length);
|
||||
// 构造函数:创建用于发送数据包的对象
|
||||
DatagramPacket(const char* data, size_t length, const InetAddress& addr, int portNum);
|
||||
// 构造函数:创建用于发送数据包的对象(使用vector)
|
||||
DatagramPacket(const ByteArray& data, InetAddress addr, const int portNum)
|
||||
: dataBuffer(data), packetLength(data.size()), address(addr), port(portNum) {}
|
||||
// 获取数据缓冲区(const版本)
|
||||
[[nodiscard]] const char* getData() const;
|
||||
// 获取数据缓冲区长度
|
||||
[[nodiscard]] size_t getLength() const;
|
||||
// 设置数据长度
|
||||
void setLength(size_t length);
|
||||
// 获取缓冲区容量
|
||||
[[nodiscard]] size_t getCapacity() const;
|
||||
// 获取目标地址
|
||||
[[nodiscard]] InetAddress getAddress() const;
|
||||
// 设置目标地址
|
||||
void setAddress(const InetAddress& addr);
|
||||
// 获取目标端口
|
||||
[[nodiscard]] int getPort() const;
|
||||
// 设置目标端口
|
||||
void setPort(int portNum);
|
||||
// 设置数据(从字符数组)
|
||||
void setData(const char* data, size_t length);
|
||||
// 设置数据(从vector)
|
||||
void setData(const ByteArray& data);
|
||||
// 重置数据包(清空内容)
|
||||
void reset();
|
||||
// 获取数据为字符串(如果数据是文本)
|
||||
[[nodiscard]] std::string getDataAsString() const;
|
||||
// 获取数据为字节数组
|
||||
[[nodiscard]] ByteArray getDataAsByteArray() const;
|
||||
};
|
||||
class DatagramSocket {
|
||||
Socket* socket;
|
||||
IPVX IP_x;
|
||||
std::string hostAddress;
|
||||
bool isClosed_t, isBound_t;
|
||||
int Port;
|
||||
bool Init(int Port, const InetAddress &address);
|
||||
public:
|
||||
DatagramSocket();
|
||||
explicit DatagramSocket(int Port, const InetAddress &address = InetAddress::getAnyAddress());
|
||||
~DatagramSocket();
|
||||
// 绑定到特定地址和端口
|
||||
bool bind(int Port, const InetAddress &address = InetAddress::getAnyAddress());
|
||||
// 发送数据包
|
||||
[[nodiscard]] bool send(const DatagramPacket& packet) const;
|
||||
// 接收数据包
|
||||
void receive(DatagramPacket& packet) const;
|
||||
// 关闭套接字
|
||||
void close();
|
||||
// 检查套接字是否已绑定
|
||||
[[nodiscard]] bool isBound() const;
|
||||
// 检查套接字是否已关闭
|
||||
[[nodiscard]] bool isClosed() const;
|
||||
// 获取本地端口
|
||||
[[nodiscard]] int getLocalPort() const;
|
||||
// 获取本地地址
|
||||
[[nodiscard]] InetAddress getLocalAddress() const;
|
||||
// 是否有数据可读
|
||||
[[nodiscard]] bool available() const;
|
||||
// 获取Socket
|
||||
[[nodiscard]] Socket* getSocket() const;
|
||||
// 广播数据包
|
||||
void broadcast(const DatagramPacket& packet) const;
|
||||
// 设置参数
|
||||
bool setSockOpt(CCOpt opt) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
78
CC_SDK_VS/Socket/CCServerSocket.cpp
Normal file
78
CC_SDK_VS/Socket/CCServerSocket.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "CCServerSocket.h"
|
||||
|
||||
bool CTL::ServerSocket::Init(const int Port, const InetAddress &address) {
|
||||
socket = new Socket();
|
||||
return bind(Port,address);
|
||||
}
|
||||
|
||||
CTL::ServerSocket::ServerSocket() {
|
||||
socket = new Socket();
|
||||
IP_x = IPVX::IPV4;
|
||||
isClosed_t = true;
|
||||
isBound_t = false;
|
||||
isListen_t = false;
|
||||
Port = 0;
|
||||
}
|
||||
|
||||
CTL::ServerSocket::~ServerSocket() {
|
||||
delete socket;
|
||||
}
|
||||
|
||||
CTL::ServerSocket::ServerSocket(const int Port, const InetAddress &address) {
|
||||
Init(Port,address);
|
||||
}
|
||||
|
||||
bool CTL::ServerSocket::bind(const int Port, const InetAddress &address) {
|
||||
if (socket) {
|
||||
this->IP_x = address.getIPx();
|
||||
this->Port = Port;
|
||||
this->hostAddress = address.getHostAddress();
|
||||
socket->Init(IP_x, TORU::TCP, TYPE::STREAM);
|
||||
this->isBound_t = socket->Bind(hostAddress.c_str(), Port);
|
||||
if (this->isBound_t) {
|
||||
this->isClosed_t = false;
|
||||
}
|
||||
return this->isBound_t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTL::ServerSocket::listen(const int backlog){
|
||||
if (socket) {
|
||||
this->isListen_t = socket->Listen(backlog);
|
||||
if (this->isListen_t) {
|
||||
this->isClosed_t = false;
|
||||
this->isListen_t = true;
|
||||
}
|
||||
return this->isListen_t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTL::ServerSocket::close() {
|
||||
if (socket) {
|
||||
this->isClosed_t = true;
|
||||
this->isBound_t = false;
|
||||
socket->Close();
|
||||
}
|
||||
}
|
||||
|
||||
bool CTL::ServerSocket::isBound() const {
|
||||
return this->isBound_t;
|
||||
}
|
||||
|
||||
bool CTL::ServerSocket::isClosed() const {
|
||||
return this->isClosed_t;
|
||||
}
|
||||
|
||||
CTL::Socket * CTL::ServerSocket::getSocket() const {
|
||||
return this->socket;
|
||||
}
|
||||
|
||||
CTL::ClientSocket * CTL::ServerSocket::accept() const {
|
||||
if (!this->isListen_t) {
|
||||
throw std::runtime_error("ServerSocket::accept() error: ServerSocket is not listening.");
|
||||
}
|
||||
const auto clientSocket = new Socket(socket->Accept());
|
||||
return new ClientSocket(clientSocket);
|
||||
}
|
||||
32
CC_SDK_VS/Socket/CCServerSocket.h
Normal file
32
CC_SDK_VS/Socket/CCServerSocket.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef SERVER_SOCKET_H
|
||||
#define SERVER_SOCKET_H
|
||||
|
||||
#include "CCSocket.h"
|
||||
#include "CCClientSocket.h"
|
||||
|
||||
namespace CTL {
|
||||
class ServerSocket {
|
||||
Socket* socket;
|
||||
IPVX IP_x;
|
||||
std::string hostAddress;
|
||||
bool isClosed_t, isBound_t,isListen_t;
|
||||
int Port;
|
||||
public:
|
||||
private:
|
||||
bool Init(int Port,const InetAddress& address);
|
||||
public:
|
||||
ServerSocket();
|
||||
~ServerSocket();
|
||||
explicit ServerSocket(int Port, const InetAddress &address = InetAddress::getAnyAddress());
|
||||
bool bind(int Port,const InetAddress& address = InetAddress::getAnyAddress());
|
||||
bool listen(int backlog = 50);
|
||||
void close();
|
||||
bool isBound() const;
|
||||
bool isClosed() const;
|
||||
Socket* getSocket() const;
|
||||
ClientSocket* accept() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
1183
CC_SDK_VS/Socket/CCSocket.cpp
Normal file
1183
CC_SDK_VS/Socket/CCSocket.cpp
Normal file
File diff suppressed because it is too large
Load Diff
208
CC_SDK_VS/Socket/CCSocket.h
Normal file
208
CC_SDK_VS/Socket/CCSocket.h
Normal file
@ -0,0 +1,208 @@
|
||||
#ifndef CC_Socket_
|
||||
#define CC_Socket_
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "../base/CCByteArray.h"
|
||||
#include "string"
|
||||
|
||||
#define SockError -1
|
||||
#define CC_Sock_Close 0
|
||||
|
||||
// 定义主机信息结构体
|
||||
struct CCHostInfo{
|
||||
std::string IPAddress;
|
||||
int Port;
|
||||
};
|
||||
|
||||
// 定义套接字选项枚举
|
||||
enum CCOpt
|
||||
{
|
||||
BROADCAST,
|
||||
REUSEADDR,
|
||||
REUSEPORT,
|
||||
NOBLOCK,
|
||||
LINGER_t,
|
||||
SNDBUF,
|
||||
RCVBUF,
|
||||
TIMESTAMP,
|
||||
};
|
||||
|
||||
// 定义地址类型枚举
|
||||
enum CCAddress
|
||||
{
|
||||
Local,
|
||||
Any
|
||||
};
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define MSL_N 0
|
||||
|
||||
// Windows平台下WSA初始化与清理类
|
||||
class WinWSADWAInitAndClean
|
||||
{
|
||||
public:
|
||||
WSADATA wsd{};
|
||||
WinWSADWAInitAndClean(){
|
||||
if (WSAStartup(MAKEWORD(2, 2), &this->wsd) != 0){
|
||||
WSACleanup();
|
||||
}
|
||||
}
|
||||
~WinWSADWAInitAndClean(){
|
||||
WSACleanup();
|
||||
}
|
||||
};
|
||||
static WinWSADWAInitAndClean winsc;
|
||||
|
||||
#elif __linux__
|
||||
#define MSL_N MSG_NOSIGNAL
|
||||
#define SOCKET_ERROR (-1)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/select.h>
|
||||
#include "poll.h"
|
||||
typedef int SOCKET;
|
||||
#endif
|
||||
|
||||
// 命名空间CTL,包含网络编程相关类和枚举
|
||||
namespace CTL {
|
||||
enum IPVX
|
||||
{
|
||||
IPV4 = AF_INET,
|
||||
IPV6 = AF_INET6
|
||||
};
|
||||
enum TORU
|
||||
{
|
||||
TCP = IPPROTO_TCP,
|
||||
UDP = IPPROTO_UDP
|
||||
};
|
||||
enum TYPE
|
||||
{
|
||||
STREAM = SOCK_STREAM,
|
||||
DGRAM = SOCK_DGRAM
|
||||
};
|
||||
|
||||
// Socket类,封装了网络编程的常见操作
|
||||
class Socket{
|
||||
public:
|
||||
SOCKET Socketbit = -1;
|
||||
sockaddr_in client = {}, server = {};
|
||||
sockaddr_in6 client_6 = {}, server_6 = {};
|
||||
short IPVx = 0;
|
||||
// 默认构造函数
|
||||
Socket();
|
||||
// 构造函数,初始化Socket
|
||||
Socket(SOCKET sock);
|
||||
// 初始化Socket并设置属性
|
||||
bool Init(IPVX IPV4orIPV6, TORU TCPorUDP, TYPE Type = TYPE::STREAM);
|
||||
// 获取Socket句柄
|
||||
SOCKET GetSOCKET() const;
|
||||
// 设置Socket选项
|
||||
bool SetSockOpt(CCOpt opt) const;
|
||||
// 设置Socket为非阻塞模式
|
||||
void SetSocketNonBlocking() const;
|
||||
// 检查Socket是否有可用数据
|
||||
bool isDataAvailable() const;
|
||||
// 获取本地IP地址
|
||||
static std::vector<std::string> GetLocalIP(IPVX ipvx = IPVX::IPV4,int Number = 1);
|
||||
// 获取客户端主机信息
|
||||
CCHostInfo GetClientHost() const;
|
||||
// 获取本地主机信息
|
||||
CCHostInfo GetLocalHost() const;
|
||||
// 连接到远程主机
|
||||
bool Connect(const char* IP, unsigned short Port);
|
||||
// 绑定Socket到指定地址和端口
|
||||
bool Bind(const char* IP,unsigned short Port);
|
||||
// 监听连接请求
|
||||
bool Listen(unsigned short UserNum = 10);
|
||||
// 接受连接请求
|
||||
Socket Accept() const;
|
||||
// 发送数据
|
||||
bool Send(const char* str) const;
|
||||
// 发送数据,带标志
|
||||
bool Send(const char *__buf, size_t __n, int __flags) const;
|
||||
// 发送数据到指定地址和端口
|
||||
bool SendData(const char * str,const int length,sockaddr_in addr_in) const;
|
||||
// 发送指定长度的数据
|
||||
bool SendByte(const char* str,int len) const;
|
||||
// 发送指定长度的数据
|
||||
bool SendByte(const char* str,int len,int* ret) const;
|
||||
// UDP发送数据
|
||||
bool UDPSend(const char* str,const char* IP,int Port) const;
|
||||
// UDP发送指定长度的数据
|
||||
bool UDPSendByte(const char* str, ByteHander len, const char* IP, int Port) const;
|
||||
// UDP发送指定长度的数据
|
||||
bool UDPSendByte(void* str, ByteHander len, const char* IP, int Port) const;
|
||||
// 接收数据
|
||||
ByteHander RecvData(char* buffer,ByteHander lens) const;
|
||||
// UDP接收数据
|
||||
ByteHander UDPRecvData(char* buffer,ByteHander lens,CCHostInfo* info) const;
|
||||
// 关闭Socket
|
||||
void Close();
|
||||
// 获取数据头部
|
||||
static bool GetDateHead(char* data, ByteHander* size);
|
||||
// 获取字符串头部
|
||||
static bool GetStrHead(char* data,ByteHander size);
|
||||
// 重载等号运算符,比较Socket对象是否相等
|
||||
bool operator == (Socket socket) const;
|
||||
// 重载不等号运算符,比较Socket对象是否不等
|
||||
bool operator != (Socket socket) const;
|
||||
// 检查连接是否有效
|
||||
bool isConnectionAlive() const;
|
||||
// 检查Socket是否可写
|
||||
static bool IsSocketWritable(SOCKET sock);
|
||||
static int GetLastError();
|
||||
private:
|
||||
int sock;
|
||||
bool Stop;
|
||||
int opt;
|
||||
};
|
||||
class InetAddress {
|
||||
std::string hostAddress;
|
||||
std::string hostName;
|
||||
IPVX Ip_x;
|
||||
public:
|
||||
// 默认构造函数
|
||||
InetAddress();
|
||||
// 根据IP地址构造
|
||||
InetAddress(const std::string& ip) : hostAddress(ip) {}
|
||||
InetAddress(IPVX ip_x,const std::string& ip= "");
|
||||
// 根据IP地址和主机名构造
|
||||
InetAddress(const std::string& ip, const std::string& hostname)
|
||||
: hostAddress(ip), hostName(hostname) {}
|
||||
// 获取本地主机InetAddress对象
|
||||
static InetAddress getLocalHost(IPVX ipvx = IPVX::IPV4);
|
||||
// 根据主机名获取InetAddress对象
|
||||
static std::vector<InetAddress> getAllByName(const std::string& host);
|
||||
// 根据IP地址获取InetAddress对象
|
||||
static InetAddress getByName(const std::string& host);
|
||||
// 获取IP地址字符串
|
||||
std::string getHostAddress() const;
|
||||
// 获取主机名
|
||||
std::string getHostName() const;
|
||||
// 获取任意地址 (相当于Java中的InetAddress.getByName("0.0.0.0"))
|
||||
static InetAddress getAnyAddress();
|
||||
// 获取回环地址 (相当于Java中的InetAddress.getByName("localhost"))
|
||||
static InetAddress getLoopbackAddress();
|
||||
// 获取广播地址
|
||||
static InetAddress getBroadcastAddress(IPVX ipvx = IPVX::IPV4);
|
||||
// 重载相等运算符
|
||||
bool operator==(const InetAddress& other) const;
|
||||
// 重载不等运算符
|
||||
bool operator!=(const InetAddress& other) const;
|
||||
// 转换为字符串
|
||||
std::string toString() const;
|
||||
IPVX getIPx() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
118
CC_SDK_VS/TL/Array_CTL.h
Normal file
118
CC_SDK_VS/TL/Array_CTL.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef CTL_ARRAY_CTL_H
|
||||
#define CTL_ARRAY_CTL_H
|
||||
|
||||
|
||||
|
||||
namespace CTL {
|
||||
template<typename V>
|
||||
class Array_CTL {
|
||||
public:
|
||||
private:
|
||||
struct BinaryTree {
|
||||
size_t Key = 0;
|
||||
V* value = nullptr;
|
||||
BinaryTree* left = nullptr;
|
||||
BinaryTree* right = nullptr;
|
||||
};
|
||||
BinaryTree* root = nullptr;
|
||||
size_t _size_m = 0;
|
||||
public:
|
||||
Array_CTL() {
|
||||
delete root;
|
||||
root = new BinaryTree();
|
||||
}
|
||||
~Array_CTL() {
|
||||
clear(this->root);
|
||||
}
|
||||
void add(const V value) {
|
||||
insert(_size_m, value);
|
||||
}
|
||||
void clear() {
|
||||
clear(this->root);
|
||||
}
|
||||
V get(const size_t index) {
|
||||
return *find(index,this->root);
|
||||
}
|
||||
V* getPtr(const size_t index) {
|
||||
return find(index,this->root);
|
||||
}
|
||||
private:
|
||||
void clear(BinaryTree* node) {
|
||||
if (node) {
|
||||
clear(node->left);
|
||||
clear(node->right);
|
||||
delete node->value;
|
||||
node->value = nullptr;
|
||||
delete node;
|
||||
node = nullptr;
|
||||
_size_m--;
|
||||
}
|
||||
}
|
||||
V* find(int key, const BinaryTree* node) {
|
||||
V* value = nullptr;
|
||||
if (node) {
|
||||
if (node->Key == key) {
|
||||
return node->value;
|
||||
}
|
||||
else if (node->Key < key) {
|
||||
if (node->right) {
|
||||
return find(key,node->right);
|
||||
}
|
||||
}
|
||||
else if (node->Key > key) {
|
||||
if (node->left) {
|
||||
return find(key,node->left);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
void insert(size_t key,V value) {
|
||||
V* newValue = new V(value);
|
||||
|
||||
if (!this->root) {
|
||||
this->root = new BinaryTree();
|
||||
this->root->Key = key;
|
||||
this->root->value = newValue;
|
||||
_size_m++;
|
||||
return;
|
||||
}
|
||||
|
||||
BinaryTree* current = this->root;
|
||||
while (current) {
|
||||
if (key == current->Key) {
|
||||
if (current->value) {
|
||||
delete current->value;
|
||||
}
|
||||
else {
|
||||
_size_m++;
|
||||
}
|
||||
current->value = newValue;
|
||||
return;
|
||||
}
|
||||
else if (key < current->Key) {
|
||||
if (!current->left) {
|
||||
current->left = new BinaryTree();
|
||||
current->left->Key = key;
|
||||
current->left->value = newValue;
|
||||
_size_m++;
|
||||
return;
|
||||
}
|
||||
current = current->left;
|
||||
}
|
||||
else {
|
||||
if (!current->right) {
|
||||
current->right = new BinaryTree();
|
||||
current->right->Key = key;
|
||||
current->right->value = newValue;
|
||||
_size_m++;
|
||||
return;
|
||||
}
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
65
CC_SDK_VS/TL/AutoDestruct.h
Normal file
65
CC_SDK_VS/TL/AutoDestruct.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef SDK_TL_AUTODESTRUCT_H
|
||||
#define SDK_TL_AUTODESTRUCT_H
|
||||
|
||||
#include "iostream"
|
||||
|
||||
namespace CTL{
|
||||
template<typename T>
|
||||
class AutoDestruct{
|
||||
T* m_ptr;
|
||||
bool m_is_owner;
|
||||
public:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
AutoDestruct(T* ptr) {
|
||||
this->m_ptr = ptr;
|
||||
m_is_owner = true;
|
||||
}
|
||||
AutoDestruct(AutoDestruct&& other) {
|
||||
this->m_ptr = other.m_ptr;
|
||||
other.m_ptr = NULL;
|
||||
}
|
||||
~AutoDestruct(){
|
||||
if (m_ptr && m_is_owner) {
|
||||
delete m_ptr;
|
||||
}
|
||||
m_ptr = NULL;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
T* Get(){
|
||||
return m_ptr;
|
||||
}
|
||||
const T* Get() const{
|
||||
return m_ptr;
|
||||
}
|
||||
T* get(){
|
||||
return m_ptr;
|
||||
}
|
||||
const T* get() const{
|
||||
return m_ptr;
|
||||
}
|
||||
operator bool() const {
|
||||
return m_ptr != NULL;
|
||||
}
|
||||
T& operator*() const {
|
||||
return *m_ptr; // 假设 ptr 是内部 Term*
|
||||
}
|
||||
T* operator->() const {
|
||||
return m_ptr; // 假设 ptr 是内部 Term*
|
||||
}
|
||||
AutoDestruct& operator=(T* ptr){
|
||||
delete m_ptr;
|
||||
m_ptr = ptr;
|
||||
return *this;
|
||||
}
|
||||
void reset(T* ptr = NULL){
|
||||
delete m_ptr;
|
||||
m_ptr = ptr;
|
||||
}
|
||||
void release() {
|
||||
m_is_owner = false;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
202
CC_SDK_VS/TL/List.h
Normal file
202
CC_SDK_VS/TL/List.h
Normal file
@ -0,0 +1,202 @@
|
||||
#ifndef SDK_TL_LIST_H
|
||||
#define SDK_TL_LIST_H
|
||||
|
||||
#include "list"
|
||||
#include "mutex"
|
||||
#include "iostream"
|
||||
#include "vector"
|
||||
|
||||
namespace CTL{
|
||||
template<typename T>
|
||||
class List{
|
||||
private:
|
||||
std::mutex _mutex;
|
||||
std::list<T> _list;
|
||||
public:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
List() = default;
|
||||
explicit List(const std::list<T> list){
|
||||
_list = list;
|
||||
}
|
||||
explicit List(const std::vector<T> list){
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
_list.push_back(list[i]);
|
||||
}
|
||||
}
|
||||
List(const List<T>& list) {
|
||||
auto L = list._list;
|
||||
for (auto O : L) {
|
||||
_list.push_back(O);
|
||||
}
|
||||
}
|
||||
List(const std::initializer_list<T>& list) {
|
||||
for (auto item : list) {
|
||||
_list.push_back(item);
|
||||
}
|
||||
}
|
||||
~List() = default;
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
friend std::ostream& operator<<(std::ostream& os, const List<T>& list) {
|
||||
os << "[";
|
||||
const auto& items = list._list;
|
||||
if (!items.empty()) {
|
||||
auto it = items.begin();
|
||||
os << *it;
|
||||
++it;
|
||||
for (; it != items.end(); ++it) {
|
||||
os << "," << *it;
|
||||
}
|
||||
}
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void Add(const T &item){
|
||||
_mutex.lock();
|
||||
_list.push_back(item);
|
||||
_mutex.unlock();
|
||||
}
|
||||
bool Set(const int index, const T &item){
|
||||
_mutex.lock();
|
||||
if (index >= 0 && index < _list.size()) {
|
||||
auto it = _list.begin();
|
||||
std::advance(it, index); // 将迭代器移动到指定索引
|
||||
*it = item; // 修改该位置的值
|
||||
_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
_mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
T* Get(int index){
|
||||
_mutex.lock(); // 加锁,保证线程安全
|
||||
if (index >= 0 && index < _list.size()) { // 检查索引是否合法
|
||||
auto it = _list.begin();
|
||||
std::advance(it, index); // 将迭代器移动到指定索引
|
||||
_mutex.unlock(); // 解锁
|
||||
return &(*it); // 返回元素的指针(原代码返回 it 是错误的,应返回指向对象的指针)
|
||||
}
|
||||
else {
|
||||
_mutex.unlock(); // 解锁
|
||||
return nullptr; // 索引越界返回空指针
|
||||
}
|
||||
}
|
||||
bool Remove(int index){
|
||||
_mutex.lock();
|
||||
if (index >= 0 && index < _list.size()) {
|
||||
auto it = _list.begin();
|
||||
std::advance(it, index);
|
||||
_list.erase(it);
|
||||
_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
_mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void RemoveAll(const T& item){
|
||||
_mutex.lock();
|
||||
_list.remove(item);
|
||||
_mutex.unlock();
|
||||
}
|
||||
void Clear(){
|
||||
_mutex.lock();
|
||||
_list.clear();
|
||||
_mutex.unlock();
|
||||
}
|
||||
int Size(){
|
||||
_mutex.lock();
|
||||
int size = _list.size();
|
||||
_mutex.unlock();
|
||||
return size;
|
||||
}
|
||||
bool IsEmpty(){
|
||||
_mutex.lock();
|
||||
bool isEmpty = _list.empty();
|
||||
_mutex.unlock();
|
||||
return isEmpty;
|
||||
}
|
||||
bool Insert(const int index, const T &item){
|
||||
_mutex.lock();
|
||||
if (index >= 0 && index <= _list.size()) {
|
||||
auto it = _list.begin();
|
||||
std::advance(it, index);
|
||||
_list.insert(it, item);
|
||||
_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
_mutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void Sort(){
|
||||
_mutex.lock();
|
||||
_list.sort();
|
||||
_mutex.unlock();
|
||||
}
|
||||
void Reverse(){
|
||||
_mutex.lock();
|
||||
_list.reverse();
|
||||
_mutex.unlock();
|
||||
}
|
||||
int find(const T& value) {
|
||||
const int count = _list.size();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if(Get(i) == &value){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // 未找到
|
||||
}
|
||||
bool IsContains(const T& item){
|
||||
_mutex.lock();
|
||||
bool isContains = find(item) != -1;
|
||||
_mutex.unlock();
|
||||
return isContains;
|
||||
}
|
||||
std::list<T> ToList(){
|
||||
_mutex.lock();
|
||||
std::list<T> list = _list;
|
||||
_mutex.unlock();
|
||||
return list;
|
||||
}
|
||||
std::vector<T> ToVector(){
|
||||
_mutex.lock();
|
||||
std::vector<T> vector;
|
||||
for (auto& item : _list) {
|
||||
vector.push_back(item);
|
||||
}
|
||||
_mutex.unlock();
|
||||
return vector;
|
||||
}
|
||||
typename std::list<T>::iterator begin() {
|
||||
return _list.begin();
|
||||
}
|
||||
typename std::list<T>::iterator end() {
|
||||
return _list.end();
|
||||
}
|
||||
List<T> operator=(const List<T>& list){
|
||||
_mutex.lock();
|
||||
_list = list._list;
|
||||
_mutex.unlock();
|
||||
return list;
|
||||
}
|
||||
List<T> operator=(const std::list<T>& list){
|
||||
_mutex.lock();
|
||||
_list = list;
|
||||
_mutex.unlock();
|
||||
return *this;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
private:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
209
CC_SDK_VS/TL/Map.h
Normal file
209
CC_SDK_VS/TL/Map.h
Normal file
@ -0,0 +1,209 @@
|
||||
#ifndef SDK_TL_MAP_H
|
||||
#define SDK_TL_MAP_H
|
||||
|
||||
#include "iostream"
|
||||
#include "vector"
|
||||
#include "list"
|
||||
#include "map"
|
||||
#include "mutex"
|
||||
#include "string"
|
||||
#include "shared_mutex"
|
||||
|
||||
namespace CTL{
|
||||
template<typename K, typename V>
|
||||
class Map{
|
||||
private:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
mutable std::shared_mutex _mutex;
|
||||
std::map<K, V> _map;
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
public:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
friend std::ostream& operator<<(std::ostream& os,Map<K,V>& map) {
|
||||
os << "[\n";
|
||||
auto items = map.ToStdMap();
|
||||
auto it = items.begin();
|
||||
while (it != items.end()) {
|
||||
os << " {\n " << it->first << ": " << it->second << "\n }";
|
||||
++it;
|
||||
if (it != items.end()) {
|
||||
os << ",\n";
|
||||
}
|
||||
}
|
||||
os << "\n]";
|
||||
return os;
|
||||
}
|
||||
friend std::ostream& operator<<(std::ostream& os,const Map<K,V>& map) {
|
||||
os << "[\n";
|
||||
auto items = map.ToStdMap();
|
||||
auto it = items.begin();
|
||||
while (it != items.end()) {
|
||||
os << " {\n " << it->first << ": " << it->second << "\n }";
|
||||
++it;
|
||||
if (it != items.end()) {
|
||||
os << ",\n";
|
||||
}
|
||||
}
|
||||
os << "\n]";
|
||||
return os;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
Map() = default;
|
||||
explicit Map(const std::map<K,V>& map){
|
||||
std::lock_guard lock(_mutex);
|
||||
_map = map;
|
||||
}
|
||||
Map(const Map<K,V>& map){
|
||||
std::lock_guard lock(_mutex);
|
||||
this->_map = map._map;
|
||||
}
|
||||
Map(const std::initializer_list<std::pair<K, V>>& list){
|
||||
std::lock_guard lock(_mutex);
|
||||
for (const auto& item : list) {
|
||||
_map.insert(item);
|
||||
}
|
||||
}
|
||||
~Map() {
|
||||
Clear();
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void Put(K key, V value){
|
||||
std::lock_guard lock(_mutex);
|
||||
_map.insert(std::make_pair(key, value));
|
||||
}
|
||||
void put(K key, V value){
|
||||
Put(key,value);
|
||||
}
|
||||
void Revise(K key, V value){
|
||||
std::lock_guard lock(_mutex);
|
||||
_map[key] = value;
|
||||
}
|
||||
void revise(K key, V value){
|
||||
std::lock_guard lock(_mutex);
|
||||
_map[key] = value;
|
||||
}
|
||||
void Remove(K key){
|
||||
std::lock_guard lock(_mutex);
|
||||
_map.erase(key);
|
||||
}
|
||||
void remove(K key){
|
||||
std::lock_guard lock(_mutex);
|
||||
_map.erase(key);
|
||||
}
|
||||
void Clear(){
|
||||
std::lock_guard lock(_mutex);
|
||||
std::map<K, V>().swap(this->_map);
|
||||
}
|
||||
void clear(){
|
||||
std::lock_guard lock(_mutex);
|
||||
std::map<K, V>().swap(this->_map);
|
||||
}
|
||||
static void swap(Map<K,V>* map) {
|
||||
std::map<K, V>().swap(map->_map);
|
||||
}
|
||||
V* Get(const K& key){
|
||||
std::shared_lock lock(_mutex);
|
||||
const bool F = _map.find(key) != _map.end();
|
||||
if (!F) {
|
||||
return nullptr;
|
||||
}
|
||||
return &_map[key];
|
||||
}
|
||||
V* get(const K& key){
|
||||
return Get(key);
|
||||
}
|
||||
V at(const K& key) const{
|
||||
std::shared_lock lock(_mutex);
|
||||
return _map.at(key);
|
||||
}
|
||||
V* operator[](const K& key){
|
||||
std::shared_lock lock(_mutex);
|
||||
const bool F = _map.find(key) != _map.end();
|
||||
if (!F) {
|
||||
return nullptr;
|
||||
}
|
||||
return &_map[key];
|
||||
}
|
||||
int Size(){
|
||||
std::shared_lock lock(_mutex);
|
||||
return _map.size();
|
||||
}
|
||||
int size(){
|
||||
std::shared_lock lock(_mutex);
|
||||
return _map.size();
|
||||
}
|
||||
bool IsContains(const K& key){
|
||||
std::shared_lock lock(_mutex);
|
||||
return _map.find(key) != _map.end();
|
||||
}
|
||||
bool IsEmpty(){
|
||||
std::shared_lock lock(_mutex);
|
||||
return _map.empty();
|
||||
}
|
||||
bool IsFull(){
|
||||
std::shared_lock lock(_mutex);
|
||||
return _map.size() == _map.max_size();
|
||||
}
|
||||
std::list<K> Keys(){
|
||||
std::shared_lock lock(_mutex);
|
||||
std::list<K> keys;
|
||||
for(auto& item : _map){
|
||||
keys.push_back(item.first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
std::list<K> keys(){
|
||||
return Keys();
|
||||
}
|
||||
std::vector<V> Values(){
|
||||
std::shared_lock lock(_mutex);
|
||||
std::vector<V> values;
|
||||
for(auto& item : _map){
|
||||
values.push_back(item.second);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
std::vector<V> values(){
|
||||
return Values();
|
||||
}
|
||||
std::map<K,V> ToStdMap(){
|
||||
return _map;
|
||||
}
|
||||
std::map<K,V> ToStdMap() const { // 实现处同样添加 const
|
||||
return _map; // 假设内部存储为 _map
|
||||
}
|
||||
void SetStdMap(const Map<K,V>& map) {
|
||||
std::lock_guard lock(_mutex);
|
||||
_map = map._map;
|
||||
}
|
||||
void SetStdMap(const std::map<K,V>& map) {
|
||||
std::lock_guard lock(_mutex);
|
||||
_map = map;
|
||||
}
|
||||
typename std::map<K, V>::iterator begin() {
|
||||
return _map.begin();
|
||||
}
|
||||
typename std::map<K, V>::iterator end() {
|
||||
return _map.end();
|
||||
}
|
||||
Map<K,V> operator=(const Map<K,V>& map) {
|
||||
std::lock_guard lock(_mutex);
|
||||
_map = map._map;
|
||||
return map;
|
||||
}
|
||||
Map<K,V> operator=(const std::map<K,V>& map) {
|
||||
std::lock_guard lock(_mutex);
|
||||
_map = map;
|
||||
return this;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
private:
|
||||
};
|
||||
template<typename K, typename V>
|
||||
class MapPtr:public Map<K,V*> {
|
||||
public:
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
409
CC_SDK_VS/TL/Map_CTL.h
Normal file
409
CC_SDK_VS/TL/Map_CTL.h
Normal file
@ -0,0 +1,409 @@
|
||||
#ifndef MAP_CTL_H
|
||||
#define MAP_CTL_H
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
namespace CTL {
|
||||
enum COLOR{
|
||||
BLACK_t,
|
||||
RED_t
|
||||
};
|
||||
template <class V>
|
||||
struct RBTreeNode{
|
||||
RBTreeNode<V>* _parent; //父节点
|
||||
RBTreeNode<V>* _left; //左孩子
|
||||
RBTreeNode<V>* _right; //右孩子
|
||||
V _val;
|
||||
COLOR _color; //颜色
|
||||
explicit RBTreeNode(const V& val = V())
|
||||
:_parent(nullptr)
|
||||
, _left(nullptr)
|
||||
, _right(nullptr)
|
||||
, _val(val)
|
||||
, _color(RED_t) {
|
||||
|
||||
}
|
||||
};
|
||||
template <class K, class V, class KeyOfValue>
|
||||
class RBTree{
|
||||
public:
|
||||
typedef RBTreeNode<V> Node;
|
||||
RBTree():_header(new Node){
|
||||
_header->_left = _header->_right = _header;
|
||||
}
|
||||
~RBTree() {
|
||||
clear();
|
||||
delete _header;
|
||||
_header = nullptr;
|
||||
}
|
||||
bool insert(const V& val){
|
||||
if (_header->_parent == nullptr){
|
||||
Node* root = new Node(val);
|
||||
_header->_parent = root;
|
||||
root->_parent = _header;
|
||||
_header->_left = _header->_right = root;
|
||||
//根节点为黑色
|
||||
root->_color = BLACK_t;
|
||||
return true;
|
||||
}
|
||||
|
||||
Node* cur = _header->_parent;
|
||||
Node* parent = nullptr;
|
||||
|
||||
KeyOfValue kov;
|
||||
//1.寻找到要插入的结点的位置
|
||||
while (cur){
|
||||
parent = cur;
|
||||
if (kov(cur->_val) == kov(val)) {
|
||||
return false;
|
||||
}
|
||||
else if (kov(cur->_val) > kov(val)) {
|
||||
cur = cur->_left;
|
||||
}
|
||||
else {
|
||||
cur = cur->_right;
|
||||
}
|
||||
}
|
||||
//2.创建节点
|
||||
cur = new Node(val);
|
||||
if (kov(parent->_val) > kov(cur->_val)) {
|
||||
parent->_left = cur;
|
||||
}
|
||||
else {
|
||||
parent->_right = cur;
|
||||
}
|
||||
cur->_parent = parent;
|
||||
|
||||
//3.颜色的修改或者结构的调整
|
||||
while (cur != _header->_parent && cur->_parent->_color == RED_t){ //不为根且存在连续红色,则需要调整
|
||||
parent = cur->_parent;
|
||||
Node* gfather = parent->_parent;
|
||||
|
||||
if (gfather->_left == parent){
|
||||
Node* uncle = gfather->_right;
|
||||
//情况1.uncle存在且为红
|
||||
if (uncle && uncle->_color == RED_t){
|
||||
parent->_color = uncle->_color = BLACK_t;
|
||||
gfather->_color = RED_t;
|
||||
//向上追溯
|
||||
cur = gfather;
|
||||
}
|
||||
else{
|
||||
if (parent->_right == cur){ //情况3
|
||||
RotateL(parent);
|
||||
swap(cur, parent);
|
||||
}
|
||||
//情况2.uncle不存在或者uncle为黑
|
||||
RotateR(gfather);
|
||||
parent->_color = BLACK_t;
|
||||
gfather->_color = RED_t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Node* uncle = gfather->_left;
|
||||
if (uncle && uncle->_color == RED_t){
|
||||
parent->_color = uncle->_color = BLACK_t;
|
||||
gfather->_color = RED_t;
|
||||
//向上追溯
|
||||
cur = gfather;
|
||||
}
|
||||
else{
|
||||
if (parent->_left == cur){
|
||||
RotateR(parent);
|
||||
swap(cur, parent);
|
||||
}
|
||||
|
||||
RotateL(gfather);
|
||||
parent->_color = BLACK_t;
|
||||
gfather->_color = RED_t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//根节点为黑色
|
||||
_header->_parent->_color = BLACK_t;
|
||||
//更新头结点的左右指向
|
||||
_header->_left = leftMost();
|
||||
_header->_right = rightMost();
|
||||
return true;
|
||||
}
|
||||
void RotateL(Node* parent){
|
||||
Node* subR = parent->_right;
|
||||
Node* subRL = subR->_left;
|
||||
|
||||
parent->_right = subRL;
|
||||
if (subRL) {
|
||||
subRL->_parent = parent;
|
||||
}
|
||||
if (parent == _header->_parent){
|
||||
_header->_parent = subR;
|
||||
subR->_parent = _header;
|
||||
}
|
||||
else{
|
||||
Node* gfather = parent->_parent;
|
||||
if (gfather->_left == parent) {
|
||||
gfather->_left = subR;
|
||||
}
|
||||
else {
|
||||
gfather->_right = subR;
|
||||
}
|
||||
subR->_parent = gfather;
|
||||
}
|
||||
subR->_left = parent;
|
||||
parent->_parent = subR;
|
||||
}
|
||||
void RotateR(Node* parent){
|
||||
Node* subL = parent->_left;
|
||||
Node* subLR = subL->_right;
|
||||
|
||||
parent->_left = subLR;
|
||||
if (subLR) {
|
||||
subLR->_parent = parent;
|
||||
}
|
||||
|
||||
if (parent == _header->_parent){
|
||||
_header->_parent = subL;
|
||||
subL->_parent = _header;
|
||||
}
|
||||
else{
|
||||
Node* gfather = parent->_parent;
|
||||
if (gfather->_left == parent) {
|
||||
gfather->_left = subL;
|
||||
}
|
||||
else {
|
||||
gfather->_right = subL;
|
||||
}
|
||||
subL->_parent = gfather;
|
||||
}
|
||||
subL->_right = parent;
|
||||
parent->_parent = subL;
|
||||
}
|
||||
Node* leftMost() const {
|
||||
Node* cur = _header->_parent;
|
||||
while (cur && cur->_left){
|
||||
cur = cur->_left;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
Node* rightMost() const {
|
||||
Node* cur = _header->_parent;
|
||||
while (cur && cur->_right){
|
||||
cur = cur->_right;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
Node* leftMostPublic() const {
|
||||
Node* node = leftMost();
|
||||
if (node == _header) {
|
||||
return nullptr;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
Node* getRoot() const {
|
||||
return _header->_parent;
|
||||
}
|
||||
Node* findNode(const K& key) {
|
||||
Node* cur = getRoot();
|
||||
KeyOfValue kov;
|
||||
while (cur) {
|
||||
if (kov(cur->_val) == key) {
|
||||
return cur;
|
||||
}
|
||||
else if (kov(cur->_val) > key) {
|
||||
cur = cur->_left;
|
||||
}
|
||||
else {
|
||||
cur = cur->_right;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
Node* getHeader() const {
|
||||
return _header;
|
||||
}
|
||||
bool erase(const K& key) {
|
||||
Node* node = findNode(key);
|
||||
if (!node) return false;
|
||||
|
||||
// 实际删除节点的逻辑
|
||||
deleteNode(node);
|
||||
return true;
|
||||
}
|
||||
void clear() {
|
||||
destroy(_header->_parent);
|
||||
_header->_parent = nullptr;
|
||||
_header->_left = _header->_right = _header;
|
||||
}
|
||||
private:
|
||||
void destroy(Node* node) {
|
||||
if (!node || node == _header) return;
|
||||
std::stack<Node*> nodes_to_delete;
|
||||
nodes_to_delete.push(node);
|
||||
while (!nodes_to_delete.empty()) {
|
||||
Node* current = nodes_to_delete.top();
|
||||
nodes_to_delete.pop();
|
||||
if (current->_left && current->_left != _header && current->_left != nullptr) {
|
||||
nodes_to_delete.push(current->_left);
|
||||
}
|
||||
if (current->_right && current->_right != _header && current->_right != nullptr) {
|
||||
nodes_to_delete.push(current->_right);
|
||||
}
|
||||
delete current;
|
||||
current = nullptr;
|
||||
}
|
||||
}
|
||||
void destroy_t(Node* node) {
|
||||
if (node && node != _header) {
|
||||
destroy(node->_left);
|
||||
destroy(node->_right);
|
||||
delete node;
|
||||
node = nullptr;
|
||||
}
|
||||
}
|
||||
void deleteNode(Node* node) {
|
||||
// 简化的删除实现(实际红黑树删除更复杂)
|
||||
if (node->_left && node->_right) {
|
||||
// 找到中序后继
|
||||
Node* successor = node->_right;
|
||||
while (successor->_left) {
|
||||
successor = successor->_left;
|
||||
}
|
||||
|
||||
// 交换值
|
||||
std::swap(node->_val, successor->_val);
|
||||
|
||||
// 删除后继节点
|
||||
deleteNode(successor);
|
||||
return;
|
||||
}
|
||||
|
||||
// 节点最多只有一个子节点
|
||||
Node* child = node->_left ? node->_left : node->_right;
|
||||
if (!node->_parent) {
|
||||
// 删除根节点
|
||||
_header->_parent = child;
|
||||
} else if (node == node->_parent->_left) {
|
||||
node->_parent->_left = child;
|
||||
} else {
|
||||
node->_parent->_right = child;
|
||||
}
|
||||
|
||||
if (child) {
|
||||
child->_parent = node->_parent;
|
||||
}
|
||||
|
||||
delete node;
|
||||
|
||||
// 更新边界节点
|
||||
if (_header->_parent) {
|
||||
_header->_left = leftMost();
|
||||
_header->_right = rightMost();
|
||||
} else {
|
||||
_header->_left = _header->_right = _header;
|
||||
}
|
||||
}
|
||||
public:
|
||||
private:
|
||||
Node* _header = nullptr;
|
||||
};
|
||||
template<typename K, typename V>
|
||||
class Map_CTL {
|
||||
struct MapKeyOfValue{
|
||||
const K& operator()(const std::pair<K, V>& val){
|
||||
return val.first;
|
||||
}
|
||||
};
|
||||
typedef RBTree<K, std::pair<K, V>, MapKeyOfValue> rbt;
|
||||
rbt _rbt;
|
||||
public:
|
||||
class iterator {
|
||||
typename rbt::Node* _node;
|
||||
const Map_CTL* _map;
|
||||
const rbt* _tree;
|
||||
public:
|
||||
iterator(typename rbt::Node* node, const rbt* tree)
|
||||
: _node(node), _map(nullptr), _tree(tree) {
|
||||
}
|
||||
iterator& operator++() {
|
||||
if (_node) {
|
||||
// 如果有右子树,找到右子树的最左节点
|
||||
if (_node->_right) {
|
||||
_node = _node->_right;
|
||||
while (_node->_left) {
|
||||
_node = _node->_left;
|
||||
}
|
||||
} else {
|
||||
// 否则向上找到第一个父节点,当前节点在其左子树中
|
||||
typename rbt::Node* parent = _node->_parent;
|
||||
while (parent && _node == parent->_right) {
|
||||
_node = parent;
|
||||
parent = parent->_parent;
|
||||
}
|
||||
// 检查是否到达了 header(即遍历完成)
|
||||
if (parent == _tree->getHeader()) {
|
||||
_node = nullptr;
|
||||
} else {
|
||||
_node = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int) {
|
||||
iterator temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
std::pair<K, V>& operator*() const {
|
||||
return _node->_val;
|
||||
}
|
||||
std::pair<K, V>* operator->() const {
|
||||
return &(_node->_val);
|
||||
}
|
||||
bool operator==(const iterator& other) const {
|
||||
return _node == other._node && _map == other._map;
|
||||
}
|
||||
bool operator!=(const iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
friend class iterator;
|
||||
private:
|
||||
bool insert(const std::pair<K, V>& kv){
|
||||
return _rbt.insert(kv);
|
||||
}
|
||||
public:
|
||||
Map_CTL() = default;
|
||||
~Map_CTL() {
|
||||
clear();
|
||||
}
|
||||
void put(const K& key, const V& value) {
|
||||
insert(std::pair<K, V>(key,value));
|
||||
}
|
||||
V* get(const K& key) {
|
||||
typename rbt::Node* node = _rbt.findNode(key);
|
||||
if (node) {
|
||||
return &(node->_val.second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void remove(const K& key) {
|
||||
_rbt.erase(key);
|
||||
}
|
||||
void clear() {
|
||||
_rbt.clear();
|
||||
}
|
||||
iterator begin() {
|
||||
return iterator(_rbt.leftMostPublic(), &_rbt);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(nullptr, &_rbt);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
69
CC_SDK_VS/TL/Queue.h
Normal file
69
CC_SDK_VS/TL/Queue.h
Normal file
@ -0,0 +1,69 @@
|
||||
#ifndef SDK_TL_QUEUE_H
|
||||
#define SDK_TL_QUEUE_H
|
||||
|
||||
#include "mutex"
|
||||
#include "AutoDestruct.h"
|
||||
#include "deque"
|
||||
|
||||
namespace CTL{
|
||||
template<typename T>
|
||||
class Queue{
|
||||
private:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
std::mutex _mutex;
|
||||
std::deque<T> _deque;
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
public:
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
Queue() = default;
|
||||
~Queue() = default;
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void Add(const T& data){
|
||||
_mutex.lock();
|
||||
_deque.push_back(std::move(data));
|
||||
_mutex.unlock();
|
||||
}
|
||||
void AddFirst(const T& data){
|
||||
_mutex.lock();
|
||||
_deque.push_front(std::move(data));
|
||||
_mutex.unlock();
|
||||
}
|
||||
AutoDestruct<T> Poll(){
|
||||
_mutex.lock();
|
||||
if(_deque.empty()){
|
||||
_mutex.unlock();
|
||||
return nullptr;
|
||||
}
|
||||
T* data = new T(_deque.front());
|
||||
_deque.pop_front();
|
||||
_mutex.unlock();
|
||||
return data;
|
||||
}
|
||||
AutoDestruct<T> PollBack(){
|
||||
_mutex.lock();
|
||||
if(_deque.empty()){
|
||||
_mutex.unlock();
|
||||
return nullptr;
|
||||
}
|
||||
T* data = new T(_deque.back());
|
||||
_deque.pop_back();
|
||||
_mutex.unlock();
|
||||
return data;
|
||||
}
|
||||
bool IsEmpty(){
|
||||
_mutex.lock();
|
||||
bool empty = _deque.empty();
|
||||
_mutex.unlock();
|
||||
return empty;
|
||||
}
|
||||
int Size(){
|
||||
_mutex.lock();
|
||||
int size = _deque.size();
|
||||
_mutex.unlock();
|
||||
return size;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,6 +1,8 @@
|
||||
#ifndef CC_WEBSOCKET_H
|
||||
#define CC_WEBSOCKET_H
|
||||
|
||||
#include "../CCMutex.h"
|
||||
#include "../CCThreadPool.h"
|
||||
|
||||
namespace CTL{
|
||||
class WebSocket {
|
||||
188
CC_SDK_VS/base/CCByte.h
Normal file
188
CC_SDK_VS/base/CCByte.h
Normal file
@ -0,0 +1,188 @@
|
||||
#ifndef CC_BYTE_H
|
||||
#define CC_BYTE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <bits/stdint-uintn.h>
|
||||
|
||||
#include "iostream"
|
||||
|
||||
namespace CTL {
|
||||
class Byte {
|
||||
uint8_t value; // 存储单个字节的数据
|
||||
public:
|
||||
// 构造函数
|
||||
Byte(const uint8_t& val = 0) : value(val) {}
|
||||
Byte(const char& c) {
|
||||
value = c;
|
||||
}
|
||||
Byte(const int& val) {
|
||||
value = val;
|
||||
}
|
||||
Byte(const size_t& val) {
|
||||
value = val;
|
||||
}
|
||||
// 获取当前字节的值
|
||||
[[nodiscard]] uint8_t get() const {
|
||||
return value;
|
||||
}
|
||||
// 设置当前字节的值
|
||||
void set(const uint8_t val) {
|
||||
value = val;
|
||||
}
|
||||
// 按位与操作
|
||||
Byte operator&(const Byte& other) const {
|
||||
return Byte(value & other.value);
|
||||
}
|
||||
// 按位或操作
|
||||
Byte operator|(const Byte& other) const {
|
||||
return Byte(value | other.value);
|
||||
}
|
||||
// 按位异或操作
|
||||
Byte operator^(const Byte& other) const {
|
||||
return Byte(value ^ other.value);
|
||||
}
|
||||
// 按位取反操作
|
||||
Byte operator~() const {
|
||||
return Byte(~value);
|
||||
}
|
||||
// 左移操作
|
||||
Byte operator<<(int n) const {
|
||||
return Byte(value << n);
|
||||
}
|
||||
// 右移操作
|
||||
Byte operator>>(int n) const {
|
||||
return Byte(value >> n);
|
||||
}
|
||||
bool operator==(const Byte& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
bool operator!=(const Byte& other) const {
|
||||
return value != other.value;
|
||||
}
|
||||
bool operator<(const Byte& other) const {
|
||||
return value < other.value;
|
||||
}
|
||||
bool operator>(const Byte& other) const {
|
||||
return value > other.value;
|
||||
}
|
||||
bool operator<=(const Byte& other) const {
|
||||
return value <= other.value;
|
||||
}
|
||||
bool operator>=(const Byte& other) const {
|
||||
return value >= other.value;
|
||||
}
|
||||
bool operator==(const int& other) const {
|
||||
return value == other;
|
||||
}
|
||||
bool operator!=(const int& other) const {
|
||||
return value != other;
|
||||
}
|
||||
bool operator<(const int& other) const {
|
||||
return value < other;
|
||||
}
|
||||
bool operator>(const int& other) const {
|
||||
return value > other;
|
||||
}
|
||||
bool operator<=(const int& other) const {
|
||||
return value <= other;
|
||||
}
|
||||
bool operator>=(const int& other) const {
|
||||
return value >= other;
|
||||
}
|
||||
Byte& operator=(const Byte& other) = default;
|
||||
Byte& operator=(uint8_t val) {
|
||||
value = val;
|
||||
return *this;
|
||||
}
|
||||
Byte operator++() {
|
||||
++value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator++(int) {
|
||||
Byte temp = *this;
|
||||
++value;
|
||||
return temp;
|
||||
}
|
||||
Byte operator--() {
|
||||
--value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator--(int) {
|
||||
Byte temp = *this;
|
||||
--value;
|
||||
return temp;
|
||||
}
|
||||
Byte operator+=(const Byte& other) {
|
||||
value += other.value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator-=(const Byte& other) {
|
||||
value -= other.value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator*=(const Byte& other) {
|
||||
value *= other.value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator/=(const Byte& other) {
|
||||
value /= other.value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator%=(const Byte& other) {
|
||||
value %= other.value;
|
||||
return *this;
|
||||
}
|
||||
Byte operator<<=(int n) {
|
||||
value <<= n;
|
||||
return *this;
|
||||
}
|
||||
Byte operator>>=(int n) {
|
||||
value >>= n;
|
||||
return *this;
|
||||
}
|
||||
operator uint8_t() const {
|
||||
return value;
|
||||
}
|
||||
operator uint8_t() {
|
||||
return value;
|
||||
}
|
||||
operator char() const {
|
||||
return value;
|
||||
}
|
||||
operator char() {
|
||||
return value;
|
||||
}
|
||||
// 提供显式的转换操作符
|
||||
operator int() const {
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
operator int() {
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
// 输出字节的二进制表示
|
||||
friend std::ostream& operator<<(std::ostream& os, const Byte& byte) {
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
os << ((byte.value >> i) & 1);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
friend std::istream& operator>>(std::istream& is, Byte& byte) {
|
||||
uint8_t val;
|
||||
is >> val;
|
||||
byte.value = val;
|
||||
return is;
|
||||
}
|
||||
static Byte* fromCString(const char* cstr) {
|
||||
size_t length = strlen(cstr);
|
||||
auto* bytes = new Byte[length + 1];
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
bytes[i] = cstr[i];
|
||||
}
|
||||
bytes[length] = '\0';
|
||||
return bytes;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
454
CC_SDK_VS/base/CCByteArray.cpp
Normal file
454
CC_SDK_VS/base/CCByteArray.cpp
Normal file
@ -0,0 +1,454 @@
|
||||
#include "CCByteArray.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "vector"
|
||||
#include "list"
|
||||
|
||||
using namespace CTL;
|
||||
|
||||
static const char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static const unsigned char base64_decode_table[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
ByteArray::ByteArray(const std::string &str) {
|
||||
bytes.assign(str.begin(), str.end());
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const void *str, const size_t size) {
|
||||
this->Conversion<>(str,size);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const char *str) {
|
||||
bytes.assign(str, str + strlen(str));
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const ByteArray &other) {
|
||||
bytes.assign(other.bytes.begin(), other.bytes.end());
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const std::vector<Byte> &bytes) {
|
||||
this->bytes.assign(bytes.begin(), bytes.end());
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const std::list<Byte> &bytes) {
|
||||
this->bytes.assign(bytes.begin(), bytes.end());
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const Byte *bytes) {
|
||||
this->bytes.assign(bytes, bytes + strlen(reinterpret_cast<const char *>(bytes)));
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const ByteHander size) {
|
||||
bytes.resize(size);
|
||||
}
|
||||
|
||||
void ByteArray::add(const Byte byte) {
|
||||
bytes.push_back(byte);
|
||||
}
|
||||
|
||||
Byte ByteArray::get(const int index) const {
|
||||
if (index < 0 || index >= bytes.size()) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
return bytes[index];
|
||||
}
|
||||
|
||||
void ByteArray::set(const int index, const Byte byte) {
|
||||
if (index < 0 || index >= bytes.size()) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
bytes[index] = byte;
|
||||
}
|
||||
|
||||
void ByteArray::remove(const int index) {
|
||||
if (index < 0 || index >= bytes.size()) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
bytes.erase(bytes.begin() + index);
|
||||
}
|
||||
|
||||
size_t ByteArray::size() const {
|
||||
return bytes.size();
|
||||
}
|
||||
|
||||
void ByteArray::clear() {
|
||||
bytes.clear();
|
||||
}
|
||||
|
||||
void ByteArray::assign(char *buffer, const ByteHander size) {
|
||||
bytes.assign(buffer, buffer + size);
|
||||
}
|
||||
|
||||
void ByteArray::assign(const void *buffer, const ByteHander size) {
|
||||
const char* cstr = static_cast<const char*>(buffer);
|
||||
bytes.assign(cstr, cstr + size);
|
||||
}
|
||||
|
||||
bool ByteArray::IsEmpty() const {
|
||||
return bytes.empty();
|
||||
}
|
||||
|
||||
void ByteArray::append(const std::string& str) {
|
||||
bytes.insert(bytes.end(), str.begin(), str.end());
|
||||
}
|
||||
|
||||
void ByteArray::append(const ByteArray& str) {
|
||||
bytes.insert(bytes.end(), str.bytes.begin(), str.bytes.end());
|
||||
}
|
||||
|
||||
std::vector<Byte>::iterator ByteArray::begin() {
|
||||
return bytes.begin();
|
||||
}
|
||||
|
||||
std::vector<Byte>::iterator ByteArray::end() {
|
||||
return bytes.end();
|
||||
}
|
||||
|
||||
std::vector<Byte>::const_iterator ByteArray::begin() const {
|
||||
return bytes.begin();
|
||||
}
|
||||
|
||||
std::vector<Byte>::const_iterator ByteArray::end() const {
|
||||
return bytes.end();
|
||||
}
|
||||
|
||||
ByteArray ByteArray::fromString(const std::string &str) {
|
||||
ByteArray byteArray;
|
||||
for (const char c : str) {
|
||||
byteArray.add(Byte(static_cast<unsigned char>(c)));
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
std::string ByteArray::toString() const {
|
||||
std::string result;
|
||||
for (const Byte& byte : bytes) {
|
||||
result += static_cast<char>(byte.get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Byte> ByteArray::toVector() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
std::vector<Byte> ByteArray::toVector() const{
|
||||
return bytes;
|
||||
}
|
||||
|
||||
char * ByteArray::buffer() {
|
||||
return reinterpret_cast<char*>(bytes.data());
|
||||
}
|
||||
|
||||
const char* ByteArray::buffer() const {
|
||||
return reinterpret_cast<const char*>(bytes.data());
|
||||
}
|
||||
|
||||
char * ByteArray::newBuffer() const {
|
||||
const auto str = new char[bytes.size() + 1];
|
||||
std::memcpy(str, bytes.data(), bytes.size());
|
||||
str[bytes.size()] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
void ByteArray::resize(const size_t len) {
|
||||
bytes.resize(len);
|
||||
}
|
||||
|
||||
void ByteArray::operator=(const ByteArray &other) {
|
||||
bytes = other.bytes;
|
||||
}
|
||||
|
||||
void ByteArray::operator=(const std::string &str) {
|
||||
bytes.assign(str.begin(), str.end());
|
||||
}
|
||||
|
||||
bool ByteArray::operator==(const ByteArray &other) const {
|
||||
return bytes == other.bytes;
|
||||
}
|
||||
|
||||
bool ByteArray::operator!=(const ByteArray &other) const {
|
||||
return bytes != other.bytes;
|
||||
}
|
||||
|
||||
void ByteArray::operator+=(const ByteArray &other) {
|
||||
bytes.insert(bytes.end(), other.bytes.begin(), other.bytes.end());
|
||||
}
|
||||
|
||||
void ByteArray::operator-=(const ByteArray &other) {
|
||||
if (other.bytes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从当前字节数组中移除所有在other中出现的元素
|
||||
for (const auto& byte : other.bytes) {
|
||||
bytes.erase(std::remove(bytes.begin(), bytes.end(), byte), bytes.end());
|
||||
}
|
||||
}
|
||||
|
||||
Byte& ByteArray::operator[](const int index) {
|
||||
if (index < 0 || index >= bytes.size()) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
return *(bytes.data() + index);
|
||||
}
|
||||
|
||||
Byte ByteArray::operator[](const int index) const {
|
||||
if (index < 0 || index >= bytes.size()) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
return *(bytes.data() + index);
|
||||
}
|
||||
|
||||
ByteArray ByteArray::subBuffer(const ByteHander start, const ByteHander end) const {
|
||||
if (start > end || end > bytes.size()) {
|
||||
throw std::out_of_range("subBuffer Index out of range");
|
||||
}
|
||||
ByteArray ret(bytes.data() + start, end - start);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string ByteArray::toBase64() {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
uint8_t char_array_3[3];
|
||||
uint8_t char_array_4[4];
|
||||
auto it = bytes.begin();
|
||||
while (it != bytes.end()) {
|
||||
char_array_3[i++] = *(it++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (i = 0; (i < 4); i++) {
|
||||
ret += base64_chars[char_array_4[i]];
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
int j = 0;
|
||||
for (j = i; j < 3; j++) {
|
||||
char_array_3[j] = '\0';
|
||||
}
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++) {
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
}
|
||||
|
||||
while ((i++ < 3)) {
|
||||
ret += '=';
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ByteArray ByteArray::fromBase64(const std::string &base64Str) {
|
||||
ByteArray result;
|
||||
unsigned char char_array_4[4];
|
||||
unsigned char char_array_3[3];
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
auto it = base64Str.begin();
|
||||
while (it != base64Str.end() && *it != '=') {
|
||||
// 跳过非Base64字符
|
||||
if (*it == ' ' || *it == '\r' || *it == '\n') {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
char_array_4[i++] = static_cast<unsigned char>(*it);
|
||||
++it;
|
||||
|
||||
if (i == 4) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
char_array_4[j] = base64_decode_table[char_array_4[j]];
|
||||
}
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
result.add(Byte(char_array_3[j]));
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理剩余字符
|
||||
if (i > 0) {
|
||||
for (j = i; j < 4; j++) {
|
||||
char_array_4[j] = 0;
|
||||
}
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
char_array_4[j] = base64_decode_table[char_array_4[j]];
|
||||
}
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; j < i - 1; j++) {
|
||||
result.add(Byte(char_array_3[j]));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ByteArray::fill(const Byte value, const size_t start, size_t end) {
|
||||
if (bytes.empty()) return;
|
||||
|
||||
if (end == static_cast<size_t>(-1)) {
|
||||
end = bytes.size();
|
||||
}
|
||||
|
||||
if (start >= bytes.size() || end > bytes.size() || start > end) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
|
||||
std::fill(bytes.begin() + start, bytes.begin() + end, value);
|
||||
}
|
||||
|
||||
void ByteArray::copyTo(ByteArray &dest, const size_t srcStart, const size_t destStart, size_t count) const {
|
||||
if (bytes.empty()) return;
|
||||
|
||||
if (srcStart >= bytes.size()) {
|
||||
throw std::out_of_range("Source start index out of range");
|
||||
}
|
||||
|
||||
if (count == static_cast<size_t>(-1)) {
|
||||
count = bytes.size() - srcStart;
|
||||
}
|
||||
|
||||
if (srcStart + count > bytes.size()) {
|
||||
throw std::out_of_range("Copy count exceeds source size");
|
||||
}
|
||||
|
||||
// 确保目标数组有足够的空间
|
||||
if (destStart + count > dest.bytes.size()) {
|
||||
dest.bytes.resize(destStart + count);
|
||||
}
|
||||
|
||||
// C++98兼容的实现:使用std::copy替代std::copy_n
|
||||
std::copy(bytes.begin() + srcStart,
|
||||
bytes.begin() + srcStart + count,
|
||||
dest.bytes.begin() + destStart);
|
||||
}
|
||||
|
||||
ByteArray ByteArray::clone() const {
|
||||
return ByteArray(*this);
|
||||
}
|
||||
|
||||
int ByteArray::indexOf(const Byte value, const size_t start) const {
|
||||
if (bytes.empty() || start >= bytes.size()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto it = std::find(bytes.begin() + start, bytes.end(), value);
|
||||
if (it != bytes.end()) {
|
||||
return static_cast<int>(std::distance(bytes.begin(), it));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ByteArray::lastIndexOf(const Byte value, size_t start) const {
|
||||
if (bytes.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (start == static_cast<size_t>(-1) || start >= bytes.size()) {
|
||||
start = bytes.size() - 1;
|
||||
}
|
||||
|
||||
for (int i = static_cast<int>(start); i >= 0; --i) {
|
||||
if (bytes[i] == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ByteArray::indexOf(const ByteArray &pattern, const size_t start) const {
|
||||
if (pattern.bytes.empty() || bytes.empty() || start >= bytes.size()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto it = std::search(bytes.begin() + start, bytes.end(),
|
||||
pattern.bytes.begin(), pattern.bytes.end());
|
||||
if (it != bytes.end()) {
|
||||
return static_cast<int>(std::distance(bytes.begin(), it));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ByteArray::lastIndexOf(const ByteArray &pattern, size_t start) const {
|
||||
if (pattern.bytes.empty() || bytes.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pattern.bytes.size() > bytes.size()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (start == static_cast<size_t>(-1) || start >= bytes.size()) {
|
||||
start = bytes.size() - 1;
|
||||
}
|
||||
|
||||
// 限制start确保不会越界
|
||||
if (start < pattern.bytes.size() - 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t end = start - pattern.bytes.size() + 1;
|
||||
for (int i = static_cast<int>(start); i >= static_cast<int>(end); --i) {
|
||||
bool match = true;
|
||||
for (size_t j = 0; j < pattern.bytes.size(); ++j) {
|
||||
if (bytes[i - static_cast<int>(pattern.bytes.size()) + 1 + j] != pattern.bytes[j]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return i - static_cast<int>(pattern.bytes.size()) + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ByteArray::equals(const ByteArray &other) const {
|
||||
return *this == other;
|
||||
}
|
||||
|
||||
331
CC_SDK_VS/base/CCByteArray.h
Normal file
331
CC_SDK_VS/base/CCByteArray.h
Normal file
@ -0,0 +1,331 @@
|
||||
#ifndef CC_BYTEARRAY_H
|
||||
#define CC_BYTEARRAY_H
|
||||
|
||||
#include <vector>
|
||||
#include "list"
|
||||
#include "CCByte.h"
|
||||
#include "../TL/AutoDestruct.h"
|
||||
|
||||
typedef size_t ByteHander; //
|
||||
#define HanderSize sizeof(ByteHander)
|
||||
|
||||
namespace CTL {
|
||||
/**
|
||||
* ByteArray类用于处理字节数组,提供多种方式的字节操作和转换。
|
||||
*/
|
||||
class ByteArray{
|
||||
std::vector<Byte> bytes;
|
||||
public:
|
||||
ByteArray() = default;
|
||||
/**
|
||||
* 构造函数,从std::string初始化字节数组。
|
||||
* @param str 用于初始化字节数组的字符串。
|
||||
*/
|
||||
ByteArray(const std::string& str);
|
||||
/**
|
||||
* 构造函数,将结构体指针初始化字节数组。
|
||||
* @param str 结构体指针。
|
||||
* @param size 结构体指针大小。
|
||||
*/
|
||||
ByteArray(const void* str, size_t size);
|
||||
/**
|
||||
* 构造函数,从C风格字符串初始化字节数组。
|
||||
* @param str 用于初始化字节数组的C风格字符串。
|
||||
*/
|
||||
ByteArray(const char* str);
|
||||
/**
|
||||
* 复制构造函数,从另一个ByteArray对象初始化字节数组。
|
||||
* @param other 用于初始化的另一个ByteArray对象。
|
||||
*/
|
||||
ByteArray(const ByteArray& other);
|
||||
/**
|
||||
* 构造函数,从std::vector<Byte>初始化字节数组。
|
||||
* @param bytes 用于初始化字节数组的vector。
|
||||
*/
|
||||
ByteArray(const std::vector<Byte>& bytes);
|
||||
/**
|
||||
* 构造函数,从std::list<Byte>初始化字节数组。
|
||||
* @param bytes 用于初始化字节数组的list。
|
||||
*/
|
||||
ByteArray(const std::list<Byte>& bytes);
|
||||
/**
|
||||
* 构造函数,从Byte指针初始化字节数组。
|
||||
* @param bytes 用于初始化字节数组的Byte指针。
|
||||
*/
|
||||
ByteArray(const Byte* bytes);
|
||||
/**
|
||||
* 构造函数,创建指定大小的字节数组。
|
||||
* @param size 要创建的字节数组的大小。
|
||||
*/
|
||||
ByteArray(ByteHander size);
|
||||
/**
|
||||
* 添加一个字节到字节数组末尾。
|
||||
* @param byte 要添加的字节。
|
||||
*/
|
||||
void add(Byte byte);
|
||||
/**
|
||||
* 获取指定索引处的字节。
|
||||
* @param index 字节的索引。
|
||||
* @return 指定索引处的字节。
|
||||
*/
|
||||
[[nodiscard]] Byte get(int index) const;
|
||||
/**
|
||||
* 设置指定索引处的字节。
|
||||
* @param index 要设置字节的索引。
|
||||
* @param byte 要设置的新字节。
|
||||
*/
|
||||
void set(int index, Byte byte);
|
||||
/**
|
||||
* 删除指定索引处的字节。
|
||||
* @param index 要删除字节的索引。
|
||||
*/
|
||||
void remove(int index);
|
||||
/**
|
||||
* 获取字节数组的大小。
|
||||
* @return 字节数组的大小。
|
||||
*/
|
||||
[[nodiscard]] size_t size() const;
|
||||
/**
|
||||
* 清空字节数组。
|
||||
*/
|
||||
void clear();
|
||||
/**
|
||||
* 用指定的缓冲区和大小赋值字节数组。
|
||||
* @param buffer 指定的缓冲区。
|
||||
* @param size 缓冲区的大小。
|
||||
*/
|
||||
void assign(char * buffer, ByteHander size);
|
||||
/**
|
||||
* 用指定的缓冲区和大小赋值字节数组。
|
||||
* @param buffer 指定的缓冲区。
|
||||
* @param size 缓冲区的大小。
|
||||
*/
|
||||
void assign(const void* buffer, ByteHander size);
|
||||
/**
|
||||
* 判断字节数组是否为空。
|
||||
* @return 字节数组是否为空。
|
||||
*/
|
||||
[[nodiscard]] bool IsEmpty() const;
|
||||
/**
|
||||
* 在字节数组末尾追加一个字符串。
|
||||
* @param str 要追加的字符串。
|
||||
*/
|
||||
void append(const std::string& str);
|
||||
/**
|
||||
* 在字节数组末尾追加另一个字节数组。
|
||||
* @param str 要追加的字节数组。
|
||||
*/
|
||||
void append(const ByteArray& str);
|
||||
/**
|
||||
* 返回字节数组的开始迭代器。
|
||||
* @return 字节数组的开始迭代器。
|
||||
*/
|
||||
std::vector<Byte>::iterator begin();
|
||||
/**
|
||||
* 返回字节数组的结束迭代器。
|
||||
* @return 字节数组的结束迭代器。
|
||||
*/
|
||||
std::vector<Byte>::iterator end();
|
||||
/**
|
||||
* 返回常量字节数组的开始迭代器。
|
||||
* @return 常量字节数组的开始迭代器。
|
||||
*/
|
||||
std::vector<Byte>::const_iterator begin() const;
|
||||
/**
|
||||
* 返回常量字节数组的结束迭代器。
|
||||
* @return 常量字节数组的结束迭代器。
|
||||
*/
|
||||
std::vector<Byte>::const_iterator end() const;
|
||||
/**
|
||||
* 从字符串创建字节数组。
|
||||
* @param str 用于创建字节数组的字符串。
|
||||
* @return 从字符串创建的字节数组。
|
||||
*/
|
||||
static ByteArray fromString(const std::string& str);
|
||||
/**
|
||||
* 将字节数组转换为字符串。
|
||||
* @return 字节数组的字符串表示。
|
||||
*/
|
||||
std::string toString() const;
|
||||
/**
|
||||
* 获取字节数组的底层vector。
|
||||
* @return 字节数组的底层vector。
|
||||
*/
|
||||
std::vector<Byte> toVector();
|
||||
/**
|
||||
* 获取字节数组的底层vector。
|
||||
* @return 字节数组的底层vector。
|
||||
*/
|
||||
std::vector<Byte> toVector() const;
|
||||
/**
|
||||
* 获取字节数组的缓冲区。
|
||||
* @return 字节数组的缓冲区。
|
||||
*/
|
||||
char* buffer();
|
||||
/**
|
||||
* 获取字节数组的缓冲区。
|
||||
* @return 字节数组的缓冲区。
|
||||
*/
|
||||
[[nodiscard]] const char* buffer() const;
|
||||
/**
|
||||
* 获取字节数组的缓冲区。
|
||||
* @return 新创建的字节数组的缓冲区(需要手动管理内存)
|
||||
*/
|
||||
char* newBuffer() const;
|
||||
/**
|
||||
* 调整字节数组的大小。
|
||||
* @param len 新的大小。
|
||||
*/
|
||||
void resize(size_t len);
|
||||
/**
|
||||
* 赋值运算符重载,用于字节数组之间的赋值。
|
||||
* @param other 要赋值的另一个字节数组。
|
||||
*/
|
||||
void operator = (const ByteArray& other);
|
||||
/**
|
||||
* 赋值运算符重载,用于字符串到字节数组的赋值。
|
||||
* @param str 要赋值的字符串。
|
||||
*/
|
||||
void operator = (const std::string& str);
|
||||
/**
|
||||
* 比较运算符重载,用于比较两个字节数组是否相等。
|
||||
* @param other 要比较的另一个字节数组。
|
||||
* @return 如果两个字节数组相等则返回true,否则返回false。
|
||||
*/
|
||||
bool operator == (const ByteArray& other) const;
|
||||
/**
|
||||
* 比较运算符重载,用于比较两个字节数组是否不相等。
|
||||
* @param other 要比较的另一个字节数组。
|
||||
* @return 如果两个字节数组不相等则返回true,否则返回false。
|
||||
*/
|
||||
bool operator != (const ByteArray& other) const;
|
||||
/**
|
||||
* 加法运算符重载,用于追加另一个字节数组到当前字节数组末尾。
|
||||
* @param other 要追加的另一个字节数组。
|
||||
*/
|
||||
void operator += (const ByteArray& other);
|
||||
/**
|
||||
* 减法运算符重载,用于从当前字节数组中移除另一个字节数组的内容。
|
||||
* @param other 要移除的另一个字节数组。
|
||||
*/
|
||||
void operator -= (const ByteArray& other);
|
||||
/**
|
||||
* 索引运算符重载,用于获取字节数组中的指定索引处的字节。
|
||||
* @param index 要获取的字节索引。
|
||||
* @return 指定索引处的字节。
|
||||
*/
|
||||
Byte& operator [] (int index);
|
||||
/**
|
||||
* 索引运算符重载,用于获取字节数组中的指定索引处的字节。
|
||||
* @param index 要获取的字节索引。
|
||||
* @return 指定索引处的字节。
|
||||
*/
|
||||
Byte operator [] (int index) const;
|
||||
/**
|
||||
* 将字节数组转换为指定类型的指针。
|
||||
* @param other 要转换的字节数组
|
||||
* @return 返回指向字节数组的指定类型的指针(需要手动管理内存)
|
||||
*/
|
||||
template<typename T>
|
||||
static T* Conversion(const ByteArray& other) {
|
||||
const T* t_const = reinterpret_cast<const T*>(other.newBuffer());
|
||||
T* t = const_cast<T*>(t_const);
|
||||
return t;
|
||||
}
|
||||
/**
|
||||
* 将字节数组转换为指定类型的指针。
|
||||
* @return 指向字节数组的指定类型的指针(RAII管理内存)
|
||||
*/
|
||||
template<typename T>
|
||||
AutoDestruct<T> Conversion() {
|
||||
const T* t_const = reinterpret_cast<const T*>(this->newBuffer());
|
||||
T* t = const_cast<T*>(t_const);
|
||||
return CTL::AutoDestruct<T>(t);
|
||||
}
|
||||
/**
|
||||
* 将字节数组转换为指定类型的指针。
|
||||
* @param str 要转换的字节数组
|
||||
* @param size 字节数组的长度
|
||||
* @return 返回指向字节数组的指定类型的指针(RAII管理内存)
|
||||
*/
|
||||
template<typename T>
|
||||
void Conversion(T* str, const ByteHander size) {
|
||||
const auto c_str = reinterpret_cast<const char*>(str);
|
||||
bytes.assign(c_str, c_str + size);
|
||||
}
|
||||
/**
|
||||
* 获取字节数组的子数组。
|
||||
* @param start 子数组的起始索引。
|
||||
* @param end 子数组的结束索引。
|
||||
* @return 返回子数组。
|
||||
*/
|
||||
[[nodiscard]] ByteArray subBuffer(ByteHander start, ByteHander end) const;
|
||||
/**
|
||||
* 将字节数组转换为Base64字符串。
|
||||
* @return Base64字符串。
|
||||
*/
|
||||
std::string toBase64();
|
||||
/**
|
||||
* 将Base64字符串转换为字节数组。
|
||||
* @param base64Str Base64字符串。
|
||||
* @return 转换后的字节数组。
|
||||
*/
|
||||
static ByteArray fromBase64(const std::string& base64Str);
|
||||
/**
|
||||
* 将指定值填充到数组的某个范围
|
||||
* @param value 要填充的值
|
||||
* @param start 起始索引
|
||||
* @param end 结束索引(不包含)
|
||||
*/
|
||||
void fill(Byte value, size_t start = 0, size_t end = -1);
|
||||
/**
|
||||
* 复制数组的一部分到另一个ByteArray
|
||||
* @param dest 目标ByteArray
|
||||
* @param srcStart 源起始索引
|
||||
* @param destStart 目标起始索引
|
||||
* @param count 复制的元素数量
|
||||
*/
|
||||
void copyTo(ByteArray& dest, size_t srcStart = 0, size_t destStart = 0, size_t count = -1) const;
|
||||
/**
|
||||
* 克隆当前ByteArray
|
||||
* @return 新的ByteArray副本
|
||||
*/
|
||||
ByteArray clone() const;
|
||||
/**
|
||||
* 查找特定字节第一次出现的位置
|
||||
* @param value 要查找的字节
|
||||
* @param start 起始搜索位置
|
||||
* @return 找到的位置,未找到返回-1
|
||||
*/
|
||||
int indexOf(Byte value, size_t start = 0) const;
|
||||
/**
|
||||
* 查找特定字节最后一次出现的位置
|
||||
* @param value 要查找的字节
|
||||
* @param start 起始搜索位置
|
||||
* @return 找到的位置,未找到返回-1
|
||||
*/
|
||||
int lastIndexOf(Byte value, size_t start = -1) const;
|
||||
/**
|
||||
* 查找字节序列第一次出现的位置
|
||||
* @param pattern 要查找的字节序列
|
||||
* @param start 起始搜索位置
|
||||
* @return 找到的位置,未找到返回-1
|
||||
*/
|
||||
int indexOf(const ByteArray& pattern, size_t start = 0) const;
|
||||
/**
|
||||
* 查找字节序列最后一次出现的位置
|
||||
* @param pattern 要查找的字节序列
|
||||
* @param start 起始搜索位置
|
||||
* @return 找到的位置,未找到返回-1
|
||||
*/
|
||||
int lastIndexOf(const ByteArray& pattern, size_t start = -1) const;
|
||||
/**
|
||||
* 比较两个ByteArray是否相等
|
||||
* @param other 要比较的另一个ByteArray
|
||||
* @return 如果相等返回true,否则返回false
|
||||
*/
|
||||
bool equals(const ByteArray& other) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,10 +1,19 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
cmake_minimum_required(VERSION 3.0...4.0)
|
||||
project(WebSocket)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 98)
|
||||
|
||||
add_executable(WebSocket
|
||||
main.cpp
|
||||
WebSocket/CCWebSocket.cpp
|
||||
WebSocket/CCWebSocket.h
|
||||
CC_SDK_VS/WebSocket/CCWebSocket.cpp
|
||||
CC_SDK_VS/WebSocket/CCWebSocket.h
|
||||
CC_SDK_VS/CCMutex.cpp
|
||||
CC_SDK_VS/CCThread.cpp
|
||||
CC_SDK_VS/CCThreadPool.cpp
|
||||
CC_SDK_VS/Socket/CCClientSocket.cpp
|
||||
CC_SDK_VS/Socket/CCDatagramSocket.cpp
|
||||
CC_SDK_VS/Socket/CCServerSocket.cpp
|
||||
CC_SDK_VS/Socket/CCSocket.cpp
|
||||
CC_SDK_VS/base/CCByteArray.cpp
|
||||
CC_SDK_VS/TL/AutoDestruct.h
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user