VirtualBox

source: vbox/trunk/include/iprt/asn1-generator-pass.h@ 76417

Last change on this file since 76417 was 76351, checked in by vboxsync, 6 years ago

iprt/*.h: Avoid including err.h when possible. bugref:9344

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 79.1 KB
Line 
1/** @file
2 * IPRT - ASN.1 Code Generator, One Pass.
3 */
4
5/*
6 * Copyright (C) 2006-2017 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26
27#ifndef ___iprt_asn1_generator_pass_h
28#define ___iprt_asn1_generator_pass_h
29
30#include <iprt/formats/asn1.h>
31#include <iprt/err.h>
32
33
34/** @def RTASN1TMPL_MEMBER_OPT_ANY
35 * Used for optional entries without any specific type at the end of a
36 * structure.
37 *
38 * For example PolicyQualifierInfo's qualifier member which is defined as:
39 * ANY DEFINED BY policyQualifierId
40 *
41 * Defaults to RTASN1TMPL_MEMBER_EX.
42 */
43
44/** @def RTASN1TMPL_MEMBER_OPT_ITAG_EX
45 * Optional member with implict tag, extended version.
46 *
47 * This is what all the other RTASN1TMPL_MEMBER_OPT_ITAG* macros defere to.
48 */
49/** @def RTASN1TMPL_MEMBER_OPT_ITAG_CP
50 * Optional member of a typical primitive type with an implicit context tag.
51 *
52 * Examples of this can be found in AuthorityKeyIdentifier where the first and
53 * last member are primitive types (normally anyways).:
54 * keyIdentifier [1] OCTET STRING OPTIONAL,
55 * authorityCertSerialNumber [3] INTEGER OPTIONAL
56 */
57/** @def RTASN1TMPL_MEMBER_OPT_ITAG_UC
58 * Optional member of a constructed type from the universal tag class.
59 */
60/** @def RTASN1TMPL_MEMBER_OPT_ITAG_UP
61 * Optional member of a primitive type from the universal tag class.
62 */
63
64
65/** @name Expansion Passes (RTASN1TMPL_PASS values)
66 * @{ */
67#define RTASN1TMPL_PASS_INTERNAL_HEADER 1
68
69#define RTASN1TMPL_PASS_XTAG 2
70#define RTASN1TMPL_PASS_VTABLE 3
71#define RTASN1TMPL_PASS_ENUM 4
72#define RTASN1TMPL_PASS_DELETE 5
73#define RTASN1TMPL_PASS_COMPARE 6
74
75#define RTASN1TMPL_PASS_CHECK_SANITY 8
76
77#define RTASN1TMPL_PASS_INIT 16
78#define RTASN1TMPL_PASS_CLONE 17
79#define RTASN1TMPL_PASS_SETTERS_1 18
80#define RTASN1TMPL_PASS_SETTERS_2 19
81#define RTASN1TMPL_PASS_ARRAY 20
82
83#define RTASN1TMPL_PASS_DECODE 24
84/** @} */
85
86/** @name ITAG clues
87 * @{ */
88#define RTASN1TMPL_ITAG_F_CC 1 /**< context, constructed. */
89#define RTASN1TMPL_ITAG_F_CP 2 /**< context, probably primary. (w/ numeric value) */
90#define RTASN1TMPL_ITAG_F_UP 3 /**< universal, probably primary. (w/ ASN1_TAG_XXX value) */
91#define RTASN1TMPL_ITAG_F_UC 4 /**< universal, constructed. (w/ ASN1_TAG_XXX value) */
92/** @} */
93/** Expands the ITAG clues into tag flag and tag class. */
94#define RTASN1TMPL_ITAG_F_EXPAND(a_fClue) \
95 ( a_fClue == RTASN1TMPL_ITAG_F_CC ? (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED ) \
96 : a_fClue == RTASN1TMPL_ITAG_F_CP ? (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE) \
97 : a_fClue == RTASN1TMPL_ITAG_F_UP ? (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE) \
98 : a_fClue == RTASN1TMPL_ITAG_F_UC ? (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED) \
99 : 0 )
100
101#define RTASN1TMPL_SEMICOLON_DUMMY() typedef unsigned RTASN1TMPLSEMICOLONDUMMY
102
103#endif /* !___iprt_asn1_generator_pass_h */
104
105
106#if RTASN1TMPL_PASS == RTASN1TMPL_PASS_INTERNAL_HEADER
107/*
108 *
109 * Internal header file.
110 *
111 */
112# define RTASN1TMPL_BEGIN_COMMON() extern DECLHIDDEN(RTASN1COREVTABLE const) RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
113
114# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
115# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
116# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
117# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
118 extern "C" DECLHIDDEN(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable)
119
120# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
121# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
122# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
123# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
124
125
126# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_BEGIN_COMMON()
127# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
128 RTASN1TMPL_SEMICOLON_DUMMY()
129# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
130 extern "C" DECLHIDDEN(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable)
131
132# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
133
134
135# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_BEGIN_COMMON()
136# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_BEGIN_COMMON()
137
138
139
140#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_XTAG
141/*
142 *
143 * Generate a vtable and associated methods for explicitly tagged items (XTAG).
144 *
145 * These turned out to be a little problematic during encoding since there are
146 * two tags, the first encapsulating the second, thus the enumeration has to be
147 * nested or we cannot calculate the size of the first tag.
148 *
149 *
150 */
151# define RTASN1TMPL_BEGIN_COMMON() RTASN1TMPL_SEMICOLON_DUMMY()
152# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
153# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
154# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
155# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
156# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
157# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
158 /* This is the method we need to make it work. */ \
159 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Enum)(PRTASN1CORE pThisCore, \
160 PFNRTASN1ENUMCALLBACK pfnCallback, \
161 uint32_t uDepth, void *pvUser) \
162 { \
163 RTASN1TMPL_TYPE *pThis = RT_FROM_MEMBER(pThisCore, RTASN1TMPL_TYPE, a_TnNm.a_CtxTagN); \
164 if (RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
165 return pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_TnNm.a_Name), #a_TnNm "." #a_Name, uDepth + 1, pvUser); \
166 return VINF_SUCCESS; \
167 } \
168 /* The reminder of the methods shouldn't normally be needed, just stub them. */ \
169 static DECLCALLBACK(void) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Delete)(PRTASN1CORE pThisCore) \
170 { AssertFailed(); RT_NOREF_PV(pThisCore); } \
171 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Clone)(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, \
172 PCRTASN1ALLOCATORVTABLE pAllocator) \
173 { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(pSrcCore); RT_NOREF_PV(pAllocator); return VERR_INTERNAL_ERROR_2; } \
174 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Compare)(PCRTASN1CORE pLeftCore, \
175 PCRTASN1CORE pRightCore) \
176 { AssertFailed(); RT_NOREF_PV(pLeftCore); RT_NOREF_PV(pRightCore); return VERR_INTERNAL_ERROR_2; } \
177 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_CheckSanity)(PCRTASN1CORE pThisCore, uint32_t fFlags, \
178 PRTERRINFO pErrInfo, const char *pszErrorTag) \
179 { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(fFlags); RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pszErrorTag); \
180 return VERR_INTERNAL_ERROR_2; } \
181 DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable) = \
182 { \
183 /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
184 /* .pszName = */ RT_XSTR(RTASN1TMPL_INT_NAME) "_XTAG_" RT_XSTR(a_Name), \
185 /* .cb = */ RT_SIZEOFMEMB(RTASN1TMPL_TYPE, a_TnNm), \
186 /* .uDefaultTag = */ a_uTag, \
187 /* .fDefaultClass = */ ASN1_TAGCLASS_CONTEXT, \
188 /* .uReserved = */ 0, \
189 RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Delete), \
190 RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Enum), \
191 RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Clone), \
192 RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Compare), \
193 RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_CheckSanity), \
194 /*.pfnEncodePrep */ NULL, \
195 /*.pfnEncodeWrite */ NULL \
196 }
197
198
199# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
200# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
201# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
202# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
203 RTASN1TMPL_SEMICOLON_DUMMY()
204# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
205 /* This is the method we need to make it work. */ \
206 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Enum)(PRTASN1CORE pThisCore, \
207 PFNRTASN1ENUMCALLBACK pfnCallback, \
208 uint32_t uDepth, void *pvUser) \
209 { \
210 if (RTASN1CORE_IS_PRESENT(pThisCore)) \
211 { \
212 /** @todo optimize this one day, possibly change the PCHOICE+XTAG representation. */ \
213 RTASN1TMPL_TYPE Tmp; \
214 *(PRTASN1CORE *)&Tmp.a_PtrTnNm = pThisCore; \
215 Assert(&Tmp.a_PtrTnNm->a_CtxTagN.Asn1Core == pThisCore); \
216 return pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&Tmp.a_PtrTnNm->a_Name), "T" #a_uTag "." #a_Name, uDepth + 1, pvUser); \
217 } \
218 return VINF_SUCCESS; \
219 } \
220 /* The reminder of the methods shouldn't normally be needed, just stub them. */ \
221 static DECLCALLBACK(void) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Delete)(PRTASN1CORE pThisCore) \
222 { AssertFailed(); RT_NOREF_PV(pThisCore); } \
223 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Clone)(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, \
224 PCRTASN1ALLOCATORVTABLE pAllocator) \
225 { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(pSrcCore); RT_NOREF_PV(pAllocator); return VERR_INTERNAL_ERROR_3; } \
226 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Compare)(PCRTASN1CORE pLeftCore, \
227 PCRTASN1CORE pRightCore) \
228 { AssertFailed(); RT_NOREF_PV(pLeftCore); RT_NOREF_PV(pRightCore); return VERR_INTERNAL_ERROR_3; } \
229 static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_CheckSanity)(PCRTASN1CORE pThisCore, uint32_t fFlags, \
230 PRTERRINFO pErrInfo, const char *pszErrorTag) \
231 { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(fFlags); RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pszErrorTag); \
232 return VERR_INTERNAL_ERROR_3; } \
233 DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable) = \
234 { \
235 /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
236 /* .pszName = */ RT_XSTR(RTASN1TMPL_INT_NAME) "_PCHOICE_XTAG_" RT_XSTR(a_Name), \
237 /* .cb = */ sizeof(*((RTASN1TMPL_TYPE *)(void *)0)->a_PtrTnNm), \
238 /* .uDefaultTag = */ a_uTag, \
239 /* .fDefaultClass = */ ASN1_TAGCLASS_CONTEXT, \
240 /* .uReserved = */ 0, \
241 RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Delete), \
242 RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Enum), \
243 RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Clone), \
244 RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Compare), \
245 RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_CheckSanity), \
246 /*.pfnEncodePrep */ NULL, \
247 /*.pfnEncodeWrite */ NULL \
248 }
249
250
251
252# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
253# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
254# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
255
256
257
258#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_VTABLE
259/*
260 *
261 * Internal header file.
262 *
263 */
264# ifndef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
265# define RTASN1TMPL_VTABLE_FN_ENCODE_PREP NULL
266# endif
267# ifndef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
268# define RTASN1TMPL_VTABLE_FN_ENCODE_WRITE NULL
269# endif
270# define RTASN1TMPL_BEGIN_COMMON(a_uDefaultTag, a_fDefaultClass) \
271 DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable) = \
272 { \
273 /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
274 /* .pszName = */ RT_XSTR(RTASN1TMPL_EXT_NAME), \
275 /* .cb = */ sizeof(RTASN1TMPL_TYPE), \
276 /* .uDefaultTag = */ a_uDefaultTag, \
277 /* .fDefaultClass = */ a_fDefaultClass, \
278 /* .uReserved = */ 0, \
279 (PFNRTASN1COREVTDTOR)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete), \
280 (PFNRTASN1COREVTENUM)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum), \
281 (PFNRTASN1COREVTCLONE)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone), \
282 (PFNRTASN1COREVTCOMPARE)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare), \
283 (PFNRTASN1COREVTCHECKSANITY)RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity), \
284 RTASN1TMPL_VTABLE_FN_ENCODE_PREP, \
285 RTASN1TMPL_VTABLE_FN_ENCODE_WRITE \
286 }
287
288# define RTASN1TMPL_BEGIN_SEQCORE() \
289 AssertCompileMemberOffset(RTASN1TMPL_TYPE, SeqCore, 0); \
290 RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SEQUENCE, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
291# define RTASN1TMPL_BEGIN_SETCORE() \
292 AssertCompileMemberOffset(RTASN1TMPL_TYPE, SetCore, 0); \
293 RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SET, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
294# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
295# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
296# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
297# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
298# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
299
300# define RTASN1TMPL_BEGIN_PCHOICE() \
301 AssertCompileMemberOffset(RTASN1TMPL_TYPE, Dummy, 0); \
302 RTASN1TMPL_BEGIN_COMMON(UINT8_MAX, UINT8_MAX)
303# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
304 RTASN1TMPL_SEMICOLON_DUMMY()
305# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
306 RTASN1TMPL_SEMICOLON_DUMMY()
307# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
308
309# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
310 AssertCompileMemberOffset(RTASN1TMPL_TYPE, SeqCore, 0); \
311 RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SEQUENCE, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
312# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
313 AssertCompileMemberOffset(RTASN1TMPL_TYPE, SetCore, 0); \
314 RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SET, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
315
316
317
318#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_INIT
319/*
320 *
321 * Initialization to standard / default values.
322 *
323 */
324# define RTASN1TMPL_BEGIN_COMMON() \
325RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Init)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
326{ \
327 RT_NOREF_PV(pAllocator); \
328 RT_ZERO(*pThis)
329# define RTASN1TMPL_END_COMMON() \
330 return rc; \
331} RTASN1TMPL_SEMICOLON_DUMMY()
332
333# define RTASN1TMPL_BEGIN_SEQCORE() \
334 RTASN1TMPL_BEGIN_COMMON(); \
335 int rc = RTAsn1SequenceCore_Init(&pThis->SeqCore, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable))
336# define RTASN1TMPL_BEGIN_SETCORE() \
337 RTASN1TMPL_BEGIN_COMMON(); \
338 int rc = RTAsn1SetCore_Init(&pThis->SetCore, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable))
339# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
340 if (RT_SUCCESS(rc)) \
341 rc = RT_CONCAT(a_Api,_Init)(&pThis->a_Name, pAllocator)
342
343# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
344 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
345 pThis->a_enmMembNm = RT_CONCAT(a_enmType,_NOT_PRESENT)
346# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
347 do { } while (0)
348# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
349
350# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
351 if (RT_SUCCESS(rc)) \
352 { \
353 rc = RT_CONCAT(a_Api,_InitDefault)(&pThis->a_Name, a_DefVal, pAllocator); \
354 if (RT_SUCCESS(rc)) \
355 rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
356 a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
357 }
358# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) do { } while (0) /* All optional members are left as not-present. */
359# define RTASN1TMPL_END_SEQCORE() \
360 if (RT_FAILURE(rc)) \
361 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
362 RTASN1TMPL_END_COMMON()
363# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
364
365/* No choice, just an empty, non-present structure. */
366# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_BEGIN_COMMON(); int rc = VINF_SUCCESS
367# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
368 do { } while (0)
369# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
370 do { } while (0)
371# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_END_COMMON()
372
373
374# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
375 RTASN1TMPL_BEGIN_COMMON(); \
376 RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
377 int rc = RT_CONCAT(a_OfApi,_Init)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)); \
378 if (RT_FAILURE(rc)) \
379 RT_ZERO(*pThis); \
380 RTASN1TMPL_END_COMMON()
381# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
382# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
383
384
385
386#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DECODE
387/*
388 *
389 * Decode ASN.1.
390 *
391 */
392# define RTASN1TMPL_BEGIN_COMMON() \
393RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
394 RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, const char *pszErrorTag) \
395{ \
396 RT_ZERO(*pThis);
397
398# define RTASN1TMPL_END_COMMON() \
399 return rc; \
400} RTASN1TMPL_SEMICOLON_DUMMY()
401
402
403# define RTASN1TMPL_BEGIN_SEQCORE() \
404 RTASN1TMPL_BEGIN_COMMON(); \
405 RTASN1CURSOR ThisCursor; \
406 int rc = RTAsn1CursorGetSequenceCursor(pCursor, fFlags, &pThis->SeqCore, &ThisCursor, pszErrorTag); \
407 if (RT_FAILURE(rc)) \
408 return rc; \
409 pCursor = &ThisCursor; \
410 pThis->SeqCore.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
411# define RTASN1TMPL_BEGIN_SETCORE() \
412 RTASN1TMPL_BEGIN_COMMON(); \
413 RTASN1CURSOR ThisCursor; \
414 int rc = RTAsn1CursorGetSetCursor(pCursor, fFlags, &pThis->SetCore, &ThisCursor, pszErrorTag); \
415 if (RT_FAILURE(rc)) \
416 return rc; \
417 pCursor = &ThisCursor; \
418 pThis->SetCore.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
419
420# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
421 if (RT_SUCCESS(rc)) \
422 rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, &pThis->a_Name, #a_Name)
423
424# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
425 if (RT_SUCCESS(rc)) \
426 { \
427 int rc2; /* not initialized! */ \
428 RTAsn1CursorInitAllocation(pCursor, &pThis->a_Allocation); \
429 pThis->a_enmMembNm = RT_CONCAT(a_enmType, _INVALID); \
430 if (false) do { /*nothing*/ } while (0)
431# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
432 else a_IfStmt \
433 do { \
434 rc2 = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
435 sizeof(*pThis->a_UnionNm.a_PtrName)); \
436 if (RT_SUCCESS(rc2)) \
437 { \
438 pThis->a_enmMembNm = a_enmValue; \
439 rc2 = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, pThis->a_UnionNm.a_PtrName, #a_UnionNm "." #a_PtrName); \
440 } \
441 } while (0)
442# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
443 rc = rc2; /* Should trigger warning if a _DEFAULT is missing. */ \
444 }
445
446# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
447 Error_Missing_Specific_Macro_In_Decode_Pass()
448
449# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
450 if (RT_SUCCESS(rc)) \
451 { \
452 if (RTAsn1CursorIsNextEx(pCursor, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue))) \
453 rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, &pThis->a_Name, #a_Name); \
454 else \
455 rc = RT_CONCAT(a_Api,_InitDefault)(&pThis->a_Name, a_DefVal, pCursor->pPrimary->pAllocator); \
456 if (RT_SUCCESS(rc)) \
457 rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
458 a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
459 } do {} while (0)
460
461# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
462 if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_UTF8_STRING, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE)) \
463 rc = RTAsn1CursorGetUtf8String(pCursor, 0, &pThis->a_Name, #a_Name)
464
465# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
466 if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) /** @todo || CER */) \
467 rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, &pThis->a_Name, #a_Name)
468
469# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
470 if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
471 rc = RTAsn1CursorGetBitStringEx(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, a_cMaxBits, &pThis->a_Name, #a_Name)
472
473# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
474 if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
475 { \
476 RTASN1CURSOR CtxCursor; \
477 rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
478 &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable), \
479 &pThis->a_TnNm.a_CtxTagN, &CtxCursor, #a_TnNm); \
480 if (RT_SUCCESS(rc)) \
481 { \
482 rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, 0, &pThis->a_TnNm.a_Name, #a_Name); \
483 if (RT_SUCCESS(rc)) \
484 rc = RTAsn1CursorCheckEnd(&CtxCursor); \
485 } \
486 } do { } while (0)
487
488# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
489 if (RT_SUCCESS(rc) && pCursor->cbLeft > 0) \
490 RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
491
492# define RTASN1TMPL_END_SEQCORE() \
493 if (RT_SUCCESS(rc)) \
494 rc = RTAsn1CursorCheckSeqEnd(&ThisCursor, &pThis->SeqCore); \
495 if (RT_SUCCESS(rc)) \
496 return VINF_SUCCESS; \
497 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
498 RTASN1TMPL_END_COMMON()
499# define RTASN1TMPL_END_SETCORE() \
500 if (RT_SUCCESS(rc)) \
501 rc = RTAsn1CursorCheckSetEnd(&ThisCursor, &pThis->SetCore); \
502 if (RT_SUCCESS(rc)) \
503 return VINF_SUCCESS; \
504 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
505 RTASN1TMPL_END_COMMON()
506
507# define RTASN1TMPL_BEGIN_PCHOICE() \
508 RTASN1TMPL_BEGIN_COMMON(); \
509 RT_NOREF_PV(fFlags); \
510 RTAsn1Dummy_InitEx(&pThis->Dummy); \
511 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
512 RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation); \
513 RTASN1CORE Asn1Peek; \
514 int rc = RTAsn1CursorPeek(pCursor, &Asn1Peek); \
515 if (RT_SUCCESS(rc)) \
516 { \
517 if (false) do {} while (0)
518# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
519 else if ( Asn1Peek.uTag == (a_uTag) \
520 && (Asn1Peek.fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue) /** @todo || CER */ ) ) \
521 do { \
522 pThis->enmChoice = a_enmChoice; \
523 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
524 if (RT_SUCCESS(rc)) \
525 rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, pThis->a_PtrName, #a_PtrName); \
526 } while (0)
527# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
528 else if (Asn1Peek.uTag == (a_uTag) && Asn1Peek.fClass == (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
529 do { \
530 pThis->enmChoice = a_enmChoice; \
531 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
532 if (RT_SUCCESS(rc)) \
533 { \
534 RTASN1CURSOR CtxCursor; \
535 rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
536 &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
537 &pThis->a_PtrTnNm->a_CtxTagN, &CtxCursor, "T" #a_uTag); \
538 if (RT_SUCCESS(rc)) \
539 rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, RTASN1CURSOR_GET_F_IMPLICIT, \
540 &pThis->a_PtrTnNm->a_Name, #a_Name); \
541 if (RT_SUCCESS(rc)) \
542 rc = RTAsn1CursorCheckEnd(&CtxCursor); \
543 } \
544 } while (0)
545#define RTASN1TMPL_END_PCHOICE() \
546 else \
547 rc = RTAsn1CursorSetInfo(pCursor, VERR_GENERAL_FAILURE, "%s: Unknown choice: tag=%#x fClass=%#x", \
548 pszErrorTag, Asn1Peek.uTag, Asn1Peek.fClass); \
549 if (RT_SUCCESS(rc)) \
550 return VINF_SUCCESS; \
551 } \
552 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
553 RTASN1TMPL_END_COMMON()
554
555
556# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember, a_fnGetCursor) \
557 RTASN1TMPL_BEGIN_COMMON(); \
558 RTASN1CURSOR ThisCursor; \
559 int rc = a_fnGetCursor(pCursor, fFlags, &pThis->a_OfMember, &ThisCursor, pszErrorTag); \
560 if (RT_SUCCESS(rc)) \
561 { \
562 pCursor = &ThisCursor; \
563 pThis->a_OfMember.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
564 RTAsn1CursorInitArrayAllocation(pCursor, &pThis->Allocation, sizeof(a_ItemType)); \
565 \
566 uint32_t i = 0; \
567 while ( pCursor->cbLeft > 0 \
568 && RT_SUCCESS(rc)) \
569 { \
570 rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, i, i + 1); \
571 if (RT_SUCCESS(rc)) \
572 { \
573 rc = RT_CONCAT(a_ItemApi,_DecodeAsn1)(pCursor, 0, pThis->papItems[i], "papItems[#]"); \
574 if (RT_SUCCESS(rc)) \
575 { \
576 i++; \
577 pThis->cItems = i; \
578 continue; \
579 } \
580 } \
581 break; \
582 } \
583 if (RT_SUCCESS(rc)) \
584 { \
585 rc = RTAsn1CursorCheckEnd(pCursor); \
586 if (RT_SUCCESS(rc)) \
587 return VINF_SUCCESS; \
588 } \
589 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
590 } \
591 RTASN1TMPL_END_COMMON()
592# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
593 RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore, RTAsn1CursorGetSequenceCursor)
594# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
595 RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore, RTAsn1CursorGetSetCursor)
596
597
598# define RTASN1TMPL_EXEC_DECODE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
599
600
601
602#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ENUM
603/*
604 *
605 * Enumeration.
606 *
607 */
608# define RTASN1TMPL_BEGIN_COMMON() \
609RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
610 PFNRTASN1ENUMCALLBACK pfnCallback, \
611 uint32_t uDepth, void *pvUser) \
612{ \
613 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
614 return VINF_SUCCESS; \
615 uDepth++; \
616 int rc = VINF_SUCCESS
617
618# define RTASN1TMPL_END_COMMON() \
619 return rc; \
620} RTASN1TMPL_SEMICOLON_DUMMY()
621
622# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
623# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
624# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
625 if (rc == VINF_SUCCESS) \
626 rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
627# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
628 if (rc == VINF_SUCCESS) \
629 switch (pThis->a_enmMembNm) \
630 { \
631 default: rc = VERR_INTERNAL_ERROR_3; break
632# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
633 case a_enmValue: \
634 rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_UnionNm.a_PtrName), #a_UnionNm "." #a_PtrName, \
635 uDepth, pvUser); \
636 break
637# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
638 case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
639 }
640# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
641 if (rc == VINF_SUCCESS && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
642 rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
643# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
644 if (rc == VINF_SUCCESS && RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
645 { \
646 rc = pfnCallback(&pThis->a_TnNm.a_CtxTagN.Asn1Core, #a_Name, uDepth, pvUser); \
647 } do {} while (0)
648# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
649# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
650
651
652# define RTASN1TMPL_BEGIN_PCHOICE() \
653 RTASN1TMPL_BEGIN_COMMON(); \
654 switch (pThis->enmChoice) \
655 { \
656 default: rc = VERR_INTERNAL_ERROR_3; break
657# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
658 case a_enmChoice: rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), #a_PtrName, uDepth, pvUser); break
659# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
660 case a_enmChoice: rc = pfnCallback(&pThis->a_PtrTnNm->a_CtxTagN.Asn1Core, "T" #a_uTag "." #a_CtxTagN, uDepth, pvUser); break
661#define RTASN1TMPL_END_PCHOICE() \
662 } \
663 RTASN1TMPL_END_COMMON()
664
665# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
666 RTASN1TMPL_BEGIN_COMMON(); \
667 for (uint32_t i = 0; i < pThis->cItems && rc == VINF_SUCCESS; i++) \
668 rc = pfnCallback(RT_CONCAT(a_ItemApi,_GetAsn1Core)(pThis->papItems[i]), "papItems[#]", uDepth, pvUser); \
669 RTASN1TMPL_END_COMMON()
670# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
671# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
672
673
674
675#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CLONE
676/*
677 *
678 * Clone another instance of the type.
679 *
680 */
681# define RTASN1TMPL_BEGIN_COMMON() \
682RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
683 RT_CONCAT(PC,RTASN1TMPL_TYPE) pSrc, \
684 PCRTASN1ALLOCATORVTABLE pAllocator) \
685{ \
686 RT_ZERO(*pThis); \
687 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pSrc)) \
688 return VINF_SUCCESS; \
689
690# define RTASN1TMPL_END_COMMON() \
691 return rc; \
692} RTASN1TMPL_SEMICOLON_DUMMY()
693
694# define RTASN1TMPL_BEGIN_SEQCORE() \
695 RTASN1TMPL_BEGIN_COMMON(); \
696 int rc = RTAsn1SequenceCore_Clone(&pThis->SeqCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SeqCore)
697# define RTASN1TMPL_BEGIN_SETCORE() \
698 RTASN1TMPL_BEGIN_COMMON(); \
699 int rc = RTAsn1SetCore_Clone(&pThis->SetCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SetCore)
700
701# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
702 if (RT_SUCCESS(rc)) \
703 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, &pSrc->a_Name, pAllocator); \
704
705# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
706 if (RT_SUCCESS(rc)) \
707 { \
708 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
709 pThis->a_enmMembNm = pSrc->a_enmMembNm; \
710 switch (pSrc->a_enmMembNm) \
711 { \
712 default: rc = VERR_INTERNAL_ERROR_3; break
713# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
714 case a_enmValue: \
715 rc = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
716 sizeof(*pThis->a_UnionNm.a_PtrName)); \
717 if (RT_SUCCESS(rc)) \
718 rc = RT_CONCAT(a_Api,_Clone)(pThis->a_UnionNm.a_PtrName, pSrc->a_UnionNm.a_PtrName, pAllocator); \
719 break
720# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
721 case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
722 } \
723 }
724
725/* Optional members and members with defaults are the same as a normal member when cloning. */
726# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
727 RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1Utf8String, a_Constraints RT_NOTHING)
728# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
729 if (RTASN1CORE_IS_PRESENT(&pSrc->a_TnNm.a_CtxTagN.Asn1Core) && RT_SUCCESS(rc)) \
730 { \
731 rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_TnNm.a_CtxTagN, &pSrc->a_TnNm.a_CtxTagN); \
732 if (RT_SUCCESS(rc)) \
733 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_TnNm.a_Name, &pSrc->a_TnNm.a_Name, pAllocator); \
734 } do { } while (0)
735
736# define RTASN1TMPL_END_SEQCORE() \
737 if (RT_FAILURE(rc)) \
738 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
739 RTASN1TMPL_END_COMMON()
740# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
741
742
743# define RTASN1TMPL_BEGIN_PCHOICE() \
744 RTASN1TMPL_BEGIN_COMMON(); \
745 RTAsn1Dummy_InitEx(&pThis->Dummy); \
746 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
747 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
748 int rc; \
749 pThis->enmChoice = pSrc->enmChoice; \
750 switch (pSrc->enmChoice) \
751 { \
752 default: rc = VERR_INTERNAL_ERROR_3; break
753# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
754 case a_enmChoice: \
755 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
756 if (RT_SUCCESS(rc)) \
757 rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc->a_PtrName, pAllocator); break
758# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
759 case a_enmChoice: /* A bit of presence paranoia here, but better safe than sorry... */ \
760 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
761 if (RT_SUCCESS(rc) && RTASN1CORE_IS_PRESENT(&pSrc->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
762 { \
763 RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_PtrTnNm->a_CtxTagN, &pSrc->a_PtrTnNm->a_CtxTagN); \
764 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, &pSrc->a_PtrTnNm->a_Name, pAllocator); \
765 } \
766 break
767#define RTASN1TMPL_END_PCHOICE() \
768 } \
769 if (RT_FAILURE(rc)) \
770 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
771 RTASN1TMPL_END_COMMON()
772
773
774# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
775 RTASN1TMPL_BEGIN_COMMON(); \
776 int rc = RT_CONCAT(a_OfApi,_Clone)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable), &pSrc->a_OfMember); \
777 if (RT_SUCCESS(rc)) \
778 { \
779 RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
780 uint32_t const cItems = pSrc->cItems; \
781 if (cItems > 0) \
782 { \
783 rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, 0, cItems); \
784 if (RT_SUCCESS(rc)) \
785 { \
786 uint32_t i = 0; \
787 while (i < cItems) \
788 { \
789 rc = RT_CONCAT(a_ItemApi,_Clone)(pThis->papItems[i], pSrc->papItems[i], pAllocator); \
790 if (RT_SUCCESS(rc)) \
791 pThis->cItems = ++i; \
792 else \
793 { \
794 pThis->cItems = i; \
795 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
796 return rc; \
797 } \
798 } \
799 } \
800 else \
801 RT_ZERO(*pThis); \
802 } \
803 } \
804 RTASN1TMPL_END_COMMON()
805# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
806# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
807
808# define RTASN1TMPL_EXEC_CLONE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
809
810
811
812#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_1
813/*
814 *
815 * Member setter helpers.
816 *
817 */
818# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
819# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
820#if 1 /** @todo later */
821# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
822#else
823# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
824 RTDECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RTASN1TMPL_TYPE *pThis, a_Type const *pValue, \
825 PCRTASN1ALLOCATORVTABLE pAllocator) \
826 { \
827 if (RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
828 RT_CONCAT(a_Api,_Delete)(&pThis->a_Name); \
829 return RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, pValue, pAllocator, true /* fResetImplicit */); \
830 } RTASN1TMPL_SEMICOLON_DUMMY()
831#endif
832
833# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
834# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
835# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
836# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
837
838
839# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
840# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
841# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
842# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
843
844
845# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
846# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
847
848
849
850#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_2
851/*
852 *
853 * Member setters.
854 *
855 */
856# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
857# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
858# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
859# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
860# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
861# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
862# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
863
864
865# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
866
867# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
868RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, RT_CONCAT(PC,a_Type) pSrc,\
869 PCRTASN1ALLOCATORVTABLE pAllocator) \
870{ \
871 AssertPtr(pSrc); AssertPtr(pThis); \
872 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
873 RTAsn1Dummy_InitEx(&pThis->Dummy); \
874 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
875 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
876 pThis->enmChoice = a_enmChoice; \
877 int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
878 if (RT_SUCCESS(rc)) \
879 { \
880 rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc, pAllocator); \
881 if (RT_SUCCESS(rc)) \
882 { \
883 RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName)); \
884 rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), \
885 a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
886 } \
887 } \
888 return rc; \
889} RTASN1TMPL_SEMICOLON_DUMMY()
890
891# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
892RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, RT_CONCAT(PC,a_Type) pSrc,\
893 PCRTASN1ALLOCATORVTABLE pAllocator) \
894{ \
895 AssertPtr(pThis); AssertPtr(pSrc); Assert(RT_CONCAT(a_Api,_IsPresent)(pSrc)); \
896 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
897 RTAsn1Dummy_InitEx(&pThis->Dummy); \
898 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
899 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
900 pThis->enmChoice = a_enmChoice; \
901 int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
902 if (RT_SUCCESS(rc)) \
903 { \
904 rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(&pThis->a_PtrTnNm->a_CtxTagN, \
905 &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
906 pAllocator); \
907 if (RT_SUCCESS(rc)) \
908 { \
909 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, pSrc, pAllocator); \
910 if (RT_SUCCESS(rc)) \
911 RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_PtrTnNm->a_Name)); \
912 } \
913 } \
914 return rc; \
915} RTASN1TMPL_SEMICOLON_DUMMY()
916
917# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
918
919
920# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
921# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
922
923
924#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ARRAY
925/*
926 *
927 * Array operations.
928 *
929 */
930# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
931# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
932# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
933# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
934# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
935# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
936# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
937# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
938# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
939 RTASN1TMPL_SEMICOLON_DUMMY()
940# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
941 RTASN1TMPL_SEMICOLON_DUMMY()
942# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
943
944# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
945 RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Erase)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition) \
946 { \
947 /* Check and adjust iPosition. */ \
948 uint32_t const cItems = pThis->cItems; \
949 if (iPosition < cItems) \
950 { /* likely */ } \
951 else \
952 { \
953 AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
954 AssertReturn(cItems > 0, VERR_OUT_OF_RANGE); \
955 iPosition = cItems - 1; \
956 } \
957 \
958 /* Delete the entry instance. */ \
959 RT_CONCAT(P, a_ItemType) pErased = pThis->papItems[iPosition]; \
960 if (RT_CONCAT(a_ItemApi,_IsPresent)(pErased)) \
961 RT_CONCAT(a_ItemApi,_Delete)(pErased); \
962 \
963 /* If not the final entry, shift the other entries up and place the erased on at the end. */ \
964 if (iPosition < cItems - 1) \
965 { \
966 memmove(&pThis->papItems[iPosition], &pThis->papItems[iPosition + 1], (cItems - iPosition - 1) * sizeof(void *)); \
967 pThis->papItems[cItems - 1] = pErased; \
968 } \
969 /* Commit the new array size. */ \
970 pThis->cItems = cItems - 1; \
971 \
972 /* Call the allocator to resize the array (ignore return). */ \
973 RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems - 1, cItems); \
974 return VINF_SUCCESS; \
975 } \
976 \
977 RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_InsertEx)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition, \
978 RT_CONCAT(PC, a_ItemType) pToClone, \
979 PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t *piActualPos) \
980 { \
981 /* Check and adjust iPosition. */ \
982 uint32_t const cItems = pThis->cItems; \
983 if (iPosition <= cItems) \
984 { /* likely */ } \
985 else \
986 { \
987 AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
988 iPosition = cItems; \
989 } \
990 \
991 /* Ensure we've got space in the array. */ \
992 int rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems, cItems + 1); \
993 if (RT_SUCCESS(rc)) \
994 { \
995 /* Initialize the new entry (which is currently at the end of the array) either with defaults or as a clone. */ \
996 RT_CONCAT(P,a_ItemType) pInserted = pThis->papItems[cItems]; \
997 if (RT_CONCAT(a_ItemApi,_IsPresent)(pToClone)) \
998 rc = RT_CONCAT(a_ItemApi,_Clone)(pInserted, pToClone, pAllocator); \
999 else \
1000 rc = RT_CONCAT(a_ItemApi,_Init)(pInserted, pAllocator); \
1001 if (RT_SUCCESS(rc)) \
1002 { \
1003 pThis->cItems = cItems + 1; \
1004 \
1005 /* If not inserting at the end of the array, shift existing items out of the way and insert the new as req. */ \
1006 if (iPosition != cItems) \
1007 { \
1008 memmove(&pThis->papItems[iPosition + 1], &pThis->papItems[iPosition], (cItems - iPosition) * sizeof(void *)); \
1009 pThis->papItems[iPosition] = pInserted; \
1010 } \
1011 \
1012 /* Done! */ \
1013 if (piActualPos) \
1014 *piActualPos = iPosition; \
1015 return VINF_SUCCESS; \
1016 } \
1017 RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems + 1, cItems); \
1018 } \
1019 return rc; \
1020 } RTASN1TMPL_SEMICOLON_DUMMY()
1021
1022# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1023# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1024
1025
1026#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_COMPARE
1027/*
1028 *
1029 * Compare two instances of the type.
1030 *
1031 */
1032# define RTASN1TMPL_BEGIN_COMMON() \
1033RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pLeft, \
1034 RT_CONCAT(PC,RTASN1TMPL_TYPE) pRight) \
1035{ \
1036 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pLeft)) \
1037 return 0 - (int)RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight); \
1038 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight)) \
1039 return -1; \
1040 int iDiff = 0
1041
1042# define RTASN1TMPL_END_COMMON() \
1043 return iDiff; \
1044} RTASN1TMPL_SEMICOLON_DUMMY()
1045
1046# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
1047# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
1048# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
1049 if (!iDiff) \
1050 iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_Name, &pRight->a_Name)
1051# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
1052 if (!iDiff && pLeft->a_enmMembNm != pRight->a_enmMembNm) \
1053 iDiff = pLeft->a_enmMembNm < pRight->a_enmMembNm ? -1 : 1; \
1054 else if (!iDiff) \
1055 switch (pLeft->a_enmMembNm) \
1056 { \
1057 default: break
1058# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1059 case a_enmValue: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_UnionNm.a_PtrName, pRight->a_UnionNm.a_PtrName); break
1060# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
1061 case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
1062 }
1063# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1064 if (!iDiff) \
1065 { \
1066 if (RTASN1CORE_IS_PRESENT(&pLeft->a_TnNm.a_CtxTagN.Asn1Core)) \
1067 { \
1068 if (RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core)) \
1069 iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_TnNm.a_Name, &pRight->a_TnNm.a_Name); \
1070 else \
1071 iDiff = -1; \
1072 } \
1073 else \
1074 iDiff = 0 - (int)RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core); \
1075 } do { } while (0)
1076# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
1077# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
1078
1079# define RTASN1TMPL_BEGIN_PCHOICE() \
1080 RTASN1TMPL_BEGIN_COMMON(); \
1081 if (pLeft->enmChoice != pRight->enmChoice) \
1082 return pLeft->enmChoice < pRight->enmChoice ? -1 : 1; \
1083 switch (pLeft->enmChoice) \
1084 { \
1085 default: break
1086# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
1087 case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_PtrName, pRight->a_PtrName); break
1088# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
1089 case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_PtrTnNm->a_Name, &pRight->a_PtrTnNm->a_Name); break
1090#define RTASN1TMPL_END_PCHOICE() \
1091 } \
1092 RTASN1TMPL_END_COMMON()
1093
1094
1095# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
1096 RTASN1TMPL_BEGIN_COMMON(); \
1097 uint32_t cItems = pLeft->cItems; \
1098 if (cItems == pRight->cItems) \
1099 for (uint32_t i = 0; iDiff == 0 && i < cItems; i++) \
1100 iDiff = RT_CONCAT(a_ItemApi,_Compare)(pLeft->papItems[i], pRight->papItems[i]); \
1101 else \
1102 iDiff = cItems < pRight->cItems ? -1 : 1; \
1103 RTASN1TMPL_END_COMMON()
1104# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1105# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1106
1107
1108
1109#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CHECK_SANITY
1110/*
1111 *
1112 * Checks the sanity of the type.
1113 *
1114 */
1115# ifndef RTASN1TMPL_SANITY_CHECK_EXPR
1116# define RTASN1TMPL_SANITY_CHECK_EXPR() VINF_SUCCESS
1117# endif
1118# define RTASN1TMPL_BEGIN_COMMON() \
1119RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pThis, uint32_t fFlags, \
1120 PRTERRINFO pErrInfo, const char *pszErrorTag) \
1121{ \
1122 if (RT_LIKELY(RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis))) \
1123 { /* likely */ } \
1124 else \
1125 return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing (%s).", pszErrorTag, RT_XSTR(RTASN1TMPL_TYPE)); \
1126 int rc = VINF_SUCCESS
1127
1128# define RTASN1TMPL_END_COMMON() \
1129 if (RT_SUCCESS(rc)) \
1130 rc = (RTASN1TMPL_SANITY_CHECK_EXPR()); \
1131 return rc; \
1132} RTASN1TMPL_SEMICOLON_DUMMY()
1133
1134# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
1135# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
1136# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
1137 if (RT_SUCCESS(rc)) \
1138 { \
1139 if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
1140 { \
1141 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1142 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1143 { a_Constraints } \
1144 } \
1145 else \
1146 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing member %s (%s).", \
1147 pszErrorTag, #a_Name, RT_XSTR(RTASN1TMPL_TYPE)); \
1148 } do {} while (0)
1149# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
1150 if (RT_SUCCESS(rc)) \
1151 switch (pThis->a_enmMembNm) \
1152 { \
1153 default: \
1154 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1155 "%s: Invalid " #a_enmMembNm " value: %d", pszErrorTag, pThis->a_enmMembNm); \
1156 break
1157# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1158 case a_enmValue: \
1159 rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_UnionNm.a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1160 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_UnionNm "." #a_PtrName); \
1161 break
1162# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
1163 case RT_CONCAT(a_enmType,_NOT_PRESENT): \
1164 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1165 "%s: Invalid " #a_enmMembNm " value: " #a_enmType "_NOT_PRESENT", pszErrorTag); \
1166 break; \
1167 }
1168# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
1169 if (RT_SUCCESS(rc) && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
1170 { \
1171 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1172 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1173 { a_Constraints } \
1174 }
1175# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1176 if (RT_SUCCESS(rc)) \
1177 { \
1178 bool const fOuterPresent = RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core); \
1179 bool const fInnerPresent = RT_CONCAT(a_Api,_IsPresent)(&pThis->a_TnNm.a_Name); \
1180 if (fOuterPresent && fInnerPresent) \
1181 { \
1182 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_TnNm.a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1183 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1184 { a_Constraints } \
1185 } \
1186 else if (RT_LIKELY(RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core) == fInnerPresent)) \
1187 { /* likely */ } \
1188 else \
1189 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1190 "%s::" #a_TnNm "." #a_Name ": Explict tag precense mixup; " #a_CtxTagN "=%d " #a_Name "=%d.", \
1191 pszErrorTag, fOuterPresent, fInnerPresent); \
1192 } do { } while (0)
1193# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
1194# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
1195
1196
1197# define RTASN1TMPL_BEGIN_PCHOICE() \
1198 RTASN1TMPL_BEGIN_COMMON(); \
1199 switch (pThis->enmChoice) \
1200 { \
1201 default: \
1202 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1203 "%s: Invalid enmChoice value: %d", pszErrorTag, pThis->enmChoice); \
1204 break
1205# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
1206 case a_enmChoice: \
1207 if (pThis->a_PtrName && RT_CONCAT(a_Api,_IsPresent)(pThis->a_PtrName)) \
1208 { \
1209 PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName); \
1210 if (pCore->uTag == a_uTag && pCore->fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) \
1211 { \
1212 rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1213 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1214 { a_Constraints } \
1215 } \
1216 else \
1217 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1218 "%s::" #a_Name ": Tag/class mismatch: expected %#x/%#x, actual %#x/%x.", \
1219 pszErrorTag, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue), pCore->uTag, pCore->fClass); \
1220 } \
1221 else \
1222 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
1223 break
1224# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
1225 case a_enmChoice: \
1226 if ( pThis->a_PtrTnNm \
1227 && RTASN1CORE_IS_PRESENT(&(pThis->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
1228 && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_PtrTnNm->a_Name) ) \
1229 { \
1230 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_PtrTnNm->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1231 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1232 { a_Constraints } \
1233 } \
1234 else \
1235 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
1236 break
1237#define RTASN1TMPL_END_PCHOICE() \
1238 } \
1239 RTASN1TMPL_END_COMMON()
1240
1241
1242# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
1243 RTASN1TMPL_BEGIN_COMMON(); \
1244 for (uint32_t i = 0; RT_SUCCESS(rc) && i < pThis->cItems; i++) \
1245 rc = RT_CONCAT(a_ItemApi,_CheckSanity)(pThis->papItems[i], fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1246 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::papItems[#]"); \
1247 if (RT_SUCCESS(rc)) { RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY(); } \
1248 RTASN1TMPL_END_COMMON()
1249# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1250# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1251
1252/* The constraints. */
1253# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints) \
1254 if (RT_SUCCESS(rc) && ((cbMin) != 0 || (cbMax) != UINT32_MAX)) \
1255 { \
1256 PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name); \
1257 if (RT_LIKELY(pCore->cb >= (cbMin) && pCore->cb <= (cbMax))) \
1258 { /* likely */ } \
1259 else \
1260 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1261 "%s::" #a_Name ": Content size is out of range: %#x not in {%#x..%#x}", \
1262 pszErrorTag, pCore->cb, cbMin, cbMax); \
1263 } \
1264 { a_MoreConstraints }
1265
1266# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints) \
1267 if (RT_SUCCESS(rc) && ((cMinBits) != 0 || (cMaxBits) != UINT32_MAX)) \
1268 { \
1269 if (RT_LIKELY( ((cMinBits) == 0 ? true : pThis->a_Name.cBits + 1U >= (cMinBits) + 1U /* warning avoiding */) \
1270 && ((cMaxBits) == UINT32_MAX ? true : pThis->a_Name.cBits + 1U <= (cMaxBits) + 1U /* ditto */) ) ) \
1271 { /* likely */ } \
1272 else \
1273 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1274 "%s::" #a_Name ": Bit size is out of range: %#x not in {%#x..%#x}", \
1275 pszErrorTag, pThis->a_Name.cBits, cMinBits, cMaxBits); \
1276 } \
1277 { a_MoreConstraints }
1278
1279# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints) \
1280 if (RT_SUCCESS(rc)) \
1281 { \
1282 if (RT_LIKELY( RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMin) >= 0 \
1283 && RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMax) <= 0) ) \
1284 { /* likely */ } \
1285 else \
1286 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1287 "%s::" #a_Name ": Out of range: %#x not in {%#llx..%#llx}", \
1288 pszErrorTag, pThis->a_Name.Asn1Core.cb > 8 ? UINT64_MAX : pThis->a_Name.uValue.u, \
1289 (uint64_t)(uMin), (uint64_t)(uMax)); \
1290 } \
1291 { a_MoreConstraints }
1292
1293# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints) \
1294 if (RT_SUCCESS(rc)) \
1295 { \
1296 if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
1297 { /* likely */ } \
1298 else \
1299 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Missing.", pszErrorTag); \
1300 } \
1301 { a_MoreConstraints }
1302
1303
1304
1305# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
1306
1307
1308#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DELETE
1309/*
1310 *
1311 * Delete wrappers.
1312 *
1313 */
1314# define RTASN1TMPL_BEGIN_COMMON() \
1315RTASN1TMPL_DECL(void) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis) \
1316{ \
1317 if (RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
1318 { do { } while (0)
1319
1320# define RTASN1TMPL_END_COMMON() \
1321 } \
1322 RT_ZERO(*pThis); \
1323} RTASN1TMPL_SEMICOLON_DUMMY()
1324
1325# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
1326# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
1327# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RT_CONCAT(a_Api,_Delete)(&pThis->a_Name)
1328# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
1329 switch (pThis->a_enmMembNm) \
1330 { \
1331 default: break
1332# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1333 case a_enmValue: \
1334 if (pThis->a_UnionNm.a_PtrName) \
1335 { \
1336 RT_CONCAT(a_Api,_Delete)(pThis->a_UnionNm.a_PtrName); \
1337 RTAsn1MemFree(&pThis->Allocation, pThis->a_UnionNm.a_PtrName); \
1338 pThis->a_UnionNm.a_PtrName = NULL; \
1339 } \
1340 break
1341# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
1342 }
1343# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
1344# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
1345
1346
1347# define RTASN1TMPL_BEGIN_PCHOICE() \
1348 RTASN1TMPL_BEGIN_COMMON(); \
1349 switch (pThis->enmChoice) \
1350 { \
1351 default: break
1352# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
1353 case a_enmChoice: \
1354 if (pThis->a_PtrName) \
1355 { \
1356 RT_CONCAT(a_Api,_Delete)(pThis->a_PtrName); \
1357 RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrName); \
1358 pThis->a_PtrName = NULL; \
1359 } \
1360 break
1361# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
1362 case a_enmChoice: \
1363 if (pThis->a_PtrTnNm) \
1364 { \
1365 RT_CONCAT(a_Api,_Delete)(&pThis->a_PtrTnNm->a_Name); \
1366 RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrTnNm); \
1367 pThis->a_PtrTnNm = NULL; \
1368 } \
1369 break
1370# define RTASN1TMPL_END_PCHOICE() \
1371 } \
1372 RTASN1TMPL_END_COMMON()
1373
1374
1375# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
1376 RTASN1TMPL_BEGIN_COMMON(); \
1377 uint32_t i = pThis->cItems; \
1378 while (i-- > 0) \
1379 RT_CONCAT(a_ItemApi,_Delete)(pThis->papItems[i]); \
1380 RTAsn1MemFreeArray(&pThis->Allocation, (void **)pThis->papItems); \
1381 pThis->papItems = NULL; \
1382 pThis->cItems = 0; \
1383 RTASN1TMPL_END_COMMON()
1384# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1385# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1386
1387
1388#else
1389# error "Invalid/missing RTASN1TMPL_PASS value."
1390#endif
1391
1392
1393
1394/*
1395 * Default aliases for simplified versions of macros if no specialization
1396 * was required above.
1397 */
1398/* Non-optional members. */
1399#ifndef RTASN1TMPL_MEMBER
1400# define RTASN1TMPL_MEMBER(a_Name, a_Type, a_Api) \
1401 RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
1402#endif
1403
1404#ifndef RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX
1405# define RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name) \
1406 RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
1407#endif
1408#ifndef RTASN1TMPL_MEMBER_UTF8_STRING
1409# define RTASN1TMPL_MEMBER_UTF8_STRING(a_Name) \
1410 RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
1411#endif
1412
1413#ifndef RTASN1TMPL_MEMBER_STRING_MIN_MAX
1414# define RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, a_cbMin, a_cbMax) \
1415 RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
1416#endif
1417#ifndef RTASN1TMPL_MEMBER_STRING
1418# define RTASN1TMPL_MEMBER_STRING(a_Name) \
1419 RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
1420#endif
1421#ifndef RTASN1TMPL_MEMBER_XTAG_EX
1422# define RTASN1TMPL_MEMBER_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1423 RTASN1TMPL_MEMBER_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1424#endif
1425
1426/* Any/dynamic members. */
1427#ifndef RTASN1TMPL_MEMBER_DYN_BEGIN
1428# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
1429#endif
1430#ifndef RTASN1TMPL_MEMBER_DYN_END
1431# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
1432#endif
1433#ifndef RTASN1TMPL_MEMBER_DYN_COMMON
1434# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1435 RTASN1TMPL_MEMBER(a_UnionNm.a_PtrName, a_Type, a_Api)
1436#endif
1437#ifndef RTASN1TMPL_MEMBER_DYN
1438# define RTASN1TMPL_MEMBER_DYN(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_WhenExpr) \
1439 RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, if (a_WhenExpr))
1440#endif
1441#ifndef RTASN1TMPL_MEMBER_DYN_DEFAULT
1442# define RTASN1TMPL_MEMBER_DYN_DEFAULT(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue) \
1443 RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, RT_NOTHING)
1444#endif
1445
1446/* Optional members. */
1447#ifndef RTASN1TMPL_MEMBER_OPT_EX
1448# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
1449 RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1450#endif
1451#ifndef RTASN1TMPL_MEMBER_OPT
1452# define RTASN1TMPL_MEMBER_OPT(a_Name, a_Type, a_Api) \
1453 RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
1454#endif
1455
1456#ifndef RTASN1TMPL_MEMBER_OPT_XTAG_EX
1457# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1458 RTASN1TMPL_MEMBER_OPT_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1459#endif
1460#ifndef RTASN1TMPL_MEMBER_OPT_XTAG
1461# define RTASN1TMPL_MEMBER_OPT_XTAG(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag) \
1462 RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, RT_NOTHING)
1463#endif
1464
1465#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_EX
1466# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
1467 RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1468#endif
1469#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UP
1470# define RTASN1TMPL_MEMBER_OPT_ITAG_UP(a_Name, a_Type, a_Api, a_uTag) \
1471 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
1472#endif
1473#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UC
1474# define RTASN1TMPL_MEMBER_OPT_ITAG_UC(a_Name, a_Type, a_Api, a_uTag) \
1475 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
1476#endif
1477#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_CP
1478# define RTASN1TMPL_MEMBER_OPT_ITAG_CP(a_Name, a_Type, a_Api, a_uTag) \
1479 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
1480#endif
1481#ifndef RTASN1TMPL_MEMBER_OPT_ITAG
1482# define RTASN1TMPL_MEMBER_OPT_ITAG(a_Name, a_Type, a_Api, a_uTag) \
1483 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
1484#endif
1485#ifndef RTASN1TMPL_MEMBER_OPT_ANY
1486# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
1487 RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
1488#endif
1489
1490#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_EX
1491# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
1492 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints RT_NOTHING)
1493#endif
1494#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_UP
1495# define RTASN1TMPL_MEMBER_DEF_ITAG_UP(a_Name, a_Type, a_Api, a_uTag, a_DefVal) \
1496 RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, a_DefVal, RT_NOTHING)
1497#endif
1498
1499#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
1500# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
1501 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, RTASN1BITSTRING, RTAsn1BitString, a_uTag, RTASN1TMPL_ITAG_F_CP, \
1502 RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, 0, a_cMaxBits, RT_NOTHING))
1503#endif
1504
1505#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
1506# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
1507 RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
1508#endif
1509#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
1510# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING(a_Name) \
1511 RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, RT_NOTHING)
1512#endif
1513
1514#ifndef RTASN1TMPL_MEMBER_OPT_STRING_EX
1515# define RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, a_Constraints) \
1516 RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
1517#endif
1518#ifndef RTASN1TMPL_MEMBER_OPT_STRING
1519# define RTASN1TMPL_MEMBER_OPT_STRING(a_Name) \
1520 RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, RT_NOTHING)
1521#endif
1522
1523/* Pointer choices. */
1524#ifndef RTASN1TMPL_PCHOICE_ITAG_UP
1525# define RTASN1TMPL_PCHOICE_ITAG_UP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1526 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
1527#endif
1528#ifndef RTASN1TMPL_PCHOICE_ITAG_UC
1529# define RTASN1TMPL_PCHOICE_ITAG_UC(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1530 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
1531#endif
1532#ifndef RTASN1TMPL_PCHOICE_ITAG_CP
1533# define RTASN1TMPL_PCHOICE_ITAG_CP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1534 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
1535#endif
1536#ifndef RTASN1TMPL_PCHOICE_ITAG
1537# define RTASN1TMPL_PCHOICE_ITAG(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1538 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
1539#endif
1540
1541#ifndef RTASN1TMPL_PCHOICE_XTAG
1542# define RTASN1TMPL_PCHOICE_XTAG(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api) \
1543 RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, RT_NOTHING)
1544#endif
1545
1546
1547/*
1548 * Constraints are only used in the sanity check pass, so provide subs for the
1549 * others passes.
1550 */
1551#ifndef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
1552# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints)
1553#endif
1554#ifndef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
1555# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints)
1556#endif
1557#ifndef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
1558# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints)
1559#endif
1560#ifndef RTASN1TMPL_MEMBER_CONSTR_PRESENT
1561# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints)
1562#endif
1563
1564
1565/*
1566 * Stub exec hacks.
1567 */
1568#ifndef RTASN1TMPL_EXEC_DECODE
1569# define RTASN1TMPL_EXEC_DECODE(a_Expr) /* no semi colon allowed after this */
1570#endif
1571#ifndef RTASN1TMPL_EXEC_CLONE
1572# define RTASN1TMPL_EXEC_CLONE(a_Expr) /* no semi colon allowed after this */
1573#endif
1574#ifndef RTASN1TMPL_EXEC_CHECK_SANITY
1575# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) /* no semi colon allowed after this */
1576#endif
1577
1578#define RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY() do { } while (0)
1579
1580
1581/*
1582 * Generate the requested code.
1583 */
1584#ifndef RTASN1TMPL_TEMPLATE_FILE
1585# error "No template file (RTASN1TMPL_TEMPLATE_FILE) is specified."
1586#endif
1587#include RTASN1TMPL_TEMPLATE_FILE
1588
1589
1590
1591/*
1592 * Undo all the macros.
1593 */
1594#undef RTASN1TMPL_DECL
1595#undef RTASN1TMPL_TYPE
1596#undef RTASN1TMPL_EXT_NAME
1597#undef RTASN1TMPL_INT_NAME
1598
1599#undef RTASN1TMPL_PASS
1600
1601#undef RTASN1TMPL_BEGIN_COMMON
1602#undef RTASN1TMPL_END_COMMON
1603#undef RTASN1TMPL_BEGIN_SEQCORE
1604#undef RTASN1TMPL_BEGIN_SETCORE
1605#undef RTASN1TMPL_MEMBER
1606#undef RTASN1TMPL_MEMBER_EX
1607#undef RTASN1TMPL_MEMBER_DYN_BEGIN
1608#undef RTASN1TMPL_MEMBER_DYN
1609#undef RTASN1TMPL_MEMBER_DYN_DEFAULT
1610#undef RTASN1TMPL_MEMBER_DYN_COMMON
1611#undef RTASN1TMPL_MEMBER_DYN_END
1612#undef RTASN1TMPL_MEMBER_OPT
1613#undef RTASN1TMPL_MEMBER_OPT_EX
1614#undef RTASN1TMPL_MEMBER_OPT_ITAG
1615#undef RTASN1TMPL_MEMBER_OPT_ITAG_EX
1616#undef RTASN1TMPL_MEMBER_OPT_ITAG_CP
1617#undef RTASN1TMPL_MEMBER_OPT_ITAG_UC
1618#undef RTASN1TMPL_MEMBER_OPT_ITAG_UP
1619#undef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
1620#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
1621#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
1622#undef RTASN1TMPL_MEMBER_OPT_XTAG
1623#undef RTASN1TMPL_MEMBER_OPT_XTAG_EX
1624#undef RTASN1TMPL_MEMBER_OPT_ANY
1625#undef RTASN1TMPL_MEMBER_DEF_ITAG_UP
1626#undef RTASN1TMPL_MEMBER_DEF_ITAG_EX
1627#undef RTASN1TMPL_END_SEQCORE
1628#undef RTASN1TMPL_END_SETCORE
1629
1630#undef RTASN1TMPL_BEGIN_PCHOICE
1631#undef RTASN1TMPL_PCHOICE_ITAG
1632#undef RTASN1TMPL_PCHOICE_ITAG_UP
1633#undef RTASN1TMPL_PCHOICE_ITAG_CP
1634#undef RTASN1TMPL_PCHOICE_ITAG_EX
1635#undef RTASN1TMPL_PCHOICE_XTAG
1636#undef RTASN1TMPL_PCHOICE_XTAG_EX
1637#undef RTASN1TMPL_END_PCHOICE
1638
1639#undef RTASN1TMPL_SET_SEQ_OF_COMMON
1640#undef RTASN1TMPL_SEQ_OF
1641#undef RTASN1TMPL_SET_OF
1642
1643#undef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
1644#undef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
1645
1646#undef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
1647#undef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
1648#undef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
1649#undef RTASN1TMPL_MEMBER_CONSTR_PRESENT
1650
1651#undef RTASN1TMPL_SANITY_CHECK_EXPR
1652
1653#undef RTASN1TMPL_EXEC_DECODE
1654#undef RTASN1TMPL_EXEC_CLONE
1655#undef RTASN1TMPL_EXEC_CHECK_SANITY
1656
1657#undef RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY
1658
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette