VirtualBox

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

Last change on this file since 73768 was 69105, checked in by vboxsync, 7 years ago

include/iprt/: (C) year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use