From f4f968241b1518175192c4f5302c36d420497fa5 Mon Sep 17 00:00:00 2001 From: take_cheeze Date: Fri, 13 Jun 2014 17:56:36 +0900 Subject: Add support of little endian float. --- src/pack.c | 31 ++++++++++++++++++++++++++++++- test/pack.rb | 4 ++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/pack.c b/src/pack.c index 3e56454f2..f8cdcbaad 100644 --- a/src/pack.c +++ b/src/pack.c @@ -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 */ @@ -245,6 +245,26 @@ pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned i 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); + +#ifdef MRB_ENDIAN_BIG + #error unsupported +#else + for(i = 0; i < 4; i++){ + RSTRING_PTR(str)[sidx+i] = buffer[i]; + } +#endif + + return 4; +} + static int pack_a(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags) { @@ -580,6 +600,12 @@ read_tmpl(mrb_state *mrb, struct tmpl *tmpl, int *dirp, int *typep, int *sizep, size = 8; flags |= PACK_FLAG_SIGNED; break; + case 'e': + dir = PACK_DIR_FLOAT; + type = PACK_TYPE_FLOAT; + size = 4; + flags |= PACK_FLAG_SIGNED; + break; case 'H': dir = PACK_DIR_HEX; type = PACK_TYPE_STRING; @@ -756,6 +782,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; } diff --git a/test/pack.rb b/test/pack.rb index 7789fb446..2d754dfc1 100644 --- a/test/pack.rb +++ b/test/pack.rb @@ -88,3 +88,7 @@ end 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') +end -- cgit v1.2.3 From 7dc2b4f59f2b9019089d8a934c96148b1cdfd3b5 Mon Sep 17 00:00:00 2001 From: take_cheeze Date: Fri, 13 Jun 2014 18:22:56 +0900 Subject: Implement g/f/F/G/d/D packing. --- src/pack.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- test/pack.rb | 18 +++++++++++++++ 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/pack.c b/src/pack.c index f8cdcbaad..93fd3f16b 100644 --- a/src/pack.c +++ b/src/pack.c @@ -234,14 +234,26 @@ 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_LT) { #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 if (flags & PACK_FLAG_GT) { +#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 - + } else { + memcpy(RSTRING_PTR(str) + sidx, buffer, 8); + } + return 8; } @@ -254,14 +266,26 @@ pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned in str = str_len_ensure(mrb, str, sidx + 4); f = mrb_float(o); + if (flags & PACK_FLAG_LT) { #ifdef MRB_ENDIAN_BIG - #error unsupported + for (i = 0; i < 4; ++i) { + RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1]; + } #else - for(i = 0; i < 4; i++){ - RSTRING_PTR(str)[sidx+i] = buffer[i]; - } + memcpy(RSTRING_PTR(str) + sidx, buffer, 4); +#endif + } else if (flags & PACK_FLAG_GT) { +#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 - + } else { + memcpy(RSTRING_PTR(str) + sidx, buffer, 4); + } + return 4; } @@ -594,17 +618,41 @@ 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 = 8; + 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; + 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; diff --git a/test/pack.rb b/test/pack.rb index 2d754dfc1..02265f126 100644 --- a/test/pack.rb +++ b/test/pack.rb @@ -91,4 +91,22 @@ end assert 'pack float' do assert_equal "\x00\x00@@", [3.0].pack('e') + assert_equal "@@\x00\x00", [3.0].pack('g') + + native = [3.0].pack 'f' + assert_true native == "\x00\x00@@" or native == "@@\x00\x00" + + native = [3.0].pack 'F' + assert_true native == "\x00\x00@@" or native == "@@\x00\x00" +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" end -- cgit v1.2.3 From 514450e891e015efa9fd01f13a46863d4f118c13 Mon Sep 17 00:00:00 2001 From: take_cheeze Date: Fri, 13 Jun 2014 20:19:47 +0900 Subject: Use PACK_FLAG_LITTLEENDIAN. --- src/pack.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/pack.c b/src/pack.c index 93fd3f16b..6b211c961 100644 --- a/src/pack.c +++ b/src/pack.c @@ -234,7 +234,7 @@ 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_LT) { + if (flags & PACK_FLAG_LITTLEENDIAN) { #ifdef MRB_ENDIAN_BIG for (i = 0; i < 8; ++i) { RSTRING_PTR(str)[sidx + i] = buffer[8 - i - 1]; @@ -242,7 +242,7 @@ pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned i #else memcpy(RSTRING_PTR(str) + sidx, buffer, 8); #endif - } else if (flags & PACK_FLAG_GT) { + } else { #ifdef MRB_ENDIAN_BIG memcpy(RSTRING_PTR(str) + sidx, buffer, 8); #else @@ -250,8 +250,6 @@ pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned i RSTRING_PTR(str)[sidx + i] = buffer[8 - i - 1]; } #endif - } else { - memcpy(RSTRING_PTR(str) + sidx, buffer, 8); } return 8; @@ -266,7 +264,7 @@ pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned in str = str_len_ensure(mrb, str, sidx + 4); f = mrb_float(o); - if (flags & PACK_FLAG_LT) { + if (flags & PACK_FLAG_LITTLEENDIAN) { #ifdef MRB_ENDIAN_BIG for (i = 0; i < 4; ++i) { RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1]; @@ -274,7 +272,7 @@ pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned in #else memcpy(RSTRING_PTR(str) + sidx, buffer, 4); #endif - } else if (flags & PACK_FLAG_GT) { + } else { #ifdef MRB_ENDIAN_BIG memcpy(RSTRING_PTR(str) + sidx, buffer, 4); #else @@ -282,8 +280,6 @@ pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned in RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1]; } #endif - } else { - memcpy(RSTRING_PTR(str) + sidx, buffer, 4); } return 4; -- cgit v1.2.3 From 8f4b7ac15c77f24952364f1b3b1ac42e2e52ebd5 Mon Sep 17 00:00:00 2001 From: take_cheeze Date: Sat, 14 Jun 2014 13:16:13 +0900 Subject: Support float/double unpacking. --- src/pack.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- test/pack.rb | 41 +++++++++++++++++++++++-------------- 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 @@ -255,6 +255,35 @@ pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned i 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) { @@ -285,6 +314,35 @@ pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned in 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) { @@ -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 -- cgit v1.2.3 From 7b2611ea28aad709d16f6196baabbdbdbd806087 Mon Sep 17 00:00:00 2001 From: take_cheeze Date: Sat, 14 Jun 2014 13:20:37 +0900 Subject: Update supported template list. --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e11a61a5..fb2ce15ec 100644 --- a/README.md +++ b/README.md @@ -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) -- cgit v1.2.3