source: mainline/uspace/lib/cpp/include/impl/string.hpp@ b08a62c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b08a62c was b08a62c, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added implementation of the most basic string functions

  • Property mode set to 100644
File size: 20.7 KB
RevLine 
[52d025c]1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_STRING
30#define LIBCPP_STRING
31
32#include <initializer_list>
33#include <iosfwd>
34#include <cstdio>
35#include <cstdlib>
36#include <cstring>
37
38namespace std
39{
40
41 /**
42 * 21.2, char_traits:
43 */
44
45 template<class Char>
46 struct char_traits;
47
48 /**
49 * 21.2.3, char_traits specializations:
50 */
51
52 template<>
53 struct char_traits<char>
54 {
55 using char_type = char;
56 using int_type = int;
57 using off_type = streamoff;
58 using pos_type = streampos;
59 /* using state_type = mbstate_t; */
60
61 static void assign(char_type& c1, char_type& c2) noexcept
62 {
63 c1 = c2;
64 }
65
66 static constexpr bool eq(char_type c1, char_type c2) noexcept
67 {
68 return c1 == c2;
69 }
70
71 static constexpr bool lt(char_type c1, char_type c2) noexcept
72 {
73 return c1 < c2;
74 }
75
76 static int compare(const char_type* s1, const char_type* s2, size_t n)
77 {
78 return std::str_lcmp(s1, s2, n);
79 }
80
81 static size_t length(const char_type* s)
82 {
83 return std::str_size(s);
84 }
85
86 static const char_type* find(const char_type* s, size_t n, const char_type& c)
87 {
88 size_t i{};
89 while (i++ < n)
90 {
91 if (s[i] == c)
92 return s + i;
93 }
94
95 return nullptr;
96 }
97
98 static char_type* move(char_type* s1, const char_type* s2, size_t n)
99 {
100 return static_cast<char_type*>(memmove(s1, s2, n));
101 }
102
103 static char_type* copy(char_type* s1, const char_type* s2, size_t n)
104 {
105 return static_cast<char_type*>(memcpy(s1, s2, n));
106 }
107
108 static char_type* assign(char_type* s, size_t n, char_type c)
109 {
110 /**
111 * Note: Even though memset accepts int as its second argument,
112 * the actual implementation assigns that int to a dereferenced
113 * char pointer.
114 */
115 return static_cast<char_type*>(memset(s, static_cast<int>(c), n));
116 }
117
118 static constexpr int_type not_eof(int_type c) noexcept
119 {
120 if (!eq_int_type(c, eof()))
121 return c;
122 else
123 return to_int_type('a'); // We just need something that is not eof.
124 }
125
126 static constexpr char_type to_char_type(int_type c) noexcept
127 {
128 return static_cast<char_type>(c);
129 }
130
131 static constexpr int_type to_int_type(char_type c) noexcept
132 {
133 return static_cast<int_type>(c);
134 }
135
136 static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept
137 {
138 return c1 == c2;
139 }
140
141 static constexpr int_type eof() noexcept
142 {
143 return static_cast<int_type>(EOF);
144 }
145 };
146
147 template<>
148 struct char_traits<char16_t>
149 { /* TODO: implement */ };
150
151 template<>
152 struct char_traits<char32_t>
153 { /* TODO: implement */ };
154
155 template<>
156 struct char_traits<wchar_t>
157 {
158 using char_type = wchar_t;
159 using int_type = wint_t;
160 using off_type = streamoff;
161 using pos_type = wstreampos;
162 /* using state_type = mbstate_t; */
163
164 static void assign(char_type& c1, char_type& c2) noexcept
165 {
166 c1 = c2;
167 }
168
169 static constexpr bool eq(char_type c1, char_type c2) noexcept
170 {
171 return c1 == c2;
172 }
173
174 static constexpr bool lt(char_type c1, char_type c2) noexcept
175 {
176 return c1 < c2;
177 }
178
179 static int compare(const char_type* s1, const char_type* s2, size_t n)
180 {
181 return std::wstr_lcmp(s1, s2, n);
182 }
183
184 static size_t length(const char_type* s)
185 {
186 return std::wstr_size(s);
187 }
188
189 static const char_type* find(const char_type* s, size_t n, const char_type& c)
190 {
191 size_t i{};
192 while (i++ < n)
193 {
194 if (s[i] == c)
195 return s + i;
196 }
197
198 return nullptr;
199 }
200
201 static char_type* move(char_type* s1, const char_type* s2, size_t n)
202 {
203 return static_cast<char_type*>(memmove(s1, s2, n * sizeof(wchar_t)));
204 }
205
206 static char_type* copy(char_type* s1, const char_type* s2, size_t n)
207 {
208 return static_cast<char_type*>(memcpy(s1, s2, n * sizeof(wchar_t)));
209 }
210
211 static char_type* assign(char_type* s, size_t n, char_type c)
212 {
213 return static_cast<char_type*>(memset(s, static_cast<int>(c), n * sizeof(wchar_t)));
214 }
215
216 static constexpr int_type not_eof(int_type c) noexcept
217 {
218 if (!eq_int_type(c, eof()))
219 return c;
220 else
221 return to_int_type(L'a'); // We just need something that is not eof.
222 }
223
224 static constexpr char_type to_char_type(int_type c) noexcept
225 {
226 return static_cast<char_type>(c);
227 }
228
229 static constexpr int_type to_int_type(char_type c) noexcept
230 {
231 return static_cast<int_type>(c);
232 }
233
234 static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept
235 {
236 return c1 == c2;
237 }
238
239 static constexpr int_type eof() noexcept
240 {
241 return static_cast<int_type>(EOF);
242 }
243 };
244
245 /**
246 * 21.4, class template basic_string:
247 */
248
249 template<class Char, class Traits = char_traits<Char>,
250 class Allocator = allocator<Char>>
251 class basic_string
252 {
[177a576]253 public:
254 using traits_type = Traits;
255 using value_type = typename traits_type::char_type;
256 using allocator_type = Allocator;
257 using size_type = typename allocator_traits<allocator_type>::size_type;
258 using difference_type = typename allocator_traits<allocator_type>::difference_type;
[52d025c]259
[177a576]260 using reference = value_type&;
261 using const_reference = const value_type&;
262 using pointer = allocator_traits<allocator_type>::pointer;
263 using const_pointer = allocator_traits<allocator_type>::const_pointer;
[52d025c]264
[177a576]265 using iterator = pointer;
266 using const_iterator = const_pointer;
267 using reverse_iterator = std::reverse_iterator<iterator>;
268 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
[52d025c]269
[177a576]270 static constexpr size_type npos = -1;
[52d025c]271
[177a576]272 /**
273 * 21.4.2, construct/copy/destroy:
274 */
275 basic_string() noexcept
276 : basic_string(allocator_type{})
277 { /* DUMMY BODY */ }
[52d025c]278
[177a576]279 explicit basic_string(const allocator_type& alloc);
[52d025c]280
[177a576]281 basic_string(const basic_string& other);
[52d025c]282
[177a576]283 basic_string(basic_string&& other);
[52d025c]284
[177a576]285 basic_string(const basic_string& other, size_type pos, size_type n = npos,
286 const allocator_type& alloc = allocator_type{});
[52d025c]287
[177a576]288 basic_string(const value_type*, size_type n, const allocator_type& alloc = allocator{});
[52d025c]289
[177a576]290 basic_string(const value_type*, const allocator_type& alloc = allocator{});
[52d025c]291
[177a576]292 basic_string(size_type n, value_type c, const allocator_type& alloc = allocator{});
[52d025c]293
[177a576]294 template<class InputIterator>
295 basic_string(InputIterator first, InputIterator last,
296 const allocator_type& alloc = allocator{});
[52d025c]297
[177a576]298 basic_string(initializer_list<value_type> init, const allocator_type& alloc = allocator{});
[52d025c]299
[177a576]300 basic_string(const basic_string& other, const allocator_type& alloc);
[52d025c]301
[177a576]302 basic_string(basic_string&& other, const allocator_type& alloc);
[52d025c]303
[177a576]304 ~basic_string();
[52d025c]305
[177a576]306 basic_string& operator=(const basic_string& other);
[52d025c]307
[177a576]308 basic_string& operator=(basic_string&& other)
309 noexcept(allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
310 allocator_traits<allocator_type>::is_always_equal::value);
[52d025c]311
[177a576]312 basic_string& operator=(const value_type* other);
[52d025c]313
[177a576]314 basic_string& operator=(value_type c);
[52d025c]315
[177a576]316 basic_string& operator=(initializer_list<value_type>);
[52d025c]317
[177a576]318 /**
319 * 21.4.3, iterators:
320 */
[52d025c]321
[b08a62c]322 iterator begin() noexcept
323 {
324 return &data_[0];
325 }
[52d025c]326
[b08a62c]327 const_iterator begin() const noexcept
328 {
329 return &data_[0];
330 }
[52d025c]331
[b08a62c]332 iterator end() noexcept
333 {
334 return begin() + size_;
335 }
[52d025c]336
[b08a62c]337 const_iterator end() const noexcept
338 {
339 return begin() + size_;
340 }
[52d025c]341
[177a576]342 reverse_iterator rbegin() noexcept
343 {
[98c99ba]344 return make_reverse_iterator(end());
[177a576]345 }
[52d025c]346
[177a576]347 const_reverse_iterator rbegin() const noexcept
348 {
[98c99ba]349 return make_reverse_iterator(cend());
[177a576]350 }
[52d025c]351
[177a576]352 reverse_iterator rend() noexcept
353 {
[98c99ba]354 return make_reverse_iterator(begin());
[177a576]355 }
[52d025c]356
[177a576]357 const_reverse_iterator rend() const noexcept
358 {
[98c99ba]359 return make_reverse_iterator(cbegin());
[177a576]360 }
[52d025c]361
[b08a62c]362 const_iterator cbegin() const noexcept
363 {
364 return &data_[0];
365 }
[52d025c]366
[b08a62c]367 const_iterator cend() const noexcept
368 {
369 return cbegin() + size_;
370 }
[52d025c]371
[177a576]372 const_reverse_iterator crbegin() const noexcept
373 {
[98c99ba]374 return rbegin();
[177a576]375 }
[52d025c]376
[177a576]377 const_reverse_iterator crend() const noexcept
378 {
[98c99ba]379 return rend();
[177a576]380 }
[52d025c]381
[177a576]382 /**
383 * 21.4.4, capacity:
384 */
[52d025c]385
[b08a62c]386 size_type size() const noexcept
387 {
388 return size_;
389 }
[52d025c]390
[b08a62c]391 size_type length() const noexcept
392 {
393 return size_;
394 }
[52d025c]395
[b08a62c]396 size_type max_size() const noexcept
397 {
398 return allocator_traits<allocator_type>::max_size(allocator_);
399 }
[52d025c]400
[177a576]401 void resize(size_type n, value_type c);
[52d025c]402
[177a576]403 void resize(size_type n);
[52d025c]404
[b08a62c]405 size_type capacity() const noexcept
406 {
407 return capacity_;
408 }
[52d025c]409
[177a576]410 void reserve(size_type res_arg = 0);
[52d025c]411
[177a576]412 void shrink_to_fit();
[52d025c]413
[177a576]414 void clear() noexcept;
[52d025c]415
[b08a62c]416 bool empty() const noexcept
417 {
418 return size_ == 0;
419 }
[52d025c]420
[177a576]421 /**
422 * 21.4.5, element access:
423 */
[52d025c]424
[b08a62c]425 const_reference operator[](size_type idx) const
426 {
427 return data_[idx];
428 }
[52d025c]429
[b08a62c]430 reference operator[](size_type idx)
431 {
432 return data_[idx];
433 }
[52d025c]434
[b08a62c]435 const_reference at(size_type idx) const
436 {
437 // TODO: bounds checking
438 return data_[idx];
439 }
[52d025c]440
[b08a62c]441 reference at(size_type idx)
442 {
443 // TODO: bounds checking
444 return data_[idx];
445 }
[52d025c]446
[b08a62c]447 const_reference front() const
448 {
449 return at(0);
450 }
[52d025c]451
[b08a62c]452 reference front()
453 {
454 return at(0);
455 }
[52d025c]456
[b08a62c]457 const_reference back() const
458 {
459 return at(size_ - 1);
460 }
[52d025c]461
[b08a62c]462 reference back()
463 {
464 return at(size_ - 1);
465 }
[52d025c]466
[177a576]467 /**
468 * 21.4.6, modifiers:
469 */
[52d025c]470
[177a576]471 basic_string& operator+=(const basic_string& str);
[52d025c]472
[177a576]473 basic_string& operator+=(const value_type* str);
[52d025c]474
[177a576]475 basic_string& operator+=(value_type c);
[52d025c]476
[177a576]477 basic_string& operator+=(initializer_list<value_type> init);
[52d025c]478
[177a576]479 basic_string& append(const basic_string& str);
[52d025c]480
[177a576]481 basic_string& append(const basic_string& str, size_type pos
482 size_type n = npos);
[52d025c]483
[177a576]484 basic_string& append(const value_type* str, size_type n);
[52d025c]485
[177a576]486 basic_string& append(const value_type* str);
[52d025c]487
[177a576]488 basic_string& append(size_type n, value_type c);
[52d025c]489
[177a576]490 template<class InputIterator>
491 basic_string& append(InputIterator first, InputIterator last);
[52d025c]492
[177a576]493 basic_string& append(initializer_list<value_type> init);
[52d025c]494
[177a576]495 void push_back(value_type c);
[52d025c]496
[177a576]497 basic_string& assign(const basic_string& str);
[52d025c]498
[177a576]499 basic_string& assign(basic_string&& str);
[52d025c]500
[177a576]501 basic_string& assign(const basic_string& str, size_type pos,
502 size_type n = npos);
[52d025c]503
[177a576]504 basic_string& assign(const value_type* str, size_type n);
[52d025c]505
[177a576]506 basic_string& assign(const value_type* str);
[52d025c]507
[177a576]508 basic_string& assign(size_type n, value_type c);
[52d025c]509
[177a576]510 template<class InputIterator>
511 basic_string& assign(InputIterator first, InputIterator last);
[52d025c]512
[177a576]513 basic_string& assign(initializer_list<value_type> init);
[52d025c]514
[177a576]515 basic_string& insert(size_type pos, const basic_string& str);
[52d025c]516
[177a576]517 basic_string& insert(size_type pos1, const basic_string& str,
518 size_type pos2, size_type n = npos);
[52d025c]519
[177a576]520 basic_string& insert(size_type pos, const value_type* str, size_type n);
[52d025c]521
[177a576]522 basic_string& insert(size_type pos, const value_type* str);
[52d025c]523
[177a576]524 basic_string& insert(size_type pos, size_type n, value_type c);
[52d025c]525
[177a576]526 iterator insert(const_iterator pos, value_type c);
[52d025c]527
[177a576]528 iterator insert(const_iterator pos, size_type n, value_type c);
[52d025c]529
[177a576]530 template<class InputIterator>
531 iterator insert(const_iterator pos, InputIterator first,
532 InputIterator last);
[52d025c]533
[177a576]534 iterator insert(const_iterator pos, initializer_list<value_type>);
[52d025c]535
[177a576]536 basic_string& erase(size_type pos = 0; size_type n = npos);
[52d025c]537
[177a576]538 iterator erase(const_iterator pos);
[52d025c]539
[177a576]540 iterator erase(const_iterator pos, const_iterator last);
[52d025c]541
[177a576]542 void pop_back();
[52d025c]543
[177a576]544 basic_string& replace(size_type pos, size_type n, const basic_string& str);
[52d025c]545
[177a576]546 basic_string& replace(size_type pos1, size_type n1, const basic_string& str
547 size_type pos2, size_type n2);
[52d025c]548
[177a576]549 basic_string& replace(size_type pos, size_type n1, const value_type* str,
550 size_type n2);
[52d025c]551
[177a576]552 basic_string& replace(size_type pos, size_type n, const value_type* str);
[52d025c]553
[177a576]554 basic_string& replace(size_type pos, size_type n1, size_type n2,
555 value_type c);
[52d025c]556
[177a576]557 basic_string& replace(const_iterator i1, const_iterator i2,
558 const basic_string& str);
[52d025c]559
[177a576]560 basic_string& replace(const_iterator i1, const_iterator i2,
561 const value_type* str, size_type n);
[52d025c]562
[177a576]563 basic_string& replace(const_iterator i1, const_iterator i2,
564 const value_type* str);
[52d025c]565
[177a576]566 basic_string& replace(const_iterator i1, const_iterator i2,
567 value_type c);
[52d025c]568
[177a576]569 template<class InputIterator>
570 basic_string& replace(const_iterator i1, const_iterator i2,
571 InputIterator j1, InputIterator j2);
[52d025c]572
[177a576]573 basic_string& replace(const_iterator i1, const_iterator i2,
574 initializer_list<value_type> init);
[52d025c]575
[177a576]576 size_type copy(value_type* str, size_type n, size_type pos = 0) const;
[52d025c]577
[177a576]578 void swap(basic_string& other)
579 noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
[b08a62c]580 allocator_traits<allocator_type>::is_always_equal)
581 {
582 std::swap(data_, other.data_);
583 std::swap(size_, other.size_);
584 std::swap(capacity_, other.capacity_);
585 }
[52d025c]586
[177a576]587 /**
588 * 21.4.7, string operations:
589 */
[52d025c]590
[b08a62c]591 const value_type* c_str() const noexcept
592 {
593 return data_;
594 }
[52d025c]595
[b08a62c]596 const value_type* data() const noexcept
597 {
598 return data_;
599 }
[52d025c]600
[b08a62c]601 allocator_type get_allocator() const noexcept
602 {
603 return allocator_type{allocator_};
604 }
[52d025c]605
[177a576]606 size_type find(const basic_string& str, size_type pos = 0) const noexcept;
[52d025c]607
[177a576]608 size_type find(const value_type* str, size_type pos, size_type n) const;
[52d025c]609
[177a576]610 size_type find(const value_type* str, size_type pos = 0) const;
[52d025c]611
[177a576]612 size_type find(value_type c, size_type pos = 0) const;
[52d025c]613
[177a576]614 size_type rfind(const basic_string& str, size_type pos = npos) const noexcept;
[52d025c]615
[177a576]616 size_type rfind(const value_type* str, size_type pos, size_type n) const;
[52d025c]617
[177a576]618 size_type rfind(const value_type* str, size_type pos = npos) const;
[52d025c]619
[177a576]620 size_type rfind(value_type c, size_type pos = npos) const;
[52d025c]621
[177a576]622 size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;
[52d025c]623
[177a576]624 size_type find_first_of(const value_type* str, size_type pos, size_type n) const;
[52d025c]625
[177a576]626 size_type find_first_of(const value_type* str, size_type pos = 0) const;
[52d025c]627
[177a576]628 size_type find_first_of(value_type c, size_type pos = 0) const;
[52d025c]629
[177a576]630 size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept;
[52d025c]631
[177a576]632 size_type find_last_of(const value_type* str, size_type pos, size_type n) const;
[52d025c]633
[177a576]634 size_type find_last_of(const value_type* str, size_type pos = npos) const;
[52d025c]635
[177a576]636 size_type find_last_of(value_type c, size_type pos = npos) const;
[52d025c]637
[177a576]638 size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;
[52d025c]639
[177a576]640 size_type find_first_not_of(const value_type* str, size_type pos, size_type n) const;
[52d025c]641
[177a576]642 size_type find_first_not_of(const value_type* str, size_type pos = 0) const;
[52d025c]643
[177a576]644 size_type find_first_not_of(value_type c, size_type pos = 0) const;
[52d025c]645
[177a576]646 size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept;
[52d025c]647
[177a576]648 size_type find_last_not_of(const value_type* str, size_type pos, size_type n) const;
[52d025c]649
[177a576]650 size_type find_last_not_of(const value_type* str, size_type pos = npos) const;
[52d025c]651
[177a576]652 size_type find_last_not_of(value_type c, size_type pos = npos) const;
[52d025c]653
[177a576]654 basic_string substr(size_type pos = 0, size_type n = npos) const;
[52d025c]655
[177a576]656 int compare(const basic_string& other) const noexcept;
[52d025c]657
[177a576]658 int compare(size_type pos, size_type n, const basic_string& other) const;
[52d025c]659
[177a576]660 int compare(size_type pos1, size_type n1, const basic_string& other,
661 size_type pos2, size_type n2 = npos) const;
[52d025c]662
[177a576]663 int compare(const value_type* other) const;
[52d025c]664
[177a576]665 int compare(size_type pos, size_type n, const value_type* other) const;
[52d025c]666
[177a576]667 int compare(size_type pos1, size_type n1,
668 const value_type* other, size_type n2) const;
[b08a62c]669
670 private:
671 value_type* data_;
672 size_type size_;
673 size_type capacity_;
674 allocator_type allocator_;
[52d025c]675 };
676}
677
678#endif
Note: See TracBrowser for help on using the repository browser.