VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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