version 1.36, 2002/03/07 22:21:17
|
version 1.46, 2002/03/25 20:13:58
|
|
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) | // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
|
#include <Pegasus/Common/Config.h> |
#include <cassert> | #include <cassert> |
#include <cctype> | #include <cctype> |
#include <cstdio> | #include <cstdio> |
#include <cstdlib> | #include <cstdlib> |
|
#if defined(PEGASUS_OS_TYPE_UNIX) |
|
#include <errno.h> |
|
#endif |
#include "CIMName.h" | #include "CIMName.h" |
#include "XmlReader.h" | #include "XmlReader.h" |
#include "XmlWriter.h" | #include "XmlWriter.h" |
|
|
| |
Boolean XmlReader::stringToReal(const char* stringValue, Real64& x) | Boolean XmlReader::stringToReal(const char* stringValue, Real64& x) |
{ | { |
|
// |
|
// Check the string against the DMTF-defined grammar |
|
// |
const char* p = stringValue; | const char* p = stringValue; |
| |
if (!*p) | if (!*p) |
|
|
if (*p) | if (*p) |
return false; | return false; |
| |
|
// |
|
// Do the conversion |
|
// |
char* end; | char* end; |
|
errno = 0; |
x = strtod(stringValue, &end); | x = strtod(stringValue, &end); |
|
if (*end || (errno == ERANGE)) |
|
{ |
|
return false; |
|
} |
|
|
return true; | return true; |
} | } |
| |
|
inline Uint8 _hexCharToNumeric(const char c) |
|
{ |
|
Uint8 n; |
|
|
|
if (isdigit(c)) |
|
n = (c - '0'); |
|
else if (isupper(c)) |
|
n = (c - 'A' + 10); |
|
else // if (islower(c)) |
|
n = (c - 'a' + 10); |
|
|
|
return n; |
|
} |
|
|
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
// | // |
// stringToSignedInteger | // stringToSignedInteger |
// | // |
// [ "+" | "-" ] ( positiveDecimalDigit *decimalDigit | "0" ) | // [ "+" | "-" ] ( positiveDecimalDigit *decimalDigit | "0" ) |
|
// or |
|
// [ "+" | "-" ] ( "0x" | "0X" ) 1*hexDigit |
// | // |
// ATTN-B: handle conversion from hexadecimal. |
|
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
| |
Boolean XmlReader::stringToSignedInteger( | Boolean XmlReader::stringToSignedInteger( |
|
|
x = 0; | x = 0; |
const char* p = stringValue; | const char* p = stringValue; |
| |
if (!*p) |
if (!p || !*p) |
return false; | return false; |
| |
// Skip optional sign: | // Skip optional sign: |
|
|
if (negative || *p == '+') | if (negative || *p == '+') |
p++; | p++; |
| |
// If the next thing is a zero, then it must be the last: |
|
|
|
if (*p == '0') | if (*p == '0') |
return p[1] == '\0'; |
{ |
|
if ( (p[1] == 'x') || (p[1] == 'X') ) |
// Expect a positive decimal digit: |
{ |
|
// Convert a hexadecimal string |
| |
const char* first = p; |
// Skip over the "0x" |
|
p+=2; |
| |
if (!isdigit(*p) || *p == '0') |
// At least one hexadecimal digit is required |
|
if (!isxdigit(*p)) |
return false; | return false; |
| |
p++; |
// Build the Sint64 as a negative number, regardless of the |
|
// eventual sign (negative numbers can be bigger than positive ones) |
| |
// Expect zero or more digits: |
// Add on each digit, checking for overflow errors |
|
while (isxdigit(*p)) |
|
{ |
|
// Make sure we won't overflow when we multiply by 16 |
|
if (x < PEGASUS_LLONG_MIN/16) |
|
{ |
|
return false; |
|
} |
|
x = x << 4; |
| |
while (isdigit(*p)) |
// Make sure we don't overflow when we add the next digit |
p++; |
Sint64 newDigit = Sint64(_hexCharToNumeric(*p++)); |
|
if (PEGASUS_LLONG_MIN - x > -newDigit) |
|
{ |
|
return false; |
|
} |
|
x = x - newDigit; |
|
} |
| |
|
// If we found a non-hexadecimal digit, report an error |
if (*p) | if (*p) |
return false; | return false; |
| |
const char* last = p; |
// Return the integer to positive, if necessary, checking for an |
|
// overflow error |
|
if (!negative) |
|
{ |
|
if (x == PEGASUS_LLONG_MIN) |
|
{ |
|
return false; |
|
} |
|
x = -x; |
|
} |
|
return true; |
|
} |
|
else |
|
{ |
|
// A decimal string that starts with '0' must be exactly "0". |
|
return p[1] == '\0'; |
|
} |
|
} |
| |
while (first != last) |
// Expect a positive decimal digit: |
x = 10 * x + (*first++ - '0'); |
|
| |
if (negative) |
// At least one decimal digit is required |
x = -x; |
if (!isdigit(*p)) |
|
return false; |
| |
|
// Build the Sint64 as a negative number, regardless of the |
|
// eventual sign (negative numbers can be bigger than positive ones) |
|
|
|
// Add on each digit, checking for overflow errors |
|
while (isdigit(*p)) |
|
{ |
|
// Make sure we won't overflow when we multiply by 10 |
|
if (x < PEGASUS_LLONG_MIN/10) |
|
{ |
|
return false; |
|
} |
|
x = 10 * x; |
|
|
|
// Make sure we won't overflow when we add the next digit |
|
Sint64 newDigit = (*p++ - '0'); |
|
if (PEGASUS_LLONG_MIN - x > -newDigit) |
|
{ |
|
return false; |
|
} |
|
x = x - newDigit; |
|
} |
|
|
|
// If we found a non-decimal digit, report an error |
|
if (*p) |
|
return false; |
|
|
|
// Return the integer to positive, if necessary, checking for an |
|
// overflow error |
|
if (!negative) |
|
{ |
|
if (x == PEGASUS_LLONG_MIN) |
|
{ |
|
return false; |
|
} |
|
x = -x; |
|
} |
return true; | return true; |
} | } |
| |
|
|
// | // |
// stringToUnsignedInteger | // stringToUnsignedInteger |
// | // |
// [ "+" | "-" ] ( positiveDecimalDigit *decimalDigit | "0" ) |
// ( positiveDecimalDigit *decimalDigit | "0" ) |
|
// or |
|
// ( "0x" | "0X" ) 1*hexDigit |
// | // |
// ATTN-B: handle conversion from hexadecimal. |
|
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
| |
Boolean XmlReader::stringToUnsignedInteger( | Boolean XmlReader::stringToUnsignedInteger( |
|
|
x = 0; | x = 0; |
const char* p = stringValue; | const char* p = stringValue; |
| |
if (!*p) |
if (!p || !*p) |
return false; | return false; |
| |
// Skip optional sign: |
if (*p == '0') |
|
{ |
|
if ( (p[1] == 'x') || (p[1] == 'X') ) |
|
{ |
|
// Convert a hexadecimal string |
| |
if (*p == '-') |
// Skip over the "0x" |
|
p+=2; |
|
|
|
// At least one hexadecimal digit is required |
|
if (!*p) |
return false; | return false; |
| |
if (*p == '+') |
// Add on each digit, checking for overflow errors |
p++; |
while (isxdigit(*p)) |
|
{ |
|
// Make sure we won't overflow when we multiply by 16 |
|
if (x > PEGASUS_ULLONG_MAX/16) |
|
{ |
|
return false; |
|
} |
|
x = x << 4; |
| |
// If the next thing is a zero, then it must be the last: |
// We can't overflow when we add the next digit |
|
Uint64 newDigit = Uint64(_hexCharToNumeric(*p++)); |
|
if (PEGASUS_ULLONG_MAX - x < newDigit) |
|
{ |
|
return false; |
|
} |
|
x = x + newDigit; |
|
} |
| |
if (*p == '0') |
// If we found a non-hexadecimal digit, report an error |
|
if (*p) |
|
return false; |
|
|
|
return true; |
|
} |
|
else |
|
{ |
|
// A decimal string that starts with '0' must be exactly "0". |
return p[1] == '\0'; | return p[1] == '\0'; |
|
} |
|
} |
| |
// Expect a positive decimal digit: | // Expect a positive decimal digit: |
| |
const char* first = p; |
// Add on each digit, checking for overflow errors |
|
while (isdigit(*p)) |
if (!isdigit(*p) || *p == '0') |
{ |
|
// Make sure we won't overflow when we multiply by 10 |
|
if (x > PEGASUS_ULLONG_MAX/10) |
|
{ |
return false; | return false; |
|
} |
|
x = 10 * x; |
| |
p++; |
// Make sure we won't overflow when we add the next digit |
|
Uint64 newDigit = (*p++ - '0'); |
// Expect zero or more digits: |
if (PEGASUS_ULLONG_MAX - x < newDigit) |
|
{ |
while (isdigit(*p)) |
return false; |
p++; |
} |
|
x = x + newDigit; |
|
} |
| |
|
// If we found a non-decimal digit, report an error |
if (*p) | if (*p) |
return false; | return false; |
| |
const char* last = p; |
|
|
|
while (first != last) |
|
x = 10 * x + (*first++ - '0'); |
|
|
|
return true; | return true; |
} | } |
| |
|
|
// | // |
// stringToValue() | // stringToValue() |
// | // |
// ATTN-C: note that integers are truncated without warning. What should be |
|
// done in this case? In C they are truncated without warning by design. |
|
// |
|
// Return: CIMValue. If the string input is zero length creates a CIMValue | // Return: CIMValue. If the string input is zero length creates a CIMValue |
// with value defined by the type. Else the value is inserted. | // with value defined by the type. Else the value is inserted. |
// | // |
|
|
{ | { |
// ATTN-B: accepting only UTF-8 for now! (affects string and char16): | // ATTN-B: accepting only UTF-8 for now! (affects string and char16): |
| |
|
// The Specification for the Representation of CIM in XML does not indicate |
|
// that a default value should be used when a VALUE element is empty. |
|
//#if 0 ATTN-RK-P3-20020321: Take this code out when null qualifiers are fixed |
// If strlen == 0, set to default value for type | // If strlen == 0, set to default value for type |
| |
if (strlen(valueString)==0) | if (strlen(valueString)==0) |
|
|
case CIMType::REAL64: return CIMValue(Real64(0)); | case CIMType::REAL64: return CIMValue(Real64(0)); |
} | } |
} | } |
|
//#endif |
| |
// Create value per type | // Create value per type |
switch (type) | switch (type) |
|
|
| |
switch (type) | switch (type) |
{ | { |
case CIMType::UINT8: return CIMValue(Uint8(x)); |
case CIMType::UINT8: |
case CIMType::UINT16: return CIMValue(Uint16(x)); |
{ |
case CIMType::UINT32: return CIMValue(Uint32(x)); |
if (x >= (Uint64(1)<<8)) |
|
{ |
|
throw XmlSemanticError( |
|
lineNumber, "Uint8 value out of range"); |
|
} |
|
return CIMValue(Uint8(x)); |
|
} |
|
case CIMType::UINT16: |
|
{ |
|
if (x >= (Uint64(1)<<16)) |
|
{ |
|
throw XmlSemanticError( |
|
lineNumber, "Uint16 value out of range"); |
|
} |
|
return CIMValue(Uint16(x)); |
|
} |
|
case CIMType::UINT32: |
|
{ |
|
if (x >= (Uint64(1)<<32)) |
|
{ |
|
throw XmlSemanticError( |
|
lineNumber, "Uint32 value out of range"); |
|
} |
|
return CIMValue(Uint32(x)); |
|
} |
case CIMType::UINT64: return CIMValue(Uint64(x)); | case CIMType::UINT64: return CIMValue(Uint64(x)); |
default: break; | default: break; |
} | } |
|
|
| |
switch (type) | switch (type) |
{ | { |
case CIMType::SINT8: return CIMValue(Sint8(x)); |
case CIMType::SINT8: |
case CIMType::SINT16: return CIMValue(Sint16(x)); |
{ |
case CIMType::SINT32: return CIMValue(Sint32(x)); |
if( (x >= (Sint64(1)<<7)) || (x < (-(Sint64(1)<<7))) ) |
|
{ |
|
throw XmlSemanticError( |
|
lineNumber, "Sint8 value out of range"); |
|
} |
|
return CIMValue(Sint8(x)); |
|
} |
|
case CIMType::SINT16: |
|
{ |
|
if( (x >= (Sint64(1)<<15)) || (x < (-(Sint64(1)<<15))) ) |
|
{ |
|
throw XmlSemanticError( |
|
lineNumber, "Sint16 value out of range"); |
|
} |
|
return CIMValue(Sint16(x)); |
|
} |
|
case CIMType::SINT32: |
|
{ |
|
if( (x >= (Sint64(1)<<31)) || (x < (-(Sint64(1)<<31))) ) |
|
{ |
|
throw XmlSemanticError( |
|
lineNumber, "Sint32 value out of range"); |
|
} |
|
return CIMValue(Sint32(x)); |
|
} |
case CIMType::SINT64: return CIMValue(Sint64(x)); | case CIMType::SINT64: return CIMValue(Sint64(x)); |
default: break; | default: break; |
} | } |
|
|
Real64 x; | Real64 x; |
| |
if (!stringToReal(valueString, x)) | if (!stringToReal(valueString, x)) |
throw XmlSemanticError(lineNumber, "Bad real value"); |
throw XmlSemanticError(lineNumber, "Bad real number value"); |
| |
return CIMValue(Real32(x)); | return CIMValue(Real32(x)); |
} | } |
|
|
Real64 x; | Real64 x; |
| |
if (!stringToReal(valueString, x)) | if (!stringToReal(valueString, x)) |
throw XmlSemanticError(lineNumber, "Bad real value"); |
throw XmlSemanticError(lineNumber, "Bad real number value"); |
| |
return CIMValue(x); | return CIMValue(x); |
} | } |
|
|
Boolean translatable = getCimBooleanAttribute( | Boolean translatable = getCimBooleanAttribute( |
lineNumber, entry, tagName, "TRANSLATABLE", false, false); | lineNumber, entry, tagName, "TRANSLATABLE", false, false); |
| |
// ATTN: KS P1 5 Mar 2002 Should this not be CIMFlavor::DEFAULTS?? |
// Start with CIMFlavor::NONE. Defaults are specified in the |
//Uint32 flavor = CIMFlavor::DEFAULTS; |
// getCimBooleanAttribute() calls above. |
// ATTN-RK-P1-20020307: No, Karl. If you initialize to the defaults, |
|
// you have to unset the default flavors that don't apply. The code |
|
// below only adds qualifiers. |
|
Uint32 flavor = CIMFlavor::NONE; | Uint32 flavor = CIMFlavor::NONE; |
| |
if (overridable) | if (overridable) |