11b8d9b87Sopenharmony_ci/*
21b8d9b87Sopenharmony_ci* Copyright (C) 2021 Huawei Device Co., Ltd.
31b8d9b87Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License");
41b8d9b87Sopenharmony_ci* you may not use this file except in compliance with the License.
51b8d9b87Sopenharmony_ci* You may obtain a copy of the License at
61b8d9b87Sopenharmony_ci*
71b8d9b87Sopenharmony_ci*    http://www.apache.org/licenses/LICENSE-2.0
81b8d9b87Sopenharmony_ci*
91b8d9b87Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software
101b8d9b87Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS,
111b8d9b87Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121b8d9b87Sopenharmony_ci* See the License for the specific language governing permissions and
131b8d9b87Sopenharmony_ci* limitations under the License.
141b8d9b87Sopenharmony_ci*/
151b8d9b87Sopenharmony_ci
161b8d9b87Sopenharmony_ci#include "hcf_parcel.h"
171b8d9b87Sopenharmony_ci#include "securec.h"
181b8d9b87Sopenharmony_ci#include "memory.h"
191b8d9b87Sopenharmony_ci
201b8d9b87Sopenharmony_ciconst int PARCEL_DEFAULT_INCREASE_STEP = 16;
211b8d9b87Sopenharmony_ciconst uint32_t PARCEL_UINT_MAX = 0xffffffffU;
221b8d9b87Sopenharmony_ciconst int HALF_LEN = 2;
231b8d9b87Sopenharmony_ci
241b8d9b87Sopenharmony_ciHcParcel CreateParcel(uint32_t size, uint32_t allocUnit)
251b8d9b87Sopenharmony_ci{
261b8d9b87Sopenharmony_ci    HcParcel parcel;
271b8d9b87Sopenharmony_ci    (void)memset_s(&parcel, sizeof(parcel), 0, sizeof(parcel));
281b8d9b87Sopenharmony_ci    parcel.allocUnit = allocUnit;
291b8d9b87Sopenharmony_ci    if (parcel.allocUnit == 0) {
301b8d9b87Sopenharmony_ci        parcel.allocUnit = PARCEL_DEFAULT_INCREASE_STEP;
311b8d9b87Sopenharmony_ci    }
321b8d9b87Sopenharmony_ci    if (size > 0) {
331b8d9b87Sopenharmony_ci        parcel.data = (char *)HcfMalloc(size, 0);
341b8d9b87Sopenharmony_ci        if (parcel.data != NULL) {
351b8d9b87Sopenharmony_ci            parcel.length = size;
361b8d9b87Sopenharmony_ci        }
371b8d9b87Sopenharmony_ci    }
381b8d9b87Sopenharmony_ci    return parcel;
391b8d9b87Sopenharmony_ci}
401b8d9b87Sopenharmony_ci
411b8d9b87Sopenharmony_civoid DeleteParcel(HcParcel *parcel)
421b8d9b87Sopenharmony_ci{
431b8d9b87Sopenharmony_ci    if (parcel == NULL) {
441b8d9b87Sopenharmony_ci        return;
451b8d9b87Sopenharmony_ci    }
461b8d9b87Sopenharmony_ci
471b8d9b87Sopenharmony_ci    if (parcel->data != NULL) {
481b8d9b87Sopenharmony_ci        HcfFree(parcel->data);
491b8d9b87Sopenharmony_ci        parcel->data = NULL;
501b8d9b87Sopenharmony_ci    }
511b8d9b87Sopenharmony_ci    parcel->length = 0;
521b8d9b87Sopenharmony_ci    parcel->beginPos = 0;
531b8d9b87Sopenharmony_ci    parcel->endPos = 0;
541b8d9b87Sopenharmony_ci}
551b8d9b87Sopenharmony_ci
561b8d9b87Sopenharmony_ciuint32_t GetParcelDataSize(const HcParcel *parcel)
571b8d9b87Sopenharmony_ci{
581b8d9b87Sopenharmony_ci    if (parcel == NULL) {
591b8d9b87Sopenharmony_ci        return 0;
601b8d9b87Sopenharmony_ci    }
611b8d9b87Sopenharmony_ci    if (parcel->endPos >= parcel->beginPos) {
621b8d9b87Sopenharmony_ci        return parcel->endPos - parcel->beginPos;
631b8d9b87Sopenharmony_ci    }
641b8d9b87Sopenharmony_ci    return 0;
651b8d9b87Sopenharmony_ci}
661b8d9b87Sopenharmony_ci
671b8d9b87Sopenharmony_ciconst char *GetParcelData(const HcParcel *parcel)
681b8d9b87Sopenharmony_ci{
691b8d9b87Sopenharmony_ci    if (parcel == NULL || parcel->data == NULL) {
701b8d9b87Sopenharmony_ci        return NULL;
711b8d9b87Sopenharmony_ci    }
721b8d9b87Sopenharmony_ci    return parcel->data + parcel->beginPos;
731b8d9b87Sopenharmony_ci}
741b8d9b87Sopenharmony_ci
751b8d9b87Sopenharmony_cistatic bool ParcelRealloc(HcParcel *parcel, uint32_t size)
761b8d9b87Sopenharmony_ci{
771b8d9b87Sopenharmony_ci    if (parcel->length >= size) {
781b8d9b87Sopenharmony_ci        return false;
791b8d9b87Sopenharmony_ci    }
801b8d9b87Sopenharmony_ci    char *newData = (char *)HcfMalloc(size, 0);
811b8d9b87Sopenharmony_ci    if (newData == NULL) {
821b8d9b87Sopenharmony_ci        return false;
831b8d9b87Sopenharmony_ci    }
841b8d9b87Sopenharmony_ci    if (memcpy_s(newData, size, parcel->data, parcel->length) != EOK) {
851b8d9b87Sopenharmony_ci        HcfFree(newData);
861b8d9b87Sopenharmony_ci        return false;
871b8d9b87Sopenharmony_ci    }
881b8d9b87Sopenharmony_ci    HcfFree(parcel->data);
891b8d9b87Sopenharmony_ci    parcel->data = newData;
901b8d9b87Sopenharmony_ci    parcel->length = size;
911b8d9b87Sopenharmony_ci    return true;
921b8d9b87Sopenharmony_ci}
931b8d9b87Sopenharmony_ci
941b8d9b87Sopenharmony_cistatic bool ParcelIncrease(HcParcel *parcel, uint32_t size)
951b8d9b87Sopenharmony_ci{
961b8d9b87Sopenharmony_ci    if (parcel == NULL || size == 0) {
971b8d9b87Sopenharmony_ci        return false;
981b8d9b87Sopenharmony_ci    }
991b8d9b87Sopenharmony_ci    if (parcel->data == NULL) {
1001b8d9b87Sopenharmony_ci        if (parcel->length != 0) {
1011b8d9b87Sopenharmony_ci            return false;
1021b8d9b87Sopenharmony_ci        }
1031b8d9b87Sopenharmony_ci        *parcel = CreateParcel(size, parcel->allocUnit);
1041b8d9b87Sopenharmony_ci        if (parcel->data == NULL) {
1051b8d9b87Sopenharmony_ci            return false;
1061b8d9b87Sopenharmony_ci        } else {
1071b8d9b87Sopenharmony_ci            return true;
1081b8d9b87Sopenharmony_ci        }
1091b8d9b87Sopenharmony_ci    } else {
1101b8d9b87Sopenharmony_ci        return ParcelRealloc(parcel, size);
1111b8d9b87Sopenharmony_ci    }
1121b8d9b87Sopenharmony_ci}
1131b8d9b87Sopenharmony_ci
1141b8d9b87Sopenharmony_cistatic void ParcelRecycle(HcParcel *parcel)
1151b8d9b87Sopenharmony_ci{
1161b8d9b87Sopenharmony_ci    if (parcel == NULL) {
1171b8d9b87Sopenharmony_ci        return;
1181b8d9b87Sopenharmony_ci    }
1191b8d9b87Sopenharmony_ci    if (parcel->data == NULL || parcel->beginPos < parcel->allocUnit) {
1201b8d9b87Sopenharmony_ci        return;
1211b8d9b87Sopenharmony_ci    }
1221b8d9b87Sopenharmony_ci
1231b8d9b87Sopenharmony_ci    uint32_t contentSize = parcel->endPos - parcel->beginPos;
1241b8d9b87Sopenharmony_ci    if (contentSize > 0) {
1251b8d9b87Sopenharmony_ci        (void)memmove_s(parcel->data, parcel->endPos - parcel->beginPos,
1261b8d9b87Sopenharmony_ci            parcel->data + parcel->beginPos, parcel->endPos - parcel->beginPos);
1271b8d9b87Sopenharmony_ci    }
1281b8d9b87Sopenharmony_ci    parcel->beginPos = 0;
1291b8d9b87Sopenharmony_ci    parcel->endPos = contentSize;
1301b8d9b87Sopenharmony_ci}
1311b8d9b87Sopenharmony_ci
1321b8d9b87Sopenharmony_cistatic uint32_t GetParcelIncreaseSize(HcParcel *parcel, uint32_t newSize)
1331b8d9b87Sopenharmony_ci{
1341b8d9b87Sopenharmony_ci    if (parcel == NULL || parcel->allocUnit == 0) {
1351b8d9b87Sopenharmony_ci        return 0;
1361b8d9b87Sopenharmony_ci    }
1371b8d9b87Sopenharmony_ci    if (newSize % parcel->allocUnit) {
1381b8d9b87Sopenharmony_ci        return (newSize / parcel->allocUnit + 1) * parcel->allocUnit;
1391b8d9b87Sopenharmony_ci    } else {
1401b8d9b87Sopenharmony_ci        return (newSize / parcel->allocUnit) * parcel->allocUnit;
1411b8d9b87Sopenharmony_ci    }
1421b8d9b87Sopenharmony_ci}
1431b8d9b87Sopenharmony_ci
1441b8d9b87Sopenharmony_cibool ParcelWrite(HcParcel *parcel, const void *src, uint32_t dataSize)
1451b8d9b87Sopenharmony_ci{
1461b8d9b87Sopenharmony_ci    errno_t rc;
1471b8d9b87Sopenharmony_ci    if (parcel == NULL || src == NULL || dataSize == 0) {
1481b8d9b87Sopenharmony_ci        return false;
1491b8d9b87Sopenharmony_ci    }
1501b8d9b87Sopenharmony_ci    if (parcel->endPos > PARCEL_UINT_MAX - dataSize) {
1511b8d9b87Sopenharmony_ci        return false;
1521b8d9b87Sopenharmony_ci    }
1531b8d9b87Sopenharmony_ci    if (parcel->endPos + dataSize > parcel->length) {
1541b8d9b87Sopenharmony_ci        ParcelRecycle(parcel);
1551b8d9b87Sopenharmony_ci        if (parcel->endPos + dataSize > parcel->length) {
1561b8d9b87Sopenharmony_ci            uint32_t newSize = GetParcelIncreaseSize(parcel, parcel->endPos + dataSize);
1571b8d9b87Sopenharmony_ci            if (!ParcelIncrease(parcel, newSize)) {
1581b8d9b87Sopenharmony_ci                return false;
1591b8d9b87Sopenharmony_ci            }
1601b8d9b87Sopenharmony_ci        }
1611b8d9b87Sopenharmony_ci    }
1621b8d9b87Sopenharmony_ci    rc = memmove_s(parcel->data + parcel->endPos, dataSize, src, dataSize);
1631b8d9b87Sopenharmony_ci    if (rc != EOK) {
1641b8d9b87Sopenharmony_ci        return false;
1651b8d9b87Sopenharmony_ci    }
1661b8d9b87Sopenharmony_ci    parcel->endPos += dataSize;
1671b8d9b87Sopenharmony_ci    return true;
1681b8d9b87Sopenharmony_ci}
1691b8d9b87Sopenharmony_ci
1701b8d9b87Sopenharmony_cibool ParcelWriteInt8(HcParcel *parcel, char src)
1711b8d9b87Sopenharmony_ci{
1721b8d9b87Sopenharmony_ci    return ParcelWrite(parcel, &src, sizeof(src));
1731b8d9b87Sopenharmony_ci}
1741b8d9b87Sopenharmony_ci
1751b8d9b87Sopenharmony_cibool ParcelPopBack(HcParcel *parcel, uint32_t size)
1761b8d9b87Sopenharmony_ci{
1771b8d9b87Sopenharmony_ci    if (parcel != NULL && size > 0 && GetParcelDataSize(parcel) >= size) {
1781b8d9b87Sopenharmony_ci        parcel->endPos -= size;
1791b8d9b87Sopenharmony_ci        return true;
1801b8d9b87Sopenharmony_ci    }
1811b8d9b87Sopenharmony_ci    return false;
1821b8d9b87Sopenharmony_ci}
183