├── 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 String
String& 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


--------------------------------------------------------------------------------