Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
8.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "importkeyvaluebase.h"
  7. #include "dmserializers.h"
  8. #include "datamodel/idatamodel.h"
  9. #include "datamodel/dmelement.h"
  10. #include "tier1/KeyValues.h"
  11. #include "tier1/utlbuffer.h"
  12. #include <limits.h>
  13. //-----------------------------------------------------------------------------
  14. // Default serialization method
  15. //-----------------------------------------------------------------------------
  16. bool CImportKeyValueBase::Serialize( CUtlBuffer &outBuf, CDmElement *pRoot )
  17. {
  18. Warning( "Serialization not supported for importing from keyvalues files\n");
  19. return false;
  20. }
  21. //-----------------------------------------------------------------------------
  22. // Creates a new element
  23. //-----------------------------------------------------------------------------
  24. CDmElement* CImportKeyValueBase::CreateDmElement( const char *pElementType, const char *pElementName, DmObjectId_t *pId )
  25. {
  26. // See if we can create an element of that type
  27. DmElementHandle_t hElement = g_pDataModel->CreateElement( pElementType, pElementName, DMFILEID_INVALID, pId );
  28. if ( hElement == DMELEMENT_HANDLE_INVALID )
  29. {
  30. Warning("%s: Element uses unknown element type %s\n", m_pFileName, pElementType );
  31. return NULL;
  32. }
  33. return g_pDataModel->GetElement( hElement );
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Used to output typed attributes to keyvalues
  37. //-----------------------------------------------------------------------------
  38. void CImportKeyValueBase::PrintBoolAttribute( CDmElement* pElement, CUtlBuffer &outBuf, const char *pKeyName )
  39. {
  40. if ( pElement->HasAttribute( pKeyName ) )
  41. {
  42. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  43. if ( pAttribute->GetType() == AT_BOOL )
  44. {
  45. outBuf.Printf("\"%s\" \"%d\"\n", pKeyName, pAttribute->GetValue<bool>( ) );
  46. }
  47. }
  48. }
  49. void CImportKeyValueBase::PrintIntAttribute( CDmElement* pElement, CUtlBuffer &outBuf, const char *pKeyName )
  50. {
  51. if ( pElement->HasAttribute( pKeyName ) )
  52. {
  53. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  54. if ( pAttribute->GetType() == AT_INT )
  55. {
  56. outBuf.Printf("\"%s\" \"%d\"\n", pKeyName, pAttribute->GetValue<int>( ) );
  57. }
  58. }
  59. }
  60. void CImportKeyValueBase::PrintFloatAttribute( CDmElement* pElement, CUtlBuffer &outBuf, const char *pKeyName )
  61. {
  62. if ( pElement->HasAttribute( pKeyName ) )
  63. {
  64. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  65. if ( pAttribute->GetType() == AT_FLOAT )
  66. {
  67. outBuf.Printf("\"%s\" \"%.10f\"\n", pKeyName, pAttribute->GetValue<float>( ) );
  68. }
  69. }
  70. }
  71. void CImportKeyValueBase::PrintStringAttribute( CDmElement* pElement, CUtlBuffer &outBuf, const char *pKeyName, bool bSkipEmptryStrings, bool bPrintValueOnly )
  72. {
  73. if ( pElement->HasAttribute( pKeyName ) )
  74. {
  75. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  76. if ( pAttribute->GetType() == AT_STRING )
  77. {
  78. const char *pValue = pAttribute->GetValueString();
  79. if ( !bSkipEmptryStrings || pValue[0] )
  80. {
  81. if ( !bPrintValueOnly )
  82. {
  83. outBuf.Printf("\"%s\" \"%s\"\n", pKeyName, pValue );
  84. }
  85. else
  86. {
  87. outBuf.Printf("\"%s\"\n", pValue );
  88. }
  89. }
  90. }
  91. }
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Used to add typed attributes from keyvalues
  95. //-----------------------------------------------------------------------------
  96. bool CImportKeyValueBase::AddBoolAttribute( CDmElement* pElement, KeyValues *pKeyValues, const char *pKeyName, bool *pDefault )
  97. {
  98. KeyValues *pKey = pKeyValues->FindKey( pKeyName );
  99. bool bValue;
  100. if ( pKey )
  101. {
  102. bValue = pKey->GetInt() != 0;
  103. }
  104. else
  105. {
  106. if ( !pDefault )
  107. return true;
  108. bValue = *pDefault;
  109. }
  110. return pElement->SetValue( pKeyName, bValue ) != NULL;
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Used to add typed attributes from keyvalues
  114. //-----------------------------------------------------------------------------
  115. bool CImportKeyValueBase::AddIntAttribute( CDmElement* pElement, KeyValues *pKeyValues, const char *pKeyName, int *pDefault )
  116. {
  117. KeyValues *pKey = pKeyValues->FindKey( pKeyName );
  118. int nValue;
  119. if ( pKey )
  120. {
  121. nValue = pKey->GetInt();
  122. }
  123. else
  124. {
  125. if ( !pDefault )
  126. return true;
  127. nValue = *pDefault;
  128. }
  129. return pElement->SetValue( pKeyName, nValue ) != NULL;
  130. }
  131. bool CImportKeyValueBase::AddFloatAttribute( CDmElement* pElement, KeyValues *pKeyValues, const char *pKeyName, float *pDefault )
  132. {
  133. KeyValues *pKey = pKeyValues->FindKey( pKeyName );
  134. float flValue;
  135. if ( pKey )
  136. {
  137. flValue = pKey->GetFloat();
  138. }
  139. else
  140. {
  141. if ( !pDefault )
  142. return true;
  143. flValue = *pDefault;
  144. }
  145. return pElement->SetValue( pKeyName, flValue ) != NULL;
  146. }
  147. bool CImportKeyValueBase::AddStringAttribute( CDmElement* pElement, KeyValues *pKeyValues, const char *pKeyName, const char *pDefault )
  148. {
  149. KeyValues *pKey = pKeyValues->FindKey( pKeyName );
  150. const char *pValue = "";
  151. if ( pKey )
  152. {
  153. pValue = pKey->GetString();
  154. }
  155. else
  156. {
  157. if ( !pDefault )
  158. return true;
  159. pValue = pDefault;
  160. }
  161. return pElement->SetValue( pKeyName, pValue ) != NULL;
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Used to add typed attributes from keyvalues
  165. //-----------------------------------------------------------------------------
  166. bool CImportKeyValueBase::AddBoolAttributeFlags( CDmElement* pElement, KeyValues *pKeyValue, const char *pKeyName, int nFlags, bool *pDefault )
  167. {
  168. if ( !AddBoolAttribute( pElement, pKeyValue, pKeyName, pDefault ) )
  169. return false;
  170. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  171. pAttribute->AddFlag( nFlags );
  172. return true;
  173. }
  174. bool CImportKeyValueBase::AddIntAttributeFlags( CDmElement* pElement, KeyValues *pKeyValue, const char *pKeyName, int nFlags, int *pDefault )
  175. {
  176. if ( !AddIntAttribute( pElement, pKeyValue, pKeyName, pDefault ) )
  177. return false;
  178. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  179. pAttribute->AddFlag( nFlags );
  180. return true;
  181. }
  182. bool CImportKeyValueBase::AddFloatAttributeFlags( CDmElement* pElement, KeyValues *pKeyValue, const char *pKeyName, int nFlags, float *pDefault )
  183. {
  184. if ( !AddFloatAttribute( pElement, pKeyValue, pKeyName, pDefault ) )
  185. return false;
  186. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  187. pAttribute->AddFlag( nFlags );
  188. return true;
  189. }
  190. bool CImportKeyValueBase::AddStringAttributeFlags( CDmElement* pElement, KeyValues *pKeyValue, const char *pKeyName, int nFlags, const char *pDefault )
  191. {
  192. if ( !AddStringAttribute( pElement, pKeyValue, pKeyName, pDefault ) )
  193. return false;
  194. CDmAttribute *pAttribute = pElement->GetAttribute( pKeyName );
  195. pAttribute->AddFlag( nFlags );
  196. return true;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Recursively resolves all attributes pointing to elements
  200. //-----------------------------------------------------------------------------
  201. void CImportKeyValueBase::RecursivelyResolveElement( CDmElement* pElement )
  202. {
  203. if ( !pElement )
  204. return;
  205. pElement->Resolve();
  206. CDmAttribute *pAttribute = pElement->FirstAttribute();
  207. while ( pAttribute )
  208. {
  209. switch ( pAttribute->GetType() )
  210. {
  211. case AT_ELEMENT:
  212. {
  213. CDmElement *pElementAt = pAttribute->GetValueElement<CDmElement>();
  214. RecursivelyResolveElement( pElementAt );
  215. }
  216. break;
  217. case AT_ELEMENT_ARRAY:
  218. {
  219. CDmrElementArray<> array( pAttribute );
  220. int nCount = array.Count();
  221. for ( int i = 0; i < nCount; ++i )
  222. {
  223. CDmElement *pElementAt = array[ i ];
  224. RecursivelyResolveElement( pElementAt );
  225. }
  226. }
  227. break;
  228. }
  229. pAttribute = pAttribute->NextAttribute( );
  230. }
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Main entry point for the unserialization
  234. //-----------------------------------------------------------------------------
  235. bool CImportKeyValueBase::Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion,
  236. const char *pSourceFormatName, int nSourceFormatVersion,
  237. DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot )
  238. {
  239. *ppRoot = NULL;
  240. m_pFileName = g_pDataModel->GetFileName( fileid );
  241. KeyValues *kv = new KeyValues( "dmx file" );
  242. if ( !kv )
  243. return false;
  244. bool bOk = kv->LoadFromBuffer( "dmx file", buf );
  245. if ( bOk )
  246. {
  247. *ppRoot = UnserializeFromKeyValues( kv );
  248. }
  249. kv->deleteThis();
  250. return bOk;
  251. }