]> git.ipfire.org Git - thirdparty/util-linux.git/blob - include/carefulputc.h
lscpu: add --bytes
[thirdparty/util-linux.git] / include / carefulputc.h
1 #ifndef UTIL_LINUX_CAREFULPUTC_H
2 #define UTIL_LINUX_CAREFULPUTC_H
3
4 /*
5 * A putc() for use in write and wall (that sometimes are sgid tty).
6 * It avoids control characters in our locale, and also ASCII control
7 * characters. Note that the locale of the recipient is unknown.
8 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 static inline int fputc_careful(int c, FILE *fp, const char fail)
14 {
15 int ret;
16
17 if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
18 ret = putc(c, fp);
19 else if (!isascii(c))
20 ret = fprintf(fp, "\\%3o", (unsigned char)c);
21 else {
22 ret = putc(fail, fp);
23 if (ret != EOF)
24 ret = putc(c ^ 0x40, fp);
25 }
26 return (ret < 0) ? EOF : 0;
27 }
28
29 /*
30 * Requirements enumerated via testing (V8, Firefox, IE11):
31 *
32 * var charsToEscape = [];
33 * for (var i = 0; i < 65535; i += 1) {
34 * try {
35 * JSON.parse('{"sample": "' + String.fromCodePoint(i) + '"}');
36 * } catch (e) {
37 * charsToEscape.push(i);
38 * }
39 * }
40 */
41 static inline void fputs_quoted_case_json(const char *data, FILE *out, int dir)
42 {
43 const char *p;
44
45 fputc('"', out);
46 for (p = data; p && *p; p++) {
47
48 const unsigned char c = (unsigned char) *p;
49
50 /* From http://www.json.org
51 *
52 * The double-quote and backslashes would break out a string or
53 * init an escape sequence if not escaped.
54 *
55 * Note that single-quotes and forward slashes, while they're
56 * in the JSON spec, don't break double-quoted strings.
57 */
58 if (c == '"' || c == '\\') {
59 fputc('\\', out);
60 fputc(c, out);
61 continue;
62 }
63
64 /* All non-control characters OK; do the case swap as required. */
65 if (c >= 0x20) {
66 fputc(dir == 1 ? toupper(c) :
67 dir == -1 ? tolower(c) : *p, out);
68 continue;
69 }
70
71 /* In addition, all chars under ' ' break Node's/V8/Chrome's, and
72 * Firefox's JSON.parse function
73 */
74 switch (c) {
75 /* Handle short-hand cases to reduce output size. C
76 * has most of the same stuff here, so if there's an
77 * "Escape for C" function somewhere in the STL, we
78 * should probably be using it.
79 */
80 case '\b':
81 fputs("\\b", out);
82 break;
83 case '\t':
84 fputs("\\t", out);
85 break;
86 case '\n':
87 fputs("\\n", out);
88 break;
89 case '\f':
90 fputs("\\f", out);
91 break;
92 case '\r':
93 fputs("\\r", out);
94 break;
95 default:
96 /* Other assorted control characters */
97 fprintf(out, "\\u00%02x", c);
98 break;
99 }
100 }
101 fputc('"', out);
102 }
103
104
105 static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
106 {
107 const char *p;
108
109 fputc('"', out);
110 for (p = data; p && *p; p++) {
111 if ((unsigned char) *p == 0x22 || /* " */
112 (unsigned char) *p == 0x5c || /* \ */
113 (unsigned char) *p == 0x60 || /* ` */
114 (unsigned char) *p == 0x24 || /* $ */
115 !isprint((unsigned char) *p) ||
116 iscntrl((unsigned char) *p)) {
117
118 fprintf(out, "\\x%02x", (unsigned char) *p);
119 } else
120 fputc(dir == 1 ? toupper(*p) :
121 dir == -1 ? tolower(*p) :
122 *p, out);
123 }
124 fputc('"', out);
125 }
126
127 #define fputs_quoted(_d, _o) fputs_quoted_case(_d, _o, 0)
128 #define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1)
129 #define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1)
130
131 #define fputs_quoted_json(_d, _o) fputs_quoted_case_json(_d, _o, 0)
132 #define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1)
133 #define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1)
134
135 static inline void fputs_nonblank(const char *data, FILE *out)
136 {
137 const char *p;
138
139 for (p = data; p && *p; p++) {
140 if (isblank((unsigned char) *p) ||
141 (unsigned char) *p == 0x5c || /* \ */
142 !isprint((unsigned char) *p) ||
143 iscntrl((unsigned char) *p)) {
144
145 fprintf(out, "\\x%02x", (unsigned char) *p);
146
147 } else
148 fputc(*p, out);
149 }
150 }
151
152
153 #endif /* _CAREFULPUTC_H */