重构SmartOS的结构,基本类型独立Core目录,平台无关
This commit is contained in:
parent
bedd031f56
commit
8194e555e1
|
@ -1,4 +1,6 @@
|
|||
#include "Config.h"
|
||||
#include "stddef.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Flash.h"
|
||||
#include "Security\Crc.h"
|
||||
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <math.h>
|
||||
//#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "_Core.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
|
||||
/******************************** Array ********************************/
|
||||
|
||||
// 数组最大容量。初始化时决定,后面不允许改变
|
||||
//int Array::Capacity() const { return _Capacity; }
|
||||
|
||||
/*int MemLen(const void* data)
|
||||
{
|
||||
if(!data) return 0;
|
||||
|
||||
// 自动计算长度,\0结尾,单字节大小时才允许
|
||||
int len = 0;
|
||||
const byte* p =(const byte*)data;
|
||||
while(*p++) len++;
|
||||
return len;
|
||||
}*/
|
||||
|
||||
Array::Array(void* data, int len) : Buffer(data, len)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
Array::Array(const void* data, int len) : Buffer((void*)data, len)
|
||||
{
|
||||
Init();
|
||||
|
||||
_canWrite = false;
|
||||
}
|
||||
|
||||
Array::Array(const Buffer& rhs) : Buffer(nullptr, 0)
|
||||
{
|
||||
Copy(0, rhs, 0, -1);
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
/*Array::Array(const Array& rhs) : Buffer(nullptr, 0)
|
||||
{
|
||||
Copy(0, rhs, 0, -1);
|
||||
|
||||
Init();
|
||||
}*/
|
||||
|
||||
Array::Array(Array&& rval) : Buffer(nullptr, 0)
|
||||
{
|
||||
//*this = rval;
|
||||
move(rval);
|
||||
}
|
||||
|
||||
void Array::move(Array& rval)
|
||||
{
|
||||
Buffer::move(rval);
|
||||
|
||||
_Capacity = rval._Capacity;
|
||||
_needFree = rval._needFree;
|
||||
_canWrite = rval._canWrite;
|
||||
|
||||
rval._Capacity = 0;
|
||||
rval._needFree = false;
|
||||
rval._canWrite = false;
|
||||
}
|
||||
|
||||
void Array::Init()
|
||||
{
|
||||
_Size = 1;
|
||||
|
||||
_Capacity = _Length;
|
||||
_needFree = false;
|
||||
_canWrite = true;
|
||||
}
|
||||
|
||||
// 析构。释放资源
|
||||
Array::~Array()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
// 释放已占用内存
|
||||
bool Array::Release()
|
||||
{
|
||||
auto p = _Arr;
|
||||
bool fr = _needFree;
|
||||
|
||||
_Arr = nullptr;
|
||||
_Capacity = 0;
|
||||
_Length = 0;
|
||||
_needFree = false;
|
||||
_canWrite = true;
|
||||
|
||||
if(fr && p)
|
||||
{
|
||||
delete (byte*)p;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Array& Array::operator = (const Buffer& rhs)
|
||||
{
|
||||
// 可能需要先扩容,否则Buffer拷贝时,长度可能不准确
|
||||
// 长度也要相等,可能会因此而扩容
|
||||
//SetLength(rhs.Length());
|
||||
|
||||
Buffer::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array& Array::operator = (const void* p)
|
||||
{
|
||||
Buffer::operator=(p);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array& Array::operator = (Array&& rval)
|
||||
{
|
||||
//Buffer::operator=(rval);
|
||||
move(rval);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 设置数组长度。容量足够则缩小Length,否则扩容以确保数组容量足够大避免多次分配内存
|
||||
bool Array::SetLength(int len)
|
||||
{
|
||||
return SetLength(len, false);
|
||||
}
|
||||
|
||||
bool Array::SetLength(int len, bool bak)
|
||||
{
|
||||
if(len <= _Capacity)
|
||||
{
|
||||
_Length = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!CheckCapacity(len, bak ? _Length : 0)) return false;
|
||||
// 扩大长度
|
||||
if(len > _Length) _Length = len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*void Array::SetBuffer(void* ptr, int len)
|
||||
{
|
||||
Release();
|
||||
|
||||
Buffer::SetBuffer(ptr, len);
|
||||
}
|
||||
|
||||
void Array::SetBuffer(const void* ptr, int len)
|
||||
{
|
||||
SetBuffer((void*)ptr, len);
|
||||
|
||||
_canWrite = false;
|
||||
}*/
|
||||
|
||||
// 拷贝数据,默认-1长度表示使用右边最大长度,左边不足时自动扩容
|
||||
int Array::Copy(int destIndex, const Buffer& src, int srcIndex, int len)
|
||||
{
|
||||
// 可能需要先扩容,否则Buffer拷贝时,长度可能不准确
|
||||
int remain = src.Length() - srcIndex;
|
||||
if(len < 0)
|
||||
{
|
||||
// -1时选择右边最大长度
|
||||
len = remain;
|
||||
if(len <= 0) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 右边可能不足len
|
||||
if(len > remain) len = remain;
|
||||
}
|
||||
|
||||
// 左边不足时自动扩容
|
||||
if(Length() < len) SetLength(len);
|
||||
|
||||
return Buffer::Copy(destIndex, src, srcIndex, len);
|
||||
}
|
||||
|
||||
// 设置数组元素为指定值,自动扩容
|
||||
bool Array::SetItem(const void* data, int index, int count)
|
||||
{
|
||||
assert(_canWrite, "禁止SetItem修改");
|
||||
assert(data, "Array::SetItem data Error");
|
||||
|
||||
// count<=0 表示设置全部元素
|
||||
if(count <= 0) count = _Length - index;
|
||||
assert(count > 0, "Array::SetItem count Error");
|
||||
|
||||
// 检查长度是否足够
|
||||
int len2 = index + count;
|
||||
CheckCapacity(len2, index);
|
||||
|
||||
byte* buf = (byte*)GetBuffer();
|
||||
// 如果元素类型大小为1,那么可以直接调用内存设置函数
|
||||
if(_Size == 1)
|
||||
memset(&buf[index], *(byte*)data, count);
|
||||
else
|
||||
{
|
||||
while(count-- > 0)
|
||||
{
|
||||
memcpy(buf, data, _Size);
|
||||
buf += _Size;
|
||||
}
|
||||
}
|
||||
|
||||
// 扩大长度
|
||||
if(len2 > _Length) _Length = len2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Array::Set(void* data, int len)
|
||||
{
|
||||
if(!Set((const void*)data, len)) return false;
|
||||
|
||||
_canWrite = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Array::Set(const void* data, int len)
|
||||
{
|
||||
// 销毁旧的
|
||||
if(_needFree && _Arr != data) Release();
|
||||
|
||||
_Arr = (char*)data;
|
||||
_Length = len;
|
||||
_Capacity = len;
|
||||
_needFree = false;
|
||||
_canWrite = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 清空已存储数据。
|
||||
void Array::Clear()
|
||||
{
|
||||
assert(_canWrite, "禁止Clear修改");
|
||||
assert(_Arr, "Clear数据不能为空指针");
|
||||
|
||||
memset(_Arr, 0, _Size * _Length);
|
||||
}
|
||||
|
||||
// 设置指定位置的值,不足时自动扩容
|
||||
void Array::SetItemAt(int i, const void* item)
|
||||
{
|
||||
assert(_canWrite, "禁止SetItemAt修改");
|
||||
|
||||
// 检查长度,不足时扩容
|
||||
CheckCapacity(i + 1, _Length);
|
||||
|
||||
if(i >= _Length) _Length = i + 1;
|
||||
|
||||
memcpy((byte*)_Arr + _Size * i, item, _Size);
|
||||
}
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte Array::operator[](int i) const
|
||||
{
|
||||
assert(_Arr && i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
if(_Size > 1) i *= _Size;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
byte& Array::operator[](int i)
|
||||
{
|
||||
assert(_Arr && i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
if(_Size > 1) i *= _Size;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
// 检查容量。如果不足则扩大,并备份指定长度的数据
|
||||
bool Array::CheckCapacity(int len, int bak)
|
||||
{
|
||||
// 是否超出容量
|
||||
// 如果不是可写,在扩容检查时,也要进行扩容,避免内部不可写数据被修改
|
||||
if(_Arr && len <= _Capacity && _canWrite) return true;
|
||||
|
||||
// 自动计算合适的容量
|
||||
int sz = 0x40;
|
||||
while(sz < len) sz <<= 1;
|
||||
|
||||
bool _free = _needFree;
|
||||
|
||||
void* p = Alloc(sz);
|
||||
if(!p) return false;
|
||||
|
||||
// 是否需要备份数据
|
||||
if(bak > _Length) bak = _Length;
|
||||
if(bak > 0 && _Arr)
|
||||
// 为了安全,按照字节拷贝
|
||||
Buffer(p, sz).Copy(0, _Arr, bak);
|
||||
|
||||
int oldlen = _Length;
|
||||
if(_free && _Arr != p) Release();
|
||||
|
||||
_Arr = (char*)p;
|
||||
_Capacity = sz;
|
||||
_Length = oldlen;
|
||||
|
||||
// _needFree 由Alloc决定
|
||||
// 有可能当前用的内存不是内部内存,然后要分配的内存小于内部内存,则直接使用内部,不需要释放
|
||||
//_needFree = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* Array::Alloc(int len)
|
||||
{
|
||||
_needFree = true;
|
||||
|
||||
return new byte[_Size * len];
|
||||
}
|
||||
|
||||
bool operator==(const Array& bs1, const Array& bs2)
|
||||
{
|
||||
if(bs1.Length() != bs2.Length()) return false;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length() * bs1._Size) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const Array& bs1, const Array& bs2)
|
||||
{
|
||||
if(bs1.Length() != bs2.Length()) return true;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length() * bs1._Size) != 0;
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
#ifndef _Array_H_
|
||||
#define _Array_H_
|
||||
|
||||
// 变长数组。自动扩容
|
||||
class Array : public Buffer
|
||||
{
|
||||
public:
|
||||
// 数组最大容量。初始化时决定,后面不允许改变
|
||||
inline int Capacity() const { return _Capacity; }
|
||||
|
||||
Array(void* data, int len);
|
||||
Array(const void* data, int len);
|
||||
explicit Array(const Buffer& rhs);
|
||||
Array(const Array& rhs) = delete;
|
||||
Array(Array&& rval);
|
||||
|
||||
virtual ~Array();
|
||||
|
||||
Array& operator = (const Buffer& rhs);
|
||||
Array& operator = (const void* p);
|
||||
Array& operator = (Array&& rval);
|
||||
|
||||
using Buffer::Set;
|
||||
using Buffer::SetLength;
|
||||
using Buffer::Copy;
|
||||
|
||||
// 设置数组长度。容量足够则缩小Length,否则扩容以确保数组容量足够大避免多次分配内存
|
||||
virtual bool SetLength(int len);
|
||||
virtual bool SetLength(int len, bool bak);
|
||||
//virtual void SetBuffer(void* ptr, int len);
|
||||
//virtual void SetBuffer(const void* ptr, int len);
|
||||
// 拷贝数据,默认-1长度表示使用右边最大长度,左边不足时自动扩容
|
||||
virtual int Copy(int destIndex, const Buffer& src, int srcIndex, int len);
|
||||
|
||||
// 设置数组元素为指定值,自动扩容
|
||||
bool SetItem(const void* data, int index, int count);
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Set(void* data, int len);
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Set(const void* data, int len);
|
||||
// 清空已存储数据。
|
||||
virtual void Clear();
|
||||
// 设置指定位置的值,不足时自动扩容
|
||||
virtual void SetItemAt(int i, const void* item);
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte operator[](int i) const;
|
||||
byte& operator[](int i);
|
||||
|
||||
friend bool operator==(const Array& bs1, const Array& bs2);
|
||||
friend bool operator!=(const Array& bs1, const Array& bs2);
|
||||
|
||||
protected:
|
||||
uint _Capacity; // 最大个数。非字节数
|
||||
bool _needFree; // 是否需要释放
|
||||
bool _canWrite; // 是否可写
|
||||
ushort _Size; // 单个元素大小。字节
|
||||
|
||||
void Init();
|
||||
void move(Array& rval);
|
||||
|
||||
// 检查容量。如果不足则扩大,并备份指定长度的数据
|
||||
bool CheckCapacity(int len, int bak);
|
||||
virtual void* Alloc(int len);
|
||||
// 释放已占用内存
|
||||
virtual bool Release();
|
||||
};
|
||||
|
||||
// 数组长度
|
||||
#define ArrayLength(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||
// 数组清零,固定长度
|
||||
//#define ArrayZero(arr) memset(arr, 0, sizeof(arr))
|
||||
|
||||
// 使用常量数组来定义一个指针数组
|
||||
//#define CArray(arr) (Array(arr, ArrayLength(arr)))
|
||||
//#define SArray(obj) (Array(&obj, sizeof(obj)))
|
||||
|
||||
// 使用常量数组来定义一个指针数组
|
||||
//#define CBuffer(arr) (Buffer(arr, ArrayLength(arr)))
|
||||
//#define SBuffer(obj) (Buffer(&obj, sizeof(obj)))
|
||||
|
||||
// 数组
|
||||
/*
|
||||
数组是指针和长度的封装。
|
||||
设计本意:
|
||||
1,数据处理函数无需同时传递指针和长度
|
||||
2,数组下标越界检查,避免指针越界
|
||||
3,数组自动扩容,避免因不知道函数内部需要多大缓存空间而带来的设计复杂度
|
||||
|
||||
按照指针来源可分为两大用法:
|
||||
1,内部分配。随时可以扩容,对象拷贝时共用空间
|
||||
2,外部指针。此时认为只是封装,不允许扩容
|
||||
*/
|
||||
template<typename T, int ArraySize = 0x40>
|
||||
class TArray : public Array
|
||||
{
|
||||
protected:
|
||||
T Arr[ArraySize]; // 内部缓冲区
|
||||
|
||||
virtual void* Alloc(int len)
|
||||
{
|
||||
if(len <= ArraySize)
|
||||
{
|
||||
_needFree = false;
|
||||
return Arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_needFree = true;
|
||||
return new T[len];
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// 数组长度
|
||||
virtual int Length() const { return _Length; }
|
||||
// 缓冲区
|
||||
T* GetBuffer() const { return (T*)_Arr; }
|
||||
|
||||
// 初始化指定长度的数组。默认使用内部缓冲区
|
||||
TArray(int length = ArraySize) : Array(Arr, ArrayLength(Arr))
|
||||
{
|
||||
//assert(length <= 0x400, "禁止分配超过1k的数组");
|
||||
if(length < 0) length = ArrayLength(Arr);
|
||||
|
||||
_Length = length;
|
||||
if(length > ArrayLength(Arr))
|
||||
{
|
||||
_Arr = (char*)new T[length];
|
||||
_Capacity = length;
|
||||
_needFree = true;
|
||||
}
|
||||
|
||||
_Size = sizeof(T);
|
||||
}
|
||||
|
||||
// 重载等号运算符,使用另一个固定数组来初始化
|
||||
/*TArray& operator=(const TArray& arr)
|
||||
{
|
||||
Array::operator=(arr);
|
||||
|
||||
return *this;
|
||||
}*/
|
||||
TArray& operator=(const TArray& arr) = delete;
|
||||
|
||||
// 让父类的所有Set函数在这里可见
|
||||
using Array::Set;
|
||||
|
||||
// 设置数组元素为指定值,自动扩容
|
||||
bool Set(const T& item, int index, int count)
|
||||
{
|
||||
return SetItem(&item, index, count);
|
||||
}
|
||||
|
||||
// 设置指定位置的值,不足时自动扩容
|
||||
virtual void SetAt(int i, const T& item)
|
||||
{
|
||||
SetItemAt(i, &item);
|
||||
}
|
||||
|
||||
// 加入一个数据到末尾
|
||||
virtual int Push(const T& item)
|
||||
{
|
||||
SetItemAt(_Length, &item);
|
||||
|
||||
return _Length;
|
||||
}
|
||||
|
||||
// 末尾加入一个空数据,并返回引用,允许外部修改
|
||||
virtual T& Push()
|
||||
{
|
||||
//assert(_canWrite, "禁止修改");
|
||||
|
||||
int i = _Length;
|
||||
// 检查长度,不足时扩容
|
||||
CheckCapacity(i + 1, _Length);
|
||||
|
||||
_Length++;
|
||||
|
||||
T* buf = (T*)_Arr;
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
// 弹出最后一个数组元素,长度减一
|
||||
virtual T& Pop()
|
||||
{
|
||||
//assert(_canWrite, "禁止修改");
|
||||
|
||||
T* buf = (T*)_Arr;
|
||||
return buf[--_Length];
|
||||
}
|
||||
|
||||
// 查找元素
|
||||
virtual int FindIndex(const T item)
|
||||
{
|
||||
T* buf = (T*)_Arr;
|
||||
for(int i=0; i<Length(); i++)
|
||||
{
|
||||
if(buf[i] == item) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 重载索引运算符[],让它可以像数组一样使用下标索引。
|
||||
virtual T& operator[](int i) const
|
||||
{
|
||||
//assert(_Arr && i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
T* buf = (T*)_Arr;
|
||||
return buf[i];
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,363 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "_Core.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
#include "ByteArray.h"
|
||||
#include "SString.h"
|
||||
|
||||
/******************************** Buffer ********************************/
|
||||
|
||||
Buffer::Buffer(void* ptr, int len)
|
||||
{
|
||||
_Arr = (char*)ptr;
|
||||
_Length = len;
|
||||
}
|
||||
|
||||
/*Buffer::Buffer(const Buffer& buf)
|
||||
{
|
||||
Copy(0, rhs, 0, -1);
|
||||
}*/
|
||||
|
||||
Buffer::Buffer(Buffer&& rval)
|
||||
{
|
||||
move(rval);
|
||||
}
|
||||
|
||||
void Buffer::move(Buffer& rval)
|
||||
{
|
||||
_Arr = rval._Arr;
|
||||
_Length = rval._Length;
|
||||
|
||||
rval._Arr = nullptr;
|
||||
rval._Length = 0;
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator = (const Buffer& rhs)
|
||||
{
|
||||
if(!SetLength(rhs.Length())) assert(false, "赋值操作无法扩容");
|
||||
|
||||
//Copy(0, rhs, 0, -1);
|
||||
Copy(rhs, 0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator = (const void* ptr)
|
||||
{
|
||||
if(ptr) Copy(0, ptr, -1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator = (Buffer&& rval)
|
||||
{
|
||||
move(rval);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte Buffer::operator[](int i) const
|
||||
{
|
||||
assert(i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
byte& Buffer::operator[](int i)
|
||||
{
|
||||
assert(i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
// 设置数组长度。容量足够则缩小Length,否则失败。子类可以扩展以实现自动扩容
|
||||
bool Buffer::SetLength(int len)
|
||||
{
|
||||
if(len > _Length) return false;
|
||||
|
||||
_Length = len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*void Buffer::SetBuffer(void* ptr, int len)
|
||||
{
|
||||
_Arr = (char*)ptr;
|
||||
_Length = len;
|
||||
}*/
|
||||
|
||||
// 拷贝数据,默认-1长度表示当前长度
|
||||
int Buffer::Copy(int destIndex, const void* src, int len)
|
||||
{
|
||||
if(!src) return 0;
|
||||
|
||||
int remain = _Length - destIndex;
|
||||
|
||||
// 如果没有指明长度,则拷贝起始位置之后的剩余部分
|
||||
if(len < 0 )
|
||||
{
|
||||
// 不指定长度,又没有剩余量,无法拷贝
|
||||
if(remain <= 0)
|
||||
{
|
||||
debug_printf("Buffer::Copy (0x%08X, %d) <= (%d, 0x%08X, %d) \r\n", _Arr, _Length, destIndex, src, len);
|
||||
assert(false, "Buffer::Copy 未指明要拷贝的长度");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = remain;
|
||||
}
|
||||
else if(len > remain)
|
||||
{
|
||||
// 要拷贝进来的数据超过内存大小,给子类尝试扩容,如果扩容失败,则只拷贝没有超长的那一部分
|
||||
// 子类可能在这里扩容
|
||||
if(!SetLength(destIndex + len))
|
||||
{
|
||||
debug_printf("Buffer::Copy (0x%08X, %d) <= (%d, 0x%08X, %d) \r\n", _Arr, _Length, destIndex, src, len);
|
||||
assert(false, "Buffer::Copy 缓冲区太小");
|
||||
|
||||
len = remain;
|
||||
}
|
||||
}
|
||||
|
||||
// 放到这里判断,前面有可能自动扩容
|
||||
if(!_Arr) return 0;
|
||||
|
||||
// 自我拷贝,跳过
|
||||
if(_Arr == src) return len;
|
||||
|
||||
// 拷贝数据
|
||||
if(len) memmove((byte*)_Arr + destIndex, src, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// 拷贝数据,默认-1长度表示两者最小长度
|
||||
int Buffer::Copy(int destIndex, const Buffer& src, int srcIndex, int len)
|
||||
{
|
||||
if(len < 0 ) len = _Length - destIndex;
|
||||
|
||||
// 允许自身拷贝
|
||||
// 源数据的实际长度可能跟要拷贝的长度不一致
|
||||
int remain = src._Length - srcIndex;
|
||||
if(len > remain) len = remain;
|
||||
//if(len <= 0) return 0;
|
||||
|
||||
return Copy(destIndex, (byte*)src._Arr + srcIndex, len);
|
||||
}
|
||||
|
||||
int Buffer::Copy(const Buffer& src, int destIndex)
|
||||
{
|
||||
return Copy(destIndex, (byte*)src._Arr, src.Length());
|
||||
}
|
||||
|
||||
// 把数据复制到目标缓冲区,默认-1长度表示当前长度
|
||||
int Buffer::CopyTo(int srcIndex, void* data, int len) const
|
||||
{
|
||||
if(!_Arr || !data) return 0;
|
||||
|
||||
int remain = _Length - srcIndex;
|
||||
if(remain <= 0) return 0;
|
||||
|
||||
if(len < 0 || len > remain) len = remain;
|
||||
|
||||
// 拷贝数据
|
||||
if(len)
|
||||
{
|
||||
if(data != (byte*)_Arr + srcIndex)
|
||||
memcpy(data, (byte*)_Arr + srcIndex, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// 用指定字节设置初始化一个区域
|
||||
int Buffer::Set(byte item, int index, int len)
|
||||
{
|
||||
if(!_Arr || len == 0) return 0;
|
||||
|
||||
int remain = _Length - index;
|
||||
if(remain <= 0) return 0;
|
||||
|
||||
if(len < 0 || len > remain) len = remain;
|
||||
|
||||
if(len) memset((byte*)_Arr + index, item, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void Buffer::Clear(byte item)
|
||||
{
|
||||
Set(item, 0, _Length);
|
||||
}
|
||||
|
||||
// 截取一个子缓冲区,默认-1长度表示剩余全部
|
||||
//### 这里逻辑可以考虑修改为,当len大于内部长度时,直接用内部长度而不报错,方便应用层免去比较长度的啰嗦
|
||||
Buffer Buffer::Sub(int index, int len)
|
||||
{
|
||||
assert(index >= 0, "index >= 0");
|
||||
assert(index <= _Length, "index < _Length");
|
||||
if(len < 0) len = _Length - index;
|
||||
assert(index + len <= _Length, "len <= _Length");
|
||||
|
||||
return Buffer((byte*)_Arr + index, len);
|
||||
|
||||
/*// 预留子类自动扩容
|
||||
Buffer bs((byte*)_Arr + index, 0);
|
||||
// 如果不支持自动扩容,这里会失败
|
||||
if(!bs.SetLength(len)) bs._Length = len;
|
||||
return false;*/
|
||||
}
|
||||
|
||||
const Buffer Buffer::Sub(int index, int len) const
|
||||
{
|
||||
assert(index >= 0, "index >= 0");
|
||||
assert(index <= _Length, "index < _Length");
|
||||
if(len < 0) len = _Length - index;
|
||||
assert(index + len <= _Length, "len <= _Length");
|
||||
|
||||
return Buffer((byte*)_Arr + index, len);
|
||||
|
||||
/*// 预留子类自动扩容
|
||||
Buffer bs((byte*)_Arr + index, 0);
|
||||
// 如果不支持自动扩容,这里会失败
|
||||
if(!bs.SetLength(len)) bs._Length = len;
|
||||
return false;*/
|
||||
}
|
||||
|
||||
|
||||
// 显示十六进制数据,指定分隔字符
|
||||
String& Buffer::ToHex(String& str, char sep, int newLine) const
|
||||
{
|
||||
auto buf = GetBuffer();
|
||||
|
||||
// 拼接在字符串后面
|
||||
for(int i=0; i < Length(); i++, buf++)
|
||||
{
|
||||
if(i)
|
||||
{
|
||||
if(newLine > 0 && i % newLine == 0)
|
||||
str += "\r\n";
|
||||
else if(sep != '\0')
|
||||
str += sep;
|
||||
}
|
||||
|
||||
str.Concat(*buf, -16);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// 显示十六进制数据,指定分隔字符
|
||||
String Buffer::ToHex(char sep, int newLine) const
|
||||
{
|
||||
String str;
|
||||
|
||||
// 优化为使用RVO
|
||||
ToHex(str, sep, newLine);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
ushort Buffer::ToUInt16() const
|
||||
{
|
||||
auto p = GetBuffer();
|
||||
// 字节对齐时才能之前转为目标整数
|
||||
if(((int)p & 0x01) == 0) return *(ushort*)p;
|
||||
|
||||
return p[0] | (p[1] << 8);
|
||||
}
|
||||
|
||||
uint Buffer::ToUInt32() const
|
||||
{
|
||||
auto p = GetBuffer();
|
||||
// 字节对齐时才能之前转为目标整数
|
||||
if(((int)p & 0x03) == 0) return *(uint*)p;
|
||||
|
||||
return p[0] | (p[1] << 8) | (p[2] << 0x10) | (p[3] << 0x18);
|
||||
}
|
||||
|
||||
UInt64 Buffer::ToUInt64() const
|
||||
{
|
||||
auto p = GetBuffer();
|
||||
// 字节对齐时才能之前转为目标整数
|
||||
if(((int)p & 0x07) == 0) return *(UInt64*)p;
|
||||
|
||||
uint n1 = p[0] | (p[1] << 8) | (p[2] << 0x10) | (p[3] << 0x18);
|
||||
p += 4;
|
||||
uint n2 = p[0] | (p[1] << 8) | (p[2] << 0x10) | (p[3] << 0x18);
|
||||
|
||||
return n1 | ((UInt64)n2 << 0x20);
|
||||
}
|
||||
|
||||
void Buffer::Write(ushort value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(ushort));
|
||||
}
|
||||
|
||||
void Buffer::Write(short value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(short));
|
||||
}
|
||||
|
||||
void Buffer::Write(uint value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(uint));
|
||||
}
|
||||
|
||||
void Buffer::Write(int value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(int));
|
||||
}
|
||||
|
||||
void Buffer::Write(UInt64 value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(UInt64));
|
||||
}
|
||||
|
||||
String& Buffer::ToStr(String& str) const
|
||||
{
|
||||
return ToHex(str, '-', 0x20);
|
||||
}
|
||||
|
||||
bool operator == (const Buffer& bs1, const Buffer& bs2)
|
||||
{
|
||||
if(bs1._Arr == bs2._Arr) return true;
|
||||
if(!bs1._Arr || !bs2._Arr) return false;
|
||||
if(bs1.Length() != bs2.Length()) return false;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length()) == 0;
|
||||
}
|
||||
|
||||
bool operator == (const Buffer& bs1, const void* ptr)
|
||||
{
|
||||
if(bs1._Arr == ptr) return true;
|
||||
if(!bs1._Arr || !ptr) return false;
|
||||
|
||||
return memcmp(bs1._Arr, ptr, bs1.Length()) == 0;
|
||||
}
|
||||
|
||||
bool operator != (const Buffer& bs1, const Buffer& bs2)
|
||||
{
|
||||
if(bs1._Arr == bs2._Arr) return false;
|
||||
if(!bs1._Arr || !bs2._Arr) return true;
|
||||
if(bs1.Length() != bs2.Length()) return true;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length()) != 0;
|
||||
}
|
||||
|
||||
bool operator != (const Buffer& bs1, const void* ptr)
|
||||
{
|
||||
if(bs1._Arr == ptr) return false;
|
||||
if(!bs1._Arr || !ptr) return true;
|
||||
|
||||
return memcmp(bs1._Arr, ptr, bs1.Length()) != 0;
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
#ifndef _Buffer_H_
|
||||
#define _Buffer_H_
|
||||
|
||||
/*
|
||||
数据区设计原则:
|
||||
1,固定数据区封装 Buffer => Object
|
||||
2,变长数据区封装 Array => Buffer
|
||||
3,自带初始缓冲区封装 ByteArray/String/TArray<T> => Array
|
||||
|
||||
赋值运算符原则:
|
||||
1,赋值运算拷贝长度和数据,核心语义为拷贝一份数据区
|
||||
2,左值长度大于等于右值时,左值长度变小
|
||||
3,左值长度小于右值时,左值尝试SetLength扩容
|
||||
4,如果扩容失败,调试版断言失败,发行版左值长度保持不变
|
||||
*/
|
||||
|
||||
// 内存数据区。包装指针和长度
|
||||
// 参考C#的Byte[],主要实现对象与指针的相互转化、赋值、拷贝、设置、截取、比较等操作。
|
||||
// 内部指针指向的内存和长度,都由外部传入,内部不会自动分配。
|
||||
// 所有的进出拷贝都是针对内部指针和最大长度,不会自动扩容,除非子类继承扩展SetLength。
|
||||
// 拷贝的原则是尽力而为,有多少可用空间就拷贝多少长度。
|
||||
class Buffer : public Object
|
||||
{
|
||||
public:
|
||||
// 打包一个指针和长度指定的数据区
|
||||
Buffer(void* ptr, int len);
|
||||
// 不能用简写的模板,否则String可能命中自己的构造函数
|
||||
/*template<typename T, int N>
|
||||
Buffer(T (&arr)[N])
|
||||
{
|
||||
_Arr = (char*)arr;
|
||||
_Length = sizeof(arr);
|
||||
}
|
||||
template<typename T>
|
||||
Buffer(T (&obj))
|
||||
{
|
||||
_Arr = (char*)&obj;
|
||||
_Length = sizeof(obj);
|
||||
}*/
|
||||
// 拷贝构造函数。直接把指针和长度拿过来用
|
||||
Buffer(const Buffer& buf) = delete;
|
||||
// 对象mov操作,指针和长度归我,清空对方
|
||||
Buffer(Buffer&& rval);
|
||||
|
||||
// 从另一个对象拷贝数据和长度,长度不足且扩容失败时报错
|
||||
Buffer& operator = (const Buffer& rhs);
|
||||
// 从指针拷贝,使用我的长度
|
||||
Buffer& operator = (const void* ptr);
|
||||
// 对象mov操作,指针和长度归我,清空对方
|
||||
Buffer& operator = (Buffer&& rval);
|
||||
|
||||
// 拿出指针供外部使用
|
||||
inline byte* GetBuffer() { return (byte*)_Arr; }
|
||||
inline const byte* GetBuffer() const { return (byte*)_Arr; }
|
||||
inline int Length() const { return _Length; }
|
||||
|
||||
// 设置数组长度。只能缩小不能扩大,子类可以扩展以实现自动扩容
|
||||
virtual bool SetLength(int len);
|
||||
//virtual void SetBuffer(void* ptr, int len);
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte operator[](int i) const;
|
||||
// 支持 buf[i] = 0x36 的语法
|
||||
byte& operator[](int i);
|
||||
|
||||
// 拷贝数据,默认-1长度表示当前长度
|
||||
virtual int Copy(int destIndex, const void* src, int len);
|
||||
// 把数据复制到目标缓冲区,默认-1长度表示当前长度
|
||||
virtual int CopyTo(int srcIndex, void* dest, int len) const;
|
||||
// 拷贝数据,默认-1长度表示两者最小长度
|
||||
virtual int Copy(int destIndex, const Buffer& src, int srcIndex, int len);
|
||||
int Copy(const Buffer& src, int destIndex = 0);
|
||||
|
||||
// 用指定字节设置初始化一个区域
|
||||
int Set(byte item, int index, int len);
|
||||
void Clear(byte item = 0);
|
||||
|
||||
// 截取一个子缓冲区,默认-1长度表示剩余全部
|
||||
//### 这里逻辑可以考虑修改为,当len大于内部长度时,直接用内部长度而不报错,方便应用层免去比较长度的啰嗦
|
||||
Buffer Sub(int index, int len);
|
||||
const Buffer Sub(int index, int len) const;
|
||||
|
||||
// 显示十六进制数据,指定分隔字符和换行长度
|
||||
String& ToHex(String& str, char sep = 0, int newLine = 0) const;
|
||||
// 显示十六进制数据,指定分隔字符和换行长度
|
||||
String ToHex(char sep = 0, int newLine = 0) const;
|
||||
|
||||
ushort ToUInt16() const;
|
||||
uint ToUInt32() const;
|
||||
UInt64 ToUInt64() const;
|
||||
void Write(ushort value, int index = 0);
|
||||
void Write(short value, int index = 0);
|
||||
void Write(uint value, int index = 0);
|
||||
void Write(int value, int index = 0);
|
||||
void Write(UInt64 value, int index = 0);
|
||||
|
||||
// 输出对象的字符串表示方式
|
||||
virtual String& ToStr(String& str) const;
|
||||
|
||||
explicit operator bool() const { return _Length > 0; }
|
||||
bool operator !() const { return _Length == 0; }
|
||||
friend bool operator == (const Buffer& bs1, const Buffer& bs2);
|
||||
friend bool operator == (const Buffer& bs1, const void* ptr);
|
||||
friend bool operator != (const Buffer& bs1, const Buffer& bs2);
|
||||
friend bool operator != (const Buffer& bs1, const void* ptr);
|
||||
|
||||
protected:
|
||||
char* _Arr; // 数据指针
|
||||
int _Length; // 长度
|
||||
|
||||
void move(Buffer& rval);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,156 @@
|
|||
#include "_Core.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
#include "ByteArray.h"
|
||||
|
||||
/******************************** ByteArray ********************************/
|
||||
|
||||
ByteArray::ByteArray(int length) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
//_Length = length;
|
||||
SetLength(length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(byte item, int length) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
//_Length = length;
|
||||
SetLength(length);
|
||||
Set(item, 0, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const void* data, int length, bool copy) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
if(copy)
|
||||
{
|
||||
_Length = length;
|
||||
Copy(0, data, length);
|
||||
}
|
||||
else
|
||||
Set(data, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(void* data, int length, bool copy) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
if(copy)
|
||||
{
|
||||
_Length = length;
|
||||
Copy(0, data, length);
|
||||
}
|
||||
else
|
||||
Set(data, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const Buffer& arr) : Array(Arr, arr.Length())
|
||||
{
|
||||
Copy(0, arr, 0, -1);
|
||||
}
|
||||
|
||||
/*ByteArray::ByteArray(const ByteArray& arr) : Array(Arr, arr.Length())
|
||||
{
|
||||
Copy(0, arr, 0, -1);
|
||||
}*/
|
||||
|
||||
ByteArray::ByteArray(ByteArray&& rval) : Array((const void*)nullptr, 0)
|
||||
{
|
||||
move(rval);
|
||||
}
|
||||
|
||||
/*// 字符串转为字节数组
|
||||
ByteArray::ByteArray(String& str) : Array(Arr, str.Length())
|
||||
{
|
||||
char* p = str.GetBuffer();
|
||||
Set((byte*)p, str.Length());
|
||||
}
|
||||
|
||||
// 不允许修改,拷贝
|
||||
ByteArray::ByteArray(const String& str) : Array(Arr, str.Length())
|
||||
{
|
||||
const char* p = str.GetBuffer();
|
||||
//Copy((const byte*)p, str.Length());
|
||||
Set((const byte*)p, str.Length());
|
||||
}*/
|
||||
|
||||
void ByteArray::move(ByteArray& rval)
|
||||
{
|
||||
/*
|
||||
move逻辑:
|
||||
1,如果右值是内部指针,则必须拷贝数据,因为右值销毁的时候,内部数据跟着释放
|
||||
2,如果右值是外部指针,并且需要释放,则直接拿指针过来使用,由当前对象负责释放
|
||||
3,如果右值是外部指针,而不需要释放,则拷贝数据,因为那指针可能是借用外部的栈内存
|
||||
*/
|
||||
|
||||
if(rval._Arr != (char*)rval.Arr && rval._needFree)
|
||||
{
|
||||
Array::move(rval);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetLength(rval.Length());
|
||||
Copy(0, rval._Arr, rval._Length);
|
||||
}
|
||||
|
||||
void* ByteArray::Alloc(int len)
|
||||
{
|
||||
if(len <= sizeof(Arr))
|
||||
{
|
||||
_needFree = false;
|
||||
return Arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_needFree = true;
|
||||
return new byte[len];
|
||||
}
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (const Buffer& rhs)
|
||||
{
|
||||
Buffer::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (const ByteArray& rhs)
|
||||
{
|
||||
Buffer::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (const void* p)
|
||||
{
|
||||
Buffer::operator=(p);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (ByteArray&& rval)
|
||||
{
|
||||
move(rval);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 保存到普通字节数组,首字节为长度
|
||||
int ByteArray::Load(const void* data, int maxsize)
|
||||
{
|
||||
const byte* p = (const byte*)data;
|
||||
_Length = p[0] <= maxsize ? p[0] : maxsize;
|
||||
|
||||
return Copy(0, p + 1, _Length);
|
||||
}
|
||||
|
||||
// 从普通字节数据组加载,首字节为长度
|
||||
int ByteArray::Save(void* data, int maxsize) const
|
||||
{
|
||||
assert(_Length <= 0xFF, "_Length <= 0xFF");
|
||||
|
||||
byte* p = (byte*)data;
|
||||
int len = _Length <= maxsize ? _Length : maxsize;
|
||||
p[0] = len;
|
||||
|
||||
return CopyTo(0, p + 1, len);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _ByteArray_H_
|
||||
#define _ByteArray_H_
|
||||
|
||||
// 字节数组
|
||||
class ByteArray : public Array
|
||||
{
|
||||
public:
|
||||
explicit ByteArray(int length = 0);
|
||||
ByteArray(byte item, int length);
|
||||
// 因为使用外部指针,这里初始化时没必要分配内存造成浪费
|
||||
ByteArray(const void* data, int length, bool copy = false);
|
||||
ByteArray(void* data, int length, bool copy = false);
|
||||
explicit ByteArray(const Buffer& arr);
|
||||
ByteArray(const ByteArray& arr) = delete;
|
||||
ByteArray(ByteArray&& rval);
|
||||
//ByteArray(String& str); // 直接引用数据缓冲区
|
||||
//ByteArray(const String& str); // 不允许修改,拷贝
|
||||
|
||||
ByteArray& operator = (const Buffer& rhs);
|
||||
ByteArray& operator = (const ByteArray& rhs);
|
||||
ByteArray& operator = (const void* p);
|
||||
ByteArray& operator = (ByteArray&& rval);
|
||||
|
||||
// 重载等号运算符,使用外部指针、内部长度,用户自己注意安全
|
||||
//ByteArray& operator=(const void* data);
|
||||
|
||||
// 保存到普通字节数组,首字节为长度
|
||||
int Load(const void* data, int maxsize = -1);
|
||||
// 从普通字节数据组加载,首字节为长度
|
||||
int Save(void* data, int maxsize = -1) const;
|
||||
|
||||
//friend bool operator==(const ByteArray& bs1, const ByteArray& bs2);
|
||||
//friend bool operator!=(const ByteArray& bs1, const ByteArray& bs2);
|
||||
|
||||
protected:
|
||||
byte Arr[0x40]; // 内部缓冲区
|
||||
|
||||
virtual void* Alloc(int len);
|
||||
|
||||
void move(ByteArray& rval);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,252 @@
|
|||
#ifndef _LinkedList_H_
|
||||
#define _LinkedList_H_
|
||||
|
||||
// 双向链表
|
||||
template <class T> class LinkedList;
|
||||
|
||||
// 双向链表节点。实体类继承该类
|
||||
template <class T> class LinkedNode
|
||||
{
|
||||
// 友元类。允许链表类控制本类私有成员
|
||||
friend class LinkedList<T>;
|
||||
|
||||
public:
|
||||
T* Prev; // 上一个节点
|
||||
T* Next; // 下一个节点
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Next = nullptr;
|
||||
Prev = nullptr;
|
||||
}
|
||||
|
||||
// 从链表中删除。需要修改前后节点的指针指向,但当前节点仍然指向之前的前后节点
|
||||
void RemoveFromList()
|
||||
{
|
||||
if(Prev) Prev->Next = Next;
|
||||
if(Next) Next->Prev = Prev;
|
||||
}
|
||||
|
||||
// 完全脱离链表。不再指向其它节点
|
||||
void Unlink()
|
||||
{
|
||||
if(Prev) Prev->Next = Next;
|
||||
if(Next) Next->Prev = Prev;
|
||||
|
||||
Next = nullptr;
|
||||
Prev = nullptr;
|
||||
}
|
||||
|
||||
// 把当前节点附加到另一个节点之后
|
||||
void LinkAfter(T* node)
|
||||
{
|
||||
node->Next = (T*)this;
|
||||
Prev = node;
|
||||
// 不能清空Next,因为可能是两个链表的合并
|
||||
//Next = nullptr;
|
||||
}
|
||||
|
||||
// 最后一个节点
|
||||
T* Last()
|
||||
{
|
||||
T* node = (T*)this;
|
||||
while(node->Next) node = node->Next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// 附加到当前节点后面
|
||||
void Append(T* node)
|
||||
{
|
||||
Next = node;
|
||||
node->Prev = (T*)this;
|
||||
//node->Next = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/*// 双向链表
|
||||
template <class T>
|
||||
class LinkedList
|
||||
{
|
||||
public:
|
||||
// 链表节点。实体类不需要继承该内部类
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
T Item; // 元素
|
||||
Node* Prev; // 前一节点
|
||||
Node* Next; // 下一节点
|
||||
|
||||
Node()
|
||||
{
|
||||
Prev = nullptr;
|
||||
Next = nullptr;
|
||||
}
|
||||
|
||||
// 从队列中脱离
|
||||
void RemoveFromList()
|
||||
{
|
||||
// 双保险,只有在前后节点指向当前节点时,才修改它们的值
|
||||
if(Prev && Prev->Next == this) Prev->Next = Next;
|
||||
if(Next && Next->Prev == this) Next->Prev = Prev;
|
||||
}
|
||||
|
||||
// 附加到当前节点后面
|
||||
void Append(Node* node)
|
||||
{
|
||||
Next = node;
|
||||
node->Prev = this;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Node* _Head; // 链表头部
|
||||
Node* _Tail; // 链表尾部
|
||||
int _Count; // 元素个数
|
||||
|
||||
void Init()
|
||||
{
|
||||
_Head = nullptr;
|
||||
_Tail = nullptr;
|
||||
_Count = 0;
|
||||
}
|
||||
|
||||
void Remove(Node* node)
|
||||
{
|
||||
// 脱离队列
|
||||
node->RemoveFromList();
|
||||
// 特殊处理头尾
|
||||
if(node == _Head) _Head = node->Next;
|
||||
if(node == _Tail) _Tail = node->Prev;
|
||||
|
||||
delete node;
|
||||
_Count--;
|
||||
}
|
||||
|
||||
public:
|
||||
LinkedList()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// 计算链表节点数
|
||||
virtual int Count() const { return _Count; }
|
||||
|
||||
// 将某项添加到集合
|
||||
virtual void Add(const T& item)
|
||||
{
|
||||
Node* node = new Node();
|
||||
node->Item = item;
|
||||
|
||||
if(_Tail)
|
||||
_Tail->Append(node);
|
||||
else
|
||||
_Head = _Tail = node;
|
||||
|
||||
_Count++;
|
||||
}
|
||||
|
||||
// 从集合中移除特定对象的第一个匹配项
|
||||
virtual void Remove(const T& item)
|
||||
{
|
||||
if(!_Count) return;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node; node = node->Next)
|
||||
{
|
||||
if(node->Item == item) break;
|
||||
}
|
||||
|
||||
if(node) Remove(node);
|
||||
}
|
||||
|
||||
// 确定集合是否包含特定值
|
||||
virtual bool Contains(const T& item)
|
||||
{
|
||||
if(!_Count) return false;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node; node = node->Next)
|
||||
{
|
||||
if(node->Item == item) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 从集合中移除所有项。注意,该方法不会释放元素指针
|
||||
virtual void Clear()
|
||||
{
|
||||
if(!_Count) return;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node;)
|
||||
{
|
||||
// 先备份,待会删除可能影响指针
|
||||
Node* next = node->Next;
|
||||
delete node;
|
||||
node = next;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
// 将集合元素复制到数组中
|
||||
virtual void CopyTo(T* arr)
|
||||
{
|
||||
assert_ptr(arr);
|
||||
|
||||
if(!_Count) return;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node; node = node->Next)
|
||||
{
|
||||
*arr++ = node->Item;
|
||||
}
|
||||
}
|
||||
|
||||
T& First() { return _Head->Item; }
|
||||
T& Last() { return _Tail->Item; }
|
||||
|
||||
// 释放第一个有效节点
|
||||
T& ExtractFirst()
|
||||
{
|
||||
if(!_Count) return nullptr;
|
||||
|
||||
Node* node = _Head;
|
||||
_Head = _Head->Next;
|
||||
// 可能只有一个节点
|
||||
if(!_Head)
|
||||
_Tail = nullptr;
|
||||
else
|
||||
_Head->Prev = nullptr;
|
||||
|
||||
T& item = node->Item;
|
||||
delete node;
|
||||
_Count--;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// 释放最后一个有效节点
|
||||
T& ExtractLast()
|
||||
{
|
||||
if(!_Count) return nullptr;
|
||||
|
||||
Node* node = _Tail;
|
||||
_Tail = _Tail->Prev;
|
||||
// 可能只有一个节点
|
||||
if(!_Tail)
|
||||
_Head = nullptr;
|
||||
else
|
||||
_Tail->Next = nullptr;
|
||||
|
||||
T& item = node->Item;
|
||||
delete node;
|
||||
_Count--;
|
||||
|
||||
return item;
|
||||
}
|
||||
};*/
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "List.h"
|
||||
|
||||
List::List(int size)
|
||||
{
|
||||
_Count = 0;
|
||||
}
|
||||
|
||||
//List::List(T* items, uint count) { Set(items, count); }
|
||||
|
||||
int List::Count() const { return _Count; }
|
||||
|
||||
// 添加单个元素
|
||||
void List::Add(void* item)
|
||||
{
|
||||
//Push(item);
|
||||
}
|
||||
|
||||
/*// 添加多个元素
|
||||
void List::Add(T* items, int count)
|
||||
{
|
||||
for(int i=0; i<count; i++) Push(*items++);
|
||||
}*/
|
||||
|
||||
// 删除指定位置元素
|
||||
void List::RemoveAt(int index)
|
||||
{
|
||||
int len = _Count;
|
||||
if(len <= 0 || index >= len) return;
|
||||
|
||||
// 复制元素
|
||||
//if(index < len - 1) memmove(&_Arr[index], &_Arr[index + 1], (len - index - 1) * sizeof(T));
|
||||
if(index < len - 1)
|
||||
{
|
||||
len = (len - index - 1) * sizeof(void*);
|
||||
Buffer(&_Arr[index], len).Copy(0, &_Arr[index + 1], len);
|
||||
}
|
||||
_Count--;
|
||||
}
|
||||
|
||||
// 删除指定元素
|
||||
void List::Remove(const void* item)
|
||||
{
|
||||
//int index = FindIndex(item);
|
||||
//if(index >= 0) RemoveAt(index);
|
||||
}
|
||||
|
||||
// 释放所有指针指向的内存
|
||||
List& List::DeleteAll()
|
||||
{
|
||||
for(int i=0; i < _Count; i++)
|
||||
{
|
||||
if(_Arr[i]) delete _Arr[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void List::Clear()
|
||||
{
|
||||
_Count = 0;
|
||||
}
|
||||
|
||||
/*// 返回内部指针
|
||||
const void** List::ToArray() const
|
||||
{
|
||||
return _Arr;
|
||||
}*/
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef _List_H_
|
||||
#define _List_H_
|
||||
|
||||
// 变长列表
|
||||
class List
|
||||
{
|
||||
public:
|
||||
List(int count = 0);
|
||||
//List(void* items, uint count);
|
||||
|
||||
int Count() const;
|
||||
|
||||
// 添加单个元素
|
||||
void Add(void* item);
|
||||
|
||||
// 添加多个元素
|
||||
void Add(void* items, int count);
|
||||
|
||||
// 删除指定位置元素
|
||||
void RemoveAt(int index);
|
||||
|
||||
// 删除指定元素
|
||||
void Remove(const void* item);
|
||||
|
||||
void Clear();
|
||||
|
||||
// 释放所有指针指向的内存
|
||||
List& DeleteAll();
|
||||
|
||||
// 返回内部指针
|
||||
//const void** ToArray() const;
|
||||
|
||||
private:
|
||||
void** _Arr;
|
||||
int _Count;
|
||||
int _Capacity;
|
||||
|
||||
void* Arr[0x10];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +1,29 @@
|
|||
#include "Queue.h"
|
||||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
#include "ByteArray.h"
|
||||
|
||||
#include "Queue.h"
|
||||
|
||||
extern void EnterCritical();
|
||||
extern void ExitCritical();
|
||||
|
||||
|
||||
// 智能IRQ,初始化时备份,销毁时还原
|
||||
// SmartIRQ相当霸道,它直接关闭所有中断,再也没有别的任务可以跟当前任务争夺MCU
|
||||
class SmartIRQ
|
||||
{
|
||||
public:
|
||||
SmartIRQ()
|
||||
{
|
||||
EnterCritical();
|
||||
}
|
||||
|
||||
~SmartIRQ()
|
||||
{
|
||||
ExitCritical();
|
||||
}
|
||||
};
|
||||
|
||||
Queue::Queue(uint len) : _s(len)
|
||||
{
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef _Queue_H_
|
||||
#define _Queue_H_
|
||||
|
||||
#include "Sys.h"
|
||||
|
||||
// 内存缓冲区
|
||||
// 缓冲区内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
|
||||
class Queue
|
|
@ -1,9 +1,6 @@
|
|||
#ifndef __String_H__
|
||||
#define __String_H__
|
||||
|
||||
#include "Sys.h"
|
||||
#include "Type.h"
|
||||
|
||||
// 字符串助手,主要用于字符串连接
|
||||
//class StringHelper;
|
||||
class StringSplit;
|
|
@ -0,0 +1,50 @@
|
|||
#include "Sys.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "SmartPtr.h"
|
||||
|
||||
// 内部包装。指针的多个智能指针SmartPtr对象共用该内部包装
|
||||
class WrapPtr
|
||||
{
|
||||
public:
|
||||
void* Ptr; // 目标指针
|
||||
uint Count; // 引用计数
|
||||
|
||||
WrapPtr(void* ptr) { Ptr = ptr; Count = 1; }
|
||||
~WrapPtr() { delete Ptr; }
|
||||
};
|
||||
|
||||
// 为某个指针封装
|
||||
SmartPtr::SmartPtr(void* ptr)
|
||||
{
|
||||
assert_ptr(ptr);
|
||||
|
||||
_ptr = new WrapPtr(ptr);
|
||||
}
|
||||
|
||||
// 拷贝智能指针。仅拷贝内部包装,然后引用计数加一
|
||||
SmartPtr::SmartPtr(const SmartPtr& ptr)
|
||||
{
|
||||
assert_ptr(ptr._ptr);
|
||||
|
||||
auto p = (WrapPtr*)ptr._ptr;
|
||||
assert_ptr(p->Ptr);
|
||||
|
||||
_ptr = p;
|
||||
p->Count++;
|
||||
}
|
||||
|
||||
SmartPtr::~SmartPtr()
|
||||
{
|
||||
auto p = (WrapPtr*)_ptr;
|
||||
// 释放智能指针时,指针引用计数减一
|
||||
p->Count--;
|
||||
// 如果指针引用计数为0,则释放指针
|
||||
if(!p->Count)
|
||||
{
|
||||
delete p;
|
||||
_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* SmartPtr::ToPtr() { return ((WrapPtr*)_ptr)->Ptr; }
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _SmartPtr_H_
|
||||
#define _SmartPtr_H_
|
||||
|
||||
// 自动释放的智能指针
|
||||
class SmartPtr
|
||||
{
|
||||
private:
|
||||
void* _ptr;
|
||||
|
||||
public:
|
||||
// 为某个指针封装
|
||||
SmartPtr(void* ptr);
|
||||
// 拷贝智能指针。仅拷贝内部包装,然后引用计数加一
|
||||
SmartPtr(const SmartPtr& ptr);
|
||||
|
||||
~SmartPtr();
|
||||
|
||||
void* ToPtr();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +1,17 @@
|
|||
#include "Stream.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include "_Core.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
#include "ByteArray.h"
|
||||
#include "SString.h"
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
extern ushort _Rev16(ushort);
|
||||
extern uint _Rev32(uint);
|
||||
|
||||
// 使用缓冲区初始化数据流。注意,此时指针位于0,而内容长度为缓冲区长度
|
||||
Stream::Stream(void* buf, uint len)
|
||||
|
@ -318,7 +331,7 @@ ushort Stream::ReadUInt16()
|
|||
ushort v;
|
||||
Buffer bs(&v, sizeof(v));
|
||||
if(!Read(bs)) return 0;
|
||||
if(!Little) v = _REV16(v);
|
||||
if(!Little) v = _Rev16(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -327,7 +340,7 @@ uint Stream::ReadUInt32()
|
|||
uint v;
|
||||
Buffer bs(&v, sizeof(v));
|
||||
if(!Read(bs)) return 0;
|
||||
if(!Little) v = _REV(v);
|
||||
if(!Little) v = _Rev32(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -336,7 +349,7 @@ UInt64 Stream::ReadUInt64()
|
|||
UInt64 v;
|
||||
Buffer bs(&v, sizeof(v));
|
||||
if(!Read(bs)) return 0;
|
||||
if(!Little) v = _REV(v >> 32) | ((UInt64)_REV(v & 0xFFFFFFFF) << 32);
|
||||
if(!Little) v = _Rev32(v >> 32) | ((UInt64)_Rev32(v & 0xFFFFFFFF) << 32);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -347,21 +360,21 @@ bool Stream::Write(byte value)
|
|||
|
||||
bool Stream::Write(ushort value)
|
||||
{
|
||||
if(!Little) value = _REV16(value);
|
||||
if(!Little) value = _Rev16(value);
|
||||
|
||||
return Write(Buffer(&value, sizeof(value)));
|
||||
}
|
||||
|
||||
bool Stream::Write(uint value)
|
||||
{
|
||||
if(!Little) value = _REV(value);
|
||||
if(!Little) value = _Rev32(value);
|
||||
|
||||
return Write(Buffer(&value, sizeof(value)));
|
||||
}
|
||||
|
||||
bool Stream::Write(UInt64 value)
|
||||
{
|
||||
if(!Little) value = _REV(value >> 32) | ((UInt64)_REV(value & 0xFFFFFFFF) << 32);
|
||||
if(!Little) value = _Rev32(value >> 32) | ((UInt64)_Rev32(value & 0xFFFFFFFF) << 32);
|
||||
|
||||
return Write(Buffer(&value, sizeof(value)));
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
#ifndef _Stream_H_
|
||||
#define _Stream_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "Sys.h"
|
||||
|
||||
// 数据流
|
||||
// 数据流内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
|
||||
class Stream
|
|
@ -5,6 +5,13 @@
|
|||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "_Core.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
#include "ByteArray.h"
|
||||
|
||||
#include "SString.h"
|
||||
|
||||
char* utohex(uint value, byte size, char* string, bool upper);
|
|
@ -0,0 +1,73 @@
|
|||
#include "Type.h"
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "Array.h"
|
||||
#include "ByteArray.h"
|
||||
#include "SString.h"
|
||||
|
||||
#include <typeinfo>
|
||||
using namespace ::std;
|
||||
|
||||
/******************************** Object ********************************/
|
||||
|
||||
// 输出对象的字符串表示方式
|
||||
String& Object::ToStr(String& str) const
|
||||
{
|
||||
auto name = typeid(*this).name();
|
||||
while(*name >= '0' && *name <= '9') name++;
|
||||
|
||||
str += name;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// 输出对象的字符串表示方式。支持RVO优化。
|
||||
// 该方法直接返回给另一个String作为初始值,只有一次构造,没有多余构造、拷贝和析构。
|
||||
String Object::ToString() const
|
||||
{
|
||||
String str;
|
||||
ToStr(str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void Object::Show(bool newLine) const
|
||||
{
|
||||
// 为了减少堆分配,采用较大的栈缓冲区
|
||||
char cs[0x200];
|
||||
String str(cs, ArrayLength(cs));
|
||||
ToStr(str);
|
||||
str.Show(newLine);
|
||||
}
|
||||
|
||||
const Type Object::GetType() const
|
||||
{
|
||||
auto p = (int*)this;
|
||||
|
||||
//return Type(&typeid(*this), *(p - 1));
|
||||
|
||||
Type type;
|
||||
|
||||
type._info = &typeid(*this);
|
||||
type.Size = *(p - 1);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/******************************** Type ********************************/
|
||||
|
||||
Type::Type()
|
||||
{
|
||||
//_info = ti;
|
||||
|
||||
//Size = size;
|
||||
}
|
||||
|
||||
const String Type::Name() const
|
||||
{
|
||||
auto ti = (const type_info*)_info;
|
||||
auto name = ti->name();
|
||||
while(*name >= '0' && *name <= '9') name++;
|
||||
|
||||
return String(name);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef __Type_H__
|
||||
#define __Type_H__
|
||||
|
||||
/*#include <stdio.h>
|
||||
#include <stdlib.h>*/
|
||||
|
||||
/* 类型定义 */
|
||||
typedef char sbyte;
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long long UInt64;
|
||||
typedef long long Int64;
|
||||
|
||||
#define UInt64_Max 0xFFFFFFFFFFFFFFFFull
|
||||
|
||||
// 逐步使用char替代byte,在返回类型中使用char*替代void*
|
||||
// 因为格式化输出时,可以用%c输出char,用%s输出char*
|
||||
|
||||
class String;
|
||||
class Type;
|
||||
|
||||
// 根对象
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
// 输出对象的字符串表示方式
|
||||
virtual String& ToStr(String& str) const;
|
||||
// 输出对象的字符串表示方式。支持RVO优化
|
||||
virtual String ToString() const;
|
||||
// 显示对象。默认显示ToString
|
||||
virtual void Show(bool newLine = false) const;
|
||||
|
||||
const Type GetType() const;
|
||||
};
|
||||
|
||||
// 类型
|
||||
class Type
|
||||
{
|
||||
private:
|
||||
const void* _info;
|
||||
|
||||
friend class Object;
|
||||
|
||||
Type();
|
||||
|
||||
public:
|
||||
int Size; // 大小
|
||||
//String Name; // 名称
|
||||
|
||||
const String Name() const; // 名称
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef __Core_H__
|
||||
#define __Core_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#if defined(DEBUG) || defined(MSGDEBUG)
|
||||
|
||||
#define debug_printf printf
|
||||
|
||||
#else
|
||||
|
||||
#define debug_printf(format, ...)
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
|
||||
// 验证确保对象不为空,并且在有效的内存范围内
|
||||
//extern void assert_failed(uint8_t* file, uint32_t line);
|
||||
|
||||
#define assert_ptr(expr) (assert_ptr_(expr) ? (void)0 : assert_failed2("ptr==nullptr", (const char*)__FILE__, __LINE__))
|
||||
bool assert_ptr_(const void* p);
|
||||
|
||||
void assert_failed2(const char* msg, const char* file, unsigned int line);
|
||||
#define assert(expr, msg) ((expr) ? (void)0 : assert_failed2(msg, (const char*)__FILE__, __LINE__))
|
||||
|
||||
#else
|
||||
|
||||
#define assert_ptr(expr) ((void)0)
|
||||
#define assert(expr, msg) ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef _auto_ptr_H_
|
||||
#define _auto_ptr_H_
|
||||
|
||||
// 经典的C++自动指针
|
||||
// 超出对象作用域时自动销毁被管理指针
|
||||
template<class T>
|
||||
class auto_ptr
|
||||
{
|
||||
private:
|
||||
T* _ptr;
|
||||
|
||||
public:
|
||||
// 普通指针构造自动指针,隐式转换
|
||||
// 构造函数的explicit关键词有效阻止从一个“裸”指针隐式转换成auto_ptr类型
|
||||
explicit auto_ptr(T* p = 0) : _ptr(p) { }
|
||||
// 拷贝构造函数,解除原来自动指针的管理权
|
||||
auto_ptr(auto_ptr& ap) : _ptr(ap.release()) { }
|
||||
// 析构时销毁被管理指针
|
||||
~auto_ptr()
|
||||
{
|
||||
// 因为C++保证删除一个空指针是安全的,所以我们没有必要判断空
|
||||
delete _ptr;
|
||||
}
|
||||
|
||||
// 自动指针拷贝,解除原来自动指针的管理权
|
||||
auto_ptr& operator=(T* p)
|
||||
{
|
||||
_ptr = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 自动指针拷贝,解除原来自动指针的管理权
|
||||
auto_ptr& operator=(auto_ptr& ap)
|
||||
{
|
||||
reset(ap.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 获取原始指针
|
||||
T* get() const { return _ptr; }
|
||||
|
||||
// 重载*和->运算符
|
||||
T& operator*() const { assert_param(_ptr); return *_ptr; }
|
||||
T* operator->() const { return _ptr; }
|
||||
|
||||
// 接触指针的管理权
|
||||
T* release()
|
||||
{
|
||||
T* p = _ptr;
|
||||
_ptr = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
// 销毁原指针,管理新指针
|
||||
void reset(T* p = 0)
|
||||
{
|
||||
if(_ptr != p)
|
||||
{
|
||||
//if(_ptr) delete _ptr;
|
||||
// 因为C++保证删除一个空指针是安全的,所以我们没有必要判断空
|
||||
delete _ptr;
|
||||
_ptr = p;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +1,13 @@
|
|||
#include "W5500.h"
|
||||
#include "stddef.h"
|
||||
|
||||
#include "Sys.h"
|
||||
#include "Spi.h"
|
||||
#include "Power.h"
|
||||
#include "Net\ITransport.h"
|
||||
#include "Net\Net.h"
|
||||
#include "Message\DataStore.h"
|
||||
|
||||
#include "W5500.h"
|
||||
#include "Time.h"
|
||||
#include "Task.h"
|
||||
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
#ifndef _W5500_H_
|
||||
#define _W5500_H_
|
||||
|
||||
#include "Sys.h"
|
||||
#include "Stream.h"
|
||||
#include "Spi.h"
|
||||
#include "Power.h"
|
||||
#include "Net\ITransport.h"
|
||||
#include "Net\Net.h"
|
||||
#include "Message\DataStore.h"
|
||||
|
||||
// 硬件Socket基类
|
||||
class HardSocket;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "Stream.h"
|
||||
#include "Sys.h"
|
||||
#include "ITransport.h"
|
||||
|
||||
#include "Net.h"
|
||||
|
||||
#include "Dhcp.h"
|
||||
#include "Ethernet.h"
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef _TinyIP_DHCP_H_
|
||||
#define _TinyIP_DHCP_H_
|
||||
|
||||
#include "Net.h"
|
||||
|
||||
// DHCP协议
|
||||
class Dhcp
|
||||
{
|
||||
|
|
8
Sys.h
8
Sys.h
|
@ -40,8 +40,12 @@ void assert_failed2(const char* msg, const char* file, unsigned int line);
|
|||
|
||||
#endif
|
||||
|
||||
#include "Type.h"
|
||||
#include "SString.h"
|
||||
#include "Core\Type.h"
|
||||
#include "Core\Buffer.h"
|
||||
#include "Core\Array.h"
|
||||
#include "Core\ByteArray.h"
|
||||
#include "Core\SString.h"
|
||||
#include "Core\Stream.h"
|
||||
|
||||
/* 引脚定义 */
|
||||
#include "Platform\Pin.h"
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
#include "Drivers\W5500.h"
|
||||
#include "Sys.h"
|
||||
#include "Spi.h"
|
||||
#include "Power.h"
|
||||
#include "Net\ITransport.h"
|
||||
#include "Net\Net.h"
|
||||
#include "Message\DataStore.h"
|
||||
#include "Drivers\W5500.h"
|
||||
|
||||
void TestTask(void* param)
|
||||
{
|
||||
|
|
1
Thread.h
1
Thread.h
|
@ -2,6 +2,7 @@
|
|||
#define __Thread_H__
|
||||
|
||||
#include "Sys.h"
|
||||
#include "Core\LinkedList.h"
|
||||
|
||||
class Thread;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __DataMessage_H__
|
||||
#define __DataMessage_H__
|
||||
|
||||
#include "Stream.h"
|
||||
#include "Sys.h"
|
||||
#include "Message\DataStore.h"
|
||||
#include "Message\Message.h"
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ bool TokenController::Valid(const Message& msg)
|
|||
if (Token != 0) return true;
|
||||
|
||||
// 合法来源验证,暂时验证云平台,其它连接将来验证
|
||||
auto svr = (IPEndPoint*)Server;
|
||||
//auto svr = (IPEndPoint*)Server;
|
||||
auto rmt = (IPEndPoint*)msg.State;
|
||||
|
||||
if (!rmt)
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace NewLife.Reflection
|
|||
build.Output = "F1";
|
||||
build.AddIncludes("..\\..\\Lib\\CMSIS");
|
||||
build.AddIncludes("..\\..\\Lib\\Inc");
|
||||
build.AddIncludes("..\\Core");
|
||||
build.AddFiles("..\\Core");
|
||||
build.AddFiles("..\\", "*.c;*.cpp", false, "CAN;DMA;Memory");
|
||||
build.AddFiles("..\\Platform", "Boot_F1.cpp");
|
||||
build.AddFiles("..\\Platform", "startup_stm32f10x.s");
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace NewLife.Reflection
|
|||
build.Cortex = 3;
|
||||
build.Output = "F1";
|
||||
build.AddIncludes("..\\..\\Lib");
|
||||
build.AddIncludes("..\\Core");
|
||||
build.AddFiles("..\\Core");
|
||||
build.AddFiles("..\\", "*.c;*.cpp", false, "CAN;DMA;Memory;Thread");
|
||||
build.AddFiles("..\\Platform", "Boot_F1.cpp");
|
||||
//build.AddFiles("..\\Platform", "startup_stm32f10x.s");
|
||||
|
|
909
Type.cpp
909
Type.cpp
|
@ -1,909 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Sys.h"
|
||||
//#include "Type.h"
|
||||
//#include "String.h"
|
||||
|
||||
/******************************** Object ********************************/
|
||||
|
||||
// 输出对象的字符串表示方式
|
||||
String& Object::ToStr(String& str) const
|
||||
{
|
||||
auto name = typeid(*this).name();
|
||||
while(*name >= '0' && *name <= '9') name++;
|
||||
|
||||
str += name;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// 输出对象的字符串表示方式。支持RVO优化。
|
||||
// 该方法直接返回给另一个String作为初始值,只有一次构造,没有多余构造、拷贝和析构。
|
||||
String Object::ToString() const
|
||||
{
|
||||
String str;
|
||||
ToStr(str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void Object::Show(bool newLine) const
|
||||
{
|
||||
// 为了减少堆分配,采用较大的栈缓冲区
|
||||
char cs[0x200];
|
||||
String str(cs, ArrayLength(cs));
|
||||
ToStr(str);
|
||||
str.Show(newLine);
|
||||
}
|
||||
|
||||
const Type Object::GetType() const
|
||||
{
|
||||
auto p = (int*)this;
|
||||
|
||||
return Type(&typeid(*this), *(p - 1));
|
||||
}
|
||||
|
||||
/******************************** Type ********************************/
|
||||
|
||||
Type::Type(const type_info* ti, int size)
|
||||
{
|
||||
_info = ti;
|
||||
|
||||
Size = size;
|
||||
}
|
||||
|
||||
const String Type::Name() const
|
||||
{
|
||||
auto name = _info->name();
|
||||
while(*name >= '0' && *name <= '9') name++;
|
||||
|
||||
return String(name);
|
||||
}
|
||||
|
||||
/******************************** Buffer ********************************/
|
||||
|
||||
Buffer::Buffer(void* ptr, int len)
|
||||
{
|
||||
_Arr = (char*)ptr;
|
||||
_Length = len;
|
||||
}
|
||||
|
||||
/*Buffer::Buffer(const Buffer& buf)
|
||||
{
|
||||
Copy(0, rhs, 0, -1);
|
||||
}*/
|
||||
|
||||
Buffer::Buffer(Buffer&& rval)
|
||||
{
|
||||
move(rval);
|
||||
}
|
||||
|
||||
void Buffer::move(Buffer& rval)
|
||||
{
|
||||
_Arr = rval._Arr;
|
||||
_Length = rval._Length;
|
||||
|
||||
rval._Arr = nullptr;
|
||||
rval._Length = 0;
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator = (const Buffer& rhs)
|
||||
{
|
||||
if(!SetLength(rhs.Length())) assert(false, "赋值操作无法扩容");
|
||||
|
||||
//Copy(0, rhs, 0, -1);
|
||||
Copy(rhs, 0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator = (const void* ptr)
|
||||
{
|
||||
if(ptr) Copy(0, ptr, -1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator = (Buffer&& rval)
|
||||
{
|
||||
move(rval);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte Buffer::operator[](int i) const
|
||||
{
|
||||
assert(i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
byte& Buffer::operator[](int i)
|
||||
{
|
||||
assert(i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
// 设置数组长度。容量足够则缩小Length,否则失败。子类可以扩展以实现自动扩容
|
||||
bool Buffer::SetLength(int len)
|
||||
{
|
||||
if(len > _Length) return false;
|
||||
|
||||
_Length = len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*void Buffer::SetBuffer(void* ptr, int len)
|
||||
{
|
||||
_Arr = (char*)ptr;
|
||||
_Length = len;
|
||||
}*/
|
||||
|
||||
// 拷贝数据,默认-1长度表示当前长度
|
||||
int Buffer::Copy(int destIndex, const void* src, int len)
|
||||
{
|
||||
if(!src) return 0;
|
||||
|
||||
int remain = _Length - destIndex;
|
||||
|
||||
// 如果没有指明长度,则拷贝起始位置之后的剩余部分
|
||||
if(len < 0 )
|
||||
{
|
||||
// 不指定长度,又没有剩余量,无法拷贝
|
||||
if(remain <= 0)
|
||||
{
|
||||
debug_printf("Buffer::Copy (0x%08X, %d) <= (%d, 0x%08X, %d) \r\n", _Arr, _Length, destIndex, src, len);
|
||||
assert(false, "Buffer::Copy 未指明要拷贝的长度");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = remain;
|
||||
}
|
||||
else if(len > remain)
|
||||
{
|
||||
// 要拷贝进来的数据超过内存大小,给子类尝试扩容,如果扩容失败,则只拷贝没有超长的那一部分
|
||||
// 子类可能在这里扩容
|
||||
if(!SetLength(destIndex + len))
|
||||
{
|
||||
debug_printf("Buffer::Copy (0x%08X, %d) <= (%d, 0x%08X, %d) \r\n", _Arr, _Length, destIndex, src, len);
|
||||
assert(false, "Buffer::Copy 缓冲区太小");
|
||||
|
||||
len = remain;
|
||||
}
|
||||
}
|
||||
|
||||
// 放到这里判断,前面有可能自动扩容
|
||||
if(!_Arr) return 0;
|
||||
|
||||
// 自我拷贝,跳过
|
||||
if(_Arr == src) return len;
|
||||
|
||||
// 拷贝数据
|
||||
if(len) memmove((byte*)_Arr + destIndex, src, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// 拷贝数据,默认-1长度表示两者最小长度
|
||||
int Buffer::Copy(int destIndex, const Buffer& src, int srcIndex, int len)
|
||||
{
|
||||
if(len < 0 ) len = _Length - destIndex;
|
||||
|
||||
// 允许自身拷贝
|
||||
// 源数据的实际长度可能跟要拷贝的长度不一致
|
||||
int remain = src._Length - srcIndex;
|
||||
if(len > remain) len = remain;
|
||||
//if(len <= 0) return 0;
|
||||
|
||||
return Copy(destIndex, (byte*)src._Arr + srcIndex, len);
|
||||
}
|
||||
|
||||
int Buffer::Copy(const Buffer& src, int destIndex)
|
||||
{
|
||||
return Copy(destIndex, (byte*)src._Arr, src.Length());
|
||||
}
|
||||
|
||||
// 把数据复制到目标缓冲区,默认-1长度表示当前长度
|
||||
int Buffer::CopyTo(int srcIndex, void* data, int len) const
|
||||
{
|
||||
if(!_Arr || !data) return 0;
|
||||
|
||||
int remain = _Length - srcIndex;
|
||||
if(remain <= 0) return 0;
|
||||
|
||||
if(len < 0 || len > remain) len = remain;
|
||||
|
||||
// 拷贝数据
|
||||
if(len)
|
||||
{
|
||||
if(data != (byte*)_Arr + srcIndex)
|
||||
memcpy(data, (byte*)_Arr + srcIndex, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// 用指定字节设置初始化一个区域
|
||||
int Buffer::Set(byte item, int index, int len)
|
||||
{
|
||||
if(!_Arr || len == 0) return 0;
|
||||
|
||||
int remain = _Length - index;
|
||||
if(remain <= 0) return 0;
|
||||
|
||||
if(len < 0 || len > remain) len = remain;
|
||||
|
||||
if(len) memset((byte*)_Arr + index, item, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void Buffer::Clear(byte item)
|
||||
{
|
||||
Set(item, 0, _Length);
|
||||
}
|
||||
|
||||
// 截取一个子缓冲区,默认-1长度表示剩余全部
|
||||
//### 这里逻辑可以考虑修改为,当len大于内部长度时,直接用内部长度而不报错,方便应用层免去比较长度的啰嗦
|
||||
Buffer Buffer::Sub(int index, int len)
|
||||
{
|
||||
assert(index >= 0, "index >= 0");
|
||||
assert(index <= _Length, "index < _Length");
|
||||
if(len < 0) len = _Length - index;
|
||||
assert(index + len <= _Length, "len <= _Length");
|
||||
|
||||
return Buffer((byte*)_Arr + index, len);
|
||||
|
||||
/*// 预留子类自动扩容
|
||||
Buffer bs((byte*)_Arr + index, 0);
|
||||
// 如果不支持自动扩容,这里会失败
|
||||
if(!bs.SetLength(len)) bs._Length = len;
|
||||
return false;*/
|
||||
}
|
||||
|
||||
const Buffer Buffer::Sub(int index, int len) const
|
||||
{
|
||||
assert(index >= 0, "index >= 0");
|
||||
assert(index <= _Length, "index < _Length");
|
||||
if(len < 0) len = _Length - index;
|
||||
assert(index + len <= _Length, "len <= _Length");
|
||||
|
||||
return Buffer((byte*)_Arr + index, len);
|
||||
|
||||
/*// 预留子类自动扩容
|
||||
Buffer bs((byte*)_Arr + index, 0);
|
||||
// 如果不支持自动扩容,这里会失败
|
||||
if(!bs.SetLength(len)) bs._Length = len;
|
||||
return false;*/
|
||||
}
|
||||
|
||||
|
||||
// 显示十六进制数据,指定分隔字符
|
||||
String& Buffer::ToHex(String& str, char sep, int newLine) const
|
||||
{
|
||||
auto buf = GetBuffer();
|
||||
|
||||
// 拼接在字符串后面
|
||||
for(int i=0; i < Length(); i++, buf++)
|
||||
{
|
||||
if(i)
|
||||
{
|
||||
if(newLine > 0 && i % newLine == 0)
|
||||
str += "\r\n";
|
||||
else if(sep != '\0')
|
||||
str += sep;
|
||||
}
|
||||
|
||||
str.Concat(*buf, -16);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// 显示十六进制数据,指定分隔字符
|
||||
String Buffer::ToHex(char sep, int newLine) const
|
||||
{
|
||||
String str;
|
||||
|
||||
// 优化为使用RVO
|
||||
ToHex(str, sep, newLine);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
ushort Buffer::ToUInt16() const
|
||||
{
|
||||
auto p = GetBuffer();
|
||||
// 字节对齐时才能之前转为目标整数
|
||||
if(((int)p & 0x01) == 0) return *(ushort*)p;
|
||||
|
||||
return p[0] | (p[1] << 8);
|
||||
}
|
||||
|
||||
uint Buffer::ToUInt32() const
|
||||
{
|
||||
auto p = GetBuffer();
|
||||
// 字节对齐时才能之前转为目标整数
|
||||
if(((int)p & 0x03) == 0) return *(uint*)p;
|
||||
|
||||
return p[0] | (p[1] << 8) | (p[2] << 0x10) | (p[3] << 0x18);
|
||||
}
|
||||
|
||||
UInt64 Buffer::ToUInt64() const
|
||||
{
|
||||
auto p = GetBuffer();
|
||||
// 字节对齐时才能之前转为目标整数
|
||||
if(((int)p & 0x07) == 0) return *(UInt64*)p;
|
||||
|
||||
uint n1 = p[0] | (p[1] << 8) | (p[2] << 0x10) | (p[3] << 0x18);
|
||||
p += 4;
|
||||
uint n2 = p[0] | (p[1] << 8) | (p[2] << 0x10) | (p[3] << 0x18);
|
||||
|
||||
return n1 | ((UInt64)n2 << 0x20);
|
||||
}
|
||||
|
||||
void Buffer::Write(ushort value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(ushort));
|
||||
}
|
||||
|
||||
void Buffer::Write(short value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(short));
|
||||
}
|
||||
|
||||
void Buffer::Write(uint value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(uint));
|
||||
}
|
||||
|
||||
void Buffer::Write(int value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(int));
|
||||
}
|
||||
|
||||
void Buffer::Write(UInt64 value, int index)
|
||||
{
|
||||
Copy(index, (byte*)&value, sizeof(UInt64));
|
||||
}
|
||||
|
||||
String& Buffer::ToStr(String& str) const
|
||||
{
|
||||
return ToHex(str, '-', 0x20);
|
||||
}
|
||||
|
||||
bool operator == (const Buffer& bs1, const Buffer& bs2)
|
||||
{
|
||||
if(bs1._Arr == bs2._Arr) return true;
|
||||
if(!bs1._Arr || !bs2._Arr) return false;
|
||||
if(bs1.Length() != bs2.Length()) return false;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length()) == 0;
|
||||
}
|
||||
|
||||
bool operator == (const Buffer& bs1, const void* ptr)
|
||||
{
|
||||
if(bs1._Arr == ptr) return true;
|
||||
if(!bs1._Arr || !ptr) return false;
|
||||
|
||||
return memcmp(bs1._Arr, ptr, bs1.Length()) == 0;
|
||||
}
|
||||
|
||||
bool operator != (const Buffer& bs1, const Buffer& bs2)
|
||||
{
|
||||
if(bs1._Arr == bs2._Arr) return false;
|
||||
if(!bs1._Arr || !bs2._Arr) return true;
|
||||
if(bs1.Length() != bs2.Length()) return true;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length()) != 0;
|
||||
}
|
||||
|
||||
bool operator != (const Buffer& bs1, const void* ptr)
|
||||
{
|
||||
if(bs1._Arr == ptr) return false;
|
||||
if(!bs1._Arr || !ptr) return true;
|
||||
|
||||
return memcmp(bs1._Arr, ptr, bs1.Length()) != 0;
|
||||
}
|
||||
|
||||
/******************************** TArray ********************************/
|
||||
|
||||
// 数组最大容量。初始化时决定,后面不允许改变
|
||||
//int Array::Capacity() const { return _Capacity; }
|
||||
|
||||
/*int MemLen(const void* data)
|
||||
{
|
||||
if(!data) return 0;
|
||||
|
||||
// 自动计算长度,\0结尾,单字节大小时才允许
|
||||
int len = 0;
|
||||
const byte* p =(const byte*)data;
|
||||
while(*p++) len++;
|
||||
return len;
|
||||
}*/
|
||||
|
||||
Array::Array(void* data, int len) : Buffer(data, len)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
Array::Array(const void* data, int len) : Buffer((void*)data, len)
|
||||
{
|
||||
Init();
|
||||
|
||||
_canWrite = false;
|
||||
}
|
||||
|
||||
Array::Array(const Buffer& rhs) : Buffer(nullptr, 0)
|
||||
{
|
||||
Copy(0, rhs, 0, -1);
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
/*Array::Array(const Array& rhs) : Buffer(nullptr, 0)
|
||||
{
|
||||
Copy(0, rhs, 0, -1);
|
||||
|
||||
Init();
|
||||
}*/
|
||||
|
||||
Array::Array(Array&& rval) : Buffer(nullptr, 0)
|
||||
{
|
||||
//*this = rval;
|
||||
move(rval);
|
||||
}
|
||||
|
||||
void Array::move(Array& rval)
|
||||
{
|
||||
Buffer::move(rval);
|
||||
|
||||
_Capacity = rval._Capacity;
|
||||
_needFree = rval._needFree;
|
||||
_canWrite = rval._canWrite;
|
||||
|
||||
rval._Capacity = 0;
|
||||
rval._needFree = false;
|
||||
rval._canWrite = false;
|
||||
}
|
||||
|
||||
void Array::Init()
|
||||
{
|
||||
_Size = 1;
|
||||
|
||||
_Capacity = _Length;
|
||||
_needFree = false;
|
||||
_canWrite = true;
|
||||
}
|
||||
|
||||
// 析构。释放资源
|
||||
Array::~Array()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
// 释放已占用内存
|
||||
bool Array::Release()
|
||||
{
|
||||
auto p = _Arr;
|
||||
bool fr = _needFree;
|
||||
|
||||
_Arr = nullptr;
|
||||
_Capacity = 0;
|
||||
_Length = 0;
|
||||
_needFree = false;
|
||||
_canWrite = true;
|
||||
|
||||
if(fr && p)
|
||||
{
|
||||
delete (byte*)p;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Array& Array::operator = (const Buffer& rhs)
|
||||
{
|
||||
// 可能需要先扩容,否则Buffer拷贝时,长度可能不准确
|
||||
// 长度也要相等,可能会因此而扩容
|
||||
//SetLength(rhs.Length());
|
||||
|
||||
Buffer::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array& Array::operator = (const void* p)
|
||||
{
|
||||
Buffer::operator=(p);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array& Array::operator = (Array&& rval)
|
||||
{
|
||||
//Buffer::operator=(rval);
|
||||
move(rval);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 设置数组长度。容量足够则缩小Length,否则扩容以确保数组容量足够大避免多次分配内存
|
||||
bool Array::SetLength(int len)
|
||||
{
|
||||
return SetLength(len, false);
|
||||
}
|
||||
|
||||
bool Array::SetLength(int len, bool bak)
|
||||
{
|
||||
if(len <= _Capacity)
|
||||
{
|
||||
_Length = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!CheckCapacity(len, bak ? _Length : 0)) return false;
|
||||
// 扩大长度
|
||||
if(len > _Length) _Length = len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*void Array::SetBuffer(void* ptr, int len)
|
||||
{
|
||||
Release();
|
||||
|
||||
Buffer::SetBuffer(ptr, len);
|
||||
}
|
||||
|
||||
void Array::SetBuffer(const void* ptr, int len)
|
||||
{
|
||||
SetBuffer((void*)ptr, len);
|
||||
|
||||
_canWrite = false;
|
||||
}*/
|
||||
|
||||
// 拷贝数据,默认-1长度表示使用右边最大长度,左边不足时自动扩容
|
||||
int Array::Copy(int destIndex, const Buffer& src, int srcIndex, int len)
|
||||
{
|
||||
// 可能需要先扩容,否则Buffer拷贝时,长度可能不准确
|
||||
int remain = src.Length() - srcIndex;
|
||||
if(len < 0)
|
||||
{
|
||||
// -1时选择右边最大长度
|
||||
len = remain;
|
||||
if(len <= 0) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 右边可能不足len
|
||||
if(len > remain) len = remain;
|
||||
}
|
||||
|
||||
// 左边不足时自动扩容
|
||||
if(Length() < len) SetLength(len);
|
||||
|
||||
return Buffer::Copy(destIndex, src, srcIndex, len);
|
||||
}
|
||||
|
||||
// 设置数组元素为指定值,自动扩容
|
||||
bool Array::SetItem(const void* data, int index, int count)
|
||||
{
|
||||
assert(_canWrite, "禁止SetItem修改");
|
||||
assert(data, "Array::SetItem data Error");
|
||||
|
||||
// count<=0 表示设置全部元素
|
||||
if(count <= 0) count = _Length - index;
|
||||
assert(count > 0, "Array::SetItem count Error");
|
||||
|
||||
// 检查长度是否足够
|
||||
int len2 = index + count;
|
||||
CheckCapacity(len2, index);
|
||||
|
||||
byte* buf = (byte*)GetBuffer();
|
||||
// 如果元素类型大小为1,那么可以直接调用内存设置函数
|
||||
if(_Size == 1)
|
||||
memset(&buf[index], *(byte*)data, count);
|
||||
else
|
||||
{
|
||||
while(count-- > 0)
|
||||
{
|
||||
memcpy(buf, data, _Size);
|
||||
buf += _Size;
|
||||
}
|
||||
}
|
||||
|
||||
// 扩大长度
|
||||
if(len2 > _Length) _Length = len2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Array::Set(void* data, int len)
|
||||
{
|
||||
if(!Set((const void*)data, len)) return false;
|
||||
|
||||
_canWrite = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Array::Set(const void* data, int len)
|
||||
{
|
||||
// 销毁旧的
|
||||
if(_needFree && _Arr != data) Release();
|
||||
|
||||
_Arr = (char*)data;
|
||||
_Length = len;
|
||||
_Capacity = len;
|
||||
_needFree = false;
|
||||
_canWrite = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 清空已存储数据。
|
||||
void Array::Clear()
|
||||
{
|
||||
assert(_canWrite, "禁止Clear修改");
|
||||
assert(_Arr, "Clear数据不能为空指针");
|
||||
|
||||
memset(_Arr, 0, _Size * _Length);
|
||||
}
|
||||
|
||||
// 设置指定位置的值,不足时自动扩容
|
||||
void Array::SetItemAt(int i, const void* item)
|
||||
{
|
||||
assert(_canWrite, "禁止SetItemAt修改");
|
||||
|
||||
// 检查长度,不足时扩容
|
||||
CheckCapacity(i + 1, _Length);
|
||||
|
||||
if(i >= _Length) _Length = i + 1;
|
||||
|
||||
memcpy((byte*)_Arr + _Size * i, item, _Size);
|
||||
}
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte Array::operator[](int i) const
|
||||
{
|
||||
assert(_Arr && i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
if(_Size > 1) i *= _Size;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
byte& Array::operator[](int i)
|
||||
{
|
||||
assert(_Arr && i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
byte* buf = (byte*)_Arr;
|
||||
if(_Size > 1) i *= _Size;
|
||||
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
// 检查容量。如果不足则扩大,并备份指定长度的数据
|
||||
bool Array::CheckCapacity(int len, int bak)
|
||||
{
|
||||
// 是否超出容量
|
||||
// 如果不是可写,在扩容检查时,也要进行扩容,避免内部不可写数据被修改
|
||||
if(_Arr && len <= _Capacity && _canWrite) return true;
|
||||
|
||||
// 自动计算合适的容量
|
||||
int sz = 0x40;
|
||||
while(sz < len) sz <<= 1;
|
||||
|
||||
bool _free = _needFree;
|
||||
|
||||
void* p = Alloc(sz);
|
||||
if(!p) return false;
|
||||
|
||||
// 是否需要备份数据
|
||||
if(bak > _Length) bak = _Length;
|
||||
if(bak > 0 && _Arr)
|
||||
// 为了安全,按照字节拷贝
|
||||
Buffer(p, sz).Copy(0, _Arr, bak);
|
||||
|
||||
int oldlen = _Length;
|
||||
if(_free && _Arr != p) Release();
|
||||
|
||||
_Arr = (char*)p;
|
||||
_Capacity = sz;
|
||||
_Length = oldlen;
|
||||
|
||||
// _needFree 由Alloc决定
|
||||
// 有可能当前用的内存不是内部内存,然后要分配的内存小于内部内存,则直接使用内部,不需要释放
|
||||
//_needFree = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* Array::Alloc(int len)
|
||||
{
|
||||
_needFree = true;
|
||||
|
||||
return new byte[_Size * len];
|
||||
}
|
||||
|
||||
bool operator==(const Array& bs1, const Array& bs2)
|
||||
{
|
||||
if(bs1.Length() != bs2.Length()) return false;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length() * bs1._Size) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const Array& bs1, const Array& bs2)
|
||||
{
|
||||
if(bs1.Length() != bs2.Length()) return true;
|
||||
|
||||
return memcmp(bs1._Arr, bs2._Arr, bs1.Length() * bs1._Size) != 0;
|
||||
}
|
||||
|
||||
/******************************** ByteArray ********************************/
|
||||
|
||||
ByteArray::ByteArray(int length) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
//_Length = length;
|
||||
SetLength(length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(byte item, int length) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
//_Length = length;
|
||||
SetLength(length);
|
||||
Set(item, 0, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const void* data, int length, bool copy) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
if(copy)
|
||||
{
|
||||
_Length = length;
|
||||
Copy(0, data, length);
|
||||
}
|
||||
else
|
||||
Set(data, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(void* data, int length, bool copy) : Array(Arr, sizeof(Arr))
|
||||
{
|
||||
if(copy)
|
||||
{
|
||||
_Length = length;
|
||||
Copy(0, data, length);
|
||||
}
|
||||
else
|
||||
Set(data, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const Buffer& arr) : Array(Arr, arr.Length())
|
||||
{
|
||||
Copy(0, arr, 0, -1);
|
||||
}
|
||||
|
||||
/*ByteArray::ByteArray(const ByteArray& arr) : Array(Arr, arr.Length())
|
||||
{
|
||||
Copy(0, arr, 0, -1);
|
||||
}*/
|
||||
|
||||
ByteArray::ByteArray(ByteArray&& rval) : Array((const void*)nullptr, 0)
|
||||
{
|
||||
move(rval);
|
||||
}
|
||||
|
||||
/*// 字符串转为字节数组
|
||||
ByteArray::ByteArray(String& str) : Array(Arr, str.Length())
|
||||
{
|
||||
char* p = str.GetBuffer();
|
||||
Set((byte*)p, str.Length());
|
||||
}
|
||||
|
||||
// 不允许修改,拷贝
|
||||
ByteArray::ByteArray(const String& str) : Array(Arr, str.Length())
|
||||
{
|
||||
const char* p = str.GetBuffer();
|
||||
//Copy((const byte*)p, str.Length());
|
||||
Set((const byte*)p, str.Length());
|
||||
}*/
|
||||
|
||||
void ByteArray::move(ByteArray& rval)
|
||||
{
|
||||
/*
|
||||
move逻辑:
|
||||
1,如果右值是内部指针,则必须拷贝数据,因为右值销毁的时候,内部数据跟着释放
|
||||
2,如果右值是外部指针,并且需要释放,则直接拿指针过来使用,由当前对象负责释放
|
||||
3,如果右值是外部指针,而不需要释放,则拷贝数据,因为那指针可能是借用外部的栈内存
|
||||
*/
|
||||
|
||||
if(rval._Arr != (char*)rval.Arr && rval._needFree)
|
||||
{
|
||||
Array::move(rval);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetLength(rval.Length());
|
||||
Copy(0, rval._Arr, rval._Length);
|
||||
}
|
||||
|
||||
void* ByteArray::Alloc(int len)
|
||||
{
|
||||
if(len <= sizeof(Arr))
|
||||
{
|
||||
_needFree = false;
|
||||
return Arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_needFree = true;
|
||||
return new byte[len];
|
||||
}
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (const Buffer& rhs)
|
||||
{
|
||||
Buffer::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (const ByteArray& rhs)
|
||||
{
|
||||
Buffer::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (const void* p)
|
||||
{
|
||||
Buffer::operator=(p);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteArray& ByteArray::operator = (ByteArray&& rval)
|
||||
{
|
||||
move(rval);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 保存到普通字节数组,首字节为长度
|
||||
int ByteArray::Load(const void* data, int maxsize)
|
||||
{
|
||||
const byte* p = (const byte*)data;
|
||||
_Length = p[0] <= maxsize ? p[0] : maxsize;
|
||||
|
||||
return Copy(0, p + 1, _Length);
|
||||
}
|
||||
|
||||
// 从普通字节数据组加载,首字节为长度
|
||||
int ByteArray::Save(void* data, int maxsize) const
|
||||
{
|
||||
assert(_Length <= 0xFF, "_Length <= 0xFF");
|
||||
|
||||
byte* p = (byte*)data;
|
||||
int len = _Length <= maxsize ? _Length : maxsize;
|
||||
p[0] = len;
|
||||
|
||||
return CopyTo(0, p + 1, len);
|
||||
}
|
843
Type.h
843
Type.h
|
@ -1,843 +0,0 @@
|
|||
#ifndef __Type_H__
|
||||
#define __Type_H__
|
||||
|
||||
/*#include <stdio.h>
|
||||
#include <stdlib.h>*/
|
||||
|
||||
/* 类型定义 */
|
||||
typedef char sbyte;
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long long UInt64;
|
||||
typedef long long Int64;
|
||||
|
||||
#define UInt64_Max 0xFFFFFFFFFFFFFFFFull
|
||||
|
||||
// 逐步使用char替代byte,在返回类型中使用char*替代void*
|
||||
// 因为格式化输出时,可以用%c输出char,用%s输出char*
|
||||
|
||||
#include <typeinfo>
|
||||
using namespace ::std;
|
||||
|
||||
class String;
|
||||
class Type;
|
||||
|
||||
// 根对象
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
// 输出对象的字符串表示方式
|
||||
virtual String& ToStr(String& str) const;
|
||||
// 输出对象的字符串表示方式。支持RVO优化
|
||||
virtual String ToString() const;
|
||||
// 显示对象。默认显示ToString
|
||||
virtual void Show(bool newLine = false) const;
|
||||
|
||||
const Type GetType() const;
|
||||
};
|
||||
|
||||
// 类型
|
||||
class Type
|
||||
{
|
||||
private:
|
||||
const type_info* _info;
|
||||
|
||||
friend class Object;
|
||||
|
||||
Type(const type_info* ti, int size);
|
||||
|
||||
public:
|
||||
int Size; // 大小
|
||||
//String Name; // 名称
|
||||
|
||||
const String Name() const; // 名称
|
||||
};
|
||||
|
||||
/*
|
||||
数据区设计原则:
|
||||
1,固定数据区封装 Buffer => Object
|
||||
2,变长数据区封装 Array => Buffer
|
||||
3,自带初始缓冲区封装 ByteArray/String/TArray<T> => Array
|
||||
|
||||
赋值运算符原则:
|
||||
1,赋值运算拷贝长度和数据,核心语义为拷贝一份数据区
|
||||
2,左值长度大于等于右值时,左值长度变小
|
||||
3,左值长度小于右值时,左值尝试SetLength扩容
|
||||
4,如果扩容失败,调试版断言失败,发行版左值长度保持不变
|
||||
*/
|
||||
|
||||
// 内存数据区。包装指针和长度
|
||||
// 参考C#的Byte[],主要实现对象与指针的相互转化、赋值、拷贝、设置、截取、比较等操作。
|
||||
// 内部指针指向的内存和长度,都由外部传入,内部不会自动分配。
|
||||
// 所有的进出拷贝都是针对内部指针和最大长度,不会自动扩容,除非子类继承扩展SetLength。
|
||||
// 拷贝的原则是尽力而为,有多少可用空间就拷贝多少长度。
|
||||
class Buffer : public Object
|
||||
{
|
||||
public:
|
||||
// 打包一个指针和长度指定的数据区
|
||||
Buffer(void* ptr, int len);
|
||||
// 不能用简写的模板,否则String可能命中自己的构造函数
|
||||
/*template<typename T, int N>
|
||||
Buffer(T (&arr)[N])
|
||||
{
|
||||
_Arr = (char*)arr;
|
||||
_Length = sizeof(arr);
|
||||
}
|
||||
template<typename T>
|
||||
Buffer(T (&obj))
|
||||
{
|
||||
_Arr = (char*)&obj;
|
||||
_Length = sizeof(obj);
|
||||
}*/
|
||||
// 拷贝构造函数。直接把指针和长度拿过来用
|
||||
Buffer(const Buffer& buf) = delete;
|
||||
// 对象mov操作,指针和长度归我,清空对方
|
||||
Buffer(Buffer&& rval);
|
||||
|
||||
// 从另一个对象拷贝数据和长度,长度不足且扩容失败时报错
|
||||
Buffer& operator = (const Buffer& rhs);
|
||||
// 从指针拷贝,使用我的长度
|
||||
Buffer& operator = (const void* ptr);
|
||||
// 对象mov操作,指针和长度归我,清空对方
|
||||
Buffer& operator = (Buffer&& rval);
|
||||
|
||||
// 拿出指针供外部使用
|
||||
inline byte* GetBuffer() { return (byte*)_Arr; }
|
||||
inline const byte* GetBuffer() const { return (byte*)_Arr; }
|
||||
inline int Length() const { return _Length; }
|
||||
|
||||
// 设置数组长度。只能缩小不能扩大,子类可以扩展以实现自动扩容
|
||||
virtual bool SetLength(int len);
|
||||
//virtual void SetBuffer(void* ptr, int len);
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte operator[](int i) const;
|
||||
// 支持 buf[i] = 0x36 的语法
|
||||
byte& operator[](int i);
|
||||
|
||||
// 拷贝数据,默认-1长度表示当前长度
|
||||
virtual int Copy(int destIndex, const void* src, int len);
|
||||
// 把数据复制到目标缓冲区,默认-1长度表示当前长度
|
||||
virtual int CopyTo(int srcIndex, void* dest, int len) const;
|
||||
// 拷贝数据,默认-1长度表示两者最小长度
|
||||
virtual int Copy(int destIndex, const Buffer& src, int srcIndex, int len);
|
||||
int Copy(const Buffer& src, int destIndex = 0);
|
||||
|
||||
// 用指定字节设置初始化一个区域
|
||||
int Set(byte item, int index, int len);
|
||||
void Clear(byte item = 0);
|
||||
|
||||
// 截取一个子缓冲区,默认-1长度表示剩余全部
|
||||
//### 这里逻辑可以考虑修改为,当len大于内部长度时,直接用内部长度而不报错,方便应用层免去比较长度的啰嗦
|
||||
Buffer Sub(int index, int len);
|
||||
const Buffer Sub(int index, int len) const;
|
||||
|
||||
// 显示十六进制数据,指定分隔字符和换行长度
|
||||
String& ToHex(String& str, char sep = 0, int newLine = 0) const;
|
||||
// 显示十六进制数据,指定分隔字符和换行长度
|
||||
String ToHex(char sep = 0, int newLine = 0) const;
|
||||
|
||||
ushort ToUInt16() const;
|
||||
uint ToUInt32() const;
|
||||
UInt64 ToUInt64() const;
|
||||
void Write(ushort value, int index = 0);
|
||||
void Write(short value, int index = 0);
|
||||
void Write(uint value, int index = 0);
|
||||
void Write(int value, int index = 0);
|
||||
void Write(UInt64 value, int index = 0);
|
||||
|
||||
// 输出对象的字符串表示方式
|
||||
virtual String& ToStr(String& str) const;
|
||||
|
||||
explicit operator bool() const { return _Length > 0; }
|
||||
bool operator !() const { return _Length == 0; }
|
||||
friend bool operator == (const Buffer& bs1, const Buffer& bs2);
|
||||
friend bool operator == (const Buffer& bs1, const void* ptr);
|
||||
friend bool operator != (const Buffer& bs1, const Buffer& bs2);
|
||||
friend bool operator != (const Buffer& bs1, const void* ptr);
|
||||
|
||||
protected:
|
||||
char* _Arr; // 数据指针
|
||||
int _Length; // 长度
|
||||
|
||||
void move(Buffer& rval);
|
||||
};
|
||||
|
||||
// 变长数组。自动扩容
|
||||
class Array : public Buffer
|
||||
{
|
||||
public:
|
||||
// 数组最大容量。初始化时决定,后面不允许改变
|
||||
inline int Capacity() const { return _Capacity; }
|
||||
|
||||
Array(void* data, int len);
|
||||
Array(const void* data, int len);
|
||||
explicit Array(const Buffer& rhs);
|
||||
Array(const Array& rhs) = delete;
|
||||
Array(Array&& rval);
|
||||
|
||||
virtual ~Array();
|
||||
|
||||
Array& operator = (const Buffer& rhs);
|
||||
Array& operator = (const void* p);
|
||||
Array& operator = (Array&& rval);
|
||||
|
||||
using Buffer::Set;
|
||||
using Buffer::SetLength;
|
||||
using Buffer::Copy;
|
||||
|
||||
// 设置数组长度。容量足够则缩小Length,否则扩容以确保数组容量足够大避免多次分配内存
|
||||
virtual bool SetLength(int len);
|
||||
virtual bool SetLength(int len, bool bak);
|
||||
//virtual void SetBuffer(void* ptr, int len);
|
||||
//virtual void SetBuffer(const void* ptr, int len);
|
||||
// 拷贝数据,默认-1长度表示使用右边最大长度,左边不足时自动扩容
|
||||
virtual int Copy(int destIndex, const Buffer& src, int srcIndex, int len);
|
||||
|
||||
// 设置数组元素为指定值,自动扩容
|
||||
bool SetItem(const void* data, int index, int count);
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Set(void* data, int len);
|
||||
// 设置数组。直接使用指针,不拷贝数据
|
||||
bool Set(const void* data, int len);
|
||||
// 清空已存储数据。
|
||||
virtual void Clear();
|
||||
// 设置指定位置的值,不足时自动扩容
|
||||
virtual void SetItemAt(int i, const void* item);
|
||||
|
||||
// 重载索引运算符[],返回指定元素的第一个字节
|
||||
byte operator[](int i) const;
|
||||
byte& operator[](int i);
|
||||
|
||||
friend bool operator==(const Array& bs1, const Array& bs2);
|
||||
friend bool operator!=(const Array& bs1, const Array& bs2);
|
||||
|
||||
protected:
|
||||
uint _Capacity; // 最大个数。非字节数
|
||||
bool _needFree; // 是否需要释放
|
||||
bool _canWrite; // 是否可写
|
||||
ushort _Size; // 单个元素大小。字节
|
||||
|
||||
void Init();
|
||||
void move(Array& rval);
|
||||
|
||||
// 检查容量。如果不足则扩大,并备份指定长度的数据
|
||||
bool CheckCapacity(int len, int bak);
|
||||
virtual void* Alloc(int len);
|
||||
// 释放已占用内存
|
||||
virtual bool Release();
|
||||
};
|
||||
|
||||
// 数组长度
|
||||
#define ArrayLength(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||
// 数组清零,固定长度
|
||||
//#define ArrayZero(arr) memset(arr, 0, sizeof(arr))
|
||||
|
||||
// 使用常量数组来定义一个指针数组
|
||||
//#define CArray(arr) (Array(arr, ArrayLength(arr)))
|
||||
//#define SArray(obj) (Array(&obj, sizeof(obj)))
|
||||
|
||||
// 使用常量数组来定义一个指针数组
|
||||
//#define CBuffer(arr) (Buffer(arr, ArrayLength(arr)))
|
||||
//#define SBuffer(obj) (Buffer(&obj, sizeof(obj)))
|
||||
|
||||
// 数组
|
||||
/*
|
||||
数组是指针和长度的封装。
|
||||
设计本意:
|
||||
1,数据处理函数无需同时传递指针和长度
|
||||
2,数组下标越界检查,避免指针越界
|
||||
3,数组自动扩容,避免因不知道函数内部需要多大缓存空间而带来的设计复杂度
|
||||
|
||||
按照指针来源可分为两大用法:
|
||||
1,内部分配。随时可以扩容,对象拷贝时共用空间
|
||||
2,外部指针。此时认为只是封装,不允许扩容
|
||||
*/
|
||||
template<typename T, int ArraySize = 0x40>
|
||||
class TArray : public Array
|
||||
{
|
||||
protected:
|
||||
T Arr[ArraySize]; // 内部缓冲区
|
||||
|
||||
virtual void* Alloc(int len)
|
||||
{
|
||||
if(len <= ArraySize)
|
||||
{
|
||||
_needFree = false;
|
||||
return Arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_needFree = true;
|
||||
return new T[len];
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// 数组长度
|
||||
virtual int Length() const { return _Length; }
|
||||
// 缓冲区
|
||||
T* GetBuffer() const { return (T*)_Arr; }
|
||||
|
||||
// 初始化指定长度的数组。默认使用内部缓冲区
|
||||
TArray(int length = ArraySize) : Array(Arr, ArrayLength(Arr))
|
||||
{
|
||||
assert(length <= 0x400, "禁止分配超过1k的数组");
|
||||
if(length < 0) length = ArrayLength(Arr);
|
||||
|
||||
_Length = length;
|
||||
if(length > ArrayLength(Arr))
|
||||
{
|
||||
_Arr = (char*)new T[length];
|
||||
_Capacity = length;
|
||||
_needFree = true;
|
||||
}
|
||||
|
||||
_Size = sizeof(T);
|
||||
}
|
||||
|
||||
// 重载等号运算符,使用另一个固定数组来初始化
|
||||
/*TArray& operator=(const TArray& arr)
|
||||
{
|
||||
Array::operator=(arr);
|
||||
|
||||
return *this;
|
||||
}*/
|
||||
TArray& operator=(const TArray& arr) = delete;
|
||||
|
||||
// 让父类的所有Set函数在这里可见
|
||||
using Array::Set;
|
||||
|
||||
// 设置数组元素为指定值,自动扩容
|
||||
bool Set(const T& item, int index, int count)
|
||||
{
|
||||
return SetItem(&item, index, count);
|
||||
}
|
||||
|
||||
// 设置指定位置的值,不足时自动扩容
|
||||
virtual void SetAt(int i, const T& item)
|
||||
{
|
||||
SetItemAt(i, &item);
|
||||
}
|
||||
|
||||
// 加入一个数据到末尾
|
||||
virtual int Push(const T& item)
|
||||
{
|
||||
SetItemAt(_Length, &item);
|
||||
|
||||
return _Length;
|
||||
}
|
||||
|
||||
// 末尾加入一个空数据,并返回引用,允许外部修改
|
||||
virtual T& Push()
|
||||
{
|
||||
assert(_canWrite, "禁止修改");
|
||||
|
||||
int i = _Length;
|
||||
// 检查长度,不足时扩容
|
||||
CheckCapacity(i + 1, _Length);
|
||||
|
||||
_Length++;
|
||||
|
||||
T* buf = (T*)_Arr;
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
// 弹出最后一个数组元素,长度减一
|
||||
virtual T& Pop()
|
||||
{
|
||||
assert(_canWrite, "禁止修改");
|
||||
|
||||
T* buf = (T*)_Arr;
|
||||
return buf[--_Length];
|
||||
}
|
||||
|
||||
// 查找元素
|
||||
virtual int FindIndex(const T item)
|
||||
{
|
||||
T* buf = (T*)_Arr;
|
||||
for(int i=0; i<Length(); i++)
|
||||
{
|
||||
if(buf[i] == item) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 重载索引运算符[],让它可以像数组一样使用下标索引。
|
||||
virtual T& operator[](int i) const
|
||||
{
|
||||
assert(_Arr && i >= 0 && i < _Length, "下标越界");
|
||||
|
||||
T* buf = (T*)_Arr;
|
||||
return buf[i];
|
||||
}
|
||||
};
|
||||
|
||||
// 字节数组
|
||||
class ByteArray : public Array
|
||||
{
|
||||
public:
|
||||
explicit ByteArray(int length = 0);
|
||||
ByteArray(byte item, int length);
|
||||
// 因为使用外部指针,这里初始化时没必要分配内存造成浪费
|
||||
ByteArray(const void* data, int length, bool copy = false);
|
||||
ByteArray(void* data, int length, bool copy = false);
|
||||
explicit ByteArray(const Buffer& arr);
|
||||
ByteArray(const ByteArray& arr) = delete;
|
||||
ByteArray(ByteArray&& rval);
|
||||
//ByteArray(String& str); // 直接引用数据缓冲区
|
||||
//ByteArray(const String& str); // 不允许修改,拷贝
|
||||
|
||||
ByteArray& operator = (const Buffer& rhs);
|
||||
ByteArray& operator = (const ByteArray& rhs);
|
||||
ByteArray& operator = (const void* p);
|
||||
ByteArray& operator = (ByteArray&& rval);
|
||||
|
||||
// 重载等号运算符,使用外部指针、内部长度,用户自己注意安全
|
||||
//ByteArray& operator=(const void* data);
|
||||
|
||||
// 保存到普通字节数组,首字节为长度
|
||||
int Load(const void* data, int maxsize = -1);
|
||||
// 从普通字节数据组加载,首字节为长度
|
||||
int Save(void* data, int maxsize = -1) const;
|
||||
|
||||
//friend bool operator==(const ByteArray& bs1, const ByteArray& bs2);
|
||||
//friend bool operator!=(const ByteArray& bs1, const ByteArray& bs2);
|
||||
|
||||
protected:
|
||||
byte Arr[0x40]; // 内部缓冲区
|
||||
|
||||
virtual void* Alloc(int len);
|
||||
|
||||
void move(ByteArray& rval);
|
||||
};
|
||||
|
||||
// 从数组创建列表
|
||||
#define MakeList(T, arr) List<T>(&arr[0], sizeof(arr)/sizeof(arr[0]))
|
||||
|
||||
/*// 变长列表模版
|
||||
// T一般是指针,列表内部有一个数组用于存放指针
|
||||
template<typename T>
|
||||
class List : public TArray<T*>
|
||||
{
|
||||
public:
|
||||
List(int size = 0) : TArray(size) { _Length = 0; }
|
||||
List(T* items, uint count) { Set(items, count); }
|
||||
|
||||
// 添加单个元素
|
||||
virtual void Add(const T& item) { Push(item); }
|
||||
|
||||
// 添加多个元素
|
||||
void Add(T* items, int count)
|
||||
{
|
||||
for(int i=0; i<count; i++) Push(*items++);
|
||||
}
|
||||
|
||||
// 删除指定位置元素
|
||||
void RemoveAt(int index)
|
||||
{
|
||||
int len = Length();
|
||||
if(len <= 0 || index >= len) return;
|
||||
|
||||
// 复制元素
|
||||
if(index < len - 1) memmove(&_Arr[index], &_Arr[index + 1], (len - index - 1) * sizeof(T));
|
||||
_Length--;
|
||||
}
|
||||
|
||||
// 删除指定元素
|
||||
virtual void Remove(const T& item)
|
||||
{
|
||||
int index = FindIndex(item);
|
||||
if(index >= 0) RemoveAt(index);
|
||||
}
|
||||
|
||||
// 释放所有指针指向的内存
|
||||
List& DeleteAll()
|
||||
{
|
||||
for(int i=0; i < Length(); i++)
|
||||
{
|
||||
if(_Arr[i]) delete _Arr[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual void Clear() { _Length = 0; }
|
||||
|
||||
// 返回内部指针
|
||||
const T* ToArray() { return _Arr; }
|
||||
};*/
|
||||
|
||||
// 双向链表
|
||||
template <class T> class LinkedList;
|
||||
|
||||
// 双向链表节点。实体类继承该类
|
||||
template <class T> class LinkedNode
|
||||
{
|
||||
// 友元类。允许链表类控制本类私有成员
|
||||
friend class LinkedList<T>;
|
||||
|
||||
public:
|
||||
T* Prev; // 上一个节点
|
||||
T* Next; // 下一个节点
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Next = nullptr;
|
||||
Prev = nullptr;
|
||||
}
|
||||
|
||||
// 从链表中删除。需要修改前后节点的指针指向,但当前节点仍然指向之前的前后节点
|
||||
void RemoveFromList()
|
||||
{
|
||||
if(Prev) Prev->Next = Next;
|
||||
if(Next) Next->Prev = Prev;
|
||||
}
|
||||
|
||||
// 完全脱离链表。不再指向其它节点
|
||||
void Unlink()
|
||||
{
|
||||
if(Prev) Prev->Next = Next;
|
||||
if(Next) Next->Prev = Prev;
|
||||
|
||||
Next = nullptr;
|
||||
Prev = nullptr;
|
||||
}
|
||||
|
||||
// 把当前节点附加到另一个节点之后
|
||||
void LinkAfter(T* node)
|
||||
{
|
||||
node->Next = (T*)this;
|
||||
Prev = node;
|
||||
// 不能清空Next,因为可能是两个链表的合并
|
||||
//Next = nullptr;
|
||||
}
|
||||
|
||||
// 最后一个节点
|
||||
T* Last()
|
||||
{
|
||||
T* node = (T*)this;
|
||||
while(node->Next) node = node->Next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// 附加到当前节点后面
|
||||
void Append(T* node)
|
||||
{
|
||||
Next = node;
|
||||
node->Prev = (T*)this;
|
||||
//node->Next = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/*// 双向链表
|
||||
template <class T>
|
||||
class LinkedList
|
||||
{
|
||||
public:
|
||||
// 链表节点。实体类不需要继承该内部类
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
T Item; // 元素
|
||||
Node* Prev; // 前一节点
|
||||
Node* Next; // 下一节点
|
||||
|
||||
Node()
|
||||
{
|
||||
Prev = nullptr;
|
||||
Next = nullptr;
|
||||
}
|
||||
|
||||
// 从队列中脱离
|
||||
void RemoveFromList()
|
||||
{
|
||||
// 双保险,只有在前后节点指向当前节点时,才修改它们的值
|
||||
if(Prev && Prev->Next == this) Prev->Next = Next;
|
||||
if(Next && Next->Prev == this) Next->Prev = Prev;
|
||||
}
|
||||
|
||||
// 附加到当前节点后面
|
||||
void Append(Node* node)
|
||||
{
|
||||
Next = node;
|
||||
node->Prev = this;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Node* _Head; // 链表头部
|
||||
Node* _Tail; // 链表尾部
|
||||
int _Count; // 元素个数
|
||||
|
||||
void Init()
|
||||
{
|
||||
_Head = nullptr;
|
||||
_Tail = nullptr;
|
||||
_Count = 0;
|
||||
}
|
||||
|
||||
void Remove(Node* node)
|
||||
{
|
||||
// 脱离队列
|
||||
node->RemoveFromList();
|
||||
// 特殊处理头尾
|
||||
if(node == _Head) _Head = node->Next;
|
||||
if(node == _Tail) _Tail = node->Prev;
|
||||
|
||||
delete node;
|
||||
_Count--;
|
||||
}
|
||||
|
||||
public:
|
||||
LinkedList()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// 计算链表节点数
|
||||
virtual int Count() const { return _Count; }
|
||||
|
||||
// 将某项添加到集合
|
||||
virtual void Add(const T& item)
|
||||
{
|
||||
Node* node = new Node();
|
||||
node->Item = item;
|
||||
|
||||
if(_Tail)
|
||||
_Tail->Append(node);
|
||||
else
|
||||
_Head = _Tail = node;
|
||||
|
||||
_Count++;
|
||||
}
|
||||
|
||||
// 从集合中移除特定对象的第一个匹配项
|
||||
virtual void Remove(const T& item)
|
||||
{
|
||||
if(!_Count) return;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node; node = node->Next)
|
||||
{
|
||||
if(node->Item == item) break;
|
||||
}
|
||||
|
||||
if(node) Remove(node);
|
||||
}
|
||||
|
||||
// 确定集合是否包含特定值
|
||||
virtual bool Contains(const T& item)
|
||||
{
|
||||
if(!_Count) return false;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node; node = node->Next)
|
||||
{
|
||||
if(node->Item == item) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 从集合中移除所有项。注意,该方法不会释放元素指针
|
||||
virtual void Clear()
|
||||
{
|
||||
if(!_Count) return;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node;)
|
||||
{
|
||||
// 先备份,待会删除可能影响指针
|
||||
Node* next = node->Next;
|
||||
delete node;
|
||||
node = next;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
// 将集合元素复制到数组中
|
||||
virtual void CopyTo(T* arr)
|
||||
{
|
||||
assert_ptr(arr);
|
||||
|
||||
if(!_Count) return;
|
||||
|
||||
Node* node;
|
||||
for(node = _Head; node; node = node->Next)
|
||||
{
|
||||
*arr++ = node->Item;
|
||||
}
|
||||
}
|
||||
|
||||
T& First() { return _Head->Item; }
|
||||
T& Last() { return _Tail->Item; }
|
||||
|
||||
// 释放第一个有效节点
|
||||
T& ExtractFirst()
|
||||
{
|
||||
if(!_Count) return nullptr;
|
||||
|
||||
Node* node = _Head;
|
||||
_Head = _Head->Next;
|
||||
// 可能只有一个节点
|
||||
if(!_Head)
|
||||
_Tail = nullptr;
|
||||
else
|
||||
_Head->Prev = nullptr;
|
||||
|
||||
T& item = node->Item;
|
||||
delete node;
|
||||
_Count--;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// 释放最后一个有效节点
|
||||
T& ExtractLast()
|
||||
{
|
||||
if(!_Count) return nullptr;
|
||||
|
||||
Node* node = _Tail;
|
||||
_Tail = _Tail->Prev;
|
||||
// 可能只有一个节点
|
||||
if(!_Tail)
|
||||
_Head = nullptr;
|
||||
else
|
||||
_Tail->Next = nullptr;
|
||||
|
||||
T& item = node->Item;
|
||||
delete node;
|
||||
_Count--;
|
||||
|
||||
return item;
|
||||
}
|
||||
};*/
|
||||
|
||||
/*void* operator new(uint size) throw(std::bad_alloc);
|
||||
void* operator new[](uint size) throw(std::bad_alloc);
|
||||
void operator delete(void* p) throw();
|
||||
void operator delete[](void* p) throw();*/
|
||||
|
||||
//#define DEBUG_NEW new(__FILE__, __LINE__)
|
||||
//#define new DEBUG_NEW
|
||||
//#endif
|
||||
|
||||
/*// 自动释放的智能指针
|
||||
class SmartPtr
|
||||
{
|
||||
private:
|
||||
// 内部包装。指针的多个智能指针SmartPtr对象共用该内部包装
|
||||
class WrapPtr
|
||||
{
|
||||
public:
|
||||
void* Ptr; // 目标指针
|
||||
uint Count; // 引用计数
|
||||
|
||||
WrapPtr(void* ptr) { Ptr = ptr; Count = 1; }
|
||||
~WrapPtr() { delete Ptr; }
|
||||
};
|
||||
WrapPtr* _ptr;
|
||||
|
||||
public:
|
||||
// 为某个指针封装
|
||||
SmartPtr(void* ptr)
|
||||
{
|
||||
assert_ptr(ptr);
|
||||
|
||||
_ptr = new WrapPtr(ptr);
|
||||
}
|
||||
|
||||
// 拷贝智能指针。仅拷贝内部包装,然后引用计数加一
|
||||
SmartPtr(const SmartPtr& ptr)
|
||||
{
|
||||
assert_ptr(ptr._ptr);
|
||||
assert_ptr(ptr._ptr->Ptr);
|
||||
|
||||
_ptr = ptr._ptr;
|
||||
_ptr->Count++;
|
||||
}
|
||||
|
||||
~SmartPtr()
|
||||
{
|
||||
// 释放智能指针时,指针引用计数减一
|
||||
_ptr->Count--;
|
||||
// 如果指针引用计数为0,则释放指针
|
||||
if(!_ptr->Count)
|
||||
{
|
||||
delete _ptr;
|
||||
_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* ToPtr() { return _ptr->Ptr; }
|
||||
};*/
|
||||
|
||||
/*// 经典的C++自动指针
|
||||
// 超出对象作用域时自动销毁被管理指针
|
||||
template<class T>
|
||||
class auto_ptr
|
||||
{
|
||||
private:
|
||||
T* _ptr;
|
||||
|
||||
public:
|
||||
// 普通指针构造自动指针,隐式转换
|
||||
// 构造函数的explicit关键词有效阻止从一个“裸”指针隐式转换成auto_ptr类型
|
||||
explicit auto_ptr(T* p = 0) : _ptr(p) { }
|
||||
// 拷贝构造函数,解除原来自动指针的管理权
|
||||
auto_ptr(auto_ptr& ap) : _ptr(ap.release()) { }
|
||||
// 析构时销毁被管理指针
|
||||
~auto_ptr()
|
||||
{
|
||||
// 因为C++保证删除一个空指针是安全的,所以我们没有必要判断空
|
||||
delete _ptr;
|
||||
}
|
||||
|
||||
// 自动指针拷贝,解除原来自动指针的管理权
|
||||
auto_ptr& operator=(T* p)
|
||||
{
|
||||
_ptr = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 自动指针拷贝,解除原来自动指针的管理权
|
||||
auto_ptr& operator=(auto_ptr& ap)
|
||||
{
|
||||
reset(ap.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 获取原始指针
|
||||
T* get() const { return _ptr; }
|
||||
|
||||
// 重载*和->运算符
|
||||
T& operator*() const { assert_param(_ptr); return *_ptr; }
|
||||
T* operator->() const { return _ptr; }
|
||||
|
||||
// 接触指针的管理权
|
||||
T* release()
|
||||
{
|
||||
T* p = _ptr;
|
||||
_ptr = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
// 销毁原指针,管理新指针
|
||||
void reset(T* p = 0)
|
||||
{
|
||||
if(_ptr != p)
|
||||
{
|
||||
//if(_ptr) delete _ptr;
|
||||
// 因为C++保证删除一个空指针是安全的,所以我们没有必要判断空
|
||||
delete _ptr;
|
||||
_ptr = p;
|
||||
}
|
||||
}
|
||||
};*/
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue