[前][次][番号順一覧][スレッド一覧]

ruby-changes:16253

From: shyouhei <ko1@a...>
Date: Tue, 8 Jun 2010 17:43:05 +0900 (JST)
Subject: [ruby-changes:16253] Ruby:r28220 (ruby_1_8_7): merge revision(s) 27721:27725,27738:27740:

shyouhei	2010-06-08 17:42:55 +0900 (Tue, 08 Jun 2010)

  New Revision: 28220

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=28220

  Log:
    merge revision(s) 27721:27725,27738:27740:
    * pack.c: backport integer pack/unpack from 1.9 for [ruby-core:21937].
    * configure.in: backport RUBY_DEFINT and fixed size integer checks.
    * ruby.h: include stdint.h if available.
    * bignum.c (rb_big_pack): defined..
      (rb_big_unpack): defined.
    * intern.h (rb_big_pack): declared.
      (rb_big_unpack): declared.
    * pack.c (pack_pack): call rb_quad_pack to preserve RangeError.

  Modified files:
    branches/ruby_1_8_7/ChangeLog
    branches/ruby_1_8_7/bignum.c
    branches/ruby_1_8_7/configure.in
    branches/ruby_1_8_7/intern.h
    branches/ruby_1_8_7/pack.c
    branches/ruby_1_8_7/ruby.h
    branches/ruby_1_8_7/test/ruby/test_pack.rb
    branches/ruby_1_8_7/version.h

Index: ruby_1_8_7/intern.h
===================================================================
--- ruby_1_8_7/intern.h	(revision 28219)
+++ ruby_1_8_7/intern.h	(revision 28220)
@@ -83,6 +83,8 @@
 #endif  /* HAVE_LONG_LONG */
 void rb_quad_pack _((char*,VALUE));
 VALUE rb_quad_unpack _((const char*,int));
+void rb_big_pack(VALUE val, unsigned long *buf, long num_longs);
+VALUE rb_big_unpack(unsigned long *buf, long num_longs);
 VALUE rb_dbl2big _((double));
 double rb_big2dbl _((VALUE));
 VALUE rb_big_plus _((VALUE, VALUE));
Index: ruby_1_8_7/configure.in
===================================================================
--- ruby_1_8_7/configure.in	(revision 28219)
+++ ruby_1_8_7/configure.in	(revision 28220)
@@ -544,6 +544,43 @@
 AC_STRUCT_ST_BLOCKS
 AC_STRUCT_ST_RDEV
 
+dnl RUBY_DEFINT TYPENAME, SIZE, [SIGNED-OR-UNSIGNED], [INCLUDES = DEFAULT-INCLUDES]
+AC_DEFUN([RUBY_DEFINT], [dnl
+AC_CACHE_CHECK([for $1], [rb_cv_type_$1],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT([$4])
+typedef $1 t; int s = sizeof(t) == 42;])],
+   [rb_cv_type_$1=yes],
+   [AS_CASE([m4_bmatch([$2], [^[1-9][0-9]*$], $2, [$ac_cv_sizeof_]AS_TR_SH($2))],
+    ["1"], [ rb_cv_type_$1="m4_if([$3], [], [signed ], [$3 ])char"],
+    ["$ac_cv_sizeof_short"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])short"],
+    ["$ac_cv_sizeof_int"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])int"],
+    ["$ac_cv_sizeof_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long"],
+    ["$ac_cv_sizeof_long_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long long"],
+    ["$ac_cv_sizeof___int64"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int64"],
+    [ rb_cv_type_$1=no])])])
+if test "${rb_cv_type_$1}" != no; then
+    AC_DEFINE([HAVE_]AS_TR_CPP($1), 1)
+    if test "${rb_cv_type_$1}" = yes; then
+        m4_bmatch([$2], [^[1-9][0-9]*$], [AC_CHECK_SIZEOF([$1], 0, [AC_INCLUDES_DEFAULT([$4])])],
+                        [RUBY_CHECK_SIZEOF([$1], [$2], [], [AC_INCLUDES_DEFAULT([$4])])])
+    else
+        AC_DEFINE_UNQUOTED($1, [$rb_cv_type_$1])
+        AC_DEFINE_UNQUOTED([SIZEOF_]AS_TR_CPP($1), [SIZEOF_]AS_TR_CPP([$rb_cv_type_$1]))
+    fi
+fi
+])
+
+RUBY_DEFINT(int8_t, 1)
+RUBY_DEFINT(uint8_t, 1, unsigned)
+RUBY_DEFINT(int16_t, 2)
+RUBY_DEFINT(uint16_t, 2, unsigned)
+RUBY_DEFINT(int32_t, 4)
+RUBY_DEFINT(uint32_t, 4, unsigned)
+RUBY_DEFINT(int64_t, 8)
+RUBY_DEFINT(uint64_t, 8, unsigned)
+RUBY_DEFINT(int128_t, 16)
+RUBY_DEFINT(uint128_t, 16, unsigned)
+
 dnl Checks for library functions.
 AC_TYPE_GETGROUPS
 AC_TYPE_SIGNAL
Index: ruby_1_8_7/ChangeLog
===================================================================
--- ruby_1_8_7/ChangeLog	(revision 28219)
+++ ruby_1_8_7/ChangeLog	(revision 28220)
@@ -1,3 +1,21 @@
+Tue Jun  8 17:32:37 2010  Tanaka Akira  <akr@f...>
+
+	* pack.c (pack_pack): call rb_quad_pack to preserve RangeError.
+
+Tue Jun  8 17:32:37 2010  Tanaka Akira  <akr@f...>
+
+	* pack.c: backport integer pack/unpack from 1.9 for [ruby-core:21937].
+
+	* configure.in: backport RUBY_DEFINT and fixed size integer checks.
+
+	* ruby.h: include stdint.h if available.
+
+	* bignum.c (rb_big_pack): defined..
+	  (rb_big_unpack): defined.
+
+	* intern.h (rb_big_pack): declared.
+	  (rb_big_unpack): declared.
+
 Tue Jun  8 16:52:35 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* regex.c (read_special): get rid of overrun.
Index: ruby_1_8_7/version.h
===================================================================
--- ruby_1_8_7/version.h	(revision 28219)
+++ ruby_1_8_7/version.h	(revision 28220)
@@ -2,7 +2,7 @@
 #define RUBY_RELEASE_DATE "2010-06-08"
 #define RUBY_VERSION_CODE 187
 #define RUBY_RELEASE_CODE 20100608
-#define RUBY_PATCHLEVEL 284
+#define RUBY_PATCHLEVEL 285
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
Index: ruby_1_8_7/pack.c
===================================================================
--- ruby_1_8_7/pack.c	(revision 28219)
+++ ruby_1_8_7/pack.c	(revision 28220)
@@ -14,6 +14,12 @@
 #include <sys/types.h>
 #include <ctype.h>
 
+#define GCC_VERSION_SINCE(major, minor, patchlevel) \
+  (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
+   ((__GNUC__ > (major)) ||  \
+    (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
+    (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))
+
 #define SIZE16 2
 #define SIZE32 4
 
@@ -21,34 +27,41 @@
 # define NATINT_PACK
 #endif
 
+#ifdef DYNAMIC_ENDIAN
+ /* for universal binary of NEXTSTEP and MacOS X */
+ /* useless since autoconf 2.63? */
+ static int
+ is_bigendian(void)
+ {
+     static int init = 0;
+     static int endian_value;
+     char *p;
+
+     if (init) return endian_value;
+     init = 1;
+     p = (char*)&init;
+     return endian_value = p[0]?0:1;
+ }
+# define BIGENDIAN_P() (is_bigendian())
+#elif defined(WORDS_BIGENDIAN)
+# define BIGENDIAN_P() 1
+#else
+# define BIGENDIAN_P() 0
+#endif
+
 #ifdef NATINT_PACK
-# define OFF16B(p) ((char*)(p) + (natint?0:(sizeof(short) - SIZE16)))
-# define OFF32B(p) ((char*)(p) + (natint?0:(sizeof(long) - SIZE32)))
-# define NATINT_LEN(type,len) (natint?sizeof(type):(len))
-# ifdef WORDS_BIGENDIAN
-#   define OFF16(p) OFF16B(p)
-#   define OFF32(p) OFF32B(p)
-# endif
-# define NATINT_HTOVS(x) (natint?htovs(x):htov16(x))
-# define NATINT_HTOVL(x) (natint?htovl(x):htov32(x))
-# define NATINT_HTONS(x) (natint?htons(x):hton16(x))
-# define NATINT_HTONL(x) (natint?htonl(x):hton32(x))
+# define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len))
 #else
-# define NATINT_LEN(type,len) sizeof(type)
-# define NATINT_HTOVS(x) htovs(x)
-# define NATINT_HTOVL(x) htovl(x)
-# define NATINT_HTONS(x) htons(x)
-# define NATINT_HTONL(x) htonl(x)
+# define NATINT_LEN(type,len) ((int)sizeof(type))
 #endif
 
-#ifndef OFF16
-# define OFF16(p) (char*)(p)
-# define OFF32(p) (char*)(p)
+#if SIZEOF_LONG == 8
+# define INT64toNUM(x) LONG2NUM(x)
+# define UINT64toNUM(x) ULONG2NUM(x)
+#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
+# define INT64toNUM(x) LL2NUM(x)
+# define UINT64toNUM(x) ULL2NUM(x)
 #endif
-#ifndef OFF16B
-# define OFF16B(p) (char*)(p)
-# define OFF32B(p) (char*)(p)
-#endif
 
 #define define_swapx(x, xtype)		\
 static xtype				\
@@ -73,262 +86,185 @@
     return r;				\
 }
 
+#if GCC_VERSION_SINCE(4,3,0)
+# define swap32(x) __builtin_bswap32(x)
+# define swap64(x) __builtin_bswap64(x)
+#endif
+
 #ifndef swap16
-#define swap16(x)	((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+# define swap16(x)	((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
 #endif
-#if SIZEOF_SHORT == 2
-#define swaps(x)	swap16(x)
-#else
-#if SIZEOF_SHORT == 4
-#define swaps(x)	((((x)&0xFF)<<24)	\
+
+#ifndef swap32
+# define swap32(x)      ((((x)&0xFF)<<24)       \
 			|(((x)>>24)&0xFF)	\
 			|(((x)&0x0000FF00)<<8)	\
 			|(((x)&0x00FF0000)>>8)	)
