string_piece.h revision 776ca3085c44e6570813270df75278849c37d400
1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4// Copied from strings/stringpiece.h with modifications
5//
6// A string-like object that points to a sized piece of memory.
7//
8// Functions or methods may use const StringPiece& parameters to accept either
9// a "const char*" or a "string" value that will be implicitly converted to
10// a StringPiece.  The implicit conversion means that it is often appropriate
11// to include this .h file in other files rather than forward-declaring
12// StringPiece as would be appropriate for most other Google classes.
13//
14// Systematic usage of StringPiece is encouraged as it will reduce unnecessary
15// conversions from "const char*" to "string" and back again.
16//
17
18#ifndef BASE_STRING_PIECE_H_
19#define BASE_STRING_PIECE_H_
20#pragma once
21
22#include <stddef.h>
23#include <string.h>
24
25#include <string>
26
27//#include "base/base_api.h"
28//#include "base/basictypes.h"
29
30#define STRING_PIECE(s) StringPiece(s, sizeof(s) - 1)
31
32class StringPiece {
33 public:
34  // standard STL container boilerplate
35  typedef size_t size_type;
36  typedef char value_type;
37  typedef const char* pointer;
38  typedef const char& reference;
39  typedef const char& const_reference;
40  typedef ptrdiff_t difference_type;
41  typedef const char* const_iterator;
42  typedef const char* iterator;
43  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
44  typedef std::reverse_iterator<iterator> reverse_iterator;
45
46  static const size_type npos;
47
48 public:
49  // We provide non-explicit singleton constructors so users can pass
50  // in a "const char*" or a "string" wherever a "StringPiece" is
51  // expected.
52  StringPiece() : ptr_(NULL), length_(0) { }
53  StringPiece(const char* str)
54    : ptr_(str), length_((str == NULL) ? 0 : strlen(str)) { }
55  StringPiece(const std::string& str)
56    : ptr_(str.data()), length_(str.size()) { }
57  StringPiece(const char* offset, size_type len)
58    : ptr_(offset), length_(len) { }
59
60  // data() may return a pointer to a buffer with embedded NULs, and the
61  // returned buffer may or may not be null terminated.  Therefore it is
62  // typically a mistake to pass data() to a routine that expects a NUL
63  // terminated string.
64  const char* data() const { return ptr_; }
65  size_type size() const { return length_; }
66  size_type length() const { return length_; }
67  bool empty() const { return length_ == 0; }
68
69  void clear() {
70    ptr_ = NULL;
71    length_ = 0;
72  }
73  void set(const char* data, size_type len) {
74    ptr_ = data;
75    length_ = len;
76  }
77  void set(const char* str) {
78    ptr_ = str;
79    length_ = str ? strlen(str) : 0;
80  }
81  void set(const void* data, size_type len) {
82    ptr_ = reinterpret_cast<const char*>(data);
83    length_ = len;
84  }
85
86  char operator[](size_type i) const { return ptr_[i]; }
87
88  void remove_prefix(size_type n) {
89    ptr_ += n;
90    length_ -= n;
91  }
92
93  void remove_suffix(size_type n) {
94    length_ -= n;
95  }
96
97  int compare(const StringPiece& x) const {
98    int r = wordmemcmp(
99        ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_));
100    if (r == 0) {
101      if (length_ < x.length_) r = -1;
102      else if (length_ > x.length_) r = +1;
103    }
104    return r;
105  }
106
107  std::string as_string() const {
108    // std::string doesn't like to take a NULL pointer even with a 0 size.
109    return std::string(!empty() ? data() : "", size());
110  }
111
112  void CopyToString(std::string* target) const;
113  void AppendToString(std::string* target) const;
114
115  // Does "this" start with "x"
116  bool starts_with(const StringPiece& x) const {
117    return ((length_ >= x.length_) &&
118            (wordmemcmp(ptr_, x.ptr_, x.length_) == 0));
119  }
120
121  // Does "this" end with "x"
122  bool ends_with(const StringPiece& x) const {
123    return ((length_ >= x.length_) &&
124            (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
125  }
126
127  iterator begin() const { return ptr_; }
128  iterator end() const { return ptr_ + length_; }
129  const_reverse_iterator rbegin() const {
130    return const_reverse_iterator(ptr_ + length_);
131  }
132  const_reverse_iterator rend() const {
133    return const_reverse_iterator(ptr_);
134  }
135
136  size_type max_size() const { return length_; }
137  size_type capacity() const { return length_; }
138
139  size_type copy(char* buf, size_type n, size_type pos = 0) const;
140
141  size_type find(const StringPiece& s, size_type pos = 0) const;
142  size_type find(char c, size_type pos = 0) const;
143  size_type rfind(const StringPiece& s, size_type pos = npos) const;
144  size_type rfind(char c, size_type pos = npos) const;
145
146  size_type find_first_of(const StringPiece& s, size_type pos = 0) const;
147  size_type find_first_of(char c, size_type pos = 0) const {
148    return find(c, pos);
149  }
150  size_type find_first_not_of(const StringPiece& s, size_type pos = 0) const;
151  size_type find_first_not_of(char c, size_type pos = 0) const;
152  size_type find_last_of(const StringPiece& s, size_type pos = npos) const;
153  size_type find_last_of(char c, size_type pos = npos) const {
154    return rfind(c, pos);
155  }
156  size_type find_last_not_of(const StringPiece& s, size_type pos = npos) const;
157  size_type find_last_not_of(char c, size_type pos = npos) const;
158
159  StringPiece substr(size_type pos, size_type n = npos) const;
160
161  static int wordmemcmp(const char* p, const char* p2, size_type N) {
162    return memcmp(p, p2, N);
163  }
164
165  // kati specific functions will follow.
166
167  char get(size_type i) const { return i < length_ ? ptr_[i] : 0; }
168
169  StringPiece StripLeftSpaces() const;
170  StringPiece StripRightSpaces() const;
171  StringPiece StripSpaces() const;
172
173 private:
174  const char*   ptr_;
175  size_type     length_;
176};
177
178bool operator==(const StringPiece& x, const StringPiece& y);
179
180inline bool operator!=(const StringPiece& x, const StringPiece& y) {
181  return !(x == y);
182}
183
184inline bool operator<(const StringPiece& x, const StringPiece& y) {
185  const int r = StringPiece::wordmemcmp(
186      x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size()));
187  return ((r < 0) || ((r == 0) && (x.size() < y.size())));
188}
189
190inline bool operator>(const StringPiece& x, const StringPiece& y) {
191  return y < x;
192}
193
194inline bool operator<=(const StringPiece& x, const StringPiece& y) {
195  return !(x > y);
196}
197
198inline bool operator>=(const StringPiece& x, const StringPiece& y) {
199  return !(x < y);
200}
201
202namespace std {
203template<> struct hash<StringPiece> {
204  size_t operator()(const StringPiece& s) const {
205    size_t result = 0;
206    for (char c : s) {
207      result = (result * 131) + c;
208    }
209    return result;
210  }
211};
212
213}
214
215#define SPF(s) static_cast<int>((s).size()), (s).data()
216
217#endif  // BASE_STRING_PIECE_H_
218