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

Diff for /pegasus/src/Pegasus/Common/CIMObjectPath.cpp between version 1.22 and 1.55

version 1.22, 2002/09/20 19:40:11 version 1.55, 2006/05/02 20:26:58
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // The Open Group, Tivoli Systems  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // 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 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 26 
Line 34 
 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 //              Carol Ann Krug Graves, Hewlett-Packard Company //              Carol Ann Krug Graves, Hewlett-Packard Company
 //                (carolann_graves@hp.com) //                (carolann_graves@hp.com)
   //              Dave Sudlik, IBM (dsudlik@us.ibm.com)
   //              Vijay Eli, IBM (vijayeli@in.ibm.com), bug#2556.
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include <Pegasus/Common/Config.h> #include <Pegasus/Common/Config.h>
 #include <cctype>  
 #include <cstring> #include <cstring>
 #include <iostream> #include <iostream>
 #include "HashTable.h" #include "HashTable.h"
 #include "CIMObjectPath.h" #include "CIMObjectPath.h"
 #include "Indentor.h" #include "Indentor.h"
 #include "CIMName.h" #include "CIMName.h"
 #include "Destroyer.h"  
 #include "XmlWriter.h" #include "XmlWriter.h"
 #include "XmlReader.h" #include "XmlReader.h"
 #include "ArrayInternal.h" #include "ArrayInternal.h"
 #include "CIMOMPort.h"  
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
Line 77 
Line 84 
     {     {
         switch (str[i])         switch (str[i])
         {         {
             case '\n':              case '\\':
                 result.append("\\n");                  result.append("\\\\");
                 break;  
   
             case '\r':  
                 result.append("\\r");  
                 break;  
   
             case '\t':  
                 result.append("\\t");  
                 break;                 break;
  
             case '"':             case '"':
Line 105 
Line 104 
 { {
     Uint32 n = x.size();     Uint32 n = x.size();
  
       //
       //  If the key is a reference, the keys in the reference must also be
       //  sorted
       //
       for (Uint32 k = 0; k < n ; k++)
           if (x[k].getType () == CIMKeyBinding::REFERENCE)
           {
               CIMObjectPath tmp (x[k].getValue ());
               Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings ();
               _BubbleSort (keyBindings);
               tmp.setKeyBindings (keyBindings);
               x[k].setValue (tmp.toString ());
           }
   
     if (n < 2)     if (n < 2)
         return;         return;
  
Line 208 
Line 221 
     case CIMTYPE_REFERENCE:     case CIMTYPE_REFERENCE:
         kbType = REFERENCE;         kbType = REFERENCE;
         break;         break;
   //  case CIMTYPE_REAL32:
   //  case CIMTYPE_REAL64:
       case CIMTYPE_OBJECT:
   #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
       case CIMTYPE_INSTANCE:
   #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
           // From PEP 194: EmbeddedObjects cannot be keys.
           throw TypeMismatchException();
           break;
     default:     default:
         kbType = NUMERIC;         kbType = NUMERIC;
         break;         break;
Line 291 
Line 313 
             kbValue = XmlReader::stringToValue(0, getValue().getCString(),             kbValue = XmlReader::stringToValue(0, getValue().getCString(),
                                                value.getType());                                                value.getType());
             break;             break;
   //      case CIMTYPE_REAL32:
   //      case CIMTYPE_REAL64:
           case CIMTYPE_OBJECT:
   #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
           case CIMTYPE_INSTANCE:
   #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
               // From PEP 194: EmbeddedObjects cannot be keys.
               return false;
               break;
         default:  // Numerics         default:  // Numerics
             if (getType() != NUMERIC) return false;             if (getType() != NUMERIC) return false;
             kbValue = XmlReader::stringToValue(0, getValue().getCString(),             kbValue = XmlReader::stringToValue(0, getValue().getCString(),
Line 308 
Line 339 
  
 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y) Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
 { {
     return      // Check that the names and types match
         x.getName().equal(y.getName()) &&      if (!(x.getName().equal(y.getName())) ||
         String::equal(x.getValue(), y.getValue()) &&          !(x.getType() == y.getType()))
         x.getType() == y.getType();      {
           return false;
       }
   
       switch (x.getType())
       {
       case CIMKeyBinding::REFERENCE:
           try
           {
               // References should be compared as CIMObjectPaths
               return (CIMObjectPath(x.getValue()) == CIMObjectPath(y.getValue()));
           }
           catch (Exception&)
           {
               // If CIMObjectPath parsing fails, just compare strings
               return (String::equal(x.getValue(), y.getValue()));
           }
           break;
       case CIMKeyBinding::BOOLEAN:
           // Case-insensitive comparison is sufficient for booleans
           return (String::equalNoCase(x.getValue(), y.getValue()));
           break;
       case CIMKeyBinding::NUMERIC:
           // Note: This comparison assumes XML syntax for integers
           // First try comparing as unsigned integers
           {
               Uint64 xValue;
               Uint64 yValue;
               if (XmlReader::stringToUnsignedInteger(
                       x.getValue().getCString(), xValue) &&
                   XmlReader::stringToUnsignedInteger(
                       y.getValue().getCString(), yValue))
               {
                   return (xValue == yValue);
               }
           }
           // Next try comparing as signed integers
           {
               Sint64 xValue;
               Sint64 yValue;
               if (XmlReader::stringToSignedInteger(
                       x.getValue().getCString(), xValue) &&
                   XmlReader::stringToSignedInteger(
                       y.getValue().getCString(), yValue))
               {
                   return (xValue == yValue);
               }
           }
           // Note: Keys may not be real values, so don't try comparing as reals
           // We couldn't parse the numbers, so just compare the strings
           return (String::equal(x.getValue(), y.getValue()));
           break;
       default:  // CIMKeyBinding::STRING
           return (String::equal(x.getValue(), y.getValue()));
           break;
       }
   
       PEGASUS_UNREACHABLE(return false;)
 } }
  
  
Line 360 
Line 448 
         return *this;         return *this;
     }     }
  
       static Boolean isValidHostname(const String& hostname)
       {
           //------------------------------------------------------------------
           // Validate the hostname.  The hostname value may or may not be a
           // fully-qualified domain name (e.g., xyz.company.com) or may be an
           // IP address.  A port number may follow the hostname.
           // Hostnames must match one of the following regular expressions:
           // ^([A-Za-z0-9][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*(:[0-9]*)?$
           // ^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)(:[0-9]*)?$
           // Note for Bug#1462. Be careful here, from RFC 1123:
           // - The syntax of a legal Internet host name was specified in
           //   RFC-952 [DNS:4]. One aspect of host name syntax is hereby
           //   changed: the restriction on the first character is relaxed to
           //   allow either a letter or a digit.
           // - If a dotted-decimal number can be entered without identifying
           //   delimiters, then a full syntactic check must be made, because
           //   a segment of a host domain name is now allowed to begin with a
           //   digit and could legally be entirely numeric (see Section 6.1.2.4).
           //   However, a valid host name can never have the dotted-decimal form
           //   #.#.#.#, since at least the highest-level component label will be
           //   alphabetic.
           // The algorithm below has been updated accordingly.
           //------------------------------------------------------------------
   
           Uint32 i = 0;
   
           Boolean isValid = false;
   
           if (isascii(hostname[0]) && isdigit(hostname[0]))
           {
               //--------------------------------------------------------------
               // Attempt to validate an IP address, but keep in mind that it
               // might be a host name, since the leading character can now be
               // a digit.
               //--------------------------------------------------------------
               isValid = true;
   
               for (Uint32 octet=1; octet<=4; octet++)
               {
                   Uint32 octetValue = 0;
   
                   //----------------------------------------------------------
                   // If a non-digit is encountered in the input parameter,
                   // then break from here and attempt to validate as host name.
                   //----------------------------------------------------------
                   if (!(isascii(hostname[i]) && isdigit(hostname[i])))
                   {
                       isValid = false;
                       break;
                   }
   
                   // skip over digits
                   while (isascii(hostname[i]) && isdigit(hostname[i]))
                   {
                       octetValue = octetValue*10 + (hostname[i] - '0');
                       i++;
                   }
   
                   if (octetValue > 255)
                   {
                       isValid = false;
                       break;
                   }
   
                   // Check for invalid character in IP address
                   if ((octet != 4) && (hostname[i++] != '.'))
                   {
                       isValid = false;
                       break;
                   }
   
                   // Check for the case where it's a valid host name that happens
                   // to have 4 (or more) leading all-numeric host segments.
                   if ((octet == 4) && (hostname[i] != ':') && hostname[i] != char(0))
                   {
                       isValid = false;
                       break;
                   }
               }
           }
           if (!isValid)   // if it is not a valid IP address
           {
               i = 0;  // reset index for host name check
   
               // Validate a host name
               isValid = true;
   
               Boolean expectHostSegment = true;
               Boolean hostSegmentIsNumeric;
   
               while (expectHostSegment == true)
               {
                   expectHostSegment = false;
                   hostSegmentIsNumeric = true; // assume all-numeric host segment
   
                   if (!(isascii(hostname[i]) &&
                         (isalnum(hostname[i]) || (hostname[i] == '_'))))
                   {
                       return false;
                   }
   
                   while (isascii(hostname[i]) &&
                          (isalnum(hostname[i]) || (hostname[i] == '-') ||
                           (hostname[i] == '_')))
                   {
                       // If a non-digit is encountered, set "all-numeric"
                       // flag to false
                       if (isalpha(hostname[i]) || (hostname[i] == '-') ||
                                                   (hostname[i] == '_')) {
                           hostSegmentIsNumeric = false;
                       }
                       i++;
                   }
   
                   if (hostname[i] == '.')
                   {
                       i++;
                       expectHostSegment = true;
                   }
               }
               // If the last Host Segment is all numeric, then return false.
               // RFC 1123 says "highest-level component label will be alphabetic".
               if (hostSegmentIsNumeric) {
                   return false;
               }
           }
   
           if (!isValid) // if not a valid IP address or host name
           {
               return false;
           }
   
           // Check for a port number:
   
           if (hostname[i] == ':')
           {
               i++;
               if (!(isascii(hostname[i]) && isdigit(hostname[i])))
               {
                   return false;
               }
               i++;
   
               while (isascii(hostname[i]) && isdigit(hostname[i]))
               {
                   i++;
               }
           }
   
           return (hostname[i] == char(0));
       }
   
     //     //
     // Contains port as well (e.g., myhost:1234).     // Contains port as well (e.g., myhost:1234).
     //     //
Line 440 
Line 680 
     String& host)     String& host)
 { {
     // See if there is a host name (true if it begins with "//"):     // See if there is a host name (true if it begins with "//"):
     // Host is of the from <hostname>-<port> and begins with "//"      // Host is of the form <hostname>:<port> and begins with "//"
     // and ends with "/":     // and ends with "/":
  
     if (p[0] != '/' || p[1] != '/')     if (p[0] != '/' || p[1] != '/')
Line 450 
Line 690 
  
     p += 2;     p += 2;
  
     //----------------------------------------------------------------------      char* slash = strchr(p, '/');
     // Validate the hostname. Hostnames must match the following      if (!slash)
     // regular expression: "[A-Za-z][A-Za-z0-9-]*"  
     //----------------------------------------------------------------------  
   
     char* q = p;  
   
     if (!isalpha(*q))  
         throw MalformedObjectNameException(objectName);  
   
     q++;  
   
     while (isalnum(*q) || *q == '-')  
         q++;  
   
     // We now expect a port (or default the port).  
   
     if (*q == ':')  
     {     {
         q++;  
         // Check for a port number:  
   
         if (!isdigit(*q))  
             throw MalformedObjectNameException(objectName);             throw MalformedObjectNameException(objectName);
   
         while (isdigit(*q))  
             q++;  
   
         // Finally, assign the host name:  
   
         host.assign(p, q - p);  
     }     }
     else  
     {  
         host.assign(p, q - p);  
   
         // Assign the default port number:  
  
         host.append(":");      String hostname = String(p, (Uint32)(slash - p));
         host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING);      if (!CIMObjectPathRep::isValidHostname(hostname))
     }  
   
     // Check for slash terminating the entire sequence:  
   
     if (*q != '/')  
     {     {
         host.clear();  
         throw MalformedObjectNameException(objectName);         throw MalformedObjectNameException(objectName);
     }     }
       host = hostname;
  
     p = ++q;      // Do not step past the '/'; it will be consumed by the namespace parser
       p = slash;
  
     return true;     return true;
 } }
Line 519 
Line 723 
         return false;         return false;
     }     }
  
       // A ':' as part of a keybinding value should not be interpreted as
       // a namespace delimiter.  Since keybinding pairs follow the first '.'
       // in the object path string, the ':' delimiter only counts if it
       // appears before the '.'.
   
       char* dot = strchr(p, '.');
       if (dot && (dot < colon))
       {
           return false;
       }
   
     //----------------------------------------------------------------------     //----------------------------------------------------------------------
     // Validate the namespace path.  Namespaces must match the following     // Validate the namespace path.  Namespaces must match the following
     // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"     // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
     //----------------------------------------------------------------------     //----------------------------------------------------------------------
  
     String namespaceName = String(p, colon - p);      String namespaceName = String(p, (Uint32)(colon - p));
     if (!CIMNamespaceName::legal(namespaceName))     if (!CIMNamespaceName::legal(namespaceName))
     {     {
         throw MalformedObjectNameException(objectName);         throw MalformedObjectNameException(objectName);
Line 536 
Line 751 
 } }
  
 /** /**
     ATTN: RK - Association classes have keys whose types are      ATTN-RK: The DMTF specification for the string form of an
     references.  These reference values must be treated specially      object path makes it impossible for a parser to distinguish
     in the XML encoding, using the VALUE.REFERENCE tag structure.      between a key values of String type and Reference type.
   
     Pegasus had been passing reference values simply as String      Given the ambiguity, this implementation takes a guess at the
     values.  For example, EnumerateInstanceNames returned      type of a quoted key value.  If the value can be parsed into
     KEYVALUEs of string type rather than VALUE.REFERENCEs.      a CIMObjectPath with at least one key binding, the type is
       set to REFERENCE.  Otherwise, the type is set to STRING.
     I've modified the XmlReader::getKeyBindingElement() and      Note: This algorithm appears to be in line with what the Sun
     XmlWriter::appendInstanceNameElement() methods to read and write      WBEM Services implementation does.
     the XML in the proper format.  However, making that change  
     required that a CIMObjectPath object be able to distinguish      To be totally correct, it would be necessary to retrieve the
     between a key of String type and a key of reference type.      class definition and look up the types of the key properties
       to determine how to interpret the key values.  This is clearly
     I've modified the String format of CIMObjectPaths slightly to      too inefficient for internal transformations between
     allow efficient processing of references whose keys are also      CIMObjectPaths and String values.
     of reference type.  The "official" form uses the same  
     encoding for key values of String type and of reference type,  
     and so it would be necessary to retrieve the class definition  
     and look up the types of the key properties to determine how  
     to treat the key values.  This is clearly too inefficient for  
     internal transformations between CIMObjectPaths and String  
     values.  
   
     The workaround is to encode a 'R' at the beginning of the  
     value for a key of reference type (before the opening '"').  
     This allows the parser to know a priori whether the key is of  
     String or reference type.  
   
     In this example:  
   
         MyClass.Key1="StringValue",Key2=R"RefClass.KeyA="StringA",KeyB=10"  
   
     Property Key1 of class MyClass is of String type, and so it  
     gets the usual encoding.  Key2 is a reference property, so  
     the extra 'R' is inserted before its encoded value.  Note  
     that this algorithm is recursive, such that RefClass could  
     include KeyC of reference type, which would also get encoded  
     with the 'R' notation.  
   
     The toString() method inserts the 'R' to provide symmetry.  A  
     new CIMKeyBinding type (REFERENCE) has been defined to denote  
     keys in a CIMObjectPath that are of reference type.  This  
     CIMKeyBinding type must be used appropriately for  
     CIMObjectPath::toString() to behave correctly.  
   
     A result of this change is that instances names in the  
     instance repository will include this extra 'R' character.  
     Note that for user-facing uses of the String encoding of  
     instance names (such as might appear in MOF for static  
     association instances or in the CGI client), this solution  
     is non-standard and therefore unacceptable.  It is likely  
     that these points will need to process the more expensive  
     operation of retrieving the class definition to determine  
     the key property types.  
 */ */
 void _parseKeyBindingPairs( void _parseKeyBindingPairs(
     const String& objectName,     const String& objectName,
Line 622 
Line 798 
         p = equalsign + 1;         p = equalsign + 1;
         CIMKeyBinding::Type type;         CIMKeyBinding::Type type;
  
         if (*p == 'R')          if (*p == '"')
         {         {
             p++;              // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE
   
             type = CIMKeyBinding::REFERENCE;  
  
             if (*p++ != '"')              p++;
                 throw MalformedObjectNameException(objectName);  
  
             while (*p && *p != '"')             while (*p && *p != '"')
             {             {
                 // ATTN: need to handle special characters here:  
   
                 if (*p == '\\')                 if (*p == '\\')
                   {
                     *p++;                     *p++;
  
                       if ((*p != '\\') && (*p != '"'))
                       {
                           throw MalformedObjectNameException(objectName);
                       }
                   }
   
                 valueString.append(*p++);                 valueString.append(*p++);
             }             }
  
             if (*p++ != '"')             if (*p++ != '"')
                 throw MalformedObjectNameException(objectName);                 throw MalformedObjectNameException(objectName);
         }  
         else if (*p == '"')  
         {  
             p++;  
  
               /*
                   Guess at the type of this quoted key value.  If the value
                   can be parsed into a CIMObjectPath with at least one key
                   binding, the type is assumed to be a REFERENCE.  Otherwise,
                   the type is set to STRING.  (See method header for details.)
                */
             type = CIMKeyBinding::STRING;             type = CIMKeyBinding::STRING;
  
             while (*p && *p != '"')              try
             {             {
                 // ATTN: need to handle special characters here:                  CIMObjectPath testForPath(valueString);
                   if (testForPath.getKeyBindings().size() > 0)
                 if (*p == '\\')                  {
                     *p++;                      // We've found a reference value!
                       type = CIMKeyBinding::REFERENCE;
                 valueString.append(*p++);                  }
               }
               catch (const Exception &)
               {
                   // Not a reference value; leave type as STRING
             }             }
   
             if (*p++ != '"')  
                 throw MalformedObjectNameException(objectName);  
         }         }
         else if (toupper(*p) == 'T' || toupper(*p) == 'F')         else if (toupper(*p) == 'T' || toupper(*p) == 'F')
         {         {
Line 748 
Line 929 
  
     // Convert to a C String first:     // Convert to a C String first:
  
     char* p = strdup(objectName.getCString());      CString pCString = objectName.getCString();
     Destroyer<char> destroyer(p);      char* p = const_cast<char*>((const char*) pCString);
     Boolean gotHost;     Boolean gotHost;
     Boolean gotNamespace;     Boolean gotNamespace;
  
Line 779 
Line 960 
         return;         return;
     }     }
  
     String className = String(p, dot - p);      String className = String(p, (Uint32)(dot - p));
     if (!CIMName::legal(className))     if (!CIMName::legal(className))
     {     {
         throw MalformedObjectNameException(objectName);         throw MalformedObjectNameException(objectName);
Line 806 
Line 987 
  
 void CIMObjectPath::setHost(const String& host) void CIMObjectPath::setHost(const String& host)
 { {
       if ((host != String::EMPTY) && !CIMObjectPathRep::isValidHostname(host))
       {
           throw MalformedObjectNameException(host);
       }
   
     _rep->_host = host;     _rep->_host = host;
 } }
  
Line 889 
Line 1075 
  
             CIMKeyBinding::Type type = keyBindings[i].getType();             CIMKeyBinding::Type type = keyBindings[i].getType();
  
             if (type == CIMKeyBinding::REFERENCE)  
                 objectName.append('R');  
   
             if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)             if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
                 objectName.append('"');                 objectName.append('"');
  
Line 912 
Line 1095 
 { {
     CIMObjectPath ref = *this;     CIMObjectPath ref = *this;
  
     // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case?      // Normalize hostname by changing to lower case
       ref._rep->_host.toLower(); // ICU_TODO:
   
       // Normalize namespace by changing to lower case
       if (!ref._rep->_nameSpace.isNull())
       {
           String nameSpaceLower = ref._rep->_nameSpace.getString();
           nameSpaceLower.toLower(); // ICU_TODO:
           ref._rep->_nameSpace = nameSpaceLower;
       }
  
       // Normalize class name by changing to lower case
       if (!ref._rep->_className.isNull())
       {
     String classNameLower = ref._rep->_className.getString ();     String classNameLower = ref._rep->_className.getString ();
     classNameLower.toLower();          classNameLower.toLower(); // ICU_TODO:
     ref._rep->_className = classNameLower;     ref._rep->_className = classNameLower;
       }
  
     for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)     for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
     {     {
           // Normalize key binding name by changing to lower case
           if (!ref._rep->_keyBindings[i]._rep->_name.isNull())
           {
         String keyBindingNameLower =         String keyBindingNameLower =
             ref._rep->_keyBindings[i]._rep->_name.getString ();             ref._rep->_keyBindings[i]._rep->_name.getString ();
         keyBindingNameLower.toLower();              keyBindingNameLower.toLower(); // ICU_TODO:
         ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;         ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
     }     }
  
     // ATTN-RK-20020826: Need to sort keys?          // Normalize the key value
           switch (ref._rep->_keyBindings[i]._rep->_type)
           {
           case CIMKeyBinding::REFERENCE:
               try
               {
                   // Convert reference to CIMObjectPath and recurse
                   ref._rep->_keyBindings[i]._rep->_value =
                       CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value).
                           _toStringCanonical();
               }
               catch (Exception&)
               {
                   // Leave value unchanged if the CIMObjectPath parsing fails
               }
               break;
           case CIMKeyBinding::BOOLEAN:
               // Normalize the boolean string by changing to lower case
               ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO:
               break;
           case CIMKeyBinding::NUMERIC:
               // Normalize the numeric string by converting to integer and back
               Uint64 uValue;
               Sint64 sValue;
               // First try converting to unsigned integer
               if (XmlReader::stringToUnsignedInteger(
                       ref._rep->_keyBindings[i]._rep->_value.getCString(),
                           uValue))
               {
                   char buffer[32];  // Should need 21 chars max
                   sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue);
                   ref._rep->_keyBindings[i]._rep->_value = String(buffer);
               }
               // Next try converting to signed integer
               else if (XmlReader::stringToSignedInteger(
                            ref._rep->_keyBindings[i]._rep->_value.getCString(),
                                sValue))
               {
                   char buffer[32];  // Should need 21 chars max
                   sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue);
                   ref._rep->_keyBindings[i]._rep->_value = String(buffer);
               }
               // Leave value unchanged if it cannot be converted to an integer
               break;
           default:  // CIMKeyBinding::STRING
               // No normalization required for STRING
               break;
           }
       }
   
       // Note: key bindings are sorted when set in the CIMObjectPath
  
     return ref.toString();     return ref.toString();
 } }
Line 934 
Line 1183 
 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
 { {
     return     return
         String::equal(_rep->_host, x._rep->_host) &&          String::equalNoCase(_rep->_host, x._rep->_host) &&
         _rep->_nameSpace.equal(x._rep->_nameSpace) &&         _rep->_nameSpace.equal(x._rep->_nameSpace) &&
         _rep->_className.equal(x._rep->_className) &&         _rep->_className.equal(x._rep->_className) &&
         _rep->_keyBindings == x._rep->_keyBindings;         _rep->_keyBindings == x._rep->_keyBindings;
Line 955 
Line 1204 
     return !operator==(x, y);     return !operator==(x, y);
 } }
  
 #ifndef PEGASUS_REMOVE_DEPRECATED  
 PEGASUS_STD(ostream)& operator<<(  
     PEGASUS_STD(ostream)& os,  
     const CIMObjectPath& x)  
 {  
     return os << x.toString();  
 }  
 #endif  
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.22  
changed lines
  Added in v.1.55

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2