@@ -37,10 +37,33 @@ #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFMalformedXMLException.h" #import "OFOutOfRangeException.h" #import "OFUnboundPrefixException.h" + +enum { + stateInByteOrderMark, + stateOutsideTag, + stateTagOpened, + stateInProcessingInstruction, + stateInTagName, + stateInCloseTagName, + stateInTag, + stateInAttributeName, + stateExpectAttributeEqualSign, + stateExpectAttributeDelimiter, + stateInAttributeValue, + stateExpectTagClose, + stateExpectSpaceOrTagClose, + stateInExclamationMark, + stateInCDATAOpening, + stateInCDATA, + stateInCommentOpening, + stateInComment1, + stateInComment2, + stateInDOCTYPE +}; @interface OFXMLParser () @end static void inByteOrderMarkState(OFXMLParser *); @@ -63,33 +86,30 @@ static void inCommentState1(OFXMLParser *); static void inCommentState2(OFXMLParser *); static void inDOCTYPEState(OFXMLParser *); typedef void (*StateFunction)(OFXMLParser *); static StateFunction lookupTable[] = { - [OFXMLParserStateInByteOrderMark] = inByteOrderMarkState, - [OFXMLParserStateOutsideTag] = outsideTagState, - [OFXMLParserStateTagOpened] = tagOpenedState, - [OFXMLParserStateInProcessingInstruction] = - inProcessingInstructionState, - [OFXMLParserStateInTagName] = inTagNameState, - [OFXMLParserStateInCloseTagName] = inCloseTagNameState, - [OFXMLParserStateInTag] = inTagState, - [OFXMLParserStateInAttributeName] = inAttributeNameState, - [OFXMLParserStateExpectAttributeEqualSign] = - expectAttributeEqualSignState, - [OFXMLParserStateExpectAttributeDelimiter] = - expectAttributeDelimiterState, - [OFXMLParserStateInAttributeValue] = inAttributeValueState, - [OFXMLParserStateExpectTagClose] = expectTagCloseState, - [OFXMLParserStateExpectSpaceOrTagClose] = expectSpaceOrTagCloseState, - [OFXMLParserStateInExclamationMark] = inExclamationMarkState, - [OFXMLParserStateInCDATAOpening] = inCDATAOpeningState, - [OFXMLParserStateInCDATA] = inCDATAState, - [OFXMLParserStateInCommentOpening] = inCommentOpeningState, - [OFXMLParserStateInComment1] = inCommentState1, - [OFXMLParserStateInComment2] = inCommentState2, - [OFXMLParserStateInDOCTYPE] = inDOCTYPEState + [stateInByteOrderMark] = inByteOrderMarkState, + [stateOutsideTag] = outsideTagState, + [stateTagOpened] = tagOpenedState, + [stateInProcessingInstruction] = inProcessingInstructionState, + [stateInTagName] = inTagNameState, + [stateInCloseTagName] = inCloseTagNameState, + [stateInTag] = inTagState, + [stateInAttributeName] = inAttributeNameState, + [stateExpectAttributeEqualSign] = expectAttributeEqualSignState, + [stateExpectAttributeDelimiter] = expectAttributeDelimiterState, + [stateInAttributeValue] = inAttributeValueState, + [stateExpectTagClose] = expectTagCloseState, + [stateExpectSpaceOrTagClose] = expectSpaceOrTagCloseState, + [stateInExclamationMark] = inExclamationMarkState, + [stateInCDATAOpening] = inCDATAOpeningState, + [stateInCDATA] = inCDATAState, + [stateInCommentOpening] = inCommentOpeningState, + [stateInComment1] = inCommentState1, + [stateInComment2] = inCommentState2, + [stateInDOCTYPE] = inDOCTYPEState }; static OF_INLINE void appendToBuffer(OFMutableData *buffer, const char *string, OFStringEncoding encoding, size_t length) @@ -256,12 +276,12 @@ _lineNumber++; _lastCarriageReturn = (_data[_i] == '\r'); } - /* In OFXMLParserStateInTag, there can be only spaces */ - if (length - _last > 0 && _state != OFXMLParserStateInTag) + /* In stateInTag, there can be only spaces */ + if (length - _last > 0 && _state != stateInTag) appendToBuffer(_buffer, _data + _last, _encoding, length - _last); } - (void)parseString: (OFString *)string @@ -288,20 +308,20 @@ static void inByteOrderMarkState(OFXMLParser *self) { if (self->_data[self->_i] != "\xEF\xBB\xBF"[self->_level]) { if (self->_level == 0) { - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; self->_i--; return; } @throw [OFMalformedXMLException exceptionWithParser: self]; } if (self->_level++ == 2) - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; self->_last = self->_i + 1; } /* Not in a tag */ @@ -337,11 +357,11 @@ } [self->_buffer removeAllItems]; self->_last = self->_i + 1; - self->_state = OFXMLParserStateTagOpened; + self->_state = stateTagOpened; } /* Tag was just opened */ static void tagOpenedState(OFXMLParser *self) @@ -351,29 +371,29 @@ @throw [OFMalformedXMLException exceptionWithParser: self]; switch (self->_data[self->_i]) { case '?': self->_last = self->_i + 1; - self->_state = OFXMLParserStateInProcessingInstruction; + self->_state = stateInProcessingInstruction; self->_level = 0; break; case '/': self->_last = self->_i + 1; - self->_state = OFXMLParserStateInCloseTagName; + self->_state = stateInCloseTagName; self->_acceptProlog = false; break; case '!': self->_last = self->_i + 1; - self->_state = OFXMLParserStateInExclamationMark; + self->_state = stateInExclamationMark; self->_acceptProlog = false; break; default: if (self->_depthLimit > 0 && self->_previous.count >= self->_depthLimit) @throw [OFOutOfRangeException exception]; - self->_state = OFXMLParserStateInTagName; + self->_state = stateInTagName; self->_acceptProlog = false; self->_i--; break; } } @@ -514,11 +534,11 @@ objc_autoreleasePoolPop(pool); [self->_buffer removeAllItems]; self->_last = self->_i + 1; - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; } else self->_level = 0; } /* Inside a tag, no name yet */ @@ -592,14 +612,13 @@ [self->_name release]; [self->_prefix release]; self->_name = self->_prefix = nil; self->_state = (self->_data[self->_i] == '/' - ? OFXMLParserStateExpectTagClose - : OFXMLParserStateOutsideTag); + ? stateExpectTagClose : stateOutsideTag); } else - self->_state = OFXMLParserStateInTag; + self->_state = stateInTag; if (self->_data[self->_i] != '/') [self->_namespaces addObject: [OFMutableDictionary dictionary]]; objc_autoreleasePoolPop(pool); @@ -673,12 +692,11 @@ [self->_prefix release]; self->_name = self->_prefix = nil; self->_last = self->_i + 1; self->_state = (self->_data[self->_i] == '>' - ? OFXMLParserStateOutsideTag - : OFXMLParserStateExpectSpaceOrTagClose); + ? stateOutsideTag : stateExpectSpaceOrTagClose); if (self->_previous.count == 0) self->_finishedParsing = true; } @@ -695,11 +713,11 @@ if (self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r') { self->_last = self->_i; - self->_state = OFXMLParserStateInAttributeName; + self->_state = stateInAttributeName; self->_i--; } return; } @@ -754,11 +772,11 @@ [self->_attributes removeAllObjects]; self->_name = self->_prefix = nil; self->_last = self->_i + 1; self->_state = (self->_data[self->_i] == '/' - ? OFXMLParserStateExpectTagClose : OFXMLParserStateOutsideTag); + ? stateExpectTagClose : stateOutsideTag); } /* Looking for attribute name */ static void inAttributeNameState(OFXMLParser *self) @@ -802,21 +820,20 @@ [self->_buffer removeAllItems]; self->_last = self->_i + 1; self->_state = (self->_data[self->_i] == '=' - ? OFXMLParserStateExpectAttributeDelimiter - : OFXMLParserStateExpectAttributeEqualSign); + ? stateExpectAttributeDelimiter : stateExpectAttributeEqualSign); } /* Expecting equal sign of an attribute */ static void expectAttributeEqualSignState(OFXMLParser *self) { if (self->_data[self->_i] == '=') { self->_last = self->_i + 1; - self->_state = OFXMLParserStateExpectAttributeDelimiter; + self->_state = stateExpectAttributeDelimiter; return; } if (self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r') @@ -835,11 +852,11 @@ if (self->_data[self->_i] != '\'' && self->_data[self->_i] != '"') @throw [OFMalformedXMLException exceptionWithParser: self]; self->_delimiter = self->_data[self->_i]; - self->_state = OFXMLParserStateInAttributeValue; + self->_state = stateInAttributeValue; } /* Looking for attribute value */ static void inAttributeValueState(OFXMLParser *self) @@ -879,20 +896,20 @@ [self->_attributeName release]; [self->_attributePrefix release]; self->_attributeName = self->_attributePrefix = nil; self->_last = self->_i + 1; - self->_state = OFXMLParserStateInTag; + self->_state = stateInTag; } /* Expecting closing '>' */ static void expectTagCloseState(OFXMLParser *self) { if (self->_data[self->_i] == '>') { self->_last = self->_i + 1; - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; } else @throw [OFMalformedXMLException exceptionWithParser: self]; } /* Expecting closing '>' or space */ @@ -899,11 +916,11 @@ static void expectSpaceOrTagCloseState(OFXMLParser *self) { if (self->_data[self->_i] == '>') { self->_last = self->_i + 1; - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; } else if (self->_data[self->_i] != ' ' && self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r') @throw [OFMalformedXMLException exceptionWithParser: self]; } @@ -914,16 +931,16 @@ { if (self->_finishedParsing && self->_data[self->_i] != '-') @throw [OFMalformedXMLException exceptionWithParser: self]; if (self->_data[self->_i] == '-') - self->_state = OFXMLParserStateInCommentOpening; + self->_state = stateInCommentOpening; else if (self->_data[self->_i] == '[') { - self->_state = OFXMLParserStateInCDATAOpening; + self->_state = stateInCDATAOpening; self->_level = 0; } else if (self->_data[self->_i] == 'D') { - self->_state = OFXMLParserStateInDOCTYPE; + self->_state = stateInDOCTYPE; self->_level = 0; } else @throw [OFMalformedXMLException exceptionWithParser: self]; self->_last = self->_i + 1; @@ -935,11 +952,11 @@ { if (self->_data[self->_i] != "CDATA["[self->_level]) @throw [OFMalformedXMLException exceptionWithParser: self]; if (++self->_level == 6) { - self->_state = OFXMLParserStateInCDATA; + self->_state = stateInCDATA; self->_level = 0; } self->_last = self->_i + 1; } @@ -964,11 +981,11 @@ objc_autoreleasePoolPop(pool); [self->_buffer removeAllItems]; self->_last = self->_i + 1; - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; } else self->_level = 0; } /* Comment */ @@ -977,11 +994,11 @@ { if (self->_data[self->_i] != '-') @throw [OFMalformedXMLException exceptionWithParser: self]; self->_last = self->_i + 1; - self->_state = OFXMLParserStateInComment1; + self->_state = stateInComment1; self->_level = 0; } static void inCommentState1(OFXMLParser *self) @@ -990,11 +1007,11 @@ self->_level++; else self->_level = 0; if (self->_level == 2) - self->_state = OFXMLParserStateInComment2; + self->_state = stateInComment2; } static void inCommentState2(OFXMLParser *self) { @@ -1017,11 +1034,11 @@ objc_autoreleasePoolPop(pool); [self->_buffer removeAllItems]; self->_last = self->_i + 1; - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; } /* In */ static void inDOCTYPEState(OFXMLParser *self) @@ -1034,11 +1051,11 @@ @throw [OFMalformedXMLException exceptionWithParser: self]; self->_level++; if (self->_level > 6 && self->_data[self->_i] == '>') - self->_state = OFXMLParserStateOutsideTag; + self->_state = stateOutsideTag; self->_last = self->_i + 1; } - (size_t)lineNumber