(file) Return to XmlGenerator.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

   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("&#0;")},
  67                {STRLIT_ARGS("&#1;")},
  68                {STRLIT_ARGS("&#2;")},
  69                {STRLIT_ARGS("&#3;")},
  70                {STRLIT_ARGS("&#4;")},
  71 kumpf  1.1     {STRLIT_ARGS("&#5;")},
  72                {STRLIT_ARGS("&#6;")},
  73                {STRLIT_ARGS("&#7;")},
  74                {STRLIT_ARGS("&#8;")},
  75                {STRLIT_ARGS("&#9;")},
  76                {STRLIT_ARGS("&#10;")},
  77                {STRLIT_ARGS("&#11;")},
  78                {STRLIT_ARGS("&#12;")},
  79                {STRLIT_ARGS("&#13;")},
  80                {STRLIT_ARGS("&#14;")},
  81                {STRLIT_ARGS("&#15;")},
  82                {STRLIT_ARGS("&#16;")},
  83                {STRLIT_ARGS("&#17;")},
  84                {STRLIT_ARGS("&#18;")},
  85                {STRLIT_ARGS("&#19;")},
  86                {STRLIT_ARGS("&#20;")},
  87                {STRLIT_ARGS("&#21;")},
  88                {STRLIT_ARGS("&#22;")},
  89                {STRLIT_ARGS("&#23;")},
  90                {STRLIT_ARGS("&#24;")},
  91                {STRLIT_ARGS("&#25;")},
  92 kumpf  1.1     {STRLIT_ARGS("&#26;")},
  93                {STRLIT_ARGS("&#27;")},
  94                {STRLIT_ARGS("&#28;")},
  95                {STRLIT_ARGS("&#29;")},
  96                {STRLIT_ARGS("&#30;")},
  97                {STRLIT_ARGS("&#31;")},
  98                {STRLIT_ARGS(" ")},
  99                {STRLIT_ARGS("!")},
 100                {STRLIT_ARGS("&quot;")},
 101                {STRLIT_ARGS("#")},
 102                {STRLIT_ARGS("$")},
 103                {STRLIT_ARGS("%")},
 104                {STRLIT_ARGS("&amp;")},
 105                {STRLIT_ARGS("&apos;")},
 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("&lt;")},
 127                {STRLIT_ARGS("=")},
 128                {STRLIT_ARGS("&gt;")},
 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("&#127;")},
 194            };
 195            
 196            // If _isSpecialChar7[ch] is true, then ch is a special character, which must
 197 kumpf  1.1 // have a special encoding in XML. But only use 7-bit ASCII characters to
 198            // index this array.
 199            static const int _isSpecialChar7[] =
 200            {
 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 marek  1.6.4.6 // If _isSpecialChar7[ch] is true, then ch is a special character, which must
 208                // have a special encoding in XML. But only use 7-biat ASCII characters to
 209                // index this array.
 210                static const int _isNormalChar7[] =
 211                {
 212                    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,
 213                    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,
 214                    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,
 215                    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
 216                };
 217                
 218                
 219 kumpf  1.1     ////////////////////////////////////////////////////////////////////////////////
 220                
 221                Buffer& operator<<(Buffer& out, const Char16& x)
 222                {
 223                    XmlGenerator::append(out, x);
 224                    return out;
 225                }
 226                
 227                Buffer& operator<<(Buffer& out, const String& x)
 228                {
 229                    XmlGenerator::append(out, x);
 230                    return out;
 231                }
 232                
 233                Buffer& operator<<(Buffer& out, const Buffer& x)
 234                {
 235                    out.append(x.getData(), x.size());
 236                    return out;
 237                }
 238                
 239                Buffer& operator<<(Buffer& out, Uint32 x)
 240 kumpf  1.1     {
 241                    XmlGenerator::append(out, x);
 242                    return out;
 243                }
 244                
 245                Buffer& operator<<(Buffer& out, const CIMName& name)
 246                {
 247                    XmlGenerator::append(out, name.getString ());
 248                    return out;
 249                }
 250                
 251                Buffer& operator<<(Buffer& out, const AcceptLanguageList& al)
 252                {
 253                    XmlGenerator::append(out, LanguageParser::buildAcceptLanguageHeader(al));
 254                    return out;
 255                }
 256                
 257                Buffer& operator<<(Buffer& out, const ContentLanguageList& cl)
 258                {
 259                    XmlGenerator::append(out, LanguageParser::buildContentLanguageHeader(cl));
 260                    return out;
 261 kumpf  1.1     }
 262                
 263 marek  1.6.4.2 const StrLit XmlGenerator::_XmlWriterTypeStrings[17] =
 264                {
 265                    STRLIT("TYPE=\"boolean\""),   STRLIT("TYPE=\"uint8\""),
 266                    STRLIT("TYPE=\"sint8\""),     STRLIT("TYPE=\"uint16\""),
 267                    STRLIT("TYPE=\"sint16\""),    STRLIT("TYPE=\"uint32\""),
 268                    STRLIT("TYPE=\"sint32\""),    STRLIT("TYPE=\"uint64\""),
 269                    STRLIT("TYPE=\"sint64\""),    STRLIT("TYPE=\"real32\""),
 270                    STRLIT("TYPE=\"real64\""),    STRLIT("TYPE=\"char16\""),
 271                    STRLIT("TYPE=\"string\""),    STRLIT("TYPE=\"datetime\""),
 272                    STRLIT("TYPE=\"reference\""), STRLIT("TYPE=\"object\""),
 273                    STRLIT("TYPE=\"instance\"")
 274                };
 275                
 276 marek  1.6.4.3 const StrLit XmlGenerator::_XmlWriterKeyTypeStrings[17] =
 277                {
 278                    STRLIT("boolean"), STRLIT("numeric"),
 279                    STRLIT("numeric"), STRLIT("numeric"),
 280                    STRLIT("numeric"), STRLIT("numeric"),
 281                    STRLIT("numeric"), STRLIT("numeric"),
 282                    STRLIT("numeric"), STRLIT("numeric"),
 283                    STRLIT("numeric"), STRLIT("string"),
 284                    STRLIT("string"),  STRLIT("string"),
 285                    /* The following are not valid values for a keytype, but left in here
 286                       so in case something is going wrong it can be easily concluded from the
 287                       generated XML */
 288                    STRLIT("reference"), STRLIT("object"),
 289                    STRLIT("instance")
 290                };
 291                
 292 kumpf  1.1     void XmlGenerator::_appendChar(Buffer& out, const Char16& c)
 293                {
 294                    // We need to convert the Char16 to UTF8 then append the UTF8
 295                    // character into the array.
 296                    // NOTE: The UTF8 character could be several bytes long.
 297                    // WARNING: This function will put in replacement character for
 298                    // all characters that have surogate pairs.
 299                    char str[6];
 300                    memset(str,0x00,sizeof(str));
 301                    Uint8* charIN = (Uint8 *)&c;
 302                
 303                    const Uint16 *strsrc = (Uint16 *)charIN;
 304                    Uint16 *endsrc = (Uint16 *)&charIN[1];
 305                
 306                    Uint8 *strtgt = (Uint8 *)str;
 307                    Uint8 *endtgt = (Uint8 *)&str[5];
 308                
 309                    UTF16toUTF8(
 310                        &strsrc,
 311                        endsrc,
 312                        &strtgt,
 313 kumpf  1.1             endtgt);
 314                
 315                    out.append(str, UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1);
 316                }
 317                
 318                void XmlGenerator::_appendSpecialChar7(Buffer& out, char c)
 319                {
 320                    if (_isSpecialChar7[int(c)])
 321                        out.append(_specialChars[int(c)].str, _specialChars[int(c)].size);
 322                    else
 323                        out.append(c);
 324                }
 325                
 326                void XmlGenerator::_appendSpecialChar(Buffer& out, const Char16& c)
 327                {
 328                    if (c < 128)
 329                        _appendSpecialChar7(out, char(c));
 330                    else
 331                        _appendChar(out, c);
 332                }
 333                
 334 kumpf  1.1     void XmlGenerator::_appendSpecialChar(PEGASUS_STD(ostream)& os, char c)
 335                {
 336                    if ( ((c < 0x20) && (c >= 0)) || (c == 0x7f) )
 337                    {
 338                        char scratchBuffer[22];
 339                        Uint32 outputLength;
 340 kumpf  1.6             const char * output = Uint8ToString(scratchBuffer,
 341                                                            static_cast<Uint8>(c),
 342 kumpf  1.1                                                 outputLength);
 343                        os << "&#" << output << ";";
 344                    }
 345                    else
 346                    {
 347                        switch (c)
 348                        {
 349                            case '&':
 350                                os << "&amp;";
 351                                break;
 352                
 353                            case '<':
 354                                os << "&lt;";
 355                                break;
 356                
 357                            case '>':
 358                                os << "&gt;";
 359                                break;
 360                
 361                            case '"':
 362                                os << "&quot;";
 363 kumpf  1.1                     break;
 364                
 365                            case '\'':
 366                                os << "&apos;";
 367                                break;
 368                
 369                            default:
 370                                os << c;
 371                        }
 372                    }
 373                }
 374                
 375                void XmlGenerator::_appendSurrogatePair(Buffer& out, Uint16 high, Uint16 low)
 376                {
 377                    char str[6];
 378                    Uint8 charIN[5];
 379                    memset(str,0x00,sizeof(str));
 380                    memcpy(&charIN,&high,2);
 381                    memcpy(&charIN[2],&low,2);
 382                    const Uint16 *strsrc = (Uint16 *)charIN;
 383                    Uint16 *endsrc = (Uint16 *)&charIN[3];
 384 kumpf  1.1     
 385                    Uint8 *strtgt = (Uint8 *)str;
 386                    Uint8 *endtgt = (Uint8 *)&str[5];
 387                
 388                    UTF16toUTF8(
 389                        &strsrc,
 390                        endsrc,
 391                        &strtgt,
 392                        endtgt);
 393                
 394                    Uint32 number1 = UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1;
 395                    out.append(str,number1);
 396                }
 397                
 398                void XmlGenerator::_appendSpecial(PEGASUS_STD(ostream)& os, const char* str)
 399                {
 400                    while (*str)
 401                        _appendSpecialChar(os, *str++);
 402                }
 403                
 404                void XmlGenerator::append(Buffer& out, const Char16& x)
 405 kumpf  1.1     {
 406                    _appendChar(out, x);
 407                }
 408                
 409                void XmlGenerator::append(Buffer& out, Boolean x)
 410                {
 411                    if (x)
 412                        out.append(STRLIT_ARGS("TRUE"));
 413                    else
 414                        out.append(STRLIT_ARGS("FALSE"));
 415                }
 416                
 417                void XmlGenerator::append(Buffer& out, Uint32 x)
 418                {
 419                    Uint32 outputLength=0;
 420                    char buffer[22];
 421                    const char * output = Uint32ToString(buffer, x, outputLength);
 422                    out.append(output, outputLength);
 423                }
 424                
 425                void XmlGenerator::append(Buffer& out, Sint32 x)
 426 kumpf  1.1     {
 427                    Uint32 outputLength=0;
 428                    char buffer[22];
 429                    const char * output = Sint32ToString(buffer, x, outputLength);
 430                    out.append(output, outputLength);
 431                }
 432                
 433                void XmlGenerator::append(Buffer& out, Uint64 x)
 434                {
 435                    Uint32 outputLength=0;
 436                    char buffer[22];
 437                    const char * output = Uint64ToString(buffer, x, outputLength);
 438                    out.append(output, outputLength);
 439                }
 440                
 441                void XmlGenerator::append(Buffer& out, Sint64 x)
 442                {
 443                    Uint32 outputLength=0;
 444                    char buffer[22];
 445                    const char * output = Sint64ToString(buffer, x, outputLength);
 446                    out.append(output, outputLength);
 447 kumpf  1.1     }
 448                
 449                void XmlGenerator::append(Buffer& out, Real32 x)
 450                {
 451 thilo.boehm 1.6.4.1     Uint32 outputLength=0;
 452 kumpf       1.1         char buffer[128];
 453 thilo.boehm 1.6.4.1     const char * output = Real32ToString(buffer, x, outputLength);
 454                         out.append(output, outputLength);
 455 kumpf       1.1     }
 456                     
 457                     void XmlGenerator::append(Buffer& out, Real64 x)
 458                     {
 459 thilo.boehm 1.6.4.1     Uint32 outputLength=0;
 460 kumpf       1.1         char buffer[128];
 461 thilo.boehm 1.6.4.1     const char * output = Real64ToString(buffer, x, outputLength);
 462                         out.append(output, outputLength);
 463 kumpf       1.1     }
 464                     
 465                     void XmlGenerator::append(Buffer& out, const char* str)
 466                     {
 467                         size_t n = strlen(str);
 468                         out.append(str, n);
 469                     }
 470                     
 471                     void XmlGenerator::append(Buffer& out, const String& str)
 472                     {
 473                         const Uint16* p = (const Uint16*)str.getChar16Data();
 474                         size_t n = str.size();
 475                     
 476                         // Handle leading ASCII 7 characers in these next two loops (use unrolling).
 477                     
 478                         while (n >= 8 && ((p[0]|p[1]|p[2]|p[3]|p[4]|p[5]|p[6]|p[7]) & 0xFF80) == 0)
 479                         {
 480                             out.append(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
 481                             p += 8;
 482                             n -= 8;
 483                         }
 484 kumpf       1.1     
 485                         while (n >= 4 && ((p[0]|p[1]|p[2]|p[3]) & 0xFF80) == 0)
 486                         {
 487                             out.append(p[0], p[1], p[2], p[3]);
 488                             p += 4;
 489                             n -= 4;
 490                         }
 491                     
 492                         while (n--)
 493                         {
 494                             Uint16 c = *p++;
 495                     
 496                             // Special processing for UTF8 case:
 497                     
 498                             if (c < 128)
 499                             {
 500                                 out.append(c);
 501                                 continue;
 502                             }
 503                     
 504                             // Handle UTF8 case (if reached).
 505 kumpf       1.1     
 506                             if (((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
 507                                 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE)))
 508                             {
 509                                 Char16 highSurrogate = p[-1];
 510                                 Char16 lowSurrogate = p[0];
 511                                 p++;
 512                                 n--;
 513                     
 514                                 _appendSurrogatePair(
 515                                     out, Uint16(highSurrogate),Uint16(lowSurrogate));
 516                             }
 517                             else
 518                             {
 519                                 _appendChar(out, c);
 520                             }
 521                         }
 522                     }
 523                     
 524                     void XmlGenerator::appendSpecial(Buffer& out, const Char16& x)
 525                     {
 526 kumpf       1.1         _appendSpecialChar(out, x);
 527                     }
 528                     
 529                     void XmlGenerator::appendSpecial(Buffer& out, char x)
 530                     {
 531                         _appendSpecialChar7(out, x);
 532                     }
 533                     
 534                     void XmlGenerator::appendSpecial(Buffer& out, const char* str)
 535                     {
 536                         while (*str)
 537                             _appendSpecialChar7(out, *str++);
 538                     }
 539                     
 540                     void XmlGenerator::appendSpecial(Buffer& out, const String& str)
 541                     {
 542                         const Uint16* p = (const Uint16*)str.getChar16Data();
 543                         // prevCharIsSpace is true when the last character written to the Buffer
 544                         // is a space character (not a character reference).
 545                         Boolean prevCharIsSpace = false;
 546                     
 547 kumpf       1.1         // If the first character is a space, use a character reference to avoid
 548                         // space compression.
 549                         if (*p == ' ')
 550                         {
 551                             out.append(STRLIT_ARGS("&#32;"));
 552                             p++;
 553                         }
 554                     
 555                         Uint16 c;
 556                         while ((c = *p++) != 0)
 557                         {
 558                             if (c < 128)
 559                             {
 560                                 if (_isSpecialChar7[c])
 561                                 {
 562                                     // Write the character reference for the special character
 563                                     out.append(
 564                                         _specialChars[int(c)].str, _specialChars[int(c)].size);
 565                                     prevCharIsSpace = false;
 566                                 }
 567                                 else if (prevCharIsSpace && (c == ' '))
 568 kumpf       1.1                 {
 569                                     // Write the character reference for the space character, to
 570                                     // avoid compression
 571                                     out.append(STRLIT_ARGS("&#32;"));
 572                                     prevCharIsSpace = false;
 573                                 }
 574                                 else
 575                                 {
 576                                     out.append(c);
 577                                     prevCharIsSpace = (c == ' ');
 578                                 }
 579                             }
 580                             else
 581                             {
 582                                 // Handle UTF8 case
 583                     
 584                                 if ((((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
 585                                      ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE))) &&
 586                                     *p)
 587                                 {
 588                                     _appendSurrogatePair(out, c, *p++);
 589 kumpf       1.1                 }
 590                                 else
 591                                 {
 592                                     _appendChar(out, c);
 593                                 }
 594                     
 595                                 prevCharIsSpace = false;
 596                             }
 597                         }
 598                     
 599                         // If the last character is a space, use a character reference to avoid
 600                         // space compression.
 601                         if (prevCharIsSpace)
 602                         {
 603                             out.remove(out.size() - 1);
 604                             out.append(STRLIT_ARGS("&#32;"));
 605                         }
 606                     }
 607                     
 608 marek       1.6.4.6 // str has to be UTF-8 encoded
 609                     // that means the characters used cannot be larger than 7bit ASCII in value
 610                     // range
 611 marek       1.6.4.2 void XmlGenerator::appendSpecial(Buffer& out, const char* str, Uint32 size)
 612                     {
 613                         // employ loop unrolling and a less checking optimized Buffer access
 614                     
 615                         // Buffer cannot grow more than 6*size characters (ie. 4*size+2*size)
 616 marek       1.6.4.4     Uint32 newMaxSize = (size << 2) + (size << 1);
 617 r.kieninger 1.6.4.5     if (out.size() + newMaxSize >= out.capacity())
 618 marek       1.6.4.4     {
 619                             out.reserveCapacity(out.capacity() + newMaxSize);
 620                         }
 621 marek       1.6.4.2 
 622 marek       1.6.4.6     // Before using a loop unrolled algorithm to pick out the special chars
 623                         // we are going to assume there is no special char as this is the case most
 624                         // of the time anyway
 625                         Uint32 sizeStart=size;
 626                         const Uint8* p= (const Uint8*) str;
 627                     
 628                         while (size >= 4 &&
 629 r.kieninger 1.6.4.7              (_isNormalChar7[p[0]] &
 630                                   _isNormalChar7[p[1]] &
 631                                   _isNormalChar7[p[2]] &
 632 marek       1.6.4.6               _isNormalChar7[p[3]]))
 633                         {
 634                             size -= 4;
 635                             p += 4;
 636                         }
 637                         out.append_unchecked(str,sizeStart-size);
 638                         str=(const char*)p;
 639                     
 640 marek       1.6.4.2     while (size>=8)
 641                         {
 642                             register int c;
 643                             c = str[0];
 644                             if (_isSpecialChar7[c])
 645                             {
 646                                 out.append_unchecked(
 647                                     _specialChars[c].str,
 648                                     _specialChars[c].size);
 649                             }
 650                             else
 651                             {
 652                                 out.append_unchecked(c);
 653                             }
 654                             c = str[1];
 655                             if (_isSpecialChar7[c])
 656                             {
 657                                 out.append_unchecked(
 658                                     _specialChars[c].str,
 659                                     _specialChars[c].size);
 660                             }
 661 marek       1.6.4.2         else
 662                             {
 663                                 out.append_unchecked(c);
 664                             }
 665                             c = str[2];
 666                             if (_isSpecialChar7[c])
 667                             {
 668                                 out.append_unchecked(
 669                                     _specialChars[c].str,
 670                                     _specialChars[c].size);
 671                             }
 672                             else
 673                             {
 674                                 out.append_unchecked(c);
 675                             }
 676                             c = str[3];
 677                             if (_isSpecialChar7[c])
 678                             {
 679                                 out.append_unchecked(
 680                                     _specialChars[c].str,
 681                                     _specialChars[c].size);
 682 marek       1.6.4.2         }
 683                             else
 684                             {
 685                                 out.append_unchecked(c);
 686                             }
 687                             c = str[4];
 688                             if (_isSpecialChar7[c])
 689                             {
 690                                 out.append_unchecked(
 691                                     _specialChars[c].str,
 692                                     _specialChars[c].size);
 693                             }
 694                             else
 695                             {
 696                                 out.append_unchecked(c);
 697                             }
 698                             c = str[5];
 699                             if (_isSpecialChar7[c])
 700                             {
 701                                 out.append_unchecked(
 702                                     _specialChars[c].str,
 703 marek       1.6.4.2                 _specialChars[c].size);
 704                             }
 705                             else
 706                             {
 707                                 out.append_unchecked(c);
 708                             }
 709                             c = str[6];
 710                             if (_isSpecialChar7[c])
 711                             {
 712                                 out.append_unchecked(
 713                                     _specialChars[c].str,
 714                                     _specialChars[c].size);
 715                             }
 716                             else
 717                             {
 718                                 out.append_unchecked(c);
 719                             }
 720                             c = str[7];
 721                             if (_isSpecialChar7[c])
 722                             {
 723                                 out.append_unchecked(
 724 marek       1.6.4.2                 _specialChars[c].str,
 725                                     _specialChars[c].size);
 726                             }
 727                             else
 728                             {
 729                                 out.append_unchecked(c);
 730                             }
 731                             str+=8;
 732                             size-=8;
 733                         }
 734                     
 735                         while (size>=4)
 736                         {
 737                             register int c;
 738                             c = str[0];
 739                             if (_isSpecialChar7[c])
 740                             {
 741                                 out.append_unchecked(
 742                                     _specialChars[c].str,
 743                                     _specialChars[c].size);
 744                             }
 745 marek       1.6.4.2         else
 746                             {
 747                                 out.append_unchecked(c);
 748                             }
 749                             c = str[1];
 750                             if (_isSpecialChar7[c])
 751                             {
 752                                 out.append_unchecked(
 753                                     _specialChars[c].str,
 754                                     _specialChars[c].size);
 755                             }
 756                             else
 757                             {
 758                                 out.append_unchecked(c);
 759                             }
 760                             c = str[2];
 761                             if (_isSpecialChar7[c])
 762                             {
 763                                 out.append_unchecked(
 764                                     _specialChars[c].str,
 765                                     _specialChars[c].size);
 766 marek       1.6.4.2         }
 767                             else
 768                             {
 769                                 out.append_unchecked(c);
 770                             }
 771                             c = str[3];
 772                             if (_isSpecialChar7[c])
 773                             {
 774                                 out.append_unchecked(
 775                                     _specialChars[c].str,
 776                                     _specialChars[c].size);
 777                             }
 778                             else
 779                             {
 780                                 out.append_unchecked(c);
 781                             }
 782                             str+=4;
 783                             size-=4;
 784                         }
 785                     
 786                         while (size--)
 787 marek       1.6.4.2     {
 788                             register int c;
 789                             c=*str;
 790                             if (_isSpecialChar7[c])
 791                             {
 792                                 out.append_unchecked(
 793                                     _specialChars[c].str,
 794                                     _specialChars[c].size);
 795                             }
 796                             else
 797                             {
 798                                 out.append_unchecked(c);
 799                             }
 800                             str++;
 801                         }
 802                     }
 803                     
 804                     
 805 kumpf       1.1     // See http://www.ietf.org/rfc/rfc2396.txt section 2
 806                     // Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ','
 807                     // Excluded characters:
 808                     //   Control characters = 0x00-0x1f, 0x7f
 809                     //   Space character = 0x20
 810                     //   Delimiters = '<' '>' '#' '%' '"'
 811                     //   Unwise = '{' '}' '|' '\\' '^' '[' ']' '`'
 812                     //
 813                     
 814                     static const char _is_uri[128] =
 815                     {
 816                         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,
 817                         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,
 818                         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,
 819                         0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,
 820                     };
 821                     
 822                     // Perform the necessary URI encoding of characters in HTTP header values.
 823                     // This is required by the HTTP/1.1 specification and the CIM/HTTP
 824                     // Specification (section 3.3.2).
 825                     void XmlGenerator::_encodeURIChar(String& outString, Sint8 char8)
 826 kumpf       1.1     {
 827                         Uint8 c = (Uint8)char8;
 828                     
 829                     #ifndef PEGASUS_DO_NOT_IMPLEMENT_URI_ENCODING
 830                         if (c > 127 || _is_uri[int(c)])
 831                         {
 832                             char hexencoding[4];
 833                             int n = sprintf(hexencoding, "%%%X%X", c/16, c%16);
 834                     #ifdef PEGASUS_USE_STRING_EXTENSIONS
 835                             outString.append(hexencoding, n);
 836                     #else /* PEGASUS_USE_STRING_EXTENSIONS */
 837                             outString.append(hexencoding);
 838                     #endif /* PEGASUS_USE_STRING_EXTENSIONS */
 839                         }
 840                         else
 841                     #endif
 842                         {
 843                             outString.append((Uint16)c);
 844                         }
 845                     }
 846                     
 847 kumpf       1.1     String XmlGenerator::encodeURICharacters(const Buffer& uriString)
 848                     {
 849                         String encodedString;
 850                     
 851                         for (Uint32 i=0; i<uriString.size(); i++)
 852                         {
 853                             _encodeURIChar(encodedString, uriString[i]);
 854                         }
 855                     
 856                         return encodedString;
 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                         // First, convert to UTF-8 (include handling of surrogate pairs)
 867                         Buffer utf8;
 868 kumpf       1.1         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                         // Second, escape the non HTTP-safe chars
 888                         for (Uint32 i=0; i<utf8.size(); i++)
 889 kumpf       1.1         {
 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                         {
 909                             os << attributes[i].name << "=";
 910 kumpf       1.1     
 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                         Uint32 indentChars)
 930                     {
 931 kumpf       1.1         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                         XmlParser parser(tmp.get());
 951                         XmlEntry entry;
 952 kumpf       1.1         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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2