blob: fc501e1a1ebb84b37e303c2eb427ce3a90514ca9 [file] [log] [blame]
<#--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<#-- Prevent freemarker from escaping stuff -->
<#outputformat "undefined">
<#-- Declare the name and type of variables passed in to the template -->
<#-- @ftlvariable name="languageName" type="java.lang.String" -->
<#-- @ftlvariable name="protocolName" type="java.lang.String" -->
<#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
<#-- @ftlvariable name="helper" type="org.apache.plc4x.language.c.CLanguageTemplateHelper" -->
<#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
<#-- Declare the name and type of variables declared locally inside the template -->
<#-- @ftlvariable name="field" type="org.apache.plc4x.plugins.codegenerator.types.fields.NamedField" -->
<#if !helper.isDiscriminatedChildTypeDefinition(type)>${helper.getIncludesDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(type.name)}.h
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#ifndef ${helper.getCTypeName(type.name)?upper_case}_H_
#define ${helper.getCTypeName(type.name)?upper_case}_H_
#include <stdbool.h>
#include <stdint.h>
#include <plc4c/spi/read_buffer.h>
#include <plc4c/spi/write_buffer.h>
#include <plc4c/utils/list.h>
<#--
Add any import statements for partent-types, complex types used in properties or parser arguments.
-->
<#if helper.getComplexTypeReferences()?has_content>
<#list helper.getComplexTypeReferences() as typeReference>
#include "${helper.camelCaseToSnakeCase(typeReference)}.h"
</#list>
</#if>
#ifdef __cplusplus
extern "C" {
#endif
<#--
Abstract types only occur as parents in the case of discriminated types.
As C doesn't have any form of polymorph type-system, we need to save the type information in the
data-structure. So with this enum we're doing exactly this. It will be used in the serializers and
parsers and stored in discriminated types.
-->
<#if helper.isDiscriminatedParentTypeDefinition(type)>
// Structure used to contain the discriminator values for discriminated types using this as a parent
struct ${helper.getCTypeName(type.name)}_discriminator {
<#if helper.getDiscriminatorTypes()?has_content>
<#list helper.getDiscriminatorTypes()?keys as discriminatorName>
${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])} ${discriminatorName};
</#list>
</#if>
};
typedef struct ${helper.getCTypeName(type.name)}_discriminator ${helper.getCTypeName(type.name)}_discriminator;
// Enum assigning each sub-type an individual id.
enum ${helper.getCTypeName(type.name)}_type {
<#list helper.getSubTypeDefinitions() as subtype>
${helper.getCTypeName(type.name)}_type_${helper.getCTypeName(subtype.name)} = ${subtype?index}<#sep>,
</#list>
};
typedef enum ${helper.getCTypeName(type.name)}_type ${helper.getCTypeName(type.name)}_type;
// Function to get the discriminator values for a given type.
${helper.getCTypeName(type.name)}_discriminator ${helper.getCTypeName(type.name)}_get_discriminator(${helper.getCTypeName(type.name)}_type type);
</#if>
<#--
When using const fields, output the constant reference values
as global const values so we can use them elsewhere.
-->
<#if helper.getAllConstFields()?has_content>
// Constant values.
<#list helper.getAllConstFields() as parentType, constField>
${helper.getLanguageTypeNameForField(constField)} ${helper.getCTypeName(parentType.name)?upper_case}_${helper.camelCaseToSnakeCase(constField.name)?upper_case}();
</#list>
</#if>
<#--
Create the general data-structure for this type
-->
struct ${helper.getCTypeName(type.name)} {
<#if helper.isDiscriminatedParentTypeDefinition(type)>
/* This is an abstract type so this property saves the type of this typed union */
${helper.getCTypeName(type.name)}_type _type;
</#if>
/* Properties */
<#list helper.getPropertyAndSwitchFields() as field>
<#if helper.isSwitchField(field)>
union {
<#list field.cases as case>
struct { /* ${case.name} */
<#list case.propertyFields as caseField>
<#if (helper.isSimpleTypeReference(caseField.type) || helper.isEnumField(caseField)) && !helper.isOptionalField(caseField) && !helper.isArrayField(caseField) && !helper.isManualArrayField(caseField)>
${helper.getLanguageTypeNameForField(caseField)} ${helper.camelCaseToSnakeCase(case.name)}_${helper.camelCaseToSnakeCase(caseField.name)}${helper.getTypeSizeForField(caseField)}<#if field.loopType??>${helper.getLoopExpressionSuffix(caseField)}</#if>;
<#elseif helper.isArrayField(caseField) || helper.isManualArrayField(caseField)>
plc4c_list* ${helper.camelCaseToSnakeCase(case.name)}_${helper.camelCaseToSnakeCase(caseField.name)};
<#else>
${helper.getLanguageTypeNameForField(caseField)}* ${helper.camelCaseToSnakeCase(case.name)}_${helper.camelCaseToSnakeCase(caseField.name)};
</#if>
</#list>
};
</#list>
};
<#elseif (helper.isSimpleTypeReference(field.type) || helper.isEnumField(field)) && !helper.isOptionalField(field) && !helper.isArrayField(field) && !helper.isManualArrayField(field)>
${helper.getLanguageTypeNameForField(field)} ${helper.camelCaseToSnakeCase(field.name)}${helper.getTypeSizeForField(field)}<#if field.loopType??>${helper.getLoopExpressionSuffix(field)}</#if>;
<#elseif helper.isArrayField(field) || helper.isManualArrayField(field)>
plc4c_list* ${helper.camelCaseToSnakeCase(field.name)};
<#else>
${helper.getLanguageTypeNameForField(field)}* ${helper.camelCaseToSnakeCase(field.name)};
</#if>
</#list>
};
typedef struct ${helper.getCTypeName(type.name)} ${helper.getCTypeName(type.name)};
// Create an empty NULL-struct
${helper.getCTypeName(type.name)} ${helper.getCTypeName(type.name)}_null();
<#--
Define the parse-method for elements of this tpye
-->
plc4c_return_code ${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_buffer* io, <#if type.parserArguments?has_content><#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#if !helper.isSimpleTypeReference(parserArgument.type)>*</#if> ${parserArgument.name}<#sep>, </#list>, </#if>${helper.getCTypeName(type.name)}** message);
<#--
Define the serialize-method for elements of this tpye
-->
plc4c_return_code ${helper.getCTypeName(type.name)}_serialize(plc4c_spi_write_buffer* io, ${helper.getCTypeName(type.name)}* message<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)} ${parserArgument.name}<#sep>, </#sep></#list></#if>);
uint16_t ${helper.getCTypeName(type.name)}_length_in_bytes(${helper.getCTypeName(type.name)}* message);
uint16_t ${helper.getCTypeName(type.name)}_length_in_bits(${helper.getCTypeName(type.name)}* message);
#ifdef __cplusplus
}
#endif
#endif // ${helper.getCTypeName(type.name)?upper_case}_H_
</#if>
</#outputformat>