1/* 2* Copyright (C) 2021 Huawei Device Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16#include "hcf_parcel.h" 17#include "securec.h" 18#include "memory.h" 19 20const int PARCEL_DEFAULT_INCREASE_STEP = 16; 21const uint32_t PARCEL_UINT_MAX = 0xffffffffU; 22const int HALF_LEN = 2; 23 24HcParcel CreateParcel(uint32_t size, uint32_t allocUnit) 25{ 26 HcParcel parcel; 27 (void)memset_s(&parcel, sizeof(parcel), 0, sizeof(parcel)); 28 parcel.allocUnit = allocUnit; 29 if (parcel.allocUnit == 0) { 30 parcel.allocUnit = PARCEL_DEFAULT_INCREASE_STEP; 31 } 32 if (size > 0) { 33 parcel.data = (char *)HcfMalloc(size, 0); 34 if (parcel.data != NULL) { 35 parcel.length = size; 36 } 37 } 38 return parcel; 39} 40 41void DeleteParcel(HcParcel *parcel) 42{ 43 if (parcel == NULL) { 44 return; 45 } 46 47 if (parcel->data != NULL) { 48 HcfFree(parcel->data); 49 parcel->data = NULL; 50 } 51 parcel->length = 0; 52 parcel->beginPos = 0; 53 parcel->endPos = 0; 54} 55 56uint32_t GetParcelDataSize(const HcParcel *parcel) 57{ 58 if (parcel == NULL) { 59 return 0; 60 } 61 if (parcel->endPos >= parcel->beginPos) { 62 return parcel->endPos - parcel->beginPos; 63 } 64 return 0; 65} 66 67const char *GetParcelData(const HcParcel *parcel) 68{ 69 if (parcel == NULL || parcel->data == NULL) { 70 return NULL; 71 } 72 return parcel->data + parcel->beginPos; 73} 74 75static bool ParcelRealloc(HcParcel *parcel, uint32_t size) 76{ 77 if (parcel->length >= size) { 78 return false; 79 } 80 char *newData = (char *)HcfMalloc(size, 0); 81 if (newData == NULL) { 82 return false; 83 } 84 if (memcpy_s(newData, size, parcel->data, parcel->length) != EOK) { 85 HcfFree(newData); 86 return false; 87 } 88 HcfFree(parcel->data); 89 parcel->data = newData; 90 parcel->length = size; 91 return true; 92} 93 94static bool ParcelIncrease(HcParcel *parcel, uint32_t size) 95{ 96 if (parcel == NULL || size == 0) { 97 return false; 98 } 99 if (parcel->data == NULL) { 100 if (parcel->length != 0) { 101 return false; 102 } 103 *parcel = CreateParcel(size, parcel->allocUnit); 104 if (parcel->data == NULL) { 105 return false; 106 } else { 107 return true; 108 } 109 } else { 110 return ParcelRealloc(parcel, size); 111 } 112} 113 114static void ParcelRecycle(HcParcel *parcel) 115{ 116 if (parcel == NULL) { 117 return; 118 } 119 if (parcel->data == NULL || parcel->beginPos < parcel->allocUnit) { 120 return; 121 } 122 123 uint32_t contentSize = parcel->endPos - parcel->beginPos; 124 if (contentSize > 0) { 125 (void)memmove_s(parcel->data, parcel->endPos - parcel->beginPos, 126 parcel->data + parcel->beginPos, parcel->endPos - parcel->beginPos); 127 } 128 parcel->beginPos = 0; 129 parcel->endPos = contentSize; 130} 131 132static uint32_t GetParcelIncreaseSize(HcParcel *parcel, uint32_t newSize) 133{ 134 if (parcel == NULL || parcel->allocUnit == 0) { 135 return 0; 136 } 137 if (newSize % parcel->allocUnit) { 138 return (newSize / parcel->allocUnit + 1) * parcel->allocUnit; 139 } else { 140 return (newSize / parcel->allocUnit) * parcel->allocUnit; 141 } 142} 143 144bool ParcelWrite(HcParcel *parcel, const void *src, uint32_t dataSize) 145{ 146 errno_t rc; 147 if (parcel == NULL || src == NULL || dataSize == 0) { 148 return false; 149 } 150 if (parcel->endPos > PARCEL_UINT_MAX - dataSize) { 151 return false; 152 } 153 if (parcel->endPos + dataSize > parcel->length) { 154 ParcelRecycle(parcel); 155 if (parcel->endPos + dataSize > parcel->length) { 156 uint32_t newSize = GetParcelIncreaseSize(parcel, parcel->endPos + dataSize); 157 if (!ParcelIncrease(parcel, newSize)) { 158 return false; 159 } 160 } 161 } 162 rc = memmove_s(parcel->data + parcel->endPos, dataSize, src, dataSize); 163 if (rc != EOK) { 164 return false; 165 } 166 parcel->endPos += dataSize; 167 return true; 168} 169 170bool ParcelWriteInt8(HcParcel *parcel, char src) 171{ 172 return ParcelWrite(parcel, &src, sizeof(src)); 173} 174 175bool ParcelPopBack(HcParcel *parcel, uint32_t size) 176{ 177 if (parcel != NULL && size > 0 && GetParcelDataSize(parcel) >= size) { 178 parcel->endPos -= size; 179 return true; 180 } 181 return false; 182} 183