@@ -1501,7 +1501,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
1501
1501
PyObject * tzinfo = get_tzinfo_member (object );
1502
1502
1503
1503
if (tzinfo == Py_None || tzinfo == NULL ) {
1504
- return PyBytes_FromStringAndSize (NULL , 0 );
1504
+ return PyUnicode_FromStringAndSize (NULL , 0 );
1505
1505
}
1506
1506
1507
1507
assert (tzinfoarg != NULL );
@@ -1512,7 +1512,7 @@ make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg)
1512
1512
tzinfoarg ) < 0 )
1513
1513
return NULL ;
1514
1514
1515
- return PyBytes_FromStringAndSize (buf , strlen ( buf ) );
1515
+ return PyUnicode_FromString (buf );
1516
1516
}
1517
1517
1518
1518
static PyObject *
@@ -1569,7 +1569,7 @@ make_freplacement(PyObject *object)
1569
1569
else
1570
1570
sprintf (freplacement , "%06d" , 0 );
1571
1571
1572
- return PyBytes_FromStringAndSize (freplacement , strlen ( freplacement ) );
1572
+ return PyUnicode_FromString (freplacement );
1573
1573
}
1574
1574
1575
1575
/* 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,
1590
1590
PyObject * Zreplacement = NULL ; /* py string, replacement for %Z */
1591
1591
PyObject * freplacement = NULL ; /* py string, replacement for %f */
1592
1592
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
-
1606
1593
assert (object && format && timetuple );
1607
1594
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 ) {
1611
1598
return NULL ;
1599
+ }
1612
1600
1613
1601
/* Scan the input format, looking for %z/%Z/%f escapes, building
1614
1602
* a new format. Since computing the replacements for those codes
1615
1603
* is expensive, don't unless they're actually used.
1616
1604
*/
1617
- if (flen > INT_MAX - 1 ) {
1618
- PyErr_NoMemory ();
1619
- goto Done ;
1620
- }
1621
1605
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 ;
1632
1619
}
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 ;
1641
1624
}
1625
+ Py_UCS4 ch = PyUnicode_READ_CHAR (format , i );
1626
+ i ++ ;
1642
1627
/* A % has been seen and ch is the character after it. */
1643
- else if (ch == 'z' ) {
1628
+ PyObject * replacement = NULL ;
1629
+ if (ch == 'z' ) {
1644
1630
/* %z -> +HHMM */
1645
1631
if (zreplacement == NULL ) {
1646
1632
zreplacement = make_somezreplacement (object , "" , tzinfoarg );
1647
1633
if (zreplacement == NULL )
1648
- goto Done ;
1634
+ goto Error ;
1649
1635
}
1650
- assert (zreplacement != NULL );
1651
- assert (PyBytes_Check (zreplacement ));
1652
- ptoappend = PyBytes_AS_STRING (zreplacement );
1653
- ntoappend = PyBytes_GET_SIZE (zreplacement );
1636
+ replacement = zreplacement ;
1654
1637
}
1655
- else if (ch == ':' && * pin == 'z' && pin ++ ) {
1638
+ else if (ch == ':' && i < flen && PyUnicode_READ_CHAR ( format , i ) == 'z' ) {
1656
1639
/* %:z -> +HH:MM */
1640
+ i ++ ;
1657
1641
if (colonzreplacement == NULL ) {
1658
1642
colonzreplacement = make_somezreplacement (object , ":" , tzinfoarg );
1659
1643
if (colonzreplacement == NULL )
1660
- goto Done ;
1644
+ goto Error ;
1661
1645
}
1662
- assert (colonzreplacement != NULL );
1663
- assert (PyBytes_Check (colonzreplacement ));
1664
- ptoappend = PyBytes_AS_STRING (colonzreplacement );
1665
- ntoappend = PyBytes_GET_SIZE (colonzreplacement );
1646
+ replacement = colonzreplacement ;
1666
1647
}
1667
1648
else if (ch == 'Z' ) {
1668
1649
/* format tzname */
1669
1650
if (Zreplacement == NULL ) {
1670
1651
Zreplacement = make_Zreplacement (object ,
1671
1652
tzinfoarg );
1672
1653
if (Zreplacement == NULL )
1673
- goto Done ;
1654
+ goto Error ;
1674
1655
}
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 ;
1681
1657
}
1682
1658
else if (ch == 'f' ) {
1683
1659
/* format microseconds */
1684
1660
if (freplacement == NULL ) {
1685
1661
freplacement = make_freplacement (object );
1686
1662
if (freplacement == NULL )
1687
- goto Done ;
1663
+ goto Error ;
1688
1664
}
1689
- assert (freplacement != NULL );
1690
- assert (PyBytes_Check (freplacement ));
1691
- ptoappend = PyBytes_AS_STRING (freplacement );
1692
- ntoappend = PyBytes_GET_SIZE (freplacement );
1665
+ replacement = freplacement ;
1693
1666
}
1694
1667
else {
1695
1668
/* 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 )
1704
1669
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 ;
1716
1670
}
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
+ }
1721
1680
} /* end while() */
1722
1681
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 ) {
1730
1693
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 );
1736
1694
}
1737
- Py_DECREF (strftime );
1738
1695
}
1696
+ result = PyObject_CallFunctionObjArgs (strftime ,
1697
+ newformat , timetuple , NULL );
1698
+ Py_DECREF (newformat );
1699
+
1739
1700
Done :
1740
1701
Py_XDECREF (freplacement );
1741
1702
Py_XDECREF (zreplacement );
1742
1703
Py_XDECREF (colonzreplacement );
1743
1704
Py_XDECREF (Zreplacement );
1744
- Py_XDECREF (newfmt );
1705
+ Py_XDECREF (strftime );
1745
1706
return result ;
1707
+
1708
+ Error :
1709
+ _PyUnicodeWriter_Dealloc (& writer );
1710
+ goto Done ;
1746
1711
}
1747
1712
1748
1713
/* ---------------------------------------------------------------------------
0 commit comments