mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #5 from take-cheeze/float
Add full support of float templates.
This commit is contained in:
@@ -14,7 +14,12 @@ rake ENABLE_GEMS="true"
|
||||
## support template string
|
||||
- C : 8-bit unsigned (unsigned char)
|
||||
- c : 8-bit signed (signed char)
|
||||
- E : 64-bit double, little endian
|
||||
- D, d: 64-bit float, native format
|
||||
- F, f: 32-bit float, native format
|
||||
- E : 64-bit float, little endian byte order
|
||||
- e : 32-bit float, little endian byte order
|
||||
- G : 64-bit float, network (big-endian) byte order
|
||||
- g : 32-bit float, network (big-endian) byte order
|
||||
- S : 16-bit unsigned, native endian (uint16_t)
|
||||
- s : 16-bit signed, native endian (int16_t)
|
||||
- L : 32-bit unsigned, native endian (uint32_t)
|
||||
|
||||
+144
-7
@@ -31,7 +31,7 @@ enum {
|
||||
//PACK_DIR_UTF8, /* U */
|
||||
//PACK_DIR_BER,
|
||||
PACK_DIR_DOUBLE, /* E */
|
||||
//PACK_DIR_FLOAT, /* f */
|
||||
PACK_DIR_FLOAT, /* f */
|
||||
PACK_DIR_STR, /* A */
|
||||
PACK_DIR_HEX, /* h */
|
||||
PACK_DIR_BASE64, /* m */
|
||||
@@ -234,17 +234,115 @@ pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned i
|
||||
str = str_len_ensure(mrb, str, sidx + 8);
|
||||
d = mrb_float(o);
|
||||
|
||||
if (flags & PACK_FLAG_LITTLEENDIAN) {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
#error unsupported
|
||||
for (i = 0; i < 8; ++i) {
|
||||
RSTRING_PTR(str)[sidx + i] = buffer[8 - i - 1];
|
||||
}
|
||||
#else
|
||||
for(i = 0; i < 8; i++){
|
||||
RSTRING_PTR(str)[sidx+i] = buffer[i];
|
||||
}
|
||||
memcpy(RSTRING_PTR(str) + sidx, buffer, 8);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
memcpy(RSTRING_PTR(str) + sidx, buffer, 8);
|
||||
#else
|
||||
for (i = 0; i < 8; ++i) {
|
||||
RSTRING_PTR(str)[sidx + i] = buffer[8 - i - 1];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_double(mrb_state *mrb, const unsigned char * src, int srclen, mrb_value ary, unsigned int flags)
|
||||
{
|
||||
int i;
|
||||
double d;
|
||||
uint8_t *buffer = (uint8_t *)&d;
|
||||
|
||||
if (flags & PACK_FLAG_LITTLEENDIAN) {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
for (i = 0; i < 8; ++i) {
|
||||
buffer[8 - i - 1] = src[i];
|
||||
}
|
||||
#else
|
||||
memcpy(buffer, src, 8);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
memcpy(buffer, src, 8);
|
||||
#else
|
||||
for (i = 0; i < 8; ++i) {
|
||||
buffer[8 - i - 1] = src[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
mrb_ary_push(mrb, ary, mrb_float_value(mrb, d));
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
static int
|
||||
pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
uint8_t *buffer = (uint8_t *)&f;
|
||||
str = str_len_ensure(mrb, str, sidx + 4);
|
||||
f = mrb_float(o);
|
||||
|
||||
if (flags & PACK_FLAG_LITTLEENDIAN) {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
for (i = 0; i < 4; ++i) {
|
||||
RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1];
|
||||
}
|
||||
#else
|
||||
memcpy(RSTRING_PTR(str) + sidx, buffer, 4);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
memcpy(RSTRING_PTR(str) + sidx, buffer, 4);
|
||||
#else
|
||||
for (i = 0; i < 4; ++i) {
|
||||
RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_float(mrb_state *mrb, const unsigned char * src, int srclen, mrb_value ary, unsigned int flags)
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
uint8_t *buffer = (uint8_t *)&f;
|
||||
|
||||
if (flags & PACK_FLAG_LITTLEENDIAN) {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
for (i = 0; i < 4; ++i) {
|
||||
buffer[4 - i - 1] = src[i];
|
||||
}
|
||||
#else
|
||||
memcpy(buffer, src, 4);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
memcpy(buffer, src, 4);
|
||||
#else
|
||||
for (i = 0; i < 4; ++i) {
|
||||
buffer[4 - i - 1] = src[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
mrb_ary_push(mrb, ary, mrb_float_value(mrb, f));
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int
|
||||
pack_a(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags)
|
||||
{
|
||||
@@ -574,12 +672,42 @@ read_tmpl(mrb_state *mrb, struct tmpl *tmpl, int *dirp, int *typep, int *sizep,
|
||||
size = 1;
|
||||
flags |= PACK_FLAG_SIGNED;
|
||||
break;
|
||||
case 'E':
|
||||
case 'D': case 'd':
|
||||
dir = PACK_DIR_DOUBLE;
|
||||
type = PACK_TYPE_FLOAT;
|
||||
size = 8;
|
||||
flags |= PACK_FLAG_SIGNED;
|
||||
break;
|
||||
case 'F': case 'f':
|
||||
dir = PACK_DIR_FLOAT;
|
||||
type = PACK_TYPE_FLOAT;
|
||||
size = 4;
|
||||
flags |= PACK_FLAG_SIGNED;
|
||||
break;
|
||||
case 'E':
|
||||
dir = PACK_DIR_DOUBLE;
|
||||
type = PACK_TYPE_FLOAT;
|
||||
size = 8;
|
||||
flags |= PACK_FLAG_SIGNED | PACK_FLAG_LT;
|
||||
break;
|
||||
case 'e':
|
||||
dir = PACK_DIR_FLOAT;
|
||||
type = PACK_TYPE_FLOAT;
|
||||
size = 4;
|
||||
flags |= PACK_FLAG_SIGNED | PACK_FLAG_LT;
|
||||
break;
|
||||
case 'G':
|
||||
dir = PACK_DIR_DOUBLE;
|
||||
type = PACK_TYPE_FLOAT;
|
||||
size = 8;
|
||||
flags |= PACK_FLAG_SIGNED | PACK_FLAG_GT;
|
||||
break;
|
||||
case 'g':
|
||||
dir = PACK_DIR_FLOAT;
|
||||
type = PACK_TYPE_FLOAT;
|
||||
size = 4;
|
||||
flags |= PACK_FLAG_SIGNED | PACK_FLAG_GT;
|
||||
break;
|
||||
case 'H':
|
||||
dir = PACK_DIR_HEX;
|
||||
type = PACK_TYPE_STRING;
|
||||
@@ -756,6 +884,9 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
|
||||
case PACK_DIR_DOUBLE:
|
||||
ridx += pack_double(mrb, o, result, ridx, flags);
|
||||
break;
|
||||
case PACK_DIR_FLOAT:
|
||||
ridx += pack_float(mrb, o, result, ridx, flags);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -826,6 +957,12 @@ mrb_pack_unpack(mrb_state *mrb, mrb_value str)
|
||||
case PACK_DIR_BASE64:
|
||||
srcidx += unpack_m(mrb, sptr, srclen - srcidx, result, flags);
|
||||
break;
|
||||
case PACK_DIR_FLOAT:
|
||||
srcidx += unpack_float(mrb, sptr, srclen - srcidx, result, flags);
|
||||
break;
|
||||
case PACK_DIR_DOUBLE:
|
||||
srcidx += unpack_double(mrb, sptr, srclen - srcidx, result, flags);
|
||||
break;
|
||||
}
|
||||
if (count > 0) {
|
||||
count--;
|
||||
|
||||
@@ -88,3 +88,36 @@ end
|
||||
assert('issue #1') do
|
||||
[1, 2].pack("nn") == "\000\001\000\002"
|
||||
end
|
||||
|
||||
def assert_pack tmpl, packed, unpacked
|
||||
assert_equal packed, unpacked.pack(tmpl)
|
||||
assert_equal unpacked, packed.unpack(tmpl)
|
||||
end
|
||||
|
||||
PACK_IS_LITTLE_ENDIAN = "\x01\00".unpack('S')[0] == 0x01
|
||||
|
||||
assert 'pack float' do
|
||||
assert_pack 'e', "\x00\x00@@", [3.0]
|
||||
assert_pack 'g', "@@\x00\x00", [3.0]
|
||||
|
||||
if PACK_IS_LITTLE_ENDIAN
|
||||
assert_pack 'f', "\x00\x00@@", [3.0]
|
||||
assert_pack 'F', "\x00\x00@@", [3.0]
|
||||
else
|
||||
assert_pack 'f', "@@\x00\x00", [3.0]
|
||||
assert_pack 'F', "@@\x00\x00", [3.0]
|
||||
end
|
||||
end
|
||||
|
||||
assert 'pack double' do
|
||||
assert_pack 'E', "\x00\x00\x00\x00\x00\x00\b@", [3.0]
|
||||
assert_pack 'G', "@\b\x00\x00\x00\x00\x00\x00", [3.0]
|
||||
|
||||
if PACK_IS_LITTLE_ENDIAN
|
||||
assert_pack 'd', "\x00\x00\x00\x00\x00\x00\b@", [3.0]
|
||||
assert_pack 'D', "\x00\x00\x00\x00\x00\x00\b@", [3.0]
|
||||
else
|
||||
assert_pack 'd', "@\b\x00\x00\x00\x00\x00\x00", [3.0]
|
||||
assert_pack 'D', "@\b\x00\x00\x00\x00\x00\x00", [3.0]
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user