VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-basics.cpp@ 53401

Last change on this file since 53401 was 51770, checked in by vboxsync, 11 years ago

Merged in iprt++ dev branch.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.2 KB
Line 
1/* $Id: asn1-basics.cpp 51770 2014-07-01 18:14:02Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, Basic Operations.
4 */
5
6/*
7 * Copyright (C) 2006-2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include "internal/iprt.h"
31#include <iprt/asn1.h>
32
33#include <iprt/alloca.h>
34#include <iprt/bignum.h>
35#include <iprt/ctype.h>
36#include <iprt/err.h>
37#include <iprt/string.h>
38#include <iprt/uni.h>
39
40#include <iprt/formats/asn1.h>
41
42
43/*******************************************************************************
44* Structures and Typedefs *
45*******************************************************************************/
46/**
47 * ASN.1 content/value allocation.
48 *
49 * The currently most frequent use of the RTAsn1 module is to decode ASN.1 byte
50 * streams. In that scenario we do not allocate memory for the raw content
51 * bytes, but share it with the byte stream. Also, a great number of RTASN1CORE
52 * structures will never need to have any content bytes allocated with this.
53 *
54 * So, in order to avoid adding an extra 16 (64-bit) or 8 (32-bit) bytes to each
55 * RTASN1CORE structure just to keep track of the occational content allocation,
56 * we put the allocator tracking structure inside the allocation. During
57 * allocator operations it lives temporarily on the stack.
58 */
59typedef struct RTASN1MEMCONTENT
60{
61 /** The allocation tracker. */
62 RTASN1ALLOCATION Allocation;
63#if ARCH_BITS == 32
64 uint32_t Padding; /**< Alignment padding. */
65#endif
66 /** The content bytes, i.e. what RTASN1CORE::uData.pv points to. Use a 64-bit
67 * type here to emphasize that it's 8-byte aligned on all platforms. */
68 uint64_t au64Content[1];
69} RTASN1MEMCONTENT;
70AssertCompileMemberAlignment(RTASN1MEMCONTENT, au64Content, 8);
71/** Pointer to a ASN.1 content allocation. */
72typedef RTASN1MEMCONTENT *PRTASN1MEMCONTENT;
73
74
75
76
77RTDECL(int) RTAsn1MemGrowArray(PRTASN1ALLOCATION pAllocation, void **ppvArray, size_t cbEntry,
78 uint32_t cCurrent, uint32_t cNew)
79{
80 AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER);
81 AssertReturn(cbEntry > 0, VERR_INVALID_PARAMETER);
82 AssertReturn(cNew > cCurrent, VERR_INVALID_PARAMETER);
83 AssertReturn(cNew < _1M, VERR_OUT_OF_RANGE);
84
85 pAllocation->cReallocs++;
86
87 void *pvOld = *ppvArray;
88
89 /* Initial allocation? */
90 if (cCurrent == 0)
91 {
92 AssertReturn(pvOld == NULL, VERR_INVALID_PARAMETER);
93 AssertReturn(cNew != 0, VERR_INVALID_PARAMETER);
94 return pAllocation->pAllocator->pfnAlloc(pAllocation->pAllocator, pAllocation, ppvArray, cNew * cbEntry);
95 }
96
97 /* Do we need to grow the allocation or did we already allocate sufficient memory in a previous call? */
98 size_t cbNew = cNew * cbEntry;
99 if (pAllocation->cbAllocated < cbNew)
100 {
101 /* Need to grow. Adjust the new size according to how many times we've been called. */
102 if (pAllocation->cReallocs > 2)
103 {
104 if (pAllocation->cReallocs > 8)
105 cNew += 8;
106 else if (pAllocation->cReallocs < 4)
107 cNew += 2;
108 else
109 cNew += 4;
110 cbNew += cNew * cbEntry;
111 }
112
113 int rc = pAllocation->pAllocator->pfnRealloc(pAllocation->pAllocator, pAllocation, pvOld, ppvArray, cbNew);
114 if (RT_FAILURE(rc))
115 return rc;
116 Assert(pAllocation->cbAllocated >= cbNew);
117
118 /* Clear the memory. */
119 size_t cbOld = cCurrent * cbEntry;
120 RT_BZERO((uint8_t *)*ppvArray + cbOld, pAllocation->cbAllocated - cbOld);
121 }
122
123 return VINF_SUCCESS;
124}
125
126
127RTDECL(int) RTAsn1MemAllocZ(PRTASN1ALLOCATION pAllocation, void **ppvMem, size_t cbMem)
128{
129 AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER);
130 AssertPtr(ppvMem);
131 Assert(cbMem > 0);
132 int rc = pAllocation->pAllocator->pfnAlloc(pAllocation->pAllocator, pAllocation, ppvMem, cbMem);
133 Assert(pAllocation->cbAllocated >= cbMem || RT_FAILURE_NP(rc));
134 return rc;
135}
136
137
138RTDECL(int) RTAsn1MemDup(PRTASN1ALLOCATION pAllocation, void **ppvMem, const void *pvSrc, size_t cbMem)
139{
140 AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER);
141 AssertPtr(ppvMem);
142 AssertPtr(pvSrc);
143 Assert(cbMem > 0);
144 int rc = pAllocation->pAllocator->pfnAlloc(pAllocation->pAllocator, pAllocation, ppvMem, cbMem);
145 if (RT_SUCCESS(rc))
146 {
147 Assert(pAllocation->cbAllocated >= cbMem);
148 memcpy(*ppvMem, pvSrc, cbMem);
149 return VINF_SUCCESS;
150 }
151 return rc;
152}
153
154
155RTDECL(void) RTAsn1MemFree(PRTASN1ALLOCATION pAllocation, void *pv)
156{
157 Assert(pAllocation->pAllocator != NULL);
158 if (pv)
159 {
160 pAllocation->pAllocator->pfnFree(pAllocation->pAllocator, pAllocation, pv);
161 Assert(pAllocation->cbAllocated == 0);
162 }
163}
164
165
166RTDECL(PRTASN1ALLOCATION) RTAsn1MemInitAllocation(PRTASN1ALLOCATION pAllocation, PCRTASN1ALLOCATORVTABLE pAllocator)
167{
168 pAllocation->cbAllocated = 0;
169 pAllocation->cReallocs = 0;
170 pAllocation->uReserved0 = 0;
171 pAllocation->pAllocator = pAllocator;
172 return pAllocation;
173}
174
175
176RTDECL(int) RTAsn1ContentAllocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator)
177{
178 AssertReturn(pAllocator != NULL, VERR_WRONG_ORDER);
179 AssertReturn(cb > 0 && cb < _1G, VERR_INVALID_PARAMETER);
180 AssertPtr(pAsn1Core);
181 AssertReturn(!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT), VERR_INVALID_STATE);
182
183 /* Initialize the temporary allocation tracker. */
184 RTASN1ALLOCATION Allocation;
185 Allocation.cbAllocated = 0;
186 Allocation.cReallocs = 0;
187 Allocation.uReserved0 = 0;
188 Allocation.pAllocator = pAllocator;
189
190 /* Make the allocation. */
191 uint32_t cbAlloc = RT_OFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb;
192 PRTASN1MEMCONTENT pHdr;
193 int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdr, cbAlloc);
194 if (RT_SUCCESS(rc))
195 {
196 Assert(Allocation.cbAllocated >= cbAlloc);
197 pHdr->Allocation = Allocation;
198 pAsn1Core->cb = (uint32_t)cb;
199 pAsn1Core->uData.pv = &pHdr->au64Content[0];
200 pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT;
201 }
202
203 return rc;
204}
205
206
207RTDECL(int) RTAsn1ContentDup(PRTASN1CORE pAsn1Core, void const *pvSrc, size_t cbSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
208{
209 int rc = RTAsn1ContentAllocZ(pAsn1Core, cbSrc, pAllocator);
210 if (RT_SUCCESS(rc))
211 memcpy((void *)pAsn1Core->uData.pv, pvSrc, cbSrc);
212 return rc;
213}
214
215
216RTDECL(int) RTAsn1ContentReallocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator)
217{
218 /* Validate input. */
219 AssertPtr(pAsn1Core);
220 AssertReturn(cb < _1G, VERR_INVALID_PARAMETER);
221
222 if (cb > 0)
223 {
224 /*
225 * Case 1 - Initial allocation.
226 */
227 uint32_t cbNeeded = RT_OFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb;
228 if (!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT))
229 return RTAsn1ContentAllocZ(pAsn1Core, cb, pAllocator);
230
231 /* Locate the header. */
232 PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content);
233
234 /*
235 * Case 2 - Reallocation using the same allocator.
236 */
237 if ( pHdr->Allocation.pAllocator == pAllocator
238 || !pAllocator)
239 {
240 pHdr->Allocation.cReallocs++;
241
242 /* Modify the allocation if necessary. */
243 if (pHdr->Allocation.cbAllocated < cbNeeded)
244 {
245 RTASN1ALLOCATION Allocation = pHdr->Allocation;
246 int rc = Allocation.pAllocator->pfnRealloc(Allocation.pAllocator, &Allocation, pHdr, (void **)&pHdr, cbNeeded);
247 if (RT_FAILURE(rc))
248 return rc;
249 Assert(Allocation.cbAllocated >= cbNeeded);
250 pAsn1Core->uData.pv = &pHdr->au64Content[0];
251 pHdr->Allocation = Allocation;
252 }
253
254 /* Clear any additional memory we're letting the user use and
255 update the content size. */
256 if (pAsn1Core->cb < cb)
257 RT_BZERO((uint8_t *)&pAsn1Core->uData.pu8[pAsn1Core->cb], cb - pAsn1Core->cb);
258 pAsn1Core->cb = (uint32_t)cb;
259 }
260 /*
261 * Case 3 - Reallocation using a different allocator.
262 */
263 else
264 {
265 /* Initialize the temporary allocation tracker. */
266 RTASN1ALLOCATION Allocation;
267 Allocation.cbAllocated = 0;
268 Allocation.cReallocs = pHdr->Allocation.cReallocs + 1;
269 Allocation.uReserved0 = 0;
270 Allocation.pAllocator = pAllocator;
271
272 /* Make the allocation. */
273 PRTASN1MEMCONTENT pHdrNew;
274 int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdrNew, cbNeeded);
275 if (RT_FAILURE(rc))
276 return rc;
277 Assert(Allocation.cbAllocated >= cbNeeded);
278
279 /* Duplicate the old content and zero any new memory we might've added. */
280 if (pAsn1Core->cb >= cb)
281 memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], cb);
282 else
283 {
284 memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], pAsn1Core->cb);
285 RT_BZERO((uint8_t *)&pHdrNew->au64Content[0] + pAsn1Core->cb, cb - pAsn1Core->cb);
286 }
287
288 /* Update the core. */
289 pHdrNew->Allocation = Allocation;
290 pAsn1Core->uData.pv = &pHdrNew->au64Content[0];
291 pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT; /* free cleared it. */
292 pAsn1Core->cb = (uint32_t)cb;
293
294 /* Free the old content. */
295 Allocation = pHdr->Allocation;
296 Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr);
297 Assert(Allocation.cbAllocated == 0);
298 }
299 }
300 /*
301 * Case 4 - It's a request to free the memory.
302 */
303 else
304 RTAsn1ContentFree(pAsn1Core);
305 return VINF_SUCCESS;
306}
307
308
309RTDECL(void) RTAsn1ContentFree(PRTASN1CORE pAsn1Core)
310{
311 if (pAsn1Core)
312 {
313 pAsn1Core->cb = 0;
314 if (pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT)
315 {
316 pAsn1Core->fFlags &= ~RTASN1CORE_F_ALLOCATED_CONTENT;
317 AssertReturnVoid(pAsn1Core->uData.pv);
318
319 PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content);
320 RTASN1ALLOCATION Allocation = pHdr->Allocation;
321
322 Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr);
323 Assert(Allocation.cbAllocated == 0);
324 }
325 pAsn1Core->uData.pv = NULL;
326 }
327}
328
329
330
331/*
332 * Virtual method table based API.
333 */
334
335RTDECL(void) RTAsn1VtDelete(PRTASN1CORE pAsn1Core)
336{
337 if (pAsn1Core)
338 {
339 PCRTASN1COREVTABLE pOps = pAsn1Core->pOps;
340 if (pOps)
341 pOps->pfnDtor(pAsn1Core);
342 }
343}
344
345
346/**
347 * Context data passed by RTAsn1VtDeepEnum to it's worker callbacks.
348 */
349typedef struct RTASN1DEEPENUMCTX
350{
351 PFNRTASN1ENUMCALLBACK pfnCallback;
352 void *pvUser;
353} RTASN1DEEPENUMCTX;
354
355
356static DECLCALLBACK(int) rtAsn1VtDeepEnumDepthFirst(PRTASN1CORE pAsn1Core, const char *pszName, uint32_t uDepth, void *pvUser)
357{
358 AssertReturn(pAsn1Core, VINF_SUCCESS);
359
360 if (pAsn1Core->pOps && pAsn1Core->pOps->pfnEnum)
361 {
362 int rc = pAsn1Core->pOps->pfnEnum(pAsn1Core, rtAsn1VtDeepEnumDepthFirst, uDepth, pvUser);
363 if (rc != VINF_SUCCESS)
364 return rc;
365 }
366
367 RTASN1DEEPENUMCTX *pCtx = (RTASN1DEEPENUMCTX *)pvUser;
368 return pCtx->pfnCallback(pAsn1Core, pszName, uDepth, pCtx->pvUser);
369}
370
371
372static DECLCALLBACK(int) rtAsn1VtDeepEnumDepthLast(PRTASN1CORE pAsn1Core, const char *pszName, uint32_t uDepth, void *pvUser)
373{
374 AssertReturn(pAsn1Core, VINF_SUCCESS);
375
376 RTASN1DEEPENUMCTX *pCtx = (RTASN1DEEPENUMCTX *)pvUser;
377 int rc = pCtx->pfnCallback(pAsn1Core, pszName, uDepth, pCtx->pvUser);
378 if (rc == VINF_SUCCESS)
379 {
380 if (pAsn1Core->pOps && pAsn1Core->pOps->pfnEnum)
381 rc = pAsn1Core->pOps->pfnEnum(pAsn1Core, rtAsn1VtDeepEnumDepthFirst, uDepth, pvUser);
382 }
383 return rc;
384}
385
386
387RTDECL(int) RTAsn1VtDeepEnum(PRTASN1CORE pThisCore, bool fDepthFirst, uint32_t uDepth,
388 PFNRTASN1ENUMCALLBACK pfnCallback, void *pvUser)
389{
390 int rc;
391 if (RTAsn1Core_IsPresent(pThisCore))
392 {
393 PCRTASN1COREVTABLE pOps = pThisCore->pOps;
394 if (pOps && pOps->pfnEnum)
395 {
396 RTASN1DEEPENUMCTX Ctx;
397 Ctx.pfnCallback = pfnCallback;
398 Ctx.pvUser = pvUser;
399 rc = pOps->pfnEnum(pThisCore, fDepthFirst ? rtAsn1VtDeepEnumDepthFirst : rtAsn1VtDeepEnumDepthLast, uDepth, &Ctx);
400 }
401 else
402 rc = VINF_SUCCESS;
403 }
404 else
405 rc = VINF_SUCCESS;
406 return rc;
407}
408
409
410RTDECL(int) RTAsn1VtClone(PRTASN1CORE pThisCore, PRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator)
411{
412 AssertPtrReturn(pThisCore, VERR_INVALID_POINTER);
413 AssertPtrReturn(pSrcCore, VERR_INVALID_POINTER);
414 AssertPtrReturn(pAllocator, VERR_INVALID_POINTER);
415
416 if (RTAsn1Core_IsPresent(pSrcCore))
417 {
418 AssertPtrReturn(pSrcCore->pOps, VERR_INVALID_POINTER);
419 AssertPtr(pSrcCore->pOps->pfnClone);
420 return pSrcCore->pOps->pfnClone(pThisCore, pSrcCore, pAllocator);
421 }
422
423 RT_ZERO(*pThisCore);
424 return VINF_SUCCESS;
425}
426
427
428RTDECL(int) RTAsn1VtCompare(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore)
429{
430 int iDiff;
431 if (RTAsn1Core_IsPresent(pLeftCore))
432 {
433 if (RTAsn1Core_IsPresent(pRightCore))
434 {
435 PCRTASN1COREVTABLE pOps = pLeftCore->pOps;
436 if (pOps == pRightCore->pOps)
437 {
438 AssertPtr(pOps->pfnCompare);
439 iDiff = pOps->pfnCompare(pLeftCore, pRightCore);
440 }
441 else
442 iDiff = (uintptr_t)pOps < (uintptr_t)pRightCore->pOps ? -1 : 1;
443 }
444 else
445 iDiff = 1;
446 }
447 else
448 iDiff = 0 - (int)RTAsn1Core_IsPresent(pRightCore);
449 return iDiff;
450}
451
452
453RTDECL(int) RTAsn1VtCheckSanity(PCRTASN1CORE pThisCore, uint32_t fFlags,
454 PRTERRINFO pErrInfo, const char *pszErrorTag)
455{
456 int rc;
457 if (RTAsn1Core_IsPresent(pThisCore))
458 {
459 PCRTASN1COREVTABLE pOps = pThisCore->pOps;
460 if (pOps && pOps->pfnCheckSanity)
461 rc = pOps->pfnCheckSanity(pThisCore, fFlags, pErrInfo, pszErrorTag);
462 else if (pOps)
463 rc = RTErrInfoSetF(pErrInfo, VERR_ASN1_NO_CHECK_SANITY_METHOD,
464 "%s: Has no pfnCheckSanity function.", pszErrorTag);
465 else
466 rc = RTErrInfoSetF(pErrInfo, VERR_ASN1_NO_VTABLE, "%s: Has no Vtable function.", pszErrorTag);
467 }
468 else
469 rc = RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Not present.", pszErrorTag);
470 return rc;
471}
472
473
474
475/*
476 * Dummy ASN.1 object.
477 */
478
479RTDECL(int) RTAsn1Dummy_InitEx(PRTASN1DUMMY pThis)
480{
481 return RTAsn1Core_InitEx(&pThis->Asn1Core,
482 UINT32_MAX,
483 ASN1_TAGCLASS_PRIVATE | ASN1_TAGFLAG_CONSTRUCTED,
484 NULL,
485 RTASN1CORE_F_DUMMY);
486}
487
488
489/*
490 * ASN.1 SEQUENCE OF object.
491 */
492
493RTDECL(int) RTAsn1SeqOfCore_Init(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable)
494{
495 return RTAsn1Core_InitEx(&pThis->Asn1Core,
496 ASN1_TAG_SEQUENCE,
497 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
498 pVtable,
499 RTASN1CORE_F_PRESENT);
500}
501
502
503RTDECL(int) RTAsn1SeqOfCore_Clone(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQOFCORE pSrc)
504{
505 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
506 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
507}
508
509
510/*
511 * ASN.1 SET OF object.
512 */
513
514RTDECL(int) RTAsn1SetOfCore_Init(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable)
515{
516 return RTAsn1Core_InitEx(&pThis->Asn1Core,
517 ASN1_TAG_SET,
518 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
519 pVtable,
520 RTASN1CORE_F_PRESENT);
521}
522
523
524RTDECL(int) RTAsn1SetOfCore_Clone(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETOFCORE pSrc)
525{
526 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
527 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
528}
529
530
531/*
532 * ASN.1 SEQUENCE object.
533 */
534
535RTDECL(int) RTAsn1SequenceCore_Init(PRTASN1SEQUENCECORE pThis, PCRTASN1COREVTABLE pVtable)
536{
537 return RTAsn1Core_InitEx(&pThis->Asn1Core,
538 ASN1_TAG_SEQUENCE,
539 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
540 pVtable,
541 RTASN1CORE_F_PRESENT);
542}
543
544
545RTDECL(int) RTAsn1SequenceCore_Clone(PRTASN1SEQUENCECORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQUENCECORE pSrc)
546{
547 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
548 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
549}
550
551
552/*
553 * ASN.1 SEQUENCE object - only used by SPC, so probably doing something wrong there.
554 */
555
556RTDECL(int) RTAsn1SetCore_Init(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable)
557{
558 return RTAsn1Core_InitEx(&pThis->Asn1Core,
559 ASN1_TAG_SET,
560 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
561 pVtable,
562 RTASN1CORE_F_PRESENT);
563}
564
565
566RTDECL(int) RTAsn1SetCore_Clone(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETCORE pSrc)
567{
568 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
569 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
570}
571
572
573/*
574 * ASN.1 Context Tag object.
575 */
576
577RTDECL(int) RTAsn1ContextTagN_Init(PRTASN1CONTEXTTAG pThis, uint32_t uTag)
578{
579 return RTAsn1Core_InitEx(&pThis->Asn1Core,
580 uTag,
581 ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED,
582 NULL,
583 RTASN1CORE_F_PRESENT);
584}
585
586
587RTDECL(int) RTAsn1ContextTagN_Clone(PRTASN1CONTEXTTAG pThis, PCRTASN1CONTEXTTAG pSrc, uint32_t uTag)
588{
589 Assert(pSrc->Asn1Core.uTag == uTag || !RTASN1CORE_IS_PRESENT(&pSrc->Asn1Core));
590 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
591}
592
Note: See TracBrowser for help on using the repository browser.

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