Comment: | Always use "." for the decimal point
This is achieved by replacing the locale's decimal point with "." after To still use the decimal point from the locale for formatting, the new While this is an ugly hack, there is no better way to do this other than This commit also enables the locale in OFApplication to notice when |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
6dff0f59220b3915dfe2e699b4278eaa |
User & Date: | js on 2017-01-07 02:34:39 |
Other Links: | manifest | tags |
2017-01-07
| ||
03:26 | Use strtof_l, strtod_l and asprintf_l if available check-in: 0ad678f125 user: js tags: trunk | |
02:34 | Always use "." for the decimal point check-in: 6dff0f5922 user: js tags: trunk | |
00:37 | Add of_ascii_{to{upper,lower},is{alpha,alnum}} check-in: d9eb7b50b3 user: js tags: trunk | |
Modified src/OFApplication.m from [e942c20c56] to [669a08ac5c].
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #import "OFApplication.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFSystemInfo.h" | > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> #include <signal.h> #import "OFApplication.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFSystemInfo.h" |
︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | of_application_main(int *argc, char **argv[], Class cls) { id <OFApplicationDelegate> delegate; #ifdef OF_WINDOWS wchar_t **wargv, **wenvp; int wargc, si = 0; #endif if ([cls isSubclassOfClass: [OFApplication class]]) { fprintf(stderr, "FATAL ERROR:\n Class %s is a subclass of " "class OFApplication, but class\n %s was specified as " "application delegate!\n Most likely, you wanted to " "subclass OFObject instead or specified\n the wrong class " "with OF_APPLICATION_DELEGATE().\n", | > > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | of_application_main(int *argc, char **argv[], Class cls) { id <OFApplicationDelegate> delegate; #ifdef OF_WINDOWS wchar_t **wargv, **wenvp; int wargc, si = 0; #endif setlocale(LC_ALL, ""); if ([cls isSubclassOfClass: [OFApplication class]]) { fprintf(stderr, "FATAL ERROR:\n Class %s is a subclass of " "class OFApplication, but class\n %s was specified as " "application delegate!\n Most likely, you wanted to " "subclass OFObject instead or specified\n the wrong class " "with OF_APPLICATION_DELEGATE().\n", |
︙ | ︙ |
Modified src/OFNumber.m from [424f2af76e] to [114905a94e].
︙ | ︙ | |||
13 14 15 16 17 18 19 | * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <inttypes.h> | < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <inttypes.h> #include <math.h> #import "OFNumber.h" #import "OFString.h" #import "OFXMLElement.h" #import "OFXMLAttribute.h" #import "OFDataArray.h" |
︙ | ︙ | |||
903 904 905 906 907 908 909 | case OF_NUMBER_TYPE_INTMAX: case OF_NUMBER_TYPE_PTRDIFF: case OF_NUMBER_TYPE_INTPTR: return [OFString stringWithFormat: @"%jd", [self intMaxValue]]; case OF_NUMBER_TYPE_FLOAT: ret = [OFMutableString stringWithFormat: @"%g", _value.float_]; | < < < < < | | < < < < < < < < | | < < < | 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 | case OF_NUMBER_TYPE_INTMAX: case OF_NUMBER_TYPE_PTRDIFF: case OF_NUMBER_TYPE_INTPTR: return [OFString stringWithFormat: @"%jd", [self intMaxValue]]; case OF_NUMBER_TYPE_FLOAT: ret = [OFMutableString stringWithFormat: @"%g", _value.float_]; if (![ret containsString: @"."]) [ret appendString: @".0"]; [ret makeImmutable]; return ret; case OF_NUMBER_TYPE_DOUBLE: ret = [OFMutableString stringWithFormat: @"%g", _value.double_]; if (![ret containsString: @"."]) [ret appendString: @".0"]; [ret makeImmutable]; return ret; default: @throw [OFInvalidFormatException exception]; } |
︙ | ︙ |
Modified src/OFString.m from [4bcce6446e] to [2a34be912f].
︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #import "OFString.h" #import "OFString_UTF8.h" #import "OFString_UTF8+Private.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFDataArray.h" #ifdef OF_HAVE_FILES # import "OFFile.h" #endif #import "OFURL.h" #ifdef OF_HAVE_SOCKETS # import "OFHTTPClient.h" # import "OFHTTPRequest.h" | > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #import "OFString.h" #import "OFString_UTF8.h" #import "OFString_UTF8+Private.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFDataArray.h" #import "OFSystemInfo.h" #ifdef OF_HAVE_FILES # import "OFFile.h" #endif #import "OFURL.h" #ifdef OF_HAVE_SOCKETS # import "OFHTTPClient.h" # import "OFHTTPRequest.h" |
︙ | ︙ | |||
2331 2332 2333 2334 2335 2336 2337 | return value; } - (float)floatValue { void *pool = objc_autoreleasePoolPush(); | > | > > | 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 | return value; } - (float)floatValue { void *pool = objc_autoreleasePoolPush(); OFString *decimalPoint = [OFSystemInfo decimalPoint]; const char *UTF8String = [[self stringByReplacingOccurrencesOfString: @"." withString: decimalPoint] UTF8String]; char *endPointer = NULL; float value; while (*UTF8String == ' ' || *UTF8String == '\t' || *UTF8String == '\n' || *UTF8String == '\r' || *UTF8String == '\f') UTF8String++; |
︙ | ︙ | |||
2357 2358 2359 2360 2361 2362 2363 | return value; } - (double)doubleValue { void *pool = objc_autoreleasePoolPush(); | > | > > | 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 | return value; } - (double)doubleValue { void *pool = objc_autoreleasePoolPush(); OFString *decimalPoint = [OFSystemInfo decimalPoint]; const char *UTF8String = [[self stringByReplacingOccurrencesOfString: @"." withString: decimalPoint] UTF8String]; char *endPointer = NULL; double value; while (*UTF8String == ' ' || *UTF8String == '\t' || *UTF8String == '\n' || *UTF8String == '\r' || *UTF8String == '\f') UTF8String++; |
︙ | ︙ |
Modified src/OFSystemInfo.h from [b6d210b0c4] to [0c8db08aa1].
︙ | ︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 60 | * This is useful to encode strings correctly for passing them to operating * system calls. * * @return The native 8-bit string encoding of the operating system */ + (of_string_encoding_t)native8BitEncoding; /*! * @brief Returns the path where user data for the application can be stored. * * On Unix systems, this adheres to the XDG Base Directory specification.@n * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n * On Windows, it uses the `APPDATA` environment variable.@n * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory. | > > > > > > > | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | * This is useful to encode strings correctly for passing them to operating * system calls. * * @return The native 8-bit string encoding of the operating system */ + (of_string_encoding_t)native8BitEncoding; /*! * @brief Returns the decimal point in the system's locale. * * @return The decimal point in the system's locale */ + (OFString*)decimalPoint; /*! * @brief Returns the path where user data for the application can be stored. * * On Unix systems, this adheres to the XDG Base Directory specification.@n * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n * On Windows, it uses the `APPDATA` environment variable.@n * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory. |
︙ | ︙ |
Modified src/OFSystemInfo.m from [7a2395920f] to [c6d392a88f].
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | /* Work around __block being used by glibc */ #include <stdlib.h> /* include any libc header to get the libc defines */ #ifdef __GLIBC__ # undef __USE_XOPEN #endif #include <unistd.h> #include "platform.h" #ifdef OF_MAC_OS_X # include <sys/sysctl.h> #endif | > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /* Work around __block being used by glibc */ #include <stdlib.h> /* include any libc header to get the libc defines */ #ifdef __GLIBC__ # undef __USE_XOPEN #endif #include <locale.h> #include <unistd.h> #include "platform.h" #ifdef OF_MAC_OS_X # include <sys/sysctl.h> #endif |
︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 153 154 155 156 157 | } + (of_string_encoding_t)native8BitEncoding { /* FIXME */ return OF_STRING_ENCODING_UTF_8; } + (OFString*)userDataPath { #if defined(OF_MAC_OS_X) || defined(OF_IOS) void *pool = objc_autoreleasePoolPush(); char pathC[PATH_MAX]; OFMutableString *path; | > > > > > | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | } + (of_string_encoding_t)native8BitEncoding { /* FIXME */ return OF_STRING_ENCODING_UTF_8; } + (OFString*)decimalPoint { return [OFString stringWithUTF8String: localeconv()->decimal_point]; } + (OFString*)userDataPath { #if defined(OF_MAC_OS_X) || defined(OF_IOS) void *pool = objc_autoreleasePoolPush(); char pathC[PATH_MAX]; OFMutableString *path; |
︙ | ︙ |
Modified src/of_asprintf.m from [bff5bd9808] to [91cd8b629a].
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <stdarg.h> #include <stdbool.h> #include <wchar.h> #include <sys/types.h> #import "OFString.h" #define MAX_SUBFORMAT_LEN 64 #ifndef HAVE_ASPRINTF /* * (v)asprintf might be declared, but HAVE_ASPRINTF not defined because * configure determined it is broken. In this case, we must make sure there is | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <stdarg.h> #include <stdbool.h> #include <wchar.h> #include <sys/types.h> #import "OFString.h" #import "OFSystemInfo.h" #define MAX_SUBFORMAT_LEN 64 #ifndef HAVE_ASPRINTF /* * (v)asprintf might be declared, but HAVE_ASPRINTF not defined because * configure determined it is broken. In this case, we must make sure there is |
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | LENGTH_MODIFIER_L, LENGTH_MODIFIER_LL, LENGTH_MODIFIER_J, LENGTH_MODIFIER_Z, LENGTH_MODIFIER_T, LENGTH_MODIFIER_CAPITAL_L } lengthModifier; }; #ifndef HAVE_ASPRINTF static int vasprintf(char **string, const char *format, va_list arguments) { int length; | > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | LENGTH_MODIFIER_L, LENGTH_MODIFIER_LL, LENGTH_MODIFIER_J, LENGTH_MODIFIER_Z, LENGTH_MODIFIER_T, LENGTH_MODIFIER_CAPITAL_L } lengthModifier; bool useLocale; }; #ifndef HAVE_ASPRINTF static int vasprintf(char **string, const char *format, va_list arguments) { int length; |
︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 174 | case ' ': case '#': case '0': if (!appendSubformat(ctx, ctx->format + ctx->i, 1)) return false; break; default: ctx->state = STATE_FORMAT_FIELD_WIDTH; ctx->i--; break; } | > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | case ' ': case '#': case '0': if (!appendSubformat(ctx, ctx->format + ctx->i, 1)) return false; break; case ',': /* ObjFW extension: Use decimal point from locale */ ctx->useLocale = true; break; default: ctx->state = STATE_FORMAT_FIELD_WIDTH; ctx->i--; break; } |
︙ | ︙ | |||
497 498 499 500 501 502 503 504 505 506 507 508 509 510 | case LENGTH_MODIFIER_CAPITAL_L: tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, long double)); break; default: return false; } break; case 'c': switch (ctx->lengthModifier) { case LENGTH_MODIFIER_NONE: tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, int)); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | case LENGTH_MODIFIER_CAPITAL_L: tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, long double)); break; default: return false; } /* * Ugly hack to undo locale, as there is nothing such as * asprintf_l in POSIX. */ if (!ctx->useLocale) { void *pool = objc_autoreleasePoolPush(); char *tmp2; @try { OFMutableString *tmpStr = [OFMutableString stringWithUTF8String: tmp length: tmpLen]; OFString *decimalPoint = [OFSystemInfo decimalPoint]; [tmpStr replaceOccurrencesOfString: decimalPoint withString: @"."]; if ([tmpStr UTF8StringLength] > INT_MAX) return false; tmpLen = (int)[tmpStr UTF8StringLength]; tmp2 = malloc(tmpLen); memcpy(tmp2, [tmpStr UTF8String], tmpLen); } @finally { free(tmp); objc_autoreleasePoolPop(pool); } tmp = tmp2; } break; case 'c': switch (ctx->lengthModifier) { case LENGTH_MODIFIER_NONE: tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, int)); |
︙ | ︙ | |||
608 609 610 611 612 613 614 615 616 617 618 619 620 621 | free(tmp); } memset(ctx->subformat, 0, MAX_SUBFORMAT_LEN); ctx->subformatLen = 0; ctx->lengthModifier = LENGTH_MODIFIER_NONE; ctx->last = ctx->i + 1; ctx->state = STATE_STRING; return true; } | > | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | free(tmp); } memset(ctx->subformat, 0, MAX_SUBFORMAT_LEN); ctx->subformatLen = 0; ctx->lengthModifier = LENGTH_MODIFIER_NONE; ctx->useLocale = false; ctx->last = ctx->i + 1; ctx->state = STATE_STRING; return true; } |
︙ | ︙ | |||
637 638 639 640 641 642 643 644 645 646 647 648 649 650 | memset(ctx.subformat, 0, MAX_SUBFORMAT_LEN + 1); ctx.subformatLen = 0; va_copy(ctx.arguments, arguments); ctx.bufferLen = 0; ctx.last = 0; ctx.state = STATE_STRING; ctx.lengthModifier = LENGTH_MODIFIER_NONE; if ((ctx.buffer = malloc(1)) == NULL) return -1; for (ctx.i = 0; ctx.i < ctx.formatLen; ctx.i++) { if (!states[ctx.state](&ctx)) { free(ctx.buffer); | > | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | memset(ctx.subformat, 0, MAX_SUBFORMAT_LEN + 1); ctx.subformatLen = 0; va_copy(ctx.arguments, arguments); ctx.bufferLen = 0; ctx.last = 0; ctx.state = STATE_STRING; ctx.lengthModifier = LENGTH_MODIFIER_NONE; ctx.useLocale = false; if ((ctx.buffer = malloc(1)) == NULL) return -1; for (ctx.i = 0; ctx.i < ctx.formatLen; ctx.i++) { if (!states[ctx.state](&ctx)) { free(ctx.buffer); |
︙ | ︙ |
Modified tests/OFStringTests.m from [461bffb20c] to [cd4f1dfd47].
︙ | ︙ | |||
520 521 522 523 524 525 526 | OFInvalidFormatException, [@"0x" hexadecimalValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #3", OFInvalidFormatException, [@"$" hexadecimalValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #4", OFInvalidFormatException, [@"$ " hexadecimalValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #1", | < < | < < | | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | OFInvalidFormatException, [@"0x" hexadecimalValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #3", OFInvalidFormatException, [@"$" hexadecimalValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #4", OFInvalidFormatException, [@"$ " hexadecimalValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #1", OFInvalidFormatException, [@"0.0a" floatValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #2", OFInvalidFormatException, [@"0 0" floatValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[doubleValue] #1", OFInvalidFormatException, [@"0.0a" floatValue]) EXPECT_EXCEPTION(@"Detect invalid chars in -[doubleValue] #2", OFInvalidFormatException, [@"0 0" floatValue]) EXPECT_EXCEPTION(@"Detect out of range in -[decimalValue]", OFOutOfRangeException, [@"12345678901234567890123456789012345678901234567890" @"12345678901234567890123456789012345678901234567890" decimalValue]) |
︙ | ︙ |
Modified utils/ofhttp/OFHTTP.m from [676c6715db] to [3ef2bcb62b].
︙ | ︙ | |||
709 710 711 712 713 714 715 | if (!_quiet) { if (type == nil) type = @"unknown"; if (_length >= 0) { if (_resumedFrom + _length >= GIBIBYTE) lengthString = [OFString stringWithFormat: | | | | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 | if (!_quiet) { if (type == nil) type = @"unknown"; if (_length >= 0) { if (_resumedFrom + _length >= GIBIBYTE) lengthString = [OFString stringWithFormat: @"%,.2f GiB", (float)(_resumedFrom + _length) / GIBIBYTE]; else if (_resumedFrom + _length >= MEBIBYTE) lengthString = [OFString stringWithFormat: @"%,.2f MiB", (float)(_resumedFrom + _length) / MEBIBYTE]; else if (_resumedFrom + _length >= KIBIBYTE) lengthString = [OFString stringWithFormat: @"%,.2f KiB", (float)(_resumedFrom + _length) / KIBIBYTE]; else lengthString = [OFString stringWithFormat: @"%jd bytes", _resumedFrom + _length]; } else lengthString = @"unknown"; |
︙ | ︙ |
Modified utils/ofhttp/ProgressBar.m from [dd50353974] to [b2906f802b].
︙ | ︙ | |||
123 124 125 126 127 128 129 | else [of_stdout writeString: @" "]; for (size_t i = 0; i < barWidth - (size_t)bars - 1; i++) [of_stdout writeString: @" "]; } | | | | | | | | | | | | | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | else [of_stdout writeString: @" "]; for (size_t i = 0; i < barWidth - (size_t)bars - 1; i++) [of_stdout writeString: @" "]; } [of_stdout writeFormat: @"▏ %,6.2f%% ", percent]; if (percent == 100) { double timeInterval = -[_startDate timeIntervalSinceNow]; _BPS = (float)_received / (float)timeInterval; _ETA = timeInterval; } if (isinf(_ETA)) [of_stdout writeString: @"--:--:-- "]; else if (_ETA >= 99 * 3600) [of_stdout writeFormat: @"%,4.2f d ", _ETA / (24 * 3600)]; else [of_stdout writeFormat: @"%2u:%02u:%02u ", (uint8_t)(_ETA / 3600), (uint8_t)(_ETA / 60) % 60, (uint8_t)_ETA % 60]; if (_BPS >= GIBIBYTE) [of_stdout writeFormat: @"%,7.2f GiB/s", _BPS / GIBIBYTE]; else if (_BPS >= MEBIBYTE) [of_stdout writeFormat: @"%,7.2f MiB/s", _BPS / MEBIBYTE]; else if (_BPS >= KIBIBYTE) [of_stdout writeFormat: @"%,7.2f KiB/s", _BPS / KIBIBYTE]; else [of_stdout writeFormat: @"%,7.2f B/s ", _BPS]; } - (void)_drawReceived { if (_resumedFrom + _received >= GIBIBYTE) [of_stdout writeFormat: @"\r %,7.2f GiB ", (float)(_resumedFrom + _received) / GIBIBYTE]; else if (_resumedFrom + _received >= MEBIBYTE) [of_stdout writeFormat: @"\r %,7.2f MiB ", (float)(_resumedFrom + _received) / MEBIBYTE]; else if (_resumedFrom + _received >= KIBIBYTE) [of_stdout writeFormat: @"\r %,7.2f KiB ", (float)(_resumedFrom + _received) / KIBIBYTE]; else [of_stdout writeFormat: @"\r %jd bytes ", _resumedFrom + _received]; if (_stopped) _BPS = (float)_received / -(float)[_startDate timeIntervalSinceNow]; if (_BPS >= GIBIBYTE) [of_stdout writeFormat: @"%,7.2f GiB/s", _BPS / GIBIBYTE]; else if (_BPS >= MEBIBYTE) [of_stdout writeFormat: @"%,7.2f MiB/s", _BPS / MEBIBYTE]; else if (_BPS >= KIBIBYTE) [of_stdout writeFormat: @"%,7.2f KiB/s", _BPS / KIBIBYTE]; else [of_stdout writeFormat: @"%,7.2f B/s ", _BPS]; } - (void)draw { if (_length > 0) [self _drawProgress]; else |
︙ | ︙ |