Update internal state before callback; that way, if during the callback we inject some more data
into the parser (e.g. it's an <include> tag or something), the parser is in the correct state.
This commit is contained in:
		
							parent
							
								
									f1fa8b5625
								
							
						
					
					
						commit
						71fda14981
					
				| 
						 | 
				
			
			@ -141,8 +141,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
 | 
			
		||||
    if(ch == xmlRestartMarker[ctx->restartCount]) {
 | 
			
		||||
        if(++ctx->restartCount == 11) {
 | 
			
		||||
            csxml_reset(ctx);
 | 
			
		||||
            ctx->state = StateRestartMarker;
 | 
			
		||||
            csxml_reset(ctx);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -179,8 +179,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
            break;
 | 
			
		||||
 | 
			
		||||
        case ClassOpenTag:
 | 
			
		||||
            if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data));
 | 
			
		||||
            ctx->state = StateOpen;
 | 
			
		||||
            if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data));
 | 
			
		||||
            CLEAR_BUFFER(buffer);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -197,8 +197,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
            // fall through
 | 
			
		||||
        default:
 | 
			
		||||
            if(!ctx->elementDepth) ERROR("Content cannot appear at stream level.");
 | 
			
		||||
            if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data));
 | 
			
		||||
            ctx->state = StateData;
 | 
			
		||||
            if(ctx->buffer.len) TRY(ctx->whiteSpace(ctx, ctx->buffer.data));
 | 
			
		||||
            CLEAR_BUFFER(buffer);
 | 
			
		||||
            APPEND_CH(buffer, ch);
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -208,9 +208,9 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
    case StateData:
 | 
			
		||||
        switch(c) {
 | 
			
		||||
        case ClassOpenTag:
 | 
			
		||||
            ctx->state = StateOpen;
 | 
			
		||||
            TRY(ctx->content(ctx, ctx->buffer.data));
 | 
			
		||||
            CLEAR_BUFFER(buffer);
 | 
			
		||||
            ctx->state = StateOpen;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case ClassEntity:
 | 
			
		||||
| 
						 | 
				
			
			@ -240,9 +240,9 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
 | 
			
		||||
    case StateCDATA2:
 | 
			
		||||
        if(ch == '>') {
 | 
			
		||||
            ctx->state = StateNone;
 | 
			
		||||
            TRY(ctx->cdata(ctx, ctx->buffer.data));
 | 
			
		||||
            CLEAR_BUFFER(buffer);
 | 
			
		||||
            ctx->state = StateNone;
 | 
			
		||||
        } else if(ch == ']') {
 | 
			
		||||
            APPEND_CH(buffer, ']');
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -317,8 +317,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
    case StatePI2:
 | 
			
		||||
        if(ch != '>') ERROR("Invalid target for PI");
 | 
			
		||||
        else {
 | 
			
		||||
            TRY(ctx->PI(ctx, ctx->buffer2.data, 0));
 | 
			
		||||
            ctx->state = StateNone;
 | 
			
		||||
            TRY(ctx->PI(ctx, ctx->buffer2.data, 0));
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -329,9 +329,9 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
 | 
			
		||||
    case StatePI3:
 | 
			
		||||
        if(ch == '>') {
 | 
			
		||||
            ctx->state = StateNone;
 | 
			
		||||
            TRY(ctx->PI(ctx, ctx->buffer2.data, ctx->buffer.data));
 | 
			
		||||
            CLEAR_BUFFER(buffer);
 | 
			
		||||
            ctx->state = StateNone;
 | 
			
		||||
        } else if(ch == '?') {
 | 
			
		||||
            APPEND_CH(buffer, '?');
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -378,9 +378,9 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
 | 
			
		||||
    case StateComment3:
 | 
			
		||||
        if(ch != '>') ERROR("`--' not valid in comments");
 | 
			
		||||
        ctx->state = StateNone;
 | 
			
		||||
        TRY(ctx->comment(ctx, ctx->buffer.data));
 | 
			
		||||
        CLEAR_BUFFER(buffer);
 | 
			
		||||
        ctx->state = StateNone;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case StateElemName:
 | 
			
		||||
| 
						 | 
				
			
			@ -399,8 +399,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
            switch(ch) {
 | 
			
		||||
            case L'>':
 | 
			
		||||
                TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName));
 | 
			
		||||
                TRY(ctx->element(ctx, ctx->elemName.data, 0));
 | 
			
		||||
                ctx->state = StateNone;
 | 
			
		||||
                TRY(ctx->element(ctx, ctx->elemName.data, 0));
 | 
			
		||||
                ++ctx->elementDepth;
 | 
			
		||||
                CLEAR_BUFFER(buffer);
 | 
			
		||||
                break;
 | 
			
		||||
| 
						 | 
				
			
			@ -430,8 +430,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
            switch(ch) {
 | 
			
		||||
            case '>':
 | 
			
		||||
                TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName));
 | 
			
		||||
                TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrNames.len));
 | 
			
		||||
                ctx->state = StateNone;
 | 
			
		||||
                TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrNames.len));
 | 
			
		||||
                ++ctx->elementDepth;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -488,10 +488,10 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
            if(ch == '/') {
 | 
			
		||||
                ctx->state = StateNeedClose;
 | 
			
		||||
            } else if(ch == '>') {
 | 
			
		||||
                ctx->state = StateNone;
 | 
			
		||||
                TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len));
 | 
			
		||||
                TRY(list_push(ctx, &ctx->elemStack, &ctx->elemName));
 | 
			
		||||
                CLEAR_BUFFER(buffer);
 | 
			
		||||
                ctx->state = StateNone;
 | 
			
		||||
                ++ctx->elementDepth;
 | 
			
		||||
            } else ERROR("Invalid character after attribute.");
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -500,10 +500,10 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
 | 
			
		||||
    case StateNeedClose:
 | 
			
		||||
        if(ch != '>') ERROR("Stray `/' in open tag.");
 | 
			
		||||
        ctx->state = StateNone;
 | 
			
		||||
        TRY(ctx->element(ctx, ctx->elemName.data, ctx->elemAttrVals.len));
 | 
			
		||||
        TRY(ctx->closeTag(ctx, ctx->elemName.data));
 | 
			
		||||
        CLEAR_BUFFER(buffer);
 | 
			
		||||
        ctx->state = StateNone;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case StateClose:
 | 
			
		||||
