1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 // StringPiece is a simple structure containing a pointer into some external
17 // storage and a size. The user of a StringPiece must ensure that the slice
18 // is not used after the corresponding external storage has been
19 // deallocated.
20 //
21 // Multiple threads can invoke const methods on a StringPiece without
22 // external synchronization, but if any of the threads may call a
23 // non-const method, all threads accessing the same StringPiece must use
24 // external synchronization.
25
26 #ifndef TENSORFLOW_LIB_CORE_STRINGPIECE_H_
27 #define TENSORFLOW_LIB_CORE_STRINGPIECE_H_
28
29 #include <assert.h>
30 #include <stddef.h>
31 #include <string.h>
32 #include <iosfwd>
33 #include <string>
34 #include "tensorflow/core/platform/types.h"
35
36 namespace tensorflow {
37
38 struct StringPieceHasher;
39
40 class StringPiece {
41 public:
42 typedef size_t size_type;
43
44 // Create an empty slice.
StringPiece()45 StringPiece() : data_(nullptr), size_(0) {}
46
47 // Create a slice that refers to d[0,n-1].
StringPiece(const char * d,size_t n)48 StringPiece(const char* d, size_t n) : data_(d), size_(n) {}
49
50 // Create a slice that refers to the contents of "s"
StringPiece(const string & s)51 StringPiece(const string& s) : data_(s.data()), size_(s.size()) {}
52
53 // Create a slice that refers to s[0,strlen(s)-1]
StringPiece(const char * s)54 StringPiece(const char* s) : data_(s), size_(strlen(s)) {}
55
56 // Return a pointer to the beginning of the referenced data
data()57 const char* data() const { return data_; }
58
59 // Return the length (in bytes) of the referenced data
size()60 size_t size() const { return size_; }
61
62 // Return true iff the length of the referenced data is zero
empty()63 bool empty() const { return size_ == 0; }
64
65 typedef const char* const_iterator;
66 typedef const char* iterator;
begin()67 iterator begin() const { return data_; }
end()68 iterator end() const { return data_ + size_; }
69
70 static const size_t npos;
71
72 // Return the ith byte in the referenced data.
73 // REQUIRES: n < size()
74 char operator[](size_t n) const {
75 assert(n < size());
76 return data_[n];
77 }
78
79 // Drop the first "n" bytes from this slice.
remove_prefix(size_t n)80 void remove_prefix(size_t n) {
81 assert(n <= size());
82 data_ += n;
83 size_ -= n;
84 }
85
remove_suffix(size_t n)86 void remove_suffix(size_t n) {
87 assert(size_ >= n);
88 size_ -= n;
89 }
90
91 size_t find(char c, size_t pos = 0) const;
92 size_t rfind(char c, size_t pos = npos) const;
93 bool contains(StringPiece s) const;
94
95 // Checks whether StringPiece starts with x and if so advances the beginning
96 // of it to past the match. It's basically a shortcut for starts_with
97 // followed by remove_prefix.
Consume(StringPiece x)98 bool Consume(StringPiece x) {
99 if (starts_with(x)) {
100 remove_prefix(x.size_);
101 return true;
102 }
103 return false;
104 }
105
106 StringPiece substr(size_t pos, size_t n = npos) const;
107
108 // Return a string that contains the copy of the referenced data.
ToString()109 std::string ToString() const { return std::string(data_, size_); }
110
111 // Three-way comparison. Returns value:
112 // < 0 iff "*this" < "b",
113 // == 0 iff "*this" == "b",
114 // > 0 iff "*this" > "b"
115 int compare(StringPiece b) const;
116
117 // Return true iff "x" is a prefix of "*this"
starts_with(StringPiece x)118 bool starts_with(StringPiece x) const {
119 return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
120 }
121 // Return true iff "x" is a suffix of "*this"
ends_with(StringPiece x)122 bool ends_with(StringPiece x) const {
123 return ((size_ >= x.size_) &&
124 (memcmp(data_ + (size_ - x.size_), x.data_, x.size_) == 0));
125 }
126
127 private:
128 const char* data_;
129 size_t size_;
130
131 // Intentionally copyable
132 };
133
134 struct StringPieceHasher {
135 size_t operator()(StringPiece s) const;
136 };
137
138 inline bool operator==(StringPiece x, StringPiece y) {
139 return ((x.size() == y.size()) &&
140 (memcmp(x.data(), y.data(), x.size()) == 0));
141 }
142
143 inline bool operator!=(StringPiece x, StringPiece y) { return !(x == y); }
144
145 inline bool operator<(StringPiece x, StringPiece y) { return x.compare(y) < 0; }
146 inline bool operator>(StringPiece x, StringPiece y) { return x.compare(y) > 0; }
147 inline bool operator<=(StringPiece x, StringPiece y) {
148 return x.compare(y) <= 0;
149 }
150 inline bool operator>=(StringPiece x, StringPiece y) {
151 return x.compare(y) >= 0;
152 }
153
compare(StringPiece b)154 inline int StringPiece::compare(StringPiece b) const {
155 const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
156 int r = memcmp(data_, b.data_, min_len);
157 if (r == 0) {
158 if (size_ < b.size_)
159 r = -1;
160 else if (size_ > b.size_)
161 r = +1;
162 }
163 return r;
164 }
165
166 // allow StringPiece to be logged
167 extern std::ostream& operator<<(std::ostream& o, tensorflow::StringPiece piece);
168
169 } // namespace tensorflow
170
171 #endif // TENSORFLOW_LIB_CORE_STRINGPIECE_H_
172