A modelling and serializer library for Microsoft Azure IoTHub client applications
Dependents: sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more
This library implements a serializer library to be used in projects involving Microsoft Azure IoT Hub connectivity. The code is replicated from https://github.com/Azure/azure-iot-sdks
Diff: schema.c
- Revision:
- 17:fa1bba4c6053
- Parent:
- 13:16e88f0cfa5f
- Child:
- 18:58b667752399
--- a/schema.c Thu Oct 20 17:08:06 2016 -0700 +++ b/schema.c Wed Nov 16 21:38:26 2016 -0800 @@ -15,64 +15,86 @@ DEFINE_ENUM_STRINGS(SCHEMA_RESULT, SCHEMA_RESULT_VALUES); -typedef struct PROPERTY_TAG +typedef struct SCHEMA_PROPERTY_HANDLE_DATA_TAG { const char* PropertyName; const char* PropertyType; -} PROPERTY; +} SCHEMA_PROPERTY_HANDLE_DATA; + +typedef struct SCHEMA_REPORTED_PROPERTY_HANDLE_DATA_TAG +{ + const char* reportedPropertyName; + const char* reportedPropertyType; +} SCHEMA_REPORTED_PROPERTY_HANDLE_DATA; -typedef struct SCHEMA_ACTION_ARGUMENT_TAG +typedef struct SCHEMA_DESIRED_PROPERTY_HANDLE_DATA_TAG +{ + pfOnDesiredProperty onDesiredProperty; + pfDesiredPropertyInitialize desiredPropertInitialize; + pfDesiredPropertyDeinitialize desiredPropertDeinitialize; + const char* desiredPropertyName; + const char* desiredPropertyType; + pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE; + size_t offset; +} SCHEMA_DESIRED_PROPERTY_HANDLE_DATA; + +typedef struct SCHEMA_ACTION_ARGUMENT_HANDLE_DATA_TAG { const char* Name; const char* Type; -} SCHEMA_ACTION_ARGUMENT; +} SCHEMA_ACTION_ARGUMENT_HANDLE_DATA; -typedef struct ACTION_TAG +typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG { const char* ActionName; size_t ArgumentCount; SCHEMA_ACTION_ARGUMENT_HANDLE* ArgumentHandles; -} ACTION; +} SCHEMA_ACTION_HANDLE_DATA; typedef struct MODEL_IN_MODEL_TAG { + pfOnDesiredProperty onDesiredProperty; /*is NULL if not specified or if the model in model is not WITH_DESIRED_PROPERTY*/ + size_t offset; /*offset of the model in model (offsetof)*/ const char* propertyName; SCHEMA_MODEL_TYPE_HANDLE modelHandle; } MODEL_IN_MODEL; -typedef struct MODEL_TYPE_TAG +typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG { + VECTOR_HANDLE desiredProperties; /*holds SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*/ const char* Name; SCHEMA_HANDLE SchemaHandle; SCHEMA_PROPERTY_HANDLE* Properties; size_t PropertyCount; + VECTOR_HANDLE reportedProperties; /*holds SCHEMA_REPORTED_PROPERTY_HANDLE*/ SCHEMA_ACTION_HANDLE* Actions; size_t ActionCount; VECTOR_HANDLE models; size_t DeviceCount; -} MODEL_TYPE; +} SCHEMA_MODEL_TYPE_HANDLE_DATA; -typedef struct STRUCT_TYPE_TAG +typedef struct SCHEMA_STRUCT_TYPE_HANDLE_DATA_TAG { const char* Name; SCHEMA_PROPERTY_HANDLE* Properties; size_t PropertyCount; -} STRUCT_TYPE; +} SCHEMA_STRUCT_TYPE_HANDLE_DATA; -typedef struct SCHEMA_TAG +typedef struct SCHEMA_HANDLE_DATA_TAG { + void* metadata; const char* Namespace; SCHEMA_MODEL_TYPE_HANDLE* ModelTypes; size_t ModelTypeCount; SCHEMA_STRUCT_TYPE_HANDLE* StructTypes; size_t StructTypeCount; -} SCHEMA; +} SCHEMA_HANDLE_DATA; static VECTOR_HANDLE g_schemas = NULL; static void DestroyProperty(SCHEMA_PROPERTY_HANDLE propertyHandle) { - PROPERTY* propertyType = (PROPERTY*)propertyHandle; + SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle; free((void*)propertyType->PropertyName); free((void*)propertyType->PropertyType); free(propertyType); @@ -80,7 +102,7 @@ static void DestroyActionArgument(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle) { - SCHEMA_ACTION_ARGUMENT* actionArgument = (SCHEMA_ACTION_ARGUMENT*)actionArgumentHandle; + SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle; if (actionArgument != NULL) { free((void*)actionArgument->Name); @@ -91,7 +113,7 @@ static void DestroyAction(SCHEMA_ACTION_HANDLE actionHandle) { - ACTION* action = (ACTION*)actionHandle; + SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; if (action != NULL) { size_t j; @@ -110,7 +132,7 @@ static void DestroyStruct(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle) { size_t i; - STRUCT_TYPE* structType = (STRUCT_TYPE*)structTypeHandle; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; if (structType != NULL) { for (i = 0; i < structType->PropertyCount; i++) @@ -127,8 +149,8 @@ static void DestroyModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) { - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; - size_t i; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + size_t i, nReportedProperties; free((void*)modelType->Name); modelType->Name = NULL; @@ -151,6 +173,27 @@ MODEL_IN_MODEL* temp = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); free((void*)temp->propertyName); } + + nReportedProperties = VECTOR_size(modelType->reportedProperties); + for (i = 0;i < nReportedProperties;i++) + { + SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->reportedProperties, i); + free((void*)reportedProperty->reportedPropertyName); + free((void*)reportedProperty->reportedPropertyType); + free(reportedProperty); + } + VECTOR_destroy(modelType->reportedProperties); + + size_t nDesiredProperties = VECTOR_size(modelType->desiredProperties); + for (i = 0;i < nDesiredProperties;i++) + { + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->desiredProperties, i); + free((void*)desiredProperty->desiredPropertyName); + free((void*)desiredProperty->desiredPropertyType); + free(desiredProperty); + } + VECTOR_destroy(modelType->desiredProperties); + VECTOR_clear(modelType->models); VECTOR_destroy(modelType->models); @@ -158,7 +201,7 @@ free(modelType); } -static SCHEMA_RESULT AddModelProperty(MODEL_TYPE* modelType, const char* name, const char* type) +static SCHEMA_RESULT AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType, const char* name, const char* type) { SCHEMA_RESULT result; @@ -177,7 +220,7 @@ /* Codes_SRS_SCHEMA_99_015:[The property name shall be unique per model, if the same property name is added twice to a model, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */ for (i = 0; i < modelType->PropertyCount; i++) { - PROPERTY* property = (PROPERTY*)modelType->Properties[i]; + SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i]; if (strcmp(property->PropertyName, name) == 0) { break; @@ -200,10 +243,10 @@ } else { - PROPERTY* newProperty; + SCHEMA_PROPERTY_HANDLE_DATA* newProperty; modelType->Properties = newProperties; - if ((newProperty = (PROPERTY*)malloc(sizeof(PROPERTY))) == NULL) + if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL) { /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */ result = SCHEMA_ERROR; @@ -264,31 +307,34 @@ static bool SchemaNamespacesMatch(const SCHEMA_HANDLE* handle, const char* schemaNamespace) { - const SCHEMA* schema = (SCHEMA*)*handle; + const SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)*handle; return (strcmp(schema->Namespace, schemaNamespace) == 0); } /* Codes_SRS_SCHEMA_99_001:[Schema_Create shall initialize a schema with a given namespace.] */ -SCHEMA_HANDLE Schema_Create(const char* schemaNamespace) +SCHEMA_HANDLE Schema_Create(const char* schemaNamespace, void* metadata) { - SCHEMA* result; - + SCHEMA_HANDLE_DATA* result; + /*Codes_SRS_SCHEMA_02_090: [ If metadata is NULL then Schema_Create shall fail and return NULL. ]*/ /* Codes_SRS_SCHEMA_99_004:[If schemaNamespace is NULL, Schema_Create shall fail.] */ - if (schemaNamespace == NULL) + if ( + (schemaNamespace == NULL)|| + (metadata == NULL) + ) { /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ + LogError("invalid arg const char* schemaNamespace=%p, void* metadata=%p",schemaNamespace, metadata); result = NULL; - LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); } else { - if (g_schemas == NULL && (g_schemas = VECTOR_create(sizeof(SCHEMA*) ) ) == NULL) + if (g_schemas == NULL && (g_schemas = VECTOR_create(sizeof(SCHEMA_HANDLE_DATA*) ) ) == NULL) { /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ result = NULL; LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); } - else if ((result = (SCHEMA*)malloc(sizeof(SCHEMA))) == NULL) + else if ((result = (SCHEMA_HANDLE_DATA*)malloc(sizeof(SCHEMA_HANDLE_DATA))) == NULL) { /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); @@ -314,6 +360,7 @@ result->ModelTypeCount = 0; result->StructTypes = NULL; result->StructTypeCount = 0; + result->metadata = metadata; } } @@ -359,7 +406,7 @@ else { /* Codes_SRS_SCHEMA_99_129: [Schema_GetSchemaNamespace shall return the namespace for the schema identified by schemaHandle.] */ - result = ((SCHEMA*)schemaHandle)->Namespace; + result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->Namespace; } return result; @@ -370,7 +417,7 @@ /* Codes_SRS_SCHEMA_99_006:[If the schemaHandle is NULL, Schema_Destroy shall do nothing.] */ if (schemaHandle != NULL) { - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; size_t i; /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */ @@ -391,7 +438,7 @@ free((void*)schema->Namespace); free(schema); - schema = (SCHEMA*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHandlesMatch, &schemaHandle); + schema = (SCHEMA_HANDLE_DATA*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHandlesMatch, &schemaHandle); if (schema != NULL) { VECTOR_erase(g_schemas, schema, 1); @@ -419,13 +466,13 @@ } else { - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; size_t nIndex; /* Codes_SRS_SCHEMA_07_190: [Schema_DestroyIfUnused shall iterate through the ModuleTypes objects and if all the DeviceCount variables 0 then it will delete the schemaHandle.] */ for (nIndex = 0; nIndex < schema->ModelTypeCount; nIndex++) { - MODEL_TYPE* modelType = (MODEL_TYPE*)schema->ModelTypes[nIndex]; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[nIndex]; if (modelType->DeviceCount > 0) break; } @@ -459,8 +506,8 @@ } else { - MODEL_TYPE* model = (MODEL_TYPE*)modelTypeHandle; - /* Codes_SRS_SCHEMA_07_188: [If the modelTypeHandle is nonNULL, Schema_AddDeviceRef shall increment the MODEL_TYPE DeviceCount variable.] */ + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /* Codes_SRS_SCHEMA_07_188: [If the modelTypeHandle is nonNULL, Schema_AddDeviceRef shall increment the SCHEMA_MODEL_TYPE_HANDLE_DATA DeviceCount variable.] */ model->DeviceCount++; result = SCHEMA_OK; } @@ -478,7 +525,7 @@ } else { - MODEL_TYPE* model = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; if (model->DeviceCount > 0) { /* Codes_SRS_SCHEMA_07_186: [On a nonNULL SCHEMA_MODEL_TYPE_HANDLE if the DeviceCount variable is > 0 then the variable will be decremented.] */ @@ -487,8 +534,8 @@ } else { - result = SCHEMA_DEVICE_COUNT_ZERO; - LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); +result = SCHEMA_DEVICE_COUNT_ZERO; +LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); } } return result; @@ -509,13 +556,13 @@ } else { - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_100: [Schema_CreateModelType shall return SCHEMA_DUPLICATE_ELEMENT if modelName already exists.] */ size_t i; for (i = 0; i < schema->ModelTypeCount; i++) { - MODEL_TYPE* model = (MODEL_TYPE*)(schema->ModelTypes[i]); + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)(schema->ModelTypes[i]); if (strcmp(model->Name, modelName) == 0) { break; @@ -540,10 +587,10 @@ } else { - MODEL_TYPE* modelType; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType; schema->ModelTypes = newModelTypes; - if ((modelType = (MODEL_TYPE*)malloc(sizeof(MODEL_TYPE))) == NULL) + if ((modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)malloc(sizeof(SCHEMA_MODEL_TYPE_HANDLE_DATA))) == NULL) { /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ @@ -559,27 +606,60 @@ } else { - modelType->PropertyCount = 0; - modelType->Properties = NULL; - modelType->ActionCount = 0; - modelType->Actions = NULL; - modelType->SchemaHandle = schemaHandle; - modelType->DeviceCount = 0; - modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL) ); - schema->ModelTypes[schema->ModelTypeCount] = modelType; - schema->ModelTypeCount++; + modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL)); + if (modelType->models == NULL) + { + LogError("unable to VECTOR_create"); + free((void*)modelType->Name); + free((void*)modelType); + result = NULL; + } + else + { + if ((modelType->reportedProperties = VECTOR_create(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE))) == NULL) + { + LogError("failed to VECTOR_create (reported properties)"); + VECTOR_destroy(modelType->models); + free((void*)modelType->Name); + free((void*)modelType); + result = NULL; - /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */ - result = (SCHEMA_MODEL_TYPE_HANDLE)modelType; + } + else + { + if ((modelType->desiredProperties = VECTOR_create(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE))) == NULL) + { + LogError("failure in VECTOR_create (desired properties)"); + VECTOR_destroy(modelType->reportedProperties); + VECTOR_destroy(modelType->models); + free((void*)modelType->Name); + free((void*)modelType); + result = NULL; + } + else + { + modelType->PropertyCount = 0; + modelType->Properties = NULL; + modelType->ActionCount = 0; + modelType->Actions = NULL; + modelType->SchemaHandle = schemaHandle; + modelType->DeviceCount = 0; + + schema->ModelTypes[schema->ModelTypeCount] = modelType; + schema->ModelTypeCount++; + /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */ + result = (SCHEMA_MODEL_TYPE_HANDLE)modelType; + } + } + } } /* If possible, reduce the memory of over allocation */ - if (result == NULL) + if ((result == NULL) &&(schema->ModelTypeCount>0)) { SCHEMA_MODEL_TYPE_HANDLE* oldModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * schema->ModelTypeCount); if (oldModelTypes == NULL) { - result = NULL; LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); } else @@ -606,7 +686,7 @@ else { /* Codes_SRS_SCHEMA_99_131: [Schema_GetSchemaForModelType returns the schema handle for a given model type.] */ - result = ((MODEL_TYPE*)modelTypeHandle)->SchemaHandle; + result = ((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle)->SchemaHandle; } return result; @@ -615,7 +695,90 @@ /* Codes_SRS_SCHEMA_99_011:[Schema_AddModelProperty shall add one property to the model type identified by modelTypeHandle.] */ SCHEMA_RESULT Schema_AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, const char* propertyType) { - return AddModelProperty((MODEL_TYPE*)modelTypeHandle, propertyName, propertyType); + return AddModelProperty((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle, propertyName, propertyType); +} + +static bool reportedPropertyExists(const void* element, const void* value) +{ + SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA**)element; + return (strcmp(reportedProperty->reportedPropertyName, value) == 0); +} + +SCHEMA_RESULT Schema_AddModelReportedProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName, const char* reportedPropertyType) +{ + SCHEMA_RESULT result; + /*Codes_SRS_SCHEMA_02_001: [ If modelTypeHandle is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_002: [ If reportedPropertyName is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_003: [ If reportedPropertyType is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + if ( + (modelTypeHandle == NULL) || + (reportedPropertyName == NULL) || + (reportedPropertyType == NULL) + ) + { + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p, const char* reportedPropertyType=%p", modelTypeHandle, reportedPropertyName, reportedPropertyType); + result = SCHEMA_INVALID_ARG; + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /*Codes_SRS_SCHEMA_02_004: [ If reportedPropertyName has already been added then Schema_AddModelReportedProperty shall fail and return SCHEMA_PROPERTY_ELEMENT_EXISTS. ]*/ + if (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName) != NULL) + { + LogError("unable to add reportedProperty %s because it already exists", reportedPropertyName); + result = SCHEMA_DUPLICATE_ELEMENT; + } + else + { + /*Codes_SRS_SCHEMA_02_005: [ Schema_AddModelReportedProperty shall record reportedPropertyName and reportedPropertyType. ]*/ + SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = (SCHEMA_REPORTED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA)); + if (reportedProperty == NULL) + { + /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("unable to malloc"); + result = SCHEMA_ERROR; + } + else + { + if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyName, reportedPropertyName) != 0) + { + /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("unable to mallocAndStrcpy_s"); + free(reportedProperty); + result = SCHEMA_ERROR; + } + else + { + if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyType, reportedPropertyType) != 0) + { + /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("unable to mallocAndStrcpy_s"); + free((void*)reportedProperty->reportedPropertyName); + free(reportedProperty); + result = SCHEMA_ERROR; + } + else + { + if (VECTOR_push_back(modelType->reportedProperties, &reportedProperty, 1) != 0) + { + /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("unable to VECTOR_push_back"); + free((void*)reportedProperty->reportedPropertyType); + free((void*)reportedProperty->reportedPropertyName); + free(reportedProperty); + result = SCHEMA_ERROR; + } + else + { + /*Codes_SRS_SCHEMA_02_007: [ Otherwise Schema_AddModelReportedProperty shall succeed and return SCHEMA_OK. ]*/ + result = SCHEMA_OK; + } + } + } + } + } + } + return result; } SCHEMA_ACTION_HANDLE Schema_CreateModelAction(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName) @@ -631,13 +794,13 @@ } else { - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; size_t i; /* Codes_SRS_SCHEMA_99_105: [The action name shall be unique per model, if the same action name is added twice to a model, Schema_CreateModelAction shall return NULL.] */ for (i = 0; i < modelType->ActionCount; i++) { - ACTION* action = (ACTION*)modelType->Actions[i]; + SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i]; if (strcmp(action->ActionName, actionName) == 0) { break; @@ -661,11 +824,11 @@ } else { - ACTION* newAction; + SCHEMA_ACTION_HANDLE_DATA* newAction; modelType->Actions = newActions; /* Codes_SRS_SCHEMA_99_103: [On success, Schema_CreateModelAction shall return a none-NULL SCHEMA_ACTION_HANDLE to the newly created action.] */ - if ((newAction = (ACTION*)malloc(sizeof(ACTION))) == NULL) + if ((newAction = (SCHEMA_ACTION_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_HANDLE_DATA))) == NULL) { /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/ result = NULL; @@ -724,14 +887,14 @@ } else { - ACTION* action = (ACTION*)actionHandle; + SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; /* Codes_SRS_SCHEMA_99_110: [The argument name shall be unique per action, if the same name is added twice to an action, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */ /* Codes_SRS_SCHEMA_99_111: [Schema_AddModelActionArgument shall accept arguments with different names of the same type.] */ size_t i; for (i = 0; i < action->ArgumentCount; i++) { - SCHEMA_ACTION_ARGUMENT* actionArgument = (SCHEMA_ACTION_ARGUMENT*)action->ArgumentHandles[i]; + SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)action->ArgumentHandles[i]; if (strcmp((actionArgument->Name), argumentName) == 0) { break; @@ -755,8 +918,8 @@ } else { - SCHEMA_ACTION_ARGUMENT* newActionArgument; - if ((newActionArgument = (SCHEMA_ACTION_ARGUMENT*)malloc(sizeof(SCHEMA_ACTION_ARGUMENT))) == NULL) + SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* newActionArgument; + if ((newActionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE_DATA))) == NULL) { /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */ result = SCHEMA_ERROR; @@ -824,12 +987,12 @@ else { size_t i; - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_036:[Schema_GetModelPropertyByName shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the model type identified by modelTypeHandle and matching the propertyName argument value.] */ for (i = 0; i < modelType->PropertyCount; i++) { - PROPERTY* modelProperty = (PROPERTY*)modelType->Properties[i]; + SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i]; if (strcmp(modelProperty->PropertyName, propertyName) == 0) { break; @@ -864,7 +1027,7 @@ else { /* Codes_SRS_SCHEMA_99_089: [Schema_GetModelPropertyCount shall provide the number of properties defined in the model type identified by modelTypeHandle.] */ - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_090: [The count shall be provided via the out argument propertyCount.]*/ *propertyCount = modelType->PropertyCount; @@ -876,10 +1039,90 @@ return result; } +SCHEMA_RESULT Schema_GetModelReportedPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* reportedPropertyCount) +{ + SCHEMA_RESULT result; + /*Codes_SRS_SCHEMA_02_008: [ If parameter modelTypeHandle is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_009: [ If parameter reportedPropertyCount is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ + if ( + (modelTypeHandle == NULL)|| + (reportedPropertyCount==NULL) + ) + { + LogError("SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* reportedPropertyCount=%p", modelTypeHandle, reportedPropertyCount); + result = SCHEMA_INVALID_ARG; + } + else + { + /*Codes_SRS_SCHEMA_02_010: [ Schema_GetModelReportedPropertyCount shall provide in reportedPropertyCount the number of reported properties and return SCHEMA_OK. ]*/ + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + *reportedPropertyCount = VECTOR_size(modelType->reportedProperties); + result = SCHEMA_OK; + } + return result; +} + +SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName) +{ + SCHEMA_REPORTED_PROPERTY_HANDLE result; + /*Codes_SRS_SCHEMA_02_011: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/ + /*Codes_SRS_SCHEMA_02_012: [ If argument reportedPropertyName is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/ + if( + (modelTypeHandle == NULL) || + (reportedPropertyName == NULL) + ) + { + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p", modelTypeHandle, reportedPropertyName); + result = NULL; + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /*Codes_SRS_SCHEMA_02_013: [ If reported property by the name reportedPropertyName exists then Schema_GetModelReportedPropertyByName shall succeed and return a non-NULL value. ]*/ + /*Codes_SRS_SCHEMA_02_014: [ Otherwise Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/ + if((result = VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName))==NULL) + { + LogError("a reported property with name \"%s\" does not exist", reportedPropertyName); + } + else + { + /*return as is*/ + } + } + return result; +} + +SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) +{ + SCHEMA_REPORTED_PROPERTY_HANDLE result; + /*Codes_SRS_SCHEMA_02_015: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/ + if (modelTypeHandle == NULL) + { + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%zu", modelTypeHandle, index); + result = NULL; + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + + /*Codes_SRS_SCHEMA_02_016: [ If a reported property with index equal to index exists then Schema_GetModelReportedPropertyByIndex shall succeed and return the non-NULL handle of that REPORTED_PROPERTY. ]*/ + /*Codes_SRS_SCHEMA_02_017: [ Otherwise Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/ + if ((result = VECTOR_element(modelType->reportedProperties, index)) == NULL) + { + LogError("index %zu is invalid", index); + } + else + { + /*return as is*/ + } + } + return result; +} + SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) { SCHEMA_PROPERTY_HANDLE result; - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_094: [Schema_GetModelProperty shall return NULL if the index specified is outside the valid range or if modelTypeHandle argument is NULL.] */ if ((modelTypeHandle == NULL) || @@ -912,12 +1155,12 @@ else { size_t i; - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_040:[Schema_GetModelActionByName shall return a non-NULL SCHEMA_ACTION_HANDLE corresponding to the model type identified by modelTypeHandle and matching the actionName argument value.] */ for (i = 0; i < modelType->ActionCount; i++) { - ACTION* modelAction = (ACTION*)modelType->Actions[i]; + SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i]; if (strcmp(modelAction->ActionName, actionName) == 0) { break; @@ -953,7 +1196,7 @@ else { /* Codes_SRS_SCHEMA_99_042:[Schema_GetModelActionCount shall provide the total number of actions defined in a model type identified by the modelTypeHandle.] */ - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_043:[The count shall be provided via the out argument actionCount.] */ *actionCount = modelType->ActionCount; @@ -968,7 +1211,7 @@ SCHEMA_ACTION_HANDLE Schema_GetModelActionByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) { SCHEMA_ACTION_HANDLE result; - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_048:[Schema_GetModelAction shall return NULL if the index specified is outside the valid range or if modelTypeHandle argument is NULL.] */ if ((modelType == NULL) || @@ -999,7 +1242,7 @@ } else { - ACTION* action = (ACTION*)actionHandle; + SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; /* Codes_SRS_SCHEMA_99_049:[Schema_GetModelActionName shall return the action name for a given action handle.] */ result = action->ActionName; } @@ -1020,7 +1263,7 @@ } else { - ACTION* modelAction = (ACTION*)actionHandle; + SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; /* Codes_SRS_SCHEMA_99_051:[Schema_GetModelActionArgumentCount shall provide the number of arguments for a specific schema action identified by actionHandle.] */ /* Codes_SRS_SCHEMA_99_052:[The argument count shall be provided via the out argument argumentCount.] */ @@ -1047,12 +1290,12 @@ else { /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */ - ACTION* modelAction = (ACTION*)actionHandle; + SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; size_t i; for (i = 0; i < modelAction->ArgumentCount; i++) { - SCHEMA_ACTION_ARGUMENT* actionArgument = (SCHEMA_ACTION_ARGUMENT*)modelAction->ArgumentHandles[i]; + SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)modelAction->ArgumentHandles[i]; if (strcmp(actionArgument->Name, actionArgumentName) == 0) { break; @@ -1078,7 +1321,7 @@ SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByIndex(SCHEMA_ACTION_HANDLE actionHandle, size_t argumentIndex) { SCHEMA_ACTION_ARGUMENT_HANDLE result; - ACTION* modelAction = (ACTION*)actionHandle; + SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; /* Codes_SRS_SCHEMA_99_056:[Schema_GetModelActionArgument shall return NULL if the index specified is outside the valid range or if the actionHandle argument is NULL.] */ if ((actionHandle == NULL) || @@ -1108,7 +1351,7 @@ else { /* Codes_SRS_SCHEMA_99_113: [Schema_GetActionArgumentName shall return the argument name identified by the actionArgumentHandle.] */ - SCHEMA_ACTION_ARGUMENT* actionArgument = (SCHEMA_ACTION_ARGUMENT*)actionArgumentHandle; + SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle; result = actionArgument->Name; } return result; @@ -1126,7 +1369,7 @@ else { /* Codes_SRS_SCHEMA_99_115: [Schema_GetActionArgumentType shall return the argument type identified by the actionArgumentHandle.] */ - SCHEMA_ACTION_ARGUMENT* actionArgument = (SCHEMA_ACTION_ARGUMENT*)actionArgumentHandle; + SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle; result = actionArgument->Type; } return result; @@ -1135,7 +1378,7 @@ SCHEMA_STRUCT_TYPE_HANDLE Schema_CreateStructType(SCHEMA_HANDLE schemaHandle, const char* typeName) { SCHEMA_STRUCT_TYPE_HANDLE result; - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_060:[If any of the arguments is NULL, Schema_CreateStructType shall return NULL.] */ if ((schema == NULL) || @@ -1146,13 +1389,13 @@ } else { - STRUCT_TYPE* structType; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType; size_t i; /* Codes_SRS_SCHEMA_99_061:[If a struct type with the same name already exists, Schema_CreateStructType shall return NULL.] */ for (i = 0; i < schema->StructTypeCount; i++) { - structType = (STRUCT_TYPE*)schema->StructTypes[i]; + structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i]; if (strcmp(structType->Name, typeName) == 0) { break; @@ -1176,7 +1419,7 @@ else { schema->StructTypes = newStructTypes; - if ((structType = (STRUCT_TYPE*)malloc(sizeof(STRUCT_TYPE))) == NULL) + if ((structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)malloc(sizeof(SCHEMA_STRUCT_TYPE_HANDLE_DATA))) == NULL) { /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */ result = NULL; @@ -1235,7 +1478,7 @@ else { /* Codes_SRS_SCHEMA_99_135: [Schema_GetStructTypeName shall return the name of a struct type identified by the structTypeHandle argument.] */ - result = ((STRUCT_TYPE*)structTypeHandle)->Name; + result = ((SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle)->Name; } return result; @@ -1255,7 +1498,7 @@ else { /* Codes_SRS_SCHEMA_99_137: [Schema_GetStructTypeCount shall provide the number of structs defined in the schema identified by schemaHandle.] */ - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_138: [The count shall be provided via the out argument structTypeCount.] */ *structTypeCount = schema->StructTypeCount; /* Codes_SRS_SCHEMA_99_139: [On success, Schema_GetStructTypeCount shall return SCHEMA_OK.] */ @@ -1267,8 +1510,8 @@ SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByName(SCHEMA_HANDLE schemaHandle, const char* name) { - SCHEMA_ACTION_HANDLE result; - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_STRUCT_TYPE_HANDLE result; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_069:[Schema_GetStructTypeByName shall return NULL if unable to find a matching struct or if any of the arguments are NULL.] */ if ((schemaHandle == NULL) || @@ -1284,7 +1527,7 @@ /* Codes_SRS_SCHEMA_99_068:[Schema_GetStructTypeByName shall return a non-NULL handle corresponding to the struct type identified by the structTypeName in the schemaHandle schema.] */ for (i = 0; i < schema->StructTypeCount; i++) { - STRUCT_TYPE* structType = (STRUCT_TYPE*)schema->StructTypes[i]; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i]; if (strcmp(structType->Name, name) == 0) { break; @@ -1309,7 +1552,7 @@ SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByIndex(SCHEMA_HANDLE schemaHandle, size_t index) { SCHEMA_STRUCT_TYPE_HANDLE result; - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_143: [Schema_GetStructTypeByIndex shall return NULL if the index specified is outside the valid range or if schemaHandle argument is NULL.] */ /* Codes_SRS_SCHEMA_99_142: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */ @@ -1344,12 +1587,12 @@ else { size_t i; - STRUCT_TYPE* structType = (STRUCT_TYPE*)structTypeHandle; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; /* Codes_SRS_SCHEMA_99_074:[The property name shall be unique per struct type, if the same property name is added twice to a struct type, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */ for (i = 0; i < structType->PropertyCount; i++) { - PROPERTY* property = (PROPERTY*)structType->Properties[i]; + SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i]; if (strcmp(property->PropertyName, propertyName) == 0) { break; @@ -1371,10 +1614,10 @@ } else { - PROPERTY* newProperty; + SCHEMA_PROPERTY_HANDLE_DATA* newProperty; structType->Properties = newProperties; - if ((newProperty = (PROPERTY*)malloc(sizeof(PROPERTY))) == NULL) + if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL) { result = SCHEMA_ERROR; LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); @@ -1440,11 +1683,11 @@ else { size_t i; - STRUCT_TYPE* structType = (STRUCT_TYPE*)structTypeHandle; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; for (i = 0; i < structType->PropertyCount; i++) { - PROPERTY* modelProperty = (PROPERTY*)structType->Properties[i]; + SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i]; if (strcmp(modelProperty->PropertyName, propertyName) == 0) { break; @@ -1480,7 +1723,7 @@ } else { - STRUCT_TYPE* structType = (STRUCT_TYPE*)structTypeHandle; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; /* Codes_SRS_SCHEMA_99_077: [Schema_GetStructTypePropertyCount shall provide the total number of properties defined in a struct type identified by structTypeHandle. The value is provided via the out argument propertyCount.] */ /* Codes_SRS_SCHEMA_99_081: [The count shall be provided via the out argument propertyCount.] */ @@ -1496,7 +1739,7 @@ SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByIndex(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t index) { SCHEMA_PROPERTY_HANDLE result; - STRUCT_TYPE* structType = (STRUCT_TYPE*)structTypeHandle; + SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; /* Codes_SRS_SCHEMA_99_083: [Schema_ GetStructTypeProperty shall return NULL if the index specified is outside the valid range, if structTypeHandle argument is NULL] */ if ((structTypeHandle == NULL) || @@ -1527,7 +1770,7 @@ } else { - PROPERTY* propertyType = (PROPERTY*)propertyHandle; + SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle; /* Codes_SRS_SCHEMA_99_085: [Schema_GetPropertyName shall return the property name identified by the propertyHandle.] */ result = propertyType->PropertyName; @@ -1548,7 +1791,7 @@ } else { - PROPERTY* modelProperty = (PROPERTY*)propertyHandle; + SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle; /* Codes_SRS_SCHEMA_99_087: [Schema_GetPropertyType shall return the property type identified by the propertyHandle.] */ result = modelProperty->PropertyType; @@ -1570,7 +1813,7 @@ else { /* Codes_SRS_SCHEMA_99_120: [Schema_GetModelCount shall provide the number of models defined in the schema identified by schemaHandle.] */ - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_121: [The count shall be provided via the out argument modelCount.] */ *modelCount = schema->ModelTypeCount; /* Codes_SRS_SCHEMA_99_122: [On success, Schema_GetModelCount shall return SCHEMA_OK.] */ @@ -1593,11 +1836,11 @@ else { /* Codes_SRS_SCHEMA_99_124: [Schema_GetModelByName shall return a non-NULL SCHEMA_MODEL_TYPE_HANDLE corresponding to the model identified by schemaHandle and matching the modelName argument value.] */ - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; size_t i; for (i = 0; i < schema->ModelTypeCount; i++) { - MODEL_TYPE* modelType = (MODEL_TYPE*)schema->ModelTypes[i]; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[i]; if (strcmp(modelName, modelType->Name)==0) { break; @@ -1619,7 +1862,7 @@ SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByIndex(SCHEMA_HANDLE schemaHandle, size_t index) { SCHEMA_MODEL_TYPE_HANDLE result; - SCHEMA* schema = (SCHEMA*)schemaHandle; + SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; /* Codes_SRS_SCHEMA_99_128: [Schema_GetModelByIndex shall return NULL if the index specified is outside the valid range or if schemaHandle argument is NULL.] */ /* Codes_SRS_SCHEMA_99_127: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */ @@ -1649,14 +1892,14 @@ } else { - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; result = modelType->Name; } return result; } /*Codes_SRS_SCHEMA_99_163: [Schema_AddModelModel shall insert an existing model, identified by the handle modelType, into the existing model identified by modelTypeHandle under a property having the name propertyName.]*/ -SCHEMA_RESULT Schema_AddModelModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, SCHEMA_MODEL_TYPE_HANDLE modelType) +SCHEMA_RESULT Schema_AddModelModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, SCHEMA_MODEL_TYPE_HANDLE modelType, size_t offset, pfOnDesiredProperty onDesiredProperty) { SCHEMA_RESULT result; /*Codes_SRS_SCHEMA_99_165: [If any of the parameters is NULL then Schema_AddModelModel shall return SCHEMA_INVALID_ARG.]*/ @@ -1671,9 +1914,11 @@ } else { - MODEL_TYPE* parentModel = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* parentModel = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; MODEL_IN_MODEL temp; temp.modelHandle = modelType; + temp.offset = offset; + temp.onDesiredProperty = onDesiredProperty; if (mallocAndStrcpy_s((char**)&(temp.propertyName), propertyName) != 0) { result = SCHEMA_ERROR; @@ -1689,6 +1934,7 @@ else { /*Codes_SRS_SCHEMA_99_164: [If the function succeeds, then the return value shall be SCHEMA_OK.]*/ + result = SCHEMA_OK; } } @@ -1710,7 +1956,7 @@ } else { - MODEL_TYPE* model = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /*Codes_SRS_SCHEMA_99_167: [Schema_GetModelModelCount shall return in parameter modelCount the number of models inserted in the model identified by parameter modelTypeHandle.]*/ *modelCount = VECTOR_size(model->models); /*SRS_SCHEMA_99_168: [If the function succeeds, it shall return SCHEMA_OK.]*/ @@ -1740,7 +1986,7 @@ } else { - MODEL_TYPE* model = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /*Codes_SRS_SCHEMA_99_170: [Schema_GetModelModelByName shall return a handle to the model identified by the property with the name propertyName in the model identified by the handle modelTypeHandle.]*/ /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/ void* temp = VECTOR_find_if(model->models, matchModelName, propertyName); @@ -1757,6 +2003,101 @@ return result; } +size_t Schema_GetModelModelByName_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) +{ + size_t result; + /*Codes_SRS_SCHEMA_02_053: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/ + /*Codes_SRS_SCHEMA_02_054: [ If propertyName is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/ + if ( + (modelTypeHandle == NULL) || + (propertyName == NULL) + ) + { + /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/ + result = 0; + LogError("error SCHEMA_INVALID_ARG"); + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /*Codes_SRS_SCHEMA_02_056: [ If propertyName is not a model then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/ + void* temp = VECTOR_find_if(model->models, matchModelName, propertyName); + if (temp == NULL) + { + LogError("specified propertyName not found (%s)", propertyName); + result = 0; + } + else + { + /*Codes_SRS_SCHEMA_02_055: [ Otherwise Schema_GetModelModelByName_Offset shall succeed and return the offset. ]*/ + result = ((MODEL_IN_MODEL*)temp)->offset; + } + } + return result; +} + +pfOnDesiredProperty Schema_GetModelModelByName_OnDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) +{ + pfOnDesiredProperty result; + /*Codes_SRS_SCHEMA_02_086: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/ + /*Codes_SRS_SCHEMA_02_087: [ If propertyName is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/ + if ( + (modelTypeHandle == NULL) || + (propertyName == NULL) + ) + { + result = NULL; + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* propertyName=%p",modelTypeHandle, propertyName); + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + void* temp = VECTOR_find_if(model->models, matchModelName, propertyName); + if (temp == NULL) + { + LogError("specified propertyName not found (%s)", propertyName); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_089: [ Otherwise Schema_GetModelModelByName_OnDesiredProperty shall return the desired property callback. ]*/ + result = ((MODEL_IN_MODEL*)temp)->onDesiredProperty; + } + } + return result; + +} + +size_t Schema_GetModelModelByIndex_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) +{ + size_t result; + /*Codes_SRS_SCHEMA_02_057: [ If modelTypeHandle is NULL then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/ + if ( + (modelTypeHandle == NULL) + ) + { + result = 0; + LogError("error SCHEMA_INVALID_ARG"); + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /*Codes_SRS_SCHEMA_02_058: [ If index is not valid then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/ + void* temp = VECTOR_element(model->models, index); + if (temp == 0) + { + LogError("specified index [out of bounds] (%zu)", index); + result = 0; + } + else + { + /*Codes_SRS_SCHEMA_02_059: [ Otherwise Schema_GetModelModelByIndex_Offset shall succeed and return the offset. ]*/ + result = ((MODEL_IN_MODEL*)temp)->offset; + } + } + return result; +} + SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) { SCHEMA_MODEL_TYPE_HANDLE result; @@ -1770,7 +2111,7 @@ } else { - MODEL_TYPE* model = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; size_t nModelsInModel; /*Codes_SRS_SCHEMA_99_172: [ Schema_GetModelModelyByIndex shall return a handle to the "index"th model inserted in the model identified by the parameter modelTypeHandle.]*/ /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/ @@ -1798,7 +2139,7 @@ } else { - MODEL_TYPE* model = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; size_t nModelsInModel; /*Codes_SRS_SCHEMA_99_175: [Schema_GetModelModelPropertyNameByIndex shall return the name of the property for the "index"th model in the model identified by modelTypeHandle parameter.]*/ /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/ @@ -1843,7 +2184,7 @@ const char* endPos; size_t i; size_t modelCount; - MODEL_TYPE* modelType = (MODEL_TYPE*)modelTypeHandle; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; /* Codes_SRS_SCHEMA_99_179: [The propertyPath shall be assumed to be in the format model1/model2/.../propertyName.] */ slashPos = strchr(propertyPath, '/'); @@ -1888,7 +2229,7 @@ /* Codes_SRS_SCHEMA_99_178: [The argument propertyPath shall be used to find the leaf property.] */ for (i = 0; i < modelType->PropertyCount; i++) { - PROPERTY* property = (PROPERTY*)modelType->Properties[i]; + SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i]; if ((strncmp(property->PropertyName, propertyPath, endPos - propertyPath) == 0) && (strlen(property->PropertyName) == (size_t)(endPos - propertyPath))) { @@ -1906,3 +2247,618 @@ return result; } + +bool Schema_ModelReportedPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyPath) +{ + bool result; + + /*Codes_SRS_SCHEMA_02_018: [ If argument modelTypeHandle is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/ + /*Codes_SRS_SCHEMA_02_019: [ If argument reportedPropertyPath is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/ + if ((modelTypeHandle == NULL) || + (reportedPropertyPath == NULL)) + { + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyPath=%s", modelTypeHandle, reportedPropertyPath); + result = false; + } + else + { + const char* slashPos; + + /*Codes_SRS_SCHEMA_02_021: [ If the reported property cannot be found Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/ + result = false; + + /*Codes_SRS_SCHEMA_02_020: [ reportedPropertyPath shall be assumed to be in the format model1/model2/.../reportedPropertyName. ]*/ + if (*reportedPropertyPath == '/') + { + reportedPropertyPath++; + } + + do + { + const char* endPos; + size_t i; + size_t modelCount; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + + slashPos = strchr(reportedPropertyPath, '/'); + endPos = slashPos; + if (endPos == NULL) + { + endPos = &reportedPropertyPath[strlen(reportedPropertyPath)]; + } + + modelCount = VECTOR_size(modelType->models); + for (i = 0; i < modelCount; i++) + { + MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); + if ((strncmp(childModel->propertyName, reportedPropertyPath, endPos - reportedPropertyPath) == 0) && + (strlen(childModel->propertyName) == (size_t)(endPos - reportedPropertyPath))) + { + /* found */ + modelTypeHandle = childModel->modelHandle; + break; + } + } + + if (i < modelCount) + { + /* model found, check if there is more in the path */ + if (slashPos == NULL) + { + /*Codes_SRS_SCHEMA_02_022: [ If the path reportedPropertyPath points to a sub-model, Schema_ModelReportedPropertyByPathExists shall succeed and true. ]*/ + /* this is the last one, so this is the thing we were looking for */ + result = true; + break; + } + else + { + /* continue looking, there's more */ + reportedPropertyPath = slashPos + 1; + } + } + else + { + /* no model found, let's see if this is a property */ + result = (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyPath) != NULL); + if (!result) + { + LogError("no such reported property \"%s\"", reportedPropertyPath); + } + break; + } + } while (slashPos != NULL); + } + + return result; +} + +static bool desiredPropertyExists(const void* element, const void* value) +{ + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA**)element; + return (strcmp(desiredProperty->desiredPropertyName, value) == 0); +} + +SCHEMA_RESULT Schema_AddModelDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName, const char* desiredPropertyType, pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE, pfDesiredPropertyInitialize desiredPropertyInitialize, pfDesiredPropertyDeinitialize desiredPropertyDeinitialize, size_t offset, pfOnDesiredProperty onDesiredProperty) +{ + SCHEMA_RESULT result; + /*Codes_SRS_SCHEMA_02_024: [ If modelTypeHandle is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_025: [ If desiredPropertyName is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_026: [ If desiredPropertyType is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_048: [ If desiredPropertyFromAGENT_DATA_TYPE is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_049: [ If desiredPropertyInitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_050: [ If desiredPropertyDeinitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ + if ( + (modelTypeHandle == NULL) || + (desiredPropertyName == NULL) || + (desiredPropertyType == NULL) || + (desiredPropertyFromAGENT_DATA_TYPE == NULL) || + (desiredPropertyInitialize == NULL) || + (desiredPropertyDeinitialize== NULL) + ) + { + LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p, const char* desiredPropertyType=%p, pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE=%p, pfDesiredPropertyInitialize desiredPropertyInitialize=%p, pfDesiredPropertyDeinitialize desiredPropertyDeinitialize=%p, size_t offset=%zu", + modelTypeHandle, desiredPropertyName, desiredPropertyType, desiredPropertyFromAGENT_DATA_TYPE, desiredPropertyInitialize, desiredPropertyDeinitialize, offset); + result = SCHEMA_INVALID_ARG; + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /*Codes_SRS_SCHEMA_02_027: [ Schema_AddModelDesiredProperty shall add the desired property given by the name desiredPropertyName and the type desiredPropertyType to the collection of existing desired properties. ]*/ + if (VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName) != NULL) + { + /*Codes_SRS_SCHEMA_02_047: [ If the desired property already exists, then Schema_AddModelDesiredProperty shall fail and return SCHEMA_DUPLICATE_ELEMENT. ]*/ + LogError("unable to Schema_AddModelDesiredProperty because a desired property with the same name (%s) already exists", desiredPropertyName); + result = SCHEMA_DUPLICATE_ELEMENT; + } + else + { + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA)); + if (desiredProperty == NULL) + { + /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in malloc"); + result = SCHEMA_ERROR; + } + else + { + if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyName, desiredPropertyName) != 0) + { + /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in mallocAndStrcpy_s"); + free(desiredProperty); + result = SCHEMA_ERROR; + } + else + { + if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyType, desiredPropertyType) != 0) + { + /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in mallocAndStrcpy_s"); + free((void*)desiredProperty->desiredPropertyName); + free(desiredProperty); + result = SCHEMA_ERROR; + } + else + { + if (VECTOR_push_back(handleData->desiredProperties, &desiredProperty, 1) != 0) + { + /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ + LogError("failure in VECTOR_push_back"); + free((void*)desiredProperty->desiredPropertyType); + free((void*)desiredProperty->desiredPropertyName); + free(desiredProperty); + result = SCHEMA_ERROR; + } + else + { + /*Codes_SRS_SCHEMA_02_029: [ Otherwise, Schema_AddModelDesiredProperty shall succeed and return SCHEMA_OK. ]*/ + desiredProperty->desiredPropertyFromAGENT_DATA_TYPE = desiredPropertyFromAGENT_DATA_TYPE; + desiredProperty->desiredPropertInitialize = desiredPropertyInitialize; + desiredProperty->desiredPropertDeinitialize = desiredPropertyDeinitialize; + desiredProperty->onDesiredProperty = onDesiredProperty; /*NULL is a perfectly fine value*/ + desiredProperty->offset = offset; + result = SCHEMA_OK; + } + } + } + } + } + } + return result; +} + + +SCHEMA_RESULT Schema_GetModelDesiredPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* desiredPropertyCount) +{ + SCHEMA_RESULT result; + /*Codes_SRS_SCHEMA_02_030: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_031: [ If desiredPropertyCount is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ + if ( + (modelTypeHandle == NULL) || + (desiredPropertyCount == NULL) + ) + { + LogError("invalid arg: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* desiredPropertyCount=%p", modelTypeHandle, desiredPropertyCount); + result = SCHEMA_INVALID_ARG; + } + else + { + /*Codes_SRS_SCHEMA_02_032: [ Otherwise, Schema_GetModelDesiredPropertyCount shall succeed and write in desiredPropertyCount the existing number of desired properties. ]*/ + SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + *desiredPropertyCount = VECTOR_size(handleData->desiredProperties); + result = SCHEMA_OK; + } + return result; +} + +SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName) +{ + SCHEMA_DESIRED_PROPERTY_HANDLE result; + /*Codes_SRS_SCHEMA_02_034: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/ + /*Codes_SRS_SCHEMA_02_035: [ If desiredPropertyName is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/ + if ( + (modelTypeHandle == NULL) || + (desiredPropertyName == NULL) + ) + { + LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p", modelTypeHandle, desiredPropertyName); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_036: [ If a desired property having the name desiredPropertyName exists then Schema_GetModelDesiredPropertyByName shall succeed and return a non-NULL value. ]*/ + /*Codes_SRS_SCHEMA_02_037: [ Otherwise, Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/ + SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName); + if (temp == NULL) + { + LogError("no such desired property by name %s", desiredPropertyName); + result = NULL; + } + else + { + result = *temp; + } + } + return result; +} + +SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) +{ + SCHEMA_DESIRED_PROPERTY_HANDLE result; + /*Codes_SRS_SCHEMA_02_038: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/ + if (modelTypeHandle == NULL) + { + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%p", modelTypeHandle, index); + result = NULL; + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + /*Codes_SRS_SCHEMA_02_039: [ If index is outside the range for existing indexes of desire properties, then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/ + /*Codes_SRS_SCHEMA_02_040: [ Otherwise, Schema_GetModelDesiredPropertyByIndex shall succeed and return a non-NULL value. ]*/ + SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_element(handleData->desiredProperties, index); + if (temp == NULL) + { + LogError("VECTOR_element produced NULL (likely out of bounds index)"); + result = NULL; + } + else + { + result = *temp; + } + } + return result; +} + +bool Schema_ModelDesiredPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyPath) +{ + bool result; + /*Codes_SRS_SCHEMA_02_041: [ If modelTypeHandle is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/ + /*Codes_SRS_SCHEMA_02_042: [ If desiredPropertyPath is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/ + if ( + (modelTypeHandle == NULL) || + (desiredPropertyPath == NULL) + ) + { + LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyPath=%p", modelTypeHandle, desiredPropertyPath); + result = false; + } + else + { + const char* slashPos; + + /*Codes_SRS_SCHEMA_02_044: [ If the desired property cannot be found Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/ + result = false; + + /*Codes_SRS_SCHEMA_02_043: [ desiredPropertyPath shall be assumed to be in the format model1/model2/.../desiredPropertyName. ]*/ + if (*desiredPropertyPath == '/') + { + desiredPropertyPath++; + } + + do + { + const char* endPos; + size_t i; + size_t modelCount; + SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + + slashPos = strchr(desiredPropertyPath, '/'); + endPos = slashPos; + if (endPos == NULL) + { + endPos = &desiredPropertyPath[strlen(desiredPropertyPath)]; + } + + modelCount = VECTOR_size(modelType->models); + for (i = 0; i < modelCount; i++) + { + MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); + if ((strncmp(childModel->propertyName, desiredPropertyPath, endPos - desiredPropertyPath) == 0) && + (strlen(childModel->propertyName) == (size_t)(endPos - desiredPropertyPath))) + { + /* found */ + modelTypeHandle = childModel->modelHandle; + break; + } + } + + if (i < modelCount) + { + /* model found, check if there is more in the path */ + if (slashPos == NULL) + { + /*Codes_SRS_SCHEMA_02_045: [ If the path desiredPropertyPath points to a sub-model, Schema_ModelDesiredPropertyByPathExists shall succeed and true. ]*/ + /* this is the last one, so this is the thing we were looking for */ + result = true; + break; + } + else + { + /* continue looking, there's more */ + desiredPropertyPath = slashPos + 1; + } + } + else + { + /* no model found, let's see if this is a property */ + result = (VECTOR_find_if(modelType->desiredProperties, desiredPropertyExists, desiredPropertyPath) != NULL); + if (!result) + { + LogError("no such desired property \"%s\"", desiredPropertyPath); + } + break; + } + } while (slashPos != NULL); + } + return result; +} + +const char* Schema_GetModelDesiredPropertyType(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) +{ + const char* result; + /*Codes_SRS_SCHEMA_02_062: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredPropertyType shall fail and return NULL. ]*/ + if (desiredPropertyHandle == NULL) + { + LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_063: [ Otherwise, Schema_GetModelDesiredPropertyType shall return the type of the desired property. ]*/ + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; + result = desirePropertyHandleData->desiredPropertyType; + } + return result; +} + +pfDesiredPropertyFromAGENT_DATA_TYPE Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) +{ + pfDesiredPropertyFromAGENT_DATA_TYPE result; + if (desiredPropertyHandle == NULL) + { + LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); + result = NULL; + } + else + { + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; + result = desirePropertyHandleData->desiredPropertyFromAGENT_DATA_TYPE; + } + return result; +} + +pfOnDesiredProperty Schema_GetModelDesiredProperty_pfOnDesiredProperty(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) +{ + pfOnDesiredProperty result; + /*Codes_SRS_SCHEMA_02_084: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return NULL. ]*/ + if (desiredPropertyHandle == NULL) + { + LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_085: [ Otherwise Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return the saved desired property callback. ]*/ + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; + result = desirePropertyHandleData->onDesiredProperty; + } + return result; +} + +size_t Schema_GetModelDesiredProperty_offset(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) +{ + size_t result; + /*Codes_SRS_SCHEMA_02_060: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_offset shall fail and return 0. ]*/ + if (desiredPropertyHandle == NULL) + { + LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); + result = 0; + } + else + { + /*Codes_SRS_SCHEMA_02_061: [ Otherwise Schema_GetModelDesiredProperty_offset shall succeed and return the offset. ]*/ + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; + result = desirePropertyHandleData->offset; + } + return result; +} + +static bool modelInModelExists(const void* element, const void* value) +{ + MODEL_IN_MODEL* modelInModel = (MODEL_IN_MODEL*)element; + return (strcmp(modelInModel->propertyName, value) == 0); +} + +SCHEMA_MODEL_ELEMENT Schema_GetModelElementByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* elementName) +{ + SCHEMA_MODEL_ELEMENT result; + /*Codes_SRS_SCHEMA_02_076: [ If modelTypeHandle is NULL then Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_SEARCH_INVALID_ARG. ]*/ + /*Codes_SRS_SCHEMA_02_077: [ If elementName is NULL then Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_SEARCH_INVALID_ARG. ]*/ + if ( + (modelTypeHandle == NULL) || + (elementName == NULL) + ) + { + LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* elementName=%p", modelTypeHandle, elementName); + result.elementType = SCHEMA_SEARCH_INVALID_ARG; + } + else + { + SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; + + SCHEMA_DESIRED_PROPERTY_HANDLE* desiredPropertyHandle = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, elementName); + if (desiredPropertyHandle != NULL) + { + /*Codes_SRS_SCHEMA_02_080: [ If elementName is a desired property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_DESIRED_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.desiredPropertyHandle to the handle of the desired property. ]*/ + result.elementType = SCHEMA_DESIRED_PROPERTY; + result.elementHandle.desiredPropertyHandle = *desiredPropertyHandle; + } + else + { + size_t nProcessedProperties = 0; + SCHEMA_PROPERTY_HANDLE_DATA* property = NULL; + for (size_t i = 0; i < handleData->PropertyCount;i++) + { + property = (SCHEMA_PROPERTY_HANDLE_DATA*)(handleData->Properties[i]); + if (strcmp(property->PropertyName, elementName) == 0) + { + i = handleData->PropertyCount; /*found it*/ + } + else + { + nProcessedProperties++; + } + } + + if (nProcessedProperties < handleData->PropertyCount) + { + /*Codes_SRS_SCHEMA_02_078: [ If elementName is a property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.propertyHandle to the handle of the property. ]*/ + result.elementType = SCHEMA_PROPERTY; + result.elementHandle.propertyHandle = property; + } + else + { + + SCHEMA_REPORTED_PROPERTY_HANDLE* reportedPropertyHandle = VECTOR_find_if(handleData->reportedProperties, reportedPropertyExists, elementName); + if (reportedPropertyHandle != NULL) + { + /*Codes_SRS_SCHEMA_02_079: [ If elementName is a reported property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_REPORTED_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.reportedPropertyHandle to the handle of the reported property. ]*/ + result.elementType = SCHEMA_REPORTED_PROPERTY; + result.elementHandle.reportedPropertyHandle = *reportedPropertyHandle; + } + else + { + + size_t nProcessedActions = 0; + SCHEMA_ACTION_HANDLE_DATA* actionHandleData = NULL; + for (size_t i = 0;i < handleData->ActionCount; i++) + { + actionHandleData = (SCHEMA_ACTION_HANDLE_DATA*)(handleData->Actions[i]); + if (strcmp(actionHandleData->ActionName, elementName) == 0) + { + i = handleData->ActionCount; /*get out quickly*/ + } + else + { + nProcessedActions++; + } + } + + if (nProcessedActions < handleData->ActionCount) + { + /*Codes_SRS_SCHEMA_02_081: [ If elementName is a model action then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_MODEL_ACTION and SCHEMA_MODEL_ELEMENT.elementHandle.actionHandle to the handle of the action. ]*/ + result.elementType = SCHEMA_MODEL_ACTION; + result.elementHandle.actionHandle = actionHandleData; + } + else + { + MODEL_IN_MODEL* modelInModel = VECTOR_find_if(handleData->models, modelInModelExists, elementName); + if (modelInModel != NULL) + { + /*Codes_SRS_SCHEMA_02_082: [ If elementName is a model in model then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_MODEL_IN_MODEL and SCHEMA_MODEL_ELEMENT.elementHandle.modelHandle to the handle of the model. ]*/ + result.elementType = SCHEMA_MODEL_IN_MODEL; + result.elementHandle.modelHandle = modelInModel->modelHandle; + } + else + { + /*Codes_SRS_SCHEMA_02_083: [ Otherwise Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_NOT_FOUND. ]*/ + result.elementType = SCHEMA_NOT_FOUND; + } + } + } + } + } + } + return result; +} + +pfDesiredPropertyDeinitialize Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) +{ + pfDesiredPropertyDeinitialize result; + /*Ccodes_SRS_SCHEMA_02_064: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall fail and return NULL. ]*/ + if (desiredPropertyHandle == NULL) + { + LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_065: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall return a non-NULL function pointer. ]*/ + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; + result = handleData->desiredPropertDeinitialize; + } + return result; +} + +pfDesiredPropertyInitialize Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) +{ + pfDesiredPropertyInitialize result; + /*Codes_SRS_SCHEMA_02_066: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall fail and return NULL. ]*/ + if (desiredPropertyHandle == NULL) + { + LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_067: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall return a non-NULL function pointer. ]*/ + SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; + result = handleData->desiredPropertInitialize; + } + return result; +} + +static bool SchemaHasModel(const SCHEMA_HANDLE* schemaHandle, const char* modelName) +{ + return (Schema_GetModelByName(*schemaHandle, modelName) != NULL); +} + + +SCHEMA_HANDLE Schema_GetSchemaForModel(const char* modelName) +{ + SCHEMA_HANDLE result; + /*Codes_SRS_SCHEMA_02_093: [ If modelName is NULL then Schema_GetSchemaForModel shall fail and return NULL. ]*/ + if (modelName == NULL) + { + LogError("invalid arg const char* modelName=%p", modelName); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_094: [ Schema_GetSchemaForModel shall find the SCHEMA_HANDLE that contains a model by name modelName and if found, succeed and return that. ]*/ + SCHEMA_HANDLE* temp = VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHasModel, modelName); + + if (temp == NULL) + { + /*Codes_SRS_SCHEMA_02_095: [ If the model is not found in any schema, then Schema_GetSchemaForModel shall fail and return NULL. ]*/ + LogError("unable to find a schema that has a model named %s", modelName); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_094: [ Schema_GetSchemaForModel shall find the SCHEMA_HANDLE that contains a model by name modelName and if found, succeed and return that. ]*/ + result = *temp; + } + } + + return result; +} + +void* Schema_GetMetadata(SCHEMA_HANDLE schemaHandle) +{ + void* result; + /*Codes_SRS_SCHEMA_02_091: [ If schemaHandle is NULL then Schema_GetMetadata shall fail and return NULL. ]*/ + if (schemaHandle == NULL) + { + LogError("invalid arg SCHEMA_HANDLE schemaHandle=%p", schemaHandle); + result = NULL; + } + else + { + /*Codes_SRS_SCHEMA_02_092: [ Otherwise, Schema_GetMetadata shall succeed and return the saved metadata pointer. ]*/ + result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->metadata; + } + return result; +}