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>
11 #include <anna/xml/Compiler.hpp>
12 #include <anna/xml/Node.hpp>
13 #include <anna/xml/Attribute.hpp>
14 #include <anna/xml/Text.hpp>
15 #include <anna/xml/internal/sccs.hpp>
16 #include <anna/xml/Document.hpp>
17 #include <anna/xml/Namespace.hpp>
20 using namespace anna::xml;
22 Compiler::Compiler() {
26 const char* Compiler::apply(const Node* node, const int flags)
27 throw(RuntimeException) {
28 Guard guard(this, "xml::Compiler::apply");
31 if(flags & Mode::Compact)
32 apply(node, a_result, flags);
34 apply(node, a_result, 0, flags);
36 return a_result.c_str();
39 const char* Compiler::apply(const Document& document, const Node* node, const int flags)
40 throw(RuntimeException) {
41 Guard guard(this, "xml::Compiler::apply");
43 const char* version = document.getVersion();
47 a_result += " version='";
52 const char* encoding = document.getEncoding();
54 if(encoding != NULL) {
55 a_result += " encoding='";
62 if(flags & Mode::Compact)
63 apply(node, a_result, flags);
65 apply(node, a_result, 0, flags);
67 return a_result.c_str();
70 //------------------------------------------------------------------------------------
71 // (1) Si tiene nodos hijos => ignora el texto, porque no se como representar
73 //------------------------------------------------------------------------------------
74 void Compiler::apply(const Node* node, Result& result, const int level, const int flags)
75 throw(RuntimeException) {
76 const bool hasText(node->getText() != NULL);
77 Node::const_child_iterator ii = node->child_begin();
78 Node::const_child_iterator maxii = node->child_end();
79 const bool hasChildren(ii != maxii);
81 if(hasChildren == false && hasText == false)
82 open(node, result, level, true, true, flags);
83 else if(hasChildren == false && hasText == true) {
84 open(node, result, level, false, false, flags);
85 result += node->getText()->getValue();
86 close(node, result, 0, flags);
87 } else if(hasChildren == true) { // (1)
88 open(node, result, level, false, true, flags);
90 for(; ii != maxii; ii ++)
91 apply(Node::node(ii), result, level + 1, flags);
93 close(node, result, level, flags);
97 //------------------------------------------------------------------------------------
98 // (1) Si tiene nodos hijos => ignora el texto, porque no se como representar
100 //------------------------------------------------------------------------------------
101 void Compiler::apply(const Node* node, Result& result, const int flags)
102 throw(RuntimeException) {
103 static const int level = 0;
104 const bool hasText(node->getText() != NULL);
105 Node::const_child_iterator ii = node->child_begin();
106 Node::const_child_iterator maxii = node->child_end();
107 const bool hasChildren(ii != maxii);
109 if(hasChildren == false && hasText == false)
110 open(node, result, level, true, false, flags);
111 else if(hasChildren == false && hasText == true) {
112 open(node, result, level, false, false, flags);
113 result += node->getText()->getValue();
115 writeFullName(node, result, flags);
117 } else if(hasChildren == true) { // (1)
118 open(node, result, level, false, false, flags);
120 for(; ii != maxii; ii ++)
121 apply(Node::node(ii), result, flags);
124 writeFullName(node, result, flags);
130 void Compiler::open(const Node* node, Result& result, const int level, const bool quickClose, const bool newline, const int flags)
131 throw(RuntimeException) {
132 const Attribute* attribute;
135 for(int i = 0; i < level; i ++)
136 result += ANNA_XML_COMPILER_TAB;
139 writeFullName(node, result, flags);
141 // Si es el nodo ROOT => Tenemos que representar la deficiĆ³n de los namespaces
142 if(node->getParent() == NULL && node->namespace_size() != 0) {
143 for(xml::Node::const_namespace_iterator ii = node->namespace_begin(), maxii = node->namespace_end(); ii != maxii; ii ++) {
144 ns = xml::Node::xnamespace(ii);
146 result += ns->getName();
148 result += ns->getReference();
153 for(Node::const_attribute_iterator ii = node->attribute_begin(), maxii = node->attribute_end(); ii != maxii; ii ++) {
154 attribute = Node::attribute(ii);
156 writeFullName(attribute, result, flags);
157 const std::string& value = attribute->getValue();
159 if(value.length() > 0) {
161 result += attribute->getValue();
163 } else if(flags & Mode::ShowNullAttribute)
167 if(quickClose == true)
177 void Compiler::writeFullName(const Node* node, Result& result, const int flags)
178 throw(RuntimeException) {
181 if((flags & Mode::NoNamespaces) == 0 && (ns = node->getNamespace()) != NULL) {
182 result += ns->getName();
186 result += node->getName();
190 void Compiler::writeFullName(const Attribute* attr, Result& result, const int flags)
191 throw(RuntimeException) {
194 if((flags & Mode::NoNamespaces) == 0 && (ns = attr->getNamespace()) != NULL) {
195 result += ns->getName();
199 result += attr->getName();
203 void Compiler::close(const Node* node, Result& result, const int level, const int flags)
204 throw(RuntimeException) {
205 for(int i = 0; i < level; i ++)
206 result += ANNA_XML_COMPILER_TAB;
209 writeFullName(node, result, flags);
213 void Compiler::Result::extend(const int nbytes)
214 throw(RuntimeException) {
215 if((a_size + nbytes) >= a_maxSize) {
216 int newSize = ((a_size + nbytes) << 1) - ((a_size + nbytes) >> 1);
217 char* newBuffer = new char [newSize];
219 if(newBuffer == NULL)
220 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
223 anna_memcpy(newBuffer, a_buffer, a_size);
226 a_buffer = newBuffer;