VirtualBox

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

Last change on this file since 93941 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • 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-2022 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#ifndef ___iprt_asn1_generator_pass_h /* (special, only part of the file) */
27#define ___iprt_asn1_generator_pass_h
28
29#include <iprt/formats/asn1.h>
30#include <iprt/err.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 DECL_HIDDEN_DATA(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" DECL_HIDDEN_DATA(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" DECL_HIDDEN_DATA(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 = RTAsn1CursorCheckSeqEnd(&ThisCursor, &pThis->SeqCore); \
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() \
499 if (RT_SUCCESS(rc)) \
500 rc = RTAsn1CursorCheckSetEnd(&ThisCursor, &pThis->SetCore); \
501 if (RT_SUCCESS(rc)) \
502 return VINF_SUCCESS; \
503 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
504 RTASN1TMPL_END_COMMON()
505
506# define RTASN1TMPL_BEGIN_PCHOICE() \
507 RTASN1TMPL_BEGIN_COMMON(); \
508 RT_NOREF_PV(fFlags); \
509 RTAsn1Dummy_InitEx(&pThis->Dummy); \
510 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
511 RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation); \
512 RTASN1CORE Asn1Peek; \
513 int rc = RTAsn1CursorPeek(pCursor, &Asn1Peek); \
514 if (RT_SUCCESS(rc)) \
515 { \
516 if (false) do {} while (0)
517# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
518 else if ( Asn1Peek.uTag == (a_uTag) \
519 && (Asn1Peek.fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue) /** @todo || CER */ ) ) \
520 do { \
521 pThis->enmChoice = a_enmChoice; \
522 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
523 if (RT_SUCCESS(rc)) \
524 rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, pThis->a_PtrName, #a_PtrName); \
525 } while (0)
526# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
527 else if (Asn1Peek.uTag == (a_uTag) && Asn1Peek.fClass == (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
528 do { \
529 pThis->enmChoice = a_enmChoice; \
530 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
531 if (RT_SUCCESS(rc)) \
532 { \
533 RTASN1CURSOR CtxCursor; \
534 rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
535 &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
536 &pThis->a_PtrTnNm->a_CtxTagN, &CtxCursor, "T" #a_uTag); \
537 if (RT_SUCCESS(rc)) \
538 rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, RTASN1CURSOR_GET_F_IMPLICIT, \
539 &pThis->a_PtrTnNm->a_Name, #a_Name); \
540 if (RT_SUCCESS(rc)) \
541 rc = RTAsn1CursorCheckEnd(&CtxCursor); \
542 } \
543 } while (0)
544#define RTASN1TMPL_END_PCHOICE() \
545 else \
546 rc = RTAsn1CursorSetInfo(pCursor, VERR_GENERAL_FAILURE, "%s: Unknown choice: tag=%#x fClass=%#x", \
547 pszErrorTag, Asn1Peek.uTag, Asn1Peek.fClass); \
548 if (RT_SUCCESS(rc)) \
549 return VINF_SUCCESS; \
550 } \
551 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
552 RTASN1TMPL_END_COMMON()
553
554
555# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember, a_fnGetCursor) \
556 RTASN1TMPL_BEGIN_COMMON(); \
557 RTASN1CURSOR ThisCursor; \
558 int rc = a_fnGetCursor(pCursor, fFlags, &pThis->a_OfMember, &ThisCursor, pszErrorTag); \
559 if (RT_SUCCESS(rc)) \
560 { \
561 pCursor = &ThisCursor; \
562 pThis->a_OfMember.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
563 RTAsn1CursorInitArrayAllocation(pCursor, &pThis->Allocation, sizeof(a_ItemType)); \
564 \
565 uint32_t i = 0; \
566 while ( pCursor->cbLeft > 0 \
567 && RT_SUCCESS(rc)) \
568 { \
569 rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, i, i + 1); \
570 if (RT_SUCCESS(rc)) \
571 { \
572 rc = RT_CONCAT(a_ItemApi,_DecodeAsn1)(pCursor, 0, pThis->papItems[i], "papItems[#]"); \
573 if (RT_SUCCESS(rc)) \
574 { \
575 i++; \
576 pThis->cItems = i; \
577 continue; \
578 } \
579 } \
580 break; \
581 } \
582 if (RT_SUCCESS(rc)) \
583 { \
584 rc = RTAsn1CursorCheckEnd(pCursor); \
585 if (RT_SUCCESS(rc)) \
586 return VINF_SUCCESS; \
587 } \
588 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
589 } \
590 RTASN1TMPL_END_COMMON()
591# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
592 RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore, RTAsn1CursorGetSequenceCursor)
593# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
594 RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore, RTAsn1CursorGetSetCursor)
595
596
597# define RTASN1TMPL_EXEC_DECODE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
598
599
600
601#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ENUM
602/*
603 *
604 * Enumeration.
605 *
606 */
607# define RTASN1TMPL_BEGIN_COMMON() \
608RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
609 PFNRTASN1ENUMCALLBACK pfnCallback, \
610 uint32_t uDepth, void *pvUser) \
611{ \
612 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
613 return VINF_SUCCESS; \
614 uDepth++; \
615 int rc = VINF_SUCCESS
616
617# define RTASN1TMPL_END_COMMON() \
618 return rc; \
619} RTASN1TMPL_SEMICOLON_DUMMY()
620
621# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
622# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
623# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
624 if (rc == VINF_SUCCESS) \
625 rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
626# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
627 if (rc == VINF_SUCCESS) \
628 switch (pThis->a_enmMembNm) \
629 { \
630 default: rc = VERR_INTERNAL_ERROR_3; break
631# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
632 case a_enmValue: \
633 rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_UnionNm.a_PtrName), #a_UnionNm "." #a_PtrName, \
634 uDepth, pvUser); \
635 break
636# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
637 case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
638 }
639# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
640 if (rc == VINF_SUCCESS && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
641 rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
642# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
643 if (rc == VINF_SUCCESS && RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
644 { \
645 rc = pfnCallback(&pThis->a_TnNm.a_CtxTagN.Asn1Core, #a_Name, uDepth, pvUser); \
646 } do {} while (0)
647# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
648# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
649
650
651# define RTASN1TMPL_BEGIN_PCHOICE() \
652 RTASN1TMPL_BEGIN_COMMON(); \
653 switch (pThis->enmChoice) \
654 { \
655 default: rc = VERR_INTERNAL_ERROR_3; break
656# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
657 case a_enmChoice: rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), #a_PtrName, uDepth, pvUser); break
658# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
659 case a_enmChoice: rc = pfnCallback(&pThis->a_PtrTnNm->a_CtxTagN.Asn1Core, "T" #a_uTag "." #a_CtxTagN, uDepth, pvUser); break
660#define RTASN1TMPL_END_PCHOICE() \
661 } \
662 RTASN1TMPL_END_COMMON()
663
664# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
665 RTASN1TMPL_BEGIN_COMMON(); \
666 for (uint32_t i = 0; i < pThis->cItems && rc == VINF_SUCCESS; i++) \
667 rc = pfnCallback(RT_CONCAT(a_ItemApi,_GetAsn1Core)(pThis->papItems[i]), "papItems[#]", uDepth, pvUser); \
668 RTASN1TMPL_END_COMMON()
669# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
670# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
671
672
673
674#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CLONE
675/*
676 *
677 * Clone another instance of the type.
678 *
679 */
680# define RTASN1TMPL_BEGIN_COMMON() \
681RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
682 RT_CONCAT(PC,RTASN1TMPL_TYPE) pSrc, \
683 PCRTASN1ALLOCATORVTABLE pAllocator) \
684{ \
685 RT_ZERO(*pThis); \
686 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pSrc)) \
687 return VINF_SUCCESS; \
688
689# define RTASN1TMPL_END_COMMON() \
690 return rc; \
691} RTASN1TMPL_SEMICOLON_DUMMY()
692
693# define RTASN1TMPL_BEGIN_SEQCORE() \
694 RTASN1TMPL_BEGIN_COMMON(); \
695 int rc = RTAsn1SequenceCore_Clone(&pThis->SeqCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SeqCore)
696# define RTASN1TMPL_BEGIN_SETCORE() \
697 RTASN1TMPL_BEGIN_COMMON(); \
698 int rc = RTAsn1SetCore_Clone(&pThis->SetCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SetCore)
699
700# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
701 if (RT_SUCCESS(rc)) \
702 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, &pSrc->a_Name, pAllocator); \
703
704# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
705 if (RT_SUCCESS(rc)) \
706 { \
707 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
708 pThis->a_enmMembNm = pSrc->a_enmMembNm; \
709 switch (pSrc->a_enmMembNm) \
710 { \
711 default: rc = VERR_INTERNAL_ERROR_3; break
712# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
713 case a_enmValue: \
714 rc = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
715 sizeof(*pThis->a_UnionNm.a_PtrName)); \
716 if (RT_SUCCESS(rc)) \
717 rc = RT_CONCAT(a_Api,_Clone)(pThis->a_UnionNm.a_PtrName, pSrc->a_UnionNm.a_PtrName, pAllocator); \
718 break
719# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
720 case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
721 } \
722 }
723
724/* Optional members and members with defaults are the same as a normal member when cloning. */
725# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
726 RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1Utf8String, a_Constraints RT_NOTHING)
727# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
728 if (RTASN1CORE_IS_PRESENT(&pSrc->a_TnNm.a_CtxTagN.Asn1Core) && RT_SUCCESS(rc)) \
729 { \
730 rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_TnNm.a_CtxTagN, &pSrc->a_TnNm.a_CtxTagN); \
731 if (RT_SUCCESS(rc)) \
732 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_TnNm.a_Name, &pSrc->a_TnNm.a_Name, pAllocator); \
733 } do { } while (0)
734
735# define RTASN1TMPL_END_SEQCORE() \
736 if (RT_FAILURE(rc)) \
737 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
738 RTASN1TMPL_END_COMMON()
739# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
740
741
742# define RTASN1TMPL_BEGIN_PCHOICE() \
743 RTASN1TMPL_BEGIN_COMMON(); \
744 RTAsn1Dummy_InitEx(&pThis->Dummy); \
745 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
746 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
747 int rc; \
748 pThis->enmChoice = pSrc->enmChoice; \
749 switch (pSrc->enmChoice) \
750 { \
751 default: rc = VERR_INTERNAL_ERROR_3; break
752# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
753 case a_enmChoice: \
754 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
755 if (RT_SUCCESS(rc)) \
756 rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc->a_PtrName, pAllocator); \
757 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