Coverage Report

Created: 2024-11-21 12:31

/root/doris/be/src/gutil/strings/stringpiece.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2001, Google Inc.  All rights reserved.
2
// Maintainer: mec@google.com (Michael Chastain)
3
//
4
// A StringPiece points to part or all of a string, Cord, double-quoted string
5
// literal, or other string-like object.  A StringPiece does *not* own the
6
// string to which it points.  A StringPiece is not null-terminated.
7
//
8
// You can use StringPiece as a function or method parameter.  A StringPiece
9
// parameter can receive a double-quoted string literal argument, a "const
10
// char*" argument, a string argument, or a StringPiece argument with no data
11
// copying.  Systematic use of StringPiece for arguments reduces data
12
// copies and strlen() calls.
13
//
14
// You may pass a StringPiece argument by value or const reference.
15
// Passing by value generates slightly smaller code.
16
//   void MyFunction(const StringPiece& arg);
17
//   // Slightly better, but same lifetime requirements as const-ref parameter:
18
//   void MyFunction(StringPiece arg);
19
//
20
// StringPiece is also suitable for local variables if you know that
21
// the lifetime of the underlying object is longer than the lifetime
22
// of your StringPiece variable.
23
//
24
// Beware of binding a StringPiece to a temporary:
25
//   StringPiece sp = obj.MethodReturningString();  // BAD: lifetime problem
26
//
27
// This code is okay:
28
//   string str = obj.MethodReturningString();  // str owns its contents
29
//   StringPiece sp(str);  // GOOD, although you may not need sp at all
30
//
31
// StringPiece is sometimes a poor choice for a return value and usually a poor
32
// choice for a data member.  If you do use a StringPiece this way, it is your
33
// responsibility to ensure that the object pointed to by the StringPiece
34
// outlives the StringPiece.
35
//
36
// A StringPiece may represent just part of a string; thus the name "Piece".
37
// For example, when splitting a string, vector<StringPiece> is a natural data
38
// type for the output.  For another example, a Cord is a non-contiguous,
39
// potentially very long string-like object.  The Cord class has an interface
40
// that iteratively provides StringPiece objects that point to the
41
// successive pieces of a Cord object.
42
//
43
// A StringPiece is not null-terminated.  If you write code that scans a
44
// StringPiece, you must check its length before reading any characters.
45
// Common idioms that work on null-terminated strings do not work on
46
// StringPiece objects.
47
//
48
// There are several ways to create a null StringPiece:
49
//   StringPiece()
50
//   StringPiece(NULL)
51
//   StringPiece(NULL, 0)
52
// For all of the above, sp.data() == NULL, sp.length() == 0,
53
// and sp.empty() == true.  Also, if you create a StringPiece with
54
// a non-NULL pointer then sp.data() != non-NULL.  Once created,
55
// sp.data() will stay either NULL or not-NULL, except if you call
56
// sp.clear() or sp.set().
57
//
58
// Thus, you can use StringPiece(NULL) to signal an out-of-band value
59
// that is different from other StringPiece values.  This is similar
60
// to the way that const char* p1 = NULL; is different from
61
// const char* p2 = "";.
62
//
63
// There are many ways to create an empty StringPiece:
64
//   StringPiece()
65
//   StringPiece(NULL)
66
//   StringPiece(NULL, 0)
67
//   StringPiece("")
68
//   StringPiece("", 0)
69
//   StringPiece("abcdef", 0)
70
//   StringPiece("abcdef"+6, 0)
71
// For all of the above, sp.length() will be 0 and sp.empty() will be true.
72
// For some empty StringPiece values, sp.data() will be NULL.
73
// For some empty StringPiece values, sp.data() will not be NULL.
74
//
75
// Be careful not to confuse: null StringPiece and empty StringPiece.
76
// The set of empty StringPieces properly includes the set of null StringPieces.
77
// That is, every null StringPiece is an empty StringPiece,
78
// but some non-null StringPieces are empty Stringpieces too.
79
//
80
// All empty StringPiece values compare equal to each other.
81
// Even a null StringPieces compares equal to a non-null empty StringPiece:
82
//  StringPiece() == StringPiece("", 0)
83
//  StringPiece(NULL) == StringPiece("abc", 0)
84
//  StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0)
85
//
86
// Look carefully at this example:
87
//   StringPiece("") == NULL
88
// True or false?  TRUE, because StringPiece::operator== converts
89
// the right-hand side from NULL to StringPiece(NULL),
90
// and then compares two zero-length spans of characters.
91
// However, we are working to make this example produce a compile error.
92
//
93
// Suppose you want to write:
94
//   bool TestWhat?(StringPiece sp) { return sp == NULL; }  // BAD
95
// Do not do that.  Write one of these instead:
96
//   bool TestNull(StringPiece sp) { return sp.data() == NULL; }
97
//   bool TestEmpty(StringPiece sp) { return sp.empty(); }
98
// The intent of TestWhat? is unclear.  Did you mean TestNull or TestEmpty?
99
// Right now, TestWhat? behaves likes TestEmpty.
100
// We are working to make TestWhat? produce a compile error.
101
// TestNull is good to test for an out-of-band signal.
102
// TestEmpty is good to test for an empty StringPiece.
103
//
104
// Caveats (again):
105
// (1) The lifetime of the pointed-to string (or piece of a string)
106
//     must be longer than the lifetime of the StringPiece.
107
// (2) There may or may not be a '\0' character after the end of
108
//     StringPiece data.
109
// (3) A null StringPiece is empty.
110
//     An empty StringPiece may or may not be a null StringPiece.
111
112
#pragma once
113
114
#include <assert.h>
115
#include <stddef.h>
116
#include <string.h>
117
118
#include <cstddef>
119
#include <iosfwd>
120
#include <iterator>
121
#include <limits> // IWYU pragma: keep
122
#include <string>
123
#include <string_view>
124
125
class StringPiece {
126
private:
127
    const char* ptr_ = nullptr;
128
    int length_;
129
130
public:
131
    // We provide non-explicit singleton constructors so users can pass
132
    // in a "const char*" or a "string" wherever a "StringPiece" is
133
    // expected.
134
    //
135
    // Style guide exception granted:
136
    // http://goto/style-guide-exception-20978288
137
2.02k
    StringPiece() : ptr_(NULL), length_(0) {}
138
    StringPiece(const char* str) // NOLINT(runtime/explicit)
139
116k
            : ptr_(str), length_(0) {
140
116k
        if (str != NULL) {
141
116k
            size_t length = strlen(str);
142
116k
            assert(length <= static_cast<size_t>(std::numeric_limits<int>::max()));
143
0
            length_ = static_cast<int>(length);
144
116k
        }
145
116k
    }
146
    StringPiece(const std::string& str) // NOLINT(runtime/explicit)
147
4.54k
            : ptr_(str.data()), length_(0) {
148
4.54k
        size_t length = str.size();
149
4.54k
        assert(length <= static_cast<size_t>(std::numeric_limits<int>::max()));
150
0
        length_ = static_cast<int>(length);
151
4.54k
    }
152
3.04k
    StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { assert(len >= 0); }
153
154
    // Substring of another StringPiece.
155
    // pos must be non-negative and <= x.length().
156
    StringPiece(StringPiece x, int pos);
157
    // Substring of another StringPiece.
158
    // pos must be non-negative and <= x.length().
159
    // len must be non-negative and will be pinned to at most x.length() - pos.
160
    StringPiece(StringPiece x, int pos, int len);
161
162
    // data() may return a pointer to a buffer with embedded NULs, and the
163
    // returned buffer may or may not be null terminated.  Therefore it is
164
    // typically a mistake to pass data() to a routine that expects a NUL
165
    // terminated string.
166
12.0k
    const char* data() const { return ptr_; }
167
2.86M
    int size() const { return length_; }
168
2.29k
    int length() const { return length_; }
169
5.63k
    bool empty() const { return length_ == 0; }
170
171
0
    void clear() {
172
0
        ptr_ = NULL;
173
0
        length_ = 0;
174
0
    }
175
176
7.94k
    void set(const char* data, int len) {
177
7.94k
        assert(len >= 0);
178
0
        ptr_ = data;
179
7.94k
        length_ = len;
180
7.94k
    }
181
182
0
    void set(const char* str) {
183
0
        ptr_ = str;
184
0
        if (str != NULL)
185
0
            length_ = static_cast<int>(strlen(str));
186
0
        else
187
0
            length_ = 0;
188
0
    }
189
0
    void set(const void* data, int len) {
190
0
        ptr_ = reinterpret_cast<const char*>(data);
191
0
        length_ = len;
192
0
    }
193
194
4.44M
    char operator[](int i) const {
195
4.44M
        assert(0 <= i);
196
0
        assert(i < length_);
197
0
        return ptr_[i];
198
4.44M
    }
199
200
2.96k
    void remove_prefix(int n) {
201
2.96k
        assert(length_ >= n);
202
0
        ptr_ += n;
203
2.96k
        length_ -= n;
204
2.96k
    }
205
206
2
    void remove_suffix(int n) {
207
2
        assert(length_ >= n);
208
0
        length_ -= n;
209
2
    }
210
211
    // returns {-1, 0, 1}
212
0
    int compare(StringPiece x) const {
213
0
        const int min_size = length_ < x.length_ ? length_ : x.length_;
214
0
        int r = memcmp(ptr_, x.ptr_, min_size);
215
0
        if (r < 0) return -1;
216
0
        if (r > 0) return 1;
217
0
        if (length_ < x.length_) return -1;
218
0
        if (length_ > x.length_) return 1;
219
0
        return 0;
220
0
    }
221
222
736
    std::string as_string() const { return ToString(); }
223
    // We also define ToString() here, since many other string-like
224
    // interfaces name the routine that converts to a C++ string
225
    // "ToString", and it's confusing to have the method that does that
226
    // for a StringPiece be called "as_string()".  We also leave the
227
    // "as_string()" method defined here for existing code.
228
3.87k
    std::string ToString() const {
229
3.87k
        if (ptr_ == NULL) return std::string();
230
3.86k
        return std::string(data(), size());
231
3.87k
    }
232
233
    void CopyToString(std::string* target) const;
234
    void AppendToString(std::string* target) const;
235
236
368
    bool starts_with(StringPiece x) const {
237
368
        return (length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0);
238
368
    }
239
240
368
    bool ends_with(StringPiece x) const {
241
368
        return ((length_ >= x.length_) &&
242
368
                (memcmp(ptr_ + (length_ - x.length_), x.ptr_, x.length_) == 0));
243
368
    }
244
245
    // standard STL container boilerplate
246
    typedef char value_type;
247
    typedef const char* pointer;
248
    typedef const char& reference;
249
    typedef const char& const_reference;
250
    typedef size_t size_type;
251
    typedef ptrdiff_t difference_type;
252
    static const size_type npos;
253
    typedef const char* const_iterator;
254
    typedef const char* iterator;
255
    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
256
    typedef std::reverse_iterator<iterator> reverse_iterator;
257
17.7k
    iterator begin() const { return ptr_; }
258
19.0k
    iterator end() const { return ptr_ + length_; }
259
0
    const_reverse_iterator rbegin() const { return const_reverse_iterator(ptr_ + length_); }
260
0
    const_reverse_iterator rend() const { return const_reverse_iterator(ptr_); }
261
    // STLS says return size_type, but Google says return int
262
0
    int max_size() const { return length_; }
263
0
    int capacity() const { return length_; }
264
265
    // cpplint.py emits a false positive [build/include_what_you_use]
266
    int copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT
267
268
    bool contains(StringPiece s) const;
269
270
    int find(StringPiece s, size_type pos = 0) const;
271
    int find(char c, size_type pos = 0) const;
272
    int rfind(StringPiece s, size_type pos = npos) const;
273
    int rfind(char c, size_type pos = npos) const;
274
275
    int find_first_of(StringPiece s, size_type pos = 0) const;
276
0
    int find_first_of(char c, size_type pos = 0) const { return find(c, pos); }
277
    int find_first_not_of(StringPiece s, size_type pos = 0) const;
278
    int find_first_not_of(char c, size_type pos = 0) const;
279
    int find_last_of(StringPiece s, size_type pos = npos) const;
280
0
    int find_last_of(char c, size_type pos = npos) const { return rfind(c, pos); }
281
    int find_last_not_of(StringPiece s, size_type pos = npos) const;
282
    int find_last_not_of(char c, size_type pos = npos) const;
283
284
    StringPiece substr(size_type pos, size_type n = npos) const;
285
};
286
287
// This large function is defined inline so that in a fairly common case where
288
// one of the arguments is a literal, the compiler can elide a lot of the
289
// following comparisons.
290
0
inline bool operator==(StringPiece x, StringPiece y) {
291
0
    int len = x.size();
292
0
    if (len != y.size()) {
293
0
        return false;
294
0
    }
295
296
0
    return x.data() == y.data() || len <= 0 || 0 == memcmp(x.data(), y.data(), len);
297
0
}
298
299
0
inline bool operator!=(StringPiece x, StringPiece y) {
300
0
    return !(x == y);
301
0
}
302
303
0
inline bool operator<(StringPiece x, StringPiece y) {
304
0
    const int min_size = x.size() < y.size() ? x.size() : y.size();
305
0
    const int r = memcmp(x.data(), y.data(), min_size);
306
0
    return (r < 0) || (r == 0 && x.size() < y.size());
307
0
}
308
309
0
inline bool operator>(StringPiece x, StringPiece y) {
310
0
    return y < x;
311
0
}
312
313
0
inline bool operator<=(StringPiece x, StringPiece y) {
314
0
    return !(x > y);
315
0
}
316
317
0
inline bool operator>=(StringPiece x, StringPiece y) {
318
0
    return !(x < y);
319
0
}
320
321
// allow StringPiece to be logged
322
extern std::ostream& operator<<(std::ostream& o, StringPiece piece);