1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
9 #include <anna/core/mt/Guard.hpp>
10 #include <anna/core/util/defines.hpp>
12 #include <anna/xml/Compiler.hpp>
13 #include <anna/xml/Node.hpp>
14 #include <anna/xml/Attribute.hpp>
15 #include <anna/xml/Text.hpp>
16 #include <anna/xml/internal/sccs.hpp>
17 #include <anna/xml/Document.hpp>
18 #include <anna/xml/Namespace.hpp>
25 using namespace anna::xml;
27 Compiler::Compiler() {
31 const char* Compiler::apply(const Node* node, const int flags)
33 Guard guard(this, "xml::Compiler::apply");
36 if(flags & Mode::Compact)
37 apply(node, a_result, flags);
39 apply(node, a_result, 0, flags);
41 return a_result.c_str();
44 const char* Compiler::apply(const Document& document, const Node* node, const int flags)
46 Guard guard(this, "xml::Compiler::apply");
48 const char* version = document.getVersion();
52 a_result += " version='";
57 const char* encoding = document.getEncoding();
59 if(encoding != NULL) {
60 a_result += " encoding='";
67 if(flags & Mode::Compact)
68 apply(node, a_result, flags);
70 apply(node, a_result, 0, flags);
72 return a_result.c_str();
75 //------------------------------------------------------------------------------------
76 // (1) Si tiene nodos hijos => ignora el texto, porque no se como representar
78 //------------------------------------------------------------------------------------
79 void Compiler::apply(const Node* node, Result& result, const int level, const int flags)
81 const bool hasText(node->getText() != NULL);
82 Node::const_child_iterator ii = node->child_begin();
83 Node::const_child_iterator maxii = node->child_end();
84 const bool hasChildren(ii != maxii);
86 if(hasChildren == false && hasText == false)
87 open(node, result, level, true, true, flags);
88 else if(hasChildren == false && hasText == true) {
89 open(node, result, level, false, false, flags);
90 result += node->getText()->getValue();
91 close(node, result, 0, flags);
92 } else if(hasChildren == true) { // (1)
93 open(node, result, level, false, true, flags);
95 for(; ii != maxii; ii ++)
96 apply(Node::node(ii), result, level + 1, flags);
98 close(node, result, level, flags);
102 //------------------------------------------------------------------------------------
103 // (1) Si tiene nodos hijos => ignora el texto, porque no se como representar
105 //------------------------------------------------------------------------------------
106 void Compiler::apply(const Node* node, Result& result, const int flags)
108 static const int level = 0;
109 const bool hasText(node->getText() != NULL);
110 Node::const_child_iterator ii = node->child_begin();
111 Node::const_child_iterator maxii = node->child_end();
112 const bool hasChildren(ii != maxii);
114 if(hasChildren == false && hasText == false)
115 open(node, result, level, true, false, flags);
116 else if(hasChildren == false && hasText == true) {
117 open(node, result, level, false, false, flags);
118 result += node->getText()->getValue();
120 writeFullName(node, result, flags);
122 } else if(hasChildren == true) { // (1)
123 open(node, result, level, false, false, flags);
125 for(; ii != maxii; ii ++)
126 apply(Node::node(ii), result, flags);
129 writeFullName(node, result, flags);
135 void Compiler::open(const Node* node, Result& result, const int level, const bool quickClose, const bool newline, const int flags)
137 const Attribute* attribute;
140 for(int i = 0; i < level; i ++)
141 result += std::string(ANNA_XML_INDENTATION_SPACES, ' ');
144 writeFullName(node, result, flags);
146 // Si es el nodo ROOT => Tenemos que representar la deficiĆ³n de los namespaces
147 if(node->getParent() == NULL && node->namespace_size() != 0) {
148 for(xml::Node::const_namespace_iterator ii = node->namespace_begin(), maxii = node->namespace_end(); ii != maxii; ii ++) {
149 ns = xml::Node::xnamespace(ii);
151 result += ns->getName();
153 result += ns->getReference();
158 // Sort node attributes (this is a compiler used for on-demand representation, this sorting is not permanent in the object which uses it):
159 if(flags & Mode::Sort) {
160 Node *nc_node = const_cast<Node*>(node);
161 std::sort(nc_node->attribute_begin(), nc_node->attribute_end(),
162 [](Attribute *a, Attribute *b) { return (std::strcmp(a->getName(), b->getName()) < 0); }); // sort alphabetically by attribute name
165 for(Node::const_attribute_iterator ii = node->attribute_begin(), maxii = node->attribute_end(); ii != maxii; ii ++) {
166 attribute = Node::attribute(ii);
168 writeFullName(attribute, result, flags);
169 const std::string& value = attribute->getValue();
171 if(value.length() > 0) {
173 result += attribute->getValue();
175 } else if(flags & Mode::ShowNullAttribute)
179 if(quickClose == true)
189 void Compiler::writeFullName(const Node* node, Result& result, const int flags)
193 if((flags & Mode::NoNamespaces) == 0 && (ns = node->getNamespace()) != NULL) {
194 result += ns->getName();
198 result += node->getName();
202 void Compiler::writeFullName(const Attribute* attr, Result& result, const int flags)
206 if((flags & Mode::NoNamespaces) == 0 && (ns = attr->getNamespace()) != NULL) {
207 result += ns->getName();
211 result += attr->getName();
215 void Compiler::close(const Node* node, Result& result, const int level, const int flags)
217 for(int i = 0; i < level; i ++)
218 result += std::string(ANNA_XML_INDENTATION_SPACES, ' ');
221 writeFullName(node, result, flags);
225 void Compiler::Result::extend(const int nbytes)
227 if((a_size + nbytes) >= a_maxSize) {
228 int newSize = ((a_size + nbytes) << 1) - ((a_size + nbytes) >> 1);
229 char* newBuffer = new char [newSize];
231 if(newBuffer == NULL)
232 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
235 anna_memcpy(newBuffer, a_buffer, a_size);
238 a_buffer = newBuffer;