RTDECL(int) RTAsn1ContentDup(PRTASN1CORE pAsn1Core, void const *pvSrc, size_t cbSrc, PCRTASN1ALLOCATORVTABLE pAllocator) { int rc = RTAsn1ContentAllocZ(pAsn1Core, cbSrc, pAllocator); if (RT_SUCCESS(rc)) memcpy((void *)pAsn1Core->uData.pv, pvSrc, cbSrc); return rc; }
RTDECL(int) RTAsn1ContentReallocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator) { /* Validate input. */ AssertPtr(pAsn1Core); AssertReturn(cb < _1G, VERR_INVALID_PARAMETER); if (cb > 0) { /* * Case 1 - Initial allocation. */ uint32_t cbNeeded = RT_OFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb; if (!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT)) return RTAsn1ContentAllocZ(pAsn1Core, cb, pAllocator); /* Locate the header. */ PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content); /* * Case 2 - Reallocation using the same allocator. */ if ( pHdr->Allocation.pAllocator == pAllocator || !pAllocator) { pHdr->Allocation.cReallocs++; /* Modify the allocation if necessary. */ if (pHdr->Allocation.cbAllocated < cbNeeded) { RTASN1ALLOCATION Allocation = pHdr->Allocation; int rc = Allocation.pAllocator->pfnRealloc(Allocation.pAllocator, &Allocation, pHdr, (void **)&pHdr, cbNeeded); if (RT_FAILURE(rc)) return rc; Assert(Allocation.cbAllocated >= cbNeeded); pAsn1Core->uData.pv = &pHdr->au64Content[0]; pHdr->Allocation = Allocation; } /* Clear any additional memory we're letting the user use and update the content size. */ if (pAsn1Core->cb < cb) RT_BZERO((uint8_t *)&pAsn1Core->uData.pu8[pAsn1Core->cb], cb - pAsn1Core->cb); pAsn1Core->cb = (uint32_t)cb; } /* * Case 3 - Reallocation using a different allocator. */ else { /* Initialize the temporary allocation tracker. */ RTASN1ALLOCATION Allocation; Allocation.cbAllocated = 0; Allocation.cReallocs = pHdr->Allocation.cReallocs + 1; Allocation.uReserved0 = 0; Allocation.pAllocator = pAllocator; /* Make the allocation. */ PRTASN1MEMCONTENT pHdrNew; int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdrNew, cbNeeded); if (RT_FAILURE(rc)) return rc; Assert(Allocation.cbAllocated >= cbNeeded); /* Duplicate the old content and zero any new memory we might've added. */ if (pAsn1Core->cb >= cb) memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], cb); else { memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], pAsn1Core->cb); RT_BZERO((uint8_t *)&pHdrNew->au64Content[0] + pAsn1Core->cb, cb - pAsn1Core->cb); } /* Update the core. */ pHdrNew->Allocation = Allocation; pAsn1Core->uData.pv = &pHdrNew->au64Content[0]; pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT; /* free cleared it. */ pAsn1Core->cb = (uint32_t)cb; /* Free the old content. */ Allocation = pHdr->Allocation; Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr); Assert(Allocation.cbAllocated == 0); } } /* * Case 4 - It's a request to free the memory. */ else RTAsn1ContentFree(pAsn1Core); return VINF_SUCCESS; }
RTDECL(int) RTAsn1Integer_InitU64(PRTASN1INTEGER pThis, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator) { /* * Initialize the core and the native value. */ RTAsn1Core_InitEx(&pThis->Asn1Core, ASN1_TAG_INTEGER, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE, &g_RTAsn1Integer_Vtable, RTASN1CORE_F_PRESENT | RTASN1CORE_F_PRIMITE_TAG_STRUCT); pThis->uValue.u = uValue; /* * Use one of the constants if possible. */ if (uValue < RT_ELEMENTS(g_abSmall)) { pThis->Asn1Core.cb = 1; pThis->Asn1Core.uData.pv = (void *)&g_abSmall[0]; } else { /* * Need to turn uValue into a big endian number without any * unnecessary leading zero bytes. */ /* Figure the size. */ uint32_t cb = 0; if (uValue <= UINT32_MAX) { if (uValue <= UINT16_MAX) { if (uValue <= UINT8_MAX) cb = 1; else cb = 2; } else { if (uValue <= UINT32_C(0xffffff)) cb = 3; else cb = 4; } } else { if (uValue <= UINT64_C(0x0000FfffFfffFfff)) { if (uValue <= UINT64_C(0x000000ffFfffFfff)) cb = 5; else cb = 6; } else { if (uValue <= UINT64_C(0x00ffFfffFfffFfff)) cb = 7; else cb = 8; } } /* Allocate space. */ int rc = RTAsn1ContentAllocZ(&pThis->Asn1Core, cb, pAllocator); if (RT_FAILURE(rc)) { RT_ZERO(*pThis); return rc; } /* Serialize the number in MSB order. */ uint8_t *pb = (uint8_t *)pThis->Asn1Core.uData.pu8; while (cb-- > 0) { pb[cb] = (uint8_t)uValue; uValue >>= 8; } Assert(uValue == 0); } return VINF_SUCCESS; }