VirtualBox

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

Last change on this file since 76327 was 74672, checked in by vboxsync, 6 years ago

IPRT/asn1: Hacked code into handling the necessary indefinite length stuff from apple. bugref:9232

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 79.0 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 = 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); break
757# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
758 case a_enmChoice: /* A bit of presence paranoia here, but better safe than sorry... */ \
759 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
760 if (RT_SUCCESS(rc) && RTASN1CORE_IS_PRESENT(&pSrc->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
761 { \
762 RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_PtrTnNm->a_CtxTagN, &pSrc->a_PtrTnNm->a_CtxTagN); \
763 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, &pSrc->a_PtrTnNm->a_Name, pAllocator); \
764 } \
765 break
766#define RTASN1TMPL_END_PCHOICE() \
767 } \
768 if (RT_FAILURE(rc)) \
769 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
770 RTASN1TMPL_END_COMMON()
771
772
773# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
774 RTASN1TMPL_BEGIN_COMMON(); \
775 int rc = RT_CONCAT(a_OfApi,_Clone)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable), &pSrc->a_OfMember); \
776 if (RT_SUCCESS(rc)) \
777 { \
778 RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
779 uint32_t const cItems = pSrc->cItems; \
780 if (cItems > 0) \
781 { \
782 rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, 0, cItems); \
783 if (RT_SUCCESS(rc)) \
784 { \
785 uint32_t i = 0; \
786 while (i < cItems) \
787 { \
788 rc = RT_CONCAT(a_ItemApi,_Clone)(pThis->papItems[i], pSrc->papItems[i], pAllocator); \
789 if (RT_SUCCESS(rc)) \
790 pThis->cItems = ++i; \
791 else \
792 { \
793 pThis->cItems = i; \
794 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
795 return rc; \
796 } \
797 } \
798 } \
799 else \
800 RT_ZERO(*pThis); \
801 } \
802 } \
803 RTASN1TMPL_END_COMMON()
804# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
805# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
806
807# define RTASN1TMPL_EXEC_CLONE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
808
809
810
811#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_1
812/*
813 *
814 * Member setter helpers.
815 *
816 */
817# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
818# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
819#if 1 /** @todo later */
820# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
821#else
822# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
823 RTDECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RTASN1TMPL_TYPE *pThis, a_Type const *pValue, \
824 PCRTASN1ALLOCATORVTABLE pAllocator) \
825 { \
826 if (RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
827 RT_CONCAT(a_Api,_Delete)(&pThis->a_Name); \
828 return RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, pValue, pAllocator, true /* fResetImplicit */); \
829 } RTASN1TMPL_SEMICOLON_DUMMY()
830#endif
831
832# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
833# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
834# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
835# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
836
837
838# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
839# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
840# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
841# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
842
843
844# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
845# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
846
847
848
849#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_2
850/*
851 *
852 * Member setters.
853 *
854 */
855# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
856# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
857# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
858# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
859# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
860# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
861# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
862
863
864# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
865
866# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
867RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, RT_CONCAT(PC,a_Type) pSrc,\
868 PCRTASN1ALLOCATORVTABLE pAllocator) \
869{ \
870 AssertPtr(pSrc); AssertPtr(pThis); \
871 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
872 RTAsn1Dummy_InitEx(&pThis->Dummy); \
873 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
874 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
875 pThis->enmChoice = a_enmChoice; \
876 int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
877 if (RT_SUCCESS(rc)) \
878 { \
879 rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc, pAllocator); \
880 if (RT_SUCCESS(rc)) \
881 { \
882 RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName)); \
883 rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), \
884 a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
885 } \
886 } \
887 return rc; \
888} RTASN1TMPL_SEMICOLON_DUMMY()
889
890# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
891RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, RT_CONCAT(PC,a_Type) pSrc,\
892 PCRTASN1ALLOCATORVTABLE pAllocator) \
893{ \
894 AssertPtr(pThis); AssertPtr(pSrc); Assert(RT_CONCAT(a_Api,_IsPresent)(pSrc)); \
895 RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
896 RTAsn1Dummy_InitEx(&pThis->Dummy); \
897 pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
898 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
899 pThis->enmChoice = a_enmChoice; \
900 int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
901 if (RT_SUCCESS(rc)) \
902 { \
903 rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(&pThis->a_PtrTnNm->a_CtxTagN, \
904 &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
905 pAllocator); \
906 if (RT_SUCCESS(rc)) \
907 { \
908 rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, pSrc, pAllocator); \
909 if (RT_SUCCESS(rc)) \
910 RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_PtrTnNm->a_Name)); \
911 } \
912 } \
913 return rc; \
914} RTASN1TMPL_SEMICOLON_DUMMY()
915
916# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
917
918
919# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
920# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
921
922
923#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ARRAY
924/*
925 *
926 * Array operations.
927 *
928 */
929# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
930# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
931# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
932# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
933# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
934# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
935# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
936# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
937# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
938 RTASN1TMPL_SEMICOLON_DUMMY()
939# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
940 RTASN1TMPL_SEMICOLON_DUMMY()
941# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
942
943# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
944 RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Erase)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition) \
945 { \
946 /* Check and adjust iPosition. */ \
947 uint32_t const cItems = pThis->cItems; \
948 if (iPosition < cItems) \
949 { /* likely */ } \
950 else \
951 { \
952 AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
953 AssertReturn(cItems > 0, VERR_OUT_OF_RANGE); \
954 iPosition = cItems - 1; \
955 } \
956 \
957 /* Delete the entry instance. */ \
958 RT_CONCAT(P, a_ItemType) pErased = pThis->papItems[iPosition]; \
959 if (RT_CONCAT(a_ItemApi,_IsPresent)(pErased)) \
960 RT_CONCAT(a_ItemApi,_Delete)(pErased); \
961 \
962 /* If not the final entry, shift the other entries up and place the erased on at the end. */ \
963 if (iPosition < cItems - 1) \
964 { \
965 memmove(&pThis->papItems[iPosition], &pThis->papItems[iPosition + 1], (cItems - iPosition - 1) * sizeof(void *)); \
966 pThis->papItems[cItems - 1] = pErased; \
967 } \
968 /* Commit the new array size. */ \
969 pThis->cItems = cItems - 1; \
970 \
971 /* Call the allocator to resize the array (ignore return). */ \
972 RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems - 1, cItems); \
973 return VINF_SUCCESS; \
974 } \
975 \
976 RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_InsertEx)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition, \
977 RT_CONCAT(PC, a_ItemType) pToClone, \
978 PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t *piActualPos) \
979 { \
980 /* Check and adjust iPosition. */ \
981 uint32_t const cItems = pThis->cItems; \
982 if (iPosition <= cItems) \
983 { /* likely */ } \
984 else \
985 { \
986 AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
987 iPosition = cItems; \
988 } \
989 \
990 /* Ensure we've got space in the array. */ \
991 int rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems, cItems + 1); \
992 if (RT_SUCCESS(rc)) \
993 { \
994 /* Initialize the new entry (which is currently at the end of the array) either with defaults or as a clone. */ \
995 RT_CONCAT(P,a_ItemType) pInserted = pThis->papItems[cItems]; \
996 if (RT_CONCAT(a_ItemApi,_IsPresent)(pToClone)) \
997 rc = RT_CONCAT(a_ItemApi,_Clone)(pInserted, pToClone, pAllocator); \
998 else \
999 rc = RT_CONCAT(a_ItemApi,_Init)(pInserted, pAllocator); \
1000 if (RT_SUCCESS(rc)) \
1001 { \
1002 pThis->cItems = cItems + 1; \
1003 \
1004 /* If not inserting at the end of the array, shift existing items out of the way and insert the new as req. */ \
1005 if (iPosition != cItems) \
1006 { \
1007 memmove(&pThis->papItems[iPosition + 1], &pThis->papItems[iPosition], (cItems - iPosition) * sizeof(void *)); \
1008 pThis->papItems[iPosition] = pInserted; \
1009 } \
1010 \
1011 /* Done! */ \
1012 if (piActualPos) \
1013 *piActualPos = iPosition; \
1014 return VINF_SUCCESS; \
1015 } \
1016 RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems + 1, cItems); \
1017 } \
1018 return rc; \
1019 } RTASN1TMPL_SEMICOLON_DUMMY()
1020
1021# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1022# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1023
1024
1025#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_COMPARE
1026/*
1027 *
1028 * Compare two instances of the type.
1029 *
1030 */
1031# define RTASN1TMPL_BEGIN_COMMON() \
1032RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pLeft, \
1033 RT_CONCAT(PC,RTASN1TMPL_TYPE) pRight) \
1034{ \
1035 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pLeft)) \
1036 return 0 - (int)RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight); \
1037 if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight)) \
1038 return -1; \
1039 int iDiff = 0
1040
1041# define RTASN1TMPL_END_COMMON() \
1042 return iDiff; \
1043} RTASN1TMPL_SEMICOLON_DUMMY()
1044
1045# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
1046# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
1047# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
1048 if (!iDiff) \
1049 iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_Name, &pRight->a_Name)
1050# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
1051 if (!iDiff && pLeft->a_enmMembNm != pRight->a_enmMembNm) \
1052 iDiff = pLeft->a_enmMembNm < pRight->a_enmMembNm ? -1 : 1; \
1053 else if (!iDiff) \
1054 switch (pLeft->a_enmMembNm) \
1055 { \
1056 default: break
1057# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1058 case a_enmValue: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_UnionNm.a_PtrName, pRight->a_UnionNm.a_PtrName); break
1059# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
1060 case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
1061 }
1062# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1063 if (!iDiff) \
1064 { \
1065 if (RTASN1CORE_IS_PRESENT(&pLeft->a_TnNm.a_CtxTagN.Asn1Core)) \
1066 { \
1067 if (RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core)) \
1068 iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_TnNm.a_Name, &pRight->a_TnNm.a_Name); \
1069 else \
1070 iDiff = -1; \
1071 } \
1072 else \
1073 iDiff = 0 - (int)RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core); \
1074 } do { } while (0)
1075# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
1076# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
1077
1078# define RTASN1TMPL_BEGIN_PCHOICE() \
1079 RTASN1TMPL_BEGIN_COMMON(); \
1080 if (pLeft->enmChoice != pRight->enmChoice) \
1081 return pLeft->enmChoice < pRight->enmChoice ? -1 : 1; \
1082 switch (pLeft->enmChoice) \
1083 { \
1084 default: break
1085# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
1086 case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_PtrName, pRight->a_PtrName); break
1087# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
1088 case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_PtrTnNm->a_Name, &pRight->a_PtrTnNm->a_Name); break
1089#define RTASN1TMPL_END_PCHOICE() \
1090 } \
1091 RTASN1TMPL_END_COMMON()
1092
1093
1094# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
1095 RTASN1TMPL_BEGIN_COMMON(); \
1096 uint32_t cItems = pLeft->cItems; \
1097 if (cItems == pRight->cItems) \
1098 for (uint32_t i = 0; iDiff == 0 && i < cItems; i++) \
1099 iDiff = RT_CONCAT(a_ItemApi,_Compare)(pLeft->papItems[i], pRight->papItems[i]); \
1100 else \
1101 iDiff = cItems < pRight->cItems ? -1 : 1; \
1102 RTASN1TMPL_END_COMMON()
1103# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1104# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1105
1106
1107
1108#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CHECK_SANITY
1109/*
1110 *
1111 * Checks the sanity of the type.
1112 *
1113 */
1114# ifndef RTASN1TMPL_SANITY_CHECK_EXPR
1115# define RTASN1TMPL_SANITY_CHECK_EXPR() VINF_SUCCESS
1116# endif
1117# define RTASN1TMPL_BEGIN_COMMON() \
1118RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pThis, uint32_t fFlags, \
1119 PRTERRINFO pErrInfo, const char *pszErrorTag) \
1120{ \
1121 if (RT_LIKELY(RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis))) \
1122 { /* likely */ } \
1123 else \
1124 return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing (%s).", pszErrorTag, RT_XSTR(RTASN1TMPL_TYPE)); \
1125 int rc = VINF_SUCCESS
1126
1127# define RTASN1TMPL_END_COMMON() \
1128 if (RT_SUCCESS(rc)) \
1129 rc = (RTASN1TMPL_SANITY_CHECK_EXPR()); \
1130 return rc; \
1131} RTASN1TMPL_SEMICOLON_DUMMY()
1132
1133# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
1134# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
1135# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
1136 if (RT_SUCCESS(rc)) \
1137 { \
1138 if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
1139 { \
1140 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1141 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1142 { a_Constraints } \
1143 } \
1144 else \
1145 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing member %s (%s).", \
1146 pszErrorTag, #a_Name, RT_XSTR(RTASN1TMPL_TYPE)); \
1147 } do {} while (0)
1148# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
1149 if (RT_SUCCESS(rc)) \
1150 switch (pThis->a_enmMembNm) \
1151 { \
1152 default: \
1153 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1154 "%s: Invalid " #a_enmMembNm " value: %d", pszErrorTag, pThis->a_enmMembNm); \
1155 break
1156# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1157 case a_enmValue: \
1158 rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_UnionNm.a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1159 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_UnionNm "." #a_PtrName); \
1160 break
1161# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
1162 case RT_CONCAT(a_enmType,_NOT_PRESENT): \
1163 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1164 "%s: Invalid " #a_enmMembNm " value: " #a_enmType "_NOT_PRESENT", pszErrorTag); \
1165 break; \
1166 }
1167# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
1168 if (RT_SUCCESS(rc) && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
1169 { \
1170 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1171 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1172 { a_Constraints } \
1173 }
1174# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1175 if (RT_SUCCESS(rc)) \
1176 { \
1177 bool const fOuterPresent = RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core); \
1178 bool const fInnerPresent = RT_CONCAT(a_Api,_IsPresent)(&pThis->a_TnNm.a_Name); \
1179 if (fOuterPresent && fInnerPresent) \
1180 { \
1181 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_TnNm.a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1182 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1183 { a_Constraints } \
1184 } \
1185 else if (RT_LIKELY(RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core) == fInnerPresent)) \
1186 { /* likely */ } \
1187 else \
1188 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1189 "%s::" #a_TnNm "." #a_Name ": Explict tag precense mixup; " #a_CtxTagN "=%d " #a_Name "=%d.", \
1190 pszErrorTag, fOuterPresent, fInnerPresent); \
1191 } do { } while (0)
1192# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
1193# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
1194
1195
1196# define RTASN1TMPL_BEGIN_PCHOICE() \
1197 RTASN1TMPL_BEGIN_COMMON(); \
1198 switch (pThis->enmChoice) \
1199 { \
1200 default: \
1201 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1202 "%s: Invalid enmChoice value: %d", pszErrorTag, pThis->enmChoice); \
1203 break
1204# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
1205 case a_enmChoice: \
1206 if (pThis->a_PtrName && RT_CONCAT(a_Api,_IsPresent)(pThis->a_PtrName)) \
1207 { \
1208 PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName); \
1209 if (pCore->uTag == a_uTag && pCore->fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) \
1210 { \
1211 rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1212 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1213 { a_Constraints } \
1214 } \
1215 else \
1216 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1217 "%s::" #a_Name ": Tag/class mismatch: expected %#x/%#x, actual %#x/%x.", \
1218 pszErrorTag, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue), pCore->uTag, pCore->fClass); \
1219 } \
1220 else \
1221 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
1222 break
1223# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
1224 case a_enmChoice: \
1225 if ( pThis->a_PtrTnNm \
1226 && RTASN1CORE_IS_PRESENT(&(pThis->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
1227 && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_PtrTnNm->a_Name) ) \
1228 { \
1229 rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_PtrTnNm->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1230 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
1231 { a_Constraints } \
1232 } \
1233 else \
1234 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
1235 break
1236#define RTASN1TMPL_END_PCHOICE() \
1237 } \
1238 RTASN1TMPL_END_COMMON()
1239
1240
1241# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
1242 RTASN1TMPL_BEGIN_COMMON(); \
1243 for (uint32_t i = 0; RT_SUCCESS(rc) && i < pThis->cItems; i++) \
1244 rc = RT_CONCAT(a_ItemApi,_CheckSanity)(pThis->papItems[i], fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
1245 pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::papItems[#]"); \
1246 if (RT_SUCCESS(rc)) { RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY(); } \
1247 RTASN1TMPL_END_COMMON()
1248# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1249# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1250
1251/* The constraints. */
1252# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints) \
1253 if (RT_SUCCESS(rc) && ((cbMin) != 0 || (cbMax) != UINT32_MAX)) \
1254 { \
1255 PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name); \
1256 if (RT_LIKELY(pCore->cb >= (cbMin) && pCore->cb <= (cbMax))) \
1257 { /* likely */ } \
1258 else \
1259 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1260 "%s::" #a_Name ": Content size is out of range: %#x not in {%#x..%#x}", \
1261 pszErrorTag, pCore->cb, cbMin, cbMax); \
1262 } \
1263 { a_MoreConstraints }
1264
1265# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints) \
1266 if (RT_SUCCESS(rc) && ((cMinBits) != 0 || (cMaxBits) != UINT32_MAX)) \
1267 { \
1268 if (RT_LIKELY( ((cMinBits) == 0 ? true : pThis->a_Name.cBits + 1U >= (cMinBits) + 1U /* warning avoiding */) \
1269 && ((cMaxBits) == UINT32_MAX ? true : pThis->a_Name.cBits + 1U <= (cMaxBits) + 1U /* ditto */) ) ) \
1270 { /* likely */ } \
1271 else \
1272 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1273 "%s::" #a_Name ": Bit size is out of range: %#x not in {%#x..%#x}", \
1274 pszErrorTag, pThis->a_Name.cBits, cMinBits, cMaxBits); \
1275 } \
1276 { a_MoreConstraints }
1277
1278# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints) \
1279 if (RT_SUCCESS(rc)) \
1280 { \
1281 if (RT_LIKELY( RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMin) >= 0 \
1282 && RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMax) <= 0) ) \
1283 { /* likely */ } \
1284 else \
1285 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
1286 "%s::" #a_Name ": Out of range: %#x not in {%#llx..%#llx}", \
1287 pszErrorTag, pThis->a_Name.Asn1Core.cb > 8 ? UINT64_MAX : pThis->a_Name.uValue.u, \
1288 (uint64_t)(uMin), (uint64_t)(uMax)); \
1289 } \
1290 { a_MoreConstraints }
1291
1292# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints) \
1293 if (RT_SUCCESS(rc)) \
1294 { \
1295 if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
1296 { /* likely */ } \
1297 else \
1298 rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Missing.", pszErrorTag); \
1299 } \
1300 { a_MoreConstraints }
1301
1302
1303
1304# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
1305
1306
1307#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DELETE
1308/*
1309 *
1310 * Delete wrappers.
1311 *
1312 */
1313# define RTASN1TMPL_BEGIN_COMMON() \
1314RTASN1TMPL_DECL(void) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis) \
1315{ \
1316 if (RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
1317 { do { } while (0)
1318
1319# define RTASN1TMPL_END_COMMON() \
1320 } \
1321 RT_ZERO(*pThis); \
1322} RTASN1TMPL_SEMICOLON_DUMMY()
1323
1324# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
1325# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
1326# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RT_CONCAT(a_Api,_Delete)(&pThis->a_Name)
1327# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
1328 switch (pThis->a_enmMembNm) \
1329 { \
1330 default: break
1331# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1332 case a_enmValue: \
1333 if (pThis->a_UnionNm.a_PtrName) \
1334 { \
1335 RT_CONCAT(a_Api,_Delete)(pThis->a_UnionNm.a_PtrName); \
1336 RTAsn1MemFree(&pThis->Allocation, pThis->a_UnionNm.a_PtrName); \
1337 pThis->a_UnionNm.a_PtrName = NULL; \
1338 } \
1339 break
1340# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
1341 }
1342# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
1343# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
1344
1345
1346# define RTASN1TMPL_BEGIN_PCHOICE() \
1347 RTASN1TMPL_BEGIN_COMMON(); \
1348 switch (pThis->enmChoice) \
1349 { \
1350 default: break
1351# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
1352 case a_enmChoice: \
1353 if (pThis->a_PtrName) \
1354 { \
1355 RT_CONCAT(a_Api,_Delete)(pThis->a_PtrName); \
1356 RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrName); \
1357 pThis->a_PtrName = NULL; \
1358 } \
1359 break
1360# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
1361 case a_enmChoice: \
1362 if (pThis->a_PtrTnNm) \
1363 { \
1364 RT_CONCAT(a_Api,_Delete)(&pThis->a_PtrTnNm->a_Name); \
1365 RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrTnNm); \
1366 pThis->a_PtrTnNm = NULL; \
1367 } \
1368 break
1369# define RTASN1TMPL_END_PCHOICE() \
1370 } \
1371 RTASN1TMPL_END_COMMON()
1372
1373
1374# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
1375 RTASN1TMPL_BEGIN_COMMON(); \
1376 uint32_t i = pThis->cItems; \
1377 while (i-- > 0) \
1378 RT_CONCAT(a_ItemApi,_Delete)(pThis->papItems[i]); \
1379 RTAsn1MemFreeArray(&pThis->Allocation, (void **)pThis->papItems); \
1380 pThis->papItems = NULL; \
1381 pThis->cItems = 0; \
1382 RTASN1TMPL_END_COMMON()
1383# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1384# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
1385
1386
1387#else
1388# error "Invalid/missing RTASN1TMPL_PASS value."
1389#endif
1390
1391
1392
1393/*
1394 * Default aliases for simplified versions of macros if no specialization
1395 * was required above.
1396 */
1397/* Non-optional members. */
1398#ifndef RTASN1TMPL_MEMBER
1399# define RTASN1TMPL_MEMBER(a_Name, a_Type, a_Api) \
1400 RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
1401#endif
1402
1403#ifndef RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX
1404# define RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name) \
1405 RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
1406#endif
1407#ifndef RTASN1TMPL_MEMBER_UTF8_STRING
1408# define RTASN1TMPL_MEMBER_UTF8_STRING(a_Name) \
1409 RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
1410#endif
1411
1412#ifndef RTASN1TMPL_MEMBER_STRING_MIN_MAX
1413# define RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, a_cbMin, a_cbMax) \
1414 RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
1415#endif
1416#ifndef RTASN1TMPL_MEMBER_STRING
1417# define RTASN1TMPL_MEMBER_STRING(a_Name) \
1418 RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
1419#endif
1420#ifndef RTASN1TMPL_MEMBER_XTAG_EX
1421# define RTASN1TMPL_MEMBER_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1422 RTASN1TMPL_MEMBER_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1423#endif
1424
1425/* Any/dynamic members. */
1426#ifndef RTASN1TMPL_MEMBER_DYN_BEGIN
1427# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
1428#endif
1429#ifndef RTASN1TMPL_MEMBER_DYN_END
1430# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
1431#endif
1432#ifndef RTASN1TMPL_MEMBER_DYN_COMMON
1433# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
1434 RTASN1TMPL_MEMBER(a_UnionNm.a_PtrName, a_Type, a_Api)
1435#endif
1436#ifndef RTASN1TMPL_MEMBER_DYN
1437# define RTASN1TMPL_MEMBER_DYN(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_WhenExpr) \
1438 RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, if (a_WhenExpr))
1439#endif
1440#ifndef RTASN1TMPL_MEMBER_DYN_DEFAULT
1441# define RTASN1TMPL_MEMBER_DYN_DEFAULT(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue) \
1442 RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, RT_NOTHING)
1443#endif
1444
1445/* Optional members. */
1446#ifndef RTASN1TMPL_MEMBER_OPT_EX
1447# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
1448 RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1449#endif
1450#ifndef RTASN1TMPL_MEMBER_OPT
1451# define RTASN1TMPL_MEMBER_OPT(a_Name, a_Type, a_Api) \
1452 RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
1453#endif
1454
1455#ifndef RTASN1TMPL_MEMBER_OPT_XTAG_EX
1456# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
1457 RTASN1TMPL_MEMBER_OPT_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1458#endif
1459#ifndef RTASN1TMPL_MEMBER_OPT_XTAG
1460# define RTASN1TMPL_MEMBER_OPT_XTAG(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag) \
1461 RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, RT_NOTHING)
1462#endif
1463
1464#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_EX
1465# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
1466 RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
1467#endif
1468#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UP
1469# define RTASN1TMPL_MEMBER_OPT_ITAG_UP(a_Name, a_Type, a_Api, a_uTag) \
1470 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
1471#endif
1472#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UC
1473# define RTASN1TMPL_MEMBER_OPT_ITAG_UC(a_Name, a_Type, a_Api, a_uTag) \
1474 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
1475#endif
1476#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_CP
1477# define RTASN1TMPL_MEMBER_OPT_ITAG_CP(a_Name, a_Type, a_Api, a_uTag) \
1478 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
1479#endif
1480#ifndef RTASN1TMPL_MEMBER_OPT_ITAG
1481# define RTASN1TMPL_MEMBER_OPT_ITAG(a_Name, a_Type, a_Api, a_uTag) \
1482 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
1483#endif
1484#ifndef RTASN1TMPL_MEMBER_OPT_ANY
1485# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
1486 RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
1487#endif
1488
1489#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_EX
1490# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
1491 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints RT_NOTHING)
1492#endif
1493#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_UP
1494# define RTASN1TMPL_MEMBER_DEF_ITAG_UP(a_Name, a_Type, a_Api, a_uTag, a_DefVal) \
1495 RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, a_DefVal, RT_NOTHING)
1496#endif
1497
1498#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
1499# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
1500 RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, RTASN1BITSTRING, RTAsn1BitString, a_uTag, RTASN1TMPL_ITAG_F_CP, \
1501 RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, 0, a_cMaxBits, RT_NOTHING))
1502#endif
1503
1504#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
1505# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
1506 RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
1507#endif
1508#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
1509# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING(a_Name) \
1510 RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, RT_NOTHING)
1511#endif
1512
1513#ifndef RTASN1TMPL_MEMBER_OPT_STRING_EX
1514# define RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, a_Constraints) \
1515 RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
1516#endif
1517#ifndef RTASN1TMPL_MEMBER_OPT_STRING
1518# define RTASN1TMPL_MEMBER_OPT_STRING(a_Name) \
1519 RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, RT_NOTHING)
1520#endif
1521
1522/* Pointer choices. */
1523#ifndef RTASN1TMPL_PCHOICE_ITAG_UP
1524# define RTASN1TMPL_PCHOICE_ITAG_UP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1525 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
1526#endif
1527#ifndef RTASN1TMPL_PCHOICE_ITAG_UC
1528# define RTASN1TMPL_PCHOICE_ITAG_UC(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1529 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
1530#endif
1531#ifndef RTASN1TMPL_PCHOICE_ITAG_CP
1532# define RTASN1TMPL_PCHOICE_ITAG_CP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1533 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
1534#endif
1535#ifndef RTASN1TMPL_PCHOICE_ITAG
1536# define RTASN1TMPL_PCHOICE_ITAG(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
1537 RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
1538#endif
1539
1540#ifndef RTASN1TMPL_PCHOICE_XTAG
1541# define RTASN1TMPL_PCHOICE_XTAG(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api) \
1542 RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, RT_NOTHING)
1543#endif
1544
1545
1546/*
1547 * Constraints are only used in the sanity check pass, so provide subs for the
1548 * others passes.
1549 */
1550#ifndef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
1551# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints)
1552#endif
1553#ifndef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
1554# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints)
1555#endif
1556#ifndef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
1557# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints)
1558#endif
1559#ifndef RTASN1TMPL_MEMBER_CONSTR_PRESENT
1560# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints)
1561#endif
1562
1563
1564/*
1565 * Stub exec hacks.
1566 */
1567#ifndef RTASN1TMPL_EXEC_DECODE
1568# define RTASN1TMPL_EXEC_DECODE(a_Expr) /* no semi colon allowed after this */
1569#endif
1570#ifndef RTASN1TMPL_EXEC_CLONE
1571# define RTASN1TMPL_EXEC_CLONE(a_Expr) /* no semi colon allowed after this */
1572#endif
1573#ifndef RTASN1TMPL_EXEC_CHECK_SANITY
1574# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) /* no semi colon allowed after this */
1575#endif
1576
1577#define RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY() do { } while (0)
1578
1579
1580/*
1581 * Generate the requested code.
1582 */
1583#ifndef RTASN1TMPL_TEMPLATE_FILE
1584# error "No template file (RTASN1TMPL_TEMPLATE_FILE) is specified."
1585#endif
1586#include RTASN1TMPL_TEMPLATE_FILE
1587
1588
1589
1590/*
1591 * Undo all the macros.
1592 */
1593#undef RTASN1TMPL_DECL
1594#undef RTASN1TMPL_TYPE
1595#undef RTASN1TMPL_EXT_NAME
1596#undef RTASN1TMPL_INT_NAME
1597
1598#undef RTASN1TMPL_PASS
1599
1600#undef RTASN1TMPL_BEGIN_COMMON
1601#undef RTASN1TMPL_END_COMMON
1602#undef RTASN1TMPL_BEGIN_SEQCORE
1603#undef RTASN1TMPL_BEGIN_SETCORE
1604#undef RTASN1TMPL_MEMBER
1605#undef RTASN1TMPL_MEMBER_EX
1606#undef RTASN1TMPL_MEMBER_DYN_BEGIN
1607#undef RTASN1TMPL_MEMBER_DYN
1608#undef RTASN1TMPL_MEMBER_DYN_DEFAULT
1609#undef RTASN1TMPL_MEMBER_DYN_COMMON
1610#undef RTASN1TMPL_MEMBER_DYN_END
1611#undef RTASN1TMPL_MEMBER_OPT
1612#undef RTASN1TMPL_MEMBER_OPT_EX
1613#undef RTASN1TMPL_MEMBER_OPT_ITAG
1614#undef RTASN1TMPL_MEMBER_OPT_ITAG_EX
1615#undef RTASN1TMPL_MEMBER_OPT_ITAG_CP
1616#undef RTASN1TMPL_MEMBER_OPT_ITAG_UC
1617#undef RTASN1TMPL_MEMBER_OPT_ITAG_UP
1618#undef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
1619#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
1620#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
1621#undef RTASN1TMPL_MEMBER_OPT_XTAG
1622#undef RTASN1TMPL_MEMBER_OPT_XTAG_EX
1623#undef RTASN1TMPL_MEMBER_OPT_ANY
1624#undef RTASN1TMPL_MEMBER_DEF_ITAG_UP
1625#undef RTASN1TMPL_MEMBER_DEF_ITAG_EX
1626#undef RTASN1TMPL_END_SEQCORE
1627#undef RTASN1TMPL_END_SETCORE
1628
1629#undef RTASN1TMPL_BEGIN_PCHOICE
1630#undef RTASN1TMPL_PCHOICE_ITAG
1631#undef RTASN1TMPL_PCHOICE_ITAG_UP
1632#undef RTASN1TMPL_PCHOICE_ITAG_CP
1633#undef RTASN1TMPL_PCHOICE_ITAG_EX
1634#undef RTASN1TMPL_PCHOICE_XTAG
1635#undef RTASN1TMPL_PCHOICE_XTAG_EX
1636#undef RTASN1TMPL_END_PCHOICE
1637
1638#undef RTASN1TMPL_SET_SEQ_OF_COMMON
1639#undef RTASN1TMPL_SEQ_OF
1640#undef RTASN1TMPL_SET_OF
1641
1642#undef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
1643#undef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
1644
1645#undef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
1646#undef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
1647#undef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
1648#undef RTASN1TMPL_MEMBER_CONSTR_PRESENT
1649
1650#undef RTASN1TMPL_SANITY_CHECK_EXPR
1651
1652#undef RTASN1TMPL_EXEC_DECODE
1653#undef RTASN1TMPL_EXEC_CLONE
1654#undef RTASN1TMPL_EXEC_CHECK_SANITY
1655
1656#undef RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY
1657
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