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_IMPL_CODEGEN_STRING_REF_H 20 #define GRPCPP_IMPL_CODEGEN_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/impl/codegen/config.h> 30 31 namespace 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. 41 class 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. string_ref()51 string_ref() : data_(nullptr), length_(0) {} string_ref(const string_ref & other)52 string_ref(const string_ref& other) 53 : data_(other.data_), length_(other.length_) {} 54 string_ref& operator=(const string_ref& rhs) { 55 data_ = rhs.data_; 56 length_ = rhs.length_; 57 return *this; 58 } 59 string_ref(const char * s)60 string_ref(const char* s) : data_(s), length_(strlen(s)) {} string_ref(const char * s,size_t l)61 string_ref(const char* s, size_t l) : data_(s), length_(l) {} string_ref(const grpc::string & s)62 string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {} 63 64 /// iterators begin()65 const_iterator begin() const { return data_; } end()66 const_iterator end() const { return data_ + length_; } cbegin()67 const_iterator cbegin() const { return data_; } cend()68 const_iterator cend() const { return data_ + length_; } rbegin()69 const_reverse_iterator rbegin() const { 70 return const_reverse_iterator(end()); 71 } rend()72 const_reverse_iterator rend() const { 73 return const_reverse_iterator(begin()); 74 } crbegin()75 const_reverse_iterator crbegin() const { 76 return const_reverse_iterator(end()); 77 } crend()78 const_reverse_iterator crend() const { 79 return const_reverse_iterator(begin()); 80 } 81 82 /// capacity size()83 size_t size() const { return length_; } length()84 size_t length() const { return length_; } max_size()85 size_t max_size() const { return length_; } empty()86 bool empty() const { return length_ == 0; } 87 88 /// element access data()89 const char* data() const { return data_; } 90 91 /// string operations compare(string_ref x)92 int compare(string_ref x) const { 93 size_t min_size = length_ < x.length_ ? length_ : x.length_; 94 int r = memcmp(data_, x.data_, min_size); 95 if (r < 0) return -1; 96 if (r > 0) return 1; 97 if (length_ < x.length_) return -1; 98 if (length_ > x.length_) return 1; 99 return 0; 100 } 101 starts_with(string_ref x)102 bool starts_with(string_ref x) const { 103 return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0); 104 } 105 ends_with(string_ref x)106 bool ends_with(string_ref x) const { 107 return length_ >= x.length_ && 108 (memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0); 109 } 110 find(string_ref s)111 size_t find(string_ref s) const { 112 auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend()); 113 return it == cend() ? npos : std::distance(cbegin(), it); 114 } 115 find(char c)116 size_t find(char c) const { 117 auto it = std::find(cbegin(), cend(), c); 118 return it == cend() ? npos : std::distance(cbegin(), it); 119 } 120 121 string_ref substr(size_t pos, size_t n = npos) const { 122 if (pos > length_) pos = length_; 123 if (n > (length_ - pos)) n = length_ - pos; 124 return string_ref(data_ + pos, n); 125 } 126 127 private: 128 const char* data_; 129 size_t length_; 130 }; 131 132 /// Comparison operators 133 inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; } 134 inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; } 135 inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; } 136 inline bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; } 137 inline bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; } 138 inline bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; } 139 140 inline std::ostream& operator<<(std::ostream& out, const string_ref& string) { 141 return out << grpc::string(string.begin(), string.end()); 142 } 143 144 } // namespace grpc 145 146 #endif // GRPCPP_IMPL_CODEGEN_STRING_REF_H 147