@@ -2295,6 +2295,260 @@ PySys_GetOptionalAttr(PyObject *name, PyObject **value)
2295
2295
#endif // PY_VERSION_HEX < 0x030F00A1
2296
2296
2297
2297
2298
+ #if PY_VERSION_HEX < 0x030F00A1
2299
+ typedef struct PyBytesWriter {
2300
+ char small_buffer[256 ];
2301
+ PyObject *obj;
2302
+ Py_ssize_t size;
2303
+ } PyBytesWriter;
2304
+
2305
+ static inline Py_ssize_t
2306
+ _PyBytesWriter_GetAllocated (PyBytesWriter *writer)
2307
+ {
2308
+ if (writer->obj == NULL ) {
2309
+ return sizeof (writer->small_buffer );
2310
+ }
2311
+ else {
2312
+ return PyBytes_GET_SIZE (writer->obj );
2313
+ }
2314
+ }
2315
+
2316
+
2317
+ static inline int
2318
+ _PyBytesWriter_Resize_impl (PyBytesWriter *writer, Py_ssize_t size,
2319
+ int resize)
2320
+ {
2321
+ int overallocate = resize;
2322
+ assert (size >= 0 );
2323
+
2324
+ if (size <= _PyBytesWriter_GetAllocated (writer)) {
2325
+ return 0 ;
2326
+ }
2327
+
2328
+ if (overallocate) {
2329
+ #ifdef MS_WINDOWS
2330
+ /* On Windows, overallocate by 50% is the best factor */
2331
+ if (size <= (PY_SSIZE_T_MAX - size / 2 )) {
2332
+ size += size / 2 ;
2333
+ }
2334
+ #else
2335
+ /* On Linux, overallocate by 25% is the best factor */
2336
+ if (size <= (PY_SSIZE_T_MAX - size / 4 )) {
2337
+ size += size / 4 ;
2338
+ }
2339
+ #endif
2340
+ }
2341
+
2342
+ if (writer->obj != NULL ) {
2343
+ if (_PyBytes_Resize (&writer->obj , size)) {
2344
+ return -1 ;
2345
+ }
2346
+ assert (writer->obj != NULL );
2347
+ }
2348
+ else {
2349
+ writer->obj = PyBytes_FromStringAndSize (NULL , size);
2350
+ if (writer->obj == NULL ) {
2351
+ return -1 ;
2352
+ }
2353
+
2354
+ if (resize) {
2355
+ assert ((size_t )size > sizeof (writer->small_buffer ));
2356
+ memcpy (PyBytes_AS_STRING (writer->obj ),
2357
+ writer->small_buffer ,
2358
+ sizeof (writer->small_buffer ));
2359
+ }
2360
+ }
2361
+ return 0 ;
2362
+ }
2363
+
2364
+ static inline void *
2365
+ PyBytesWriter_GetData (PyBytesWriter *writer)
2366
+ {
2367
+ if (writer->obj == NULL ) {
2368
+ return writer->small_buffer ;
2369
+ }
2370
+ else {
2371
+ return PyBytes_AS_STRING (writer->obj );
2372
+ }
2373
+ }
2374
+
2375
+ static inline Py_ssize_t
2376
+ PyBytesWriter_GetSize (PyBytesWriter *writer)
2377
+ {
2378
+ return writer->size ;
2379
+ }
2380
+
2381
+ static inline void
2382
+ PyBytesWriter_Discard (PyBytesWriter *writer)
2383
+ {
2384
+ if (writer == NULL ) {
2385
+ return ;
2386
+ }
2387
+
2388
+ Py_XDECREF (writer->obj );
2389
+ PyMem_Free (writer);
2390
+ }
2391
+
2392
+ static inline PyBytesWriter*
2393
+ PyBytesWriter_Create (Py_ssize_t size)
2394
+ {
2395
+ if (size < 0 ) {
2396
+ PyErr_SetString (PyExc_ValueError, " size must be >= 0" );
2397
+ return NULL ;
2398
+ }
2399
+
2400
+ PyBytesWriter *writer = (PyBytesWriter*)PyMem_Malloc (sizeof (PyBytesWriter));
2401
+ if (writer == NULL ) {
2402
+ PyErr_NoMemory ();
2403
+ return NULL ;
2404
+ }
2405
+
2406
+ writer->obj = NULL ;
2407
+ writer->size = 0 ;
2408
+
2409
+ if (size >= 1 ) {
2410
+ if (_PyBytesWriter_Resize_impl (writer, size, 0 ) < 0 ) {
2411
+ PyBytesWriter_Discard (writer);
2412
+ return NULL ;
2413
+ }
2414
+ writer->size = size;
2415
+ }
2416
+ return writer;
2417
+ }
2418
+
2419
+ static inline PyObject*
2420
+ PyBytesWriter_FinishWithSize (PyBytesWriter *writer, Py_ssize_t size)
2421
+ {
2422
+ PyObject *result;
2423
+ if (size == 0 ) {
2424
+ result = PyBytes_FromStringAndSize (" " , 0 );
2425
+ }
2426
+ else if (writer->obj != NULL ) {
2427
+ if (size != PyBytes_GET_SIZE (writer->obj )) {
2428
+ if (_PyBytes_Resize (&writer->obj , size)) {
2429
+ goto error;
2430
+ }
2431
+ }
2432
+ result = writer->obj ;
2433
+ writer->obj = NULL ;
2434
+ }
2435
+ else {
2436
+ result = PyBytes_FromStringAndSize (writer->small_buffer , size);
2437
+ }
2438
+ PyBytesWriter_Discard (writer);
2439
+ return result;
2440
+
2441
+ error:
2442
+ PyBytesWriter_Discard (writer);
2443
+ return NULL ;
2444
+ }
2445
+
2446
+ static inline PyObject*
2447
+ PyBytesWriter_Finish (PyBytesWriter *writer)
2448
+ {
2449
+ return PyBytesWriter_FinishWithSize (writer, writer->size );
2450
+ }
2451
+
2452
+ static inline PyObject*
2453
+ PyBytesWriter_FinishWithPointer (PyBytesWriter *writer, void *buf)
2454
+ {
2455
+ Py_ssize_t size = (char *)buf - (char *)PyBytesWriter_GetData (writer);
2456
+ if (size < 0 || size > _PyBytesWriter_GetAllocated (writer)) {
2457
+ PyBytesWriter_Discard (writer);
2458
+ PyErr_SetString (PyExc_ValueError, " invalid end pointer" );
2459
+ return NULL ;
2460
+ }
2461
+
2462
+ return PyBytesWriter_FinishWithSize (writer, size);
2463
+ }
2464
+
2465
+ static inline int
2466
+ PyBytesWriter_Resize (PyBytesWriter *writer, Py_ssize_t size)
2467
+ {
2468
+ if (size < 0 ) {
2469
+ PyErr_SetString (PyExc_ValueError, " size must be >= 0" );
2470
+ return -1 ;
2471
+ }
2472
+ if (_PyBytesWriter_Resize_impl (writer, size, 1 ) < 0 ) {
2473
+ return -1 ;
2474
+ }
2475
+ writer->size = size;
2476
+ return 0 ;
2477
+ }
2478
+
2479
+ static inline int
2480
+ PyBytesWriter_Grow (PyBytesWriter *writer, Py_ssize_t size)
2481
+ {
2482
+ if (size < 0 && writer->size + size < 0 ) {
2483
+ PyErr_SetString (PyExc_ValueError, " invalid size" );
2484
+ return -1 ;
2485
+ }
2486
+ if (size > PY_SSIZE_T_MAX - writer->size ) {
2487
+ PyErr_NoMemory ();
2488
+ return -1 ;
2489
+ }
2490
+ size = writer->size + size;
2491
+
2492
+ if (_PyBytesWriter_Resize_impl (writer, size, 1 ) < 0 ) {
2493
+ return -1 ;
2494
+ }
2495
+ writer->size = size;
2496
+ return 0 ;
2497
+ }
2498
+
2499
+ static inline void *
2500
+ PyBytesWriter_GrowAndUpdatePointer (PyBytesWriter *writer,
2501
+ Py_ssize_t size, void *buf)
2502
+ {
2503
+ Py_ssize_t pos = (char *)buf - (char *)PyBytesWriter_GetData (writer);
2504
+ if (PyBytesWriter_Grow (writer, size) < 0 ) {
2505
+ return NULL ;
2506
+ }
2507
+ return (char *)PyBytesWriter_GetData (writer) + pos;
2508
+ }
2509
+
2510
+ static inline int
2511
+ PyBytesWriter_WriteBytes (PyBytesWriter *writer,
2512
+ const void *bytes, Py_ssize_t size)
2513
+ {
2514
+ if (size < 0 ) {
2515
+ size_t len = strlen ((const char *)bytes);
2516
+ if (len > (size_t )PY_SSIZE_T_MAX) {
2517
+ PyErr_NoMemory ();
2518
+ return -1 ;
2519
+ }
2520
+ size = (Py_ssize_t)len;
2521
+ }
2522
+
2523
+ Py_ssize_t pos = writer->size ;
2524
+ if (PyBytesWriter_Grow (writer, size) < 0 ) {
2525
+ return -1 ;
2526
+ }
2527
+ char *buf = (char *)PyBytesWriter_GetData (writer);
2528
+ memcpy (buf + pos, bytes, (size_t )size);
2529
+ return 0 ;
2530
+ }
2531
+
2532
+ static inline int
2533
+ PyBytesWriter_Format (PyBytesWriter *writer, const char *format, ...)
2534
+ {
2535
+ va_list vargs;
2536
+ va_start (vargs, format);
2537
+ PyObject *str = PyBytes_FromFormatV (format, vargs);
2538
+ va_end (vargs);
2539
+
2540
+ if (str == NULL ) {
2541
+ return -1 ;
2542
+ }
2543
+ int res = PyBytesWriter_WriteBytes (writer,
2544
+ PyBytes_AS_STRING (str),
2545
+ PyBytes_GET_SIZE (str));
2546
+ Py_DECREF (str);
2547
+ return res;
2548
+ }
2549
+ #endif // PY_VERSION_HEX < 0x030F00A1
2550
+
2551
+
2298
2552
#ifdef __cplusplus
2299
2553
}
2300
2554
#endif
0 commit comments