From 62e648e148b3cb9f96dcce808c55c02b7ccb4486 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 20 Jan 1999 04:59:39 +0000 Subject: ruby 1.3 cycle git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/RUBY@372 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- pack.c | 407 +++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 286 insertions(+), 121 deletions(-) (limited to 'pack.c') diff --git a/pack.c b/pack.c index 20d12d4003..dc393b83fe 100644 --- a/pack.c +++ b/pack.c @@ -6,13 +6,13 @@ $Date$ created at: Thu Feb 10 15:17:05 JST 1994 - Copyright (C) 1993-1996 Yukihiro Matsumoto + Copyright (C) 1993-1998 Yukihiro Matsumoto ************************************************/ #include "ruby.h" -#include #include +#include #define swaps(x) ((((x)&0xFF)<<8) + (((x)>>8)&0xFF)) #define swapl(x) ((((x)&0xFF)<<24) \ @@ -74,14 +74,22 @@ endian() #endif #endif -extern VALUE cString, cArray; -#ifndef atof -double atof(); -#endif - static char *toofew = "too few arguments"; -static void encodes(); +static void encodes _((VALUE,char*,int,int)); +static void qpencode _((VALUE,VALUE,int)); + +static void +pack_add_ptr(str, add) + VALUE str, add; +{ +#define STR_NO_ORIG FL_USER3 /* copied from string.c */ + if (!RSTRING(str)->orig) { + RSTRING(str)->orig = rb_ary_new(); + FL_SET(str, STR_NO_ORIG); + } + rb_ary_push(RSTRING(str)->orig, add); +} static VALUE pack_pack(ary, fmt) @@ -89,23 +97,22 @@ pack_pack(ary, fmt) { static char *nul10 = "\0\0\0\0\0\0\0\0\0\0"; static char *spc10 = " "; - UCHAR *p, *pend; + char *p, *pend; VALUE res, from; char type; int items, len, idx; - UCHAR *ptr; + char *ptr; int plen; - Check_Type(fmt, T_STRING); - - p = RSTRING(fmt)->ptr; - pend = RSTRING(fmt)->ptr + RSTRING(fmt)->len; - res = str_new(0, 0); + + p = rb_str2cstr(fmt, &plen); + pend = p + plen; + res = rb_str_new(0, 0); items = RARRAY(ary)->len; idx = 0; -#define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (ArgError(toofew),0)) +#define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (rb_raise(rb_eArgError, toofew),0)) while (p < pend) { type = *p++; /* get data type */ @@ -114,7 +121,7 @@ pack_pack(ary, fmt) len = strchr("@Xxu", type) ? 0 : items; p++; } - else if (isdigit(*p)) { + else if (ISDIGIT(*p)) { len = strtoul(p, (char**)&p, 10); } else { @@ -127,11 +134,11 @@ pack_pack(ary, fmt) case 'H': case 'h': from = NEXTFROM; if (NIL_P(from)) { - ptr = 0; + ptr = ""; plen = 0; } else { - from = obj_as_string(from); + from = rb_obj_as_string(from); ptr = RSTRING(from)->ptr; plen = RSTRING(from)->len; } @@ -143,15 +150,15 @@ pack_pack(ary, fmt) case 'a': case 'A': if (plen >= len) - str_cat(res, ptr, len); + rb_str_cat(res, ptr, len); else { - str_cat(res, ptr, plen); + rb_str_cat(res, ptr, plen); len -= plen; while (len >= 10) { - str_cat(res, (type == 'A')?spc10:nul10, 10); + rb_str_cat(res, (type == 'A')?spc10:nul10, 10); len -= 10; } - str_cat(res, (type == 'A')?spc10:nul10, len); + rb_str_cat(res, (type == 'A')?spc10:nul10, len); } break; @@ -167,7 +174,7 @@ pack_pack(ary, fmt) byte >>= 1; else { char c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); byte = 0; } } @@ -175,7 +182,7 @@ pack_pack(ary, fmt) char c; byte >>= 7 - (len & 7); c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); } } break; @@ -191,7 +198,7 @@ pack_pack(ary, fmt) byte <<= 1; else { char c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); byte = 0; } } @@ -199,7 +206,7 @@ pack_pack(ary, fmt) char c; byte <<= 7 - (len & 7); c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); } } break; @@ -210,8 +217,8 @@ pack_pack(ary, fmt) int i; for (i=0; i++ < len; ptr++) { - if (isxdigit(*ptr)) { - if (isalpha(*ptr)) + if (ISXDIGIT(*ptr)) { + if (ISALPHA(*ptr)) byte |= (((*ptr & 15) + 9) & 15) << 4; else byte |= (*ptr & 15) << 4; @@ -219,14 +226,14 @@ pack_pack(ary, fmt) byte >>= 4; else { char c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); byte = 0; } } } if (len & 1) { char c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); } } break; @@ -237,8 +244,8 @@ pack_pack(ary, fmt) int i; for (i=0; i++ < len; ptr++) { - if (isxdigit(*ptr)) { - if (isalpha(*ptr)) + if (ISXDIGIT(*ptr)) { + if (ISALPHA(*ptr)) byte |= ((*ptr & 15) + 9) & 15; else byte |= *ptr & 15; @@ -246,14 +253,14 @@ pack_pack(ary, fmt) byte <<= 4; else { char c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); byte = 0; } } } if (len & 1) { char c = byte & 0xff; - str_cat(res, &c, 1); + rb_str_cat(res, &c, 1); } } break; @@ -270,7 +277,7 @@ pack_pack(ary, fmt) else { c = NUM2INT(from); } - str_cat(res, &c, sizeof(char)); + rb_str_cat(res, &c, sizeof(char)); } break; @@ -284,7 +291,7 @@ pack_pack(ary, fmt) else { s = NUM2INT(from); } - str_cat(res, (UCHAR*)&s, sizeof(short)); + rb_str_cat(res, (char*)&s, sizeof(short)); } break; @@ -296,9 +303,9 @@ pack_pack(ary, fmt) from = NEXTFROM; if (NIL_P(from)) i = 0; else { - i = NUM2INT(from); + i = NUM2UINT(from); } - str_cat(res, (UCHAR*)&i, sizeof(int)); + rb_str_cat(res, (char*)&i, sizeof(int)); } break; @@ -310,9 +317,9 @@ pack_pack(ary, fmt) from = NEXTFROM; if (NIL_P(from)) l = 0; else { - l = NUM2INT(from); + l = NUM2ULONG(from); } - str_cat(res, (UCHAR*)&l, sizeof(long)); + rb_str_cat(res, (char*)&l, sizeof(long)); } break; @@ -326,7 +333,7 @@ pack_pack(ary, fmt) s = NUM2INT(from); } s = htons(s); - str_cat(res, (UCHAR*)&s, sizeof(short)); + rb_str_cat(res, (char*)&s, sizeof(short)); } break; @@ -337,10 +344,10 @@ pack_pack(ary, fmt) from = NEXTFROM; if (NIL_P(from)) l = 0; else { - l = NUM2INT(from); + l = NUM2ULONG(from); } l = htonl(l); - str_cat(res, (UCHAR*)&l, sizeof(long)); + rb_str_cat(res, (char*)&l, sizeof(long)); } break; @@ -354,7 +361,7 @@ pack_pack(ary, fmt) s = NUM2INT(from); } s = htovs(s); - str_cat(res, (UCHAR*)&s, sizeof(short)); + rb_str_cat(res, (char*)&s, sizeof(short)); } break; @@ -365,10 +372,10 @@ pack_pack(ary, fmt) from = NEXTFROM; if (NIL_P(from)) l = 0; else { - l = NUM2INT(from); + l = NUM2ULONG(from); } l = htovl(l); - str_cat(res, (UCHAR*)&l, sizeof(long)); + rb_str_cat(res, (char*)&l, sizeof(long)); } break; @@ -388,7 +395,7 @@ pack_pack(ary, fmt) f = (float)NUM2INT(from); break; } - str_cat(res, (UCHAR*)&f, sizeof(float)); + rb_str_cat(res, (char*)&f, sizeof(float)); } break; @@ -408,23 +415,23 @@ pack_pack(ary, fmt) d = (double)NUM2INT(from); break; } - str_cat(res, (UCHAR*)&d, sizeof(double)); + rb_str_cat(res, (char*)&d, sizeof(double)); } break; case 'x': grow: while (len >= 10) { - str_cat(res, nul10, 10); + rb_str_cat(res, nul10, 10); len -= 10; } - str_cat(res, nul10, len); + rb_str_cat(res, nul10, len); break; case 'X': shrink: if (RSTRING(res)->len < len) - ArgError("X outside of string"); + rb_raise(rb_eArgError, "X outside of string"); RSTRING(res)->len -= len; RSTRING(res)->ptr[RSTRING(res)->len] = '\0'; break; @@ -437,12 +444,12 @@ pack_pack(ary, fmt) break; case '%': - ArgError("% may only be used in unpack"); + rb_raise(rb_eArgError, "% may only be used in unpack"); break; case 'u': case 'm': - from = obj_as_string(NEXTFROM); + from = rb_obj_as_string(NEXTFROM); ptr = RSTRING(from)->ptr; plen = RSTRING(from)->len; @@ -463,6 +470,29 @@ pack_pack(ary, fmt) } break; + case 'M': + from = rb_obj_as_string(NEXTFROM); + if (len <= 1) + len = 72; + qpencode(res, from, len); + break; + + case 'P': + len = 1; + /* FALL THROUGH */ + case 'p': + while (len-- > 0) { + char *t; + from = NEXTFROM; + if (NIL_P(from)) t = ""; + else { + t = STR2CSTR(from); + pack_add_ptr(res, from); + } + rb_str_cat(res, (char*)&t, sizeof(char*)); + } + break; + default: break; } @@ -479,42 +509,124 @@ static char b64_table[] = static void encodes(str, s, len, type) VALUE str; - UCHAR *s; + char *s; int len; int type; { - char hunk[4]; - UCHAR *p, *pend; + char *buff = ALLOCA_N(char, len * 4 / 3 + 6); + int i = 0; 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 == 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'; + rb_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) { + rb_str_cat(str, buff, i); + i = 0; + } + s++; + } + if (n > 0) { + buff[i++] = '='; + buff[i++] = '\n'; } - else if (len == -2) { - pend[-2] = padding; - pend[-1] = padding; + if (i > 0) { + rb_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 @@ -522,27 +634,25 @@ pack_unpack(str, fmt) VALUE str, fmt; { static char *hexdigits = "0123456789abcdef0123456789ABCDEFx"; - UCHAR *s, *send; - UCHAR *p, *pend; + char *s, *send; + char *p, *pend; VALUE ary; char type; int len; - Check_Type(fmt, T_STRING); - - s = RSTRING(str)->ptr; - send = s + RSTRING(str)->len; - p = RSTRING(fmt)->ptr; - pend = p + RSTRING(fmt)->len; + s = rb_str2cstr(str, &len); + send = s + len; + p = rb_str2cstr(fmt, &len); + pend = p + len; - ary = ary_new(); + ary = rb_ary_new(); while (p < pend) { type = *p++; if (*p == '*') { len = send - s; p++; } - else if (isdigit(*p)) { + else if (ISDIGIT(*p)) { len = strtoul(p, (char**)&p, 10); } else { @@ -551,41 +661,41 @@ pack_unpack(str, fmt) switch (type) { case '%': - ArgError("% is not supported(yet)"); + rb_raise(rb_eArgError, "% is not supported(yet)"); break; case 'A': if (len > send - s) len = send - s; { int end = len; - UCHAR *t = s + len - 1; + char *t = s + len - 1; while (t >= s) { if (*t != ' ' && *t != '\0') break; t--; len--; } - ary_push(ary, str_new(s, len)); + rb_ary_push(ary, rb_str_new(s, len)); s += end; } break; case 'a': if (len > send - s) len = send - s; - ary_push(ary, str_new(s, len)); + rb_ary_push(ary, rb_str_new(s, len)); s += len; break; case 'b': { VALUE bitstr; - UCHAR *t; + char *t; int bits, i; if (p[-1] == '*' || len > (send - s) * 8) len = (send - s) * 8; bits = 0; - ary_push(ary, bitstr = str_new(0, len)); + rb_ary_push(ary, bitstr = rb_str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i>= 1; @@ -598,13 +708,13 @@ pack_unpack(str, fmt) case 'B': { VALUE bitstr; - UCHAR *t; + char *t; int bits, i; if (p[-1] == '*' || len > (send - s) * 8) len = (send - s) * 8; bits = 0; - ary_push(ary, bitstr = str_new(0, len)); + rb_ary_push(ary, bitstr = rb_str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i (send - s) * 2) len = (send - s) * 2; bits = 0; - ary_push(ary, bitstr = str_new(0, len)); + rb_ary_push(ary, bitstr = rb_str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i (send - s) * 2) len = (send - s) * 2; bits = 0; - ary_push(ary, bitstr = str_new(0, len)); + rb_ary_push(ary, bitstr = rb_str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i 0) { int c = *s++; if (c > (char)127) c-=256; - ary_push(ary, INT2FIX(c)); + rb_ary_push(ary, INT2FIX(c)); } break; @@ -670,8 +780,8 @@ pack_unpack(str, fmt) if (len > send - s) len = send - s; while (len-- > 0) { - UCHAR c = *s++; - ary_push(ary, INT2FIX(c)); + unsigned char c = *s++; + rb_ary_push(ary, INT2FIX(c)); } break; @@ -682,7 +792,7 @@ pack_unpack(str, fmt) short tmp; memcpy(&tmp, s, sizeof(short)); s += sizeof(short); - ary_push(ary, INT2FIX(tmp)); + rb_ary_push(ary, INT2FIX(tmp)); } break; @@ -693,7 +803,7 @@ pack_unpack(str, fmt) unsigned short tmp; memcpy(&tmp, s, sizeof(short)); s += sizeof(short); - ary_push(ary, INT2FIX(tmp)); + rb_ary_push(ary, INT2FIX(tmp)); } break; @@ -704,7 +814,7 @@ pack_unpack(str, fmt) int tmp; memcpy(&tmp, s, sizeof(int)); s += sizeof(int); - ary_push(ary, int2inum(tmp)); + rb_ary_push(ary, rb_int2inum(tmp)); } break; @@ -715,7 +825,7 @@ pack_unpack(str, fmt) unsigned int tmp; memcpy(&tmp, s, sizeof(int)); s += sizeof(int); - ary_push(ary, int2inum(tmp)); + rb_ary_push(ary, rb_uint2inum(tmp)); } break; @@ -726,7 +836,7 @@ pack_unpack(str, fmt) long tmp; memcpy(&tmp, s, sizeof(long)); s += sizeof(long); - ary_push(ary, int2inum(tmp)); + rb_ary_push(ary, rb_int2inum(tmp)); } break; @@ -737,7 +847,7 @@ pack_unpack(str, fmt) unsigned long tmp; memcpy(&tmp, s, sizeof(long)); s += sizeof(long); - ary_push(ary, uint2inum(tmp)); + rb_ary_push(ary, rb_uint2inum(tmp)); } break; @@ -749,7 +859,7 @@ pack_unpack(str, fmt) memcpy(&tmp, s, sizeof(short)); s += sizeof(short); tmp = ntohs(tmp); - ary_push(ary, uint2inum(tmp)); + rb_ary_push(ary, rb_uint2inum(tmp)); } break; @@ -761,7 +871,7 @@ pack_unpack(str, fmt) memcpy(&tmp, s, sizeof(long)); s += sizeof(long); tmp = ntohl(tmp); - ary_push(ary, uint2inum(tmp)); + rb_ary_push(ary, rb_uint2inum(tmp)); } break; @@ -773,7 +883,7 @@ pack_unpack(str, fmt) memcpy(&tmp, s, sizeof(short)); s += sizeof(short); tmp = vtohs(tmp); - ary_push(ary, uint2inum(tmp)); + rb_ary_push(ary, rb_uint2inum(tmp)); } break; @@ -785,7 +895,7 @@ pack_unpack(str, fmt) memcpy(&tmp, s, sizeof(long)); s += sizeof(long); tmp = vtohl(tmp); - ary_push(ary, uint2inum(tmp)); + rb_ary_push(ary, rb_uint2inum(tmp)); } break; @@ -797,7 +907,7 @@ pack_unpack(str, fmt) float tmp; memcpy(&tmp, s, sizeof(float)); s += sizeof(float); - ary_push(ary, float_new((double)tmp)); + rb_ary_push(ary, rb_float_new((double)tmp)); } break; @@ -809,14 +919,14 @@ pack_unpack(str, fmt) double tmp; memcpy(&tmp, s, sizeof(double)); s += sizeof(double); - ary_push(ary, float_new(tmp)); + rb_ary_push(ary, rb_float_new(tmp)); } break; case 'u': { - VALUE str = str_new(0, (send - s)*3/4); - UCHAR *ptr = RSTRING(str)->ptr; + VALUE str = rb_str_new(0, (send - s)*3/4); + char *ptr = RSTRING(str)->ptr; int total = 0; while (s < send && *s > ' ' && *s < 'a') { @@ -863,15 +973,14 @@ pack_unpack(str, fmt) s += 2; /* possible checksum byte */ } RSTRING(str)->len = total; - ary_push(ary, str); + rb_ary_push(ary, str); } break; case 'm': { - VALUE str = str_new(0, (send - s)*3/4); - UCHAR *ptr = RSTRING(str)->ptr; - int total = 0; + VALUE str = rb_str_new(0, (send - s)*3/4); + char *ptr = RSTRING(str)->ptr; int a,b,c,d; static int first = 1; static int b64_xtable[256]; @@ -906,7 +1015,33 @@ pack_unpack(str, fmt) *ptr++ = b << 4 | c >> 2; } RSTRING(str)->len = ptr - RSTRING(str)->ptr; - ary_push(ary, str); + rb_ary_push(ary, str); + } + break; + + case 'M': + { + VALUE str = rb_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') { + 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; + rb_ary_push(ary, str); } break; @@ -916,16 +1051,46 @@ pack_unpack(str, fmt) case 'X': if (len > s - RSTRING(str)->ptr) - ArgError("X outside of string"); + rb_raise(rb_eArgError, "X outside of string"); s -= len; break; case 'x': if (len > send - s) - ArgError("x outside of string"); + rb_raise(rb_eArgError, "x outside of string"); s += len; break; + case 'P': + if (sizeof(char *) <= send - s) { + char *t; + VALUE str = rb_str_new(0, 0); + memcpy(&t, s, sizeof(char *)); + s += sizeof(char *); + if (t) + rb_str_cat(str, t, len); + rb_ary_push(ary, str); + } + break; + + case 'p': + if (len > (send - s) / sizeof(char *)) + len = (send - s) / sizeof(char *); + while (len-- > 0) { + if (send - s < sizeof(char *)) + break; + else { + char *t; + VALUE str = rb_str_new(0, 0); + memcpy(&t, s, sizeof(char *)); + s += sizeof(char *); + if (t) + rb_str_cat(str, t, strlen(t)); + rb_ary_push(ary, str); + } + } + break; + default: break; } @@ -937,6 +1102,6 @@ pack_unpack(str, fmt) void Init_pack() { - rb_define_method(cArray, "pack", pack_pack, 1); - rb_define_method(cString, "unpack", pack_unpack, 1); + rb_define_method(rb_cArray, "pack", pack_pack, 1); + rb_define_method(rb_cString, "unpack", pack_unpack, 1); } -- cgit v1.2.3