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 "hc_parcel.h" 17#include "securec.h" 18#include "hc_types.h" 19 20const int PARCEL_DEFAULT_INCREASE_STEP = 16; 21const uint32_t PARCEL_UINT_MAX = 0xffffffffU; 22 23HcParcel CreateParcel(uint32_t size, uint32_t allocUnit) 24{ 25 HcParcel parcel; 26 (void)memset_s(&parcel, sizeof(parcel), 0, sizeof(parcel)); 27 parcel.allocUnit = allocUnit; 28 if (parcel.allocUnit == 0) { 29 parcel.allocUnit = PARCEL_DEFAULT_INCREASE_STEP; 30 } 31 if (size > 0) { 32 parcel.data = (char *)HcMalloc(size, 0); 33 if (parcel.data != NULL) { 34 parcel.length = size; 35 } 36 } 37 return parcel; 38} 39 40void DeleteParcel(HcParcel *parcel) 41{ 42 if (parcel == NULL) { 43 return; 44 } 45 46 if (parcel->data != NULL) { 47 HcFree(parcel->data); 48 parcel->data = 0; 49 } 50 parcel->length = 0; 51 parcel->beginPos = 0; 52 parcel->endPos = 0; 53} 54 55void ClearParcel(HcParcel *parcel) 56{ 57 if (parcel != NULL) { 58 parcel->beginPos = 0; 59 parcel->endPos = 0; 60 } 61} 62 63void ResetParcel(HcParcel *parcel, uint32_t size, uint32_t allocUnit) 64{ 65 if (parcel != NULL) { 66 DeleteParcel(parcel); 67 HcParcel newParcel = CreateParcel(size, allocUnit); 68 (void)memcpy_s(parcel, sizeof(HcParcel), &newParcel, sizeof(HcParcel)); 69 } 70} 71 72uint32_t GetParcelDataSize(const HcParcel *parcel) 73{ 74 if (parcel == NULL) { 75 return 0; 76 } 77 if (parcel->endPos >= parcel->beginPos) { 78 return parcel->endPos - parcel->beginPos; 79 } 80 return 0; 81} 82 83const char *GetParcelData(const HcParcel *parcel) 84{ 85 if (parcel == NULL) { 86 return NULL; 87 } 88 return parcel->data + parcel->beginPos; 89} 90 91const char *GetParcelLastChar(const HcParcel *parcel) 92{ 93 if (parcel == NULL || GetParcelDataSize(parcel) == 0) { 94 return NULL; 95 } 96 return parcel->data + parcel->endPos - 1; 97} 98 99HcBool ParcelReadWithoutPopData(HcParcel *parcel, void *dst, uint32_t dataSize) 100{ 101#ifdef IS_BIG_ENDIAN 102 HcBool ret = ParcelReadRevert(parcel, dst, dataSize); 103#else 104 HcBool ret = ParcelRead(parcel, dst, dataSize); 105#endif 106 if (ret == HC_TRUE) { 107 parcel->beginPos -= dataSize; 108 } 109 return ret; 110} 111 112HcBool ParcelRead(HcParcel *parcel, void *dst, uint32_t dataSize) 113{ 114 errno_t rc; 115 if (parcel == NULL || dst == NULL || dataSize == 0) { 116 return HC_FALSE; 117 } 118 if (parcel->beginPos > PARCEL_UINT_MAX - dataSize) { 119 return HC_FALSE; 120 } 121 if (parcel->beginPos + dataSize > parcel->endPos) { 122 return HC_FALSE; 123 } 124 rc = memmove_s(dst, dataSize, parcel->data + parcel->beginPos, dataSize); 125 if (rc != EOK) { 126 return HC_FALSE; 127 } 128 parcel->beginPos += dataSize; 129 return HC_TRUE; 130} 131 132HcBool ParcelEraseBlock(HcParcel *parcel, uint32_t start, uint32_t dataSize, void *dst) 133{ 134 errno_t rc; 135 if (parcel == NULL || dst == NULL || dataSize == 0) { 136 return HC_FALSE; 137 } 138 if (start > PARCEL_UINT_MAX - dataSize) { 139 return HC_FALSE; 140 } 141 uint32_t parcelSizeOrg = GetParcelDataSize(parcel); 142 if (parcelSizeOrg < start + dataSize) { 143 return HC_FALSE; 144 } 145 char *beginCopy = parcel->data + parcel->beginPos + start; 146 uint32_t copySize = parcelSizeOrg - start - dataSize; 147 148 rc = memmove_s(dst, dataSize, beginCopy, dataSize); 149 if (rc != EOK) { 150 return HC_FALSE; 151 } 152 if (copySize != 0) { 153 rc = memmove_s(beginCopy, copySize, beginCopy + dataSize, copySize); 154 if (rc != EOK) { 155 return HC_FALSE; 156 } 157 } 158 parcel->endPos -= dataSize; 159 return HC_TRUE; 160} 161 162HcBool ParcelReadRevert(HcParcel *parcel, void *dst, uint32_t dataSize) 163{ 164 if (ParcelRead(parcel, dst, dataSize)) { 165 DataRevert(dst, dataSize); 166 return HC_TRUE; 167 } else { 168 return HC_FALSE; 169 } 170} 171 172HcBool ParcelWriteRevert(HcParcel *parcel, const void *src, uint32_t dataSize) 173{ 174 errno_t rc; 175 void *srcCopy = HcMalloc(dataSize, 0); 176 if (srcCopy == NULL) { 177 return HC_FALSE; 178 } 179 rc = memmove_s(srcCopy, dataSize, src, dataSize); 180 if (rc != EOK) { 181 HcFree(srcCopy); 182 return HC_FALSE; 183 } 184 DataRevert(srcCopy, dataSize); 185 HcBool ret = ParcelWrite(parcel, srcCopy, dataSize); 186 HcFree(srcCopy); 187 return ret; 188} 189 190HcBool ParcelReadInt32(HcParcel *parcel, int *dst) 191{ 192 return ParcelRead(parcel, dst, sizeof(int)); 193} 194 195HcBool ParcelReadUint32(HcParcel *parcel, uint32_t *dst) 196{ 197 return ParcelRead(parcel, dst, sizeof(uint32_t)); 198} 199 200HcBool ParcelReadInt16(HcParcel *parcel, short *dst) 201{ 202 return ParcelRead(parcel, dst, sizeof(short)); 203} 204 205HcBool ParcelReadUint16(HcParcel *parcel, uint16_t *dst) 206{ 207 return ParcelRead(parcel, dst, sizeof(uint16_t)); 208} 209 210HcBool ParcelReadInt8(HcParcel *parcel, char *dst) 211{ 212 return ParcelRead(parcel, dst, sizeof(char)); 213} 214 215HcBool ParcelReadUint8(HcParcel *parcel, uint8_t *dst) 216{ 217 return ParcelRead(parcel, dst, sizeof(uint8_t)); 218} 219 220HcBool ParcelReadUint64(HcParcel *parcel, uint64_t *dst) 221{ 222 return ParcelRead(parcel, dst, sizeof(uint64_t)); 223} 224 225HcBool ParcelReadInt64(HcParcel *parcel, int64_t *dst) 226{ 227 return ParcelRead(parcel, dst, sizeof(int64_t)); 228} 229 230static HcBool ParcelRealloc(HcParcel *parcel, uint32_t size) 231{ 232 if (parcel->length >= size) { 233 return HC_FALSE; 234 } 235 char *newData = (char *)HcMalloc(size, 0); 236 if (newData == NULL) { 237 return HC_FALSE; 238 } 239 if (memcpy_s(newData, size, parcel->data, parcel->length) != EOK) { 240 HcFree(newData); 241 return HC_FALSE; 242 } 243 HcFree(parcel->data); 244 parcel->data = newData; 245 parcel->length = size; 246 return HC_TRUE; 247} 248 249static HcBool ParcelIncrease(HcParcel *parcel, uint32_t size) 250{ 251 if (parcel == NULL || size == 0) { 252 return HC_FALSE; 253 } 254 if (parcel->data == NULL) { 255 if (parcel->length != 0) { 256 return HC_FALSE; 257 } 258 *parcel = CreateParcel(size, parcel->allocUnit); 259 if (parcel->data == NULL) { 260 return HC_FALSE; 261 } else { 262 return HC_TRUE; 263 } 264 } else { 265 return ParcelRealloc(parcel, size); 266 } 267} 268 269static void ParcelRecycle(HcParcel *parcel) 270{ 271 if (parcel == NULL) { 272 return; 273 } 274 if (parcel->data == NULL || parcel->beginPos < parcel->allocUnit) { 275 return; 276 } 277 278 uint32_t contentSize = parcel->endPos - parcel->beginPos; 279 if (contentSize > 0) { 280 if (memmove_s(parcel->data, parcel->endPos - parcel->beginPos, 281 parcel->data + parcel->beginPos, parcel->endPos - parcel->beginPos) != EOK) { 282 } 283 } 284 parcel->beginPos = 0; 285 parcel->endPos = contentSize; 286} 287 288static uint32_t GetParcelIncreaseSize(HcParcel *parcel, uint32_t newSize) 289{ 290 if (parcel == NULL || parcel->allocUnit == 0) { 291 return 0; 292 } 293 if (newSize % parcel->allocUnit) { 294 return (newSize / parcel->allocUnit + 1) * parcel->allocUnit; 295 } else { 296 return (newSize / parcel->allocUnit) * parcel->allocUnit; 297 } 298} 299 300HcBool ParcelWrite(HcParcel *parcel, const void *src, uint32_t dataSize) 301{ 302 errno_t rc; 303 if (parcel == NULL || src == NULL || dataSize == 0) { 304 return HC_FALSE; 305 } 306 if (parcel->endPos > PARCEL_UINT_MAX - dataSize) { 307 return HC_FALSE; 308 } 309 if (parcel->endPos + dataSize > parcel->length) { 310 ParcelRecycle(parcel); 311 if (parcel->endPos + dataSize > parcel->length) { 312 uint32_t newSize = GetParcelIncreaseSize(parcel, parcel->endPos + dataSize); 313 if (!ParcelIncrease(parcel, newSize)) { 314 return HC_FALSE; 315 } 316 } 317 } 318 rc = memmove_s(parcel->data + parcel->endPos, dataSize, src, dataSize); 319 if (rc != EOK) { 320 return HC_FALSE; 321 } 322 parcel->endPos += dataSize; 323 return HC_TRUE; 324} 325 326HcBool ParcelWriteInt32(HcParcel *parcel, int src) 327{ 328 return ParcelWrite(parcel, &src, sizeof(src)); 329} 330 331HcBool ParcelWriteUint32(HcParcel *parcel, uint32_t src) 332{ 333 return ParcelWrite(parcel, &src, sizeof(src)); 334} 335 336HcBool ParcelWriteInt16(HcParcel *parcel, short src) 337{ 338 return ParcelWrite(parcel, &src, sizeof(src)); 339} 340 341HcBool ParcelWriteUint16(HcParcel *parcel, uint16_t src) 342{ 343 return ParcelWrite(parcel, &src, sizeof(src)); 344} 345 346HcBool ParcelWriteInt8(HcParcel *parcel, char src) 347{ 348 return ParcelWrite(parcel, &src, sizeof(src)); 349} 350 351HcBool ParcelWriteUint8(HcParcel *parcel, uint8_t src) 352{ 353 return ParcelWrite(parcel, &src, sizeof(src)); 354} 355 356HcBool ParcelWriteUint64(HcParcel *parcel, uint64_t src) 357{ 358 return ParcelWrite(parcel, &src, sizeof(src)); 359} 360 361HcBool ParcelWriteInt64(HcParcel *parcel, int64_t src) 362{ 363 return ParcelWrite(parcel, &src, sizeof(src)); 364} 365 366HcBool ParcelReadParcel(HcParcel *src, HcParcel *dst, uint32_t size, HcBool copy) 367{ 368 if (src == NULL || dst == NULL) { 369 return HC_FALSE; 370 } 371 if (GetParcelDataSize(src) < size) { 372 return HC_FALSE; 373 } 374 if (!ParcelWrite(dst, (void *)GetParcelData(src), size)) { 375 return HC_FALSE; 376 } 377 378 if (!copy) { 379 src->beginPos += size; 380 } 381 return HC_TRUE; 382} 383 384HcBool ParcelCopy(HcParcel *src, HcParcel *dst) 385{ 386 if (src == NULL || dst == NULL) { 387 return HC_FALSE; 388 } 389 if (GetParcelDataSize(src) == 0) { 390 return HC_TRUE; 391 } 392 return ParcelReadParcel(src, dst, GetParcelDataSize(src), HC_TRUE); 393} 394 395void DataRevert(void *data, uint32_t length) 396{ 397 if (data != NULL) { 398 uint8_t *pc = (uint8_t *) data; 399 uint32_t i = 0; 400 for (; i < length / 2; ++i) { /* half of the length */ 401 /* swap p[i] and p[length-i-1] */ 402 pc[i] ^= pc[length - i - 1]; 403 pc[length - i - 1] ^= pc[i]; 404 pc[i] ^= pc[length - i - 1]; 405 } 406 } 407} 408 409HcBool ParcelReadInt32Revert(HcParcel *parcel, int32_t *dst) 410{ 411 HcBool ret = ParcelRead(parcel, dst, sizeof(int)); 412 if (ret) { 413 DataRevert(dst, sizeof(int)); 414 } 415 return ret; 416} 417 418HcBool ParcelReadUint32Revert(HcParcel *parcel, uint32_t *dst) 419{ 420 HcBool ret = ParcelRead(parcel, dst, sizeof(uint32_t)); 421 if (ret) { 422 DataRevert(dst, sizeof(uint32_t)); 423 } 424 return ret; 425} 426 427HcBool ParcelReadInt16Revert(HcParcel *parcel, short *dst) 428{ 429 HcBool ret = ParcelRead(parcel, dst, sizeof(short)); 430 if (ret) { 431 DataRevert(dst, sizeof(short)); 432 } 433 return ret; 434} 435 436HcBool ParcelReadUint16Revert(HcParcel *parcel, uint16_t *dst) 437{ 438 if (parcel == NULL || dst == NULL) { 439 return HC_FALSE; 440 } 441 HcBool ret = ParcelRead(parcel, dst, sizeof(uint16_t)); 442 if (ret) { 443 DataRevert(dst, sizeof(uint16_t)); 444 } 445 return ret; 446} 447 448HcBool ParcelReadInt8Revert(HcParcel *parcel, char *dst) 449{ 450 return ParcelRead(parcel, dst, sizeof(char)); 451} 452 453HcBool ParcelReadUint8Revert(HcParcel *parcel, uint8_t *dst) 454{ 455 return ParcelRead(parcel, dst, sizeof(uint8_t)); 456} 457 458HcBool ParcelReadUint64Revert(HcParcel *parcel, uint64_t *dst) 459{ 460 HcBool ret = ParcelRead(parcel, dst, sizeof(uint64_t)); 461 if (ret) { 462 DataRevert(dst, sizeof(uint64_t)); 463 } 464 return ret; 465} 466 467HcBool ParcelReadInt64Revert(HcParcel *parcel, int64_t *dst) 468{ 469 HcBool ret = ParcelRead(parcel, dst, sizeof(int64_t)); 470 if (ret) { 471 DataRevert(dst, sizeof(int64_t)); 472 } 473 return ret; 474} 475 476HcBool ParcelWriteInt32Revert(HcParcel *parcel, int src) 477{ 478 DataRevert(&src, sizeof(src)); 479 return ParcelWriteInt32(parcel, src); 480} 481 482HcBool ParcelWriteUint32Revert(HcParcel *parcel, uint32_t src) 483{ 484 DataRevert(&src, sizeof(src)); 485 return ParcelWriteUint32(parcel, src); 486} 487 488HcBool ParcelWriteInt16Revert(HcParcel *parcel, short src) 489{ 490 DataRevert(&src, sizeof(src)); 491 return ParcelWriteInt16(parcel, src); 492} 493 494HcBool ParcelWriteUint16Revert(HcParcel *parcel, uint16_t src) 495{ 496 DataRevert(&src, sizeof(src)); 497 return ParcelWriteUint16(parcel, src); 498} 499 500HcBool ParcelWriteInt8Revert(HcParcel *parcel, char src) 501{ 502 return ParcelWriteInt8(parcel, src); 503} 504 505HcBool ParcelWriteUint8Revert(HcParcel *parcel, uint8_t src) 506{ 507 return ParcelWriteUint8(parcel, src); 508} 509 510HcBool ParcelWriteUint64Revert(HcParcel *parcel, uint64_t src) 511{ 512 DataRevert(&src, sizeof(src)); 513 return ParcelWriteUint64(parcel, src); 514} 515 516HcBool ParcelWriteInt64Revert(HcParcel *parcel, int64_t src) 517{ 518 DataRevert(&src, sizeof(src)); 519 return ParcelWriteInt64(parcel, src); 520} 521 522HcBool ParcelPopBack(HcParcel *parcel, uint32_t size) 523{ 524 if (parcel != NULL && size > 0 && GetParcelDataSize(parcel) >= size) { 525 parcel->endPos -= size; 526 return HC_TRUE; 527 } 528 return HC_FALSE; 529} 530 531HcBool ParcelPopFront(HcParcel *parcel, uint32_t size) 532{ 533 if ((parcel != NULL) && (size > 0) && (GetParcelDataSize(parcel) >= size)) { 534 parcel->beginPos += size; 535 return HC_TRUE; 536 } 537 return HC_FALSE; 538} 539