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 
23 {
24  m_string = new char[STRING_DEFAULT_SIZE];
25  m_string[0] = ZERO;
26  m_allocated = true;
28  m_count = 0;
30 }
31 
32 String::String(const String & str)
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 
42 String::String(char *str, const bool copy)
43 {
44  m_count = length(str);
46  m_allocated = copy;
48 
49  if (copy)
50  {
51  m_string = new char[m_size];
53  }
54  else
55  m_string = str;
56 }
57 
58 String::String(const char *str, const bool copy)
59 {
60  m_count = length(str);
62  m_allocated = copy;
64 
65  if (copy)
66  {
67  m_string = new char[m_size];
69  }
70  else
71  m_string = (char *) str;
72 }
73 
74 String::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 
115 Size String::length(const char *str)
116 {
117  Size len = 0;
118 
119  while (*str++)
120  len++;
121 
122  return len;
123 }
124 
125 bool 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 
157 bool 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 
165 const char * String::get(const Size position) const
166 {
167  return position < m_count ? m_string + position : ZERO;
168 }
169 
170 const char & String::at(const Size position) const
171 {
172  return m_string[position];
173 }
174 
175 const char String::value(const Size position) const
176 {
177  return m_string[position];
178 }
179 
180 bool 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 
189 bool String::startsWith(const String & prefix) const
190 {
191  return startsWith(prefix.m_string);
192 }
193 
194 bool 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 
210 bool String::endsWith(const String & suffix) const
211 {
212  return endsWith(suffix.m_string);
213 }
214 
215 bool 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 
231 int String::compareTo(const String & str) const
232 {
233  return compareTo(str, true);
234 }
235 
236 int String::compareTo(const String & str, const bool caseSensitive) const
237 {
238  return compareTo(str.m_string, caseSensitive, 0);
239 }
240 
241 int 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 
262 bool String::equals(const String & str) const
263 {
264  return compareTo(str.m_string, true, 0) == 0;
265 }
266 
267 bool 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 
314 String 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;
352  m_string[m_count] = ZERO;
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
365  reserve(m_count);
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
389  reserve(m_count);
390 
391  for (Size i = 0; i < m_count; i++)
393 
394  return (*this);
395 }
396 
398 {
399  // Make sure the string is allocated
400  reserve(m_count);
401 
402  for (Size i = 0; i < m_count; i++)
404 
405  return (*this);
406 }
407 
408 List<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 
416 List<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 
456 long 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 
533 Size 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  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 
610 void 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;
618  m_string[m_count] = ZERO;
619  }
620 }
621 
622 void String::operator = (const String & str)
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;
630  m_string[m_count] = ZERO;
631  }
632 }
633 
634 bool String::operator == (const String & str) const
635 {
636  return compareTo(str, true) == 0;
637 }
638 
639 bool String::operator != (const String & str) const
640 {
641  return compareTo(str, true) != 0;
642 }
643 
644 const char * String::operator * () const
645 {
646  return m_string;
647 }
648 
649 char * String::operator * ()
650 {
651  return m_string;
652 }
653 
654 String & 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;
662  m_string[m_count] = ZERO;
663  }
664  return (*this);
665 }
666 
668 {
669  this->operator << (str.m_string);
670  return (*this);
671 }
672 
673 String & 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 
681 String & String::operator << (const unsigned int number)
682 {
683  if (reserve(m_count + 16))
684  m_count += setUnsigned(number, m_base, m_string + m_count);
685 
686  return (*this);
687 }
688 
689 String & 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 }
Character::isUpper
bool isUpper(char c)
Test for an uppercase letter.
Definition: Character.h:74
String::value
virtual const char value(const Size position) const
Return value at the given position.
Definition: String.cpp:175
copy
void copy(Terminal *term, const teken_rect_t *rect, const teken_pos_t *pos)
Copy bytes to the terminal.
Definition: Terminal.cpp:282
String::upper
String & upper()
Convert all Characters to upper case.
Definition: String.cpp:397
MemoryBlock::copy
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Definition: MemoryBlock.cpp:36
Character.h
String::resize
virtual bool resize(const Size size)
Change the size of the String buffer.
Definition: String.cpp:125
Character::isWildcard
bool isWildcard(char c)
Test for a wildcard character.
Definition: Character.h:50
String::pad
String & pad(const Size length)
Pad line with trailing whitespace.
Definition: String.cpp:332
ulong
unsigned long ulong
Unsigned long number.
Definition: Types.h:47
String::length
Size length() const
Same as count().
Definition: String.cpp:105
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
String::operator==
bool operator==(const String &str) const
Comparision operator.
Definition: String.cpp:634
String
Abstraction of strings.
Definition: String.h:41
LONG_MAX
#define LONG_MAX
Maximum value of an object of type long int.
Definition: Macros.h:66
String::~String
virtual ~String()
Destructor.
Definition: String.cpp:86
String::at
virtual const char & at(const Size position) const
Returns a reference to the item at the given position.
Definition: String.cpp:170
String::set
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
STRING_DEFAULT_SIZE
#define STRING_DEFAULT_SIZE
Default maximum length of a String's value.
Definition: String.h:36
Number::Base
Base
Numeral system base type.
Definition: Types.h:168
Number::Dec
@ Dec
Definition: Types.h:170
MemoryBlock.h
String::get
virtual const char * get(const Size position) const
Returns the item at the given position.
Definition: String.cpp:165
String::compareTo
virtual int compareTo(const String &str) const
Compares this String to the given String.
Definition: String.cpp:231
String::m_base
Number::Base m_base
Number format to use for convertions.
Definition: String.h:460
String::reserve
virtual bool reserve(const Size count)
Make sure at least given number of bytes available.
Definition: String.cpp:157
String::lower
String & lower()
Convert all Characters to lower case.
Definition: String.cpp:386
Character::isDigit
bool isDigit(char c)
Test for a decimal digit.
Definition: Character.h:38
String::split
List< String > split(const char delimiter) const
Split the String into parts separated by a delimiter.
Definition: String.cpp:408
String::String
String()
Default constructor.
Definition: String.cpp:22
String::operator*
const char * operator*() const
Dereference operator (read-only).
Definition: String.cpp:644
String::contains
virtual bool contains(const char character) const
Check if the given character occurs in the String.
Definition: String.cpp:180
String::match
bool match(const char *mask) const
Matches the String against a mask.
Definition: String.cpp:267
String::count
virtual Size count() const
Number of characters in the string.
Definition: String.cpp:100
List::append
void append(T t)
Insert an item at the end of the list.
Definition: List.h:139
Character::isAlpha
bool isAlpha(char c)
Test for an alphabetic character.
Definition: Character.h:86
Character::isWhitespace
bool isWhitespace(char c)
Test for a white-space character.
Definition: Character.h:122
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
String::trim
String & trim()
Remove leading and trailing whitespace from the String.
Definition: String.cpp:357
LONG_MIN
#define LONG_MIN
Minimum value of an object of type long int.
Definition: Macros.h:63
String::operator!=
bool operator!=(const String &str) const
Inequal operator.
Definition: String.cpp:639
String::substring
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<<
String & operator<<(const char *str)
Append character string to the String.
Definition: String.cpp:654
String::m_string
char * m_string
Current value of the String.
Definition: String.h:448
String::size
virtual Size size() const
Calculates the length of the String.
Definition: String.cpp:95
String::m_count
Size m_count
Length of the string text, excluding NULL byte(s) at the end.
Definition: String.h:454
Character::upper
char upper(char c)
Converts the letter c to uppercase.
Definition: Character.h:147
String.h
Character::lower
char lower(char c)
Converts the letter c to lowercase.
Definition: Character.h:135
String::endsWith
bool endsWith(const String &suffix) const
Tests if this String ends with the specified suffix.
Definition: String.cpp:210
String::m_size
Size m_size
Size of the string buffer, including any NULL byte(s) at the end.
Definition: String.h:451
String::operator=
void operator=(const char *str)
Assignment operator.
Definition: String.cpp:610
String::startsWith
bool startsWith(const String &prefix) const
Tests if this String starts with the specified prefix.
Definition: String.cpp:189
List< String >
String::equals
virtual bool equals(const String &str) const
Alias for compareTo().
Definition: String.cpp:262
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
Number::Hex
@ Hex
Decimal: 0-10.
Definition: Types.h:171
String::toLong
long toLong(const Number::Base base=Number::Dec) const
Convert the String to a signed long integer.
Definition: String.cpp:456
length
u32 length
Definition: IntelACPI.h:64
String::setUnsigned
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
String::m_allocated
bool m_allocated
True if the string buffer is a deep copy, false otherwise.
Definition: String.h:457