Index: Python/import.c =================================================================== --- Python/import.c (révision 85081) +++ Python/import.c (copie de travail) @@ -1961,21 +1961,21 @@ _Py_fopen(PyObject *unicode, const char *mode) { #ifdef MS_WINDOWS - wchar_t path[MAXPATHLEN+1]; + wchar_t *path; wchar_t wmode[10]; - Py_ssize_t len; int usize; + FILE *f; - len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, MAXPATHLEN); - if (len == -1) - return NULL; - path[len] = L'\0'; - usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); if (usize == 0) return NULL; - return _wfopen(path, wmode); + path = PyUnicode_AsWideCharString((PyUnicodeObject*)unicode, NULL); + if (path == NULL) + return NULL; + f = _wfopen(path, wmode); + PyMem_Free(path); + return f; #else FILE *f; PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); @@ -1997,17 +1997,15 @@ _Py_stat(PyObject *unicode, struct stat *statbuf) { #ifdef MS_WINDOWS - wchar_t path[MAXPATHLEN+1]; - Py_ssize_t len; + wchar_t *path; int err; struct _stat wstatbuf; - len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, MAXPATHLEN); - if (len == -1) + path = PyUnicode_AsWideCharString((PyUnicodeObject*)unicode, NULL); + if (path == NULL) return -1; - path[len] = L'\0'; - err = _wstat(path, &wstatbuf); + PyMem_Free(path); if (!err) statbuf->st_mode = wstatbuf.st_mode; return err; @@ -3724,7 +3722,7 @@ #else /* MS_WINDOWS */ PyObject *pathobj; DWORD rv; - wchar_t path[MAXPATHLEN+1]; + wchar_t *path; Py_ssize_t len; if (!_PyArg_NoKeywords("NullImporter()", kwds)) @@ -3739,15 +3737,15 @@ return -1; } - len = PyUnicode_AsWideChar((PyUnicodeObject*)pathobj, - path, sizeof(path) / sizeof(path[0])); - if (len == -1) + path = PyUnicode_AsWideCharString((PyUnicodeObject*)pathobj, NULL); + if (path == NULL) return -1; /* see issue1293 and issue3677: * stat() on Windows doesn't recognise paths like * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. */ rv = GetFileAttributesW(path); + PyMem_Free(path); if (rv != INVALID_FILE_ATTRIBUTES) { /* it exists */ if (rv & FILE_ATTRIBUTE_DIRECTORY) { Index: Include/unicodeobject.h =================================================================== --- Include/unicodeobject.h (révision 85081) +++ Include/unicodeobject.h (copie de travail) @@ -99,8 +99,8 @@ #endif /* If the compiler provides a wchar_t type we try to support it - through the interface functions PyUnicode_FromWideChar() and - PyUnicode_AsWideChar(). */ + through the interface functions PyUnicode_FromWideChar(), + PyUnicode_AsWideChar() and PyUnicode_AsWideCharString(). */ #ifdef HAVE_USABLE_WCHAR_T # ifndef HAVE_WCHAR_H @@ -156,6 +156,7 @@ # define PyUnicode_AsUnicode PyUnicodeUCS2_AsUnicode # define PyUnicode_AsUnicodeEscapeString PyUnicodeUCS2_AsUnicodeEscapeString # define PyUnicode_AsWideChar PyUnicodeUCS2_AsWideChar +# define PyUnicode_AsWideCharString PyUnicodeUCS2_AsWideCharString # define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist # define PyUnicode_Compare PyUnicodeUCS2_Compare # define PyUnicode_CompareWithASCII PyUnicodeUCS2_CompareASCII @@ -239,6 +240,7 @@ # define PyUnicode_AsUnicode PyUnicodeUCS4_AsUnicode # define PyUnicode_AsUnicodeEscapeString PyUnicodeUCS4_AsUnicodeEscapeString # define PyUnicode_AsWideChar PyUnicodeUCS4_AsWideChar +# define PyUnicode_AsWideCharString PyUnicodeUCS4_AsWideCharString # define PyUnicode_ClearFreeList PyUnicodeUCS4_ClearFreelist # define PyUnicode_Compare PyUnicodeUCS4_Compare # define PyUnicode_CompareWithASCII PyUnicodeUCS4_CompareWithASCII @@ -570,6 +572,19 @@ Py_ssize_t size /* size of buffer */ ); +/* Convert the Unicode object to a wide character string. The output string + always ends with a nul character. If size is not NULL, write the number of + wide characters (including the final nul character) into *size. + + Returns a buffer allocated by PyMem_Alloc() (use PyMem_Free() to free it) + on success. On error, returns NULL, *size is undefined and raises a + MemoryError. */ + +PyAPI_FUNC(wchar_t*) PyUnicode_AsWideCharString( + PyUnicodeObject *unicode, /* Unicode object */ + Py_ssize_t *size /* number of characters of the result */ + ); + #endif /* --- Unicode ordinals --------------------------------------------------- */ Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (révision 85081) +++ Objects/unicodeobject.c (copie de travail) @@ -1153,10 +1153,27 @@ return ret; } -Py_ssize_t PyUnicode_AsWideChar(PyUnicodeObject *unicode, - wchar_t *w, - Py_ssize_t size) +static void +unicode_aswidechar(PyUnicodeObject *unicode, + wchar_t *w, + Py_ssize_t size) { +#if Py_UNICODE_SIZE == SIZEOF_WCHAR_T + memcpy(w, unicode->str, size * sizeof(wchar_t)); +#else + register Py_UNICODE *u; + register Py_ssize_t i; + u = PyUnicode_AS_UNICODE(unicode); + for (i = size; i > 0; i--) + *w++ = *u++; +#endif +} + +Py_ssize_t +PyUnicode_AsWideChar(PyUnicodeObject *unicode, + wchar_t *w, + Py_ssize_t size) +{ if (unicode == NULL) { PyErr_BadInternalCall(); return -1; @@ -1166,17 +1183,7 @@ if (size > PyUnicode_GET_SIZE(unicode)) size = PyUnicode_GET_SIZE(unicode) + 1; -#if Py_UNICODE_SIZE == SIZEOF_WCHAR_T - memcpy(w, unicode->str, size * sizeof(wchar_t)); -#else - { - register Py_UNICODE *u; - register Py_ssize_t i; - u = PyUnicode_AS_UNICODE(unicode); - for (i = size; i > 0; i--) - *w++ = *u++; - } -#endif + unicode_aswidechar(unicode, w, size); if (size > PyUnicode_GET_SIZE(unicode)) return PyUnicode_GET_SIZE(unicode); @@ -1184,6 +1191,33 @@ return size; } +wchar_t* +PyUnicode_AsWideCharString(PyUnicodeObject *unicode, + Py_ssize_t *size) +{ + wchar_t* buffer; + Py_ssize_t buflen; + + if (unicode == NULL) { + PyErr_BadInternalCall(); + return NULL; + } + + if ((PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) < PyUnicode_GET_SIZE(unicode)) { + PyErr_NoMemory(); + return NULL; + } + + buflen = PyUnicode_GET_SIZE(unicode) + 1; /* copy L'\0' */ + buffer = PyMem_MALLOC(buflen * sizeof(wchar_t)); + if (buffer == NULL) { + PyErr_NoMemory(); + return NULL; + } + unicode_aswidechar(unicode, buffer, buflen); + return buffer; +} + #endif PyObject *PyUnicode_FromOrdinal(int ordinal) Index: Doc/c-api/unicode.rst =================================================================== --- Doc/c-api/unicode.rst (révision 85081) +++ Doc/c-api/unicode.rst (copie de travail) @@ -462,6 +462,17 @@ required by the application. +.. cfunction:: wchar_t* PyUnicode_AsWideCharString(PyUnicodeObject *unicode, Py_ssize_t *size) + + Convert the Unicode object to a wide character string. The output string + always ends with a nul character. If *size* is not *NULL*, write the number + of wide characters (including the final nul character) into *\*size*. + + Returns a buffer allocated by :cfunc:`PyMem_Alloc` (use :cfunc:`PyMem_Free` + to free it) on success. On error, returns *NULL*, *\*size* is undefined and + raises a :exc:`MemoryError`. + + .. _builtincodecs: Built-in Codecs Index: Modules/_ctypes/callproc.c =================================================================== --- Modules/_ctypes/callproc.c (révision 85081) +++ Modules/_ctypes/callproc.c (copie de travail) @@ -665,24 +665,15 @@ pa->keep = obj; return 0; #else - int size = PyUnicode_GET_SIZE(obj); pa->ffi_type = &ffi_type_pointer; - size += 1; /* terminating NUL */ - size *= sizeof(wchar_t); - pa->value.p = PyMem_Malloc(size); - if (!pa->value.p) { - PyErr_NoMemory(); + pa->value.p = PyUnicode_AsWideCharString((PyUnicodeObject *)obj, NULL); + if (pa->value.p == NULL) return -1; - } - memset(pa->value.p, 0, size); pa->keep = PyCapsule_New(pa->value.p, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor); if (!pa->keep) { PyMem_Free(pa->value.p); return -1; } - if (-1 == PyUnicode_AsWideChar((PyUnicodeObject *)obj, - pa->value.p, PyUnicode_GET_SIZE(obj))) - return -1; return 0; #endif } @@ -1147,7 +1138,7 @@ } for (i = 0; i < argcount; ++i) { atypes[i] = args[i].ffi_type; - if (atypes[i]->type == FFI_TYPE_STRUCT + if (atypes[i]->type == FFI_TYPE_STRUCT #ifdef _WIN64 && atypes[i]->size <= sizeof(void *) #endif Index: Modules/_ctypes/cfield.c =================================================================== --- Modules/_ctypes/cfield.c (révision 85081) +++ Modules/_ctypes/cfield.c (copie de travail) @@ -1433,15 +1433,11 @@ PyObject *keep; wchar_t *buffer; - int size = PyUnicode_GET_SIZE(value); - size += 1; /* terminating NUL */ - size *= sizeof(wchar_t); - buffer = (wchar_t *)PyMem_Malloc(size); + buffer = PyUnicode_AsWideCharString((PyUnicodeObject *)value, NULL); if (!buffer) { Py_DECREF(value); - return PyErr_NoMemory(); + return NULL; } - memset(buffer, 0, size); keep = PyCapsule_New(buffer, CTYPES_CFIELD_CAPSULE_NAME_PYMEM, pymem_destructor); if (!keep) { Py_DECREF(value); @@ -1449,12 +1445,6 @@ return NULL; } *(wchar_t **)ptr = (wchar_t *)buffer; - if (-1 == PyUnicode_AsWideChar((PyUnicodeObject *)value, - buffer, PyUnicode_GET_SIZE(value))) { - Py_DECREF(value); - Py_DECREF(keep); - return NULL; - } Py_DECREF(value); return keep; } Index: Modules/_localemodule.c =================================================================== --- Modules/_localemodule.c (révision 85081) +++ Modules/_localemodule.c (copie de travail) @@ -242,29 +242,16 @@ { PyObject *os1, *os2, *result = NULL; wchar_t *ws1 = NULL, *ws2 = NULL; - Py_ssize_t len1, len2; if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2)) return NULL; /* Convert the unicode strings to wchar[]. */ - len1 = PyUnicode_GET_SIZE(os1) + 1; - ws1 = PyMem_MALLOC(len1 * sizeof(wchar_t)); - if (!ws1) { - PyErr_NoMemory(); + ws1 = PyUnicode_AsWideCharString((PyUnicodeObject*)os1, NULL); + if (ws1 == NULL) goto done; - } - if (PyUnicode_AsWideChar((PyUnicodeObject*)os1, ws1, len1) == -1) + ws2 = PyUnicode_AsWideCharString((PyUnicodeObject*)os2, NULL); + if (ws2 == NULL) goto done; - ws1[len1 - 1] = 0; - len2 = PyUnicode_GET_SIZE(os2) + 1; - ws2 = PyMem_MALLOC(len2 * sizeof(wchar_t)); - if (!ws2) { - PyErr_NoMemory(); - goto done; - } - if (PyUnicode_AsWideChar((PyUnicodeObject*)os2, ws2, len2) == -1) - goto done; - ws2[len2 - 1] = 0; /* Collate the strings. */ result = PyLong_FromLong(wcscoll(ws1, ws2)); done: Index: Modules/timemodule.c =================================================================== --- Modules/timemodule.c (révision 85081) +++ Modules/timemodule.c (copie de travail) @@ -394,10 +394,15 @@ PyObject *tup = NULL; struct tm buf; const time_char *fmt; - PyObject *format, *tmpfmt; +#ifdef HAVE_WCSFTIME + wchar_t *format; +#else + PyObject *format; +#endif size_t fmtlen, buflen; - time_char *outbuf = 0; + time_char *outbuf = NULL; size_t i; + PyObject *ret = NULL; memset((void *) &buf, '\0', sizeof(buf)); @@ -482,19 +487,10 @@ buf.tm_isdst = 1; #ifdef HAVE_WCSFTIME - tmpfmt = PyBytes_FromStringAndSize(NULL, - sizeof(wchar_t) * (PyUnicode_GetSize(format)+1)); - if (!tmpfmt) + format = PyUnicode_AsWideCharString((PyUnicodeObject*)format, NULL); + if (format == NULL) return NULL; - /* This assumes that PyUnicode_AsWideChar doesn't do any UTF-16 - expansion. */ - if (PyUnicode_AsWideChar((PyUnicodeObject*)format, - (wchar_t*)PyBytes_AS_STRING(tmpfmt), - PyUnicode_GetSize(format)+1) == (size_t)-1) - /* This shouldn't fail. */ - Py_FatalError("PyUnicode_AsWideChar failed"); - format = tmpfmt; - fmt = (wchar_t*)PyBytes_AS_STRING(format); + fmt = format; #else /* Convert the unicode string to an ascii one */ format = PyUnicode_AsEncodedString(format, TZNAME_ENCODING, NULL); @@ -528,8 +524,8 @@ for (i = 1024; ; i += i) { outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char)); if (outbuf == NULL) { - Py_DECREF(format); - return PyErr_NoMemory(); + PyErr_NoMemory(); + break; } buflen = format_time(outbuf, i, fmt, &buf); if (buflen > 0 || i >= 256 * fmtlen) { @@ -538,7 +534,6 @@ More likely, the format yields an empty result, e.g. an empty format, or %Z when the timezone is unknown. */ - PyObject *ret; #ifdef HAVE_WCSFTIME ret = PyUnicode_FromWideChar(outbuf, buflen); #else @@ -546,19 +541,23 @@ TZNAME_ENCODING, NULL); #endif PyMem_Free(outbuf); - Py_DECREF(format); - return ret; + break; } PyMem_Free(outbuf); #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) /* VisualStudio .NET 2005 does this properly */ if (buflen == 0 && errno == EINVAL) { PyErr_SetString(PyExc_ValueError, "Invalid format string"); - Py_DECREF(format); - return 0; + break; } #endif } +#ifdef HAVE_WCSFTIME + PyMem_Free(format); +#else + Py_DECREF(format); +#endif + return ret; } #undef time_char