summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2015-01-12 11:57:19 -0200
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-04-14 01:06:57 -0300
commitbe58d02cb655c244a659abbcdb9ab44e8a5459ce (patch)
tree83843b97d1c05122da119e9ee6811fb2329d61ad
parent9eb19f8852faf1b5cc7d64bd28eefb9307c78baf (diff)
eina_cxx: Add eina::string_view class (non owning reference to string)
Add an implementation of string_view to Eina C++. It is a non owning reference to a string that allows lightweight argument passing of both C++ std::string and C strings (const char*) on interfaces.
-rw-r--r--src/Makefile_Eina_Cxx.am1
-rw-r--r--src/bindings/eina_cxx/Eina.hh1
-rw-r--r--src/bindings/eina_cxx/eina_string_view.hh358
3 files changed, 360 insertions, 0 deletions
diff --git a/src/Makefile_Eina_Cxx.am b/src/Makefile_Eina_Cxx.am
index 77cf577..4607ece 100644
--- a/src/Makefile_Eina_Cxx.am
+++ b/src/Makefile_Eina_Cxx.am
@@ -27,6 +27,7 @@ bindings/eina_cxx/eina_ptrlist.hh \
27bindings/eina_cxx/eina_range_types.hh \ 27bindings/eina_cxx/eina_range_types.hh \
28bindings/eina_cxx/eina_ref.hh \ 28bindings/eina_cxx/eina_ref.hh \
29bindings/eina_cxx/eina_stringshare.hh \ 29bindings/eina_cxx/eina_stringshare.hh \
30bindings/eina_cxx/eina_string_view.hh \
30bindings/eina_cxx/eina_thread.hh \ 31bindings/eina_cxx/eina_thread.hh \
31bindings/eina_cxx/eina_throw.hh \ 32bindings/eina_cxx/eina_throw.hh \
32bindings/eina_cxx/eina_tuple.hh \ 33bindings/eina_cxx/eina_tuple.hh \
diff --git a/src/bindings/eina_cxx/Eina.hh b/src/bindings/eina_cxx/Eina.hh
index c1d755f..18a4a8d 100644
--- a/src/bindings/eina_cxx/Eina.hh
+++ b/src/bindings/eina_cxx/Eina.hh
@@ -13,6 +13,7 @@
13#include <eina_array.hh> 13#include <eina_array.hh>
14#include <eina_list.hh> 14#include <eina_list.hh>
15#include <eina_stringshare.hh> 15#include <eina_stringshare.hh>
16#include <eina_string_view.hh>
16#include <eina_error.hh> 17#include <eina_error.hh>
17#include <eina_accessor.hh> 18#include <eina_accessor.hh>
18#include <eina_thread.hh> 19#include <eina_thread.hh>
diff --git a/src/bindings/eina_cxx/eina_string_view.hh b/src/bindings/eina_cxx/eina_string_view.hh
new file mode 100644
index 0000000..cfa3ba0
--- /dev/null
+++ b/src/bindings/eina_cxx/eina_string_view.hh
@@ -0,0 +1,358 @@
1#ifndef EINA_STRING_VIEW_HH_
2#define EINA_STRING_VIEW_HH_
3
4#include <string>
5#include <iterator>
6#include <stdexcept>
7#include <algorithm>
8
9#include <eina_throw.hh>
10
11namespace efl { namespace eina {
12
13template <typename CharT, typename Traits = std::char_traits<CharT> >
14class basic_string_view
15{
16public:
17 // Types:
18 typedef Traits traits_type;
19 typedef CharT value_type;
20 typedef CharT& reference;
21 typedef CharT const& const_reference;
22 typedef CharT* pointer;
23 typedef CharT const* const_pointer;
24 typedef const_pointer const_iterator;
25 typedef const_iterator iterator;
26 typedef std::reverse_iterator<iterator> reverse_iterator;
27 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
28 typedef std::ptrdiff_t difference_type;
29 typedef std::size_t size_type;
30
31 // Constants:
32 static constexpr size_type npos = size_type(-1);
33
34 // Constructors:
35 constexpr basic_string_view() noexcept
36 : _str(nullptr), _len(0)
37 {}
38
39 basic_string_view(basic_string_view<CharT, Traits> const& other) noexcept = default;
40 basic_string_view(basic_string_view<CharT, Traits>&& other) noexcept = default;
41
42 template<typename Allocator>
43 basic_string_view(std::basic_string<CharT, Traits, Allocator> const& str) noexcept
44 : _str(str.data()), _len(str.length())
45 {}
46
47 basic_string_view(CharT const* c_str)
48 : _str(c_str), _len(Traits::length(c_str))
49 {}
50
51// basic_string_view(CharT const* c_str, size_type len) noexcept
52// : _str(c_str), _len(len)
53// {}
54
55 // Assignment:
56 basic_string_view<CharT, Traits>& operator=(basic_string_view<CharT, Traits> const& other) noexcept = default;
57 basic_string_view<CharT, Traits>& operator=(basic_string_view<CharT, Traits>&& other) noexcept = default;
58
59 // Iterators
60 const_iterator begin() const noexcept { return _str; }
61 const_iterator cbegin() const noexcept { return _str; }
62 const_iterator end() const noexcept { return _str + _len; }
63 const_iterator cend() const noexcept { return _str + _len; }
64 const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
65 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
66 const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
67 const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
68
69 // Capacity:
70 size_type size() const noexcept { return _len; }
71 size_type length() const noexcept { return _len; }
72 bool empty() const noexcept { return _len == 0; }
73
74 // Element access:
75 const_reference operator[](size_type pos) const { return _str[pos]; }
76
77 const_reference at(size_type pos) const
78 {
79 if (pos >= _len)
80 EFL_CXX_THROW(std::out_of_range("efl::eina::basic_string_view::at"));
81 return _str[pos];
82 }
83
84 const_reference front() const { return _str[0]; }
85 const_reference back() const { return _str[_len-1]; }
86
87 // Operations:
88 CharT const* data() const noexcept { return _str; }
89
90 size_type copy(CharT* s, size_type len, size_type pos = 0) const
91 {
92 Traits::copy(s, _str+pos, len);
93 return len;
94 }
95
96 int compare(basic_string_view<CharT, Traits> const& s) const
97 {
98 const int cmp = Traits::compare(_str, s._str, (std::min)(_len, s._len));
99 return cmp != 0 ? cmp : ( _len == s._len ? 0 : _len < s._len ? -1 : 1 );
100 }
101
102 int compare(size_type pos, size_type len, basic_string_view<CharT, Traits> const& s) const
103 {
104 const int cmp = Traits::compare(_str+pos, s._str, (std::min)(len, s._len));
105 return cmp != 0 ? cmp : ( len == s._len ? 0 : len < s._len ? -1 : 1 );
106 }
107
108 int compare(size_type pos1, size_type len1, basic_string_view<CharT, Traits> const& s, size_type pos2, size_type len2) const
109 {
110 const int cmp = Traits::compare(_str+pos1, s._str+pos2, (std::min)(len1, len2));
111 return cmp != 0 ? cmp : ( len1 == len2 ? 0 : len1 < len2 ? -1 : 1 );
112 }
113
114 bool starts_with(CharT c) const
115 {
116 return !empty() && Traits::eq(c, front());
117 }
118
119 bool starts_with(basic_string_view<CharT, Traits> const& s) const
120 {
121 return _len >= s._len && Traits::compare(_str, s._str, s._len) == 0;
122 }
123
124 bool ends_with(CharT c) const
125 {
126 return !empty() && Traits::eq(c, back());
127 }
128
129 bool ends_with(basic_string_view<CharT, Traits> const& s) const
130 {
131 return _len >= s._len && Traits::compare(_str + _len - s._len, s._str, s._len) == 0;
132 }
133
134 size_type find(basic_string_view<CharT, Traits> const& s) const
135 {
136 const_iterator iter = std::search(cbegin(), cend(), s.cbegin(), s.cend(), Traits::eq);
137 return iter == cend () ? npos : std::distance(cbegin(), iter);
138 }
139
140 size_type find(basic_string_view<CharT, Traits> const& s, size_type pos) const
141 {
142 if (pos >= _len)
143 return npos;
144 const_iterator iter = std::search(cbegin()+pos, cend(), s.cbegin(), s.cend(), Traits::eq);
145 return iter == cend () ? npos : std::distance(cbegin(), iter);
146 }
147
148 size_type find(CharT c) const
149 {
150 const_iterator iter = std::find_if(cbegin(), cend(), [=](CharT val) { return Traits::eq(c, val); });
151 return iter == cend() ? npos : std::distance(cbegin(), iter);
152 }
153
154 size_type find(CharT c, size_type pos) const
155 {
156 if (pos >= _len)
157 return npos;
158 const_iterator iter = std::find_if(cbegin()+pos, cend(), [=](CharT val) { return Traits::eq(c, val); });
159 return iter == cend() ? npos : std::distance(cbegin(), iter);
160 }
161
162 size_type rfind(basic_string_view<CharT, Traits> const& s) const
163 {
164 const_reverse_iterator iter = std::search(crbegin(), crend(), s.crbegin(), s.crend(), Traits::eq);
165 return iter == crend() ? npos : reverse_distance(crbegin(), iter) - s.lenght();
166 }
167
168 size_type rfind(basic_string_view<CharT, Traits> const& s, size_type pos) const
169 {
170 if (pos >= _len)
171 return npos;
172 const_reverse_iterator iter = std::search(crbegin()+pos, crend(), s.crbegin(), s.crend(), Traits::eq);
173 return iter == crend() ? npos : reverse_distance(crbegin(), iter) - s.lenght();
174 }
175
176 size_type rfind(CharT c) const
177 {
178 const_reverse_iterator iter = std::find_if(crbegin(), crend(), [&](CharT val) { return Traits::eq(c, val); });
179 return iter == crend() ? npos : reverse_distance(crbegin(), iter);
180 }
181
182 size_type rfind(CharT c, size_type pos) const
183 {
184 pos = (pos >= _len) ? 0 : _len - pos - 1;
185 const_reverse_iterator iter = std::find_if(crbegin()+pos, crend(), [&](CharT val) { return Traits::eq(c, val); });
186 return iter == crend() ? npos : reverse_distance(crbegin(), iter);
187 }
188
189 size_type find_first_of(CharT c) const { return find(c); }
190 size_type find_last_of (CharT c) const { return rfind(c); }
191
192 size_type find_first_of(basic_string_view<CharT, Traits> const& s) const
193 {
194 const_iterator iter = std::find_first_of(cbegin(), cend(), s.cbegin(), s.cend(), Traits::eq);
195 return iter == cend() ? npos : std::distance(cbegin(), iter);
196 }
197
198 size_type find_last_of(basic_string_view<CharT, Traits> const& s) const
199 {
200 const_reverse_iterator iter = std::find_first_of(crbegin(), crend(), s.cbegin(), s.cend(), Traits::eq);
201 return iter == crend () ? npos : reverse_distance(crbegin(), iter);
202 }
203
204 size_type find_first_not_of(basic_string_view<CharT, Traits> const& s) const
205 {
206 const_iterator iter = find_not_of(cbegin(), cend(), s);
207 return iter == cend() ? npos : std::distance(cbegin(), iter);
208 }
209
210 size_type find_first_not_of(CharT c) const
211 {
212 for (const_iterator iter = cbegin(); iter != cend(); ++iter)
213 if (!Traits::eq(c, *iter))
214 return std::distance(cbegin(), iter);
215 return npos;
216 }
217
218 size_type find_last_not_of(basic_string_view<CharT, Traits> const& s) const
219 {
220 const_reverse_iterator iter = find_not_of(crbegin(), crend(), s);
221 return iter == crend() ? npos : reverse_distance(crbegin(), iter);
222 }
223
224 size_type find_last_not_of(CharT c) const
225 {
226 for (const_reverse_iterator iter = crbegin(); iter != crend(); ++iter)
227 if (!Traits::eq(c, *iter))
228 return reverse_distance(crbegin(), iter);
229 return npos;
230 }
231
232 // XXX: returning std::string instead of eina::string_view
233 std::basic_string<CharT, Traits> substr(size_type pos, size_type len=npos) const
234 {
235 if (pos > size())
236 EFL_CXX_THROW(std::out_of_range("efl::eina::string_view::substr"));
237 if (len == npos || pos + len > size())
238 len = size () - pos;
239 return std::basic_string<CharT, Traits>(data() + pos, len);
240 }
241
242 // Conversions:
243 std::basic_string<CharT, Traits> to_string() const
244 {
245 return std::basic_string<CharT, Traits>(_str, _len);
246 }
247
248 std::basic_string<CharT, Traits> str() const
249 {
250 return to_string();
251 }
252
253 template<typename Allocator>
254 operator std::basic_string<CharT, Traits, Allocator>() const
255 {
256 return std::basic_string<CharT, Traits, Allocator>(_str, _len);
257 }
258
259 // Modifiers:
260// void clear() noexcept { _len = 0; }
261//
262// void remove_prefix(size_type n) noexcept
263// {
264// if (n > _len)
265// n = _len;
266// _str += n;
267// _len -= n;
268// }
269//
270// void remove_suffix(size_type n) noexcept
271// {
272// if (n > _len)
273// n = _len;
274// _len -= n;
275// }
276
277 void swap(basic_string_view<CharT, Traits>& s)
278 {
279 std::swap(_str, s._str);
280 std::swap(_len, s._len);
281 }
282
283 // Comparison operators:
284 friend inline bool operator==(basic_string_view<CharT, Traits> const& s1, basic_string_view<CharT, Traits> const& s2)
285 {
286 if (s1.size() != s2.size())
287 return false;
288 return s1.compare(s2) == 0;
289 }
290
291 friend inline bool operator!=(basic_string_view<CharT, Traits> const& s1, basic_string_view<CharT, Traits> const& s2)
292 {
293 return !(s1 == s2);
294 }
295
296 friend inline bool operator<(basic_string_view<CharT, Traits> const& s1, basic_string_view<CharT, Traits> const& s2)
297 {
298 return s1.compare(s2) < 0;
299 }
300
301 friend inline bool operator>(basic_string_view<CharT, Traits> const& s1, basic_string_view<CharT, Traits> const& s2)
302 {
303 return s2 < s1;
304 }
305
306 friend inline bool operator<=(basic_string_view<CharT, Traits> const& s1, basic_string_view<CharT, Traits> const& s2)
307 {
308 return !(s2 < s1);
309 }
310
311 friend inline bool operator>=(basic_string_view<CharT, Traits> const& s1, basic_string_view<CharT, Traits> const& s2)
312 {
313 return !(s1 < s2);
314 }
315
316private:
317 template <typename Iterator>
318 size_type reverse_distance(Iterator first, Iterator last) const
319 {
320 return _len - 1 - std::distance(first, last);
321 }
322
323 template <typename Iterator>
324 Iterator find_not_of(Iterator first, Iterator last, basic_string_view<CharT, Traits>& s) const
325 {
326 for (; first != last; ++first)
327 if (0 == Traits::find(s._str, s._len, *first))
328 return first;
329 return last;
330 }
331
332 const CharT* _str;
333 size_type _len;
334};
335
336// Stream operation
337template<class CharT, class Traits>
338inline std::basic_ostream<CharT, Traits>&
339operator<<(std::basic_ostream<CharT, Traits>& os, basic_string_view<CharT,Traits> const& s)
340{
341 return os << s.data();
342}
343
344template <typename CharT, typename Traits>
345void swap(basic_string_view<CharT, Traits>& s1, basic_string_view<CharT, Traits>& s2)
346{
347 s1.swap(s2);
348}
349
350// Instantiations:
351typedef basic_string_view<char> string_view;
352typedef basic_string_view<wchar_t> wstring_view;
353typedef basic_string_view<char16_t> u16string_view;
354typedef basic_string_view<char32_t> u32string_view;
355
356} }
357
358#endif