summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/pack.c72
-rw-r--r--test/pack.rb18
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