From 583c8e89153dc5fab189d24b6688c31a70a63dbb Mon Sep 17 00:00:00 2001 From: akr Date: Tue, 2 Apr 2013 11:28:57 +0000 Subject: * 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40067 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- pack.c | 62 +++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 17 deletions(-) (limited to 'pack.c') diff --git a/pack.c b/pack.c index fabbb7ddb0..bc4e1ed548 100644 --- a/pack.c +++ b/pack.c @@ -20,7 +20,23 @@ ((__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 @@ # 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 char*,long*); * 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) } { - static const char natstr[] = "sSiIlL"; - static const char endstr[] = "sSiIlLqQ"; - modifiers: switch (*p) { case '_': @@ -680,13 +705,13 @@ pack_pack(VALUE ary, VALUE fmt) 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 len, VALUE str) * 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) 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) 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; -- cgit v1.2.3