X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fbasic%2Fescape.c;h=2e483880c80c53996a73c9d9816c8cbcac524b0c;hp=42a84c93174e619736e33b7a395179c947deca9b;hb=66ecc207e203db5434610395cd04c40ae8727b58;hpb=538a7c37c543255dbcb21c3854191c855150fa1d diff --git a/src/basic/escape.c b/src/basic/escape.c index 42a84c931..2e483880c 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,12 +17,15 @@ along with systemd; If not, see . ***/ +#include +#include +#include + #include "alloc-util.h" #include "escape.h" #include "hexdecoct.h" -#include "string-util.h" +#include "macro.h" #include "utf8.h" -#include "util.h" size_t cescape_char(char c, char *buf) { char * buf_old = buf; @@ -116,16 +117,18 @@ char *cescape(const char *s) { return cescape_length(s, strlen(s)); } -int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) { +int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) { int r = 1; assert(p); assert(*p); assert(ret); - /* Unescapes C style. Returns the unescaped character in ret, - * unless we encountered a \u sequence in which case the full - * unicode character is returned in ret_unicode, instead. */ + /* Unescapes C style. Returns the unescaped character in ret. + * Sets *eight_bit to true if the escaped sequence either fits in + * one byte in UTF-8 or is a non-unicode literal byte and should + * instead be copied directly. + */ if (length != (size_t) -1 && length < 1) return -EINVAL; @@ -187,7 +190,8 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode if (a == 0 && b == 0) return -EINVAL; - *ret = (char) ((a << 4U) | b); + *ret = (a << 4U) | b; + *eight_bit = true; r = 3; break; } @@ -214,16 +218,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode if (c == 0) return -EINVAL; - if (c < 128) - *ret = c; - else { - if (!ret_unicode) - return -EINVAL; - - *ret = 0; - *ret_unicode = c; - } - + *ret = c; r = 5; break; } @@ -233,7 +228,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode int a[8]; unsigned i; - uint32_t c; + char32_t c; if (length != (size_t) -1 && length < 9) return -EINVAL; @@ -255,16 +250,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode if (!unichar_is_valid(c)) return -EINVAL; - if (c < 128) - *ret = c; - else { - if (!ret_unicode) - return -EINVAL; - - *ret = 0; - *ret_unicode = c; - } - + *ret = c; r = 9; break; } @@ -279,7 +265,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode case '7': { /* octal encoding */ int a, b, c; - uint32_t m; + char32_t m; if (length != (size_t) -1 && length < 3) return -EINVAL; @@ -306,6 +292,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode return -EINVAL; *ret = m; + *eight_bit = true; r = 3; break; } @@ -338,8 +325,8 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi for (f = s, t = r + pl; f < s + length; f++) { size_t remaining; - uint32_t u; - char c; + bool eight_bit = false; + char32_t u; int k; remaining = s + length - f; @@ -362,7 +349,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi return -EINVAL; } - k = cunescape_one(f + 1, remaining - 1, &c, &u); + k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit); if (k < 0) { if (flags & UNESCAPE_RELAX) { /* Invalid escape code, let's take it literal then */ @@ -374,14 +361,13 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi return k; } - if (c != 0) - /* Non-Unicode? Let's encode this directly */ - *(t++) = c; + f += k; + if (eight_bit) + /* One byte? Set directly as specified */ + *(t++) = u; else - /* Unicode? Then let's encode this in UTF-8 */ + /* Otherwise encode as multi-byte UTF-8 */ t += utf8_encode_unichar(t, u); - - f += k; } *t = 0;