ruby-changes:28015
From: akr <ko1@a...>
Date: Tue, 2 Apr 2013 20:29:07 +0900 (JST)
Subject: [ruby-changes:28015] akr:r40067 (trunk): * pack.c: Support Q! and q! for long long.
akr 2013-04-02 20:28:57 +0900 (Tue, 02 Apr 2013) New Revision: 40067 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40067 Log: * pack.c: Support Q! and q! for long long. (natstr): Moved to toplevel. Add q and Q if there is long long type. (endstr): Moved to toplevel. (NATINT_PACK): Consider long long. (NATINT_LEN_Q): New macro. (pack_pack): Support Q! and q!. (pack_unpack): Ditto. Modified files: trunk/ChangeLog trunk/NEWS trunk/pack.c trunk/test/ruby/test_pack.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 40066) +++ ChangeLog (revision 40067) @@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Apr 2 20:24:52 2013 Tanaka Akira <akr@f...> + + * pack.c: Support Q! and q! for long long. + (natstr): Moved to toplevel. Add q and Q if there is long long type. + (endstr): Moved to toplevel. + (NATINT_PACK): Consider long long. + (NATINT_LEN_Q): New macro. + (pack_pack): Support Q! and q!. + (pack_unpack): Ditto. + Tue Apr 2 19:24:26 2013 Tanaka Akira <akr@f...> * ext/-test-/num2int/num2int.c: Define utility methods Index: pack.c =================================================================== --- pack.c (revision 40066) +++ pack.c (revision 40067) @@ -20,7 +20,23 @@ https://github.com/ruby/ruby/blob/trunk/pack.c#L20 ((__GNUC__ > (major)) || \ (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \ (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel)))) -#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 + +/* + * It is intentional that the condition for natstr is HAVE_LONG_LONG + * instead of LONG_LONG. + * This means q! and Q! means always the standard long long type and + * causes ArgumentError for platforms which has no long long type, + * even if the platform has an implementation specific 64bit type. + * This behavior is consistent with the document of pack/unpack. + */ +#ifdef HAVE_LONG_LONG +static const char natstr[] = "sSiIlLqQ"; +#else +static const char natstr[] = "sSiIlL"; +#endif +static const char endstr[] = "sSiIlLqQ"; + +#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 || (defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG != 8) # define NATINT_PACK #endif @@ -52,6 +68,12 @@ https://github.com/ruby/ruby/blob/trunk/pack.c#L68 # define NATINT_LEN(type,len) ((int)sizeof(type)) #endif +#ifdef HAVE_LONG_LONG +# define NATINT_LEN_Q NATINT_LEN(long long, 8) +#else +# define NATINT_LEN_Q 8 +#endif + #if SIZEOF_LONG == 8 # define INT64toNUM(x) LONG2NUM(x) # define UINT64toNUM(x) ULONG2NUM(x) @@ -303,24 +325,30 @@ static unsigned long utf8_to_uv(const ch https://github.com/ruby/ruby/blob/trunk/pack.c#L325 * S_, S! | Integer | unsigned short, native endian * I, I_, I! | Integer | unsigned int, native endian * L_, L! | Integer | unsigned long, native endian + * Q_, Q! | Integer | unsigned long long, native endian (ArgumentError + * | | if the platform has no long long type.) + * | | (Q_ and Q! is available since Ruby 2.1.) * | | * s_, s! | Integer | signed short, native endian * i, i_, i! | Integer | signed int, native endian * l_, l! | Integer | signed long, native endian + * q_, q! | Integer | signed long long, native endian (ArgumentError + * | | if the platform has no long long type.) + * | | (q_ and q! is available since Ruby 2.1.) * | | * S> L> Q> | Integer | same as the directives without ">" except * s> l> q> | | big endian * S!> I!> | | (available since Ruby 1.9.3) - * L!> | | "S>" is same as "n" + * L!> Q!> | | "S>" is same as "n" * s!> i!> | | "L>" is same as "N" - * l!> | | + * l!> q!> | | * | | * S< L< Q< | Integer | same as the directives without "<" except * s< l< q< | | little endian * S!< I!< | | (available since Ruby 1.9.3) - * L!< | | "S<" is same as "v" + * L!< Q!< | | "S<" is same as "v" * s!< i!< | | "L<" is same as "V" - * l!< | | + * l!< q!< | | * | | * n | Integer | 16-bit unsigned, network (big-endian) byte order * N | Integer | 32-bit unsigned, network (big-endian) byte order @@ -412,9 +440,6 @@ pack_pack(VALUE ary, VALUE fmt) https://github.com/ruby/ruby/blob/trunk/pack.c#L440 } { - static const char natstr[] = "sSiIlL"; - static const char endstr[] = "sSiIlLqQ"; - modifiers: switch (*p) { case '_': @@ -680,13 +705,13 @@ pack_pack(VALUE ary, VALUE fmt) https://github.com/ruby/ruby/blob/trunk/pack.c#L705 bigendian_p = BIGENDIAN_P(); goto pack_integer; - case 'q': /* signed quad (64bit) int */ - integer_size = 8; + case 'q': /* signed long long or int64_t */ + integer_size = NATINT_LEN_Q; bigendian_p = BIGENDIAN_P(); goto pack_integer; - case 'Q': /* unsigned quad (64bit) int */ - integer_size = 8; + case 'Q': /* unsigned long long or uint64_t */ + integer_size = NATINT_LEN_Q; bigendian_p = BIGENDIAN_P(); goto pack_integer; @@ -1249,10 +1274,16 @@ infected_str_new(const char *ptr, long l https://github.com/ruby/ruby/blob/trunk/pack.c#L1274 * S_, S! | Integer | unsigned short, native endian * I, I_, I! | Integer | unsigned int, native endian * L_, L! | Integer | unsigned long, native endian + * Q_, Q! | Integer | unsigned long long, native endian (ArgumentError + * | | if the platform has no long long type.) + * | | (Q_ and Q! is available since Ruby 2.1.) * | | * s_, s! | Integer | signed short, native endian * i, i_, i! | Integer | signed int, native endian * l_, l! | Integer | signed long, native endian + * q_, q! | Integer | signed long long, native endian (ArgumentError + * | | if the platform has no long long type.) + * | | (q_ and q! is available since Ruby 2.1.) * | | * S> L> Q> | Integer | same as the directives without ">" except * s> l> q> | | big endian @@ -1361,9 +1392,6 @@ pack_unpack(VALUE str, VALUE fmt) https://github.com/ruby/ruby/blob/trunk/pack.c#L1392 star = 0; { - static const char natstr[] = "sSiIlL"; - static const char endstr[] = "sSiIlLqQ"; - modifiers: switch (*p) { case '_': @@ -1590,13 +1618,13 @@ pack_unpack(VALUE str, VALUE fmt) https://github.com/ruby/ruby/blob/trunk/pack.c#L1618 case 'q': signed_p = 1; - integer_size = 8; + integer_size = NATINT_LEN_Q; bigendian_p = BIGENDIAN_P(); goto unpack_integer; case 'Q': signed_p = 0; - integer_size = 8; + integer_size = NATINT_LEN_Q; bigendian_p = BIGENDIAN_P(); goto unpack_integer; Index: NEWS =================================================================== --- NEWS (revision 40066) +++ NEWS (revision 40067) @@ -22,6 +22,9 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L22 * misc * Mutex#owned? is no longer experimental. +* pack/unpack (Array/String) + * Q! and q! directives for long long type if platform has the type. + === Core classes compatibility issues (excluding feature bug fixes) * Module#ancestors Index: test/ruby/test_pack.rb =================================================================== --- test/ruby/test_pack.rb (revision 40066) +++ test/ruby/test_pack.rb (revision 40067) @@ -403,8 +403,15 @@ class TestPack < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_pack.rb#L403 assert_equal([578437695752307201, -506097522914230529], s2.unpack("q*")) assert_equal([578437695752307201, 17940646550795321087], s1.unpack("Q*")) + s1 = [578437695752307201, -506097522914230529].pack("q!*") + s2 = [578437695752307201, 17940646550795321087].pack("Q!*") + assert_equal([578437695752307201, -506097522914230529], s2.unpack("q!*")) + assert_equal([578437695752307201, 17940646550795321087], s1.unpack("Q!*")) + assert_equal(8, [1].pack("q").bytesize) assert_equal(8, [1].pack("Q").bytesize) + assert_operator(8, :<=, [1].pack("q!").bytesize) + assert_operator(8, :<=, [1].pack("Q!").bytesize) end def test_pack_unpack_nN -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/