@@ -1501,7 +1501,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
15011501 PyObject * tzinfo = get_tzinfo_member (object );
15021502
15031503 if (tzinfo == Py_None || tzinfo == NULL ) {
1504- return PyBytes_FromStringAndSize (NULL , 0 );
1504+ return PyUnicode_FromStringAndSize (NULL , 0 );
15051505 }
15061506
15071507 assert (tzinfoarg != NULL );
@@ -1512,7 +1512,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
15121512 tzinfoarg ) < 0 )
15131513 return NULL ;
15141514
1515- return PyBytes_FromStringAndSize (buf , strlen ( buf ) );
1515+ return PyUnicode_FromString (buf );
15161516}
15171517
15181518static PyObject *
@@ -1569,7 +1569,7 @@ make_freplacement(PyObject *object)
15691569 else
15701570 sprintf (freplacement , "%06d" , 0 );
15711571
1572- return PyBytes_FromStringAndSize (freplacement , strlen ( freplacement ) );
1572+ return PyUnicode_FromString (freplacement );
15731573}
15741574
15751575/* I sure don't want to reproduce the strftime code from the time module,
@@ -1590,159 +1590,124 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
15901590 PyObject * Zreplacement = NULL ; /* py string, replacement for %Z */
15911591 PyObject * freplacement = NULL ; /* py string, replacement for %f */
15921592
1593- const char * pin ; /* pointer to next char in input format */
1594- Py_ssize_t flen ; /* length of input format */
1595- char ch ; /* next char in input format */
1596-
1597- PyObject * newfmt = NULL ; /* py string, the output format */
1598- char * pnew ; /* pointer to available byte in output format */
1599- size_t totalnew ; /* number bytes total in output format buffer,
1600- exclusive of trailing \0 */
1601- size_t usednew ; /* number bytes used so far in output format buffer */
1602-
1603- const char * ptoappend ; /* ptr to string to append to output buffer */
1604- Py_ssize_t ntoappend ; /* # of bytes to append to output buffer */
1605-
16061593 assert (object && format && timetuple );
16071594 assert (PyUnicode_Check (format ));
1608- /* Convert the input format to a C string and size */
1609- pin = PyUnicode_AsUTF8AndSize ( format , & flen );
1610- if (! pin )
1595+
1596+ PyObject * strftime = _PyImport_GetModuleAttrString ( "time" , "strftime" );
1597+ if (strftime == NULL ) {
16111598 return NULL ;
1599+ }
16121600
16131601 /* Scan the input format, looking for %z/%Z/%f escapes, building
16141602 * a new format. Since computing the replacements for those codes
16151603 * is expensive, don't unless they're actually used.
16161604 */
1617- if (flen > INT_MAX - 1 ) {
1618- PyErr_NoMemory ();
1619- goto Done ;
1620- }
16211605
1622- totalnew = flen + 1 ; /* realistic if no %z/%Z */
1623- newfmt = PyBytes_FromStringAndSize (NULL , totalnew );
1624- if (newfmt == NULL ) goto Done ;
1625- pnew = PyBytes_AsString (newfmt );
1626- usednew = 0 ;
1627-
1628- while ((ch = * pin ++ ) != '\0' ) {
1629- if (ch != '%' ) {
1630- ptoappend = pin - 1 ;
1631- ntoappend = 1 ;
1606+ _PyUnicodeWriter writer ;
1607+ _PyUnicodeWriter_Init (& writer );
1608+ writer .overallocate = 1 ;
1609+
1610+ Py_ssize_t flen = PyUnicode_GET_LENGTH (format );
1611+ Py_ssize_t i = 0 ;
1612+ Py_ssize_t start = 0 ;
1613+ Py_ssize_t end = 0 ;
1614+ while (i != flen ) {
1615+ i = PyUnicode_FindChar (format , '%' , i , flen , 1 );
1616+ if (i < 0 ) {
1617+ assert (!PyErr_Occurred ());
1618+ break ;
16321619 }
1633- else if ((ch = * pin ++ ) == '\0' ) {
1634- /* Null byte follows %, copy only '%'.
1635- *
1636- * Back the pin up one char so that we catch the null check
1637- * the next time through the loop.*/
1638- pin -- ;
1639- ptoappend = pin - 1 ;
1640- ntoappend = 1 ;
1620+ end = i ;
1621+ i ++ ;
1622+ if (i == flen ) {
1623+ break ;
16411624 }
1625+ Py_UCS4 ch = PyUnicode_READ_CHAR (format , i );
1626+ i ++ ;
16421627 /* A % has been seen and ch is the character after it. */
1643- else if (ch == 'z' ) {
1628+ PyObject * replacement = NULL ;
1629+ if (ch == 'z' ) {
16441630 /* %z -> +HHMM */
16451631 if (zreplacement == NULL ) {
16461632 zreplacement = make_somezreplacement (object , "" , tzinfoarg );
16471633 if (zreplacement == NULL )
1648- goto Done ;
1634+ goto Error ;
16491635 }
1650- assert (zreplacement != NULL );
1651- assert (PyBytes_Check (zreplacement ));
1652- ptoappend = PyBytes_AS_STRING (zreplacement );
1653- ntoappend = PyBytes_GET_SIZE (zreplacement );
1636+ replacement = zreplacement ;
16541637 }
1655- else if (ch == ':' && * pin == 'z' && pin ++ ) {
1638+ else if (ch == ':' && i < flen && PyUnicode_READ_CHAR ( format , i ) == 'z' ) {
16561639 /* %:z -> +HH:MM */
1640+ i ++ ;
16571641 if (colonzreplacement == NULL ) {
16581642 colonzreplacement = make_somezreplacement (object , ":" , tzinfoarg );
16591643 if (colonzreplacement == NULL )
1660- goto Done ;
1644+ goto Error ;
16611645 }
1662- assert (colonzreplacement != NULL );
1663- assert (PyBytes_Check (colonzreplacement ));
1664- ptoappend = PyBytes_AS_STRING (colonzreplacement );
1665- ntoappend = PyBytes_GET_SIZE (colonzreplacement );
1646+ replacement = colonzreplacement ;
16661647 }
16671648 else if (ch == 'Z' ) {
16681649 /* format tzname */
16691650 if (Zreplacement == NULL ) {
16701651 Zreplacement = make_Zreplacement (object ,
16711652 tzinfoarg );
16721653 if (Zreplacement == NULL )
1673- goto Done ;
1654+ goto Error ;
16741655 }
1675- assert (Zreplacement != NULL );
1676- assert (PyUnicode_Check (Zreplacement ));
1677- ptoappend = PyUnicode_AsUTF8AndSize (Zreplacement ,
1678- & ntoappend );
1679- if (ptoappend == NULL )
1680- goto Done ;
1656+ replacement = Zreplacement ;
16811657 }
16821658 else if (ch == 'f' ) {
16831659 /* format microseconds */
16841660 if (freplacement == NULL ) {
16851661 freplacement = make_freplacement (object );
16861662 if (freplacement == NULL )
1687- goto Done ;
1663+ goto Error ;
16881664 }
1689- assert (freplacement != NULL );
1690- assert (PyBytes_Check (freplacement ));
1691- ptoappend = PyBytes_AS_STRING (freplacement );
1692- ntoappend = PyBytes_GET_SIZE (freplacement );
1665+ replacement = freplacement ;
16931666 }
16941667 else {
16951668 /* percent followed by something else */
1696- ptoappend = pin - 2 ;
1697- ntoappend = 2 ;
1698- }
1699-
1700- /* Append the ntoappend chars starting at ptoappend to
1701- * the new format.
1702- */
1703- if (ntoappend == 0 )
17041669 continue ;
1705- assert (ptoappend != NULL );
1706- assert (ntoappend > 0 );
1707- while (usednew + ntoappend > totalnew ) {
1708- if (totalnew > (PY_SSIZE_T_MAX >> 1 )) { /* overflow */
1709- PyErr_NoMemory ();
1710- goto Done ;
1711- }
1712- totalnew <<= 1 ;
1713- if (_PyBytes_Resize (& newfmt , totalnew ) < 0 )
1714- goto Done ;
1715- pnew = PyBytes_AsString (newfmt ) + usednew ;
17161670 }
1717- memcpy (pnew , ptoappend , ntoappend );
1718- pnew += ntoappend ;
1719- usednew += ntoappend ;
1720- assert (usednew <= totalnew );
1671+ assert (replacement != NULL );
1672+ assert (PyUnicode_Check (replacement ));
1673+ if (_PyUnicodeWriter_WriteSubstring (& writer , format , start , end ) < 0 ) {
1674+ goto Error ;
1675+ }
1676+ start = i ;
1677+ if (_PyUnicodeWriter_WriteStr (& writer , replacement ) < 0 ) {
1678+ goto Error ;
1679+ }
17211680 } /* end while() */
17221681
1723- if (_PyBytes_Resize (& newfmt , usednew ) < 0 )
1724- goto Done ;
1725- {
1726- PyObject * format ;
1727- PyObject * strftime = _PyImport_GetModuleAttrString ("time" , "strftime" );
1728-
1729- if (strftime == NULL )
1682+ PyObject * newformat ;
1683+ if (start == 0 ) {
1684+ _PyUnicodeWriter_Dealloc (& writer );
1685+ newformat = Py_NewRef (format );
1686+ }
1687+ else {
1688+ if (_PyUnicodeWriter_WriteSubstring (& writer , format , start , flen ) < 0 ) {
1689+ goto Error ;
1690+ }
1691+ newformat = _PyUnicodeWriter_Finish (& writer );
1692+ if (newformat == NULL ) {
17301693 goto Done ;
1731- format = PyUnicode_FromString (PyBytes_AS_STRING (newfmt ));
1732- if (format != NULL ) {
1733- result = PyObject_CallFunctionObjArgs (strftime ,
1734- format , timetuple , NULL );
1735- Py_DECREF (format );
17361694 }
1737- Py_DECREF (strftime );
17381695 }
1696+ result = PyObject_CallFunctionObjArgs (strftime ,
1697+ newformat , timetuple , NULL );
1698+ Py_DECREF (newformat );
1699+
17391700 Done :
17401701 Py_XDECREF (freplacement );
17411702 Py_XDECREF (zreplacement );
17421703 Py_XDECREF (colonzreplacement );
17431704 Py_XDECREF (Zreplacement );
1744- Py_XDECREF (newfmt );
1705+ Py_XDECREF (strftime );
17451706 return result ;
1707+
1708+ Error :
1709+ _PyUnicodeWriter_Dealloc (& writer );
1710+ goto Done ;
17461711}
17471712
17481713/* ---------------------------------------------------------------------------
0 commit comments