diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-07-02 09:01:31 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-07-02 09:01:31 -0700 | 
| commit | 27eb2c4b3d3e13f376a359e293c212a2e9407af5 (patch) | |
| tree | 556aa7b5cd6eeb4214dec129c789515157187010 /lib/string_helpers.c | |
| parent | 5705b8aca5a80141de5637ff0e23b31b26f2c5bf (diff) | |
| parent | 67bf12ca50d524f9e225347fe63533562e2004de (diff) | |
Merge branch 'next' into for-linus
Prepare first set of updates for 3.11 merge window.
Diffstat (limited to 'lib/string_helpers.c')
| -rw-r--r-- | lib/string_helpers.c | 133 | 
1 files changed, 133 insertions, 0 deletions
| diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 1cffc223bff5..ed5c1454dd62 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -2,10 +2,12 @@   * Helpers for formatting and printing strings   *   * Copyright 31 August 2008 James Bottomley + * Copyright (C) 2013, Intel Corporation   */  #include <linux/kernel.h>  #include <linux/math64.h>  #include <linux/export.h> +#include <linux/ctype.h>  #include <linux/string_helpers.h>  /** @@ -66,3 +68,134 @@ int string_get_size(u64 size, const enum string_size_units units,  	return 0;  }  EXPORT_SYMBOL(string_get_size); + +static bool unescape_space(char **src, char **dst) +{ +	char *p = *dst, *q = *src; + +	switch (*q) { +	case 'n': +		*p = '\n'; +		break; +	case 'r': +		*p = '\r'; +		break; +	case 't': +		*p = '\t'; +		break; +	case 'v': +		*p = '\v'; +		break; +	case 'f': +		*p = '\f'; +		break; +	default: +		return false; +	} +	*dst += 1; +	*src += 1; +	return true; +} + +static bool unescape_octal(char **src, char **dst) +{ +	char *p = *dst, *q = *src; +	u8 num; + +	if (isodigit(*q) == 0) +		return false; + +	num = (*q++) & 7; +	while (num < 32 && isodigit(*q) && (q - *src < 3)) { +		num <<= 3; +		num += (*q++) & 7; +	} +	*p = num; +	*dst += 1; +	*src = q; +	return true; +} + +static bool unescape_hex(char **src, char **dst) +{ +	char *p = *dst, *q = *src; +	int digit; +	u8 num; + +	if (*q++ != 'x') +		return false; + +	num = digit = hex_to_bin(*q++); +	if (digit < 0) +		return false; + +	digit = hex_to_bin(*q); +	if (digit >= 0) { +		q++; +		num = (num << 4) | digit; +	} +	*p = num; +	*dst += 1; +	*src = q; +	return true; +} + +static bool unescape_special(char **src, char **dst) +{ +	char *p = *dst, *q = *src; + +	switch (*q) { +	case '\"': +		*p = '\"'; +		break; +	case '\\': +		*p = '\\'; +		break; +	case 'a': +		*p = '\a'; +		break; +	case 'e': +		*p = '\e'; +		break; +	default: +		return false; +	} +	*dst += 1; +	*src += 1; +	return true; +} + +int string_unescape(char *src, char *dst, size_t size, unsigned int flags) +{ +	char *out = dst; + +	while (*src && --size) { +		if (src[0] == '\\' && src[1] != '\0' && size > 1) { +			src++; +			size--; + +			if (flags & UNESCAPE_SPACE && +					unescape_space(&src, &out)) +				continue; + +			if (flags & UNESCAPE_OCTAL && +					unescape_octal(&src, &out)) +				continue; + +			if (flags & UNESCAPE_HEX && +					unescape_hex(&src, &out)) +				continue; + +			if (flags & UNESCAPE_SPECIAL && +					unescape_special(&src, &out)) +				continue; + +			*out++ = '\\'; +		} +		*out++ = *src++; +	} +	*out = '\0'; + +	return out - dst; +} +EXPORT_SYMBOL(string_unescape); | 
