1/*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19#ifndef GRPCPP_SUPPORT_STRING_REF_H
20#define GRPCPP_SUPPORT_STRING_REF_H
21
22#include <string.h>
23
24#include <algorithm>
25#include <iosfwd>
26#include <iostream>
27#include <iterator>
28
29#include <grpcpp/support/config.h>
30
31namespace grpc {
32
33/// This class is a non owning reference to a string.
34///
35/// It should be a strict subset of the upcoming std::string_ref.
36///
37/// \see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
38///
39/// The constexpr is dropped or replaced with const for legacy compiler
40/// compatibility.
41class string_ref {
42 public:
43 /// types
44 typedef const char* const_iterator;
45 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
46
47 /// constants
48 const static size_t npos;
49
50 /// construct/copy.
51 string_ref() : data_(nullptr), length_(0) {}
52 string_ref(const string_ref& other)
53 : data_(other.data_), length_(other.length_) {}
54 // NOLINTNEXTLINE(bugprone-unhandled-self-assignment)
55 string_ref& operator=(const string_ref& rhs) {
56 data_ = rhs.data_;
57 length_ = rhs.length_;
58 return *this;
59 }
60
61 /* NOLINTNEXTLINE(google-explicit-constructor) */
62 string_ref(const char* s) : data_(s), length_(strlen(s: s)) {}
63 string_ref(const char* s, size_t l) : data_(s), length_(l) {}
64 /* NOLINTNEXTLINE(google-explicit-constructor) */
65 string_ref(const std::string& s) : data_(s.data()), length_(s.length()) {}
66
67 /// iterators
68 const_iterator begin() const { return data_; }
69 const_iterator end() const { return data_ + length_; }
70 const_iterator cbegin() const { return data_; }
71 const_iterator cend() const { return data_ + length_; }
72 const_reverse_iterator rbegin() const {
73 return const_reverse_iterator(end());
74 }
75 const_reverse_iterator rend() const {
76 return const_reverse_iterator(begin());
77 }
78 const_reverse_iterator crbegin() const {
79 return const_reverse_iterator(end());
80 }
81 const_reverse_iterator crend() const {
82 return const_reverse_iterator(begin());
83 }
84
85 /// capacity
86 size_t size() const { return length_; }
87 size_t length() const { return length_; }
88 size_t max_size() const { return length_; }
89 bool empty() const { return length_ == 0; }
90
91 /// element access
92 const char* data() const { return data_; }
93
94 /// string operations
95 int compare(string_ref x) const {
96 size_t min_size = length_ < x.length_ ? length_ : x.length_;
97 int r = memcmp(s1: data_, s2: x.data_, n: min_size);
98 if (r < 0) return -1;
99 if (r > 0) return 1;
100 if (length_ < x.length_) return -1;
101 if (length_ > x.length_) return 1;
102 return 0;
103 }
104
105 bool starts_with(string_ref x) const {
106 return length_ >= x.length_ && (memcmp(s1: data_, s2: x.data_, n: x.length_) == 0);
107 }
108
109 bool ends_with(string_ref x) const {
110 return length_ >= x.length_ &&
111 (memcmp(s1: data_ + (length_ - x.length_), s2: x.data_, n: x.length_) == 0);
112 }
113
114 size_t find(string_ref s) const {
115 auto it = std::search(first1: cbegin(), last1: cend(), first2: s.cbegin(), last2: s.cend());
116 return it == cend() ? npos : std::distance(first: cbegin(), last: it);
117 }
118
119 size_t find(char c) const {
120 auto it = std::find(first: cbegin(), last: cend(), val: c);
121 return it == cend() ? npos : std::distance(first: cbegin(), last: it);
122 }
123
124 string_ref substr(size_t pos, size_t n = npos) const {
125 if (pos > length_) pos = length_;
126 if (n > (length_ - pos)) n = length_ - pos;
127 return string_ref(data_ + pos, n);
128 }
129
130 private:
131 const char* data_;
132 size_t length_;
133};
134
135/// Comparison operators
136inline bool operator==(string_ref x, string_ref y) { return x.compare(x: y) == 0; }
137inline bool operator!=(string_ref x, string_ref y) { return x.compare(x: y) != 0; }
138inline bool operator<(string_ref x, string_ref y) { return x.compare(x: y) < 0; }
139inline bool operator<=(string_ref x, string_ref y) { return x.compare(x: y) <= 0; }
140inline bool operator>(string_ref x, string_ref y) { return x.compare(x: y) > 0; }
141inline bool operator>=(string_ref x, string_ref y) { return x.compare(x: y) >= 0; }
142
143inline std::ostream& operator<<(std::ostream& out, const string_ref& string) {
144 return out << std::string(string.begin(), string.end());
145}
146
147} // namespace grpc
148
149#endif // GRPCPP_SUPPORT_STRING_REF_H
150

source code of include/grpcpp/support/string_ref.h