@@ -1746,7 +1746,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
17461746 PyObject * tzinfo = get_tzinfo_member (object );
17471747
17481748 if (tzinfo == Py_None || tzinfo == NULL ) {
1749- return PyBytes_FromStringAndSize (NULL , 0 );
1749+ return PyUnicode_FromStringAndSize (NULL , 0 );
17501750 }
17511751
17521752 assert (tzinfoarg != NULL );
@@ -1757,7 +1757,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
17571757 tzinfoarg ) < 0 )
17581758 return NULL ;
17591759
1760- return PyBytes_FromStringAndSize (buf , strlen ( buf ) );
1760+ return PyUnicode_FromString (buf );
17611761}
17621762
17631763static PyObject *
@@ -1814,7 +1814,7 @@ make_freplacement(PyObject *object)
18141814 else
18151815 sprintf (freplacement , "%06d" , 0 );
18161816
1817- return PyBytes_FromStringAndSize (freplacement , strlen ( freplacement ) );
1817+ return PyUnicode_FromString (freplacement );
18181818}
18191819
18201820/* I sure don't want to reproduce the strftime code from the time module,
@@ -1835,159 +1835,124 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
18351835 PyObject * Zreplacement = NULL ; /* py string, replacement for %Z */
18361836 PyObject * freplacement = NULL ; /* py string, replacement for %f */
18371837
1838- const char * pin ; /* pointer to next char in input format */
1839- Py_ssize_t flen ; /* length of input format */
1840- char ch ; /* next char in input format */
1841-
1842- PyObject * newfmt = NULL ; /* py string, the output format */
1843- char * pnew ; /* pointer to available byte in output format */
1844- size_t totalnew ; /* number bytes total in output format buffer,
1845- exclusive of trailing \0 */
1846- size_t usednew ; /* number bytes used so far in output format buffer */
1847-
1848- const char * ptoappend ; /* ptr to string to append to output buffer */
1849- Py_ssize_t ntoappend ; /* # of bytes to append to output buffer */
1850-
18511838 assert (object && format && timetuple );
18521839 assert (PyUnicode_Check (format ));
1853- /* Convert the input format to a C string and size */
1854- pin = PyUnicode_AsUTF8AndSize ( format , & flen );
1855- if (! pin )
1840+
1841+ PyObject * strftime = _PyImport_GetModuleAttrString ( "time" , "strftime" );
1842+ if (strftime == NULL ) {
18561843 return NULL ;
1844+ }
18571845
18581846 /* Scan the input format, looking for %z/%Z/%f escapes, building
18591847 * a new format. Since computing the replacements for those codes
18601848 * is expensive, don't unless they're actually used.
18611849 */
1862- if (flen > INT_MAX - 1 ) {
1863- PyErr_NoMemory ();
1864- goto Done ;
1865- }
18661850
1867- totalnew = flen + 1 ; /* realistic if no %z/%Z */
1868- newfmt = PyBytes_FromStringAndSize (NULL , totalnew );
1869- if (newfmt == NULL ) goto Done ;
1870- pnew = PyBytes_AsString (newfmt );
1871- usednew = 0 ;
1872-
1873- while ((ch = * pin ++ ) != '\0' ) {
1874- if (ch != '%' ) {
1875- ptoappend = pin - 1 ;
1876- ntoappend = 1 ;
1851+ _PyUnicodeWriter writer ;
1852+ _PyUnicodeWriter_Init (& writer );
1853+ writer .overallocate = 1 ;
1854+
1855+ Py_ssize_t flen = PyUnicode_GET_LENGTH (format );
1856+ Py_ssize_t i = 0 ;
1857+ Py_ssize_t start = 0 ;
1858+ Py_ssize_t end = 0 ;
1859+ while (i != flen ) {
1860+ i = PyUnicode_FindChar (format , '%' , i , flen , 1 );
1861+ if (i < 0 ) {
1862+ assert (!PyErr_Occurred ());
1863+ break ;
18771864 }
1878- else if ((ch = * pin ++ ) == '\0' ) {
1879- /* Null byte follows %, copy only '%'.
1880- *
1881- * Back the pin up one char so that we catch the null check
1882- * the next time through the loop.*/
1883- pin -- ;
1884- ptoappend = pin - 1 ;
1885- ntoappend = 1 ;
1865+ end = i ;
1866+ i ++ ;
1867+ if (i == flen ) {
1868+ break ;
18861869 }
1870+ Py_UCS4 ch = PyUnicode_READ_CHAR (format , i );
1871+ i ++ ;
18871872 /* A % has been seen and ch is the character after it. */
1888- else if (ch == 'z' ) {
1873+ PyObject * replacement = NULL ;
1874+ if (ch == 'z' ) {
18891875 /* %z -> +HHMM */
18901876 if (zreplacement == NULL ) {
18911877 zreplacement = make_somezreplacement (object , "" , tzinfoarg );
18921878 if (zreplacement == NULL )
1893- goto Done ;
1879+ goto Error ;
18941880 }
1895- assert (zreplacement != NULL );
1896- assert (PyBytes_Check (zreplacement ));
1897- ptoappend = PyBytes_AS_STRING (zreplacement );
1898- ntoappend = PyBytes_GET_SIZE (zreplacement );
1881+ replacement = zreplacement ;
18991882 }
1900- else if (ch == ':' && * pin == 'z' && pin ++ ) {
1883+ else if (ch == ':' && i < flen && PyUnicode_READ_CHAR ( format , i ) == 'z' ) {
19011884 /* %:z -> +HH:MM */
1885+ i ++ ;
19021886 if (colonzreplacement == NULL ) {
19031887 colonzreplacement = make_somezreplacement (object , ":" , tzinfoarg );
19041888 if (colonzreplacement == NULL )
1905- goto Done ;
1889+ goto Error ;
19061890 }
1907- assert (colonzreplacement != NULL );
1908- assert (PyBytes_Check (colonzreplacement ));
1909- ptoappend = PyBytes_AS_STRING (colonzreplacement );
1910- ntoappend = PyBytes_GET_SIZE (colonzreplacement );
1891+ replacement = colonzreplacement ;
19111892 }
19121893 else if (ch == 'Z' ) {
19131894 /* format tzname */
19141895 if (Zreplacement == NULL ) {
19151896 Zreplacement = make_Zreplacement (object ,
19161897 tzinfoarg );
19171898 if (Zreplacement == NULL )
1918- goto Done ;
1899+ goto Error ;
19191900 }
1920- assert (Zreplacement != NULL );
1921- assert (PyUnicode_Check (Zreplacement ));
1922- ptoappend = PyUnicode_AsUTF8AndSize (Zreplacement ,
1923- & ntoappend );
1924- if (ptoappend == NULL )
1925- goto Done ;
1901+ replacement = Zreplacement ;
19261902 }
19271903 else if (ch == 'f' ) {
19281904 /* format microseconds */
19291905 if (freplacement == NULL ) {
19301906 freplacement = make_freplacement (object );
19311907 if (freplacement == NULL )
1932- goto Done ;
1908+ goto Error ;
19331909 }
1934- assert (freplacement != NULL );
1935- assert (PyBytes_Check (freplacement ));
1936- ptoappend = PyBytes_AS_STRING (freplacement );
1937- ntoappend = PyBytes_GET_SIZE (freplacement );
1910+ replacement = freplacement ;
19381911 }
19391912 else {
19401913 /* percent followed by something else */
1941- ptoappend = pin - 2 ;
1942- ntoappend = 2 ;
1943- }
1944-
1945- /* Append the ntoappend chars starting at ptoappend to
1946- * the new format.
1947- */
1948- if (ntoappend == 0 )
19491914 continue ;
1950- assert (ptoappend != NULL );
1951- assert (ntoappend > 0 );
1952- while (usednew + ntoappend > totalnew ) {
1953- if (totalnew > (PY_SSIZE_T_MAX >> 1 )) { /* overflow */
1954- PyErr_NoMemory ();
1955- goto Done ;
1956- }
1957- totalnew <<= 1 ;
1958- if (_PyBytes_Resize (& newfmt , totalnew ) < 0 )
1959- goto Done ;
1960- pnew = PyBytes_AsString (newfmt ) + usednew ;
19611915 }
1962- memcpy (pnew , ptoappend , ntoappend );
1963- pnew += ntoappend ;
1964- usednew += ntoappend ;
1965- assert (usednew <= totalnew );
1916+ assert (replacement != NULL );
1917+ assert (PyUnicode_Check (replacement ));
1918+ if (_PyUnicodeWriter_WriteSubstring (& writer , format , start , end ) < 0 ) {
1919+ goto Error ;
1920+ }
1921+ start = i ;
1922+ if (_PyUnicodeWriter_WriteStr (& writer , replacement ) < 0 ) {
1923+ goto Error ;
1924+ }
19661925 } /* end while() */
19671926
1968- if (_PyBytes_Resize (& newfmt , usednew ) < 0 )
1969- goto Done ;
1970- {
1971- PyObject * format ;
1972- PyObject * strftime = _PyImport_GetModuleAttrString ("time" , "strftime" );
1973-
1974- if (strftime == NULL )
1927+ PyObject * newformat ;
1928+ if (start == 0 ) {
1929+ _PyUnicodeWriter_Dealloc (& writer );
1930+ newformat = Py_NewRef (format );
1931+ }
1932+ else {
1933+ if (_PyUnicodeWriter_WriteSubstring (& writer , format , start , flen ) < 0 ) {
1934+ goto Error ;
1935+ }
1936+ newformat = _PyUnicodeWriter_Finish (& writer );
1937+ if (newformat == NULL ) {
19751938 goto Done ;
1976- format = PyUnicode_FromString (PyBytes_AS_STRING (newfmt ));
1977- if (format != NULL ) {
1978- result = PyObject_CallFunctionObjArgs (strftime ,
1979- format , timetuple , NULL );
1980- Py_DECREF (format );
19811939 }
1982- Py_DECREF (strftime );
19831940 }
1941+ result = PyObject_CallFunctionObjArgs (strftime ,
1942+ newformat , timetuple , NULL );
1943+ Py_DECREF (newformat );
1944+
19841945 Done :
19851946 Py_XDECREF (freplacement );
19861947 Py_XDECREF (zreplacement );
19871948 Py_XDECREF (colonzreplacement );
19881949 Py_XDECREF (Zreplacement );
1989- Py_XDECREF (newfmt );
1950+ Py_XDECREF (strftime );
19901951 return result ;
1952+
1953+ Error :
1954+ _PyUnicodeWriter_Dealloc (& writer );
1955+ goto Done ;
19911956}
19921957
19931958/* ---------------------------------------------------------------------------
0 commit comments