rvm  1.11
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
estring.cc
Go to the documentation of this file.
1 #include "config.h"
2 
3 #include <iostream>
4 #include <string>
5 #include <cstdio>
6 #include <cctype>
7 #include <string.h>
8 
9 #include "asserts.h"
10 #include "types.h"
11 #include "error.h"
12 #include "estring.h"
13 
14 //----------------------------------------------------------------------------
15 
17 {
18  clear();
19 }
20 
22 {
23  memset(static_cast<void*>(&value), 0, sizeof(value));
24 }
25 
27 {
28  value = a_estring_value.value;
29 
30  return(*this);
31 }
32 
33 //----------------------------------------------------------------------------
34 
35 /** Alphabet used for base number conversions
36  */
37 
38 const char * estring::m_alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
39 
40 /** The length of the alphabet used for base number conversions
41  */
42 const size_t estring::m_alphabet_len = 36;
43 
44 /** Helper member template function to convert an integral type to an estring.
45 
46  Integrals are converted to string form using a default base of 10 unless
47  specified otherwise through the base() member function. For bases greater
48  than ten the letters of the alphabet are used, starting with 'a' for eleven,
49  'b' for twelve, etc.
50 
51  Variables:
52  - a_t - the integral type. Usually uint8, uint16, uint32, or uint64.
53  - a_str - the std::string object in which to store the string converstion.
54 
55  Exceptions:
56  - An err_nomem is thrown for memory allocation failure.
57  */
58 template <class T>
59 void estring::T_integral_to_string(const T& a_t, value_type& a_str)
60 {
61  T num = a_t;
62  int digit;
63  char ch;
64 
65  ASSERT(a_t >= 0);
66  ASSERT(m_base >= 2);
68 
69  TRY_nomem(a_str = "");
70  if (a_t == 0) {
71  TRY_nomem(a_str = "0");
72  return;
73  }
74  while (num > 0) {
75  digit = num % m_base;
76  ch = m_alphabet[digit];
77  TRY_nomem(a_str = ch + a_str);
78  num /= m_base;
79  }
80 }
81 
82 /** Helper member template function to convert a fractional type to an estring.
83 
84  Fractions are converted to string form using a default base of 10 unless
85  specified otherwise through the base() member function. For bases greater
86  than ten the letters of the alphabet are used, starting with 'a' for eleven,
87  'b' for twelve, etc.
88 
89  By default a precision of 1 digit to the right of the decimal point is used
90  unless specified otherwise by the precision() member function.
91 
92  Variables:
93  - a_t - the fractional type: float or double.
94  - a_ws - the std::string object in which to store the whole part.
95  - a_fs - the std::string object in which to store the fractional part.
96 
97  Exceptions:
98  - An err_nomem is thrown for memory allocation failure.
99  */
100 template <class T>
102  value_type& a_ws, value_type& a_fs)
103 {
104  T fraction = a_t;
105  uint64 rounded;
106  bool negative = false;
107  uint64 whole_part;
108  uint64 fractional_part;
109  uint64 multiplier;
110  size_type c;
111  int digit;
112  char ch;
113 
114  ASSERT(m_base >= 2);
116 
117  TRY_nomem(a_ws = "");
118  TRY_nomem(a_fs = "");
119 
120  if (fraction < 0.0) {
121  negative = true;
122  fraction = -fraction;
123  }
124 
125  multiplier = m_base;
126  for (c = 0; c < m_precision; c++) {
127  multiplier *= m_base;
128  }
129 
130  rounded = static_cast<uint64>(fraction * multiplier);
131  fractional_part = rounded % multiplier;
132  whole_part = rounded / multiplier;
133 
134  if ((fractional_part % m_base) + (m_base/2) >= m_base) {
135  fractional_part += m_base/2;
136  if (fractional_part > (fractional_part % multiplier)) {
137  whole_part++;
138  }
139  fractional_part %= multiplier;
140  }
141 
142  if (whole_part == 0) {
143  TRY_nomem(a_ws = "0");
144  }
145  else {
146  while (whole_part > 0) {
147  digit = whole_part % m_base;
148  ch = m_alphabet[digit];
149  TRY_nomem(a_ws = ch + a_ws);
150  whole_part /= m_base;
151  }
152  }
153 
154  fractional_part /= m_base;
155  if (fractional_part == 0) {
156  TRY_nomem(a_fs = "0");
157  }
158  else {
159  while (fractional_part > 0) {
160  digit = fractional_part % m_base;
161  ch = m_alphabet[digit];
162  TRY_nomem(a_fs = ch +a_fs);
163  fractional_part /= m_base;
164  }
165  }
166  if (a_fs.size() > m_precision) {
167  a_fs.erase(m_precision);
168  }
169  for (c = a_fs.size(); c < m_precision; c++) {
170  TRY_nomem(a_fs += "0");
171  }
172 
173  if (negative) {
174  TRY_nomem(a_ws = "-" + a_ws);
175  }
176 }
177 
178 /** Helper member template function to convert a string to an integral type.
179 
180  Characters in the string are converted using a default base of 10 unless
181  specified otherwise through the base() member function. For bases greater
182  than ten the letters of the alphabet will be assumed, starting with 'a' for
183  eleven, 'b' for twelve, etc.
184 
185  Variables:
186  - a_str - the std::string object from which to convert.
187  - a_t - a variable of the integral type to which to convert.
188 
189  Exceptions:
190  - An err_nomem is thrown for memory allocation failure.
191  - If a symbol is encountered in the string that is not expected then an
192  invalid character or invalid base error is thrown.
193  - If the type to which to convert the string is not large enough to hold
194  the value of the converted string then an overflow error is thrown.
195  */
196 template<class T>
197 void estring::T_string_to_integral(const value_type& a_str, T& a_t) const
198 {
199  value_type::const_iterator stri;
200  T value = 0;
201  T digit = 0;
202  T overflow_check_1 = 0;
203  T overflow_check_2 = 0;
204  value_type es;
205  value_type alphabet;
206  size_type idx;
207  const static size_t buffer_len = 256;
208  char buffer[buffer_len] = { 0 };
209  unsigned int index;
210 
211  ASSERT(m_base >= 2);
213 
214  TRY_nomem(alphabet = m_alphabet);
215  for (stri = a_str.begin(), index = 0;
216  stri != a_str.end();
217  ++stri, ++index
218  )
219  {
220  idx = alphabet.find(*stri);
221  if (idx > m_base) {
222  snprintf(buffer, buffer_len, "%u", index);
223 
224  TRY_nomem(es = "Parse error at index ");
225  TRY_nomem(es += buffer);
226  TRY_nomem(es += " (char '");
227  TRY_nomem(es += *stri);
228  TRY_nomem(es += "')");
229  TRY_nomem(es += " converting \"");
230  TRY_nomem(es += (*this));
231  TRY_nomem(es += "\"");
232  if (idx == value_type::npos) {
233  TRY_nomem(es += ", invalid character");
234  }
235  else {
236  TRY_nomem(es += ", invalid base or invalid string");
237  }
238  throw(ERROR(0,es));
239  }
240 
241  value *= m_base;
242  digit = static_cast<unsigned int>(idx);
243  value += digit;
244 
245  overflow_check_1 *= m_base;
246  overflow_check_1 += 1;
247  if (overflow_check_1 == overflow_check_2) {
248  snprintf(buffer, buffer_len, "%u", index);
249 
250  TRY_nomem(es = "Overflow error at index ");
251  TRY_nomem(es += buffer);
252  TRY_nomem(es += " (char '");
253  TRY_nomem(es += *stri);
254  TRY_nomem(es += "')");
255  TRY_nomem(es += " converting \"");
256  TRY_nomem(es += (*this));
257  TRY_nomem(es += "\" to unsigned int");
258  throw(ERROR(0,es));
259  }
260  overflow_check_2 = overflow_check_1;
261  }
262  a_t = value;
263 }
264 
265 /** Helper member template function to convert a string to a signed integral.
266 
267  Variables:
268  - a_str - the std::string to convert from.
269  - a_t - a variable of the type to convert to.
270 
271  Exceptions:
272  - An err_nomem is thrown for memory allocation failure.
273  - Any exception thrown from the called member template function
274  T_string_to_integral().
275  */
276 template <class T>
278  const
279 {
280  value_type tmp;
281  T value = 0;
282  bool negative = false;
283 
284  if ((value_type::size() > 0) && (this->at(0) == '-')) {
285  negative = true;
286  TRY_nomem(tmp = (*this).substr(1));
287  }
288  else {
289  TRY_nomem(tmp = (*this));
290  }
291  T_string_to_integral(tmp,value);
292  if (negative)
293  value = -value;
294  a_t = value;
295 }
296 
297 /** Helper member template function to convert a string to a fractional.
298 
299  Variables:
300  - a_str - the std::string to convert from.
301  - a_t - a variable of the type to convert to.
302 
303  Exceptions:
304  - An err_nomem is thrown for memory allocation failure.
305  - Any exception thrown by the member template function
306  T_string_to_integral().
307  - An overflow error is thrown if the wole part of the string is too large
308  for the type a_t.
309  - An underflow error is thrown if the fractional part of the string is too
310  large for the type a_t.
311  */
312 template <class T>
313 void estring::T_string_to_fractional(const value_type& a_str, T& a_t) const
314 {
315  value_type es;
316  value_type tmp;
317  value_type whole_string;
318  value_type fractional_string;
319  size_type idx = 0;
320  bool negative = false;;
321  uint64 whole_part_converter = 0;
322  uint64 fractional_part_converter = 0;
323  uint64 fractional_check = 0;
324  T whole_part = 0;
325  T fractional_part = 0;
326  T value =0;
327  unsigned int divisor = 0;
328  unsigned int c = 0;
329 
330  ASSERT(m_base >= 2);
332 
333  if ((value_type::size() > 0) && (this->at(0) == '-')) {
334  negative = true;
335  TRY_nomem(tmp = (*this).substr(1));
336  }
337  else {
338  TRY_nomem(tmp = (*this));
339  }
340 
341  idx = tmp.find('.');
342  if (idx != value_type::npos) {
343  TRY_nomem(whole_string = tmp.substr(0,idx));
344  TRY_nomem(fractional_string = tmp.substr(idx+1));
345  }
346  else {
347  TRY_nomem(whole_string = tmp);
348  TRY_nomem(fractional_string = "");
349  }
350 
351  TRY_nomem(es = "Could not convert whole part of estring \"");
352  TRY_nomem(es += a_str);
353  TRY_nomem(es += "\"");
354  TRY(T_string_to_integral(whole_string, whole_part_converter),es);
355 
356  TRY_nomem(es = "Could not convert fractional part of estring \"");
357  TRY_nomem(es += a_str);
358  TRY_nomem(es += "\"");
359  TRY(T_string_to_integral(fractional_string, fractional_part_converter),es);
360 
361  divisor = 1;
362  for (c = 0; c < fractional_string.size(); c++)
363  divisor *= m_base;
364 
365  whole_part = static_cast<T>(whole_part_converter);
366  if (static_cast<uint64>(whole_part) != whole_part_converter) {
367  TRY_nomem(es = "Overflow error converting whole part of estring \"");
368  TRY_nomem(es += a_str);
369  TRY_nomem(es += "\"");
370  throw(ERROR(0,es));
371  }
372  fractional_part = static_cast<T>(fractional_part_converter)/divisor;
373  fractional_check = static_cast<uint64>(fractional_part*divisor);
374  if (fractional_check != fractional_part_converter) {
375  TRY_nomem(es = "Underflow error converting fractional part of estring \"");
376  TRY_nomem(es += a_str);
377  TRY_nomem(es += "\"");
378  throw(ERROR(0,es));
379  }
380 
381  value = whole_part + fractional_part;
382 
383  if (negative) {
384  value = -value;
385  }
386  a_t = value;
387 }
388 
389 //---------
390 
391 /** Initialize the estring object.
392 
393  Defaults:
394  - A precision of one digit to the right of the decimal.
395  - A base of 10.
396  - A width of 5 characters for formatted printing.
397  - A space as the fill character for padding the left of a string.
398  - A space as the fill character for padding the right of a string.
399  - Initialize the conversion type to type_unknown.
400  */
401 void estring::init(void)
402 {
403  m_precision = 1;
404  m_base = 10;
405  m_width = 5;
406  m_alignment = left;
407  m_left_fillchar = ' ';
408  m_right_fillchar = ' ';
410 }
411 
412 /** Erase the string value.
413  */
414 void estring::clear(void)
415 {
416  value_type::erase();
417 }
418 
419 /** Erase and reinitialize.
420  */
421 void estring::reset(void)
422 {
423  clear();
424  init();
425 }
426 
427 //---------
428 
429 /** Default constructor
430  */
432 {
433  init();
434 }
435 
436 //---------
437 
438 /** Set the width of a formatted string.
439 
440  Variables:
441  - a_l - new width to use for formatting strings.
442 
443  Returns:
444  - size_type - the last width.
445  */
447 {
448  size_type old;
449 
450  old = m_width;
451  m_width = a_l;
452 
453  return(old);
454 }
455 
456 /** Retrieve the set width for formatted strings.
457 
458  Returns:
459  - size_type - the current width.
460  */
462 {
463  return(m_width);
464 }
465 
466 /** Set the alignment used for formatted strings.
467 
468  Vaiables:
469  - a_alignment - the type of alignment to use for formatting strings.
470  */
472 {
473  alignment old;
474 
475  old = m_alignment;
476  m_alignment = a_alignment;
477 
478  return(old);
479 }
480 
481 /** Retrieve the set alignment for formatted strings.
482 
483  Returns:
484  - enum alignment - the current alignment.
485  */
487 {
488  return(m_alignment);
489 }
490 
491 /** Set the precision used in converting to/from fractional types.
492 
493  Variables:
494  - a_p - the number of digits to use to the right of the decimal point when
495  converting fractional types.
496 
497  Returns:
498  - size_type - the last precision.
499 
500  */
502 {
503  size_type old;
504 
505  old = m_precision;
506  m_precision = a_p;
507 
508  if (m_type == type_float)
510  else if (m_type == type_double)
512 
513  return(old);
514 }
515 
516 /** Retrieve the set precision used in fractional conversions.
517 
518  Returns:
519  - size_type - the current precision.
520  */
522 {
523  return(m_precision);
524 }
525 
526 /** Set the base used in numeric conversions.
527 
528  Variables:
529  - a_base - The base to use in converting numbers to/from strings.
530 
531  Return:
532  - const unsigned int - the last base.
533 
534  Exceptions:
535  - An err_nomem is thrown for memory allocation failure.
536  - An invalid base is thrown if the base is smaller than 2 (binary).
537  - A base too large is thrown if the base is larger than the alphabet of
538  usable symbols.
539  */
540 const unsigned int estring::base(const unsigned int a_base)
541 {
542  unsigned int old = m_base;
543  value_type es;
544  char str[255] = { 0 };
545 
546  if (a_base < 2) {
547  sprintf(str, "%u", a_base);
548  TRY_nomem(es = "Invalid base: ");
549  TRY_nomem(es += str);
550  throw(ERROR(0,es));
551  }
552  if (a_base > m_alphabet_len) {
553  sprintf(str, "%u", a_base);
554  TRY_nomem(es = "Base too large: ");
555  TRY_nomem(es += str);
556  throw(ERROR(0,es));
557  }
558  m_base = a_base;
559 
560  if (m_type == type_unsigned_int)
562  if (m_type == type_int)
566  if (m_type == type_short)
568  if (m_type == type_unsigned_long)
570  if (m_type == type_long)
574  if (m_type == type_long_long)
576  if (m_type == type_float)
578  if (m_type == type_double)
580 
581  return(old);
582 }
583 
584 /** Retrieve the base used in numeric conversions.
585 
586  Returns:
587  - const unsigned int - the current numeric base.
588  */
589 const unsigned int estring::base(void) const
590 {
591  return(m_base);
592 }
593 
594 /** Set the fill character used to padd the left side of a formatted string.
595 
596  Variables:
597  - a_char - the character to use as the fill character.
598 
599  Returns:
600  - char - the last fill character.
601 
602  */
603 char estring::left_fillchar(const char a_char)
604 {
605  char old;
606 
607  old = m_left_fillchar;
608  m_left_fillchar = a_char;
609 
610  return(old);
611 }
612 
613 /** Retrieve the fill character used to padd the left side of a formatted
614  string.
615 
616  Returns:
617  - char - the current fill character.
618 
619  */
620 char estring::left_fillchar(void) const
621 {
622  return(m_left_fillchar);
623 }
624 
625 /** Set the fill character used to padd the right side of a formatted string.
626 
627  Variables:
628  - a_char - the character to use as the fill character.
629 
630  Returns:
631  - char - the last fill character.
632 
633  */
634 char estring::right_fillchar(const char a_char)
635 {
636  char old;
637 
638  old = m_right_fillchar;
639  m_right_fillchar = a_char;
640 
641  return(old);
642 }
643 
644 /** Retrieve the fill character used to padd the right side of a formatted
645  string.
646 
647  Returns:
648  - char - the current fill character.
649 
650  */
651 char estring::right_fillchar(void) const
652 {
653  return(m_right_fillchar);
654 }
655 
656 /** Set the fill character used for padding both the left and right side of a
657  formatted string.
658 
659  Variables:
660  - a_char - the character to use as the fill character.
661  */
662 void estring::fillchar(const char a_char)
663 {
664  left_fillchar(a_char);
665  right_fillchar(a_char);
666 }
667 
668 //---------
669 
670 /** Generate a formatted string.
671 
672  Returns:
673  - value_type - a formatted rendition of the current string.
674 
675  If the string being printed is wider than the assigned width then as many as
676  three periods are used ("...") to denote that the contents of the string
677  have been truncated. For strings that use left alignment these three
678  periods are printed on the right-hand side of the string, while showing as
679  many characters on the left as possible beginning with the left-most
680  character. For strings that use right alignment these three periods are
681  printed on the left-hand side of the string, while showing as many
682  characters on the right as possible includingn the right-most character.
683  For strings that are center-aligned as many characters on both the left and
684  the right are printed, including the left-most and the right-most
685  characters, while characters in the center of the string are replaced with
686  the three periods.
687  */
689 {
690  std::string str;
691  std::string lstr;
692  std::string rstr;
693  std::string::size_type c = 0;
694  std::string::size_type c_max = 0;
695  std::string::size_type offset = 0;
696  std::string::size_type length = 0;
697  std::string::size_type l_offset = 0;
698  std::string::size_type r_offset = 0;
699  bool last = true;
700 
701  TRY_nomem(str = "");
702  TRY_nomem(lstr = "");
703  TRY_nomem(rstr = "");
704 
705  if (std::string::size() > m_width) {
706  if (m_alignment == left) {
707  if (m_width >= 3)
708  length = m_width-3;
709  else
710  length = 0;
711  TRY_nomem(str = std::string::substr(0,length) + "...");
712  TRY_nomem(str = str.substr(0,m_width));
713  }
714  else if (m_alignment == right) {
715  if (m_width >= 3)
716  length = m_width-3;
717  else
718  length = 0;
719 
720  offset = std::string::size()-length;
721  TRY_nomem(str = "..." + std::string::substr(offset,length));
722  TRY_nomem(str = str.substr(str.size()-m_width,m_width));
723  }
724  else {
725  if (m_width < 4) {
726  TRY_nomem(str = static_cast<std::string>("....").substr(0,m_width));
727  return(str);
728  }
729 
730  c_max = m_width-3;
731  r_offset = std::string::size()-1;
732  for (c = 0; c < c_max; c++) {
733  if (last) {
734  TRY_nomem(lstr += (*this)[l_offset++]);
735  }
736  else {
737  TRY_nomem(rstr = (*this)[r_offset--] + rstr);
738  }
739  last = !last;
740  }
741 
742  TRY_nomem(str = lstr);
743  TRY_nomem(str += "...");
744  TRY_nomem(str += rstr);
745  }
746  return(str);
747  }
748 
749  TRY_nomem(str = (*this));
750  c_max = m_width - std::string::size();
751  for (c = 0; c < c_max; c++) {
752  if (m_alignment == right) {
753  TRY_nomem(str = m_left_fillchar + str);
754  }
755  else if (m_alignment == left) {
756  TRY_nomem(str += m_right_fillchar);
757  }
758  else {
759  if (last) {
760  TRY_nomem(str += m_right_fillchar);
761  }
762  else {
763  TRY_nomem(str = m_left_fillchar + str);
764  }
765  last = !last;
766  }
767  }
768 
769  return(str);
770 }
771 
772 /** Set all the formatting options.
773 
774  Variables:
775  - a_width - the width of the formatted string.
776  - a_alignment - the alignment used to format the string.
777  - a_left_fill - the character used for left-hand padding.
778  - a_right_fill - the character used for right-hand padding.
779 
780  Returns:
781  - value_type - a formatted rendition of the current string.
782 
783  */
785  const size_type a_width,
786  const alignment a_alignment,
787  const char a_left_fill,
788  const char a_right_fill
789  )
790 {
791  value_type str;
792 
793  width(a_width);
794  align(a_alignment);
795  left_fillchar(a_left_fill);
796  right_fillchar(a_right_fill);
797 
798  str = fmt_str();
799 
800  return(str);
801 }
802 
803 //---------
804 
805 /** Retrieve the type of value being held by this estring.
806 
807  Returns:
808  - set_from_type& - the enumeration of the type of value currently assigned.
809  */
811 {
812  return(m_type);
813 }
814 
815 /** Retrieve the typeless_value being held by this estring.
816 
817  Returns:
818  - typeless_value& - the union that holds the current value.
819 
820  */
822 {
823  return(m_value);
824 }
825 
826 /** Copy constructor for estring objects.
827 
828  Variables:
829  - a_estr - the estring object to copy.
830 
831  Exceptions:
832  - Anything thrown by estring::assign(const estring& a_estr).
833  */
834 estring::estring(const estring& a_estr)
835 {
836  init();
837  assign(a_estr);
838 }
839 
840 /** Assignment for estring objects.
841 
842  Variables:
843  - a_estr - the estring object to copy.
844 
845  Returns:
846  - estring& - a reference to self.
847 
848  Exceptions:
849  - An err_nomem is thrown if memory allocation fails.
850  - It is possible that an "Invalid base" or "Base too large" may be thrown
851  if the estring object is corrupted, but this should never happen.
852 */
854 {
855  TRY_nomem(std::string::assign(a_estr));
856  m_precision = a_estr.m_precision;
857  m_width = a_estr.m_width;
858  m_alignment = a_estr.m_alignment;
861  m_type = a_estr.m_type;
862  m_value = a_estr.m_value;
863 
864  return(*this);
865 }
866 
867 /** Assignment operator for estring objects.
868 
869  Variables:
870  - a_estr - the estring object to copy.
871 
872  Returns:
873  - estring& - a reference to self.
874 
875  Exceptions:
876  - Anything thrown by estring::assign(const estring& a_estr).
877  */
879 {
880  assign(a_estr);
881 
882  return(*this);
883 }
884 
885 /** Convert all characters to lowercase.
886 
887  Returns:
888  - estring& - a reference to self.
889 
890  */
892 {
893  std::string::iterator si;
894 
895  for (si = (*this).begin(); si != (*this).end(); ++si) {
896  (*si) = tolower((*si));
897  }
898 
899  return(*this);
900 }
901 
902 /** Convert all characters to uppercase.
903 
904  Returns:
905  - estring& - a reference to self.
906 
907  */
909 {
910  std::string::iterator si;
911 
912  for (si = (*this).begin(); si != (*this).end(); ++si) {
913  (*si) = toupper((*si));
914  }
915 
916  return(*this);
917 }
918 
919 //---------
920 
921 /** Copy constructor for chars.
922 
923  Exceptions:
924  - Anything thrown by estring::assign(const char& a_char).
925  */
926 estring::estring(const char a_char)
927 {
928  init();
929  assign(a_char);
930 }
931 
932 /** Assignment for chars.
933 
934  Variables:
935  - a_char - the character to assign.
936 
937  Returns:
938  - estring& - a reference to self.
939 
940  Exceptions:
941  - An err_nomem is thrown if memory allocation fails.
942  */
943 estring& estring::assign(const char a_char)
944 {
945  std::string s;
946 
947  TRY_nomem(s = a_char);
948  TRY_nomem(std::string::assign(s));
950 
951  return(*this);
952 }
953 
954 /** Assignment operator for chars
955 
956  Variables:
957  - a_char - the character to assign.
958 
959  Returns:
960  - estring& - a reference to self.
961 
962  Exceptions:
963  - Anything thrown by estring::assign(const char& a_char).
964  */
965 estring& estring::operator=(const char a_char)
966 {
967  assign(a_char);
968 
969  return(*this);
970 }
971 
972 //---------
973 
974 /** Copy constructor for std::string objects.
975 
976  Variables:
977  - a_string - the std::string object to copy.
978 
979  Exceptions:
980  - Anything thrown by estring::assign(const value_type& a_string).
981  */
982 estring::estring(const value_type& a_string)
983 {
984  init();
985  assign(a_string);
986 }
987 
988 /** Assignment for std::string objects.
989 
990  Variables:
991  - a_string - the std::string object to assign.
992 
993  Returns:
994  - estring& - a reference to self.
995 
996  Exceptions:
997  - An err_nomem is thrown if memory allocation fails.
998  */
1000 {
1001  TRY_nomem(std::string::assign(a_string));
1002  m_type = type_string;
1003 
1004  return(*this);
1005 }
1006 
1007 /** Assignment operator for std::string objects.
1008 
1009  Variables:
1010  - a_string - the std::string object to copy.
1011 
1012  Returns:
1013  - estring& - a reference to self.
1014 
1015  Exceptions:
1016  - An err_nomem is thrown if memory allocation fails.
1017  */
1019 {
1020  assign(a_string);
1021 
1022  return(*this);
1023 }
1024 
1025 //---------
1026 
1027 /** Copy constructor for unsigned ints.
1028 
1029  Variables:
1030  - a_int - unsigned int to copy.
1031 
1032  Exceptions:
1033  - Anything thrown by estring::assign(const unsigned int& a_int).
1034  */
1035 estring::estring(const unsigned int a_int)
1036 {
1037  init();
1038  assign(a_int);
1039 }
1040 
1041 /** Assignment for unsigned ints.
1042 
1043  Variables:
1044  - a_int - unsigned int to assign.
1045 
1046  Returns:
1047  - estring& - a reference to self.
1048 
1049  Exceptions:
1050  - err_nomem on memory allocation failure.
1051  - Anything thrown by
1052  T_integral_to_string(const T& a_t, value_type& a_str).
1053  */
1054 estring& estring::assign(const unsigned int a_int)
1055 {
1056  std::string s;
1057 
1058  TRY(T_integral_to_string(a_int,s),
1059  "Could not convert unsigned int to string");
1060  TRY_nomem(std::string::assign(s));
1062  m_value.clear();
1063  m_value.value.ui = a_int;
1064 
1065  return(*this);
1066 }
1067 
1068 /** Assignment operator for unsigned ints.
1069  */
1070 estring& estring::operator=(const unsigned int a_int)
1071 {
1072  assign(a_int);
1073 
1074  return(*this);
1075 }
1076 
1077 /** Implicit conversion operator to an unsigned int.
1078  */
1079 estring::operator unsigned int() const
1080 {
1081  unsigned int value = 0;
1082 
1083  TRY(T_string_to_integral((*this),value),
1084  "Cannot convert string to unsigned int");
1085 
1086  return(value);
1087 }
1088 
1089 //---------
1090 
1091 estring::estring(const int a_int)
1092 {
1093  init();
1094  assign(a_int);
1095 }
1096 
1097 estring& estring::assign(const int a_int)
1098 {
1099  if (a_int < 0) {
1100  TRY(assign(static_cast<unsigned int>(-a_int)),
1101  "Coud not convert signed int to string");
1102  TRY_nomem(std::string::insert(0,"-"));
1103  }
1104  else {
1105  TRY(assign(static_cast<unsigned int>(a_int)),
1106  "Could not convert signed int to string");
1107  }
1108  m_type = type_int;
1109  m_value.clear();
1110  m_value.value.i = a_int;
1111 
1112  return(*this);
1113 }
1114 
1115 estring& estring::operator=(const int a_int)
1116 {
1117  assign(a_int);
1118 
1119  return(*this);
1120 }
1121 
1122 estring::operator int() const
1123 {
1124  int value = 0;
1125 
1126  TRY(T_string_to_signed_integral((*this),value),
1127  "Cannot convert string to signed int");
1128 
1129  return(value);
1130 }
1131 
1132 //---------
1133 
1134 estring::estring(const unsigned short a_short)
1135 {
1136  init();
1137  assign(a_short);
1138 }
1139 
1140 estring& estring::assign(const unsigned short a_short)
1141 {
1142  std::string s;
1143 
1144  TRY(T_integral_to_string(a_short,s),
1145  "Could not convert unsigned short to string");
1146  TRY_nomem(std::string::assign(s));
1148  m_value.clear();
1149  m_value.value.us = a_short;
1150 
1151  return(*this);
1152 }
1153 
1154 estring& estring::operator=(const unsigned short a_short)
1155 {
1156  assign(a_short);
1157 
1158  return(*this);
1159 }
1160 
1161 estring::operator unsigned short() const
1162 {
1163  unsigned short value = 0;
1164 
1165  TRY(T_string_to_integral((*this),value),
1166  "Cannot convert string to unsigned short");
1167 
1168  return(value);
1169 }
1170 
1171 //---------
1172 
1173 estring::estring(const short a_short)
1174 {
1175  init();
1176  assign(a_short);
1177 }
1178 
1179 estring& estring::assign(const short a_short)
1180 {
1181  if (a_short < 0) {
1182  TRY(assign(static_cast<unsigned short>(-a_short)),
1183  "Could not convert signed short to string");
1184  TRY_nomem(std::string::insert(0,"-"));
1185  }
1186  else {
1187  TRY(assign(static_cast<unsigned short>(a_short)),
1188  "Could not convert signed short to string");
1189  }
1190  m_type = type_short;
1191  m_value.clear();
1192  m_value.value.s = a_short;
1193 
1194  return(*this);
1195 }
1196 
1197 estring& estring::operator=(const short a_short)
1198 {
1199  assign(a_short);
1200 
1201  return(*this);
1202 }
1203 
1204 estring::operator short() const
1205 {
1206  short value = 0;
1207 
1208  TRY(T_string_to_signed_integral((*this),value),
1209  "Cannot convert string to signed short");
1210 
1211  return(value);
1212 }
1213 
1214 //---------
1215 
1216 estring::estring(const unsigned long a_long)
1217 {
1218  init();
1219  assign(a_long);
1220 }
1221 
1222 estring& estring::assign(const unsigned long a_long)
1223 {
1224  std::string s;
1225 
1226  TRY(T_integral_to_string(a_long,s),
1227  "Could not convert unsigned long to string");
1228  TRY_nomem(std::string::assign(s));
1230  m_value.clear();
1231  m_value.value.ul = a_long;
1232 
1233  return(*this);
1234 }
1235 
1236 estring& estring::operator=(const unsigned long a_long)
1237 {
1238  assign(a_long);
1239 
1240  return(*this);
1241 }
1242 
1243 estring::operator unsigned long() const
1244 {
1245  unsigned long value = 0;
1246 
1247  TRY(T_string_to_integral((*this),value),
1248  "Cannot convert string to unsigned long");
1249 
1250  return(value);
1251 }
1252 
1253 //---------
1254 
1255 estring::estring(const long a_long)
1256 {
1257  init();
1258  assign(a_long);
1259 }
1260 
1261 estring& estring::assign(const long a_long)
1262 {
1263  if (a_long < 0) {
1264  TRY(assign(static_cast<unsigned long>(-a_long)),
1265  "Could not convert signed long to string");
1266  TRY_nomem(std::string::insert(0,"-"));
1267  }
1268  else {
1269  TRY(assign(static_cast<unsigned long>(a_long)),
1270  "Could not convert signed long to string");
1271  }
1272  m_type = type_long;
1273  m_value.clear();
1274  m_value.value.l = a_long;
1275 
1276  return(*this);
1277 }
1278 
1279 estring& estring::operator=(const long a_long)
1280 {
1281  assign(a_long);
1282 
1283  return(*this);
1284 }
1285 
1286 estring::operator long() const
1287 {
1288  long value = 0;
1289 
1290  TRY(T_string_to_signed_integral((*this),value),
1291  "Cannot convert string to signed long");
1292 
1293  return(value);
1294 }
1295 
1296 //---------
1297 
1298 estring::estring(const unsigned long long a_long)
1299 {
1300  init();
1301  assign(a_long);
1302 }
1303 
1304 estring& estring::assign(const unsigned long long a_long)
1305 {
1306  std::string s;
1307 
1308  TRY(T_integral_to_string(a_long,s),
1309  "Could not convert unsigned long long to string");
1310  TRY_nomem(std::string::assign(s));
1312  m_value.clear();
1313  m_value.value.ull = a_long;
1314 
1315  return(*this);
1316 }
1317 
1318 estring& estring::operator=(const unsigned long long a_long)
1319 {
1320  assign(a_long);
1321 
1322  return(*this);
1323 }
1324 
1325 estring::operator unsigned long long() const
1326 {
1327  unsigned long long value = 0;
1328 
1329  TRY(T_string_to_integral((*this),value),
1330  "Cannot convert string to unsigned long long");
1331 
1332  return(value);
1333 }
1334 
1335 //---------
1336 
1337 estring::estring(const long long a_long)
1338 {
1339  init();
1340  assign(a_long);
1341 }
1342 
1343 estring& estring::assign(const long long a_long)
1344 {
1345  if (a_long < 0) {
1346  TRY(assign(static_cast<unsigned long long>(-a_long)),
1347  "Could not convert unsigned long long to string");
1348  TRY_nomem(insert(0,"-"));
1349  }
1350  else {
1351  TRY(assign(static_cast<unsigned long long>(a_long)),
1352  "Could not convert unsigned long long to string");
1353  }
1355  m_value.clear();
1356  m_value.value.ll = a_long;
1357 
1358  return(*this);
1359 }
1360 
1361 estring& estring::operator=(const long long a_long)
1362 {
1363  assign(a_long);
1364 
1365  return(*this);
1366 }
1367 
1368 estring::operator long long() const
1369 {
1370  long long value = 0;
1371 
1372  TRY(T_string_to_signed_integral((*this),value),
1373  "Cannot convert string to signed long long");
1374 
1375  return(value);
1376 }
1377 
1378 //---------
1379 
1380 estring::estring(char const * a_ptr)
1381 {
1382  init();
1383  assign(a_ptr);
1384 }
1385 
1386 estring& estring::assign(char const * a_ptr)
1387 {
1388  std::string str;
1389 
1390  TRY_nomem(str = a_ptr);
1391  TRY_nomem(assign(str));
1393  m_value.clear();
1394  m_value.value.char_ptr = a_ptr;
1395 
1396  return(*this);
1397 }
1398 
1399 estring& estring::operator=(char const * a_ptr)
1400 {
1401  assign(a_ptr);
1402 
1403  return(*this);
1404 }
1405 
1406 estring::operator char const *()const
1407 {
1408  char const * value = 0;
1409 
1410  if ((m_type != type_char_ptr) && (m_type != type_void_ptr)) {
1411  throw(ERROR(0,"Value type is not a pointer"));
1412  }
1413 
1414  value = m_value.value.char_ptr;
1415 
1416  return(value);
1417 }
1418 
1419 //---------
1420 
1421 estring::estring(void* const a_ptr)
1422 {
1423  init();
1424  assign(a_ptr);
1425 }
1426 
1427 estring& estring::assign(void* const a_ptr)
1428 {
1429  static const size_t buffer_len = 32;
1430  char buffer[buffer_len] = { 0 };
1431 
1432  snprintf(buffer, buffer_len, "%p", a_ptr);
1433  TRY_nomem(std::string::assign(buffer));
1435  m_value.clear();
1436  m_value.value.void_ptr = a_ptr;
1437 
1438  return(*this);
1439 }
1440 
1441 estring& estring::operator=(void* const a_ptr)
1442 {
1443  assign(a_ptr);
1444 
1445  return(*this);
1446 }
1447 
1448 estring::operator void*()const
1449 {
1450  void * value = 0;
1451 
1452  if ((m_type != type_void_ptr) && (m_type != type_char_ptr)) {
1453  throw(ERROR(0,"Value type is not a pointer"));
1454  }
1455 
1456  value = m_value.value.void_ptr;
1457 
1458  return(value);
1459 }
1460 
1461 //---------
1462 
1463 estring::estring(const float a_float)
1464 {
1465  init();
1466  assign(a_float);
1467 }
1468 
1469 estring& estring::assign(const float a_float)
1470 {
1471  std::string ws;
1472  std::string fs;
1473  std::string s;
1474 
1475  TRY(T_fraction_to_strings(a_float,ws,fs),
1476  "Cannot convert float to string");
1477  TRY_nomem(s = ws);
1478  if (fs.size() > 0) {
1479  TRY_nomem(s += ".");
1480  TRY_nomem(s += fs);
1481  }
1482  TRY_nomem(std::string::assign(s));
1483  m_type = type_float;
1484  m_value.clear();
1485  m_value.value.f = a_float;
1486 
1487  return(*this);
1488 }
1489 
1490 estring& estring::operator=(const float a_float)
1491 {
1492  assign(a_float);
1493 
1494  return(*this);
1495 }
1496 
1497 estring::estring(const float a_float, unsigned a_precision,
1498  unsigned int a_base)
1499 {
1500  init();
1501  assign(a_float, a_precision, a_base);
1502 }
1503 
1504 estring& estring::assign(const float a_float, unsigned a_precision,
1505  unsigned int a_base)
1506 {
1507  std::string ws;
1508  std::string fs;
1509  std::string s;
1510 
1511  precision(a_precision);
1512  base(a_base);
1513  assign(a_float);
1514 
1515  return(*this);
1516 }
1517 
1518 estring::operator float() const
1519 {
1520  float value = 0.0;
1521 
1522  TRY(T_string_to_fractional((*this), value),
1523  "Cannot convert string to float");
1524 
1525  return(value);
1526 }
1527 
1528 //---------
1529 
1530 estring::estring(const double a_double)
1531 {
1532  init();
1533  assign(a_double);
1534 }
1535 
1536 estring& estring::assign(const double a_double)
1537 {
1538  std::string ws;
1539  std::string fs;
1540  std::string s;
1541 
1542  TRY(T_fraction_to_strings(a_double,ws,fs),
1543  "Cannot convert double to string");
1544  TRY_nomem(s = ws);
1545  if (fs.size() > 0) {
1546  TRY_nomem(s += ".");
1547  TRY_nomem(s += fs);
1548  }
1549  TRY_nomem(std::string::assign(s));
1550  m_type = type_double;
1551  m_value.clear();
1552  m_value.value.d = a_double;
1553 
1554  return(*this);
1555 }
1556 
1557 estring& estring::operator=(const double a_double)
1558 {
1559  assign(a_double);
1560 
1561  return(*this);
1562 }
1563 
1564 estring::estring(const double a_double, unsigned a_precision,
1565  unsigned int a_base)
1566 {
1567  init();
1568  assign(a_double, a_precision, a_base);
1569 }
1570 
1571 estring& estring::assign(const double a_double, unsigned a_precision,
1572  unsigned int a_base)
1573 {
1574  std::string ws;
1575  std::string fs;
1576  std::string s;
1577 
1578  precision(a_precision);
1579  assign(a_base);
1580  assign(a_double);
1581 
1582  return(*this);
1583 }
1584 
1585 estring::operator double() const
1586 {
1587  double value = 0.0;
1588 
1589  TRY(T_string_to_fractional((*this), value),
1590  "Cannot convert string to double");
1591 
1592  return(value);
1593 }
1594 
static const size_t m_alphabet_len
The length of the alphabet.
Definition: estring.h:243
Left-justified.
Definition: estring.h:64
set_from_type m_type
The current value type.
Definition: estring.h:253
void clear(void)
Erase the string value.
Definition: estring.cc:414
Basic types definitions and templates.
unsigned short us
Definition: estring.h:24
An extended string class.
Definition: estring.h:52
value_type value
Definition: estring.h:38
#define ASSERT(code)
Definition: asserts.h:9
void reset(void)
Erase and reinitialize.
Definition: estring.cc:421
void clear(void)
Definition: estring.cc:21
void T_string_to_integral(const value_type &a_str, T &a_t) const
Helper member template function to convert a string to an integral type.
Definition: estring.cc:197
const set_from_type & get_from_type(void) const
Retrieve the type of value being held by this estring.
Definition: estring.cc:810
estring & assign(const estring &a_estr)
Assignment for estring objects.
Definition: estring.cc:853
Right-justified.
Definition: estring.h:66
estring_value & operator=(const estring_value &a_estring_value)
Definition: estring.cc:26
char m_left_fillchar
The current left-hand fill character.
Definition: estring.h:249
unsigned long ul
Definition: estring.h:26
unsigned long long ull
Definition: estring.h:28
char m_right_fillchar
The current right-hand fill character.
Definition: estring.h:251
unsigned short
Definition: estring.h:80
void T_integral_to_string(const T &a_t, value_type &a_str)
Helper member template function to convert an integral type to an estring.
Definition: estring.cc:59
alignment align(void) const
Retrieve the set alignment for formatted strings.
Definition: estring.cc:486
static const char * m_alphabet
The alphabet used for any base from 2 to 36.
Definition: estring.h:241
char const * char_ptr
Definition: estring.h:30
unsigned long long
Definition: estring.h:88
alignment m_alignment
The current formatting alignment.
Definition: estring.h:247
size_type width(void) const
Retrieve the set width for formatted strings.
Definition: estring.cc:461
#define TRY_nomem(code)
Definition: error.h:144
void init(void)
Initialize the estring object.
Definition: estring.cc:401
size_type m_precision
The current fractional number precision.
Definition: estring.h:237
value_type fmt_str(void)
Generate a formatted string.
Definition: estring.cc:688
char left_fillchar(void) const
Retrieve the fill character used to padd the left side of a formatted string.
Definition: estring.cc:620
estring & operator=(const estring &a_estr)
Assignment operator for estring objects.
Definition: estring.cc:878
void fillchar(const char a_char)
Set the fill character used for padding both the left and right side of a formatted string...
Definition: estring.cc:662
void T_string_to_fractional(const value_type &a_str, T &a_t) const
Helper member template function to convert a string to a fractional.
Definition: estring.cc:313
const estring_value & get_from_value(void) const
Retrieve the typeless_value being held by this estring.
Definition: estring.cc:821
#define TRY(code, es)
Definition: error.h:126
alignment
Alignment values for formatted strings.
Definition: estring.h:62
set_from_type
The type last assigned.
Definition: estring.h:72
estring & lower(void)
Convert all characters to lowercase.
Definition: estring.cc:891
void T_fraction_to_strings(const T &a_t, value_type &a_ws, value_type &a_fs)
Helper member template function to convert a fractional type to an estring.
Definition: estring.cc:101
std::string value_type
The type from which estring inherits, std::string.
Definition: estring.h:56
size_type precision(void) const
Retrieve the set precision used in fractional conversions.
Definition: estring.cc:521
value_type::size_type size_type
The size type.
Definition: estring.h:59
estring()
Default constructor.
Definition: estring.cc:431
void T_string_to_signed_integral(const value_type &a_str, T &a_t) const
Helper member template function to convert a string to a signed integral.
Definition: estring.cc:277
estring & upper(void)
Convert all characters to uppercase.
Definition: estring.cc:908
estring_value m_value
The current value.
Definition: estring.h:255
std::string
Definition: estring.h:74
#define ERROR(e, s)
Definition: error.h:120
unsigned long
Definition: estring.h:84
size_type m_width
The current formatting width.
Definition: estring.h:245
char right_fillchar(void) const
Retrieve the fill character used to padd the right side of a formatted string.
Definition: estring.cc:651
const unsigned int base(void) const
Retrieve the base used in numeric conversions.
Definition: estring.cc:589
unsigned int m_base
The current numerical base.
Definition: estring.h:239