Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more
schema.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 #include <stdlib.h> 00005 #include "azure_c_shared_utility/gballoc.h" 00006 00007 #include "schema.h" 00008 #include "azure_c_shared_utility/crt_abstractions.h" 00009 #include "azure_c_shared_utility/xlogging.h" 00010 #include "azure_c_shared_utility/vector.h" 00011 00012 00013 DEFINE_ENUM_STRINGS(SCHEMA_RESULT, SCHEMA_RESULT_VALUES); 00014 00015 typedef struct SCHEMA_PROPERTY_HANDLE_DATA_TAG 00016 { 00017 const char* PropertyName; 00018 const char* PropertyType; 00019 } SCHEMA_PROPERTY_HANDLE_DATA; 00020 00021 typedef struct SCHEMA_REPORTED_PROPERTY_HANDLE_DATA_TAG 00022 { 00023 const char* reportedPropertyName; 00024 const char* reportedPropertyType; 00025 } SCHEMA_REPORTED_PROPERTY_HANDLE_DATA; 00026 00027 typedef struct SCHEMA_DESIRED_PROPERTY_HANDLE_DATA_TAG 00028 { 00029 pfOnDesiredProperty onDesiredProperty; 00030 pfDesiredPropertyInitialize desiredPropertInitialize; 00031 pfDesiredPropertyDeinitialize desiredPropertDeinitialize; 00032 const char* desiredPropertyName; 00033 const char* desiredPropertyType; 00034 pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE; 00035 size_t offset; 00036 } SCHEMA_DESIRED_PROPERTY_HANDLE_DATA; 00037 00038 typedef struct SCHEMA_ACTION_ARGUMENT_HANDLE_DATA_TAG 00039 { 00040 const char* Name; 00041 const char* Type; 00042 } SCHEMA_ACTION_ARGUMENT_HANDLE_DATA; 00043 00044 typedef struct SCHEMA_METHOD_ARGUMENT_HANDLE_DATA_TAG 00045 { 00046 char* Name; 00047 char* Type; 00048 } SCHEMA_METHOD_ARGUMENT_HANDLE_DATA; 00049 00050 typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG 00051 { 00052 const char* ActionName; 00053 size_t ArgumentCount; 00054 SCHEMA_ACTION_ARGUMENT_HANDLE* ArgumentHandles; 00055 } SCHEMA_ACTION_HANDLE_DATA; 00056 00057 typedef struct SCHEMA_METHOD_HANDLE_DATA_TAG 00058 { 00059 char* methodName; 00060 VECTOR_HANDLE methodArguments; /*holds SCHEMA_METHOD_ARGUMENT_HANDLE*/ 00061 } SCHEMA_METHOD_HANDLE_DATA; 00062 00063 typedef struct MODEL_IN_MODEL_TAG 00064 { 00065 pfOnDesiredProperty onDesiredProperty; /*is NULL if not specified or if the model in model is not WITH_DESIRED_PROPERTY*/ 00066 size_t offset; /*offset of the model in model (offsetof)*/ 00067 const char* propertyName; 00068 SCHEMA_MODEL_TYPE_HANDLE modelHandle; 00069 } MODEL_IN_MODEL; 00070 00071 typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG 00072 { 00073 VECTOR_HANDLE methods; /*holds SCHEMA_METHOD_HANDLE*/ 00074 VECTOR_HANDLE desiredProperties; /*holds SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*/ 00075 const char* Name; 00076 SCHEMA_HANDLE SchemaHandle; 00077 SCHEMA_PROPERTY_HANDLE* Properties; 00078 size_t PropertyCount; 00079 VECTOR_HANDLE reportedProperties; /*holds SCHEMA_REPORTED_PROPERTY_HANDLE*/ 00080 SCHEMA_ACTION_HANDLE* Actions; 00081 size_t ActionCount; 00082 VECTOR_HANDLE models; 00083 size_t DeviceCount; 00084 } SCHEMA_MODEL_TYPE_HANDLE_DATA; 00085 00086 typedef struct SCHEMA_STRUCT_TYPE_HANDLE_DATA_TAG 00087 { 00088 const char* Name; 00089 SCHEMA_PROPERTY_HANDLE* Properties; 00090 size_t PropertyCount; 00091 } SCHEMA_STRUCT_TYPE_HANDLE_DATA; 00092 00093 typedef struct SCHEMA_HANDLE_DATA_TAG 00094 { 00095 void* metadata; 00096 const char* Namespace; 00097 SCHEMA_MODEL_TYPE_HANDLE* ModelTypes; 00098 size_t ModelTypeCount; 00099 SCHEMA_STRUCT_TYPE_HANDLE* StructTypes; 00100 size_t StructTypeCount; 00101 } SCHEMA_HANDLE_DATA; 00102 00103 static VECTOR_HANDLE g_schemas = NULL; 00104 00105 static void DestroyProperty(SCHEMA_PROPERTY_HANDLE propertyHandle) 00106 { 00107 SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle; 00108 free((void*)propertyType->PropertyName); 00109 free((void*)propertyType->PropertyType); 00110 free(propertyType); 00111 } 00112 00113 static void DestroyActionArgument(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle) 00114 { 00115 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle; 00116 if (actionArgument != NULL) 00117 { 00118 free((void*)actionArgument->Name); 00119 free((void*)actionArgument->Type); 00120 free(actionArgument); 00121 } 00122 } 00123 00124 static void DestroyMethodArgument(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle) 00125 { 00126 free(methodArgumentHandle->Name); 00127 free(methodArgumentHandle->Type); 00128 free(methodArgumentHandle); 00129 } 00130 00131 static void DestroyAction(SCHEMA_ACTION_HANDLE actionHandle) 00132 { 00133 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; 00134 if (action != NULL) 00135 { 00136 size_t j; 00137 00138 for (j = 0; j < action->ArgumentCount; j++) 00139 { 00140 DestroyActionArgument(action->ArgumentHandles[j]); 00141 } 00142 free(action->ArgumentHandles); 00143 00144 free((void*)action->ActionName); 00145 free(action); 00146 } 00147 } 00148 00149 static void DestroyMethod(SCHEMA_METHOD_HANDLE methodHandle) 00150 { 00151 size_t nArguments = VECTOR_size(methodHandle->methodArguments); 00152 00153 for (size_t j = 0; j < nArguments; j++) 00154 { 00155 SCHEMA_METHOD_ARGUMENT_HANDLE* methodArgumentHandle = VECTOR_element(methodHandle->methodArguments, j); 00156 DestroyMethodArgument(*methodArgumentHandle); 00157 } 00158 free(methodHandle->methodName); 00159 VECTOR_destroy(methodHandle->methodArguments); 00160 free(methodHandle); 00161 } 00162 00163 static void DestroyMethods(SCHEMA_MODEL_TYPE_HANDLE modelHandle) 00164 { 00165 size_t nMethods = VECTOR_size(modelHandle->methods); 00166 00167 for (size_t j = 0; j < nMethods; j++) 00168 { 00169 SCHEMA_METHOD_HANDLE* methodHandle = VECTOR_element(modelHandle->methods, j); 00170 DestroyMethod(*methodHandle); 00171 } 00172 VECTOR_destroy(modelHandle->methods); 00173 } 00174 00175 00176 static void DestroyStruct(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle) 00177 { 00178 size_t i; 00179 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; 00180 if (structType != NULL) 00181 { 00182 for (i = 0; i < structType->PropertyCount; i++) 00183 { 00184 DestroyProperty(structType->Properties[i]); 00185 } 00186 free(structType->Properties); 00187 00188 free((void*)structType->Name); 00189 00190 free(structType); 00191 } 00192 } 00193 00194 static void DestroyModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) 00195 { 00196 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 00197 size_t i, nReportedProperties; 00198 00199 free((void*)modelType->Name); 00200 modelType->Name = NULL; 00201 00202 for (i = 0; i < modelType->PropertyCount; i++) 00203 { 00204 DestroyProperty(modelType->Properties[i]); 00205 } 00206 00207 free(modelType->Properties); 00208 00209 for (i = 0; i < modelType->ActionCount; i++) 00210 { 00211 DestroyAction(modelType->Actions[i]); 00212 } 00213 00214 DestroyMethods(modelType); 00215 00216 /*destroy the vector holding the added models. This does not destroy the said models, however, their names shall be*/ 00217 for (i = 0; i < VECTOR_size(modelType->models); i++) 00218 { 00219 MODEL_IN_MODEL* temp = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); 00220 free((void*)temp->propertyName); 00221 } 00222 00223 nReportedProperties = VECTOR_size(modelType->reportedProperties); 00224 for (i = 0;i < nReportedProperties;i++) 00225 { 00226 SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->reportedProperties, i); 00227 free((void*)reportedProperty->reportedPropertyName); 00228 free((void*)reportedProperty->reportedPropertyType); 00229 free(reportedProperty); 00230 } 00231 VECTOR_destroy(modelType->reportedProperties); 00232 00233 size_t nDesiredProperties = VECTOR_size(modelType->desiredProperties); 00234 for (i = 0;i < nDesiredProperties;i++) 00235 { 00236 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->desiredProperties, i); 00237 free((void*)desiredProperty->desiredPropertyName); 00238 free((void*)desiredProperty->desiredPropertyType); 00239 free(desiredProperty); 00240 } 00241 VECTOR_destroy(modelType->desiredProperties); 00242 00243 VECTOR_clear(modelType->models); 00244 VECTOR_destroy(modelType->models); 00245 00246 free(modelType->Actions); 00247 free(modelType); 00248 } 00249 00250 static SCHEMA_RESULT AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType, const char* name, const char* type) 00251 { 00252 SCHEMA_RESULT result; 00253 00254 /* Codes_SRS_SCHEMA_99_013:[If any of the arguments is NULL, Schema_AddModelProperty shall return SCHEMA_INVALID_ARG.] */ 00255 if ((modelType == NULL) || 00256 (name == NULL) || 00257 (type == NULL)) 00258 { 00259 result = SCHEMA_INVALID_ARG; 00260 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00261 } 00262 else 00263 { 00264 size_t i; 00265 00266 /* 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.] */ 00267 for (i = 0; i < modelType->PropertyCount; i++) 00268 { 00269 SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i]; 00270 if (strcmp(property->PropertyName, name) == 0) 00271 { 00272 break; 00273 } 00274 } 00275 00276 if (i < modelType->PropertyCount) 00277 { 00278 result = SCHEMA_DUPLICATE_ELEMENT; 00279 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00280 } 00281 else 00282 { 00283 SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (modelType->PropertyCount + 1)); 00284 if (newProperties == NULL) 00285 { 00286 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */ 00287 result = SCHEMA_ERROR; 00288 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00289 } 00290 else 00291 { 00292 SCHEMA_PROPERTY_HANDLE_DATA* newProperty; 00293 00294 modelType->Properties = newProperties; 00295 if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL) 00296 { 00297 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */ 00298 result = SCHEMA_ERROR; 00299 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00300 } 00301 else 00302 { 00303 if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, name) != 0) 00304 { 00305 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */ 00306 free(newProperty); 00307 result = SCHEMA_ERROR; 00308 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00309 } 00310 else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, type) != 0) 00311 { 00312 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */ 00313 free((void*)newProperty->PropertyName); 00314 free(newProperty); 00315 result = SCHEMA_ERROR; 00316 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00317 } 00318 else 00319 { 00320 modelType->Properties[modelType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty; 00321 modelType->PropertyCount++; 00322 00323 /* Codes_SRS_SCHEMA_99_012:[On success, Schema_AddModelProperty shall return SCHEMA_OK.] */ 00324 result = SCHEMA_OK; 00325 } 00326 } 00327 00328 /* If possible, reduce the memory of over allocation */ 00329 if (result != SCHEMA_OK) 00330 { 00331 if (modelType->PropertyCount > 0) 00332 { 00333 SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * modelType->PropertyCount); 00334 if (oldProperties == NULL) 00335 { 00336 result = SCHEMA_ERROR; 00337 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00338 } 00339 else 00340 { 00341 modelType->Properties = oldProperties; 00342 } 00343 } 00344 else 00345 { 00346 modelType->Properties = NULL; 00347 } 00348 } 00349 } 00350 } 00351 } 00352 00353 return result; 00354 } 00355 00356 static bool SchemaHandlesMatch(const SCHEMA_HANDLE* handle, const SCHEMA_HANDLE* otherHandle) 00357 { 00358 return (*handle == *otherHandle); 00359 } 00360 00361 static bool SchemaNamespacesMatch(const SCHEMA_HANDLE* handle, const char* schemaNamespace) 00362 { 00363 const SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)*handle; 00364 return (strcmp(schema->Namespace, schemaNamespace) == 0); 00365 } 00366 00367 /* Codes_SRS_SCHEMA_99_001:[Schema_Create shall initialize a schema with a given namespace.] */ 00368 SCHEMA_HANDLE Schema_Create(const char* schemaNamespace, void* metadata) 00369 { 00370 SCHEMA_HANDLE_DATA* result; 00371 /*Codes_SRS_SCHEMA_02_090: [ If metadata is NULL then Schema_Create shall fail and return NULL. ]*/ 00372 /* Codes_SRS_SCHEMA_99_004:[If schemaNamespace is NULL, Schema_Create shall fail.] */ 00373 if ( 00374 (schemaNamespace == NULL)|| 00375 (metadata == NULL) 00376 ) 00377 { 00378 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ 00379 LogError("invalid arg const char* schemaNamespace=%p, void* metadata=%p",schemaNamespace, metadata); 00380 result = NULL; 00381 } 00382 else 00383 { 00384 if (g_schemas == NULL && (g_schemas = VECTOR_create(sizeof(SCHEMA_HANDLE_DATA*) ) ) == NULL) 00385 { 00386 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ 00387 result = NULL; 00388 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00389 } 00390 else if ((result = (SCHEMA_HANDLE_DATA*)malloc(sizeof(SCHEMA_HANDLE_DATA))) == NULL) 00391 { 00392 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ 00393 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00394 } 00395 else if (mallocAndStrcpy_s((char**)&result->Namespace, schemaNamespace) != 0) 00396 { 00397 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */ 00398 free(result); 00399 result = NULL; 00400 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00401 } 00402 else if (VECTOR_push_back(g_schemas, &result, 1) != 0) 00403 { 00404 free((void*)result->Namespace); 00405 free(result); 00406 result = NULL; 00407 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00408 } 00409 else 00410 { 00411 /* Codes_SRS_SCHEMA_99_002:[On success a non-NULL handle to the newly created schema shall be returned.] */ 00412 result->ModelTypes = NULL; 00413 result->ModelTypeCount = 0; 00414 result->StructTypes = NULL; 00415 result->StructTypeCount = 0; 00416 result->metadata = metadata; 00417 } 00418 } 00419 00420 return (SCHEMA_HANDLE)result; 00421 } 00422 00423 size_t Schema_GetSchemaCount(void) 00424 { 00425 /* Codes_SRS_SCHEMA_99_153: [Schema_GetSchemaCount shall return the number of "active" schemas (all schemas created with Schema_Create 00426 in the current process, for which Schema_Destroy has not been called).] */ 00427 return VECTOR_size(g_schemas); 00428 } 00429 00430 SCHEMA_HANDLE Schema_GetSchemaByNamespace(const char* schemaNamespace) 00431 { 00432 /* Codes_SRS_SCHEMA_99_151: [If no active schema matches the schemaNamespace argument, Schema_GetSchemaByNamespace shall return NULL.] */ 00433 SCHEMA_HANDLE result = NULL; 00434 00435 /* Codes_SRS_SCHEMA_99_150: [If the schemaNamespace argument is NULL, Schema_GetSchemaByNamespace shall return NULL.] */ 00436 if (schemaNamespace != NULL) 00437 { 00438 SCHEMA_HANDLE* handle = (g_schemas==NULL)?NULL:(SCHEMA_HANDLE*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaNamespacesMatch, schemaNamespace); 00439 if (handle != NULL) 00440 { 00441 /* Codes_SRS_SCHEMA_99_148: [Schema_GetSchemaByNamespace shall search all active schemas and return the schema with the 00442 namespace given by the schemaNamespace argument.] */ 00443 result = *handle; 00444 } 00445 } 00446 00447 return result; 00448 } 00449 00450 const char* Schema_GetSchemaNamespace(SCHEMA_HANDLE schemaHandle) 00451 { 00452 const char* result; 00453 00454 /* Codes_SRS_SCHEMA_99_130: [If the schemaHandle argument is NULL, Schema_GetSchemaNamespace shall return NULL.] */ 00455 if (schemaHandle == NULL) 00456 { 00457 result = NULL; 00458 } 00459 else 00460 { 00461 /* Codes_SRS_SCHEMA_99_129: [Schema_GetSchemaNamespace shall return the namespace for the schema identified by schemaHandle.] */ 00462 result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->Namespace; 00463 } 00464 00465 return result; 00466 } 00467 00468 void Schema_Destroy(SCHEMA_HANDLE schemaHandle) 00469 { 00470 /* Codes_SRS_SCHEMA_99_006:[If the schemaHandle is NULL, Schema_Destroy shall do nothing.] */ 00471 if (schemaHandle != NULL) 00472 { 00473 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 00474 size_t i; 00475 00476 /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */ 00477 for (i = 0; i < schema->ModelTypeCount; i++) 00478 { 00479 DestroyModel(schema->ModelTypes[i]); 00480 } 00481 00482 free(schema->ModelTypes); 00483 00484 /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */ 00485 for (i = 0; i < schema->StructTypeCount; i++) 00486 { 00487 DestroyStruct(schema->StructTypes[i]); 00488 } 00489 00490 free(schema->StructTypes); 00491 free((void*)schema->Namespace); 00492 free(schema); 00493 00494 schema = (SCHEMA_HANDLE_DATA*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHandlesMatch, &schemaHandle); 00495 if (schema != NULL) 00496 { 00497 VECTOR_erase(g_schemas, schema, 1); 00498 } 00499 // If the g_schema is empty then destroy it 00500 if (VECTOR_size(g_schemas) == 0) 00501 { 00502 VECTOR_destroy(g_schemas); 00503 g_schemas = NULL; 00504 } 00505 } 00506 } 00507 00508 SCHEMA_RESULT Schema_DestroyIfUnused(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) 00509 { 00510 SCHEMA_RESULT result; 00511 00512 /* Codes_SRS_SCHEMA_07_189: [If modelHandle variable is NULL Schema_DestroyIfUnused shall do nothing.] */ 00513 if (modelTypeHandle != NULL) 00514 { 00515 SCHEMA_HANDLE schemaHandle = Schema_GetSchemaForModelType(modelTypeHandle); 00516 if (schemaHandle == NULL) 00517 { 00518 result = SCHEMA_ERROR; 00519 } 00520 else 00521 { 00522 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 00523 size_t nIndex; 00524 00525 /* 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.] */ 00526 for (nIndex = 0; nIndex < schema->ModelTypeCount; nIndex++) 00527 { 00528 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[nIndex]; 00529 if (modelType->DeviceCount > 0) 00530 break; 00531 } 00532 /* Codes_SRS_SCHEMA_07_191: [If 1 or more DeviceCount variables are > 0 then Schema_DestroyIfUnused shall do nothing.] */ 00533 if (nIndex == schema->ModelTypeCount) 00534 { 00535 Schema_Destroy(schemaHandle); 00536 result = SCHEMA_OK; 00537 } 00538 else 00539 { 00540 result = SCHEMA_MODEL_IN_USE; 00541 } 00542 } 00543 } 00544 else 00545 { 00546 result = SCHEMA_INVALID_ARG; 00547 } 00548 return result; 00549 } 00550 00551 SCHEMA_RESULT Schema_AddDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) 00552 { 00553 SCHEMA_RESULT result; 00554 if (modelTypeHandle == NULL) 00555 { 00556 /* Codes_SRS_SCHEMA_07_187: [Schema_AddDeviceRef shall return SCHEMA_INVALID_ARG if modelTypeHandle is NULL.] */ 00557 result = SCHEMA_INVALID_ARG; 00558 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00559 } 00560 else 00561 { 00562 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 00563 /* Codes_SRS_SCHEMA_07_188: [If the modelTypeHandle is nonNULL, Schema_AddDeviceRef shall increment the SCHEMA_MODEL_TYPE_HANDLE_DATA DeviceCount variable.] */ 00564 model->DeviceCount++; 00565 result = SCHEMA_OK; 00566 } 00567 return result; 00568 } 00569 00570 SCHEMA_RESULT Schema_ReleaseDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) 00571 { 00572 SCHEMA_RESULT result; 00573 /* Codes_SRS_SCHEMA_07_184: [Schema_DeviceRelease shall do nothing if the supplied modelHandle is NULL.] */ 00574 if (modelTypeHandle == NULL) 00575 { 00576 result = SCHEMA_INVALID_ARG; 00577 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00578 } 00579 else 00580 { 00581 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 00582 if (model->DeviceCount > 0) 00583 { 00584 /* Codes_SRS_SCHEMA_07_186: [On a nonNULL SCHEMA_MODEL_TYPE_HANDLE if the DeviceCount variable is > 0 then the variable will be decremented.] */ 00585 model->DeviceCount--; 00586 result = SCHEMA_OK; 00587 } 00588 else 00589 { 00590 result = SCHEMA_DEVICE_COUNT_ZERO; 00591 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 00592 } 00593 } 00594 return result; 00595 } 00596 00597 /* Codes_SRS_SCHEMA_99_007:[Schema_CreateModelType shall create a new model type and return a handle to it.] */ 00598 SCHEMA_MODEL_TYPE_HANDLE Schema_CreateModelType(SCHEMA_HANDLE schemaHandle, const char* modelName) 00599 { 00600 SCHEMA_MODEL_TYPE_HANDLE result; 00601 00602 /* Codes_SRS_SCHEMA_99_010:[If any of the arguments is NULL, Schema_CreateModelType shall fail.] */ 00603 if ((schemaHandle == NULL) || 00604 (modelName == NULL)) 00605 { 00606 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00607 result = NULL; 00608 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 00609 } 00610 else 00611 { 00612 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 00613 00614 /* Codes_SRS_SCHEMA_99_100: [Schema_CreateModelType shall return SCHEMA_DUPLICATE_ELEMENT if modelName already exists.] */ 00615 size_t i; 00616 for (i = 0; i < schema->ModelTypeCount; i++) 00617 { 00618 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)(schema->ModelTypes[i]); 00619 if (strcmp(model->Name, modelName) == 0) 00620 { 00621 break; 00622 } 00623 } 00624 00625 if (i < schema->ModelTypeCount) 00626 { 00627 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00628 result = NULL; 00629 LogError("%s Model Name already exists", modelName); 00630 } 00631 00632 else 00633 { 00634 SCHEMA_MODEL_TYPE_HANDLE* newModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * (schema->ModelTypeCount + 1)); 00635 if (newModelTypes == NULL) 00636 { 00637 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00638 result = NULL; 00639 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00640 } 00641 else 00642 { 00643 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType; 00644 schema->ModelTypes = newModelTypes; 00645 00646 if ((modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)malloc(sizeof(SCHEMA_MODEL_TYPE_HANDLE_DATA))) == NULL) 00647 { 00648 00649 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00650 result = NULL; 00651 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00652 } 00653 else if (mallocAndStrcpy_s((char**)&modelType->Name, modelName) != 0) 00654 { 00655 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00656 result = NULL; 00657 free(modelType); 00658 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00659 } 00660 else 00661 { 00662 modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL)); 00663 if (modelType->models == NULL) 00664 { 00665 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00666 LogError("unable to VECTOR_create"); 00667 free((void*)modelType->Name); 00668 free((void*)modelType); 00669 result = NULL; 00670 } 00671 else 00672 { 00673 if ((modelType->reportedProperties = VECTOR_create(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE))) == NULL) 00674 { 00675 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00676 LogError("failed to VECTOR_create (reported properties)"); 00677 VECTOR_destroy(modelType->models); 00678 free((void*)modelType->Name); 00679 free((void*)modelType); 00680 result = NULL; 00681 00682 } 00683 else 00684 { 00685 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */ 00686 if ((modelType->desiredProperties = VECTOR_create(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE))) == NULL) 00687 { 00688 LogError("failure in VECTOR_create (desired properties)"); 00689 VECTOR_destroy(modelType->reportedProperties); 00690 VECTOR_destroy(modelType->models); 00691 free((void*)modelType->Name); 00692 free((void*)modelType); 00693 result = NULL; 00694 } 00695 else 00696 { 00697 if ((modelType->methods = VECTOR_create(sizeof(SCHEMA_METHOD_HANDLE))) == NULL) 00698 { 00699 LogError("failure in VECTOR_create (desired properties)"); 00700 VECTOR_destroy(modelType->desiredProperties); 00701 VECTOR_destroy(modelType->reportedProperties); 00702 VECTOR_destroy(modelType->models); 00703 free((void*)modelType->Name); 00704 free((void*)modelType); 00705 result = NULL; 00706 } 00707 else 00708 { 00709 modelType->PropertyCount = 0; 00710 modelType->Properties = NULL; 00711 modelType->ActionCount = 0; 00712 modelType->Actions = NULL; 00713 modelType->SchemaHandle = schemaHandle; 00714 modelType->DeviceCount = 0; 00715 00716 schema->ModelTypes[schema->ModelTypeCount] = modelType; 00717 schema->ModelTypeCount++; 00718 /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */ 00719 result = (SCHEMA_MODEL_TYPE_HANDLE)modelType; 00720 } 00721 } 00722 } 00723 } 00724 } 00725 00726 /* If possible, reduce the memory of over allocation */ 00727 if ((result == NULL) &&(schema->ModelTypeCount>0)) 00728 { 00729 SCHEMA_MODEL_TYPE_HANDLE* oldModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * schema->ModelTypeCount); 00730 if (oldModelTypes == NULL) 00731 { 00732 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00733 } 00734 else 00735 { 00736 schema->ModelTypes = oldModelTypes; 00737 } 00738 } 00739 } 00740 } 00741 } 00742 00743 return result; 00744 } 00745 00746 SCHEMA_HANDLE Schema_GetSchemaForModelType(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) 00747 { 00748 SCHEMA_HANDLE result; 00749 00750 if (modelTypeHandle == NULL) 00751 { 00752 /* Codes_SRS_SCHEMA_99_132: [If the modelTypeHandle argument is NULL, Schema_GetSchemaForModelType shall return NULL.] */ 00753 result = NULL; 00754 } 00755 else 00756 { 00757 /* Codes_SRS_SCHEMA_99_131: [Schema_GetSchemaForModelType returns the schema handle for a given model type.] */ 00758 result = ((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle)->SchemaHandle; 00759 } 00760 00761 return result; 00762 } 00763 00764 /* Codes_SRS_SCHEMA_99_011:[Schema_AddModelProperty shall add one property to the model type identified by modelTypeHandle.] */ 00765 SCHEMA_RESULT Schema_AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, const char* propertyType) 00766 { 00767 return AddModelProperty((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle, propertyName, propertyType); 00768 } 00769 00770 static bool reportedPropertyExists(const void* element, const void* value) 00771 { 00772 SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA**)element; 00773 return (strcmp(reportedProperty->reportedPropertyName, value) == 0); 00774 } 00775 00776 SCHEMA_RESULT Schema_AddModelReportedProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName, const char* reportedPropertyType) 00777 { 00778 SCHEMA_RESULT result; 00779 /*Codes_SRS_SCHEMA_02_001: [ If modelTypeHandle is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 00780 /*Codes_SRS_SCHEMA_02_002: [ If reportedPropertyName is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 00781 /*Codes_SRS_SCHEMA_02_003: [ If reportedPropertyType is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 00782 if ( 00783 (modelTypeHandle == NULL) || 00784 (reportedPropertyName == NULL) || 00785 (reportedPropertyType == NULL) 00786 ) 00787 { 00788 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p, const char* reportedPropertyType=%p", modelTypeHandle, reportedPropertyName, reportedPropertyType); 00789 result = SCHEMA_INVALID_ARG; 00790 } 00791 else 00792 { 00793 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 00794 /*Codes_SRS_SCHEMA_02_004: [ If reportedPropertyName has already been added then Schema_AddModelReportedProperty shall fail and return SCHEMA_PROPERTY_ELEMENT_EXISTS. ]*/ 00795 if (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName) != NULL) 00796 { 00797 LogError("unable to add reportedProperty %s because it already exists", reportedPropertyName); 00798 result = SCHEMA_DUPLICATE_ELEMENT; 00799 } 00800 else 00801 { 00802 /*Codes_SRS_SCHEMA_02_005: [ Schema_AddModelReportedProperty shall record reportedPropertyName and reportedPropertyType. ]*/ 00803 SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = (SCHEMA_REPORTED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA)); 00804 if (reportedProperty == NULL) 00805 { 00806 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ 00807 LogError("unable to malloc"); 00808 result = SCHEMA_ERROR; 00809 } 00810 else 00811 { 00812 if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyName, reportedPropertyName) != 0) 00813 { 00814 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ 00815 LogError("unable to mallocAndStrcpy_s"); 00816 free(reportedProperty); 00817 result = SCHEMA_ERROR; 00818 } 00819 else 00820 { 00821 if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyType, reportedPropertyType) != 0) 00822 { 00823 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ 00824 LogError("unable to mallocAndStrcpy_s"); 00825 free((void*)reportedProperty->reportedPropertyName); 00826 free(reportedProperty); 00827 result = SCHEMA_ERROR; 00828 } 00829 else 00830 { 00831 if (VECTOR_push_back(modelType->reportedProperties, &reportedProperty, 1) != 0) 00832 { 00833 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/ 00834 LogError("unable to VECTOR_push_back"); 00835 free((void*)reportedProperty->reportedPropertyType); 00836 free((void*)reportedProperty->reportedPropertyName); 00837 free(reportedProperty); 00838 result = SCHEMA_ERROR; 00839 } 00840 else 00841 { 00842 /*Codes_SRS_SCHEMA_02_007: [ Otherwise Schema_AddModelReportedProperty shall succeed and return SCHEMA_OK. ]*/ 00843 result = SCHEMA_OK; 00844 } 00845 } 00846 } 00847 } 00848 } 00849 } 00850 return result; 00851 } 00852 00853 SCHEMA_ACTION_HANDLE Schema_CreateModelAction(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName) 00854 { 00855 SCHEMA_ACTION_HANDLE result; 00856 00857 /* Codes_SRS_SCHEMA_99_104: [If any of the modelTypeHandle or actionName arguments is NULL, Schema_CreateModelAction shall return NULL.] */ 00858 if ((modelTypeHandle == NULL) || 00859 (actionName == NULL)) 00860 { 00861 result = NULL; 00862 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 00863 } 00864 else 00865 { 00866 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 00867 size_t i; 00868 00869 /* 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.] */ 00870 for (i = 0; i < modelType->ActionCount; i++) 00871 { 00872 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i]; 00873 if (strcmp(action->ActionName, actionName) == 0) 00874 { 00875 break; 00876 } 00877 } 00878 00879 if (i < modelType->ActionCount) 00880 { 00881 result = NULL; 00882 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT)); 00883 } 00884 else 00885 { 00886 /* Codes_SRS_SCHEMA_99_102: [Schema_CreateModelAction shall add one action to the model type identified by modelTypeHandle.] */ 00887 SCHEMA_ACTION_HANDLE* newActions = (SCHEMA_ACTION_HANDLE*)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * (modelType->ActionCount + 1)); 00888 if (newActions == NULL) 00889 { 00890 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/ 00891 result = NULL; 00892 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00893 } 00894 else 00895 { 00896 SCHEMA_ACTION_HANDLE_DATA* newAction; 00897 modelType->Actions = newActions; 00898 00899 /* Codes_SRS_SCHEMA_99_103: [On success, Schema_CreateModelAction shall return a none-NULL SCHEMA_ACTION_HANDLE to the newly created action.] */ 00900 if ((newAction = (SCHEMA_ACTION_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_HANDLE_DATA))) == NULL) 00901 { 00902 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/ 00903 result = NULL; 00904 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00905 } 00906 else 00907 { 00908 if (mallocAndStrcpy_s((char**)&newAction->ActionName, actionName) != 0) 00909 { 00910 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/ 00911 free(newAction); 00912 result = NULL; 00913 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00914 } 00915 else 00916 { 00917 newAction->ArgumentCount = 0; 00918 newAction->ArgumentHandles = NULL; 00919 00920 modelType->Actions[modelType->ActionCount] = newAction; 00921 modelType->ActionCount++; 00922 result = (SCHEMA_ACTION_HANDLE)(newAction); 00923 } 00924 00925 /* If possible, reduce the memory of over allocation */ 00926 if (result == NULL) 00927 { 00928 if (modelType->ActionCount > 0) 00929 { 00930 SCHEMA_ACTION_HANDLE *oldActions = (SCHEMA_ACTION_HANDLE *)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * modelType->ActionCount); 00931 if (oldActions == NULL) 00932 { 00933 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 00934 } 00935 else 00936 { 00937 modelType->Actions = oldActions; 00938 } 00939 } 00940 else 00941 { 00942 modelType->Actions = NULL; 00943 } 00944 } 00945 } 00946 } 00947 } 00948 } 00949 return result; 00950 } 00951 00952 00953 static bool methodExists(const void* element, const void* value) 00954 { 00955 const SCHEMA_METHOD_HANDLE* method = (const SCHEMA_METHOD_HANDLE*)element; 00956 return (strcmp((*method)->methodName, value) == 0); 00957 } 00958 00959 00960 SCHEMA_METHOD_HANDLE Schema_CreateModelMethod(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName) 00961 { 00962 SCHEMA_METHOD_HANDLE result; 00963 00964 /*Codes_SRS_SCHEMA_02_096: [ If modelTypeHandle is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/ 00965 /*Codes_SRS_SCHEMA_02_097: [ If methodName is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/ 00966 if ((modelTypeHandle == NULL) || 00967 (methodName == NULL)) 00968 { 00969 result = NULL; 00970 LogError("invalid argument: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName); 00971 } 00972 else 00973 { 00974 /*Codes_SRS_SCHEMA_02_103: [ If methodName already exists, then Schema_CreateModelMethod shall fail and return NULL. ]*/ 00975 if (VECTOR_find_if(modelTypeHandle->methods, methodExists, methodName) != NULL) 00976 { 00977 LogError("method %s already exists", methodName); 00978 result = NULL; 00979 } 00980 else 00981 { 00982 /*Codes_SRS_SCHEMA_02_098: [ Schema_CreateModelMethod shall allocate the space for the method. ]*/ 00983 result = malloc(sizeof(SCHEMA_METHOD_HANDLE_DATA)); 00984 if (result == NULL) 00985 { 00986 LogError("failed to malloc"); 00987 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ 00988 /*return as is*/ 00989 } 00990 else 00991 { 00992 /*Codes_SRS_SCHEMA_02_099: [ Schema_CreateModelMethod shall create a VECTOR that will hold the method's arguments. ]*/ 00993 result->methodArguments = VECTOR_create(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE)); 00994 if (result->methodArguments == NULL) 00995 { 00996 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ 00997 LogError("failure in VECTOR_create"); 00998 free(result); 00999 result = NULL; 01000 } 01001 else 01002 { 01003 /*Codes_SRS_SCHEMA_02_100: [ Schema_CreateModelMethod shall clone methodName ]*/ 01004 if (mallocAndStrcpy_s(&result->methodName, methodName) != 0) 01005 { 01006 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ 01007 LogError("failure in mallocAndStrcpy_s"); 01008 VECTOR_destroy(result->methodArguments); 01009 free(result); 01010 result = NULL; 01011 } 01012 else 01013 { 01014 /*Codes_SRS_SCHEMA_02_101: [ Schema_CreateModelMethod shall add the new created method to the model's list of methods. ]*/ 01015 if (VECTOR_push_back(modelTypeHandle->methods, &result, 1) != 0) 01016 { 01017 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/ 01018 LogError("failure in VECTOR_push_back"); 01019 free(result->methodName); 01020 VECTOR_destroy(result->methodArguments); 01021 free(result); 01022 result = NULL; 01023 } 01024 else 01025 { 01026 /*Codes_SRS_SCHEMA_02_104: [ Otherwise, Schema_CreateModelMethod shall succeed and return a non-NULL SCHEMA_METHOD_HANDLE. ]*/ 01027 /*return as is*/ 01028 } 01029 } 01030 } 01031 } 01032 } 01033 } 01034 return result; 01035 } 01036 01037 01038 SCHEMA_RESULT Schema_AddModelActionArgument(SCHEMA_ACTION_HANDLE actionHandle, const char* argumentName, const char* argumentType) 01039 { 01040 SCHEMA_RESULT result; 01041 01042 /* Codes_SRS_SCHEMA_99_109: [If any of the arguments is NULL, Schema_AddModelActionArgument shall return SCHEMA_INVALID_ARG.] */ 01043 if ((actionHandle == NULL) || 01044 (argumentName == NULL) || 01045 (argumentType == NULL)) 01046 { 01047 result = SCHEMA_INVALID_ARG; 01048 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01049 } 01050 else 01051 { 01052 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; 01053 01054 /* 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.] */ 01055 /* Codes_SRS_SCHEMA_99_111: [Schema_AddModelActionArgument shall accept arguments with different names of the same type.] */ 01056 size_t i; 01057 for (i = 0; i < action->ArgumentCount; i++) 01058 { 01059 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)action->ArgumentHandles[i]; 01060 if (strcmp((actionArgument->Name), argumentName) == 0) 01061 { 01062 break; 01063 } 01064 } 01065 01066 if (i < action->ArgumentCount) 01067 { 01068 result = SCHEMA_DUPLICATE_ELEMENT; 01069 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01070 } 01071 else 01072 { 01073 /* Codes_SRS_SCHEMA_99_107: [Schema_AddModelActionArgument shall add one argument name & type to an action identified by actionHandle.] */ 01074 SCHEMA_ACTION_ARGUMENT_HANDLE* newArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE*)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * (action->ArgumentCount + 1)); 01075 if (newArguments == NULL) 01076 { 01077 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */ 01078 result = SCHEMA_ERROR; 01079 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01080 } 01081 else 01082 { 01083 action->ArgumentHandles = newArguments; 01084 01085 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* newActionArgument; 01086 01087 action->ArgumentHandles = newArguments; 01088 if ((newActionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE_DATA))) == NULL) 01089 { 01090 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */ 01091 result = SCHEMA_ERROR; 01092 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01093 } 01094 else 01095 { 01096 if (mallocAndStrcpy_s((char**)&newActionArgument->Name, argumentName) != 0) 01097 { 01098 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */ 01099 free(newActionArgument); 01100 result = SCHEMA_ERROR; 01101 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01102 } 01103 else if (mallocAndStrcpy_s((char**)&newActionArgument->Type, argumentType) != 0) 01104 { 01105 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */ 01106 free((void*)newActionArgument->Name); 01107 free(newActionArgument); 01108 result = SCHEMA_ERROR; 01109 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01110 } 01111 else 01112 { 01113 /* Codes_SRS_SCHEMA_99_119: [Schema_AddModelActionArgument shall preserve the order of the action arguments according to the order in which they were added, starting with index 0 for the first added argument.] */ 01114 action->ArgumentHandles[action->ArgumentCount] = newActionArgument; 01115 action->ArgumentCount++; 01116 01117 /* Codes_SRS_SCHEMA_99_108: [On success, Schema_AddModelActionArgunent shall return SCHEMA_OK.] */ 01118 result = SCHEMA_OK; 01119 } 01120 } 01121 01122 /* If possible, reduce the memory of over allocation */ 01123 if (result == SCHEMA_ERROR) 01124 { 01125 if (action->ArgumentCount > 0) 01126 { 01127 SCHEMA_ACTION_ARGUMENT_HANDLE *oldArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE *)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * action->ArgumentCount); 01128 if (oldArguments == NULL) 01129 { 01130 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 01131 } 01132 else 01133 { 01134 action->ArgumentHandles = oldArguments; 01135 } 01136 } 01137 else 01138 { 01139 action->ArgumentHandles = NULL; 01140 } 01141 } 01142 } 01143 } 01144 } 01145 return result; 01146 } 01147 01148 static bool methodFindArgumentByBame(const void* element, const void* value) 01149 { 01150 /*element is a pointer to SCHEMA_METHOD_ARGUMENT_HANDLE*/ 01151 const SCHEMA_METHOD_ARGUMENT_HANDLE* decodedElement = (const SCHEMA_METHOD_ARGUMENT_HANDLE*)element; 01152 const char* name = (const char*)value; 01153 return (strcmp((*decodedElement)->Name, name) == 0); 01154 } 01155 01156 SCHEMA_RESULT Schema_AddModelMethodArgument(SCHEMA_METHOD_HANDLE methodHandle, const char* argumentName, const char* argumentType) 01157 { 01158 SCHEMA_RESULT result; 01159 /*Codes_SRS_SCHEMA_02_105: [ If methodHandle is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ 01160 /*Codes_SRS_SCHEMA_02_106: [ If argumentName is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ 01161 /*Codes_SRS_SCHEMA_02_107: [ If argumentType is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ 01162 if ((methodHandle == NULL) || 01163 (argumentName == NULL) || 01164 (argumentType == NULL)) 01165 { 01166 result = SCHEMA_INVALID_ARG; 01167 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01168 } 01169 else 01170 { 01171 /*Codes_SRS_SCHEMA_02_108: [ If argumentName already exists in the list of arguments then then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/ 01172 if (VECTOR_find_if(methodHandle->methodArguments, methodFindArgumentByBame, argumentName) != NULL) 01173 { 01174 LogError("an argument with name %s already exists", argumentName); 01175 result = SCHEMA_INVALID_ARG; 01176 } 01177 else 01178 { 01179 /*Codes_SRS_SCHEMA_02_109: [ Schema_AddModelMethodArgument shall allocate memory for the new argument. ]*/ 01180 SCHEMA_METHOD_ARGUMENT_HANDLE_DATA* argument = malloc(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE_DATA)); 01181 if (argument == NULL) 01182 { 01183 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ 01184 LogError("failure to malloc"); 01185 result = SCHEMA_ERROR; 01186 } 01187 else 01188 { 01189 /*Codes_SRS_SCHEMA_02_110: [ Schema_AddModelMethodArgument shall clone methodHandle. ]*/ 01190 if (mallocAndStrcpy_s(&argument->Name, argumentName) != 0) 01191 { 01192 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ 01193 LogError("failure in mallocAndStrcpy_s"); 01194 free(argument); 01195 result = SCHEMA_ERROR; 01196 } 01197 else 01198 { 01199 /*Codes_SRS_SCHEMA_02_111: [ Schema_AddModelMethodArgument shall clone argumentType. ]*/ 01200 if (mallocAndStrcpy_s(&argument->Type, argumentType) != 0) 01201 { 01202 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ 01203 LogError("failure in mallocAndStrcpy_s"); 01204 free(argument->Name); 01205 free(argument); 01206 result = SCHEMA_ERROR; 01207 } 01208 else 01209 { 01210 /*Codes_SRS_SCHEMA_02_112: [ Schema_AddModelMethodArgument shall add the created argument to the method's list of arguments. ]*/ 01211 if (VECTOR_push_back(methodHandle->methodArguments, &argument, 1) != 0) 01212 { 01213 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/ 01214 LogError("failure in VECTOR_push_back"); 01215 free(argument->Name); 01216 free(argument->Type); 01217 free(argument); 01218 result = SCHEMA_ERROR; 01219 } 01220 else 01221 { 01222 /*Codes_SRS_SCHEMA_02_114: [ Otherwise, Schema_AddModelMethodArgument shall succeed and return SCHEMA_OK. ]*/ 01223 result = SCHEMA_OK; 01224 } 01225 } 01226 } 01227 } 01228 } 01229 } 01230 return result; 01231 } 01232 01233 SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) 01234 { 01235 SCHEMA_PROPERTY_HANDLE result; 01236 01237 /* Codes_SRS_SCHEMA_99_038:[Schema_GetModelPropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */ 01238 if ((modelTypeHandle == NULL) || 01239 (propertyName == NULL)) 01240 { 01241 result = NULL; 01242 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01243 } 01244 else 01245 { 01246 size_t i; 01247 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01248 01249 /* 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.] */ 01250 for (i = 0; i < modelType->PropertyCount; i++) 01251 { 01252 SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i]; 01253 if (strcmp(modelProperty->PropertyName, propertyName) == 0) 01254 { 01255 break; 01256 } 01257 } 01258 01259 if (i == modelType->PropertyCount) 01260 { 01261 /* Codes_SRS_SCHEMA_99_038:[Schema_GetModelPropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */ 01262 result = NULL; 01263 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND)); 01264 } 01265 else 01266 { 01267 result = (SCHEMA_PROPERTY_HANDLE)(modelType->Properties[i]); 01268 } 01269 } 01270 01271 return result; 01272 } 01273 01274 SCHEMA_RESULT Schema_GetModelPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* propertyCount) 01275 { 01276 SCHEMA_RESULT result; 01277 01278 /* Codes_SRS_SCHEMA_99_092: [Schema_GetModelPropertyCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */ 01279 if ((modelTypeHandle == NULL) || 01280 (propertyCount == NULL)) 01281 { 01282 result = SCHEMA_INVALID_ARG; 01283 } 01284 else 01285 { 01286 /* Codes_SRS_SCHEMA_99_089: [Schema_GetModelPropertyCount shall provide the number of properties defined in the model type identified by modelTypeHandle.] */ 01287 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01288 01289 /* Codes_SRS_SCHEMA_99_090: [The count shall be provided via the out argument propertyCount.]*/ 01290 *propertyCount = modelType->PropertyCount; 01291 01292 /* Codes_SRS_SCHEMA_99_091: [On success, Schema_GetModelPropertyCount shall return SCHEMA_OK.] */ 01293 result = SCHEMA_OK; 01294 } 01295 01296 return result; 01297 } 01298 01299 SCHEMA_RESULT Schema_GetModelReportedPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* reportedPropertyCount) 01300 { 01301 SCHEMA_RESULT result; 01302 /*Codes_SRS_SCHEMA_02_008: [ If parameter modelTypeHandle is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ 01303 /*Codes_SRS_SCHEMA_02_009: [ If parameter reportedPropertyCount is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ 01304 if ( 01305 (modelTypeHandle == NULL)|| 01306 (reportedPropertyCount==NULL) 01307 ) 01308 { 01309 LogError("SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* reportedPropertyCount=%p", modelTypeHandle, reportedPropertyCount); 01310 result = SCHEMA_INVALID_ARG; 01311 } 01312 else 01313 { 01314 /*Codes_SRS_SCHEMA_02_010: [ Schema_GetModelReportedPropertyCount shall provide in reportedPropertyCount the number of reported properties and return SCHEMA_OK. ]*/ 01315 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01316 *reportedPropertyCount = VECTOR_size(modelType->reportedProperties); 01317 result = SCHEMA_OK; 01318 } 01319 return result; 01320 } 01321 01322 SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName) 01323 { 01324 SCHEMA_REPORTED_PROPERTY_HANDLE result; 01325 /*Codes_SRS_SCHEMA_02_011: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/ 01326 /*Codes_SRS_SCHEMA_02_012: [ If argument reportedPropertyName is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/ 01327 if( 01328 (modelTypeHandle == NULL) || 01329 (reportedPropertyName == NULL) 01330 ) 01331 { 01332 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p", modelTypeHandle, reportedPropertyName); 01333 result = NULL; 01334 } 01335 else 01336 { 01337 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01338 /*Codes_SRS_SCHEMA_02_013: [ If reported property by the name reportedPropertyName exists then Schema_GetModelReportedPropertyByName shall succeed and return a non-NULL value. ]*/ 01339 /*Codes_SRS_SCHEMA_02_014: [ Otherwise Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/ 01340 if((result = VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName))==NULL) 01341 { 01342 LogError("a reported property with name \"%s\" does not exist", reportedPropertyName); 01343 } 01344 else 01345 { 01346 /*return as is*/ 01347 } 01348 } 01349 return result; 01350 } 01351 01352 SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 01353 { 01354 SCHEMA_REPORTED_PROPERTY_HANDLE result; 01355 /*Codes_SRS_SCHEMA_02_015: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/ 01356 if (modelTypeHandle == NULL) 01357 { 01358 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%zu", modelTypeHandle, index); 01359 result = NULL; 01360 } 01361 else 01362 { 01363 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01364 01365 /*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. ]*/ 01366 /*Codes_SRS_SCHEMA_02_017: [ Otherwise Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/ 01367 if ((result = VECTOR_element(modelType->reportedProperties, index)) == NULL) 01368 { 01369 LogError("index %zu is invalid", index); 01370 } 01371 else 01372 { 01373 /*return as is*/ 01374 } 01375 } 01376 return result; 01377 } 01378 01379 SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 01380 { 01381 SCHEMA_PROPERTY_HANDLE result; 01382 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01383 01384 /* 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.] */ 01385 if ((modelTypeHandle == NULL) || 01386 (index >= modelType->PropertyCount)) 01387 { 01388 result = NULL; 01389 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01390 } 01391 else 01392 { 01393 /* Tests_SRS_SCHEMA_99_093: [Schema_GetModelProperty shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the model type identified by modelTypeHandle and matching the index number provided by the index argument.] */ 01394 /* Codes_SRS_SCHEMA_99_097: [index is zero based, and the order in which actions were added shall be the index in which they will be retrieved.] */ 01395 result = modelType->Properties[index]; 01396 } 01397 01398 return result; 01399 } 01400 01401 SCHEMA_ACTION_HANDLE Schema_GetModelActionByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName) 01402 { 01403 SCHEMA_ACTION_HANDLE result; 01404 01405 /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */ 01406 if ((modelTypeHandle == NULL) || 01407 (actionName == NULL)) 01408 { 01409 result = NULL; 01410 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01411 } 01412 else 01413 { 01414 size_t i; 01415 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01416 01417 /* 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.] */ 01418 for (i = 0; i < modelType->ActionCount; i++) 01419 { 01420 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i]; 01421 if (strcmp(modelAction->ActionName, actionName) == 0) 01422 { 01423 break; 01424 } 01425 } 01426 01427 if (i == modelType->ActionCount) 01428 { 01429 /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */ 01430 result = NULL; 01431 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND)); 01432 } 01433 else 01434 { 01435 result = modelType->Actions[i]; 01436 } 01437 } 01438 01439 return result; 01440 } 01441 01442 static bool matchModelMethod(const void* element, const void* value) 01443 { 01444 /*element is a pointer to SCHEMA_METHOD_HANDLE_DATA*/ 01445 const SCHEMA_METHOD_HANDLE* decodedElement = (const SCHEMA_METHOD_HANDLE* )element; 01446 const char* name = (const char*)value; 01447 return (strcmp((*decodedElement)->methodName, name) == 0); 01448 } 01449 01450 SCHEMA_METHOD_HANDLE Schema_GetModelMethodByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName) 01451 { 01452 SCHEMA_METHOD_HANDLE result; 01453 01454 /*Codes_SRS_SCHEMA_02_115: [ If modelTypeHandle is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/ 01455 /*Codes_SRS_SCHEMA_02_116: [ If methodName is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/ 01456 if ((modelTypeHandle == NULL) || 01457 (methodName == NULL)) 01458 { 01459 result = NULL; 01460 LogError("invalid arguments SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName); 01461 } 01462 else 01463 { 01464 /*Codes_SRS_SCHEMA_02_117: [ If a method with the name methodName exists then Schema_GetModelMethodByName shall succeed and returns its handle. ]*/ 01465 SCHEMA_METHOD_HANDLE* found = VECTOR_find_if(modelTypeHandle->methods, matchModelMethod, methodName); 01466 if (found == NULL) 01467 { 01468 /*Codes_SRS_SCHEMA_02_118: [ Otherwise, Schema_GetModelMethodByName shall fail and return NULL. ]*/ 01469 LogError("no such method by name = %s", methodName); 01470 result = NULL; 01471 } 01472 else 01473 { 01474 result = *found; 01475 } 01476 } 01477 01478 return result; 01479 } 01480 01481 SCHEMA_RESULT Schema_GetModelActionCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* actionCount) 01482 { 01483 SCHEMA_RESULT result; 01484 01485 /* Codes_SRS_SCHEMA_99_045:[If any of the modelTypeHandle or actionCount arguments is NULL, Schema_GetModelActionCount shall return SCHEMA_INVALID_ARG.] */ 01486 if ((modelTypeHandle == NULL) || 01487 (actionCount == NULL)) 01488 { 01489 result = SCHEMA_INVALID_ARG; 01490 LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01491 } 01492 else 01493 { 01494 /* Codes_SRS_SCHEMA_99_042:[Schema_GetModelActionCount shall provide the total number of actions defined in a model type identified by the modelTypeHandle.] */ 01495 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01496 01497 /* Codes_SRS_SCHEMA_99_043:[The count shall be provided via the out argument actionCount.] */ 01498 *actionCount = modelType->ActionCount; 01499 01500 /* Codes_SRS_SCHEMA_99_044:[On success, Schema_GetModelActionCount shall return SCHEMA_OK.] */ 01501 result = SCHEMA_OK; 01502 } 01503 01504 return result; 01505 } 01506 01507 SCHEMA_ACTION_HANDLE Schema_GetModelActionByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 01508 { 01509 SCHEMA_ACTION_HANDLE result; 01510 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 01511 01512 /* 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.] */ 01513 if ((modelType == NULL) || 01514 (index >= modelType->ActionCount)) 01515 { 01516 result = NULL; 01517 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01518 } 01519 else 01520 { 01521 /* Codes_SRS_SCHEMA_99_047:[Schema_GetModelAction shall return a non-NULL SCHEMA_ACTION_HANDLE corresponding to the model type identified by modelTypeHandle and matching the index number provided by the index argument.] */ 01522 /* Codes_SRS_SCHEMA_99_096: [index is zero based and the order in which actions were added shall be the index in which they will be retrieved.] */ 01523 result = modelType->Actions[index]; 01524 } 01525 01526 return result; 01527 } 01528 01529 const char* Schema_GetModelActionName(SCHEMA_ACTION_HANDLE actionHandle) 01530 { 01531 const char* result; 01532 01533 /* Codes_SRS_SCHEMA_99_050:[If the actionHandle is NULL, Schema_GetModelActionName shall return NULL.] */ 01534 if (actionHandle == NULL) 01535 { 01536 result = NULL; 01537 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01538 } 01539 else 01540 { 01541 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; 01542 /* Codes_SRS_SCHEMA_99_049:[Schema_GetModelActionName shall return the action name for a given action handle.] */ 01543 result = action->ActionName; 01544 } 01545 01546 return result; 01547 } 01548 01549 SCHEMA_RESULT Schema_GetModelActionArgumentCount(SCHEMA_ACTION_HANDLE actionHandle, size_t* argumentCount) 01550 { 01551 SCHEMA_RESULT result; 01552 01553 /* Codes_SRS_SCHEMA_99_054:[If any argument is NULL, Schema_GetModelActionArgumentCount shall return SCHEMA_INVALID_ARG.] */ 01554 if ((actionHandle == NULL) || 01555 (argumentCount == NULL)) 01556 { 01557 result = SCHEMA_INVALID_ARG; 01558 LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01559 } 01560 else 01561 { 01562 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; 01563 01564 /* Codes_SRS_SCHEMA_99_051:[Schema_GetModelActionArgumentCount shall provide the number of arguments for a specific schema action identified by actionHandle.] */ 01565 /* Codes_SRS_SCHEMA_99_052:[The argument count shall be provided via the out argument argumentCount.] */ 01566 *argumentCount = modelAction->ArgumentCount; 01567 01568 /* Codes_SRS_SCHEMA_99_053:[On success, Schema_GetModelActionArgumentCount shall return SCHEMA_OK.] */ 01569 result = SCHEMA_OK; 01570 } 01571 01572 return result; 01573 } 01574 01575 SCHEMA_RESULT Schema_GetModelMethodArgumentCount(SCHEMA_METHOD_HANDLE methodHandle, size_t* argumentCount) 01576 { 01577 SCHEMA_RESULT result; 01578 01579 /*Codes_SRS_SCHEMA_02_119: [ If methodHandle is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/ 01580 /*Codes_SRS_SCHEMA_02_120: [ If argumentCount is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/ 01581 if ((methodHandle == NULL) || 01582 (argumentCount == NULL)) 01583 { 01584 result = SCHEMA_INVALID_ARG; 01585 LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01586 } 01587 else 01588 { 01589 /*Codes_SRS_SCHEMA_02_121: [ Otherwise, Schema_GetModelMethodArgumentCount shall succeed, return in argumentCount the number of arguments for the method and return SCHEMA_OK. ]*/ 01590 *argumentCount = VECTOR_size(methodHandle->methodArguments); 01591 result = SCHEMA_OK; 01592 } 01593 01594 return result; 01595 } 01596 01597 01598 SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByName(SCHEMA_ACTION_HANDLE actionHandle, const char* actionArgumentName) 01599 { 01600 SCHEMA_ACTION_ARGUMENT_HANDLE result; 01601 01602 /* 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.] */ 01603 if ((actionHandle == NULL) || 01604 (actionArgumentName == NULL)) 01605 { 01606 result = NULL; 01607 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01608 } 01609 else 01610 { 01611 /* 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.] */ 01612 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; 01613 size_t i; 01614 01615 for (i = 0; i < modelAction->ArgumentCount; i++) 01616 { 01617 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)modelAction->ArgumentHandles[i]; 01618 if (strcmp(actionArgument->Name, actionArgumentName) == 0) 01619 { 01620 break; 01621 } 01622 } 01623 01624 if (i == modelAction->ArgumentCount) 01625 { 01626 /* 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.] */ 01627 result = NULL; 01628 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND)); 01629 } 01630 else 01631 { 01632 /* Codes_SRS_SCHEMA_99_117: [Schema_GetModelActionArgumentByName shall return a non-NULL handle corresponding to an action argument identified by the actionHandle and actionArgumentName.] */ 01633 result = modelAction->ArgumentHandles[i]; 01634 } 01635 } 01636 01637 return result; 01638 } 01639 01640 SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByIndex(SCHEMA_ACTION_HANDLE actionHandle, size_t argumentIndex) 01641 { 01642 SCHEMA_ACTION_ARGUMENT_HANDLE result; 01643 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle; 01644 01645 /* 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.] */ 01646 if ((actionHandle == NULL) || 01647 (argumentIndex >= modelAction->ArgumentCount)) 01648 { 01649 result = NULL; 01650 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01651 } 01652 else 01653 { 01654 /* Codes_SRS_SCHEMA_99_055:[Schema_GetModelActionArgument shall return a non-NULL SCHEMA_ACTION_ARGUMENT_HANDLE corresponding to the action type identified by actionHandle and matching the index number provided by the argumentIndex argument.] */ 01655 result = modelAction->ArgumentHandles[argumentIndex]; 01656 } 01657 01658 return result; 01659 } 01660 01661 SCHEMA_METHOD_ARGUMENT_HANDLE Schema_GetModelMethodArgumentByIndex(SCHEMA_METHOD_HANDLE methodHandle, size_t argumentIndex) 01662 { 01663 SCHEMA_METHOD_ARGUMENT_HANDLE result; 01664 01665 /*Codes_SRS_SCHEMA_02_122: [ If methodHandle is NULL then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/ 01666 if (methodHandle == NULL) 01667 { 01668 result = NULL; 01669 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01670 } 01671 else 01672 { 01673 /*Codes_SRS_SCHEMA_02_123: [ If argumentIndex does not exist then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/ 01674 SCHEMA_METHOD_ARGUMENT_HANDLE *temp = VECTOR_element(methodHandle->methodArguments, argumentIndex); 01675 if (temp == NULL) 01676 { 01677 result = NULL; 01678 } 01679 else 01680 { 01681 /*Codes_SRS_SCHEMA_02_124: [ Otherwise, Schema_GetModelMethodArgumentByIndex shall succeed and return a non-NULL value. ]*/ 01682 result = *temp; 01683 } 01684 } 01685 01686 return result; 01687 } 01688 01689 01690 const char* Schema_GetActionArgumentName(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle) 01691 { 01692 const char* result; 01693 /* Codes_SRS_SCHEMA_99_114: [Schema_GetActionArgumentName shall return NULL if actionArgumentHandle is NULL.] */ 01694 if (actionArgumentHandle == NULL) 01695 { 01696 result = NULL; 01697 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01698 } 01699 else 01700 { 01701 /* Codes_SRS_SCHEMA_99_113: [Schema_GetActionArgumentName shall return the argument name identified by the actionArgumentHandle.] */ 01702 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle; 01703 result = actionArgument->Name; 01704 } 01705 return result; 01706 } 01707 01708 const char* Schema_GetMethodArgumentName(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle) 01709 { 01710 const char* result; 01711 /*Codes_SRS_SCHEMA_02_125: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentName shall fail and return NULL. ]*/ 01712 if (methodArgumentHandle == NULL) 01713 { 01714 result = NULL; 01715 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01716 } 01717 else 01718 { 01719 /*Codes_SRS_SCHEMA_02_126: [ Otherwise, Schema_GetMethodArgumentName shall succeed and return a non-NULL value. ]*/ 01720 result = methodArgumentHandle->Name; 01721 } 01722 return result; 01723 } 01724 01725 01726 const char* Schema_GetActionArgumentType(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle) 01727 { 01728 const char* result; 01729 /* Codes_SRS_SCHEMA_99_116: [Schema_GetActionArgumentType shall return NULL if actionArgumentHandle is NULL.] */ 01730 if (actionArgumentHandle == NULL) 01731 { 01732 result = NULL; 01733 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01734 } 01735 else 01736 { 01737 /* Codes_SRS_SCHEMA_99_115: [Schema_GetActionArgumentType shall return the argument type identified by the actionArgumentHandle.] */ 01738 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle; 01739 result = actionArgument->Type; 01740 } 01741 return result; 01742 } 01743 01744 const char* Schema_GetMethodArgumentType(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle) 01745 { 01746 const char* result; 01747 /*Codes_SRS_SCHEMA_02_127: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentType shall fail and return NULL. ]*/ 01748 if (methodArgumentHandle == NULL) 01749 { 01750 result = NULL; 01751 LogError("invalid argument SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle=%p", methodArgumentHandle); 01752 } 01753 else 01754 { 01755 /*Codes_SRS_SCHEMA_02_128: [ Otherwise, Schema_GetMethodArgumentType shall succeed and return a non-NULL value. ]*/ 01756 result = methodArgumentHandle->Type; 01757 } 01758 return result; 01759 } 01760 01761 01762 SCHEMA_STRUCT_TYPE_HANDLE Schema_CreateStructType(SCHEMA_HANDLE schemaHandle, const char* typeName) 01763 { 01764 SCHEMA_STRUCT_TYPE_HANDLE result; 01765 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 01766 01767 /* Codes_SRS_SCHEMA_99_060:[If any of the arguments is NULL, Schema_CreateStructType shall return NULL.] */ 01768 if ((schema == NULL) || 01769 (typeName == NULL)) 01770 { 01771 result = NULL; 01772 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01773 } 01774 else 01775 { 01776 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType; 01777 size_t i; 01778 01779 /* Codes_SRS_SCHEMA_99_061:[If a struct type with the same name already exists, Schema_CreateStructType shall return NULL.] */ 01780 for (i = 0; i < schema->StructTypeCount; i++) 01781 { 01782 structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i]; 01783 if (strcmp(structType->Name, typeName) == 0) 01784 { 01785 break; 01786 } 01787 } 01788 01789 if (i < schema->StructTypeCount) 01790 { 01791 result = NULL; 01792 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT)); 01793 } 01794 else 01795 { 01796 SCHEMA_STRUCT_TYPE_HANDLE* newStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE*)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * (schema->StructTypeCount + 1)); 01797 if (newStructTypes == NULL) 01798 { 01799 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */ 01800 result = NULL; 01801 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 01802 } 01803 else 01804 { 01805 schema->StructTypes = newStructTypes; 01806 if ((structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)malloc(sizeof(SCHEMA_STRUCT_TYPE_HANDLE_DATA))) == NULL) 01807 { 01808 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */ 01809 result = NULL; 01810 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 01811 } 01812 else if (mallocAndStrcpy_s((char**)&structType->Name, typeName) != 0) 01813 { 01814 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */ 01815 result = NULL; 01816 free(structType); 01817 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 01818 } 01819 else 01820 { 01821 /* Codes_SRS_SCHEMA_99_057:[Schema_CreateStructType shall create a new struct type and return a handle to it.] */ 01822 schema->StructTypes[schema->StructTypeCount] = structType; 01823 schema->StructTypeCount++; 01824 structType->PropertyCount = 0; 01825 structType->Properties = NULL; 01826 01827 /* Codes_SRS_SCHEMA_99_058:[On success, a non-NULL handle shall be returned.] */ 01828 result = (SCHEMA_STRUCT_TYPE_HANDLE)structType; 01829 } 01830 01831 /* If possible, reduce the memory of over allocation */ 01832 if (result == NULL) 01833 { 01834 if (schema->StructTypeCount > 0) 01835 { 01836 SCHEMA_STRUCT_TYPE_HANDLE *oldStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE *)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * schema->StructTypeCount); 01837 if (oldStructTypes == NULL) 01838 { 01839 result = NULL; 01840 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR)); 01841 } 01842 else 01843 { 01844 schema->StructTypes = oldStructTypes; 01845 } 01846 } 01847 else 01848 { 01849 schema->StructTypes = NULL; 01850 } 01851 } 01852 } 01853 } 01854 } 01855 01856 return result; 01857 } 01858 01859 const char* Schema_GetStructTypeName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle) 01860 { 01861 const char* result; 01862 01863 /* Codes_SRS_SCHEMA_99_136: [If structTypeHandle is NULL, Schema_GetStructTypeName shall return NULL.] */ 01864 if (structTypeHandle == NULL) 01865 { 01866 result = NULL; 01867 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01868 } 01869 else 01870 { 01871 /* Codes_SRS_SCHEMA_99_135: [Schema_GetStructTypeName shall return the name of a struct type identified by the structTypeHandle argument.] */ 01872 result = ((SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle)->Name; 01873 } 01874 01875 return result; 01876 } 01877 01878 SCHEMA_RESULT Schema_GetStructTypeCount(SCHEMA_HANDLE schemaHandle, size_t* structTypeCount) 01879 { 01880 SCHEMA_RESULT result; 01881 01882 /* Codes_SRS_SCHEMA_99_140: [Schema_GetStructTypeCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */ 01883 if ((schemaHandle == NULL) || 01884 (structTypeCount == NULL)) 01885 { 01886 result = SCHEMA_INVALID_ARG; 01887 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01888 } 01889 else 01890 { 01891 /* Codes_SRS_SCHEMA_99_137: [Schema_GetStructTypeCount shall provide the number of structs defined in the schema identified by schemaHandle.] */ 01892 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 01893 /* Codes_SRS_SCHEMA_99_138: [The count shall be provided via the out argument structTypeCount.] */ 01894 *structTypeCount = schema->StructTypeCount; 01895 /* Codes_SRS_SCHEMA_99_139: [On success, Schema_GetStructTypeCount shall return SCHEMA_OK.] */ 01896 result = SCHEMA_OK; 01897 } 01898 01899 return result; 01900 } 01901 01902 SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByName(SCHEMA_HANDLE schemaHandle, const char* name) 01903 { 01904 SCHEMA_STRUCT_TYPE_HANDLE result; 01905 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 01906 01907 /* 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.] */ 01908 if ((schemaHandle == NULL) || 01909 (name == NULL)) 01910 { 01911 result = NULL; 01912 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01913 } 01914 else 01915 { 01916 size_t i; 01917 01918 /* 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.] */ 01919 for (i = 0; i < schema->StructTypeCount; i++) 01920 { 01921 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i]; 01922 if (strcmp(structType->Name, name) == 0) 01923 { 01924 break; 01925 } 01926 } 01927 01928 if (i == schema->StructTypeCount) 01929 { 01930 /* 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.] */ 01931 result = NULL; 01932 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND)); 01933 } 01934 else 01935 { 01936 result = schema->StructTypes[i]; 01937 } 01938 } 01939 01940 return result; 01941 } 01942 01943 SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByIndex(SCHEMA_HANDLE schemaHandle, size_t index) 01944 { 01945 SCHEMA_STRUCT_TYPE_HANDLE result; 01946 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 01947 01948 /* 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.] */ 01949 /* 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.] */ 01950 if ((schemaHandle == NULL) || 01951 (index >= schema->StructTypeCount)) 01952 { 01953 result = NULL; 01954 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 01955 } 01956 else 01957 { 01958 01959 /* Codes_SRS_SCHEMA_99_141: [Schema_GetStructTypeByIndex shall return a non-NULL SCHEMA_STRUCT_TYPE_HANDLE corresponding to the struct type identified by schemaHandle and matching the index number provided by the index argument.] */ 01960 /* 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.] */ 01961 result = schema->StructTypes[index]; 01962 } 01963 return result; 01964 } 01965 01966 SCHEMA_RESULT Schema_AddStructTypeProperty(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName, const char* propertyType) 01967 { 01968 SCHEMA_RESULT result; 01969 01970 /* Codes_SRS_SCHEMA_99_072:[If any of the arguments is NULL, Schema_AddStructTypeProperty shall return SCHEMA_INVALID_ARG.] */ 01971 if ((structTypeHandle == NULL) || 01972 (propertyName == NULL) || 01973 (propertyType == NULL)) 01974 { 01975 result = SCHEMA_INVALID_ARG; 01976 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01977 } 01978 else 01979 { 01980 size_t i; 01981 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; 01982 01983 /* 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.] */ 01984 for (i = 0; i < structType->PropertyCount; i++) 01985 { 01986 SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i]; 01987 if (strcmp(property->PropertyName, propertyName) == 0) 01988 { 01989 break; 01990 } 01991 } 01992 01993 if (i < structType->PropertyCount) 01994 { 01995 result = SCHEMA_DUPLICATE_ELEMENT; 01996 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 01997 } 01998 else 01999 { 02000 SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (structType->PropertyCount + 1)); 02001 if (newProperties == NULL) 02002 { 02003 result = SCHEMA_ERROR; 02004 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02005 } 02006 else 02007 { 02008 SCHEMA_PROPERTY_HANDLE_DATA* newProperty; 02009 02010 structType->Properties = newProperties; 02011 if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL) 02012 { 02013 result = SCHEMA_ERROR; 02014 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02015 } 02016 else 02017 { 02018 if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, propertyName) != 0) 02019 { 02020 free(newProperty); 02021 result = SCHEMA_ERROR; 02022 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02023 } 02024 else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, propertyType) != 0) 02025 { 02026 free((void*)newProperty->PropertyName); 02027 free(newProperty); 02028 result = SCHEMA_ERROR; 02029 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02030 } 02031 else 02032 { 02033 /* Codes_SRS_SCHEMA_99_070:[Schema_AddStructTypeProperty shall add one property to the struct type identified by structTypeHandle.] */ 02034 structType->Properties[structType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty; 02035 structType->PropertyCount++; 02036 02037 /* Codes_SRS_SCHEMA_99_071:[On success, Schema_AddStructTypeProperty shall return SCHEMA_OK.] */ 02038 result = SCHEMA_OK; 02039 } 02040 } 02041 02042 /* If possible, reduce the memory of over allocation */ 02043 if (result != SCHEMA_OK) 02044 { 02045 if (structType->PropertyCount > 0) 02046 { 02047 SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * structType->PropertyCount); 02048 if (oldProperties == NULL) 02049 { 02050 result = SCHEMA_ERROR; 02051 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02052 } 02053 else 02054 { 02055 structType->Properties = oldProperties; 02056 } 02057 } 02058 else 02059 { 02060 structType->Properties = NULL; 02061 } 02062 } 02063 } 02064 } 02065 } 02066 02067 return result; 02068 } 02069 02070 SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName) 02071 { 02072 SCHEMA_PROPERTY_HANDLE result; 02073 02074 /* Codes_SRS_SCHEMA_99_076:[Schema_GetStructTypePropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */ 02075 if ((structTypeHandle == NULL) || 02076 (propertyName == NULL)) 02077 { 02078 result = NULL; 02079 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02080 } 02081 else 02082 { 02083 size_t i; 02084 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; 02085 02086 for (i = 0; i < structType->PropertyCount; i++) 02087 { 02088 SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i]; 02089 if (strcmp(modelProperty->PropertyName, propertyName) == 0) 02090 { 02091 break; 02092 } 02093 } 02094 02095 /* Codes_SRS_SCHEMA_99_076:[Schema_GetStructTypePropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */ 02096 if (i == structType->PropertyCount) 02097 { 02098 result = NULL; 02099 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND)); 02100 } 02101 /* Codes_SRS_SCHEMA_99_075:[Schema_GetStructTypePropertyByName shall return a non-NULL handle corresponding to a property identified by the structTypeHandle and propertyName.] */ 02102 else 02103 { 02104 result = structType->Properties[i]; 02105 } 02106 } 02107 02108 return result; 02109 } 02110 02111 SCHEMA_RESULT Schema_GetStructTypePropertyCount(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t* propertyCount) 02112 { 02113 SCHEMA_RESULT result; 02114 02115 /* Codes_SRS_SCHEMA_99_079: [Schema_GetStructTypePropertyCount shall return SCHEMA_INVALID_ARG if any of the structlTypeHandle or propertyCount arguments is NULL.] */ 02116 if ((structTypeHandle == NULL) || 02117 (propertyCount == NULL)) 02118 { 02119 result = SCHEMA_INVALID_ARG; 02120 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02121 } 02122 else 02123 { 02124 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; 02125 02126 /* 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.] */ 02127 /* Codes_SRS_SCHEMA_99_081: [The count shall be provided via the out argument propertyCount.] */ 02128 *propertyCount = structType->PropertyCount; 02129 02130 /* Codes_SRS_SCHEMA_99_078: [On success, Schema_ GetStructTypePropertyCount shall return SCHEMA_OK.] */ 02131 result = SCHEMA_OK; 02132 } 02133 02134 return result; 02135 } 02136 02137 SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByIndex(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t index) 02138 { 02139 SCHEMA_PROPERTY_HANDLE result; 02140 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle; 02141 02142 /* Codes_SRS_SCHEMA_99_083: [Schema_ GetStructTypeProperty shall return NULL if the index specified is outside the valid range, if structTypeHandle argument is NULL] */ 02143 if ((structTypeHandle == NULL) || 02144 (index >= structType->PropertyCount)) 02145 { 02146 result = NULL; 02147 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02148 } 02149 else 02150 { 02151 /* Codes_SRS_SCHEMA_99_082: [Schema_GetStructTypeProperty shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the struct type identified by strutTypeHandle and matching the index number provided by the index argument.] */ 02152 /* Codes_SRS_SCHEMA_99_098: [index is zero based and the order in which actions were added shall be the index in which they will be retrieved.] */ 02153 result = structType->Properties[index]; 02154 } 02155 02156 return result; 02157 } 02158 02159 const char* Schema_GetPropertyName(SCHEMA_PROPERTY_HANDLE propertyHandle) 02160 { 02161 const char* result; 02162 02163 /* Codes_SRS_SCHEMA_99_086: [If propertyHandle is NULL, Schema_GetPropertyName shall return NULL.] */ 02164 if (propertyHandle == NULL) 02165 { 02166 result = NULL; 02167 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02168 } 02169 else 02170 { 02171 SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle; 02172 02173 /* Codes_SRS_SCHEMA_99_085: [Schema_GetPropertyName shall return the property name identified by the propertyHandle.] */ 02174 result = propertyType->PropertyName; 02175 } 02176 02177 return result; 02178 } 02179 02180 const char* Schema_GetPropertyType(SCHEMA_PROPERTY_HANDLE propertyHandle) 02181 { 02182 const char* result; 02183 02184 /* Codes_SRS_SCHEMA_99_088: [If propertyHandle is NULL, Schema_GetPropertyType shall return NULL.] */ 02185 if (propertyHandle == NULL) 02186 { 02187 result = NULL; 02188 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02189 } 02190 else 02191 { 02192 SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle; 02193 02194 /* Codes_SRS_SCHEMA_99_087: [Schema_GetPropertyType shall return the property type identified by the propertyHandle.] */ 02195 result = modelProperty->PropertyType; 02196 } 02197 02198 return result; 02199 } 02200 02201 SCHEMA_RESULT Schema_GetModelCount(SCHEMA_HANDLE schemaHandle, size_t* modelCount) 02202 { 02203 SCHEMA_RESULT result; 02204 /* Codes_SRS_SCHEMA_99_123: [Schema_GetModelCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */ 02205 if ((schemaHandle == NULL) || 02206 (modelCount == NULL) ) 02207 { 02208 result = SCHEMA_INVALID_ARG; 02209 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02210 } 02211 else 02212 { 02213 /* Codes_SRS_SCHEMA_99_120: [Schema_GetModelCount shall provide the number of models defined in the schema identified by schemaHandle.] */ 02214 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 02215 /* Codes_SRS_SCHEMA_99_121: [The count shall be provided via the out argument modelCount.] */ 02216 *modelCount = schema->ModelTypeCount; 02217 /* Codes_SRS_SCHEMA_99_122: [On success, Schema_GetModelCount shall return SCHEMA_OK.] */ 02218 result = SCHEMA_OK; 02219 } 02220 return result; 02221 } 02222 02223 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByName(SCHEMA_HANDLE schemaHandle, const char* modelName) 02224 { 02225 SCHEMA_MODEL_TYPE_HANDLE result; 02226 02227 /* Codes_SRS_SCHEMA_99_125: [Schema_GetModelByName shall return NULL if unable to find a matching model, or if any of the arguments are NULL.] */ 02228 if ((schemaHandle == NULL) || 02229 (modelName == NULL)) 02230 { 02231 result = NULL; 02232 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02233 } 02234 else 02235 { 02236 /* 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.] */ 02237 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 02238 size_t i; 02239 for (i = 0; i < schema->ModelTypeCount; i++) 02240 { 02241 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[i]; 02242 if (strcmp(modelName, modelType->Name)==0) 02243 { 02244 break; 02245 } 02246 } 02247 if (i == schema->ModelTypeCount) 02248 { 02249 /* Codes_SRS_SCHEMA_99_125: [Schema_GetModelByName shall return NULL if unable to find a matching model, or if any of the arguments are NULL.] */ 02250 result = NULL; 02251 } 02252 else 02253 { 02254 result = schema->ModelTypes[i]; 02255 } 02256 } 02257 return result; 02258 } 02259 02260 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByIndex(SCHEMA_HANDLE schemaHandle, size_t index) 02261 { 02262 SCHEMA_MODEL_TYPE_HANDLE result; 02263 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle; 02264 02265 /* 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.] */ 02266 /* 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.] */ 02267 if ((schemaHandle == NULL) || 02268 (index >= schema->ModelTypeCount)) 02269 { 02270 result = NULL; 02271 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02272 } 02273 else 02274 { 02275 02276 /* Codes_SRS_SCHEMA_99_126: [Schema_GetModelByIndex shall return a non-NULL SCHEMA_MODEL_TYPE_HANDLE corresponding to the model identified by schemaHandle and matching the index number provided by the index argument.] */ 02277 /* 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.] */ 02278 result = schema->ModelTypes[index]; 02279 } 02280 return result; 02281 } 02282 02283 /*Codes_SRS_SCHEMA_99_160: [Schema_GetModelName shall return the name of the model identified by modelTypeHandle. If the name cannot be retrieved, then NULL shall be returned.]*/ 02284 const char* Schema_GetModelName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle) 02285 { 02286 const char* result; 02287 if (modelTypeHandle == NULL) 02288 { 02289 result = NULL; 02290 } 02291 else 02292 { 02293 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02294 result = modelType->Name; 02295 } 02296 return result; 02297 } 02298 02299 /*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.]*/ 02300 SCHEMA_RESULT Schema_AddModelModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, SCHEMA_MODEL_TYPE_HANDLE modelType, size_t offset, pfOnDesiredProperty onDesiredProperty) 02301 { 02302 SCHEMA_RESULT result; 02303 /*Codes_SRS_SCHEMA_99_165: [If any of the parameters is NULL then Schema_AddModelModel shall return SCHEMA_INVALID_ARG.]*/ 02304 if ( 02305 (modelTypeHandle == NULL) || 02306 (propertyName == NULL) || 02307 (modelType == NULL) 02308 ) 02309 { 02310 result = SCHEMA_INVALID_ARG; 02311 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG)); 02312 } 02313 else 02314 { 02315 SCHEMA_MODEL_TYPE_HANDLE_DATA* parentModel = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02316 MODEL_IN_MODEL temp; 02317 temp.modelHandle = modelType; 02318 temp.offset = offset; 02319 temp.onDesiredProperty = onDesiredProperty; 02320 if (mallocAndStrcpy_s((char**)&(temp.propertyName), propertyName) != 0) 02321 { 02322 result = SCHEMA_ERROR; 02323 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02324 } 02325 else if (VECTOR_push_back(parentModel->models, &temp, 1) != 0) 02326 { 02327 /*Codes_SRS_SCHEMA_99_174: [The function shall return SCHEMA_ERROR if any other error occurs.]*/ 02328 free((void*)temp.propertyName); 02329 result = SCHEMA_ERROR; 02330 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02331 } 02332 else 02333 { 02334 /*Codes_SRS_SCHEMA_99_164: [If the function succeeds, then the return value shall be SCHEMA_OK.]*/ 02335 02336 result = SCHEMA_OK; 02337 } 02338 } 02339 return result; 02340 } 02341 02342 02343 SCHEMA_RESULT Schema_GetModelModelCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* modelCount) 02344 { 02345 SCHEMA_RESULT result; 02346 /*Codes_SRS_SCHEMA_99_169: [If any of the parameters is NULL, then the function shall return SCHEMA_INVALID_ARG.]*/ 02347 if ( 02348 (modelTypeHandle == NULL) || 02349 (modelCount == NULL) 02350 ) 02351 { 02352 result = SCHEMA_INVALID_ARG; 02353 LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, result)); 02354 } 02355 else 02356 { 02357 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02358 /*Codes_SRS_SCHEMA_99_167: [Schema_GetModelModelCount shall return in parameter modelCount the number of models inserted in the model identified by parameter modelTypeHandle.]*/ 02359 *modelCount = VECTOR_size(model->models); 02360 /*SRS_SCHEMA_99_168: [If the function succeeds, it shall return SCHEMA_OK.]*/ 02361 result = SCHEMA_OK; 02362 } 02363 return result; 02364 } 02365 02366 static bool matchModelName(const void* element, const void* value) 02367 { 02368 MODEL_IN_MODEL* decodedElement = (MODEL_IN_MODEL*)element; 02369 const char* name = (const char*)value; 02370 return (strcmp(decodedElement->propertyName, name) == 0); 02371 } 02372 02373 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) 02374 { 02375 SCHEMA_MODEL_TYPE_HANDLE result; 02376 if ( 02377 (modelTypeHandle == NULL) || 02378 (propertyName == NULL) 02379 ) 02380 { 02381 /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/ 02382 result = NULL; 02383 LogError("error SCHEMA_INVALID_ARG"); 02384 } 02385 else 02386 { 02387 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02388 /*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.]*/ 02389 /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/ 02390 void* temp = VECTOR_find_if(model->models, matchModelName, propertyName); 02391 if (temp == NULL) 02392 { 02393 LogError("specified propertyName not found (%s)", propertyName); 02394 result = NULL; 02395 } 02396 else 02397 { 02398 result = ((MODEL_IN_MODEL*)temp)->modelHandle; 02399 } 02400 } 02401 return result; 02402 } 02403 02404 size_t Schema_GetModelModelByName_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) 02405 { 02406 size_t result; 02407 /*Codes_SRS_SCHEMA_02_053: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/ 02408 /*Codes_SRS_SCHEMA_02_054: [ If propertyName is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/ 02409 if ( 02410 (modelTypeHandle == NULL) || 02411 (propertyName == NULL) 02412 ) 02413 { 02414 /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/ 02415 result = 0; 02416 LogError("error SCHEMA_INVALID_ARG"); 02417 } 02418 else 02419 { 02420 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02421 /*Codes_SRS_SCHEMA_02_056: [ If propertyName is not a model then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/ 02422 void* temp = VECTOR_find_if(model->models, matchModelName, propertyName); 02423 if (temp == NULL) 02424 { 02425 LogError("specified propertyName not found (%s)", propertyName); 02426 result = 0; 02427 } 02428 else 02429 { 02430 /*Codes_SRS_SCHEMA_02_055: [ Otherwise Schema_GetModelModelByName_Offset shall succeed and return the offset. ]*/ 02431 result = ((MODEL_IN_MODEL*)temp)->offset; 02432 } 02433 } 02434 return result; 02435 } 02436 02437 pfOnDesiredProperty Schema_GetModelModelByName_OnDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName) 02438 { 02439 pfOnDesiredProperty result; 02440 /*Codes_SRS_SCHEMA_02_086: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/ 02441 /*Codes_SRS_SCHEMA_02_087: [ If propertyName is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/ 02442 if ( 02443 (modelTypeHandle == NULL) || 02444 (propertyName == NULL) 02445 ) 02446 { 02447 result = NULL; 02448 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* propertyName=%p",modelTypeHandle, propertyName); 02449 } 02450 else 02451 { 02452 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02453 void* temp = VECTOR_find_if(model->models, matchModelName, propertyName); 02454 if (temp == NULL) 02455 { 02456 LogError("specified propertyName not found (%s)", propertyName); 02457 result = NULL; 02458 } 02459 else 02460 { 02461 /*Codes_SRS_SCHEMA_02_089: [ Otherwise Schema_GetModelModelByName_OnDesiredProperty shall return the desired property callback. ]*/ 02462 result = ((MODEL_IN_MODEL*)temp)->onDesiredProperty; 02463 } 02464 } 02465 return result; 02466 02467 } 02468 02469 size_t Schema_GetModelModelByIndex_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 02470 { 02471 size_t result; 02472 /*Codes_SRS_SCHEMA_02_057: [ If modelTypeHandle is NULL then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/ 02473 if (modelTypeHandle == NULL) 02474 { 02475 result = 0; 02476 LogError("error SCHEMA_INVALID_ARG"); 02477 } 02478 else 02479 { 02480 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02481 /*Codes_SRS_SCHEMA_02_058: [ If index is not valid then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/ 02482 void* temp = VECTOR_element(model->models, index); 02483 if (temp == 0) 02484 { 02485 LogError("specified index [out of bounds] (%zu)", index); 02486 result = 0; 02487 } 02488 else 02489 { 02490 /*Codes_SRS_SCHEMA_02_059: [ Otherwise Schema_GetModelModelByIndex_Offset shall succeed and return the offset. ]*/ 02491 result = ((MODEL_IN_MODEL*)temp)->offset; 02492 } 02493 } 02494 return result; 02495 } 02496 02497 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 02498 { 02499 SCHEMA_MODEL_TYPE_HANDLE result; 02500 if (modelTypeHandle == NULL) 02501 { 02502 /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/ 02503 result = NULL; 02504 LogError("error SCHEMA_INVALID_ARG"); 02505 } 02506 else 02507 { 02508 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02509 size_t nModelsInModel; 02510 /*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.]*/ 02511 /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/ 02512 nModelsInModel = VECTOR_size(model->models); 02513 if (index < nModelsInModel) 02514 { 02515 result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->modelHandle; 02516 } 02517 else 02518 { 02519 LogError("attempted out of bounds access in array."); 02520 result = NULL; /*out of bounds array access*/ 02521 } 02522 } 02523 return result; 02524 } 02525 02526 const char* Schema_GetModelModelPropertyNameByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 02527 { 02528 const char* result; 02529 if (modelTypeHandle == NULL) 02530 { 02531 /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/ 02532 result = NULL; 02533 } 02534 else 02535 { 02536 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02537 size_t nModelsInModel; 02538 /*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.]*/ 02539 /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/ 02540 nModelsInModel = VECTOR_size(model->models); 02541 if (index < nModelsInModel) 02542 { 02543 result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->propertyName; 02544 } 02545 else 02546 { 02547 LogError("attempted out of bounds access in array."); 02548 result = NULL; /*out of bounds array access*/ 02549 } 02550 } 02551 return result; 02552 } 02553 02554 bool Schema_ModelPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyPath) 02555 { 02556 bool result; 02557 02558 /* Codes_SRS_SCHEMA_99_180: [If any of the arguments are NULL, Schema_ModelPropertyByPathExists shall return false.] */ 02559 if ((modelTypeHandle == NULL) || 02560 (propertyPath == NULL)) 02561 { 02562 LogError("error SCHEMA_INVALID_ARG"); 02563 result = false; 02564 } 02565 else 02566 { 02567 const char* slashPos; 02568 result = false; 02569 02570 /* Codes_SRS_SCHEMA_99_182: [A single slash ('/') at the beginning of the path shall be ignored and the path shall still be valid.] */ 02571 if (*propertyPath == '/') 02572 { 02573 propertyPath++; 02574 } 02575 02576 do 02577 { 02578 const char* endPos; 02579 size_t i; 02580 size_t modelCount; 02581 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02582 02583 /* Codes_SRS_SCHEMA_99_179: [The propertyPath shall be assumed to be in the format model1/model2/.../propertyName.] */ 02584 slashPos = strchr(propertyPath, '/'); 02585 endPos = slashPos; 02586 if (endPos == NULL) 02587 { 02588 endPos = &propertyPath[strlen(propertyPath)]; 02589 } 02590 02591 /* get the child-model */ 02592 modelCount = VECTOR_size(modelType->models); 02593 for (i = 0; i < modelCount; i++) 02594 { 02595 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); 02596 if ((strncmp(childModel->propertyName, propertyPath, endPos - propertyPath) == 0) && 02597 (strlen(childModel->propertyName) == (size_t)(endPos - propertyPath))) 02598 { 02599 /* found */ 02600 modelTypeHandle = childModel->modelHandle; 02601 break; 02602 } 02603 } 02604 02605 if (i < modelCount) 02606 { 02607 /* model found, check if there is more in the path */ 02608 if (slashPos == NULL) 02609 { 02610 /* this is the last one, so this is the thing we were looking for */ 02611 result = true; 02612 break; 02613 } 02614 else 02615 { 02616 /* continue looking, there's more */ 02617 propertyPath = slashPos + 1; 02618 } 02619 } 02620 else 02621 { 02622 /* no model found, let's see if this is a property */ 02623 /* Codes_SRS_SCHEMA_99_178: [The argument propertyPath shall be used to find the leaf property.] */ 02624 for (i = 0; i < modelType->PropertyCount; i++) 02625 { 02626 SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i]; 02627 if ((strncmp(property->PropertyName, propertyPath, endPos - propertyPath) == 0) && 02628 (strlen(property->PropertyName) == (size_t)(endPos - propertyPath))) 02629 { 02630 /* found property */ 02631 /* Codes_SRS_SCHEMA_99_177: [Schema_ModelPropertyByPathExists shall return true if a leaf property exists in the model modelTypeHandle.] */ 02632 result = true; 02633 break; 02634 } 02635 } 02636 02637 break; 02638 } 02639 } while (slashPos != NULL); 02640 } 02641 02642 return result; 02643 } 02644 02645 bool Schema_ModelReportedPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyPath) 02646 { 02647 bool result; 02648 02649 /*Codes_SRS_SCHEMA_02_018: [ If argument modelTypeHandle is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/ 02650 /*Codes_SRS_SCHEMA_02_019: [ If argument reportedPropertyPath is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/ 02651 if ((modelTypeHandle == NULL) || 02652 (reportedPropertyPath == NULL)) 02653 { 02654 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyPath=%s", modelTypeHandle, reportedPropertyPath); 02655 result = false; 02656 } 02657 else 02658 { 02659 const char* slashPos; 02660 02661 /*Codes_SRS_SCHEMA_02_021: [ If the reported property cannot be found Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/ 02662 result = false; 02663 02664 /*Codes_SRS_SCHEMA_02_020: [ reportedPropertyPath shall be assumed to be in the format model1/model2/.../reportedPropertyName. ]*/ 02665 if (*reportedPropertyPath == '/') 02666 { 02667 reportedPropertyPath++; 02668 } 02669 02670 do 02671 { 02672 const char* endPos; 02673 size_t i; 02674 size_t modelCount; 02675 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02676 02677 slashPos = strchr(reportedPropertyPath, '/'); 02678 endPos = slashPos; 02679 if (endPos == NULL) 02680 { 02681 endPos = &reportedPropertyPath[strlen(reportedPropertyPath)]; 02682 } 02683 02684 modelCount = VECTOR_size(modelType->models); 02685 for (i = 0; i < modelCount; i++) 02686 { 02687 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); 02688 if ((strncmp(childModel->propertyName, reportedPropertyPath, endPos - reportedPropertyPath) == 0) && 02689 (strlen(childModel->propertyName) == (size_t)(endPos - reportedPropertyPath))) 02690 { 02691 /* found */ 02692 modelTypeHandle = childModel->modelHandle; 02693 break; 02694 } 02695 } 02696 02697 if (i < modelCount) 02698 { 02699 /* model found, check if there is more in the path */ 02700 if (slashPos == NULL) 02701 { 02702 /*Codes_SRS_SCHEMA_02_022: [ If the path reportedPropertyPath points to a sub-model, Schema_ModelReportedPropertyByPathExists shall succeed and true. ]*/ 02703 /* this is the last one, so this is the thing we were looking for */ 02704 result = true; 02705 break; 02706 } 02707 else 02708 { 02709 /* continue looking, there's more */ 02710 reportedPropertyPath = slashPos + 1; 02711 } 02712 } 02713 else 02714 { 02715 /* no model found, let's see if this is a property */ 02716 result = (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyPath) != NULL); 02717 if (!result) 02718 { 02719 LogError("no such reported property \"%s\"", reportedPropertyPath); 02720 } 02721 break; 02722 } 02723 } while (slashPos != NULL); 02724 } 02725 02726 return result; 02727 } 02728 02729 static bool desiredPropertyExists(const void* element, const void* value) 02730 { 02731 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA**)element; 02732 return (strcmp(desiredProperty->desiredPropertyName, value) == 0); 02733 } 02734 02735 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) 02736 { 02737 SCHEMA_RESULT result; 02738 /*Codes_SRS_SCHEMA_02_024: [ If modelTypeHandle is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 02739 /*Codes_SRS_SCHEMA_02_025: [ If desiredPropertyName is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 02740 /*Codes_SRS_SCHEMA_02_026: [ If desiredPropertyType is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 02741 /*Codes_SRS_SCHEMA_02_048: [ If desiredPropertyFromAGENT_DATA_TYPE is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 02742 /*Codes_SRS_SCHEMA_02_049: [ If desiredPropertyInitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 02743 /*Codes_SRS_SCHEMA_02_050: [ If desiredPropertyDeinitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/ 02744 if ( 02745 (modelTypeHandle == NULL) || 02746 (desiredPropertyName == NULL) || 02747 (desiredPropertyType == NULL) || 02748 (desiredPropertyFromAGENT_DATA_TYPE == NULL) || 02749 (desiredPropertyInitialize == NULL) || 02750 (desiredPropertyDeinitialize== NULL) 02751 ) 02752 { 02753 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", 02754 modelTypeHandle, desiredPropertyName, desiredPropertyType, desiredPropertyFromAGENT_DATA_TYPE, desiredPropertyInitialize, desiredPropertyDeinitialize, offset); 02755 result = SCHEMA_INVALID_ARG; 02756 } 02757 else 02758 { 02759 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02760 /*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. ]*/ 02761 if (VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName) != NULL) 02762 { 02763 /*Codes_SRS_SCHEMA_02_047: [ If the desired property already exists, then Schema_AddModelDesiredProperty shall fail and return SCHEMA_DUPLICATE_ELEMENT. ]*/ 02764 LogError("unable to Schema_AddModelDesiredProperty because a desired property with the same name (%s) already exists", desiredPropertyName); 02765 result = SCHEMA_DUPLICATE_ELEMENT; 02766 } 02767 else 02768 { 02769 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA)); 02770 if (desiredProperty == NULL) 02771 { 02772 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ 02773 LogError("failure in malloc"); 02774 result = SCHEMA_ERROR; 02775 } 02776 else 02777 { 02778 if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyName, desiredPropertyName) != 0) 02779 { 02780 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ 02781 LogError("failure in mallocAndStrcpy_s"); 02782 free(desiredProperty); 02783 result = SCHEMA_ERROR; 02784 } 02785 else 02786 { 02787 if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyType, desiredPropertyType) != 0) 02788 { 02789 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ 02790 LogError("failure in mallocAndStrcpy_s"); 02791 free((void*)desiredProperty->desiredPropertyName); 02792 free(desiredProperty); 02793 result = SCHEMA_ERROR; 02794 } 02795 else 02796 { 02797 if (VECTOR_push_back(handleData->desiredProperties, &desiredProperty, 1) != 0) 02798 { 02799 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/ 02800 LogError("failure in VECTOR_push_back"); 02801 free((void*)desiredProperty->desiredPropertyType); 02802 free((void*)desiredProperty->desiredPropertyName); 02803 free(desiredProperty); 02804 result = SCHEMA_ERROR; 02805 } 02806 else 02807 { 02808 /*Codes_SRS_SCHEMA_02_029: [ Otherwise, Schema_AddModelDesiredProperty shall succeed and return SCHEMA_OK. ]*/ 02809 desiredProperty->desiredPropertyFromAGENT_DATA_TYPE = desiredPropertyFromAGENT_DATA_TYPE; 02810 desiredProperty->desiredPropertInitialize = desiredPropertyInitialize; 02811 desiredProperty->desiredPropertDeinitialize = desiredPropertyDeinitialize; 02812 desiredProperty->onDesiredProperty = onDesiredProperty; /*NULL is a perfectly fine value*/ 02813 desiredProperty->offset = offset; 02814 result = SCHEMA_OK; 02815 } 02816 } 02817 } 02818 } 02819 } 02820 } 02821 return result; 02822 } 02823 02824 02825 SCHEMA_RESULT Schema_GetModelDesiredPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* desiredPropertyCount) 02826 { 02827 SCHEMA_RESULT result; 02828 /*Codes_SRS_SCHEMA_02_030: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ 02829 /*Codes_SRS_SCHEMA_02_031: [ If desiredPropertyCount is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/ 02830 if ( 02831 (modelTypeHandle == NULL) || 02832 (desiredPropertyCount == NULL) 02833 ) 02834 { 02835 LogError("invalid arg: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* desiredPropertyCount=%p", modelTypeHandle, desiredPropertyCount); 02836 result = SCHEMA_INVALID_ARG; 02837 } 02838 else 02839 { 02840 /*Codes_SRS_SCHEMA_02_032: [ Otherwise, Schema_GetModelDesiredPropertyCount shall succeed and write in desiredPropertyCount the existing number of desired properties. ]*/ 02841 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02842 *desiredPropertyCount = VECTOR_size(handleData->desiredProperties); 02843 result = SCHEMA_OK; 02844 } 02845 return result; 02846 } 02847 02848 SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName) 02849 { 02850 SCHEMA_DESIRED_PROPERTY_HANDLE result; 02851 /*Codes_SRS_SCHEMA_02_034: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/ 02852 /*Codes_SRS_SCHEMA_02_035: [ If desiredPropertyName is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/ 02853 if ( 02854 (modelTypeHandle == NULL) || 02855 (desiredPropertyName == NULL) 02856 ) 02857 { 02858 LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p", modelTypeHandle, desiredPropertyName); 02859 result = NULL; 02860 } 02861 else 02862 { 02863 /*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. ]*/ 02864 /*Codes_SRS_SCHEMA_02_037: [ Otherwise, Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/ 02865 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02866 SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName); 02867 if (temp == NULL) 02868 { 02869 LogError("no such desired property by name %s", desiredPropertyName); 02870 result = NULL; 02871 } 02872 else 02873 { 02874 result = *temp; 02875 } 02876 } 02877 return result; 02878 } 02879 02880 SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index) 02881 { 02882 SCHEMA_DESIRED_PROPERTY_HANDLE result; 02883 /*Codes_SRS_SCHEMA_02_038: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/ 02884 if (modelTypeHandle == NULL) 02885 { 02886 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%p", modelTypeHandle, index); 02887 result = NULL; 02888 } 02889 else 02890 { 02891 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02892 /*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. ]*/ 02893 /*Codes_SRS_SCHEMA_02_040: [ Otherwise, Schema_GetModelDesiredPropertyByIndex shall succeed and return a non-NULL value. ]*/ 02894 SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_element(handleData->desiredProperties, index); 02895 if (temp == NULL) 02896 { 02897 LogError("VECTOR_element produced NULL (likely out of bounds index)"); 02898 result = NULL; 02899 } 02900 else 02901 { 02902 result = *temp; 02903 } 02904 } 02905 return result; 02906 } 02907 02908 bool Schema_ModelDesiredPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyPath) 02909 { 02910 bool result; 02911 /*Codes_SRS_SCHEMA_02_041: [ If modelTypeHandle is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/ 02912 /*Codes_SRS_SCHEMA_02_042: [ If desiredPropertyPath is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/ 02913 if ( 02914 (modelTypeHandle == NULL) || 02915 (desiredPropertyPath == NULL) 02916 ) 02917 { 02918 LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyPath=%p", modelTypeHandle, desiredPropertyPath); 02919 result = false; 02920 } 02921 else 02922 { 02923 const char* slashPos; 02924 02925 /*Codes_SRS_SCHEMA_02_044: [ If the desired property cannot be found Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/ 02926 result = false; 02927 02928 /*Codes_SRS_SCHEMA_02_043: [ desiredPropertyPath shall be assumed to be in the format model1/model2/.../desiredPropertyName. ]*/ 02929 if (*desiredPropertyPath == '/') 02930 { 02931 desiredPropertyPath++; 02932 } 02933 02934 do 02935 { 02936 const char* endPos; 02937 size_t i; 02938 size_t modelCount; 02939 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 02940 02941 slashPos = strchr(desiredPropertyPath, '/'); 02942 endPos = slashPos; 02943 if (endPos == NULL) 02944 { 02945 endPos = &desiredPropertyPath[strlen(desiredPropertyPath)]; 02946 } 02947 02948 modelCount = VECTOR_size(modelType->models); 02949 for (i = 0; i < modelCount; i++) 02950 { 02951 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i); 02952 if ((strncmp(childModel->propertyName, desiredPropertyPath, endPos - desiredPropertyPath) == 0) && 02953 (strlen(childModel->propertyName) == (size_t)(endPos - desiredPropertyPath))) 02954 { 02955 /* found */ 02956 modelTypeHandle = childModel->modelHandle; 02957 break; 02958 } 02959 } 02960 02961 if (i < modelCount) 02962 { 02963 /* model found, check if there is more in the path */ 02964 if (slashPos == NULL) 02965 { 02966 /*Codes_SRS_SCHEMA_02_045: [ If the path desiredPropertyPath points to a sub-model, Schema_ModelDesiredPropertyByPathExists shall succeed and true. ]*/ 02967 /* this is the last one, so this is the thing we were looking for */ 02968 result = true; 02969 break; 02970 } 02971 else 02972 { 02973 /* continue looking, there's more */ 02974 desiredPropertyPath = slashPos + 1; 02975 } 02976 } 02977 else 02978 { 02979 /* no model found, let's see if this is a property */ 02980 result = (VECTOR_find_if(modelType->desiredProperties, desiredPropertyExists, desiredPropertyPath) != NULL); 02981 if (!result) 02982 { 02983 LogError("no such desired property \"%s\"", desiredPropertyPath); 02984 } 02985 break; 02986 } 02987 } while (slashPos != NULL); 02988 } 02989 return result; 02990 } 02991 02992 const char* Schema_GetModelDesiredPropertyType(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) 02993 { 02994 const char* result; 02995 /*Codes_SRS_SCHEMA_02_062: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredPropertyType shall fail and return NULL. ]*/ 02996 if (desiredPropertyHandle == NULL) 02997 { 02998 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); 02999 result = NULL; 03000 } 03001 else 03002 { 03003 /*Codes_SRS_SCHEMA_02_063: [ Otherwise, Schema_GetModelDesiredPropertyType shall return the type of the desired property. ]*/ 03004 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; 03005 result = desirePropertyHandleData->desiredPropertyType; 03006 } 03007 return result; 03008 } 03009 03010 pfDesiredPropertyFromAGENT_DATA_TYPE Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) 03011 { 03012 pfDesiredPropertyFromAGENT_DATA_TYPE result; 03013 if (desiredPropertyHandle == NULL) 03014 { 03015 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); 03016 result = NULL; 03017 } 03018 else 03019 { 03020 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; 03021 result = desirePropertyHandleData->desiredPropertyFromAGENT_DATA_TYPE; 03022 } 03023 return result; 03024 } 03025 03026 pfOnDesiredProperty Schema_GetModelDesiredProperty_pfOnDesiredProperty(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) 03027 { 03028 pfOnDesiredProperty result; 03029 /*Codes_SRS_SCHEMA_02_084: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return NULL. ]*/ 03030 if (desiredPropertyHandle == NULL) 03031 { 03032 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); 03033 result = NULL; 03034 } 03035 else 03036 { 03037 /*Codes_SRS_SCHEMA_02_085: [ Otherwise Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return the saved desired property callback. ]*/ 03038 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; 03039 result = desirePropertyHandleData->onDesiredProperty; 03040 } 03041 return result; 03042 } 03043 03044 size_t Schema_GetModelDesiredProperty_offset(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) 03045 { 03046 size_t result; 03047 /*Codes_SRS_SCHEMA_02_060: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_offset shall fail and return 0. ]*/ 03048 if (desiredPropertyHandle == NULL) 03049 { 03050 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); 03051 result = 0; 03052 } 03053 else 03054 { 03055 /*Codes_SRS_SCHEMA_02_061: [ Otherwise Schema_GetModelDesiredProperty_offset shall succeed and return the offset. ]*/ 03056 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; 03057 result = desirePropertyHandleData->offset; 03058 } 03059 return result; 03060 } 03061 03062 static bool modelInModelExists(const void* element, const void* value) 03063 { 03064 MODEL_IN_MODEL* modelInModel = (MODEL_IN_MODEL*)element; 03065 return (strcmp(modelInModel->propertyName, value) == 0); 03066 } 03067 03068 SCHEMA_MODEL_ELEMENT Schema_GetModelElementByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* elementName) 03069 { 03070 SCHEMA_MODEL_ELEMENT result; 03071 /*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. ]*/ 03072 /*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. ]*/ 03073 if ( 03074 (modelTypeHandle == NULL) || 03075 (elementName == NULL) 03076 ) 03077 { 03078 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* elementName=%p", modelTypeHandle, elementName); 03079 result.elementType = SCHEMA_SEARCH_INVALID_ARG; 03080 } 03081 else 03082 { 03083 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle; 03084 03085 SCHEMA_DESIRED_PROPERTY_HANDLE* desiredPropertyHandle = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, elementName); 03086 if (desiredPropertyHandle != NULL) 03087 { 03088 /*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. ]*/ 03089 result.elementType = SCHEMA_DESIRED_PROPERTY; 03090 result.elementHandle.desiredPropertyHandle = *desiredPropertyHandle; 03091 } 03092 else 03093 { 03094 size_t nProcessedProperties = 0; 03095 SCHEMA_PROPERTY_HANDLE_DATA* property = NULL; 03096 for (size_t i = 0; i < handleData->PropertyCount;i++) 03097 { 03098 property = (SCHEMA_PROPERTY_HANDLE_DATA*)(handleData->Properties[i]); 03099 if (strcmp(property->PropertyName, elementName) == 0) 03100 { 03101 i = handleData->PropertyCount; /*found it*/ 03102 } 03103 else 03104 { 03105 nProcessedProperties++; 03106 } 03107 } 03108 03109 if (nProcessedProperties < handleData->PropertyCount) 03110 { 03111 /*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. ]*/ 03112 result.elementType = SCHEMA_PROPERTY; 03113 result.elementHandle.propertyHandle = property; 03114 } 03115 else 03116 { 03117 03118 SCHEMA_REPORTED_PROPERTY_HANDLE* reportedPropertyHandle = VECTOR_find_if(handleData->reportedProperties, reportedPropertyExists, elementName); 03119 if (reportedPropertyHandle != NULL) 03120 { 03121 /*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. ]*/ 03122 result.elementType = SCHEMA_REPORTED_PROPERTY; 03123 result.elementHandle.reportedPropertyHandle = *reportedPropertyHandle; 03124 } 03125 else 03126 { 03127 03128 size_t nProcessedActions = 0; 03129 SCHEMA_ACTION_HANDLE_DATA* actionHandleData = NULL; 03130 for (size_t i = 0;i < handleData->ActionCount; i++) 03131 { 03132 actionHandleData = (SCHEMA_ACTION_HANDLE_DATA*)(handleData->Actions[i]); 03133 if (strcmp(actionHandleData->ActionName, elementName) == 0) 03134 { 03135 i = handleData->ActionCount; /*get out quickly*/ 03136 } 03137 else 03138 { 03139 nProcessedActions++; 03140 } 03141 } 03142 03143 if (nProcessedActions < handleData->ActionCount) 03144 { 03145 /*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. ]*/ 03146 result.elementType = SCHEMA_MODEL_ACTION; 03147 result.elementHandle.actionHandle = actionHandleData; 03148 } 03149 else 03150 { 03151 MODEL_IN_MODEL* modelInModel = VECTOR_find_if(handleData->models, modelInModelExists, elementName); 03152 if (modelInModel != NULL) 03153 { 03154 /*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. ]*/ 03155 result.elementType = SCHEMA_MODEL_IN_MODEL; 03156 result.elementHandle.modelHandle = modelInModel->modelHandle; 03157 } 03158 else 03159 { 03160 /*Codes_SRS_SCHEMA_02_083: [ Otherwise Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_NOT_FOUND. ]*/ 03161 result.elementType = SCHEMA_NOT_FOUND; 03162 } 03163 } 03164 } 03165 } 03166 } 03167 } 03168 return result; 03169 } 03170 03171 pfDesiredPropertyDeinitialize Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) 03172 { 03173 pfDesiredPropertyDeinitialize result; 03174 /*Ccodes_SRS_SCHEMA_02_064: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall fail and return NULL. ]*/ 03175 if (desiredPropertyHandle == NULL) 03176 { 03177 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); 03178 result = NULL; 03179 } 03180 else 03181 { 03182 /*Codes_SRS_SCHEMA_02_065: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall return a non-NULL function pointer. ]*/ 03183 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; 03184 result = handleData->desiredPropertDeinitialize; 03185 } 03186 return result; 03187 } 03188 03189 pfDesiredPropertyInitialize Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle) 03190 { 03191 pfDesiredPropertyInitialize result; 03192 /*Codes_SRS_SCHEMA_02_066: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall fail and return NULL. ]*/ 03193 if (desiredPropertyHandle == NULL) 03194 { 03195 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle); 03196 result = NULL; 03197 } 03198 else 03199 { 03200 /*Codes_SRS_SCHEMA_02_067: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall return a non-NULL function pointer. ]*/ 03201 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle; 03202 result = handleData->desiredPropertInitialize; 03203 } 03204 return result; 03205 } 03206 03207 static bool SchemaHasModel(const SCHEMA_HANDLE* schemaHandle, const char* modelName) 03208 { 03209 return (Schema_GetModelByName(*schemaHandle, modelName) != NULL); 03210 } 03211 03212 03213 SCHEMA_HANDLE Schema_GetSchemaForModel(const char* modelName) 03214 { 03215 SCHEMA_HANDLE result; 03216 /*Codes_SRS_SCHEMA_02_093: [ If modelName is NULL then Schema_GetSchemaForModel shall fail and return NULL. ]*/ 03217 if (modelName == NULL) 03218 { 03219 LogError("invalid arg const char* modelName=%p", modelName); 03220 result = NULL; 03221 } 03222 else 03223 { 03224 /*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. ]*/ 03225 SCHEMA_HANDLE* temp = VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHasModel, modelName); 03226 03227 if (temp == NULL) 03228 { 03229 /*Codes_SRS_SCHEMA_02_095: [ If the model is not found in any schema, then Schema_GetSchemaForModel shall fail and return NULL. ]*/ 03230 LogError("unable to find a schema that has a model named %s", modelName); 03231 result = NULL; 03232 } 03233 else 03234 { 03235 /*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. ]*/ 03236 result = *temp; 03237 } 03238 } 03239 03240 return result; 03241 } 03242 03243 void* Schema_GetMetadata(SCHEMA_HANDLE schemaHandle) 03244 { 03245 void* result; 03246 /*Codes_SRS_SCHEMA_02_091: [ If schemaHandle is NULL then Schema_GetMetadata shall fail and return NULL. ]*/ 03247 if (schemaHandle == NULL) 03248 { 03249 LogError("invalid arg SCHEMA_HANDLE schemaHandle=%p", schemaHandle); 03250 result = NULL; 03251 } 03252 else 03253 { 03254 /*Codes_SRS_SCHEMA_02_092: [ Otherwise, Schema_GetMetadata shall succeed and return the saved metadata pointer. ]*/ 03255 result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->metadata; 03256 } 03257 return result; 03258 }
Generated on Tue Jul 12 2022 19:56:37 by
1.7.2