// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. /** @file serializer.h * @brief The IoT Hub Serializer APIs allows developers to define models for * their devices * * @details The IoT Hub Serializer APIs allows developers to quickly and easily define * models for their devices directly as code, while supporting the required * features for modeling devices (including multiple models and multiple * devices within the same application). For example: * *
*       BEGIN_NAMESPACE(Contoso);
*
*           DECLARE_STRUCT(SystemProperties,
*               ascii_char_ptr, DeviceID,
*               _Bool, Enabled
*           );
*
*           DECLARE_MODEL(VendingMachine,
*
*               WITH_DATA(int, SensorValue),
*
*               WITH_DATA(ascii_char_ptr, ObjectName),
*               WITH_DATA(ascii_char_ptr, ObjectType),
*               WITH_DATA(ascii_char_ptr, Version),
*               WITH_DATA(SystemProperties, SystemProperties),
*               WITH_DATA(ascii_char_ptr_no_quotes, Commands),
*
*               WITH_ACTION(SetItemPrice, ascii_char_ptr, itemId, ascii_char_ptr, price)
*           );
*
*       END_NAMESPACE(Contoso);
*       
*/ #ifndef SERIALIZER_H #define SERIALIZER_H #ifdef __cplusplus #include #include #else #include #include #endif #include "azure_c_shared_utility/gballoc.h" #include "azure_macro_utils/macro_utils.h" #include "iotdevice.h" #include "azure_c_shared_utility/crt_abstractions.h" #include "azure_c_shared_utility/xlogging.h" #include "methodreturn.h" #include "schemalib.h" #include "codefirst.h" #include "agenttypesystem.h" #include "schema.h" #ifdef __cplusplus extern "C" { #endif /* IOT Agent Macros */ /** * @def BEGIN_NAMESPACE(schemaNamespace) * This macro marks the start of a section that declares IOT model * elements (like complex types, etc.). Declarations are typically * placed in header files, so that they can be shared between * translation units. */ #define BEGIN_NAMESPACE(schemaNamespace) \ REFLECTED_END_OF_LIST /** * @def END_NAMESPACE(schemaNamespace) * This macro marks the end of a section that declares IOT model * elements. */ #define END_NAMESPACE(schemaNamespace) \ REFLECTED_LIST_HEAD(schemaNamespace) #define GLOBAL_INITIALIZE_STRUCT_FIELD(structType, destination, type, name) GlobalInitialize_##type((char*)destination+offsetof(structType, name)); #define GLOBAL_DEINITIALIZE_STRUCT_FIELD(structType, destination, type, name) GlobalDeinitialize_##type((char*)destination+offsetof(structType, name)); /** * @def DECLARE_STRUCT(name, ...) * This macro allows the definition of a struct type that can then be used as * part of a model definition. * * @param name Name of the struct * @param element1, element2... Specifies a list of struct members */ #define DECLARE_STRUCT(name, ...) \ typedef struct name##_TAG { \ MU_FOR_EACH_2(INSERT_FIELD_INTO_STRUCT, __VA_ARGS__) \ } name; \ REFLECTED_STRUCT(name) \ MU_FOR_EACH_2_KEEP_1(REFLECTED_FIELD, name, __VA_ARGS__) \ TO_AGENT_DATA_TYPE(name, __VA_ARGS__) \ static AGENT_DATA_TYPES_RESULT FromAGENT_DATA_TYPE_##name(const AGENT_DATA_TYPE* source, name* destination) \ { \ AGENT_DATA_TYPES_RESULT result; \ if(source->type != EDM_COMPLEX_TYPE_TYPE) \ { \ result = AGENT_DATA_TYPES_INVALID_ARG; \ } \ else if(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)) != source->value.edmComplexType.nMembers) \ { \ /*too many or too few fields*/ \ result = AGENT_DATA_TYPES_INVALID_ARG; \ } \ else \ { \ result = AGENT_DATA_TYPES_OK; \ MU_FOR_EACH_2(BUILD_DESTINATION_FIELD, __VA_ARGS__); \ } \ return result; \ } \ static void MU_C2(destroyLocalParameter, name)(name * value) \ { \ MU_FOR_EACH_2_KEEP_1(UNBUILD_DESTINATION_FIELD, value, __VA_ARGS__); \ } \ static void MU_C2(GlobalInitialize_, name)(void* destination) \ { \ MU_FOR_EACH_2_KEEP_2(GLOBAL_INITIALIZE_STRUCT_FIELD, name, destination, __VA_ARGS__); \ } \ static void MU_C2(GlobalDeinitialize_, name)(void* destination) \ { \ MU_FOR_EACH_2_KEEP_2(GLOBAL_DEINITIALIZE_STRUCT_FIELD, name, destination, __VA_ARGS__); \ } \ /** * @def DECLARE_MODEL(name, ...) * This macro allows declaring a model that can be later used to instantiate * a device. * * @param name Specifies the model name * @param element1, element2... Specifies a model element which can be * a property or an action. * - A property is described in a * model by using the WITH_DATA * - An action is described in a * model by using the ::WITH_ACTION * macro. * */ /* WITH_DATA's name argument shall be one of the following data types: */ #define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_ACTION(...) #define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_METHOD(...) #define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_DESIRED_PROPERTY(type, name, ...) MU_IF(MU_COUNT_ARG(__VA_ARGS__), void __VA_ARGS__ (void*);, ) #define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_PROPERTY(...) #define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_REPORTED_PROPERTY(...) #define CREATE_DESIRED_PROPERTY_CALLBACK(...) CREATE_DESIRED_PROPERTY_CALLBACK_##__VA_ARGS__ #define SERIALIZER_REGISTER_NAMESPACE(NAMESPACE) CodeFirst_RegisterSchema(#NAMESPACE, & ALL_REFLECTED(NAMESPACE)) #define DECLARE_MODEL(name, ...) \ REFLECTED_MODEL(name) \ MU_FOR_EACH_1(CREATE_DESIRED_PROPERTY_CALLBACK, __VA_ARGS__) \ typedef struct name { int :1; MU_FOR_EACH_1(BUILD_MODEL_STRUCT, __VA_ARGS__) } name; \ MU_FOR_EACH_1_KEEP_1(CREATE_MODEL_ELEMENT, name, __VA_ARGS__) \ TO_AGENT_DATA_TYPE(name, DROP_FIRST_COMMA_FROM_ARGS(EXPAND_MODEL_ARGS(__VA_ARGS__))) \ int FromAGENT_DATA_TYPE_##name(const AGENT_DATA_TYPE* source, void* destination) \ { \ (void)source; \ (void)destination; \ LogError("SHOULD NOT GET CALLED... EVER"); \ return 0; \ } \ static void MU_C2(GlobalInitialize_, name)(void* destination) \ { \ (void)destination; \ MU_FOR_EACH_1_KEEP_1(CREATE_MODEL_ELEMENT_GLOBAL_INITIALIZE, name, __VA_ARGS__) \ } \ static void MU_C2(GlobalDeinitialize_, name)(void* destination) \ { \ (void)destination; \ MU_FOR_EACH_1_KEEP_1(CREATE_MODEL_ELEMENT_GLOBAL_DEINITIALIZE, name, __VA_ARGS__) \ } \ /** * @def WITH_DATA(type, name) * The ::WITH_DATA macro allows declaring a model property in a model. A * property can be published by using the ::SERIALIZE macro. * * @param type Specifies the property type. Can be any of the following * types: * - int * - double * - float * - long * - int8_t * - uint8_t * - int16_t * - int32_t * - int64_t * - bool * - ascii_char_ptr * - EDM_DATE_TIME_OFFSET * - EDM_GUID * - EDM_BINARY * - Any struct type previously introduced by another ::DECLARE_STRUCT. * * @param name Specifies the property name */ #define WITH_DATA(type, name) MODEL_PROPERTY(type, name) #define WITH_REPORTED_PROPERTY(type, name) MODEL_REPORTED_PROPERTY(type, name) #define WITH_DESIRED_PROPERTY(type, name, ...) MODEL_DESIRED_PROPERTY(type, name, __VA_ARGS__) /** * @def WITH_ACTION(name, ...) * The ::WITH_ACTION macro allows declaring a model action. * * @param name Specifies the action name. * @param argXtype, argXName... Defines the type and name for the Xth * argument of the action. The type can be any of * the primitive types or a struct type. */ #define WITH_ACTION(name, ...) MODEL_ACTION(name, __VA_ARGS__) /** * @def WITH_METHOD(name, ...) * The ::WITH_METHOD macro allows declaring a model method. * * @param name Specifies the method name. * @param argXtype, argXName... Defines the type and name for the Xth * argument of the method. The type can be any of * the primitive types or a struct type. */ #define WITH_METHOD(name, ...) MODEL_METHOD(name, __VA_ARGS__) /** * @def GET_MODEL_HANDLE(schemaNamespace, modelName) * The ::GET_MODEL_HANDLE macro returns a model handle that can be used in * subsequent operations like generating the CSDL schema for the model, * uploading the schema, creating a device, etc. * * @param schemaNamespace The namespace to which the model belongs. * @param modelName The name of the model. */ #define GET_MODEL_HANDLE(schemaNamespace, modelName) \ Schema_GetModelByName(CodeFirst_RegisterSchema(MU_TOSTRING(schemaNamespace), &ALL_REFLECTED(schemaNamespace)), #modelName) #define CREATE_DEVICE_WITH_INCLUDE_PROPERTY_PATH(schemaNamespace, modelName, serializerIncludePropertyPath) \ (modelName*)CodeFirst_CreateDevice(GET_MODEL_HANDLE(schemaNamespace, modelName), &ALL_REFLECTED(schemaNamespace), sizeof(modelName), serializerIncludePropertyPath) #define CREATE_DEVICE_WITHOUT_INCLUDE_PROPERTY_PATH(schemaNamespace, modelName) \ (modelName*)CodeFirst_CreateDevice(GET_MODEL_HANDLE(schemaNamespace, modelName), &ALL_REFLECTED(schemaNamespace), sizeof(modelName), false) #define CREATE_MODEL_INSTANCE(schemaNamespace, ...) \ MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), CREATE_DEVICE_WITH_INCLUDE_PROPERTY_PATH, CREATE_DEVICE_WITHOUT_INCLUDE_PROPERTY_PATH) (schemaNamespace, __VA_ARGS__) #define DESTROY_MODEL_INSTANCE(deviceData) \ CodeFirst_DestroyDevice(deviceData) /** * @def SERIALIZE(destination, destinationSize,...) * This macro produces JSON serialized representation of the properties. * * @param destination Pointer to an @c unsigned @c char* that * will receive the serialized data. * @param destinationSize Pointer to a @c size_t that gets * written with the size in bytes of the * serialized data * @param property1, property2... A list of property values to send. The * order in which the properties appear in * the list does not matter, all values * will be sent together. * */ #define SERIALIZE(destination, destinationSize,...) CodeFirst_SendAsync(destination, destinationSize, MU_COUNT_ARG(__VA_ARGS__) MU_FOR_EACH_1(ADDRESS_MACRO, __VA_ARGS__)) #define SERIALIZE_REPORTED_PROPERTIES(destination, destinationSize,...) CodeFirst_SendAsyncReported(destination, destinationSize, MU_COUNT_ARG(__VA_ARGS__) MU_FOR_EACH_1(ADDRESS_MACRO, __VA_ARGS__)) #define IDENTITY_MACRO(x) ,x #define SERIALIZE_REPORTED_PROPERTIES_FROM_POINTERS(destination, destinationSize, ...) CodeFirst_SendAsyncReported(destination, destinationSize, MU_COUNT_ARG(__VA_ARGS__) MU_FOR_EACH_1(IDENTITY_MACRO, __VA_ARGS__)) /** * @def EXECUTE_COMMAND(device, command) * Any action that is declared in a model must also have an implementation as * a C function. * * @param device Pointer to device data. * @param command Values that match the arguments declared in the model * action. */ #define EXECUTE_COMMAND(device, command) (CodeFirst_ExecuteCommand(device, command)) /** * @def EXECUTE_METHOD(device, methodName, methodPayload) * Any method that is declared in a model must also have an implementation as * a C function. * * @param device Pointer to device data. * @param methodName The method name. * @param methodPayload The method payload. */ #define EXECUTE_METHOD(device, methodName, methodPayload) CodeFirst_ExecuteMethod(device, methodName, methodPayload) /** * @def INGEST_DESIRED_PROPERTIES(device, desiredProperties) * * @param device return of CodeFirst_CreateDevice. * @param desiredProperties a null terminated string containing in JSON format the desired properties */ #define INGEST_DESIRED_PROPERTIES(device, jsonPayload, parseDesiredNode) (CodeFirst_IngestDesiredProperties(device, jsonPayload, parseDesiredNode)) /* Helper macros */ /* These macros remove a useless comma from the beginning of an argument list that looks like: ,x1,y1,x2,y2 */ #ifdef _MSC_VER #define DROP_FIRST_COMMA(N, x) \ x MU_IFCOMMA_NOFIRST(N) #define DROP_IF_EMPTY(N, x) \ MU_IF(MU_COUNT_ARG(x),DROP_FIRST_COMMA(N,x),x) #define DROP_FIRST_COMMA_FROM_ARGS(...) \ MU_FOR_EACH_1_COUNTED(DROP_IF_EMPTY, MU_C1(__VA_ARGS__)) #else #define DROP_FIRST_COMMA_0(N, x) \ x MU_IFCOMMA_NOFIRST(N) #define DROP_FIRST_COMMA_1(N, x) \ x #define DROP_FIRST_COMMA(empty, N, x) \ MU_C2(DROP_FIRST_COMMA_,empty)(N,x) #define DROP_IF_EMPTY(N, x) \ DROP_FIRST_COMMA(MU_ISEMPTY(x),N,x) #define DROP_FIRST_COMMA_FROM_ARGS(...) \ MU_FOR_EACH_1_COUNTED(DROP_IF_EMPTY, __VA_ARGS__) #endif /* These macros expand a sequence of arguments for DECLARE_MODEL that looks like WITH_DATA(x, y), WITH_DATA(x2, y2) to a list of arguments consumed by the macro that marshalls a struct, like: x, y, x2, y2 Actions are discarded, since no marshalling will be done for those when sending state data */ #define TO_AGENT_DT_EXPAND_MODEL_PROPERTY(x, y) ,x,y #define TO_AGENT_DT_EXPAND_MODEL_REPORTED_PROPERTY(x, y) ,x,y #define TO_AGENT_DT_EXPAND_MODEL_DESIRED_PROPERTY(x, y, ...) ,x,y #define TO_AGENT_DT_EXPAND_MODEL_ACTION(...) #define TO_AGENT_DT_EXPAND_MODEL_METHOD(...) #define TO_AGENT_DT_EXPAND_ELEMENT_ARGS(N, ...) TO_AGENT_DT_EXPAND_##__VA_ARGS__ #define EXPAND_MODEL_ARGS(...) \ MU_FOR_EACH_1_COUNTED(TO_AGENT_DT_EXPAND_ELEMENT_ARGS, __VA_ARGS__) #define TO_AGENT_DATA_TYPE(name, ...) \ static AGENT_DATA_TYPES_RESULT ToAGENT_DATA_TYPE_##name(AGENT_DATA_TYPE *destination, const name value) \ { \ AGENT_DATA_TYPES_RESULT result = AGENT_DATA_TYPES_OK; \ size_t iMember = 0; \ const char* memberNames[MU_IF(MU_DIV2(MU_C1(MU_COUNT_ARG(__VA_ARGS__))), MU_DIV2(MU_C1(MU_COUNT_ARG(__VA_ARGS__))), 1)] = { 0 }; \ size_t memberCount = sizeof(memberNames) / sizeof(memberNames[0]); \ (void)value; \ if (memberCount == 0) \ { \ result = AGENT_DATA_TYPES_OK; \ } \ else \ { \ AGENT_DATA_TYPE members[sizeof(memberNames) / sizeof(memberNames[0])]; \ MU_FOR_EACH_2(FIELD_AS_STRING, MU_EXPAND_TWICE(__VA_ARGS__)) \ iMember = 0; \ { \ MU_FOR_EACH_2(CREATE_AGENT_DATA_TYPE, MU_EXPAND_TWICE(__VA_ARGS__)) \ result = ((result == AGENT_DATA_TYPES_OK) && (Create_AGENT_DATA_TYPE_from_Members(destination, #name, sizeof(memberNames) / sizeof(memberNames[0]), memberNames, members) == AGENT_DATA_TYPES_OK)) \ ? AGENT_DATA_TYPES_OK \ : AGENT_DATA_TYPES_ERROR; \ { \ size_t jMember; \ for (jMember = 0; jMember < iMember; jMember++) \ { \ Destroy_AGENT_DATA_TYPE(&members[jMember]); \ } \ } \ } \ } \ return result; \ } #define FIELD_AS_STRING(x,y) memberNames[iMember++] = #y; #define REFLECTED_LIST_HEAD(name) \ static const REFLECTED_DATA_FROM_DATAPROVIDER ALL_REFLECTED(name) = { &MU_C2(REFLECTED_, MU_C1(MU_DEC(__COUNTER__))) }; #define REFLECTED_STRUCT(name) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_STRUCT_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {MU_TOSTRING(name)}, {0}, {0}, {0}, {0}} }; #define REFLECTED_FIELD(XstructName, XfieldType, XfieldName) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_FIELD_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {MU_TOSTRING(XfieldName), MU_TOSTRING(XfieldType), MU_TOSTRING(XstructName)}, {0}, {0}, {0} } }; #define REFLECTED_MODEL(name) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_MODEL_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {0}, {0}, {0}, {MU_TOSTRING(name)} } }; #define REFLECTED_PROPERTY(type, name, modelName) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_PROPERTY_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {0}, {MU_TOSTRING(name), MU_TOSTRING(type), Create_AGENT_DATA_TYPE_From_Ptr_##modelName##name, offsetof(modelName, name), sizeof(type), MU_TOSTRING(modelName)}, {0}, {0} } }; #define REFLECTED_REPORTED_PROPERTY(type, name, modelName) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_REPORTED_PROPERTY_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {MU_TOSTRING(name), MU_TOSTRING(type), Create_AGENT_DATA_TYPE_From_Ptr_##modelName##name, offsetof(modelName, name), sizeof(type), MU_TOSTRING(modelName)}, {0}, {0}, {0}, {0}, {0} } }; #define REFLECTED_DESIRED_PROPERTY_WITH_ON_DESIRED_PROPERTY_CHANGE(type, name, modelName, COUNTER, onDesiredPropertyChange) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(COUNTER))) = { REFLECTION_DESIRED_PROPERTY_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(COUNTER))), { {0}, {onDesiredPropertyChange, DesiredPropertyInitialize_##modelName##name, DesiredPropertyDeinitialize_##modelName##name, MU_TOSTRING(name), MU_TOSTRING(type), (int(*)(const AGENT_DATA_TYPE*, void*))FromAGENT_DATA_TYPE_##type, offsetof(modelName, name), sizeof(type), MU_TOSTRING(modelName)}, {0}, {0}, {0}, {0}, {0}, {0}} }; #define REFLECTED_DESIRED_PROPERTY(type, name, modelName, ...) \ MU_IF(MU_COUNT_ARG(__VA_ARGS__), \ MACRO_UTILS_DELAY(REFLECTED_DESIRED_PROPERTY_WITH_ON_DESIRED_PROPERTY_CHANGE)(type, name, modelName,__COUNTER__, __VA_ARGS__), \ MACRO_UTILS_DELAY(REFLECTED_DESIRED_PROPERTY_WITH_ON_DESIRED_PROPERTY_CHANGE)(type, name, modelName,MU_DEC(__COUNTER__), NULL) \ ) \ #define REFLECTED_ACTION(name, argc, argv, fn, modelName) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_ACTION_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {0}, {0}, {MU_TOSTRING(name), argc, argv, fn, MU_TOSTRING(modelName)}, {0}} }; #define REFLECTED_METHOD(name, argc, argv, fn, modelName) \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_METHOD_TYPE, &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {MU_TOSTRING(name), argc, argv, fn, MU_TOSTRING(modelName)}, {0}, {0}, {0}, {0}, {0}, {0}, {0}} }; #define REFLECTED_END_OF_LIST \ static const REFLECTED_SOMETHING MU_C2(REFLECTED_, __COUNTER__) = { REFLECTION_NOTHING, NULL, { {0},{0}, {0}, {0}, {0}, {0}, {0}, {0}} }; #define EXPAND_MODEL_PROPERTY(type, name) MU_EXPAND_ARGS(MODEL_PROPERTY, type, name) #define EXPAND_MODEL_REPORTED_PROPERTY(type, name) MU_EXPAND_ARGS(MODEL_REPORTED_PROPERTY, type, name) #define EXPAND_MODEL_DESIRED_PROPERTY(type, name, ...) MU_EXPAND_ARGS(MODEL_DESIRED_PROPERTY, type, name, __VA_ARGS__) #define EXPAND_MODEL_ACTION(...) MU_EXPAND_ARGS(MODEL_ACTION, __VA_ARGS__) #define EXPAND_MODEL_METHOD(...) MU_EXPAND_ARGS(MODEL_METHOD, __VA_ARGS__) #define BUILD_MODEL_STRUCT(elem) INSERT_FIELD_FOR_##elem #define CREATE_MODEL_ENTITY(modelName, callType, ...) MU_EXPAND_ARGS(CREATE_##callType(modelName, __VA_ARGS__)) #define CREATE_SOMETHING(modelName, ...) MU_EXPAND_ARGS(CREATE_MODEL_ENTITY(modelName, __VA_ARGS__)) #define CREATE_ELEMENT(modelName, elem) MU_EXPAND_ARGS(CREATE_SOMETHING(modelName, MU_EXPAND_ARGS(EXPAND_##elem))) #define CREATE_MODEL_ELEMENT(modelName, elem) MU_EXPAND_ARGS(CREATE_ELEMENT(modelName, elem)) #define CREATE_MODEL_ENTITY_GLOBAL_INITIALIZATION(modelName, callType, ...) MU_EXPAND_ARGS(CREATE_GLOBAL_INITIALIZE_##callType(modelName, __VA_ARGS__)) #define CREATE_SOMETHING_GLOBAL_INITIALIZATION(modelName, ...) MU_EXPAND_ARGS(CREATE_MODEL_ENTITY_GLOBAL_INITIALIZATION(modelName, __VA_ARGS__)) #define CREATE_ELEMENT_GLOBAL_INITIALIZATION(modelName, elem) MU_EXPAND_ARGS(CREATE_SOMETHING_GLOBAL_INITIALIZATION(modelName, MU_EXPAND_ARGS(EXPAND_##elem))) #define CREATE_MODEL_ELEMENT_GLOBAL_INITIALIZE(modelName, elem) MU_EXPAND_ARGS(CREATE_ELEMENT_GLOBAL_INITIALIZATION(modelName, elem)) #define CREATE_MODEL_ENTITY_GLOBAL_DEINITIALIZATION(modelName, callType, ...) MU_EXPAND_ARGS(CREATE_GLOBAL_DEINITIALIZE_##callType(modelName, __VA_ARGS__)) #define CREATE_SOMETHING_GLOBAL_DEINITIALIZATION(modelName, ...) MU_EXPAND_ARGS(CREATE_MODEL_ENTITY_GLOBAL_DEINITIALIZATION(modelName, __VA_ARGS__)) #define CREATE_ELEMENT_GLOBAL_DEINITIALIZATION(modelName, elem) MU_EXPAND_ARGS(CREATE_SOMETHING_GLOBAL_DEINITIALIZATION(modelName, MU_EXPAND_ARGS(EXPAND_##elem))) #define CREATE_MODEL_ELEMENT_GLOBAL_DEINITIALIZE(modelName, elem) MU_EXPAND_ARGS(CREATE_ELEMENT_GLOBAL_DEINITIALIZATION(modelName, elem)) #define INSERT_FIELD_INTO_STRUCT(x, y) x y; #define INSERT_FIELD_FOR_MODEL_PROPERTY(type, name) INSERT_FIELD_INTO_STRUCT(type, name) #define CREATE_GLOBAL_INITIALIZE_MODEL_PROPERTY(modelName, type, name) /*do nothing, this is written by user*/ #define CREATE_GLOBAL_DEINITIALIZE_MODEL_PROPERTY(modelName, type, name) /*do nothing, this is user's stuff*/ /*REPORTED_PROPERTY is not different than regular WITH_DATA*/ #define INSERT_FIELD_FOR_MODEL_REPORTED_PROPERTY(type, name) INSERT_FIELD_INTO_STRUCT(type, name) #define CREATE_GLOBAL_INITIALIZE_MODEL_REPORTED_PROPERTY(modelName, type,name) GlobalInitialize_##type((char*)destination+offsetof(modelName, name)); #define CREATE_GLOBAL_DEINITIALIZE_MODEL_REPORTED_PROPERTY(modelName, type,name) GlobalDeinitialize_##type((char*)destination+offsetof(modelName, name)); /*DESIRED_PROPERTY is not different than regular WITH_DATA*/ #define INSERT_FIELD_FOR_MODEL_DESIRED_PROPERTY(type, name, ...) INSERT_FIELD_INTO_STRUCT(type, name) #define CREATE_GLOBAL_INITIALIZE_MODEL_DESIRED_PROPERTY(modelName, type, name, ...) /*do nothing*/ #define CREATE_GLOBAL_DEINITIALIZE_MODEL_DESIRED_PROPERTY(modelName, type, name, ...) /*do nothing*/ #define INSERT_FIELD_FOR_MODEL_ACTION(name, ...) /* action isn't a part of the model struct */ #define INSERT_FIELD_FOR_MODEL_METHOD(name, ...) /* method isn't a part of the model struct */ #define CREATE_GLOBAL_INITIALIZE_MODEL_ACTION(...) /*do nothing*/ #define CREATE_GLOBAL_DEINITIALIZE_MODEL_ACTION(...) /*do nothing*/ #define CREATE_GLOBAL_INITIALIZE_MODEL_METHOD(...) /*do nothing*/ #define CREATE_GLOBAL_DEINITIALIZE_MODEL_METHOD(...) /*do nothing*/ #define CREATE_MODEL_PROPERTY(modelName, type, name) \ IMPL_PROPERTY(type, name, modelName) #define CREATE_MODEL_REPORTED_PROPERTY(modelName, type, name) \ IMPL_REPORTED_PROPERTY(type, name, modelName) #define CREATE_MODEL_DESIRED_PROPERTY(modelName, type, name, ...) \ IMPL_DESIRED_PROPERTY(type, name, modelName, __VA_ARGS__) #define IMPL_PROPERTY(propertyType, propertyName, modelName) \ static int Create_AGENT_DATA_TYPE_From_Ptr_##modelName##propertyName(void* param, AGENT_DATA_TYPE* dest) \ { \ return MU_C1(ToAGENT_DATA_TYPE_##propertyType)(dest, *(propertyType*)param); \ } \ REFLECTED_PROPERTY(propertyType, propertyName, modelName) #define IMPL_REPORTED_PROPERTY(propertyType, propertyName, modelName) \ static int Create_AGENT_DATA_TYPE_From_Ptr_##modelName##propertyName(void* param, AGENT_DATA_TYPE* dest) \ { \ return MU_C1(ToAGENT_DATA_TYPE_##propertyType)(dest, *(propertyType*)param); \ } \ REFLECTED_REPORTED_PROPERTY(propertyType, propertyName, modelName) #define IMPL_DESIRED_PROPERTY(propertyType, propertyName, modelName, ...) \ static void DesiredPropertyInitialize_##modelName##propertyName(void* destination) \ { \ GlobalInitialize_##propertyType(destination); \ } \ static void DesiredPropertyDeinitialize_##modelName##propertyName(void* destination) \ { \ GlobalDeinitialize_##propertyType(destination); \ } \ REFLECTED_DESIRED_PROPERTY(propertyType, propertyName, modelName, __VA_ARGS__) \ #define CREATE_MODEL_ACTION(modelName, actionName, ...) \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(modelName##actionName, 1); \ EXECUTE_COMMAND_RESULT actionName (modelName* device MU_FOR_EACH_2(DEFINE_FUNCTION_PARAMETER, __VA_ARGS__)); \ static EXECUTE_COMMAND_RESULT MU_C2(actionName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values); \ /*for macro purposes, this array always has at least 1 element*/ \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 1); \ static const WRAPPER_ARGUMENT MU_C2(actionName, WRAPPERARGUMENTS)[MU_DIV2(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__))))] = { MU_FOR_EACH_2_COUNTED(MAKE_WRAPPER_ARGUMENT, __VA_ARGS__) MU_IFCOMMA(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__)))) {0} }; \ REFLECTED_ACTION(actionName, MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), MU_C2(actionName, WRAPPERARGUMENTS), MU_C2(actionName, WRAPPER), modelName) \ static EXECUTE_COMMAND_RESULT MU_C2(actionName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values) \ { \ EXECUTE_COMMAND_RESULT result; \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 2); \ if(ParameterCount != MU_DIV2(MU_COUNT_ARG(__VA_ARGS__))) \ { \ result = EXECUTE_COMMAND_ERROR; \ } \ else \ { \ /*the below line takes care of initialized but not referenced parameter warning*/ \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 3); \ MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), size_t iParameter = 0;, ) \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 4); \ /*the below line takes care of an unused parameter when values is really never questioned*/ \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 5); \ MU_FOR_EACH_2(DEFINE_LOCAL_PARAMETER, __VA_ARGS__) \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 6); \ MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), , (void)values;) \ { \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 7); \ } \ MU_FOR_EACH_2_KEEP_1(START_BUILD_LOCAL_PARAMETER, EXECUTE_COMMAND_ERROR, __VA_ARGS__) \ { \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 8); \ } \ result = actionName((modelName*)device MU_FOR_EACH_2(PUSH_LOCAL_PARAMETER, __VA_ARGS__)); \ MU_FOR_EACH_2_REVERSE(END_BUILD_LOCAL_PARAMETER, __VA_ARGS__) \ } \ return result; \ } #define CREATE_MODEL_METHOD(modelName, methodName, ...) \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(modelName##methodName, 1); \ METHODRETURN_HANDLE methodName (modelName* device MU_FOR_EACH_2(DEFINE_FUNCTION_PARAMETER, __VA_ARGS__)); \ static METHODRETURN_HANDLE MU_C2(methodName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values); \ /*for macro purposes, this array always has at least 1 element*/ \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 1); \ static const WRAPPER_ARGUMENT MU_C2(methodName, WRAPPERARGUMENTS)[MU_DIV2(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__))))] = { MU_FOR_EACH_2_COUNTED(MAKE_WRAPPER_ARGUMENT, __VA_ARGS__) MU_IFCOMMA(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__)))) {0} }; \ REFLECTED_METHOD(methodName, MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), MU_C2(methodName, WRAPPERARGUMENTS), MU_C2(methodName, WRAPPER), modelName) \ static METHODRETURN_HANDLE MU_C2(methodName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values) \ { \ METHODRETURN_HANDLE result; \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 2); \ if(ParameterCount != MU_DIV2(MU_COUNT_ARG(__VA_ARGS__))) \ { \ LogError("expected parameter count (%lu) does not match the actual parameter count (%lu)", (unsigned long)ParameterCount, (unsigned long)MU_COUNT_ARG(__VA_ARGS__)); \ result = NULL; \ } \ else \ { \ /*the below line takes care of initialized but not referenced parameter warning*/ \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 3); \ MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), size_t iParameter = 0;, ) \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 4); \ /*the below line takes care of an unused parameter when values is really never questioned*/ \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 5); \ MU_FOR_EACH_2(DEFINE_LOCAL_PARAMETER, __VA_ARGS__) \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 6); \ MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), , (void)values;) \ { \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 7); \ } \ MU_FOR_EACH_2_KEEP_1(START_BUILD_LOCAL_PARAMETER, NULL,__VA_ARGS__) \ { \ DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 8); \ } \ result = methodName((modelName*)device MU_FOR_EACH_2(PUSH_LOCAL_PARAMETER, __VA_ARGS__)); \ MU_FOR_EACH_2_REVERSE(END_BUILD_LOCAL_PARAMETER, __VA_ARGS__) \ } \ return result; \ } #define CREATE_AGENT_DATA_TYPE(type, name) \ result = (( result==AGENT_DATA_TYPES_OK) && (ToAGENT_DATA_TYPE_##type( &(members[iMember]), value.name) == AGENT_DATA_TYPES_OK))?AGENT_DATA_TYPES_OK:AGENT_DATA_TYPES_ERROR; \ iMember+= ((result==AGENT_DATA_TYPES_OK)?1:0); #define BUILD_DESTINATION_FIELD(type, name) \ if(result == AGENT_DATA_TYPES_OK) \ { \ size_t i; \ bool wasFieldConverted = false; \ for (i = 0; i < source->value.edmComplexType.nMembers; i++) \ { \ /*the name of the field of the complex type must match the name of the field of the structure (parameter name here)*/ \ if (strcmp(source->value.edmComplexType.fields[i].fieldName, MU_TOSTRING(name)) == 0) \ { \ wasFieldConverted = (MU_C2(FromAGENT_DATA_TYPE_, type)(source->value.edmComplexType.fields[i].value, &(destination->name)) == AGENT_DATA_TYPES_OK); \ break; \ } \ } \ result = (wasFieldConverted == true)? AGENT_DATA_TYPES_OK: AGENT_DATA_TYPES_INVALID_ARG; \ } \ else \ { \ /*fallthrough*/ \ } #define UNBUILD_DESTINATION_FIELD(value, type, name) \ MU_C2(destroyLocalParameter, type)(&(value->name)); #define ADDRESS_MACRO(x) ,&x #define KEEP_FIRST_(X, ...) X #ifdef _MSC_VER #define KEEP_FIRST(X) KEEP_FIRST_ LPAREN X) #else #define KEEP_FIRST(X) KEEP_FIRST_(X) #endif #define PROMOTIONMAP_float double, double #define PROMOTIONMAP_int8_t int, int #define PROMOTIONMAP_uint8_t int, int #define PROMOTIONMAP_int16_t int, int #define PROMOTIONMAP__Bool int, int #define PROMOTIONMAP_bool int, int #define CASTMAP_float (float), (float) #define CASTMAP_int8_t (int8_t), (int8_t) #define CASTMAP_uint8_t (uint8_t), (uint8_t) #define CASTMAP_int16_t (int16_t), (int16_t) #define CASTMAP__Bool 0!=, 0!= #define CASTMAP_bool 0!=, 0!= #define EMPTY_TOKEN #define ANOTHERIF(x) MU_C2(ANOTHERIF,x) #define ANOTHERIF0(a,b) a #define ANOTHERIF1(a,b) b #define ANOTHERIF2(a,b) b #define ANOTHERIF3(a,b) b #define ANOTHERIF4(a,b) b #define ANOTHERIF5(a,b) b #define ANOTHERIF6(a,b) b #define ANOTHERIF7(a,b) b #define ANOTHERIF8(a,b) b #define ANOTHERIF9(a,b) b #define ANOTHERIF10(a,b) b #define ANOTHERIF11(a,b) b #define ANOTHERIF12(a,b) b #define MAP_PROMOTED_TYPE(X) ANOTHERIF(MU_DEC(MU_COUNT_ARG(PROMOTIONMAP_##X))) (X, KEEP_FIRST(PROMOTIONMAP_##X)) #define MAP_CAST_TYPE(X) ANOTHERIF(MU_DEC(MU_COUNT_ARG(CASTMAP_##X))) (EMPTY_TOKEN, KEEP_FIRST(CASTMAP_##X) ) #define MU_IFCOMMA(N) MU_C2(MU_IFCOMMA_, N) #define MU_IFCOMMA_0 #define MU_IFCOMMA_2 #define MU_IFCOMMA_4 , #define MU_IFCOMMA_6 , #define MU_IFCOMMA_8 , #define MU_IFCOMMA_10 , #define MU_IFCOMMA_12 , #define MU_IFCOMMA_14 , #define MU_IFCOMMA_16 , #define MU_IFCOMMA_18 , #define MU_IFCOMMA_20 , #define MU_IFCOMMA_22 , #define MU_IFCOMMA_24 , #define MU_IFCOMMA_26 , #define MU_IFCOMMA_28 , #define MU_IFCOMMA_30 , #define MU_IFCOMMA_32 , #define MU_IFCOMMA_34 , #define MU_IFCOMMA_36 , #define MU_IFCOMMA_38 , #define MU_IFCOMMA_40 , #define MU_IFCOMMA_42 , #define MU_IFCOMMA_44 , #define MU_IFCOMMA_46 , #define MU_IFCOMMA_48 , #define MU_IFCOMMA_50 , #define MU_IFCOMMA_52 , #define MU_IFCOMMA_54 , #define MU_IFCOMMA_56 , #define MU_IFCOMMA_58 , #define MU_IFCOMMA_60 , #define MU_IFCOMMA_62 , #define MU_IFCOMMA_64 , #define MU_IFCOMMA_66 , #define MU_IFCOMMA_68 , #define MU_IFCOMMA_70 , #define MU_IFCOMMA_72 , #define MU_IFCOMMA_74 , #define MU_IFCOMMA_76 , #define MU_IFCOMMA_78 , #define MU_IFCOMMA_80 , #define MU_IFCOMMA_82 , #define MU_IFCOMMA_84 , #define MU_IFCOMMA_86 , #define MU_IFCOMMA_88 , #define MU_IFCOMMA_90 , #define MU_IFCOMMA_92 , #define MU_IFCOMMA_94 , #define MU_IFCOMMA_96 , #define MU_IFCOMMA_98 , #define MU_IFCOMMA_100 , #define MU_IFCOMMA_102 , #define MU_IFCOMMA_104 , #define MU_IFCOMMA_106 , #define MU_IFCOMMA_108 , #define MU_IFCOMMA_110 , #define MU_IFCOMMA_112 , #define MU_IFCOMMA_114 , #define MU_IFCOMMA_116 , #define MU_IFCOMMA_118 , #define MU_IFCOMMA_120 , #define MU_IFCOMMA_122 , #define MU_IFCOMMA_124 , #define MU_IFCOMMA_126 , #define MU_IFCOMMA_128 , #define DEFINE_LOCAL_PARAMETER(type, name) type MU_C2(name,_local); GlobalInitialize_##type(& MU_C2(name, _local)); #define START_BUILD_LOCAL_PARAMETER(errorWhenItFails, type, name) \ if (MU_C2(FromAGENT_DATA_TYPE_, type)(&values[iParameter], &MU_C2(name, _local)) != AGENT_DATA_TYPES_OK) \ { \ result = errorWhenItFails; \ }\ else \ { \ iParameter++; #define END_BUILD_LOCAL_PARAMETER(type, name) \ (void)MU_C2(destroyLocalParameter, type)(&MU_C2(name, _local)); \ } /*The following constructs have been devised to work around the precompiler bug of Visual Studio 2005, version 14.00.50727.42*/ /* The bug is explained in https://connect.microsoft.com/VisualStudio/feedback/details/278752/comma-missing-when-using-va-args */ /*A short description is: preprocessor is mysteriously eating commas ','. In order to feed the appetite of the preprocessor, several constructs have been devised that can sustain a missing ',' while still compiling and while still doing nothing and while hopefully being eliminated from the code based on "doesn't do anything" so no code size penalty */ /*the reason why all these constructs work is: if two strings separated by a comma will lose the comma (myteriously) then they will become just one string: "a", "b" ------Preprocessor------> "a" "b" -----Compiler----> "ab" */ #define LOTS_OF_COMMA_TO_BE_EATEN /*there were witnesses where as many as THREE commas have been eaten!*/ \ "0" "1", "2", "3", "4", "5", "6", "7", "8", "9" #define DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(name, instance) static const char* eatThese_COMMA_##name##instance[] = {LOTS_OF_COMMA_TO_BE_EATEN} #define PUSH_LOCAL_PARAMETER(type, name) , MU_C2(name, _local) #define DEFINE_FUNCTION_PARAMETER(type, name) , type name #define MAKE_WRAPPER_ARGUMENT(N, type, name) {MU_TOSTRING(type), MU_TOSTRING(name)} MU_IFCOMMA(N) static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, double)(AGENT_DATA_TYPE* dest, double source) { return Create_AGENT_DATA_TYPE_from_DOUBLE(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, double)(const AGENT_DATA_TYPE* agentData, double* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_DOUBLE_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmDouble.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, double)(void* dest) { *(double*)dest = 0.0; } static void MU_C2(GlobalDeinitialize_, double)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, float)(AGENT_DATA_TYPE* dest, float source) { return Create_AGENT_DATA_TYPE_from_FLOAT(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, float)(const AGENT_DATA_TYPE* agentData, float* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_SINGLE_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmSingle.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, float)(void* dest) { *(float*)dest = 0.0f; } static void MU_C2(GlobalDeinitialize_, float)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int)(AGENT_DATA_TYPE* dest, int source) { return Create_AGENT_DATA_TYPE_from_SINT32(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int)(const AGENT_DATA_TYPE* agentData, int* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_INT32_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmInt32.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, int)(void* dest) { *(int*)dest = 0; } static void MU_C2(GlobalDeinitialize_, int)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, long)(AGENT_DATA_TYPE* dest, long source) { return Create_AGENT_DATA_TYPE_from_SINT64(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, long)(const AGENT_DATA_TYPE* agentData, long* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_INT64_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = (long)agentData->value.edmInt64.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, long)(void* dest) { *(long*)dest = 0; } static void MU_C2(GlobalDeinitialize_, long)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int8_t)(AGENT_DATA_TYPE* dest, int8_t source) { return Create_AGENT_DATA_TYPE_from_SINT8(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int8_t)(const AGENT_DATA_TYPE* agentData, int8_t* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_SBYTE_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmSbyte.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, int8_t)(void* dest) { *(int8_t*)dest = 0; } static void MU_C2(GlobalDeinitialize_, int8_t)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, uint8_t)(AGENT_DATA_TYPE* dest, uint8_t source) { return Create_AGENT_DATA_TYPE_from_UINT8(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, uint8_t)(const AGENT_DATA_TYPE* agentData, uint8_t* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_BYTE_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmByte.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, uint8_t)(void* dest) { *(uint8_t*)dest = 0; } static void MU_C2(GlobalDeinitialize_, uint8_t)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int16_t)(AGENT_DATA_TYPE* dest, int16_t source) { return Create_AGENT_DATA_TYPE_from_SINT16(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int16_t)(const AGENT_DATA_TYPE* agentData, int16_t* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_INT16_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmInt16.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, int16_t)(void* dest) { *(int16_t*)dest = 0; } static void MU_C2(GlobalDeinitialize_, int16_t)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int32_t)(AGENT_DATA_TYPE* dest, int32_t source) { return Create_AGENT_DATA_TYPE_from_SINT32(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int32_t)(const AGENT_DATA_TYPE* agentData, int32_t* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_INT32_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmInt32.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, int32_t)(void* dest) { *(int32_t*)dest = 0; } static void MU_C2(GlobalDeinitialize_, int32_t)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int64_t)(AGENT_DATA_TYPE* dest, int64_t source) { return Create_AGENT_DATA_TYPE_from_SINT64(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int64_t)(const AGENT_DATA_TYPE* agentData, int64_t* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_INT64_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmInt64.value; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, int64_t)(void* dest) { *(int64_t*)dest = 0; } static void MU_C2(GlobalDeinitialize_, int64_t)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, bool)(AGENT_DATA_TYPE* dest, bool source) { return Create_EDM_BOOLEAN_from_int(dest, source == true); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, bool)(const AGENT_DATA_TYPE* agentData, bool* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_BOOLEAN_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = (agentData->value.edmBoolean.value == EDM_TRUE) ? true : false; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, bool)(void* dest) { *(bool*)dest = false; } static void MU_C2(GlobalDeinitialize_, bool)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, ascii_char_ptr)(AGENT_DATA_TYPE* dest, ascii_char_ptr source) { return Create_AGENT_DATA_TYPE_from_charz(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, ascii_char_ptr)(const AGENT_DATA_TYPE* agentData, ascii_char_ptr* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_STRING_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { if (*dest != NULL) { free(*dest); *dest = NULL; } if (mallocAndStrcpy_s(dest, agentData->value.edmString.chars) != 0) { LogError("failure in mallocAndStrcpy_s"); result = AGENT_DATA_TYPES_ERROR; } else { result = AGENT_DATA_TYPES_OK; } } return result; } static void MU_C2(GlobalInitialize_, ascii_char_ptr)(void* dest) { *(ascii_char_ptr*)dest = NULL; } static void MU_C2(GlobalDeinitialize_, ascii_char_ptr)(void* dest) { if (*(ascii_char_ptr*)dest != NULL) { free(*(ascii_char_ptr*)dest); } } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, ascii_char_ptr_no_quotes)(AGENT_DATA_TYPE* dest, ascii_char_ptr_no_quotes source) { return Create_AGENT_DATA_TYPE_from_charz_no_quotes(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, ascii_char_ptr_no_quotes)(const AGENT_DATA_TYPE* agentData, ascii_char_ptr_no_quotes* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_STRING_NO_QUOTES_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { if (*dest != NULL) { free(*dest); *dest = NULL; } if (mallocAndStrcpy_s(dest, agentData->value.edmStringNoQuotes.chars) != 0) { LogError("failure in mallocAndStrcpy_s"); result = AGENT_DATA_TYPES_ERROR; } else { result = AGENT_DATA_TYPES_OK; } } return result; } static void MU_C2(GlobalInitialize_, ascii_char_ptr_no_quotes)(void* dest) { *(ascii_char_ptr_no_quotes*)dest = NULL; } static void MU_C2(GlobalDeinitialize_, ascii_char_ptr_no_quotes)(void* dest) { if (*(ascii_char_ptr_no_quotes*)dest != NULL) { free(*(ascii_char_ptr_no_quotes*)dest); } } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, EDM_DATE_TIME_OFFSET)(AGENT_DATA_TYPE* dest, EDM_DATE_TIME_OFFSET source) { return Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET(dest, source); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, EDM_DATE_TIME_OFFSET)(const AGENT_DATA_TYPE* agentData, EDM_DATE_TIME_OFFSET* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_DATE_TIME_OFFSET_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { *dest = agentData->value.edmDateTimeOffset; result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, EDM_DATE_TIME_OFFSET)(void* dest) { memset(dest, 0, sizeof(EDM_DATE_TIME_OFFSET)); } static void MU_C2(GlobalDeinitialize_, EDM_DATE_TIME_OFFSET)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, EDM_GUID)(AGENT_DATA_TYPE* dest, EDM_GUID guid) { return Create_AGENT_DATA_TYPE_from_EDM_GUID(dest, guid); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, EDM_GUID)(const AGENT_DATA_TYPE* agentData, EDM_GUID* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_GUID_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { (void)memcpy(dest->GUID, agentData->value.edmGuid.GUID, 16); result = AGENT_DATA_TYPES_OK; } return result; } static void MU_C2(GlobalInitialize_, EDM_GUID)(void* dest) { memset(dest, 0, sizeof(EDM_GUID)); } static void MU_C2(GlobalDeinitialize_, EDM_GUID)(void* dest) { (void)(dest); } static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, EDM_BINARY)(AGENT_DATA_TYPE* dest, EDM_BINARY edmBinary) { return Create_AGENT_DATA_TYPE_from_EDM_BINARY(dest, edmBinary); } static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, EDM_BINARY)(const AGENT_DATA_TYPE* agentData, EDM_BINARY* dest) { AGENT_DATA_TYPES_RESULT result; if (agentData->type != EDM_BINARY_TYPE) { result = AGENT_DATA_TYPES_INVALID_ARG; } else { if ((dest->data = (unsigned char *)malloc(agentData->value.edmBinary.size)) == NULL) /*cast because this get included in a C++ file.*/ { result = AGENT_DATA_TYPES_ERROR; } else { (void)memcpy(dest->data, agentData->value.edmBinary.data, agentData->value.edmBinary.size); dest->size = agentData->value.edmBinary.size; result = AGENT_DATA_TYPES_OK; } } return result; } static void MU_C2(GlobalInitialize_, EDM_BINARY)(void* dest) { ((EDM_BINARY*)dest)->data = NULL; ((EDM_BINARY*)dest)->size = 0; } static void MU_C2(GlobalDeinitialize_, EDM_BINARY)(void* dest) { if ((((EDM_BINARY*)dest)->data) != NULL) { free(((EDM_BINARY*)dest)->data); } } static void MU_C2(destroyLocalParameter, EDM_BINARY)(EDM_BINARY* value) { if (value != NULL) { free(value->data); value->data = NULL; value->size = 0; } } static void MU_C2(destroyLocalParameter, EDM_BOOLEAN)(EDM_BOOLEAN* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_BYTE)(EDM_BYTE* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_DATE)(EDM_DATE* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_DATE_TIME_OFFSET)(EDM_DATE_TIME_OFFSET* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_DECIMAL)(EDM_DECIMAL* value) { if (value != NULL) { STRING_delete(value->value); value->value = NULL; } } static void MU_C2(destroyLocalParameter, EDM_DOUBLE)(EDM_DOUBLE* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_DURATION)(EDM_DURATION* value) { if (value != NULL) { free(value->digits); value->digits = NULL; value->nDigits = 0; } } static void MU_C2(destroyLocalParameter, EDM_GUID)(EDM_GUID* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_INT16)(EDM_INT16* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_INT32)(EDM_INT32* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_INT64)(EDM_INT64* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_SBYTE)(EDM_SBYTE* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_SINGLE)(EDM_SINGLE* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_STRING)(EDM_STRING* value) { (void)value; } static void MU_C2(destroyLocalParameter, EDM_TIME_OF_DAY)(EDM_TIME_OF_DAY* value) { (void)value; } static void MU_C2(destroyLocalParameter, int)(int* value) { (void)value; } static void MU_C2(destroyLocalParameter, float)(float* value) { (void)value; } static void MU_C2(destroyLocalParameter, double)(double* value) { (void)value; } static void MU_C2(destroyLocalParameter, long)(long* value) { (void)value; } static void MU_C2(destroyLocalParameter, int8_t)(int8_t* value) { (void)value; } static void MU_C2(destroyLocalParameter, uint8_t)(uint8_t* value) { (void)value; } static void MU_C2(destroyLocalParameter, int16_t)(int16_t* value) { (void)value; } static void MU_C2(destroyLocalParameter, int32_t)(int32_t* value) { (void)value; } static void MU_C2(destroyLocalParameter, int64_t)(int64_t* value) { (void)value; } static void MU_C2(destroyLocalParameter, bool)(bool* value) { (void)value; } static void MU_C2(destroyLocalParameter, ascii_char_ptr)(ascii_char_ptr* value) { if (value != NULL) { free(*value); } } static void MU_C2(destroyLocalParameter, ascii_char_ptr_no_quotes)(ascii_char_ptr_no_quotes* value) { if (value != NULL) { free(*value); } } #ifdef __cplusplus } #endif #endif /*SERIALIZER_H*/