1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #include <anna/core/mt/Guard.hpp>
39 #include <anna/xml/Compiler.hpp>
40 #include <anna/xml/Node.hpp>
41 #include <anna/xml/Attribute.hpp>
42 #include <anna/xml/Text.hpp>
43 #include <anna/xml/internal/sccs.hpp>
44 #include <anna/xml/Document.hpp>
45 #include <anna/xml/Namespace.hpp>
48 using namespace anna::xml;
50 Compiler::Compiler() {
54 const char* Compiler::apply(const Node* node, const int flags)
55 throw(RuntimeException) {
56 Guard guard(this, "xml::Compiler::apply");
59 if(flags & Mode::Compact)
60 apply(node, a_result, flags);
62 apply(node, a_result, 0, flags);
64 return a_result.c_str();
67 const char* Compiler::apply(const Document& document, const Node* node, const int flags)
68 throw(RuntimeException) {
69 Guard guard(this, "xml::Compiler::apply");
71 const char* version = document.getVersion();
75 a_result += " version='";
80 const char* encoding = document.getEncoding();
82 if(encoding != NULL) {
83 a_result += " encoding='";
90 if(flags & Mode::Compact)
91 apply(node, a_result, flags);
93 apply(node, a_result, 0, flags);
95 return a_result.c_str();
98 //------------------------------------------------------------------------------------
99 // (1) Si tiene nodos hijos => ignora el texto, porque no se como representar
101 //------------------------------------------------------------------------------------
102 void Compiler::apply(const Node* node, Result& result, const int level, const int flags)
103 throw(RuntimeException) {
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, true, flags);
111 else if(hasChildren == false && hasText == true) {
112 open(node, result, level, false, false, flags);
113 result += node->getText()->getValue();
114 close(node, result, 0, flags);
115 } else if(hasChildren == true) { // (1)
116 open(node, result, level, false, true, flags);
118 for(; ii != maxii; ii ++)
119 apply(Node::node(ii), result, level + 1, flags);
121 close(node, result, level, flags);
125 //------------------------------------------------------------------------------------
126 // (1) Si tiene nodos hijos => ignora el texto, porque no se como representar
128 //------------------------------------------------------------------------------------
129 void Compiler::apply(const Node* node, Result& result, const int flags)
130 throw(RuntimeException) {
131 static const int level = 0;
132 const bool hasText(node->getText() != NULL);
133 Node::const_child_iterator ii = node->child_begin();
134 Node::const_child_iterator maxii = node->child_end();
135 const bool hasChildren(ii != maxii);
137 if(hasChildren == false && hasText == false)
138 open(node, result, level, true, false, flags);
139 else if(hasChildren == false && hasText == true) {
140 open(node, result, level, false, false, flags);
141 result += node->getText()->getValue();
143 writeFullName(node, result, flags);
145 } else if(hasChildren == true) { // (1)
146 open(node, result, level, false, false, flags);
148 for(; ii != maxii; ii ++)
149 apply(Node::node(ii), result, flags);
152 writeFullName(node, result, flags);
158 void Compiler::open(const Node* node, Result& result, const int level, const bool quickClose, const bool newline, const int flags)
159 throw(RuntimeException) {
160 const Attribute* attribute;
163 for(int i = 0; i < level; i ++)
164 result += ANNA_XML_COMPILER_TAB;
167 writeFullName(node, result, flags);
169 // Si es el nodo ROOT => Tenemos que representar la deficiĆ³n de los namespaces
170 if(node->getParent() == NULL && node->namespace_size() != 0) {
171 for(xml::Node::const_namespace_iterator ii = node->namespace_begin(), maxii = node->namespace_end(); ii != maxii; ii ++) {
172 ns = xml::Node::xnamespace(ii);
174 result += ns->getName();
176 result += ns->getReference();
181 for(Node::const_attribute_iterator ii = node->attribute_begin(), maxii = node->attribute_end(); ii != maxii; ii ++) {
182 attribute = Node::attribute(ii);
184 writeFullName(attribute, result, flags);
185 const std::string& value = attribute->getValue();
187 if(value.length() > 0) {
189 result += attribute->getValue();
191 } else if(flags & Mode::ShowNullAttribute)
195 if(quickClose == true)
205 void Compiler::writeFullName(const Node* node, Result& result, const int flags)
206 throw(RuntimeException) {
209 if((flags & Mode::NoNamespaces) == 0 && (ns = node->getNamespace()) != NULL) {
210 result += ns->getName();
214 result += node->getName();
218 void Compiler::writeFullName(const Attribute* attr, Result& result, const int flags)
219 throw(RuntimeException) {
222 if((flags & Mode::NoNamespaces) == 0 && (ns = attr->getNamespace()) != NULL) {
223 result += ns->getName();
227 result += attr->getName();
231 void Compiler::close(const Node* node, Result& result, const int level, const int flags)
232 throw(RuntimeException) {
233 for(int i = 0; i < level; i ++)
234 result += ANNA_XML_COMPILER_TAB;
237 writeFullName(node, result, flags);
241 void Compiler::Result::extend(const int nbytes)
242 throw(RuntimeException) {
243 if((a_size + nbytes) >= a_maxSize) {
244 int newSize = ((a_size + nbytes) << 1) - ((a_size + nbytes) >> 1);
245 char* newBuffer = new char [newSize];
247 if(newBuffer == NULL)
248 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
251 anna_memcpy(newBuffer, a_buffer, a_size);
254 a_buffer = newBuffer;