@@ -1746,7 +1746,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
1746
1746
PyObject * tzinfo = get_tzinfo_member (object );
1747
1747
1748
1748
if (tzinfo == Py_None || tzinfo == NULL ) {
1749
- return PyBytes_FromStringAndSize (NULL , 0 );
1749
+ return PyUnicode_FromStringAndSize (NULL , 0 );
1750
1750
}
1751
1751
1752
1752
assert (tzinfoarg != NULL );
@@ -1757,7 +1757,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
1757
1757
tzinfoarg ) < 0 )
1758
1758
return NULL ;
1759
1759
1760
- return PyBytes_FromStringAndSize (buf , strlen ( buf ) );
1760
+ return PyUnicode_FromString (buf );
1761
1761
}
1762
1762
1763
1763
static PyObject *
@@ -1814,7 +1814,7 @@ make_freplacement(PyObject *object)
1814
1814
else
1815
1815
sprintf (freplacement , "%06d" , 0 );
1816
1816
1817
- return PyBytes_FromStringAndSize (freplacement , strlen ( freplacement ) );
1817
+ return PyUnicode_FromString (freplacement );
1818
1818
}
1819
1819
1820
1820
/* 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,
1835
1835
PyObject * Zreplacement = NULL ; /* py string, replacement for %Z */
1836
1836
PyObject * freplacement = NULL ; /* py string, replacement for %f */
1837
1837
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
-
1851
1838
assert (object && format && timetuple );
1852
1839
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 ) {
1856
1843
return NULL ;
1844
+ }
1857
1845
1858
1846
/* Scan the input format, looking for %z/%Z/%f escapes, building
1859
1847
* a new format. Since computing the replacements for those codes
1860
1848
* is expensive, don't unless they're actually used.
1861
1849
*/
1862
- if (flen > INT_MAX - 1 ) {
1863
- PyErr_NoMemory ();
1864
- goto Done ;
1865
- }
1866
1850
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 ;
1877
1864
}
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 ;
1886
1869
}
1870
+ Py_UCS4 ch = PyUnicode_READ_CHAR (format , i );
1871
+ i ++ ;
1887
1872
/* A % has been seen and ch is the character after it. */
1888
- else if (ch == 'z' ) {
1873
+ PyObject * replacement = NULL ;
1874
+ if (ch == 'z' ) {
1889
1875
/* %z -> +HHMM */
1890
1876
if (zreplacement == NULL ) {
1891
1877
zreplacement = make_somezreplacement (object , "" , tzinfoarg );
1892
1878
if (zreplacement == NULL )
1893
- goto Done ;
1879
+ goto Error ;
1894
1880
}
1895
- assert (zreplacement != NULL );
1896
- assert (PyBytes_Check (zreplacement ));
1897
- ptoappend = PyBytes_AS_STRING (zreplacement );
1898
- ntoappend = PyBytes_GET_SIZE (zreplacement );
1881
+ replacement = zreplacement ;
1899
1882
}
1900
- else if (ch == ':' && * pin == 'z' && pin ++ ) {
1883
+ else if (ch == ':' && i < flen && PyUnicode_READ_CHAR ( format , i ) == 'z' ) {
1901
1884
/* %:z -> +HH:MM */
1885
+ i ++ ;
1902
1886
if (colonzreplacement == NULL ) {
1903
1887
colonzreplacement = make_somezreplacement (object , ":" , tzinfoarg );
1904
1888
if (colonzreplacement == NULL )
1905
- goto Done ;
1889
+ goto Error ;
1906
1890
}
1907
- assert (colonzreplacement != NULL );
1908
- assert (PyBytes_Check (colonzreplacement ));
1909
- ptoappend = PyBytes_AS_STRING (colonzreplacement );
1910
- ntoappend = PyBytes_GET_SIZE (colonzreplacement );
1891
+ replacement = colonzreplacement ;
1911
1892
}
1912
1893
else if (ch == 'Z' ) {
1913
1894
/* format tzname */
1914
1895
if (Zreplacement == NULL ) {
1915
1896
Zreplacement = make_Zreplacement (object ,
1916
1897
tzinfoarg );
1917
1898
if (Zreplacement == NULL )
1918
- goto Done ;
1899
+ goto Error ;
1919
1900
}
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 ;
1926
1902
}
1927
1903
else if (ch == 'f' ) {
1928
1904
/* format microseconds */
1929
1905
if (freplacement == NULL ) {
1930
1906
freplacement = make_freplacement (object );
1931
1907
if (freplacement == NULL )
1932
- goto Done ;
1908
+ goto Error ;
1933
1909
}
1934
- assert (freplacement != NULL );
1935
- assert (PyBytes_Check (freplacement ));
1936
- ptoappend = PyBytes_AS_STRING (freplacement );
1937
- ntoappend = PyBytes_GET_SIZE (freplacement );
1910
+ replacement = freplacement ;
1938
1911
}
1939
1912
else {
1940
1913
/* 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 )
1949
1914
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 ;
1961
1915
}
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
+ }
1966
1925
} /* end while() */
1967
1926
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 ) {
1975
1938
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 );
1981
1939
}
1982
- Py_DECREF (strftime );
1983
1940
}
1941
+ result = PyObject_CallFunctionObjArgs (strftime ,
1942
+ newformat , timetuple , NULL );
1943
+ Py_DECREF (newformat );
1944
+
1984
1945
Done :
1985
1946
Py_XDECREF (freplacement );
1986
1947
Py_XDECREF (zreplacement );
1987
1948
Py_XDECREF (colonzreplacement );
1988
1949
Py_XDECREF (Zreplacement );
1989
- Py_XDECREF (newfmt );
1950
+ Py_XDECREF (strftime );
1990
1951
return result ;
1952
+
1953
+ Error :
1954
+ _PyUnicodeWriter_Dealloc (& writer );
1955
+ goto Done ;
1991
1956
}
1992
1957
1993
1958
/* ---------------------------------------------------------------------------
0 commit comments