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#ifndef HC_VECTOR_H
17#define HC_VECTOR_H
18
19#include "hc_parcel.h"
20#include "securec.h"
21
22/*
23 * Use DECLARE_HC_VECTOR to declare the vector in the head/src file.
24 * @para ClassName: the name of the vector-class/vector-struct
25 * @para Element: the type of the vector element
26 * @for example:
27 * DECLARE_HC_VECTOR(IntVec, int)
28 */
29#define DECLARE_HC_VECTOR(ClassName, Element) \
30typedef struct V##ClassName{ \
31    Element* (*pushBack)(struct V##ClassName*, const Element*); \
32    Element* (*pushBackT)(struct V##ClassName*, Element); \
33    HcBool (*popFront)(struct V##ClassName*, Element*); \
34    HcBool (*eraseElement)(struct V##ClassName*, Element*, uint32_t index); \
35    uint32_t (*size)(const struct V##ClassName*); \
36    Element (*get)(const struct V##ClassName*, uint32_t index); \
37    Element* (*getp)(const struct V##ClassName*, uint32_t index); \
38    void (*clear)(struct V##ClassName*); \
39    HcParcel parcel; \
40} ClassName;
41
42/*
43 * Use IMPLEMENT_HC_VECTOR to implement the vector in the source file.
44 * @para ClassName: the name of the vector-class/vector-struct
45 * @para Element: the type of the vector element
46 * @para allocCount: the minimum alloc count
47 * @for example:
48 * IMPLEMENT_HC_VECTOR(IntVec, int)
49 */
50#define IMPLEMENT_HC_VECTOR(ClassName, Element, allocCount) \
51Element* VPushBack##ClassName(ClassName* obj, const Element *e) { \
52    if (obj == NULL || e == NULL) { \
53        return NULL; \
54    } \
55      \
56    if (ParcelWrite(&obj->parcel, e, sizeof(Element))) { \
57        uint32_t size = obj->size(obj); \
58        return obj->getp(obj, size - 1); \
59    } else { \
60        return NULL; \
61    } \
62} \
63Element* VPushBackT##ClassName(ClassName* obj, Element e) { \
64    if (obj == NULL) { \
65        return NULL; \
66    } \
67      \
68    if (ParcelWrite(&obj->parcel, &e, sizeof(Element))) { \
69        uint32_t size = obj->size(obj); \
70        return obj->getp(obj, size - 1); \
71    } else { \
72        return NULL; \
73    } \
74} \
75HcBool VPopFront##ClassName(ClassName* obj, Element* e) { \
76        if (NULL == obj || NULL == e) { \
77            return HC_FALSE; \
78        } \
79        if (obj->size(obj) > 0) { \
80            return ParcelRead(&obj->parcel, e, sizeof(Element)); \
81        } else { \
82            return HC_FALSE; \
83        } \
84} \
85HcBool VErase##ClassName(ClassName* obj, Element* e, uint32_t index) { \
86        if (NULL == obj || NULL == e || index + 1 > obj->size(obj)) { \
87            return HC_FALSE; \
88        } \
89        if (obj->size(obj) > 0) { \
90            return ParcelEraseBlock(&obj->parcel, index * sizeof(Element), sizeof(Element), e); \
91        } else { \
92            return HC_FALSE; \
93        } \
94} \
95uint32_t VSize##ClassName(const ClassName* obj) \
96{ \
97    if (NULL == obj) { \
98        return 0; \
99    } \
100    return GetParcelDataSize(&obj->parcel) / sizeof(Element); \
101} \
102Element VGet##ClassName(const ClassName* obj, uint32_t index) \
103{ \
104    Element e; \
105    (void)memset_s(&e, sizeof(e), 0, sizeof(e)); \
106    if (NULL != obj) { \
107        if (index < obj->size(obj)) { \
108            if (GetParcelData(&obj->parcel)) { \
109                return *((Element*)(GetParcelData(&obj->parcel)) + index); \
110            } else { \
111                return e; \
112            } \
113        } \
114    } \
115    (void)memset_s(&e, sizeof(e), 0, sizeof(e)); \
116    return e; \
117} \
118Element* VGetPointer##ClassName(const ClassName* obj, uint32_t index) \
119{ \
120    if (NULL != obj) { \
121        if (index < obj->size(obj)) { \
122            if (GetParcelData(&obj->parcel)) { \
123                return ((Element*)(GetParcelData(&obj->parcel)) + index); \
124            } else { \
125                return NULL; \
126            } \
127        } \
128    } \
129    return NULL; \
130} \
131void VClear##ClassName(ClassName* obj) \
132{ \
133    if (NULL != obj) { \
134        ClearParcel(&obj->parcel); \
135    } \
136} \
137ClassName Create##ClassName(void) \
138{ \
139    ClassName obj; \
140    obj.pushBack = VPushBack##ClassName; \
141    obj.pushBackT = VPushBackT##ClassName; \
142    obj.popFront = VPopFront##ClassName; \
143    obj.clear = VClear##ClassName; \
144    obj.eraseElement = VErase##ClassName; \
145    obj.size = VSize##ClassName; \
146    obj.get = VGet##ClassName; \
147    obj.getp = VGetPointer##ClassName; \
148    obj.parcel = CreateParcel(0, sizeof(Element) * allocCount); \
149    return obj; \
150} \
151void Destroy##ClassName(ClassName* obj) \
152{ \
153    if (NULL != obj) { \
154        DeleteParcel(&obj->parcel); \
155    } \
156}
157
158/* Use these two macros to create and destroy vector */
159#define CREATE_HC_VECTOR(classname) Create##classname()
160#define DESTROY_HC_VECTOR(classname, obj) Destroy##classname(obj)
161
162#define FOR_EACH_HC_VECTOR(vec, index, iter) for (index = 0; index < (vec).size(&(vec)) && \
163    (iter = (vec).getp(&(vec), index)); ++index)
164
165#define HC_VECTOR_PUSHBACK(obj, element) (obj)->pushBack((obj), (element))
166#define HC_VECTOR_POPFRONT(obj, element) (obj)->popFront((obj), (element))
167#define HC_VECTOR_POPELEMENT(obj, element, index) (obj)->eraseElement((obj), (element), (index))
168#define HC_VECTOR_SIZE(obj) (obj)->size(obj)
169#define HC_VECTOR_GET(obj, index) (obj)->get((obj), (index))
170#define HC_VECTOR_GETP(_obj, _index) (_obj)->getp((_obj), (_index))
171
172#endif
173