+#endif
+
+#ifndef swap64
+# ifdef HAVE_INT64_T
+#  define byte_in_64bit(n) ((uint64_t)0xff << (n))
+#  define swap64(x)       ((((x)&byte_in_64bit(0))<<56)         \
+                           |(((x)>>56)&0xFF)                    \
+                           |(((x)&byte_in_64bit(8))<<40)        \
+                           |(((x)&byte_in_64bit(48))>>40)       \
+                           |(((x)&byte_in_64bit(16))<<24)       \
+                           |(((x)&byte_in_64bit(40))>>24)       \
+                           |(((x)&byte_in_64bit(24))<<8)        \
+                           |(((x)&byte_in_64bit(32))>>8))
+# endif
+#endif
+
+#if SIZEOF_SHORT == 2
+# define swaps(x)       swap16(x)
+#elif SIZEOF_SHORT == 4
+# define swaps(x)       swap32(x)
 #else
-define_swapx(s,short)
+  define_swapx(s,short)
 #endif
+
+#if SIZEOF_INT == 2
+# define swapi(x)       swap16(x)
+#elif SIZEOF_INT == 4
+# define swapi(x)       swap32(x)
+#else
+  define_swapx(i,int)
 #endif
 
-#ifndef swap32
-#define swap32(x)	((((x)&0xFF)<<24)	\
-			|(((x)>>24)&0xFF)	\
-			|(((x)&0x0000FF00)<<8)	\
-			|(((x)&0x00FF0000)>>8)	)
-#endif
 #if SIZEOF_LONG == 4
-#define swapl(x)	swap32(x)
+# define swapl(x)       swap32(x)
+#elif SIZEOF_LONG == 8
+# define swapl(x)       swap64(x)
 #else
-#if SIZEOF_LONG == 8
-#define swapl(x)        ((((x)&0x00000000000000FF)<<56)	\
-			|(((x)&0xFF00000000000000)>>56)	\
-			|(((x)&0x000000000000FF00)<<40)	\
-			|(((x)&0x00FF000000000000)>>40)	\
-			|(((x)&0x0000000000FF0000)<<24)	\
-			|(((x)&0x0000FF0000000000)>>24)	\
-			|(((x)&0x00000000FF000000)<<8)	\
-			|(((x)&0x000000FF00000000)>>8))
-#else
-define_swapx(l,long)
+  define_swapx(l,long)
 #endif
+
+#ifdef HAVE_LONG_LONG
+# if SIZEOF_LONG_LONG == 8
+#  define swapll(x)        swap64(x)
+# else
+   define_swapx(ll,LONG_LONG)
+# endif
 #endif
 
 #if SIZEOF_FLOAT == 4
-#if SIZEOF_LONG == 4	/* SIZEOF_FLOAT == 4 == SIZEOF_LONG */
-#define swapf(x)	swapl(x)
-#define FLOAT_SWAPPER	unsigned long
-#else
-#if SIZEOF_SHORT == 4	/* SIZEOF_FLOAT == 4 == SIZEOF_SHORT */
-#define swapf(x)	swaps(x)
-#define FLOAT_SWAPPER	unsigned short
-#else	/* SIZEOF_FLOAT == 4 but undivide by known size of int */
-define_swapx(f,float)
-#endif	/* #if SIZEOF_SHORT == 4 */
-#endif	/* #if SIZEOF_LONG == 4 */
+# ifdef HAVE_UINT32_T
+#  define swapf(x)     swap32(x)
+#  define FLOAT_SWAPPER        uint32_t
+# else /* SIZEOF_FLOAT == 4 but undivide by known size of int */
+   define_swapx(f,float)
+# endif
 #else	/* SIZEOF_FLOAT != 4 */
-define_swapx(f,float)
+  define_swapx(f,float)
 #endif	/* #if SIZEOF_FLOAT == 4 */
 
 #if SIZEOF_DOUBLE == 8
-#if SIZEOF_LONG == 8	/* SIZEOF_DOUBLE == 8 == SIZEOF_LONG */
-#define swapd(x)	swapl(x)
-#define DOUBLE_SWAPPER	unsigned long
-#else
-#if SIZEOF_LONG == 4	/* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
-static double
-swapd(d)
-    const double d;
-{
-    double dtmp = d;
-    unsigned long utmp[2];
-    unsigned long utmp0;
+# ifdef HAVE_UINT64_T  /* SIZEOF_DOUBLE == 8 == SIZEOF_UINT64_T */
+#  define swapd(x)     swap64(x)
+#  define DOUBLE_SWAPPER       uint64_t
+# else
+#  if SIZEOF_LONG == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
+    static double
+    swapd(const double d)
+    {
+        double dtmp = d;
+        unsigned long utmp[2];
+        unsigned long utmp0;
 
-    utmp[0] = 0; utmp[1] = 0;
-    memcpy(utmp,&dtmp,sizeof(double));
-    utmp0 = utmp[0];
-    utmp[0] = swapl(utmp[1]);
-    utmp[1] = swapl(utmp0);
-    memcpy(&dtmp,utmp,sizeof(double));
-    return dtmp;
-}
-#else
-#if SIZEOF_SHORT == 4	/* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
-static double
-swapd(d)
-    const double d;
-{
-    double dtmp = d;
-    unsigned short utmp[2];
-    unsigned short utmp0;
+        utmp[0] = 0; utmp[1] = 0;
+        memcpy(utmp,&dtmp,sizeof(double));
+        utmp0 = utmp[0];
+        utmp[0] = swapl(utmp[1]);
+        utmp[1] = swapl(utmp0);
+        memcpy(&dtmp,utmp,sizeof(double));
+        return dtmp;
+    }
+#  elif SIZEOF_SHORT == 4      /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
+    static double
+    swapd(const double d)
+    {
+        double dtmp = d;
+        unsigned short utmp[2];
+        unsigned short utmp0;
 
-    utmp[0] = 0; utmp[1] = 0;
-    memcpy(utmp,&dtmp,sizeof(double));
-    utmp0 = utmp[0];
-    utmp[0] = swaps(utmp[1]);
-    utmp[1] = swaps(utmp0);
-    memcpy(&dtmp,utmp,sizeof(double));
-    return dtmp;
-}
-#else	/* SIZEOF_DOUBLE == 8 but undivied by known size of int */
-define_swapx(d, double)
-#endif	/* #if SIZEOF_SHORT == 4 */
-#endif	/* #if SIZEOF_LONG == 4 */
-#endif	/* #if SIZEOF_LONG == 8 */
+        utmp[0] = 0; utmp[1] = 0;
+        memcpy(utmp,&dtmp,sizeof(double));
+        utmp0 = utmp[0];
+        utmp[0] = swaps(utmp[1]);
+        utmp[1] = swaps(utmp0);
+        memcpy(&dtmp,utmp,sizeof(double));
+        return dtmp;
+    }
+#  else        /* SIZEOF_DOUBLE == 8 but undivide by known size of int */
+    define_swapx(d, double)
+#  endif
+# endif        /* #if SIZEOF_LONG == 8 */
 #else	/* SIZEOF_DOUBLE != 8 */
