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