Differences From Artifact [2a34be912f]:
- File
src/OFString.m
— part of check-in
[6dff0f5922]
at
2017-01-07 02:34:39
on branch trunk
— Always use "." for the decimal point
This is achieved by replacing the locale's decimal point with "." after
formatting and replacing "." with the locale's decimal point before
parsing.To still use the decimal point from the locale for formatting, the new
flag "," is introduced to formats. This is useful for just printing a
string to the user that is not saved to a file or sent via a network.While this is an ugly hack, there is no better way to do this other than
implementing the functionality of printf and strtod myself, as POSIX
does not specify versions of these that take a locale as an argument.
While this is a lot of work and error-prone, I will most likely end up
doing this eventually.This commit also enables the locale in OFApplication to notice when
things break. As a nice side effect, ofhttp now uses the locale's
decimal point in its user interface. (user: js, size: 58336) [annotate] [blame] [check-ins using]
To Artifact [011cdaca0e]:
- File
src/OFString.m
— part of check-in
[0ad678f125]
at
2017-01-07 03:26:50
on branch trunk
— Use strtof_l, strtod_l and asprintf_l if available
This avoids the hacks introduced in the previous commit, if those
functions are available. (user: js, size: 59306) [annotate] [blame] [check-ins using]
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include "config.h" #include <ctype.h> #include <errno.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #import "OFString.h" #import "OFString_UTF8.h" #import "OFString_UTF8+Private.h" #import "OFArray.h" | > > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include "config.h" #include <ctype.h> #include <errno.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) # include <locale.h> #endif #ifdef HAVE_XLOCALE_H # include <xlocale.h> #endif #include <sys/stat.h> #import "OFString.h" #import "OFString_UTF8.h" #import "OFString_UTF8+Private.h" #import "OFArray.h" |
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | /* * It seems strtod is buggy on Win32. * However, the MinGW version __strtod seems to be ok. */ #ifdef __MINGW32__ # define strtod __strtod #endif @interface OFString () - (size_t)OF_getCString: (char*)cString maxLength: (size_t)maxLength encoding: (of_string_encoding_t)encoding lossy: (bool)lossy; - (const char*)OF_cStringWithEncoding: (of_string_encoding_t)encoding | > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | /* * It seems strtod is buggy on Win32. * However, the MinGW version __strtod seems to be ok. */ #ifdef __MINGW32__ # define strtod __strtod #endif #if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) static locale_t cLocale; #endif @interface OFString () - (size_t)OF_getCString: (char*)cString maxLength: (size_t)maxLength encoding: (of_string_encoding_t)encoding lossy: (bool)lossy; - (const char*)OF_cStringWithEncoding: (of_string_encoding_t)encoding |
︙ | ︙ | |||
497 498 499 500 501 502 503 | OF_DEALLOC_UNSUPPORTED } @end @implementation OFString + (void)initialize { | | > > | > > > > > | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | OF_DEALLOC_UNSUPPORTED } @end @implementation OFString + (void)initialize { if (self != [OFString class]) return; placeholder.isa = [OFString_placeholder class]; #if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL) @throw [OFInitializationFailedException exception]; #endif } + alloc { if (self == [OFString class]) return (id)&placeholder; |
︙ | ︙ | |||
2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 | 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++; value = strtof(UTF8String, &endPointer); /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) if (*endPointer != ' ' && *endPointer != '\t' && *endPointer != '\n' && *endPointer != '\r' && *endPointer != '\f') @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); 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++; value = strtod(UTF8String, &endPointer); /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) if (*endPointer != ' ' && *endPointer != '\t' && *endPointer != '\n' && *endPointer != '\r' && *endPointer != '\f') | > > > > > > > > > > > > > > > > > > > > > > > > | 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 | return value; } - (float)floatValue { void *pool = objc_autoreleasePoolPush(); #ifdef HAVE_STRTOF_L const char *UTF8String = [self UTF8String]; #else /* * If we have no strtof_l, we have no other choice but to replace "." * with the locale's decimal point. */ OFString *decimalPoint = [OFSystemInfo decimalPoint]; const char *UTF8String = [[self stringByReplacingOccurrencesOfString: @"." withString: decimalPoint] UTF8String]; #endif char *endPointer = NULL; float value; while (*UTF8String == ' ' || *UTF8String == '\t' || *UTF8String == '\n' || *UTF8String == '\r' || *UTF8String == '\f') UTF8String++; #ifdef HAVE_STRTOF_L value = strtof_l(UTF8String, &endPointer, cLocale); #else value = strtof(UTF8String, &endPointer); #endif /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) if (*endPointer != ' ' && *endPointer != '\t' && *endPointer != '\n' && *endPointer != '\r' && *endPointer != '\f') @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); return value; } - (double)doubleValue { void *pool = objc_autoreleasePoolPush(); #ifdef HAVE_STRTOD_L const char *UTF8String = [self UTF8String]; #else /* * If we have no strtod_l, we have no other choice but to replace "." * with the locale's decimal point. */ OFString *decimalPoint = [OFSystemInfo decimalPoint]; const char *UTF8String = [[self stringByReplacingOccurrencesOfString: @"." withString: decimalPoint] UTF8String]; #endif char *endPointer = NULL; double value; while (*UTF8String == ' ' || *UTF8String == '\t' || *UTF8String == '\n' || *UTF8String == '\r' || *UTF8String == '\f') UTF8String++; #ifdef HAVE_STRTOD_L value = strtod_l(UTF8String, &endPointer, cLocale); #else value = strtod(UTF8String, &endPointer); #endif /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) if (*endPointer != ' ' && *endPointer != '\t' && *endPointer != '\n' && *endPointer != '\r' && *endPointer != '\f') |
︙ | ︙ |