├── README.md ├── String.cpp ├── String.h └── macros.h /README.md: -------------------------------------------------------------------------------- 1 | # String Class 2 | A simple customisable implementation of a String class that mimics functionality of std::string, including iterators. 3 | 4 | ## Using Statements 5 |
using size_type = size_t; // size_type for positions of char in cstring
6 | using const_pointer = const_iterator;
7 | using pointer = iterator;
8 | using const_reverse_pointer = const_reverse_iterator;
9 | using reverse_pointer = reverse_iterator;
10 |
11 |
12 | ## Constructor
13 | String(); // default constructor
14 | String(const String &); // copy constructor
15 | String(const String& other, size_type pos, size_t len = npos); // substring constructor
16 | String(String &&); // move constructor
17 | String(const char *); // from c-string
18 | String(const char* s, size_t n); // from buffer
19 | String(size_t n, char c);// fill constructor
20 | String(const const_iterator first, const const_iterator second); // range constructor
21 |
22 |
23 | ## Equality operator
24 | String & operator= (const String &); // copy assignment
25 | String & operator = (String &&); // move assignment
26 |
27 |
28 | ## Destructor
29 | ~String();
30 |
31 | ## Iterators
32 | Returns iterator/const_iterator to the first character
33 | iterator begin();
34 | const_iterator begin() const;
35 |
36 | Returns iterator/const_iterator pointing to past-the-end character of the string
37 | iterator end();
38 | const_iterator end() const;
39 |
40 | Returns const_iterator pointing to the first character / past-the-end character of the string
41 | const_iterator cbegin() const;
42 | const_iterator cend() const;
43 |
44 | Returns reverse_iterator/const_reverse_iterator to the last character
45 | reverse_iterator rbegin();
46 | const_reverse_iterator rbegin() const;
47 |
48 | Returns reverse_iterator/const_reverse_iterator pointing to reverse past-the-end character of the string
49 | reverse_iterator rend();
50 | const_reverse_iterator rend() const;
51 |
52 | Returns const_reverse_iterator pointing to the last character / reverse past-the-end character of the string
53 | const_reverse_iterator crbegin() const;
54 | const_reverse_iterator crend() const;
55 |
56 |
57 | ## Element access
58 | Get character of string
59 | const char & operator [] (size_type) const;
60 | char & operator [] (size_type);
61 |
62 | Get character in string
63 | const char & at(size_type) const;
64 | char & at(size_type);
65 |
66 | Access first character
67 | const char & front() const;
68 | char & front();
69 |
70 | Access last character
71 | const char & back() const;
72 | char & back();
73 |
74 |
75 | ## Modifiers
76 | Append to String
77 | String & operator += (const String &); // string (1)
78 | String & operator += (const char *); // c - string (2)
79 | String & operator += (char); // char (3)
80 |
81 | Append to StringString& append(const String& str); // string (1)
82 | String& append(const String& str, size_type subpos, size_t sublen = npos); // substring (2)
83 | String& append(const char* s); // c - string (3)
84 | String& append(const char* s, size_t n); // buffer(4)
85 | String& append(size_type n, char c); // fill(5)
86 | String& append(const const_iterator first, const const_iterator second); // range(6)
87 |
88 | Append character to string
89 | String & push_back(char);
90 |
91 | Insert into string
92 | String& insert(size_type pos, const String& other); // string(1)
93 | String& insert(size_type pos, const String& other, size_type subpos, size_t sublen = npos); // substring(2)
94 | String& insert(size_type pos, const char* other); // c - string(3)
95 | String& insert(size_type pos, const char* s, size_t n); // buffer(4)
96 | String& insert(size_type pos, size_t n, char c); // fill(5)
97 | void insert(iterator p, size_t n, char c); // fill(6)
98 | iterator insert(iterator p, char c); // single character(7)
99 | void insert(iterator p, const const_iterator first, const const_iterator last); // range(8)
100 |
101 | Erase characters from string
102 | String& erase(size_type pos = 0, size_t len = npos); // sequence(1)
103 | iterator erase(const_iterator p); // character(2)
104 | iterator erase(const_iterator first, const_iterator last); // range(3)
105 |
106 | Replace portion of string
107 | String& replace(size_type pos, size_t len, const String& other); // string(1)
108 | String& replace(const_iterator i1, const_iterator i2, const String& other); // string(2)
109 | String& replace(size_type pos, size_t len, const String& other, size_type subpos, size_t sublen = npos); // substring(3)
110 | String& replace(size_type pos, size_t len, const char* s); // c - string(4)
111 | String& replace(const_iterator i1, const_iterator i2, const char* other); // c - string(5)
112 | String& replace(size_type pos, size_t len, const char* other, size_t n); // buffer(6)
113 | String& replace(const_iterator i1, const_iterator i2, const char* other, size_t n); // buffer(7)
114 | String& replace(size_type pos, size_t len, size_t n, char c); // fill(8)
115 | String& replace(const_iterator i1, const_iterator i2, size_type n, char c); // fill(9)
116 | String& replace(const_iterator i1, const_iterator i2, const_iterator first, const_iterator second); // range(10)
117 |
118 | Swap string values
119 | void swap(String &);
120 |
121 | Delete last character
122 | String & pop_back();
123 |
124 |
125 | ## String Operation
126 | Get C string equivalent
127 | const char * c_str() const;
128 |
129 | Copy sequence of characters from string
130 | size_t copy(char* s, size_t len, size_type pos = 0) const;
131 |
132 | Find content in string
133 | size_type find(const String& other, size_type pos = 0) const; //string(1)
134 | size_type find(const char* s, size_type pos = 0) const; // c - string(2)
135 | size_type find(const char* s, size_type pos, size_type n) const; // buffer(3)
136 | size_type find(char c, size_type pos = 0) const; // character(4)
137 |
138 | Find last occurrence of content in string
139 | size_type rfind(const String& other, size_type pos = npos) const; // string(1)
140 | size_type rfind(const char* s, size_type pos = npos) const; // c - string(2)
141 | size_type rfind(const char* s, size_type pos, size_t n) const; // buffer(3)
142 | size_type rfind(char c, size_type pos = npos) const; // character(4)
143 |
144 | Find character in string
145 | size_type find_first_of(const String& other, size_type pos = 0) const; // string(1)
146 | size_type find_first_of(const char* other, size_type pos = 0) const; // c - string(2)
147 | size_type find_first_of(const char* other, size_type pos, size_t n) const; // buffer(3)
148 | size_type find_first_of(char c, size_type pos = 0) const; // character(4)
149 |
150 | Find character in string from the end
151 | size_type find_last_of(const String& other, size_type pos = String::npos) const; // string(1)
152 | size_type find_last_of(const char* other, size_type pos = String::npos) const; // c - string(2)
153 | size_type find_last_of(const char* other, size_type pos, size_t n) const; // buffer(3)
154 | size_type find_last_of(char c, size_type pos = String::npos) const; // character(4)
155 |
156 | Find absence of character in string
157 | size_type find_first_not_of(const String& other, size_type pos = 0) const; // string(1)
158 | size_type find_first_not_of(const char* other, size_type pos = 0) const; // c - string(2)
159 | size_type find_first_not_of(const char* other, size_type pos, size_t n) const; // buffer(3)
160 | size_type find_first_not_of(char c, size_type pos = 0) const; // character(4)
161 |
162 | Find non-matching character in string from the end
163 | size_type find_last_not_of(const String& other, size_type pos = String::npos) const; // string(1)
164 | size_type find_last_not_of(const char* other, size_type pos = String::npos) const; // c - string(2)
165 | size_type find_last_not_of(const char* other, size_type pos, size_t n) const; // buffer(3)
166 | size_type find_last_not_of(char c, size_type pos = String::npos) const; // character(4)
167 |
168 | Generate substring
169 | String substr(size_type pos = 0, size_t len = npos) const;
170 |
171 |
172 | ## Capacity
173 | Returns length of string
174 | size_t length() const;
175 | size_t size() const;
176 |
177 | Returns maximum size of string
178 | size_t max_size() const;
179 |
180 | Resize string
181 | void resize(size_t n);
182 | void resize(size_type n, char c);
183 |
184 | Return size of allocated storage
185 | size_t capacity() const;
186 |
187 | Request a change in capacity
188 | void reserve(size_t n = 0);
189 |
190 | Clear string
191 | void clear();
192 |
193 | Return true is string is empty
194 | bool empty() const;
195 |
196 | Shrink to fit
197 | void shrink_to_fit();
198 |
199 |
200 | ## Member constants
201 | static const size_t npos = -1; // Maximum value for size_t
202 |
203 |
204 | ## Non-member functions overloads
205 |
206 | Comparisions
207 | // Size is compared and if equal then comapred lexicographically
208 | friend bool operator == (const String &, const String &);
209 | friend bool operator != (const String &, const String &);
210 | friend bool operator < (const String &, const String &);
211 | friend bool operator > (const String &, const String &);
212 | friend bool operator <= (const String &, const String &);
213 | friend bool operator >= (const String &, const String &);
214 |
215 | Exchanges the values of two strings
216 | void swap(String& x, String& y);
217 |
218 | Returns concatenated Strings
219 | String operator+ (const String& lhs, const String& rhs);
220 | String operator+ (const String& lhs, const char* rhs);
221 | String operator+ (const char* lhs, const String& rhs);
222 | String operator+ (const String& lhs, char rhs);
223 | String operator+ (char lhs, const String& rhs);
224 |
225 | Insert string into stream
226 | std::ostream& operator<< (std::ostream& os, const _JD String& str);
227 |
228 | Extract string from stream
229 | std::istream& operator>> (std::istream& is, _JD String& str);
230 |
231 | Get line from stream into string
232 | std::istream& getline(std::istream& is, _JD String& str, char delim);
233 | std::istream& getline(std::istream& is, _JD String& str);
234 |
--------------------------------------------------------------------------------
/String.cpp:
--------------------------------------------------------------------------------
1 | #include "String.h"
2 | #include "macros.h"
3 | #include
4 | #include
5 |
6 | _JD_BEGIN
7 |
8 | using size_type = size_t;
9 |
10 | /*
11 | Constructors
12 | */
13 |
14 | String::String() {
15 | _setCapacity(0);
16 | _setLength(0);
17 | }
18 |
19 | String::String(const String & other) {
20 | _append(other._str, other._str_len);
21 | }
22 |
23 | String::String(const String & other, size_type pos, size_t len) {
24 | append(other._str, pos, len);
25 | }
26 |
27 | String::String(String && other) {
28 | *this = std::move(other);
29 | }
30 |
31 | String::String(const char * copy) {
32 | _append(copy);
33 | }
34 |
35 | String::String(const char * s, size_t n) {
36 | append(s, 0, n);
37 | }
38 |
39 | String::String(size_t n, char c) {
40 | append(n, c);
41 | }
42 |
43 | String::String(const String::const_iterator first, const String::const_iterator second) {
44 | append(first, second);
45 | }
46 |
47 | /*
48 | Equality operator overload
49 | */
50 |
51 | String & String::operator= (const String & other) {
52 | if (this != &other) {
53 | _setLength(0);
54 | _append(other._str, other._str_len);
55 | }
56 | return *this;
57 | }
58 |
59 | String & String::operator = (String && other) {
60 | if (this != &other) {
61 | safe_delete(_str);
62 | _str = other._str;
63 | _str_len = other._str_len;
64 | _str_cap = other._str_cap;
65 | other._str = nullptr;
66 | other._str_len = 0;
67 | other._str_cap = 0;
68 | }
69 | return *this;
70 | }
71 |
72 | /*
73 | Destructor
74 | */
75 |
76 | String::~String() {
77 | safe_delete(_str);
78 | _str_len = 0;
79 | _str_cap = 0;
80 | _increaseBy = 0;
81 | }
82 |
83 | /*
84 | Comparision Operators
85 | */
86 |
87 | bool operator == (const String & lhs, const String & rhs) {
88 | return lhs._compare(rhs) == 0;
89 | }
90 |
91 | bool operator != (const String & lhs, const String & rhs) {
92 | return lhs._compare(rhs) != 0;
93 | }
94 |
95 | bool operator < (const String & lhs, const String & rhs) {
96 | return lhs._compare(rhs) < 0;
97 | }
98 |
99 | bool operator > (const String & lhs, const String & rhs) {
100 | return lhs._compare(rhs) > 0;
101 | }
102 |
103 | bool operator <= (const String & lhs, const String & rhs) {
104 | return lhs._compare(rhs) <= 0;
105 | }
106 |
107 | bool operator >= (const String & lhs, const String & rhs) {
108 | return lhs._compare(rhs) >= 0;
109 | }
110 |
111 | // private helper comparision operators functions
112 |
113 | int String::_compare(const String & rhs) const {
114 |
115 | if (_str_len < rhs._str_len)
116 | return 1;
117 | else if (_str_len > rhs._str_len)
118 | return -1;
119 |
120 | return strcmp(_str, rhs._str);
121 | }
122 |
123 | /*
124 | Element access
125 | */
126 |
127 | const char & String::operator [] (size_type i) const {
128 | return *(_str + i);
129 | }
130 |
131 | char & String::operator [] (size_type i) {
132 | return *(_str + i);
133 | }
134 |
135 | const char & String::at(size_type i) const {
136 | if (i < 0 || _str_len <= i)
137 | throw;
138 | return operator[](i);
139 | }
140 |
141 | char & String::at(size_type i) {
142 | if (i < 0 || _str_len <= i)
143 | throw;
144 | return operator[](i);
145 | }
146 |
147 | const char & String::front() const {
148 | return operator[](0);
149 | }
150 |
151 | char & String::front() {
152 | return operator[](0);
153 | }
154 |
155 | const char & String::back() const {
156 | return operator[](_str_len - 1);
157 | }
158 |
159 | char & String::back() {
160 | return operator[](_str_len - 1);
161 | }
162 |
163 | /*
164 | Modifiers
165 | */
166 |
167 | // operator +=
168 |
169 | String & String::operator += (const String & s) {
170 | _append(s._str, s._str_len);
171 | return *this;
172 | }
173 |
174 | String & String::operator += (const char * s) {
175 | _append(s);
176 | return *this;
177 | }
178 |
179 | String & String::operator += (char c) {
180 | _append(&c, 1);
181 | return *this;
182 | }
183 |
184 | // append
185 |
186 | String & String::append(const String & other)
187 | {
188 | _append(other._str, other._str_len);
189 | return *this;
190 | }
191 |
192 | String & String::append(const String & other, size_type subpos, size_t sublen)
193 | {
194 | sublen = _getLength(other, subpos, sublen);
195 | char * buffer = nullptr;
196 | _substr(buffer, other._str, subpos, sublen);
197 | _append(buffer, sublen);
198 | safe_delete(buffer);
199 | return *this;
200 | }
201 |
202 | String & String::append(const char * other)
203 | {
204 | _append(other);
205 | return *this;
206 | }
207 |
208 | String & String::append(const char * s, size_t n)
209 | {
210 | char * buffer = nullptr;
211 | _substr(buffer, s, 0, n);
212 | _append(buffer, n);
213 | safe_delete(buffer);
214 | return *this;
215 | }
216 |
217 | String & String::append(size_type n, char c)
218 | {
219 | char * buffer = nullptr;
220 | _alloc_cstring(buffer, n, c);
221 | _append(buffer, n);
222 | safe_delete(buffer);
223 | return *this;
224 | }
225 |
226 | String & String::append(const String::const_iterator first, const String::const_iterator second)
227 | {
228 | const size_t n = _getLength(first, second);
229 | if (n != 0) { // if length is not zero then _append
230 | char * buffer = nullptr;
231 | _alloc_cstring(buffer, n, first, second);
232 | _append(buffer, n);
233 | safe_delete(buffer);
234 | }
235 | return *this;
236 | }
237 |
238 | // push_back
239 |
240 | String & String::push_back(char c) {
241 | _append(&c, 1);
242 | return *this;
243 | }
244 |
245 | // insert
246 |
247 | String& String::insert(size_type pos, const String& other) {
248 | _insert_str(pos, other._str, other._str_len);
249 | return *this;
250 | }
251 |
252 | String & String::insert(size_type pos, const String & other, size_type subpos, size_t sublen)
253 | {
254 | sublen = _getLength(other, subpos, sublen);
255 | char * buffer = nullptr;
256 | _substr(buffer, other._str, subpos, sublen);
257 | _insert_str(pos, buffer, sublen);
258 | safe_delete(buffer);
259 | return *this;
260 | }
261 |
262 | String& String::insert(size_type pos, const char* other) {
263 | _insert_str(pos, other);
264 | return *this;
265 | }
266 |
267 | String & String::insert(size_type pos, const char * s, size_t n)
268 | {
269 | char * buffer = nullptr;
270 | _substr(buffer, s, 0, n);
271 | _insert_str(pos, buffer, n);
272 | safe_delete(buffer);
273 | return *this;
274 | }
275 |
276 | String & String::insert(size_type pos, size_t n, char c)
277 | {
278 | char * buffer = nullptr;
279 | _alloc_cstring(buffer, n, c);
280 | _insert_str(pos, buffer, n);
281 | safe_delete(buffer);
282 | return *this;
283 | }
284 |
285 | void String::insert(iterator p, size_t n, char c)
286 | {
287 | char * buffer = nullptr;
288 | _alloc_cstring(buffer, n, c);
289 | _insert_str(p.current.pos, buffer, n);
290 | safe_delete(buffer);
291 | }
292 |
293 | String::iterator String::insert(String::iterator p, char c)
294 | {
295 | _insert_str(p.current.pos, &c, 1);
296 | return p;
297 | }
298 |
299 | void String::insert(String::iterator p, const String::const_iterator first, const String::const_iterator second)
300 | {
301 | const size_t n = _getLength(first, second);
302 | if (n == 0) // if length is zero then do nothing
303 | return;
304 | char * buffer = nullptr;
305 | _alloc_cstring(buffer, n, first, second);
306 | _insert_str(p.current.pos, buffer, n);
307 | safe_delete(buffer);
308 | }
309 |
310 | // erase
311 |
312 | String& String::erase(size_type pos, size_t len) { // sequence(1)
313 | _erase(pos, len);
314 | return *this;
315 | }
316 |
317 | String::iterator String::erase(String::const_iterator p) { // character(2)
318 | _erase(p.current.pos, 1);
319 | return p.current;
320 | }
321 |
322 | String::iterator String::erase(String::const_iterator first, String::const_iterator last) { // range(3)
323 | _erase(first.current.pos, _getLength(first, last));
324 | return first.current;
325 | }
326 |
327 | // replace
328 |
329 | String& String::replace(size_type pos, size_t len, const String& other) {
330 | _replace(pos, len, other._str, other._str_len);
331 | return *this;
332 | }
333 |
334 | String& String::replace(String::const_iterator i1, String::const_iterator i2, const String& other) {
335 | replace(i1.current.pos, _getLength(i1, i2), other._str, other._str_len);
336 | return *this;
337 | }
338 |
339 | String& String::replace(size_type pos, size_t len, const String& other, size_type subpos, size_t sublen) {
340 | sublen = _getLength(other, subpos, sublen);
341 | char * buffer = nullptr;
342 | _substr(buffer, other._str, subpos, sublen);
343 | _replace(pos, len, buffer, strlen(buffer));
344 | safe_delete(buffer);
345 | return *this;
346 | }
347 |
348 | String& String::replace(size_type pos, size_t len, const char* s) {
349 | _replace(pos, len, s, strlen(s));
350 | return *this;
351 | }
352 |
353 | String& String::replace(const_iterator i1, const_iterator i2, const char* other) {
354 | _replace(i1.current.pos, _getLength(i1, i2), other, strlen(other));
355 | return *this;
356 | }
357 |
358 | String& String::replace(size_type pos, size_t len, const char* other, size_t n) {
359 | _replace(pos, len, other, n);
360 | return *this;
361 | }
362 |
363 | String& String::replace(const_iterator i1, const_iterator i2, const char* other, size_t n) {
364 | _replace(i1.current.pos, _getLength(i1, i2), other, n);
365 | return *this;
366 | }
367 |
368 | String& String::replace(size_type pos, size_t len, size_t n, char c) {
369 | char * buffer = nullptr;
370 | _alloc_cstring(buffer, n, c);
371 | _replace(pos, len, buffer, n);
372 | safe_delete(buffer);
373 | return *this;
374 | }
375 |
376 | String& String::replace(const_iterator i1, const_iterator i2, size_type n, char c) {
377 | char * buffer = nullptr;
378 | _alloc_cstring(buffer, n, c);
379 | _replace(i1.current.pos, _getLength(i1, i2), buffer, n);
380 | safe_delete(buffer);
381 | return *this;
382 | }
383 |
384 | // swap
385 |
386 | void String::swap(String & other) {
387 | String temp = std::move(*this);
388 | *this = std::move(other);
389 | other = std::move(temp);
390 | }
391 |
392 | // pop_back
393 |
394 | String & String::pop_back() {
395 | _erase((end() - 1).current.pos, 1);
396 | return *this;
397 | }
398 |
399 | String& String::replace(String::const_iterator i1, String::const_iterator i2,
400 | String::const_iterator first, String::const_iterator second) {
401 |
402 | const size_t n = _getLength(first, second);
403 | char * buffer = nullptr;
404 | _alloc_cstring(buffer, n, first, second);
405 | _replace(i1.current.pos, _getLength(i1, i2), buffer, n);
406 | safe_delete(buffer);
407 | return *this;
408 | }
409 |
410 | // private helper string modifier functions
411 |
412 | inline void String::_append(const char * other) {
413 | return _append(other, strlen(other));
414 | }
415 |
416 | void String::_append(const char * other, size_t n)
417 | {
418 | if (!other || n == 0) // if other is null or size is 0 do nothing
419 | return;
420 | _increaseCapacity(_str_len + n);
421 | size_type i = 0;
422 | for (; i < n; ++i)
423 | operator[](_str_len + i) = other[i];
424 | operator[](_str_len + i) = '\0';
425 | _setLength(_str_len + n);
426 | }
427 |
428 | void String::_insert_str(size_type pos, const char * other) {
429 | if (other != nullptr)
430 | _insert_str(pos, other, strlen(other));
431 | }
432 |
433 | void String::_insert_str(size_type pos, const char * other, size_t n)
434 | {
435 | if (pos == _str_len) // if pos is _str_len then append
436 | return _append(other, n);
437 |
438 | if (pos > _str_len) { // if pos is bigger than size then throw
439 | throw;
440 |
441 | }
442 |
443 | if (n == 0) // if other is null or empty then do nothing
444 | return;
445 |
446 | _increaseCapacity(_str_len + n); // increase capacity to hold new length
447 |
448 | if (_str) {
449 | char * buffer = nullptr;
450 | _substr(buffer, _str, pos, _str_len); // store third part of string
451 | _clear_str(pos); // string contains only first part
452 | _append(other, n); // append second (new) part to string
453 | _append(buffer, strlen(buffer)); // append thrid part to string
454 | safe_delete(buffer); // freeMemory used
455 | }
456 | else
457 | _append(other, n); // cat other to _str
458 | }
459 |
460 | void String::_substr(char * & buffer, const char * other, size_type pos, size_t len) const
461 | {
462 |
463 | if (other == nullptr) {
464 | throw;
465 | }
466 | _alloc_cstring(buffer, len);
467 | for (size_type i = 0; i < len; ++i)
468 | buffer[i] = other[pos + i];
469 | }
470 |
471 | void String::_erase(size_type pos, size_t len)
472 | {
473 | len = _getLength(*this, pos, len);
474 | for (size_t i = pos+ len; i < _str_len; ++i)
475 | operator[](i - len) = operator[](i);
476 | _clear_str(_str_len - len); // only first part of string
477 | }
478 |
479 | void String::_replace(size_type pos, size_t len, const char * other, size_t n)
480 | {
481 | len = _getLength(*this, pos, len); // get length
482 | char * buffer = nullptr;
483 | _substr(buffer, _str, pos + len, _str_len); // store third part of string
484 | _clear_str(pos); // first part of string
485 | char * replace_buffer = nullptr;
486 | _substr(replace_buffer, other, 0, n); // store second part of string
487 | _append(replace_buffer); // append second part of string
488 | _append(buffer); // append third part of string
489 | // free memory
490 | safe_delete(replace_buffer);
491 | safe_delete(buffer);
492 | }
493 |
494 | size_t String::_getLength(const String & str, size_type pos, size_t len) const {
495 | if (len == npos)
496 | len = _str_len - pos;
497 |
498 | if (pos + len > str._str_len) {
499 | throw;
500 | }
501 | return len;
502 | }
503 |
504 | /*
505 | String Operations
506 | */
507 |
508 | // c_string
509 |
510 | const char * String::c_str() const {
511 | return _str;
512 | }
513 |
514 | // copy
515 |
516 | size_t String::copy(char* s, size_t len, size_type pos) const {
517 | if (!s)
518 | throw;
519 | len = _getLength(*this, pos, len);
520 | for (size_type i = 0; i < len; ++i)
521 | *(s + i) = operator[](pos + i);
522 | return len;
523 | }
524 |
525 | // find
526 |
527 | size_t String::find(const String& other, size_type pos) const { //string(1)
528 | return _find(other._str, other._str_len, pos);
529 | }
530 |
531 | size_t String::find(const char* s, size_type pos) const { // c - string(2)
532 | return _find(s, strlen(s), pos);
533 | }
534 |
535 | size_t String::find(const char* s, size_type pos, size_type n) const { // buffer(3)
536 | return _find(s, n, pos);
537 | }
538 |
539 | size_t String::find(char c, size_type pos) const { // character(4)
540 | return _find(&c, 1, pos);
541 | }
542 |
543 | // reverse find
544 |
545 | size_t String::rfind(const String& other, size_type pos) const { // string(1)
546 | return _rfind(other._str, other._str_len, pos);
547 | }
548 |
549 | size_t String::rfind(const char* s, size_type pos) const { // c - string(2)
550 | return _rfind(s, strlen(s), pos);
551 | }
552 |
553 | size_t String::rfind(const char* s, size_type pos, size_t n) const { // buffer(3)
554 | return _rfind(s, n, pos);
555 | }
556 |
557 | size_t String::rfind(char c, size_type pos) const { // character(4)
558 | return _rfind(&c, 1, pos);
559 | }
560 |
561 | // find_first_of
562 |
563 | size_t String::find_first_of(const String& other, size_type pos) const { // string(1)
564 | return _find_first_of(other._str, other._str_len, pos, true);
565 | }
566 |
567 | size_t String::find_first_of(const char* other, size_type pos) const { // c - string(2)
568 | return _find_first_of(other, strlen(other), pos, true);
569 | }
570 |
571 | size_t String::find_first_of(const char* other, size_type pos, size_t n) const { // buffer(3)
572 | return _find_first_of(other, n, pos, true);
573 | }
574 |
575 | size_t String::find_first_of(char c, size_type pos) const { // character(4)
576 | return _find_first_of(&c, 1, pos, true);
577 | }
578 |
579 | // find_last_of
580 |
581 | size_t String::find_last_of(const String& other, size_type pos) const { // string(1)
582 | return _find_last_of(other._str, other._str_len, pos, true);
583 | }
584 |
585 | size_t String::find_last_of(const char* other, size_type pos) const { // c - string(2)
586 | return _find_last_of(other, strlen(other), pos, true);
587 | }
588 |
589 | size_t String::find_last_of(const char* other, size_type pos, size_t n) const { // buffer(3)
590 | return _find_last_of(other, n, pos, true);
591 | }
592 |
593 | size_t String::find_last_of(char c, size_type pos) const { // character(4)
594 | return _find_last_of(&c, 1, pos, true);
595 | }
596 |
597 | // find_first_not_of
598 |
599 | size_t String::find_first_not_of(const String& other, size_type pos) const { // string(1)
600 | return _find_first_of(other._str, other._str_len, pos, false);
601 | }
602 |
603 | size_t String::find_first_not_of(const char* other, size_type pos) const { // c - string(2)
604 | return _find_first_of(other, strlen(other), pos, false);
605 | }
606 |
607 | size_t String::find_first_not_of(const char* other, size_type pos, size_t n) const { // buffer(3)
608 | return _find_first_of(other, n, pos, false);
609 | }
610 |
611 | size_t String::find_first_not_of(char c, size_type pos) const { // character(4)
612 | return _find_first_of(&c, 1, pos, false);
613 | }
614 |
615 | // find_last_not_of
616 |
617 | size_t String::find_last_not_of(const String& other, size_type pos) const { // string(1)
618 | return _find_last_of(other._str, other._str_len, pos, false);
619 | }
620 |
621 | size_t String::find_last_not_of(const char* other, size_type pos) const { // c - string(2)
622 | return _find_last_of(other, strlen(other), pos, false);
623 | }
624 |
625 | size_t String::find_last_not_of(const char* other, size_type pos, size_t n) const { // buffer(3)
626 | return _find_last_of(other, n, pos, false);
627 | }
628 |
629 | size_t String::find_last_not_of(char c, size_type pos) const { // character(4)
630 | return _find_last_of(&c, 1, pos, false);
631 | }
632 |
633 | // substring
634 |
635 | String String::substr(size_type pos, size_t len) const
636 | {
637 | len = _getLength(*this, pos, len);
638 | char * buffer = nullptr;
639 | _substr(buffer, _str, pos, len);
640 | String toReturn(buffer);
641 | safe_delete(buffer);
642 | return toReturn;
643 | }
644 |
645 | // private helper String Operations functions
646 |
647 | size_t String::_find(const char * other, size_t len, size_type pos) const {
648 | size_t toReturn = npos;
649 | if (pos == npos)
650 | pos = _str_len - 1;
651 | for (; pos <= _str_len - len; ++pos)
652 | if (operator[](pos) == *other && _find_compare(other, len, pos)) {
653 | toReturn = pos;
654 | break;
655 | }
656 | return toReturn;
657 | }
658 |
659 | size_t String::_rfind(const char * other, size_t len, size_type pos) const {
660 | size_t toReturn = npos;
661 | if (pos == npos || pos + len > _str_len + 1)
662 | pos = _str_len - len + 1;
663 |
664 | for (int i = pos; 0 <= i; --i)
665 | if (operator[](i) == *other && _find_compare(other, len, i)) {
666 | toReturn = i;
667 | break;
668 | }
669 | return toReturn;
670 | }
671 |
672 | bool String::_find_compare(const char * other, size_t len, size_type pos) const {
673 | for (size_type i = 1; i < len; ++i)
674 | if (operator[](pos + i) != *(other + i))
675 | return false;
676 | return true;
677 | }
678 |
679 | size_t String::_find_first_of(const char * other, size_t len, size_type pos, bool isTrue) const {
680 | size_t toReturn = npos;
681 | if (pos == npos)
682 | pos = _str_len - 1;
683 |
684 | for (; pos < _str_len; ++pos)
685 | if (_find_of_compare(other, len, pos, isTrue)) {
686 | toReturn = pos;
687 | break;
688 | }
689 | return toReturn;
690 | }
691 |
692 | size_t String::_find_last_of(const char * other, size_t len, size_type pos, bool isTrue) const {
693 | size_t toReturn = npos;
694 | if (pos == npos)
695 | pos = _str_len - 1;
696 |
697 | for (int i = pos; 0 <= i; --i)
698 | if (_find_of_compare(other, len, i, isTrue)) {
699 | toReturn = i;
700 | break;
701 | }
702 | return toReturn;
703 | }
704 |
705 | bool String::_find_of_compare(const char *other, size_t len, size_type pos, bool isTrue) const {
706 | for (size_type i = 0; i < len; ++i)
707 | if (operator[](pos) == *(other + i))
708 | return isTrue; // isTrue ? true : false;
709 | return !isTrue; // isTrue ? false : true;
710 | }
711 |
712 | /*
713 | Data Management
714 | */
715 |
716 | size_t String::length() const {
717 | return _str_len;
718 | }
719 |
720 | inline size_t String::size() const {
721 | return length();
722 | }
723 |
724 | size_t String::max_size() const {
725 | return String::npos -1;
726 | }
727 |
728 | void String::resize(size_t n) {
729 | if (_str_len == n) return; // length already allocated
730 | if (_str_len < n) {
731 | _setLength(n);
732 | return;
733 | }
734 | _clear_str(n); // clear string from n onwards
735 | }
736 |
737 | void String::resize(size_type n, char c) {
738 | if (_str_len == n) return; // length already allocated
739 | if (_str_len < n) {
740 | size_type pos = _str_len;
741 | _setLength(n);
742 | _fill_str(_str, _str_len, pos, c);
743 | return;
744 | }
745 | _clear_str(n); // clear string from n onwards
746 | }
747 |
748 | size_t String::capacity() const {
749 | return _str_cap;
750 | }
751 |
752 | void String::reserve(size_t n) {
753 | if (_str_cap == n) return;
754 | if (_str_cap < n) {
755 | _setCapacity(n);
756 | return;
757 | }
758 | // reduce size only if capacity is twice the size of length
759 | if (_str_cap / 2 > _str_len) {
760 | _decreaseCapacity(_str_cap / 2);
761 | }
762 | }
763 |
764 | void String::clear() {
765 | _clear_str(0);
766 | }
767 |
768 | bool String::empty() const {
769 | return _str_len ? false : true;
770 | }
771 |
772 | void String::shrink_to_fit() {
773 | _decreaseCapacity(_str_len);
774 | }
775 |
776 | // private data management functions
777 |
778 | void String::_setLength(const size_t len) {
779 | if (_str_len > len) // space already allocated
780 | _clear_str(len);
781 | else if (_str_cap < len) // length is greater than capacity
782 | _increaseCapacity(len); // allocate memory, increase capacity
783 | _str_len = len;
784 | }
785 |
786 | void String::_setCapacity(const size_t cap) {
787 | if (_str_cap == cap && _str) // capacity set already
788 | return;
789 | if (cap < _str_len) // capacity less than length
790 | return;
791 | _str_cap = cap; // set capacity
792 |
793 | char * buffer = _str; // store _str
794 | _str = nullptr; // set str nullptr
795 | _alloc_cstring(_str, _str_cap); // allocate memory
796 | if (buffer) { // if temp_str is not null then strcpy
797 | for (size_type i = 0; i < _str_len; ++i)
798 | operator[](i) = buffer[i];
799 | operator[](_str_len) = '\0';
800 | }
801 | safe_delete(buffer);
802 | }
803 |
804 | void String::_increaseCapacity(const size_t n) {
805 | if (_str_cap > n && _str)
806 | return;
807 | // Increase Capacity Calculation
808 | size_t cap = _str_cap;
809 | while (cap <= n)
810 | cap += _increaseBy;
811 | _increaseBy++;
812 |
813 | _setCapacity(cap); // increase Capacity
814 | }
815 |
816 | void String::_decreaseCapacity(const size_t cap) {
817 | if (_str_cap < cap)
818 | return; // if capacity greater than current capacity then do nothing
819 | // Algrorith to decrease increase by
820 | if (_increaseBy > 15)
821 | --_increaseBy;
822 | _setCapacity(cap);
823 | }
824 |
825 | void String::_alloc_cstring(char * &buffer, const size_t n) const
826 | {
827 | if (buffer)
828 | throw;
829 | buffer = new char[n + 1]();
830 | }
831 |
832 | void String::_alloc_cstring(char * &buffer, const size_t n, char c) const
833 | {
834 | _alloc_cstring(buffer, n);
835 | _fill_str(buffer, n, 0, c);
836 | }
837 |
838 | void String::_alloc_cstring(char * &buffer, const size_t n, const String::const_iterator i1, const String::const_iterator i2) const {
839 | _alloc_cstring(buffer, n);
840 | String::const_iterator begin = i1;
841 | for (size_type i = 0; i < n; ++i)
842 | buffer[i] = *begin++;
843 | }
844 |
845 | void String::_fill_str(char * other, const size_t len, const size_type pos, char c) const
846 | {
847 | size_type begin = pos;
848 | while (begin != len)
849 | other[begin++] = c;
850 | other[begin] = '\0';
851 | }
852 |
853 | void String::_clear_str(const size_type pos) {
854 | _fill_str(_str, _str_len, pos, '\0');
855 | _str_len = pos;
856 | }
857 |
858 | /*
859 | String iterator
860 | */
861 |
862 | String::iterator String::begin() {
863 | return _ibegin();
864 | }
865 |
866 | String::const_iterator String::begin() const {
867 | return _ibegin();
868 | }
869 |
870 | String::iterator String::end() {
871 | return _end();
872 | }
873 |
874 | String::const_iterator String::end() const {
875 | return _end();
876 | }
877 |
878 | String::const_iterator String::cbegin() const {
879 | return _ibegin();
880 | }
881 |
882 | String::const_iterator String::cend() const {
883 | return _end();
884 | }
885 |
886 | // Not tested -> currently private
887 |
888 | String::reverse_iterator String::rbegin() {
889 | return _rbegin();
890 | }
891 | String::const_reverse_iterator String::rbegin() const {
892 | return _rbegin();
893 | }
894 |
895 | String::reverse_iterator String::rend() {
896 | return _end();
897 | }
898 |
899 | String::const_reverse_iterator String::rend() const {
900 | return _end();
901 | }
902 |
903 | String::const_reverse_iterator String::crbegin() const {
904 | return _rbegin();
905 | }
906 |
907 | String::const_reverse_iterator String::crend() const {
908 | return _end();
909 | }
910 |
911 | // private string iterator
912 |
913 | inline String::String_iterator_type String::_ibegin() const {
914 | return String_iterator_type(_str, &_str_len, 0);
915 | }
916 |
917 | inline String::String_iterator_type String::_end() const {
918 | return String_iterator_type(_str, &_str_len, _str_len);
919 | }
920 |
921 | inline String::String_iterator_type String::_rbegin() const {
922 | return String_iterator_type(_str, &_str_len, _str_len-1);
923 | }
924 |
925 | size_t String::_getLength(const String::const_iterator first, const String::const_iterator second) {
926 | if (first.current.first != second.current.first) {
927 | throw;
928 | }
929 | if (first.current.pos > second.current.pos) {
930 | throw;
931 | }
932 | return second.current.pos - first.current.pos;
933 | }
934 |
935 | /*
936 | const_iterator
937 | */
938 |
939 | String::const_iterator::const_iterator() {}
940 |
941 | String::const_iterator::const_iterator(String_iterator_type p) : current(p) {}
942 |
943 | const char & String::const_iterator::operator[](int i) const
944 | {
945 | return _randomAccess(i);
946 | }
947 |
948 | const char & String::const_iterator::operator* () const {
949 | return retrieve();
950 | }
951 |
952 | String::const_iterator& String::const_iterator::operator++ () {
953 | _increment();
954 | return *this;
955 | }
956 |
957 | String::const_iterator String::const_iterator::operator++ (int) {
958 | const_iterator old = *this;
959 | _increment();
960 | return old;
961 | }
962 |
963 | String::const_iterator & String::const_iterator::operator-- () {
964 | _decrement();
965 | return *this;
966 | }
967 |
968 | String::const_iterator String::const_iterator::operator-- (int) {
969 | const_iterator old = *this;
970 | _decrement();
971 | return old;
972 | }
973 |
974 | bool String::const_iterator::operator == (const String::const_iterator & rhs) const {
975 | return current.first == rhs.current.first && current.pos == rhs.current.pos;
976 | }
977 |
978 | bool String::const_iterator::operator != (const String::const_iterator & rhs) const {
979 | return !(*this == rhs);
980 | }
981 |
982 | String::const_iterator String::const_iterator::operator+ (size_type i) {
983 | const_iterator toReturn;
984 | _add(toReturn, i);
985 | return toReturn;
986 | }
987 |
988 | String::const_iterator String::const_iterator::operator- (size_type i) {
989 | const_iterator toReturn;
990 | _subtract(toReturn, i);
991 | return toReturn;
992 | }
993 |
994 | // protected const_iterator function
995 |
996 | char & String::const_iterator::retrieve() const {
997 | return *(current.first + current.pos);
998 | }
999 |
1000 | void String::const_iterator::_increment() {
1001 | if (current.pos > *current.size) {
1002 | throw;
1003 | }
1004 | ++current.pos;
1005 | }
1006 |
1007 | void String::const_iterator::_decrement() {
1008 | if (current.pos == 0) {
1009 | throw;
1010 | }
1011 | --current.pos;
1012 | }
1013 |
1014 | char& String::const_iterator::_randomAccess(size_type i) const
1015 | {
1016 | if (i < 0 || i >= *current.size) {
1017 | throw;
1018 | }
1019 | return *(current.first + i);
1020 | }
1021 |
1022 | void String::const_iterator::_add(const_iterator & toReturn, size_type i) {
1023 | if (current.pos + i > *current.size) { // beyond end
1024 | throw;
1025 | }
1026 | toReturn = *this;
1027 | toReturn.current.pos += i;
1028 | }
1029 |
1030 | void String::const_iterator::_subtract(const_iterator& toReturn, size_type i) {
1031 | if (current.pos < i) { // if pos will be less than zero
1032 | throw;
1033 | }
1034 | toReturn = *this;
1035 | toReturn.current.pos -= i;
1036 | }
1037 |
1038 | /*
1039 | iterator
1040 | */
1041 |
1042 | String::iterator::iterator() : _myBase() {}
1043 |
1044 | String::iterator::iterator(String_iterator_type p) : _myBase(p) {}
1045 |
1046 | char & String::iterator::operator[](int i)
1047 | {
1048 | return _myBase::_randomAccess(i);
1049 | }
1050 |
1051 | const char & String::iterator::operator[](int i) const
1052 | {
1053 | return _myBase::operator[](i);
1054 | }
1055 |
1056 | char & String::iterator::operator* () {
1057 | return _myBase::retrieve();
1058 | }
1059 |
1060 | const char & String::iterator::operator* () const {
1061 | return _myBase::operator*();
1062 | }
1063 |
1064 | String::iterator& String::iterator::operator++ () {
1065 | _myBase::_increment();
1066 | return *this;
1067 | }
1068 |
1069 | String::iterator String::iterator::operator++ (int) {
1070 | iterator old = *this;
1071 | _myBase::_increment();
1072 | return old;
1073 | }
1074 |
1075 | String::iterator & String::iterator::operator-- () {
1076 | _myBase::_decrement();
1077 | return *this;
1078 | }
1079 |
1080 | String::iterator String::iterator::operator-- (int) {
1081 | iterator old = *this;
1082 | _myBase::_decrement();
1083 | return old;
1084 | }
1085 |
1086 | String::iterator String::iterator::operator+ (size_type i) {
1087 | iterator toReturn;
1088 | _add(toReturn, i);
1089 | return toReturn;
1090 | }
1091 |
1092 | String::iterator String::iterator::operator- (size_type i) {
1093 | iterator toReturn;
1094 | _subtract(toReturn, i);
1095 | return toReturn;
1096 | }
1097 |
1098 | /*
1099 | const_reverse_iterator Private
1100 | */
1101 |
1102 | String::const_reverse_iterator::const_reverse_iterator() : _myBase() {}
1103 |
1104 | String::const_reverse_iterator::const_reverse_iterator(String_iterator_type p) : _myBase(p) {}
1105 |
1106 | const char & String::const_reverse_iterator::operator[](int i) const
1107 | {
1108 | return _myBase::operator[](i);
1109 | }
1110 |
1111 | const char & String::const_reverse_iterator::operator* () const {
1112 | return _myBase::operator*();
1113 | }
1114 |
1115 | String::const_reverse_iterator& String::const_reverse_iterator::operator++ () {
1116 | _increment();
1117 | return *this;
1118 | }
1119 |
1120 | String::const_reverse_iterator String::const_reverse_iterator::operator++ (int) {
1121 | const_reverse_iterator old = *this;
1122 | _increment();
1123 | return old;
1124 | }
1125 |
1126 | String::const_reverse_iterator & String::const_reverse_iterator::operator-- () {
1127 | _decrement();
1128 | return *this;
1129 | }
1130 |
1131 | String::const_reverse_iterator String::const_reverse_iterator::operator-- (int) {
1132 | const_reverse_iterator old = *this;
1133 | _decrement();
1134 | return old;
1135 | }
1136 |
1137 | String::const_reverse_iterator String::const_reverse_iterator::operator+ (size_type i) {
1138 | const_reverse_iterator toReturn;
1139 | _add(toReturn, i);
1140 | return toReturn;
1141 | }
1142 |
1143 | String::const_reverse_iterator String::const_reverse_iterator::operator- (size_type i) {
1144 | const_reverse_iterator toReturn;
1145 | _subtract(toReturn, i);
1146 | return toReturn;
1147 | }
1148 |
1149 | // protected functions
1150 |
1151 | void String::const_reverse_iterator::_increment() {
1152 | if (_myBase::current.pos == 0) {
1153 | _myBase::current.pos = *_myBase::current.size;
1154 | return;
1155 | }
1156 | else if (current.pos == *current.size) {
1157 | throw;
1158 | }
1159 | _myBase::_decrement();
1160 | }
1161 |
1162 | void String::const_reverse_iterator::_decrement() {
1163 | if (current.pos == *_myBase::current.size) {
1164 | _myBase::current.pos = 0;
1165 | return;
1166 | }
1167 | if (current.pos + 1 == *_myBase::current.size) {
1168 | throw;
1169 | }
1170 | _myBase::_increment();
1171 | }
1172 |
1173 | void String::const_reverse_iterator::_add(const_reverse_iterator & toReturn, size_type i) {
1174 | if (current.pos == *_myBase::current.size && !i) { // at the end and i not equal to 0
1175 | throw;
1176 | }
1177 | if (current.pos == i - 1) { // reached end
1178 | _myBase::current.pos = *_myBase::current.size;
1179 | return;
1180 | }
1181 | else if (current.pos < i -1) // moved past end
1182 | throw;
1183 |
1184 | toReturn = *this;
1185 | toReturn.current.pos -= i;
1186 | }
1187 |
1188 | void String::const_reverse_iterator::_subtract(const_reverse_iterator& toReturn, size_type i) {
1189 | if (*_myBase::current.size <= _myBase::current.pos + i) // moved past reverse first element
1190 | throw;
1191 |
1192 | toReturn = *this;
1193 | toReturn.current.pos += i;
1194 | }
1195 |
1196 | /*
1197 | Reverse iterator
1198 | */
1199 |
1200 | String::reverse_iterator::reverse_iterator() : _myBase() {}
1201 |
1202 | String::reverse_iterator::reverse_iterator(String_iterator_type p) : _myBase(p) {}
1203 |
1204 | char & String::reverse_iterator::operator[](int i)
1205 | {
1206 | return _myBase::_randomAccess(i);
1207 | }
1208 |
1209 | const char & String::reverse_iterator::operator[](int i) const
1210 | {
1211 | return _myBase::operator[](i);
1212 | }
1213 |
1214 | char & String::reverse_iterator::operator* () {
1215 | return _myBase::retrieve();
1216 | }
1217 |
1218 | const char & String::reverse_iterator::operator* () const {
1219 | return _myBase::operator*();
1220 | }
1221 |
1222 | String::reverse_iterator& String::reverse_iterator::operator++ () {
1223 | _myBase::_increment();
1224 | return *this;
1225 | }
1226 |
1227 | String::reverse_iterator String::reverse_iterator::operator++ (int) {
1228 | reverse_iterator old = *this;
1229 | _myBase::_increment();
1230 | return old;
1231 | }
1232 |
1233 | String::reverse_iterator & String::reverse_iterator::operator-- () {
1234 | _myBase::_decrement();
1235 | return *this;
1236 | }
1237 |
1238 | String::reverse_iterator String::reverse_iterator::operator-- (int) {
1239 | reverse_iterator old = *this;
1240 | _myBase::_decrement();
1241 | return old;
1242 | }
1243 |
1244 | String::reverse_iterator String::reverse_iterator::operator+ (size_type i) {
1245 | reverse_iterator toReturn;
1246 | _myBase::_add(toReturn, i);
1247 | return toReturn;
1248 | }
1249 |
1250 | String::reverse_iterator String::reverse_iterator::operator- (size_type i) {
1251 | reverse_iterator toReturn;
1252 | _myBase::_subtract(toReturn, i);
1253 | return toReturn;
1254 | }
1255 |
1256 | /*
1257 | Non Member Function
1258 | */
1259 |
1260 | void swap(String& x, String& y) {
1261 | x.swap(y);
1262 | }
1263 |
1264 | String operator+ (const String& lhs, const String& rhs) {
1265 | String toReturn = lhs;
1266 | toReturn += rhs;
1267 | return toReturn;
1268 | }
1269 |
1270 | String operator+ (const String& lhs, const char* rhs) {
1271 | String toReturn = lhs;
1272 | toReturn += rhs;
1273 | return toReturn;
1274 | }
1275 |
1276 | String operator+ (const char* lhs, const String& rhs) {
1277 | String toReturn = lhs;
1278 | toReturn += rhs;
1279 | return toReturn;
1280 | }
1281 |
1282 | String operator+ (const String& lhs, char rhs) {
1283 | String toReturn = lhs;
1284 | toReturn += rhs;
1285 | return toReturn;
1286 | }
1287 |
1288 | String operator+ (char lhs, const String& rhs) {
1289 | String toReturn = rhs;
1290 | toReturn += lhs;
1291 | return toReturn;
1292 | }
1293 |
1294 | std::ostream& operator<< (std::ostream& os, const _JD String& str) {
1295 | for (size_t i = 0; i < str.length(); ++i)
1296 | os << str[i];
1297 | return os;
1298 | }
1299 |
1300 | std::istream& operator>> (std::istream& is, _JD String& str) {
1301 | str.clear();
1302 | char c;
1303 | do {
1304 | c = is.get();
1305 | if (c == '\n' || c == ' ')
1306 | break;
1307 | str.push_back(c);
1308 | } while (true);
1309 |
1310 | return is;
1311 | }
1312 |
1313 | std::istream& getline(std::istream& is, _JD String& str, char delim) {
1314 | str.clear();
1315 | char c;
1316 | do {
1317 | c = is.get();
1318 | if (c == delim)
1319 | break;
1320 | str.push_back(c);
1321 | } while (true);
1322 | return is;
1323 | }
1324 |
1325 | std::istream& getline(std::istream& is, _JD String& str) {
1326 | return _JD getline(is, str, '\n');
1327 | }
1328 |
1329 | _JD_END
1330 |
--------------------------------------------------------------------------------
/String.h:
--------------------------------------------------------------------------------
1 | #ifndef __JD_STRING__
2 | #define __JD_STRING__
3 |
4 | #include "macros.h"
5 | #include
6 |
7 | _JD_BEGIN
8 |
9 | class String {
10 |
11 | public:
12 | using size_type = size_t; // size_type for positions
13 | static const size_t npos = -1;
14 |
15 | private:
16 |
17 | char * _str = nullptr; // c-string
18 | size_t _str_len = 0; // length
19 | size_t _str_cap = 0; // capacity
20 |
21 | size_t _increaseBy = 15;
22 |
23 |
24 | // iterators
25 |
26 | struct String_iterator_type {
27 | char * first;
28 | const size_t * size;
29 | size_type pos;
30 |
31 | String_iterator_type
32 | (char* f = nullptr, const size_t * s = nullptr, size_type p = 0)
33 | : first(f), size(s), pos(p) {};
34 | };
35 |
36 | public:
37 |
38 | class const_iterator {
39 | public:
40 | const_iterator();
41 | const_iterator(String_iterator_type p);
42 |
43 | const char & operator* () const;
44 | const char & operator[] (int) const;
45 |
46 | const_iterator& operator++ ();
47 | const_iterator operator++ (int);
48 | const_iterator & operator-- ();
49 | const_iterator operator-- (int);
50 |
51 | bool operator == (const const_iterator & rhs) const;
52 | bool operator != (const const_iterator & rhs) const;
53 |
54 | const_iterator operator+ (size_type i);
55 | const_iterator operator- (size_type i);
56 |
57 | protected:
58 | String_iterator_type current;
59 |
60 | char & retrieve() const;
61 | void _increment();
62 | void _decrement();
63 | char& _randomAccess(size_type i) const;
64 | void _add(const_iterator & toReturn, size_type i);
65 | void _subtract(const_iterator& toReturn, size_type i);
66 |
67 | friend class _JD String;
68 | };
69 | class iterator : public const_iterator {
70 | using _myBase = const_iterator;
71 | friend class _JD String;
72 | public:
73 | iterator();
74 | iterator(String_iterator_type p);
75 |
76 | char & operator* ();
77 | const char & operator* () const;
78 | char & operator[] (int);
79 | const char & operator[] (int) const;
80 |
81 | iterator& operator++ ();
82 | iterator operator++ (int);
83 | iterator & operator-- ();
84 | iterator operator-- (int);
85 | iterator operator+ (size_type i);
86 | iterator operator- (size_type i);
87 |
88 | };
89 |
90 | using const_pointer = const_iterator;
91 | using pointer = iterator;
92 |
93 | class const_reverse_iterator: public const_iterator {
94 | using _myBase = const_iterator;
95 | friend class _JD String;
96 | public:
97 | const_reverse_iterator();
98 | const_reverse_iterator(String_iterator_type p);
99 |
100 | const char & operator* () const;
101 | const char & operator[] (int) const;
102 |
103 | const_reverse_iterator& operator++ ();
104 | const_reverse_iterator operator++ (int);
105 | const_reverse_iterator & operator-- ();
106 | const_reverse_iterator operator-- (int);
107 |
108 | const_reverse_iterator operator+ (size_type i);
109 | const_reverse_iterator operator- (size_type i);
110 |
111 | protected:
112 | void _increment();
113 | void _decrement();
114 | void _add(const_reverse_iterator & toReturn, size_type i);
115 | void _subtract(const_reverse_iterator& toReturn, size_type i);
116 |
117 | };
118 | class reverse_iterator : public const_reverse_iterator {
119 | using _myBase = const_reverse_iterator;
120 | friend class _JD String;
121 | public:
122 | reverse_iterator();
123 | reverse_iterator(String_iterator_type p);
124 |
125 | char & operator* ();
126 | const char & operator* () const;
127 | char & operator[] (int);
128 | const char & operator[] (int) const;
129 |
130 | reverse_iterator& operator++ ();
131 | reverse_iterator operator++ (int);
132 | reverse_iterator & operator-- ();
133 | reverse_iterator operator-- (int);
134 | reverse_iterator operator+ (size_type i);
135 | reverse_iterator operator- (size_type i);
136 |
137 | };
138 |
139 | using const_reverse_pointer = const_reverse_iterator;
140 | using reverse_pointer = reverse_iterator;
141 |
142 | // Constructor
143 | public:
144 | String();
145 | String(const String &);
146 | String(const String& other, size_type pos, size_t len = npos);
147 | String(String &&);
148 | String(const char *);
149 | String(const char* s, size_t n);
150 | String(size_t n, char c);
151 | String(const const_iterator first, const const_iterator second);
152 |
153 | // Iterators
154 | public:
155 | iterator begin();
156 | const_iterator begin() const;
157 | iterator end();
158 | const_iterator end() const;
159 | const_iterator cbegin() const;
160 | const_iterator cend() const;
161 |
162 | reverse_iterator rbegin();
163 | const_reverse_iterator rbegin() const;
164 | reverse_iterator rend();
165 | const_reverse_iterator rend() const;
166 | const_reverse_iterator crbegin() const;
167 | const_reverse_iterator crend() const;
168 |
169 | private:
170 | inline String_iterator_type _ibegin() const;
171 | inline String::String_iterator_type _rbegin() const;
172 | inline String_iterator_type _end() const;
173 | size_t _getLength(const const_iterator first, const const_iterator second);
174 |
175 | // Equality operator overload
176 | public:
177 | String & operator= (const String &);
178 | String & operator = (String &&);
179 |
180 | // Destructor
181 | public:
182 | ~String();
183 |
184 |
185 | // Comparision Operators
186 | public:
187 | friend bool operator == (const String &, const String &);
188 | friend bool operator != (const String &, const String &);
189 | friend bool operator < (const String &, const String &);
190 | friend bool operator > (const String &, const String &);
191 | friend bool operator <= (const String &, const String &);
192 | friend bool operator >= (const String &, const String &);
193 |
194 | private:
195 | int _compare(const String & rhs) const;
196 |
197 | // Element access
198 | public:
199 | const char & operator [] (size_type) const;
200 | char & operator [] (size_type);
201 | const char & at(size_type) const;
202 | char & at(size_type);
203 | const char & front() const;
204 | char & front();
205 | const char & back() const;
206 | char & back();
207 |
208 | // Modifiers
209 | public:
210 | String & operator += (const String &); // string (1)
211 | String & operator += (const char *); // c - string (2)
212 | String & operator += (char); // char (3)
213 |
214 | String& append(const String& str); // string (1)
215 | String& append(const String& str, size_type subpos, size_t sublen = npos); // substring (2)
216 | String& append(const char* s); // c - string (3)
217 | String& append(const char* s, size_t n); // buffer(4)
218 | String& append(size_type n, char c); // fill(5)
219 | String& append(const const_iterator first, const const_iterator second); // range(6)
220 |
221 | String & push_back(char);
222 |
223 | String& insert(size_type pos, const String& other); // string(1)
224 | String& insert(size_type pos, const String& other, size_type subpos, size_t sublen = npos); // substring(2)
225 | String& insert(size_type pos, const char* other); // c - string(3)
226 | String& insert(size_type pos, const char* s, size_t n); // buffer(4)
227 | String& insert(size_type pos, size_t n, char c); // fill(5)
228 | void insert(iterator p, size_t n, char c); // fill(6)
229 | iterator insert(iterator p, char c); // single character(7)
230 | void insert(iterator p, const const_iterator first, const const_iterator last); // range(8)
231 |
232 | String& erase(size_type pos = 0, size_t len = npos); // sequence(1)
233 | iterator erase(const_iterator p); // character(2)
234 | iterator erase(const_iterator first, const_iterator last); // range(3)
235 |
236 | String& replace(size_type pos, size_t len, const String& other); // string(1)
237 | String& replace(const_iterator i1, const_iterator i2, const String& other); // string(2)
238 | String& replace(size_type pos, size_t len, const String& other, size_type subpos, size_t sublen = npos); // substring(3)
239 | String& replace(size_type pos, size_t len, const char* s); // c - string(4)
240 | String& replace(const_iterator i1, const_iterator i2, const char* other); // c - string(5)
241 | String& replace(size_type pos, size_t len, const char* other, size_t n); // buffer(6)
242 | String& replace(const_iterator i1, const_iterator i2, const char* other, size_t n); // buffer(7)
243 | String& replace(size_type pos, size_t len, size_t n, char c); // fill(8)
244 | String& replace(const_iterator i1, const_iterator i2, size_type n, char c); // fill(9)
245 | String& replace(const_iterator i1, const_iterator i2, const_iterator first, const_iterator second); // range(10)
246 |
247 | void swap(String &);
248 |
249 | String & pop_back();
250 |
251 | private:
252 | inline void _append(const char *);
253 | void _append(const char *, size_t n);
254 | void _insert_str(size_type pos, const char * other);
255 | void _insert_str(size_type pos, const char * other, size_t n);
256 | void _substr(char * & buffer, const char * other, size_type pos = 0, size_t len = npos) const;
257 | void _erase(size_type pos, size_t size);
258 | void _replace(size_type pos, size_t len, const char * other, size_t n);
259 | size_t _getLength(const String & str, size_type pos, size_t len = npos) const;
260 |
261 | // String Operations
262 | public:
263 | const char * c_str() const;
264 |
265 | size_t copy(char* s, size_t len, size_type pos = 0) const;
266 |
267 | size_type find(const String& other, size_type pos = 0) const; //string(1)
268 | size_type find(const char* s, size_type pos = 0) const; // c - string(2)
269 | size_type find(const char* s, size_type pos, size_type n) const; // buffer(3)
270 | size_type find(char c, size_type pos = 0) const; // character(4)
271 |
272 | size_type rfind(const String& other, size_type pos = npos) const; // string(1)
273 | size_type rfind(const char* s, size_type pos = npos) const; // c - string(2)
274 | size_type rfind(const char* s, size_type pos, size_t n) const; // buffer(3)
275 | size_type rfind(char c, size_type pos = npos) const; // character(4)
276 |
277 | size_type find_first_of(const String& other, size_type pos = 0) const; // string(1)
278 | size_type find_first_of(const char* other, size_type pos = 0) const; // c - string(2)
279 | size_type find_first_of(const char* other, size_type pos, size_t n) const; // buffer(3)
280 | size_type find_first_of(char c, size_type pos = 0) const; // character(4)
281 |
282 | size_type find_last_of(const String& other, size_type pos = String::npos) const; // string(1)
283 | size_type find_last_of(const char* other, size_type pos = String::npos) const; // c - string(2)
284 | size_type find_last_of(const char* other, size_type pos, size_t n) const; // buffer(3)
285 | size_type find_last_of(char c, size_type pos = String::npos) const; // character(4)
286 |
287 | size_type find_first_not_of(const String& other, size_type pos = 0) const; // string(1)
288 | size_type find_first_not_of(const char* other, size_type pos = 0) const; // c - string(2)
289 | size_type find_first_not_of(const char* other, size_type pos, size_t n) const; // buffer(3)
290 | size_type find_first_not_of(char c, size_type pos = 0) const; // character(4)
291 |
292 | size_type find_last_not_of(const String& other, size_type pos = String::npos) const; // string(1)
293 | size_type find_last_not_of(const char* other, size_type pos = String::npos) const; // c - string(2)
294 | size_type find_last_not_of(const char* other, size_type pos, size_t n) const; // buffer(3)
295 | size_type find_last_not_of(char c, size_type pos = String::npos) const; // character(4)
296 |
297 | String substr(size_type pos = 0, size_t len = npos) const;
298 | private:
299 | size_type _find(const char * other, size_t len, size_type pos) const;
300 | size_type _rfind(const char * other, size_t len, size_type pos) const;
301 | bool _find_compare(const char * other, size_t len, size_type pos) const;
302 | size_type _find_first_of(const char * other, size_t len, size_type pos, bool isTrue) const;
303 | size_type _find_last_of(const char * other, size_t len, size_type pos, bool isTrue) const;
304 | bool _find_of_compare(const char *other, size_t len, size_type pos, bool isTrue) const;
305 |
306 | // Data Management
307 | public:
308 | size_t length() const;
309 | inline size_t size() const;
310 | size_t max_size() const;
311 | void resize(size_t n);
312 | void resize(size_type n, char c);
313 | size_t capacity() const;
314 | void reserve(size_t n = 0);
315 | void clear();
316 | bool empty() const;
317 | void shrink_to_fit();
318 |
319 | private:
320 | void _setLength(const size_t len);
321 | void _setCapacity(const size_t cap);
322 | void _increaseCapacity(const size_t cap);
323 | void _decreaseCapacity(const size_t cap);
324 | void _alloc_cstring(char * &buffer,const size_t n) const;
325 | void _alloc_cstring(char * &buffer,const size_t n, char c) const;
326 | void _alloc_cstring(char * &buffer,const size_t n, const const_iterator i1, const const_iterator i2) const;
327 | void _fill_str(char * other, const size_t len, size_type pos, char c) const;
328 | void _clear_str(const size_type pos);
329 |
330 | };
331 |
332 | void swap(String& x, String& y);
333 |
334 | String operator+ (const String& lhs, const String& rhs);
335 | String operator+ (const String& lhs, const char* rhs);
336 | String operator+ (const char* lhs, const String& rhs);
337 | String operator+ (const String& lhs, char rhs);
338 | String operator+ (char lhs, const String& rhs);
339 |
340 |
341 | std::ostream& operator<< (std::ostream& os, const _JD String& str);
342 |
343 | std::istream& operator>> (std::istream& is, _JD String& str);
344 |
345 | std::istream& getline(std::istream& is, _JD String& str, char delim);
346 |
347 | std::istream& getline(std::istream& is, _JD String& str);
348 |
349 | _JD_END
350 |
351 |
352 | #endif // !_JD_STRING
353 |
--------------------------------------------------------------------------------
/macros.h:
--------------------------------------------------------------------------------
1 | #ifndef __JD_DEFINE
2 | #define __JD_DEFINE
3 |
4 | #define _JD_BEGIN namespace jd {
5 | #define _JD_END }
6 | #define _JD jd::
7 | #define _USING_JD using namespace jd;
8 |
9 | #define safe_delete(x) { delete x; x = nullptr; }
10 |
11 | #include
12 | #include
13 |
14 |
15 | #endif // !__JD_DEFINE
--------------------------------------------------------------------------------