BVB Source Codes

CRYENGINE Show XMLCPB_NodeLiveWriter.cpp Source code

Return Download CRYENGINE: download XMLCPB_NodeLiveWriter.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4. *************************************************************************/
  5.  
  6. #include "StdAfx.h"
  7. #include "XMLCPB_NodeLiveWriter.h"
  8. #include "XMLCPB_Writer.h"
  9.  
  10. using namespace XMLCPB;
  11.  
  12. const int CNodeLiveWriter::INITIAL_SIZE_CHILDREN_VECTOR = 4;
  13. const int CNodeLiveWriter::INITIAL_SIZE_ATTRS_VECTOR = 4;
  14.  
  15. #ifdef XMLCPB_COLLECT_STATS
  16. CNodeLiveWriter::TStats CNodeLiveWriter::m_stats;
  17. #endif
  18.  
  19. /////////////////
  20. void CNodeLiveWriterRef::CopyFrom(const CNodeLiveWriterRef& other)
  21. {
  22.         m_nodeId = other.m_nodeId;
  23.         m_pNode_Debug = other.m_pNode_Debug;
  24.         m_safecheckID = other.m_safecheckID;
  25.  
  26.         if (m_nodeId != XMLCPB_INVALID_ID)
  27.         {
  28.                 CNodeLiveWriter* pNode = m_Writer.GetNodeLive(m_nodeId);
  29.                 if (!pNode->IsValid() || pNode->GetSafeCheckID() != m_safecheckID)
  30.                 {
  31.                         assert(false);
  32.                         m_nodeId = XMLCPB_INVALID_ID;
  33.                         m_pNode_Debug = NULL;
  34.                 }
  35.         }
  36. }
  37.  
  38. ///////////////
  39. CNodeLiveWriter* CNodeLiveWriterRef::GetNode() const
  40. {
  41.         if (m_nodeId == XMLCPB_INVALID_ID)
  42.                 return NULL;
  43.  
  44.         CNodeLiveWriter* pNode = m_Writer.GetNodeLive(m_nodeId);
  45.  
  46.         if (!pNode->IsValid() || pNode->GetSafeCheckID() != m_safecheckID)
  47.         {
  48.                 assert(false);
  49.                 return NULL;
  50.         }
  51.  
  52.         return pNode;
  53. }
  54.  
  55. /////////////////
  56. CNodeLiveWriterRef::CNodeLiveWriterRef(CWriter& Writer, NodeLiveID nodeId)
  57.         : m_Writer(Writer)
  58. {
  59.         m_nodeId = nodeId;
  60.         m_pNode_Debug = NULL;
  61.         if (m_nodeId == XMLCPB_INVALID_ID)
  62.                 return;
  63.  
  64.         CNodeLiveWriter* pNode = m_Writer.GetNodeLive(m_nodeId);
  65.  
  66.         if (!pNode->IsValid())
  67.         {
  68.                 assert(false);
  69.                 return;
  70.         }
  71.  
  72.         m_pNode_Debug = pNode;
  73.         m_safecheckID = pNode->GetSafeCheckID();
  74. }
  75.  
  76. /////////////////
  77. bool CNodeLiveWriterRef::IsValid() const
  78. {
  79.         if (m_nodeId == XMLCPB_INVALID_ID)
  80.                 return false;
  81.  
  82.         CNodeLiveWriter* pNode = m_Writer.GetNodeLive(m_nodeId);
  83.         return (pNode->IsValid() && pNode->GetSafeCheckID() == m_safecheckID);
  84. }
  85.  
  86. //////////////////////////////////////////////////////////////////////////
  87.  
  88. CNodeLiveWriter::CNodeLiveWriter(CWriter& Writer, NodeLiveID ID, StringID IDTag, uint32 safecheckID)
  89.         : m_Writer(Writer)
  90.         , m_ID(ID)
  91. {
  92.         m_attrs.reserve(INITIAL_SIZE_ATTRS_VECTOR);
  93.         m_children.reserve(INITIAL_SIZE_CHILDREN_VECTOR);
  94.         Reuse(IDTag, safecheckID);
  95. }
  96.  
  97. //////////////////////////////////////////////////////////////////////////
  98.  
  99. CNodeLiveWriterRef CNodeLiveWriter::AddChildNode(const char* pChildName)
  100. {
  101.         assert(!m_done && m_valid);
  102.  
  103.         m_totalAmountChildren++;
  104.  
  105.         // only 1 child can be not done at any time
  106.         if (!m_children.empty())
  107.         {
  108.                 CNodeLiveWriter* pPreviousChild = m_Writer.GetNodeLive(m_children.back());
  109.                 if (!pPreviousChild->IsDone())
  110.                         pPreviousChild->Done();
  111.         }
  112.  
  113.         assert(m_children.size() <= CHILDREN_PER_BLOCK);
  114.         if (m_children.size() == CHILDREN_PER_BLOCK)
  115.                 CompactPendingChildren();
  116.  
  117.         //
  118.         CNodeLiveWriter* pChild = m_Writer.CreateAndAddLiveNode(pChildName);
  119.  
  120.         m_children.push_back(pChild->GetID());
  121.  
  122.         pChild->SetParent(GetID());
  123.  
  124.         return CNodeLiveWriterRef(m_Writer, pChild->GetID());
  125. }
  126.  
  127. //////////////////////////////////////////////////////////////////////////
  128.  
  129. void CNodeLiveWriter::SetParent(NodeLiveID ID)
  130. {
  131.         assert(m_IDParent == XMLCPB_INVALID_ID);
  132.         m_IDParent = ID;
  133. }
  134.  
  135. //////////////////////////////////////////////////////////////////////////
  136. // "Done" node is a node that can not be modified anymore, or added more children. Is only waiting for when is the time to be compacted into the main buffer, and discarded.
  137.  
  138. void CNodeLiveWriter::Done()
  139. {
  140.         assert(!m_done && m_valid);
  141.         m_done = true;
  142.  
  143.         int numChildren = m_children.size();
  144.         for (int i = 0; i < numChildren; ++i)
  145.         {
  146.                 CNodeLiveWriter* pChild = m_Writer.GetNodeLive(m_children[i]);
  147.                 if (!pChild->IsDone())
  148.                         pChild->Done();
  149.         }
  150.  
  151.         if (!m_childrenAreCompacted)
  152.         {
  153.                 CompactPendingChildren();
  154.                 m_childrenAreCompacted = true;
  155.         }
  156.  
  157.         if (m_IDParent != XMLCPB_INVALID_ID)
  158.         {
  159.                 CNodeLiveWriter* pParent = m_Writer.GetNodeLive(m_IDParent);
  160.                 pParent->ChildIsDone();
  161.         }
  162.         else
  163.         {
  164.                 Compact();
  165.         }
  166. }
  167.  
  168. //////////////////////////////////////////////////////////////////////////
  169.  
  170. void CNodeLiveWriter::ChildIsDone()
  171. {
  172.         // if all children done, and this is done too, compact the children
  173.         if (m_done)
  174.         {
  175.                 CompactPendingChildren();
  176.                 m_childrenAreCompacted = true;
  177.         }
  178. }
  179.  
  180. //////////////////////////////////////////////////////////////////////////
  181.  
  182. void CNodeLiveWriter::CompactPendingChildren()
  183. {
  184.         int numChildren = m_children.size();
  185.         if (numChildren == 0)
  186.                 return;
  187.  
  188.         for (int i = 0; i < numChildren; ++i)
  189.         {
  190.                 CNodeLiveWriter* pChild = m_Writer.GetNodeLive(m_children[i]);
  191.                 pChild->Compact();
  192.         }
  193.         m_globalIdLastChildInBlock.push_back(m_Writer.GetLastUsedGlobalId());    // the global id is just the order of the node in the final big buffer
  194.         m_children.clear();
  195. }
  196.  
  197. //////////////////////////////////////////////////////////////////////////
  198.  
  199. void CNodeLiveWriter::AddAttr(const char* pAttrName, const uint8* data, uint32 len, bool needInmediateCopy)
  200. {
  201.         assert(data && len > 0);
  202.         assert(!m_done && m_valid);
  203.  
  204.         CAttrWriter attr(m_Writer);
  205.         attr.Set(pAttrName, data, len, needInmediateCopy);
  206.  
  207.         m_attrs.push_back(attr);
  208. }
  209.  
  210. //////////////////////////////////////////////////////////////////////////
  211.  
  212. const char* CNodeLiveWriter::GetTag() const
  213. {
  214.         return m_Writer.GetTagsTable().GetString(m_IDTag);
  215. }
  216.  
  217. //////////////////////////////////////////////////////////////////////////
  218.  
  219. void CNodeLiveWriter::Reuse(StringID IDTag, uint32 safecheckID)
  220. {
  221.         m_IDTag = IDTag;
  222.         m_IDParent = XMLCPB_INVALID_ID;
  223.         m_done = false;
  224.         m_valid = true;
  225.         m_childrenAreCompacted = false;
  226.         m_children.resize(0);
  227.         m_attrs.clear();
  228.         m_totalAmountChildren = 0;
  229.         m_safecheckID = safecheckID;
  230.         m_globalIdLastChildInBlock.resize(0);
  231. }
  232.  
  233. //////////////////////////////////////////////////////////////////////////
  234. // compacting is the process of convert the node information into final binary data, and store it into the writer main buffer.
  235. // binary format for a node:
  236. // 2 bytes  -> header, split into:
  237. //                                                             15 -> 1 = has attrs
  238. //                                                                               14 -> 1 = children are right before
  239. //                                                                               13 ->    -| 0-2 number of children. 3 = more than 2 children
  240. //                                                                               12 ->    -|
  241. //                                                                               11 ->  -|
  242. //                                                                               10 ->  -| 2 bits high for the attrSet id
  243. //                                                                      -> 10 bits  (9-0)  -> Tag ID
  244. //
  245. // 1 byte                               -> children.
  246. //               bit 7 ->  1 = more than 63 children.
  247. //                  -- when bit7 ==1, bit0-6 are the high part of the number
  248. //                  -- when bit7 ==0:
  249. //                                                                              bit 6 -> 1 = compact form. 0 = bits0-5 are number of children
  250. //                                                                              -- when bit6 == 1:
  251. //                        bits 0-2  -> number of children
  252. //                        bits 3-5  -> distance of the last children from this node (in nodes)
  253. // 1 byte                               -> children. Only used if there are more than 127 children. In that case, this is the 8 lower bits, the previous byte is the 7 higher bits
  254. //
  255. // 1/0                      -> 8 lower bits for the attrSet id (only if has attrs )
  256. // 2/0          -> when the final attrSetId is >1022, it is stored in 16 bits here. In that case, the previous byte is 255 and the 2 bits in the header are both 1.
  257. //
  258. // [..]        -> array of children block. Each entry is the distance, in nodes, from this one to the last children of the block.
  259. //                when there is only 1 children block, it can be stored in 8 or 16 bits. When there are more than 1 block, each entry is always 24 bits.
  260. //                -- first byte:
  261. //                      bit 7 -> 0 = 8 bits. in this case, bits 0-6 is the dist.
  262. //                      if bit7 ==1 then:
  263. //                           bit 6 -> 0 = 16 bits. in this case, 0-5 is the high bits, the next byte is the lower bits.
  264. //                              if bit6 ==1 then:
  265. //                                 bits 0-5 is the high bits. the next 2 bytes are the lower bits, stored as a single uint16
  266. //
  267. //
  268. // [...]                                                                        -> attr data
  269.  
  270. void CNodeLiveWriter::Compact()
  271. {
  272.         assert(m_done);
  273.  
  274.         CBufferWriter& writeBuffer = m_Writer.GetMainBuffer();
  275.  
  276.         if (m_IDParent == XMLCPB_INVALID_ID)
  277.                 m_Writer.NotifyRootNodeStartCompact();
  278.  
  279. #ifdef XMLCPB_COLLECT_STATS
  280.         uint32 startSize = writeBuffer.GetDataSize();
  281. #endif
  282.  
  283.         NodeGlobalID lastGlobalId = m_Writer.GetLastUsedGlobalId();
  284.         uint32 numChildBlocks = m_globalIdLastChildInBlock.size();
  285.  
  286.         assert(m_IDTag <= MAX_TAGID);
  287.         uint16 nodeHeader = m_IDTag;
  288.  
  289.         static_assert(BITS_TAGID + HIGHPART_ATTRID_NUM_BITS + CHILDREN_HEADER_BITS <= LOWEST_BIT_USED_AS_FLAG_IN_NODE_HEADER, "Unexpected values!");
  290.  
  291.         uint32 numAttrs = m_attrs.size();
  292.         assert(numAttrs <= MAX_NUM_ATTRS);
  293.  
  294. #ifdef XMLCPB_CHECK_HARDCODED_LIMITS
  295.         CheckHardcodedLimits();
  296. #endif
  297.  
  298.         // attrSetId madness. specified in a few bits in the header + 8 bits outside, but sometimes need 16 extra bits
  299.         AttrSetID attrSetIdReal = XMLCPB_INVALID_ID;
  300.         AttrSetID attrSetId8Bits = XMLCPB_INVALID_ID;
  301.         uint8 attrSetLow8Bits = 0;
  302.         if (numAttrs > 0)
  303.         {
  304.                 nodeHeader |= FLN_HASATTRS;
  305.  
  306.                 uint16 attrHeaders[MAX_NUM_ATTRS];
  307.                 for (int a = 0; a < numAttrs; ++a)
  308.                         attrHeaders[a] = m_attrs[a].CalcHeader();
  309.  
  310.                 CAttrSet set;
  311.                 set.m_numAttrs = numAttrs;
  312.                 set.m_pHeaders = &attrHeaders[0];
  313.  
  314.                 attrSetIdReal = m_Writer.GetAttrSetTable().GetSetID(set);
  315.                 attrSetId8Bits = attrSetIdReal > ATTRID_MAX_VALUE_8BITS ? ATRID_USING_16_BITS : attrSetIdReal;
  316.  
  317.                 attrSetLow8Bits = attrSetId8Bits;
  318.                 uint32 highBitsAttrSetId = (attrSetId8Bits << (HIGHPART_ATTRID_BIT_POSITION - 8)) & HIGHPART_ATTRID_MASK;
  319.                 nodeHeader |= highBitsAttrSetId;
  320.         }
  321.  
  322.         // amount of children is specified in a few bits in the header, when that is possible
  323.         {
  324.                 uint32 val = m_totalAmountChildren;
  325.                 if (m_totalAmountChildren > CHILDREN_HEADER_MAXNUM)
  326.                         val = CHILDREN_HEADER_CANTFIT;
  327.                 val = val << CHILDREN_HEADER_BIT_POSITION;
  328.                 nodeHeader |= val;
  329.         }
  330.  
  331.         bool childrenRightBefore = numChildBlocks == 1 && m_globalIdLastChildInBlock[0] == lastGlobalId;
  332.         if (childrenRightBefore)
  333.                 nodeHeader |= FLN_CHILDREN_ARE_RIGHT_BEFORE;
  334.  
  335.         // write node header, in case you didnt notice!
  336.         writeBuffer.AddData(&nodeHeader, sizeof(nodeHeader));
  337.  
  338.         bool childrenAndDistStoredInFirstByte = false;
  339.  
  340.         // add num children
  341.         if (m_totalAmountChildren > MAX_NUMBER_OF_CHILDREN_IN_8BITS)  // when the number of children does not fit in 8 bits
  342.         {
  343.                 assert(m_totalAmountChildren < MAX_NUMBER_OF_CHILDREN_IN_16BITS);
  344.                 uint8 childrenLow = m_totalAmountChildren & 255;
  345.                 uint8 childrenHigh = m_totalAmountChildren >> 8;
  346.                 childrenHigh |= FL_CHILDREN_NUMBER_IS_16BITS;
  347.                 writeBuffer.AddData(&childrenHigh, sizeof(childrenHigh));
  348.                 writeBuffer.AddData(&childrenLow, sizeof(childrenLow));
  349.         }
  350.         else if (m_totalAmountChildren > CHILDREN_HEADER_MAXNUM)  // when the number of children does not fit in the header, but it does fit in 8 bits
  351.         {
  352.                 // tries to store both the number of children and the distance to them in one single byte.
  353.                 uint32 children = m_totalAmountChildren - CHILDREN_HEADER_MAXNUM; // dirty trick: subtracts the value that could fit in the header, to increase a bit the range of valid values for the all-in-single-byte attempt.
  354.  
  355.                 if (children <= CHILDANDDISTINONEBYTE_MAX_AMOUNT_CHILDREN && !childrenRightBefore)
  356.                 {
  357.                         assert(lastGlobalId > m_globalIdLastChildInBlock[0]);
  358.                         uint32 distNodes = (lastGlobalId - m_globalIdLastChildInBlock[0]) - 1; // dirty trick: -1 because, as it cant never be 0, by doing that we can extend the range a little bit
  359.                         if (distNodes <= CHILDANDDISTINONEBYTE_MAX_DIST)
  360.                         {
  361.                                 uint8 val = children | (distNodes << CHILDANDDISTINONEBYTE_CHILD_BITS) | FL_CHILDREN_NUMBER_AND_BLOCKDIST_IN_ONE_BYTE;
  362.                                 childrenAndDistStoredInFirstByte = true;
  363.                                 writeBuffer.AddData(&val, sizeof(val));
  364.                         }
  365.                 }
  366.                 if (!childrenAndDistStoredInFirstByte)
  367.                 {
  368.                         uint8 val = m_totalAmountChildren;
  369.                         writeBuffer.AddData(&val, sizeof(val));
  370.                 }
  371.         }
  372.  
  373.         // add 8 lower bits of the attrSetId, in case there are attrs, that is. And a full value in 16 bits in case it does not fit. (still need the 8 bits because they mark that situation with an special value)
  374.         if (numAttrs > 0)
  375.         {
  376.                 writeBuffer.AddData(&attrSetLow8Bits, sizeof(attrSetLow8Bits));
  377.                 if (attrSetIdReal > ATTRID_MAX_VALUE_8BITS)
  378.                 {
  379.                         uint16 val16 = attrSetIdReal;
  380.                         assert(attrSetIdReal < 65536);
  381.                         writeBuffer.AddData(&val16, sizeof(val16));
  382.                 }
  383.         }
  384.  
  385.         // addr child blocks
  386.         if (!childrenRightBefore && !childrenAndDistStoredInFirstByte)
  387.         {
  388.                 bool isChildBlockSaved = false;
  389.                 if (numChildBlocks == 1)
  390.                 {
  391.                         uint32 dist = lastGlobalId - m_globalIdLastChildInBlock[0];
  392.  
  393.                         if (dist <= CHILDBLOCKS_MAX_DIST_FOR_8BITS)
  394.                         {
  395.                                 uint8 byteDist = dist;
  396.                                 writeBuffer.AddData(&byteDist, sizeof(byteDist));
  397.                                 isChildBlockSaved = true;
  398.                         }
  399.                         else if (dist <= CHILDBLOCKS_MAX_DIST_FOR_16BITS)
  400.                         {
  401.                                 uint8 byteHigh = CHILDBLOCKS_USING_MORE_THAN_8BITS | (dist >> 8);
  402.                                 uint8 byteLow = dist & 255;
  403.                                 writeBuffer.AddData(&byteHigh, sizeof(byteHigh));
  404.                                 writeBuffer.AddData(&byteLow, sizeof(byteLow));
  405.                                 isChildBlockSaved = true;
  406.                         }
  407.                 }
  408.  
  409.                 if (!isChildBlockSaved)  // can happen either if has only 1 block and the dist cant fit in 8-16 bits, or because it has more than 1 block of children
  410.                 {
  411.                         for (int i = 0; i < numChildBlocks; ++i)
  412.                         {
  413.                                 uint32 dist = lastGlobalId - m_globalIdLastChildInBlock[i];
  414.                                 uint8 byteHigh = CHILDBLOCKS_USING_24BITS | (dist >> 16);
  415.                                 uint16 wordLow = dist & 65535;
  416.                                 writeBuffer.AddData(&byteHigh, sizeof(byteHigh));
  417.                                 writeBuffer.AddData(&wordLow, sizeof(wordLow));
  418.                         }
  419.                 }
  420.         }
  421.  
  422. #ifdef XMLCPB_COLLECT_STATS
  423.         uint32 endSize = writeBuffer.GetDataSize();
  424.         if (m_Writer.IsSavingIntoFile())
  425.         {
  426.                 m_stats.m_totalSizeNodeData += (endSize - startSize);
  427.                 startSize = endSize; // to calc the attrs
  428.         }
  429. #endif
  430.  
  431.         for (int a = 0; a < m_attrs.size(); ++a)
  432.         {
  433.                 m_attrs[a].Compact();
  434.         }
  435.  
  436. #ifdef XMLCPB_COLLECT_STATS
  437.         if (m_Writer.IsSavingIntoFile())
  438.         {
  439.                 endSize = writeBuffer.GetDataSize();
  440.                 m_stats.m_totalSizeAttrData += (endSize - startSize);
  441.  
  442.                 m_stats.m_maxNumChildren = max(m_stats.m_maxNumChildren, m_totalAmountChildren);
  443.                 m_stats.m_maxNumAttrs = max(m_stats.m_maxNumAttrs, m_attrs.size());
  444.                 m_stats.m_totalAttrs += m_attrs.size();
  445.                 m_stats.m_totalChildren += m_totalAmountChildren;
  446.                 m_stats.m_totalNodesCreated++;
  447.         }
  448. #endif
  449.  
  450.         m_valid = false;
  451.         m_Writer.NotifyNodeCompacted();
  452.         m_Writer.FreeNodeLive(GetID());
  453. }
  454.  
  455. //////////////////////////////////////////////////////////////////////////
  456. // used only for debug purposes
  457. const char* CNodeLiveWriter::ReadAttrStr(const char* pAttrName)
  458. {
  459.         for (int i = 0; i < m_attrs.size(); ++i)
  460.         {
  461.                 if (strcmp(m_attrs[i].GetName(), pAttrName) == 0)
  462.                 {
  463.                         return m_attrs[i].GetStrData();
  464.                 }
  465.         }
  466.  
  467.         return NULL;
  468. }
  469.  
  470. //////////////////////////////////////////////////////////////////////////
  471. // used only for debug purposes
  472. bool CNodeLiveWriter::HaveAttr(const char* pAttrName)
  473. {
  474.         for (int i = 0; i < m_attrs.size(); ++i)
  475.         {
  476.                 if (strcmp(m_attrs[i].GetName(), pAttrName) == 0)
  477.                 {
  478.                         return true;
  479.                 }
  480.         }
  481.  
  482.         return false;
  483. }
  484.  
  485. #ifdef XMLCPB_CHECK_HARDCODED_LIMITS
  486.  
  487. //////////////////////////////////////////////////////////////////////////
  488. void CNodeLiveWriter::CheckHardcodedLimits()
  489. {
  490.         if (!m_Writer.HasInternalError())
  491.         {
  492.                 uint32 numAttrs = m_attrs.size();
  493.                 if (m_IDTag > MAX_TAGID)
  494.                 {
  495.                         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: IDTag overflow: %u / %d", m_IDTag, MAX_TAGID);
  496.                         ShowExtendedErrorInfo();
  497.                         m_Writer.NotifyInternalError();
  498.                 }
  499.                 else if (numAttrs > MAX_NUM_ATTRS)
  500.                 {
  501.                         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: NumAttrs overflow: %u / %d", numAttrs, MAX_NUM_ATTRS);
  502.                         ShowExtendedErrorInfo();
  503.                         m_Writer.NotifyInternalError();
  504.                 }
  505.                 else if (m_totalAmountChildren > MAX_NUMBER_OF_CHILDREN_IN_16BITS)
  506.                 {
  507.                         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "XMLCPB ERROR: NumChildren overflow: %u / %d", m_totalAmountChildren, MAX_NUMBER_OF_CHILDREN_IN_16BITS);
  508.                         ShowExtendedErrorInfo();
  509.                         m_Writer.NotifyInternalError();
  510.                 }
  511.                 else
  512.                 {
  513.                         for (uint32 a = 0; a < numAttrs; ++a)
  514.                         {
  515.                                 m_attrs[a].CheckHardcodedLimits(a);
  516.                                 if (m_Writer.HasInternalError())
  517.                                 {
  518.                                         ShowExtendedErrorInfo();
  519.                                         break;
  520.                                 }
  521.                         }
  522.                 }
  523.         }
  524. }
  525.  
  526. void CNodeLiveWriter::ShowExtendedErrorInfo() const
  527. {
  528.         const CNodeLiveWriter* pNode = this;
  529.         std::vector<const CNodeLiveWriter*> nodesVec;
  530.         do
  531.         {
  532.                 nodesVec.push_back(pNode);
  533.                 if (pNode->m_IDParent != XMLCPB_INVALID_ID)
  534.                         pNode = m_Writer.GetNodeLive(pNode->m_IDParent);
  535.         }
  536.         while (pNode->m_IDParent != XMLCPB_INVALID_ID);
  537.  
  538.         string buf;
  539.         for (int i = nodesVec.size() - 1; i >= 0; --i)
  540.         {
  541.                 const CNodeLiveWriter* pNodeInt = nodesVec[i];
  542.                 buf.append(m_Writer.GetTagsTable().GetStringSafe(pNodeInt->m_IDTag));
  543.                 if (i != 0)
  544.                         buf.append("->");
  545.         }
  546.  
  547.         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Node: %s", buf.c_str());
  548. }
  549. #endif
  550.  
downloadXMLCPB_NodeLiveWriter.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top