-define_swapx(d, double)
+  define_swapx(d, double)
 #endif	/* #if SIZEOF_DOUBLE == 8 */
 
 #undef define_swapx
 
-#ifdef DYNAMIC_ENDIAN
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-static int
-endian()
-{
-    static int init = 0;
-    static int endian_value;
-    char *p;
+#define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x))
+#define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x))
+#define rb_htonf(x) (BIGENDIAN_P()?(x):swapf(x))
+#define rb_htond(x) (BIGENDIAN_P()?(x):swapd(x))
+#define rb_htovf(x) (BIGENDIAN_P()?swapf(x):(x))
+#define rb_htovd(x) (BIGENDIAN_P()?swapd(x):(x))
+#define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x))
+#define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x))
 
-    if (init) return endian_value;
-    init = 1;
-    p = (char*)&init;
-    return endian_value = p[0]?0:1;
-}
-
-#define ntohs(x) (endian()?(x):swaps(x))
-#define ntohl(x) (endian()?(x):swapl(x))
-#define ntohf(x) (endian()?(x):swapf(x))
-#define ntohd(x) (endian()?(x):swapd(x))
-#define htons(x) (endian()?(x):swaps(x))
-#define htonl(x) (endian()?(x):swapl(x))
-#define htonf(x) (endian()?(x):swapf(x))
-#define htond(x) (endian()?(x):swapd(x))
-#define htovs(x) (endian()?swaps(x):(x))
-#define htovl(x) (endian()?swapl(x):(x))
-#define htovf(x) (endian()?swapf(x):(x))
-#define htovd(x) (endian()?swapd(x):(x))
-#define vtohs(x) (endian()?swaps(x):(x))
-#define vtohl(x) (endian()?swapl(x):(x))
-#define vtohf(x) (endian()?swapf(x):(x))
-#define vtohd(x) (endian()?swapd(x):(x))
-# ifdef NATINT_PACK
-#define htov16(x) (endian()?swap16(x):(x))
-#define htov32(x) (endian()?swap32(x):(x))
-#define hton16(x) (endian()?(x):swap16(x))
-#define hton32(x) (endian()?(x):swap32(x))
-# endif
-#else
-#ifdef WORDS_BIGENDIAN
-#ifndef ntohs
-#define ntohs(x) (x)
-#define ntohl(x) (x)
-#define htons(x) (x)
-#define htonl(x) (x)
-#endif
-#define ntohf(x) (x)
-#define ntohd(x) (x)
-#define htonf(x) (x)
-#define htond(x) (x)
-#define htovs(x) swaps(x)
-#define htovl(x) swapl(x)
-#define htovf(x) swapf(x)
-#define htovd(x) swapd(x)
-#define vtohs(x) swaps(x)
-#define vtohl(x) swapl(x)
-#define vtohf(x) swapf(x)
-#define vtohd(x) swapd(x)
-# ifdef NATINT_PACK
-#define htov16(x) swap16(x)
-#define htov32(x) swap32(x)
-#define hton16(x) (x)
-#define hton32(x) (x)
-# endif
-#else /* LITTLE ENDIAN */
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-#define ntohs(x) swaps(x)
-#define ntohl(x) swapl(x)
-#define htons(x) swaps(x)
-#define htonl(x) swapl(x)
-#define ntohf(x) swapf(x)
-#define ntohd(x) swapd(x)
-#define htonf(x) swapf(x)
-#define htond(x) swapd(x)
-#define htovs(x) (x)
-#define htovl(x) (x)
-#define htovf(x) (x)
-#define htovd(x) (x)
-#define vtohs(x) (x)
-#define vtohl(x) (x)
-#define vtohf(x) (x)
-#define vtohd(x) (x)
-# ifdef NATINT_PACK
-#define htov16(x) (x)
-#define htov32(x) (x)
-#define hton16(x) swap16(x)
-#define hton32(x) swap32(x)
-# endif
-#endif
-#endif
-
 #ifdef FLOAT_SWAPPER
 #define FLOAT_CONVWITH(y)	FLOAT_SWAPPER y;
 #define HTONF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = htonf((FLOAT_SWAPPER)y),	\
+			 y = rb_htonf((FLOAT_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(float)),	\
 			 x)
 #define HTOVF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = htovf((FLOAT_SWAPPER)y),	\
+			 y = rb_htovf((FLOAT_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(float)),	\
 			 x)
 #define NTOHF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = ntohf((FLOAT_SWAPPER)y),	\
+			 y = rb_ntohf((FLOAT_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(float)),	\
 			 x)
 #define VTOHF(x,y)	(memcpy(&y,&x,sizeof(float)),	\
-			 y = vtohf((FLOAT_SWAPPER)y),	\
+			 y = rb_vtohf((FLOAT_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(float)),	\
 			 x)
 #else
 #define FLOAT_CONVWITH(y)
-#define HTONF(x,y)	htonf(x)
-#define HTOVF(x,y)	htovf(x)
-#define NTOHF(x,y)	ntohf(x)
-#define VTOHF(x,y)	vtohf(x)
+# define HTONF(x,y)    rb_htonf(x)
+# define HTOVF(x,y)    rb_htovf(x)
+# define NTOHF(x,y)    rb_ntohf(x)
+# define VTOHF(x,y)    rb_vtohf(x)
 #endif
 
 #ifdef DOUBLE_SWAPPER
 #define DOUBLE_CONVWITH(y)	DOUBLE_SWAPPER y;
 #define HTOND(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = htond((DOUBLE_SWAPPER)y),	\
+			 y = rb_htond((DOUBLE_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(double)),	\
 			 x)
 #define HTOVD(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = htovd((DOUBLE_SWAPPER)y),	\
+			 y = rb_htovd((DOUBLE_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(double)),	\
 			 x)
 #define NTOHD(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = ntohd((DOUBLE_SWAPPER)y),	\
+			 y = rb_ntohd((DOUBLE_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(double)),	\
 			 x)
 #define VTOHD(x,y)	(memcpy(&y,&x,sizeof(double)),	\
-			 y = vtohd((DOUBLE_SWAPPER)y),	\
+			 y = rb_vtohd((DOUBLE_SWAPPER)y),	\
 			 memcpy(&x,&y,sizeof(double)),	\
 			 x)
 #else
 #define DOUBLE_CONVWITH(y)
-#define HTOND(x,y)	htond(x)
-#define HTOVD(x,y)	htovd(x)
-#define NTOHD(x,y)	ntohd(x)
-#define VTOHD(x,y)	vtohd(x)
+# define HTOND(x,y)    rb_htond(x)
+# define HTOVD(x,y)    rb_htovd(x)
+# define NTOHD(x,y)    rb_ntohd(x)
+# define VTOHD(x,y)    rb_vtohd(x)
 #endif
 
 unsigned long rb_big2ulong_pack _((VALUE x));
@@ -359,11 +295,10 @@
 # define EXTEND16(x) do { if (!natint) {(x) = (short)(((1<<15)-1-(x))^~(~0<<15));}} while(0)
 #endif
 
-#ifdef HAVE_LONG_LONG
-# define QUAD_SIZE sizeof(LONG_LONG)
-#else
-# define QUAD_SIZE 8
-#endif
+#define QUAD_SIZE 8
+#define MAX_INTEGER_PACK_SIZE 8
+/* #define FORCE_BIG_PACK */
+
 static const char toofew[] = "too few arguments";
 
 static void encodes _((VALUE,const char*,long,int));
@@ -397,44 +332,67 @@
  *     
  *  Directives for +pack+.
  *
