summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authortake_cheeze <[email protected]>2014-06-14 13:16:13 +0900
committertake_cheeze <[email protected]>2014-06-14 13:25:00 +0900
commit8f4b7ac15c77f24952364f1b3b1ac42e2e52ebd5 (patch)
treed5a6c984a017c0cbe8c3e28d59a6a72a2cfe28c2
parent514450e891e015efa9fd01f13a46863d4f118c13 (diff)
downloadmruby-8f4b7ac15c77f24952364f1b3b1ac42e2e52ebd5.tar.gz
mruby-8f4b7ac15c77f24952364f1b3b1ac42e2e52ebd5.zip
Support float/double unpacking.
-rw-r--r--src/pack.c66
-rw-r--r--test/pack.rb41
2 files changed, 91 insertions, 16 deletions
diff --git a/src/pack.c b/src/pack.c
index 6b211c961..69cf740ff 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -256,6 +256,35 @@ pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned i
}
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;
@@ -286,6 +315,35 @@ pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned in
}
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)
{
int copylen, slen, padlen;
@@ -623,7 +681,7 @@ read_tmpl(mrb_state *mrb, struct tmpl *tmpl, int *dirp, int *typep, int *sizep,
case 'F': case 'f':
dir = PACK_DIR_FLOAT;
type = PACK_TYPE_FLOAT;
- size = 8;
+ size = 4;
flags |= PACK_FLAG_SIGNED;
break;
case 'E':
@@ -899,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--;
diff --git a/test/pack.rb b/test/pack.rb
index 02265f126..c7899e2d7 100644
--- a/test/pack.rb
+++ b/test/pack.rb
@@ -89,24 +89,35 @@ assert('issue #1') do
[1, 2].pack("nn") == "\000\001\000\002"
end
-assert 'pack float' do
- assert_equal "\x00\x00@@", [3.0].pack('e')
- assert_equal "@@\x00\x00", [3.0].pack('g')
+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
- native = [3.0].pack 'f'
- assert_true native == "\x00\x00@@" or native == "@@\x00\x00"
+assert 'pack float' do
+ assert_pack 'e', "\x00\x00@@", [3.0]
+ assert_pack 'g', "@@\x00\x00", [3.0]
- native = [3.0].pack 'F'
- assert_true native == "\x00\x00@@" or native == "@@\x00\x00"
+ 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_equal "\x00\x00\x00\x00\x00\x00\b@", [3.0].pack('E')
- assert_equal "@\b\x00\x00\x00\x00\x00\x00", [3.0].pack('G')
-
- native = [3.0].pack 'd'
- assert_true native == "\x00\x00\x00\x00\x00\x00\b@" or native == "@\b\x00\x00\x00\x00\x00\x00"
-
- native = [3.0].pack 'D'
- assert_true native == "\x00\x00\x00\x00\x00\x00\b@" or native == "@\b\x00\x00\x00\x00\x00\x00"
+ 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