VirtualBox

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

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

/include: scm --fix-header-guards. bugref:9344

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

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