--- Modules/_struct2.6b1.c 2008-06-21 10:22:42.000000000 -0700 +++ Modules/_struct.c 2008-06-21 10:46:48.000000000 -0700 @@ -88,6 +88,7 @@ typedef struct { char c; long x; } st_long; typedef struct { char c; float x; } st_float; typedef struct { char c; double x; } st_double; +typedef struct { char c; size_t x; } st_size_t; typedef struct { char c; void *x; } st_void_p; #define SHORT_ALIGN (sizeof(st_short) - sizeof(short)) @@ -95,6 +96,7 @@ #define LONG_ALIGN (sizeof(st_long) - sizeof(long)) #define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) #define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double)) +#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t)) #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) /* We can't support q and Q in native mode unless the compiler does; @@ -795,6 +797,13 @@ {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint}, {'l', sizeof(long), LONG_ALIGN, nu_long, np_long}, {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong}, +#if (SIZEOF_SIZE_T == SIZEOF_INT) + {'z', sizeof(size_t), SIZE_T_ALIGN, nu_int, np_int}, /* ssize_t */ + {'Z', sizeof(size_t), SIZE_T_ALIGN, nu_uint, np_uint}, /* size_t */ +#elif (SIZEOF_SIZE_T == SIZEOF_LONG_LONG) && defined(HAVE_LONG_LONG) + {'z', sizeof(size_t), SIZE_T_ALIGN, nu_longlong, np_longlong}, /* ssize_t */ + {'Z', sizeof(size_t), SIZE_T_ALIGN, nu_ulonglong, np_ulonglong}, /* size_t */ +#endif #ifdef HAVE_LONG_LONG {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, @@ -1034,6 +1043,15 @@ {'I', 4, 0, bu_uint, bp_uint}, {'l', 4, 0, bu_int, bp_int}, {'L', 4, 0, bu_uint, bp_uint}, +#if (SIZEOF_SIZE_T == SIZEOF_INT) + {'z', 4, 0, bu_int, bp_int}, /* ssize_t */ + {'Z', 4, 0, bu_uint, bp_uint}, /* size_t */ +#elif (SIZEOF_SIZE_T == SIZEOF_LONG_LONG) + {'z', 8, 0, bu_longlong, bp_longlong}, /* ssize_t */ + {'Z', 8, 0, bu_ulonglong, bp_ulonglong}, /* size_t */ +#else +# error "unsupported SIZEOF_SIZE_T value" +#endif {'q', 8, 0, bu_longlong, bp_longlong}, {'Q', 8, 0, bu_ulonglong, bp_ulonglong}, {'?', 1, 0, bu_bool, bp_bool}, @@ -1253,6 +1271,15 @@ {'I', 4, 0, lu_uint, lp_uint}, {'l', 4, 0, lu_int, lp_int}, {'L', 4, 0, lu_uint, lp_uint}, +#if (SIZEOF_SIZE_T == SIZEOF_INT) + {'z', 4, 0, lu_int, lp_int}, /* ssize_t */ + {'Z', 4, 0, lu_uint, lp_uint}, /* size_t */ +#elif (SIZEOF_SIZE_T == SIZEOF_LONG_LONG) + {'z', 8, 0, lu_longlong, lp_longlong}, /* ssize_t */ + {'Z', 8, 0, lu_ulonglong, lp_ulonglong}, /* size_t */ +#else +# error "unsupported SIZEOF_SIZE_T value" +#endif {'q', 8, 0, lu_longlong, lp_longlong}, {'Q', 8, 0, lu_ulonglong, lp_ulonglong}, {'?', 1, 0, bu_bool, bp_bool}, /* Std rep not endian dep, @@ -1386,7 +1413,7 @@ } /* check for overflow */ - if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) { + if (len > ((PY_SSIZE_T_MAX / sizeof(formatcode)) - 1)) { PyErr_NoMemory(); return -1; } @@ -2049,9 +2076,13 @@ \n\ The remaining chars indicate types of args and must match exactly;\n\ these can be preceded by a decimal repeat count:\n\ - x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ - h:short; H:unsigned short; i:int; I:unsigned int;\n\ - l:long; L:unsigned long; f:float; d:double.\n\ + x: pad byte (no data); c:char;\n\ + b:signed byte; B:unsigned byte;\n\ + h:short; H:unsigned short;\n\ + i:int; I:unsigned int;\n\ + l:long; L:unsigned long;\n\ + z:ssize_t; Z:size_t;\n\ + f:float; d:double.\n\ Special cases (preceding decimal count indicates length):\n\ s:string (array of char); p: pascal string (with count byte).\n\ Special case (only available in native format):\n\ --- Doc/library/struct2.6b1.rst 2008-06-21 10:22:10.000000000 -0700 +++ Doc/library/struct.rst 2008-06-21 10:38:22.000000000 -0700 @@ -91,9 +91,13 @@ +--------+-------------------------+--------------------+-------+ | ``L`` | :ctype:`unsigned long` | long | | +--------+-------------------------+--------------------+-------+ -| ``q`` | :ctype:`long long` | long | \(2) | +| ``z`` | :ctype:`ssize_t` | integer or long | \(2) | +--------+-------------------------+--------------------+-------+ -| ``Q`` | :ctype:`unsigned long | long | \(2) | +| ``Z`` | :ctype:`size_t` | integer or long | \(2) | ++--------+-------------------------+--------------------+-------+ +| ``q`` | :ctype:`long long` | long | \(3) | ++--------+-------------------------+--------------------+-------+ +| ``Q`` | :ctype:`unsigned long | long | \(3) | | | long` | | | +--------+-------------------------+--------------------+-------+ | ``f`` | :ctype:`float` | float | | @@ -117,6 +121,14 @@ .. versionadded:: 2.6 (2) + The ``'z'`` and ``'Z'`` conversion codes are not available in native mode if + sizeof(:ctype:'size_t') is 8 and the platform C compiler does not supports C + :ctype:`long long`, or, on Windows, :ctype:`__int64`. They are always + available in standard modes. + + .. versionadded:: 2.6 + +(3) The ``'q'`` and ``'Q'`` conversion codes are available in native mode only if the platform C compiler supports C :ctype:`long long`, or, on Windows, :ctype:`__int64`. They are always available in standard modes. @@ -147,8 +159,8 @@ used. Note that for :func:`unpack`, the ``'p'`` format character consumes count bytes, but that the string returned can never contain more than 255 characters. -For the ``'I'``, ``'L'``, ``'q'`` and ``'Q'`` format characters, the return -value is a Python long integer. +For the ``'I'``, ``'L'``, ``'Z'``, ``'q'`` and ``'Q'`` format characters, the +return value is a Python long integer. For the ``'P'`` format character, the return value is a Python integer or long integer, depending on the size needed to hold a pointer when it has been cast to --- Lib/test/test_struct2.6b1.py 2008-06-21 11:10:58.000000000 -0700 +++ Lib/test/test_struct.py 2008-06-21 11:12:30.000000000 -0700 @@ -87,7 +87,7 @@ self.assertEqual((struct.pack('=i', 1)[0] == chr(0)), ISBIGENDIAN) def test_consistence(self): - self.assertRaises(struct.error, struct.calcsize, 'Z') + self.assertRaises(struct.error, struct.calcsize, 'Y') sz = struct.calcsize('i') self.assertEqual(sz * 3, struct.calcsize('iii')) @@ -385,6 +385,7 @@ ("hH", 2), ("iI", 4), ("lL", 4), + ("zZ", len(struct.pack('Z', 0))), ("qQ", 8)]: t = IntTester(*args) t.run()