| /*! |
| \file property.c |
| \brief Native property implementation. |
| |
| This module implements a native property, which is not public to any |
| provider programmer. It is used to implement various other data types |
| natively, such as instances, object-paths and args. |
| |
| It provides means to maintain linked lists of named properties including |
| functionality to add, remove, clone and release them. |
| |
| (C) Copyright IBM Corp. 2003 |
| |
| THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE |
| ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE |
| CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT. |
| |
| You can obtain a current copy of the Eclipse Public License from |
| http://www.opensource.org/licenses/eclipse-1.0.php |
| |
| \author Frank Scheffler |
| $Revision: 1.5 $ |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include "cmcidt.h" |
| #include "cmcift.h" |
| #include "cmcimacs.h" |
| #include "native.h" |
| |
| #ifdef DMALLOC |
| #include "dmalloc.h" |
| #endif |
| |
| //! Storage container for commonly needed data within native CMPI data types. |
| /*! |
| This structure is used to build linked lists of data containers as needed |
| for various native data types. |
| */ |
| /****************************************************************************/ |
| |
| static CMPIData __convert2CMPIData ( struct native_property * prop, |
| CMPIString ** propname ) |
| { |
| CMPIData result = { 0, CMPI_nullValue, {0} }; |
| |
| if ( prop != NULL ) { |
| result.type = prop->type; |
| result.state = prop->state; |
| result.value = prop->value; |
| |
| if ( propname ) { |
| *propname = native_new_CMPIString ( prop->name, |
| NULL ); |
| } |
| |
| } |
| |
| return result; |
| } |
| |
| |
| /** |
| * returns non-zero if already existant |
| */ |
| static int __addProperty ( struct native_property ** prop, |
| const char * name, |
| CMPIType type, |
| CMPIValueState state, |
| CMPIValue * value ) |
| { |
| CMPIStatus rc; |
| |
| if ( *prop == NULL ) { |
| struct native_property * tmp = *prop = |
| (struct native_property *) calloc ( 1, sizeof ( struct native_property ) ); |
| |
| tmp->qualifiers = NULL; |
| tmp->name = strdup ( name ); |
| tmp->type = type; |
| tmp->state = state; |
| |
| if ( type != CMPI_null && state != CMPI_nullValue) { |
| if ( type == CMPI_chars ) { |
| tmp->type = CMPI_string; |
| tmp->value.string = native_new_CMPIString ( (char *) value, &rc ); |
| } |
| else tmp->value = native_clone_CMPIValue ( type, value, &rc ); |
| } |
| else { |
| tmp->state = CMPI_nullValue; |
| tmp->value.uint64=0; |
| } |
| |
| return 0; |
| } |
| |
| return ( strcasecmp ( (*prop)->name, name ) == 0 || |
| __addProperty ( &( (*prop)->next ), name, type, state, value ) ); |
| } |
| |
| |
| /** |
| * returns -1 if non-existant |
| */ |
| static int __setProperty ( struct native_property * prop, |
| const char * name, |
| CMPIType type, |
| CMPIValue * value ) |
| { |
| CMPIStatus rc; |
| |
| if ( prop == NULL ) return -1; |
| |
| if ( strcasecmp ( prop->name, name ) == 0 ) { |
| |
| if ( ! ( prop->state & CMPI_nullValue ) ) |
| native_release_CMPIValue ( prop->type, &prop->value ); |
| |
| prop->type = type; |
| if ( type == CMPI_chars ) { |
| prop->type = CMPI_string; |
| prop->value.string = native_new_CMPIString ( (char *) value, &rc ); |
| } |
| |
| else { |
| if ( type != CMPI_null && value != NULL) |
| prop->value = native_clone_CMPIValue ( type, value, &rc ); |
| else prop->state = CMPI_nullValue; |
| } |
| return 0; |
| } |
| return __setProperty ( prop->next, name, type, value); |
| } |
| |
| |
| static struct native_property * __getProperty ( struct native_property * prop, |
| const char * name ) |
| { |
| if ( ! prop || ! name ) { |
| return NULL; |
| } |
| return ( strcasecmp ( prop->name, name ) == 0 )? |
| prop: __getProperty ( prop->next, name ); |
| } |
| |
| |
| static CMPIData __getDataProperty ( struct native_property * prop, |
| const char * name, |
| CMPIStatus * rc ) |
| { |
| struct native_property * p = __getProperty ( prop, name ); |
| |
| CMSetStatus( rc, ( p ) ? CMPI_RC_OK : CMPI_RC_ERR_NO_SUCH_PROPERTY ); |
| |
| return __convert2CMPIData ( p, NULL ); |
| } |
| |
| static struct native_qualifier *__getDataPropertyQualifiers ( struct native_property * prop, |
| const char * name, |
| CMPIStatus * rc ) |
| { |
| struct native_property * p = __getProperty ( prop, name ); |
| |
| CMSetStatus( rc, ( p ) ? CMPI_RC_OK : CMPI_RC_ERR_NO_SUCH_PROPERTY ); |
| |
| return p ? p->qualifiers : NULL; |
| } |
| |
| |
| static struct native_property * __getPropertyAt( struct native_property * prop, |
| unsigned int pos ) |
| { |
| if ( ! prop ) { |
| return NULL; |
| } |
| |
| return ( pos == 0 )? |
| prop: __getPropertyAt ( prop->next, --pos ); |
| } |
| |
| |
| static CMPIData __getDataPropertyAt ( struct native_property * prop, |
| unsigned int pos, |
| CMPIString ** propname, |
| CMPIStatus * rc ) |
| { |
| struct native_property * p = __getPropertyAt ( prop, pos ); |
| |
| CMSetStatus ( rc, ( p ) ? CMPI_RC_OK : CMPI_RC_ERR_NO_SUCH_PROPERTY ); |
| |
| return __convert2CMPIData ( p, propname ); |
| } |
| |
| |
| static CMPICount __getPropertyCount ( struct native_property * prop, |
| CMPIStatus * rc ) |
| { |
| CMPICount c = 0; |
| |
| CMSetStatus ( rc, CMPI_RC_OK ); |
| |
| while ( prop != NULL ) { |
| c++; |
| prop = prop->next; |
| } |
| |
| return c; |
| } |
| |
| |
| static void __release ( struct native_property * prop ) |
| { |
| struct native_property * next; |
| for ( ; prop; prop = next ) { |
| free ( prop->name ); |
| if(prop->state != CMPI_nullValue) |
| native_release_CMPIValue ( prop->type, &prop->value ); |
| qualifierFT.release(prop->qualifiers); |
| next=prop->next; |
| free ( prop ); |
| } |
| } |
| |
| |
| static struct native_property * __clone ( struct native_property * prop, |
| CMPIStatus * rc ) |
| { |
| struct native_property * result; |
| CMPIStatus tmp; |
| |
| if ( prop == NULL ) { |
| |
| CMSetStatus ( rc, CMPI_RC_OK ); |
| return NULL; |
| } |
| |
| result = (struct native_property * ) |
| calloc ( 1, sizeof ( struct native_property ) ); |
| |
| result->name = strdup ( prop->name ); |
| result->type = prop->type; |
| result->state = prop->state; |
| if (prop->state != CMPI_nullValue |
| && prop->state != CMPI_badValue) { |
| result->value = native_clone_CMPIValue ( prop->type, |
| &prop->value, |
| &tmp ); |
| if ( tmp.rc != CMPI_RC_OK ) { |
| |
| result->state = CMPI_nullValue; |
| } |
| } |
| result->qualifiers = qualifierFT.clone ( prop->qualifiers, rc ); |
| |
| result->next = __clone ( prop->next, rc ); |
| return result; |
| } |
| |
| |
| /** |
| * Global function table to access native_property helper functions. |
| */ |
| struct native_propertyFT const propertyFT = { |
| NATIVE_FT_VERSION, |
| __release, |
| __clone, |
| __getProperty, |
| __addProperty, |
| __setProperty, |
| __getDataProperty, |
| __getDataPropertyAt, |
| __getPropertyCount, |
| __getDataPropertyQualifiers |
| }; |
| |
| /****************************************************************************/ |
| |
| /*** Local Variables: ***/ |
| /*** mode: C ***/ |
| /*** c-basic-offset: 8 ***/ |
| /*** End: ***/ |