- *   Directive    Meaning
- *   ---------------------------------------------------------------
- *       @     |  Moves to absolute position
- *       A     |  ASCII string (space padded, count is width)
- *       a     |  ASCII string (null padded, count is width)
- *       B     |  Bit string (descending bit order)
- *       b     |  Bit string (ascending bit order)
- *       C     |  Unsigned char
- *       c     |  Char
- *       D, d  |  Double-precision float, native format
- *       E     |  Double-precision float, little-endian byte order
- *       e     |  Single-precision float, little-endian byte order
- *       F, f  |  Single-precision float, native format
- *       G     |  Double-precision float, network (big-endian) byte order
- *       g     |  Single-precision float, network (big-endian) byte order
- *       H     |  Hex string (high nibble first)
- *       h     |  Hex string (low nibble first)
- *       I     |  Unsigned integer
- *       i     |  Integer
- *       L     |  Unsigned long
- *       l     |  Long
- *       M     |  Quoted printable, MIME encoding (see RFC2045)
- *       m     |  Base64 encoded string
- *       N     |  Long, network (big-endian) byte order
- *       n     |  Short, network (big-endian) byte-order
- *       P     |  Pointer to a structure (fixed-length string)
- *       p     |  Pointer to a null-terminated string
- *       Q, q  |  64-bit number
- *       S     |  Unsigned short
- *       s     |  Short
- *       U     |  UTF-8
- *       u     |  UU-encoded string
- *       V     |  Long, little-endian byte order
- *       v     |  Short, little-endian byte order
- *       w     |  BER-compressed integer\fnm
- *       X     |  Back up a byte
- *       x     |  Null byte
- *       Z     |  Same as ``a'', except that null is added with *
+ *   Integer   | Array   |
+ *   Directive | Element | Meaning
+ *   ------------------------------------------------------------------------
+ *      C      | Integer | 8-bit unsigned integer (unsigned char)
+ *      S      | Integer | 16-bit unsigned integer, native endian (uint16_t)
+ *      L      | Integer | 32-bit unsigned integer, native endian (uint32_t)
+ *      Q      | Integer | 64-bit unsigned integer, native endian (uint64_t)
+ *             |         |
+ *      c      | Integer | 8-bit signed integer (char)
+ *      s      | Integer | 16-bit signed integer, native endian (int16_t)
+ *      l      | Integer | 32-bit signed integer, native endian (int32_t)
+ *      q      | Integer | 64-bit signed integer, native endian (int64_t)
+ *             |         | 
+ *      S_     | Integer | unsigned short, native endian
+ *      I, I_  | Integer | unsigned int, native endian
+ *      L_     | Integer | unsigned long, native endian
+ *             |         |
+ *      s_     | Integer | signed short, native endian
+ *      i, i_  | Integer | signed int, native endian
+ *      l_     | Integer | signed long, native endian
+ *             |         |
+ *      n      | Integer | 16-bit unsigned integer, network (big-endian) byte order
+ *      N      | Integer | 32-bit unsigned integer, network (big-endian) byte order
+ *      v      | Integer | 16-bit unsigned integer, VAX (little-endian) byte order
+ *      V      | Integer | 32-bit unsigned integer, VAX (little-endian) byte order
+ *             |         |
+ *      U      | Integer | UTF-8 character
+ *      w      | Integer | BER-compressed integer
+ *                        
+ *   Float     |         |
+ *   Directive |         | Meaning
+ *   ------------------------------------------------------------------------
+ *      D, d   | Float   | double-precision float, native format
+ *      F, f   | Float   | single-precision float, native format
+ *      E      | Float   | double-precision float, little-endian byte order
+ *      e      | Float   | single-precision float, little-endian byte order
+ *      G      | Float   | double-precision float, network (big-endian) byte order
+ *      g      | Float   | single-precision float, network (big-endian) byte order
+ *                        
+ *   String    |         |
+ *   Directive |         | Meaning
+ *   ------------------------------------------------------------------------
+ *      A      | String  | arbitrary binary string (space padded, count is width)
+ *      a      | String  | arbitrary binary string (null padded, count is width)
+ *      Z      | String  | same as ``a'', except that null is added with *
+ *      B      | String  | bit string (MSB first)
+ *      b      | String  | bit string (LSB first)
+ *      H      | String  | hex string (high nibble first)
+ *      h      | String  | hex string (low nibble first)
+ *      u      | String  | UU-encoded string
+ *      M      | String  | quoted printable, MIME encoding (see RFC2045)
+ *      m      | String  | base64 encoded string (see RFC 2045, count is width)
+ *      P      | String  | pointer to a structure (fixed-length string)
+ *      p      | String  | pointer to a null-terminated string
+ *                        
+ *   Misc.     |         |
+ *   Directive |         | Meaning
+ *   ------------------------------------------------------------------------
+ *      @      | ---     | moves to absolute position
+ *      X      | ---     | back up a byte
+ *      x      | ---     | null byte
  */
 
 static VALUE
@@ -451,6 +409,7 @@
 #ifdef NATINT_PACK
     int natint;		/* native integer */
 #endif
+    int signed_p, integer_size, bigendian_p;
 
     StringValue(fmt);
     p = RSTRING(fmt)->ptr;
@@ -682,93 +641,164 @@
 	    break;
 
 	  case 's':		/* signed short */
+            signed_p = 1;
+            integer_size = NATINT_LEN(short, 2);
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
+
 	  case 'S':		/* unsigned short */
-	    while (len-- > 0) {
-		short s;
+            signed_p = 0;
+            integer_size = NATINT_LEN(short, 2);
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-		from = NEXTFROM;
-		s = num2i32(from);
-		rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
-	    }
-	    break;
+	  case 'i':		/* signed int */
+            signed_p = 1;
+            integer_size = (int)sizeof(int);
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-	  case 'i':		/* signed int */
 	  case 'I':		/* unsigned int */
-	    while (len-- > 0) {
-		long i;
+            signed_p = 0;
+            integer_size = (int)sizeof(int);
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-		from = NEXTFROM;
-		i = num2i32(from);
-		rb_str_buf_cat(res, OFF32(&i), NATINT_LEN(int,4));
-	    }
-	    break;
+	  case 'l':		/* signed long */
+            signed_p = 1;
+            integer_size = NATINT_LEN(long, 4);
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-	  case 'l':		/* signed long */
 	  case 'L':		/* unsigned long */
-	    while (len-- > 0) {
-		long l;
+            signed_p = 0;
+            integer_size = NATINT_LEN(long, 4);
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-		from = NEXTFROM;
-		l = num2i32(from);
-		rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
-	    }
-	    break;
+	  case 'q':		/* signed quad (64bit) int */
+            signed_p = 1;
+            integer_size = 8;
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-	  case 'q':		/* signed quad (64bit) int */
 	  case 'Q':		/* unsigned quad (64bit) int */
-	    while (len-- > 0) {
-		char tmp[QUAD_SIZE];
+            signed_p = 0;
+            integer_size = 8;
+            bigendian_p = BIGENDIAN_P();
+            goto pack_integer;
 
-		from = NEXTFROM;
-		rb_quad_pack(tmp, from);
-		rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE);
-	    }
-	    break;
-
 	  case 'n':		/* unsigned short (network byte-order)  */
-	    while (len-- > 0) {
-		unsigned short s;
+            signed_p = 0;
+            integer_size = 2;
+            bigendian_p = 1;
+            goto pack_integer;
 
-		from = NEXTFROM;
-		s = num2i32(from);
-		s = NATINT_HTONS(s);
-		rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
-	    }
-	    break;
-
 	  case 'N':		/* unsigned long (network byte-order) */
-	    while (len-- > 0) {
-		unsigned long l;
+            signed_p = 0;
+            integer_size = 4;
+            bigendian_p = 1;
+            goto pack_integer;
 
-		from = NEXTFROM;
-		l = num2i32(from);
-		l = NATINT_HTONL(l);
-		rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
-	    }
-	    break;
-
 	  case 'v':		/* unsigned short (VAX byte-order) */
-	    while (len-- > 0) {
-		unsigned short s;
+            signed_p = 0;
+            integer_size = 2;
+            bigendian_p = 0;
+            goto pack_integer;
 
-		from = NEXTFROM;
-		s = num2i32(from);
-		s = NATINT_HTOVS(s);
-		rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
-	    }
-	    break;
-
 	  case 'V':		/* unsigned long (VAX byte-order) */
