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