1303 lines
28 KiB
C++
1303 lines
28 KiB
C++
#ifndef __Type_H__
|
||
#define __Type_H__
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
/* 类型定义 */
|
||
typedef char sbyte;
|
||
typedef unsigned char byte;
|
||
typedef unsigned short ushort;
|
||
typedef unsigned int uint;
|
||
typedef unsigned long long ulong;
|
||
typedef char* string;
|
||
//typedef unsigned char bool;
|
||
//#define true 1
|
||
//#define false 0
|
||
|
||
#define UInt64_Max 0xFFFFFFFFFFFFFFFFull
|
||
|
||
/*
|
||
// 尚未决定是否采用下面这种类型
|
||
typedef char SByte;
|
||
typedef unsigned char Byte;
|
||
typedef short Int16;
|
||
typedef unsigned short UInt16;
|
||
typedef int Int32;
|
||
typedef unsigned int UInt32;
|
||
typedef long long Int64;
|
||
typedef unsigned long long UInt64;
|
||
typedef char* String;
|
||
*/
|
||
typedef long long Int64;
|
||
|
||
#include <typeinfo>
|
||
using namespace ::std;
|
||
|
||
class String;
|
||
class Type;
|
||
|
||
// 根对象
|
||
class Object
|
||
{
|
||
private:
|
||
//Type* _Type; // 类型
|
||
|
||
protected:
|
||
|
||
public:
|
||
// 输出对象的字符串表示方式
|
||
virtual String& ToStr(String& str) const;
|
||
// 输出对象的字符串表示方式。支持RVO优化
|
||
virtual String ToString() const;
|
||
// 显示对象。默认显示ToString
|
||
virtual void Show(bool newLine = false) const;
|
||
|
||
//Type GetType() const;
|
||
};
|
||
|
||
/*// 类型
|
||
class Type
|
||
{
|
||
private:
|
||
type_info* _info;
|
||
|
||
public:
|
||
int Size; // 大小
|
||
String Name; // 名称
|
||
|
||
Type(type_info* ti);
|
||
};*/
|
||
|
||
// 数组长度
|
||
#define ArrayLength(arr) (sizeof(arr)/sizeof(arr[0]))
|
||
// 数组清零,固定长度
|
||
#define ArrayZero(arr) memset(arr, 0, ArrayLength(arr) * sizeof(arr[0]))
|
||
// 数组清零,可变长度
|
||
#define ArrayZero2(arr, len) memset(arr, 0, len * sizeof(arr[0]))
|
||
// 数组复制
|
||
#define ArrayCopy(dst, src) memcpy(dst, src, ArrayLength(src) * sizeof(src[0]))
|
||
|
||
template<typename T>
|
||
class IArray
|
||
{
|
||
public:
|
||
virtual int Length() const = 0;
|
||
virtual void SetAt(int i, const T& item) = 0;
|
||
virtual T& operator[](int i) const = 0;
|
||
};
|
||
|
||
// 数组
|
||
/*
|
||
数组是指针和长度的封装。
|
||
设计本意:
|
||
1,数据处理函数无需同时传递指针和长度
|
||
2,数组下标越界检查,避免指针越界
|
||
3,数组自动扩容,避免因不知道函数内部需要多大缓存空间而带来的设计复杂度
|
||
|
||
按照指针来源可分为两大用法:
|
||
1,内部分配。随时可以扩容,对象拷贝时共用空间
|
||
2,外部指针。此时认为只是封装,不允许扩容
|
||
|
||
数组拷贝:
|
||
内=>内 共用数据区
|
||
内=>外 共用数据区
|
||
外=>内 仅复制指针
|
||
外=>外 仅复制指针
|
||
*/
|
||
template<typename T, int ArraySize = 0x40>
|
||
class Array : public Object, public IArray<T>
|
||
{
|
||
protected:
|
||
T* _Arr; // 数据指针
|
||
int _Length; // 数组长度
|
||
uint _Capacity; // 数组最大容量
|
||
bool _needFree; // 是否需要释放
|
||
bool _canWrite; // 是否可写
|
||
|
||
T Arr[ArraySize]; // 内部缓冲区
|
||
|
||
// 检查容量。如果不足则扩大,并备份指定长度的数据
|
||
void CheckCapacity(int len, int bak = 0)
|
||
{
|
||
// 是否超出容量
|
||
if(len <= _Capacity) return;
|
||
|
||
// 自动计算合适的容量
|
||
int k = 0x40;
|
||
while(k < len) k <<= 1;
|
||
|
||
T* p = new T[k];
|
||
|
||
// 是否需要备份数据
|
||
if(bak > _Length) bak = _Length;
|
||
if(bak > 0 && _Arr) memcpy(p, _Arr, bak);
|
||
|
||
if(_needFree && _Arr) delete _Arr;
|
||
|
||
_Capacity = k;
|
||
_Arr = p;
|
||
_needFree = true;
|
||
}
|
||
|
||
public:
|
||
// 数组长度
|
||
virtual int Length() const { return _Length; }
|
||
// 数组最大容量。初始化时决定,后面不允许改变
|
||
int Capacity() const { return _Capacity; }
|
||
// 缓冲区
|
||
T* GetBuffer() const { return _Arr; }
|
||
|
||
// 初始化指定长度的数组。默认使用内部缓冲区
|
||
Array(int length = ArraySize)
|
||
{
|
||
assert_param2(length <= 0x400, "禁止分配超过1k的数组");
|
||
if(length < 0) length = ArrayLength(Arr);
|
||
|
||
_Length = length;
|
||
if(length <= ArrayLength(Arr))
|
||
{
|
||
_Arr = Arr;
|
||
_Capacity = ArrayLength(Arr);
|
||
_needFree = false;
|
||
}
|
||
else
|
||
{
|
||
_Arr = new T[length];
|
||
_Capacity = length;
|
||
_needFree = true;
|
||
}
|
||
_canWrite = true;
|
||
}
|
||
|
||
Array(const Array& arr)
|
||
{
|
||
_Length = arr.Length();
|
||
_canWrite = true;
|
||
|
||
Copy(arr);
|
||
}
|
||
|
||
// 析构。释放资源
|
||
virtual ~Array()
|
||
{
|
||
if(_needFree && _Arr) delete _Arr;
|
||
}
|
||
|
||
// 重载等号运算符,使用另一个固定数组来初始化
|
||
Array& operator=(const Array& arr)
|
||
{
|
||
// 不要自己拷贝给自己
|
||
if(&arr == this) return *this;
|
||
|
||
_Length = 0;
|
||
|
||
Copy(arr);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// 设置数组长度。容量足够则缩小Length,否则扩容以确保数组容量足够大避免多次分配内存
|
||
bool SetLength(int length, bool bak = false)
|
||
{
|
||
if(length <= _Capacity)
|
||
{
|
||
_Length = length;
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
CheckCapacity(length, bak ? _Length : 0);
|
||
|
||
// 扩大长度
|
||
if(length > _Length) _Length = length;
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 设置数组元素为指定值,自动扩容
|
||
bool Set(const T& item, int index = 0, int count = 0)
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
// count<=0 表示设置全部元素
|
||
if(count <= 0) count = _Length - index;
|
||
assert_param2(count > 0, "Array::Set的个数必须大于0");
|
||
|
||
// 检查长度是否足够
|
||
int len2 = index + count;
|
||
CheckCapacity(len2, index);
|
||
|
||
// 如果元素类型大小为1,那么可以直接调用内存设置函数
|
||
if(sizeof(T) == 1)
|
||
memset(_Arr + index, item, sizeof(T) * count);
|
||
else
|
||
while(count-- > 0) _Arr[index++] = item;
|
||
|
||
// 扩大长度
|
||
if(len2 > _Length) _Length = len2;
|
||
|
||
return true;
|
||
}
|
||
|
||
// 设置数组。直接使用指针,不拷贝数据
|
||
bool Set(void* data, int len = 0)
|
||
{
|
||
if(!Set((const void*)data, len)) return false;
|
||
|
||
_canWrite = true;
|
||
|
||
return true;
|
||
}
|
||
|
||
// 设置数组。直接使用指针,不拷贝数据
|
||
bool Set(const void* data, int len = 0)
|
||
{
|
||
int max = len;
|
||
if(!data)
|
||
{
|
||
data = Arr;
|
||
max = ArrayLength(Arr);
|
||
}
|
||
// 自动计算长度,\0结尾
|
||
else if(!len)
|
||
{
|
||
byte* p =(byte*)data;
|
||
while(*p++) len++;
|
||
}
|
||
|
||
// 销毁旧的
|
||
if(_needFree && _Arr) delete _Arr;
|
||
|
||
_Arr = (T*)data;
|
||
_Length = len;
|
||
_Capacity = max;
|
||
_needFree = false;
|
||
_canWrite = false;
|
||
|
||
return true;
|
||
}
|
||
|
||
// 复制数组。深度克隆,拷贝数据
|
||
int Copy(const Array& arr, int index = 0)
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
if(&arr == this) return 0;
|
||
if(arr.Length() == 0) return 0;
|
||
|
||
return Copy(arr._Arr, arr.Length(), index);
|
||
}
|
||
|
||
// 复制数组。深度克隆,拷贝数据,自动扩容
|
||
int Copy(const void* data, int len = 0, int index = 0)
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
// 自动计算长度,\0结尾
|
||
if(!len)
|
||
{
|
||
byte* p =(byte*)data;
|
||
while(*p++) len++;
|
||
}
|
||
|
||
// 检查长度是否足够
|
||
int len2 = index + len;
|
||
CheckCapacity(len2, index);
|
||
|
||
// 拷贝数据
|
||
memcpy(_Arr + index, data, sizeof(T) * len);
|
||
|
||
// 扩大长度
|
||
if(len2 > _Length) _Length = len2;
|
||
|
||
return len;
|
||
}
|
||
|
||
// 把当前数组复制到目标缓冲区。未指定长度len时复制全部
|
||
int CopyTo(void* data, int len = 0, int index = 0) const
|
||
{
|
||
// 数据长度可能不足
|
||
if(_Length - index < len || len == 0) len = _Length - index;
|
||
if(len <= 0) return 0;
|
||
|
||
// 拷贝数据
|
||
memcpy(data, _Arr + index, sizeof(T) * len);
|
||
|
||
return len;
|
||
}
|
||
|
||
// 清空已存储数据。
|
||
virtual Array& Clear()
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
memset(_Arr, 0, sizeof(T) * _Length);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// 设置指定位置的值,不足时自动扩容
|
||
virtual void SetAt(int i, const T& item)
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
// 检查长度,不足时扩容
|
||
CheckCapacity(i + 1, _Length);
|
||
|
||
if(i >= _Length) _Length = i + 1;
|
||
|
||
_Arr[i] = item;
|
||
}
|
||
|
||
// 加入一个数据到末尾
|
||
virtual int Push(T& item)
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
|
||
int i = _Length;
|
||
// 检查长度,不足时扩容
|
||
CheckCapacity(i + 1, _Length);
|
||
|
||
_Length++;
|
||
|
||
_Arr[i] = item;
|
||
|
||
return i;
|
||
}
|
||
|
||
// 末尾加入一个空数据,并返回引用,允许外部修改
|
||
virtual T& Push()
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
|
||
int i = _Length;
|
||
// 检查长度,不足时扩容
|
||
CheckCapacity(i + 1, _Length);
|
||
|
||
_Length++;
|
||
|
||
return _Arr[i];
|
||
}
|
||
|
||
// 弹出最后一个数组元素,长度减一
|
||
virtual T& Pop()
|
||
{
|
||
assert_param2(_canWrite, "禁止修改数组数据");
|
||
|
||
return _Arr[--_Length];
|
||
}
|
||
|
||
// 查找元素
|
||
virtual int FindIndex(const T item)
|
||
{
|
||
for(int i=0; i<Length(); i++)
|
||
{
|
||
if(_Arr[i] == item) return i;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
// 重载索引运算符[],让它可以像数组一样使用下标索引。
|
||
virtual T& operator[](int i) const
|
||
{
|
||
assert_param2(_Arr && i >= 0 && i < _Length, "数组下标越界");
|
||
|
||
return _Arr[i];
|
||
}
|
||
|
||
friend bool operator==(const Array& bs1, const Array& bs2)
|
||
{
|
||
if(bs1.Length() != bs2.Length()) return false;
|
||
|
||
for(int i=0; i<bs1.Length(); i++)
|
||
{
|
||
if(bs1[i] != bs2[i]) return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
friend bool operator!=(const Array& bs1, const Array& bs2)
|
||
{
|
||
if(bs1.Length() != bs2.Length()) return true;
|
||
|
||
for(int i=0; i<bs1.Length(); i++)
|
||
{
|
||
if(bs1[i] != bs2[i]) return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
};
|
||
|
||
// 字节数组
|
||
class ByteArray : public Array<byte>
|
||
{
|
||
public:
|
||
ByteArray(int length = 0) : Array(length) { }
|
||
ByteArray(byte item, int length) : Array(length) { Set(item, 0, length); }
|
||
// 因为使用外部指针,这里初始化时没必要分配内存造成浪费
|
||
ByteArray(const void* data, int length, bool copy = false);
|
||
ByteArray(void* data, int length, bool copy = false);
|
||
ByteArray(const ByteArray& arr) : Array(arr.Length()) { Copy(arr); }
|
||
ByteArray(String& str); // 直接引用数据缓冲区
|
||
ByteArray(const String& str); // 不允许修改,拷贝
|
||
|
||
// 重载等号运算符,使用外部指针、内部长度,用户自己注意安全
|
||
ByteArray& operator=(const void* data);
|
||
|
||
// 显示十六进制数据,指定分隔字符和换行长度
|
||
String& ToHex(String& str, char sep = '-', int newLine = 0x10) const;
|
||
// 显示十六进制数据,指定分隔字符和换行长度
|
||
String ToHex(char sep = '-', int newLine = 0x10) const;
|
||
|
||
// 保存到普通字节数组,首字节为长度
|
||
int Load(const void* data, int maxsize = -1);
|
||
// 从普通字节数据组加载,首字节为长度
|
||
int Save(void* data, int maxsize = -1) const;
|
||
|
||
// 输出对象的字符串表示方式
|
||
virtual String& ToStr(String& str) const;
|
||
// 显示对象。默认显示ToString
|
||
virtual void Show(bool newLine = false) const;
|
||
|
||
ushort ToUInt16() const;
|
||
uint ToUInt32() const;
|
||
ulong 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(ulong value, int index = 0);
|
||
|
||
//friend bool operator==(const ByteArray& bs1, const ByteArray& bs2);
|
||
//friend bool operator!=(const ByteArray& bs1, const ByteArray& bs2);
|
||
};
|
||
|
||
// 字符串
|
||
class String : public Array<char>
|
||
{
|
||
private:
|
||
|
||
public:
|
||
// 字符串默认0长度,容量0x40
|
||
String(int length = 0) : Array(length) { }
|
||
String(char item, int count) : Array(count) { Set(item, 0, count); }
|
||
// 因为使用外部指针,这里初始化时没必要分配内存造成浪费
|
||
String(void* str, int len = 0) : Array(0) { Set(str, len); }
|
||
String(const void* str, int len = 0) : Array(0) { Set(str, len); }
|
||
String(const String& str) : Array(str.Length()) { Copy(str); }
|
||
|
||
// 输出对象的字符串表示方式
|
||
virtual String& ToStr(String& str) const;
|
||
// 输出对象的字符串表示方式
|
||
virtual String ToString() const;
|
||
// 清空已存储数据。长度放大到最大容量
|
||
virtual String& Clear();
|
||
|
||
String& Append(char ch);
|
||
String& Append(const char* str, int len = 0);
|
||
String& Append(int value, int radix = 10, int width = 0); // 写入整数,第二参数指定宽带,不足时补零
|
||
String& Append(byte bt); // 十六进制
|
||
String& Append(ByteArray& bs); // 十六进制
|
||
|
||
// 调试输出字符串
|
||
virtual void Show(bool newLine = false) const;
|
||
|
||
// 格式化字符串,输出到现有字符串后面。方便我们连续格式化多个字符串
|
||
String& Format(const char* format, ...);
|
||
|
||
String& Concat(const Object& obj);
|
||
String& Concat(const char* str, int len = 0);
|
||
|
||
String& operator+=(const Object& obj);
|
||
String& operator+=(const char* str);
|
||
friend String& operator+(String& str, const Object& obj);
|
||
friend String& operator+(String& str, const char* str2);
|
||
friend String& operator+(String& str, char ch);
|
||
friend String& operator+(String& str, byte bt);
|
||
friend String& operator+(String& str, int value);
|
||
};
|
||
|
||
//String operator+(const char* str1, const char* str2);
|
||
String operator+(const char* str, const Object& obj);
|
||
String operator+(const Object& obj, const char* str);
|
||
|
||
// 从数组创建列表
|
||
#define MakeList(T, arr) List<T>(&arr[0], sizeof(arr)/sizeof(arr[0]))
|
||
|
||
// 数组
|
||
class JArray
|
||
{
|
||
private:
|
||
void** _Arr;
|
||
int _Count;
|
||
int _Capacity;
|
||
|
||
public:
|
||
// 有效元素个数
|
||
int Count() const { return _Count; }
|
||
// 最大元素个数
|
||
int Capacity() const { return _Capacity; }
|
||
|
||
JArray(int capacity = 0x10)
|
||
{
|
||
_Capacity = capacity;
|
||
_Count = 0;
|
||
|
||
_Arr = new void*[capacity];
|
||
ArrayZero2(_Arr, capacity);
|
||
}
|
||
|
||
~JArray()
|
||
{
|
||
if(_Arr) delete _Arr;
|
||
_Arr = NULL;
|
||
}
|
||
|
||
// 压入一个元素
|
||
int Push(void* item)
|
||
{
|
||
assert_param(_Count < _Capacity);
|
||
|
||
// 找到空闲位放置
|
||
int idx = _Count++;
|
||
_Arr[idx] = item;
|
||
|
||
return idx;
|
||
}
|
||
|
||
// 弹出一个元素
|
||
const void* Pop()
|
||
{
|
||
assert_param(_Count > 0);
|
||
|
||
return _Arr[--_Count];
|
||
}
|
||
|
||
// 重载索引运算符[],让它可以像数组一样使用下标索引。
|
||
void* operator[](int i)
|
||
{
|
||
assert_param(i >= 0 && i < _Count);
|
||
return _Arr[i];
|
||
}
|
||
// 列表转为指针,注意安全
|
||
//T* operator=(Array arr) { return arr.Arr; }
|
||
};
|
||
|
||
// 固定大小的指针数组。
|
||
/*
|
||
用于数据元素不多,有个上限的场合。主要为了方便遍历。
|
||
存储数据时,从头开始找到空位来存放,不用时清空相应空位。
|
||
所以需要注意的是,在数组里面存储的元素不一定连续。
|
||
*/
|
||
template<typename T, int ArraySize>
|
||
class FixedArray
|
||
{
|
||
private:
|
||
uint _Count;
|
||
T* Arr[ArraySize];
|
||
|
||
public:
|
||
// 默认初始化。大小和数组元素全部清零
|
||
FixedArray()
|
||
{
|
||
_Count = 0;
|
||
ArrayZero(Arr);
|
||
}
|
||
|
||
// 使用另一个固定数组来初始化
|
||
FixedArray(FixedArray& arr)
|
||
{
|
||
_Count = arr._Count;
|
||
ArrayCopy(Arr, arr.Arr);
|
||
}
|
||
|
||
// 重载等号运算符,使用另一个固定数组来初始化
|
||
FixedArray& operator=(FixedArray& arr)
|
||
{
|
||
_Count = arr._Count;
|
||
ArrayCopy(Arr, arr.Arr);
|
||
|
||
return *this;
|
||
}
|
||
|
||
~FixedArray() { DeleteAll(); }
|
||
|
||
// 实际元素个数
|
||
uint Count() const { return _Count; }
|
||
|
||
// 数组总长度
|
||
uint Length() const { return ArraySize; }
|
||
|
||
// 压入一个元素。返回元素所存储的索引
|
||
int Add(T* item)
|
||
{
|
||
assert_ptr(item);
|
||
//assert_param(_Count < ArraySize);
|
||
|
||
if(_Count >= ArraySize) return -1;
|
||
|
||
// 找到空闲位放置
|
||
int i = 0;
|
||
for(; i < ArraySize && Arr[i]; i++);
|
||
// 检查是否还有空位
|
||
if(i >= ArraySize) return -1;
|
||
|
||
Arr[i] = item;
|
||
_Count++;
|
||
|
||
return i;
|
||
}
|
||
|
||
// 弹出最后一个元素
|
||
T* Pop()
|
||
{
|
||
if(_Count == 0) return NULL;
|
||
|
||
// 找到最后一个元素
|
||
int i = ArraySize - 1;
|
||
for(; i >=0 && !Arr[i]; i--);
|
||
|
||
T* item = Arr[i];
|
||
_Count--;
|
||
Arr[i] = NULL;
|
||
|
||
return item;
|
||
}
|
||
|
||
// 删除元素
|
||
bool Remove(T* item)
|
||
{
|
||
int idx = Find(item);
|
||
if(idx < 0) return false;
|
||
|
||
RemoveAt(idx);
|
||
|
||
return true;
|
||
}
|
||
|
||
// 删除指定位置的元素
|
||
void RemoveAt(int idx)
|
||
{
|
||
assert_param(idx >= 0 && idx < ArraySize);
|
||
|
||
_Count--;
|
||
Arr[idx] = NULL;
|
||
}
|
||
|
||
// 清空数组。个数设0,所有元素清零
|
||
FixedArray& Clear()
|
||
{
|
||
_Count = 0;
|
||
ArrayZero(Arr);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// 释放所有指针指向的内存
|
||
FixedArray& DeleteAll()
|
||
{
|
||
for(int i=0; i < ArraySize; i++)
|
||
{
|
||
if(Arr[i]) delete Arr[i];
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
// 查找元素
|
||
int Find(T* item)
|
||
{
|
||
assert_ptr(item);
|
||
|
||
int i = 0;
|
||
for(; i < ArraySize && Arr[i] != item; i++);
|
||
if(i >= ArraySize) return -1;
|
||
|
||
return i;
|
||
}
|
||
|
||
// 移到下一个元素,累加参数,如果没有下一个元素则返回false。
|
||
bool MoveNext(int& idx)
|
||
{
|
||
//assert_ptr(idx);
|
||
|
||
// 从idx开始,找到第一个非空节点。注意,存储不一定连续
|
||
int i = idx + 1;
|
||
for(; i < ArraySize && !Arr[i]; i++);
|
||
if(i >= ArraySize) return false;
|
||
|
||
idx = i;
|
||
|
||
return true;
|
||
}
|
||
|
||
// 重载索引运算符[],让它可以像数组一样使用下标索引。
|
||
/*T*& operator[](int i)
|
||
{
|
||
assert_param(i >= 0 && i < ArraySize);
|
||
return Arr[i];
|
||
}*/
|
||
// 不能允许[]作为左值,否则外部直接设置数据以后,Count并没有改变
|
||
T* operator[](int i)
|
||
{
|
||
assert_param(i >= 0 && i < ArraySize);
|
||
return Arr[i];
|
||
}
|
||
};
|
||
|
||
// 变长列表模版
|
||
// T一般是指针,列表内部有一个数组用于存放指针
|
||
template<typename T>
|
||
class List
|
||
{
|
||
private:
|
||
uint _Count;// 拥有实际元素个数
|
||
uint _total;// 可容纳元素总数
|
||
T* _Arr; // 存储数据的数组
|
||
|
||
void ChangeSize(int newSize)
|
||
{
|
||
if(_total == newSize) return;
|
||
|
||
T* arr2 = new T[newSize];
|
||
if(_Arr)
|
||
{
|
||
// 如果新数组较小,则直接复制;如果新数组较大,则先复制,再清空余下部分
|
||
if(newSize < _Count)
|
||
{
|
||
// 此时有数据丢失
|
||
memcpy(arr2, _Arr, newSize * sizeof(T));
|
||
_Count = newSize;
|
||
}
|
||
else
|
||
{
|
||
memcpy(arr2, _Arr, _Count * sizeof(T));
|
||
memset(&arr2[_Count], 0, (newSize - _Count) * sizeof(T));
|
||
}
|
||
delete[] _Arr;
|
||
}
|
||
else
|
||
ArrayZero2(arr2, newSize);
|
||
_Arr = arr2;
|
||
_total = newSize;
|
||
}
|
||
|
||
void CheckSize()
|
||
{
|
||
// 如果数组空间已用完,则两倍扩容
|
||
if(_Count >= _total) ChangeSize(_Count > 0 ? _Count * 2 : 4);
|
||
}
|
||
|
||
public:
|
||
List(int size = 0)
|
||
{
|
||
_Count = 0;
|
||
_total = size;
|
||
_Arr = NULL;
|
||
if(size)
|
||
{
|
||
_Arr = new T[size];
|
||
ArrayZero2(_Arr, size);
|
||
}
|
||
}
|
||
|
||
List(T* items, uint count)
|
||
{
|
||
_Arr = new T[count];
|
||
|
||
_Count = 0;
|
||
_total = count;
|
||
for(int i=0; i<count; i++)
|
||
{
|
||
_Arr[_Count++] = *items++;
|
||
}
|
||
}
|
||
|
||
~List() { if(_Arr) delete[] _Arr; _Arr = NULL; }
|
||
|
||
// 重载等号运算符,使用另一个列表来初始化
|
||
List& operator=(List& list)
|
||
{
|
||
Clear();
|
||
for(int i=0; i<list.Count(); i++)
|
||
Add(list[i]);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// 添加单个元素
|
||
virtual void Add(const T& item)
|
||
{
|
||
// 检查大小
|
||
CheckSize();
|
||
|
||
_Arr[_Count++] = item;
|
||
}
|
||
|
||
// 添加多个元素
|
||
void Add(T* items, int count)
|
||
{
|
||
int size = _Count + count;
|
||
if(size >= _total) ChangeSize(_Count > 0 ? _Count * 2 : 4);
|
||
|
||
for(int i=0; i<count; i++)
|
||
{
|
||
_Arr[_Count++] = *items++;
|
||
}
|
||
}
|
||
|
||
// 查找元素
|
||
int Find(const T& item)
|
||
{
|
||
for(int i=0; i<_Count; i++)
|
||
{
|
||
if(_Arr[i] == item) return i;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
virtual bool Contains(const T& item)
|
||
{
|
||
return Find(item) > -1;
|
||
}
|
||
|
||
// 删除指定位置元素
|
||
void RemoveAt(int index)
|
||
{
|
||
if(_Count <= 0 || index >= _Count) return;
|
||
|
||
// 复制元素
|
||
if(index < _Count - 1) memcpy(&_Arr[index], &_Arr[index + 1], (_Count - index - 1) * sizeof(T));
|
||
_Count--;
|
||
}
|
||
|
||
// 删除指定元素
|
||
virtual void Remove(const T& item)
|
||
{
|
||
int index = Find(item);
|
||
if(index >= 0) RemoveAt(index);
|
||
}
|
||
|
||
// 释放所有指针指向的内存
|
||
List& DeleteAll()
|
||
{
|
||
for(int i=0; i < _Count; i++)
|
||
{
|
||
if(_Arr[i]) delete _Arr[i];
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
virtual void Clear()
|
||
{
|
||
_Count = 0;
|
||
}
|
||
|
||
virtual void CopyTo(T* arr)
|
||
{
|
||
assert_ptr(arr);
|
||
if(!_Count) return;
|
||
|
||
memcpy(arr, _Arr, _Count * sizeof(T));
|
||
}
|
||
|
||
// 返回内部指针
|
||
const T* ToArray() { return _Arr; }
|
||
|
||
// 有效元素个数
|
||
virtual int Count() const { return _Count; }
|
||
|
||
// 设置新的容量,如果容量比元素个数小,则会丢失数据
|
||
void SetCapacity(int capacity) { ChangeSize(capacity); }
|
||
|
||
// 重载索引运算符[],让它可以像数组一样使用下标索引。
|
||
T operator[](int i)
|
||
{
|
||
assert_param(i >= 0 && i < _Count);
|
||
// 有可能多线程冲突
|
||
//if(i < 0 || i >= _Count) return NULL;
|
||
|
||
return _Arr[i];
|
||
}
|
||
};
|
||
|
||
// 双向链表
|
||
template <class T> class LinkedList;
|
||
|
||
// 双向链表节点。实体类继承该类
|
||
template <class T> class LinkedNode
|
||
{
|
||
// 友元类。允许链表类控制本类私有成员
|
||
friend class LinkedList<T>;
|
||
|
||
public:
|
||
T* Prev; // 上一个节点
|
||
T* Next; // 下一个节点
|
||
|
||
void Initialize()
|
||
{
|
||
Next = NULL;
|
||
Prev = NULL;
|
||
}
|
||
|
||
// 从链表中删除。需要修改前后节点的指针指向,但当前节点仍然指向之前的前后节点
|
||
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 = NULL;
|
||
Prev = NULL;
|
||
}
|
||
|
||
// 把当前节点附加到另一个节点之后
|
||
void LinkAfter(T* node)
|
||
{
|
||
node->Next = (T*)this;
|
||
Prev = node;
|
||
// 不能清空Next,因为可能是两个链表的合并
|
||
//Next = NULL;
|
||
}
|
||
|
||
// 最后一个节点
|
||
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 = NULL;
|
||
}
|
||
};
|
||
|
||
// 双向链表
|
||
template <class T>
|
||
class LinkedList
|
||
{
|
||
public:
|
||
// 链表节点。实体类不需要继承该内部类
|
||
class Node
|
||
{
|
||
public:
|
||
T Item; // 元素
|
||
Node* Prev; // 前一节点
|
||
Node* Next; // 下一节点
|
||
|
||
Node()
|
||
{
|
||
Prev = NULL;
|
||
Next = NULL;
|
||
}
|
||
|
||
// 从队列中脱离
|
||
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 = NULL;
|
||
_Tail = NULL;
|
||
_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 NULL;
|
||
|
||
Node* node = _Head;
|
||
_Head = _Head->Next;
|
||
// 可能只有一个节点
|
||
if(!_Head)
|
||
_Tail = NULL;
|
||
else
|
||
_Head->Prev = NULL;
|
||
|
||
T& item = node->Item;
|
||
delete node;
|
||
_Count--;
|
||
|
||
return item;
|
||
}
|
||
|
||
// 释放最后一个有效节点
|
||
T& ExtractLast()
|
||
{
|
||
if(!_Count) return NULL;
|
||
|
||
Node* node = _Tail;
|
||
_Tail = _Tail->Prev;
|
||
// 可能只有一个节点
|
||
if(!_Tail)
|
||
_Head = NULL;
|
||
else
|
||
_Tail->Next = NULL;
|
||
|
||
T& item = node->Item;
|
||
delete node;
|
||
_Count--;
|
||
|
||
return item;
|
||
}
|
||
};
|
||
|
||
void* operator new(uint size);
|
||
void* operator new[](uint size);
|
||
void operator delete(void* p);
|
||
void operator delete [] (void* p);
|
||
|
||
//#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 = NULL;
|
||
}
|
||
}
|
||
|
||
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++保证删除一个空指针是安全的,所以我们没有必要判断空
|
||
/*if(_ptr)
|
||
{
|
||
delete _ptr;
|
||
_ptr = NULL;
|
||
}*/
|
||
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
|