@@ -28,12 +28,23 @@ import_librt_strings(void)
2828
2929static void * LibRTStrings_API [LIBRT_STRINGS_API_LEN ];
3030
31+ // Length of the default buffer embedded directly in a BytesWriter object
32+ #define WRITER_EMBEDDED_BUF_LEN 512
33+
34+ typedef struct {
35+ PyObject_HEAD
36+ char * buf ; // Beginning of the buffer
37+ Py_ssize_t len ; // Current length (number of bytes written)
38+ Py_ssize_t capacity ; // Total capacity of the buffer
39+ char data [WRITER_EMBEDDED_BUF_LEN ]; // Default buffer
40+ } BytesWriterObject ;
41+
3142#define LibRTStrings_ABIVersion (*(int (*)(void)) LibRTStrings_API[0])
3243#define LibRTStrings_APIVersion (*(int (*)(void)) LibRTStrings_API[1])
3344#define LibRTStrings_BytesWriter_internal (*(PyObject* (*)(void)) LibRTStrings_API[2])
3445#define LibRTStrings_BytesWriter_getvalue_internal (*(PyObject* (*)(PyObject *source)) LibRTStrings_API[3])
3546#define LibRTStrings_BytesWriter_append_internal (*(char (*)(PyObject *source, uint8_t value)) LibRTStrings_API[4])
36- #define LibRTStrings_BytesWriter_write_internal (*(char (*)(PyObject *source, PyObject *value )) LibRTStrings_API[5])
47+ #define LibRTStrings_ByteWriter_grow_buffer_internal (*(bool (*)(BytesWriterObject *obj, Py_ssize_t size )) LibRTStrings_API[5])
3748#define LibRTStrings_BytesWriter_type_internal (*(PyTypeObject* (*)(void)) LibRTStrings_API[6])
3849#define LibRTStrings_BytesWriter_len_internal (*(CPyTagged (*)(PyObject *self)) LibRTStrings_API[7])
3950#define LibRTStrings_BytesWriter_truncate_internal (*(char (*)(PyObject *self, int64_t size)) LibRTStrings_API[8])
@@ -75,6 +86,54 @@ static inline bool CPyBytesWriter_Check(PyObject *obj) {
7586 return Py_TYPE (obj ) == LibRTStrings_BytesWriter_type_internal ();
7687}
7788
89+ static inline bool
90+ CPyBytesWriter_EnsureSize (BytesWriterObject * data , Py_ssize_t n ) {
91+ if (likely (data -> capacity - data -> len >= n )) {
92+ return true;
93+ } else {
94+ return LibRTStrings_ByteWriter_grow_buffer_internal (data , n );
95+ }
96+ }
97+
98+ static inline char
99+ CPyBytesWriter_Append (PyObject * obj , uint8_t value ) {
100+ BytesWriterObject * self = (BytesWriterObject * )obj ;
101+ // Store length in a local variable to enable additional optimizations
102+ Py_ssize_t len = self -> len ;
103+ if (!CPyBytesWriter_EnsureSize (self , 1 ))
104+ return CPY_NONE_ERROR ;
105+ self -> buf [len ] = value ;
106+ self -> len = len + 1 ;
107+ return CPY_NONE ;
108+ }
109+
110+ static char
111+ CPyBytesWriter_Write (PyObject * obj , PyObject * value ) {
112+ BytesWriterObject * self = (BytesWriterObject * )obj ;
113+ const char * data ;
114+ Py_ssize_t size ;
115+ if (likely (PyBytes_Check (value ))) {
116+ data = PyBytes_AS_STRING (value );
117+ size = PyBytes_GET_SIZE (value );
118+ } else {
119+ data = PyByteArray_AS_STRING (value );
120+ size = PyByteArray_GET_SIZE (value );
121+ }
122+ // Write bytes content.
123+ if (!CPyBytesWriter_EnsureSize (self , size ))
124+ return CPY_NONE_ERROR ;
125+ if (size < 8 ) {
126+ char * p = self -> buf + self -> len ;
127+ for (Py_ssize_t i = 0 ; i < size ; i ++ ) {
128+ p [i ] = data [i ];
129+ }
130+ } else {
131+ memcpy (self -> buf + self -> len , data , size );
132+ }
133+ self -> len += size ;
134+ return CPY_NONE ;
135+ }
136+
78137#endif // MYPYC_EXPERIMENTAL
79138
80139#endif // LIBRT_STRINGS_H
0 commit comments