LCOV - code coverage report
Current view: top level - source/ps/XMB - XMBData.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 33 34 97.1 %
Date: 2023-01-19 00:18:29 Functions: 20 21 95.2 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : /*
      19             :     Xeromyces - XMB reading library
      20             : 
      21             : Brief outline:
      22             : 
      23             : XMB originated as a binary representation of XML, with some limitations
      24             : but much more efficiency (particularly for loading simple data
      25             : classes that don't need much initialisation).
      26             : 
      27             : Theoretical file structure:
      28             : 
      29             : XMB_File {
      30             :     char Header[4]; // because everyone has one; currently "XMB0"
      31             :     u32 Version;
      32             : 
      33             :     int OffsetFromStartToElementNames;
      34             :     int ElementNameCount;
      35             : 
      36             :     int OffsetFromStartToAttributeNames;
      37             :     int AttributeNameCount;
      38             : 
      39             :     XMB_Node Root;
      40             : 
      41             :     ZStr8 ElementNames[];
      42             :     ZStr8 AttributeNames[];
      43             : 
      44             : }
      45             : 
      46             : XMB_Node {
      47             : 0)  int Length; // of entire struct, so it can be skipped over
      48             : 
      49             : 4)  int ElementName;
      50             : 
      51             : 8)  int AttributeCount;
      52             : 12) int ChildCount;
      53             : 
      54             : 16) int ChildrenOffset; // == sizeof(Text)+sizeof(Attributes)
      55             : 20) XMB_Text Text;
      56             :     XMB_Attribute Attributes[];
      57             :     XMB_Node Children[];
      58             : 
      59             : }
      60             : 
      61             : XMB_Attribute {
      62             :     int Name;
      63             :     ZStr8 Value;
      64             : }
      65             : 
      66             : ZStr8 {
      67             :     int Length; // in bytes
      68             :     char* Text; // null-terminated UTF8
      69             : }
      70             : 
      71             : XMB_Text {
      72             : 20) int Length; // 0 if there's no text, else 4+sizeof(Text) in bytes including terminator
      73             :     // If Length != 0:
      74             : 24) int LineNumber; // for e.g. debugging scripts
      75             : 28) char* Text; // null-terminated UTF8
      76             : }
      77             : 
      78             : */
      79             : 
      80             : #ifndef INCLUDED_XEROXMB
      81             : #define INCLUDED_XEROXMB
      82             : 
      83             : #include "ps/CStr.h"
      84             : 
      85             : #include <string>
      86             : #include <string_view>
      87             : 
      88             : class XMBStorage;
      89             : 
      90             : class XMBElement;
      91             : class XMBElementList;
      92             : class XMBAttributeList;
      93             : 
      94             : 
      95             : class XMBData
      96             : {
      97             : public:
      98             : 
      99         496 :     XMBData() : m_Pointer(nullptr) {}
     100             : 
     101             :     /*
     102             :     * Initialise from the contents of an XMBStorage.
     103             :     * @param doc must remain allocated and unchanged while
     104             :     * the XMBData is being used.
     105             :     * @return indication of success; main cause for failure is attempting to
     106             :     * load a partially valid XMB file (e.g. if the game was interrupted
     107             :     * while writing it), which we detect by checking the magic string.
     108             :     * It also fails when trying to load an XMB file with a different version.
     109             :     */
     110             :     bool Initialise(const XMBStorage& doc);
     111             : 
     112             :     // Returns the root element
     113             :     XMBElement GetRoot() const;
     114             : 
     115             :     // Returns internal ID for a given element/attribute string.
     116             :     int GetElementID(const char* Name) const;
     117             :     int GetAttributeID(const char* Name) const;
     118             : 
     119             :     // Returns element/attribute string for a given internal ID.
     120             :     const char* GetElementString(const int ID) const;
     121             :     const char* GetAttributeString(const int ID) const;
     122             : 
     123             :     std::string_view GetElementStringView(const int ID) const;
     124             :     std::string_view GetAttributeStringView(const int ID) const;
     125             : 
     126             : private:
     127             :     const char* m_Pointer;
     128             : 
     129             :     int m_ElementNameCount;
     130             :     int m_AttributeNameCount;
     131             :     const char* m_ElementPointer;
     132             :     const char* m_AttributePointer;
     133             : };
     134             : 
     135             : class XMBElement
     136             : {
     137             : public:
     138           3 :     XMBElement()
     139           3 :         : m_Pointer(0) {}
     140             : 
     141         869 :     XMBElement(const char* offset)
     142         869 :         : m_Pointer(offset) {}
     143             : 
     144             :     int GetNodeName() const;
     145             :     XMBElementList GetChildNodes() const;
     146             :     XMBAttributeList GetAttributes() const;
     147             :     CStr8 GetText() const;
     148             :     // Returns the line number of the text within this element,
     149             :     // or -1 if there is no text
     150             :     int GetLineNumber() const;
     151             : 
     152             : private:
     153             :     // Pointer to the start of the node
     154             :     const char* m_Pointer;
     155             : };
     156             : 
     157             : class XMBElementList
     158             : {
     159             : public:
     160         497 :     XMBElementList(const char* offset, size_t count, const char* endoffset)
     161         497 :         : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
     162             : 
     163             :     // Get first element in list with the given name.
     164             :     // Performance is linear in the number of elements in the list.
     165             :     XMBElement GetFirstNamedItem(const int ElementName) const;
     166             : 
     167             :     // Linear in the number of elements in the list
     168             :     XMBElement operator[](size_t id); // returns Children[id]
     169             : 
     170             :     class iterator
     171             :     {
     172             :     public:
     173             :         typedef ptrdiff_t difference_type;
     174             :         typedef XMBElement value_type;
     175             :         typedef XMBElement reference; // Because we need to construct the object
     176             :         typedef XMBElement pointer; // Because we need to construct the object
     177             :         typedef std::forward_iterator_tag iterator_category;
     178             : 
     179         944 :         iterator(size_t size, const char* ptr, const char* endptr = NULL)
     180         944 :             : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr) {}
     181         402 :         XMBElement operator*() const { return XMBElement(m_CurPointer); }
     182             :         XMBElement operator->() const { return **this; }
     183             :         iterator& operator++();
     184             : 
     185         874 :         bool operator==(const iterator& rhs) const
     186             :         {
     187        1748 :             return m_Size == rhs.m_Size &&
     188        1346 :                    m_CurItemID == rhs.m_CurItemID &&
     189        1346 :                    m_CurPointer == rhs.m_CurPointer;
     190             :         }
     191         874 :         bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
     192             :     private:
     193             :         size_t m_Size;
     194             :         size_t m_CurItemID;
     195             :         const char* m_CurPointer;
     196             :     };
     197         472 :     iterator begin() { return iterator(m_Size, m_Pointer); }
     198         472 :     iterator end() { return iterator(m_Size, m_Pointer, m_EndPointer); }
     199             : 
     200          12 :     size_t size() const { return m_Size; }
     201           0 :     bool empty() const { return m_Size == 0; }
     202             : 
     203             : private:
     204             :     size_t m_Size;
     205             : 
     206             :     const char* m_Pointer;
     207             : 
     208             :     // For optimised sequential access:
     209             :     size_t m_CurItemID;
     210             :     const char* m_CurPointer;
     211             : 
     212             :     const char* m_EndPointer;
     213             : };
     214             : 
     215             : 
     216         374 : struct XMBAttribute
     217             : {
     218             :     XMBAttribute() {}
     219         374 :     XMBAttribute(int name, const CStr8& value)
     220         374 :         : Name(name), Value(value) {};
     221             : 
     222             :     int Name;
     223             :     CStr8 Value; // UTF-8 encoded
     224             : };
     225             : 
     226             : class XMBAttributeList
     227             : {
     228             : public:
     229        1747 :     XMBAttributeList(const char* offset, size_t count, const char* endoffset)
     230        1747 :         : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
     231             : 
     232             :     // Get the attribute value directly
     233             :     CStr8 GetNamedItem(const int AttributeName) const;
     234             : 
     235             :     // Linear in the number of elements in the list
     236             :     XMBAttribute operator[](size_t id); // returns Children[id]
     237             : 
     238             :     class iterator
     239             :     {
     240             :     public:
     241             :         typedef ptrdiff_t difference_type;
     242             :         typedef XMBAttribute value_type;
     243             :         typedef XMBAttribute reference; // Because we need to construct the object
     244             :         typedef XMBAttribute pointer; // Because we need to construct the object
     245             :         typedef std::forward_iterator_tag iterator_category;
     246             : 
     247        2786 :         iterator(size_t size, const char* ptr, const char* endptr = NULL)
     248        2786 :             : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr) {}
     249             :         XMBAttribute operator*() const;
     250             :         XMBAttribute operator->() const { return **this; }
     251             :         iterator& operator++();
     252             : 
     253        1730 :         bool operator==(const iterator& rhs) const
     254             :         {
     255        3460 :             return m_Size == rhs.m_Size &&
     256        3091 :                    m_CurItemID == rhs.m_CurItemID &&
     257        3091 :                    m_CurPointer == rhs.m_CurPointer;
     258             :         }
     259        1730 :         bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
     260             :     private:
     261             :         size_t m_Size;
     262             :         size_t m_CurItemID;
     263             :         const char* m_CurPointer;
     264             :     };
     265        1393 :     iterator begin() const { return iterator(m_Size, m_Pointer); }
     266        1393 :     iterator end() const { return iterator(m_Size, m_Pointer, m_EndPointer); }
     267             : 
     268           6 :     size_t size() const { return m_Size; }
     269             :     bool empty() const { return m_Size == 0; }
     270             : 
     271             : private:
     272             :     size_t m_Size;
     273             : 
     274             :     // Pointer to start of attribute list
     275             :     const char* m_Pointer;
     276             : 
     277             :     // For optimised sequential access:
     278             :     size_t m_CurItemID;
     279             :     const char* m_CurPointer;
     280             : 
     281             :     const char* m_EndPointer;
     282             : };
     283             : 
     284             : #endif // INCLUDED_XEROXMB

Generated by: LCOV version 1.13