Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include <vlCore/Say.hpp> 00033 #include <cmath> 00034 00035 using namespace vl; 00036 00037 SayArg::SayArg() 00038 { 00039 init(); 00040 } 00041 00042 SayArg::SayArg(void* d) 00043 { 00044 init(); 00045 ulonglong = reinterpret_cast<unsigned long long>(d); 00046 type = ULONGLONG; 00047 } 00048 00049 SayArg::SayArg(const std::string& d) 00050 { 00051 init(); 00052 str = d.c_str(); 00053 type = STRING; 00054 } 00055 00056 SayArg::SayArg(const unsigned char* d) 00057 { 00058 init(); 00059 if (d) 00060 str = (const char*)d; 00061 type = STRING; 00062 } 00063 00064 SayArg::SayArg(const char* d) 00065 { 00066 init(); 00067 if (d) 00068 str = d; 00069 type = STRING; 00070 } 00071 00072 SayArg::SayArg(const String& d) 00073 { 00074 init(); 00075 str = d; 00076 type = STRING; 00077 } 00078 00079 SayArg::SayArg(double d) 00080 { 00081 init(); 00082 float64 = d; 00083 type = FLOAT64; 00084 } 00085 00086 SayArg::SayArg(float d) 00087 { 00088 init(); 00089 float64 = d; 00090 type = FLOAT64; 00091 } 00092 00093 SayArg::SayArg(unsigned char d) 00094 { 00095 init(); 00096 ulonglong = d; 00097 type = ULONGLONG; 00098 } 00099 00100 SayArg::SayArg(signed char d) 00101 { 00102 init(); 00103 slonglong = d; 00104 type = SLONGLONG; 00105 } 00106 00107 SayArg::SayArg(unsigned short d) 00108 { 00109 init(); 00110 ulonglong = d; 00111 type = ULONGLONG; 00112 } 00113 00114 SayArg::SayArg(signed short d) 00115 { 00116 init(); 00117 slonglong = d; 00118 type = SLONGLONG; 00119 } 00120 00121 SayArg::SayArg(unsigned int d) 00122 { 00123 init(); 00124 ulonglong = d; 00125 type = ULONGLONG; 00126 } 00127 00128 SayArg::SayArg(signed int d) 00129 { 00130 init(); 00131 slonglong = d; 00132 type = SLONGLONG; 00133 } 00134 00135 SayArg::SayArg(unsigned long d) 00136 { 00137 init(); 00138 ulonglong = d; 00139 type = ULONGLONG; 00140 } 00141 00142 SayArg::SayArg(signed long d) 00143 { 00144 init(); 00145 slonglong = d; 00146 type = SLONGLONG; 00147 } 00148 00149 SayArg::SayArg(unsigned long long d) 00150 { 00151 init(); 00152 ulonglong = d; 00153 type = ULONGLONG; 00154 } 00155 00156 SayArg::SayArg(signed long long d) 00157 { 00158 init(); 00159 slonglong = d; 00160 type = SLONGLONG; 00161 } 00162 00163 void SayArg::init() 00164 { 00165 type = NO_TYPE; 00166 float64 = 0; 00167 ulonglong = 0; 00168 slonglong = 0; 00169 } 00170 00171 String Say::parse( const Say& pset ) const 00172 { 00173 String out; 00174 String fmt = pset.format_string; 00175 00176 int param_idx = 0; 00177 00178 int eur = -1; 00179 int base = -1; 00180 int field = -1; 00181 int decimals = -1; 00182 int align = -1; 00183 int fill = -1; 00184 int plus = -1; 00185 00186 int fmtstart = -1; 00187 00188 // %H+014.5n 00189 bool fmtdata = false; 00190 for(int i=0; i<(int)fmt.length(); ++i) 00191 { 00192 int ch = (i<(int)fmt.length()) ? (int)fmt[i+0] : -1; 00193 int next_ch = (i<(int)fmt.length()-1) ? (int)fmt[i+1] : -1; 00194 int nnext_ch = (i<(int)fmt.length()-2) ? (int)fmt[i+2] : -1; 00195 00196 if (!fmtdata) 00197 { 00198 if (ch == '%' && next_ch == '%') 00199 { 00200 out += '%'; 00201 ++i; 00202 } 00203 else 00204 if (ch == '%') 00205 { 00206 if (param_idx < (int)pset.size()) 00207 { 00208 fmtdata = true; 00209 fmtstart = i; 00210 } 00211 else 00212 { 00213 out += " !!!too few parameters: %"; 00214 } 00215 } 00216 else 00217 if (ch >= 0) 00218 { 00219 out += (unsigned short)ch; 00220 } 00221 } 00222 else 00223 { 00224 00225 if(eur == -1) 00226 { 00227 if (ch == '$') 00228 { 00229 eur = 1; 00230 continue; 00231 } 00232 } 00233 00234 if (base == -1) 00235 { 00236 switch(ch) 00237 { 00238 case 'b': base = 2; break; 00239 case 'o': base = 8; break; 00240 case 'd': base = 10; break; 00241 case 'h': base = 16; break; 00242 } 00243 if (base != -1) 00244 { 00245 if (eur == -1) 00246 eur = 0; 00247 continue; 00248 } 00249 } 00250 00251 if (plus == -1) 00252 { 00253 switch(ch) 00254 { 00255 case '+': plus = 1; break; 00256 } 00257 if (plus != -1) 00258 { 00259 if (base == -1) 00260 base = 10; 00261 if (eur == -1) 00262 eur = 0; 00263 continue; 00264 } 00265 } 00266 00267 if (fill == -1) 00268 { 00269 switch(ch) 00270 { 00271 case '0': fill = '0'; break; 00272 case ' ': fill = ' '; break; 00273 } 00274 if (fill != -1) 00275 { 00276 if (base == -1) 00277 base = 10; 00278 if (plus == -1) 00279 plus = 0; 00280 if (eur == -1) 00281 eur = 0; 00282 continue; 00283 } 00284 } 00285 00286 if (field == -1) 00287 { 00288 if (ch >= '0' && ch <= '9') 00289 { 00290 field = ch - '0'; 00291 if (next_ch >= '0' && next_ch <= '9') 00292 { 00293 field = field*10 + next_ch - '0'; 00294 ++i; 00295 } 00296 } 00297 00298 if (field != -1) 00299 { 00300 if (base == -1) 00301 base = 10; 00302 if (plus == -1) 00303 plus = 0; 00304 if (fill == -1) 00305 fill = ' '; 00306 if (eur == -1) 00307 eur = 0; 00308 continue; 00309 } 00310 } 00311 00312 if (decimals == -1) 00313 { 00314 if(ch == '.') 00315 { 00316 if (next_ch >= '0' && next_ch <= '9') 00317 { 00318 decimals = next_ch - '0'; 00319 ++i; 00320 if (nnext_ch >= '0' && nnext_ch <= '9') 00321 { 00322 decimals = decimals*10 + nnext_ch - '0'; 00323 ++i; 00324 } 00325 } 00326 } 00327 00328 if (decimals != -1) 00329 { 00330 if (base == -1) 00331 base = 10; 00332 if (plus == -1) 00333 plus = 0; 00334 if (fill == -1) 00335 fill = ' '; 00336 if (field == -1) 00337 field = 0; 00338 if (eur == -1) 00339 eur = 0; 00340 continue; 00341 } 00342 } 00343 00344 if (align == -1) 00345 { 00346 if(ch == '=') 00347 align = 0; 00348 if(ch == '<') 00349 align = 1; 00350 if(ch == '>') 00351 align = 2; 00352 00353 if (align != -1) 00354 { 00355 if (base == -1) 00356 base = 10; 00357 if (plus == -1) 00358 plus = 0; 00359 if (fill == -1) 00360 fill = ' '; 00361 if (field == -1) 00362 field = 0; 00363 if (eur == -1) 00364 eur = 0; 00365 if (decimals == -1) 00366 { 00367 switch(pset[param_idx].type) 00368 { 00369 case SayArg::FLOAT64: decimals = 6; break; 00370 default: decimals = 0; break; 00371 } 00372 } 00373 continue; 00374 } 00375 } 00376 00377 // generate formatted string 00378 00379 // output parameter 00380 const SayArg& p = pset[param_idx]; 00381 00382 if (ch == 'c') 00383 { 00384 if (fmtstart != i-1) 00385 out += " !!! '%c' does not need arguments !!! "; 00386 00387 switch(p.type) 00388 { 00389 case SayArg::FLOAT64: out += (char)p.float64; break; 00390 case SayArg::SLONGLONG: out += (char)p.slonglong; break; 00391 case SayArg::ULONGLONG: out += (char)p.ulonglong; break; 00392 default: 00393 out += " !!! wrong argument type for '%c' !!! "; 00394 break; 00395 } 00396 00397 } 00398 else 00399 if (ch == 's') 00400 { 00401 if (fmtstart != i-1) 00402 out += " !!! '%s' does not need arguments !!! "; 00403 00404 switch(p.type) 00405 { 00406 case SayArg::STRING: out += p.str; break; 00407 default: 00408 out += " !!! wrong argument type for '%s' !!! "; 00409 break; 00410 } 00411 00412 } 00413 else 00414 if (ch == 'n' || ch == 'N' || ch == 'e' || ch == 'E') 00415 { 00416 00417 if (param_idx<(int)pset.size()) 00418 { 00419 if (decimals == -1) 00420 { 00421 switch(p.type) 00422 { 00423 case SayArg::FLOAT64: decimals = 6; break; 00424 default: decimals = 0; break; 00425 } 00426 } 00427 00428 if (base == -1) 00429 base = 10; 00430 if (field == -1) 00431 field = 0; 00432 if (decimals == -1) 00433 decimals = 0; 00434 if (fill == -1) 00435 fill = ' '; 00436 if (plus == -1) 00437 plus = 0; 00438 if (align == -1) 00439 align = 2; 00440 if (eur == -1) 00441 eur = 0; 00442 00443 switch(p.type) 00444 { 00445 case SayArg::FLOAT64: out += format(p.float64, base, field, decimals, align, fill, plus, ch, eur); break; 00446 case SayArg::SLONGLONG: out += format(p.slonglong, base, field, decimals, align, fill, plus, ch, eur); break; 00447 case SayArg::ULONGLONG: out += format(p.ulonglong, base, field, decimals, align, fill, plus, ch, eur); break; 00448 default: 00449 out += " !!! wrong argument type for '%n' !!! "; 00450 break; 00451 } 00452 } 00453 else 00454 { 00455 out += " !!!missing parameter!!! "; 00456 if (ch != -1) 00457 i--; 00458 } 00459 } 00460 else 00461 { 00462 out += " !!!format error: unexpected '"; 00463 out += (char)ch; 00464 out += "' !!! "; 00465 } 00466 00467 fmtdata = false; 00468 align = -1; 00469 base = -1; 00470 field = -1; 00471 decimals = -1; 00472 align = -1; 00473 fill = -1; 00474 plus = -1; 00475 eur = -1; 00476 00477 param_idx++; 00478 } 00479 } 00480 00481 if (fmtdata) 00482 { 00483 out += " !!!truncated format!!! "; 00484 param_idx++; 00485 } 00486 00487 if (param_idx < (int)pset.size()) 00488 out += " !!!too many parameters!!! "; 00489 00490 return out; 00491 // ... fare in modo che l'output venga generato anche quando non c'e' il carattere finale ... 00492 } 00493 00494 String Say::euronotation(const String& str, int base) const 00495 { 00496 String tmp; 00497 int pos = (int)str.length(); 00498 if ( str.contains('.') ) 00499 { 00500 while(pos--) 00501 { 00502 if (str[pos] == '.') 00503 { 00504 tmp.insert(0, ','); 00505 break; 00506 } 00507 tmp.insert(0, str[pos]); 00508 } 00509 if (pos < 0) 00510 pos = (int)str.length(); 00511 } 00512 00513 int count = 0; 00514 int wait = 3; 00515 if (base == 2) 00516 wait = 4; 00517 if (base == 16) 00518 wait = 2; 00519 while(pos--) 00520 { 00521 if (count && count % wait == 0) 00522 { 00523 tmp.insert(0, '.'); 00524 } 00525 tmp.insert(0, str[pos]); 00526 count ++; 00527 } 00528 00529 return tmp; 00530 } 00531 00532 String Say::format(unsigned long long n, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const 00533 { 00534 if (field < 0) 00535 field = -field; 00536 00537 if (field > 1024) 00538 field = 1024; 00539 00540 if (decimals < 0) 00541 decimals = -decimals; 00542 if (decimals > 20) 00543 decimals = 20; 00544 00545 if (align != 0 && align != 1 && align != 2) 00546 align = 0; 00547 00548 if (base > 16) 00549 base = 16; 00550 00551 if (base < 2) 00552 base = 2; 00553 00554 String str; 00555 00556 const char* hex = "0123456789abcdef"; 00557 00558 // UNSIGNED INT ALGORITHM 00559 00560 int k = base; 00561 do 00562 { 00563 int x = (int)(n % base); 00564 int c = x/(k/base); 00565 str.insert(0, hex[c]); 00566 n = n / base; 00567 } 00568 while(n); 00569 00570 if (decimals) 00571 { 00572 str += '.'; 00573 int i = decimals; 00574 while(i--) 00575 str += '0'; 00576 } 00577 00578 bool negative = false; 00579 00580 return pipeline(str, base, field, decimals, finalizer, align, eur, fill, negative, plus); 00581 } 00582 00583 String Say::format(signed long long nn, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const 00584 { 00585 if (field < 0) 00586 field = -field; 00587 00588 if (field > 1024) 00589 field = 1024; 00590 00591 if (decimals < 0) 00592 decimals = -decimals; 00593 if (decimals > 20) 00594 decimals = 20; 00595 00596 if (align != 0 && align != 1 && align != 2) 00597 align = 0; 00598 00599 if (base > 16) 00600 base = 16; 00601 00602 if (base < 2) 00603 base = 2; 00604 00605 String str; 00606 00607 const char* hex = "0123456789abcdef"; 00608 00609 // SIGNED INT ALGORITHM 00610 00611 bool negative = nn < 0; 00612 unsigned long long n; 00613 00614 if (nn<0 && -nn<0) // overflow 00615 n = (unsigned long long)nn; 00616 else 00617 if (nn<0) 00618 n = - nn; 00619 else 00620 n = nn; 00621 00622 //if (n < 0) 00623 // n = 0; 00624 00625 int k = base; 00626 do 00627 { 00628 int x = (int)(n % base); 00629 int c = x/(k/base); 00630 str.insert(0, hex[c]); 00631 n = n / base; 00632 } 00633 while(n); 00634 00635 if (decimals) 00636 { 00637 str += '.'; 00638 int i = decimals; 00639 while(i--) 00640 str += '0'; 00641 } 00642 00643 return pipeline(str, base, field, decimals, finalizer, align, eur, fill, negative, plus); 00644 } 00645 00646 String Say::format(double num, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const 00647 { 00648 if (field < 0) 00649 field = -field; 00650 if (field > 1024) 00651 field = 1024; 00652 00653 if (decimals < 0) 00654 decimals = -decimals; 00655 if (decimals > 20) 00656 decimals = 20; 00657 00658 if (align != 0 && align != 1 && align != 2) 00659 align = 0; 00660 00661 if (base > 16) 00662 base = 16; 00663 00664 if (base < 2) 00665 base = 2; 00666 00667 String str; 00668 00669 const char* hex = "0123456789abcdef"; 00670 00671 double f = num; 00672 00673 // INDEFINITE = - 127 192 0 0 00674 // -INFINITE = - 127 128 0 0 00675 // +INFINITE = + 127 128 0 0 00676 float tmp = (float)f; 00677 unsigned char *nan= (unsigned char*)&tmp; 00678 const char* sign = nan[3] >= 128 ? "-" : "+"; 00679 unsigned char exp = (nan[3] << 1) + (nan[2] >> 7); 00680 nan[2] &= 127; 00681 unsigned int frac = nan[0] + (nan[1] << 8) + (nan[2] << 16); 00682 00683 bool negative = false; 00684 if (exp == 255 && frac == 0) 00685 { 00686 return String(sign) + "#INF"; 00687 } 00688 else 00689 if (exp == 255 && frac != 0) 00690 { 00691 return "#NAN"; 00692 } 00693 else 00694 { 00695 // ROUNDING FOR FRACTIONAL PART 00696 00697 if (finalizer == 'n' || finalizer == 'N') 00698 { 00699 double fp = f - floor(f); 00700 double eps = base/2; 00701 int dec = decimals; 00702 do 00703 { 00704 if ( !(dec--) ) 00705 break; 00706 00707 int c = (int)(fp * base); 00708 fp = fp * base - c; 00709 00710 eps /= base; 00711 00712 if (c<0 || c>15) 00713 { 00714 return "#ERR"; 00715 } 00716 00717 if (dec == 0) // round only if all the decimals are here 00718 { 00719 // program rounded fp 00720 f += eps/base; 00721 break; 00722 } 00723 } 00724 while(fp>0); 00725 } 00726 00727 if (f < 0) 00728 { 00729 f = -f; 00730 negative = true; 00731 } 00732 double n = floor(f); 00733 00734 // INTEGER PART 00735 00736 int count = 0; 00737 unsigned int base2 = base*base; 00738 unsigned int base3 = base*base*base; 00739 unsigned int base4 = base*base*base*base; 00740 unsigned int base5 = base*base*base*base*base; 00741 unsigned int base6 = base*base*base*base*base*base; 00742 unsigned int base7 = base*base*base*base*base*base*base; // maximum number in base 16 00743 while (floor(n)) 00744 { 00745 if (n>=base7) 00746 { 00747 n /= base7; 00748 count+=7; 00749 } 00750 else 00751 if (n>=base6) 00752 { 00753 n /= base6; 00754 count+=6; 00755 } 00756 else 00757 if (n>=base5) 00758 { 00759 n /= base5; 00760 count+=5; 00761 } 00762 else 00763 if (n>=base4) 00764 { 00765 n /= base4; 00766 count+=4; 00767 } 00768 else 00769 if (n>=base3) 00770 { 00771 n /= base3; 00772 count+=3; 00773 } 00774 else 00775 if (n>=base2) 00776 { 00777 n /= base2; 00778 count+=2; 00779 } 00780 else 00781 { 00782 n = n / base; 00783 count++; 00784 } 00785 } 00786 00787 // prevents rounding errors 00788 double eps = (base / 2.0) / base; 00789 for(int i=0; i<count; ++i) 00790 { 00791 eps /= base; 00792 } 00793 n+=eps; 00794 00795 if (count) 00796 { 00797 do 00798 { 00799 int c = (int)(n * (double)base); 00800 n = n * (double)base - floor(n * (double)base); 00801 int next = (int)(n * base); 00802 00803 if (c<0 || c>15 || next<0 || next>15) 00804 { 00805 return "#ERR"; 00806 } 00807 00808 str += hex[c]; 00809 } 00810 while(--count); 00811 } 00812 else 00813 str += '0'; 00814 00815 str += '.'; 00816 00817 // FRACTIONAL PART 00818 00819 double fp = f - floor(f); 00820 do 00821 { 00822 int c = (int)(fp * base); 00823 fp = fp * base - c; 00824 00825 if (c<0 || c>15) 00826 { 00827 return "#ERR"; 00828 } 00829 00830 str += hex[c]; 00831 } 00832 while(fp>0); 00833 00834 // COMMON PIPELINE 00835 00836 // (1) EXPONENTIAL SHIFT 00837 // (2) CLIP & FILL DECIMALS 00838 // (3) EXPONENTIAL DECORATIONS 00839 // (4) EURO NOTATION 00840 // (5) FIELD, ALIGN AND SIGN 00841 // (6) CASE TRANSFORM 00842 00843 return pipeline(str, base, field, decimals, finalizer, align, eur, fill, negative, plus); 00844 } 00845 } 00846 00847 String Say::pipeline(const String& in_str, int base, int field, int decimals, int finalizer, int align, int eur, int fill, int negative, int plus) const 00848 { 00849 String str = in_str; 00850 // EXPONENTIAL SHIFT 00851 00852 int shift = 0; 00853 // exponential notation 00854 if (finalizer == 'e' || finalizer == 'E') 00855 { 00856 int ptpos = (int)str.length(); // point position 00857 int nzpos = -1; // non zero position 00858 for(int i=0; i<(int)str.length(); ++i) 00859 { 00860 if(str[i] != '0' && nzpos == -1 && str[i] != '.') 00861 nzpos = i; 00862 else 00863 if (str[i] == '.') 00864 ptpos = i; 00865 } 00866 00867 if (nzpos == -1) 00868 shift = 0; 00869 else 00870 shift = ptpos - nzpos - ( (ptpos > nzpos) ? 1 : 0 ); 00871 00872 // remove the point 00873 str.remove( ptpos, 1 ); 00874 00875 // remove all the zeros on the left 00876 while( str.length() && str[0] == '0' ) 00877 str.remove(0); 00878 00879 // reinsert the point at the 2-nd position 00880 // with up to 2 zero if needed. 00881 if (str.length() == 1) 00882 str += '0'; 00883 if (str.length() == 0) 00884 str = "00"; 00885 00886 str.insert(1, '.'); 00887 } 00888 00889 // CLIP AND FILL DECIMALS 00890 00891 // position of the dot 00892 if ( !str.contains('.') ) 00893 str += ".0"; 00894 int pos = str.find('.'); 00895 // number of decimals 00896 int decs = (int)str.length() - pos -1; 00897 // trim decimals 00898 if (decs > decimals) 00899 { 00900 // remove also the dot 00901 int dot = decimals == 0 ? 1 : 0; 00902 str.resize(str.length() - (decs - decimals + dot)); 00903 } 00904 else 00905 { 00906 // add missing decimals 00907 int i = decimals - decs; 00908 while(i--) 00909 str += '0'; 00910 } 00911 00912 // EXPONENTIAL DECORATION 00913 00914 if (finalizer == 'e' || finalizer == 'E') 00915 { 00916 str += 'e'; 00917 str += format((signed long long)shift, base, 0, 0, 2, 0, 1, 0,0); 00918 } 00919 else 00920 // EURO NOTATION 00921 00922 if (eur) 00923 str = euronotation(str, base); 00924 00925 // FIELD, SIGN, ALIGN 00926 00927 int right = (field - (int)str.length()) / 2; 00928 right = right < 0 ? 0 : right; 00929 00930 int left = (field - (int)str.length()) - right; 00931 left = left < 0 ? 0 : left; 00932 00933 if (align == 1) // left 00934 { 00935 right += left; 00936 left = 0; 00937 } 00938 else 00939 if (align == 2) // right 00940 { 00941 left += right; 00942 right = 0; 00943 } 00944 00945 // fill left 00946 str.insert(0, (wchar_t)fill, left); 00947 00948 // fill right 00949 str.append(fill, right); 00950 00951 if (negative) 00952 { 00953 if (left) 00954 str.remove(0); 00955 else 00956 if (right) 00957 str.resize(str.length()-1); 00958 00959 str.insert(0, '-'); 00960 } 00961 else 00962 if(plus) 00963 { 00964 if (left) 00965 str.remove(0); 00966 else 00967 if (right) 00968 str.resize(str.length()-1); 00969 00970 str.insert(0, '+'); 00971 } 00972 00973 // CASE TRANSFORM 00974 00975 if (finalizer == 'N' || finalizer == 'E') 00976 { 00977 for(int i=0; i<(int)str.length(); ++i) 00978 if (str[i] >= 'a' && str[i] <= 'z') 00979 str[i] = str[i] - 'a' + 'A'; 00980 } 00981 00982 return str; 00983 } 00984