diff options
Diffstat (limited to 'mrbgems/mruby-pack/src')
| -rw-r--r-- | mrbgems/mruby-pack/src/pack.c | 394 |
1 files changed, 302 insertions, 92 deletions
diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index e52171d6b..f0d4b8d9e 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -18,18 +18,23 @@ #define INT_OVERFLOW_P(n) ((n) < MRB_INT_MIN || (n) > MRB_INT_MAX) #define UINT_OVERFLOW_P(n) ((n) > MRB_INT_MAX) +#ifndef EOF +# define EOF (-1) /* for MRB_NO_STDIO */ +#endif + struct tmpl { mrb_value str; int idx; }; -enum { +enum pack_dir { PACK_DIR_CHAR, /* C */ PACK_DIR_SHORT, /* S */ PACK_DIR_LONG, /* L */ PACK_DIR_QUAD, /* Q */ //PACK_DIR_INT, /* i */ //PACK_DIR_VAX, + PACK_DIR_BER, /* w */ PACK_DIR_UTF8, /* U */ //PACK_DIR_BER, PACK_DIR_DOUBLE, /* E */ @@ -37,30 +42,33 @@ enum { PACK_DIR_STR, /* A */ PACK_DIR_HEX, /* h */ PACK_DIR_BASE64, /* m */ + PACK_DIR_QENC, /* M */ PACK_DIR_NUL, /* x */ + PACK_DIR_BACK, /* X */ + PACK_DIR_ABS, /* @ */ PACK_DIR_INVALID }; -enum { +enum pack_type { PACK_TYPE_INTEGER, PACK_TYPE_FLOAT, PACK_TYPE_STRING, PACK_TYPE_NONE }; -#define PACK_FLAG_s 0x00000001 /* native size ("_" "!") */ -#define PACK_FLAG_a 0x00000002 /* null padding ("a") */ -#define PACK_FLAG_Z 0x00000004 /* append nul char ("z") */ -#define PACK_FLAG_SIGNED 0x00000008 /* native size ("_" "!") */ -#define PACK_FLAG_GT 0x00000010 /* big endian (">") */ -#define PACK_FLAG_LT 0x00000020 /* little endian ("<") */ -#define PACK_FLAG_WIDTH 0x00000040 /* "count" is "width" */ -#define PACK_FLAG_LSB 0x00000080 /* LSB / low nibble first */ -#define PACK_FLAG_COUNT2 0x00000100 /* "count" is special... */ -#define PACK_FLAG_LITTLEENDIAN 0x00000200 /* little endian actually */ +#define PACK_FLAG_s 0x00000001 /* native size ("_" "!") */ +#define PACK_FLAG_a 0x00000002 /* null padding ("a") */ +#define PACK_FLAG_Z 0x00000004 /* append nul char ("z") */ +#define PACK_FLAG_SIGNED 0x00000008 /* native size ("_" "!") */ +#define PACK_FLAG_GT 0x00000010 /* big endian (">") */ +#define PACK_FLAG_LT 0x00000020 /* little endian ("<") */ +#define PACK_FLAG_WIDTH 0x00000040 /* "count" is "width" */ +#define PACK_FLAG_LSB 0x00000080 /* LSB / low nibble first */ +#define PACK_FLAG_COUNT2 0x00000100 /* "count" is special... */ +#define PACK_FLAG_LITTLEENDIAN 0x00000200 /* little endian actually */ -#define PACK_BASE64_IGNORE 0xff -#define PACK_BASE64_PADDING 0xfe +#define PACK_BASE64_IGNORE 0xff +#define PACK_BASE64_PADDING 0xfe const static unsigned char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -76,7 +84,7 @@ hex2int(unsigned char ch) else if (ch >= 'a' && ch <= 'f') return 10 + (ch - 'a'); else - return 0; + return -1; } static void @@ -113,7 +121,7 @@ str_len_ensure(mrb_state *mrb, mrb_value str, mrb_int len) static int -pack_c(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) +pack_char(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) { str = str_len_ensure(mrb, str, sidx + 1); RSTRING_PTR(str)[sidx] = (char)mrb_integer(o); @@ -121,7 +129,7 @@ pack_c(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int fl } static int -unpack_c(mrb_state *mrb, const void *src, int srclen, mrb_value ary, unsigned int flags) +unpack_char(mrb_state *mrb, const void *src, int srclen, mrb_value ary, unsigned int flags) { if (flags & PACK_FLAG_SIGNED) mrb_ary_push(mrb, ary, mrb_fixnum_value(*(signed char *)src)); @@ -131,7 +139,7 @@ unpack_c(mrb_state *mrb, const void *src, int srclen, mrb_value ary, unsigned in } static int -pack_s(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) +pack_short(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) { uint16_t n; @@ -148,7 +156,7 @@ pack_s(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int fl } static int -unpack_s(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) +unpack_short(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) { int n; @@ -165,7 +173,7 @@ unpack_s(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un } static int -pack_l(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) +pack_long(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) { uint32_t n; @@ -219,7 +227,7 @@ u32tostr(char *buf, size_t len, uint32_t n) #endif /* MRB_INT64 */ static int -unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) +unpack_long(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) { #ifndef MRB_INT64 char msg[60]; @@ -254,7 +262,7 @@ unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un } static int -pack_q(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) +pack_quad(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) { uint64_t n; @@ -336,7 +344,7 @@ i64tostr(char *buf, size_t len, int64_t n) #endif /* MRB_INT64 */ static int -unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) +unpack_quad(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) { char msg[60]; uint64_t ull; @@ -375,6 +383,46 @@ unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un return 8; } +static int +pack_BER(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) +{ + mrb_int n = mrb_integer(o); + size_t i; + char *p; + + if (n < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "can't compress negative numbers"); + } + for (i=1; i<sizeof(mrb_int)+1; i++) { + mrb_int mask = ~((1L<<(7*i))-1); + if ((n & mask) == 0) break; + } + str = str_len_ensure(mrb, str, sidx + i); + p = RSTRING_PTR(str)+sidx; + for (size_t j=i; j>0; p++,j--) { + mrb_int x = (n>>(7*(j-1)))&0x7f; + *p = (char)x; + if (j > 1) *p |= 0x80; + } + return i; +} + +static int +unpack_BER(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags) +{ + mrb_int i, n = 0; + const unsigned char *p = src; + const unsigned char *e = p + srclen; + + for (i=1; p<e; p++,i++) { + n <<= 7; + n |= *p & 0x7f; + if ((*p & 0x80) == 0) break; + } + mrb_ary_push(mrb, ary, mrb_int_value(mrb, n)); + return i; +} + #ifndef MRB_NO_FLOAT static int pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags) @@ -504,7 +552,7 @@ unpack_float(mrb_state *mrb, const unsigned char * src, int srclen, mrb_value ar #endif static int -pack_utf8(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, long count, unsigned int flags) +pack_utf8(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, int count, unsigned int flags) { char utf8[4]; int len = 0; @@ -621,7 +669,7 @@ unpack_utf8(mrb_state *mrb, const unsigned char * src, int srclen, mrb_value ary } static int -pack_a(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags) +pack_str(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count, unsigned int flags) { mrb_int copylen, slen, padlen; char *dptr, *dptr0, pad, *sptr; @@ -659,7 +707,7 @@ pack_a(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, u } static int -unpack_a(mrb_state *mrb, const void *src, int slen, mrb_value ary, long count, unsigned int flags) +unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, unsigned int flags) { mrb_value dst; const char *cp, *sptr; @@ -693,7 +741,7 @@ unpack_a(mrb_state *mrb, const void *src, int slen, mrb_value ary, long count, u static int -pack_h(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags) +pack_hex(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count, unsigned int flags) { unsigned int a, ashift, b, bshift; long slen; @@ -724,10 +772,12 @@ pack_h(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, u a = b = 0; if (slen > 0) { a = hex2int(*sptr++); + if (a < 0) break; slen--; } if (slen > 0) { b = hex2int(*sptr++); + if (b < 0) break; slen--; } *dptr++ = (a << ashift) + (b << bshift); @@ -737,7 +787,7 @@ pack_h(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, u } static int -unpack_h(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, unsigned int flags) +unpack_hex(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, unsigned int flags) { mrb_value dst; int a, ashift, b, bshift; @@ -783,9 +833,8 @@ unpack_h(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, un return (int)(sptr - sptr0); } - static int -pack_m(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags) +pack_base64(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count) { mrb_int dstlen; unsigned long l; @@ -851,7 +900,7 @@ pack_m(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, u } static int -unpack_m(mrb_state *mrb, const void *src, int slen, mrb_value ary, unsigned int flags) +unpack_base64(mrb_state *mrb, const void *src, int slen, mrb_value ary) { mrb_value dst; int dlen; @@ -874,13 +923,13 @@ unpack_m(mrb_state *mrb, const void *src, int slen, mrb_value ary, unsigned int if (slen-- == 0) goto done; c = *sptr++; - if (c >= sizeof(base64_dec_tab)) - continue; - ch[i] = base64_dec_tab[c]; - if (ch[i] == PACK_BASE64_PADDING) { - ch[i] = 0; - padding++; - } + if (c >= sizeof(base64_dec_tab)) + continue; + ch[i] = base64_dec_tab[c]; + if (ch[i] == PACK_BASE64_PADDING) { + ch[i] = 0; + padding++; + } } while (c >= sizeof(base64_dec_tab) || ch[i] == PACK_BASE64_IGNORE); } @@ -907,25 +956,117 @@ done: } static int -pack_x(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags) +pack_qenc(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count) +{ + static const char hex_table[] = "0123456789ABCDEF"; + char buff[1024]; + char *s = RSTRING_PTR(src); + char *send = s + RSTRING_LEN(src); + int i = 0, n = 0, prev = EOF; + int dlen = 0; + + if (count <= 1) count = 72; + while (s < send) { + if ((*s > 126) || + (*s < 32 && *s != '\n' && *s != '\t') || + (*s == '=')) { + buff[i++] = '='; + buff[i++] = hex_table[(*s & 0xf0) >> 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 > count) { + buff[i++] = '='; + buff[i++] = '\n'; + n = 0; + prev = '\n'; + } + if (i > 1024 - 5) { + str_len_ensure(mrb, dst, didx+dlen+i); + memcpy(RSTRING_PTR(dst)+didx+dlen, buff, i); + dlen += i; + i = 0; + } + s++; + } + if (n > 0) { + buff[i++] = '='; + buff[i++] = '\n'; + } + if (i > 0) { + str_len_ensure(mrb, dst, didx+dlen+i); + memcpy(RSTRING_PTR(dst)+didx+dlen, buff, i); + dlen += i; + } + return dlen; +} + +static int +unpack_qenc(mrb_state *mrb, const void *src, int slen, mrb_value ary) +{ + mrb_value buf = mrb_str_new(mrb, 0, slen); + const char *s = (const char*)src, *ss = s; + const char *send = s + slen; + char *ptr = RSTRING_PTR(buf); + int c1, c2; + + while (s < send) { + if (*s == '=') { + if (++s == send) break; + if (s+1 < send && *s == '\r' && *(s+1) == '\n') + s++; + if (*s != '\n') { + if ((c1 = hex2int(*s)) == -1) break; + if (++s == send) break; + if ((c2 = hex2int(*s)) == -1) break; + *ptr++ = (char)(c1 << 4 | c2); + } + } + else { + *ptr++ = *s; + } + s++; + ss = s; + } + buf = mrb_str_resize(mrb, buf, (mrb_int)(ptr - RSTRING_PTR(buf))); + mrb_str_cat(mrb, buf, ss, send-ss); + mrb_ary_push(mrb, ary, buf); + return slen; +} + +static int +pack_nul(mrb_state *mrb, mrb_value dst, mrb_int didx, int count) { long i; - if (count < 0) return 0; dst = str_len_ensure(mrb, dst, didx + count); for (i = 0; i < count; i++) { RSTRING_PTR(dst)[didx + i] = '\0'; } return count; } -static int -unpack_x(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, unsigned int flags) + +static void +check_x(mrb_state *mrb, int a, int count, char c) { - if (count < 0) return slen; - if (slen < count) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "x outside of string"); + if (a < count) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%c outside of string", c); } - return count; } static void @@ -942,10 +1083,12 @@ has_tmpl(const struct tmpl *tmpl) } static void -read_tmpl(mrb_state *mrb, struct tmpl *tmpl, int *dirp, int *typep, int *sizep, int *countp, unsigned int *flagsp) +read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_dir *dirp, enum pack_type *typep, int *sizep, int *countp, unsigned int *flagsp) { mrb_int t, tlen; - int ch, dir, type, size = 0; + int ch, size = 0; + enum pack_dir dir; + enum pack_type type; int count = 1; unsigned int flags = 0; const char *tptr; @@ -1052,11 +1195,21 @@ alias: size = 4; flags |= PACK_FLAG_SIGNED; break; + case 'w': + dir = PACK_DIR_BER; + type = PACK_TYPE_INTEGER; + flags |= PACK_FLAG_SIGNED; + break; case 'm': dir = PACK_DIR_BASE64; type = PACK_TYPE_STRING; flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2; break; + case 'M': + dir = PACK_DIR_QENC; + type = PACK_TYPE_STRING; + flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2; + break; case 'N': /* = "L>" */ dir = PACK_DIR_LONG; type = PACK_TYPE_INTEGER; @@ -1111,11 +1264,23 @@ alias: dir = PACK_DIR_NUL; type = PACK_TYPE_NONE; break; + case 'X': + dir = PACK_DIR_BACK; + type = PACK_TYPE_NONE; + break; + case '@': + dir = PACK_DIR_ABS; + type = PACK_TYPE_NONE; + break; case 'Z': dir = PACK_DIR_STR; type = PACK_TYPE_STRING; flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2 | PACK_FLAG_Z; break; + case 'p': case 'P': + case '%': + mrb_raisef(mrb, E_ARGUMENT_ERROR, "%c is not supported", (char)t); + break; default: dir = PACK_DIR_INVALID; type = PACK_TYPE_NONE; @@ -1124,19 +1289,21 @@ alias: /* read suffix [0-9*_!<>] */ while (tmpl->idx < tlen) { - ch = tptr[tmpl->idx++]; + ch = tptr[tmpl->idx]; if (ISDIGIT(ch)) { - count = ch - '0'; - while (tmpl->idx < tlen && ISDIGIT(tptr[tmpl->idx])) { - int ch = tptr[tmpl->idx++] - '0'; - if (count+ch > INT_MAX/10) { - mrb_raise(mrb, E_RUNTIME_ERROR, "too big template length"); - } - count = count * 10 + ch; + char *e; + mrb_int n = mrb_int_read(tptr+tmpl->idx, tptr+tlen, &e); + if (e == NULL || n > INT_MAX) { + mrb_raise(mrb, E_RUNTIME_ERROR, "too big template length"); } - continue; /* special case */ + count = (int)n; + tmpl->idx = e - tptr; + continue; } else if (ch == '*') { - count = -1; + if (type == PACK_TYPE_NONE) + count = 0; + else + count = -1; } else if (ch == '_' || ch == '!' || ch == '<' || ch == '>') { if (strchr("sSiIlLqQ", (int)t) == NULL) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "'%c' allowed only after types sSiIlLqQ", ch); @@ -1148,10 +1315,11 @@ alias: } else if (ch == '>') { flags |= PACK_FLAG_GT; } - } else { - tmpl->idx--; + } + else { break; } + tmpl->idx++; } if ((flags & PACK_FLAG_LT) || (!(flags & PACK_FLAG_GT) && littleendian)) { @@ -1173,7 +1341,9 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) struct tmpl tmpl; int count; unsigned int flags; - int dir, ridx, size, type; + enum pack_dir dir; + enum pack_type type; + int ridx, size; prepare_tmpl(mrb, &tmpl); @@ -1186,8 +1356,22 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) if (dir == PACK_DIR_INVALID) continue; else if (dir == PACK_DIR_NUL) { - ridx += pack_x(mrb, mrb_nil_value(), result, ridx, count, flags); - if (ridx < 0) goto overflow; + grow: + if (ridx > INT_MAX - count) goto overflow; + ridx += pack_nul(mrb, result, ridx, count); + continue; + } + else if (dir == PACK_DIR_BACK) { + check_x(mrb, ridx, count, 'X'); + ridx -= count; + continue; + } + else if (dir == PACK_DIR_ABS) { + count -= ridx; + if (count > 0) goto grow; + count = -count; + check_x(mrb, ridx, count, '@'); + ridx -= count; continue; } @@ -1200,12 +1384,12 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) o = mrb_ary_ref(mrb, ary, aidx); if (type == PACK_TYPE_INTEGER) { - o = mrb_to_int(mrb, o); + o = mrb_to_integer(mrb, o); } #ifndef MRB_NO_FLOAT else if (type == PACK_TYPE_FLOAT) { if (!mrb_float_p(o)) { - mrb_float f = mrb_to_flo(mrb, o); + mrb_float f = mrb_as_float(mrb, o); o = mrb_float_value(mrb, f); } } @@ -1218,25 +1402,31 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) switch (dir) { case PACK_DIR_CHAR: - ridx += pack_c(mrb, o, result, ridx, flags); + ridx += pack_char(mrb, o, result, ridx, flags); break; case PACK_DIR_SHORT: - ridx += pack_s(mrb, o, result, ridx, flags); + ridx += pack_short(mrb, o, result, ridx, flags); break; case PACK_DIR_LONG: - ridx += pack_l(mrb, o, result, ridx, flags); + ridx += pack_long(mrb, o, result, ridx, flags); break; case PACK_DIR_QUAD: - ridx += pack_q(mrb, o, result, ridx, flags); + ridx += pack_quad(mrb, o, result, ridx, flags); + break; + case PACK_DIR_BER: + ridx += pack_BER(mrb, o, result, ridx, flags); break; case PACK_DIR_BASE64: - ridx += pack_m(mrb, o, result, ridx, count, flags); + ridx += pack_base64(mrb, o, result, ridx, count); + break; + case PACK_DIR_QENC: + ridx += pack_qenc(mrb, o, result, ridx, count); break; case PACK_DIR_HEX: - ridx += pack_h(mrb, o, result, ridx, count, flags); + ridx += pack_hex(mrb, o, result, ridx, count, flags); break; case PACK_DIR_STR: - ridx += pack_a(mrb, o, result, ridx, count, flags); + ridx += pack_str(mrb, o, result, ridx, count, flags); break; #ifndef MRB_NO_FLOAT case PACK_DIR_DOUBLE: @@ -1252,7 +1442,7 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) default: break; } - if (dir == PACK_DIR_STR || dir == PACK_DIR_BASE64 || dir == PACK_DIR_HEX) { + if (flags & PACK_FLAG_COUNT2) { /* always consumes 1 entry */ aidx++; break; @@ -1278,7 +1468,9 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single) struct tmpl tmpl; int count; unsigned int flags; - int dir, size, type; + enum pack_dir dir; + enum pack_type type; + int size; int srcidx, srclen; const unsigned char *sptr; @@ -1294,24 +1486,39 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single) if (dir == PACK_DIR_INVALID) continue; else if (dir == PACK_DIR_NUL) { - srcidx += unpack_x(mrb, sptr, srclen - srcidx, result, count, flags); + check_x(mrb, srclen-srcidx, count, 'x'); + srcidx += count; + continue; + } + else if (dir == PACK_DIR_BACK) { + check_x(mrb, srcidx, count, 'X'); + srcidx -= count; + continue; + } + else if (dir == PACK_DIR_ABS) { + check_x(mrb, srclen, count, '@'); + srcidx = count; continue; } - if (flags & PACK_FLAG_COUNT2) { - sptr = (const unsigned char *)RSTRING_PTR(str) + srcidx; - switch (dir) { - case PACK_DIR_HEX: - srcidx += unpack_h(mrb, sptr, srclen - srcidx, result, count, flags); - break; - case PACK_DIR_STR: - srcidx += unpack_a(mrb, sptr, srclen - srcidx, result, count, flags); - break; - case PACK_DIR_BASE64: - srcidx += unpack_m(mrb, sptr, srclen - srcidx, result, flags); - break; - } + /* PACK_FLAG_COUNT2 directions */ + sptr = (const unsigned char *)RSTRING_PTR(str) + srcidx; + switch (dir) { + case PACK_DIR_HEX: + srcidx += unpack_hex(mrb, sptr, srclen - srcidx, result, count, flags); + continue; + case PACK_DIR_STR: + srcidx += unpack_str(mrb, sptr, srclen - srcidx, result, count, flags); continue; + case PACK_DIR_BASE64: + srcidx += unpack_base64(mrb, sptr, srclen - srcidx, result); + continue; + break; + case PACK_DIR_QENC: + srcidx += unpack_qenc(mrb, sptr, srclen - srcidx, result); + continue; + default: + break; } while (count != 0) { @@ -1325,16 +1532,19 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single) sptr = (const unsigned char*)RSTRING_PTR(str) + srcidx; switch (dir) { case PACK_DIR_CHAR: - srcidx += unpack_c(mrb, sptr, srclen - srcidx, result, flags); + srcidx += unpack_char(mrb, sptr, srclen - srcidx, result, flags); break; case PACK_DIR_SHORT: - srcidx += unpack_s(mrb, sptr, srclen - srcidx, result, flags); + srcidx += unpack_short(mrb, sptr, srclen - srcidx, result, flags); break; case PACK_DIR_LONG: - srcidx += unpack_l(mrb, sptr, srclen - srcidx, result, flags); + srcidx += unpack_long(mrb, sptr, srclen - srcidx, result, flags); break; case PACK_DIR_QUAD: - srcidx += unpack_q(mrb, sptr, srclen - srcidx, result, flags); + srcidx += unpack_quad(mrb, sptr, srclen - srcidx, result, flags); + break; + case PACK_DIR_BER: + srcidx += unpack_BER(mrb, sptr, srclen - srcidx, result, flags); break; #ifndef MRB_NO_FLOAT case PACK_DIR_FLOAT: |
