00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "unicode/utypes.h"
00021 #include "uprintf.h"
00022 #include "uprntf_p.h"
00023 #include "unicode/ustdio.h"
00024 #include "ufile.h"
00025 #include "unicode/ustring.h"
00026 #include "locbund.h"
00027 #include "umutex.h"
00028 #include "unicode/unum.h"
00029 #include "unicode/udat.h"
00030
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <math.h>
00034 #include <float.h>
00035 #include <limits.h>
00036
00037 static u_printf_handler g_u_printf_handlers [256];
00038 static u_printf_info g_u_printf_infos [256];
00039 static UBool g_u_printf_inited = FALSE;
00040
00041
00042 #define UFPRINTF_BUFFER_SIZE 1024
00043
00044 int32_t
00045 u_fprintf( UFILE *f,
00046 const char *patternSpecification,
00047 ... )
00048 {
00049 va_list ap;
00050 int32_t count;
00051
00052 va_start(ap, patternSpecification);
00053 count = u_vfprintf(f, patternSpecification, ap);
00054 va_end(ap);
00055
00056 return count;
00057 }
00058
00059 int32_t
00060 u_fprintf_u( UFILE *f,
00061 const UChar *patternSpecification,
00062 ... )
00063 {
00064 va_list ap;
00065 int32_t count;
00066
00067 va_start(ap, patternSpecification);
00068 count = u_vfprintf_u(f, patternSpecification, ap);
00069 va_end(ap);
00070
00071 return count;
00072 }
00073
00074 int32_t
00075 u_vfprintf( UFILE *f,
00076 const char *patternSpecification,
00077 va_list ap)
00078 {
00079 int32_t count;
00080 UChar *pattern;
00081
00082
00083 pattern = ufmt_defaultCPToUnicode(patternSpecification,
00084 strlen(patternSpecification));
00085 if(pattern == 0) {
00086 return 0;
00087 }
00088
00089
00090 count = u_vfprintf_u(f, pattern, ap);
00091
00092
00093 free(pattern);
00094
00095 return count;
00096 }
00097
00098 int32_t
00099 u_printf_register_handler(UChar spec,
00100 u_printf_info info,
00101 u_printf_handler handler)
00102 {
00103
00104 umtx_lock(0);
00105
00106
00107 g_u_printf_infos[ (unsigned char) spec ] = info;
00108 g_u_printf_handlers[ (unsigned char) spec ] = handler;
00109
00110
00111 umtx_unlock(0);
00112 return 0;
00113 }
00114
00115
00116
00117 int32_t
00118 u_printf_simple_percent_info(const u_printf_spec_info *info,
00119 int32_t *argtypes,
00120 int32_t n)
00121 {
00122
00123 return 0;
00124 }
00125
00126 int32_t
00127 u_printf_simple_percent_handler(UFILE *stream,
00128 const u_printf_spec_info *info,
00129 const ufmt_args *args)
00130 {
00131
00132 u_fputc(0x0025, stream);
00133
00134 return 1;
00135 }
00136
00137
00138
00139 int32_t
00140 u_printf_string_info(const u_printf_spec_info *info,
00141 int32_t *argtypes,
00142 int32_t n)
00143 {
00144
00145 if(n < 1)
00146 return 0;
00147
00148
00149 argtypes[0] = ufmt_string;
00150 return 1;
00151 }
00152
00153 int32_t
00154 u_printf_string_handler(UFILE *stream,
00155 const u_printf_spec_info *info,
00156 const ufmt_args *args)
00157 {
00158 UChar *s;
00159 int32_t len, written, i;
00160 const char *arg = (const char*)(args[0].ptrValue);
00161
00162
00163 s = ufmt_defaultCPToUnicode(arg, strlen(arg));
00164 if(s == 0) {
00165 return 0;
00166 }
00167 len = u_strlen(s);
00168
00169
00170
00171
00172
00173
00174 if(info->fPrecision != -1 && len > info->fPrecision) {
00175 written = u_file_write(s, info->fPrecision, stream);
00176 }
00177
00178
00179 else if(info->fWidth != -1 && len < info->fWidth) {
00180
00181 if(info->fLeft) {
00182 written = u_file_write(s, len, stream);
00183 for(i = 0; i < info->fWidth - len; ++i)
00184 written += u_file_write(&info->fPadChar, 1, stream);
00185 }
00186
00187 else {
00188 written = 0;
00189 for(i = 0; i < info->fWidth - len; ++i)
00190 written += u_file_write(&info->fPadChar, 1, stream);
00191 written += u_file_write(s, len, stream);
00192 }
00193 }
00194
00195
00196 else
00197 written = u_file_write(s, len, stream);
00198
00199
00200 free(s);
00201
00202 return written;
00203 }
00204
00205 int32_t
00206 u_printf_integer_info(const u_printf_spec_info *info,
00207 int32_t *argtypes,
00208 int32_t n)
00209 {
00210
00211 if(n < 1)
00212 return 0;
00213
00214
00215 argtypes[0] = ufmt_int;
00216 return 1;
00217 }
00218
00219 int32_t
00220 u_printf_integer_handler(UFILE *stream,
00221 const u_printf_spec_info *info,
00222 const ufmt_args *args)
00223 {
00224 int32_t written = 0;
00225 int32_t len;
00226 long num = (long) (args[0].intValue);
00227 UNumberFormat *format;
00228 UChar result [UFPRINTF_BUFFER_SIZE];
00229 int32_t i, minDigits = -1;
00230 UErrorCode status = U_ZERO_ERROR;
00231
00232
00233
00234 if(info->fIsShort)
00235 num &= SHRT_MAX;
00236 else if(! info->fIsLong || ! info->fIsLongLong)
00237 num &= INT_MAX;
00238
00239
00240 format = u_locbund_getNumberFormat(stream->fBundle);
00241
00242
00243 if(format == 0)
00244 return 0;
00245
00246
00247
00248
00249 if(info->fPrecision != -1) {
00250
00251 if(! stream->fOwnBundle) {
00252 stream->fBundle = u_locbund_clone(stream->fBundle);
00253 stream->fOwnBundle = TRUE;
00254 format = u_locbund_getNumberFormat(stream->fBundle);
00255 }
00256
00257
00258 minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
00259 unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
00260 }
00261
00262
00263 if(info->fShowSign) {
00264
00265 if(! stream->fOwnBundle) {
00266 stream->fBundle = u_locbund_clone(stream->fBundle);
00267 stream->fOwnBundle = TRUE;
00268 format = u_locbund_getNumberFormat(stream->fBundle);
00269 }
00270
00271
00272
00273 }
00274
00275
00276 unum_format(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
00277 len = u_strlen(result);
00278
00279
00280 if(info->fWidth != -1 && len < info->fWidth) {
00281
00282 if(info->fLeft) {
00283 written = u_file_write(result, len, stream);
00284 for(i = 0; i < info->fWidth - len; ++i)
00285 written += u_file_write(&info->fPadChar, 1, stream);
00286 }
00287
00288 else {
00289 written = 0;
00290 for(i = 0; i < info->fWidth - len; ++i)
00291 written += u_file_write(&info->fPadChar, 1, stream);
00292 written += u_file_write(result, len, stream);
00293 }
00294 }
00295
00296 else
00297 written = u_file_write(result, len, stream);
00298
00299
00300 if(minDigits != -1)
00301 unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
00302
00303 return written;
00304 }
00305
00306 int32_t
00307 u_printf_hex_info(const u_printf_spec_info *info,
00308 int32_t *argtypes,
00309 int32_t n)
00310 {
00311
00312 if(n < 1)
00313 return 0;
00314
00315
00316 argtypes[0] = ufmt_int;
00317 return 1;
00318 }
00319
00320 int32_t
00321 u_printf_hex_handler(UFILE *stream,
00322 const u_printf_spec_info *info,
00323 const ufmt_args *args)
00324 {
00325 int32_t written = 0;
00326 long num = (long) (args[0].intValue);
00327 int32_t i;
00328 UChar result [UFPRINTF_BUFFER_SIZE];
00329 int32_t len = UFPRINTF_BUFFER_SIZE;
00330
00331
00332
00333 if(info->fIsShort)
00334 num &= SHRT_MAX;
00335 else if(! info->fIsLong || ! info->fIsLongLong)
00336 num &= INT_MAX;
00337
00338
00339 ufmt_ltou(result, &len, num, 16,
00340 (UBool)(info->fSpec == 0x0078),
00341 (info->fPrecision == -1 && info->fZero) ? info->fWidth : info->fPrecision);
00342
00343
00344 if(num != 0 && info->fAlt && len < UFPRINTF_BUFFER_SIZE - 2) {
00345
00346 memmove(result + 2, result, len * sizeof(UChar));
00347 result[0] = 0x0030;
00348 result[1] = info->fSpec;
00349 len += 2;
00350 }
00351
00352
00353 if(info->fWidth != -1 && len < info->fWidth) {
00354
00355 if(info->fLeft) {
00356 written = u_file_write(result, len, stream);
00357 for(i = 0; i < info->fWidth - len; ++i)
00358 written += u_file_write(&info->fPadChar, 1, stream);
00359 }
00360
00361 else {
00362 written = 0;
00363 for(i = 0; i < info->fWidth - len; ++i)
00364 written += u_file_write(&info->fPadChar, 1, stream);
00365 written += u_file_write(result, len, stream);
00366 }
00367 }
00368
00369 else
00370 written = u_file_write(result, len, stream);
00371
00372 return written;
00373 }
00374
00375 int32_t
00376 u_printf_octal_info(const u_printf_spec_info *info,
00377 int32_t *argtypes,
00378 int32_t n)
00379 {
00380
00381 if(n < 1)
00382 return 0;
00383
00384
00385 argtypes[0] = ufmt_int;
00386 return 1;
00387 }
00388
00389 int32_t
00390 u_printf_octal_handler(UFILE *stream,
00391 const u_printf_spec_info *info,
00392 const ufmt_args *args)
00393 {
00394 int32_t written = 0;
00395 long num = (long) (args[0].intValue);
00396 int32_t i;
00397 UChar result [UFPRINTF_BUFFER_SIZE];
00398 int32_t len = UFPRINTF_BUFFER_SIZE;
00399
00400
00401
00402 if(info->fIsShort)
00403 num &= SHRT_MAX;
00404 else if(! info->fIsLong || ! info->fIsLongLong)
00405 num &= INT_MAX;
00406
00407
00408 ufmt_ltou(result, &len, num, 8,
00409 FALSE,
00410 info->fPrecision == -1 && info->fZero ? info->fWidth : info->fPrecision);
00411
00412
00413 if(info->fAlt && result[0] != 0x0030 && len < UFPRINTF_BUFFER_SIZE - 1) {
00414
00415 memmove(result + 1, result, len * sizeof(UChar));
00416 result[0] = 0x0030;
00417 len += 1;
00418 }
00419
00420
00421 if(info->fWidth != -1 && len < info->fWidth) {
00422
00423 if(info->fLeft) {
00424 written = u_file_write(result, len, stream);
00425 for(i = 0; i < info->fWidth - len; ++i)
00426 written += u_file_write(&info->fPadChar, 1, stream);
00427 }
00428
00429 else {
00430 written = 0;
00431 for(i = 0; i < info->fWidth - len; ++i)
00432 written += u_file_write(&info->fPadChar, 1, stream);
00433 written += u_file_write(result, len, stream);
00434 }
00435 }
00436
00437 else
00438 written = u_file_write(result, len, stream);
00439
00440 return written;
00441 }
00442
00443
00444 int32_t
00445 u_printf_double_info(const u_printf_spec_info *info,
00446 int32_t *argtypes,
00447 int32_t n)
00448 {
00449
00450 if(n < 1)
00451 return 0;
00452
00453
00454 argtypes[0] = ufmt_double;
00455 return 1;
00456 }
00457
00458 int32_t
00459 u_printf_double_handler(UFILE *stream,
00460 const u_printf_spec_info *info,
00461 const ufmt_args *args)
00462 {
00463 int32_t written = 0;
00464 int32_t len;
00465 double num = (double) (args[0].doubleValue);
00466 UNumberFormat *format;
00467 UChar result [UFPRINTF_BUFFER_SIZE];
00468 int32_t i, minDecimalDigits;
00469 int32_t maxDecimalDigits;
00470 UErrorCode status = U_ZERO_ERROR;
00471
00472
00473
00474
00475
00476
00477 format = u_locbund_getNumberFormat(stream->fBundle);
00478
00479
00480 if(format == 0)
00481 return 0;
00482
00483
00484
00485
00486 if(! stream->fOwnBundle) {
00487 stream->fBundle = u_locbund_clone(stream->fBundle);
00488 stream->fOwnBundle = TRUE;
00489 format = u_locbund_getNumberFormat(stream->fBundle);
00490 }
00491
00492
00493
00494
00495 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
00496 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
00497
00498 if(info->fPrecision != -1) {
00499
00500 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
00501 }
00502 else if(info->fPrecision == 0 && ! info->fAlt) {
00503
00504 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
00505 }
00506 else if(info->fAlt) {
00507
00508
00509 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
00510 }
00511 else {
00512
00513 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
00514 }
00515
00516
00517 if(info->fShowSign) {
00518
00519
00520 }
00521
00522
00523 unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
00524 len = u_strlen(result);
00525
00526
00527 if(info->fWidth != -1 && len < info->fWidth) {
00528
00529 if(info->fLeft) {
00530 written = u_file_write(result, len, stream);
00531 for(i = 0; i < info->fWidth - len; ++i)
00532 written += u_file_write(&info->fPadChar, 1, stream);
00533 }
00534
00535 else {
00536 written = 0;
00537 for(i = 0; i < info->fWidth - len; ++i)
00538 written += u_file_write(&info->fPadChar, 1, stream);
00539 written += u_file_write(result, len, stream);
00540 }
00541 }
00542
00543 else
00544 written = u_file_write(result, len, stream);
00545
00546
00547 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
00548 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
00549
00550 return written;
00551 }
00552
00553
00554 int32_t
00555 u_printf_char_info(const u_printf_spec_info *info,
00556 int32_t *argtypes,
00557 int32_t n)
00558 {
00559
00560 if(n < 1)
00561 return 0;
00562
00563
00564 argtypes[0] = ufmt_char;
00565 return 1;
00566 }
00567
00568 int32_t
00569 u_printf_char_handler(UFILE *stream,
00570 const u_printf_spec_info *info,
00571 const ufmt_args *args)
00572 {
00573 UChar *s;
00574 int32_t len, written = 0, i;
00575 unsigned char arg = (unsigned char)(args[0].intValue);
00576
00577
00578 s = ufmt_defaultCPToUnicode((const char *)&arg, 1);
00579 if(s == 0) {
00580 return 0;
00581 }
00582 len = u_strlen(s);
00583
00584
00585
00586
00587
00588
00589 if(info->fPrecision != -1 && len > info->fPrecision) {
00590 written = u_file_write(s, info->fPrecision, stream);
00591 }
00592
00593
00594 else if(info->fWidth != -1 && len < info->fWidth) {
00595
00596 if(info->fLeft) {
00597 written = u_file_write(s, len, stream);
00598 for(i = 0; i < info->fWidth - len; ++i)
00599 written += u_file_write(&info->fPadChar, 1, stream);
00600 }
00601
00602 else {
00603 written = 0;
00604 for(i = 0; i < info->fWidth - len; ++i)
00605 written += u_file_write(&info->fPadChar, 1, stream);
00606 written += u_file_write(s, len, stream);
00607 }
00608 }
00609
00610
00611 else
00612 written = u_file_write(s, len, stream);
00613
00614
00615 free(s);
00616
00617 return written;
00618 }
00619
00620
00621 int32_t
00622 u_printf_pointer_info(const u_printf_spec_info *info,
00623 int32_t *argtypes,
00624 int32_t n)
00625 {
00626
00627 if(n < 1)
00628 return 0;
00629
00630
00631 argtypes[0] = ufmt_pointer;
00632 return 1;
00633 }
00634
00635 int32_t
00636 u_printf_pointer_handler(UFILE *stream,
00637 const u_printf_spec_info *info,
00638 const ufmt_args *args)
00639 {
00640 int32_t written = 0;
00641 long num = (long) (args[0].intValue);
00642 int32_t i;
00643 UChar result [UFPRINTF_BUFFER_SIZE];
00644 int32_t len = UFPRINTF_BUFFER_SIZE;
00645
00646
00647
00648 ufmt_ltou(result, &len, num, 16, TRUE, info->fPrecision);
00649
00650
00651 if(info->fWidth != -1 && len < info->fWidth) {
00652
00653 if(info->fLeft) {
00654 written = u_file_write(result, len, stream);
00655 for(i = 0; i < info->fWidth - len; ++i)
00656 written += u_file_write(&info->fPadChar, 1, stream);
00657 }
00658
00659 else {
00660 written = 0;
00661 for(i = 0; i < info->fWidth - len; ++i)
00662 written += u_file_write(&info->fPadChar, 1, stream);
00663 written += u_file_write(result, len, stream);
00664 }
00665 }
00666
00667 else
00668 written = u_file_write(result, len, stream);
00669
00670 return written;
00671 }
00672
00673
00674 int32_t
00675 u_printf_scientific_info(const u_printf_spec_info *info,
00676 int32_t *argtypes,
00677 int32_t n)
00678 {
00679
00680 if(n < 1)
00681 return 0;
00682
00683
00684 argtypes[0] = ufmt_double;
00685 return 1;
00686 }
00687
00688 int32_t
00689 u_printf_scientific_handler(UFILE *stream,
00690 const u_printf_spec_info *info,
00691 const ufmt_args *args)
00692 {
00693 int32_t written = 0;
00694 int32_t len;
00695 double num = (double) (args[0].doubleValue);
00696 UNumberFormat *format;
00697 UChar result [UFPRINTF_BUFFER_SIZE];
00698 int32_t i, minDecimalDigits;
00699 int32_t maxDecimalDigits;
00700 UErrorCode status = U_ZERO_ERROR;
00701
00702
00703
00704
00705
00706
00707
00708 format = u_locbund_getScientificFormat(stream->fBundle);
00709
00710
00711 if(format == 0)
00712 return 0;
00713
00714
00715
00716
00717 if(! stream->fOwnBundle) {
00718 stream->fBundle = u_locbund_clone(stream->fBundle);
00719 stream->fOwnBundle = TRUE;
00720 format = u_locbund_getScientificFormat(stream->fBundle);
00721 }
00722
00723
00724
00725
00726 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
00727 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
00728
00729 if(info->fPrecision != -1) {
00730
00731 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
00732 }
00733 else if(info->fPrecision == 0 && ! info->fAlt) {
00734
00735 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
00736 }
00737 else if(info->fAlt) {
00738
00739
00740 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
00741 }
00742 else {
00743
00744 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
00745 }
00746
00747
00748 if(info->fShowSign) {
00749
00750
00751 }
00752
00753
00754 unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
00755 len = u_strlen(result);
00756
00757
00758 if(info->fWidth != -1 && len < info->fWidth) {
00759
00760 if(info->fLeft) {
00761 written = u_file_write(result, len, stream);
00762 for(i = 0; i < info->fWidth - len; ++i)
00763 written += u_file_write(&info->fPadChar, 1, stream);
00764 }
00765
00766 else {
00767 written = 0;
00768 for(i = 0; i < info->fWidth - len; ++i)
00769 written += u_file_write(&info->fPadChar, 1, stream);
00770 written += u_file_write(result, len, stream);
00771 }
00772 }
00773
00774 else
00775 written = u_file_write(result, len, stream);
00776
00777
00778 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
00779 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
00780
00781 return written;
00782 }
00783
00784 int32_t
00785 u_printf_date_info(const u_printf_spec_info *info,
00786 int32_t *argtypes,
00787 int32_t n)
00788 {
00789
00790 if(n < 1)
00791 return 0;
00792
00793
00794 argtypes[0] = ufmt_date;
00795 return 1;
00796 }
00797
00798 int32_t
00799 u_printf_date_handler(UFILE *stream,
00800 const u_printf_spec_info *info,
00801 const ufmt_args *args)
00802 {
00803 int32_t written = 0;
00804 int32_t len;
00805 UDate num = (UDate) (args[0].dateValue);
00806 UDateFormat *format;
00807 UChar result [UFPRINTF_BUFFER_SIZE];
00808 int32_t i;
00809 UErrorCode status = U_ZERO_ERROR;
00810
00811
00812
00813 format = u_locbund_getDateFormat(stream->fBundle);
00814
00815
00816 if(format == 0)
00817 return 0;
00818
00819
00820 udat_format(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
00821 len = u_strlen(result);
00822
00823
00824 if(info->fWidth != -1 && len < info->fWidth) {
00825
00826 if(info->fLeft) {
00827 written = u_file_write(result, len, stream);
00828 for(i = 0; i < info->fWidth - len; ++i)
00829 written += u_file_write(&info->fPadChar, 1, stream);
00830 }
00831
00832 else {
00833 written = 0;
00834 for(i = 0; i < info->fWidth - len; ++i)
00835 written += u_file_write(&info->fPadChar, 1, stream);
00836 written += u_file_write(result, len, stream);
00837 }
00838 }
00839
00840 else
00841 written = u_file_write(result, len, stream);
00842
00843 return written;
00844 }
00845
00846 int32_t
00847 u_printf_time_info(const u_printf_spec_info *info,
00848 int32_t *argtypes,
00849 int32_t n)
00850 {
00851
00852 if(n < 1)
00853 return 0;
00854
00855
00856 argtypes[0] = ufmt_date;
00857 return 1;
00858 }
00859
00860 int32_t
00861 u_printf_time_handler(UFILE *stream,
00862 const u_printf_spec_info *info,
00863 const ufmt_args *args)
00864 {
00865 int32_t written = 0;
00866 int32_t len;
00867 UDate num = (UDate) (args[0].dateValue);
00868 UDateFormat *format;
00869 UChar result [UFPRINTF_BUFFER_SIZE];
00870 int32_t i;
00871 UErrorCode status = U_ZERO_ERROR;
00872
00873
00874
00875 format = u_locbund_getTimeFormat(stream->fBundle);
00876
00877
00878 if(format == 0)
00879 return 0;
00880
00881
00882 udat_format(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
00883 len = u_strlen(result);
00884
00885
00886 if(info->fWidth != -1 && len < info->fWidth) {
00887
00888 if(info->fLeft) {
00889 written = u_file_write(result, len, stream);
00890 for(i = 0; i < info->fWidth - len; ++i)
00891 written += u_file_write(&info->fPadChar, 1, stream);
00892 }
00893
00894 else {
00895 written = 0;
00896 for(i = 0; i < info->fWidth - len; ++i)
00897 written += u_file_write(&info->fPadChar, 1, stream);
00898 written += u_file_write(result, len, stream);
00899 }
00900 }
00901
00902 else
00903 written = u_file_write(result, len, stream);
00904
00905 return written;
00906 }
00907
00908
00909 int32_t
00910 u_printf_percent_info(const u_printf_spec_info *info,
00911 int32_t *argtypes,
00912 int32_t n)
00913 {
00914
00915 if(n < 1)
00916 return 0;
00917
00918
00919 argtypes[0] = ufmt_double;
00920 return 1;
00921 }
00922
00923 int32_t
00924 u_printf_percent_handler(UFILE *stream,
00925 const u_printf_spec_info *info,
00926 const ufmt_args *args)
00927 {
00928 int32_t written = 0;
00929 int32_t len;
00930 double num = (double) (args[0].doubleValue);
00931 UNumberFormat *format;
00932 UChar result [UFPRINTF_BUFFER_SIZE];
00933 int32_t i, minDecimalDigits;
00934 int32_t maxDecimalDigits;
00935 UErrorCode status = U_ZERO_ERROR;
00936
00937
00938
00939
00940
00941
00942
00943 format = u_locbund_getPercentFormat(stream->fBundle);
00944
00945
00946 if(format == 0)
00947 return 0;
00948
00949
00950
00951
00952 if(! stream->fOwnBundle) {
00953 stream->fBundle = u_locbund_clone(stream->fBundle);
00954 stream->fOwnBundle = TRUE;
00955 format = u_locbund_getPercentFormat(stream->fBundle);
00956 }
00957
00958
00959
00960
00961 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
00962 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
00963
00964 if(info->fPrecision != -1) {
00965
00966 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
00967 }
00968 else if(info->fPrecision == 0 && ! info->fAlt) {
00969
00970 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
00971 }
00972 else if(info->fAlt) {
00973
00974
00975 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
00976 }
00977 else {
00978
00979 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
00980 }
00981
00982
00983 if(info->fShowSign) {
00984
00985
00986 }
00987
00988
00989 unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
00990 len = u_strlen(result);
00991
00992
00993 if(info->fWidth != -1 && len < info->fWidth) {
00994
00995 if(info->fLeft) {
00996 written = u_file_write(result, len, stream);
00997 for(i = 0; i < info->fWidth - len; ++i)
00998 written += u_file_write(&info->fPadChar, 1, stream);
00999 }
01000
01001 else {
01002 written = 0;
01003 for(i = 0; i < info->fWidth - len; ++i)
01004 written += u_file_write(&info->fPadChar, 1, stream);
01005 written += u_file_write(result, len, stream);
01006 }
01007 }
01008
01009 else
01010 written = u_file_write(result, len, stream);
01011
01012
01013 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
01014 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
01015
01016 return written;
01017 }
01018
01019
01020 int32_t
01021 u_printf_currency_info(const u_printf_spec_info *info,
01022 int32_t *argtypes,
01023 int32_t n)
01024 {
01025
01026 if(n < 1)
01027 return 0;
01028
01029
01030 argtypes[0] = ufmt_double;
01031 return 1;
01032 }
01033
01034 int32_t
01035 u_printf_currency_handler(UFILE *stream,
01036 const u_printf_spec_info *info,
01037 const ufmt_args *args)
01038 {
01039 int32_t written = 0;
01040 int32_t len;
01041 double num = (double) (args[0].doubleValue);
01042 UNumberFormat *format;
01043 UChar result [UFPRINTF_BUFFER_SIZE];
01044 int32_t i, minDecimalDigits;
01045 int32_t maxDecimalDigits;
01046 UErrorCode status = U_ZERO_ERROR;
01047
01048
01049
01050
01051
01052
01053
01054 format = u_locbund_getCurrencyFormat(stream->fBundle);
01055
01056
01057 if(format == 0)
01058 return 0;
01059
01060
01061
01062
01063 if(! stream->fOwnBundle) {
01064 stream->fBundle = u_locbund_clone(stream->fBundle);
01065 stream->fOwnBundle = TRUE;
01066 format = u_locbund_getCurrencyFormat(stream->fBundle);
01067 }
01068
01069
01070
01071
01072 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
01073 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
01074
01075 if(info->fPrecision != -1) {
01076
01077 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
01078 }
01079 else if(info->fPrecision == 0 && ! info->fAlt) {
01080
01081 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
01082 }
01083 else if(info->fAlt) {
01084
01085
01086 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
01087 }
01088 else {
01089
01090 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
01091 }
01092
01093
01094 if(info->fShowSign) {
01095
01096
01097 }
01098
01099
01100 unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
01101 len = u_strlen(result);
01102
01103
01104 if(info->fWidth != -1 && len < info->fWidth) {
01105
01106 if(info->fLeft) {
01107 written = u_file_write(result, len, stream);
01108 for(i = 0; i < info->fWidth - len; ++i)
01109 written += u_file_write(&info->fPadChar, 1, stream);
01110 }
01111
01112 else {
01113 written = 0;
01114 for(i = 0; i < info->fWidth - len; ++i)
01115 written += u_file_write(&info->fPadChar, 1, stream);
01116 written += u_file_write(result, len, stream);
01117 }
01118 }
01119
01120 else
01121 written = u_file_write(result, len, stream);
01122
01123
01124 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
01125 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
01126
01127 return written;
01128 }
01129
01130 int32_t
01131 u_printf_ustring_info(const u_printf_spec_info *info,
01132 int32_t *argtypes,
01133 int32_t n)
01134 {
01135
01136 if(n < 1)
01137 return 0;
01138
01139
01140 argtypes[0] = ufmt_ustring;
01141 return 1;
01142 }
01143
01144 int32_t
01145 u_printf_ustring_handler(UFILE *stream,
01146 const u_printf_spec_info *info,
01147 const ufmt_args *args)
01148 {
01149 int32_t len, written, i;
01150 const UChar *arg = (const UChar*)(args[0].ptrValue);
01151
01152
01153 len = u_strlen(arg);
01154
01155
01156
01157
01158
01159
01160 if(info->fPrecision != -1 && len > info->fPrecision) {
01161 written = u_file_write(arg, info->fPrecision, stream);
01162 }
01163
01164
01165 else if(info->fWidth != -1 && len < info->fWidth) {
01166
01167 if(info->fLeft) {
01168 written = u_file_write(arg, len, stream);
01169 for(i = 0; i < info->fWidth - len; ++i)
01170 written += u_file_write(&info->fPadChar, 1, stream);
01171 }
01172
01173 else {
01174 written = 0;
01175 for(i = 0; i < info->fWidth - len; ++i)
01176 written += u_file_write(&info->fPadChar, 1, stream);
01177 written += u_file_write(arg, len, stream);
01178 }
01179 }
01180
01181
01182 else
01183 written = u_file_write(arg, len, stream);
01184
01185 return written;
01186 }
01187
01188
01189
01190 int32_t
01191 u_printf_uchar_info(const u_printf_spec_info *info,
01192 int32_t *argtypes,
01193 int32_t n)
01194 {
01195
01196 if(n < 1)
01197 return 0;
01198
01199
01200 argtypes[0] = ufmt_uchar;
01201 return 1;
01202 }
01203
01204 int32_t
01205 u_printf_uchar_handler(UFILE *stream,
01206 const u_printf_spec_info *info,
01207 const ufmt_args *args)
01208 {
01209 int32_t written = 0, i;
01210 UChar arg = (UChar)(args[0].intValue);
01211
01212
01213
01214
01215
01216
01217
01218 if(info->fPrecision != -1 && info->fPrecision < 1) {
01219
01220 written = 0;
01221 }
01222
01223
01224 else if(info->fWidth != -1 && info->fWidth > 1) {
01225
01226 if(info->fLeft) {
01227 written = u_file_write(&arg, 1, stream);
01228 for(i = 0; i < info->fWidth - 1; ++i)
01229 written += u_file_write(&info->fPadChar, 1, stream);
01230 }
01231
01232 else {
01233 written = 0;
01234 for(i = 0; i < info->fWidth - 1; ++i)
01235 written += u_file_write(&info->fPadChar, 1, stream);
01236 written += u_file_write(&arg, 1, stream);
01237 }
01238 }
01239
01240
01241 else
01242 written = u_file_write(&arg, 1, stream);
01243
01244 return written;
01245 }
01246
01247 int32_t
01248 u_printf_scidbl_info(const u_printf_spec_info *info,
01249 int32_t *argtypes,
01250 int32_t n)
01251 {
01252
01253 if(n < 1)
01254 return 0;
01255
01256
01257 argtypes[0] = ufmt_double;
01258 return 1;
01259 }
01260
01261 int32_t
01262 u_printf_scidbl_handler(UFILE *stream,
01263 const u_printf_spec_info *info,
01264 const ufmt_args *args)
01265 {
01266 double num = (double)(args[0].doubleValue);
01267 UBool useE;
01268
01269
01270 if(info->fPrecision == 0)
01271 ((u_printf_spec_info*)info)->fPrecision = 1;
01272
01273
01274 useE = (UBool)(num < 0.0001
01275 || (info->fPrecision != -1 && num > pow(10.0, info->fPrecision)));
01276
01277
01278 if(useE) {
01279
01280 ((u_printf_spec_info*)info)->fSpec = 0x0065;
01281
01282 return u_printf_scientific_handler(stream, info, args);
01283 }
01284
01285 else {
01286
01287 ((u_printf_spec_info*)info)->fSpec = 0x0066;
01288
01289 return u_printf_double_handler(stream, info, args);
01290 }
01291 }
01292
01293
01294 int32_t
01295 u_printf_count_info(const u_printf_spec_info *info,
01296 int32_t *argtypes,
01297 int32_t n)
01298 {
01299
01300 if(n < 1)
01301 return 0;
01302
01303
01304 argtypes[0] = ufmt_count;
01305 return 1;
01306 }
01307
01308 int32_t
01309 u_printf_count_handler(UFILE *stream,
01310 const u_printf_spec_info *info,
01311 const ufmt_args *args)
01312 {
01313 int *count = (int*)(args[0].ptrValue);
01314
01315
01316
01317 *count = info->fWidth;
01318
01319 return 0;
01320 }
01321
01322
01323 int32_t
01324 u_printf_spellout_info(const u_printf_spec_info *info,
01325 int32_t *argtypes,
01326 int32_t n)
01327 {
01328
01329 if(n < 1)
01330 return 0;
01331
01332
01333 argtypes[0] = ufmt_double;
01334 return 1;
01335 }
01336
01337 int32_t
01338 u_printf_spellout_handler(UFILE *stream,
01339 const u_printf_spec_info *info,
01340 const ufmt_args *args)
01341 {
01342 int32_t written = 0;
01343 int32_t len;
01344 double num = (double) (args[0].doubleValue);
01345 UNumberFormat *format;
01346 UChar result [UFPRINTF_BUFFER_SIZE];
01347 int32_t i, minDecimalDigits;
01348 int32_t maxDecimalDigits;
01349 UErrorCode status = U_ZERO_ERROR;
01350
01351
01352
01353
01354
01355
01356
01357 format = u_locbund_getSpelloutFormat(stream->fBundle);
01358
01359
01360 if(format == 0)
01361 return 0;
01362
01363
01364
01365
01366 if(! stream->fOwnBundle) {
01367 stream->fBundle = u_locbund_clone(stream->fBundle);
01368 stream->fOwnBundle = TRUE;
01369 format = u_locbund_getSpelloutFormat(stream->fBundle);
01370 }
01371
01372
01373
01374
01375 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
01376 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
01377
01378 if(info->fPrecision != -1) {
01379
01380 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
01381 }
01382 else if(info->fPrecision == 0 && ! info->fAlt) {
01383
01384 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
01385 }
01386 else if(info->fAlt) {
01387
01388
01389 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
01390 }
01391 else {
01392
01393 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
01394 }
01395
01396
01397 if(info->fShowSign) {
01398
01399
01400 }
01401
01402
01403 unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
01404 len = u_strlen(result);
01405
01406
01407 if(info->fWidth != -1 && len < info->fWidth) {
01408
01409 if(info->fLeft) {
01410 written = u_file_write(result, len, stream);
01411 for(i = 0; i < info->fWidth - len; ++i)
01412 written += u_file_write(&info->fPadChar, 1, stream);
01413 }
01414
01415 else {
01416 written = 0;
01417 for(i = 0; i < info->fWidth - len; ++i)
01418 written += u_file_write(&info->fPadChar, 1, stream);
01419 written += u_file_write(result, len, stream);
01420 }
01421 }
01422
01423 else
01424 written = u_file_write(result, len, stream);
01425
01426
01427 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
01428 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
01429
01430 return written;
01431 }
01432
01433 void
01434 u_printf_init(void)
01435 {
01436 int32_t i;
01437
01438
01439
01440 if(g_u_printf_inited)
01441 return;
01442
01443
01444 umtx_lock(0);
01445
01446
01447 if(g_u_printf_inited) {
01448 umtx_unlock(0);
01449 return;
01450 }
01451
01452
01453 for(i = 0; i < 256; ++i) {
01454 g_u_printf_infos[i] = 0;
01455 g_u_printf_handlers[i] = 0;
01456 }
01457
01458
01459
01460
01461
01462 g_u_printf_infos[ 0x0025 ] = u_printf_simple_percent_info;
01463 g_u_printf_handlers[ 0x0025 ] = u_printf_simple_percent_handler;
01464
01465
01466 g_u_printf_infos[ 0x0073 ] = u_printf_string_info;
01467 g_u_printf_handlers[ 0x0073 ] = u_printf_string_handler;
01468
01469
01470 g_u_printf_infos[ 0x0064 ] = u_printf_integer_info;
01471 g_u_printf_handlers[ 0x0064 ] = u_printf_integer_handler;
01472
01473
01474 g_u_printf_infos[ 0x0069 ] = u_printf_integer_info;
01475 g_u_printf_handlers[ 0x0069 ] = u_printf_integer_handler;
01476
01477
01478 g_u_printf_infos[ 0x006F ] = u_printf_octal_info;
01479 g_u_printf_handlers[ 0x006F ] = u_printf_octal_handler;
01480
01481
01482 g_u_printf_infos[ 0x0075 ] = u_printf_integer_info;
01483 g_u_printf_handlers[ 0x0075 ] = u_printf_integer_handler;
01484
01485
01486 g_u_printf_infos[ 0x0078 ] = u_printf_hex_info;
01487 g_u_printf_handlers[ 0x0078 ] = u_printf_hex_handler;
01488
01489
01490 g_u_printf_infos[ 0x0058 ] = u_printf_hex_info;
01491 g_u_printf_handlers[ 0x0058 ] = u_printf_hex_handler;
01492
01493
01494 g_u_printf_infos[ 0x0066 ] = u_printf_double_info;
01495 g_u_printf_handlers[ 0x0066 ] = u_printf_double_handler;
01496
01497
01498 g_u_printf_infos[ 0x0063 ] = u_printf_char_info;
01499 g_u_printf_handlers[ 0x0063 ] = u_printf_char_handler;
01500
01501
01502 g_u_printf_infos[ 0x0070 ] = u_printf_pointer_info;
01503 g_u_printf_handlers[ 0x0070 ] = u_printf_pointer_handler;
01504
01505
01506 g_u_printf_infos[ 0x0065 ] = u_printf_scientific_info;
01507 g_u_printf_handlers[ 0x0065 ] = u_printf_scientific_handler;
01508
01509
01510 g_u_printf_infos[ 0x0045 ] = u_printf_scientific_info;
01511 g_u_printf_handlers[ 0x0045 ] = u_printf_scientific_handler;
01512
01513
01514 g_u_printf_infos[ 0x0044 ] = u_printf_date_info;
01515 g_u_printf_handlers[ 0x0044 ] = u_printf_date_handler;
01516
01517
01518 g_u_printf_infos[ 0x0050 ] = u_printf_percent_info;
01519 g_u_printf_handlers[ 0x0050 ] = u_printf_percent_handler;
01520
01521
01522 g_u_printf_infos[ 0x004D ] = u_printf_currency_info;
01523 g_u_printf_handlers[ 0x004D ] = u_printf_currency_handler;
01524
01525
01526 g_u_printf_infos[ 0x0054 ] = u_printf_time_info;
01527 g_u_printf_handlers[ 0x0054 ] = u_printf_time_handler;
01528
01529
01530 g_u_printf_infos[ 0x004B ] = u_printf_uchar_info;
01531 g_u_printf_handlers[ 0x004B ] = u_printf_uchar_handler;
01532
01533
01534 g_u_printf_infos[ 0x0055 ] = u_printf_ustring_info;
01535 g_u_printf_handlers[ 0x0055 ] = u_printf_ustring_handler;
01536
01537
01538 g_u_printf_infos[ 0x0067 ] = u_printf_scidbl_info;
01539 g_u_printf_handlers[ 0x0067 ] = u_printf_scidbl_handler;
01540
01541
01542 g_u_printf_infos[ 0x0047 ] = u_printf_scidbl_info;
01543 g_u_printf_handlers[ 0x0047 ] = u_printf_scidbl_handler;
01544
01545
01546 g_u_printf_infos[ 0x006E ] = u_printf_count_info;
01547 g_u_printf_handlers[ 0x006E ] = u_printf_count_handler;
01548
01549
01550 g_u_printf_infos[ 0x0056 ] = u_printf_spellout_info;
01551 g_u_printf_handlers[ 0x0056 ] = u_printf_spellout_handler;
01552
01553
01554
01555 g_u_printf_inited = TRUE;
01556
01557
01558 umtx_unlock(0);
01559 }
01560
01561
01562 #define U_PRINTF_MAX_ARGS 32
01563 #define UP_PERCENT 0x0025
01564
01565 int32_t
01566 u_vfprintf_u( UFILE *f,
01567 const UChar *patternSpecification,
01568 va_list ap)
01569 {
01570 u_printf_spec spec;
01571 const UChar *alias;
01572 int32_t count, written;
01573
01574 int32_t num_args_wanted;
01575 int32_t ufmt_types [U_PRINTF_MAX_ARGS];
01576 ufmt_args args[U_PRINTF_MAX_ARGS];
01577
01578 u_printf_info info;
01579 u_printf_handler handler;
01580
01581 int32_t cur_arg;
01582
01583
01584
01585 if(! g_u_printf_inited)
01586 u_printf_init();
01587
01588
01589 alias = patternSpecification;
01590
01591
01592 written = 0;
01593
01594
01595 for(;;) {
01596
01597
01598 count = 0;
01599 while(*alias != UP_PERCENT && *alias != 0x0000) {
01600 alias++;
01601 ++count;
01602 }
01603
01604
01605 if(count > 0)
01606 written += u_file_write(alias - count, count, f);
01607
01608
01609 if(*alias == 0x0000)
01610 break;
01611
01612
01613 count = u_printf_parse_spec(alias, &spec);
01614
01615
01616
01617
01618 if(spec.fInfo.fWidth == -2) {
01619 if(spec.fWidthPos == -1) {
01620
01621 spec.fInfo.fWidth = va_arg(ap, int);
01622 }
01623 else {
01624
01625 }
01626
01627
01628 if(spec.fInfo.fWidth < 0) {
01629 spec.fInfo.fWidth *= -1;
01630 spec.fInfo.fLeft = TRUE;
01631 }
01632 }
01633
01634
01635 if(spec.fInfo.fPrecision == -2) {
01636 if(spec.fPrecisionPos == -1) {
01637
01638 spec.fInfo.fPrecision = va_arg(ap, int);
01639 }
01640 else {
01641
01642 }
01643
01644
01645 if(spec.fInfo.fPrecision < 0)
01646 spec.fInfo.fPrecision = 0;
01647 }
01648
01649
01650 info = g_u_printf_infos[ (unsigned char) spec.fInfo.fSpec ];
01651 if(info != 0) {
01652 num_args_wanted = (*info)(&spec.fInfo,
01653 ufmt_types,
01654 U_PRINTF_MAX_ARGS);
01655 }
01656 else
01657 num_args_wanted = 0;
01658
01659
01660 for(cur_arg = 0;
01661 cur_arg < num_args_wanted && cur_arg < U_PRINTF_MAX_ARGS;
01662 ++cur_arg) {
01663
01664 switch(ufmt_types[cur_arg]) {
01665
01666 case ufmt_count:
01667 args[cur_arg].intValue = va_arg(ap, int);
01668
01669 spec.fInfo.fWidth = written;
01670 break;
01671
01672 case ufmt_int:
01673 args[cur_arg].intValue = va_arg(ap, int);
01674 break;
01675
01676 case ufmt_char:
01677 args[cur_arg].intValue = va_arg(ap, int);
01678 break;
01679
01680 case ufmt_wchar:
01681 args[cur_arg].wcharValue = va_arg(ap, wchar_t);
01682 break;
01683
01684 case ufmt_string:
01685 args[cur_arg].ptrValue = va_arg(ap, char*);
01686 break;
01687
01688 case ufmt_wstring:
01689 args[cur_arg].ptrValue = va_arg(ap, wchar_t*);
01690 break;
01691
01692 case ufmt_pointer:
01693 args[cur_arg].ptrValue = va_arg(ap, void*);
01694 break;
01695
01696 case ufmt_float:
01697 args[cur_arg].floatValue = (float) va_arg(ap, double);
01698 break;
01699
01700 case ufmt_double:
01701 args[cur_arg].doubleValue = va_arg(ap, double);
01702 break;
01703
01704 case ufmt_date:
01705 args[cur_arg].dateValue = va_arg(ap, UDate);
01706 break;
01707
01708 case ufmt_ustring:
01709 args[cur_arg].ptrValue = va_arg(ap, UChar*);
01710 break;
01711
01712 case ufmt_uchar:
01713 args[cur_arg].intValue = va_arg(ap, int);
01714 break;
01715 }
01716 }
01717
01718
01719 handler = g_u_printf_handlers[ (unsigned char) spec.fInfo.fSpec ];
01720 if(handler != 0) {
01721 written += (*handler)(f, &spec.fInfo, args);
01722 }
01723
01724 else
01725 written += u_file_write(alias, count, f);
01726
01727
01728 alias += count;
01729 }
01730
01731
01732 return written;
01733 }
01734