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
20 const int PARCEL_DEFAULT_INCREASE_STEP = 16;
21 const uint32_t PARCEL_UINT_MAX = 0xffffffffU;
22
CreateParcel(uint32_t size,uint32_t allocUnit)23 HcParcel 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
DeleteParcel(HcParcel * parcel)40 void 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
ClearParcel(HcParcel * parcel)55 void ClearParcel(HcParcel *parcel)
56 {
57 if (parcel != NULL) {
58 parcel->beginPos = 0;
59 parcel->endPos = 0;
60 }
61 }
62
ResetParcel(HcParcel * parcel,uint32_t size,uint32_t allocUnit)63 void 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
GetParcelDataSize(const HcParcel * parcel)72 uint32_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
GetParcelData(const HcParcel * parcel)83 const char *GetParcelData(const HcParcel *parcel)
84 {
85 if (parcel == NULL) {
86 return NULL;
87 }
88 return parcel->data + parcel->beginPos;
89 }
90
GetParcelLastChar(const HcParcel * parcel)91 const 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
ParcelReadWithoutPopData(HcParcel * parcel,void * dst,uint32_t dataSize)99 HcBool 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
ParcelRead(HcParcel * parcel,void * dst,uint32_t dataSize)112 HcBool 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
ParcelEraseBlock(HcParcel * parcel,uint32_t start,uint32_t dataSize,void * dst)132 HcBool 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
ParcelReadRevert(HcParcel * parcel,void * dst,uint32_t dataSize)162 HcBool 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
ParcelWriteRevert(HcParcel * parcel,const void * src,uint32_t dataSize)172 HcBool 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
ParcelReadInt32(HcParcel * parcel,int * dst)190 HcBool ParcelReadInt32(HcParcel *parcel, int *dst)
191 {
192 return ParcelRead(parcel, dst, sizeof(int));
193 }
194
ParcelReadUint32(HcParcel * parcel,uint32_t * dst)195 HcBool ParcelReadUint32(HcParcel *parcel, uint32_t *dst)
196 {
197 return ParcelRead(parcel, dst, sizeof(uint32_t));
198 }
199
ParcelReadInt16(HcParcel * parcel,short * dst)200 HcBool ParcelReadInt16(HcParcel *parcel, short *dst)
201 {
202 return ParcelRead(parcel, dst, sizeof(short));
203 }
204
ParcelReadUint16(HcParcel * parcel,uint16_t * dst)205 HcBool ParcelReadUint16(HcParcel *parcel, uint16_t *dst)
206 {
207 return ParcelRead(parcel, dst, sizeof(uint16_t));
208 }
209
ParcelReadInt8(HcParcel * parcel,char * dst)210 HcBool ParcelReadInt8(HcParcel *parcel, char *dst)
211 {
212 return ParcelRead(parcel, dst, sizeof(char));
213 }
214
ParcelReadUint8(HcParcel * parcel,uint8_t * dst)215 HcBool ParcelReadUint8(HcParcel *parcel, uint8_t *dst)
216 {
217 return ParcelRead(parcel, dst, sizeof(uint8_t));
218 }
219
ParcelReadUint64(HcParcel * parcel,uint64_t * dst)220 HcBool ParcelReadUint64(HcParcel *parcel, uint64_t *dst)
221 {
222 return ParcelRead(parcel, dst, sizeof(uint64_t));
223 }
224
ParcelReadInt64(HcParcel * parcel,int64_t * dst)225 HcBool ParcelReadInt64(HcParcel *parcel, int64_t *dst)
226 {
227 return ParcelRead(parcel, dst, sizeof(int64_t));
228 }
229
ParcelRealloc(HcParcel * parcel,uint32_t size)230 static 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
ParcelIncrease(HcParcel * parcel,uint32_t size)249 static 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
ParcelRecycle(HcParcel * parcel)269 static 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
GetParcelIncreaseSize(HcParcel * parcel,uint32_t newSize)288 static 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
ParcelWrite(HcParcel * parcel,const void * src,uint32_t dataSize)300 HcBool 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
ParcelWriteInt32(HcParcel * parcel,int src)326 HcBool ParcelWriteInt32(HcParcel *parcel, int src)
327 {
328 return ParcelWrite(parcel, &src, sizeof(src));
329 }
330
ParcelWriteUint32(HcParcel * parcel,uint32_t src)331 HcBool ParcelWriteUint32(HcParcel *parcel, uint32_t src)
332 {
333 return ParcelWrite(parcel, &src, sizeof(src));
334 }
335
ParcelWriteInt16(HcParcel * parcel,short src)336 HcBool ParcelWriteInt16(HcParcel *parcel, short src)
337 {
338 return ParcelWrite(parcel, &src, sizeof(src));
339 }
340
ParcelWriteUint16(HcParcel * parcel,uint16_t src)341 HcBool ParcelWriteUint16(HcParcel *parcel, uint16_t src)
342 {
343 return ParcelWrite(parcel, &src, sizeof(src));
344 }
345
ParcelWriteInt8(HcParcel * parcel,char src)346 HcBool ParcelWriteInt8(HcParcel *parcel, char src)
347 {
348 return ParcelWrite(parcel, &src, sizeof(src));
349 }
350
ParcelWriteUint8(HcParcel * parcel,uint8_t src)351 HcBool ParcelWriteUint8(HcParcel *parcel, uint8_t src)
352 {
353 return ParcelWrite(parcel, &src, sizeof(src));
354 }
355
ParcelWriteUint64(HcParcel * parcel,uint64_t src)356 HcBool ParcelWriteUint64(HcParcel *parcel, uint64_t src)
357 {
358 return ParcelWrite(parcel, &src, sizeof(src));
359 }
360
ParcelWriteInt64(HcParcel * parcel,int64_t src)361 HcBool ParcelWriteInt64(HcParcel *parcel, int64_t src)
362 {
363 return ParcelWrite(parcel, &src, sizeof(src));
364 }
365
ParcelReadParcel(HcParcel * src,HcParcel * dst,uint32_t size,HcBool copy)366 HcBool 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
ParcelCopy(HcParcel * src,HcParcel * dst)384 HcBool 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
DataRevert(void * data,uint32_t length)395 void 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
ParcelReadInt32Revert(HcParcel * parcel,int32_t * dst)409 HcBool 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
ParcelReadUint32Revert(HcParcel * parcel,uint32_t * dst)418 HcBool 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
ParcelReadInt16Revert(HcParcel * parcel,short * dst)427 HcBool 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
ParcelReadUint16Revert(HcParcel * parcel,uint16_t * dst)436 HcBool 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
ParcelReadInt8Revert(HcParcel * parcel,char * dst)448 HcBool ParcelReadInt8Revert(HcParcel *parcel, char *dst)
449 {
450 return ParcelRead(parcel, dst, sizeof(char));
451 }
452
ParcelReadUint8Revert(HcParcel * parcel,uint8_t * dst)453 HcBool ParcelReadUint8Revert(HcParcel *parcel, uint8_t *dst)
454 {
455 return ParcelRead(parcel, dst, sizeof(uint8_t));
456 }
457
ParcelReadUint64Revert(HcParcel * parcel,uint64_t * dst)458 HcBool 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
ParcelReadInt64Revert(HcParcel * parcel,int64_t * dst)467 HcBool 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
ParcelWriteInt32Revert(HcParcel * parcel,int src)476 HcBool ParcelWriteInt32Revert(HcParcel *parcel, int src)
477 {
478 DataRevert(&src, sizeof(src));
479 return ParcelWriteInt32(parcel, src);
480 }
481
ParcelWriteUint32Revert(HcParcel * parcel,uint32_t src)482 HcBool ParcelWriteUint32Revert(HcParcel *parcel, uint32_t src)
483 {
484 DataRevert(&src, sizeof(src));
485 return ParcelWriteUint32(parcel, src);
486 }
487
ParcelWriteInt16Revert(HcParcel * parcel,short src)488 HcBool ParcelWriteInt16Revert(HcParcel *parcel, short src)
489 {
490 DataRevert(&src, sizeof(src));
491 return ParcelWriteInt16(parcel, src);
492 }
493
ParcelWriteUint16Revert(HcParcel * parcel,uint16_t src)494 HcBool ParcelWriteUint16Revert(HcParcel *parcel, uint16_t src)
495 {
496 DataRevert(&src, sizeof(src));
497 return ParcelWriteUint16(parcel, src);
498 }
499
ParcelWriteInt8Revert(HcParcel * parcel,char src)500 HcBool ParcelWriteInt8Revert(HcParcel *parcel, char src)
501 {
502 return ParcelWriteInt8(parcel, src);
503 }
504
ParcelWriteUint8Revert(HcParcel * parcel,uint8_t src)505 HcBool ParcelWriteUint8Revert(HcParcel *parcel, uint8_t src)
506 {
507 return ParcelWriteUint8(parcel, src);
508 }
509
ParcelWriteUint64Revert(HcParcel * parcel,uint64_t src)510 HcBool ParcelWriteUint64Revert(HcParcel *parcel, uint64_t src)
511 {
512 DataRevert(&src, sizeof(src));
513 return ParcelWriteUint64(parcel, src);
514 }
515
ParcelWriteInt64Revert(HcParcel * parcel,int64_t src)516 HcBool ParcelWriteInt64Revert(HcParcel *parcel, int64_t src)
517 {
518 DataRevert(&src, sizeof(src));
519 return ParcelWriteInt64(parcel, src);
520 }
521
ParcelPopBack(HcParcel * parcel,uint32_t size)522 HcBool 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
ParcelPopFront(HcParcel * parcel,uint32_t size)531 HcBool 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