1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format
2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2008 Google Inc.  All rights reserved.
3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/
4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without
6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are
7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met:
8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//     * Redistributions of source code must retain the above copyright
10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer.
11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//     * Redistributions in binary form must reproduce the above
12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer
13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the
14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution.
15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//     * Neither the name of Google Inc. nor the names of its
16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from
17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission.
18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/stubs/stringpiece.h>
31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <algorithm>
34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <climits>
35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string>
36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <ostream>
37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace google {
39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace protobuf {
40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstd::ostream& operator<<(std::ostream& o, StringPiece piece) {
41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  o.write(piece.data(), piece.size());
42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return o;
43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Out-of-line error path.
46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerStringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos)
51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    : ptr_(x.ptr_ + pos), length_(x.length_ - pos) {
52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GOOGLE_DCHECK_LE(0, pos);
53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GOOGLE_DCHECK_LE(pos, x.length_);
54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerStringPiece::StringPiece(StringPiece x,
57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         stringpiece_ssize_type pos,
58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         stringpiece_ssize_type len)
59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) {
60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GOOGLE_DCHECK_LE(0, pos);
61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GOOGLE_DCHECK_LE(pos, x.length_);
62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GOOGLE_DCHECK_GE(len, 0);
63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid StringPiece::CopyToString(string* target) const {
66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  target->assign(ptr_, length_);
67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid StringPiece::AppendToString(string* target) const {
70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  target->append(ptr_, length_);
71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool StringPiece::Consume(StringPiece x) {
74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (starts_with(x)) {
75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ptr_ += x.length_;
76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    length_ -= x.length_;
77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool StringPiece::ConsumeFromEnd(StringPiece x) {
83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ends_with(x)) {
84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    length_ -= x.length_;
85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::copy(char* buf,
91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                         size_type n,
92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                         size_type pos) const {
93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  stringpiece_ssize_type ret = std::min(length_ - pos, n);
94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(buf, ptr_ + pos, ret);
95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool StringPiece::contains(StringPiece s) const {
99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return find(s, 0) != npos;
100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0 || pos > static_cast<size_type>(length_)) {
104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (length_ == 0 && pos == 0 && s.length_ == 0) return 0;
105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return npos;
106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *result = std::search(ptr_ + pos, ptr_ + length_,
108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                   s.ptr_, s.ptr_ + s.length_);
109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return result == ptr_ + length_ ? npos : result - ptr_;
110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return npos;
115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char* result = static_cast<const char*>(
117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      memchr(ptr_ + pos, c, length_ - pos));
118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return result != NULL ? result - ptr_ : npos;
119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ < s.length_) return npos;
123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t ulen = length_;
124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ == 0) return std::min(ulen, pos);
125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_;
127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return result != last ? result - ptr_ : npos;
129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Search range is [0..pos] inclusive.  If pos == npos, search everything.
132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Note: memrchr() is not available on Windows.
134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0) return npos;
135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (stringpiece_ssize_type i =
136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      std::min(pos, static_cast<size_type>(length_ - 1));
137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       i >= 0; --i) {
138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ptr_[i] == c) {
139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return i;
140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// For each character in characters_wanted, sets the index corresponding
146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// to the ASCII code of that character to 1 in table.  This is used by
147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// the find_.*_of methods below to tell whether or not a character is in
148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// the lookup table in constant time.
149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// The argument `table' must be an array that is large enough to hold all
150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// the possible values of an unsigned char.  Thus it should be be declared
151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// as follows:
152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   bool table[UCHAR_MAX + 1]
153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic inline void BuildLookupTable(StringPiece characters_wanted,
154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    bool* table) {
155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const stringpiece_ssize_type length = characters_wanted.length();
156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char* const data = characters_wanted.data();
157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (stringpiece_ssize_type i = 0; i < length; ++i) {
158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    table[static_cast<unsigned char>(data[i])] = true;
159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                  size_type pos) const {
164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0 || s.length_ <= 0) {
165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return npos;
166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Avoid the cost of BuildLookupTable() for a single-character search.
168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool lookup[UCHAR_MAX + 1] = { false };
171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  BuildLookupTable(s, lookup);
172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return i;
175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                      size_type pos) const {
182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0) return npos;
183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ <= 0) return 0;
184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Avoid the cost of BuildLookupTable() for a single-character search.
185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool lookup[UCHAR_MAX + 1] = { false };
188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  BuildLookupTable(s, lookup);
189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return i;
192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find_first_not_of(char c,
198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                      size_type pos) const {
199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0) return npos;
200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; pos < static_cast<size_type>(length_); ++pos) {
202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ptr_[pos] != c) {
203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return pos;
204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                 size_type pos) const {
211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0 || s.length_ <= 0) return npos;
212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Avoid the cost of BuildLookupTable() for a single-character search.
213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool lookup[UCHAR_MAX + 1] = { false };
216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  BuildLookupTable(s, lookup);
217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (stringpiece_ssize_type i =
218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return i;
221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                     size_type pos) const {
228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0) return npos;
229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1));
231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ <= 0) return i;
232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Avoid the cost of BuildLookupTable() for a single-character search.
234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool lookup[UCHAR_MAX + 1] = { false };
237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  BuildLookupTable(s, lookup);
238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; i >= 0; --i) {
239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return i;
241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstringpiece_ssize_type StringPiece::find_last_not_of(char c,
247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                     size_type pos) const {
248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (length_ <= 0) return npos;
249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (stringpiece_ssize_type i =
251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ptr_[i] != c) {
253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return i;
254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return npos;
257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerStringPiece StringPiece::substr(size_type pos, size_type n) const {
260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (pos > length_) pos = length_;
261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (n > length_ - pos) n = length_ - pos;
262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return StringPiece(ptr_ + pos, n);
263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst StringPiece::size_type StringPiece::npos = size_type(-1);
266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}  // namespace protobuf
268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}  // namespace google
269