openMSX
string_ref.cc
Go to the documentation of this file.
1 #include "string_ref.hh"
2 #include "likely.hh"
3 #include <algorithm>
4 #include <iostream>
5 #include <cstdlib>
6 #include <stdexcept>
7 
8 using std::string;
9 
10 // Outgoing conversion operators
11 
12 string string_ref::str() const
13 {
14  return siz ? string(dat, siz)
15  : string();
16 }
17 
18 
19 // string operations with the same semantics as std::string
20 
22 {
23  // Check prefix.
24  if (int r = memcmp(dat, rhs.dat, std::min(siz, rhs.siz))) {
25  return r;
26  }
27  // Prefixes match, check length.
28  return int(siz - rhs.siz); // Note: this overflows for very large strings.
29 }
30 
31 
33 {
34  if (pos >= siz) return string_ref();
35  return string_ref(dat + pos, std::min(n, siz - pos));
36 }
37 
39 {
40  // Simple string search algorithm O(size() * s.size()). An algorithm
41  // like Boyer–Moore has better time complexity and will run a lot
42  // faster on large strings. Though when the strings are relatively
43  // short (the typically case?) this very simple algorithm may run
44  // faster (because it has no setup-time). The implementation of
45  // std::string::find() in gcc uses a similar simple algorithm.
46  if (s.empty()) return 0;
47  if (s.size() <= siz) {
48  auto m = siz - s.size();
49  for (size_type pos = 0; pos <= m; ++pos) {
50  if ((dat[pos] == s[0]) &&
51  std::equal(s.begin() + 1, s.end(), dat + pos + 1)) {
52  return pos;
53  }
54  }
55  }
56  return npos;
57 }
58 
60 {
61  auto it = std::find(begin(), end(), c);
62  return (it == end()) ? npos : it - begin();
63 }
64 
66 {
67  // see comment in find()
68  if (s.empty()) return siz;
69  if (s.size() <= siz) {
70  auto m = siz - s.size();
71  for (auto pos = m; pos != size_type(-1); --pos) {
72  if ((dat[pos] == s[0]) &&
73  std::equal(s.begin() + 1, s.end(), dat + pos + 1)) {
74  return pos;
75  }
76  }
77  }
78  return npos;
79 }
80 
82 {
83  auto it = std::find(rbegin(), rend(), c);
84  return (it == rend()) ? npos : (it.base() - begin() - 1);
85 }
86 
88 {
89  auto it = std::find_first_of(begin(), end(), s.begin(), s.end());
90  return (it == end()) ? npos : it - begin();
91 }
92 
94 {
95  return find(c);
96 }
97 
98 //string_ref::size_type string_ref::find_first_not_of(string_ref s) const;
99 //string_ref::size_type string_ref::find_first_not_of(char c) const;
100 
102 {
103  auto it = std::find_first_of(rbegin(), rend(), s.begin(), s.end());
104  return (it == rend()) ? npos : (it.base() - begin() - 1);
105 }
106 
108 {
109  return rfind(c);
110 }
111 
112 //string_ref::size_type string_ref::find_last_not_of(string_ref s) const;
113 //string_ref::size_type string_ref::find_last_not_of(char c) const;
114 
115 // new string operations (not part of std::string)
117 {
118  return (siz >= x.size()) &&
119  (memcmp(dat, x.data(), x.size()) == 0);
120 }
121 bool string_ref::starts_with(char x) const
122 {
123  return !empty() && (front() == x);
124 }
125 
127 {
128  return (siz >= x.size()) &&
129  (memcmp(dat + siz - x.size(), x.data(), x.size()) == 0);
130 }
131 bool string_ref::ends_with(char x) const
132 {
133  return !empty() && (back() == x);
134 }
135 
136 
137 // Comparison operators
139 {
140  return x.compare(y) < 0;
141 }
142 
143 
144 // numeric conversions
146 {
147  unsigned result = 0;
148  for (char c : s) {
149  unsigned d = c - '0';
150  if (unlikely(d > 9)) {
151  throw std::invalid_argument("fast_stoi");
152  }
153  result *= 10;
154  result += d;
155  }
156  return result;
157 }
158 
159 
160 // concatenation
161 // TODO make s1 + s2 + s3 also efficient
163 {
164  string result;
165  result.reserve(x.size() + y.size());
166  result.append(x.data(), x.size());
167  result.append(y.data(), y.size());
168  return result;
169 }
170 std::string operator+(char x, string_ref y)
171 {
172  string result;
173  result.reserve(1 + y.size());
174  result.append(&x, 1);
175  result.append(y.data(), y.size());
176  return result;
177 }
178 std::string operator+(string_ref x, char y)
179 {
180  string result;
181  result.reserve(x.size() + 1);
182  result.append(x.data(), x.size());
183  result.append(&y, 1);
184  return result;
185 }
186 
187 
188 std::ostream& operator<<(std::ostream& os, string_ref s)
189 {
190  os.write(s.data(), s.size());
191  return os;
192 }
size_type find_last_of(string_ref s) const
Definition: string_ref.cc:101
#define unlikely(x)
Definition: likely.hh:15
bool ends_with(string_ref x) const
Definition: string_ref.cc:126
vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:268
const_reverse_iterator rend() const
Definition: string_ref.hh:52
bool operator<(string_ref x, string_ref y)
Definition: string_ref.cc:138
This class implements a subset of the proposal for std::string_ref (proposed for the next c++ standar...
Definition: string_ref.hh:18
const_iterator end() const
Definition: string_ref.hh:50
std::ostream & operator<<(std::ostream &os, string_ref s)
Definition: string_ref.cc:188
int compare(string_ref x) const
Definition: string_ref.cc:21
bool empty() const
Definition: string_ref.hh:56
const_iterator begin() const
Definition: string_ref.hh:49
const char * data() const
Definition: string_ref.hh:68
bool starts_with(string_ref x) const
Definition: string_ref.cc:116
const_reverse_iterator rbegin() const
Definition: string_ref.hh:51
string operator+(string_ref x, string_ref y)
Definition: string_ref.cc:162
size_t size_type
Definition: string_ref.hh:21
unsigned fast_stou(string_ref s)
Definition: string_ref.cc:145
std::string str() const
Definition: string_ref.cc:12
static const size_type npos
Definition: string_ref.hh:26
string_ref substr(size_type pos, size_type n=npos) const
Definition: string_ref.cc:32
size_type rfind(string_ref s) const
Definition: string_ref.cc:65
char back() const
Definition: string_ref.hh:67
size_type size() const
Definition: string_ref.hh:55
size_type find_first_of(string_ref s) const
Definition: string_ref.cc:87
char front() const
Definition: string_ref.hh:66
size_type find(string_ref s) const
Definition: string_ref.cc:38