LCOV - code coverage report
Current view: top level - source/tools/atlas/AtlasObject - AtlasObjectImpl.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 12 167 7.2 %
Date: 2023-01-19 00:18:29 Functions: 6 37 16.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             : #include "AtlasObject.h"
      19             : #include "AtlasObjectImpl.h"
      20             : 
      21             : #include <assert.h>
      22             : #include <sstream>
      23             : 
      24             : #define ATSMARTPTR_IMPL(T) \
      25             :     template<> void AtSmartPtr<T>::inc_ref()    \
      26             :     {                                           \
      27             :         if (ptr) ++ptr->m_Refcount;              \
      28             :     }                                           \
      29             :                                                 \
      30             :     template<> void AtSmartPtr<T>::dec_ref()    \
      31             :     {                                           \
      32             :         if (ptr && --ptr->m_Refcount == 0)       \
      33             :             delete ptr;                         \
      34             :     }   // (Don't set ptr=NULL, since it should never be possible for an
      35             :         // unreferenced pointer to exist; I would rather see it die in debug
      36             :         // mode if that ever happens, instead of just silently ignoring the error.)
      37             : 
      38             : 
      39          42 : ATSMARTPTR_IMPL(AtNode)
      40         402 : ATSMARTPTR_IMPL(const AtNode)
      41           0 : ATSMARTPTR_IMPL(AtIterImpl)
      42             : 
      43             : 
      44             : //////////////////////////////////////////////////////////////////////////
      45             : 
      46           0 : const AtIter AtIter::operator [] (const char* key) const
      47             : {
      48           0 :     if (m_Impl)
      49           0 :         return m_Impl->iter->second->getChild(key);
      50             :     else
      51           0 :         return AtIter();
      52             : }
      53             : 
      54           0 : AtIter::operator const char* () const
      55             : {
      56           0 :     return m_Impl ? m_Impl->iter->second->m_Value.c_str() : "";
      57             : }
      58             : 
      59             : //AtIter::operator const AtObj () const
      60           0 : const AtObj AtIter::operator * () const
      61             : {
      62           0 :     if (m_Impl)
      63             :     {
      64           0 :         AtObj ret;
      65           0 :         ret.m_Node = m_Impl->iter->second;
      66           0 :         return ret;
      67             :     }
      68             :     else
      69           0 :         return AtObj();
      70             : }
      71             : 
      72             : 
      73           0 : AtIter& AtIter::operator ++ ()
      74             : {
      75           0 :     assert(m_Impl);
      76             : 
      77             :     // Increment the internal iterator, and stop if we've run out children
      78             :     // to iterate over.
      79           0 :     if (m_Impl && ++m_Impl->iter == m_Impl->iter_upperbound)
      80           0 :         m_Impl = nullptr;
      81             : 
      82           0 :     return *this;
      83             : }
      84             : 
      85           0 : bool AtIter::defined() const
      86             : {
      87           0 :     return static_cast<bool>(m_Impl);
      88             : }
      89             : 
      90           0 : bool AtIter::hasContent() const
      91             : {
      92           0 :     if (!m_Impl)
      93           0 :         return false;
      94             : 
      95           0 :     if (!m_Impl->iter->second)
      96           0 :         return false;
      97             : 
      98           0 :     return m_Impl->iter->second->hasContent();
      99             : }
     100             : 
     101           0 : size_t AtIter::count() const
     102             : {
     103           0 :     if (!m_Impl)
     104           0 :         return 0;
     105             : 
     106           0 :     return std::distance(m_Impl->iter, m_Impl->iter_upperbound);
     107             : }
     108             : 
     109             : //////////////////////////////////////////////////////////////////////////
     110             : 
     111           0 : const AtIter AtObj::operator [] (const char* key) const
     112             : {
     113           0 :     if (m_Node)
     114           0 :         return m_Node->getChild(key);
     115             :     else
     116             :         // This object doesn't exist, so return another object that doesn't exist
     117           0 :         return AtIter();
     118             : }
     119             : 
     120           0 : AtObj::operator const char* () const
     121             : {
     122           0 :     return m_Node ? m_Node->m_Value.c_str() : "";
     123             : }
     124             : 
     125           0 : double AtObj::getDouble() const
     126             : {
     127           0 :     double val = 0;
     128           0 :     if (m_Node)
     129           0 :         static_cast<std::stringstream>(m_Node->m_Value) >> val;
     130           0 :     return val;
     131             : }
     132             : 
     133           0 : int AtObj::getInt() const
     134             : {
     135           0 :     int val = 0;
     136           0 :     if (m_Node)
     137           0 :         static_cast<std::stringstream>(m_Node->m_Value) >> val;
     138           0 :     return val;
     139             : }
     140             : 
     141           0 : long AtObj::getLong() const
     142             : {
     143           0 :     long val = 0;
     144           0 :     if (m_Node)
     145           0 :         static_cast<std::stringstream>(m_Node->m_Value) >> val;
     146           0 :     return val;
     147             : }
     148             : 
     149           0 : void AtObj::add(const char* key, AtObj& data)
     150             : {
     151           0 :     if (!m_Node)
     152           0 :         m_Node = new AtNode();
     153             : 
     154           0 :     m_Node = m_Node->addChild(key, data.m_Node);
     155           0 : }
     156             : 
     157           0 : void AtObj::add(const char* key, const char* value)
     158             : {
     159           0 :     const AtNode* o = new AtNode(value);
     160             : 
     161           0 :     if (!m_Node)
     162           0 :         m_Node = new AtNode();
     163             : 
     164           0 :     m_Node = m_Node->addChild(key, AtNode::Ptr(o));
     165           0 : }
     166             : 
     167          13 : void AtObj::set(const char* key, AtObj& data)
     168             : {
     169          13 :     if (!m_Node)
     170          13 :         m_Node = new AtNode();
     171             : 
     172          13 :     m_Node = m_Node->setChild(key, data.m_Node);
     173          13 : }
     174             : 
     175           0 : void AtObj::set(const char* key, const char* value)
     176             : {
     177           0 :     const AtNode* o = new AtNode(value);
     178             : 
     179           0 :     if (!m_Node)
     180           0 :         m_Node = new AtNode();
     181             : 
     182           0 :     m_Node = m_Node->setChild(key, AtNode::Ptr(o));
     183           0 : }
     184             : 
     185           0 : void AtObj::unset(const char* key)
     186             : {
     187           0 :     if (!m_Node)
     188           0 :         m_Node = new AtNode();
     189             : 
     190           0 :     m_Node = m_Node->unsetChild(key);
     191           0 : }
     192             : 
     193           0 : void AtObj::setBool(const char* key, bool value)
     194             : {
     195           0 :     AtNode* o = new AtNode(value ? "true" : "false");
     196           0 :     o->m_Children.insert(AtNode::child_pairtype("@boolean", AtNode::Ptr(new AtNode())));
     197             : 
     198           0 :     if (!m_Node)
     199           0 :         m_Node = new AtNode();
     200             : 
     201           0 :     m_Node = m_Node->setChild(key, AtNode::Ptr(o));
     202           0 : }
     203             : 
     204           0 : void AtObj::setDouble(const char* key, double value)
     205             : {
     206           0 :     std::stringstream str;
     207           0 :     str << value;
     208           0 :     AtNode* o = new AtNode(str.str().c_str());
     209           0 :     o->m_Children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
     210             : 
     211           0 :     if (!m_Node)
     212           0 :         m_Node = new AtNode();
     213             : 
     214           0 :     m_Node = m_Node->setChild(key, AtNode::Ptr(o));
     215           0 : }
     216             : 
     217           0 : void AtObj::setInt(const char* key, int value)
     218             : {
     219           0 :     std::stringstream str;
     220           0 :     str << value;
     221           0 :     AtNode* o = new AtNode(str.str().c_str());
     222           0 :     o->m_Children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
     223             : 
     224           0 :     if (!m_Node)
     225           0 :         m_Node = new AtNode();
     226             : 
     227           0 :     m_Node = m_Node->setChild(key, AtNode::Ptr(o));
     228           0 : }
     229             : 
     230           0 : void AtObj::setString(const char* value)
     231             : {
     232           0 :     if (!m_Node)
     233           0 :         m_Node = new AtNode();
     234             : 
     235           0 :     m_Node = m_Node->setValue(value);
     236           0 : }
     237             : 
     238           0 : void AtObj::addOverlay(AtObj& data)
     239             : {
     240           0 :     if (!m_Node)
     241           0 :         m_Node = new AtNode();
     242             : 
     243           0 :     m_Node = m_Node->addOverlay(data.m_Node);
     244           0 : }
     245             : 
     246           0 : bool AtObj::hasContent() const
     247             : {
     248           0 :     if (!m_Node)
     249           0 :         return false;
     250             : 
     251           0 :     return m_Node->hasContent();
     252             : }
     253             : 
     254             : //////////////////////////////////////////////////////////////////////////
     255             : 
     256           0 : const AtIter AtNode::getChild(const char* key) const
     257             : {
     258             :     // Find the range of matching children
     259           0 :     AtNode::child_maptype::const_iterator it = m_Children.lower_bound(key);
     260           0 :     AtNode::child_maptype::const_iterator it_upper = m_Children.upper_bound(key);
     261             : 
     262           0 :     if (it == it_upper) // No match found
     263           0 :         return AtIter();
     264             : 
     265           0 :     AtIter obj;
     266           0 :     obj.m_Impl = new AtIterImpl(it, it_upper);
     267           0 :     return obj;
     268             : }
     269             : 
     270           0 : bool AtNode::hasContent() const
     271             : {
     272           0 :     if (m_Value.length())
     273           0 :         return true;
     274             : 
     275           0 :     for (const child_maptype::value_type& child : m_Children)
     276           0 :         if (child.second && child.second->hasContent())
     277           0 :             return true;
     278             : 
     279           0 :     return false;
     280             : }
     281             : 
     282           0 : const AtNode::Ptr AtNode::setValue(const char* value) const
     283             : {
     284           0 :     AtNode* newNode = new AtNode();
     285           0 :     newNode->m_Children = m_Children;
     286           0 :     newNode->m_Value = value;
     287           0 :     return AtNode::Ptr(newNode);
     288             : }
     289             : 
     290          13 : const AtNode::Ptr AtNode::setChild(const char* key, const AtNode::Ptr &data) const
     291             : {
     292          13 :     AtNode* newNode = new AtNode(this);
     293          13 :     newNode->m_Children.erase(key);
     294          13 :     newNode->m_Children.insert(AtNode::child_pairtype(key, data));
     295          13 :     return AtNode::Ptr(newNode);
     296             : }
     297             : 
     298           0 : const AtNode::Ptr AtNode::unsetChild(const char* key) const
     299             : {
     300           0 :         AtNode* newNode = new AtNode(this);
     301           0 :         newNode->m_Children.erase(key);
     302           0 :         return AtNode::Ptr(newNode);
     303             : }
     304             : 
     305           0 : const AtNode::Ptr AtNode::addChild(const char* key, const AtNode::Ptr &data) const
     306             : {
     307           0 :     AtNode* newNode = new AtNode(this);
     308           0 :     newNode->m_Children.insert(AtNode::child_pairtype(key, data));
     309           0 :     return AtNode::Ptr(newNode);
     310             : }
     311             : 
     312           0 : const AtNode::Ptr AtNode::addOverlay(const AtNode::Ptr &data) const
     313             : {
     314           0 :     AtNode* newNode = new AtNode(this);
     315             : 
     316             :     // Delete old childs that are also in the overlay
     317           0 :     for (AtNode::child_maptype::const_iterator it = data->m_Children.begin(); it != data->m_Children.end(); ++it)
     318           0 :         newNode->m_Children.erase(it->first);
     319             : 
     320             :     // Add the overlay childs back in
     321           0 :     for (AtNode::child_maptype::const_iterator it = data->m_Children.begin(); it != data->m_Children.end(); ++it)
     322           0 :         newNode->m_Children.insert(*it);
     323             : 
     324           0 :     return AtNode::Ptr(newNode);
     325             : }
     326             : //////////////////////////////////////////////////////////////////////////
     327             : 
     328           0 : AtObj AtlasObject::TrimEmptyChildren(AtObj& obj)
     329             : {
     330           0 :     AtObj ret;
     331             : 
     332           0 :     for (const AtNode::child_maptype::value_type& child : obj.m_Node->m_Children)
     333             :     {
     334           0 :         if (child.second && child.second->hasContent())
     335             :         {
     336           0 :             AtObj node;
     337           0 :             node.m_Node = child.second;
     338           0 :             ret.add(child.first.c_str(), node);
     339             :         }
     340             :     }
     341             : 
     342           0 :     return ret;
     343             : }

Generated by: LCOV version 1.13