废话不说,直接上代码
struct Slice
{
SharedStr* sharedStr;
int p;
int length;
virtual ~Slice()
{
sharedStr->free();
}
Slice():Slice("") {
}
Slice(const Slice& right) : p(right.p),length(right.length)
{
right.sharedStr->copy(&sharedStr);
}
Slice& operator=(const Slice& right) {
right.sharedStr->copy(&sharedStr);
p = right.p;
length = right.length;
return *this;
}
Slice(string&& data):p(0)
{
length = data.length();
sharedStr = new SharedStr(move(data));
}
Slice(Slice* parent, int start, int end)
{
parent->sharedStr->copy(&sharedStr);
p = parent->p + start;
length = end - start;
}
Slice(int len, int cap) : length(len),p(0)
{
if (!cap)cap = len;
sharedStr = new SharedStr(cap);
}
size_t cap() {
return sharedStr->capacity() - p;
}
Slice operator()(int start, int end)
{
return Slice(this, start, end);
}
unsigned char operator[](int i)
{
return ((unsigned char*)(*sharedStr))[p+i];
}
Slice operator+(const Slice& right) {
return append((void*)right.point(), right.length);
}
const char* point() const{
return sharedStr->data.data() + p;
}
Slice append(void * data ,int len) {
if (len > cap() - length) {
string newStr;
newStr.resize(p + length + len);
memcpy((void*)newStr.data(), sharedStr->data.data(), p + length);
memcpy((void*)(newStr.data() + p + length), data, len);
return Slice(move(newStr));
}
memcpy((void*)(point() + length), data, len);
return Slice(this, 0, length + len);
}
OPERATOR_CHARS((*sharedStr)+p)
};
由于C++的下标运算符的重写没办法实现和golang一致的语法,所以只能退而求其次,使用括号运算符代替。
数据存放在一个SharedStr的结构体中,该结构体在多个Slice对象中共享,这个思路是取自C++的智能指针的设计原理。
实现了移动构造函数以提高性能
SharedStr的代码如下
struct SharedStr
{
string data;
int refCount;
SharedStr(size_t size):refCount(1) {
data.reserve(size);
}
SharedStr(string &&right) : data(move(right)),refCount(1)
{
}
void free()
{
refCount--;
if (refCount == 0)
{
delete this;
}
}
void copy(SharedStr** target) {
*target = this;
refCount++;
}
void expend(size_t t) {
data.resize(data.capacity() + t);
}
size_t capacity() {
return data.capacity();
}
OPERATOR_CHARS(data.data())
};
OPERATOR_CHARS宏不用管,是各种类型转换
每当Slice被析构的时候,都会使得共享数据引用计数减一,反之被复制就加一,达到0的时候就释放共享数据。
共享数据采用string类型存储,string类型本身实现了长度和容量等功能,可以直接使用。