diff options
author | Jean Boussier <[email protected]> | 2021-10-18 16:23:54 +0200 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2021-10-26 22:27:30 +0200 |
commit | e5319dc9856298f38aa9cdc6ed55e39ad0e8e070 () | |
tree | 7c1d685ae65979ce2ae3bee4ccce54507d3f49f8 | |
parent | 717ab0bb2ee63dfe76076e0c9f91fbac3a0de4fd (diff) |
pack.c: add an offset argument to unpack and unpack1
[Feature #18254] This is useful to avoid repeteadly copying strings when parsing binary formats
-rw-r--r-- | pack.c | 19 | ||||
-rw-r--r-- | pack.rb | 31 | ||||
-rw-r--r-- | spec/ruby/core/string/unpack/shared/basic.rb | 20 | ||||
-rw-r--r-- | spec/ruby/core/string/unpack1_spec.rb | 20 | ||||
-rw-r--r-- | test/ruby/test_pack.rb | 26 |
5 files changed, 103 insertions, 13 deletions
@@ -944,7 +944,7 @@ hex2num(char c) #define UNPACK_1 2 static VALUE -pack_unpack_internal(VALUE str, VALUE fmt, int mode) { #define hexdigits ruby_hexdigits char *s, *send; @@ -973,8 +973,15 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) StringValue(str); StringValue(fmt); s = RSTRING_PTR(str); - send = s + RSTRING_LEN(str); p = RSTRING_PTR(fmt); pend = p + RSTRING_LEN(fmt); @@ -1614,16 +1621,16 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode) } static VALUE -pack_unpack(rb_execution_context_t *ec, VALUE str, VALUE fmt) { int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY; - return pack_unpack_internal(str, fmt, mode); } static VALUE -pack_unpack1(rb_execution_context_t *ec, VALUE str, VALUE fmt) { - return pack_unpack_internal(str, fmt, UNPACK_1); } int @@ -148,10 +148,11 @@ end class String # call-seq: # str.unpack(format) -> anArray # # Decodes <i>str</i> (which may contain binary data) according to the - # format string, returning an array of each value extracted. The - # format string consists of a sequence of single-character directives, # summarized in the table at the end of this entry. # Each directive may be followed # by a number, indicating the number of times to repeat with this @@ -161,7 +162,15 @@ class String # exclamation mark (``<code>!</code>'') to use the underlying # platform's native size for the specified type; otherwise, it uses a # platform-independent consistent size. Spaces are ignored in the - # format string. See also String#unpack1, Array#pack. # # "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "] # "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"] @@ -263,15 +272,23 @@ class String # * J, J! j, and j! are available since Ruby 2.3. # * Q_, Q!, q_, and q! are available since Ruby 2.1. # * I!<, i!<, I!>, and i!> are available since Ruby 1.9.3. - def unpack(fmt) - Primitive.pack_unpack(fmt) end # call-seq: # str.unpack1(format) -> obj # # Decodes <i>str</i> (which may contain binary data) according to the # format string, returning the first value extracted. # See also String#unpack, Array#pack. # # Contrast with String#unpack: @@ -287,7 +304,7 @@ class String # # Thus unpack1 is convenient, makes clear the intention and signals # the expected return value to those reading the code. - def unpack1(fmt) - Primitive.pack_unpack1(fmt) end end @@ -16,6 +16,12 @@ describe :string_unpack_basic, shared: true do it "raises a TypeError when passed an Integer" do -> { "abc".unpack(1) }.should raise_error(TypeError) end end describe :string_unpack_no_platform, shared: true do @@ -26,4 +32,18 @@ describe :string_unpack_no_platform, shared: true do it "raises an ArgumentError when the format modifier is '!'" do -> { "abcdefgh".unpack(unpack_format("!")) }.should raise_error(ArgumentError) end end @@ -7,4 +7,24 @@ describe "String#unpack1" do "aG9nZWZ1Z2E=".unpack1("m").should == "hogefuga" "A".unpack1("B*").should == "01000001" end end @@ -869,4 +869,30 @@ EXPECTED assert_equal "hogefuga", "aG9nZWZ1Z2E=".unpack1("m") assert_equal "01000001", "A".unpack1("B*") end end |