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 = NULL;
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 || parcel->data == 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         (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 
GetParcelIncreaseSize(HcParcel * parcel,uint32_t newSize)132 static 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 
ParcelWrite(HcParcel * parcel,const void * src,uint32_t dataSize)144 bool 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 
ParcelWriteInt8(HcParcel * parcel,char src)170 bool ParcelWriteInt8(HcParcel *parcel, char src)
171 {
172     return ParcelWrite(parcel, &src, sizeof(src));
173 }
174 
ParcelPopBack(HcParcel * parcel,uint32_t size)175 bool 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