2727#define TYPE_COMPLEX 'x'
2828#define TYPE_LONG 'l'
2929#define TYPE_STRING 's'
30+ #define TYPE_INTERNED 't'
31+ #define TYPE_STRINGREF 'R'
3032#define TYPE_TUPLE '('
3133#define TYPE_LIST '['
3234#define TYPE_DICT '{'
@@ -42,6 +44,7 @@ typedef struct {
4244 PyObject * str ;
4345 char * ptr ;
4446 char * end ;
47+ PyObject * strings ; /* dict on marshal, list on unmarshal */
4548} WFILE ;
4649
4750#define w_byte (c , p ) if (((p)->fp)) putc((c), (p)->fp); \
@@ -189,7 +192,24 @@ w_object(PyObject *v, WFILE *p)
189192 }
190193#endif
191194 else if (PyString_Check (v )) {
192- w_byte (TYPE_STRING , p );
195+ if (p -> strings && PyString_CHECK_INTERNED (v )) {
196+ PyObject * o = PyDict_GetItem (p -> strings , v );
197+ if (o ) {
198+ long w = PyInt_AsLong (o );
199+ w_byte (TYPE_STRINGREF , p );
200+ w_long (w , p );
201+ goto exit ;
202+ }
203+ else {
204+ o = PyInt_FromLong (PyDict_Size (p -> strings ));
205+ PyDict_SetItem (p -> strings , v , o );
206+ Py_DECREF (o );
207+ w_byte (TYPE_INTERNED , p );
208+ }
209+ }
210+ else {
211+ w_byte (TYPE_STRING , p );
212+ }
193213 n = PyString_GET_SIZE (v );
194214 w_long ((long )n , p );
195215 w_string (PyString_AS_STRING (v ), n , p );
@@ -269,28 +289,32 @@ w_object(PyObject *v, WFILE *p)
269289 w_byte (TYPE_UNKNOWN , p );
270290 p -> error = 1 ;
271291 }
272-
292+ exit :
273293 p -> depth -- ;
274294}
275295
296+ /* version currently has no effect for writing longs. */
276297void
277- PyMarshal_WriteLongToFile (long x , FILE * fp )
298+ PyMarshal_WriteLongToFile (long x , FILE * fp , int version )
278299{
279300 WFILE wf ;
280301 wf .fp = fp ;
281302 wf .error = 0 ;
282303 wf .depth = 0 ;
304+ wf .strings = NULL ;
283305 w_long (x , & wf );
284306}
285307
286308void
287- PyMarshal_WriteObjectToFile (PyObject * x , FILE * fp )
309+ PyMarshal_WriteObjectToFile (PyObject * x , FILE * fp , int version )
288310{
289311 WFILE wf ;
290312 wf .fp = fp ;
291313 wf .error = 0 ;
292314 wf .depth = 0 ;
315+ wf .strings = (version > 0 ) ? PyDict_New () : NULL ;
293316 w_object (x , & wf );
317+ Py_XDECREF (wf .strings );
294318}
295319
296320typedef WFILE RFILE ; /* Same struct with different invariants */
@@ -491,6 +515,7 @@ r_object(RFILE *p)
491515 }
492516#endif
493517
518+ case TYPE_INTERNED :
494519 case TYPE_STRING :
495520 n = r_long (p );
496521 if (n < 0 ) {
@@ -506,6 +531,16 @@ r_object(RFILE *p)
506531 "EOF read where object expected" );
507532 }
508533 }
534+ if (type == TYPE_INTERNED ) {
535+ PyString_InternInPlace (& v );
536+ PyList_Append (p -> strings , v );
537+ }
538+ return v ;
539+
540+ case TYPE_STRINGREF :
541+ n = r_long (p );
542+ v = PyList_GET_ITEM (p -> strings , n );
543+ Py_INCREF (v );
509544 return v ;
510545
511546#ifdef Py_USING_UNICODE
@@ -673,6 +708,7 @@ PyMarshal_ReadShortFromFile(FILE *fp)
673708{
674709 RFILE rf ;
675710 rf .fp = fp ;
711+ rf .strings = NULL ;
676712 return r_short (& rf );
677713}
678714
@@ -681,6 +717,7 @@ PyMarshal_ReadLongFromFile(FILE *fp)
681717{
682718 RFILE rf ;
683719 rf .fp = fp ;
720+ rf .strings = NULL ;
684721 return r_long (& rf );
685722}
686723
@@ -747,22 +784,30 @@ PyObject *
747784PyMarshal_ReadObjectFromFile (FILE * fp )
748785{
749786 RFILE rf ;
787+ PyObject * result ;
750788 rf .fp = fp ;
751- return read_object (& rf );
789+ rf .strings = PyList_New (0 );
790+ result = r_object (& rf );
791+ Py_DECREF (rf .strings );
792+ return result ;
752793}
753794
754795PyObject *
755796PyMarshal_ReadObjectFromString (char * str , int len )
756797{
757798 RFILE rf ;
799+ PyObject * result ;
758800 rf .fp = NULL ;
759801 rf .ptr = str ;
760802 rf .end = str + len ;
761- return read_object (& rf );
803+ rf .strings = PyList_New (0 );
804+ result = r_object (& rf );
805+ Py_DECREF (rf .strings );
806+ return result ;
762807}
763808
764809PyObject *
765- PyMarshal_WriteObjectToString (PyObject * x ) /* wrs_object() */
810+ PyMarshal_WriteObjectToString (PyObject * x , int version )
766811{
767812 WFILE wf ;
768813 wf .fp = NULL ;
@@ -773,7 +818,9 @@ PyMarshal_WriteObjectToString(PyObject *x) /* wrs_object() */
773818 wf .end = wf .ptr + PyString_Size (wf .str );
774819 wf .error = 0 ;
775820 wf .depth = 0 ;
821+ wf .strings = (version > 0 ) ? PyDict_New () : NULL ;
776822 w_object (x , & wf );
823+ Py_XDECREF (wf .strings );
777824 if (wf .str != NULL )
778825 _PyString_Resize (& wf .str ,
779826 (int ) (wf .ptr -
@@ -796,7 +843,8 @@ marshal_dump(PyObject *self, PyObject *args)
796843 WFILE wf ;
797844 PyObject * x ;
798845 PyObject * f ;
799- if (!PyArg_ParseTuple (args , "OO:dump" , & x , & f ))
846+ int version = Py_MARSHAL_VERSION ;
847+ if (!PyArg_ParseTuple (args , "OO|i:dump" , & x , & f , & version ))
800848 return NULL ;
801849 if (!PyFile_Check (f )) {
802850 PyErr_SetString (PyExc_TypeError ,
@@ -808,7 +856,9 @@ marshal_dump(PyObject *self, PyObject *args)
808856 wf .ptr = wf .end = NULL ;
809857 wf .error = 0 ;
810858 wf .depth = 0 ;
859+ wf .strings = (version > 0 ) ? PyDict_New () : 0 ;
811860 w_object (x , & wf );
861+ Py_XDECREF (wf .strings );
812862 if (wf .error ) {
813863 PyErr_SetString (PyExc_ValueError ,
814864 (wf .error == 1 )?"unmarshallable object"
@@ -823,7 +873,7 @@ static PyObject *
823873marshal_load (PyObject * self , PyObject * args )
824874{
825875 RFILE rf ;
826- PyObject * f ;
876+ PyObject * f , * result ;
827877 if (!PyArg_ParseTuple (args , "O:load" , & f ))
828878 return NULL ;
829879 if (!PyFile_Check (f )) {
@@ -832,16 +882,20 @@ marshal_load(PyObject *self, PyObject *args)
832882 return NULL ;
833883 }
834884 rf .fp = PyFile_AsFile (f );
835- return read_object (& rf );
885+ rf .strings = PyList_New (0 );
886+ result = read_object (& rf );
887+ Py_DECREF (rf .strings );
888+ return result ;
836889}
837890
838891static PyObject *
839892marshal_dumps (PyObject * self , PyObject * args )
840893{
841894 PyObject * x ;
842- if (!PyArg_ParseTuple (args , "O:dumps" , & x ))
895+ int version = Py_MARSHAL_VERSION ;
896+ if (!PyArg_ParseTuple (args , "O|i:dumps" , & x , version ))
843897 return NULL ;
844- return PyMarshal_WriteObjectToString (x );
898+ return PyMarshal_WriteObjectToString (x , version );
845899}
846900
847901static PyObject *
@@ -850,12 +904,16 @@ marshal_loads(PyObject *self, PyObject *args)
850904 RFILE rf ;
851905 char * s ;
852906 int n ;
853- if (!PyArg_ParseTuple (args , "s#:loads" , & s , & n ))
907+ PyObject * result ;
908+ if (!PyArg_ParseTuple (args , "s#|i:loads" , & s , & n ))
854909 return NULL ;
855910 rf .fp = NULL ;
856911 rf .ptr = s ;
857912 rf .end = s + n ;
858- return read_object (& rf );
913+ rf .strings = PyList_New (0 );
914+ result = read_object (& rf );
915+ Py_DECREF (rf .strings );
916+ return result ;
859917}
860918
861919static PyMethodDef marshal_methods [] = {
@@ -869,5 +927,6 @@ static PyMethodDef marshal_methods[] = {
869927PyMODINIT_FUNC
870928PyMarshal_Init (void )
871929{
872- (void ) Py_InitModule ("marshal" , marshal_methods );
930+ PyObject * mod = Py_InitModule ("marshal" , marshal_methods );
931+ PyModule_AddIntConstant (mod , "version" , Py_MARSHAL_VERSION );
873932}
0 commit comments