Accelerator Independent Data Access / PVAccess 2.0
AIDA-PVA is the latest version of the AIDA framework. Built on top of EPICS 7 it enables client applications to programmatically access and manage any device or database on the SLAC Network using simple channel names.
Loading...
Searching...
No Matches
aida_pva_types_helper.h
Go to the documentation of this file.
1/** @file
2 * @brief The Header File for the Native Channel Provider AIDA-PVA type related functions.
3 * **CMS**=C_INC
4 */
5
6#ifndef aida_pva_types_helper_h
7#define aida_pva_types_helper_h
8#ifdef __cplusplus
9extern "C" {
10#endif
11
12#include "aida_pva.h"
13
14/**
15 * Minimum number of floating point allocations. When allocating space for floating point numbers the framework allocates in batches and then reallocates if the batch is full. This is the minimum batch size.
16 */
17#define MIN_FLOAT_ALLOCATIONS 100
18
19/**
20 * int format definition character for ascanf() and avscanf().
21 */
22#define FORMAT_INTEGER 'd'
23/**
24 * unsigned int format definition character for ascanf() and avscanf().
25 */
26#define FORMAT_UNSIGNED_INTEGER 'u'
27/**
28 * float format definition character for ascanf() and avscanf().
29 */
30#define FORMAT_FLOAT 'f'
31/**
32 * string format definition character for ascanf() and avscanf().
33 */
34#define FORMAT_STRING 's'
35/**
36 * byte format definition character for ascanf() and avscanf().
37 */
38#define FORMAT_BYTE 'c'
39/**
40 * boolean format definition character for ascanf() and avscanf().
41 */
42#define FORMAT_BOOLEAN 'b'
43
44/**
45 * optional format definition character for ascanf() and avscanf().
46 */
47#define FORMAT_OPTIONAL_FLAG 'o'
48
49/**
50 * short format definition character for ascanf() and avscanf().
51 */
52#define FORMAT_PREFIX_SHORT 'h'
53/**
54 * long format definition character for ascanf() and avscanf().
55 */
56#define FORMAT_PREFIX_LONG 'l'
57
58/**
59 * array format definition character for ascanf() and avscanf().
60 */
61#define FORMAT_SUFFIX_ARRAY 'a'
62
63/**
64 * Maximum number of permitted format specifiers for ascanf() and avscanf().
65 */
66#define MAX_FORMAT_SPECIFIERS 20
67/**
68 * Maximum length of s single format specifier for ascanf() and avscanf().
69 */
70#define MAX_FORMAT 8
71/**
72 * Used internally to formulate a correctly cast pointer to the array being constructed.
73 */
74#define ARRAY_TARGET(_cType) &((_cType *)(*arrayPtr))[i]
75/**
76 * Macro used internally to set a scalar value for ascanf() and avscanf().
77 */
78#define ASCANF_SET_SCALAR(_format, _cType, _jsonType, _typeName, _target) \
79{ \
80 _cType* ptr = (_cType*)(_target); \
81 if (!valueShouldBeJson) { \
82 if ( sscanf(stringValue, _format, ptr) == 0 ) { \
83 SPRINTF_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument \"%s\" to " _typeName, stringValue, EXIT_FAILURE) \
84 }\
85 } else { \
86 if (jsonRoot->type == json_integer) { \
87 *ptr = (_cType)jsonRoot->u.integer; \
88 } else if (jsonRoot->type == json_double) { \
89 *ptr = (_cType)(jsonRoot->u.dbl); \
90 } else if (jsonRoot->type == json_string) { \
91 if ( sscanf(jsonRoot->u.string.ptr, _format, ptr) == 0 ) { \
92 SPRINTF_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument \"%s\" to " _typeName, jsonRoot->u.string.ptr, EXIT_FAILURE) \
93 } \
94 } else if (isRequired) { \
95 PRINT_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument to " _typeName ": <json>", EXIT_FAILURE) \
96 }\
97 }\
98}
99
100/**
101 * Macro used internally to set a scalar boolean for ascanf() and avscanf().
102 */
103#define ASCANF_SET_BOOLEAN(_targetBoolean) \
104{ \
105 unsigned char* ptr = (unsigned char*)(_targetBoolean); \
106 if (!valueShouldBeJson) { \
107 if (isdigit(*stringValue)) {\
108 double number; \
109 sscanf(stringValue, "%lg", &number); \
110 *ptr = (unsigned char)((number == 0.0) ? 0 : 1); \
111 } else { \
112 int _val = getBooleanValue(stringValue); \
113 if ( _val == -1 ) { \
114 SPRINTF_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument to boolean: %s", stringValue, EXIT_FAILURE) \
115 } else { \
116 *ptr = _val; \
117 } \
118 } \
119 } else { \
120 if (jsonRoot->type == json_integer) { \
121 *ptr = (unsigned char)(jsonRoot->u.integer != 0); \
122 } else if (jsonRoot->type == json_double) { \
123 *ptr = (unsigned char)(jsonRoot->u.dbl != 0.0); \
124 } else if (jsonRoot->type == json_boolean) { \
125 *ptr = (unsigned char)jsonRoot->u.boolean; \
126 } else if (jsonRoot->type == json_string) { \
127 int _val = getBooleanValue(jsonRoot->u.string.ptr); \
128 if ( _val == -1 ) { \
129 SPRINTF_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument to boolean: %s", jsonRoot->u.string.ptr, EXIT_FAILURE) \
130 } else { \
131 *ptr = _val; \
132 } \
133 } else { \
134 PRINT_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument to boolean: <json>", EXIT_FAILURE) \
135 } \
136 } \
137}
138
139/**
140 * Macro used internally to set a scalar byte for ascanf() and avscanf().
141 */
142#define ASCANF_SET_BYTE(_targetByte) \
143{ \
144 unsigned char* ptr = (unsigned char*)(_targetByte); \
145 if (!valueShouldBeJson) { \
146 *ptr = *stringValue; \
147 } else { \
148 if (jsonRoot->type == json_integer) { \
149 *ptr = (int)(jsonRoot->u.integer & 0XFF) ; \
150 } else if (jsonRoot->type == json_string && jsonRoot->u.string.length == 1) { \
151 *ptr = *jsonRoot->u.string.ptr; \
152 } else { \
153 PRINT_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument to byte: <json>", EXIT_FAILURE) \
154 } \
155 } \
156}
157
158/**
159 * Macro used internally to set a string for ascanf() and avscanf().
160 */
161#define ASCANF_SET_STRING(_targetString) \
162{ \
163 char** ptr = (char**)(_targetString); \
164 if (!valueShouldBeJson) { \
165 *ptr = stringValue; \
166 } else { \
167 if (aidaType == AIDA_STRING_TYPE) { \
168 ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(env, nextStringPosition, jsonRoot->u.string.length+1, "string arguments", EXIT_FAILURE) \
169 }\
170 if (jsonRoot->type == json_string) { \
171 strcpy(nextStringPosition, jsonRoot->u.string.ptr); \
172 } else if (jsonRoot->type == json_integer) { \
173 sprintf(nextStringPosition, "%ld", jsonRoot->u.integer); \
174 } else if (jsonRoot->type == json_double) { \
175 sprintf(nextStringPosition, "%g", jsonRoot->u.dbl); \
176 } else { \
177 PRINT_ERROR_FREE_MEMORY_AND_RETURN_(AIDA_INTERNAL_EXCEPTION, "can't convert argument to string: <json>", EXIT_FAILURE) \
178 } \
179 *ptr = nextStringPosition; \
180 nextStringPosition+=strlen(nextStringPosition)+1; \
181 } \
182}
183
184/**
185 * Macro used internally to set an array for ascanf() and avscanf().
186 */
187#define ASCANF_SET_ARRAY(_format, _cType, _jsonType, _typeName) \
188{ \
189 ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(env, *arrayPtr, arrayCount * sizeof(_cType), "array arguments", EXIT_FAILURE) \
190 for (int i = 0; i < arrayCount; i++) { \
191 jsonRoot = arrayRoot->u.array.values[i]; \
192 ASCANF_SET_SCALAR(_format, _cType, _jsonType, _typeName, ARRAY_TARGET(_cType)) \
193 } \
194}
195
196/**
197 * Macro used internally for setting a boolean array or a byte array for ascanf() and avscanf().
198 */
199#define ASCANF_SET_BOOLEAN_OR_BYTE_ARRAY(_cType, _setMacro) \
200{ \
201 ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(env, *arrayPtr, arrayCount * sizeof(_cType), "array arguments", EXIT_FAILURE) \
202 for (int i = 0; i < arrayCount; i++) { \
203 jsonRoot = arrayRoot->u.array.values[i]; \
204 _setMacro(ARRAY_TARGET(_cType)) \
205 } \
206}
207
208/**
209 * Macro used to internally for setting a boolean array for ascanf() and avscanf().
210 */
211#define ASCANF_SET_BOOLEAN_ARRAY ASCANF_SET_BOOLEAN_OR_BYTE_ARRAY(unsigned char, ASCANF_SET_BOOLEAN)
212
213/**
214 * Macro used internally for setting a byte array for ascanf() and avscanf().
215 */
216#define ASCANF_SET_BYTE_ARRAY ASCANF_SET_BOOLEAN_OR_BYTE_ARRAY(unsigned char, ASCANF_SET_BYTE)
217
218/**
219 * Macro used internally to set a string array for ascanf() and avscanf().
220 * Allocates a string array by allocating a single block of memory. First part of block is list of character pointers into the last part of block which holds the strings.
221 * To free the memory simply free the pointer to the first char *.
222 */
223#define ASCANF_SET_STRING_ARRAY \
224{ \
225 size_t pointerSpace = arrayCount * sizeof(char*); \
226 ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(env, *arrayPtr, pointerSpace + totalStingLengthOf(arrayRoot) + arrayCount + 1, "string array arguments", EXIT_FAILURE) \
227 nextStringPosition = ((char*)*arrayPtr) + pointerSpace; \
228 for (int i = 0; i < arrayCount; i++) { \
229 jsonRoot = arrayRoot->u.array.values[i]; \
230 ASCANF_SET_STRING(ARRAY_TARGET(char *)) \
231 } \
232}
233#ifdef __cplusplus
234}
235#endif
236#endif
237
The Header File for the AIDA-PVA Module functions.