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
20 const int PARCEL_DEFAULT_INCREASE_STEP = 16;
21 const uint32_t PARCEL_UINT_MAX = 0xffffffffU;
22 const int HALF_LEN = 2;
23
CreateParcel(uint32_t size,uint32_t allocUnit)24 HcParcel 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
DeleteParcel(HcParcel * parcel)41 void DeleteParcel(HcParcel *parcel)
42 {
43 if (parcel == NULL) {
44 return;
45 }
46
47 if (parcel->data != NULL) {
48 HcfFree(parcel->data);
49 parcel->data = 0;
50 }
51 parcel->length = 0;
52 parcel->beginPos = 0;
53 parcel->endPos = 0;
54 }
55
GetParcelDataSize(const HcParcel * parcel)56 uint32_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
GetParcelData(const HcParcel * parcel)67 const char *GetParcelData(const HcParcel *parcel)
68 {
69 if (parcel == NULL) {
70 return NULL;
71 }
72 return parcel->data + parcel->beginPos;
73 }
74
ParcelRealloc(HcParcel * parcel,uint32_t size)75 static 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
ParcelIncrease(HcParcel * parcel,uint32_t size)94 static 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
ParcelRecycle(HcParcel * parcel)114 static 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 if (memmove_s(parcel->data, parcel->endPos - parcel->beginPos,
126 parcel->data + parcel->beginPos, parcel->endPos - parcel->beginPos) != EOK) {
127 }
128 }
129 parcel->beginPos = 0;
130 parcel->endPos = contentSize;
131 }
132
GetParcelIncreaseSize(HcParcel * parcel,uint32_t newSize)133 static uint32_t GetParcelIncreaseSize(HcParcel *parcel, uint32_t newSize)
134 {
135 if (parcel == NULL || parcel->allocUnit == 0) {
136 return 0;
137 }
138 if (newSize % parcel->allocUnit) {
139 return (newSize / parcel->allocUnit + 1) * parcel->allocUnit;
140 } else {
141 return (newSize / parcel->allocUnit) * parcel->allocUnit;
142 }
143 }
144
ParcelWrite(HcParcel * parcel,const void * src,uint32_t dataSize)145 bool ParcelWrite(HcParcel *parcel, const void *src, uint32_t dataSize)
146 {
147 errno_t rc;
148 if (parcel == NULL || src == NULL || dataSize == 0) {
149 return false;
150 }
151 if (parcel->endPos > PARCEL_UINT_MAX - dataSize) {
152 return false;
153 }
154 if (parcel->endPos + dataSize > parcel->length) {
155 ParcelRecycle(parcel);
156 if (parcel->endPos + dataSize > parcel->length) {
157 uint32_t newSize = GetParcelIncreaseSize(parcel, parcel->endPos + dataSize);
158 if (!ParcelIncrease(parcel, newSize)) {
159 return false;
160 }
161 }
162 }
163 rc = memmove_s(parcel->data + parcel->endPos, dataSize, src, dataSize);
164 if (rc != EOK) {
165 return false;
166 }
167 parcel->endPos += dataSize;
168 return true;
169 }
170
ParcelWriteInt8(HcParcel * parcel,char src)171 bool ParcelWriteInt8(HcParcel *parcel, char src)
172 {
173 return ParcelWrite(parcel, &src, sizeof(src));
174 }
175
ParcelPopBack(HcParcel * parcel,uint32_t size)176 bool ParcelPopBack(HcParcel *parcel, uint32_t size)
177 {
178 if (parcel != NULL && size > 0 && GetParcelDataSize(parcel) >= size) {
179 parcel->endPos -= size;
180 return true;
181 }
182 return false;
183 }
184