ValueNoSTL.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:31k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. #define VXIVALUE_EXPORTS
  23. #include "Value.hpp"
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. /**
  28.  * Abstractions for VXIchar
  29.  */
  30. #define _UNICODE
  31. #ifdef _UNICODE
  32. #define VXIcharStrlen  wcslen
  33. #define VXIcharStrcpy  wcscpy
  34. #define VXIcharStrcmp  wcscmp
  35. #else
  36. #define VXIcharStrlen  strlen
  37. #define VXIcharStrcpy  strcpy
  38. #define VXIcharStrcmp  strcmp
  39. #endif
  40. /**
  41.  * Real VXIString class
  42.  */
  43. class VXIString : public VXIValue {
  44.  public:
  45.   // Constructor and destructor
  46.   VXIString (const VXIchar *v)
  47.     : VXIValue (VALUE_STRING), value(NULL), length(0) 
  48.   {
  49.     if (( v ) && ( (value = new VXIchar [VXIcharStrlen (v) + 1]) != NULL )) {
  50.       VXIcharStrcpy (value, v);
  51.       length = VXIcharStrlen (v);
  52.     }
  53.   }
  54.   VXIString (const VXIchar *v, VXIunsigned u)
  55.     : VXIValue (VALUE_STRING), value(NULL), length(u)
  56.   {
  57.     if (( v ) && ( (value = new VXIchar [u + 1]) != NULL )) {
  58.       for (unsigned int i = 0; i < u; ++i) value[i] = v[i];
  59.       value[u] = '';
  60.     }
  61.   }
  62.   virtual ~VXIString( ) { if ( value ) { delete [] value; value = NULL; } }
  63.   // Get the length of the string
  64.   VXIunsigned GetLength( ) const       { return length; }
  65.   // Get and set the value
  66.   const VXIchar *GetValue( ) const { return value; }
  67.   void SetValue (const VXIchar *v) { 
  68.     if ( value ) { delete [] value; value = NULL; length = 0; }
  69.     if (( v ) && ( (value = new VXIchar [VXIcharStrlen (v) + 1]) != NULL )) {
  70.       VXIcharStrcpy (value, v);
  71.       length = VXIcharStrlen (v);
  72.     }
  73.   }
  74.   // Comparison methods, equivalent to strcmp( )
  75.   int Compare (const VXIString &s) const { 
  76.     return VXIcharStrcmp (value, s.value); }
  77.   int Compare (const VXIchar *s) const { 
  78.     return VXIcharStrcmp (value, s); }
  79.   // Copy constructor and assignment operator
  80.   VXIString (const VXIString &v) : VXIValue (VALUE_STRING), value(NULL) {
  81.     if (( v.value ) && 
  82. ( (value = new VXIchar [v.length + 1]) != NULL )) {
  83.       for (unsigned int i = 0; i < v.length + 1; ++i) value[i] = v.value[i];
  84.       length = v.length;
  85.     }
  86.   }
  87.   VXIString & operator= (const VXIString &v) {
  88.     if ( this != &v ) {
  89.       if ( value ) { delete [] value; value = NULL; length = 0; }
  90.       if (( v.value ) && 
  91.   ( (value = new VXIchar [v.length + 1]) != NULL )) {
  92.         for (unsigned int i = 0; i < v.length + 1; ++i) value[i] = v.value[i];
  93.         length = v.length;
  94.       }
  95.     }
  96.     return *this;
  97.   }
  98.   // Overrides of comparison operators for VXIMapElement use
  99.   virtual bool operator< (const VXIString &s) const {
  100.     return (Compare (s) < 0 ? true : false);
  101.   }
  102.   virtual bool operator== (const VXIString &s) const { 
  103.     return (Compare (s) == 0 ? true : false);
  104.   }
  105.   virtual bool operator!= (const VXIString &s) const { 
  106.     return (Compare (s) != 0 ? true : false);
  107.   }
  108.  private:
  109.   VXIchar *value;
  110.   unsigned int length;
  111. };
  112. /**
  113.  * Real VXIMap and supporting classes
  114.  */
  115. class VXIElement {
  116.  public:
  117.   // Constructor and destructor
  118.   VXIElement (const VXIchar *k, VXIValue *v) : 
  119.     key(k), value(v), next(NULL) { }
  120.   VXIElement (const VXIString &k, VXIValue *v) : 
  121.     key(k), value(v), next(NULL) { }
  122.   ~VXIElement( ) { value = NULL; }
  123.   // Get the key and value
  124.   const VXIString &GetKey( ) const { return key; }
  125.   const VXIValue *GetValue( ) const { return value; }
  126.   // Destroy the value
  127.   void DestroyValue( ) { if ( value ) VXIValueDestroy (&value); }
  128.   // Get and set the next element pointer
  129.   VXIElement *GetNext( ) const { return next; }
  130.   void SetNext (VXIElement *e) { next = e; }
  131.   // Overrides of comparison operators for finding elements based on
  132.   // the key name
  133.   virtual bool operator< (const VXIElement &e) const {
  134.     return key < e.key;
  135.   }
  136.   virtual bool operator== (const VXIElement &e) const { 
  137.     return key == e.key;
  138.   }
  139.   virtual bool operator!= (const VXIElement &e) const { 
  140.     return key != e.key;
  141.   }
  142.  private:
  143.   // Stubs to prevent copy constructor and assignment operator use
  144.   VXIElement (const VXIElement &e);
  145.   VXIElement & operator= (const VXIElement &e);
  146.  private:
  147.   VXIString      key;
  148.   VXIValue      *value;
  149.   VXIElement    *next;
  150. };
  151. class VXIMap : public VXIValue {
  152.  public:
  153.   // Constructor and destructor
  154.   VXIMap( ) : VXIValue (VALUE_MAP), badState(false), size(0),
  155.  head(NULL) { }
  156.   virtual ~VXIMap( );
  157.   // Copy constructor
  158.   VXIMap (const VXIMap &m);
  159.  private:
  160.   // Stub to prevent assignment operator use, use the copy constructor
  161.   VXIMap & operator= (const VXIMap &m);
  162.  public:
  163.   bool              badState;
  164.   unsigned long     size;
  165.   VXIElement       *head;
  166. };
  167. VXIMap::~VXIMap( )
  168. {
  169.   VXIElement *cur = head, *next;
  170.   while (cur) {
  171.     next = cur->GetNext( );
  172.     cur->DestroyValue( );
  173.     delete cur;
  174.     cur = next;
  175.   }
  176. }
  177. VXIMap::VXIMap (const VXIMap &m) : 
  178.   VXIValue (VALUE_MAP), badState(false), size(0), head(NULL)
  179. {
  180.   VXIElement *src = m.head, *prev = NULL, *dest;
  181.   while (src) {
  182.     dest = new VXIElement (src->GetKey( ), VXIValueClone (src->GetValue( )));
  183.     if ( dest == NULL ) {
  184.       badState = true;
  185.       return;
  186.     } else if (( dest->GetKey( ).GetLength( ) == 0 ) ||
  187.        ( dest->GetValue( ) == NULL )) {
  188.       dest->DestroyValue( );
  189.       delete dest;
  190.       badState = true;
  191.       return;
  192.     }
  193.     if ( prev == NULL )
  194.       head = dest;
  195.     else
  196.       prev->SetNext (dest);
  197.     prev = dest;
  198.     src = src->GetNext( );
  199.   }
  200.   size = m.size;
  201. }
  202. class VXIMapIterator {
  203.  public:
  204.   // Constructor and destructor
  205.   VXIMapIterator(const VXIMap *o) : curElement(o->head) { }
  206.   virtual ~VXIMapIterator( ) { }
  207.   // Get the key and value at the iterator's position
  208.   VXIvalueResult GetKeyValue (const VXIchar **key, 
  209.       const VXIValue **value) const {
  210.     if ( curElement == NULL ) {
  211.       *key = NULL;
  212.       *value = NULL;
  213.       return VXIvalue_RESULT_FAILURE;
  214.     }
  215.     *key = curElement->GetKey( ).GetValue( );
  216.     *value = curElement->GetValue( );
  217.     return VXIvalue_RESULT_SUCCESS;
  218.   }
  219.   // Increment the iterator
  220.   VXIMapIterator &operator++(int) { 
  221.     if ( curElement != NULL )
  222.       curElement = curElement->GetNext( ); 
  223.     return *this; }
  224.  private:
  225.   const VXIElement *curElement;
  226. };
  227. /**
  228.  * Real VXIVector and supporting classes
  229.  */
  230. class VXIVector : public VXIValue {
  231.  public:
  232.   static const int GROW_SIZE;
  233.  public:
  234.   // Constructor and destructor
  235.   VXIVector( ) : VXIValue (VALUE_VECTOR), badState(false), size(0), 
  236.     allocated(0), data(NULL) { }
  237.   virtual ~VXIVector( );
  238.   // Copy constructor
  239.   VXIVector (const VXIVector &v);
  240.   // Add an element
  241.   VXIvalueResult Add (VXIValue *v);
  242.  private:
  243.   // Stub to prevent assignment operator use, use the copy constructor
  244.   VXIMap & operator= (const VXIMap &o);
  245.  public:
  246.   bool              badState;
  247.   unsigned long     size;
  248.   unsigned long     allocated;
  249.   VXIElement       *data;
  250. };
  251. const int VXIVector::GROW_SIZE = 8;
  252. // Special new operator required by VXIVector, used to simply allow
  253. // us to allocate our own memory for the vector data storage, and
  254. // the matching delete
  255. inline void *operator new (size_t, void *p) { return p; }
  256. inline void operator delete(void *, void *) { }
  257. VXIVector::~VXIVector( )
  258.   if ( data ) {
  259.     // Explicit destructor of each held item which does the standard
  260.     // destruction of delete( ) but skips the memory free since we
  261.     // provided the memory ourselves
  262.     for (unsigned long i = 0; i < size; i++) {
  263.       data[i].DestroyValue( );
  264.       data[i].~VXIElement( );
  265.     }
  266.     // Now free the memory for the vector
  267.     free (data);
  268.   }
  269. }
  270. VXIVector::VXIVector (const VXIVector &v) : 
  271.   VXIValue (VALUE_VECTOR), badState(false), size(0), allocated(0), data(NULL)
  272. {
  273.   if ( v.size > 0 ) {
  274.     // Allocate just enough memory to store the vector we're copying, we're
  275.     // making a guess that they will just hold onto this clone instead of
  276.     // adding additional elements to it
  277.     data = (VXIElement *) malloc (v.size * sizeof (VXIElement));
  278.     if ( data == NULL ) {
  279.       badState = true;
  280.       return;
  281.     }
  282.     allocated = v.size; 
  283.     // Now copy the elements
  284.     while ( size < v.size ) {
  285.       // Set the new element using a new operator with placement syntax
  286.       // so it does the standard initialization of new( ) but skips the
  287.       // allocation, instead using the memory we provide
  288.       VXIElement *element = new (&data[size]) 
  289. VXIElement (v.data[size].GetKey( ),
  290.     VXIValueClone (v.data[size].GetValue( )));
  291.       size++;
  292.     }
  293.   }
  294. }
  295. VXIvalueResult VXIVector::Add (VXIValue *val)
  296. {
  297.   // Reallocate memory for the vector if required
  298.   if ( allocated <= size ) {
  299.     VXIElement *ptr = (VXIElement *)
  300.       realloc (data, (size + VXIVector::GROW_SIZE) * 
  301.        sizeof (VXIElement));
  302.     if ( ptr == NULL )
  303.       return VXIvalue_RESULT_OUT_OF_MEMORY;
  304.     
  305.     data = ptr;
  306.     allocated = size + VXIVector::GROW_SIZE;
  307.   }
  308.   // Set the new element using a new operator with placement syntax
  309.   // so it does the standard initialization of new( ) but skips the
  310.   // allocation, instead using the memory we provide
  311.   VXIElement *element = new (&data[size]) VXIElement (NULL, val);
  312.   size++;
  313.   return VXIvalue_RESULT_SUCCESS;
  314. }
  315. /**
  316.  * Create a String from a null-terminated character array
  317.  *
  318.  * @param   str   NULL-terminated character array
  319.  * @return        String with the specified value on success, 
  320.  *                NULL otherwise
  321.  */
  322. VXIVALUE_API VXIString *VXIStringCreate(const VXIchar *str)
  323. {
  324.   if ( str == NULL )
  325.     return NULL;
  326.   // Allocate the string
  327.   VXIString *s = new VXIString (str);
  328.   if (( s != NULL ) && ( s->GetValue( ) == NULL )) {
  329.     delete s;
  330.     s = NULL;
  331.   }
  332.   return s;
  333. }
  334. /**
  335.  * Create a String from a known-length character array
  336.  *
  337.  * @param   str   Character array (null characters may be embedded in the 
  338.  *                array)
  339.  * @param   len   Number of characters which will be copied.
  340.  * @return        String with the specified value on success, 
  341.  *                NULL otherwise
  342.  */
  343. VXIVALUE_API VXIString *VXIStringCreateN(const VXIchar *str, VXIunsigned len)
  344. {
  345.   if ( str == NULL )
  346.     return NULL;
  347.   // Allocate the string
  348.   VXIString *s = new VXIString (str, len);
  349.   if (( s != NULL ) && ( s->GetValue( ) == NULL )) {
  350.     delete s;
  351.     s = NULL;
  352.   }
  353.   return s;
  354. }
  355. /**
  356.  * String destructor
  357.  *
  358.  * @param   s   String to destroy
  359.  */
  360. VXIVALUE_API void VXIStringDestroy(VXIString **s)
  361. {
  362.   if (( s ) && ( *s ) && ( (*s)->GetType( ) == VALUE_STRING )) {
  363.     delete *s;
  364.     *s = NULL;
  365.   }
  366. }
  367. /**
  368.  * String clone
  369.  *
  370.  * Note: functionally redundant with VXIValueClone( ), but provided to
  371.  * reduce the need for C casts for this common operation
  372.  *
  373.  * @param    s   String to clone
  374.  * @return       Clone of the string on success, NULL otherwise
  375.  */
  376. VXIVALUE_API VXIString *VXIStringClone(const VXIString *s)
  377. {
  378.   if (( s == NULL ) || ( s->GetType( ) != VALUE_STRING ))
  379.     return NULL;
  380.   // Allocate the string
  381.   VXIString *str = new VXIString (*s);
  382.   if (( str != NULL ) && ( str->GetValue( ) == NULL )) {
  383.     delete str;
  384.     str = NULL;
  385.   }
  386.   return str;
  387. }
  388. /**
  389.  * Set the value of a String from a null-terminated character array
  390.  *
  391.  * Note: this functionality is provided to allow defining interfaces
  392.  * where the caller passes in a VXIString from VXIStringCreate( )
  393.  * (typically with an empty string as its value) with the interface
  394.  * changing that value to return a string as output. This avoids
  395.  * having to define interfaces where the client has to provide a
  396.  * fixed length buffer (and thus worry about "buffer too small" errors
  397.  * and complicated handling).
  398.  *
  399.  * @param   s     String to change the value of
  400.  * @param   str   NULL-terminated character array
  401.  * @return        VXIvalue_RESULT_SUCCESS on success 
  402.  */
  403. VXIVALUE_API VXIvalueResult VXIStringSetValue(VXIString      *s, 
  404.       const VXIchar  *str)
  405. {
  406.   if (( s == NULL ) || ( s->GetType( ) != VALUE_STRING ) || 
  407.       ( str == NULL ))
  408.     return VXIvalue_RESULT_INVALID_ARGUMENT;
  409.   s->SetValue (str);
  410.   if ( s->GetValue( ) == NULL )
  411.     return VXIvalue_RESULT_OUT_OF_MEMORY;
  412.   
  413.   return VXIvalue_RESULT_SUCCESS;
  414. }
  415. /**
  416.  * Get the value of a String
  417.  *
  418.  * @param   s     String to access
  419.  * @param   buf   Character buffer to copy the value into as a
  420.  *                NULL-terminated character array.  The buffer size must be
  421.  *                at least VXIStringLength() + 1.
  422.  * @param   len   Size of the buffer, in characters
  423.  * @return        Pointer to buf on success, NULL on failure (most likely
  424.  *                buffer too small) 
  425.  */
  426. VXIVALUE_API VXIchar *VXIStringValue(const VXIString  *s, 
  427.      VXIchar          *buf, 
  428.      VXIunsigned       len)
  429. {
  430.   if (( s == NULL ) || ( s->GetType( ) != VALUE_STRING ) || 
  431.       ( buf == NULL ))
  432.     return NULL;
  433.   // Make sure the buffer is large enough
  434.   if ( len < s->GetLength( ) + 1 ) return NULL;
  435.   const VXIchar * str = s->GetValue();
  436.   unsigned int length = s->GetLength();
  437.   for (unsigned int i = 0; i < length; ++i)
  438.     *(buf + i) = str[i];
  439.   *(buf + length) = '';
  440.   return buf;
  441. }
  442. /**
  443.  * Get direct access to the NULL-terminated character value
  444.  *
  445.  * Note: the returned buffer must never be modified, and is only
  446.  * provided for transient use (i.e. immediately logging it, comparing
  447.  * it, etc. rather than storing or returning the pointer for longer
  448.  * term access).
  449.  *
  450.  * @param   s   String to retrieve the data from
  451.  * @return      Pointer to the NULL-terminated character array retrieved
  452.  */
  453. VXIVALUE_API const VXIchar* VXIStringCStr(const VXIString *s)
  454. {
  455.   if (( s == NULL ) || ( s->GetType( ) != VALUE_STRING ))
  456.     return NULL;
  457.   return s->GetValue( );
  458. }
  459. /**
  460.  * Get the number of characters in a String's value
  461.  *
  462.  * Note: Add one byte for the NULL terminator when using this to determine
  463.  * the length of the array required for a VXIStringValue( ) call.
  464.  *
  465.  * @param   s   String to access
  466.  * @return      Length of the string, in characters
  467.  */
  468. VXIVALUE_API VXIunsigned VXIStringLength(const VXIString *s)
  469. {
  470.   if (( s == NULL ) || ( s->GetType( ) != VALUE_STRING ))
  471.     return 0;
  472.   return s->GetLength( );
  473. }
  474. /**
  475.  * Compares two Strings
  476.  *
  477.  * @param   s1   First String to compare
  478.  * @param   s2   Second String to compare
  479.  * @return       Returns a value that is less than, equal to, or greater
  480.  *               than zero depending on whether s1 is lexicographically
  481.  *               less than, equal to, or greater than s2
  482.  */
  483. VXIVALUE_API VXIint VXIStringCompare(const VXIString *s1, 
  484.      const VXIString *s2)
  485. {
  486.   if (( s1 == NULL ) || ( s1->GetType( ) != VALUE_STRING ))
  487.     return -1;
  488.   if (( s2 == NULL ) || ( s2->GetType( ) != VALUE_STRING ))
  489.     return 1;
  490.   return s1->Compare (*s2);
  491. }
  492. /**
  493.  * Compares a String to a NULL-terminated character array
  494.  *
  495.  * @param   str   String to compare
  496.  * @param   buf   NULL-terminated character array to compare
  497.  * @return        Returns a value that is less than, equal to, or greater
  498.  *                than zero depending on whether str is lexicographically
  499.  *                less than, equal to, or greater than buf
  500.  */
  501. VXIVALUE_API VXIint VXIStringCompareC(const VXIString *str, 
  502.       const VXIchar   *buf)
  503. {
  504.   if (( str == NULL ) || ( str->GetType( ) != VALUE_STRING ))
  505.     return -1;
  506.   if ( buf == NULL )
  507.     return 1;
  508.   return str->Compare (buf);
  509. }
  510. /**
  511.  * Create an empty Map
  512.  *
  513.  * @return   New map on success, NULL otherwise
  514.  */
  515. VXIVALUE_API VXIMap *VXIMapCreate(void)
  516. {
  517.   return new VXIMap;
  518. }
  519. /**
  520.  * Clear the content of the map and return an empty Map
  521.  *
  522.  * @return   None
  523.  */
  524. VXIVALUE_API void VXIMapClear(VXIMap *m)
  525. {  
  526.   if ( m  && ( m->GetType( ) == VALUE_MAP )) {
  527.     // Must manually deep destroy values
  528.     VXIElement *cur = m->head, *prev = NULL;
  529.     while( cur ) {
  530.       prev = cur;
  531.       cur = cur->GetNext( );
  532.       prev->DestroyValue( );
  533.       delete prev;  
  534.     }    
  535.     m->head = NULL;
  536.     m->size = 0;   
  537.   }   
  538. }
  539. /**
  540.  * Map destructor
  541.  *
  542.  * Note: this recursively destroys all the values contained within the
  543.  * Map, including all the values of Maps and Vectors stored
  544.  * within this map. However, for Ptr values the user is
  545.  * responsible for freeing the held memory if appropriate.
  546.  *
  547.  * @param m   Map to destroy 
  548.  */
  549. VXIVALUE_API void VXIMapDestroy(VXIMap **m)
  550. {
  551.   if (( m ) && ( *m ) && ( (*m)->GetType( ) == VALUE_MAP )) {
  552.     delete *m;
  553.     *m = NULL;
  554.   }
  555. }
  556. /**
  557.  * Map clone
  558.  *
  559.  * Recursively copies all values contained within the map,
  560.  * including all the values of Maps and Vectors stored within this
  561.  * map.
  562.  *
  563.  * Note: functionally redundant with VXIValueClone( ), but provided to
  564.  * reduce the need for C casts for this common operation
  565.  *
  566.  * @param    m   Map to clone
  567.  * @return       Clone of the Map on success, NULL otherwise 
  568.  */
  569. VXIVALUE_API VXIMap *VXIMapClone(const VXIMap *m)
  570. {
  571.   if (( m == NULL ) || ( m->GetType( ) != VALUE_MAP ))
  572.     return NULL;
  573.   VXIMap *theMap = new VXIMap (*m);
  574.   if (( theMap ) && ( theMap->badState )) {
  575.     delete theMap;
  576.     theMap = NULL;
  577.   }
  578.   return theMap;
  579. }
  580. /**
  581.  * Set a named property on an Map
  582.  *
  583.  * The value can be an Map so a tree can be constructed.
  584.  *
  585.  * If the property already exists, the existing value is first
  586.  * destroyed using VXIValueDestroy( ) (thus recursively deleting held
  587.  * values within it if it is an Map or Vector), then does the
  588.  * set operation with the new value.
  589.  *
  590.  * @param   m     Map to access
  591.  * @param   key   NULL terminated property name
  592.  * @param   val   Value to set the property to, ownership is passed
  593.  *                to the Map (a simple pointer copy is done), so on
  594.  *                success the user must not delete, modify, or otherwise
  595.  *                use this. Also be careful to not add a Map as a
  596.  *                property of itself (directly or indirectly), otherwise
  597.  *                infinite loops may occur on access or deletion.
  598.  * @return        VXIvalue_RESULT_SUCCESS on success
  599.  */
  600. VXIVALUE_API VXIvalueResult VXIMapSetProperty(VXIMap         *m, 
  601.       const VXIchar  *key,
  602.       VXIValue       *val)
  603. {
  604.   if (( m == NULL ) || ( m->GetType( ) != VALUE_MAP ) ||
  605.       ( key == NULL ) || ( key[0] == 0 ) || ( val == NULL ))
  606.     return VXIvalue_RESULT_INVALID_ARGUMENT;
  607.   // Create the element to set
  608.   VXIElement *element = new VXIElement (key, val);
  609.   if ( ! element ) {
  610.     return VXIvalue_RESULT_OUT_OF_MEMORY;
  611.   } else if ( element->GetKey( ).GetLength( ) == 0 ) {
  612.     element->DestroyValue( );
  613.     delete element;
  614.     return VXIvalue_RESULT_OUT_OF_MEMORY;
  615.   }
  616.   // Search for the insertion point for that element
  617.   VXIElement *cur = m->head, *prev = NULL;
  618.   while (( cur ) && ( *cur < *element )) {
  619.     prev = cur;
  620.     cur = cur->GetNext( );
  621.   }
  622.   // Replace any existing element with that key or insert it if
  623.   // completely new
  624.   if (( cur ) && ( *cur == *element )) {
  625.     // Replacement
  626.     element->SetNext (cur->GetNext( ));
  627.     if ( prev )
  628.       prev->SetNext (element);
  629.     else
  630.       m->head = element;
  631.     cur->DestroyValue( );
  632.     delete cur;
  633.   } else {
  634.     // Insertion
  635.     if ( cur ) {
  636.       element->SetNext (cur);
  637.     } else {
  638.     }
  639.     if ( prev ) {
  640.       prev->SetNext (element);
  641.     } else {
  642.       m->head = element;
  643.     }
  644.     m->size++;
  645.   }
  646.   return VXIvalue_RESULT_SUCCESS;
  647. }
  648. /**
  649.  * Get a named property from an Map
  650.  *
  651.  * The property value is returned for read-only access and is
  652.  * invalidated if the Map is modified. The client must clone it if
  653.  * they wish to perform modifications or wish to retain the value even
  654.  * afer modifying this Map.
  655.  *
  656.  * @param   m     Map to access
  657.  * @param   key   NULL terminated property name
  658.  * @return        On success the value of the property for read-only 
  659.  *                access (invalidated if the Map is modified), NULL
  660.  *                if the property was never set or was deleted 
  661.  */
  662. VXIVALUE_API const VXIValue *VXIMapGetProperty(const VXIMap    *m, 
  663.        const VXIchar   *key)
  664. {
  665.   if (( m == NULL ) || ( m->GetType( ) != VALUE_MAP ) || 
  666.       ( key == NULL ) || ( key[0] == 0 ))
  667.     return NULL;
  668.   // Search for that element
  669.   int rc;
  670.   VXIElement *cur = m->head;
  671.   while (( cur ) && ( (rc = cur->GetKey( ).Compare (key)) < 0 ))
  672.     cur = cur->GetNext( );
  673.   
  674.   // Return it if found
  675.   if (( cur ) && ( rc == 0 ))
  676.     return cur->GetValue( );
  677.   return NULL;
  678. }
  679. /**
  680.  * Delete a named property from an Map
  681.  *
  682.  * This does a VXIValueDestroy( ) on the value for the named property
  683.  * (thus recursively deleting held values within it if it is an Map
  684.  * or Vector). However, for Ptr properties the user is responsible for
  685.  * freeing the held memory if appropriate.
  686.  *
  687.  * @param   m     Map to access
  688.  * @param   key   NULL terminated property name
  689.  * @return        VXIvalue_RESULT_SUCCESS on success 
  690.  */
  691. VXIVALUE_API VXIvalueResult VXIMapDeleteProperty(VXIMap         *m, 
  692.  const VXIchar  *key)
  693. {
  694.   if (( m == NULL ) || ( m->GetType( ) != VALUE_MAP ) || 
  695.       ( key == NULL ) || ( key[0] == 0 ))
  696.     return VXIvalue_RESULT_INVALID_ARGUMENT;
  697.   // Search for that element
  698.   int rc;
  699.   VXIElement *cur = m->head, *prev = NULL;
  700.   while (( cur ) && ( (rc = cur->GetKey( ).Compare (key)) < 0 )) {
  701.     prev = cur;
  702.     cur = cur->GetNext( );
  703.   }
  704.   
  705.   // Delete it if found
  706.   if (( ! cur ) || ( rc != 0 ))
  707.     return VXIvalue_RESULT_FAILURE;
  708.   if ( prev )
  709.     prev->SetNext (cur->GetNext( ));
  710.   else
  711.     m->head = cur->GetNext( );
  712.   
  713.   cur->DestroyValue( );
  714.   delete cur;
  715.   m->size--;
  716.   return VXIvalue_RESULT_SUCCESS;
  717. }
  718. /**
  719.  * Return the number of properties for an Map
  720.  *
  721.  * Note: this only returns the number of properties that are direct
  722.  * children of the Map, it does not include the number of properties
  723.  * held in Maps and Vectors stored within this map.
  724.  *
  725.  * @param   m   Map to access
  726.  * @return      Number of properties stored in the Map
  727.  */
  728. VXIVALUE_API VXIunsigned VXIMapNumProperties(const VXIMap *m)
  729. {
  730.   if (( m == NULL ) || ( m->GetType( ) != VALUE_MAP ))
  731.     return 0;
  732.   return m->size;
  733. }
  734. /**
  735.  * Get the first property of an Map and an iterator
  736.  *
  737.  * Note: this is used to traverse all the properties within an map,
  738.  * there is no guarantee on what order the properties will be
  739.  * returned. The iterator must be eventually freed with
  740.  * VXIMapIteratorDestroy( ), and is invalidated if the Map is
  741.  * modified in any way.
  742.  *
  743.  * @param   m      Map to access
  744.  * @param   key    Set to point at the property name for read-only 
  745.  *                 access (must not be modified)                 
  746.  * @param   value  Set to point at the property value for read-only 
  747.  *                 access (must not be modified)
  748.  * @return         Pointer to an iterator that may be used to get
  749.  *                 additional properties via VXIMapGetNextProperty( ),
  750.  *                 or NULL on failure (typically no properties in the map)
  751.  */
  752. VXIVALUE_API 
  753. VXIMapIterator *VXIMapGetFirstProperty(const VXIMap     *m,
  754.        const VXIchar   **key,
  755.        const VXIValue  **value)
  756. {
  757.   if (( m == NULL ) || ( m->GetType( ) != VALUE_MAP ) ||
  758.       ( m->size == 0 ) || ( key == NULL ) || ( value == NULL ))
  759.     return NULL;
  760.   // Allocate an iterator map
  761.   VXIMapIterator *it = new VXIMapIterator (m);
  762.   if ( it == NULL )
  763.     return NULL;
  764.   
  765.   // Get the first property
  766.   it->GetKeyValue (key, value);
  767.   return it;
  768. }
  769. /**
  770.  * Get the next property of an Map based on an iterator
  771.  *
  772.  * Note: this is used to traverse all the properties within an map,
  773.  * there is no gaurantee on what order the properties will be
  774.  * returned.
  775.  *
  776.  * @param   it     Iterator used to access the map as obtained
  777.  *                 from VXIMapGetFirstProperty( ), this operation
  778.  *                 will advance the iterator to the next property on
  779.  *                 success
  780.  * @param   key    Set to point at the property name for read-only 
  781.  *                 access (must not be modified, invalidated if the
  782.  *                 Map is modified)                 
  783.  * @param   value  Set to point at the property value for read-only 
  784.  *                 access (must not be modified, invalidated if the
  785.  *                 Map is modified)
  786.  * @return         VXIvalue_RESULT_SUCCESS on success (property name 
  787.  *                 and value returned, iterator advanced), 
  788.  *                 VXIvalue_RESULT_FAILURE if there are no more properties
  789.  *                 to read, or a VXIvalueResult error code for severe errors
  790.  */
  791. VXIVALUE_API VXIvalueResult VXIMapGetNextProperty(VXIMapIterator  *it,
  792.   const VXIchar  **key,
  793.   const VXIValue **value)
  794. {
  795.   if (( it == NULL ) || ( key == NULL ) || ( value == NULL ))
  796.     return VXIvalue_RESULT_INVALID_ARGUMENT;
  797.   (*it)++;
  798.   return it->GetKeyValue (key, value);
  799. }
  800. /**
  801.  * Destroy an iterator
  802.  *
  803.  * @param   it     Iterator to destroy as obtained from 
  804.  *                 VXIMapGetFirstProperty( )
  805.  */
  806. VXIVALUE_API void VXIMapIteratorDestroy(VXIMapIterator **it)
  807. {
  808.   if (( it ) && ( *it )) {
  809.     delete *it;
  810.     *it = NULL;
  811.   }
  812. }
  813. /**
  814.  * Create an empty Vector
  815.  *
  816.  * @return   New vector on success, NULL otherwise
  817.  */
  818. VXIVALUE_API VXIVector *VXIVectorCreate(void)
  819. {
  820.   return new VXIVector;
  821. }
  822. /**
  823.  * Vector destructor
  824.  *
  825.  * Note: this recursively destroys all the values contained within the
  826.  * Vector, including all the values of Vectors stored within this
  827.  * vector. However, for Ptr values the user is responsible for
  828.  * freeing the held memory if appropriate.
  829.  *
  830.  * @param   v   Vector to destroy 
  831.  */
  832. VXIVALUE_API void VXIVectorDestroy(VXIVector **v)
  833. {
  834.   if (( v ) && ( *v ) && ( (*v)->GetType( ) == VALUE_VECTOR )) {
  835.     delete *v;
  836.     *v = NULL;
  837.   }
  838. }
  839. /**
  840.  * Vector clone
  841.  *
  842.  * Recursively copies all values contained within the vector,
  843.  * including all the values of Vectors and Maps stored within this
  844.  * vector.
  845.  *
  846.  * Note: functionally redundant with VXIValueClone( ), but provided to
  847.  * reduce the need for C casts for this common operation
  848.  *
  849.  * @param    v   Vector to clone
  850.  * @return Clone of the Vector on success, NULL otherwise */
  851. VXIVALUE_API VXIVector *VXIVectorClone(const VXIVector *v)
  852. {
  853.   if (( v == NULL ) || ( v->GetType( ) != VALUE_VECTOR ))
  854.     return NULL;
  855.   VXIVector *vec = new VXIVector (*v);
  856.   if (( vec ) && ( vec->badState )) {
  857.     delete vec;
  858.     vec = NULL;
  859.   }
  860.   return vec;
  861. }
  862. /**
  863.  * Adds an element to the end of the Vector
  864.  *
  865.  * The value can be a Vector so frames can be implemented.
  866.  *
  867.  * @param   v    Vector to access
  868.  * @param   val  Value to append to the vector, ownership is passed
  869.  *               to the Vector (a simple pointer copy is done), so on
  870.  *               success the user must not delete, modify, or otherwise
  871.  *               use this. Also be careful to not add a Vector as a
  872.  *               element of itself (directly or indirectly), otherwise
  873.  *               infinite loops may occur on access or deletion.
  874.  * @return       VXIvalue_RESULT_SUCCESS on success
  875.  */
  876. VXIVALUE_API VXIvalueResult VXIVectorAddElement(VXIVector      *v, 
  877. VXIValue       *val)
  878. {
  879.   if (( v == NULL ) || ( v->GetType( ) != VALUE_VECTOR ) || 
  880.       ( val == NULL ))
  881.     return VXIvalue_RESULT_INVALID_ARGUMENT;
  882.   return v->Add (val);
  883. }
  884. /**
  885.  * Set an indexed vector element
  886.  *
  887.  * Overwrites the specified element with the new value. The existing
  888.  * value is first destroyed using VXIValueDestroy( ) (thus recursively
  889.  * deleting held values within it if it is an Map or Vector), then
  890.  * does the set operation with the new value.
  891.  *
  892.  * The value can be a Vector so frames can be implemented.
  893.  *
  894.  * @param   v     Vector to access
  895.  * @param   n     Element index to set, it is an error to pass a
  896.  *                index that is greater then the number of values
  897.  *                currently in the vector
  898.  * @param   val   Value to set the element to, ownership is passed
  899.  *                to the Vector (a simple pointer copy is done), so on
  900.  *                success the user must not delete, modify, or otherwise
  901.  *                use this. Also be careful to not add a Vector as a
  902.  *                element of itself (directly or indirectly), otherwise
  903.  *                infinite loops may occur on access or deletion.
  904.  * @return        VXIvalue_RESULT_SUCCESS on success
  905.  */
  906. VXIVALUE_API VXIvalueResult VXIVectorSetElement(VXIVector      *v, 
  907. VXIunsigned     n, 
  908. VXIValue       *val)
  909. {
  910.   if (( v == NULL ) || ( v->GetType( ) != VALUE_VECTOR ) || 
  911.       ( val == NULL ) || ( n >= v->size ))
  912.     return VXIvalue_RESULT_INVALID_ARGUMENT;
  913.   // Delete the old one, we allocated the memory so we call an explicit
  914.   // destructor that doesn't free the memory
  915.   v->data[n].DestroyValue( );
  916.   v->data[n].~VXIElement( );
  917.   // Create the new one
  918.   VXIElement *element = new (&v->data[n]) VXIElement (NULL, val);
  919.   return VXIvalue_RESULT_SUCCESS;
  920. }
  921. /**
  922.  * Get an indexed vector element
  923.  *
  924.  * The element value is returned for read-only access and is
  925.  * invalidated if the Vector is modified. The client must clone it if
  926.  * they wish to perform modifications or wish to retain the value even
  927.  * after modifying this Vector.
  928.  *
  929.  * @param   v     Vector to access
  930.  * @param   n     Element index to set, it is an error to pass a
  931.  *                index that is greater or equal to then the number of values
  932.  *                currently in the vector (i.e. range is 0 to length-1)
  933.  * @return        On success the value of the property for read-only 
  934.  *                access (invalidated if the Vector is modified), NULL
  935.  *                on error 
  936.  */
  937. VXIVALUE_API const VXIValue *VXIVectorGetElement(const VXIVector *v, 
  938.  VXIunsigned      n)
  939. {
  940.   if (( v == NULL ) || ( v->GetType( ) != VALUE_VECTOR ) ||
  941.       ( n >= v->size ))
  942.     return NULL;
  943.   return v->data[n].GetValue( );
  944. }
  945. /**
  946.  * Return number of elements in a Vector
  947.  *
  948.  * This computes only the length of the Vector, elements within
  949.  * Vectors and Maps within it are not counted.
  950.  *
  951.  * @param   v    Vector to access
  952.  * @return       Number of elements stored in the Vector
  953.  */
  954. VXIVALUE_API VXIunsigned VXIVectorLength(const VXIVector *v)
  955. {
  956.   if (( v == NULL ) || ( v->GetType( ) != VALUE_VECTOR ))
  957.     return 0;
  958.   return v->size;
  959. }