tarray.c 5.6 KB
Newer Older
H
more  
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "tarray.h"

void* taosArrayInit(size_t size, size_t elemSize) {
  assert(elemSize > 0);

  if (size < TARRAY_MIN_SIZE) {
    size = TARRAY_MIN_SIZE;
  }

  SArray* pArray = calloc(1, sizeof(SArray));
  if (pArray == NULL) {
    return NULL;
  }

weixin_48148422's avatar
weixin_48148422 已提交
30
  pArray->pData = calloc(size, elemSize);
H
more  
hzcheng 已提交
31 32 33 34 35 36 37 38 39 40
  if (pArray->pData == NULL) {
    free(pArray);
    return NULL;
  }

  pArray->capacity = size;
  pArray->elemSize = elemSize;
  return pArray;
}

H
hjxilinx 已提交
41
static int32_t taosArrayResize(SArray* pArray) {
H
more  
hzcheng 已提交
42 43 44 45 46 47
  assert(pArray->size >= pArray->capacity);

  size_t size = pArray->capacity;
  size = (size << 1u);

  void* tmp = realloc(pArray->pData, size * pArray->elemSize);
H
hjxilinx 已提交
48 49
  if (tmp == NULL) {  // reallocate failed, the original buffer remains
    return -1;
H
more  
hzcheng 已提交
50 51 52 53
  }

  pArray->pData = tmp;
  pArray->capacity = size;
H
hjxilinx 已提交
54 55
  
  return 0;
H
more  
hzcheng 已提交
56 57 58 59 60 61 62 63
}

void* taosArrayPush(SArray* pArray, void* pData) {
  if (pArray == NULL || pData == NULL) {
    return NULL;
  }

  if (pArray->size >= pArray->capacity) {
H
hjxilinx 已提交
64 65 66 67 68 69
    int32_t ret = taosArrayResize(pArray);
    
    // failed to push data into buffer due to the failure of memory allocation
    if (ret != 0) {
      return NULL;
    }
H
more  
hzcheng 已提交
70 71 72 73 74 75 76 77 78
  }

  void* dst = TARRAY_GET_ELEM(pArray, pArray->size);
  memcpy(dst, pData, pArray->elemSize);

  pArray->size += 1;
  return dst;
}

weixin_48148422's avatar
weixin_48148422 已提交
79
void* taosArrayPop(SArray* pArray) {
80 81 82
  assert( pArray != NULL );

  if (pArray->size == 0) {
weixin_48148422's avatar
weixin_48148422 已提交
83
    return NULL;
H
more  
hzcheng 已提交
84 85
  }
  pArray->size -= 1;
weixin_48148422's avatar
weixin_48148422 已提交
86
  return TARRAY_GET_ELEM(pArray, pArray->size);
H
more  
hzcheng 已提交
87 88
}

89
void* taosArrayGet(const SArray* pArray, size_t index) {
H
more  
hzcheng 已提交
90 91 92 93
  assert(index < pArray->size);
  return TARRAY_GET_ELEM(pArray, index);
}

94
void* taosArrayGetP(const SArray* pArray, size_t index) {
H
Haojun Liao 已提交
95 96 97
  assert(index < pArray->size);
  
  void* d = TARRAY_GET_ELEM(pArray, index);
H
hjxilinx 已提交
98
  
H
Haojun Liao 已提交
99
  return *(void**)d;
H
hjxilinx 已提交
100 101
}

H
Haojun Liao 已提交
102 103 104 105
void* taosArrayGetLast(const SArray* pArray) {
  return TARRAY_GET_ELEM(pArray, pArray->size - 1);
}

H
hjxilinx 已提交
106
size_t taosArrayGetSize(const SArray* pArray) { return pArray->size; }
H
more  
hzcheng 已提交
107

H
hjxilinx 已提交
108
void* taosArrayInsert(SArray* pArray, size_t index, void* pData) {
H
more  
hzcheng 已提交
109
  if (pArray == NULL || pData == NULL) {
H
hjxilinx 已提交
110
    return NULL;
H
more  
hzcheng 已提交
111 112 113
  }

  if (index >= pArray->size) {
H
hjxilinx 已提交
114
    return taosArrayPush(pArray, pData);
H
more  
hzcheng 已提交
115 116 117
  }

  if (pArray->size >= pArray->capacity) {
H
hjxilinx 已提交
118 119 120 121 122
    int32_t ret = taosArrayResize(pArray);
    
    if (ret < 0) {
      return NULL;
    }
H
more  
hzcheng 已提交
123 124 125 126
  }

  void* dst = TARRAY_GET_ELEM(pArray, index);

S
Shengliang Guan 已提交
127 128
  int32_t remain = (int32_t)(pArray->size - index);
  memmove((char*)dst + pArray->elemSize, (char*)dst, pArray->elemSize * remain);
H
more  
hzcheng 已提交
129 130 131
  memcpy(dst, pData, pArray->elemSize);

  pArray->size += 1;
H
hjxilinx 已提交
132 133
  
  return dst;
H
more  
hzcheng 已提交
134 135
}

136 137 138 139 140 141 142 143 144
void taosArrayRemove(SArray* pArray, size_t index) {
  assert(index < pArray->size);
  
  if (index == pArray->size - 1) {
    taosArrayPop(pArray);
    return;
  }
  
  size_t remain = pArray->size - index - 1;
S
Shengliang Guan 已提交
145
  memmove((char*)pArray->pData + index * pArray->elemSize, (char*)pArray->pData + (index + 1) * pArray->elemSize, remain * pArray->elemSize);
146 147 148
  pArray->size -= 1;
}

H
hjxilinx 已提交
149
void taosArrayCopy(SArray* pDst, const SArray* pSrc) {
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  assert(pSrc != NULL && pDst != NULL);
  
  if (pDst->capacity < pSrc->size) {
    void* pData = realloc(pDst->pData, pSrc->size * pSrc->elemSize);
    if (pData == NULL) { // todo handle oom
    
    } else {
      pDst->pData = pData;
      pDst->capacity = pSrc->size;
    }
  }
  
  memcpy(pDst->pData, pSrc->pData, pSrc->elemSize * pSrc->size);
  pDst->elemSize = pSrc->elemSize;
  pDst->capacity = pSrc->size;
  pDst->size = pSrc->size;
}

H
hjxilinx 已提交
168
SArray* taosArrayClone(const SArray* pSrc) {
H
hjxilinx 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181
  assert(pSrc != NULL);
  
  if (pSrc->size == 0) { // empty array list
    return taosArrayInit(8, pSrc->elemSize);
  }
  
  SArray* dst = taosArrayInit(pSrc->size, pSrc->elemSize);
  
  memcpy(dst->pData, pSrc->pData, pSrc->elemSize * pSrc->size);
  dst->size = pSrc->size;
  return dst;
}

weixin_48148422's avatar
weixin_48148422 已提交
182 183 184 185 186
void taosArrayClear(SArray* pArray) {
  assert( pArray != NULL );
  pArray->size = 0;
}

H
hjxilinx 已提交
187
void taosArrayDestroy(SArray* pArray) {
H
more  
hzcheng 已提交
188 189 190 191 192 193 194
  if (pArray == NULL) {
    return;
  }

  free(pArray->pData);
  free(pArray);
}
weixin_48148422's avatar
weixin_48148422 已提交
195

H
Haojun Liao 已提交
196
void taosArrayDestroyEx(SArray* pArray, void (*fp)(void*)) {
H
Haojun Liao 已提交
197 198 199 200
  if (pArray == NULL) {
    return;
  }

H
Haojun Liao 已提交
201 202 203 204 205 206 207 208 209 210 211
  if (fp == NULL) {
    return taosArrayDestroy(pArray);
  }

  for(int32_t i = 0; i < pArray->size; ++i) {
    fp(TARRAY_GET_ELEM(pArray, i));
  }

  taosArrayDestroy(pArray);
}

weixin_48148422's avatar
weixin_48148422 已提交
212 213 214 215 216 217 218
void taosArraySort(SArray* pArray, int (*compar)(const void*, const void*)) {
  assert(pArray != NULL);
  assert(compar != NULL);

  qsort(pArray->pData, pArray->size, pArray->elemSize, compar);
}

219 220
void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t comparFn) {
  assert(pArray != NULL && comparFn != NULL);
weixin_48148422's avatar
weixin_48148422 已提交
221 222
  assert(key != NULL);

223
  return bsearch(key, pArray->pData, pArray->size, pArray->elemSize, comparFn);
weixin_48148422's avatar
weixin_48148422 已提交
224 225
}

226
void taosArraySortString(SArray* pArray, __compar_fn_t comparFn) {
weixin_48148422's avatar
weixin_48148422 已提交
227
  assert(pArray != NULL);
228
  qsort(pArray->pData, pArray->size, pArray->elemSize, comparFn);
weixin_48148422's avatar
weixin_48148422 已提交
229 230
}

231
char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t comparFn) {
weixin_48148422's avatar
weixin_48148422 已提交
232 233 234
  assert(pArray != NULL);
  assert(key != NULL);

235
  void* p = bsearch(&key, pArray->pData, pArray->size, pArray->elemSize, comparFn);
weixin_48148422's avatar
weixin_48148422 已提交
236 237 238 239 240
  if (p == NULL) {
    return NULL;
  }
  return *(char**)p;
}