@@ -86,14 +86,105 @@ typedef struct {
86
86
char * ptr ;
87
87
const char * end ;
88
88
char * buf ;
89
- _Py_hashtable_t * hashtable ;
89
+ struct {
90
+ _Py_hashtable_t * hashtable ;
91
+ } refs ;
90
92
int version ;
91
93
} WFILE ;
92
94
93
- #define w_byte (c , p ) do { \
94
- if ((p)->ptr != (p)->end || w_reserve((p), 1)) \
95
- *(p)->ptr++ = (c); \
96
- } while(0)
95
+ static void
96
+ w_decref_entry (void * key )
97
+ {
98
+ PyObject * entry_key = (PyObject * )key ;
99
+ Py_XDECREF (entry_key );
100
+ }
101
+
102
+ static int
103
+ w_init_refs (WFILE * wf )
104
+ {
105
+ if (wf -> version >= 3 ) {
106
+ wf -> refs .hashtable = _Py_hashtable_new_full (_Py_hashtable_hash_ptr ,
107
+ _Py_hashtable_compare_direct ,
108
+ w_decref_entry , NULL , NULL );
109
+ if (wf -> refs .hashtable == NULL ) {
110
+ PyErr_NoMemory ();
111
+ return -1 ;
112
+ }
113
+ }
114
+ return 0 ;
115
+ }
116
+
117
+ static void
118
+ w_clear_refs (WFILE * wf )
119
+ {
120
+ if (wf -> refs .hashtable != NULL ) {
121
+ _Py_hashtable_destroy (wf -> refs .hashtable );
122
+ }
123
+ }
124
+
125
+ static int
126
+ w_init (WFILE * wf , FILE * fp , char * buf , int version )
127
+ {
128
+ memset (wf , 0 , sizeof (* wf ));
129
+ wf -> fp = fp ;
130
+ if (fp == NULL ) {
131
+ assert (buf == NULL );
132
+ wf -> str = PyBytes_FromStringAndSize ((char * )NULL , 50 );
133
+ if (wf -> str == NULL ) {
134
+ return -1 ;
135
+ }
136
+ wf -> ptr = wf -> buf = PyBytes_AS_STRING (wf -> str );
137
+ wf -> end = wf -> ptr + PyBytes_GET_SIZE (wf -> str );
138
+ }
139
+ else {
140
+ assert (buf != NULL );
141
+ wf -> ptr = wf -> buf = buf ;
142
+ wf -> end = wf -> ptr + sizeof (buf );
143
+ }
144
+ wf -> error = WFERR_OK ;
145
+ wf -> version = version ;
146
+ return 0 ;
147
+ }
148
+
149
+ static void
150
+ w_clear (WFILE * wf )
151
+ {
152
+ Py_XDECREF (wf -> str );
153
+ w_clear_refs (wf );
154
+ }
155
+
156
+ static int
157
+ w_handle_err (WFILE * wf )
158
+ {
159
+ if (wf -> error == WFERR_OK ) {
160
+ return 0 ;
161
+ }
162
+ if (wf -> error == WFERR_NOMEMORY ) {
163
+ PyErr_NoMemory ();
164
+ }
165
+ else {
166
+ PyErr_SetString (PyExc_ValueError ,
167
+ (wf -> error == WFERR_UNMARSHALLABLE ) ? "unmarshallable object"
168
+ : "object too deeply nested to marshal" );
169
+ }
170
+ return 1 ;
171
+ }
172
+
173
+ static PyObject *
174
+ w_finish_string (WFILE * wf )
175
+ {
176
+ if (wf -> str == NULL ) {
177
+ Py_RETURN_NONE ;
178
+ }
179
+ const char * base = PyBytes_AS_STRING (wf -> str );
180
+ if (_PyBytes_Resize (& wf -> str , (Py_ssize_t )(wf -> ptr - base )) < 0 ) {
181
+ return NULL ;
182
+ }
183
+ PyObject * finished = wf -> str ;
184
+ wf -> str = NULL ;
185
+ w_clear (wf );
186
+ return finished ;
187
+ }
97
188
98
189
static void
99
190
w_flush (WFILE * p )
@@ -138,6 +229,11 @@ w_reserve(WFILE *p, Py_ssize_t needed)
138
229
}
139
230
}
140
231
232
+ #define w_byte (c , p ) do { \
233
+ if ((p)->ptr != (p)->end || w_reserve((p), 1)) \
234
+ *(p)->ptr++ = (c); \
235
+ } while(0)
236
+
141
237
static void
142
238
w_string (const void * s , Py_ssize_t n , WFILE * p )
143
239
{
@@ -296,14 +392,14 @@ w_ref(PyObject *v, char *flag, WFILE *p)
296
392
_Py_hashtable_entry_t * entry ;
297
393
int w ;
298
394
299
- if (p -> version < 3 || p -> hashtable == NULL )
395
+ if (p -> version < 3 || p -> refs . hashtable == NULL )
300
396
return 0 ; /* not writing object references */
301
397
302
398
/* if it has only one reference, it definitely isn't shared */
303
399
if (Py_REFCNT (v ) == 1 )
304
400
return 0 ;
305
401
306
- entry = _Py_hashtable_get_entry (p -> hashtable , v );
402
+ entry = _Py_hashtable_get_entry (p -> refs . hashtable , v );
307
403
if (entry != NULL ) {
308
404
/* write the reference index to the stream */
309
405
w = (int )(uintptr_t )entry -> value ;
@@ -313,15 +409,15 @@ w_ref(PyObject *v, char *flag, WFILE *p)
313
409
w_long (w , p );
314
410
return 1 ;
315
411
} else {
316
- size_t s = p -> hashtable -> nentries ;
412
+ size_t s = p -> refs . hashtable -> nentries ;
317
413
/* we don't support long indices */
318
414
if (s >= 0x7fffffff ) {
319
415
PyErr_SetString (PyExc_ValueError , "too many objects" );
320
416
goto err ;
321
417
}
322
418
w = (int )s ;
323
419
Py_INCREF (v );
324
- if (_Py_hashtable_set (p -> hashtable , v , (void * )(uintptr_t )w ) < 0 ) {
420
+ if (_Py_hashtable_set (p -> refs . hashtable , v , (void * )(uintptr_t )w ) < 0 ) {
325
421
Py_DECREF (v );
326
422
goto err ;
327
423
}
@@ -583,72 +679,35 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
583
679
}
584
680
}
585
681
586
- static void
587
- w_decref_entry (void * key )
588
- {
589
- PyObject * entry_key = (PyObject * )key ;
590
- Py_XDECREF (entry_key );
591
- }
592
-
593
- static int
594
- w_init_refs (WFILE * wf , int version )
595
- {
596
- if (version >= 3 ) {
597
- wf -> hashtable = _Py_hashtable_new_full (_Py_hashtable_hash_ptr ,
598
- _Py_hashtable_compare_direct ,
599
- w_decref_entry , NULL , NULL );
600
- if (wf -> hashtable == NULL ) {
601
- PyErr_NoMemory ();
602
- return -1 ;
603
- }
604
- }
605
- return 0 ;
606
- }
607
-
608
- static void
609
- w_clear_refs (WFILE * wf )
610
- {
611
- if (wf -> hashtable != NULL ) {
612
- _Py_hashtable_destroy (wf -> hashtable );
613
- }
614
- }
615
-
616
682
/* version currently has no effect for writing ints. */
617
683
void
618
684
PyMarshal_WriteLongToFile (long x , FILE * fp , int version )
619
685
{
620
686
char buf [4 ];
621
687
WFILE wf ;
622
- memset (& wf , 0 , sizeof (wf ));
623
- wf .fp = fp ;
624
- wf .ptr = wf .buf = buf ;
625
- wf .end = wf .ptr + sizeof (buf );
626
- wf .error = WFERR_OK ;
627
- wf .version = version ;
688
+ (void )w_init (& wf , fp , buf , version );
628
689
w_long (x , & wf );
629
690
w_flush (& wf );
691
+ w_clear (& wf );
630
692
}
631
693
632
694
void
633
695
PyMarshal_WriteObjectToFile (PyObject * x , FILE * fp , int version )
634
696
{
635
- char buf [BUFSIZ ];
636
- WFILE wf ;
637
697
if (PySys_Audit ("marshal.dumps" , "Oi" , x , version ) < 0 ) {
638
698
return ; /* caller must check PyErr_Occurred() */
639
699
}
640
- memset (& wf , 0 , sizeof (wf ));
641
- wf .fp = fp ;
642
- wf .ptr = wf .buf = buf ;
643
- wf .end = wf .ptr + sizeof (buf );
644
- wf .error = WFERR_OK ;
645
- wf .version = version ;
646
- if (w_init_refs (& wf , version )) {
700
+
701
+ char buf [BUFSIZ ];
702
+ WFILE wf ;
703
+ (void )w_init (& wf , fp , buf , version );
704
+ if (w_init_refs (& wf ) != 0 ) {
705
+ w_clear (& wf );
647
706
return ; /* caller must check PyErr_Occurred() */
648
707
}
649
708
w_object (x , & wf );
650
- w_clear_refs (& wf );
651
709
w_flush (& wf );
710
+ w_clear (& wf );
652
711
}
653
712
654
713
typedef struct {
@@ -1648,41 +1707,24 @@ PyMarshal_ReadObjectFromString(const char *str, Py_ssize_t len)
1648
1707
PyObject *
1649
1708
PyMarshal_WriteObjectToString (PyObject * x , int version )
1650
1709
{
1651
- WFILE wf ;
1652
-
1653
1710
if (PySys_Audit ("marshal.dumps" , "Oi" , x , version ) < 0 ) {
1654
1711
return NULL ;
1655
1712
}
1656
- memset ( & wf , 0 , sizeof ( wf ));
1657
- wf . str = PyBytes_FromStringAndSize (( char * ) NULL , 50 ) ;
1658
- if (wf . str == NULL )
1713
+
1714
+ WFILE wf ;
1715
+ if (w_init ( & wf , NULL , NULL , version ) != 0 ) {
1659
1716
return NULL ;
1660
- wf .ptr = wf .buf = PyBytes_AS_STRING (wf .str );
1661
- wf .end = wf .ptr + PyBytes_GET_SIZE (wf .str );
1662
- wf .error = WFERR_OK ;
1663
- wf .version = version ;
1664
- if (w_init_refs (& wf , version )) {
1665
- Py_DECREF (wf .str );
1717
+ }
1718
+ if (w_init_refs (& wf ) != 0 ) {
1719
+ w_clear (& wf );
1666
1720
return NULL ;
1667
1721
}
1668
1722
w_object (x , & wf );
1669
- w_clear_refs (& wf );
1670
- if (wf .str != NULL ) {
1671
- const char * base = PyBytes_AS_STRING (wf .str );
1672
- if (_PyBytes_Resize (& wf .str , (Py_ssize_t )(wf .ptr - base )) < 0 )
1673
- return NULL ;
1674
- }
1675
- if (wf .error != WFERR_OK ) {
1676
- Py_XDECREF (wf .str );
1677
- if (wf .error == WFERR_NOMEMORY )
1678
- PyErr_NoMemory ();
1679
- else
1680
- PyErr_SetString (PyExc_ValueError ,
1681
- (wf .error == WFERR_UNMARSHALLABLE )?"unmarshallable object"
1682
- :"object too deeply nested to marshal" );
1723
+ if (w_handle_err (& wf )) {
1724
+ w_clear (& wf );
1683
1725
return NULL ;
1684
1726
}
1685
- return wf . str ;
1727
+ return w_finish_string ( & wf ) ;
1686
1728
}
1687
1729
1688
1730
/* And an interface for Python programs... */
0 commit comments