1 martin 1.4 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.5 //
|
3 martin 1.4 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.5 //
|
10 martin 1.4 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.5 //
|
17 martin 1.4 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.5 //
|
20 martin 1.4 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.5 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.4 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.5 //
|
28 martin 1.4 //////////////////////////////////////////////////////////////////////////
|
29 kumpf 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <cstdlib>
33 #include <cstdio>
34
35 #include <Pegasus/Common/Config.h>
36 #include "XmlGenerator.h"
37 #include "Constants.h"
38 #include "StrLit.h"
39 #include "CommonUTF.h"
40 #include "StringConversion.h"
41 #include "LanguageParser.h"
42 #include "AutoPtr.h"
43
44 PEGASUS_NAMESPACE_BEGIN
45
46 ////////////////////////////////////////////////////////////////////////////////
47 //
48 // SpecialChar and table.
49 //
50 kumpf 1.1 ////////////////////////////////////////////////////////////////////////////////
51
52 // Note: we cannot use StrLit here since it has a constructor (forbids
53 // structure initialization).
54
55 struct SpecialChar
56 {
57 const char* str;
58 Uint32 size;
59 };
60
61 // Defines encodings of special characters. Just use a 7-bit ASCII character
62 // as an index into this array to retrieve its string encoding and encoding
63 // length in bytes.
64 static const SpecialChar _specialChars[] =
65 {
66 {STRLIT_ARGS("�")},
67 {STRLIT_ARGS("")},
68 {STRLIT_ARGS("")},
69 {STRLIT_ARGS("")},
70 {STRLIT_ARGS("")},
71 kumpf 1.1 {STRLIT_ARGS("")},
72 {STRLIT_ARGS("")},
73 {STRLIT_ARGS("")},
74 {STRLIT_ARGS("")},
75 {STRLIT_ARGS("	")},
76 {STRLIT_ARGS(" ")},
77 {STRLIT_ARGS("")},
78 {STRLIT_ARGS("")},
79 {STRLIT_ARGS(" ")},
80 {STRLIT_ARGS("")},
81 {STRLIT_ARGS("")},
82 {STRLIT_ARGS("")},
83 {STRLIT_ARGS("")},
84 {STRLIT_ARGS("")},
85 {STRLIT_ARGS("")},
86 {STRLIT_ARGS("")},
87 {STRLIT_ARGS("")},
88 {STRLIT_ARGS("")},
89 {STRLIT_ARGS("")},
90 {STRLIT_ARGS("")},
91 {STRLIT_ARGS("")},
92 kumpf 1.1 {STRLIT_ARGS("")},
93 {STRLIT_ARGS("")},
94 {STRLIT_ARGS("")},
95 {STRLIT_ARGS("")},
96 {STRLIT_ARGS("")},
97 {STRLIT_ARGS("")},
98 {STRLIT_ARGS(" ")},
99 {STRLIT_ARGS("!")},
100 {STRLIT_ARGS(""")},
101 {STRLIT_ARGS("#")},
102 {STRLIT_ARGS("$")},
103 {STRLIT_ARGS("%")},
104 {STRLIT_ARGS("&")},
105 {STRLIT_ARGS("'")},
106 {STRLIT_ARGS("(")},
107 {STRLIT_ARGS(")")},
108 {STRLIT_ARGS("*")},
109 {STRLIT_ARGS("+")},
110 {STRLIT_ARGS(",")},
111 {STRLIT_ARGS("-")},
112 {STRLIT_ARGS(".")},
113 kumpf 1.1 {STRLIT_ARGS("/")},
114 {STRLIT_ARGS("0")},
115 {STRLIT_ARGS("1")},
116 {STRLIT_ARGS("2")},
117 {STRLIT_ARGS("3")},
118 {STRLIT_ARGS("4")},
119 {STRLIT_ARGS("5")},
120 {STRLIT_ARGS("6")},
121 {STRLIT_ARGS("7")},
122 {STRLIT_ARGS("8")},
123 {STRLIT_ARGS("9")},
124 {STRLIT_ARGS(":")},
125 {STRLIT_ARGS(";")},
126 {STRLIT_ARGS("<")},
127 {STRLIT_ARGS("=")},
128 {STRLIT_ARGS(">")},
129 {STRLIT_ARGS("?")},
130 {STRLIT_ARGS("@")},
131 {STRLIT_ARGS("A")},
132 {STRLIT_ARGS("B")},
133 {STRLIT_ARGS("C")},
134 kumpf 1.1 {STRLIT_ARGS("D")},
135 {STRLIT_ARGS("E")},
136 {STRLIT_ARGS("F")},
137 {STRLIT_ARGS("G")},
138 {STRLIT_ARGS("H")},
139 {STRLIT_ARGS("I")},
140 {STRLIT_ARGS("J")},
141 {STRLIT_ARGS("K")},
142 {STRLIT_ARGS("L")},
143 {STRLIT_ARGS("M")},
144 {STRLIT_ARGS("N")},
145 {STRLIT_ARGS("O")},
146 {STRLIT_ARGS("P")},
147 {STRLIT_ARGS("Q")},
148 {STRLIT_ARGS("R")},
149 {STRLIT_ARGS("S")},
150 {STRLIT_ARGS("T")},
151 {STRLIT_ARGS("U")},
152 {STRLIT_ARGS("V")},
153 {STRLIT_ARGS("W")},
154 {STRLIT_ARGS("X")},
155 kumpf 1.1 {STRLIT_ARGS("Y")},
156 {STRLIT_ARGS("Z")},
157 {STRLIT_ARGS("[")},
158 {STRLIT_ARGS("\\")},
159 {STRLIT_ARGS("]")},
160 {STRLIT_ARGS("^")},
161 {STRLIT_ARGS("_")},
162 {STRLIT_ARGS("`")},
163 {STRLIT_ARGS("a")},
164 {STRLIT_ARGS("b")},
165 {STRLIT_ARGS("c")},
166 {STRLIT_ARGS("d")},
167 {STRLIT_ARGS("e")},
168 {STRLIT_ARGS("f")},
169 {STRLIT_ARGS("g")},
170 {STRLIT_ARGS("h")},
171 {STRLIT_ARGS("i")},
172 {STRLIT_ARGS("j")},
173 {STRLIT_ARGS("k")},
174 {STRLIT_ARGS("l")},
175 {STRLIT_ARGS("m")},
176 kumpf 1.1 {STRLIT_ARGS("n")},
177 {STRLIT_ARGS("o")},
178 {STRLIT_ARGS("p")},
179 {STRLIT_ARGS("q")},
180 {STRLIT_ARGS("r")},
181 {STRLIT_ARGS("s")},
182 {STRLIT_ARGS("t")},
183 {STRLIT_ARGS("u")},
184 {STRLIT_ARGS("v")},
185 {STRLIT_ARGS("w")},
186 {STRLIT_ARGS("x")},
187 {STRLIT_ARGS("y")},
188 {STRLIT_ARGS("z")},
189 {STRLIT_ARGS("{")},
190 {STRLIT_ARGS("|")},
191 {STRLIT_ARGS("}")},
192 {STRLIT_ARGS("~")},
193 {STRLIT_ARGS("")},
194 };
195
196 // If _isSpecialChar7[ch] is true, then ch is a special character, which must
|
197 marek 1.8 // have a special encoding in XML.
198 // Remaining 128 values are automatically initialised to 0 by compiler.
199 static const int _isSpecialChar7[256] =
|
200 kumpf 1.1 {
201 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,
202 0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,
203 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
204 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
205 };
206
|
207 thilo.boehm 1.7 // If _isSpecialChar7[ch] is true, then ch is a special character, which must
|
208 marek 1.8 // have a special encoding in XML.
|
209 thilo.boehm 1.7 static const int _isNormalChar7[] =
210 {
211 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,
212 1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,
213 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
214 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
|
215 marek 1.8 // remaining 128 values are used on multi-byte UTF-8 and should not be escaped
216 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
217 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
218 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
219 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
220 thilo.boehm 1.7 };
221
222
|
223 kumpf 1.1 ////////////////////////////////////////////////////////////////////////////////
224
225 Buffer& operator<<(Buffer& out, const Char16& x)
226 {
227 XmlGenerator::append(out, x);
228 return out;
229 }
230
231 Buffer& operator<<(Buffer& out, const String& x)
232 {
233 XmlGenerator::append(out, x);
234 return out;
235 }
236
237 Buffer& operator<<(Buffer& out, const Buffer& x)
238 {
239 out.append(x.getData(), x.size());
240 return out;
241 }
242
243 Buffer& operator<<(Buffer& out, Uint32 x)
244 kumpf 1.1 {
245 XmlGenerator::append(out, x);
246 return out;
247 }
248
249 Buffer& operator<<(Buffer& out, const CIMName& name)
250 {
251 XmlGenerator::append(out, name.getString ());
252 return out;
253 }
254
255 Buffer& operator<<(Buffer& out, const AcceptLanguageList& al)
256 {
257 XmlGenerator::append(out, LanguageParser::buildAcceptLanguageHeader(al));
258 return out;
259 }
260
261 Buffer& operator<<(Buffer& out, const ContentLanguageList& cl)
262 {
263 XmlGenerator::append(out, LanguageParser::buildContentLanguageHeader(cl));
264 return out;
265 kumpf 1.1 }
266
|
267 thilo.boehm 1.7 const StrLit XmlGenerator::_XmlWriterTypeStrings[17] =
268 {
269 STRLIT("TYPE=\"boolean\""), STRLIT("TYPE=\"uint8\""),
270 STRLIT("TYPE=\"sint8\""), STRLIT("TYPE=\"uint16\""),
271 STRLIT("TYPE=\"sint16\""), STRLIT("TYPE=\"uint32\""),
272 STRLIT("TYPE=\"sint32\""), STRLIT("TYPE=\"uint64\""),
273 STRLIT("TYPE=\"sint64\""), STRLIT("TYPE=\"real32\""),
274 STRLIT("TYPE=\"real64\""), STRLIT("TYPE=\"char16\""),
275 STRLIT("TYPE=\"string\""), STRLIT("TYPE=\"datetime\""),
276 STRLIT("TYPE=\"reference\""), STRLIT("TYPE=\"object\""),
277 STRLIT("TYPE=\"instance\"")
278 };
279
280 const StrLit XmlGenerator::_XmlWriterKeyTypeStrings[17] =
281 {
282 STRLIT("boolean"), STRLIT("numeric"),
283 STRLIT("numeric"), STRLIT("numeric"),
284 STRLIT("numeric"), STRLIT("numeric"),
285 STRLIT("numeric"), STRLIT("numeric"),
286 STRLIT("numeric"), STRLIT("numeric"),
287 STRLIT("numeric"), STRLIT("string"),
288 thilo.boehm 1.7 STRLIT("string"), STRLIT("string"),
289 /* The following are not valid values for a keytype, but left in here
290 so in case something is going wrong it can be easily concluded from the
291 generated XML */
292 STRLIT("reference"), STRLIT("object"),
293 STRLIT("instance")
294 };
295
|
296 kumpf 1.1 void XmlGenerator::_appendChar(Buffer& out, const Char16& c)
297 {
298 // We need to convert the Char16 to UTF8 then append the UTF8
299 // character into the array.
300 // NOTE: The UTF8 character could be several bytes long.
301 // WARNING: This function will put in replacement character for
302 // all characters that have surogate pairs.
303 char str[6];
304 memset(str,0x00,sizeof(str));
305 Uint8* charIN = (Uint8 *)&c;
306
307 const Uint16 *strsrc = (Uint16 *)charIN;
308 Uint16 *endsrc = (Uint16 *)&charIN[1];
309
310 Uint8 *strtgt = (Uint8 *)str;
311 Uint8 *endtgt = (Uint8 *)&str[5];
312
313 UTF16toUTF8(
314 &strsrc,
315 endsrc,
316 &strtgt,
317 kumpf 1.1 endtgt);
318
319 out.append(str, UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1);
320 }
321
322 void XmlGenerator::_appendSpecialChar7(Buffer& out, char c)
323 {
324 if (_isSpecialChar7[int(c)])
325 out.append(_specialChars[int(c)].str, _specialChars[int(c)].size);
326 else
327 out.append(c);
328 }
329
330 void XmlGenerator::_appendSpecialChar(Buffer& out, const Char16& c)
331 {
332 if (c < 128)
333 _appendSpecialChar7(out, char(c));
334 else
335 _appendChar(out, c);
336 }
337
|
338 ashok.pathak 1.11
339
|
340 dl.meetei 1.12 //Based on the platforms CHAR_MIN == -127 or CHAR_MIN == 0
341 //The above value is used to decide if the platform assumes
342 //char as signed char or unsigned char required to stop build
343 //btreaks for PPC under linux
|
344 dl.meetei 1.13 static inline Boolean isSpecialChar(const char &c)
|
345 ashok.pathak 1.11 {
|
346 dl.meetei 1.12 #if CHAR_MIN < 0
|
347 ashok.pathak 1.11 return (((c < 0x20) && (c >= 0)) || (c == 0x7f));
|
348 dl.meetei 1.12 #else
349 return ((c < 0x20) || (c == 0x7f));
350 #endif
351 }
|
352 ashok.pathak 1.11
|
353 kumpf 1.1 void XmlGenerator::_appendSpecialChar(PEGASUS_STD(ostream)& os, char c)
354 {
|
355 dl.meetei 1.12 if(isSpecialChar(c))
|
356 kumpf 1.1 {
357 char scratchBuffer[22];
358 Uint32 outputLength;
|
359 kumpf 1.6 const char * output = Uint8ToString(scratchBuffer,
360 static_cast<Uint8>(c),
|
361 kumpf 1.1 outputLength);
362 os << "&#" << output << ";";
363 }
364 else
365 {
366 switch (c)
367 {
368 case '&':
369 os << "&";
370 break;
371
372 case '<':
373 os << "<";
374 break;
375
376 case '>':
377 os << ">";
378 break;
379
380 case '"':
381 os << """;
382 kumpf 1.1 break;
383
384 case '\'':
385 os << "'";
386 break;
387
388 default:
389 os << c;
390 }
391 }
392 }
393
394 void XmlGenerator::_appendSurrogatePair(Buffer& out, Uint16 high, Uint16 low)
395 {
396 char str[6];
397 Uint8 charIN[5];
398 memset(str,0x00,sizeof(str));
399 memcpy(&charIN,&high,2);
400 memcpy(&charIN[2],&low,2);
401 const Uint16 *strsrc = (Uint16 *)charIN;
402 Uint16 *endsrc = (Uint16 *)&charIN[3];
403 kumpf 1.1
404 Uint8 *strtgt = (Uint8 *)str;
405 Uint8 *endtgt = (Uint8 *)&str[5];
406
407 UTF16toUTF8(
408 &strsrc,
409 endsrc,
410 &strtgt,
411 endtgt);
412
413 Uint32 number1 = UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1;
414 out.append(str,number1);
415 }
416
417 void XmlGenerator::_appendSpecial(PEGASUS_STD(ostream)& os, const char* str)
418 {
419 while (*str)
420 _appendSpecialChar(os, *str++);
421 }
422
423 void XmlGenerator::append(Buffer& out, const Char16& x)
424 kumpf 1.1 {
425 _appendChar(out, x);
426 }
427
428 void XmlGenerator::append(Buffer& out, Boolean x)
429 {
430 if (x)
431 out.append(STRLIT_ARGS("TRUE"));
432 else
433 out.append(STRLIT_ARGS("FALSE"));
434 }
435
436 void XmlGenerator::append(Buffer& out, Uint32 x)
437 {
438 Uint32 outputLength=0;
439 char buffer[22];
440 const char * output = Uint32ToString(buffer, x, outputLength);
441 out.append(output, outputLength);
442 }
443
444 void XmlGenerator::append(Buffer& out, Sint32 x)
445 kumpf 1.1 {
446 Uint32 outputLength=0;
447 char buffer[22];
448 const char * output = Sint32ToString(buffer, x, outputLength);
449 out.append(output, outputLength);
450 }
451
452 void XmlGenerator::append(Buffer& out, Uint64 x)
453 {
454 Uint32 outputLength=0;
455 char buffer[22];
456 const char * output = Uint64ToString(buffer, x, outputLength);
457 out.append(output, outputLength);
458 }
459
460 void XmlGenerator::append(Buffer& out, Sint64 x)
461 {
462 Uint32 outputLength=0;
463 char buffer[22];
464 const char * output = Sint64ToString(buffer, x, outputLength);
465 out.append(output, outputLength);
466 kumpf 1.1 }
467
468 void XmlGenerator::append(Buffer& out, Real32 x)
469 {
|
470 thilo.boehm 1.7 Uint32 outputLength=0;
|
471 kumpf 1.1 char buffer[128];
|
472 thilo.boehm 1.7 const char * output = Real32ToString(buffer, x, outputLength);
473 out.append(output, outputLength);
|
474 kumpf 1.1 }
475
476 void XmlGenerator::append(Buffer& out, Real64 x)
477 {
|
478 thilo.boehm 1.7 Uint32 outputLength=0;
|
479 kumpf 1.1 char buffer[128];
|
480 thilo.boehm 1.7 const char * output = Real64ToString(buffer, x, outputLength);
481 out.append(output, outputLength);
|
482 kumpf 1.1 }
483
484 void XmlGenerator::append(Buffer& out, const char* str)
485 {
486 size_t n = strlen(str);
487 out.append(str, n);
488 }
489
490 void XmlGenerator::append(Buffer& out, const String& str)
491 {
492 const Uint16* p = (const Uint16*)str.getChar16Data();
493 size_t n = str.size();
494
495 // Handle leading ASCII 7 characers in these next two loops (use unrolling).
496
497 while (n >= 8 && ((p[0]|p[1]|p[2]|p[3]|p[4]|p[5]|p[6]|p[7]) & 0xFF80) == 0)
498 {
499 out.append(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
500 p += 8;
501 n -= 8;
502 }
503 kumpf 1.1
504 while (n >= 4 && ((p[0]|p[1]|p[2]|p[3]) & 0xFF80) == 0)
505 {
506 out.append(p[0], p[1], p[2], p[3]);
507 p += 4;
508 n -= 4;
509 }
510
511 while (n--)
512 {
513 Uint16 c = *p++;
514
515 // Special processing for UTF8 case:
516
517 if (c < 128)
518 {
519 out.append(c);
520 continue;
521 }
522
523 // Handle UTF8 case (if reached).
524 kumpf 1.1
525 if (((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
526 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE)))
527 {
528 Char16 highSurrogate = p[-1];
529 Char16 lowSurrogate = p[0];
530 p++;
531 n--;
532
533 _appendSurrogatePair(
534 out, Uint16(highSurrogate),Uint16(lowSurrogate));
535 }
536 else
537 {
538 _appendChar(out, c);
539 }
540 }
541 }
542
543 void XmlGenerator::appendSpecial(Buffer& out, const Char16& x)
544 {
545 kumpf 1.1 _appendSpecialChar(out, x);
546 }
547
548 void XmlGenerator::appendSpecial(Buffer& out, char x)
549 {
550 _appendSpecialChar7(out, x);
551 }
552
553 void XmlGenerator::appendSpecial(Buffer& out, const char* str)
554 {
555 while (*str)
556 _appendSpecialChar7(out, *str++);
557 }
558
559 void XmlGenerator::appendSpecial(Buffer& out, const String& str)
560 {
561 const Uint16* p = (const Uint16*)str.getChar16Data();
562 // prevCharIsSpace is true when the last character written to the Buffer
563 // is a space character (not a character reference).
564 Boolean prevCharIsSpace = false;
565
566 kumpf 1.1 // If the first character is a space, use a character reference to avoid
567 // space compression.
568 if (*p == ' ')
569 {
570 out.append(STRLIT_ARGS(" "));
571 p++;
572 }
573
574 Uint16 c;
575 while ((c = *p++) != 0)
576 {
577 if (c < 128)
578 {
579 if (_isSpecialChar7[c])
580 {
581 // Write the character reference for the special character
582 out.append(
583 _specialChars[int(c)].str, _specialChars[int(c)].size);
584 prevCharIsSpace = false;
585 }
586 else if (prevCharIsSpace && (c == ' '))
587 kumpf 1.1 {
588 // Write the character reference for the space character, to
589 // avoid compression
590 out.append(STRLIT_ARGS(" "));
591 prevCharIsSpace = false;
592 }
593 else
594 {
595 out.append(c);
596 prevCharIsSpace = (c == ' ');
597 }
598 }
599 else
600 {
601 // Handle UTF8 case
602
603 if ((((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
604 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE))) &&
605 *p)
606 {
607 _appendSurrogatePair(out, c, *p++);
608 kumpf 1.1 }
609 else
610 {
611 _appendChar(out, c);
612 }
613
614 prevCharIsSpace = false;
615 }
616 }
617
618 // If the last character is a space, use a character reference to avoid
619 // space compression.
620 if (prevCharIsSpace)
621 {
622 out.remove(out.size() - 1);
623 out.append(STRLIT_ARGS(" "));
624 }
625 }
626
|
627 thilo.boehm 1.7 // str has to be UTF-8 encoded
628 // that means the characters used cannot be larger than 7bit ASCII in value
629 // range
630 void XmlGenerator::appendSpecial(Buffer& out, const char* str, Uint32 size)
631 {
632 // employ loop unrolling and a less checking optimized Buffer access
633
634 // Buffer cannot grow more than 6*size characters (ie. 4*size+2*size)
635 Uint32 newMaxSize = (size << 2) + (size << 1);
636 if (out.size() + newMaxSize >= out.capacity())
637 {
638 out.reserveCapacity(out.capacity() + newMaxSize);
639 }
640
641 // Before using a loop unrolled algorithm to pick out the special chars
642 // we are going to assume there is no special char as this is the case most
643 // of the time anyway
644 Uint32 sizeStart=size;
645 const Uint8* p= (const Uint8*) str;
646
647 while (size >= 4 &&
648 thilo.boehm 1.7 (_isNormalChar7[p[0]] &
649 _isNormalChar7[p[1]] &
650 _isNormalChar7[p[2]] &
651 _isNormalChar7[p[3]]))
652 {
653 size -= 4;
654 p += 4;
655 }
656 out.append_unchecked(str,sizeStart-size);
657 str=(const char*)p;
658
659 while (size>=8)
660 {
|
661 venkat.puvvada 1.9 register Uint8 c;
|
662 thilo.boehm 1.7 c = str[0];
663 if (_isSpecialChar7[c])
664 {
665 out.append_unchecked(
666 _specialChars[c].str,
667 _specialChars[c].size);
668 }
669 else
670 {
671 out.append_unchecked(c);
672 }
673 c = str[1];
674 if (_isSpecialChar7[c])
675 {
676 out.append_unchecked(
677 _specialChars[c].str,
678 _specialChars[c].size);
679 }
680 else
681 {
682 out.append_unchecked(c);
683 thilo.boehm 1.7 }
684 c = str[2];
685 if (_isSpecialChar7[c])
686 {
687 out.append_unchecked(
688 _specialChars[c].str,
689 _specialChars[c].size);
690 }
691 else
692 {
693 out.append_unchecked(c);
694 }
695 c = str[3];
696 if (_isSpecialChar7[c])
697 {
698 out.append_unchecked(
699 _specialChars[c].str,
700 _specialChars[c].size);
701 }
702 else
703 {
704 thilo.boehm 1.7 out.append_unchecked(c);
705 }
706 c = str[4];
707 if (_isSpecialChar7[c])
708 {
709 out.append_unchecked(
710 _specialChars[c].str,
711 _specialChars[c].size);
712 }
713 else
714 {
715 out.append_unchecked(c);
716 }
717 c = str[5];
718 if (_isSpecialChar7[c])
719 {
720 out.append_unchecked(
721 _specialChars[c].str,
722 _specialChars[c].size);
723 }
724 else
725 thilo.boehm 1.7 {
726 out.append_unchecked(c);
727 }
728 c = str[6];
729 if (_isSpecialChar7[c])
730 {
731 out.append_unchecked(
732 _specialChars[c].str,
733 _specialChars[c].size);
734 }
735 else
736 {
737 out.append_unchecked(c);
738 }
739 c = str[7];
740 if (_isSpecialChar7[c])
741 {
742 out.append_unchecked(
743 _specialChars[c].str,
744 _specialChars[c].size);
745 }
746 thilo.boehm 1.7 else
747 {
748 out.append_unchecked(c);
749 }
750 str+=8;
751 size-=8;
752 }
753
754 while (size>=4)
755 {
|
756 venkat.puvvada 1.9 register Uint8 c;
|
757 thilo.boehm 1.7 c = str[0];
758 if (_isSpecialChar7[c])
759 {
760 out.append_unchecked(
761 _specialChars[c].str,
762 _specialChars[c].size);
763 }
764 else
765 {
766 out.append_unchecked(c);
767 }
768 c = str[1];
769 if (_isSpecialChar7[c])
770 {
771 out.append_unchecked(
772 _specialChars[c].str,
773 _specialChars[c].size);
774 }
775 else
776 {
777 out.append_unchecked(c);
778 thilo.boehm 1.7 }
779 c = str[2];
780 if (_isSpecialChar7[c])
781 {
782 out.append_unchecked(
783 _specialChars[c].str,
784 _specialChars[c].size);
785 }
786 else
787 {
788 out.append_unchecked(c);
789 }
790 c = str[3];
791 if (_isSpecialChar7[c])
792 {
793 out.append_unchecked(
794 _specialChars[c].str,
795 _specialChars[c].size);
796 }
797 else
798 {
799 thilo.boehm 1.7 out.append_unchecked(c);
800 }
801 str+=4;
802 size-=4;
803 }
804
805 while (size--)
806 {
|
807 venkat.puvvada 1.9 register Uint8 c;
|
808 thilo.boehm 1.7 c=*str;
809 if (_isSpecialChar7[c])
810 {
811 out.append_unchecked(
812 _specialChars[c].str,
813 _specialChars[c].size);
814 }
815 else
816 {
817 out.append_unchecked(c);
818 }
819 str++;
820 }
821 }
822
823
|
824 kumpf 1.1 // See http://www.ietf.org/rfc/rfc2396.txt section 2
825 // Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ','
826 // Excluded characters:
827 // Control characters = 0x00-0x1f, 0x7f
828 // Space character = 0x20
829 // Delimiters = '<' '>' '#' '%' '"'
830 // Unwise = '{' '}' '|' '\\' '^' '[' ']' '`'
831 //
832
833 static const char _is_uri[128] =
834 {
835 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
836 1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
837 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
838 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,
839 };
840
841 // Perform the necessary URI encoding of characters in HTTP header values.
842 // This is required by the HTTP/1.1 specification and the CIM/HTTP
843 // Specification (section 3.3.2).
844 void XmlGenerator::_encodeURIChar(String& outString, Sint8 char8)
845 kumpf 1.1 {
846 Uint8 c = (Uint8)char8;
847 if (c > 127 || _is_uri[int(c)])
848 {
849 char hexencoding[4];
850 int n = sprintf(hexencoding, "%%%X%X", c/16, c%16);
851 outString.append(hexencoding, n);
852 }
853 else
854 {
855 outString.append((Uint16)c);
856 }
857 }
858
859 String XmlGenerator::encodeURICharacters(const String& uriString)
860 {
861 String encodedString;
862
863 // See the "CIM Operations over HTTP" spec, section 3.3.2 and
864 // 3.3.3, for the treatment of non US-ASCII (UTF-8) chars
865
866 kumpf 1.1 // First, convert to UTF-8 (include handling of surrogate pairs)
867 Buffer utf8;
868 for (Uint32 i = 0; i < uriString.size(); i++)
869 {
870 Uint16 c = uriString[i];
871
872 if (((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
873 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE)))
874 {
875 Char16 highSurrogate = uriString[i];
876 Char16 lowSurrogate = uriString[++i];
877
878 _appendSurrogatePair(
879 utf8, Uint16(highSurrogate),Uint16(lowSurrogate));
880 }
881 else
882 {
883 _appendChar(utf8, uriString[i]);
884 }
885 }
886
887 kumpf 1.1 // Second, escape the non HTTP-safe chars
888 for (Uint32 i=0; i<utf8.size(); i++)
889 {
890 _encodeURIChar(encodedString, utf8[i]);
891 }
892
893 return encodedString;
894 }
895
896 //------------------------------------------------------------------------------
897 //
898 // _printAttributes()
899 //
900 //------------------------------------------------------------------------------
901
902 void XmlGenerator::_printAttributes(
903 PEGASUS_STD(ostream)& os,
904 const XmlAttribute* attributes,
905 Uint32 attributeCount)
906 {
907 for (Uint32 i = 0; i < attributeCount; i++)
908 kumpf 1.1 {
909 os << attributes[i].name << "=";
910
911 os << '"';
912 _appendSpecial(os, attributes[i].value);
913 os << '"';
914
915 if (i + 1 != attributeCount)
916 os << ' ';
917 }
918 }
919
920 //------------------------------------------------------------------------------
921 //
922 // _indent()
923 //
924 //------------------------------------------------------------------------------
925
926 void XmlGenerator::_indent(
927 PEGASUS_STD(ostream)& os,
928 Uint32 level,
929 kumpf 1.1 Uint32 indentChars)
930 {
931 Uint32 n = level * indentChars;
932
933 for (Uint32 i = 0; i < n; i++)
934 os << ' ';
935 }
936
937 //------------------------------------------------------------------------------
938 //
939 // indentedPrint()
940 //
941 //------------------------------------------------------------------------------
942
943 void XmlGenerator::indentedPrint(
944 PEGASUS_STD(ostream)& os,
945 const char* text,
946 Uint32 indentChars)
947 {
948 AutoArrayPtr<char> tmp(strcpy(new char[strlen(text) + 1], text));
949
950 kumpf 1.1 XmlParser parser(tmp.get());
951 XmlEntry entry;
952 Stack<const char*> stack;
953
954 while (parser.next(entry))
955 {
956 switch (entry.type)
957 {
958 case XmlEntry::XML_DECLARATION:
959 {
960 _indent(os, stack.size(), indentChars);
961
962 os << "<?" << entry.text << " ";
963 _printAttributes(
|
964 kumpf 1.3 os, entry.attributes.getData(), entry.attributes.size());
|
965 kumpf 1.1 os << "?>";
966 break;
967 }
968
969 case XmlEntry::START_TAG:
970 {
971 _indent(os, stack.size(), indentChars);
972
973 os << "<" << entry.text;
974
|
975 kumpf 1.3 if (entry.attributes.size())
|
976 kumpf 1.1 os << ' ';
977
978 _printAttributes(
|
979 kumpf 1.3 os, entry.attributes.getData(), entry.attributes.size());
|
980 kumpf 1.1 os << ">";
981 stack.push(entry.text);
982 break;
983 }
984
985 case XmlEntry::EMPTY_TAG:
986 {
987 _indent(os, stack.size(), indentChars);
988
989 os << "<" << entry.text << " ";
990 _printAttributes(
|
991 kumpf 1.3 os, entry.attributes.getData(), entry.attributes.size());
|
992 kumpf 1.1 os << "/>";
993 break;
994 }
995
996 case XmlEntry::END_TAG:
997 {
998 if (!stack.isEmpty() && strcmp(stack.top(), entry.text) == 0)
999 stack.pop();
1000
1001 _indent(os, stack.size(), indentChars);
1002
1003 os << "</" << entry.text << ">";
1004 break;
1005 }
1006
1007 case XmlEntry::COMMENT:
1008 {
1009 _indent(os, stack.size(), indentChars);
1010 os << "<!--";
1011 _appendSpecial(os, entry.text);
1012 os << "-->";
1013 kumpf 1.1 break;
1014 }
1015
1016 case XmlEntry::CONTENT:
1017 {
1018 _indent(os, stack.size(), indentChars);
1019 _appendSpecial(os, entry.text);
1020 break;
1021 }
1022
1023 case XmlEntry::CDATA:
1024 {
1025 _indent(os, stack.size(), indentChars);
1026 os << "<![CDATA[" << entry.text << "]]>";
1027 break;
1028 }
1029
1030 case XmlEntry::DOCTYPE:
1031 {
1032 _indent(os, stack.size(), indentChars);
1033 os << "<!DOCTYPE...>";
1034 kumpf 1.1 break;
1035 }
1036 }
1037
1038 os << PEGASUS_STD(endl);
1039 }
1040 }
1041
1042 PEGASUS_NAMESPACE_END
|