rapidio: add core mport removal support
[deliverable/linux.git] / lib / string_helpers.c
CommitLineData
3c9f3681
JB
1/*
2 * Helpers for formatting and printing strings
3 *
4 * Copyright 31 August 2008 James Bottomley
16c7fa05 5 * Copyright (C) 2013, Intel Corporation
3c9f3681 6 */
b9f28d86 7#include <linux/bug.h>
3c9f3681
JB
8#include <linux/kernel.h>
9#include <linux/math64.h>
8bc3bcc9 10#include <linux/export.h>
16c7fa05 11#include <linux/ctype.h>
c8250381
AS
12#include <linux/errno.h>
13#include <linux/string.h>
3c9f3681
JB
14#include <linux/string_helpers.h>
15
16/**
17 * string_get_size - get the size in the specified units
b9f28d86
JB
18 * @size: The size to be converted in blocks
19 * @blk_size: Size of the block (use 1 for size in bytes)
3c9f3681
JB
20 * @units: units to use (powers of 1000 or 1024)
21 * @buf: buffer to format to
22 * @len: length of buffer
23 *
24 * This function returns a string formatted to 3 significant figures
d1214c65
RV
25 * giving the size in the required units. @buf should have room for
26 * at least 9 bytes and will always be zero terminated.
3c9f3681
JB
27 *
28 */
b9f28d86 29void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
d1214c65 30 char *buf, int len)
3c9f3681 31{
142cda5d 32 static const char *const units_10[] = {
b9f28d86 33 "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
142cda5d
MK
34 };
35 static const char *const units_2[] = {
b9f28d86 36 "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
142cda5d
MK
37 };
38 static const char *const *const units_str[] = {
39 [STRING_UNITS_10] = units_10,
3c9f3681
JB
40 [STRING_UNITS_2] = units_2,
41 };
68aecfb9 42 static const unsigned int divisor[] = {
3c9f3681
JB
43 [STRING_UNITS_10] = 1000,
44 [STRING_UNITS_2] = 1024,
45 };
564b026f
JB
46 static const unsigned int rounding[] = { 500, 50, 5 };
47 int i = 0, j;
48 u32 remainder = 0, sf_cap;
3c9f3681 49 char tmp[8];
b9f28d86 50 const char *unit;
3c9f3681
JB
51
52 tmp[0] = '\0';
564b026f
JB
53
54 if (blk_size == 0)
55 size = 0;
56 if (size == 0)
b9f28d86 57 goto out;
3c9f3681 58
564b026f
JB
59 /* This is Napier's algorithm. Reduce the original block size to
60 *
61 * coefficient * divisor[units]^i
62 *
63 * we do the reduction so both coefficients are just under 32 bits so
64 * that multiplying them together won't overflow 64 bits and we keep
65 * as much precision as possible in the numbers.
66 *
67 * Note: it's safe to throw away the remainders here because all the
68 * precision is in the coefficients.
69 */
70 while (blk_size >> 32) {
71 do_div(blk_size, divisor[units]);
b9f28d86
JB
72 i++;
73 }
74
564b026f
JB
75 while (size >> 32) {
76 do_div(size, divisor[units]);
b9f28d86 77 i++;
b9f28d86
JB
78 }
79
564b026f
JB
80 /* now perform the actual multiplication keeping i as the sum of the
81 * two logarithms */
b9f28d86 82 size *= blk_size;
3c9f3681 83
564b026f 84 /* and logarithmically reduce it until it's just under the divisor */
b9f28d86
JB
85 while (size >= divisor[units]) {
86 remainder = do_div(size, divisor[units]);
87 i++;
3c9f3681
JB
88 }
89
564b026f
JB
90 /* work out in j how many digits of precision we need from the
91 * remainder */
b9f28d86
JB
92 sf_cap = size;
93 for (j = 0; sf_cap*10 < 1000; j++)
94 sf_cap *= 10;
95
564b026f
JB
96 if (units == STRING_UNITS_2) {
97 /* express the remainder as a decimal. It's currently the
98 * numerator of a fraction whose denominator is
99 * divisor[units], which is 1 << 10 for STRING_UNITS_2 */
b9f28d86 100 remainder *= 1000;
564b026f
JB
101 remainder >>= 10;
102 }
103
104 /* add a 5 to the digit below what will be printed to ensure
105 * an arithmetical round up and carry it through to size */
106 remainder += rounding[j];
107 if (remainder >= 1000) {
108 remainder -= 1000;
109 size += 1;
110 }
111
112 if (j) {
b9f28d86
JB
113 snprintf(tmp, sizeof(tmp), ".%03u", remainder);
114 tmp[j+1] = '\0';
115 }
116
117 out:
118 if (i >= ARRAY_SIZE(units_2))
119 unit = "UNK";
120 else
121 unit = units_str[units][i];
122
84b9fbed 123 snprintf(buf, len, "%u%s %s", (u32)size,
b9f28d86 124 tmp, unit);
3c9f3681
JB
125}
126EXPORT_SYMBOL(string_get_size);
16c7fa05
AS
127
128static bool unescape_space(char **src, char **dst)
129{
130 char *p = *dst, *q = *src;
131
132 switch (*q) {
133 case 'n':
134 *p = '\n';
135 break;
136 case 'r':
137 *p = '\r';
138 break;
139 case 't':
140 *p = '\t';
141 break;
142 case 'v':
143 *p = '\v';
144 break;
145 case 'f':
146 *p = '\f';
147 break;
148 default:
149 return false;
150 }
151 *dst += 1;
152 *src += 1;
153 return true;
154}
155
156static bool unescape_octal(char **src, char **dst)
157{
158 char *p = *dst, *q = *src;
159 u8 num;
160
161 if (isodigit(*q) == 0)
162 return false;
163
164 num = (*q++) & 7;
165 while (num < 32 && isodigit(*q) && (q - *src < 3)) {
166 num <<= 3;
167 num += (*q++) & 7;
168 }
169 *p = num;
170 *dst += 1;
171 *src = q;
172 return true;
173}
174
175static bool unescape_hex(char **src, char **dst)
176{
177 char *p = *dst, *q = *src;
178 int digit;
179 u8 num;
180
181 if (*q++ != 'x')
182 return false;
183
184 num = digit = hex_to_bin(*q++);
185 if (digit < 0)
186 return false;
187
188 digit = hex_to_bin(*q);
189 if (digit >= 0) {
190 q++;
191 num = (num << 4) | digit;
192 }
193 *p = num;
194 *dst += 1;
195 *src = q;
196 return true;
197}
198
199static bool unescape_special(char **src, char **dst)
200{
201 char *p = *dst, *q = *src;
202
203 switch (*q) {
204 case '\"':
205 *p = '\"';
206 break;
207 case '\\':
208 *p = '\\';
209 break;
210 case 'a':
211 *p = '\a';
212 break;
213 case 'e':
214 *p = '\e';
215 break;
216 default:
217 return false;
218 }
219 *dst += 1;
220 *src += 1;
221 return true;
222}
223
d295634e
AS
224/**
225 * string_unescape - unquote characters in the given string
226 * @src: source buffer (escaped)
227 * @dst: destination buffer (unescaped)
228 * @size: size of the destination buffer (0 to unlimit)
229 * @flags: combination of the flags (bitwise OR):
230 * %UNESCAPE_SPACE:
231 * '\f' - form feed
232 * '\n' - new line
233 * '\r' - carriage return
234 * '\t' - horizontal tab
235 * '\v' - vertical tab
236 * %UNESCAPE_OCTAL:
237 * '\NNN' - byte with octal value NNN (1 to 3 digits)
238 * %UNESCAPE_HEX:
239 * '\xHH' - byte with hexadecimal value HH (1 to 2 digits)
240 * %UNESCAPE_SPECIAL:
241 * '\"' - double quote
242 * '\\' - backslash
243 * '\a' - alert (BEL)
244 * '\e' - escape
245 * %UNESCAPE_ANY:
246 * all previous together
247 *
248 * Description:
249 * The function unquotes characters in the given string.
250 *
251 * Because the size of the output will be the same as or less than the size of
252 * the input, the transformation may be performed in place.
253 *
254 * Caller must provide valid source and destination pointers. Be aware that
255 * destination buffer will always be NULL-terminated. Source string must be
256 * NULL-terminated as well.
257 *
258 * Return:
259 * The amount of the characters processed to the destination buffer excluding
260 * trailing '\0' is returned.
261 */
16c7fa05
AS
262int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
263{
264 char *out = dst;
265
266 while (*src && --size) {
267 if (src[0] == '\\' && src[1] != '\0' && size > 1) {
268 src++;
269 size--;
270
271 if (flags & UNESCAPE_SPACE &&
272 unescape_space(&src, &out))
273 continue;
274
275 if (flags & UNESCAPE_OCTAL &&
276 unescape_octal(&src, &out))
277 continue;
278
279 if (flags & UNESCAPE_HEX &&
280 unescape_hex(&src, &out))
281 continue;
282
283 if (flags & UNESCAPE_SPECIAL &&
284 unescape_special(&src, &out))
285 continue;
286
287 *out++ = '\\';
288 }
289 *out++ = *src++;
290 }
291 *out = '\0';
292
293 return out - dst;
294}
295EXPORT_SYMBOL(string_unescape);
c8250381 296
3aeddc7d 297static bool escape_passthrough(unsigned char c, char **dst, char *end)
c8250381
AS
298{
299 char *out = *dst;
300
3aeddc7d
RV
301 if (out < end)
302 *out = c;
303 *dst = out + 1;
304 return true;
c8250381
AS
305}
306
3aeddc7d 307static bool escape_space(unsigned char c, char **dst, char *end)
c8250381
AS
308{
309 char *out = *dst;
310 unsigned char to;
311
c8250381
AS
312 switch (c) {
313 case '\n':
314 to = 'n';
315 break;
316 case '\r':
317 to = 'r';
318 break;
319 case '\t':
320 to = 't';
321 break;
322 case '\v':
323 to = 'v';
324 break;
325 case '\f':
326 to = 'f';
327 break;
328 default:
3aeddc7d 329 return false;
c8250381
AS
330 }
331
3aeddc7d
RV
332 if (out < end)
333 *out = '\\';
334 ++out;
335 if (out < end)
336 *out = to;
337 ++out;
c8250381 338
3aeddc7d
RV
339 *dst = out;
340 return true;
c8250381
AS
341}
342
3aeddc7d 343static bool escape_special(unsigned char c, char **dst, char *end)
c8250381
AS
344{
345 char *out = *dst;
346 unsigned char to;
347
c8250381
AS
348 switch (c) {
349 case '\\':
350 to = '\\';
351 break;
352 case '\a':
353 to = 'a';
354 break;
355 case '\e':
356 to = 'e';
357 break;
358 default:
3aeddc7d 359 return false;
c8250381
AS
360 }
361
3aeddc7d
RV
362 if (out < end)
363 *out = '\\';
364 ++out;
365 if (out < end)
366 *out = to;
367 ++out;
c8250381 368
3aeddc7d
RV
369 *dst = out;
370 return true;
c8250381
AS
371}
372
3aeddc7d 373static bool escape_null(unsigned char c, char **dst, char *end)
c8250381
AS
374{
375 char *out = *dst;
376
c8250381 377 if (c)
3aeddc7d 378 return false;
c8250381 379
3aeddc7d
RV
380 if (out < end)
381 *out = '\\';
382 ++out;
383 if (out < end)
384 *out = '0';
385 ++out;
c8250381 386
3aeddc7d
RV
387 *dst = out;
388 return true;
c8250381
AS
389}
390
3aeddc7d 391static bool escape_octal(unsigned char c, char **dst, char *end)
c8250381
AS
392{
393 char *out = *dst;
394
3aeddc7d
RV
395 if (out < end)
396 *out = '\\';
397 ++out;
398 if (out < end)
399 *out = ((c >> 6) & 0x07) + '0';
400 ++out;
401 if (out < end)
402 *out = ((c >> 3) & 0x07) + '0';
403 ++out;
404 if (out < end)
405 *out = ((c >> 0) & 0x07) + '0';
406 ++out;
c8250381
AS
407
408 *dst = out;
3aeddc7d 409 return true;
c8250381
AS
410}
411
3aeddc7d 412static bool escape_hex(unsigned char c, char **dst, char *end)
c8250381
AS
413{
414 char *out = *dst;
415
3aeddc7d
RV
416 if (out < end)
417 *out = '\\';
418 ++out;
419 if (out < end)
420 *out = 'x';
421 ++out;
422 if (out < end)
423 *out = hex_asc_hi(c);
424 ++out;
425 if (out < end)
426 *out = hex_asc_lo(c);
427 ++out;
c8250381
AS
428
429 *dst = out;
3aeddc7d 430 return true;
c8250381
AS
431}
432
433/**
434 * string_escape_mem - quote characters in the given memory buffer
435 * @src: source buffer (unescaped)
436 * @isz: source buffer size
437 * @dst: destination buffer (escaped)
438 * @osz: destination buffer size
439 * @flags: combination of the flags (bitwise OR):
d89a3f73 440 * %ESCAPE_SPACE: (special white space, not space itself)
c8250381
AS
441 * '\f' - form feed
442 * '\n' - new line
443 * '\r' - carriage return
444 * '\t' - horizontal tab
445 * '\v' - vertical tab
446 * %ESCAPE_SPECIAL:
447 * '\\' - backslash
448 * '\a' - alert (BEL)
449 * '\e' - escape
450 * %ESCAPE_NULL:
451 * '\0' - null
452 * %ESCAPE_OCTAL:
453 * '\NNN' - byte with octal value NNN (3 digits)
454 * %ESCAPE_ANY:
455 * all previous together
456 * %ESCAPE_NP:
457 * escape only non-printable characters (checked by isprint)
458 * %ESCAPE_ANY_NP:
459 * all previous together
460 * %ESCAPE_HEX:
461 * '\xHH' - byte with hexadecimal value HH (2 digits)
b40bdb7f
KC
462 * @only: NULL-terminated string containing characters used to limit
463 * the selected escape class. If characters are included in @only
d89a3f73
KC
464 * that would not normally be escaped by the classes selected
465 * in @flags, they will be copied to @dst unescaped.
c8250381
AS
466 *
467 * Description:
468 * The process of escaping byte buffer includes several parts. They are applied
469 * in the following sequence.
470 * 1. The character is matched to the printable class, if asked, and in
471 * case of match it passes through to the output.
b40bdb7f 472 * 2. The character is not matched to the one from @only string and thus
d89a3f73 473 * must go as-is to the output.
c8250381
AS
474 * 3. The character is checked if it falls into the class given by @flags.
475 * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
476 * character. Note that they actually can't go together, otherwise
477 * %ESCAPE_HEX will be ignored.
478 *
479 * Caller must provide valid source and destination pointers. Be aware that
480 * destination buffer will not be NULL-terminated, thus caller have to append
481 * it if needs.
482 *
483 * Return:
41416f23
RV
484 * The total size of the escaped output that would be generated for
485 * the given input and flags. To check whether the output was
486 * truncated, compare the return value to osz. There is room left in
487 * dst for a '\0' terminator if and only if ret < osz.
c8250381 488 */
41416f23 489int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
b40bdb7f 490 unsigned int flags, const char *only)
c8250381 491{
41416f23 492 char *p = dst;
3aeddc7d 493 char *end = p + osz;
b40bdb7f 494 bool is_dict = only && *only;
c8250381
AS
495
496 while (isz--) {
497 unsigned char c = *src++;
498
499 /*
500 * Apply rules in the following sequence:
501 * - the character is printable, when @flags has
502 * %ESCAPE_NP bit set
b40bdb7f 503 * - the @only string is supplied and does not contain a
c8250381
AS
504 * character under question
505 * - the character doesn't fall into a class of symbols
506 * defined by given @flags
507 * In these cases we just pass through a character to the
508 * output buffer.
509 */
510 if ((flags & ESCAPE_NP && isprint(c)) ||
b40bdb7f 511 (is_dict && !strchr(only, c))) {
c8250381
AS
512 /* do nothing */
513 } else {
3aeddc7d
RV
514 if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
515 continue;
516
517 if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
518 continue;
519
520 if (flags & ESCAPE_NULL && escape_null(c, &p, end))
521 continue;
c8250381
AS
522
523 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */
3aeddc7d 524 if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
c8250381 525 continue;
3aeddc7d
RV
526
527 if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
c8250381 528 continue;
c8250381
AS
529 }
530
3aeddc7d 531 escape_passthrough(c, &p, end);
c8250381
AS
532 }
533
41416f23 534 return p - dst;
c8250381
AS
535}
536EXPORT_SYMBOL(string_escape_mem);
This page took 0.532276 seconds and 5 git commands to generate.