FreeNOS
String.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Character.h"
19#include "MemoryBlock.h"
20#include "String.h"
21
31
33{
34 m_size = str.m_size;
35 m_count = str.m_count;
36 m_base = str.m_base;
37 m_string = new char[m_size];
38 m_allocated = true;
40}
41
42String::String(char *str, const bool copy)
43{
44 m_count = length(str);
48
49 if (copy)
50 {
51 m_string = new char[m_size];
53 }
54 else
55 m_string = str;
56}
57
58String::String(const char *str, const bool copy)
59{
60 m_count = length(str);
64
65 if (copy)
66 {
67 m_string = new char[m_size];
69 }
70 else
71 m_string = (char *) str;
72}
73
74String::String(const int number)
75{
76 m_string = new char[STRING_DEFAULT_SIZE];
77 m_string[0] = ZERO;
78 m_allocated = true;
80 m_count = 0;
82
83 set(number);
84}
85
87{
88 if (m_allocated)
89 {
90 delete[] m_string;
91 m_allocated = false;
92 }
93}
94
96{
97 return m_size;
98}
99
101{
102 return m_count;
103}
104
106{
107 return count();
108}
109
111{
112 return length((const char *) str);
113}
114
115Size String::length(const char *str)
116{
117 Size len = 0;
118
119 while (*str++)
120 len++;
121
122 return len;
123}
124
125bool String::resize(const Size size)
126{
127 char *buffer;
128
129 // Refuse zero-sized Strings.
130 if (size == 0)
131 return false;
132
133 // Chop-off String if the current buffer is larger.
134 if (m_count >= size)
135 m_count = size - 1;
136
137 // Allocate buffer
138 buffer = new char[size];
139 if (!buffer)
140 return false;
141
142 // Copy the contents of the old buffer, if any.
143 MemoryBlock::copy(buffer, m_string, m_count + 1);
144 buffer[m_count] = ZERO;
145
146 // Only cleanup the old buffer if it was previously allocated
147 if (m_allocated)
148 delete[] m_string;
149
150 // Update administration
151 m_string = buffer;
152 m_allocated = true;
153 m_size = size;
154 return true;
155}
156
157bool String::reserve(const Size count)
158{
159 if (!m_allocated || count > m_size - 1)
160 return resize(count + 1);
161 else
162 return true;
163}
164
165const char * String::get(const Size position) const
166{
167 return position < m_count ? m_string + position : ZERO;
168}
169
170const char & String::at(const Size position) const
171{
172 return m_string[position];
173}
174
175const char String::value(const Size position) const
176{
177 return m_string[position];
178}
179
180bool String::contains(const char character) const
181{
182 for (Size i = 0; i < m_count - 1; i++)
183 if (m_string[i] == character)
184 return true;
185
186 return false;
187}
188
189bool String::startsWith(const String & prefix) const
190{
191 return startsWith(prefix.m_string);
192}
193
194bool String::startsWith(const char *prefix) const
195{
196 Size len = length(prefix);
197
198 // If the prefix is larger than the String itself, it cannot match.
199 if (!len || len > m_count)
200 return false;
201
202 // Compare against the prefix
203 for (Size i = 0; i < len; i++)
204 if (m_string[i] != prefix[i])
205 return false;
206
207 return true;
208}
209
210bool String::endsWith(const String & suffix) const
211{
212 return endsWith(suffix.m_string);
213}
214
215bool String::endsWith(const char *suffix) const
216{
217 Size len = length(suffix);
218
219 // If the suffix is larger than the String itself, it cannot match
220 if (!len || len > m_count)
221 return false;
222
223 // Compare against the suffix.
224 for (Size i = m_count - len, j = 0; i < m_count; i++, j++)
225 if (m_string[i] != suffix[j])
226 return false;
227
228 return true;
229}
230
231int String::compareTo(const String & str) const
232{
233 return compareTo(str, true);
234}
235
236int String::compareTo(const String & str, const bool caseSensitive) const
237{
238 return compareTo(str.m_string, caseSensitive, 0);
239}
240
241int String::compareTo(const char *str,
242 const bool caseSensitive,
243 const Size count) const
244{
245 const char *dest = m_string, *src = str;
246 Size n = count;
247
248 while (*dest && *src)
249 {
250 if (count && n-1 == 0)
251 break;
252
253 if (( caseSensitive && *dest != *src) ||
254 (!caseSensitive && Character::lower(*dest) != Character::lower(*src)))
255 break;
256
257 dest++, src++, n--;
258 }
259 return *dest - *src;
260}
261
262bool String::equals(const String & str) const
263{
264 return compareTo(str.m_string, true, 0) == 0;
265}
266
267bool String::match(const char *mask) const
268{
269 const char *string = m_string;
270 const char *end = ZERO;
271
272 while (*string && *mask)
273 {
274 if (Character::isWildcard(*mask))
275 {
276 // Skip extra wildcards
277 while (Character::isWildcard(*mask))
278 mask++;
279
280 // Find end of the string after the mask, if any.
281 for (end = mask; *end && !Character::isWildcard(*end); end++)
282 ;
283
284 // If the wildcard was last, its a match.
285 if (mask == end)
286 return true;
287
288 // Move the string forward until a match
289 for (; *string; string++)
290 {
291 const char *s = string, *m = mask;
292
293 while (*s && *m && *s == *m)
294 s++, m++;
295
296 if (m == end)
297 {
298 break;
299 }
300 }
301 }
302 else if (*string != *mask)
303 break;
304
305 if (*string) string++;
306 if (*mask) mask++;
307 }
308 while (Character::isWildcard(*mask))
309 mask++;
310
311 return (*string == *mask);
312}
313
314String String::substring(const Size index, const Size size) const
315{
316 // Make sure index we copy from is within bounds.
317 const Size from = index >= m_count ? m_count : index;
318
319 // Copy the string
320 String str(m_string + from);
321
322 // Set a ZERO byte at the right place, if needed.
323 if (size && size < m_count - from)
324 {
325 str.m_string[size] = ZERO;
326 str.m_count = size;
327 }
328
329 return str;
330}
331
333{
334 Size idx = 0;
335
336 // Look for the last newline character
337 for (Size i = 0; i < m_count; i++)
338 if (m_string[i] == '\n')
339 idx = i;
340
341 // Last line length
342 Size curlen = m_count - (idx+1);
343
344 // Skip if the line is already the given length
345 if (length <= curlen)
346 return (*this);
347
348 if (reserve(m_count + length - curlen))
349 {
350 MemoryBlock::set(m_string + idx + curlen + 1, ' ', length-curlen);
351 m_count += length-curlen;
353 }
354 return (*this);
355}
356
358{
359 Size from = 0, to = m_count - 1;
360
361 if (!m_count)
362 return (*this);
363
364 // Make sure the string is allocated
366
367 // Skip before
368 for (Size i = 0; i < m_count - 1; i++, from++)
370 break;
371
372 // Skip after
373 for (Size i = m_count - 1; i > 0; i--, to--)
375 break;
376
377 // Copy actual string content
378 if (from < to)
379 {
380 MemoryBlock::copy(m_string, m_string + from, to-from+2);
381 m_count = to - from + 1;
382 }
383 return (*this);
384}
385
387{
388 // Make sure the string is allocated
390
391 for (Size i = 0; i < m_count; i++)
393
394 return (*this);
395}
396
398{
399 // Make sure the string is allocated
401
402 for (Size i = 0; i < m_count; i++)
404
405 return (*this);
406}
407
408List<String> String::split(const char delimiter) const
409{
410 const char str[] = { delimiter, ZERO };
411 const String s(str);
412
413 return split(s);
414}
415
416List<String> String::split(const String & delimiter) const
417{
418 List<String> lst;
420 Size from = 0, i = 0;
421
422 // Save copy string pointer
423 char *saved = copy.m_string;
424
425 // Loop the String.
426 while (i < m_count)
427 {
428 // Find delimiter
429 if (copy.compareTo(delimiter.m_string, true, delimiter.m_count) == 0)
430 {
431 copy.m_string += delimiter.m_count;
432
433 if (i > from)
434 {
435 String sub = substring(from, i - from);
436 lst.append(sub);
437 }
438 from = i + delimiter.m_count;
439 i += delimiter.m_count;
440 }
441 else
442 copy.m_string++, i++;
443 }
444 // Append last part, if no more delimiters found
445 if (from < m_count)
446 {
447 String sub = substring(from);
448 lst.append(sub);
449 }
450
451 // Restore saved
452 copy.m_string = saved;
453 return lst;
454}
455
456long String::toLong(const Number::Base base) const
457{
458 const char *s = m_string;
459 long acc = 0, cutoff;
460 bool negative = false;
461 int cutlim, basenum = 10;
462
463 // Set the number base
464 switch (base)
465 {
466 case Number::Dec: basenum = 10; break;
467 case Number::Hex: basenum = 16; break;
468 }
469
470 // Skip whitespace
471 while (Character::isWhitespace(*s))
472 s++;
473
474 // Negative number?
475 if (s[0] == '-')
476 {
477 negative = true; s++;
478 }
479
480 // Skip '0x' prefix
481 if (basenum == 16 && s[0] == '0' && s[1] == 'x')
482 s += 2;
483
484 // Compute output range limits
485 cutoff = negative ? LONG_MIN : LONG_MAX;
486 cutlim = cutoff % basenum;
487 cutoff /= basenum;
488
489 if (negative) {
490 if (cutlim > 0) {
491 cutlim -= base;
492 cutoff += 1;
493 }
494 cutlim = -cutlim;
495 }
496
497 while (1)
498 {
499 unsigned char c = (unsigned char) *s++;
500
501 if (Character::isDigit(c))
502 c -= '0';
503 else if (Character::isAlpha(c))
504 c -= Character::isUpper(c) ? 'A' - 10 : 'a' - 10;
505 else
506 break;
507
508 if (c >= basenum)
509 break;
510
511 if (negative)
512 {
513 if (acc < cutoff || (acc == cutoff && c > cutlim))
514 {
515 acc = LONG_MIN;
516 } else {
517 acc *= basenum;
518 acc -= c;
519 }
520 } else {
521 if (acc > cutoff || (acc == cutoff && c > cutlim))
522 {
523 acc = LONG_MAX;
524 } else {
525 acc *= basenum;
526 acc += c;
527 }
528 }
529 }
530 return acc;
531}
532
533Size String::set(const long number, const Number::Base base, char *string)
534{
535 return setUnsigned((const ulong) number, base, string, true);
536}
537
539 const Number::Base base,
540 char *string,
541 const bool sign)
542{
543 volatile char *p, *p1, *p2, *saved, tmp;
544 unsigned long ud = number;
545 int remainder, divisor = 10;
546 Size written = 0;
547
548 // If needed, make sure enough allocated space is available.
549 if (!string)
551
552 // Set target buffer
553 p = string ? string : m_string;
554
555 // Set divider according to the number system base.
556 switch (base)
557 {
558 case Number::Dec: divisor = 10; break;
559 case Number::Hex: divisor = 16; break;
560 };
561
562 // Negative prefix.
563 if (sign && (long)number < 0)
564 {
565 *p++ = '-';
566 ud = -number;
567 written++;
568 }
569 // Add '0x' prefix for hexadecimal numbers
570 if (base == Number::Hex)
571 {
572 *p++ = '0';
573 *p++ = 'x';
574 written += 2;
575 }
576 saved = p;
577
578 // Divide ud by the divisor, until ud == 0
579 do
580 {
581 remainder = ud % divisor;
582 *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
583 }
584 while (ud /= divisor);
585
586 // Terminate buffer
587 *p = 0;
588
589 // Initialize pointers
590 p1 = saved;
591 p2 = p - 1;
592 written += p2-p1+1;
593
594 // Reverse buf
595 while (p1 < p2)
596 {
597 tmp = *p1;
598 *p1 = *p2;
599 *p2 = tmp;
600 p1++;
601 p2--;
602 }
603 // Update String administration, if needed.
604 if (!string)
605 m_count = written;
606
607 return written;
608}
609
610void String::operator = (const char *s)
611{
612 Size len = length(s);
613
614 if (reserve(len))
615 {
616 MemoryBlock::copy(m_string, s, len + 1);
617 m_count = len;
619 }
620}
621
623{
624 Size len = length(str.m_string);
625
626 if (reserve(len))
627 {
628 MemoryBlock::copy(m_string, str.m_string, len + 1);
629 m_count = len;
631 }
632}
633
634bool String::operator == (const String & str) const
635{
636 return compareTo(str, true) == 0;
637}
638
639bool String::operator != (const String & str) const
640{
641 return compareTo(str, true) != 0;
642}
643
644const char * String::operator * () const
645{
646 return m_string;
647}
648
650{
651 return m_string;
652}
653
654String & String::operator << (const char *str)
655{
656 Size len = length(str);
657
658 if (reserve(m_count + len))
659 {
660 MemoryBlock::copy(m_string + m_count, str, len + 1);
661 m_count += len;
663 }
664 return (*this);
665}
666
668{
669 this->operator << (str.m_string);
670 return (*this);
671}
672
673String & String::operator << (const int number)
674{
675 if (reserve(m_count + 16))
676 m_count += set(number, m_base, m_string + m_count);
677
678 return (*this);
679}
680
681String & String::operator << (const unsigned int number)
682{
683 if (reserve(m_count + 16))
685
686 return (*this);
687}
688
689String & String::operator << (const void *ptr)
690{
691 if (reserve(m_count + 16))
692 m_count += setUnsigned((const unsigned long) ptr, Number::Hex, m_string + m_count);
693
694 return (*this);
695}
696
698{
699 m_base = base;
700 return (*this);
701}
u32 length
Definition IntelACPI.h:1
Simple linked list template class.
Definition List.h:37
void append(T t)
Insert an item at the end of the list.
Definition List.h:139
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Abstraction of strings.
Definition String.h:42
const char * operator*() const
Dereference operator (read-only).
Definition String.cpp:644
Number::Base m_base
Number format to use for convertions.
Definition String.h:460
bool startsWith(const String &prefix) const
Tests if this String starts with the specified prefix.
Definition String.cpp:189
virtual Size count() const
Number of characters in the string.
Definition String.cpp:100
String & trim()
Remove leading and trailing whitespace from the String.
Definition String.cpp:357
Size m_size
Size of the string buffer, including any NULL byte(s) at the end.
Definition String.h:451
long toLong(const Number::Base base=Number::Dec) const
Convert the String to a signed long integer.
Definition String.cpp:456
virtual bool equals(const String &str) const
Alias for compareTo().
Definition String.cpp:262
String substring(const Size index, const Size size=0) const
Returns a part of the String as a copy.
Definition String.cpp:314
String & operator<<(const char *str)
Append character string to the String.
Definition String.cpp:654
Size length() const
Same as count().
Definition String.cpp:105
Size setUnsigned(const ulong number, const Number::Base base=Number::Dec, char *string=ZERO, const bool sign=false)
Set text-representation of an unsigned number.
Definition String.cpp:538
virtual bool reserve(const Size count)
Make sure at least given number of bytes available.
Definition String.cpp:157
Size set(const long number, const Number::Base base=Number::Dec, char *string=ZERO)
Set text-representation of a signed number.
Definition String.cpp:533
virtual bool contains(const char character) const
Check if the given character occurs in the String.
Definition String.cpp:180
virtual const char * get(const Size position) const
Returns the item at the given position.
Definition String.cpp:165
bool endsWith(const String &suffix) const
Tests if this String ends with the specified suffix.
Definition String.cpp:210
char * m_string
Current value of the String.
Definition String.h:448
String()
Default constructor.
Definition String.cpp:22
virtual Size size() const
Calculates the length of the String.
Definition String.cpp:95
String & lower()
Convert all Characters to lower case.
Definition String.cpp:386
void operator=(const char *str)
Assignment operator.
Definition String.cpp:610
String & pad(const Size length)
Pad line with trailing whitespace.
Definition String.cpp:332
bool operator==(const String &str) const
Comparision operator.
Definition String.cpp:634
Size m_count
Length of the string text, excluding NULL byte(s) at the end.
Definition String.h:454
virtual int compareTo(const String &str) const
Compares this String to the given String.
Definition String.cpp:231
virtual ~String()
Destructor.
Definition String.cpp:86
bool operator!=(const String &str) const
Inequal operator.
Definition String.cpp:639
List< String > split(const char delimiter) const
Split the String into parts separated by a delimiter.
Definition String.cpp:408
String & upper()
Convert all Characters to upper case.
Definition String.cpp:397
virtual const char & at(const Size position) const
Returns a reference to the item at the given position.
Definition String.cpp:170
bool match(const char *mask) const
Matches the String against a mask.
Definition String.cpp:267
bool m_allocated
True if the string buffer is a deep copy, false otherwise.
Definition String.h:457
virtual const char value(const Size position) const
Return value at the given position.
Definition String.cpp:175
virtual bool resize(const Size size)
Change the size of the String buffer.
Definition String.cpp:125
#define STRING_DEFAULT_SIZE
Default maximum length of a String's value.
Definition String.h:36
#define LONG_MAX
Maximum value of an object of type long int.
Definition Macros.h:66
unsigned long ulong
Unsigned long number.
Definition Types.h:47
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#define ZERO
Zero value.
Definition Macros.h:43
#define LONG_MIN
Minimum value of an object of type long int.
Definition Macros.h:63
void copy(Terminal *term, const teken_rect_t *rect, const teken_pos_t *pos)
Copy bytes to the terminal.
Definition Terminal.cpp:282
bool isAlpha(char c)
Test for an alphabetic character.
Definition Character.h:86
char upper(char c)
Converts the letter c to uppercase.
Definition Character.h:147
bool isWildcard(char c)
Test for a wildcard character.
Definition Character.h:50
bool isDigit(char c)
Test for a decimal digit.
Definition Character.h:38
bool isWhitespace(char c)
Test for a white-space character.
Definition Character.h:122
bool isUpper(char c)
Test for an uppercase letter.
Definition Character.h:74
char lower(char c)
Converts the letter c to lowercase.
Definition Character.h:135
Base
Numeral system base type.
Definition Types.h:169
@ Hex
Decimal: 0-10.
Definition Types.h:171
@ Dec
Definition Types.h:170