muduo StringPiece详解

1. 简介

该StringPiece是PCRE的实现,是对字符串的一个proxy类而已(即设计模式中的代理模式)。

2. 背景

很多时候,当传入一个字符串到函数时,往往只是读取字符串时

若使用std::string,当实参为const char *时,会分配内存并拷贝该字符串以生成一个std::string

当一个函数接受一个const std::string,而在该函数内部,又需要传递该值到另一个函数,则又需要重新生成一个std::string

3. 目的

当某个接口参数是接受字符串类型时,为了减少不必要的开销

该类型可以接受const char *,std::string,减少冗余代码编写

4. 要点

① 成员变量

	const char*   ptr_;
	int           length_;

通过保存字符串指针和长度,来避免不必要的复制;
开销很低,只需要sizeof(const char*) + sizeof(int)字节;
内部的ptr_ 这块内存不归他所有,要确保在StringPiece生命期内,该数据可用

② 构造函数

StringPiece()
	: ptr_(NULL), length_(0) { }
StringPiece(const char* str)
	: ptr_(str), length_(static_cast<int>(strlen(ptr_))) { }
StringPiece(const unsigned char* str)
	: ptr_(reinterpret_cast<const char*>(str)),
	  length_(static_cast<int>(strlen(ptr_))) { }
StringPiece(const string& str)
	: ptr_(str.data()), length_(static_cast<int>(str.size())) { }
StringPiece(const char* offset, int len)
	: ptr_(offset), length_(len) { }

参数都是字符串且都是const类型,只用于提取,而不用于修改

③ 字符串比较

bool operator==(const StringPiece& x) const
{
	return ((length_ == x.length_) &&
	        (memcmp(ptr_, x.ptr_, length_) == 0));
}
bool operator!=(const StringPiece& x) const
{
	return !(*this == x);
}

#define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp)                             \
  bool operator cmp (const StringPiece& x) const {                           \
    int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \
    return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_)));          \
  }
	STRINGPIECE_BINARY_PREDICATE(<,  <);
	STRINGPIECE_BINARY_PREDICATE(<=, <);
	STRINGPIECE_BINARY_PREDICATE(>=, >);
	STRINGPIECE_BINARY_PREDICATE(>,  >);
#undef STRINGPIECE_BINARY_PREDICATE

以<为例,宏展开后代码如下

bool operator < (const StringPiece& x) const {                           \
    int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \
    return ((r < 0) || ((r == 0) && (length_ < x.length_)));          \
  }

比较”abcd” < “abcdefg”, 返回的结果为true
比较”abcdx” < “abcdefg”, 返回结果为false

④ 操作

const char* data() const
{
	return ptr_;
}
int size() const
{
	return length_;
}
bool empty() const
{
	return length_ == 0;
}
const char* begin() const
{
	return ptr_;
}
const char* end() const
{
	return ptr_ + length_;
}

void clear()
{
	ptr_ = NULL;
	length_ = 0;
}
void set(const char* buffer, int len)
{
	ptr_ = buffer;
	length_ = len;
}
void set(const char* str)
{
	ptr_ = str;
	length_ = static_cast<int>(strlen(str));
}
void set(const void* buffer, int len)
{
	ptr_ = reinterpret_cast<const char*>(buffer);
	length_ = len;
}

char operator[](int i) const
{
	return ptr_[i];
}

void remove_prefix(int n)
{
	ptr_ += n;
	length_ -= n;
}

void remove_suffix(int n)
{
	length_ -= n;
}
int compare(const StringPiece& x) const
{
	int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_);
	if (r == 0) {
		if (length_ < x.length_) r = -1;
		else if (length_ > x.length_) r = +1;
	}
	return r;
}

string as_string() const
{
	return string(data(), size());
}

void CopyToString(string* target) const
{
	target->assign(ptr_, length_);
}

// Does "this" start with "x"
bool starts_with(const StringPiece& x) const
{
	return ((length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0));
}

⑤ Traits
由于StringPiece只持有目标指针,所以是POD类型,并且拥有平凡构造函数,所以可以定义如下的type traits以指示STL采用更为高效的算法实现。

#ifdef HAVE_TYPE_TRAITS
// This makes vector<StringPiece> really fast for some STL implementations
template<> struct __type_traits<StringPiece> {
	typedef __true_type    has_trivial_default_constructor;
	typedef __true_type    has_trivial_copy_constructor;
	typedef __true_type    has_trivial_assignment_operator;
	typedef __true_type    has_trivial_destructor;
	typedef __true_type    is_POD_type;
};
#endif

⑥ 输出

// allow StringPiece to be logged
std::ostream& operator<<(std::ostream& o, const StringPiece& piece);

重载<<方便打印和日志输出

5. 源码

Github

6. 参考

http://qianchenglong.github.io/2016/05/28/C++-StringPiece/
https://blog.csdn.net/q5707802/article/details/78420629
POD类型参考https://zhuanlan.zhihu.com/p/45545035

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值