-	    while (len-- > 0) {
-		unsigned long l;
+            signed_p = 0;
+            integer_size = 4;
+            bigendian_p = 0;
+            goto pack_integer;
 
-		from = NEXTFROM;
-		l = num2i32(from);
-		l = NATINT_HTOVL(l);
-		rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
-	    }
-	    break;
+          pack_integer:
+            switch (integer_size) {
+#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
+              case SIZEOF_INT16_T:
+                while (len-- > 0) {
+                    union {
+                        int16_t i;
+                        char a[sizeof(int16_t)];
+                    } v;
 
+                    from = NEXTFROM;
+                    v.i = (int16_t)num2i32(from);
+                    if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
+                    rb_str_buf_cat(res, v.a, sizeof(int16_t));
+                }
+                break;
+#endif
+
+#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
+              case SIZEOF_INT32_T:
+                while (len-- > 0) {
+                    union {
+                        int32_t i;
+                        char a[sizeof(int32_t)];
+                    } v;
+
+                    from = NEXTFROM;
+                    v.i = (int32_t)num2i32(from);
+                    if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
+                    rb_str_buf_cat(res, v.a, sizeof(int32_t));
+                }
+                break;
+#endif
+
+#if defined(HAVE_INT64_T) && SIZEOF_LONG == SIZEOF_INT64_T && !defined(FORCE_BIG_PACK)
+              case SIZEOF_INT64_T:
+                while (len-- > 0) {
+                    union {
+                        int64_t i;
+                        char a[sizeof(int64_t)];
+                    } v;
+
+                    from = NEXTFROM;
+                    v.i = num2i32(from); /* can return 64bit value if SIZEOF_LONG == SIZEOF_INT64_T */
+                    if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
+                    rb_str_buf_cat(res, v.a, sizeof(int64_t));
+                }
+                break;
+#endif
+
+              default:
+                if (integer_size > MAX_INTEGER_PACK_SIZE)
+                    rb_bug("unexpected intger size for pack: %d", integer_size);
+                while (len-- > 0) {
+                    union {
+                        unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG];
+                        char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG*SIZEOF_LONG];
+                    } v;
+                    int num_longs = (integer_size+SIZEOF_LONG-1)/SIZEOF_LONG;
+                    int i;
+
+                    from = NEXTFROM;
+                    from = rb_to_int(from);
+                    if (integer_size == QUAD_SIZE)
+                        rb_quad_pack(v.a, from); /* RangeError compatibility for Ruby 1.8. */
+                    rb_big_pack(from, v.i, num_longs);
+                    if (bigendian_p) {
+                        for (i = 0; i < num_longs/2; i++) {
+                            unsigned long t = v.i[i];
+                            v.i[i] = v.i[num_longs-1-i];
+                            v.i[num_longs-1-i] = t;
+                        }
+                    }
+                    if (bigendian_p != BIGENDIAN_P()) {
+                        for (i = 0; i < num_longs; i++)
+                            v.i[i] = swapl(v.i[i]);
+                    }
+                    rb_str_buf_cat(res,
+                                   bigendian_p ?
+                                     v.a + sizeof(long)*num_longs - integer_size :
+                                     v.a,
+                                   integer_size);
+                }
+                break;
+            }
+            break;
+
 	  case 'f':		/* single precision float in native format */
 	  case 'F':		/* ditto */
 	    while (len-- > 0) {
@@ -1132,27 +1162,20 @@
 }
 
 #define PACK_LENGTH_ADJUST_SIZE(sz) do {	\
-    tmp = 0;					\
-    if (len > (send-s)/sz) {			\
+    tmp_len = 0;				\
+    if (len > (long)((send-s)/sz)) {		\
         if (!star) {				\
-	    tmp = len-(send-s)/sz;		\
+	    tmp_len = len-(send-s)/sz;		\
         }					\
 	len = (send-s)/sz;			\
     }						\
 } while (0)
 
-#ifdef NATINT_PACK
-#define PACK_LENGTH_ADJUST(type,sz) do {	\
-    int t__len = NATINT_LEN(type,(sz));		\
-    PACK_LENGTH_ADJUST_SIZE(t__len);		\
+#define PACK_ITEM_ADJUST() do { \
+    if (tmp_len > 0) \
+        rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
 } while (0)
-#else
-#define PACK_LENGTH_ADJUST(type,sz) 		\
-    PACK_LENGTH_ADJUST_SIZE(sizeof(type))
-#endif
 
-#define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil)
-
 static VALUE
 infected_str_new(ptr, len, str)
     const char *ptr;
@@ -1312,11 +1335,12 @@
     char *p, *pend;
     VALUE ary;
     char type;
-    long len;
-    int tmp, star;
+    long len, tmp_len;
+    int star;
 #ifdef NATINT_PACK
     int natint;			/* native integer */
 #endif
+    int signed_p, integer_size, bigendian_p;
 
     StringValue(str);
     StringValue(fmt);
@@ -1490,7 +1514,7 @@
 	    break;
 
 	  case 'c':
