@@ -2199,6 +2199,256 @@ PyConfig_GetInt(const char *name, int *value)
2199
2199
#endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION)
2200
2200
2201
2201
2202
+ #if PY_VERSION_HEX < 0x030E00A7
2203
+ typedef struct PyBytesWriter {
2204
+ char small_buffer[256 ];
2205
+ PyObject *obj;
2206
+ Py_ssize_t size;
2207
+ } PyBytesWriter;
2208
+
2209
+ static inline Py_ssize_t
2210
+ _PyBytesWriter_GetAllocated (PyBytesWriter *writer)
2211
+ {
2212
+ if (writer->obj == NULL ) {
2213
+ return sizeof (writer->small_buffer );
2214
+ }
2215
+ else {
2216
+ return PyBytes_GET_SIZE (writer->obj );
2217
+ }
2218
+ }
2219
+
2220
+
2221
+ static inline int
2222
+ _PyBytesWriter_Resize_impl (PyBytesWriter *writer, Py_ssize_t size,
2223
+ int overallocate)
2224
+ {
2225
+ assert (size >= 0 );
2226
+
2227
+ if (size <= _PyBytesWriter_GetAllocated (writer)) {
2228
+ return 0 ;
2229
+ }
2230
+
2231
+ if (overallocate) {
2232
+ #ifdef MS_WINDOWS
2233
+ /* On Windows, overallocate by 50% is the best factor */
2234
+ if (size <= (PY_SSIZE_T_MAX - size / 2 )) {
2235
+ size += size / 2 ;
2236
+ }
2237
+ #else
2238
+ /* On Linux, overallocate by 25% is the best factor */
2239
+ if (size <= (PY_SSIZE_T_MAX - size / 4 )) {
2240
+ size += size / 4 ;
2241
+ }
2242
+ #endif
2243
+ }
2244
+
2245
+ if (writer->obj != NULL ) {
2246
+ if (_PyBytes_Resize (&writer->obj , size)) {
2247
+ return -1 ;
2248
+ }
2249
+ assert (writer->obj != NULL );
2250
+ }
2251
+ else {
2252
+ writer->obj = PyBytes_FromStringAndSize (NULL , size);
2253
+ if (writer->obj == NULL ) {
2254
+ return -1 ;
2255
+ }
2256
+ assert ((size_t )size > sizeof (writer->small_buffer ));
2257
+ memcpy (PyBytes_AS_STRING (writer->obj ),
2258
+ writer->small_buffer ,
2259
+ sizeof (writer->small_buffer ));
2260
+ }
2261
+ return 0 ;
2262
+ }
2263
+
2264
+ static inline void *
2265
+ PyBytesWriter_GetData (PyBytesWriter *writer)
2266
+ {
2267
+ if (writer->obj == NULL ) {
2268
+ return writer->small_buffer ;
2269
+ }
2270
+ else {
2271
+ return PyBytes_AS_STRING (writer->obj );
2272
+ }
2273
+ }
2274
+
2275
+ static inline Py_ssize_t
2276
+ PyBytesWriter_GetSize (PyBytesWriter *writer)
2277
+ {
2278
+ return writer->size ;
2279
+ }
2280
+
2281
+ static inline void
2282
+ PyBytesWriter_Discard (PyBytesWriter *writer)
2283
+ {
2284
+ if (writer == NULL ) {
2285
+ return ;
2286
+ }
2287
+
2288
+ Py_XDECREF (writer->obj );
2289
+ PyMem_Free (writer);
2290
+ }
2291
+
2292
+ static inline PyBytesWriter*
2293
+ PyBytesWriter_Create (Py_ssize_t size)
2294
+ {
2295
+ if (size < 0 ) {
2296
+ PyErr_SetString (PyExc_ValueError, " size must be >= 0" );
2297
+ return NULL ;
2298
+ }
2299
+
2300
+ PyBytesWriter *writer = (PyBytesWriter*)PyMem_Malloc (sizeof (PyBytesWriter));
2301
+ if (writer == NULL ) {
2302
+ PyErr_NoMemory ();
2303
+ return NULL ;
2304
+ }
2305
+
2306
+ writer->obj = NULL ;
2307
+ writer->size = 0 ;
2308
+
2309
+ if (size >= 1 ) {
2310
+ if (_PyBytesWriter_Resize_impl (writer, size, 0 ) < 0 ) {
2311
+ PyBytesWriter_Discard (writer);
2312
+ return NULL ;
2313
+ }
2314
+ writer->size = size;
2315
+ }
2316
+ return writer;
2317
+ }
2318
+
2319
+ static inline PyObject*
2320
+ PyBytesWriter_FinishWithSize (PyBytesWriter *writer, Py_ssize_t size)
2321
+ {
2322
+ PyObject *result;
2323
+ if (size == 0 ) {
2324
+ result = PyBytes_FromStringAndSize (" " , 0 );
2325
+ }
2326
+ else if (writer->obj != NULL ) {
2327
+ if (size != PyBytes_GET_SIZE (writer->obj )) {
2328
+ if (_PyBytes_Resize (&writer->obj , size)) {
2329
+ goto error;
2330
+ }
2331
+ }
2332
+ result = writer->obj ;
2333
+ writer->obj = NULL ;
2334
+ }
2335
+ else {
2336
+ result = PyBytes_FromStringAndSize (writer->small_buffer , size);
2337
+ }
2338
+ PyBytesWriter_Discard (writer);
2339
+ return result;
2340
+
2341
+ error:
2342
+ PyBytesWriter_Discard (writer);
2343
+ return NULL ;
2344
+ }
2345
+
2346
+ static inline PyObject*
2347
+ PyBytesWriter_Finish (PyBytesWriter *writer)
2348
+ {
2349
+ return PyBytesWriter_FinishWithSize (writer, writer->size );
2350
+ }
2351
+
2352
+ static inline PyObject*
2353
+ PyBytesWriter_FinishWithPointer (PyBytesWriter *writer, void *buf)
2354
+ {
2355
+ Py_ssize_t size = (char *)buf - (char *)PyBytesWriter_GetData (writer);
2356
+ if (size < 0 || size > _PyBytesWriter_GetAllocated (writer)) {
2357
+ PyBytesWriter_Discard (writer);
2358
+ PyErr_SetString (PyExc_ValueError, " invalid end pointer" );
2359
+ return NULL ;
2360
+ }
2361
+
2362
+ return PyBytesWriter_FinishWithSize (writer, size);
2363
+ }
2364
+
2365
+ static inline int
2366
+ PyBytesWriter_Resize (PyBytesWriter *writer, Py_ssize_t size)
2367
+ {
2368
+ if (size < 0 ) {
2369
+ PyErr_SetString (PyExc_ValueError, " size must be >= 0" );
2370
+ return -1 ;
2371
+ }
2372
+ if (_PyBytesWriter_Resize_impl (writer, size, 1 ) < 0 ) {
2373
+ return -1 ;
2374
+ }
2375
+ writer->size = size;
2376
+ return 0 ;
2377
+ }
2378
+
2379
+ static inline int
2380
+ PyBytesWriter_Grow (PyBytesWriter *writer, Py_ssize_t size)
2381
+ {
2382
+ if (size < 0 && writer->size + size < 0 ) {
2383
+ PyErr_SetString (PyExc_ValueError, " invalid size" );
2384
+ return -1 ;
2385
+ }
2386
+ if (size > PY_SSIZE_T_MAX - writer->size ) {
2387
+ PyErr_NoMemory ();
2388
+ return -1 ;
2389
+ }
2390
+ size = writer->size + size;
2391
+
2392
+ if (_PyBytesWriter_Resize_impl (writer, size, 1 ) < 0 ) {
2393
+ return -1 ;
2394
+ }
2395
+ writer->size = size;
2396
+ return 0 ;
2397
+ }
2398
+
2399
+ static inline void *
2400
+ PyBytesWriter_GrowAndUpdatePointer (PyBytesWriter *writer,
2401
+ Py_ssize_t size, void *buf)
2402
+ {
2403
+ Py_ssize_t pos = (char *)buf - (char *)PyBytesWriter_GetData (writer);
2404
+ if (PyBytesWriter_Grow (writer, size) < 0 ) {
2405
+ return NULL ;
2406
+ }
2407
+ return (char *)PyBytesWriter_GetData (writer) + pos;
2408
+ }
2409
+
2410
+ static inline int
2411
+ PyBytesWriter_WriteBytes (PyBytesWriter *writer,
2412
+ const void *bytes, Py_ssize_t size)
2413
+ {
2414
+ if (size < 0 ) {
2415
+ size_t len = strlen ((const char *)bytes);
2416
+ if (len > (size_t )PY_SSIZE_T_MAX) {
2417
+ PyErr_NoMemory ();
2418
+ return -1 ;
2419
+ }
2420
+ size = (Py_ssize_t)len;
2421
+ }
2422
+
2423
+ Py_ssize_t pos = writer->size ;
2424
+ if (PyBytesWriter_Grow (writer, size) < 0 ) {
2425
+ return -1 ;
2426
+ }
2427
+ char *buf = (char *)PyBytesWriter_GetData (writer);
2428
+ memcpy (buf + pos, bytes, (size_t )size);
2429
+ return 0 ;
2430
+ }
2431
+
2432
+ static inline int
2433
+ PyBytesWriter_Format (PyBytesWriter *writer, const char *format, ...)
2434
+ {
2435
+ va_list vargs;
2436
+ va_start (vargs, format);
2437
+ PyObject *str = PyBytes_FromFormatV (format, vargs);
2438
+ va_end (vargs);
2439
+
2440
+ if (str == NULL ) {
2441
+ return -1 ;
2442
+ }
2443
+ int res = PyBytesWriter_WriteBytes (writer,
2444
+ PyBytes_AS_STRING (str),
2445
+ PyBytes_GET_SIZE (str));
2446
+ Py_DECREF (str);
2447
+ return res;
2448
+ }
2449
+ #endif // PY_VERSION_HEX < 0x030E00A7
2450
+
2451
+
2202
2452
#ifdef __cplusplus
2203
2453
}
2204
2454
#endif
0 commit comments