version 1.2, 2008/03/07 18:09:48
|
version 1.13, 2013/01/14 11:55:43
|
|
|
//%2006//////////////////////////////////////////////////////////////////////// |
//%LICENSE//////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Licensed to The Open Group (TOG) under one or more contributor license |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with |
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; |
// this work for additional information regarding copyright ownership. |
// IBM Corp.; EMC Corporation, The Open Group. |
// Each contributor licenses this file to you under the OpenPegasus Open |
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
// Source License; you may not use this file except in compliance with the |
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
// License. |
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy |
|
// of this software and associated documentation files (the "Software"), to |
|
// deal in the Software without restriction, including without limitation the |
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|
// sell copies of the Software, and to permit persons to whom the Software is |
|
// furnished to do so, subject to the following conditions: |
|
// |
|
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN |
|
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED |
|
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
|
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// | // |
//============================================================================== |
// Permission is hereby granted, free of charge, to any person obtaining a |
|
// copy of this software and associated documentation files (the "Software"), |
|
// to deal in the Software without restriction, including without limitation |
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
// and/or sell copies of the Software, and to permit persons to whom the |
|
// Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included |
|
// in all copies or substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// |
|
////////////////////////////////////////////////////////////////////////// |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
}; | }; |
| |
// If _isSpecialChar7[ch] is true, then ch is a special character, which must | // If _isSpecialChar7[ch] is true, then ch is a special character, which must |
// have a special encoding in XML. But only use 7-bit ASCII characters to |
// have a special encoding in XML. |
// index this array. |
// Remaining 128 values are automatically initialised to 0 by compiler. |
static const int _isSpecialChar7[] = |
static const int _isSpecialChar7[256] = |
{ | { |
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, | 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, |
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, | 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, |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, |
}; | }; |
| |
|
// If _isSpecialChar7[ch] is true, then ch is a special character, which must |
|
// have a special encoding in XML. |
|
static const int _isNormalChar7[] = |
|
{ |
|
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, |
|
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, |
|
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, |
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, |
|
// remaining 128 values are used on multi-byte UTF-8 and should not be escaped |
|
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, |
|
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, |
|
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, |
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 |
|
}; |
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
| |
Buffer& operator<<(Buffer& out, const Char16& x) | Buffer& operator<<(Buffer& out, const Char16& x) |
|
|
return out; | return out; |
} | } |
| |
|
const StrLit XmlGenerator::_XmlWriterTypeStrings[17] = |
|
{ |
|
STRLIT("TYPE=\"boolean\""), STRLIT("TYPE=\"uint8\""), |
|
STRLIT("TYPE=\"sint8\""), STRLIT("TYPE=\"uint16\""), |
|
STRLIT("TYPE=\"sint16\""), STRLIT("TYPE=\"uint32\""), |
|
STRLIT("TYPE=\"sint32\""), STRLIT("TYPE=\"uint64\""), |
|
STRLIT("TYPE=\"sint64\""), STRLIT("TYPE=\"real32\""), |
|
STRLIT("TYPE=\"real64\""), STRLIT("TYPE=\"char16\""), |
|
STRLIT("TYPE=\"string\""), STRLIT("TYPE=\"datetime\""), |
|
STRLIT("TYPE=\"reference\""), STRLIT("TYPE=\"object\""), |
|
STRLIT("TYPE=\"instance\"") |
|
}; |
|
|
|
const StrLit XmlGenerator::_XmlWriterKeyTypeStrings[17] = |
|
{ |
|
STRLIT("boolean"), STRLIT("numeric"), |
|
STRLIT("numeric"), STRLIT("numeric"), |
|
STRLIT("numeric"), STRLIT("numeric"), |
|
STRLIT("numeric"), STRLIT("numeric"), |
|
STRLIT("numeric"), STRLIT("numeric"), |
|
STRLIT("numeric"), STRLIT("string"), |
|
STRLIT("string"), STRLIT("string"), |
|
/* The following are not valid values for a keytype, but left in here |
|
so in case something is going wrong it can be easily concluded from the |
|
generated XML */ |
|
STRLIT("reference"), STRLIT("object"), |
|
STRLIT("instance") |
|
}; |
|
|
void XmlGenerator::_appendChar(Buffer& out, const Char16& c) | void XmlGenerator::_appendChar(Buffer& out, const Char16& c) |
{ | { |
// We need to convert the Char16 to UTF8 then append the UTF8 | // We need to convert the Char16 to UTF8 then append the UTF8 |
|
|
_appendChar(out, c); | _appendChar(out, c); |
} | } |
| |
|
|
|
|
|
//Based on the platforms CHAR_MIN == -127 or CHAR_MIN == 0 |
|
//The above value is used to decide if the platform assumes |
|
//char as signed char or unsigned char required to stop build |
|
//btreaks for PPC under linux |
|
static inline Boolean isSpecialChar(const char &c) |
|
{ |
|
#if CHAR_MIN < 0 |
|
return (((c < 0x20) && (c >= 0)) || (c == 0x7f)); |
|
#else |
|
return ((c < 0x20) || (c == 0x7f)); |
|
#endif |
|
} |
|
|
void XmlGenerator::_appendSpecialChar(PEGASUS_STD(ostream)& os, char c) | void XmlGenerator::_appendSpecialChar(PEGASUS_STD(ostream)& os, char c) |
{ | { |
if ( ((c < 0x20) && (c >= 0)) || (c == 0x7f) ) |
if(isSpecialChar(c)) |
{ | { |
char scratchBuffer[22]; | char scratchBuffer[22]; |
Uint32 outputLength; | Uint32 outputLength; |
|
|
_appendSpecialChar(os, *str++); | _appendSpecialChar(os, *str++); |
} | } |
| |
// On windows sprintf outputs 3 digit precision exponent prepending |
|
// zeros. Make it 2 digit precision if first digit is zero in the exponent. |
|
#ifdef PEGASUS_OS_TYPE_WINDOWS |
|
void XmlGenerator::_normalizeRealValueString(char* str) |
|
{ |
|
// skip initial sign value... |
|
if (*str == '-' || *str == '+') |
|
{ |
|
++str; |
|
} |
|
while (*str && *str != '+' && *str != '-') |
|
{ |
|
++str; |
|
} |
|
if (*str && * ++str == '0') |
|
{ |
|
*str = *(str+1); |
|
*(str+1) = *(str+2); |
|
*(str+2) = 0; |
|
} |
|
} |
|
#endif |
|
|
|
void XmlGenerator::append(Buffer& out, const Char16& x) | void XmlGenerator::append(Buffer& out, const Char16& x) |
{ | { |
_appendChar(out, x); | _appendChar(out, x); |
|
|
| |
void XmlGenerator::append(Buffer& out, Real32 x) | void XmlGenerator::append(Buffer& out, Real32 x) |
{ | { |
|
Uint32 outputLength=0; |
char buffer[128]; | char buffer[128]; |
// %.7e gives '[-]m.ddddddde+/-xx', which seems compatible with the format |
const char * output = Real32ToString(buffer, x, outputLength); |
// given in the CIM/XML spec, and the precision required by the CIM 2.2 spec |
out.append(output, outputLength); |
// (4 byte IEEE floating point) |
|
sprintf(buffer, "%.7e", x); |
|
#ifdef PEGASUS_OS_TYPE_WINDOWS |
|
_normalizeRealValueString(buffer); |
|
#endif |
|
append(out, buffer); |
|
} | } |
| |
void XmlGenerator::append(Buffer& out, Real64 x) | void XmlGenerator::append(Buffer& out, Real64 x) |
{ | { |
|
Uint32 outputLength=0; |
char buffer[128]; | char buffer[128]; |
// %.16e gives '[-]m.dddddddddddddddde+/-xx', which seems compatible |
const char * output = Real64ToString(buffer, x, outputLength); |
// with the format given in the CIM/XML spec, and the precision required |
out.append(output, outputLength); |
// by the CIM 2.2 spec (8 byte IEEE floating point) |
|
sprintf(buffer, "%.16e", x); |
|
#ifdef PEGASUS_OS_TYPE_WINDOWS |
|
_normalizeRealValueString(buffer); |
|
#endif |
|
append(out, buffer); |
|
} | } |
| |
void XmlGenerator::append(Buffer& out, const char* str) | void XmlGenerator::append(Buffer& out, const char* str) |
|
|
} | } |
} | } |
| |
|
// str has to be UTF-8 encoded |
|
// that means the characters used cannot be larger than 7bit ASCII in value |
|
// range |
|
void XmlGenerator::appendSpecial(Buffer& out, const char* str, Uint32 size) |
|
{ |
|
// employ loop unrolling and a less checking optimized Buffer access |
|
|
|
// Buffer cannot grow more than 6*size characters (ie. 4*size+2*size) |
|
Uint32 newMaxSize = (size << 2) + (size << 1); |
|
if (out.size() + newMaxSize >= out.capacity()) |
|
{ |
|
out.reserveCapacity(out.capacity() + newMaxSize); |
|
} |
|
|
|
// Before using a loop unrolled algorithm to pick out the special chars |
|
// we are going to assume there is no special char as this is the case most |
|
// of the time anyway |
|
Uint32 sizeStart=size; |
|
const Uint8* p= (const Uint8*) str; |
|
|
|
while (size >= 4 && |
|
(_isNormalChar7[p[0]] & |
|
_isNormalChar7[p[1]] & |
|
_isNormalChar7[p[2]] & |
|
_isNormalChar7[p[3]])) |
|
{ |
|
size -= 4; |
|
p += 4; |
|
} |
|
out.append_unchecked(str,sizeStart-size); |
|
str=(const char*)p; |
|
|
|
while (size>=8) |
|
{ |
|
register Uint8 c; |
|
c = str[0]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[1]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[2]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[3]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[4]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[5]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[6]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[7]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
str+=8; |
|
size-=8; |
|
} |
|
|
|
while (size>=4) |
|
{ |
|
register Uint8 c; |
|
c = str[0]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[1]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[2]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
c = str[3]; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
str+=4; |
|
size-=4; |
|
} |
|
|
|
while (size--) |
|
{ |
|
register Uint8 c; |
|
c=*str; |
|
if (_isSpecialChar7[c]) |
|
{ |
|
out.append_unchecked( |
|
_specialChars[c].str, |
|
_specialChars[c].size); |
|
} |
|
else |
|
{ |
|
out.append_unchecked(c); |
|
} |
|
str++; |
|
} |
|
} |
|
|
|
|
// See http://www.ietf.org/rfc/rfc2396.txt section 2 | // See http://www.ietf.org/rfc/rfc2396.txt section 2 |
// Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ',' | // Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ',' |
// Excluded characters: | // Excluded characters: |
|
|
void XmlGenerator::_encodeURIChar(String& outString, Sint8 char8) | void XmlGenerator::_encodeURIChar(String& outString, Sint8 char8) |
{ | { |
Uint8 c = (Uint8)char8; | Uint8 c = (Uint8)char8; |
|
|
#ifndef PEGASUS_DO_NOT_IMPLEMENT_URI_ENCODING |
|
if (c > 127 || _is_uri[int(c)]) | if (c > 127 || _is_uri[int(c)]) |
{ | { |
char hexencoding[4]; | char hexencoding[4]; |
int n = sprintf(hexencoding, "%%%X%X", c/16, c%16); | int n = sprintf(hexencoding, "%%%X%X", c/16, c%16); |
#ifdef PEGASUS_USE_STRING_EXTENSIONS |
|
outString.append(hexencoding, n); | outString.append(hexencoding, n); |
#else /* PEGASUS_USE_STRING_EXTENSIONS */ |
|
outString.append(hexencoding); |
|
#endif /* PEGASUS_USE_STRING_EXTENSIONS */ |
|
} | } |
else | else |
#endif |
|
{ | { |
outString.append((Uint16)c); | outString.append((Uint16)c); |
} | } |
} | } |
| |
String XmlGenerator::encodeURICharacters(const Buffer& uriString) |
|
{ |
|
String encodedString; |
|
|
|
for (Uint32 i=0; i<uriString.size(); i++) |
|
{ |
|
_encodeURIChar(encodedString, uriString[i]); |
|
} |
|
|
|
return encodedString; |
|
} |
|
|
|
String XmlGenerator::encodeURICharacters(const String& uriString) | String XmlGenerator::encodeURICharacters(const String& uriString) |
{ | { |
String encodedString; | String encodedString; |
|
|
| |
os << "<?" << entry.text << " "; | os << "<?" << entry.text << " "; |
_printAttributes( | _printAttributes( |
os, entry.attributes, entry.attributeCount); |
os, entry.attributes.getData(), entry.attributes.size()); |
os << "?>"; | os << "?>"; |
break; | break; |
} | } |
|
|
| |
os << "<" << entry.text; | os << "<" << entry.text; |
| |
if (entry.attributeCount) |
if (entry.attributes.size()) |
os << ' '; | os << ' '; |
| |
_printAttributes( | _printAttributes( |
os, entry.attributes, entry.attributeCount); |
os, entry.attributes.getData(), entry.attributes.size()); |
os << ">"; | os << ">"; |
stack.push(entry.text); | stack.push(entry.text); |
break; | break; |
|
|
| |
os << "<" << entry.text << " "; | os << "<" << entry.text << " "; |
_printAttributes( | _printAttributes( |
os, entry.attributes, entry.attributeCount); |
os, entry.attributes.getData(), entry.attributes.size()); |
os << "/>"; | os << "/>"; |
break; | break; |
} | } |