| 
						 | 
				
			
			@ -527,8 +527,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
            if(ch != '>') ERROR("Invalid character in close tag name.");
 | 
			
		||||
            TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack)));
 | 
			
		||||
            if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag.");
 | 
			
		||||
            TRY(ctx->closeTag(ctx, ctx->elemName.data));
 | 
			
		||||
            ctx->state = StateNone;
 | 
			
		||||
            TRY(ctx->closeTag(ctx, ctx->elemName.data));
 | 
			
		||||
            --ctx->elementDepth;
 | 
			
		||||
            CLEAR_BUFFER(buffer);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -540,8 +540,8 @@ int csxml_feedChar(struct csxml* ctx, char ch)
 | 
			
		|||
        if(ch != '>') ERROR("Invalid data in close tag.");
 | 
			
		||||
        TRY(buffer_copy(ctx, &ctx->elemName, list_pop(&ctx->elemStack)));
 | 
			
		||||
        if(strcmp(ctx->elemName.data, ctx->buffer.data)) ERROR("Mismatched close tag.");
 | 
			
		||||
        TRY(ctx->closeTag(ctx, ctx->elemName.data));
 | 
			
		||||
        ctx->state = StateNone;
 | 
			
		||||
        TRY(ctx->closeTag(ctx, ctx->elemName.data));
 | 
			
		||||
        --ctx->elementDepth;
 | 
			
		||||
        CLEAR_BUFFER(buffer);
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -598,8 +598,8 @@ const char* csxml_entityRef(struct csxml* ctx, const char* ent)
 | 
			
		|||
 | 
			
		||||
    q = ctx->entityRef(ctx, ent);
 | 
			
		||||
    if(!q) {
 | 
			
		||||
        ctx->unknownEntity(ctx, ent);
 | 
			
		||||
        ctx->state = StateError;
 | 
			
		||||
        ctx->unknownEntity(ctx, ent);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,26 +163,26 @@ doBuffer:
 | 
			
		|||
                    break;
 | 
			
		||||
 | 
			
		||||
                case ClassOpenTag:
 | 
			
		||||
                    if(!buffer.empty()) callback->whiteSpace(buffer);
 | 
			
		||||
                    state = StateOpen;
 | 
			
		||||
                    if(!buffer.empty()) callback->whiteSpace(buffer);
 | 
			
		||||
                    buffer.clear();
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case ClassEntity:
 | 
			
		||||
                    if(expandEntities) {
 | 
			
		||||
                        if(!elementDepth) ERROR(L"Entities cannot appear at stream level.");
 | 
			
		||||
                        state = StateEntity;
 | 
			
		||||
                        if(!buffer.empty()) callback->whiteSpace(buffer);
 | 
			
		||||
                        buffer.clear();
 | 
			
		||||
                        parsingAttr = false;
 | 
			
		||||
                        state = StateEntity;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    // fall through
 | 
			
		||||
                default:
 | 
			
		||||
                    if(!elementDepth) ERROR(L"Content cannot appear at stream level.");
 | 
			
		||||
                    if(!buffer.empty()) callback->whiteSpace(buffer);
 | 
			
		||||
                    state = StateData;
 | 
			
		||||
                    if(!buffer.empty()) callback->whiteSpace(buffer);
 | 
			
		||||
                    buffer = ch;
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -191,16 +191,16 @@ doBuffer:
 | 
			
		|||
        case StateData:
 | 
			
		||||
            switch(c) {
 | 
			
		||||
                case ClassOpenTag:
 | 
			
		||||
                    state = StateOpen;
 | 
			
		||||
                    callback->content(buffer);
 | 
			
		||||
                    buffer.clear();
 | 
			
		||||
                    state = StateOpen;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case ClassEntity:
 | 
			
		||||
                    state = StateEntity;
 | 
			
		||||
                    callback->content(buffer);
 | 
			
		||||
                    buffer.clear();
 | 
			
		||||
                    parsingAttr = false;
 | 
			
		||||
                    state = StateEntity;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
| 
						 | 
				
			
			@ -225,9 +225,9 @@ doBuffer:
 | 
			
		|||
 | 
			
		||||
        case StateCDATA2:
 | 
			
		||||
            if(ch == L'>') {
 | 
			
		||||
                state = StateNone;
 | 
			
		||||
                callback->cdata(buffer);
 | 
			
		||||
                buffer.clear();
 | 
			
		||||
                state = StateNone;
 | 
			
		||||
            } else if(ch == L']') {
 | 
			
		||||
                buffer += ch;
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -298,9 +298,9 @@ doBuffer:
 | 
			
		|||
        case StatePI2:
 | 
			
		||||
            if(ch != L'>') ERROR(L"Invalid target for PI");
 | 
			
		||||
            else {
 | 
			
		||||
                state = StateNone;
 | 
			
		||||
                callback->PI(buffer2, L"");
 | 
			
		||||
                buffer.clear();
 | 
			
		||||
                state = StateNone;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -311,9 +311,9 @@ doBuffer:
 | 
			
		|||
            
 | 
			
		||||
        case StatePI3:
 | 
			
		||||
            if(ch == L'>') {
 | 
			
		||||
                state = StateNone;
 | 
			
		||||
                callback->PI(buffer2, buffer);
 | 
			
		||||
                buffer.clear();
 | 
			
		||||
                state = StateNone;
 | 
			
		||||
            } else if(ch == '?') {
 | 
			
		||||
                buffer += L'?';
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -360,9 +360,9 @@ doBuffer:
 | 
			
		|||
 | 
			
		||||
        case StateComment3:
 | 
			
		||||
            if(ch != L'>') ERROR(L"`--' not valid in comments");
 | 
			
		||||
            state = StateNone;
 | 
			
		||||
            callback->comment(buffer);
 | 
			
		||||
            buffer.clear();
 | 
			
		||||
            state = StateNone;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case StateElemName:
 | 
			
		||||
| 
						 | 
				
			
			@ -382,8 +382,8 @@ doBuffer:
 | 
			
		|||
                    switch(ch) {
 | 
			
		||||
                        case L'>':
 | 
			
		||||
                            elemStack.push_back(buffer);
 | 
			
		||||
                            callback->element(buffer, elemAttrs);
 | 
			
		||||
                            state = StateNone;
 | 
			
		||||
                            callback->element(buffer, elemAttrs);
 | 
			
		||||
                            ++elementDepth;
 | 
			
		||||
                            buffer.clear();
 | 
			
		||||
                            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -412,9 +412,9 @@ doBuffer:
 | 
			
		|||
                    switch(ch) {
 | 
			
		||||
                        case L'>':
 | 
			
		||||
                            elemStack.push_back(elemName);
 | 
			
		||||
                            state = StateNone;
 | 
			
		||||
                            callback->element(elemName, elemAttrs);
 | 
			
		||||
                            buffer.clear();
 | 
			
		||||
                            state = StateNone;
 | 
			
		||||
                            ++elementDepth;
 | 
			
		||||
                            break;
 | 
			
		||||
                        
 | 
			
		||||
| 
						 | 
				
			
			@ -474,10 +474,10 @@ doBuffer:
 | 
			
		|||
                    if(ch == L'/') {
 | 
			
		||||
                        state = StateNeedClose;
 | 
			
		||||
                    } else if(ch == L'>') {
 | 
			
		||||
                        state = StateNone;
 | 
			
		||||
                        callback->element(elemName, elemAttrs);
 | 
			
		||||
                        elemStack.push_back(elemName);
 | 
			
		||||
                        buffer.clear();
 | 
			
		||||
                        state = StateNone;
 | 
			
		||||
                        ++elementDepth;
 | 
			
		||||
                    } else ERROR(L"Invalid character after attribute.");
 | 
			
		||||
                    break;
 | 
			
		||||
| 
						 | 
				
			
			@ -486,10 +486,10 @@ doBuffer:
 | 
			
		|||
 | 
			
		||||
        case StateNeedClose:
 | 
			
		||||
            if(ch != L'>') ERROR(L"Stray `/' in open tag.");
 | 
			
		||||
            state = StateNone;
 | 
			
		||||
            callback->element(elemName, elemAttrs);
 | 
			
		||||
            callback->closeTag(elemName);
 | 
			
		||||
            buffer.clear();
 | 
			
		||||
            state = StateNone;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case StateClose:
 | 
			
		||||
| 
						 | 
				
			
			@ -513,9 +513,9 @@ doBuffer:
 | 
			
		|||
                    if(ch != L'>') ERROR(L"Invalid character in close tag name.");
 | 
			
		||||
                    if(elemStack.back() != buffer) ERROR(L"Mismatched close tag.");
 | 
			
		||||
                    elemStack.pop_back();
 | 
			
		||||
                    state = StateNone;
 | 
			
		||||
                    callback->closeTag(buffer);
 | 
			
		||||
                    buffer.clear();
 | 
			
		||||
                    state = StateNone;
 | 
			
		||||
                    --elementDepth;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -525,9 +525,9 @@ doBuffer:
 | 
			
		|||
            if(ch != L'>') ERROR(L"Invalid data in close tag.");
 | 
			
		||||
            if(elemStack.back() != elemName) ERROR(L"Mismatched close tag.");
 | 
			
		||||
            elemStack.pop_back();
 | 
			
		||||
            state = StateNone;
 | 
			
		||||
            callback->closeTag(elemName);
 | 
			
		||||
            buffer.clear();
 | 
			
		||||
            state = StateNone;
 | 
			
		||||
            --elementDepth;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue