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:
Laurence Withers 2006-09-29 10:51:10 +01:00
parent f1fa8b5625
commit 71fda14981
2 changed files with 30 additions and 30 deletions

View File

@ -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;
}

View File

@ -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;