• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
18 #define INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
19 
20 #include <string.h>
21 
22 #include <algorithm>
23 #include <string>
24 
25 #include "perfetto/base/hash.h"
26 #include "perfetto/base/logging.h"
27 
28 namespace perfetto {
29 namespace base {
30 
31 // A string-like object that refers to a non-owned piece of memory.
32 // Strings are internally NOT null terminated.
33 class StringView {
34  public:
35   static constexpr size_t npos = static_cast<size_t>(-1);
36 
StringView()37   StringView() : data_(nullptr), size_(0) {}
38   StringView(const StringView&) = default;
39   StringView& operator=(const StringView&) = default;
StringView(const char * data,size_t size)40   StringView(const char* data, size_t size) : data_(data), size_(size) {
41     PERFETTO_DCHECK(data != nullptr);
42   }
43 
44   // Allow implicit conversion from any class that has a |data| and |size| field
45   // and has the kConvertibleToStringView trait (e.g., protozero::ConstChars).
46   template <typename T, typename = std::enable_if<T::kConvertibleToStringView>>
StringView(const T & x)47   StringView(const T& x) : StringView(x.data, x.size) {
48     PERFETTO_DCHECK(x.data != nullptr);
49   }
50 
51   // Creates a StringView from a null-terminated C string.
52   // Deliberately not "explicit".
StringView(const char * cstr)53   StringView(const char* cstr) : data_(cstr), size_(strlen(cstr)) {
54     PERFETTO_DCHECK(cstr != nullptr);
55   }
56 
57   // This instead has to be explicit, as creating a StringView out of a
58   // std::string can be subtle.
StringView(const std::string & str)59   explicit StringView(const std::string& str)
60       : data_(str.data()), size_(str.size()) {}
61 
empty()62   bool empty() const { return size_ == 0; }
size()63   size_t size() const { return size_; }
data()64   const char* data() const { return data_; }
65 
at(size_t pos)66   char at(size_t pos) const {
67     PERFETTO_DCHECK(pos < size_);
68     return data_[pos];
69   }
70 
find(char c)71   size_t find(char c) const {
72     for (size_t i = 0; i < size_; ++i) {
73       if (data_[i] == c)
74         return i;
75     }
76     return npos;
77   }
78 
rfind(char c)79   size_t rfind(char c) const {
80     for (size_t i = size_; i > 0; --i) {
81       if (data_[i - 1] == c)
82         return i - 1;
83     }
84     return npos;
85   }
86 
87   StringView substr(size_t pos, size_t count = npos) const {
88     if (pos >= size_)
89       return StringView("", 0);
90     size_t rcount = std::min(count, size_ - pos);
91     return StringView(data_ + pos, rcount);
92   }
93 
ToStdString()94   std::string ToStdString() const {
95     return data_ == nullptr ? "" : std::string(data_, size_);
96   }
97 
Hash()98   uint64_t Hash() const {
99     base::Hash hasher;
100     hasher.Update(data_, size_);
101     return hasher.digest();
102   }
103 
104  private:
105   const char* data_ = nullptr;
106   size_t size_ = 0;
107 };
108 
109 inline bool operator==(const StringView& x, const StringView& y) {
110   if (x.size() != y.size())
111     return false;
112   if (x.size() == 0)
113     return true;
114   return memcmp(x.data(), y.data(), x.size()) == 0;
115 }
116 
117 inline bool operator!=(const StringView& x, const StringView& y) {
118   return !(x == y);
119 }
120 
121 inline bool operator<(const StringView& x, const StringView& y) {
122   auto size = std::min(x.size(), y.size());
123   if (size == 0)
124     return x.size() < y.size();
125   int result = memcmp(x.data(), y.data(), size);
126   return result < 0 || (result == 0 && x.size() < y.size());
127 }
128 
129 inline bool operator>=(const StringView& x, const StringView& y) {
130   return !(x < y);
131 }
132 
133 inline bool operator>(const StringView& x, const StringView& y) {
134   return y < x;
135 }
136 
137 inline bool operator<=(const StringView& x, const StringView& y) {
138   return !(y < x);
139 }
140 
141 }  // namespace base
142 }  // namespace perfetto
143 
144 namespace std {
145 
146 template <>
147 struct hash<::perfetto::base::StringView> {
148   size_t operator()(const ::perfetto::base::StringView& sv) const {
149     return static_cast<size_t>(sv.Hash());
150   }
151 };
152 
153 }  // namespace std
154 
155 #endif  // INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
156