tarray.c 10.5 KB
Newer Older
H
more  
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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/>.
 */

S
TD-4088  
Shengliang Guan 已提交
16
#include "os.h"
H
more  
hzcheng 已提交
17
#include "tarray.h"
18
#include "talgo.h"
H
more  
hzcheng 已提交
19

20
SArray* taosArrayInit(size_t size, size_t elemSize) {
H
more  
hzcheng 已提交
21 22 23 24 25 26
  assert(elemSize > 0);

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

H
Haojun Liao 已提交
27
  SArray* pArray = malloc(sizeof(SArray));
H
more  
hzcheng 已提交
28 29 30 31
  if (pArray == NULL) {
    return NULL;
  }

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

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

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

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

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

  pArray->pData = tmp;
  pArray->capacity = size;
H
hjxilinx 已提交
57 58
  
  return 0;
H
more  
hzcheng 已提交
59 60
}

L
Liu Jicong 已提交
61 62
int32_t taosArrayEnsureCap(SArray* pArray, size_t newCap) {
  if (newCap > pArray->capacity) {
H
Hongze Cheng 已提交
63
    size_t tsize = (pArray->capacity << 1u);
L
Liu Jicong 已提交
64
    while (newCap > tsize) {
H
Hongze Cheng 已提交
65 66 67 68 69
      tsize = (tsize << 1u);
    }

    pArray->pData = realloc(pArray->pData, tsize * pArray->elemSize);
    if (pArray->pData == NULL) {
L
Liu Jicong 已提交
70
      return -1;
H
hjxilinx 已提交
71
    }
H
Hongze Cheng 已提交
72 73

    pArray->capacity = tsize;
H
more  
hzcheng 已提交
74
  }
L
Liu Jicong 已提交
75 76 77 78 79 80 81 82 83 84 85
  return 0;
}

void* taosArrayAddBatch(SArray* pArray, const void* pData, int nEles) {
  if (pArray == NULL || pData == NULL) {
    return NULL;
  }

  if(taosArrayEnsureCap(pArray, pArray->size + nEles) != 0){
    return NULL;
  }
H
more  
hzcheng 已提交
86 87

  void* dst = TARRAY_GET_ELEM(pArray, pArray->size);
H
Hongze Cheng 已提交
88
  memcpy(dst, pData, pArray->elemSize * nEles);
H
more  
hzcheng 已提交
89

H
Hongze Cheng 已提交
90
  pArray->size += nEles;
H
more  
hzcheng 已提交
91 92 93
  return dst;
}

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
void taosArrayRemoveBatch(SArray *pArray, const int32_t* pData, int32_t numOfElems) {
  assert(pArray != NULL && pData != NULL);
  if (numOfElems <= 0) {
    return;
  }

  size_t size = taosArrayGetSize(pArray);
  if (numOfElems >= size) {
    taosArrayClear(pArray);
    return;
  }

  int32_t i = pData[0] + 1, j = 0;
  while(i < size) {
    if (j == numOfElems - 1) {
      break;
    }

    char* p = TARRAY_GET_ELEM(pArray, i);
    if (i > pData[j] && i < pData[j + 1]) {
      char* dst = TARRAY_GET_ELEM(pArray, i - (j + 1));
      memmove(dst, p, pArray->elemSize);
    } else if (i == pData[j + 1]) {
      j += 1;
    }

    i += 1;
  }

H
Haojun Liao 已提交
123
  assert(i == pData[numOfElems - 1] + 1 && i <= size);
124 125

  int32_t srcIndex = pData[numOfElems - 1] + 1;
H
Haojun Liao 已提交
126 127 128 129 130 131
  int32_t dstIndex = pData[numOfElems - 1] - numOfElems + 1;
  if (pArray->size - srcIndex > 0) {
    char* dst = TARRAY_GET_ELEM(pArray, dstIndex);
    char* src = TARRAY_GET_ELEM(pArray, srcIndex);
    memmove(dst, src, pArray->elemSize * (pArray->size - srcIndex));
  }
132 133 134 135

  pArray->size -= numOfElems;
}

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
void taosArrayRemoveDuplicate(SArray *pArray, __compar_fn_t comparFn, void (*fp)(void*)) {
  assert(pArray);

  size_t size = pArray->size;
  if (size <= 1) {
    return;
  }

  int32_t pos = 0;
  for(int32_t i = 1; i < size; ++i) {
    char* p1 = taosArrayGet(pArray, pos);
    char* p2 = taosArrayGet(pArray, i);

    if (comparFn(p1, p2) == 0) {
      // do nothing
    } else {
      if (pos + 1 != i) {
        void* p = taosArrayGet(pArray, pos + 1);
        if (fp != NULL) {
          fp(p);
        }

        taosArraySet(pArray, pos + 1, p2);
        pos += 1;
      } else {
        pos += 1;
      }
    }
  }

  if (fp != NULL) {
    for(int32_t i = pos + 1; i < pArray->size; ++i) {
      void* p = taosArrayGet(pArray, i);
      fp(p);
    }
  }

  pArray->size = pos + 1;
}

