Make test stripping locale independent
[jansson.git] / test / bin / json_process.c
1 /*
2  * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
3  *
4  * Jansson is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <jansson.h>
17
18 #if HAVE_LOCALE_H
19 #include <locale.h>
20 #endif
21
22 #if _WIN32
23 #include <io.h>  /* for _setmode() */
24 #include <fcntl.h>  /* for _O_BINARY */
25 #endif
26
27 #define l_isspace(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t')
28
29 static int getenv_int(const char *name)
30 {
31     char *value, *end;
32     long result;
33
34     value = getenv(name);
35     if(!value)
36         return 0;
37
38     result = strtol(value, &end, 10);
39     if(*end != '\0')
40         return 0;
41
42     return (int)result;
43 }
44
45 /* Return a pointer to the first non-whitespace character of str.
46    Modifies str so that all trailing whitespace characters are
47    replaced by '\0'. */
48 static const char *strip(char *str)
49 {
50     size_t length;
51     char *result = str;
52     while(*result && l_isspace(*result))
53         result++;
54
55     length = strlen(result);
56     if(length == 0)
57         return result;
58
59     while(l_isspace(result[length - 1]))
60         result[--length] = '\0';
61
62     return result;
63 }
64
65 int main(int argc, char *argv[])
66 {
67     int indent = 0;
68     size_t flags = 0;
69
70     json_t *json;
71     json_error_t error;
72
73 #if HAVE_SETLOCALE
74     setlocale(LC_ALL, "");
75 #endif
76
77     if(argc != 1) {
78         fprintf(stderr, "usage: %s\n", argv[0]);
79         return 2;
80     }
81
82 #ifdef _WIN32
83     /* On Windows, set stdout and stderr to binary mode to avoid
84        outputting DOS line terminators */
85     _setmode(_fileno(stdout), _O_BINARY);
86     _setmode(_fileno(stderr), _O_BINARY);
87 #endif
88
89     indent = getenv_int("JSON_INDENT");
90     if(indent < 0 || indent > 255) {
91         fprintf(stderr, "invalid value for JSON_INDENT: %d\n", indent);
92         return 2;
93     }
94
95     if(indent > 0)
96         flags |= JSON_INDENT(indent);
97
98     if(getenv_int("JSON_COMPACT") > 0)
99         flags |= JSON_COMPACT;
100
101     if(getenv_int("JSON_ENSURE_ASCII"))
102         flags |= JSON_ENSURE_ASCII;
103
104     if(getenv_int("JSON_PRESERVE_ORDER"))
105         flags |= JSON_PRESERVE_ORDER;
106
107     if(getenv_int("JSON_SORT_KEYS"))
108         flags |= JSON_SORT_KEYS;
109
110     if(getenv_int("STRIP")) {
111         /* Load to memory, strip leading and trailing whitespace */
112         size_t size = 0, used = 0;
113         char *buffer = NULL;
114
115         while(1) {
116             int count;
117
118             size = (size == 0 ? 128 : size * 2);
119             buffer = realloc(buffer, size);
120             if(!buffer) {
121                 fprintf(stderr, "Unable to allocate %d bytes\n", (int)size);
122                 return 1;
123             }
124
125             count = fread(buffer + used, 1, size - used, stdin);
126             if(count < size - used) {
127                 buffer[used + count] = '\0';
128                 break;
129             }
130             used += count;
131         }
132
133         json = json_loads(strip(buffer), 0, &error);
134         free(buffer);
135     }
136     else
137         json = json_loadf(stdin, 0, &error);
138
139     if(!json) {
140         fprintf(stderr, "%d %d %d\n%s\n",
141                 error.line, error.column, error.position,
142                 error.text);
143         return 1;
144     }
145
146     json_dumpf(json, stdout, flags);
147     json_decref(json);
148
149     return 0;
150 }