StringPiece

来源:互联网 发布:南京埃斯顿怎么样知乎 编辑:程序博客网 时间:2024/05/16 02:14

class StringPiece {

 public:

  typedef size_t size_type;

 

 private:

  const char*   ptr_;

  size_type     length_;

 

 public:

  // We provide non-explicit singleton constructors so users can pass

  // in a "const char*" or a "string" wherever a "StringPiece" is

  // expected.

  StringPiece() : ptr_(NULL), length_(0) { }

  StringPiece(const char* str)

    : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { }

  StringPiece(const std::string& str)

    : ptr_(str.data()), length_(str.size()) { }

  StringPiece(const char* offset, size_type len)

    : ptr_(offset), length_(len) { }

 

  // data() may return a pointer to a buffer with embedded NULs, and the

  // returned buffer may or may not be null terminated.  Therefore it is

  // typically a mistake to pass data() to a routine that expects a NUL

  // terminated string.

  const char* data() const { return ptr_; }

  size_type size() const { return length_; }

  size_type length() const { return length_; }

  bool empty() const { return length_ == 0; }

 

  void clear() { ptr_ = NULL; length_ = 0; }

  void set(const char* data, size_type len) { ptr_ = data; length_ = len; }

  void set(const char* str) {

    ptr_ = str;

    length_ = str ? strlen(str) : 0;

  }

  void set(const void* data, size_type len) {

    ptr_ = reinterpret_cast<const char*>(data);

    length_ = len;

  }

 

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

 

  void remove_prefix(size_type n) {

    ptr_ += n;

    length_ -= n;

  }

 

  void remove_suffix(size_type n) {

    length_ -= n;

  }

 

  int compare(const StringPiece& x) const {

    int r = wordmemcmp(ptr_, x.ptr_, std::min(length_, x.length_));

    if (r == 0) {

      if (length_ < x.length_) r = -1;

      else if (length_ > x.length_) r = +1;

    }

    return r;

  }

 

  std::string as_string() const {

    // std::string doesn't like to take a NULL pointer even with a 0 size.

    return std::string(!empty() ? data() : "", size());

  }

 

  void CopyToString(std::string* target) const;

  void AppendToString(std::string* target) const;

 

  // Does "this" start with "x"

  bool starts_with(const StringPiece& x) const {

    return ((length_ >= x.length_) &&

            (wordmemcmp(ptr_, x.ptr_, x.length_) == 0));

  }

 

  // Does "this" end with "x"

  bool ends_with(const StringPiece& x) const {

    return ((length_ >= x.length_) &&

            (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));

  }

 

  // standard STL container boilerplate

  typedef char value_type;

  typedef const char* pointer;

  typedef const char& reference;

  typedef const char& const_reference;

  typedef ptrdiff_t difference_type;

  static const size_type npos;

  typedef const char* const_iterator;

  typedef const char* iterator;

  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

  typedef std::reverse_iterator<iterator> reverse_iterator;

  iterator begin() const { return ptr_; }

  iterator end() const { return ptr_ + length_; }

  const_reverse_iterator rbegin() const {

    return const_reverse_iterator(ptr_ + length_);

  }

  const_reverse_iterator rend() const {

    return const_reverse_iterator(ptr_);

  }

 

  size_type max_size() const { return length_; }

  size_type capacity() const { return length_; }

 

  size_type copy(char* buf, size_type n, size_type pos = 0) const;

 

  size_type find(const StringPiece& s, size_type pos = 0) const;

  size_type find(char c, size_type pos = 0) const;

  size_type rfind(const StringPiece& s, size_type pos = npos) const;

  size_type rfind(char c, size_type pos = npos) const;

 

  size_type find_first_of(const StringPiece& s, size_type pos = 0) const;

  size_type find_first_of(char c, size_type pos = 0) const {

    return find(c, pos);

  }

  size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const;

  size_type find_first_not_of(char c, size_type pos = 0) const;

  size_type find_last_of(const StringPiece& s, size_type pos = npos) const;

  size_type find_last_of(char c, size_type pos = npos) const {

    return rfind(c, pos);

  }

  size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const;

  size_type find_last_not_of(char c, size_type pos = npos) const;

 

  StringPiece substr(size_type pos, size_type n = npos) const;

 

  static int wordmemcmp(const char* p, const char* p2, size_type N) {

    return memcmp(p, p2, N);

  }

};

 

bool operator==(const StringPiece& x, const StringPiece& y);

 

inline bool operator!=(const StringPiece& x, const StringPiece& y) {

  return !(x == y);

}

 

inline bool operator<(const StringPiece& x, const StringPiece& y) {

  const int r = StringPiece::wordmemcmp(x.data(), y.data(),

                                        std::min(x.size(), y.size()));

  return ((r < 0) || ((r == 0) && (x.size() < y.size())));

}

 

inline bool operator>(const StringPiece& x, const StringPiece& y) {

  return y < x;

}

 

inline bool operator<=(const StringPiece& x, const StringPiece& y) {

  return !(x > y);

}

 

inline bool operator>=(const StringPiece& x, const StringPiece& y) {

  return !(x < y);

}

 

// allow StringPiece to be logged (needed for unit testing).

extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece);

std::ostream& operator<<(std::ostream& o, const StringPiece& piece) {
  o.write(piece.data(), static_cast<std::streamsize>(piece.size()));
  return o;
}
bool operator==(const StringPiece& x, const StringPiece& y) {
  if (x.size() != y.size())
    return false;
  return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
}
void StringPiece::CopyToString(std::string* target) const {
  target->assign(!empty() ? data() : "", size());
}
void StringPiece::AppendToString(std::string* target) const {
  if (!empty())
    target->append(data(), size());
}
size_type StringPiece::copy(char* buf, size_type n, size_type pos) const {
  size_type ret = std::min(length_ - pos, n);
  memcpy(buf, ptr_ + pos, ret);
  return ret;
}
size_type StringPiece::find(const StringPiece& s, size_type pos) const {
  if (pos > length_)
    return npos;
  const char* result = std::search(ptr_ + pos, ptr_ + length_,
                                   s.ptr_, s.ptr_ + s.length_);
  const size_type xpos = result - ptr_;
  return xpos + s.length_ <= length_ ? xpos : npos;
}
size_type StringPiece::find(char c, size_type pos) const {
  if (pos >= length_)
    return npos;
  const char* result = std::find(ptr_ + pos, ptr_ + length_, c);
  return result != ptr_ + length_ ? result - ptr_ : npos;
}
size_type StringPiece::rfind(const StringPiece& s, size_type pos) const {
  if (length_ < s.length_)
    return npos;
  if (s.empty())
    return std::min(length_, pos);
  const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
  const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
  return result != last ? result - ptr_ : npos;
}
size_type StringPiece::rfind(char c, size_type pos) const {
  if (length_ == 0)
    return npos;
  for (size_type i = std::min(pos, length_ - 1); ; --i) {
    if (ptr_[i] == c)
      return i;
    if (i == 0)
      break;
  }
  return npos;
}
// For each character in characters_wanted, sets the index corresponding
// to the ASCII code of that character to 1 in table.  This is used by
// the find_.*_of methods below to tell whether or not a character is in
// the lookup table in constant time.
// The argument `table' must be an array that is large enough to hold all
// the possible values of an unsigned char.  Thus it should be be declared
// as follows:
//   bool table[UCHAR_MAX + 1]
static inline void BuildLookupTable(const StringPiece& characters_wanted,
                                    bool* table) {
  const size_type length = characters_wanted.length();
  const char* const data = characters_wanted.data();
  for (size_type i = 0; i < length; ++i) {
    table[static_cast<unsigned char>(data[i])] = true;
  }
}
size_type StringPiece::find_first_of(const StringPiece& s,
                                     size_type pos) const {
  if (length_ == 0 || s.length_ == 0)
    return npos;
  // Avoid the cost of BuildLookupTable() for a single-character search.
  if (s.length_ == 1)
    return find_first_of(s.ptr_[0], pos);
  bool lookup[UCHAR_MAX + 1] = { false };
  BuildLookupTable(s, lookup);
  for (size_type i = pos; i < length_; ++i) {
    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
      return i;
    }
  }
  return npos;
}
size_type StringPiece::find_first_not_of(const StringPiece& s,
                                         size_type pos) const {
  if (length_ == 0)
    return npos;
  if (s.length_ == 0)
    return 0;
  // Avoid the cost of BuildLookupTable() for a single-character search.
  if (s.length_ == 1)
    return find_first_not_of(s.ptr_[0], pos);
  bool lookup[UCHAR_MAX + 1] = { false };
  BuildLookupTable(s, lookup);
  for (size_type i = pos; i < length_; ++i) {
    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
      return i;
    }
  }
  return npos;
}
size_type StringPiece::find_first_not_of(char c, size_type pos) const {
  if (length_ == 0)
    return npos;
  for (; pos < length_; ++pos) {
    if (ptr_[pos] != c) {
      return pos;
    }
  }
  return npos;
}
size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const {
  if (length_ == 0 || s.length_ == 0)
    return npos;
  // Avoid the cost of BuildLookupTable() for a single-character search.
  if (s.length_ == 1)
    return find_last_of(s.ptr_[0], pos);
  bool lookup[UCHAR_MAX + 1] = { false };
  BuildLookupTable(s, lookup);
  for (size_type i = std::min(pos, length_ - 1); ; --i) {
    if (lookup[static_cast<unsigned char>(ptr_[i])])
      return i;
    if (i == 0)
      break;
  }
  return npos;
}
size_type StringPiece::find_last_not_of(const StringPiece& s,
                                        size_type pos) const {
  if (length_ == 0)
    return npos;
  size_type i = std::min(pos, length_ - 1);
  if (s.length_ == 0)
    return i;
  // Avoid the cost of BuildLookupTable() for a single-character search.
  if (s.length_ == 1)
    return find_last_not_of(s.ptr_[0], pos);
  bool lookup[UCHAR_MAX + 1] = { false };
  BuildLookupTable(s, lookup);
  for (; ; --i) {
    if (!lookup[static_cast<unsigned char>(ptr_[i])])
      return i;
    if (i == 0)
      break;
  }
  return npos;
}
size_type StringPiece::find_last_not_of(char c, size_type pos) const {
  if (length_ == 0)
    return npos;
  for (size_type i = std::min(pos, length_ - 1); ; --i) {
    if (ptr_[i] != c)
      return i;
    if (i == 0)
      break;
  }
  return npos;
}
StringPiece StringPiece::substr(size_type pos, size_type n) const {
  if (pos > length_) pos = length_;
  if (n > length_ - pos) n = length_ - pos;
  return StringPiece(ptr_ + pos, n);
}
const StringPiece::size_type StringPiece::npos = size_type(-1);

原创粉丝点击