H
Haojun Liao 已提交
176 177 178 179
void* taosArrayAddAll(SArray* pArray, const SArray* pInput) {
  return taosArrayAddBatch(pArray, pInput->pData, (int32_t) taosArrayGetSize(pInput));
}

weixin_48148422's avatar
weixin_48148422 已提交
180
void* taosArrayPop(SArray* pArray) {
181 182 183
  assert( pArray != NULL );

  if (pArray->size == 0) {
weixin_48148422's avatar
weixin_48148422 已提交
184
    return NULL;
H
more  
hzcheng 已提交
185 186
  }
  pArray->size -= 1;
weixin_48148422's avatar
weixin_48148422 已提交
187
  return TARRAY_GET_ELEM(pArray, pArray->size);
H
more  
hzcheng 已提交
188 189
}

190
void* taosArrayGet(const SArray* pArray, size_t index) {
H
more  
hzcheng 已提交
191 192 193 194
  assert(index < pArray->size);
  return TARRAY_GET_ELEM(pArray, index);
}

195
void* taosArrayGetP(const SArray* pArray, size_t index) {
H
Haojun Liao 已提交
196 197 198
  assert(index < pArray->size);
  
  void* d = TARRAY_GET_ELEM(pArray, index);
H
hjxilinx 已提交
199
  
H
Haojun Liao 已提交
200
  return *(void**)d;
H
hjxilinx 已提交
201 202
}

H
Haojun Liao 已提交
203 204 205 206
void* taosArrayGetLast(const SArray* pArray) {
  return TARRAY_GET_ELEM(pArray, pArray->size - 1);
}

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

209 210 211 212 213
void taosArraySetSize(SArray* pArray, size_t size) {
  assert(size <= pArray->capacity);
  pArray->size = size;
}

H
hjxilinx 已提交
214
void* taosArrayInsert(SArray* pArray, size_t index, void* pData) {
H
more  
hzcheng 已提交
215
  if (pArray == NULL || pData == NULL) {
H
hjxilinx 已提交
216
    return NULL;
H
more  
hzcheng 已提交
217 218 219
  }

  if (index >= pArray->size) {
H
hjxilinx 已提交
220
    return taosArrayPush(pArray, pData);
H
more  
hzcheng 已提交
221 222 223
  }

  if (pArray->size >= pArray->capacity) {
H
hjxilinx 已提交
224 225 226 227 228
    int32_t ret = taosArrayResize(pArray);
    
    if (ret < 0) {
      return NULL;
    }
H
more  
hzcheng 已提交
229 230 231 232
  }

  void* dst = TARRAY_GET_ELEM(pArray, index);

S
Shengliang Guan 已提交
233 234
  int32_t remain = (int32_t)(pArray->size - index);
  memmove((char*)dst + pArray->elemSize, (char*)dst, pArray->elemSize * remain);
H
more  
hzcheng 已提交
235 236 237
  memcpy(dst, pData, pArray->elemSize);

  pArray->size += 1;
H
hjxilinx 已提交
238 239
  
  return dst;
H
more  
hzcheng 已提交
240 241
}

H
Hongze Cheng 已提交
242
void taosArraySet(SArray* pArray, size_t index, void* pData) {
H
refact  
Hongze Cheng 已提交
243 244 245 246
  assert(index < pArray->size);
  memcpy(TARRAY_GET_ELEM(pArray, index), pData, pArray->elemSize);
}

L
Liu Jicong 已提交
247 248 249 250 251 252
void taosArrayPopFrontBatch(SArray* pArray, size_t cnt) {
  assert(cnt <= pArray->size);
  pArray->size = pArray->size - cnt;
  if(pArray->size == 0) {
    return;
  }
L
Liu Jicong 已提交
253
  memmove(pArray->pData, (char*)pArray->pData + cnt * pArray->elemSize, pArray->size * pArray->elemSize);
L
Liu Jicong 已提交
254 255
}

L
Liu Jicong 已提交
256 257 258 259 260
void taosArrayPopTailBatch(SArray* pArray, size_t cnt) {
  assert(cnt <= pArray->size);
  pArray->size = pArray->size - cnt;
}

261 262 263 264 265 266 267 268 269
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 已提交
270
  memmove((char*)pArray->pData + index * pArray->elemSize, (char*)pArray->pData + (index + 1) * pArray->elemSize, remain * pArray->elemSize);
271 272 273
  pArray->size -= 1;
}

H
Haojun Liao 已提交
274 275 276 277 278 279 280 281
SArray* taosArrayFromList(const void* src, size_t size, size_t elemSize) {
  assert(src != NULL && elemSize > 0);
  SArray* pDst = taosArrayInit(size, elemSize);

  memcpy(pDst->pData, src, elemSize * size);
  pDst->size = size;

  return pDst;
282 283
}

