openMSX
string_ref.cc
Go to the documentation of this file.
1 #include "string_ref.hh"
2 #include "cstdlibp.hh"
3 #include <algorithm>
4 #include <iostream>
5 
6 using std::string;
7 
8 // Outgoing conversion operators
9 
10 string string_ref::str() const
11 {
12  return siz ? string(dat, siz)
13  : string();
14 }
15 
16 
17 // mutators
18 
20 {
21  if (n <= siz) {
22  dat += n;
23  siz -= n;
24  } else {
25  clear();
26  }
27 }
28 
30 {
31  if (n <= siz) {
32  siz -= n;
33  } else {
34  clear();
35  }
36 }
37 
38 
39 // string operations with the same semantics as std::string
40 
42 {
43  // Check prefix.
44  if (int r = memcmp(dat, rhs.dat, std::min(siz, rhs.siz))) {
45  return r;
46  }
47  // Prefixes match, check length.
48  return int(siz - rhs.siz); // Note: this overflows for very large strings.
49 }
50 
51 
53 {
54  if (pos >= siz) return string_ref();
55  return string_ref(dat + pos, std::min(n, siz - pos));
56 }
57 
59 {
60  // Simple string search algorithm O(size() * s.size()). An algorithm
61  // like Boyer–Moore has better time complexity and will run a lot
62  // faster on large strings. Though when the strings are relatively
63  // short (the typically case?) this very simple algorithm may run
64  // faster (because it has no setup-time). The implementation of
65  // std::string::find() in gcc uses a similar simple algorithm.
66  if (s.empty()) return 0;
67  if (s.size() <= siz) {
68  auto m = siz - s.size();
69  for (size_type pos = 0; pos <= m; ++pos) {
70  if ((dat[pos] == s[0]) &&
71  std::equal(s.begin() + 1, s.end(), dat + pos + 1)) {
72  return pos;
73  }
74  }
75  }
76  return npos;
77 }
78 
80 {
81  auto it = std::find(begin(), end(), c);
82  return (it == end()) ? npos : it - begin();
83 }
84 
86 {
87  // see comment in find()
88  if (s.empty()) return siz;
89  if (s.size() <= siz) {
90  auto m = siz - s.size();
91  for (auto pos = m; pos != size_type(-1); --pos) {
92  if ((dat[pos] == s[0]) &&
93  std::equal(s.begin() + 1, s.end(), dat + pos + 1)) {
94  return pos;
95  }
96  }
97  }
98  return npos;
99 }
100 
102 {
103  auto it = std::find(rbegin(), rend(), c);
104  return (it == rend()) ? npos : (it.base() - begin() - 1);
105 }
106 
108 {
109  auto it = std::find_first_of(begin(), end(), s.begin(), s.end());
110  return (it == end()) ? npos : it - begin();
111 }
112 
114 {
115  return find(c);
116 }
117 
118 //string_ref::size_type string_ref::find_first_not_of(string_ref s) const;
119 //string_ref::size_type string_ref::find_first_not_of(char c) const;
120 
122 {
123  auto it = std::find_first_of( rbegin(), rend(), s.begin(), s.end());
124  return (it == rend()) ? npos : (it.base() - begin() - 1);
125 }
126 
128 {
129  return rfind(c);
130 }
131 
132 //string_ref::size_type string_ref::find_last_not_of(string_ref s) const;
133 //string_ref::size_type string_ref::find_last_not_of(char c) const;
134 
135 // new string operations (not part of std::string)
137 {
138  return (siz >= x.size()) &&
139  (memcmp(dat, x.data(), x.size()) == 0);
140 }
141 
143 {
144  return (siz >= x.size()) &&
145  (memcmp(dat + siz - x.size(), x.data(), x.size()) == 0);
146 }
147 
148 
149 // Comparison operators
151 {
152  return (x.size() == y.size()) &&
153  (memcmp(x.data(), y.data(), x.size()) == 0);
154 }
155 
157 {
158  return x.compare(y) < 0;
159 }
160 
161 
162 // numeric conversions
163 // TODO could be implemented more efficient (don't make a copy)
164 int stoi(string_ref str, string_ref::size_type* idx, int base)
165 {
166  string s = str.str();
167  const char* begin = s.c_str();
168  char* end;
169  int result = strtol(begin, &end, base);
170  if (idx) *idx = end - begin;
171  return result;
172 }
173 unsigned long stoul (string_ref str, string_ref::size_type* idx, int base)
174 {
175  string s = str.str();
176  const char* begin = s.c_str();
177  char* end;
178  int result = strtoul(begin, &end, base);
179  if (idx) *idx = end - begin;
180  return result;
181 }
182 long long stoll(string_ref str, string_ref::size_type* idx, int base)
183 {
184  string s = str.str();
185  const char* begin = s.c_str();
186  char* end;
187  int result = strtoll(begin, &end, base);
188  if (idx) *idx = end - begin;
189  return result;
190 }
191 
192 
193 // concatenation
194 // TODO make s1 + s2 + s3 also efficient
196 {
197  string result;
198  result.reserve(x.size() + y.size());
199  result.append(x.data(), x.size());
200  result.append(y.data(), y.size());
201  return result;
202 }
203 std::string operator+(char x, string_ref y)
204 {
205  string result;
206  result.reserve(1 + y.size());
207  result.append(&x, 1);
208  result.append(y.data(), y.size());
209  return result;
210 }
211 std::string operator+(string_ref x, char y)
212 {
213  string result;
214  result.reserve(x.size() + 1);
215  result.append(x.data(), x.size());
216  result.append(&y, 1);
217  return result;
218 }
219 
220 
221 std::ostream& operator<<(std::ostream& os, string_ref str)
222 {
223  os.write(str.data(), str.size());
224  return os;
225 }