-	    PACK_LENGTH_ADJUST(char,sizeof(char));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(char));
 	    while (len-- > 0) {
                 int c = *s++;
                 if (c > (char)127) c-=256;
@@ -1500,7 +1524,7 @@
 	    break;
 
 	  case 'C':
-	    PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(unsigned char));
 	    while (len-- > 0) {
 		unsigned char c = *s++;
 		rb_ary_push(ary, INT2FIX(c));
@@ -1509,139 +1533,221 @@
 	    break;
 
 	  case 's':
-	    PACK_LENGTH_ADJUST(short,2);
-	    while (len-- > 0) {
-		short tmp = 0;
-		memcpy(OFF16(&tmp), s, NATINT_LEN(short,2));
-		EXTEND16(tmp);
-		s += NATINT_LEN(short,2);
-		rb_ary_push(ary, INT2FIX(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+            signed_p = 1;
+            integer_size = NATINT_LEN(short, 2);
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
 	  case 'S':
-	    PACK_LENGTH_ADJUST(unsigned short,2);
-	    while (len-- > 0) {
-		unsigned short tmp = 0;
-		memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2));
-		s += NATINT_LEN(unsigned short,2);
-		rb_ary_push(ary, INT2FIX(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+            signed_p = 0;
+            integer_size = NATINT_LEN(short, 2);
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
 	  case 'i':
-	    PACK_LENGTH_ADJUST(int,sizeof(int));
-	    while (len-- > 0) {
-		int tmp;
-		memcpy(&tmp, s, sizeof(int));
-		s += sizeof(int);
-		rb_ary_push(ary, INT2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+            signed_p = 1;
+            integer_size = (int)sizeof(int);
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
 	  case 'I':
-	    PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int));
-	    while (len-- > 0) {
-		unsigned int tmp;
-		memcpy(&tmp, s, sizeof(unsigned int));
-		s += sizeof(unsigned int);
-		rb_ary_push(ary, UINT2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+            signed_p = 0;
+            integer_size = (int)sizeof(int);
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
 	  case 'l':
-	    PACK_LENGTH_ADJUST(long,4);
-	    while (len-- > 0) {
-		long tmp = 0;
-		memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
-		EXTEND32(tmp);
-		s += NATINT_LEN(long,4);
-		rb_ary_push(ary, LONG2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+            signed_p = 1;
+            integer_size = NATINT_LEN(long, 4);
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
-	  case 'L':
-	    PACK_LENGTH_ADJUST(unsigned long,4);
-	    while (len-- > 0) {
-		unsigned long tmp = 0;
-		memcpy(OFF32(&tmp), s, NATINT_LEN(unsigned long,4));
-		s += NATINT_LEN(unsigned long,4);
-		rb_ary_push(ary, ULONG2NUM(tmp));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+          case 'L':
+            signed_p = 0;
+            integer_size = NATINT_LEN(long, 4);
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
-	  case 'q':
-	    PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
-	    while (len-- > 0) {
-		char *tmp = (char*)s;
-		s += QUAD_SIZE;
-		rb_ary_push(ary, rb_quad_unpack(tmp, 1));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+          case 'q':
+            signed_p = 1;
+            integer_size = QUAD_SIZE;
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
-	  case 'Q':
-	    PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
-	    while (len-- > 0) {
-		char *tmp = (char*)s;
-		s += QUAD_SIZE;
-		rb_ary_push(ary, rb_quad_unpack(tmp, 0));
-	    }
-	    break;
+          case 'Q':
+            signed_p = 0;
+            integer_size = QUAD_SIZE;
+            bigendian_p = BIGENDIAN_P();
+            goto unpack_integer;
 
-	  case 'n':
-	    PACK_LENGTH_ADJUST(unsigned short,2);
-	    while (len-- > 0) {
-		unsigned short tmp = 0;
-		memcpy(OFF16B(&tmp), s, NATINT_LEN(unsigned short,2));
-		s += NATINT_LEN(unsigned short,2);
-		rb_ary_push(ary, UINT2NUM(ntohs(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+          case 'n':
+            signed_p = 0;
+            integer_size = 2;
+            bigendian_p = 1;
+            goto unpack_integer;
 
-	  case 'N':
-	    PACK_LENGTH_ADJUST(unsigned long,4);
-	    while (len-- > 0) {
-		unsigned long tmp = 0;
-		memcpy(OFF32B(&tmp), s, NATINT_LEN(unsigned long,4));
-		s += NATINT_LEN(unsigned long,4);
-		rb_ary_push(ary, ULONG2NUM(ntohl(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+          case 'N':
+            signed_p = 0;
+            integer_size = 4;
+            bigendian_p = 1;
+            goto unpack_integer;
 
-	  case 'v':
-	    PACK_LENGTH_ADJUST(unsigned short,2);
-	    while (len-- > 0) {
-		unsigned short tmp = 0;
-		memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2));
-		s += NATINT_LEN(unsigned short,2);
-		rb_ary_push(ary, UINT2NUM(vtohs(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+          case 'v':
+            signed_p = 0;
+            integer_size = 2;
+            bigendian_p = 0;
+            goto unpack_integer;
 
-	  case 'V':
-	    PACK_LENGTH_ADJUST(unsigned long,4);
-	    while (len-- > 0) {
-		unsigned long tmp = 0;
-		memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
-		s += NATINT_LEN(long,4);
-		rb_ary_push(ary, ULONG2NUM(vtohl(tmp)));
-	    }
-	    PACK_ITEM_ADJUST();
-	    break;
+          case 'V':
+            signed_p = 0;
+            integer_size = 4;
+            bigendian_p = 0;
+            goto unpack_integer;
 
+          unpack_integer:
+            switch (integer_size) {
+#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
+              case SIZEOF_INT16_T:
+                if (signed_p) {
+                    PACK_LENGTH_ADJUST_SIZE(sizeof(int16_t));
+                    while (len-- > 0) {
+                        union {
+                            int16_t i;
+                            char a[sizeof(int16_t)];
+                        } v;
+                        memcpy(v.a, s, sizeof(int16_t));
+                        if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
+                        s += sizeof(int16_t);
+                        rb_ary_push(ary, INT2FIX(v.i));
+                    }
+                    PACK_ITEM_ADJUST();
+                }
+                else {
+                    PACK_LENGTH_ADJUST_SIZE(sizeof(uint16_t));
+                    while (len-- > 0) {
+                        union {
+                            uint16_t i;
+                            char a[sizeof(uint16_t)];
+                        } v;
+                        memcpy(v.a, s, sizeof(uint16_t));
+                        if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
+                        s += sizeof(uint16_t);
+                        rb_ary_push(ary, INT2FIX(v.i));
+                    }
+                    PACK_ITEM_ADJUST();
+                }
+                break;
+#endif
+
+#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
+              case SIZEOF_INT32_T:
+                if (signed_p) {
+                    PACK_LENGTH_ADJUST_SIZE(sizeof(int32_t));
+                    while (len-- > 0) {
+                        union {
+                            int32_t i;
+                            char a[sizeof(int32_t)];
+                        } v;
+                        memcpy(v.a, s, sizeof(int32_t));
+                        if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
+                        s += sizeof(int32_t);
+                        rb_ary_push(ary, INT2NUM(v.i));
+                    }
+                    PACK_ITEM_ADJUST();
+                }
+                else {
+                    PACK_LENGTH_ADJUST_SIZE(sizeof(uint32_t));
+                    while (len-- > 0) {
+                        union {
+                            uint32_t i;
+                            char a[sizeof(uint32_t)];
+                        } v;
+                        memcpy(v.a, s, sizeof(uint32_t));
+                        if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
+                        s += sizeof(uint32_t);
+                        rb_ary_push(ary, UINT2NUM(v.i));
+                    }
+                    PACK_ITEM_ADJUST();
+                }
+                break;
+#endif
+
+#if defined(HAVE_INT64_T) && !defined(FORCE_BIG_PACK)
+              case SIZEOF_INT64_T:
+                if (signed_p) {
+                    PACK_LENGTH_ADJUST_SIZE(sizeof(int64_t));
+                    while (len-- > 0) {
+                        union {
+                            int64_t i;
+                            char a[sizeof(int64_t)];
+                        } v;
+                        memcpy(v.a, s, sizeof(int64_t));
+                        if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
+                        s += sizeof(int64_t);
+                        rb_ary_push(ary, INT64toNUM(v.i));
+                    }
+                    PACK_ITEM_ADJUST();
+                }
+                else {
+                    PACK_LENGTH_ADJUST_SIZE(sizeof(uint64_t));
+                    while (len-- > 0) {
+                        union {
+                            uint64_t i;
+                            char a[sizeof(uint64_t)];
+                        } v;
+                        memcpy(v.a, s, sizeof(uint64_t));
+                        if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
+                        s += sizeof(uint64_t);
+                        rb_ary_push(ary, UINT64toNUM(v.i));
+                    }
+                    PACK_ITEM_ADJUST();
+                }
+                break;
+#endif
+
+
+              default:
+                if (integer_size > MAX_INTEGER_PACK_SIZE)
+                    rb_bug("unexpected intger size for pack: %d", integer_size);
+                PACK_LENGTH_ADJUST_SIZE(integer_size);
+                while (len-- > 0) {
+                    union {
+                        unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG];
+                        char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG*SIZEOF_LONG];
+                    } v;
+                    int num_longs = (integer_size+SIZEOF_LONG)/SIZEOF_LONG;
+                    int i;
+
+                    if (signed_p && (signed char)s[bigendian_p ? 0 : (integer_size-1)] < 0)
+                        memset(v.a, 0xff, sizeof(long)*num_longs);
+                    else
+                        memset(v.a, 0, sizeof(long)*num_longs);
+                    if (bigendian_p)
+                        memcpy(v.a + sizeof(long)*num_longs - integer_size, s, integer_size);
+                    else
+                        memcpy(v.a, s, integer_size);
+                    if (bigendian_p) {
+                        for (i = 0; i < num_longs/2; i++) {
+                            unsigned long t = v.i[i];
+                            v.i[i] = v.i[num_longs-1-i];
+                            v.i[num_longs-1-i] = t;
+                        }
+                    }
+                    if (bigendian_p != BIGENDIAN_P()) {
+                        for (i = 0; i < num_longs; i++)
+                            v.i[i] = swapl(v.i[i]);
+                    }
+                    s += integer_size;
+                    rb_ary_push(ary, rb_big_unpack(v.i, num_longs));
+                }
+                PACK_ITEM_ADJUST();
+                break;
+            }
+            break;
+
 	  case 'f':
 	  case 'F':
-	    PACK_LENGTH_ADJUST(float,sizeof(float));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(float));
 	    while (len-- > 0) {
 		float tmp;
 		memcpy(&tmp, s, sizeof(float));
@@ -1652,7 +1758,7 @@
 	    break;
 
 	  case 'e':
-	    PACK_LENGTH_ADJUST(float,sizeof(float));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(float));
 	    while (len-- > 0) {
 	        float tmp;
 		FLOAT_CONVWITH(ftmp);
@@ -1666,7 +1772,7 @@
 	    break;
 	    
 	  case 'E':
-	    PACK_LENGTH_ADJUST(double,sizeof(double));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(double));
 	    while (len-- > 0) {
 		double tmp;
 		DOUBLE_CONVWITH(dtmp);
@@ -1681,7 +1787,7 @@
 	    
 	  case 'D':
 	  case 'd':
-	    PACK_LENGTH_ADJUST(double,sizeof(double));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(double));
 	    while (len-- > 0) {
 		double tmp;
 		memcpy(&tmp, s, sizeof(double));
@@ -1692,7 +1798,7 @@
 	    break;
 
 	  case 'g':
-	    PACK_LENGTH_ADJUST(float,sizeof(float));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(float));
 	    while (len-- > 0) {
 	        float tmp;
 		FLOAT_CONVWITH(ftmp;)
@@ -1706,7 +1812,7 @@
 	    break;
 	    
 	  case 'G':
-	    PACK_LENGTH_ADJUST(double,sizeof(double));
+	    PACK_LENGTH_ADJUST_SIZE(sizeof(double));
 	    while (len-- > 0) {
 		double tmp;
 		DOUBLE_CONVWITH(dtmp);
@@ -1886,7 +1992,7 @@
 	    break;
 
 	  case 'P':
-	    if (sizeof(char *) <= send - s) {
+	    if (sizeof(char *) <= (size_t)(send - s)) {
 		VALUE tmp = Qnil;
 		char *t;
 
@@ -1926,7 +2032,7 @@
 	    if (len > (send - s) / sizeof(char *))
 		len = (send - s) / sizeof(char *);
 	    while (len-- > 0) {
-		if (send - s < sizeof(char *))
+		if ((size_t)(send - s) < sizeof(char *))
 		    break;
 		else {
 		    VALUE tmp = Qnil;
Index: ruby_1_8_7/bignum.c
===================================================================
--- ruby_1_8_7/bignum.c	(revision 28219)
+++ ruby_1_8_7/bignum.c	(revision 28220)
@@ -222,9 +222,112 @@
     return rb_int2big(n);
 }
 
-#ifdef HAVE_LONG_LONG
+#if SIZEOF_LONG % SIZEOF_BDIGITS != 0
+# error unexpected SIZEOF_LONG : SIZEOF_BDIGITS ratio
+#endif
 
+/*
+ * buf is an array of long integers.
+ * buf is ordered from least significant word to most significant word.
+ * buf[0] is the least significant word and
+ * buf[num_longs-1] is the most significant word.
+ * This means words in buf is little endian.
+ * However each word in buf is native endian.
+ * (buf[i]&1) is the least significant bit and
+ * (buf[i]&(1<<(SIZEOF_LONG*CHAR_BIT-1))) is the most significant bit
+ * for each 0 <= i < num_longs.
+ * So buf is little endian at whole on a little endian machine.
+ * But buf is mixed endian on a big endian machine.
+ */
 void
+rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
+{
+    val = rb_to_int(val);
+    if (num_longs == 0)
+        return;
+    if (FIXNUM_P(val)) {
+        long i;
+        long tmp = FIX2LONG(val);
+        buf[0] = (unsigned long)tmp;
+        tmp = tmp < 0 ? ~0L : 0;
+        for (i = 1; i < num_longs; i++)
+            buf[i] = (unsigned long)tmp;
+        return;
+    }
+    else {
+        long len = RBIGNUM_LEN(val);
+        BDIGIT *ds = BDIGITS(val), *dend = ds + len;
+        long i, j;
+        for (i = 0; i < num_longs && ds < dend; i++) {
+            unsigned long l = 0;
+            for (j = 0; j < DIGSPERLONG && ds < dend; j++, ds++) {
+                l |= ((unsigned long)*ds << (j * BITSPERDIG));
+            }
+            buf[i] = l;
+        }
+        for (; i < num_longs; i++)
+            buf[i] = 0;
+        if (RBIGNUM_NEGATIVE_P(val)) {
+            for (i = 0; i < num_longs; i++) {
+                buf[i] = ~buf[i];
+            }
+            for (i = 0; i < num_longs; i++) {
+                buf[i]++;
+                if (buf[i] != 0)
+                    return;
+            }
+        }
+    }
+}
+
+/* See rb_big_pack comment for endianness of buf. */
+VALUE
+rb_big_unpack(unsigned long *buf, long num_longs)
+{
+    while (2 <= num_longs) {
+        if (buf[num_longs-1] == 0 && (long)buf[num_longs-2] >= 0)
+            num_longs--;
+        else if (buf[num_longs-1] == ~0UL && (long)buf[num_longs-2] < 0)
+            num_longs--;
+        else
+            break;
+    }
+    if (num_longs == 0)
+        return INT2FIX(0);
+    else if (num_longs == 1)
+        return LONG2NUM((long)buf[0]);
+    else {
+        VALUE big;
+        BDIGIT *ds;
+        long len = num_longs * DIGSPERLONG;
+        long i;
+        big = bignew(len, 1);
+        ds = BDIGITS(big);
+        for (i = 0; i < num_longs; i++) {
+            unsigned long d = buf[i];
+#if SIZEOF_LONG == SIZEOF_BDIGITS
+            *ds++ = d;
+#else
+            int j;
+            for (j = 0; j < DIGSPERLONG; j++) {
+                *ds++ = BIGLO(d);
+                d = BIGDN(d);
+            }
+#endif
+        }
+        if ((long)buf[num_longs-1] < 0) {
+            get2comp(big);
+            RBIGNUM_SET_SIGN(big, 0);
+        }
+        return bignorm(big);
+    }
+}
+
+#define QUAD_SIZE 8
+
+#if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
+
+void
 rb_quad_pack(buf, val)
     char *buf;
     VALUE val;
@@ -295,7 +398,19 @@
 
 #else
 
-#define QUAD_SIZE 8
+static int
+quad_buf_complement(char *buf, size_t len)
+{
+    size_t i;
+    for (i = 0; i < len; i++)
+        buf[i] = ~buf[i];
+    for (i = 0; i < len; i++) {
+        buf[i]++;
+        if (buf[i] != 0)
+            return 0;
+    }
+    return 1;
+}
 
 void
 rb_quad_pack(buf, val)
@@ -314,12 +429,8 @@
 	rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
     }
     memcpy(buf, (char*)BDIGITS(val), len);
-    if (!RBIGNUM(val)->sign) {
-	len = QUAD_SIZE;
-	while (len--) {
-	    *buf = ~*buf;
-	    buf++;
-	}
+    if (RBIGNUM_NEGATIVE_P(val)) {
+        quad_buf_complement(buf, QUAD_SIZE);
     }
 }
 
@@ -334,14 +445,10 @@
 
     memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
     if (sign && BNEG(buf)) {
-	long len = QUAD_SIZE;
 	char *tmp = (char*)BDIGITS(big);
 
 	RBIGNUM(big)->sign = 0;
-	while (len--) {
-	    *tmp = ~*tmp;
-	    tmp++;
-	}
+        quad_buf_complement(tmp, QUAD_SIZE);
     }
 
     return bignorm(big);
Index: ruby_1_8_7/ruby.h
===================================================================
--- ruby_1_8_7/ruby.h	(revision 28219)
+++ ruby_1_8_7/ruby.h	(revision 28220)
@@ -50,6 +50,10 @@
 # include <intrinsics.h>
 #endif
 
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
 #include <stddef.h>
 #include <stdio.h>
 
Index: ruby_1_8_7/test/ruby/test_pack.rb
===================================================================
--- ruby_1_8_7/test/ruby/test_pack.rb	(revision 28219)
+++ ruby_1_8_7/test/ruby/test_pack.rb	(revision 28220)
@@ -20,6 +20,31 @@
     assert_equal($x, $x.pack("l").unpack("l"))
   end
 
+  def test_pack_n
+    assert_equal "\000\000", [0].pack('n')
+    assert_equal "\000\001", [1].pack('n')
+    assert_equal "\000\002", [2].pack('n')
+    assert_equal "\000\003", [3].pack('n')
+    assert_equal "\377\376", [65534].pack('n')
+    assert_equal "\377\377", [65535].pack('n')
+
+    assert_equal "\200\000", [2**15].pack('n')
+    assert_equal "\177\377", [-2**15-1].pack('n')
+    assert_equal "\377\377", [-1].pack('n')
+
+    assert_equal "\000\001\000\001", [1,1].pack('n*')
+    assert_equal "\000\001\000\001\000\001", [1,1,1].pack('n*')
+  end
+
+  def test_unpack_n
+    assert_equal 1, "\000\001".unpack('n')[0]
+    assert_equal 2, "\000\002".unpack('n')[0]
+    assert_equal 3, "\000\003".unpack('n')[0]
+    assert_equal 65535, "\377\377".unpack('n')[0]
+    assert_equal [1,1], "\000\001\000\001".unpack('n*')
+    assert_equal [1,1,1], "\000\001\000\001\000\001".unpack('n*')
+  end
+
   def test_pack_N
     assert_equal "\000\000\000\000", [0].pack('N')
     assert_equal "\000\000\000\001", [1].pack('N')
@@ -40,24 +65,208 @@
     assert_equal 1, "\000\000\000\001".unpack('N')[0]
     assert_equal 2, "\000\000\000\002".unpack('N')[0]
     assert_equal 3, "\000\000\000\003".unpack('N')[0]
-    assert_equal 3, "\000\000\000\003".unpack('N')[0]
     assert_equal 4294967295, "\377\377\377\377".unpack('N')[0]
     assert_equal [1,1], "\000\000\000\001\000\000\000\001".unpack('N*')
     assert_equal [1,1,1], "\000\000\000\001\000\000\000\001\000\000\000\001".unpack('N*')
   end
 
+  def test_integer_endian
+    s = [1].pack("s")
+    assert_operator(["\0\1", "\1\0"], :include?, s)
+    if s == "\0\1"
+      # big endian
+      assert_equal("\x01\x02", [0x0102].pack("s"))
+      assert_equal("\x01\x02", [0x0102].pack("S"))
+      assert_equal("\x01\x02\x03\x04", [0x01020304].pack("l"))
+      assert_equal("\x01\x02\x03\x04", [0x01020304].pack("L"))
+      assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("q"))
+      assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("Q"))
+      assert_match(/\A\x00*\x01\x02\z/, [0x0102].pack("s!"))
+      assert_match(/\A\x00*\x01\x02\z/, [0x0102].pack("S!"))
+      assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("i"))
+      assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("I"))
+      assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("i!"))
+      assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("I!"))
+      assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("l!"))
+      assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("L!"))
+      %w[s S l L q Q s! S! i I i! I! l! L!].each {|fmt|
+        nuls = [0].pack(fmt)
+        v = 0
+        s = ""
+        nuls.bytesize.times {|i|
+          j = i + 40
+          v = v * 256 + j
+          s << [j].pack("C")
+        }
+        assert_equal(s, [v].pack(fmt), "[#{v}].pack(#{fmt.dump})")
+        assert_equal([v], s.unpack(fmt), "#{s.dump}.unpack(#{fmt.dump})")
+        s2 = s+s
+        fmt2 = fmt+"*"
+        assert_equal([v,v], s2.unpack(fmt2), "#{s2.dump}.unpack(#{fmt2.dump})")
+      }
+    else
+      # little endian
+      assert_equal("\x02\x01", [0x0102].pack("s"))
+      assert_equal("\x02\x01", [0x0102].pack("S"))
+      assert_equal("\x04\x03\x02\x01", [0x01020304].pack("l"))
+      assert_equal("\x04\x03\x02\x01", [0x01020304].pack("L"))
+      assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("q"))
+      assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("Q"))
+      assert_match(/\A\x02\x01\x00*\z/, [0x0102].pack("s!"))
+      assert_match(/\A\x02\x01\x00*\z/, [0x0102].pack("S!"))
+      assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("i"))
+      assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("I"))
+      assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("i!"))
+      assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("I!"))
+      assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("l!"))
+      assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("L!"))
+      %w[s S l L q Q s! S! i I i! I! l! L!].each {|fmt|
+        nuls = [0].pack(fmt)
+        v = 0
+        s = ""
+        nuls.bytesize.times {|i|
+          j = i+40
+          v = v * 256 + j
+          s << [j].pack("C")
+        }
+        s.reverse!
+        assert_equal(s, [v].pack(fmt), "[#{v}].pack(#{fmt.dump})")
+        assert_equal([v], s.unpack(fmt), "#{s.dump}.unpack(#{fmt.dump})")
+        s2 = s+s
+        fmt2 = fmt+"*"
+        assert_equal([v,v], s2.unpack(fmt2), "#{s2.dump}.unpack(#{fmt2.dump})")
+      }
+    end
+  end
+
   def test_pack_U
-    assert_raises(RangeError) { [-0x40000001].pack("U") }
-    assert_raises(RangeError) { [-0x40000000].pack("U") }
-    assert_raises(RangeError) { [-1].pack("U") }
+    assert_raise(RangeError) { [-0x40000001].pack("U") }
+    assert_raise(RangeError) { [-0x40000000].pack("U") }
+    assert_raise(RangeError) { [-1].pack("U") }
     assert_equal "\000", [0].pack("U")
     assert_equal "\374\277\277\277\277\277", [0x3fffffff].pack("U")
     assert_equal "\375\200\200\200\200\200", [0x40000000].pack("U")
     assert_equal "\375\277\277\277\277\277", [0x7fffffff].pack("U")
-    assert_raises(RangeError) { [0x80000000].pack("U") }
-    assert_raises(RangeError) { [0x100000000].pack("U") }
+    assert_raise(RangeError) { [0x80000000].pack("U") }
+    assert_raise(RangeError) { [0x100000000].pack("U") }
   end
 
+  def test_pack_P
+    a = ["abc"]
+    assert_equal a, a.pack("P").unpack("P*")
+    assert_equal "a", a.pack("P").unpack("P")[0]
+    assert_equal a, a.pack("P").freeze.unpack("P*")
+    assert_raise(ArgumentError) { (a.pack("P") + "").unpack("P*") }
+  end
+
+  def test_pack_p
+    a = ["abc"]
+    assert_equal a, a.pack("p").unpack("p*")
+    assert_equal a[0], a.pack("p").unpack("p")[0]
+    assert_equal a, a.pack("p").freeze.unpack("p*")
+    assert_raise(ArgumentError) { (a.pack("p") + "").unpack("p*") }
+  end
+
+  def test_format_string_modified
+    fmt = "CC"
+    o = Object.new
+    class << o; self; end.class_eval do
+      define_method(:to_int) { fmt.replace ""; 0 }
+    end
+    assert_raise(RuntimeError) do
+      [o, o].pack(fmt)
+    end
+  end
+
+  def test_comment
+    assert_equal("\0\1", [0,1].pack("  C  #foo \n  C  "))
+    assert_equal([0,1], "\0\1".unpack("  C  #foo \n  C  "))
+  end
+
+  def test_illegal_bang
+    assert_raise(ArgumentError) { [].pack("a!") }
+    assert_raise(ArgumentError) { "".unpack("a!") }
+  end
+
+  def test_pack_unpack_aA
+    assert_equal("f", ["foo"].pack("A"))
+    assert_equal("f", ["foo"].pack("a"))
+    assert_equal("foo", ["foo"].pack("A*"))
+    assert_equal("foo", ["foo"].pack("a*"))
+    assert_equal("fo", ["foo"].pack("A2"))
+    assert_equal("fo", ["foo"].pack("a2"))
+    assert_equal("foo ", ["foo"].pack("A4"))
+    assert_equal("foo\0", ["foo"].pack("a4"))
+    assert_equal(" ", [nil].pack("A"))
+    assert_equal("\0", [nil].pack("a"))
+    assert_equal("", [nil].pack("A*"))
+    assert_equal("", [nil].pack("a*"))
+    assert_equal("  ", [nil].pack("A2"))
+    assert_equal("\0\0", [nil].pack("a2"))
+
+    assert_equal("foo" + "\0" * 27, ["foo"].pack("a30"))
+
+    assert_equal(["f"], "foo\0".unpack("A"))
+    assert_equal(["f"], "foo\0".unpack("a"))
+    assert_equal(["foo"], "foo\0".unpack("A4"))
+    assert_equal(["foo\0"], "foo\0".unpack("a4"))
+    assert_equal(["foo"], "foo ".unpack("A4"))
+    assert_equal(["foo "], "foo ".unpack("a4"))
+    assert_equal(["foo"], "foo".unpack("A4"))
+    assert_equal(["foo"], "foo".unpack("a4"))
+  end
+
+  def test_pack_unpack_Z
+    assert_equal("f", ["foo"].pack("Z"))
+    assert_equal("foo\0", ["foo"].pack("Z*"))
+    assert_equal("fo", ["foo"].pack("Z2"))
+    assert_equal("foo\0\0", ["foo"].pack("Z5"))
+    assert_equal("\0", [nil].pack("Z"))
+    assert_equal("\0", [nil].pack("Z*"))
+    assert_equal("\0\0", [nil].pack("Z2"))
+
+    assert_equal(["f"], "foo\0".unpack("Z"))
+    assert_equal(["foo"], "foo".unpack("Z*"))
+    assert_equal(["foo"], "foo\0".unpack("Z*"))
+    assert_equal(["foo"], "foo".unpack("Z5"))
+  end
+
+  def test_pack_unpack_bB
+    assert_equal("\xff\x00", ["1111111100000000"].pack("b*"))
+    assert_equal("\x01\x02", ["1000000001000000"].pack("b*"))
+    assert_equal("", ["1"].pack("b0"))
+    assert_equal("\x01", ["1"].pack("b1"))
+    assert_equal("\x01\x00", ["1"].pack("b2"))
+    assert_equal("\x01\x00", ["1"].pack("b3"))
+    assert_equal("\x01\x00\x00", ["1"].pack("b4"))
+    assert_equal("\x01\x00\x00", ["1"].pack("b5"))
+    assert_equal("\x01\x00\x00\x00", ["1"].pack("b6"))
+
+    assert_equal("\xff\x00", ["1111111100000000"].pack("B*"))
+    assert_equal("\x01\x02", ["0000000100000010"].pack("B*"))
+    assert_equal("", ["1"].pack("B0"))
+    assert_equal("\x80", ["1"].pack("B1"))
+    assert_equal("\x80\x00", ["1"].pack("B2"))
+    assert_equal("\x80\x00", ["1"].pack("B3"))
+    assert_equal("\x80\x00\x00", ["1"].pack("B4"))
+    assert_equal("\x80\x00\x00", ["1"].pack("B5"))
+    assert_equal("\x80\x00\x00\x00", ["1"].pack("B6"))
+
+    assert_equal(["1111111100000000"], "\xff\x00".unpack("b*"))
+    assert_equal(["1000000001000000"], "\x01\x02".unpack("b*"))
+    assert_equal([""], "".unpack("b0"))
+    assert_equal(["1"], "\x01".unpack("b1"))
+    assert_equal(["10"], "\x01".unpack("b2"))
+    assert_equal(["100"], "\x01".unpack("b3"))
+
+    assert_equal(["1111111100000000"], "\xff\x00".unpack("B*"))
+    assert_equal(["0000000100000010"], "\x01\x02".unpack("B*"))
+    assert_equal([""], "".unpack("B0"))
+    assert_equal(["1"], "\x80".unpack("B1"))
+    assert_equal(["10"], "\x80".unpack("B2"))
+    assert_equal(["100"], "\x80".unpack("B3"))
+  end
+
   def test_pack_unpack_hH
     assert_equal("\x01\xfe", ["10ef"].pack("h*"))
     assert_equal("", ["10ef"].pack("h0"))

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]