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