Slice是一种包含字节长度与指针(指定一个外部字节数组)的简单数据结构。Leveldb以Slice作为基本数据结构来存储Key和data,Slice对数据字节的大小没有限制。

class Slice {
public:
    const char* data() const { return data_; }
    size_t size() const { return size_; }
    bool empty() const { return size_ == 0; }
private:
    const char* data_;
    size_t size_;
};

之所以采用Slice而不是string有如下原因:

  • Slice作为返回值只需要返回长度与指针,不需要复制长度较长的key和value。
  • Slice存储的有长度,不以\0作为结束,可以存储值为\0的数据。

为了便于使用,提供了string与Slice进行转换的构造函数。

class Slice {
public:
    Slice(): data_(""), size_(0) {}
    Slice(const char* d, size_t n) : data_(d), size_(n) {}
    Slice(const char* d): data_(d), size_(strlen(d)) {}
    Slice(const std::string& s): data_(s.data()), size_(s.size()) {}
    
    Slice(const Slice&)=default;
    Slice& operator=(const Slice&)=default;
 
	std::string ToString() const { return std::string(data_, size_); }
    ...
private:
...
}

Slice作为key的时候需要进行比较,所以提供了进行比较的compare函数,并重载了!=, ==函数。

class Slice {
public:
	int compare(const Slice& b) const;
};
 
inline int Slice::compare(const Slice& rhs) const {
    const size_t min_len = (size_ < rhs.size_) ? size_ : rhs.size_;
    int r = memcmp(data_, rhs.data_, min_len);
    // 前缀相同的,长度长的大
    if (r == 0) {
        if (size_ < rhs.size_)
            r = -1;
        else if (size_ > rhs.size_)
            r = 1;
    }
    return r;
}
 
inline bool operator==(const Slice& lhs, const Slice& rhs) {
    return (lhs.size() == rhs.size()) &&
            (memcmp(lhs.data_, rhs.data_, lhs.size()));
}
 
inline bool operator!=(const Slice& lhs, const Slice& rhs) {
    return !(lhs == rhs);
}