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