lib/jsonwrt: don't use ctype.h for ASCII chars
tolower() does not work "as expected" for tr_TR.UTF-8 (Turkish). Fortunately, we need to convert only objects and variables names in JSON output, and this is always old good ASCII. Anyway, for more details: $ cat a.c #include <ctype.h> #include <stdio.h> #include <locale.h> int main(void) { int in, out; setlocale(LC_ALL, ""); in ='I'; out = tolower(in); printf("%1$c [%1$d] --> %2$c [%2$d]\n", in, out); return 0; } $ make a cc a.c -o a $ LANG=en_US.utf8 ./a I [73] --> i [105] $ LANG=tr_TR.UTF-8 ./a I [73] --> I [73] Fixes: https://github.com/karelzak/util-linux/issues/1302 Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
3a07505a39
commit
64a89adaa1
|
@ -8,6 +8,8 @@
|
|||
*/
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
#include <cctype.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "jsonwrt.h"
|
||||
|
@ -31,7 +33,7 @@ static void fputs_quoted_case_json(const char *data, FILE *out, int dir)
|
|||
fputc('"', out);
|
||||
for (p = data; p && *p; p++) {
|
||||
|
||||
const unsigned char c = (unsigned char) *p;
|
||||
const unsigned int c = (unsigned int) *p;
|
||||
|
||||
/* From http://www.json.org
|
||||
*
|
||||
|
@ -49,8 +51,17 @@ static void fputs_quoted_case_json(const char *data, FILE *out, int dir)
|
|||
|
||||
/* All non-control characters OK; do the case swap as required. */
|
||||
if (c >= 0x20) {
|
||||
fputc(dir == 1 ? toupper(c) :
|
||||
dir == -1 ? tolower(c) : *p, out);
|
||||
/*
|
||||
* Don't use locale sensitive ctype.h functions for regular
|
||||
* ASCII chars, because for example with Turkish locale
|
||||
* (aka LANG=tr_TR.UTF-8) toupper('I') returns 'I'.
|
||||
*/
|
||||
if (c <= 127)
|
||||
fputc(dir == 1 ? c_toupper(c) :
|
||||
dir == -1 ? c_tolower(c) : *p, out);
|
||||
else
|
||||
fputc(dir == 1 ? toupper(c) :
|
||||
dir == -1 ? tolower(c) : *p, out);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue