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) \ 30 typedef 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) \ 51 Element* 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 } \ 63 Element* 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 } \ 75 HcBool 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 } \ 85 HcBool 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 } \ 95 uint32_t VSize##ClassName(const ClassName* obj) \ 96 { \ 97 if (NULL == obj) { \ 98 return 0; \ 99 } \ 100 return GetParcelDataSize(&obj->parcel) / sizeof(Element); \ 101 } \ 102 Element 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 } \ 118 Element* 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 } \ 131 void VClear##ClassName(ClassName* obj) \ 132 { \ 133 if (NULL != obj) { \ 134 ClearParcel(&obj->parcel); \ 135 } \ 136 } \ 137 ClassName 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 } \ 151 void 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