rvm 1.08
|
00001 #include "config.h" 00002 00003 #include <iostream> 00004 #include <string> 00005 #include <cstdio> 00006 #include <cctype> 00007 #include <string.h> 00008 00009 #include "asserts.h" 00010 #include "types.h" 00011 #include "error.h" 00012 #include "estring.h" 00013 00014 //---------------------------------------------------------------------------- 00015 00016 estring_value::estring_value() 00017 { 00018 clear(); 00019 } 00020 00021 void estring_value::clear(void) 00022 { 00023 memset(static_cast<void*>(&value), 0, sizeof(value)); 00024 } 00025 00026 estring_value& estring_value::operator=(const estring_value& a_estring_value) 00027 { 00028 value = a_estring_value.value; 00029 00030 return(*this); 00031 } 00032 00033 //---------------------------------------------------------------------------- 00034 00035 /** Alphabet used for base number conversions 00036 */ 00037 00038 const char * estring::m_alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"; 00039 00040 /** The length of the alphabet used for base number conversions 00041 */ 00042 const size_t estring::m_alphabet_len = 36; 00043 00044 /** Helper member template function to convert an integral type to an estring. 00045 00046 Integrals are converted to string form using a default base of 10 unless 00047 specified otherwise through the base() member function. For bases greater 00048 than ten the letters of the alphabet are used, starting with 'a' for eleven, 00049 'b' for twelve, etc. 00050 00051 Variables: 00052 - a_t - the integral type. Usually uint8, uint16, uint32, or uint64. 00053 - a_str - the std::string object in which to store the string converstion. 00054 00055 Exceptions: 00056 - An err_nomem is thrown for memory allocation failure. 00057 */ 00058 template <class T> 00059 void estring::T_integral_to_string(const T& a_t, value_type& a_str) 00060 { 00061 T num = a_t; 00062 int digit; 00063 char ch; 00064 00065 ASSERT(a_t >= 0); 00066 ASSERT(m_base >= 2); 00067 ASSERT(m_base <= m_alphabet_len); 00068 00069 TRY_nomem(a_str = ""); 00070 if (a_t == 0) { 00071 TRY_nomem(a_str = "0"); 00072 return; 00073 } 00074 while (num > 0) { 00075 digit = num % m_base; 00076 ch = m_alphabet[digit]; 00077 TRY_nomem(a_str = ch + a_str); 00078 num /= m_base; 00079 } 00080 } 00081 00082 /** Helper member template function to convert a fractional type to an estring. 00083 00084 Fractions are converted to string form using a default base of 10 unless 00085 specified otherwise through the base() member function. For bases greater 00086 than ten the letters of the alphabet are used, starting with 'a' for eleven, 00087 'b' for twelve, etc. 00088 00089 By default a precision of 1 digit to the right of the decimal point is used 00090 unless specified otherwise by the precision() member function. 00091 00092 Variables: 00093 - a_t - the fractional type: float or double. 00094 - a_ws - the std::string object in which to store the whole part. 00095 - a_fs - the std::string object in which to store the fractional part. 00096 00097 Exceptions: 00098 - An err_nomem is thrown for memory allocation failure. 00099 */ 00100 template <class T> 00101 void estring::T_fraction_to_strings(const T& a_t, 00102 value_type& a_ws, value_type& a_fs) 00103 { 00104 T fraction = a_t; 00105 bool negative = false; 00106 uint64 whole_part; 00107 uint64 fractional_part; 00108 uint64 multiplier; 00109 size_type c; 00110 int digit; 00111 char ch; 00112 00113 ASSERT(m_base >= 2); 00114 ASSERT(m_base <= m_alphabet_len); 00115 00116 TRY_nomem(a_ws = ""); 00117 TRY_nomem(a_fs = ""); 00118 00119 if (fraction < 0.0) { 00120 negative = true; 00121 fraction = -fraction; 00122 } 00123 00124 whole_part = static_cast<uint64>(fraction); 00125 if (whole_part == 0) { 00126 TRY_nomem(a_ws = "0"); 00127 } 00128 else { 00129 while (whole_part > 0) { 00130 digit = whole_part % m_base; 00131 ch = m_alphabet[digit]; 00132 TRY_nomem(a_ws = ch + a_ws); 00133 whole_part /= m_base; 00134 } 00135 } 00136 00137 multiplier = m_base; 00138 for (c = 0; c < m_precision; c++) 00139 multiplier *= m_base; 00140 00141 fractional_part = static_cast<uint64>( 00142 (fraction - static_cast<uint64>(fraction)) * multiplier); 00143 fractional_part += (m_base/2); 00144 fractional_part /= m_base; 00145 00146 while (fractional_part > 0) { 00147 digit = fractional_part % m_base; 00148 ch = m_alphabet[digit]; 00149 TRY_nomem(a_fs = ch +a_fs); 00150 fractional_part /= m_base; 00151 } 00152 if (a_fs.size() > m_precision) { 00153 a_fs.erase(m_precision); 00154 } 00155 for (c = a_fs.size(); c < m_precision; c++) { 00156 TRY_nomem(a_fs += "0"); 00157 } 00158 00159 if (negative) { 00160 TRY_nomem(a_ws = "-" + a_ws); 00161 } 00162 } 00163 00164 /** Helper member template function to convert a string to an integral type. 00165 00166 Characters in the string are converted using a default base of 10 unless 00167 specified otherwise through the base() member function. For bases greater 00168 than ten the letters of the alphabet will be assumed, starting with 'a' for 00169 eleven, 'b' for twelve, etc. 00170 00171 Variables: 00172 - a_str - the std::string object from which to convert. 00173 - a_t - a variable of the integral type to which to convert. 00174 00175 Exceptions: 00176 - An err_nomem is thrown for memory allocation failure. 00177 - If a symbol is encountered in the string that is not expected then an 00178 invalid character or invalid base error is thrown. 00179 - If the type to which to convert the string is not large enough to hold 00180 the value of the converted string then an overflow error is thrown. 00181 */ 00182 template<class T> 00183 void estring::T_string_to_integral(const value_type& a_str, T& a_t) const 00184 { 00185 value_type::const_iterator stri; 00186 T value = 0; 00187 T digit = 0; 00188 T overflow_check_1 = 0; 00189 T overflow_check_2 = 0; 00190 value_type es; 00191 value_type alphabet; 00192 size_type idx; 00193 const static size_t buffer_len = 256; 00194 char buffer[buffer_len] = { 0 }; 00195 unsigned int index; 00196 00197 ASSERT(m_base >= 2); 00198 ASSERT(m_base <= m_alphabet_len); 00199 00200 TRY_nomem(alphabet = m_alphabet); 00201 for (stri = a_str.begin(), index = 0; 00202 stri != a_str.end(); 00203 ++stri, ++index 00204 ) 00205 { 00206 idx = alphabet.find(*stri); 00207 if (idx > m_base) { 00208 snprintf(buffer, buffer_len, "%u", index); 00209 00210 TRY_nomem(es = "Parse error at index "); 00211 TRY_nomem(es += buffer); 00212 TRY_nomem(es += " (char '"); 00213 TRY_nomem(es += *stri); 00214 TRY_nomem(es += "')"); 00215 TRY_nomem(es += " converting \""); 00216 TRY_nomem(es += (*this)); 00217 TRY_nomem(es += "\""); 00218 if (idx == value_type::npos) { 00219 TRY_nomem(es += ", invalid character"); 00220 } 00221 else { 00222 TRY_nomem(es += ", invalid base or invalid string"); 00223 } 00224 throw(ERROR(0,es)); 00225 } 00226 00227 value *= m_base; 00228 digit = static_cast<unsigned int>(idx); 00229 value += digit; 00230 00231 overflow_check_1 *= m_base; 00232 overflow_check_1 += 1; 00233 if (overflow_check_1 == overflow_check_2) { 00234 snprintf(buffer, buffer_len, "%u", index); 00235 00236 TRY_nomem(es = "Overflow error at index "); 00237 TRY_nomem(es += buffer); 00238 TRY_nomem(es += " (char '"); 00239 TRY_nomem(es += *stri); 00240 TRY_nomem(es += "')"); 00241 TRY_nomem(es += " converting \""); 00242 TRY_nomem(es += (*this)); 00243 TRY_nomem(es += "\" to unsigned int"); 00244 throw(ERROR(0,es)); 00245 } 00246 overflow_check_2 = overflow_check_1; 00247 } 00248 a_t = value; 00249 } 00250 00251 /** Helper member template function to convert a string to a signed integral. 00252 00253 Variables: 00254 - a_str - the std::string to convert from. 00255 - a_t - a variable of the type to convert to. 00256 00257 Exceptions: 00258 - An err_nomem is thrown for memory allocation failure. 00259 - Any exception thrown from the called member template function 00260 T_string_to_integral(). 00261 */ 00262 template <class T> 00263 void estring::T_string_to_signed_integral(const value_type& a_str, T& a_t) 00264 const 00265 { 00266 value_type tmp; 00267 T value = 0; 00268 bool negative = false; 00269 00270 if ((value_type::size() > 0) && (this->at(0) == '-')) { 00271 negative = true; 00272 TRY_nomem(tmp = (*this).substr(1)); 00273 } 00274 else { 00275 TRY_nomem(tmp = (*this)); 00276 } 00277 T_string_to_integral(tmp,value); 00278 if (negative) 00279 value = -value; 00280 a_t = value; 00281 } 00282 00283 /** Helper member template function to convert a string to a fractional. 00284 00285 Variables: 00286 - a_str - the std::string to convert from. 00287 - a_t - a variable of the type to convert to. 00288 00289 Exceptions: 00290 - An err_nomem is thrown for memory allocation failure. 00291 - Any exception thrown by the member template function 00292 T_string_to_integral(). 00293 - An overflow error is thrown if the wole part of the string is too large 00294 for the type a_t. 00295 - An underflow error is thrown if the fractional part of the string is too 00296 large for the type a_t. 00297 */ 00298 template <class T> 00299 void estring::T_string_to_fractional(const value_type& a_str, T& a_t) const 00300 { 00301 value_type es; 00302 value_type tmp; 00303 value_type whole_string; 00304 value_type fractional_string; 00305 size_type idx = 0; 00306 bool negative = false;; 00307 uint64 whole_part_converter = 0; 00308 uint64 fractional_part_converter = 0; 00309 uint64 fractional_check = 0; 00310 T whole_part = 0; 00311 T fractional_part = 0; 00312 T value =0; 00313 unsigned int divisor = 0; 00314 unsigned int c = 0; 00315 00316 ASSERT(m_base >= 2); 00317 ASSERT(m_base <= m_alphabet_len); 00318 00319 if ((value_type::size() > 0) && (this->at(0) == '-')) { 00320 negative = true; 00321 TRY_nomem(tmp = (*this).substr(1)); 00322 } 00323 else { 00324 TRY_nomem(tmp = (*this)); 00325 } 00326 00327 idx = tmp.find('.'); 00328 if (idx != value_type::npos) { 00329 TRY_nomem(whole_string = tmp.substr(0,idx)); 00330 TRY_nomem(fractional_string = tmp.substr(idx+1)); 00331 } 00332 else { 00333 TRY_nomem(whole_string = tmp); 00334 TRY_nomem(fractional_string = ""); 00335 } 00336 00337 TRY_nomem(es = "Could not convert whole part of estring \""); 00338 TRY_nomem(es += a_str); 00339 TRY_nomem(es += "\""); 00340 TRY(T_string_to_integral(whole_string, whole_part_converter),es); 00341 00342 TRY_nomem(es = "Could not convert fractional part of estring \""); 00343 TRY_nomem(es += a_str); 00344 TRY_nomem(es += "\""); 00345 TRY(T_string_to_integral(fractional_string, fractional_part_converter),es); 00346 00347 divisor = 1; 00348 for (c = 0; c < fractional_string.size(); c++) 00349 divisor *= m_base; 00350 00351 whole_part = static_cast<T>(whole_part_converter); 00352 if (static_cast<uint64>(whole_part) != whole_part_converter) { 00353 TRY_nomem(es = "Overflow error converting whole part of estring \""); 00354 TRY_nomem(es += a_str); 00355 TRY_nomem(es += "\""); 00356 throw(ERROR(0,es)); 00357 } 00358 fractional_part = static_cast<T>(fractional_part_converter)/divisor; 00359 fractional_check = static_cast<uint64>(fractional_part*divisor); 00360 if (fractional_check != fractional_part_converter) { 00361 TRY_nomem(es = "Underflow error converting fractional part of estring \""); 00362 TRY_nomem(es += a_str); 00363 TRY_nomem(es += "\""); 00364 throw(ERROR(0,es)); 00365 } 00366 00367 value = whole_part + fractional_part; 00368 00369 if (negative) { 00370 value = -value; 00371 } 00372 a_t = value; 00373 } 00374 00375 //--------- 00376 00377 /** Initialize the estring object. 00378 00379 Defaults: 00380 - A precision of one digit to the right of the decimal. 00381 - A base of 10. 00382 - A width of 5 characters for formatted printing. 00383 - A space as the fill character for padding the left of a string. 00384 - A space as the fill character for padding the right of a string. 00385 - Initialize the conversion type to type_unknown. 00386 */ 00387 void estring::init(void) 00388 { 00389 m_precision = 1; 00390 m_base = 10; 00391 m_width = 5; 00392 m_alignment = left; 00393 m_left_fillchar = ' '; 00394 m_right_fillchar = ' '; 00395 m_type = type_unknown; 00396 } 00397 00398 /** Erase the string value. 00399 */ 00400 void estring::clear(void) 00401 { 00402 value_type::erase(); 00403 } 00404 00405 /** Erase and reinitialize. 00406 */ 00407 void estring::reset(void) 00408 { 00409 clear(); 00410 init(); 00411 } 00412 00413 //--------- 00414 00415 /** Default constructor 00416 */ 00417 estring::estring() 00418 { 00419 init(); 00420 } 00421 00422 //--------- 00423 00424 /** Set the width of a formatted string. 00425 00426 Variables: 00427 - a_l - new width to use for formatting strings. 00428 00429 Returns: 00430 - size_type - the last width. 00431 */ 00432 estring::size_type estring::width(const size_type a_l) 00433 { 00434 size_type old; 00435 00436 old = m_width; 00437 m_width = a_l; 00438 00439 return(old); 00440 } 00441 00442 /** Retrieve the set width for formatted strings. 00443 00444 Returns: 00445 - size_type - the current width. 00446 */ 00447 estring::size_type estring::width(void) const 00448 { 00449 return(m_width); 00450 } 00451 00452 /** Set the alignment used for formatted strings. 00453 00454 Vaiables: 00455 - a_alignment - the type of alignment to use for formatting strings. 00456 */ 00457 estring::alignment estring::align(const alignment a_alignment) 00458 { 00459 alignment old; 00460 00461 old = m_alignment; 00462 m_alignment = a_alignment; 00463 00464 return(old); 00465 } 00466 00467 /** Retrieve the set alignment for formatted strings. 00468 00469 Returns: 00470 - enum alignment - the current alignment. 00471 */ 00472 estring::alignment estring::align(void) const 00473 { 00474 return(m_alignment); 00475 } 00476 00477 /** Set the precision used in converting to/from fractional types. 00478 00479 Variables: 00480 - a_p - the number of digits to use to the right of the decimal point when 00481 converting fractional types. 00482 00483 Returns: 00484 - size_type - the last precision. 00485 00486 */ 00487 estring::size_type estring::precision(size_type a_p) 00488 { 00489 size_type old; 00490 00491 old = m_precision; 00492 m_precision = a_p; 00493 00494 if (m_type == type_float) 00495 assign(m_value.value.f); 00496 else if (m_type == type_double) 00497 assign(m_value.value.d); 00498 00499 return(old); 00500 } 00501 00502 /** Retrieve the set precision used in fractional conversions. 00503 00504 Returns: 00505 - size_type - the current precision. 00506 */ 00507 estring::size_type estring::precision(void) const 00508 { 00509 return(m_precision); 00510 } 00511 00512 /** Set the base used in numeric conversions. 00513 00514 Variables: 00515 - a_base - The base to use in converting numbers to/from strings. 00516 00517 Return: 00518 - const unsigned int - the last base. 00519 00520 Exceptions: 00521 - An err_nomem is thrown for memory allocation failure. 00522 - An invalid base is thrown if the base is smaller than 2 (binary). 00523 - A base too large is thrown if the base is larger than the alphabet of 00524 usable symbols. 00525 */ 00526 const unsigned int estring::base(const unsigned int a_base) 00527 { 00528 unsigned int old = m_base; 00529 value_type es; 00530 char str[255] = { 0 }; 00531 00532 if (a_base < 2) { 00533 sprintf(str, "%u", a_base); 00534 TRY_nomem(es = "Invalid base: "); 00535 TRY_nomem(es += str); 00536 throw(ERROR(0,es)); 00537 } 00538 if (a_base > m_alphabet_len) { 00539 sprintf(str, "%u", a_base); 00540 TRY_nomem(es = "Base too large: "); 00541 TRY_nomem(es += str); 00542 throw(ERROR(0,es)); 00543 } 00544 m_base = a_base; 00545 00546 if (m_type == type_unsigned_int) 00547 assign(m_value.value.ui); 00548 if (m_type == type_int) 00549 assign(m_value.value.i); 00550 if (m_type == type_unsigned_short) 00551 assign(m_value.value.us); 00552 if (m_type == type_short) 00553 assign(m_value.value.s); 00554 if (m_type == type_unsigned_long) 00555 assign(m_value.value.ul); 00556 if (m_type == type_long) 00557 assign(m_value.value.l); 00558 if (m_type == type_unsigned_long_long) 00559 assign(m_value.value.ull); 00560 if (m_type == type_long_long) 00561 assign(m_value.value.ll); 00562 if (m_type == type_float) 00563 assign(m_value.value.f); 00564 if (m_type == type_double) 00565 assign(m_value.value.d); 00566 00567 return(old); 00568 } 00569 00570 /** Retrieve the base used in numeric conversions. 00571 00572 Returns: 00573 - const unsigned int - the current numeric base. 00574 */ 00575 const unsigned int estring::base(void) const 00576 { 00577 return(m_base); 00578 } 00579 00580 /** Set the fill character used to padd the left side of a formatted string. 00581 00582 Variables: 00583 - a_char - the character to use as the fill character. 00584 00585 Returns: 00586 - char - the last fill character. 00587 00588 */ 00589 char estring::left_fillchar(const char a_char) 00590 { 00591 char old; 00592 00593 old = m_left_fillchar; 00594 m_left_fillchar = a_char; 00595 00596 return(old); 00597 } 00598 00599 /** Retrieve the fill character used to padd the left side of a formatted 00600 string. 00601 00602 Returns: 00603 - char - the current fill character. 00604 00605 */ 00606 char estring::left_fillchar(void) const 00607 { 00608 return(m_left_fillchar); 00609 } 00610 00611 /** Set the fill character used to padd the right side of a formatted string. 00612 00613 Variables: 00614 - a_char - the character to use as the fill character. 00615 00616 Returns: 00617 - char - the last fill character. 00618 00619 */ 00620 char estring::right_fillchar(const char a_char) 00621 { 00622 char old; 00623 00624 old = m_right_fillchar; 00625 m_right_fillchar = a_char; 00626 00627 return(old); 00628 } 00629 00630 /** Retrieve the fill character used to padd the right side of a formatted 00631 string. 00632 00633 Returns: 00634 - char - the current fill character. 00635 00636 */ 00637 char estring::right_fillchar(void) const 00638 { 00639 return(m_right_fillchar); 00640 } 00641 00642 /** Set the fill character used for padding both the left and right side of a 00643 formatted string. 00644 00645 Variables: 00646 - a_char - the character to use as the fill character. 00647 */ 00648 void estring::fillchar(const char a_char) 00649 { 00650 left_fillchar(a_char); 00651 right_fillchar(a_char); 00652 } 00653 00654 //--------- 00655 00656 /** Generate a formatted string. 00657 00658 Returns: 00659 - value_type - a formatted rendition of the current string. 00660 00661 If the string being printed is wider than the assigned width then as many as 00662 three periods are used ("...") to denote that the contents of the string 00663 have been truncated. For strings that use left alignment these three 00664 periods are printed on the right-hand side of the string, while showing as 00665 many characters on the left as possible beginning with the left-most 00666 character. For strings that use right alignment these three periods are 00667 printed on the left-hand side of the string, while showing as many 00668 characters on the right as possible includingn the right-most character. 00669 For strings that are center-aligned as many characters on both the left and 00670 the right are printed, including the left-most and the right-most 00671 characters, while characters in the center of the string are replaced with 00672 the three periods. 00673 */ 00674 estring::value_type estring::fmt_str(void) 00675 { 00676 std::string str; 00677 std::string lstr; 00678 std::string rstr; 00679 std::string::size_type c = 0; 00680 std::string::size_type c_max = 0; 00681 std::string::size_type offset = 0; 00682 std::string::size_type length = 0; 00683 std::string::size_type l_offset = 0; 00684 std::string::size_type r_offset = 0; 00685 bool last = true; 00686 00687 TRY_nomem(str = ""); 00688 TRY_nomem(lstr = ""); 00689 TRY_nomem(rstr = ""); 00690 00691 if (std::string::size() > m_width) { 00692 if (m_alignment == left) { 00693 if (m_width >= 3) 00694 length = m_width-3; 00695 else 00696 length = 0; 00697 TRY_nomem(str = std::string::substr(0,length) + "..."); 00698 TRY_nomem(str = str.substr(0,m_width)); 00699 } 00700 else if (m_alignment == right) { 00701 if (m_width >= 3) 00702 length = m_width-3; 00703 else 00704 length = 0; 00705 00706 offset = std::string::size()-length; 00707 TRY_nomem(str = "..." + std::string::substr(offset,length)); 00708 TRY_nomem(str = str.substr(str.size()-m_width,m_width)); 00709 } 00710 else { 00711 if (m_width < 4) { 00712 TRY_nomem(str = static_cast<std::string>("....").substr(0,m_width)); 00713 return(str); 00714 } 00715 00716 c_max = m_width-3; 00717 r_offset = std::string::size()-1; 00718 for (c = 0; c < c_max; c++) { 00719 if (last) { 00720 TRY_nomem(lstr += (*this)[l_offset++]); 00721 } 00722 else { 00723 TRY_nomem(rstr = (*this)[r_offset--] + rstr); 00724 } 00725 last = !last; 00726 } 00727 00728 TRY_nomem(str = lstr); 00729 TRY_nomem(str += "..."); 00730 TRY_nomem(str += rstr); 00731 } 00732 return(str); 00733 } 00734 00735 TRY_nomem(str = (*this)); 00736 c_max = m_width - std::string::size(); 00737 for (c = 0; c < c_max; c++) { 00738 if (m_alignment == right) { 00739 TRY_nomem(str = m_left_fillchar + str); 00740 } 00741 else if (m_alignment == left) { 00742 TRY_nomem(str += m_right_fillchar); 00743 } 00744 else { 00745 if (last) { 00746 TRY_nomem(str += m_right_fillchar); 00747 } 00748 else { 00749 TRY_nomem(str = m_left_fillchar + str); 00750 } 00751 last = !last; 00752 } 00753 } 00754 00755 return(str); 00756 } 00757 00758 /** Set all the formatting options. 00759 00760 Variables: 00761 - a_width - the width of the formatted string. 00762 - a_alignment - the alignment used to format the string. 00763 - a_left_fill - the character used for left-hand padding. 00764 - a_right_fill - the character used for right-hand padding. 00765 00766 Returns: 00767 - value_type - a formatted rendition of the current string. 00768 00769 */ 00770 estring::value_type estring::fmt_str( 00771 const size_type a_width, 00772 const alignment a_alignment, 00773 const char a_left_fill, 00774 const char a_right_fill 00775 ) 00776 { 00777 value_type str; 00778 00779 width(a_width); 00780 align(a_alignment); 00781 left_fillchar(a_left_fill); 00782 right_fillchar(a_right_fill); 00783 00784 str = fmt_str(); 00785 00786 return(str); 00787 } 00788 00789 //--------- 00790 00791 /** Retrieve the type of value being held by this estring. 00792 00793 Returns: 00794 - set_from_type& - the enumeration of the type of value currently assigned. 00795 */ 00796 const estring::set_from_type& estring::get_from_type(void) const 00797 { 00798 return(m_type); 00799 } 00800 00801 /** Retrieve the typeless_value being held by this estring. 00802 00803 Returns: 00804 - typeless_value& - the union that holds the current value. 00805 00806 */ 00807 const estring_value& estring::get_from_value(void) const 00808 { 00809 return(m_value); 00810 } 00811 00812 /** Copy constructor for estring objects. 00813 00814 Variables: 00815 - a_estr - the estring object to copy. 00816 00817 Exceptions: 00818 - Anything thrown by estring::assign(const estring& a_estr). 00819 */ 00820 estring::estring(const estring& a_estr) 00821 { 00822 init(); 00823 assign(a_estr); 00824 } 00825 00826 /** Assignment for estring objects. 00827 00828 Variables: 00829 - a_estr - the estring object to copy. 00830 00831 Returns: 00832 - estring& - a reference to self. 00833 00834 Exceptions: 00835 - An err_nomem is thrown if memory allocation fails. 00836 - It is possible that an "Invalid base" or "Base too large" may be thrown 00837 if the estring object is corrupted, but this should never happen. 00838 */ 00839 estring& estring::assign(const estring& a_estr) 00840 { 00841 TRY_nomem(std::string::assign(a_estr)); 00842 m_precision = a_estr.m_precision; 00843 m_width = a_estr.m_width; 00844 m_alignment = a_estr.m_alignment; 00845 m_left_fillchar = a_estr.m_left_fillchar; 00846 m_right_fillchar = a_estr.m_right_fillchar; 00847 m_type = a_estr.m_type; 00848 m_value = a_estr.m_value; 00849 00850 return(*this); 00851 } 00852 00853 /** Assignment operator for estring objects. 00854 00855 Variables: 00856 - a_estr - the estring object to copy. 00857 00858 Returns: 00859 - estring& - a reference to self. 00860 00861 Exceptions: 00862 - Anything thrown by estring::assign(const estring& a_estr). 00863 */ 00864 estring& estring::operator=(const estring& a_estr) 00865 { 00866 assign(a_estr); 00867 00868 return(*this); 00869 } 00870 00871 /** Convert all characters to lowercase. 00872 00873 Returns: 00874 - estring& - a reference to self. 00875 00876 */ 00877 estring& estring::lower(void) 00878 { 00879 std::string::iterator si; 00880 00881 for (si = (*this).begin(); si != (*this).end(); ++si) { 00882 (*si) = tolower((*si)); 00883 } 00884 00885 return(*this); 00886 } 00887 00888 /** Convert all characters to uppercase. 00889 00890 Returns: 00891 - estring& - a reference to self. 00892 00893 */ 00894 estring& estring::upper(void) 00895 { 00896 std::string::iterator si; 00897 00898 for (si = (*this).begin(); si != (*this).end(); ++si) { 00899 (*si) = toupper((*si)); 00900 } 00901 00902 return(*this); 00903 } 00904 00905 //--------- 00906 00907 /** Copy constructor for chars. 00908 00909 Exceptions: 00910 - Anything thrown by estring::assign(const char& a_char). 00911 */ 00912 estring::estring(const char a_char) 00913 { 00914 init(); 00915 assign(a_char); 00916 } 00917 00918 /** Assignment for chars. 00919 00920 Variables: 00921 - a_char - the character to assign. 00922 00923 Returns: 00924 - estring& - a reference to self. 00925 00926 Exceptions: 00927 - An err_nomem is thrown if memory allocation fails. 00928 */ 00929 estring& estring::assign(const char a_char) 00930 { 00931 std::string s; 00932 00933 TRY_nomem(s = a_char); 00934 TRY_nomem(std::string::assign(s)); 00935 m_type = type_string; 00936 00937 return(*this); 00938 } 00939 00940 /** Assignment operator for chars 00941 00942 Variables: 00943 - a_char - the character to assign. 00944 00945 Returns: 00946 - estring& - a reference to self. 00947 00948 Exceptions: 00949 - Anything thrown by estring::assign(const char& a_char). 00950 */ 00951 estring& estring::operator=(const char a_char) 00952 { 00953 assign(a_char); 00954 00955 return(*this); 00956 } 00957 00958 //--------- 00959 00960 /** Copy constructor for std::string objects. 00961 00962 Variables: 00963 - a_string - the std::string object to copy. 00964 00965 Exceptions: 00966 - Anything thrown by estring::assign(const value_type& a_string). 00967 */ 00968 estring::estring(const value_type& a_string) 00969 { 00970 init(); 00971 assign(a_string); 00972 } 00973 00974 /** Assignment for std::string objects. 00975 00976 Variables: 00977 - a_string - the std::string object to assign. 00978 00979 Returns: 00980 - estring& - a reference to self. 00981 00982 Exceptions: 00983 - An err_nomem is thrown if memory allocation fails. 00984 */ 00985 estring& estring::assign(const value_type& a_string) 00986 { 00987 TRY_nomem(std::string::assign(a_string)); 00988 m_type = type_string; 00989 00990 return(*this); 00991 } 00992 00993 /** Assignment operator for std::string objects. 00994 00995 Variables: 00996 - a_string - the std::string object to copy. 00997 00998 Returns: 00999 - estring& - a reference to self. 01000 01001 Exceptions: 01002 - An err_nomem is thrown if memory allocation fails. 01003 */ 01004 estring& estring::operator=(const value_type& a_string) 01005 { 01006 assign(a_string); 01007 01008 return(*this); 01009 } 01010 01011 //--------- 01012 01013 /** Copy constructor for unsigned ints. 01014 01015 Variables: 01016 - a_int - unsigned int to copy. 01017 01018 Exceptions: 01019 - Anything thrown by estring::assign(const unsigned int& a_int). 01020 */ 01021 estring::estring(const unsigned int a_int) 01022 { 01023 init(); 01024 assign(a_int); 01025 } 01026 01027 /** Assignment for unsigned ints. 01028 01029 Variables: 01030 - a_int - unsigned int to assign. 01031 01032 Returns: 01033 - estring& - a reference to self. 01034 01035 Exceptions: 01036 - err_nomem on memory allocation failure. 01037 - Anything thrown by 01038 T_integral_to_string(const T& a_t, value_type& a_str). 01039 */ 01040 estring& estring::assign(const unsigned int a_int) 01041 { 01042 std::string s; 01043 01044 TRY(T_integral_to_string(a_int,s), 01045 "Could not convert unsigned int to string"); 01046 TRY_nomem(std::string::assign(s)); 01047 m_type = type_unsigned_int; 01048 m_value.clear(); 01049 m_value.value.ui = a_int; 01050 01051 return(*this); 01052 } 01053 01054 /** Assignment operator for unsigned ints. 01055 */ 01056 estring& estring::operator=(const unsigned int a_int) 01057 { 01058 assign(a_int); 01059 01060 return(*this); 01061 } 01062 01063 /** Implicit conversion operator to an unsigned int. 01064 */ 01065 estring::operator unsigned int() const 01066 { 01067 unsigned int value = 0; 01068 01069 TRY(T_string_to_integral((*this),value), 01070 "Cannot convert string to unsigned int"); 01071 01072 return(value); 01073 } 01074 01075 //--------- 01076 01077 estring::estring(const int a_int) 01078 { 01079 init(); 01080 assign(a_int); 01081 } 01082 01083 estring& estring::assign(const int a_int) 01084 { 01085 if (a_int < 0) { 01086 TRY(assign(static_cast<unsigned int>(-a_int)), 01087 "Coud not convert signed int to string"); 01088 TRY_nomem(std::string::insert(0,"-")); 01089 } 01090 else { 01091 TRY(assign(static_cast<unsigned int>(a_int)), 01092 "Could not convert signed int to string"); 01093 } 01094 m_type = type_int; 01095 m_value.clear(); 01096 m_value.value.i = a_int; 01097 01098 return(*this); 01099 } 01100 01101 estring& estring::operator=(const int a_int) 01102 { 01103 assign(a_int); 01104 01105 return(*this); 01106 } 01107 01108 estring::operator int() const 01109 { 01110 int value = 0; 01111 01112 TRY(T_string_to_signed_integral((*this),value), 01113 "Cannot convert string to signed int"); 01114 01115 return(value); 01116 } 01117 01118 //--------- 01119 01120 estring::estring(const unsigned short a_short) 01121 { 01122 init(); 01123 assign(a_short); 01124 } 01125 01126 estring& estring::assign(const unsigned short a_short) 01127 { 01128 std::string s; 01129 01130 TRY(T_integral_to_string(a_short,s), 01131 "Could not convert unsigned short to string"); 01132 TRY_nomem(std::string::assign(s)); 01133 m_type = type_unsigned_short; 01134 m_value.clear(); 01135 m_value.value.us = a_short; 01136 01137 return(*this); 01138 } 01139 01140 estring& estring::operator=(const unsigned short a_short) 01141 { 01142 assign(a_short); 01143 01144 return(*this); 01145 } 01146 01147 estring::operator unsigned short() const 01148 { 01149 unsigned short value = 0; 01150 01151 TRY(T_string_to_integral((*this),value), 01152 "Cannot convert string to unsigned short"); 01153 01154 return(value); 01155 } 01156 01157 //--------- 01158 01159 estring::estring(const short a_short) 01160 { 01161 init(); 01162 assign(a_short); 01163 } 01164 01165 estring& estring::assign(const short a_short) 01166 { 01167 if (a_short < 0) { 01168 TRY(assign(static_cast<unsigned short>(-a_short)), 01169 "Could not convert signed short to string"); 01170 TRY_nomem(std::string::insert(0,"-")); 01171 } 01172 else { 01173 TRY(assign(static_cast<unsigned short>(a_short)), 01174 "Could not convert signed short to string"); 01175 } 01176 m_type = type_short; 01177 m_value.clear(); 01178 m_value.value.s = a_short; 01179 01180 return(*this); 01181 } 01182 01183 estring& estring::operator=(const short a_short) 01184 { 01185 assign(a_short); 01186 01187 return(*this); 01188 } 01189 01190 estring::operator short() const 01191 { 01192 short value = 0; 01193 01194 TRY(T_string_to_signed_integral((*this),value), 01195 "Cannot convert string to signed short"); 01196 01197 return(value); 01198 } 01199 01200 //--------- 01201 01202 estring::estring(const unsigned long a_long) 01203 { 01204 init(); 01205 assign(a_long); 01206 } 01207 01208 estring& estring::assign(const unsigned long a_long) 01209 { 01210 std::string s; 01211 01212 TRY(T_integral_to_string(a_long,s), 01213 "Could not convert unsigned long to string"); 01214 TRY_nomem(std::string::assign(s)); 01215 m_type = type_unsigned_long; 01216 m_value.clear(); 01217 m_value.value.ul = a_long; 01218 01219 return(*this); 01220 } 01221 01222 estring& estring::operator=(const unsigned long a_long) 01223 { 01224 assign(a_long); 01225 01226 return(*this); 01227 } 01228 01229 estring::operator unsigned long() const 01230 { 01231 unsigned long value = 0; 01232 01233 TRY(T_string_to_integral((*this),value), 01234 "Cannot convert string to unsigned long"); 01235 01236 return(value); 01237 } 01238 01239 //--------- 01240 01241 estring::estring(const long a_long) 01242 { 01243 init(); 01244 assign(a_long); 01245 } 01246 01247 estring& estring::assign(const long a_long) 01248 { 01249 if (a_long < 0) { 01250 TRY(assign(static_cast<unsigned long>(-a_long)), 01251 "Could not convert signed long to string"); 01252 TRY_nomem(std::string::insert(0,"-")); 01253 } 01254 else { 01255 TRY(assign(static_cast<unsigned long>(a_long)), 01256 "Could not convert signed long to string"); 01257 } 01258 m_type = type_long; 01259 m_value.clear(); 01260 m_value.value.l = a_long; 01261 01262 return(*this); 01263 } 01264 01265 estring& estring::operator=(const long a_long) 01266 { 01267 assign(a_long); 01268 01269 return(*this); 01270 } 01271 01272 estring::operator long() const 01273 { 01274 long value = 0; 01275 01276 TRY(T_string_to_signed_integral((*this),value), 01277 "Cannot convert string to signed long"); 01278 01279 return(value); 01280 } 01281 01282 //--------- 01283 01284 estring::estring(const unsigned long long a_long) 01285 { 01286 init(); 01287 assign(a_long); 01288 } 01289 01290 estring& estring::assign(const unsigned long long a_long) 01291 { 01292 std::string s; 01293 01294 TRY(T_integral_to_string(a_long,s), 01295 "Could not convert unsigned long long to string"); 01296 TRY_nomem(std::string::assign(s)); 01297 m_type = type_unsigned_long_long; 01298 m_value.clear(); 01299 m_value.value.ull = a_long; 01300 01301 return(*this); 01302 } 01303 01304 estring& estring::operator=(const unsigned long long a_long) 01305 { 01306 assign(a_long); 01307 01308 return(*this); 01309 } 01310 01311 estring::operator unsigned long long() const 01312 { 01313 unsigned long long value = 0; 01314 01315 TRY(T_string_to_integral((*this),value), 01316 "Cannot convert string to unsigned long long"); 01317 01318 return(value); 01319 } 01320 01321 //--------- 01322 01323 estring::estring(const long long a_long) 01324 { 01325 init(); 01326 assign(a_long); 01327 } 01328 01329 estring& estring::assign(const long long a_long) 01330 { 01331 if (a_long < 0) { 01332 TRY(assign(static_cast<unsigned long long>(-a_long)), 01333 "Could not convert unsigned long long to string"); 01334 TRY_nomem(insert(0,"-")); 01335 } 01336 else { 01337 TRY(assign(static_cast<unsigned long long>(a_long)), 01338 "Could not convert unsigned long long to string"); 01339 } 01340 m_type = type_long_long; 01341 m_value.clear(); 01342 m_value.value.ll = a_long; 01343 01344 return(*this); 01345 } 01346 01347 estring& estring::operator=(const long long a_long) 01348 { 01349 assign(a_long); 01350 01351 return(*this); 01352 } 01353 01354 estring::operator long long() const 01355 { 01356 long long value = 0; 01357 01358 TRY(T_string_to_signed_integral((*this),value), 01359 "Cannot convert string to signed long long"); 01360 01361 return(value); 01362 } 01363 01364 //--------- 01365 01366 estring::estring(char const * a_ptr) 01367 { 01368 init(); 01369 assign(a_ptr); 01370 } 01371 01372 estring& estring::assign(char const * a_ptr) 01373 { 01374 std::string str; 01375 01376 TRY_nomem(str = a_ptr); 01377 TRY_nomem(assign(str)); 01378 m_type = type_char_ptr; 01379 m_value.clear(); 01380 m_value.value.char_ptr = a_ptr; 01381 01382 return(*this); 01383 } 01384 01385 estring& estring::operator=(char const * a_ptr) 01386 { 01387 assign(a_ptr); 01388 01389 return(*this); 01390 } 01391 01392 estring::operator char const *()const 01393 { 01394 char const * value = 0; 01395 01396 if ((m_type != type_char_ptr) && (m_type != type_void_ptr)) { 01397 throw(ERROR(0,"Value type is not a pointer")); 01398 } 01399 01400 value = m_value.value.char_ptr; 01401 01402 return(value); 01403 } 01404 01405 //--------- 01406 01407 estring::estring(void* const a_ptr) 01408 { 01409 init(); 01410 assign(a_ptr); 01411 } 01412 01413 estring& estring::assign(void* const a_ptr) 01414 { 01415 static const size_t buffer_len = 32; 01416 char buffer[buffer_len] = { 0 }; 01417 01418 snprintf(buffer, buffer_len, "%p", a_ptr); 01419 TRY_nomem(std::string::assign(buffer)); 01420 m_type = type_void_ptr; 01421 m_value.clear(); 01422 m_value.value.void_ptr = a_ptr; 01423 01424 return(*this); 01425 } 01426 01427 estring& estring::operator=(void* const a_ptr) 01428 { 01429 assign(a_ptr); 01430 01431 return(*this); 01432 } 01433 01434 estring::operator void*()const 01435 { 01436 void * value = 0; 01437 01438 if ((m_type != type_void_ptr) && (m_type != type_char_ptr)) { 01439 throw(ERROR(0,"Value type is not a pointer")); 01440 } 01441 01442 value = m_value.value.void_ptr; 01443 01444 return(value); 01445 } 01446 01447 //--------- 01448 01449 estring::estring(const float a_float) 01450 { 01451 init(); 01452 assign(a_float); 01453 } 01454 01455 estring& estring::assign(const float a_float) 01456 { 01457 std::string ws; 01458 std::string fs; 01459 std::string s; 01460 01461 TRY(T_fraction_to_strings(a_float,ws,fs), 01462 "Cannot convert float to string"); 01463 TRY_nomem(s = ws); 01464 if (fs.size() > 0) { 01465 TRY_nomem(s += "."); 01466 TRY_nomem(s += fs); 01467 } 01468 TRY_nomem(std::string::assign(s)); 01469 m_type = type_float; 01470 m_value.clear(); 01471 m_value.value.f = a_float; 01472 01473 return(*this); 01474 } 01475 01476 estring& estring::operator=(const float a_float) 01477 { 01478 assign(a_float); 01479 01480 return(*this); 01481 } 01482 01483 estring::estring(const float a_float, unsigned a_precision, 01484 unsigned int a_base) 01485 { 01486 init(); 01487 assign(a_float, a_precision, a_base); 01488 } 01489 01490 estring& estring::assign(const float a_float, unsigned a_precision, 01491 unsigned int a_base) 01492 { 01493 std::string ws; 01494 std::string fs; 01495 std::string s; 01496 01497 precision(a_precision); 01498 base(a_base); 01499 assign(a_float); 01500 01501 return(*this); 01502 } 01503 01504 estring::operator float() const 01505 { 01506 float value = 0.0; 01507 01508 TRY(T_string_to_fractional((*this), value), 01509 "Cannot convert string to float"); 01510 01511 return(value); 01512 } 01513 01514 //--------- 01515 01516 estring::estring(const double a_double) 01517 { 01518 init(); 01519 assign(a_double); 01520 } 01521 01522 estring& estring::assign(const double a_double) 01523 { 01524 std::string ws; 01525 std::string fs; 01526 std::string s; 01527 01528 TRY(T_fraction_to_strings(a_double,ws,fs), 01529 "Cannot convert double to string"); 01530 TRY_nomem(s = ws); 01531 if (fs.size() > 0) { 01532 TRY_nomem(s += "."); 01533 TRY_nomem(s += fs); 01534 } 01535 TRY_nomem(std::string::assign(s)); 01536 m_type = type_double; 01537 m_value.clear(); 01538 m_value.value.d = a_double; 01539 01540 return(*this); 01541 } 01542 01543 estring& estring::operator=(const double a_double) 01544 { 01545 assign(a_double); 01546 01547 return(*this); 01548 } 01549 01550 estring::estring(const double a_double, unsigned a_precision, 01551 unsigned int a_base) 01552 { 01553 init(); 01554 assign(a_double, a_precision, a_base); 01555 } 01556 01557 estring& estring::assign(const double a_double, unsigned a_precision, 01558 unsigned int a_base) 01559 { 01560 std::string ws; 01561 std::string fs; 01562 std::string s; 01563 01564 precision(a_precision); 01565 assign(a_base); 01566 assign(a_double); 01567 01568 return(*this); 01569 } 01570 01571 estring::operator double() const 01572 { 01573 double value = 0.0; 01574 01575 TRY(T_string_to_fractional((*this), value), 01576 "Cannot convert string to double"); 01577 01578 return(value); 01579 } 01580