@@ -886,3 +886,73 @@ static PyObject* connect_deltas(PyObject *self, PyObject *dstreams)
886886 return (PyObject * )dcl ;
887887}
888888
889+
890+ // Write using a write function, taking remaining bytes from a base buffer
891+ // replaces the corresponding method in python
892+ static
893+ PyObject * apply_delta (PyObject * self , PyObject * args )
894+ {
895+ PyObject * pybbuf = 0 ;
896+ PyObject * pydbuf = 0 ;
897+ PyObject * pytbuf = 0 ;
898+ if (!PyArg_ParseTuple (args , "OOO" , & pybbuf , & pydbuf , & pytbuf )){
899+ PyErr_BadArgument ();
900+ return NULL ;
901+ }
902+
903+ PyObject * objects [] = { pybbuf , pydbuf , pytbuf };
904+ assert (sizeof (objects ) / sizeof (PyObject * ) == 3 );
905+
906+ uint i ;
907+ for (i = 0 ; i < 3 ; i ++ ){
908+ if (!PyObject_CheckReadBuffer (objects [i ])){
909+ PyErr_SetString (PyExc_ValueError , "Argument must be a buffer-compatible object, like a string, or a memory map" );
910+ return NULL ;
911+ }
912+ }
913+
914+ Py_ssize_t lbbuf ; Py_ssize_t ldbuf ; Py_ssize_t ltbuf ;
915+ const uchar * bbuf ; const uchar * dbuf ;
916+ uchar * tbuf ;
917+ PyObject_AsReadBuffer (pybbuf , (const void * * )(& bbuf ), & lbbuf );
918+ PyObject_AsReadBuffer (pydbuf , (const void * * )(& dbuf ), & ldbuf );
919+
920+ if (PyObject_AsWriteBuffer (pytbuf , (void * * )(& tbuf ), & ltbuf )){
921+ PyErr_SetString (PyExc_ValueError , "Argument 3 must be a writable buffer" );
922+ return NULL ;
923+ }
924+
925+ const uchar * data = dbuf ;
926+ const uchar * dend = dbuf + ldbuf ;
927+
928+ while (data < dend )
929+ {
930+ const char cmd = * data ++ ;
931+
932+ if (cmd & 0x80 )
933+ {
934+ unsigned long cp_off = 0 , cp_size = 0 ;
935+ if (cmd & 0x01 ) cp_off = * data ++ ;
936+ if (cmd & 0x02 ) cp_off |= (* data ++ << 8 );
937+ if (cmd & 0x04 ) cp_off |= (* data ++ << 16 );
938+ if (cmd & 0x08 ) cp_off |= ((unsigned ) * data ++ << 24 );
939+ if (cmd & 0x10 ) cp_size = * data ++ ;
940+ if (cmd & 0x20 ) cp_size |= (* data ++ << 8 );
941+ if (cmd & 0x40 ) cp_size |= (* data ++ << 16 );
942+ if (cp_size == 0 ) cp_size = 0x10000 ;
943+
944+ memcpy (tbuf , bbuf + cp_off , cp_size );
945+ tbuf += cp_size ;
946+
947+ } else if (cmd ) {
948+ memcpy (tbuf , data , cmd );
949+ tbuf += cmd ;
950+ data += cmd ;
951+ } else {
952+ PyErr_SetString (PyExc_RuntimeError , "Encountered an unsupported delta cmd: 0" );
953+ return NULL ;
954+ }
955+ }// END handle command opcodes
956+
957+ Py_RETURN_NONE ;
958+ }
0 commit comments