static Result parseString (const juce_wchar quoteChar, String::CharPointerType& t, var& result) { MemoryOutputStream buffer (256); for (;;) { juce_wchar c = t.getAndAdvance(); if (c == quoteChar) break; if (c == '\\') { c = t.getAndAdvance(); switch (c) { case '"': case '\'': case '\\': case '/': break; case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'u': { c = 0; for (int i = 4; --i >= 0;) { const int digitValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance()); if (digitValue < 0) return createFail ("Syntax error in unicode escape sequence"); c = (juce_wchar) ((c << 4) + digitValue); } break; } } } if (c == 0) return createFail ("Unexpected end-of-input in string constant"); buffer.appendUTF8Char (c); } result = buffer.toUTF8(); return Result::ok(); }
void XmlDocument::readChildElements (XmlElement& parent) { LinkedListPointer<XmlElement>::Appender childAppender (parent.firstChildElement); for (;;) { const String::CharPointerType preWhitespaceInput (input); skipNextWhiteSpace(); if (outOfData) { setLastError ("unmatched tags", false); break; } if (*input == '<') { const juce_wchar c1 = input[1]; if (c1 == '/') { // our close tag.. const int closeTag = input.indexOf ((juce_wchar) '>'); if (closeTag >= 0) input += closeTag + 1; break; } if (c1 == '!' && CharacterFunctions::compareUpTo (input + 2, CharPointer_ASCII ("[CDATA["), 7) == 0) { input += 9; const String::CharPointerType inputStart (input); for (;;) { const juce_wchar c0 = *input; if (c0 == 0) { setLastError ("unterminated CDATA section", false); outOfData = true; break; } else if (c0 == ']' && input[1] == ']' && input[2] == '>') { childAppender.append (XmlElement::createTextElement (String (inputStart, input))); input += 3; break; } ++input; } } else { // this is some other element, so parse and add it.. if (XmlElement* const n = readNextElement (true)) childAppender.append (n); else break; } } else // must be a character block { input = preWhitespaceInput; // roll back to include the leading whitespace MemoryOutputStream textElementContent; bool contentShouldBeUsed = ! ignoreEmptyTextElements; for (;;) { const juce_wchar c = *input; if (c == '<') { if (input[1] == '!' && input[2] == '-' && input[3] == '-') { input += 4; const int closeComment = input.indexOf (CharPointer_ASCII ("-->")); if (closeComment < 0) { setLastError ("unterminated comment", false); outOfData = true; return; } input += closeComment + 3; continue; } break; } if (c == 0) { setLastError ("unmatched tags", false); outOfData = true; return; } if (c == '&') { String entity; readEntity (entity); if (entity.startsWithChar ('<') && entity [1] != 0) { const String::CharPointerType oldInput (input); const bool oldOutOfData = outOfData; input = entity.getCharPointer(); outOfData = false; while (XmlElement* n = readNextElement (true)) childAppender.append (n); input = oldInput; outOfData = oldOutOfData; } else { textElementContent << entity; contentShouldBeUsed = contentShouldBeUsed || entity.containsNonWhitespaceChars(); } } else { for (;; ++input) { juce_wchar nextChar = *input; if (nextChar == '\r') { nextChar = '\n'; if (input[1] == '\n') continue; } if (nextChar == '<' || nextChar == '&') break; if (nextChar == 0) { setLastError ("unmatched tags", false); outOfData = true; return; } textElementContent.appendUTF8Char (nextChar); contentShouldBeUsed = contentShouldBeUsed || ! CharacterFunctions::isWhitespace (nextChar); } } } if (contentShouldBeUsed) childAppender.append (XmlElement::createTextElement (textElementContent.toUTF8())); } } }