H
Haojun Liao 已提交
284
SArray* taosArrayDup(const SArray* pSrc) {
H
hjxilinx 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297
  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 已提交
298 299 300 301 302
void taosArrayClear(SArray* pArray) {
  assert( pArray != NULL );
  pArray->size = 0;
}

H
Hongze Cheng 已提交
303 304 305 306
void* taosArrayDestroy(SArray* pArray) {
  if (pArray) {
    free(pArray->pData);
    free(pArray);
H
more  
hzcheng 已提交
307 308
  }

H
Hongze Cheng 已提交
309
  return NULL;
H
more  
hzcheng 已提交
310
}
weixin_48148422's avatar
weixin_48148422 已提交
311

H
Haojun Liao 已提交
312
void taosArrayDestroyEx(SArray* pArray, void (*fp)(void*)) {
H
Haojun Liao 已提交
313 314 315 316
  if (pArray == NULL) {
    return;
  }

H
Haojun Liao 已提交
317
  if (fp == NULL) {
H
Haojun Liao 已提交
318 319
    taosArrayDestroy(pArray);
    return;
H
Haojun Liao 已提交
320 321 322 323 324 325 326 327 328
  }

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

  taosArrayDestroy(pArray);
}

329
void taosArraySort(SArray* pArray, __compar_fn_t compar) {
weixin_48148422's avatar
weixin_48148422 已提交
330 331 332 333 334 335
  assert(pArray != NULL);
  assert(compar != NULL);

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

H
refact  
Hongze Cheng 已提交
336
void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t comparFn, int flags) {
337
  assert(pArray != NULL && comparFn != NULL);
weixin_48148422's avatar
weixin_48148422 已提交
338 339
  assert(key != NULL);

H
refact  
Hongze Cheng 已提交
340
  return taosbsearch(key, pArray->pData, pArray->size, pArray->elemSize, comparFn, flags);
weixin_48148422's avatar
weixin_48148422 已提交
341 342
}

L
Liu Jicong 已提交
343 344 345 346 347
int32_t taosArraySearchIdx(const SArray* pArray, const void* key, __compar_fn_t comparFn, int flags) {
  void* item = taosArraySearch(pArray, key, comparFn, flags);
  return (int32_t)((char*)item - (char*)pArray->pData) / pArray->elemSize;
}

348
void taosArraySortString(SArray* pArray, __compar_fn_t comparFn) {
weixin_48148422's avatar
weixin_48148422 已提交
349
  assert(pArray != NULL);
350
  qsort(pArray->pData, pArray->size, pArray->elemSize, comparFn);
weixin_48148422's avatar
weixin_48148422 已提交
351 352
}

H
refact  
Hongze Cheng 已提交
353
char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t comparFn, int flags) {
weixin_48148422's avatar
weixin_48148422 已提交
354 355 356
  assert(pArray != NULL);
  assert(key != NULL);

H
refact  
Hongze Cheng 已提交
357
  void* p = taosbsearch(&key, pArray->pData, pArray->size, pArray->elemSize, comparFn, flags);
weixin_48148422's avatar
weixin_48148422 已提交
358 359 360 361
  if (p == NULL) {
    return NULL;
  }
  return *(char**)p;
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
}

static int taosArrayPartition(SArray *pArray, int i, int j, __ext_compar_fn_t fn, const void *userData) {
  void* key = taosArrayGetP(pArray, i);  
  while (i < j) {
    while (i < j && fn(taosArrayGetP(pArray, j), key, userData) >= 0) { j--; }
    if (i < j) { 
      void *a = taosArrayGetP(pArray, j); 
      taosArraySet(pArray, i, &a);
    }
    while (i < j && fn(taosArrayGetP(pArray, i), key, userData) <= 0) { i++;} 
    if (i < j) {
      void *a = taosArrayGetP(pArray, i);
      taosArraySet(pArray, j, &a);
    }
  }
  taosArraySet(pArray, i, &key); 
  return i;
}

static void taosArrayQuicksortHelper(SArray *pArray, int low, int high, __ext_compar_fn_t fn, const void *param) {
  if (low < high) {
    int idx = taosArrayPartition(pArray, low, high, fn, param);
    taosArrayQuicksortHelper(pArray, low, idx - 1, fn, param);
    taosArrayQuicksortHelper(pArray, idx + 1, high, fn, param);
  } 
}

static void taosArrayQuickSort(SArray* pArray, __ext_compar_fn_t fn, const void *param) {
391
  if (pArray->size <= 1) {
392 393
    return;
  } 
394
  taosArrayQuicksortHelper(pArray, 0, (int)(taosArrayGetSize(pArray) - 1),  fn, param); 
395 396
}
static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void *param) {
397
  if (pArray->size <= 1) {
398 399
    return;
  } 
400 401 402 403 404 405 406 407 408 409 410 411
  for (int i = 1; i <= pArray->size - 1; ++i) {
    for (int j = i; j > 0; --j) {
      if (fn(taosArrayGetP(pArray, j), taosArrayGetP(pArray, j - 1), param) == -1) {
        void *a = taosArrayGetP(pArray, j);  
        void *b = taosArrayGetP(pArray, j - 1);
        taosArraySet(pArray, j - 1, &a);
        taosArraySet(pArray, j, &b);
      } else {
        break;
      }
    }
  }
412
  return;
413 414
   
} 
415
// order array<type *>  
416
void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void *param) {
417
  taosArrayGetSize(pArray) > 8 ? 
418 419
    taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param);
}
420
//TODO(yihaoDeng) add order array<type>