summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-pack/src/pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-pack/src/pack.c')
-rw-r--r--mrbgems/mruby-pack/src/pack.c394
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: