diff options
author | Adrian Thurston <thurston@complang.org> | 2012-01-02 20:24:43 +0000 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2012-01-02 20:24:43 +0000 |
commit | 38e5314851fba1e548ea687519044644a8941879 (patch) | |
tree | 8f25cc8d3743872aeb163c378b897f9a15fe1f39 | |
parent | ec497371a7fcab2aa2b0bbb21cb4c5064d5970e1 (diff) | |
download | colm-38e5314851fba1e548ea687519044644a8941879.tar.gz |
Need symmetrical do/undo for append/prepend to streams. Can't use the consume
functions because in some instances streams are called.
The undo of the prepend needs to distinguish between tree and data.
-rw-r--r-- | colm/input.c | 127 | ||||
-rw-r--r-- | colm/input.h | 6 | ||||
-rw-r--r-- | colm/pdarun.c | 29 |
3 files changed, 101 insertions, 61 deletions
diff --git a/colm/input.c b/colm/input.c index ceed6bf3..a4deb06c 100644 --- a/colm/input.c +++ b/colm/input.c @@ -632,54 +632,97 @@ void undoConsumeLangEl( InputStream *is ) } } - void prependData( InputStream *is, const char *data, long length ) { -/// if ( isSourceStream( is ) ) { -/// Stream *stream = (Stream*)is->queue->tree; -/// return stream->in->funcs->prependData( stream->in, data, length ); -/// } -/// else { - // #ifdef COLM_LOG_PARSE - // if ( colm_log_parse ) { - // cerr << "readying fake push" << endl; - // } - // #endif - - // takeBackBuffered( inputStream ); - - /* Create a new buffer for the data. This is the easy implementation. - * Something better is needed here. It puts a max on the amount of - * data that can be pushed back to the inputStream. */ - assert( length < FSM_BUFSIZE ); + /* Create a new buffer for the data. This is the easy implementation. + * Something better is needed here. It puts a max on the amount of + * data that can be pushed back to the inputStream. */ + assert( length < FSM_BUFSIZE ); - RunBuf *newBuf = newRunBuf(); - newBuf->length = length; - memcpy( newBuf->data, data, length ); + RunBuf *newBuf = newRunBuf(); + newBuf->length = length; + memcpy( newBuf->data, data, length ); - inputStreamPrepend( is, newBuf ); -// } + inputStreamPrepend( is, newBuf ); } -Tree *undoPrependData( InputStream *is, int length ) +int undoPrependData( InputStream *is, int length ) { -// if ( isSourceStream( is ) ) { -// Stream *stream = (Stream*)is->queue->tree; -// return stream->in->funcs->undoPrependData( stream->in, length ); -// } -// else { - if ( is->queue->type == RunBufDataType ) { - consumeData( is, length ); - return 0; + debug( REALM_INPUT, "consuming %d bytes\n", length ); + + int consumed = 0; + + /* Move over skip bytes. */ + while ( true ) { + RunBuf *buf = is->queue; + + if ( buf == 0 ) + break; + + if ( buf->type == RunBufSourceType ) { + Stream *stream = (Stream*)buf->tree; + int slen = stream->in->funcs->consumeData( stream->in, length ); + + consumed += slen; + length -= slen; } + else if ( buf->type == RunBufTokenType ) + break; + else if ( buf->type == RunBufIgnoreType ) + break; else { - /* FIXME: leak here. */ - RunBuf *rb = inputStreamPopHead( is ); - Tree *tree = rb->tree; - free(rb); - return tree; + /* Anything available in the current buffer. */ + int avail = buf->length - buf->offset; + if ( avail > 0 ) { + /* The source data from the current buffer. */ + int slen = avail <= length ? avail : length; + consumed += slen; + length -= slen; + buf->offset += slen; + } } -// } + + if ( length == 0 ) + break; + + RunBuf *runBuf = inputStreamPopHead( is ); + free( runBuf ); + } + + return consumed; +} + +void prependTree( InputStream *is, Tree *tree, int ignore ) +{ + if ( is->attached1 != 0 ) + detachInput1( is->attached1, is ); + + /* Create a new buffer for the data. This is the easy implementation. + * Something better is needed here. It puts a max on the amount of + * data that can be pushed back to the inputStream. */ + RunBuf *newBuf = newRunBuf(); + newBuf->type = ignore ? RunBufIgnoreType : RunBufTokenType; + newBuf->tree = tree; + inputStreamPrepend( is, newBuf ); +} + +Tree *undoPrependTree( InputStream *is ) +{ + while ( is->queue != 0 && is->queue->type == RunBufDataType && is->queue->offset == is->queue->length ) { + RunBuf *runBuf = inputStreamPopHead( is ); + free( runBuf ); + } + + if ( is->queue != 0 && (is->queue->type == RunBufTokenType || is->queue->type == RunBufIgnoreType) ) { + RunBuf *runBuf = inputStreamPopHead( is ); + + /* FIXME: using runbufs here for this is a poor use of memory. */ + Tree *tree = runBuf->tree; + free(runBuf); + return tree; + } + + return 0; } void appendData( InputStream *is, const char *data, long len ) @@ -766,3 +809,11 @@ Tree *undoAppendStream( InputStream *in ) free( runBuf ); return tree; } + +Tree *undoAppendTree( InputStream *in ) +{ + RunBuf *runBuf = inputStreamPopTail( in ); + Tree *tree = runBuf->tree; + free( runBuf ); + return tree; +} diff --git a/colm/input.h b/colm/input.h index 0f43eaaa..773b1bc8 100644 --- a/colm/input.h +++ b/colm/input.h @@ -195,13 +195,17 @@ void setEof( InputStream *is ); void unsetEof( InputStream *is ); void prependData( InputStream *in, const char *data, long len ); -struct ColmTree *undoPrependData( InputStream *in, int length ); +int undoPrependData( InputStream *is, int length ); + +void prependTree( InputStream *is, struct ColmTree *tree, int ignore ); +struct ColmTree *undoPrependTree( InputStream *is ); void appendData( InputStream *in, const char *data, long len ); void appendTree( InputStream *in, struct ColmTree *tree ); void appendStream( InputStream *in, struct ColmTree *tree ); struct ColmTree *undoAppendData( InputStream *in, int length ); struct ColmTree *undoAppendStream( InputStream *in ); +struct ColmTree *undoAppendTree( InputStream *in ); #ifdef __cplusplus } diff --git a/colm/pdarun.c b/colm/pdarun.c index f2e6317a..4e991da8 100644 --- a/colm/pdarun.c +++ b/colm/pdarun.c @@ -171,23 +171,25 @@ void streamPushText( FsmRun *fsmRun, InputStream *inputStream, const char *data, void streamPushTree( FsmRun *fsmRun, InputStream *inputStream, Tree *tree, int ignore ) { - undoConsumeTree( inputStream, tree, ignore ); + prependTree( inputStream, tree, ignore ); } void undoStreamPush( Program *prg, Tree **sp, FsmRun *fsmRun, InputStream *inputStream, long length ) { if ( length < 0 ) - consumeTree( inputStream ); + undoPrependTree( inputStream ); else - consumeData( inputStream, length ); + undoPrependData( inputStream, length ); } void undoStreamAppend( Program *prg, Tree **sp, FsmRun *fsmRun, InputStream *inputStream, Tree *input, long length ) { - if ( input->id == LEL_ID_STREAM ) + if ( input->id == LEL_ID_STR ) + undoAppendData( inputStream, length ); + else if ( input->id == LEL_ID_STREAM ) undoAppendStream( inputStream ); else - undoAppendData( inputStream, length ); + undoAppendTree( inputStream ); } /* Should only be sending back whole tokens/ignores, therefore the send back @@ -200,24 +202,7 @@ static void sendBackText( FsmRun *fsmRun, InputStream *inputStream, const char * if ( length == 0 ) return; -// if ( fsmRun->p == fsmRun->runBuf->data ) -// sendBackRunBufHead( fsmRun, inputStream ); - - /* If there is data in the current buffer then send the whole send back - * should be in this buffer. */ - //clearBuffered( fsmRun ); - - /* slide data back. */ -// fsmRun->p = fsmRun->pe = fsmRun->runBuf->data; undoConsumeData( fsmRun, inputStream, data, length ); - -// #if COLM_LOG -// if ( memcmp( data, fsmRun->p, length ) != 0 ) -// debug( REALM_PARSE, "mismatch of pushed back text\n" ); -// #endif - -// assert( memcmp( data, fsmRun->p, length ) == 0 ); - undoPosition( inputStream, data, length ); } |