daeTinyXMLPlugin.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright 2007 Sony Computer Entertainment Inc.
  3. *
  4. * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
  5. * file except in compliance with the License. You may obtain a copy of the License at:
  6. * http://research.scea.com/scea_shared_source_license.html
  7. *
  8. * Unless required by applicable law or agreed to in writing, software distributed under the License
  9. * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  10. * implied. See the License for the specific language governing permissions and limitations under the
  11. * License.
  12. */
  13. // The user can choose whether or not to include TinyXML support in the DOM. Supporting TinyXML will
  14. // require linking against it. By default TinyXML support isn't included.
  15. #if defined(DOM_INCLUDE_TINYXML)
  16. #if defined(DOM_DYNAMIC) && defined(_MSC_VER)
  17. #pragma comment(lib, "tinyxml.lib")
  18. #endif
  19. #if defined(_MSC_VER)
  20. #pragma warning(disable: 4100) // warning C4100: 'element' : unreferenced formal parameter
  21. #endif
  22. #include <string>
  23. #include <tinyxml2.h>
  24. #include <dae.h>
  25. #include <dom.h>
  26. #include <dae/daeMetaElement.h>
  27. #include <dae/daeErrorHandler.h>
  28. #include <dae/daeMetaElementAttribute.h>
  29. #include <dae/daeTinyXMLPlugin.h>
  30. #include <dae/daeDocument.h>
  31. using namespace std;
  32. namespace {
  33. daeInt getCurrentLineNumber(tinyxml2::XMLElement* element) {
  34. return -1;
  35. }
  36. }
  37. daeTinyXMLPlugin::daeTinyXMLPlugin()
  38. {
  39. m_doc = NULL;
  40. supportedProtocols.push_back("*");
  41. }
  42. daeTinyXMLPlugin::~daeTinyXMLPlugin()
  43. {
  44. }
  45. daeInt daeTinyXMLPlugin::setOption( daeString option, daeString value )
  46. {
  47. return DAE_ERR_INVALID_CALL;
  48. }
  49. daeString daeTinyXMLPlugin::getOption( daeString option )
  50. {
  51. return NULL;
  52. }
  53. daeElementRef daeTinyXMLPlugin::readFromFile(const daeURI& uri) {
  54. string file = cdom::uriToNativePath(uri.str());
  55. if (file.empty())
  56. return NULL;
  57. tinyxml2::XMLDocument doc;
  58. doc.LoadFile(file.c_str());
  59. if (!doc.RootElement()) {
  60. daeErrorHandler::get()->handleError((std::string("Failed to open ") + uri.str() +
  61. " in daeTinyXMLPlugin::readFromFile\n").c_str());
  62. return NULL;
  63. }
  64. return readElement(doc.RootElement(), NULL);
  65. }
  66. daeElementRef daeTinyXMLPlugin::readFromMemory(daeString buffer, const daeURI& baseUri) {
  67. tinyxml2::XMLDocument doc;
  68. doc.Parse(buffer);
  69. if (!doc.RootElement()) {
  70. daeErrorHandler::get()->handleError("Failed to open XML document from memory buffer in "
  71. "daeTinyXMLPlugin::readFromMemory\n");
  72. return NULL;
  73. }
  74. return readElement(doc.RootElement(), NULL);
  75. }
  76. daeElementRef daeTinyXMLPlugin::readElement(tinyxml2::XMLElement* tinyXmlElement, daeElement* parentElement) {
  77. std::vector<attrPair> attributes;
  78. for (const tinyxml2::XMLAttribute* attrib = tinyXmlElement->FirstAttribute(); attrib != NULL; attrib = attrib->Next())
  79. attributes.push_back(attrPair(attrib->Name(), attrib->Value()));
  80. daeElementRef element = beginReadElement(parentElement, tinyXmlElement->Value(),
  81. attributes, getCurrentLineNumber(tinyXmlElement));
  82. if (!element) {
  83. // We couldn't create the element. beginReadElement already printed an error message.
  84. return NULL;
  85. }
  86. if (tinyXmlElement->GetText() != NULL)
  87. readElementText(element, tinyXmlElement->GetText(), getCurrentLineNumber(tinyXmlElement));
  88. // Recurse children
  89. for (tinyxml2::XMLElement* child = tinyXmlElement->FirstChildElement(); child != NULL; child = child->NextSiblingElement())
  90. element->placeElement(readElement(child, element));
  91. return element;
  92. }
  93. daeInt daeTinyXMLPlugin::write(const daeURI& name, daeDocument *document, daeBool replace)
  94. {
  95. // Make sure database and document are both set
  96. if (!database)
  97. return DAE_ERR_INVALID_CALL;
  98. if(!document)
  99. return DAE_ERR_COLLECTION_DOES_NOT_EXIST;
  100. string fileName = cdom::uriToNativePath(name.str());
  101. if (fileName.empty())
  102. {
  103. daeErrorHandler::get()->handleError( "can't get path in write\n" );
  104. return DAE_ERR_BACKEND_IO;
  105. }
  106. // If replace=false, don't replace existing files
  107. if(!replace)
  108. {
  109. // Using "stat" would be better, but it's not available on all platforms
  110. FILE *tempfd = fopen(fileName.c_str(), "r");
  111. if(tempfd != NULL)
  112. {
  113. // File exists, return error
  114. fclose(tempfd);
  115. return DAE_ERR_BACKEND_FILE_EXISTS;
  116. }
  117. fclose(tempfd);
  118. }
  119. m_doc = new tinyxml2::XMLDocument();
  120. if (m_doc)
  121. {
  122. tinyxml2::XMLDeclaration* decl = m_doc->NewDeclaration("xml version=\"1.0\"");
  123. m_doc->LinkEndChild( decl );
  124. writeElement(document->getDomRoot());
  125. m_doc->SaveFile(fileName.c_str());
  126. delete m_doc;
  127. m_doc = NULL;
  128. }
  129. return DAE_OK;
  130. }
  131. void daeTinyXMLPlugin::writeElement( daeElement* element )
  132. {
  133. daeMetaElement* _meta = element->getMeta();
  134. if (!_meta->getIsTransparent() )
  135. {
  136. tinyxml2::XMLElement* tiElm = m_doc->NewElement( element->getElementName() );
  137. if (m_elements.empty() == true) {
  138. m_doc->LinkEndChild(tiElm);
  139. } else {
  140. tinyxml2::XMLElement* first = m_elements.front();
  141. first->LinkEndChild(tiElm);
  142. }
  143. m_elements.push_front(tiElm);
  144. daeMetaAttributeRefArray& attrs = _meta->getMetaAttributes();
  145. int acnt = (int)attrs.getCount();
  146. for(int i=0;i<acnt;i++)
  147. {
  148. writeAttribute( attrs[i], element );
  149. }
  150. }
  151. writeValue(element);
  152. daeElementRefArray children;
  153. element->getChildren( children );
  154. for ( size_t x = 0; x < children.getCount(); x++ )
  155. {
  156. writeElement( children.get(x) );
  157. }
  158. if (!_meta->getIsTransparent() )
  159. {
  160. m_elements.pop_front();
  161. }
  162. }
  163. void daeTinyXMLPlugin::writeValue( daeElement* element )
  164. {
  165. if (daeMetaAttribute* attr = element->getMeta()->getValueAttribute()) {
  166. std::ostringstream buffer;
  167. attr->memoryToString(element, buffer);
  168. std::string s = buffer.str();
  169. if (!s.empty())
  170. m_elements.front()->LinkEndChild( m_doc->NewText(buffer.str().c_str()) );
  171. }
  172. }
  173. void daeTinyXMLPlugin::writeAttribute( daeMetaAttribute* attr, daeElement* element )
  174. {
  175. //don't write if !required and is set && is default
  176. if ( !attr->getIsRequired() ) {
  177. //not required
  178. if ( !element->isAttributeSet( attr->getName() ) ) {
  179. //early out if !value && !required && !set
  180. return;
  181. }
  182. //is set
  183. //check for default suppression
  184. if (attr->compareToDefault(element) == 0) {
  185. // We match the default value, so exit early
  186. return;
  187. }
  188. }
  189. std::ostringstream buffer;
  190. attr->memoryToString(element, buffer);
  191. m_elements.front()->SetAttribute(attr->getName(), buffer.str().c_str());
  192. }
  193. #endif // DOM_INCLUDE_TINYXML