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;
}
Example #3
0
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;
}