summaryrefslogtreecommitdiffstats
path: root/include/iprt/asn1-generator-pass.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/iprt/asn1-generator-pass.h1657
1 files changed, 1657 insertions, 0 deletions
diff --git a/include/iprt/asn1-generator-pass.h b/include/iprt/asn1-generator-pass.h
new file mode 100644
index 00000000..a2488c43
--- /dev/null
+++ b/include/iprt/asn1-generator-pass.h
@@ -0,0 +1,1657 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, One Pass.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___iprt_asn1_generator_pass_h /* (special, only part of the file) */
+#define ___iprt_asn1_generator_pass_h
+
+#include <iprt/formats/asn1.h>
+#include <iprt/err.h>
+
+
+/** @def RTASN1TMPL_MEMBER_OPT_ANY
+ * Used for optional entries without any specific type at the end of a
+ * structure.
+ *
+ * For example PolicyQualifierInfo's qualifier member which is defined as:
+ * ANY DEFINED BY policyQualifierId
+ *
+ * Defaults to RTASN1TMPL_MEMBER_EX.
+ */
+
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_EX
+ * Optional member with implict tag, extended version.
+ *
+ * This is what all the other RTASN1TMPL_MEMBER_OPT_ITAG* macros defere to.
+ */
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_CP
+ * Optional member of a typical primitive type with an implicit context tag.
+ *
+ * Examples of this can be found in AuthorityKeyIdentifier where the first and
+ * last member are primitive types (normally anyways).:
+ * keyIdentifier [1] OCTET STRING OPTIONAL,
+ * authorityCertSerialNumber [3] INTEGER OPTIONAL
+ */
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_UC
+ * Optional member of a constructed type from the universal tag class.
+ */
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_UP
+ * Optional member of a primitive type from the universal tag class.
+ */
+
+
+/** @name Expansion Passes (RTASN1TMPL_PASS values)
+ * @{ */
+#define RTASN1TMPL_PASS_INTERNAL_HEADER 1
+
+#define RTASN1TMPL_PASS_XTAG 2
+#define RTASN1TMPL_PASS_VTABLE 3
+#define RTASN1TMPL_PASS_ENUM 4
+#define RTASN1TMPL_PASS_DELETE 5
+#define RTASN1TMPL_PASS_COMPARE 6
+
+#define RTASN1TMPL_PASS_CHECK_SANITY 8
+
+#define RTASN1TMPL_PASS_INIT 16
+#define RTASN1TMPL_PASS_CLONE 17
+#define RTASN1TMPL_PASS_SETTERS_1 18
+#define RTASN1TMPL_PASS_SETTERS_2 19
+#define RTASN1TMPL_PASS_ARRAY 20
+
+#define RTASN1TMPL_PASS_DECODE 24
+/** @} */
+
+/** @name ITAG clues
+ * @{ */
+#define RTASN1TMPL_ITAG_F_CC 1 /**< context, constructed. */
+#define RTASN1TMPL_ITAG_F_CP 2 /**< context, probably primary. (w/ numeric value) */
+#define RTASN1TMPL_ITAG_F_UP 3 /**< universal, probably primary. (w/ ASN1_TAG_XXX value) */
+#define RTASN1TMPL_ITAG_F_UC 4 /**< universal, constructed. (w/ ASN1_TAG_XXX value) */
+/** @} */
+/** Expands the ITAG clues into tag flag and tag class. */
+#define RTASN1TMPL_ITAG_F_EXPAND(a_fClue) \
+ ( a_fClue == RTASN1TMPL_ITAG_F_CC ? (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED ) \
+ : a_fClue == RTASN1TMPL_ITAG_F_CP ? (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE) \
+ : a_fClue == RTASN1TMPL_ITAG_F_UP ? (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE) \
+ : a_fClue == RTASN1TMPL_ITAG_F_UC ? (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED) \
+ : 0 )
+
+#define RTASN1TMPL_SEMICOLON_DUMMY() typedef unsigned RTASN1TMPLSEMICOLONDUMMY
+
+#endif /* !___iprt_asn1_generator_pass_h */
+
+
+#if RTASN1TMPL_PASS == RTASN1TMPL_PASS_INTERNAL_HEADER
+/*
+ *
+ * Internal header file.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() extern DECLHIDDEN(RTASN1COREVTABLE const) RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ extern "C" DECLHIDDEN(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable)
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ extern "C" DECLHIDDEN(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable)
+
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_BEGIN_COMMON()
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_XTAG
+/*
+ *
+ * Generate a vtable and associated methods for explicitly tagged items (XTAG).
+ *
+ * These turned out to be a little problematic during encoding since there are
+ * two tags, the first encapsulating the second, thus the enumeration has to be
+ * nested or we cannot calculate the size of the first tag.
+ *
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ /* This is the method we need to make it work. */ \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Enum)(PRTASN1CORE pThisCore, \
+ PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+ { \
+ RTASN1TMPL_TYPE *pThis = RT_FROM_MEMBER(pThisCore, RTASN1TMPL_TYPE, a_TnNm.a_CtxTagN); \
+ if (RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
+ return pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_TnNm.a_Name), #a_TnNm "." #a_Name, uDepth + 1, pvUser); \
+ return VINF_SUCCESS; \
+ } \
+ /* The reminder of the methods shouldn't normally be needed, just stub them. */ \
+ static DECLCALLBACK(void) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Delete)(PRTASN1CORE pThisCore) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Clone)(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(pSrcCore); RT_NOREF_PV(pAllocator); return VERR_INTERNAL_ERROR_2; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Compare)(PCRTASN1CORE pLeftCore, \
+ PCRTASN1CORE pRightCore) \
+ { AssertFailed(); RT_NOREF_PV(pLeftCore); RT_NOREF_PV(pRightCore); return VERR_INTERNAL_ERROR_2; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_CheckSanity)(PCRTASN1CORE pThisCore, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(fFlags); RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pszErrorTag); \
+ return VERR_INTERNAL_ERROR_2; } \
+ DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable) = \
+ { \
+ /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
+ /* .pszName = */ RT_XSTR(RTASN1TMPL_INT_NAME) "_XTAG_" RT_XSTR(a_Name), \
+ /* .cb = */ RT_SIZEOFMEMB(RTASN1TMPL_TYPE, a_TnNm), \
+ /* .uDefaultTag = */ a_uTag, \
+ /* .fDefaultClass = */ ASN1_TAGCLASS_CONTEXT, \
+ /* .uReserved = */ 0, \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Delete), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Enum), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Clone), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Compare), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_CheckSanity), \
+ /*.pfnEncodePrep */ NULL, \
+ /*.pfnEncodeWrite */ NULL \
+ }
+
+
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ /* This is the method we need to make it work. */ \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Enum)(PRTASN1CORE pThisCore, \
+ PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+ { \
+ if (RTASN1CORE_IS_PRESENT(pThisCore)) \
+ { \
+ /** @todo optimize this one day, possibly change the PCHOICE+XTAG representation. */ \
+ RTASN1TMPL_TYPE Tmp; \
+ *(PRTASN1CORE *)&Tmp.a_PtrTnNm = pThisCore; \
+ Assert(&Tmp.a_PtrTnNm->a_CtxTagN.Asn1Core == pThisCore); \
+ return pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&Tmp.a_PtrTnNm->a_Name), "T" #a_uTag "." #a_Name, uDepth + 1, pvUser); \
+ } \
+ return VINF_SUCCESS; \
+ } \
+ /* The reminder of the methods shouldn't normally be needed, just stub them. */ \
+ static DECLCALLBACK(void) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Delete)(PRTASN1CORE pThisCore) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Clone)(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(pSrcCore); RT_NOREF_PV(pAllocator); return VERR_INTERNAL_ERROR_3; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Compare)(PCRTASN1CORE pLeftCore, \
+ PCRTASN1CORE pRightCore) \
+ { AssertFailed(); RT_NOREF_PV(pLeftCore); RT_NOREF_PV(pRightCore); return VERR_INTERNAL_ERROR_3; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_CheckSanity)(PCRTASN1CORE pThisCore, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(fFlags); RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pszErrorTag); \
+ return VERR_INTERNAL_ERROR_3; } \
+ DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable) = \
+ { \
+ /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
+ /* .pszName = */ RT_XSTR(RTASN1TMPL_INT_NAME) "_PCHOICE_XTAG_" RT_XSTR(a_Name), \
+ /* .cb = */ sizeof(*((RTASN1TMPL_TYPE *)(void *)0)->a_PtrTnNm), \
+ /* .uDefaultTag = */ a_uTag, \
+ /* .fDefaultClass = */ ASN1_TAGCLASS_CONTEXT, \
+ /* .uReserved = */ 0, \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Delete), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Enum), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Clone), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Compare), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_CheckSanity), \
+ /*.pfnEncodePrep */ NULL, \
+ /*.pfnEncodeWrite */ NULL \
+ }
+
+
+
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_VTABLE
+/*
+ *
+ * Internal header file.
+ *
+ */
+# ifndef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
+# define RTASN1TMPL_VTABLE_FN_ENCODE_PREP NULL
+# endif
+# ifndef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
+# define RTASN1TMPL_VTABLE_FN_ENCODE_WRITE NULL
+# endif
+# define RTASN1TMPL_BEGIN_COMMON(a_uDefaultTag, a_fDefaultClass) \
+ DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable) = \
+ { \
+ /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
+ /* .pszName = */ RT_XSTR(RTASN1TMPL_EXT_NAME), \
+ /* .cb = */ sizeof(RTASN1TMPL_TYPE), \
+ /* .uDefaultTag = */ a_uDefaultTag, \
+ /* .fDefaultClass = */ a_fDefaultClass, \
+ /* .uReserved = */ 0, \
+ (PFNRTASN1COREVTDTOR)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete), \
+ (PFNRTASN1COREVTENUM)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum), \
+ (PFNRTASN1COREVTCLONE)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone), \
+ (PFNRTASN1COREVTCOMPARE)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare), \
+ (PFNRTASN1COREVTCHECKSANITY)RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity), \
+ RTASN1TMPL_VTABLE_FN_ENCODE_PREP, \
+ RTASN1TMPL_VTABLE_FN_ENCODE_WRITE \
+ }
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SeqCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SEQUENCE, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SetCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SET, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, Dummy, 0); \
+ RTASN1TMPL_BEGIN_COMMON(UINT8_MAX, UINT8_MAX)
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SeqCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SEQUENCE, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SetCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SET, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_INIT
+/*
+ *
+ * Initialization to standard / default values.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Init)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ RT_NOREF_PV(pAllocator); \
+ RT_ZERO(*pThis)
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SequenceCore_Init(&pThis->SeqCore, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable))
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SetCore_Init(&pThis->SetCore, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable))
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Init)(&pThis->a_Name, pAllocator)
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->a_enmMembNm = RT_CONCAT(a_enmType,_NOT_PRESENT)
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ do { } while (0)
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
+
+# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_Api,_InitDefault)(&pThis->a_Name, a_DefVal, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ }
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) do { } while (0) /* All optional members are left as not-present. */
+# define RTASN1TMPL_END_SEQCORE() \
+ if (RT_FAILURE(rc)) \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
+
+/* No choice, just an empty, non-present structure. */
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_BEGIN_COMMON(); int rc = VINF_SUCCESS
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ do { } while (0)
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ do { } while (0)
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
+ int rc = RT_CONCAT(a_OfApi,_Init)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)); \
+ if (RT_FAILURE(rc)) \
+ RT_ZERO(*pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DECODE
+/*
+ *
+ * Decode ASN.1.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
+ RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, const char *pszErrorTag) \
+{ \
+ RT_ZERO(*pThis);
+
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTASN1CURSOR ThisCursor; \
+ int rc = RTAsn1CursorGetSequenceCursor(pCursor, fFlags, &pThis->SeqCore, &ThisCursor, pszErrorTag); \
+ if (RT_FAILURE(rc)) \
+ return rc; \
+ pCursor = &ThisCursor; \
+ pThis->SeqCore.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTASN1CURSOR ThisCursor; \
+ int rc = RTAsn1CursorGetSetCursor(pCursor, fFlags, &pThis->SetCore, &ThisCursor, pszErrorTag); \
+ if (RT_FAILURE(rc)) \
+ return rc; \
+ pCursor = &ThisCursor; \
+ pThis->SetCore.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
+
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ int rc2; /* not initialized! */ \
+ RTAsn1CursorInitAllocation(pCursor, &pThis->a_Allocation); \
+ pThis->a_enmMembNm = RT_CONCAT(a_enmType, _INVALID); \
+ if (false) do { /*nothing*/ } while (0)
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ else a_IfStmt \
+ do { \
+ rc2 = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
+ sizeof(*pThis->a_UnionNm.a_PtrName)); \
+ if (RT_SUCCESS(rc2)) \
+ { \
+ pThis->a_enmMembNm = a_enmValue; \
+ rc2 = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, pThis->a_UnionNm.a_PtrName, #a_UnionNm "." #a_PtrName); \
+ } \
+ } while (0)
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
+ rc = rc2; /* Should trigger warning if a _DEFAULT is missing. */ \
+ }
+
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ Error_Missing_Specific_Macro_In_Decode_Pass()
+
+# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RTAsn1CursorIsNextEx(pCursor, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue))) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, &pThis->a_Name, #a_Name); \
+ else \
+ rc = RT_CONCAT(a_Api,_InitDefault)(&pThis->a_Name, a_DefVal, pCursor->pPrimary->pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ } do {} while (0)
+
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_UTF8_STRING, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE)) \
+ rc = RTAsn1CursorGetUtf8String(pCursor, 0, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) /** @todo || CER */) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
+ rc = RTAsn1CursorGetBitStringEx(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, a_cMaxBits, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
+ { \
+ RTASN1CURSOR CtxCursor; \
+ rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable), \
+ &pThis->a_TnNm.a_CtxTagN, &CtxCursor, #a_TnNm); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, 0, &pThis->a_TnNm.a_Name, #a_Name); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckEnd(&CtxCursor); \
+ } \
+ } do { } while (0)
+
+# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
+ if (RT_SUCCESS(rc) && pCursor->cbLeft > 0) \
+ RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+
+# define RTASN1TMPL_END_SEQCORE() \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckSeqEnd(&ThisCursor, &pThis->SeqCore); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckSetEnd(&ThisCursor, &pThis->SetCore); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RT_NOREF_PV(fFlags); \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation); \
+ RTASN1CORE Asn1Peek; \
+ int rc = RTAsn1CursorPeek(pCursor, &Asn1Peek); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (false) do {} while (0)
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ else if ( Asn1Peek.uTag == (a_uTag) \
+ && (Asn1Peek.fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue) /** @todo || CER */ ) ) \
+ do { \
+ pThis->enmChoice = a_enmChoice; \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, pThis->a_PtrName, #a_PtrName); \
+ } while (0)
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ else if (Asn1Peek.uTag == (a_uTag) && Asn1Peek.fClass == (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
+ do { \
+ pThis->enmChoice = a_enmChoice; \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTASN1CURSOR CtxCursor; \
+ rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
+ &pThis->a_PtrTnNm->a_CtxTagN, &CtxCursor, "T" #a_uTag); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, RTASN1CURSOR_GET_F_IMPLICIT, \
+ &pThis->a_PtrTnNm->a_Name, #a_Name); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckEnd(&CtxCursor); \
+ } \
+ } while (0)
+#define RTASN1TMPL_END_PCHOICE() \
+ else \
+ rc = RTAsn1CursorSetInfo(pCursor, VERR_GENERAL_FAILURE, "%s: Unknown choice: tag=%#x fClass=%#x", \
+ pszErrorTag, Asn1Peek.uTag, Asn1Peek.fClass); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ } \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember, a_fnGetCursor) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTASN1CURSOR ThisCursor; \
+ int rc = a_fnGetCursor(pCursor, fFlags, &pThis->a_OfMember, &ThisCursor, pszErrorTag); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ pCursor = &ThisCursor; \
+ pThis->a_OfMember.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1CursorInitArrayAllocation(pCursor, &pThis->Allocation, sizeof(a_ItemType)); \
+ \
+ uint32_t i = 0; \
+ while ( pCursor->cbLeft > 0 \
+ && RT_SUCCESS(rc)) \
+ { \
+ rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, i, i + 1); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_ItemApi,_DecodeAsn1)(pCursor, 0, pThis->papItems[i], "papItems[#]"); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ i++; \
+ pThis->cItems = i; \
+ continue; \
+ } \
+ } \
+ break; \
+ } \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RTAsn1CursorCheckEnd(pCursor); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ } \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ } \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore, RTAsn1CursorGetSequenceCursor)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore, RTAsn1CursorGetSetCursor)
+
+
+# define RTASN1TMPL_EXEC_DECODE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ENUM
+/*
+ *
+ * Enumeration.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+{ \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
+ return VINF_SUCCESS; \
+ uDepth++; \
+ int rc = VINF_SUCCESS
+
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (rc == VINF_SUCCESS) \
+ rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ if (rc == VINF_SUCCESS) \
+ switch (pThis->a_enmMembNm) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_UnionNm.a_PtrName), #a_UnionNm "." #a_PtrName, \
+ uDepth, pvUser); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
+ }
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (rc == VINF_SUCCESS && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (rc == VINF_SUCCESS && RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
+ { \
+ rc = pfnCallback(&pThis->a_TnNm.a_CtxTagN.Asn1Core, #a_Name, uDepth, pvUser); \
+ } do {} while (0)
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ switch (pThis->enmChoice) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), #a_PtrName, uDepth, pvUser); break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: rc = pfnCallback(&pThis->a_PtrTnNm->a_CtxTagN.Asn1Core, "T" #a_uTag "." #a_CtxTagN, uDepth, pvUser); break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ for (uint32_t i = 0; i < pThis->cItems && rc == VINF_SUCCESS; i++) \
+ rc = pfnCallback(RT_CONCAT(a_ItemApi,_GetAsn1Core)(pThis->papItems[i]), "papItems[#]", uDepth, pvUser); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CLONE
+/*
+ *
+ * Clone another instance of the type.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,RTASN1TMPL_TYPE) pSrc, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ RT_ZERO(*pThis); \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pSrc)) \
+ return VINF_SUCCESS; \
+
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SequenceCore_Clone(&pThis->SeqCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SeqCore)
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SetCore_Clone(&pThis->SetCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SetCore)
+
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, &pSrc->a_Name, pAllocator); \
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->a_enmMembNm = pSrc->a_enmMembNm; \
+ switch (pSrc->a_enmMembNm) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ rc = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
+ sizeof(*pThis->a_UnionNm.a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_UnionNm.a_PtrName, pSrc->a_UnionNm.a_PtrName, pAllocator); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
+ } \
+ }
+
+/* Optional members and members with defaults are the same as a normal member when cloning. */
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1Utf8String, a_Constraints RT_NOTHING)
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (RTASN1CORE_IS_PRESENT(&pSrc->a_TnNm.a_CtxTagN.Asn1Core) && RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_TnNm.a_CtxTagN, &pSrc->a_TnNm.a_CtxTagN); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_TnNm.a_Name, &pSrc->a_TnNm.a_Name, pAllocator); \
+ } do { } while (0)
+
+# define RTASN1TMPL_END_SEQCORE() \
+ if (RT_FAILURE(rc)) \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ int rc; \
+ pThis->enmChoice = pSrc->enmChoice; \
+ switch (pSrc->enmChoice) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc->a_PtrName, pAllocator); break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: /* A bit of presence paranoia here, but better safe than sorry... */ \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
+ if (RT_SUCCESS(rc) && RTASN1CORE_IS_PRESENT(&pSrc->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
+ { \
+ RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_PtrTnNm->a_CtxTagN, &pSrc->a_PtrTnNm->a_CtxTagN); \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, &pSrc->a_PtrTnNm->a_Name, pAllocator); \
+ } \
+ break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ if (RT_FAILURE(rc)) \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RT_CONCAT(a_OfApi,_Clone)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable), &pSrc->a_OfMember); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
+ uint32_t const cItems = pSrc->cItems; \
+ if (cItems > 0) \
+ { \
+ rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, 0, cItems); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ uint32_t i = 0; \
+ while (i < cItems) \
+ { \
+ rc = RT_CONCAT(a_ItemApi,_Clone)(pThis->papItems[i], pSrc->papItems[i], pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ pThis->cItems = ++i; \
+ else \
+ { \
+ pThis->cItems = i; \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ return rc; \
+ } \
+ } \
+ } \
+ else \
+ RT_ZERO(*pThis); \
+ } \
+ } \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
+
+# define RTASN1TMPL_EXEC_CLONE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_1
+/*
+ *
+ * Member setter helpers.
+ *
+ */
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+#if 1 /** @todo later */
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+#else
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ RTDECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RTASN1TMPL_TYPE *pThis, a_Type const *pValue, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { \
+ if (RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ RT_CONCAT(a_Api,_Delete)(&pThis->a_Name); \
+ return RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, pValue, pAllocator, true /* fResetImplicit */); \
+ } RTASN1TMPL_SEMICOLON_DUMMY()
+#endif
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_2
+/*
+ *
+ * Member setters.
+ *
+ */
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, RT_CONCAT(PC,a_Type) pSrc,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtr(pSrc); AssertPtr(pThis); \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->enmChoice = a_enmChoice; \
+ int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName)); \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ } \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, RT_CONCAT(PC,a_Type) pSrc,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtr(pThis); AssertPtr(pSrc); Assert(RT_CONCAT(a_Api,_IsPresent)(pSrc)); \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->enmChoice = a_enmChoice; \
+ int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(&pThis->a_PtrTnNm->a_CtxTagN, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
+ pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, pSrc, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_PtrTnNm->a_Name)); \
+ } \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ARRAY
+/*
+ *
+ * Array operations.
+ *
+ */
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Erase)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition) \
+ { \
+ /* Check and adjust iPosition. */ \
+ uint32_t const cItems = pThis->cItems; \
+ if (iPosition < cItems) \
+ { /* likely */ } \
+ else \
+ { \
+ AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
+ AssertReturn(cItems > 0, VERR_OUT_OF_RANGE); \
+ iPosition = cItems - 1; \
+ } \
+ \
+ /* Delete the entry instance. */ \
+ RT_CONCAT(P, a_ItemType) pErased = pThis->papItems[iPosition]; \
+ if (RT_CONCAT(a_ItemApi,_IsPresent)(pErased)) \
+ RT_CONCAT(a_ItemApi,_Delete)(pErased); \
+ \
+ /* If not the final entry, shift the other entries up and place the erased on at the end. */ \
+ if (iPosition < cItems - 1) \
+ { \
+ memmove(&pThis->papItems[iPosition], &pThis->papItems[iPosition + 1], (cItems - iPosition - 1) * sizeof(void *)); \
+ pThis->papItems[cItems - 1] = pErased; \
+ } \
+ /* Commit the new array size. */ \
+ pThis->cItems = cItems - 1; \
+ \
+ /* Call the allocator to resize the array (ignore return). */ \
+ RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems - 1, cItems); \
+ return VINF_SUCCESS; \
+ } \
+ \
+ RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_InsertEx)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition, \
+ RT_CONCAT(PC, a_ItemType) pToClone, \
+ PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t *piActualPos) \
+ { \
+ /* Check and adjust iPosition. */ \
+ uint32_t const cItems = pThis->cItems; \
+ if (iPosition <= cItems) \
+ { /* likely */ } \
+ else \
+ { \
+ AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
+ iPosition = cItems; \
+ } \
+ \
+ /* Ensure we've got space in the array. */ \
+ int rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems, cItems + 1); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ /* Initialize the new entry (which is currently at the end of the array) either with defaults or as a clone. */ \
+ RT_CONCAT(P,a_ItemType) pInserted = pThis->papItems[cItems]; \
+ if (RT_CONCAT(a_ItemApi,_IsPresent)(pToClone)) \
+ rc = RT_CONCAT(a_ItemApi,_Clone)(pInserted, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_ItemApi,_Init)(pInserted, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ pThis->cItems = cItems + 1; \
+ \
+ /* If not inserting at the end of the array, shift existing items out of the way and insert the new as req. */ \
+ if (iPosition != cItems) \
+ { \
+ memmove(&pThis->papItems[iPosition + 1], &pThis->papItems[iPosition], (cItems - iPosition) * sizeof(void *)); \
+ pThis->papItems[iPosition] = pInserted; \
+ } \
+ \
+ /* Done! */ \
+ if (piActualPos) \
+ *piActualPos = iPosition; \
+ return VINF_SUCCESS; \
+ } \
+ RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems + 1, cItems); \
+ } \
+ return rc; \
+ } RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_COMPARE
+/*
+ *
+ * Compare two instances of the type.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pLeft, \
+ RT_CONCAT(PC,RTASN1TMPL_TYPE) pRight) \
+{ \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pLeft)) \
+ return 0 - (int)RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight); \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight)) \
+ return -1; \
+ int iDiff = 0
+
+# define RTASN1TMPL_END_COMMON() \
+ return iDiff; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (!iDiff) \
+ iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_Name, &pRight->a_Name)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ if (!iDiff && pLeft->a_enmMembNm != pRight->a_enmMembNm) \
+ iDiff = pLeft->a_enmMembNm < pRight->a_enmMembNm ? -1 : 1; \
+ else if (!iDiff) \
+ switch (pLeft->a_enmMembNm) \
+ { \
+ default: break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_UnionNm.a_PtrName, pRight->a_UnionNm.a_PtrName); break
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
+ }
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (!iDiff) \
+ { \
+ if (RTASN1CORE_IS_PRESENT(&pLeft->a_TnNm.a_CtxTagN.Asn1Core)) \
+ { \
+ if (RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core)) \
+ iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_TnNm.a_Name, &pRight->a_TnNm.a_Name); \
+ else \
+ iDiff = -1; \
+ } \
+ else \
+ iDiff = 0 - (int)RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core); \
+ } do { } while (0)
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ if (pLeft->enmChoice != pRight->enmChoice) \
+ return pLeft->enmChoice < pRight->enmChoice ? -1 : 1; \
+ switch (pLeft->enmChoice) \
+ { \
+ default: break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_PtrName, pRight->a_PtrName); break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_PtrTnNm->a_Name, &pRight->a_PtrTnNm->a_Name); break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ uint32_t cItems = pLeft->cItems; \
+ if (cItems == pRight->cItems) \
+ for (uint32_t i = 0; iDiff == 0 && i < cItems; i++) \
+ iDiff = RT_CONCAT(a_ItemApi,_Compare)(pLeft->papItems[i], pRight->papItems[i]); \
+ else \
+ iDiff = cItems < pRight->cItems ? -1 : 1; \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CHECK_SANITY
+/*
+ *
+ * Checks the sanity of the type.
+ *
+ */
+# ifndef RTASN1TMPL_SANITY_CHECK_EXPR
+# define RTASN1TMPL_SANITY_CHECK_EXPR() VINF_SUCCESS
+# endif
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pThis, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+{ \
+ if (RT_LIKELY(RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis))) \
+ { /* likely */ } \
+ else \
+ return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing (%s).", pszErrorTag, RT_XSTR(RTASN1TMPL_TYPE)); \
+ int rc = VINF_SUCCESS
+
+# define RTASN1TMPL_END_COMMON() \
+ if (RT_SUCCESS(rc)) \
+ rc = (RTASN1TMPL_SANITY_CHECK_EXPR()); \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing member %s (%s).", \
+ pszErrorTag, #a_Name, RT_XSTR(RTASN1TMPL_TYPE)); \
+ } do {} while (0)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ if (RT_SUCCESS(rc)) \
+ switch (pThis->a_enmMembNm) \
+ { \
+ default: \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s: Invalid " #a_enmMembNm " value: %d", pszErrorTag, pThis->a_enmMembNm); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_UnionNm.a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_UnionNm "." #a_PtrName); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s: Invalid " #a_enmMembNm " value: " #a_enmType "_NOT_PRESENT", pszErrorTag); \
+ break; \
+ }
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc) && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ }
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ bool const fOuterPresent = RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core); \
+ bool const fInnerPresent = RT_CONCAT(a_Api,_IsPresent)(&pThis->a_TnNm.a_Name); \
+ if (fOuterPresent && fInnerPresent) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_TnNm.a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else if (RT_LIKELY(RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core) == fInnerPresent)) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_TnNm "." #a_Name ": Explict tag precense mixup; " #a_CtxTagN "=%d " #a_Name "=%d.", \
+ pszErrorTag, fOuterPresent, fInnerPresent); \
+ } do { } while (0)
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ switch (pThis->enmChoice) \
+ { \
+ default: \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s: Invalid enmChoice value: %d", pszErrorTag, pThis->enmChoice); \
+ break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: \
+ if (pThis->a_PtrName && RT_CONCAT(a_Api,_IsPresent)(pThis->a_PtrName)) \
+ { \
+ PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName); \
+ if (pCore->uTag == a_uTag && pCore->fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Tag/class mismatch: expected %#x/%#x, actual %#x/%x.", \
+ pszErrorTag, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue), pCore->uTag, pCore->fClass); \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
+ break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: \
+ if ( pThis->a_PtrTnNm \
+ && RTASN1CORE_IS_PRESENT(&(pThis->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
+ && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_PtrTnNm->a_Name) ) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_PtrTnNm->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
+ break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ for (uint32_t i = 0; RT_SUCCESS(rc) && i < pThis->cItems; i++) \
+ rc = RT_CONCAT(a_ItemApi,_CheckSanity)(pThis->papItems[i], fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::papItems[#]"); \
+ if (RT_SUCCESS(rc)) { RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY(); } \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+/* The constraints. */
+# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints) \
+ if (RT_SUCCESS(rc) && ((cbMin) != 0 || (cbMax) != UINT32_MAX)) \
+ { \
+ PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name); \
+ if (RT_LIKELY(pCore->cb >= (cbMin) && pCore->cb <= (cbMax))) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Content size is out of range: %#x not in {%#x..%#x}", \
+ pszErrorTag, pCore->cb, cbMin, cbMax); \
+ } \
+ { a_MoreConstraints }
+
+# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints) \
+ if (RT_SUCCESS(rc) && ((cMinBits) != 0 || (cMaxBits) != UINT32_MAX)) \
+ { \
+ if (RT_LIKELY( ((cMinBits) == 0 ? true : pThis->a_Name.cBits + 1U >= (cMinBits) + 1U /* warning avoiding */) \
+ && ((cMaxBits) == UINT32_MAX ? true : pThis->a_Name.cBits + 1U <= (cMaxBits) + 1U /* ditto */) ) ) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Bit size is out of range: %#x not in {%#x..%#x}", \
+ pszErrorTag, pThis->a_Name.cBits, cMinBits, cMaxBits); \
+ } \
+ { a_MoreConstraints }
+
+# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RT_LIKELY( RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMin) >= 0 \
+ && RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMax) <= 0) ) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Out of range: %#x not in {%#llx..%#llx}", \
+ pszErrorTag, pThis->a_Name.Asn1Core.cb > 8 ? UINT64_MAX : pThis->a_Name.uValue.u, \
+ (uint64_t)(uMin), (uint64_t)(uMax)); \
+ } \
+ { a_MoreConstraints }
+
+# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Missing.", pszErrorTag); \
+ } \
+ { a_MoreConstraints }
+
+
+
+# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DELETE
+/*
+ *
+ * Delete wrappers.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(void) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis) \
+{ \
+ if (RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
+ { do { } while (0)
+
+# define RTASN1TMPL_END_COMMON() \
+ } \
+ RT_ZERO(*pThis); \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RT_CONCAT(a_Api,_Delete)(&pThis->a_Name)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) \
+ switch (pThis->a_enmMembNm) \
+ { \
+ default: break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ if (pThis->a_UnionNm.a_PtrName) \
+ { \
+ RT_CONCAT(a_Api,_Delete)(pThis->a_UnionNm.a_PtrName); \
+ RTAsn1MemFree(&pThis->Allocation, pThis->a_UnionNm.a_PtrName); \
+ pThis->a_UnionNm.a_PtrName = NULL; \
+ } \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) \
+ }
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ switch (pThis->enmChoice) \
+ { \
+ default: break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: \
+ if (pThis->a_PtrName) \
+ { \
+ RT_CONCAT(a_Api,_Delete)(pThis->a_PtrName); \
+ RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrName); \
+ pThis->a_PtrName = NULL; \
+ } \
+ break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: \
+ if (pThis->a_PtrTnNm) \
+ { \
+ RT_CONCAT(a_Api,_Delete)(&pThis->a_PtrTnNm->a_Name); \
+ RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrTnNm); \
+ pThis->a_PtrTnNm = NULL; \
+ } \
+ break
+# define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ uint32_t i = pThis->cItems; \
+ while (i-- > 0) \
+ RT_CONCAT(a_ItemApi,_Delete)(pThis->papItems[i]); \
+ RTAsn1MemFreeArray(&pThis->Allocation, (void **)pThis->papItems); \
+ pThis->papItems = NULL; \
+ pThis->cItems = 0; \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+#else
+# error "Invalid/missing RTASN1TMPL_PASS value."
+#endif
+
+
+
+/*
+ * Default aliases for simplified versions of macros if no specialization
+ * was required above.
+ */
+/* Non-optional members. */
+#ifndef RTASN1TMPL_MEMBER
+# define RTASN1TMPL_MEMBER(a_Name, a_Type, a_Api) \
+ RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX
+# define RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name) \
+ RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
+#endif
+#ifndef RTASN1TMPL_MEMBER_UTF8_STRING
+# define RTASN1TMPL_MEMBER_UTF8_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_STRING_MIN_MAX
+# define RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, a_cbMin, a_cbMax) \
+ RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
+#endif
+#ifndef RTASN1TMPL_MEMBER_STRING
+# define RTASN1TMPL_MEMBER_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
+#endif
+#ifndef RTASN1TMPL_MEMBER_XTAG_EX
+# define RTASN1TMPL_MEMBER_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ RTASN1TMPL_MEMBER_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+
+/* Any/dynamic members. */
+#ifndef RTASN1TMPL_MEMBER_DYN_BEGIN
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN_END
+# define RTASN1TMPL_MEMBER_DYN_END(a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN_COMMON
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ RTASN1TMPL_MEMBER(a_UnionNm.a_PtrName, a_Type, a_Api)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN
+# define RTASN1TMPL_MEMBER_DYN(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_WhenExpr) \
+ RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, if (a_WhenExpr))
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN_DEFAULT
+# define RTASN1TMPL_MEMBER_DYN_DEFAULT(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue) \
+ RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, RT_NOTHING)
+#endif
+
+/* Optional members. */
+#ifndef RTASN1TMPL_MEMBER_OPT_EX
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT
+# define RTASN1TMPL_MEMBER_OPT(a_Name, a_Type, a_Api) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_XTAG_EX
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_XTAG
+# define RTASN1TMPL_MEMBER_OPT_XTAG(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_EX
+# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UP
+# define RTASN1TMPL_MEMBER_OPT_ITAG_UP(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UC
+# define RTASN1TMPL_MEMBER_OPT_ITAG_UC(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_CP
+# define RTASN1TMPL_MEMBER_OPT_ITAG_CP(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG
+# define RTASN1TMPL_MEMBER_OPT_ITAG(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ANY
+# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_EX
+# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_UP
+# define RTASN1TMPL_MEMBER_DEF_ITAG_UP(a_Name, a_Type, a_Api, a_uTag, a_DefVal) \
+ RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, a_DefVal, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
+# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, RTASN1BITSTRING, RTAsn1BitString, a_uTag, RTASN1TMPL_ITAG_F_CP, \
+ RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, 0, a_cMaxBits, RT_NOTHING))
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_STRING_EX
+# define RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_STRING
+# define RTASN1TMPL_MEMBER_OPT_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, RT_NOTHING)
+#endif
+
+/* Pointer choices. */
+#ifndef RTASN1TMPL_PCHOICE_ITAG_UP
+# define RTASN1TMPL_PCHOICE_ITAG_UP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG_UC
+# define RTASN1TMPL_PCHOICE_ITAG_UC(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG_CP
+# define RTASN1TMPL_PCHOICE_ITAG_CP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG
+# define RTASN1TMPL_PCHOICE_ITAG(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_PCHOICE_XTAG
+# define RTASN1TMPL_PCHOICE_XTAG(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+
+/*
+ * Constraints are only used in the sanity check pass, so provide subs for the
+ * others passes.
+ */
+#ifndef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_PRESENT
+# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints)
+#endif
+
+
+/*
+ * Stub exec hacks.
+ */
+#ifndef RTASN1TMPL_EXEC_DECODE
+# define RTASN1TMPL_EXEC_DECODE(a_Expr) /* no semi colon allowed after this */
+#endif
+#ifndef RTASN1TMPL_EXEC_CLONE
+# define RTASN1TMPL_EXEC_CLONE(a_Expr) /* no semi colon allowed after this */
+#endif
+#ifndef RTASN1TMPL_EXEC_CHECK_SANITY
+# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) /* no semi colon allowed after this */
+#endif
+
+#define RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY() do { } while (0)
+
+
+/*
+ * Generate the requested code.
+ */
+#ifndef RTASN1TMPL_TEMPLATE_FILE
+# error "No template file (RTASN1TMPL_TEMPLATE_FILE) is specified."
+#endif
+#include RTASN1TMPL_TEMPLATE_FILE
+
+
+
+/*
+ * Undo all the macros.
+ */
+#undef RTASN1TMPL_DECL
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+#undef RTASN1TMPL_PASS
+
+#undef RTASN1TMPL_BEGIN_COMMON
+#undef RTASN1TMPL_END_COMMON
+#undef RTASN1TMPL_BEGIN_SEQCORE
+#undef RTASN1TMPL_BEGIN_SETCORE
+#undef RTASN1TMPL_MEMBER
+#undef RTASN1TMPL_MEMBER_EX
+#undef RTASN1TMPL_MEMBER_DYN_BEGIN
+#undef RTASN1TMPL_MEMBER_DYN
+#undef RTASN1TMPL_MEMBER_DYN_DEFAULT
+#undef RTASN1TMPL_MEMBER_DYN_COMMON
+#undef RTASN1TMPL_MEMBER_DYN_END
+#undef RTASN1TMPL_MEMBER_OPT
+#undef RTASN1TMPL_MEMBER_OPT_EX
+#undef RTASN1TMPL_MEMBER_OPT_ITAG
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_EX
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_CP
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_UC
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_UP
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
+#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
+#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
+#undef RTASN1TMPL_MEMBER_OPT_XTAG
+#undef RTASN1TMPL_MEMBER_OPT_XTAG_EX
+#undef RTASN1TMPL_MEMBER_OPT_ANY
+#undef RTASN1TMPL_MEMBER_DEF_ITAG_UP
+#undef RTASN1TMPL_MEMBER_DEF_ITAG_EX
+#undef RTASN1TMPL_END_SEQCORE
+#undef RTASN1TMPL_END_SETCORE
+
+#undef RTASN1TMPL_BEGIN_PCHOICE
+#undef RTASN1TMPL_PCHOICE_ITAG
+#undef RTASN1TMPL_PCHOICE_ITAG_UP
+#undef RTASN1TMPL_PCHOICE_ITAG_CP
+#undef RTASN1TMPL_PCHOICE_ITAG_EX
+#undef RTASN1TMPL_PCHOICE_XTAG
+#undef RTASN1TMPL_PCHOICE_XTAG_EX
+#undef RTASN1TMPL_END_PCHOICE
+
+#undef RTASN1TMPL_SET_SEQ_OF_COMMON
+#undef RTASN1TMPL_SEQ_OF
+#undef RTASN1TMPL_SET_OF
+
+#undef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
+#undef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
+
+#undef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_PRESENT
+
+#undef RTASN1TMPL_SANITY_CHECK_EXPR
+
+#undef RTASN1TMPL_EXEC_DECODE
+#undef RTASN1TMPL_EXEC_CLONE
+#undef RTASN1TMPL_EXEC_CHECK_SANITY
+
+#undef RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY
+