mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
support "q" and "Q". closes #7.
This commit is contained in:
@@ -31,6 +31,8 @@ rake ENABLE_GEMS="true"
|
||||
- m : base64 encoded string (see RFC 2045, count is width)
|
||||
- N : 32-bit unsigned, network (big-endian) byte order
|
||||
- n : 16-bit unsigned, network (big-endian) byte order
|
||||
- Q : 64-bit unsigned, native endian (`uint64_t`)
|
||||
- q : 64-bit signed, native endian (`int64_t`)
|
||||
- S : 16-bit unsigned, native endian (`uint16_t`)
|
||||
- s : 16-bit signed, native endian (`int16_t`)
|
||||
- V : 32-bit unsigned, VAX (little-endian) byte order
|
||||
|
||||
@@ -60,6 +60,14 @@ pptest [16909060], "\x01\x02\x03\x04", "L>"
|
||||
|
||||
packtest [-1], "\xff\xff\xff\xff", "L<"
|
||||
|
||||
pptest [1000000000], "\x00\x00\x00\x00\x3b\x9a\xca\x00", "q>"
|
||||
pptest [-1000000000], "\xff\xff\xff\xff\xc4\x65\x36\x00", "q>"
|
||||
|
||||
if (2**33).is_a? Fixnum
|
||||
pptest [81985529216486895], "\x01\x23\x45\x67\x89\xab\xcd\xef", "q>"
|
||||
pptest [-1167088121787636991], "\x01\x23\x45\x67\x89\xab\xcd\xef", "q<"
|
||||
end
|
||||
|
||||
pptest [16909060], "\x01\x02\x03\x04", "N"
|
||||
pptest [258], "\x01\x02", "n"
|
||||
pptest [32769], "\x80\x01", "n"
|
||||
|
||||
+86
-3
@@ -25,7 +25,7 @@ enum {
|
||||
PACK_DIR_CHAR, /* C */
|
||||
PACK_DIR_SHORT, /* S */
|
||||
PACK_DIR_LONG, /* L */
|
||||
//PACK_DIR_QUAD, /* Q */
|
||||
PACK_DIR_QUAD, /* Q */
|
||||
//PACK_DIR_INT, /* i */
|
||||
//PACK_DIR_VAX,
|
||||
//PACK_DIR_UTF8, /* U */
|
||||
@@ -231,6 +231,72 @@ unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int
|
||||
pack_q(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
|
||||
{
|
||||
unsigned long long n;
|
||||
str = str_len_ensure(mrb, str, sidx + 8);
|
||||
n = mrb_fixnum(o);
|
||||
if (flags & PACK_FLAG_LITTLEENDIAN) {
|
||||
RSTRING_PTR(str)[sidx+0] = n & 0xff;
|
||||
RSTRING_PTR(str)[sidx+1] = n >> 8;
|
||||
RSTRING_PTR(str)[sidx+2] = n >> 16;
|
||||
RSTRING_PTR(str)[sidx+3] = n >> 24;
|
||||
RSTRING_PTR(str)[sidx+4] = n >> 32;
|
||||
RSTRING_PTR(str)[sidx+5] = n >> 40;
|
||||
RSTRING_PTR(str)[sidx+6] = n >> 48;
|
||||
RSTRING_PTR(str)[sidx+7] = n >> 56;
|
||||
} else {
|
||||
RSTRING_PTR(str)[sidx+0] = n >> 56;
|
||||
RSTRING_PTR(str)[sidx+1] = n >> 48;
|
||||
RSTRING_PTR(str)[sidx+2] = n >> 40;
|
||||
RSTRING_PTR(str)[sidx+3] = n >> 32;
|
||||
RSTRING_PTR(str)[sidx+4] = n >> 24;
|
||||
RSTRING_PTR(str)[sidx+5] = n >> 16;
|
||||
RSTRING_PTR(str)[sidx+6] = n >> 8;
|
||||
RSTRING_PTR(str)[sidx+7] = n & 0xff;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
|
||||
{
|
||||
char msg[60];
|
||||
uint64_t ull;
|
||||
int i, pos, step;
|
||||
mrb_int n;
|
||||
|
||||
if (flags & PACK_FLAG_LITTLEENDIAN) {
|
||||
pos = 7;
|
||||
step = -1;
|
||||
} else {
|
||||
pos = 0;
|
||||
step = 1;
|
||||
}
|
||||
ull = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ull = ull * 256 + (uint64_t)src[pos];
|
||||
pos += step;
|
||||
}
|
||||
if (flags & PACK_FLAG_SIGNED) {
|
||||
int64_t sll = ull;
|
||||
if (!FIXABLE(sll)) {
|
||||
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %lld", (long long)sll);
|
||||
mrb_raise(mrb, E_RANGE_ERROR, msg);
|
||||
}
|
||||
n = sll;
|
||||
} else {
|
||||
if (!POSFIXABLE(ull)) {
|
||||
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %llu", (unsigned long long)ull);
|
||||
mrb_raise(mrb, E_RANGE_ERROR, msg);
|
||||
}
|
||||
n = ull;
|
||||
}
|
||||
mrb_ary_push(mrb, ary, mrb_fixnum_value(n));
|
||||
return 8;
|
||||
}
|
||||
|
||||
static int
|
||||
pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
|
||||
{
|
||||
@@ -775,6 +841,17 @@ alias:
|
||||
size = 2;
|
||||
flags |= PACK_FLAG_GT;
|
||||
break;
|
||||
case 'Q':
|
||||
dir = PACK_DIR_QUAD;
|
||||
type = PACK_TYPE_INTEGER;
|
||||
size = 8;
|
||||
break;
|
||||
case 'q':
|
||||
dir = PACK_DIR_QUAD;
|
||||
type = PACK_TYPE_INTEGER;
|
||||
size = 8;
|
||||
flags |= PACK_FLAG_SIGNED;
|
||||
break;
|
||||
case 'S':
|
||||
dir = PACK_DIR_SHORT;
|
||||
type = PACK_TYPE_INTEGER;
|
||||
@@ -821,9 +898,9 @@ alias:
|
||||
} else if (ch == '*') {
|
||||
count = -1;
|
||||
} else if (ch == '_' || ch == '!' || ch == '<' || ch == '>') {
|
||||
if (strchr("sSiIlL", t) == NULL) {
|
||||
if (strchr("sSiIlLqQ", t) == NULL) {
|
||||
char ch_str = ch;
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "'%S' allowed only after types sSiIlL", mrb_str_new(mrb, &ch_str, 1));
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "'%S' allowed only after types sSiIlLqQ", mrb_str_new(mrb, &ch_str, 1));
|
||||
}
|
||||
if (ch == '_' || ch == '!') {
|
||||
flags |= PACK_FLAG_s;
|
||||
@@ -901,6 +978,9 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
|
||||
case PACK_DIR_LONG:
|
||||
ridx += pack_l(mrb, o, result, ridx, flags);
|
||||
break;
|
||||
case PACK_DIR_QUAD:
|
||||
ridx += pack_q(mrb, o, result, ridx, flags);
|
||||
break;
|
||||
case PACK_DIR_BASE64:
|
||||
ridx += pack_m(mrb, o, result, ridx, count, flags);
|
||||
break;
|
||||
@@ -987,6 +1067,9 @@ mrb_pack_unpack(mrb_state *mrb, mrb_value str)
|
||||
case PACK_DIR_LONG:
|
||||
srcidx += unpack_l(mrb, sptr, srclen - srcidx, result, flags);
|
||||
break;
|
||||
case PACK_DIR_QUAD:
|
||||
srcidx += unpack_q(mrb, sptr, srclen - srcidx, result, flags);
|
||||
break;
|
||||
case PACK_DIR_BASE64:
|
||||
srcidx += unpack_m(mrb, sptr, srclen - srcidx, result, flags);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user