VirtualBox

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

Last change on this file since 64883 was 64883, checked in by vboxsync, 8 years ago

IPRT/ASN.1: Refactored array handling (SET OF, SEQUENCE OF) to use a pointer array instead of an object instance array. The old approach would move objects around in memory after they'd be initialized/decoded, making certain core optimziations involving pointers to object members impossible, as well as causing potentially causing trouble when modifying structures that takes down pointers after decoding. Fixed validation bug in rtCrX509Name_CheckSanityExtra where it didn't check that the RDNs had subitems but instead checked the parent twice (slight risk).

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