OpenShot Audio Library | OpenShotAudio  0.6.0
juce_XmlElement.h
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 
23 namespace juce
24 {
25 
26 //==============================================================================
82 class JUCE_API XmlElement
83 {
84 public:
85  //==============================================================================
87  explicit XmlElement (const String& tagName);
88 
90  explicit XmlElement (const char* tagName);
91 
93  explicit XmlElement (const Identifier& tagName);
94 
96  explicit XmlElement (StringRef tagName);
97 
99  XmlElement (String::CharPointerType tagNameBegin, String::CharPointerType tagNameEnd);
100 
102  XmlElement (const XmlElement&);
103 
105  XmlElement& operator= (const XmlElement&);
106 
108  XmlElement& operator= (XmlElement&&) noexcept;
109 
111  XmlElement (XmlElement&&) noexcept;
112 
114  ~XmlElement() noexcept;
115 
116  //==============================================================================
128  bool isEquivalentTo (const XmlElement* other,
129  bool ignoreOrderOfAttributes) const noexcept;
130 
131  //==============================================================================
135  struct TextFormat
136  {
138  TextFormat();
139 
143  bool addDefaultHeader = true;
144  int lineWrapLength = 60;
145  const char* newLineChars = "\r\n";
147  [[nodiscard]] TextFormat singleLine() const;
148  [[nodiscard]] TextFormat withoutHeader() const;
149  };
150 
156  String toString (const TextFormat& format = {}) const;
157 
161  void writeTo (OutputStream& output, const TextFormat& format = {}) const;
162 
166  bool writeTo (const File& destinationFile, const TextFormat& format = {}) const;
167 
168  //==============================================================================
173  const String& getTagName() const noexcept { return tagName; }
174 
176  String getNamespace() const;
177 
179  String getTagNameWithoutNamespace() const;
180 
185  bool hasTagName (StringRef possibleTagName) const noexcept;
186 
191  bool hasTagNameIgnoringNamespace (StringRef possibleTagName) const;
192 
196  void setTagName (StringRef newTagName);
197 
198  //==============================================================================
204  int getNumAttributes() const noexcept;
205 
213  const String& getAttributeName (int attributeIndex) const noexcept;
214 
222  const String& getAttributeValue (int attributeIndex) const noexcept;
223 
224  //==============================================================================
225  // Attribute-handling methods..
226 
228  bool hasAttribute (StringRef attributeName) const noexcept;
229 
233  const String& getStringAttribute (StringRef attributeName) const noexcept;
234 
240  String getStringAttribute (StringRef attributeName, const String& defaultReturnValue) const;
241 
250  bool compareAttribute (StringRef attributeName,
251  StringRef stringToCompareAgainst,
252  bool ignoreCase = false) const noexcept;
253 
264  int getIntAttribute (StringRef attributeName, int defaultReturnValue = 0) const;
265 
276  double getDoubleAttribute (StringRef attributeName, double defaultReturnValue = 0.0) const;
277 
288  bool getBoolAttribute (StringRef attributeName, bool defaultReturnValue = false) const;
289 
303  void setAttribute (const Identifier& attributeName, const String& newValue);
304 
317  void setAttribute (const Identifier& attributeName, int newValue);
318 
331  void setAttribute (const Identifier& attributeName, double newValue);
332 
338  void removeAttribute (const Identifier& attributeName) noexcept;
339 
341  void removeAllAttributes() noexcept;
342 
343  //==============================================================================
344  // Child element methods..
345 
351  XmlElement* getFirstChildElement() const noexcept { return firstChildElement; }
352 
379  inline XmlElement* getNextElement() const noexcept { return nextListItem; }
380 
389  XmlElement* getNextElementWithTagName (StringRef requiredTagName) const;
390 
394  int getNumChildElements() const noexcept;
395 
404  XmlElement* getChildElement (int index) const noexcept;
405 
412  XmlElement* getChildByName (StringRef tagNameToLookFor) const noexcept;
413 
421  XmlElement* getChildByAttribute (StringRef attributeName,
422  StringRef attributeValue) const noexcept;
423 
424  //==============================================================================
438  void addChildElement (XmlElement* newChildElement) noexcept;
439 
451  void insertChildElement (XmlElement* newChildElement,
452  int indexToInsertAt) noexcept;
453 
466  void prependChildElement (XmlElement* newChildElement) noexcept;
467 
482  XmlElement* createNewChildElement (StringRef tagName);
483 
491  bool replaceChildElement (XmlElement* currentChildElement,
492  XmlElement* newChildNode) noexcept;
493 
500  void removeChildElement (XmlElement* childToRemove,
501  bool shouldDeleteTheChild) noexcept;
502 
506  void deleteAllChildElements() noexcept;
507 
511  void deleteAllChildElementsWithTagName (StringRef tagName) noexcept;
512 
514  bool containsChildElement (const XmlElement* possibleChild) const noexcept;
515 
526  XmlElement* findParentElementOf (const XmlElement* childToSearchFor) noexcept;
527 
528  //==============================================================================
551  template <class ElementComparator>
552  void sortChildElements (ElementComparator& comparator,
553  bool retainOrderOfEquivalentItems = false)
554  {
555  auto num = getNumChildElements();
556 
557  if (num > 1)
558  {
559  HeapBlock<XmlElement*> elems (num);
560  getChildElementsAsArray (elems);
561  sortArray (comparator, (XmlElement**) elems, 0, num - 1, retainOrderOfEquivalentItems);
562  reorderChildElements (elems, num);
563  }
564  }
565 
566  //==============================================================================
574  bool isTextElement() const noexcept;
575 
592  const String& getText() const noexcept;
593 
600  void setText (const String& newText);
601 
615  String getAllSubText() const;
616 
625  String getChildElementAllSubText (StringRef childTagName,
626  const String& defaultReturnValue) const;
627 
631  void addTextElement (const String& text);
632 
636  void deleteAllTextElements() noexcept;
637 
639  static XmlElement* createTextElement (const String& text);
640 
642  static bool isValidXmlName (StringRef possibleName) noexcept;
643 
644 private:
645  //==============================================================================
646  struct GetNextElement
647  {
648  XmlElement* getNext (const XmlElement& e) const { return e.getNextElement(); }
649  };
650 
651  struct GetNextElementWithTagName
652  {
653  GetNextElementWithTagName() = default;
654  explicit GetNextElementWithTagName (String n) : name (std::move (n)) {}
655  XmlElement* getNext (const XmlElement& e) const { return e.getNextElementWithTagName (name); }
656 
657  String name;
658  };
659 
660  //==============================================================================
661  template <typename Traits>
662  class Iterator : private Traits
663  {
664  public:
665  using difference_type = ptrdiff_t;
666  using value_type = XmlElement*;
667  using pointer = const value_type*;
668  using reference = value_type;
669  using iterator_category = std::input_iterator_tag;
670 
671  Iterator() = default;
672 
673  template <typename... Args>
674  Iterator (XmlElement* e, Args&&... args)
675  : Traits (std::forward<Args> (args)...), element (e) {}
676 
677  Iterator begin() const { return *this; }
678  Iterator end() const { return Iterator{}; }
679 
680  bool operator== (const Iterator& other) const { return element == other.element; }
681  bool operator!= (const Iterator& other) const { return ! operator== (other); }
682 
683  reference operator*() const { return element; }
684  pointer operator->() const { return &element; }
685 
686  Iterator& operator++()
687  {
688  element = Traits::getNext (*element);
689  return *this;
690  }
691 
692  Iterator operator++ (int)
693  {
694  auto copy = *this;
695  ++(*this);
696  return copy;
697  }
698 
699  private:
700  value_type element = nullptr;
701  };
702 
703 public:
704  //==============================================================================
715  Iterator<GetNextElement> getChildIterator() const
716  {
717  return Iterator<GetNextElement> { getFirstChildElement() };
718  }
719 
730  Iterator<GetNextElementWithTagName> getChildWithTagNameIterator (StringRef name) const
731  {
732  return Iterator<GetNextElementWithTagName> { getChildByName (name), name };
733  }
734 
735  #ifndef DOXYGEN
736  [[deprecated]] void macroBasedForLoop() const noexcept {}
737 
738  [[deprecated ("This has been deprecated in favour of the toString method.")]]
739  String createDocument (StringRef dtdToUse,
740  bool allOnOneLine = false,
741  bool includeXmlHeader = true,
742  StringRef encodingType = "UTF-8",
743  int lineWrapLength = 60) const;
744 
745  [[deprecated ("This has been deprecated in favour of the writeTo method.")]]
746  void writeToStream (OutputStream& output,
747  StringRef dtdToUse,
748  bool allOnOneLine = false,
749  bool includeXmlHeader = true,
750  StringRef encodingType = "UTF-8",
751  int lineWrapLength = 60) const;
752 
753  [[deprecated ("This has been deprecated in favour of the writeTo method.")]]
754  bool writeToFile (const File& destinationFile,
755  StringRef dtdToUse,
756  StringRef encodingType = "UTF-8",
757  int lineWrapLength = 60) const;
758  #endif
759 
760 private:
761  //==============================================================================
762  struct XmlAttributeNode
763  {
764  XmlAttributeNode (const XmlAttributeNode&) noexcept;
765  XmlAttributeNode (const Identifier&, const String&) noexcept;
766  XmlAttributeNode (String::CharPointerType, String::CharPointerType);
767 
768  LinkedListPointer<XmlAttributeNode> nextListItem;
769  Identifier name;
770  String value;
771 
772  private:
773  XmlAttributeNode& operator= (const XmlAttributeNode&) = delete;
774  };
775 
776  friend class XmlDocument;
777  friend class LinkedListPointer<XmlAttributeNode>;
778  friend class LinkedListPointer<XmlElement>;
779  friend class LinkedListPointer<XmlElement>::Appender;
780  friend class NamedValueSet;
781 
782  LinkedListPointer<XmlElement> nextListItem, firstChildElement;
783  LinkedListPointer<XmlAttributeNode> attributes;
784  String tagName;
785 
786  XmlElement (int) noexcept;
787  void copyChildrenAndAttributesFrom (const XmlElement&);
788  void writeElementAsText (OutputStream&, int, int, const char*) const;
789  void getChildElementsAsArray (XmlElement**) const noexcept;
790  void reorderChildElements (XmlElement**, int) noexcept;
791  XmlAttributeNode* getAttribute (StringRef) const noexcept;
792 
793  // Sigh.. L"" or _T ("") string literals are problematic in general, and really inappropriate
794  // for XML tags. Use a UTF-8 encoded literal instead, or if you're really determined to use
795  // UTF-16, cast it to a String and use the other constructor.
796  XmlElement (const wchar_t*) = delete;
797 
798  JUCE_LEAK_DETECTOR (XmlElement)
799 };
800 
801 //==============================================================================
802 #ifndef DOXYGEN
803 
824 #define forEachXmlChildElement(parentXmlElement, childElementVariableName) \
825  for (auto* (childElementVariableName) : ((parentXmlElement).macroBasedForLoop(), (parentXmlElement).getChildIterator()))
826 
852 #define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \
853  for (auto* (childElementVariableName) : ((parentXmlElement).macroBasedForLoop(), (parentXmlElement).getChildWithTagNameIterator ((requiredTagName))))
854 
855 #endif
856 
857 } // namespace juce
Iterator< GetNextElement > getChildIterator() const
XmlElement * getNextElement() const noexcept
const String & getTagName() const noexcept
Iterator< GetNextElementWithTagName > getChildWithTagNameIterator(StringRef name) const