in src/xercesc/internal/XMLScanner.cpp [1361:1587]
void XMLScanner::scanXMLDecl(const DeclTypes type)
{
// Get us some buffers to use
XMLBufBid bbVersion(&fBufMgr);
XMLBufBid bbEncoding(&fBufMgr);
XMLBufBid bbStand(&fBufMgr);
XMLBufBid bbDummy(&fBufMgr);
XMLBufBid bbName(&fBufMgr);
// We use this little enum and array to keep up with what we found
// and what order we found them in. This lets us get them free form
// without too much overhead, but still know that they were in the
// wrong order.
enum Strings
{
VersionString
, EncodingString
, StandaloneString
, UnknownString
, StringCount
};
int flags[StringCount] = { -1, -1, -1, -1 };
// Also set up a list of buffers in the right order so that we know
// where to put stuff.
XMLBuffer* buffers[StringCount] ;
buffers[0] = &bbVersion.getBuffer();
buffers[1] = &bbEncoding.getBuffer();
buffers[2] = &bbStand.getBuffer();
buffers[3] = &bbDummy.getBuffer();
int curCount = 0;
Strings curString;
XMLBuffer& nameBuf = bbName.getBuffer();
while (true)
{
// Skip any spaces
bool skippedSomething;
fReaderMgr.skipPastSpaces(skippedSomething, true);
// If we are looking at a question mark, then break out
if (fReaderMgr.lookingAtChar(chQuestion))
break;
// If this is not the first string, then we require the spaces
if (!skippedSomething && curCount)
emitError(XMLErrs::ExpectedWhitespace);
// Get characters up to the next whitespace or equal's sign.
if (!scanUpToWSOr(nameBuf, chEqual))
emitError(XMLErrs::ExpectedDeclString);
// See if it matches any of our expected strings
if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgVersionString))
curString = VersionString;
else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgEncodingString))
curString = EncodingString;
else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgStandaloneString))
curString = StandaloneString;
else
curString = UnknownString;
// If its an unknown string, then give that error. Else check to
// see if this one has been done already and give that error.
if (curString == UnknownString)
emitError(XMLErrs::ExpectedDeclString, nameBuf.getRawBuffer());
else if (flags[curString] != -1)
emitError(XMLErrs::DeclStringRep, nameBuf.getRawBuffer());
else if (flags[curString] == -1)
flags[curString] = ++curCount;
// Scan for an equal's sign. If we don't find it, issue an error
// but keep trying to go on.
if (!scanEq(true))
emitError(XMLErrs::ExpectedEqSign);
// Get a quote string into the buffer for the string that we are
// currently working on.
if (!getQuotedString(*buffers[curString]))
{
emitError(XMLErrs::ExpectedQuotedString);
fReaderMgr.skipPastChar(chCloseAngle);
return;
}
// And validate the value according which one it was
const XMLCh* rawValue = buffers[curString]->getRawBuffer();
if (curString == VersionString)
{
if (XMLString::equals(rawValue, XMLUni::fgVersion1_1)) {
if (type == Decl_XML) {
fXMLVersion = XMLReader::XMLV1_1;
fReaderMgr.setXMLVersion(XMLReader::XMLV1_1);
}
else {
if (fXMLVersion != XMLReader::XMLV1_1)
emitError(XMLErrs::UnsupportedXMLVersion, rawValue);
}
}
else if (XMLString::equals(rawValue, XMLUni::fgVersion1_0)) {
if (type == Decl_XML) {
fXMLVersion = XMLReader::XMLV1_0;
fReaderMgr.setXMLVersion(XMLReader::XMLV1_0);
}
}
else if (XMLString::startsWith(rawValue, XMLUni::fgVersion1)) {
if (type == Decl_XML) {
fXMLVersion = XMLReader::XMLV1_0;
fReaderMgr.setXMLVersion(XMLReader::XMLV1_0);
}
}
else
emitError(XMLErrs::UnsupportedXMLVersion, rawValue);
}
else if (curString == EncodingString)
{
if (!XMLString::isValidEncName(rawValue))
emitError(XMLErrs::BadXMLEncoding, rawValue);
}
else if (curString == StandaloneString)
{
if (XMLString::equals(rawValue, XMLUni::fgYesString))
fStandalone = true;
else if (XMLString::equals(rawValue, XMLUni::fgNoString))
fStandalone = false;
else
{
emitError(XMLErrs::BadStandalone);
//if (!XMLString::compareIString(rawValue, XMLUni::fgYesString))
//else if (!XMLString::compareIString(rawValue, XMLUni::fgNoString))
if (buffers[curString]->getLen() == 3 &&
(((rawValue[0] == chLatin_y) || (rawValue[0] == chLatin_Y)) &&
((rawValue[1] == chLatin_e) || (rawValue[1] == chLatin_E)) &&
((rawValue[2] == chLatin_s) || (rawValue[2] == chLatin_S))))
fStandalone = true;
else if (buffers[curString]->getLen() == 2 &&
(((rawValue[0] == chLatin_n) || (rawValue[0] == chLatin_N)) &&
((rawValue[1] == chLatin_o) || (rawValue[1] == chLatin_O))))
fStandalone = false;
}
}
}
// Make sure that the strings present are in order. We don't care about
// which ones are present at this point, just that any there are in the
// right order.
int curTop = 0;
for (int index = VersionString; index < StandaloneString; index++)
{
if (flags[index] != -1)
{
if (flags[index] != curTop + 1)
{
emitError(XMLErrs::DeclStringsInWrongOrder);
break;
}
curTop = flags[index];
}
}
// If its an XML decl, the version must be present.
// If its a Text decl, then encoding must be present AND standalone must not be present.
if ((type == Decl_XML) && (flags[VersionString] == -1))
emitError(XMLErrs::XMLVersionRequired);
else if (type == Decl_Text) {
if (flags[StandaloneString] != -1)
emitError(XMLErrs::StandaloneNotLegal);
if (flags[EncodingString] == -1)
emitError(XMLErrs::EncodingRequired);
}
if (!fReaderMgr.skippedChar(chQuestion))
{
emitError(XMLErrs::UnterminatedXMLDecl);
fReaderMgr.skipPastChar(chCloseAngle);
}
else if (!fReaderMgr.skippedChar(chCloseAngle))
{
emitError(XMLErrs::UnterminatedXMLDecl);
fReaderMgr.skipPastChar(chCloseAngle);
}
// Do this before we possibly update the reader with the
// actual encoding string. Otherwise, we will pass the wrong thing
// for the last parameter!
const XMLCh* actualEnc = fReaderMgr.getCurrentEncodingStr();
// Ok, we've now seen the real encoding string, if there was one, so
// lets call back on the current reader and tell it what the real
// encoding string was. If it fails, that's because it represents some
// sort of contradiction with the autosensed format, and it keeps the
// original encoding.
//
// NOTE: This can fail for a number of reasons, such as a bogus encoding
// name or because its in flagrant contradiction of the auto-sensed
// format.
if (flags[EncodingString] != -1)
{
if (!fReaderMgr.getCurrentReader()->setEncoding(bbEncoding.getRawBuffer()))
emitError(XMLErrs::ContradictoryEncoding, bbEncoding.getRawBuffer());
else
actualEnc = bbEncoding.getRawBuffer();
}
// If we have a document handler then call the XML Decl callback.
if (type == Decl_XML)
{
if (fDocHandler)
fDocHandler->XMLDecl
(
bbVersion.getRawBuffer()
, bbEncoding.getRawBuffer()
, bbStand.getRawBuffer()
, actualEnc
);
}
else if (type == Decl_Text)
{
if (fDocTypeHandler)
fDocTypeHandler->TextDecl
(
bbVersion.getRawBuffer()
, bbEncoding.getRawBuffer()
);
}
}