OpenShot Audio Library | OpenShotAudio: juce_XmlDocument.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0 |

Loading...
Searching...
No Matches
juce_XmlDocument.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26XmlDocument::XmlDocument (const String& text) : originalText (text) {}
27 XmlDocument::XmlDocument (const File& file) : inputSource (new FileInputSource (file)) {}
28
29XmlDocument::~XmlDocument() {}
30
31std::unique_ptr<XmlElement> XmlDocument::parse (const File& file)
32{
33 return XmlDocument (file).getDocumentElement();
34}
35
36std::unique_ptr<XmlElement> XmlDocument::parse (const String& textToParse)
37{
38 return XmlDocument (textToParse).getDocumentElement();
39}
40
41std::unique_ptr<XmlElement> parseXML (const String& textToParse)
42{
43 return XmlDocument (textToParse).getDocumentElement();
44}
45
46std::unique_ptr<XmlElement> parseXML (const File& file)
47{
48 return XmlDocument (file).getDocumentElement();
49}
50
51std::unique_ptr<XmlElement> parseXMLIfTagMatches (const String& textToParse, StringRef requiredTag)
52{
53 return XmlDocument (textToParse).getDocumentElementIfTagMatches (requiredTag);
54}
55
56std::unique_ptr<XmlElement> parseXMLIfTagMatches (const File& file, StringRef requiredTag)
57{
58 return XmlDocument (file).getDocumentElementIfTagMatches (requiredTag);
59}
60
61 void XmlDocument::setInputSource (InputSource* newSource) noexcept
62{
63 inputSource.reset (newSource);
64}
65
66 void XmlDocument::setEmptyTextElementsIgnored (bool shouldBeIgnored) noexcept
67{
68 ignoreEmptyTextElements = shouldBeIgnored;
69}
70
71namespace XmlIdentifierChars
72{
73 static bool isIdentifierCharSlow (juce_wchar c) noexcept
74 {
75 return CharacterFunctions::isLetterOrDigit (c)
76 || c == '_' || c == '-' || c == ':' || c == '.';
77 }
78
79 static bool isIdentifierChar (juce_wchar c) noexcept
80 {
81 static const uint32 legalChars[] = { 0, 0x7ff6000, 0x87fffffe, 0x7fffffe, 0 };
82
83 return ((int) c < (int) numElementsInArray (legalChars) * 32) ? ((legalChars [c >> 5] & (uint32) (1 << (c & 31))) != 0)
84 : isIdentifierCharSlow (c);
85 }
86
87 /*static void generateIdentifierCharConstants()
88 {
89 uint32 n[8] = { 0 };
90 for (int i = 0; i < 256; ++i)
91 if (isIdentifierCharSlow (i))
92 n[i >> 5] |= (1 << (i & 31));
93
94 String s;
95 for (int i = 0; i < 8; ++i)
96 s << "0x" << String::toHexString ((int) n[i]) << ", ";
97
98 DBG (s);
99 }*/
100
101 static String::CharPointerType findEndOfToken (String::CharPointerType p) noexcept
102 {
103 while (isIdentifierChar (*p))
104 ++p;
105
106 return p;
107 }
108}
109
110std::unique_ptr<XmlElement> XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement)
111{
112 if (originalText.isEmpty() && inputSource != nullptr)
113 {
114 std::unique_ptr<InputStream> in (inputSource->createInputStream());
115
116 if (in != nullptr)
117 {
118 MemoryOutputStream data;
119 data.writeFromInputStream (*in, onlyReadOuterDocumentElement ? 8192 : -1);
120
121 #if JUCE_STRING_UTF_TYPE == 8
122 if (data.getDataSize() > 2)
123 {
124 data.writeByte (0);
125 auto* text = static_cast<const char*> (data.getData());
126
127 if (CharPointer_UTF16::isByteOrderMarkBigEndian (text)
128 || CharPointer_UTF16::isByteOrderMarkLittleEndian (text))
129 {
130 originalText = data.toString();
131 }
132 else
133 {
134 if (CharPointer_UTF8::isByteOrderMark (text))
135 text += 3;
136
137 // parse the input buffer directly to avoid copying it all to a string..
138 return parseDocumentElement (String::CharPointerType (text), onlyReadOuterDocumentElement);
139 }
140 }
141 #else
142 originalText = data.toString();
143 #endif
144 }
145 }
146
147 return parseDocumentElement (originalText.getCharPointer(), onlyReadOuterDocumentElement);
148}
149
150std::unique_ptr<XmlElement> XmlDocument::getDocumentElementIfTagMatches (StringRef requiredTag)
151{
152 if (auto xml = getDocumentElement (true))
153 if (xml->hasTagName (requiredTag))
154 return getDocumentElement (false);
155
156 return {};
157}
158
159 const String& XmlDocument::getLastParseError() const noexcept
160{
161 return lastError;
162}
163
164void XmlDocument::setLastError (const String& desc, const bool carryOn)
165{
166 lastError = desc;
167 errorOccurred = ! carryOn;
168}
169
170String XmlDocument::getFileContents (const String& filename) const
171{
172 if (inputSource != nullptr)
173 {
174 std::unique_ptr<InputStream> in (inputSource->createInputStreamFor (filename.trim().unquoted()));
175
176 if (in != nullptr)
177 return in->readEntireStreamAsString();
178 }
179
180 return {};
181}
182
183juce_wchar XmlDocument::readNextChar() noexcept
184{
185 auto c = input.getAndAdvance();
186
187 if (c == 0)
188 {
189 outOfData = true;
190 --input;
191 }
192
193 return c;
194}
195
196std::unique_ptr<XmlElement> XmlDocument::parseDocumentElement (String::CharPointerType textToParse,
197 bool onlyReadOuterDocumentElement)
198{
199 input = textToParse;
200 errorOccurred = false;
201 outOfData = false;
202 needToLoadDTD = true;
203
204 if (textToParse.isEmpty())
205 {
206 lastError = "not enough input";
207 }
208 else if (! parseHeader())
209 {
210 lastError = "malformed header";
211 }
212 else if (! parseDTD())
213 {
214 lastError = "malformed DTD";
215 }
216 else
217 {
218 lastError.clear();
219 std::unique_ptr<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement));
220
221 if (! errorOccurred)
222 return result;
223 }
224
225 return {};
226}
227
228bool XmlDocument::parseHeader()
229{
230 skipNextWhiteSpace();
231
232 if (CharacterFunctions::compareUpTo (input, CharPointer_ASCII ("<?xml"), 5) == 0)
233 {
234 auto headerEnd = CharacterFunctions::find (input, CharPointer_ASCII ("?>"));
235
236 if (headerEnd.isEmpty())
237 return false;
238
239 #if JUCE_DEBUG
240 auto encoding = String (input, headerEnd)
241 .fromFirstOccurrenceOf ("encoding", false, true)
242 .fromFirstOccurrenceOf ("=", false, false)
243 .fromFirstOccurrenceOf ("\"", false, false)
244 .upToFirstOccurrenceOf ("\"", false, false)
245 .trim();
246
247 /* If you load an XML document with a non-UTF encoding type, it may have been
248 loaded wrongly.. Since all the files are read via the normal juce file streams,
249 they're treated as UTF-8, so by the time it gets to the parser, the encoding will
250 have been lost. Best plan is to stick to utf-8 or if you have specific files to
251 read, use your own code to convert them to a unicode String, and pass that to the
252 XML parser.
253 */
254 jassert (encoding.isEmpty() || encoding.startsWithIgnoreCase ("utf-"));
255 #endif
256
257 input = headerEnd + 2;
258 skipNextWhiteSpace();
259 }
260
261 return true;
262}
263
264bool XmlDocument::parseDTD()
265{
266 if (CharacterFunctions::compareUpTo (input, CharPointer_ASCII ("<!DOCTYPE"), 9) == 0)
267 {
268 input += 9;
269 auto dtdStart = input;
270
271 for (int n = 1; n > 0;)
272 {
273 auto c = readNextChar();
274
275 if (outOfData)
276 return false;
277
278 if (c == '<')
279 ++n;
280 else if (c == '>')
281 --n;
282 }
283
284 dtdText = String (dtdStart, input - 1).trim();
285 }
286
287 return true;
288}
289
290void XmlDocument::skipNextWhiteSpace()
291{
292 for (;;)
293 {
294 input.incrementToEndOfWhitespace();
295
296 if (input.isEmpty())
297 {
298 outOfData = true;
299 break;
300 }
301
302 if (*input == '<')
303 {
304 if (input[1] == '!'
305 && input[2] == '-'
306 && input[3] == '-')
307 {
308 input += 4;
309 auto closeComment = input.indexOf (CharPointer_ASCII ("-->"));
310
311 if (closeComment < 0)
312 {
313 outOfData = true;
314 break;
315 }
316
317 input += closeComment + 3;
318 continue;
319 }
320
321 if (input[1] == '?')
322 {
323 input += 2;
324 auto closeBracket = input.indexOf (CharPointer_ASCII ("?>"));
325
326 if (closeBracket < 0)
327 {
328 outOfData = true;
329 break;
330 }
331
332 input += closeBracket + 2;
333 continue;
334 }
335 }
336
337 break;
338 }
339}
340
341void XmlDocument::readQuotedString (String& result)
342{
343 auto quote = readNextChar();
344
345 while (! outOfData)
346 {
347 auto c = readNextChar();
348
349 if (c == quote)
350 break;
351
352 --input;
353
354 if (c == '&')
355 {
356 readEntity (result);
357 }
358 else
359 {
360 auto start = input;
361
362 for (;;)
363 {
364 auto character = *input;
365
366 if (character == quote)
367 {
368 result.appendCharPointer (start, input);
369 ++input;
370 return;
371 }
372
373 if (character == '&')
374 {
375 result.appendCharPointer (start, input);
376 break;
377 }
378
379 if (character == 0)
380 {
381 setLastError ("unmatched quotes", false);
382 outOfData = true;
383 break;
384 }
385
386 ++input;
387 }
388 }
389 }
390}
391
392 XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements)
393{
394 XmlElement* node = nullptr;
395 skipNextWhiteSpace();
396
397 if (outOfData)
398 return nullptr;
399
400 if (*input == '<')
401 {
402 ++input;
403 auto endOfToken = XmlIdentifierChars::findEndOfToken (input);
404
405 if (endOfToken == input)
406 {
407 // no tag name - but allow for a gap after the '<' before giving an error
408 skipNextWhiteSpace();
409 endOfToken = XmlIdentifierChars::findEndOfToken (input);
410
411 if (endOfToken == input)
412 {
413 setLastError ("tag name missing", false);
414 return node;
415 }
416 }
417
418 node = new XmlElement (input, endOfToken);
419 input = endOfToken;
420 LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes);
421
422 // look for attributes
423 for (;;)
424 {
425 skipNextWhiteSpace();
426 auto c = *input;
427
428 // empty tag..
429 if (c == '/' && input[1] == '>')
430 {
431 input += 2;
432 break;
433 }
434
435 // parse the guts of the element..
436 if (c == '>')
437 {
438 ++input;
439
440 if (alsoParseSubElements)
441 readChildElements (*node);
442
443 break;
444 }
445
446 // get an attribute..
447 if (XmlIdentifierChars::isIdentifierChar (c))
448 {
449 auto attNameEnd = XmlIdentifierChars::findEndOfToken (input);
450
451 if (attNameEnd != input)
452 {
453 auto attNameStart = input;
454 input = attNameEnd;
455 skipNextWhiteSpace();
456
457 if (readNextChar() == '=')
458 {
459 skipNextWhiteSpace();
460 auto nextChar = *input;
461
462 if (nextChar == '"' || nextChar == '\'')
463 {
464 auto* newAtt = new XmlElement::XmlAttributeNode (attNameStart, attNameEnd);
465 readQuotedString (newAtt->value);
466 attributeAppender.append (newAtt);
467 continue;
468 }
469 }
470 else
471 {
472 setLastError ("expected '=' after attribute '"
473 + String (attNameStart, attNameEnd) + "'", false);
474 return node;
475 }
476 }
477 }
478 else
479 {
480 if (! outOfData)
481 setLastError ("illegal character found in " + node->getTagName() + ": '" + c + "'", false);
482 }
483
484 break;
485 }
486 }
487
488 return node;
489}
490
491void XmlDocument::readChildElements (XmlElement& parent)
492{
493 LinkedListPointer<XmlElement>::Appender childAppender (parent.firstChildElement);
494
495 for (;;)
496 {
497 auto preWhitespaceInput = input;
498 skipNextWhiteSpace();
499
500 if (outOfData)
501 {
502 setLastError ("unmatched tags", false);
503 break;
504 }
505
506 if (*input == '<')
507 {
508 auto c1 = input[1];
509
510 if (c1 == '/')
511 {
512 // our close tag..
513 auto closeTag = input.indexOf ((juce_wchar) '>');
514
515 if (closeTag >= 0)
516 input += closeTag + 1;
517
518 break;
519 }
520
521 if (c1 == '!' && CharacterFunctions::compareUpTo (input + 2, CharPointer_ASCII ("[CDATA["), 7) == 0)
522 {
523 input += 9;
524 auto inputStart = input;
525
526 for (;;)
527 {
528 auto c0 = *input;
529
530 if (c0 == 0)
531 {
532 setLastError ("unterminated CDATA section", false);
533 outOfData = true;
534 break;
535 }
536
537 if (c0 == ']' && input[1] == ']' && input[2] == '>')
538 {
539 childAppender.append (XmlElement::createTextElement (String (inputStart, input)));
540 input += 3;
541 break;
542 }
543
544 ++input;
545 }
546 }
547 else
548 {
549 // this is some other element, so parse and add it..
550 if (auto* n = readNextElement (true))
551 childAppender.append (n);
552 else
553 break;
554 }
555 }
556 else // must be a character block
557 {
558 input = preWhitespaceInput; // roll back to include the leading whitespace
559 MemoryOutputStream textElementContent;
560 bool contentShouldBeUsed = ! ignoreEmptyTextElements;
561
562 for (;;)
563 {
564 auto c = *input;
565
566 if (c == '<')
567 {
568 if (input[1] == '!' && input[2] == '-' && input[3] == '-')
569 {
570 input += 4;
571 auto closeComment = input.indexOf (CharPointer_ASCII ("-->"));
572
573 if (closeComment < 0)
574 {
575 setLastError ("unterminated comment", false);
576 outOfData = true;
577 return;
578 }
579
580 input += closeComment + 3;
581 continue;
582 }
583
584 break;
585 }
586
587 if (c == 0)
588 {
589 setLastError ("unmatched tags", false);
590 outOfData = true;
591 return;
592 }
593
594 if (c == '&')
595 {
596 String entity;
597 readEntity (entity);
598
599 if (entity.startsWithChar ('<') && entity [1] != 0)
600 {
601 auto oldInput = input;
602 auto oldOutOfData = outOfData;
603
604 input = entity.getCharPointer();
605 outOfData = false;
606
607 while (auto* n = readNextElement (true))
608 childAppender.append (n);
609
610 input = oldInput;
611 outOfData = oldOutOfData;
612 }
613 else
614 {
615 textElementContent << entity;
616 contentShouldBeUsed = contentShouldBeUsed || entity.containsNonWhitespaceChars();
617 }
618 }
619 else
620 {
621 for (;; ++input)
622 {
623 auto nextChar = *input;
624
625 if (nextChar == '\r')
626 {
627 nextChar = '\n';
628
629 if (input[1] == '\n')
630 continue;
631 }
632
633 if (nextChar == '<' || nextChar == '&')
634 break;
635
636 if (nextChar == 0)
637 {
638 setLastError ("unmatched tags", false);
639 outOfData = true;
640 return;
641 }
642
643 textElementContent.appendUTF8Char (nextChar);
644 contentShouldBeUsed = contentShouldBeUsed || ! CharacterFunctions::isWhitespace (nextChar);
645 }
646 }
647 }
648
649 if (contentShouldBeUsed)
650 childAppender.append (XmlElement::createTextElement (textElementContent.toUTF8()));
651 }
652 }
653}
654
655void XmlDocument::readEntity (String& result)
656{
657 // skip over the ampersand
658 ++input;
659
660 if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("amp;"), 4) == 0)
661 {
662 input += 4;
663 result += '&';
664 }
665 else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("quot;"), 5) == 0)
666 {
667 input += 5;
668 result += '"';
669 }
670 else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("apos;"), 5) == 0)
671 {
672 input += 5;
673 result += '\'';
674 }
675 else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("lt;"), 3) == 0)
676 {
677 input += 3;
678 result += '<';
679 }
680 else if (input.compareIgnoreCaseUpTo (CharPointer_ASCII ("gt;"), 3) == 0)
681 {
682 input += 3;
683 result += '>';
684 }
685 else if (*input == '#')
686 {
687 int64_t charCode = 0;
688 ++input;
689
690 if (*input == 'x' || *input == 'X')
691 {
692 ++input;
693 int numChars = 0;
694
695 while (input[0] != ';')
696 {
697 auto hexValue = CharacterFunctions::getHexDigitValue (input[0]);
698
699 if (hexValue < 0 || ++numChars > 8)
700 {
701 setLastError ("illegal escape sequence", true);
702 break;
703 }
704
705 charCode = (charCode << 4) | hexValue;
706 ++input;
707 }
708
709 ++input;
710 }
711 else if (input[0] >= '0' && input[0] <= '9')
712 {
713 int numChars = 0;
714
715 for (;;)
716 {
717 const auto firstChar = input[0];
718
719 if (firstChar == 0)
720 {
721 setLastError ("unexpected end of input", true);
722 return;
723 }
724
725 if (firstChar == ';')
726 break;
727
728 if (++numChars > 12)
729 {
730 setLastError ("illegal escape sequence", true);
731 break;
732 }
733
734 charCode = charCode * 10 + ((int) firstChar - '0');
735 ++input;
736 }
737
738 ++input;
739 }
740 else
741 {
742 setLastError ("illegal escape sequence", true);
743 result += '&';
744 return;
745 }
746
747 result << (juce_wchar) charCode;
748 }
749 else
750 {
751 auto entityNameStart = input;
752 auto closingSemiColon = input.indexOf ((juce_wchar) ';');
753
754 if (closingSemiColon < 0)
755 {
756 outOfData = true;
757 result += '&';
758 }
759 else
760 {
761 input += closingSemiColon + 1;
762 result += expandExternalEntity (String (entityNameStart, (size_t) closingSemiColon));
763 }
764 }
765}
766
767 String XmlDocument::expandEntity (const String& ent)
768{
769 if (ent.equalsIgnoreCase ("amp")) return String::charToString ('&');
770 if (ent.equalsIgnoreCase ("quot")) return String::charToString ('"');
771 if (ent.equalsIgnoreCase ("apos")) return String::charToString ('\'');
772 if (ent.equalsIgnoreCase ("lt")) return String::charToString ('<');
773 if (ent.equalsIgnoreCase ("gt")) return String::charToString ('>');
774
775 if (ent[0] == '#')
776 {
777 auto char1 = ent[1];
778
779 if (char1 == 'x' || char1 == 'X')
780 return String::charToString (static_cast<juce_wchar> (ent.substring (2).getHexValue32()));
781
782 if (char1 >= '0' && char1 <= '9')
783 return String::charToString (static_cast<juce_wchar> (ent.substring (1).getIntValue()));
784
785 setLastError ("illegal escape sequence", false);
786 return String::charToString ('&');
787 }
788
789 return expandExternalEntity (ent);
790}
791
792 String XmlDocument::expandExternalEntity (const String& entity)
793{
794 if (needToLoadDTD)
795 {
796 if (dtdText.isNotEmpty())
797 {
798 dtdText = dtdText.trimCharactersAtEnd (">");
799 tokenisedDTD.addTokens (dtdText, true);
800
801 if (tokenisedDTD[tokenisedDTD.size() - 2].equalsIgnoreCase ("system")
802 && tokenisedDTD[tokenisedDTD.size() - 1].isQuotedString())
803 {
804 auto fn = tokenisedDTD[tokenisedDTD.size() - 1];
805
806 tokenisedDTD.clear();
807 tokenisedDTD.addTokens (getFileContents (fn), true);
808 }
809 else
810 {
811 tokenisedDTD.clear();
812 auto openBracket = dtdText.indexOfChar ('[');
813
814 if (openBracket > 0)
815 {
816 auto closeBracket = dtdText.lastIndexOfChar (']');
817
818 if (closeBracket > openBracket)
819 tokenisedDTD.addTokens (dtdText.substring (openBracket + 1,
820 closeBracket), true);
821 }
822 }
823
824 for (int i = tokenisedDTD.size(); --i >= 0;)
825 {
826 if (tokenisedDTD[i].startsWithChar ('%')
827 && tokenisedDTD[i].endsWithChar (';'))
828 {
829 auto parsed = getParameterEntity (tokenisedDTD[i].substring (1, tokenisedDTD[i].length() - 1));
830 StringArray newToks;
831 newToks.addTokens (parsed, true);
832
833 tokenisedDTD.remove (i);
834
835 for (int j = newToks.size(); --j >= 0;)
836 tokenisedDTD.insert (i, newToks[j]);
837 }
838 }
839 }
840
841 needToLoadDTD = false;
842 }
843
844 for (int i = 0; i < tokenisedDTD.size(); ++i)
845 {
846 if (tokenisedDTD[i] == entity)
847 {
848 if (tokenisedDTD[i - 1].equalsIgnoreCase ("<!entity"))
849 {
850 auto ent = tokenisedDTD [i + 1].trimCharactersAtEnd (">").trim().unquoted();
851
852 // check for sub-entities..
853 auto ampersand = ent.indexOfChar ('&');
854
855 while (ampersand >= 0)
856 {
857 auto semiColon = ent.indexOf (i + 1, ";");
858
859 if (semiColon < 0)
860 {
861 setLastError ("entity without terminating semi-colon", false);
862 break;
863 }
864
865 auto resolved = expandEntity (ent.substring (i + 1, semiColon));
866
867 ent = ent.substring (0, ampersand)
868 + resolved
869 + ent.substring (semiColon + 1);
870
871 ampersand = ent.indexOfChar (semiColon + 1, '&');
872 }
873
874 return ent;
875 }
876 }
877 }
878
879 setLastError ("unknown entity", true);
880 return entity;
881}
882
883 String XmlDocument::getParameterEntity (const String& entity)
884{
885 for (int i = 0; i < tokenisedDTD.size(); ++i)
886 {
887 if (tokenisedDTD[i] == entity
888 && tokenisedDTD [i - 1] == "%"
889 && tokenisedDTD [i - 2].equalsIgnoreCase ("<!entity"))
890 {
891 auto ent = tokenisedDTD [i + 1].trimCharactersAtEnd (">");
892
893 if (ent.equalsIgnoreCase ("system"))
894 return getFileContents (tokenisedDTD [i + 2].trimCharactersAtEnd (">"));
895
896 return ent.trim().unquoted();
897 }
898 }
899
900 return entity;
901}
902
903}
juce::CharPointer_UTF16::isByteOrderMarkBigEndian
static bool isByteOrderMarkBigEndian(const void *possibleByteOrder) noexcept
Definition juce_CharPointer_UTF16.h:487
juce::CharPointer_UTF16::isByteOrderMarkLittleEndian
static bool isByteOrderMarkLittleEndian(const void *possibleByteOrder) noexcept
Definition juce_CharPointer_UTF16.h:501
juce::CharPointer_UTF8::isByteOrderMark
static bool isByteOrderMark(const void *possibleByteOrder) noexcept
Definition juce_CharPointer_UTF8.h:555
juce::CharacterFunctions::isWhitespace
static bool isWhitespace(char character) noexcept
Definition juce_CharacterFunctions.cpp:59
juce::CharacterFunctions::getHexDigitValue
static int getHexDigitValue(juce_wchar digit) noexcept
Definition juce_CharacterFunctions.cpp:112
juce::CharacterFunctions::isLetterOrDigit
static bool isLetterOrDigit(char character) noexcept
Definition juce_CharacterFunctions.cpp:90
juce::CharacterFunctions::find
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Definition juce_CharacterFunctions.h:708
juce::CharacterFunctions::compareUpTo
static int compareUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
Definition juce_CharacterFunctions.h:624
juce::FileInputSource
Definition juce_FileInputSource.h:35
juce::File
Definition juce_File.h:45
juce::InputSource
Definition juce_InputSource.h:38
juce::MemoryOutputStream
Definition juce_MemoryOutputStream.h:36
juce::MemoryOutputStream::getData
const void * getData() const noexcept
Definition juce_MemoryOutputStream.cpp:148
juce::MemoryOutputStream::toString
String toString() const
Definition juce_MemoryOutputStream.cpp:195
juce::MemoryOutputStream::getDataSize
size_t getDataSize() const noexcept
Definition juce_MemoryOutputStream.h:80
juce::MemoryOutputStream::writeFromInputStream
int64 writeFromInputStream(InputStream &, int64 maxNumBytesToWrite) override
Definition juce_MemoryOutputStream.cpp:172
juce::OutputStream::writeByte
virtual bool writeByte(char byte)
Definition juce_OutputStream.cpp:83
juce::StringRef
Definition juce_StringRef.h:62
juce::String
Definition juce_String.h:53
juce::String::charToString
static String charToString(juce_wchar character)
Definition juce_String.cpp:359
juce::XmlDocument
Definition juce_XmlDocument.h:64
juce::XmlDocument::getLastParseError
const String & getLastParseError() const noexcept
Definition juce_XmlDocument.cpp:159
juce::XmlDocument::getDocumentElementIfTagMatches
std::unique_ptr< XmlElement > getDocumentElementIfTagMatches(StringRef requiredTag)
Definition juce_XmlDocument.cpp:150
juce::XmlDocument::getDocumentElement
std::unique_ptr< XmlElement > getDocumentElement(bool onlyReadOuterDocumentElement=false)
Definition juce_XmlDocument.cpp:110
juce::XmlDocument::XmlDocument
XmlDocument(const String &documentText)
Definition juce_XmlDocument.cpp:26
juce::XmlDocument::parse
static std::unique_ptr< XmlElement > parse(const File &file)
Definition juce_XmlDocument.cpp:31
juce::XmlDocument::setInputSource
void setInputSource(InputSource *newSource) noexcept
Definition juce_XmlDocument.cpp:61
juce::XmlDocument::~XmlDocument
~XmlDocument()
Definition juce_XmlDocument.cpp:29
juce::XmlDocument::setEmptyTextElementsIgnored
void setEmptyTextElementsIgnored(bool shouldBeIgnored) noexcept
Definition juce_XmlDocument.cpp:66
juce::XmlElement
Definition juce_XmlElement.h:83
juce::XmlElement::createTextElement
static XmlElement * createTextElement(const String &text)
Definition juce_XmlElement.cpp:952