From 17a5fa1b4344199cef86c2cea4f1ba35f021593d Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 14 Dec 1998 09:00:08 +0000 Subject: 1.1c final (hopefully) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@347 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- pack.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 134 insertions(+), 17 deletions(-) (limited to 'pack.c') diff --git a/pack.c b/pack.c index 840b837ce5..903f5a9bc0 100644 --- a/pack.c +++ b/pack.c @@ -77,6 +77,7 @@ endian() static char *toofew = "too few arguments"; static void encodes _((VALUE,char*,int,int)); +static void qpencode _((VALUE,VALUE,int)); static void pack_add_ptr(str, add) @@ -469,6 +470,13 @@ pack_pack(ary, fmt) } break; + case 'M': + from = obj_as_string(NEXTFROM); + if (len <= 1) + len = 72; + qpencode(res, from, len); + break; + case 'P': len = 1; /* FALL THROUGH */ @@ -505,38 +513,121 @@ encodes(str, s, len, type) int len; int type; { - char hunk[4]; + char *buff = ALLOCA_N(char, len * 4 / 3 + 6); + int i = 0; char *p, *pend; char *trans = type == 'u' ? uu_table : b64_table; int padding; if (type == 'u') { - *hunk = len + ' '; - str_cat(str, hunk, 1); + buff[i++] = len + ' '; padding = '`'; } else { padding = '='; } - while (len > 0) { - hunk[0] = trans[077 & (*s >> 2)]; - hunk[1] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; - hunk[2] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))]; - hunk[3] = trans[077 & s[2]]; - str_cat(str, hunk, 4); + while (len >= 3) { + buff[i++] = trans[077 & (*s >> 2)]; + buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; + buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))]; + buff[i++] = trans[077 & s[2]]; s += 3; len -= 3; } - p = RSTRING(str)->ptr; - pend = RSTRING(str)->ptr + RSTRING(str)->len; - if (len == -1) { - pend[-1] = padding; + if (len == 2) { + buff[i++] = trans[077 & (*s >> 2)]; + buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; + buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))]; + buff[i++] = padding; } - else if (len == -2) { - pend[-2] = padding; - pend[-1] = padding; + else if (len == 1) { + buff[i++] = trans[077 & (*s >> 2)]; + buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))]; + buff[i++] = padding; + buff[i++] = padding; + } + buff[i++] = '\n'; + str_cat(str, buff, i); +} + +static char hex_table[] = "0123456789ABCDEF"; + +static void +qpencode(str, from, len) + VALUE str, from; + int len; +{ + char buff[1024]; + int i = 0, n = 0, prev = EOF; + unsigned char *s = RSTRING(from)->ptr; + unsigned char *send = s + RSTRING(from)->len; + + while (s < send) { + if ((*s > 126) || + (*s < 32 && *s != '\n' && *s != '\t') || + (*s == '=')) { + buff[i++] = '='; + buff[i++] = hex_table[*s >> 4]; + buff[i++] = hex_table[*s & 0x0f]; + n += 3; + prev = EOF; + } + else if (*s == '\n') { + if (prev == ' ' || prev == '\t') { + buff[i++] = '='; + buff[i++] = *s; + } + buff[i++] = *s; + n = 0; + prev = *s; + } + else { + buff[i++] = *s; + n++; + prev = *s; + } + if (n > len) { + buff[i++] = '='; + buff[i++] = '\n'; + n = 0; + prev = '\n'; + } + if (i > 1024 - 5) { + str_cat(str, buff, i); + i = 0; + } + s++; + } + if (n > 0) { + buff[i++] = '='; + buff[i++] = '\n'; + } + if (i > 0) { + str_cat(str, buff, i); + } +} + +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE) +static __inline__ int +#else +static int +#endif +hex2num(c) + char c; +{ + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return c - '0'; + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + return c - 'a' + 10; + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + return c - 'A' + 10; + default: + return -1; } - str_cat(str, "\n", 1); } static VALUE @@ -929,6 +1020,32 @@ pack_unpack(str, fmt) } break; + case 'M': + { + VALUE str = str_new(0, send - s); + char *ptr = RSTRING(str)->ptr; + int c1, c2; + + while (s < send) { + if (*s == '=') { + if (++s == send) break; + if (*s != '\n' && s < send - 1) { + if ((c1 = hex2num(*s)) == -1) break; + if (++s == send) break; + if ((c2 = hex2num(*s)) == -1) break; + *ptr++ = c1 << 4 | c2; + } + } + else { + *ptr++ = *s; + } + s++; + } + RSTRING(str)->len = ptr - RSTRING(str)->ptr; + ary_push(ary, str); + } + break; + case '@': s = RSTRING(str)->ptr + len; break; -- cgit v1.2.3