0024284: Some trivial warnings produced by ICC 14
[occt.git] / src / LDOM / LDOM_XmlWriter.cxx
1 // Created on: 2001-06-28
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21
22 #include <LDOM_XmlWriter.hxx>
23 #include <LDOM_Document.hxx>
24 #include <LDOM_CharReference.hxx>
25
26 #define chOpenAngle     '<'
27 #define chCloseAngle    '>'
28 #define chOpenSquare    '['
29 #define chCloseSquare   ']'
30 #define chQuestion      '?'
31 #define chForwardSlash  '/'
32 #define chLF            '\n'
33 #define chNull          '\0'
34 #define chEqual         '='
35 #define chDash          '-'
36 #define chBang          '!'
37 #define chSpace         ' '
38 #define chDoubleQuote   '\"'
39 #define chZero          '0'
40 #define chOne           '1'
41 #define chTwo           '2'
42 #define chThree         '3'
43 #define chFour          '4'
44 #define chFive          '5'
45 #define chSix           '6'
46 #define chSeven         '7'
47 #define chEight         '8'
48 #define chNine          '9'
49 #define chLatin_a       'a'
50 #define chLatin_b       'b'
51 #define chLatin_c       'c'
52 #define chLatin_d       'd'
53 #define chLatin_e       'e'
54 #define chLatin_f       'f'
55 #define chLatin_g       'g'
56 #define chLatin_h       'h'
57 #define chLatin_i       'i'
58 #define chLatin_j       'j'
59 #define chLatin_k       'k'
60 #define chLatin_l       'l'
61 #define chLatin_m       'm'
62 #define chLatin_n       'n'
63 #define chLatin_o       'o'
64 #define chLatin_p       'p'
65 #define chLatin_q       'q'
66 #define chLatin_r       'r'
67 #define chLatin_s       's'
68 #define chLatin_t       't'
69 #define chLatin_u       'u'
70 #define chLatin_v       'v'
71 #define chLatin_w       'w'
72 #define chLatin_x       'x'
73 #define chLatin_y       'y'
74 #define chLatin_z       'z'
75 #define chLatin_A       'A'
76 #define chLatin_B       'B'
77 #define chLatin_C       'C'
78 #define chLatin_D       'D'
79 #define chLatin_E       'E'
80 #define chLatin_F       'F'
81 #define chLatin_G       'G'
82 #define chLatin_H       'H'
83 #define chLatin_I       'I'
84 #define chLatin_J       'J'
85 #define chLatin_K       'K'
86 #define chLatin_L       'L'
87 #define chLatin_M       'M'
88 #define chLatin_N       'N'
89 #define chLatin_O       'O'
90 #define chLatin_P       'P'
91 #define chLatin_Q       'Q'
92 #define chLatin_R       'R'
93 #define chLatin_S       'S'
94 #define chLatin_T       'T'
95 #define chLatin_U       'U'
96 #define chLatin_V       'V'
97 #define chLatin_W       'W'
98 #define chLatin_X       'X'
99 #define chLatin_Y       'Y'
100 #define chLatin_Z       'Z'
101
102 static const LXMLCh  gEndElement[] = { chOpenAngle, chForwardSlash, chNull };
103 static const LXMLCh  gEndElement1[]= { chForwardSlash, chNull };
104 //static const LXMLCh  gEndPI[] = { chQuestion, chCloseAngle, chNull };
105 //static const LXMLCh  gStartPI[] = { chOpenAngle, chQuestion, chNull };
106 static const LXMLCh  gXMLDecl1[] =
107 {       chOpenAngle, chQuestion, chLatin_x, chLatin_m, chLatin_l
108     ,   chSpace, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_i
109     ,   chLatin_o, chLatin_n, chEqual, chDoubleQuote, chNull
110 };
111 static const LXMLCh  gXMLDecl2[] =
112 {       chDoubleQuote, chSpace, chLatin_e, chLatin_n, chLatin_c
113     ,   chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chEqual
114     ,   chDoubleQuote, chNull
115 };
116 /*
117 static const LXMLCh  gXMLDecl3[] =
118 {       chDoubleQuote, chSpace, chLatin_s, chLatin_t, chLatin_a
119     ,   chLatin_n, chLatin_d, chLatin_a, chLatin_l, chLatin_o
120     ,   chLatin_n, chLatin_e, chEqual, chDoubleQuote, chNull
121 };
122 */
123 static const LXMLCh  gXMLDecl4[] =
124 {       chDoubleQuote, chQuestion, chCloseAngle
125     ,   chLF, chNull
126 };
127 static const LXMLCh  gStartCDATA[] =
128 {       chOpenAngle, chBang, chOpenSquare, chLatin_C, chLatin_D,
129         chLatin_A, chLatin_T, chLatin_A, chOpenSquare, chNull
130 };
131 static const LXMLCh  gEndCDATA[] =
132 {    chCloseSquare, chCloseSquare, chCloseAngle, chNull };
133 static const LXMLCh  gStartComment[] =
134 {    chOpenAngle, chBang, chDash, chDash, chNull };
135 static const LXMLCh  gEndComment[] =
136 {    chDash, chDash, chCloseAngle, chNull };
137 /*
138 static const LXMLCh  gStartDoctype[] =
139 {   chOpenAngle, chBang, chLatin_D, chLatin_O, chLatin_C, chLatin_T,
140     chLatin_Y, chLatin_P, chLatin_E, chSpace, chNull
141 };
142 static const LXMLCh  gPublic[] =
143 {   chLatin_P, chLatin_U, chLatin_B, chLatin_L, chLatin_I,
144     chLatin_C, chSpace, chDoubleQuote, chNull
145 };
146 static const LXMLCh  gSystem[] =
147 {   chLatin_S, chLatin_Y, chLatin_S, chLatin_T, chLatin_E,
148     chLatin_M, chSpace, chDoubleQuote, chNull
149 };
150 static const LXMLCh  gStartEntity[] =
151 {   chOpenAngle, chBang, chLatin_E, chLatin_N, chLatin_T, chLatin_I,
152     chLatin_T, chLatin_Y, chSpace, chNull
153 };
154 static const LXMLCh  gNotation[] =
155 {   chLatin_N, chLatin_D, chLatin_A, chLatin_T, chLatin_A,
156     chSpace, chDoubleQuote, chNull
157 };
158 */
159
160 static LXMLCh * getEncodingName (const LXMLCh * theEncodingName)
161 {
162   const LXMLCh * anEncoding = theEncodingName;
163   if (theEncodingName == NULL)
164   {
165 //  anEncoding =           // US-ASCII
166 //  { chLatin_U, chLatin_S, chDash, chLatin_A, chLatin_S, chLatin_C, chLatin_I,
167 //      chLatin_I, chNull };
168     static const LXMLCh anUTFEncoding [] =   // UTF-8
169       { chLatin_U, chLatin_T, chLatin_F, chDash, chEight, chNull };
170     anEncoding = anUTFEncoding;
171   }
172   Standard_Integer aLen = 0;
173   while (anEncoding[aLen++] != chNull);
174   LXMLCh * aResult = new LXMLCh [aLen];
175   memcpy (aResult, anEncoding, aLen * sizeof (LXMLCh));
176   return aResult;
177 }
178
179 //=======================================================================
180 //function : LH3D_LXMLWriter()
181 //purpose  : Constructor
182 //=======================================================================
183 LDOM_XmlWriter::LDOM_XmlWriter (FILE            * aFile,
184                                 const LXMLCh    * theEncoding)
185      : myFile         (aFile),
186        myEncodingName (::getEncodingName (theEncoding)),
187        myIndent       (0),
188        myCurIndent    (0),
189        myABuffer      (NULL),
190        myABufferLen   (0)
191 {}
192
193 //=======================================================================
194 //function : ~LDOM_XmlWriter
195 //purpose  : Destructor
196 //=======================================================================
197
198 LDOM_XmlWriter::~LDOM_XmlWriter ()
199 {
200   delete [] myEncodingName;
201   if (myABuffer != NULL) delete [] myABuffer;
202 }
203
204 //=======================================================================
205 //function : operator <<
206 //purpose  : 
207 //=======================================================================
208
209 LDOM_XmlWriter& LDOM_XmlWriter::operator <<     (const LDOM_Document& aDoc)
210 {
211   const char * anXMLversion = "1.0";
212   * this << gXMLDecl1 << anXMLversion
213     << gXMLDecl2 << myEncodingName << gXMLDecl4;
214
215   return (* this << aDoc.getDocumentElement());
216 }
217
218 //=======================================================================
219 //function : operator <<
220 //purpose  : Stream out an LDOMString
221 //=======================================================================
222
223 inline LDOM_XmlWriter& LDOM_XmlWriter::operator <<
224                                         (const LDOMBasicString& aString)
225 {
226   switch (aString.Type()) {
227   case LDOMBasicString::LDOM_Integer:
228     {
229       Standard_Integer aValue;
230       aString.GetInteger (aValue);
231       fprintf (myFile, "%d", aValue);
232       break;
233     }
234   case LDOMBasicString::LDOM_AsciiHashed:       // attr names and element tags
235   case LDOMBasicString::LDOM_AsciiDocClear:
236     {
237       const char * str = aString.GetString();
238       if (str) {
239         const Standard_Size aLen = strlen (str);
240         if (aLen > 0) fwrite (str, aLen, 1, myFile);
241       }
242     }
243     break;
244   case LDOMBasicString::LDOM_AsciiFree:
245   case LDOMBasicString::LDOM_AsciiDoc:
246     {
247       const char * str = aString.GetString();
248       if (str) {
249         Standard_Integer aLen;
250         char * encStr = LDOM_CharReference::Encode(str, aLen, Standard_False);
251         if (aLen > 0) fwrite (encStr, aLen, 1, myFile);
252         if (encStr != str) delete [] encStr;
253       }
254     }
255   default: ;
256   }
257   return * this;
258 }
259
260 //=======================================================================
261 //function : operator<<()
262 //purpose  : Stream out a char *.
263 //=======================================================================
264 inline LDOM_XmlWriter& LDOM_XmlWriter::operator << (const LXMLCh * aString)
265 {
266   Standard_Size aLength = strlen (aString);
267   if (aLength > 0) fwrite ((void *) aString, aLength, 1, myFile);
268   return * this;
269 }
270
271 //=======================================================================
272 //function : operator<<()
273 //purpose  : Stream out a character.
274 //=======================================================================
275 inline LDOM_XmlWriter& LDOM_XmlWriter::operator << (const LXMLCh aChar)
276 {
277   fputc (aChar, myFile);
278   return * this;
279 }
280
281 //=======================================================================
282 //function : WriteAttribute()
283 //purpose  : Stream out an XML attribute.
284 //=======================================================================
285 void LDOM_XmlWriter::WriteAttribute (const LDOM_Node& theAtt)
286 {
287   int        aLength;
288   const char * aName = theAtt.getNodeName().GetString();
289   const LDOMString aValueStr = theAtt.getNodeValue();
290
291   //    Integer attribute value
292   if (aValueStr.Type() == LDOMBasicString::LDOM_Integer) {
293     Standard_Integer anIntValue;
294     aValueStr.GetInteger (anIntValue);
295     aLength = (Standard_Integer) (20 + strlen (aName));
296     if (aLength > myABufferLen) {
297       if (myABuffer != NULL) delete [] myABuffer;
298       myABuffer    = new char [aLength+1];
299       myABufferLen = aLength;
300     }
301     sprintf (myABuffer, "%c%s%c%c%d%c", chSpace, aName,
302              chEqual, chDoubleQuote, anIntValue, chDoubleQuote);
303     aLength = (Standard_Integer) strlen (myABuffer);
304
305   //    String attribute value
306   } else {
307     const char  * aValue = aValueStr.GetString();
308     char        * encStr;
309     if (aValueStr.Type() == LDOMBasicString::LDOM_AsciiDocClear) {
310       encStr  = (char *) aValue;
311       aLength = (Standard_Integer) (4 + strlen (aValue) + strlen (aName));
312     } else {
313       encStr = LDOM_CharReference::Encode (aValue, aLength, Standard_True);
314       aLength += (Standard_Integer) (4 + strlen (aName));
315     }
316     if (aLength > myABufferLen) {
317       if (myABuffer != NULL) delete [] myABuffer;
318       myABuffer    = new char [aLength+1];
319       myABufferLen = aLength;
320     }
321     sprintf (myABuffer, "%c%s%c%c%s%c", chSpace, aName,
322              chEqual, chDoubleQuote, encStr, chDoubleQuote);
323     if (encStr != aValue) delete [] encStr;
324   }
325   fwrite ((void *) myABuffer, aLength, 1, myFile);
326 }
327
328 //=======================================================================
329 //function : operator<<()
330 //purpose  : Stream out a DOM node, and, recursively, all of its children.
331 //           This function is the heart of writing a DOM tree out as XML source.
332 //           Give it a document node and it will do the whole thing.
333 //=======================================================================
334 LDOM_XmlWriter& LDOM_XmlWriter::operator<<     (const LDOM_Node& theNodeToWrite)
335 {
336   // Get the name and value out for convenience
337   LDOMString   aNodeName  = theNodeToWrite.getNodeName();
338   LDOMString   aNodeValue = theNodeToWrite.getNodeValue();
339 //  unsigned long dwLent = aNodeValue.length();
340
341   switch (theNodeToWrite.getNodeType()) 
342   {
343   case LDOM_Node::TEXT_NODE : 
344     * this << aNodeValue;
345     break;
346   case LDOM_Node::ELEMENT_NODE : 
347     {
348       const int aMaxNSpaces    = 40;
349       static LXMLCh aSpaces [] = {
350         chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
351         chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
352         chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
353         chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
354         chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace, chSpace,
355         chOpenAngle, chNull };
356       const LXMLCh * anIndentString = &aSpaces [aMaxNSpaces -  myCurIndent];
357       if (anIndentString < &aSpaces[0]) anIndentString = &aSpaces[0];
358
359       // Output the element start tag.
360       * this << anIndentString << aNodeName.GetString();
361
362         // Output any attributes of this element
363       const LDOM_Element& anElemToWrite = (const LDOM_Element&) theNodeToWrite;
364       LDOM_NodeList aListAtt = anElemToWrite.GetAttributesList ();
365       Standard_Integer aListInd = aListAtt.getLength();
366       while (aListInd--) {
367         LDOM_Node aChild = aListAtt.item (aListInd);
368         WriteAttribute (aChild);
369       }
370
371       //  Test for the presence of children
372       LDOM_Node aChild = theNodeToWrite.getFirstChild();
373       if (aChild != 0) 
374       {
375         // There are children. Close start-tag, and output children.
376         * this << chCloseAngle;
377         if (aChild.getNodeType() == LDOM_Node::ELEMENT_NODE && myIndent > 0)
378           * this << chLF;
379         Standard_Boolean isChildElem = Standard_False;
380         while( aChild != 0) 
381         {
382           isChildElem = (aChild.getNodeType() == LDOM_Node::ELEMENT_NODE);
383           if (isChildElem)  myCurIndent += myIndent;
384           *this << aChild;
385           if (isChildElem)  myCurIndent -= myIndent;
386           do aChild = aChild.getNextSibling();
387           while (aChild.getNodeType() == LDOM_Node::ATTRIBUTE_NODE);
388         }
389         // Done with children.  Output the end tag.
390         //
391         if (isChildElem)
392           * this << anIndentString
393             << gEndElement1 << aNodeName.GetString() << chCloseAngle;
394         else
395           * this << gEndElement << aNodeName.GetString() << chCloseAngle;
396       }
397       else
398       {
399         //  There were no children. Output the short form close of
400         //  the element start tag, making it an empty-element tag.
401         * this << chForwardSlash << chCloseAngle;
402       }
403       if (myIndent > 0)
404         * this << chLF;
405       break;
406     }
407     case LDOM_Node::CDATA_SECTION_NODE: 
408     {
409       * this << gStartCDATA << aNodeValue << gEndCDATA;
410       break;
411     }
412     case LDOM_Node::COMMENT_NODE: 
413     {
414       * this << gStartComment << aNodeValue << gEndComment;
415       break;
416     }
417   default:
418 #ifndef WNT
419       cerr << "Unrecognized node type = "
420         << (long)theNodeToWrite.getNodeType() << endl
421 #endif
422   ; }
423   return *this;
424 }