tarray.c 12.3 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
tarray  
Shengliang Guan 已提交
16
#define _DEFAULT_SOURCE
H
more  
hzcheng 已提交
17
#include "tarray.h"
18
#include "tcoding.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;
  }

wafwerar's avatar
wafwerar 已提交
27
  SArray* pArray = taosMemoryMalloc(sizeof(SArray));
H
more  
hzcheng 已提交
28
  if (pArray == NULL) {
29
    terrno = TSDB_CODE_OUT_OF_MEMORY;
H
more  
hzcheng 已提交
30 31 32
    return NULL;
  }

H
Haojun Liao 已提交
33
  pArray->size = 0;
wafwerar's avatar
wafwerar 已提交
34
  pArray->pData = taosMemoryCalloc(size, elemSize);
H
more  
hzcheng 已提交
35
  if (pArray->pData == NULL) {
36
    terrno = TSDB_CODE_OUT_OF_MEMORY;
wafwerar's avatar
wafwerar 已提交
37
    taosMemoryFree(pArray);
H
more  
hzcheng 已提交
38 39 40 41 42 43 44 45
    return NULL;
  }

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

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

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

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

  pArray->pData = tmp;
  pArray->capacity = size;
S
tarray  
Shengliang Guan 已提交
59

H
hjxilinx 已提交
60
  return 0;
H
more  
hzcheng 已提交
61 62
}

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

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

    pArray->capacity = tsize;
H
more  
hzcheng 已提交
76
  }
L
Liu Jicong 已提交
77 78 79
  return 0;
}

S
tarray  
Shengliang Guan 已提交
80
void* taosArrayAddBatch(SArray* pArray, const void* pData, int32_t nEles) {
L
Liu Jicong 已提交
81
  if (pData == NULL) {
L
Liu Jicong 已提交
82 83 84
    return NULL;
  }

S
tarray  
Shengliang Guan 已提交
85
  if (taosArrayEnsureCap(pArray, pArray->size + nEles) != 0) {
L
Liu Jicong 已提交
86 87
    return NULL;
  }
H
more  
hzcheng 已提交
88 89

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

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

S
tarray  
Shengliang Guan 已提交
96
void taosArrayRemoveDuplicate(SArray* pArray, __compar_fn_t comparFn, void (*fp)(void*)) {
97 98 99 100 101 102 103 104
  assert(pArray);

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

  int32_t pos = 0;
S
tarray  
Shengliang Guan 已提交
105
  for (int32_t i = 1; i < size; ++i) {
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    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) {
S
tarray  
Shengliang Guan 已提交
127
    for (int32_t i = pos + 1; i < pArray->size; ++i) {
128 129 130 131 132 133 134 135
      void* p = taosArrayGet(pArray, i);
      fp(p);
    }
  }

  pArray->size = pos + 1;
}

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 taosArrayRemoveDuplicateP(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 = taosArrayGetP(pArray, i);
      fp(p);
    }
  }

  pArray->size = pos + 1;
}

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

weixin_48148422's avatar
weixin_48148422 已提交
184
void* taosArrayPop(SArray* pArray) {
S
tarray  
Shengliang Guan 已提交
185
  assert(pArray != NULL);
186 187

  if (pArray->size == 0) {
weixin_48148422's avatar
weixin_48148422 已提交
188
    return NULL;
H
more  
hzcheng 已提交
189 190
  }
  pArray->size -= 1;
weixin_48148422's avatar
weixin_48148422 已提交
191
  return TARRAY_GET_ELEM(pArray, pArray->size);
H
more  
hzcheng 已提交
192 193
}

194
void* taosArrayGet(const SArray* pArray, size_t index) {
H
more  
hzcheng 已提交
195 196 197 198
  assert(index < pArray->size);
  return TARRAY_GET_ELEM(pArray, index);
}

199
void* taosArrayGetP(const SArray* pArray, size_t index) {
H
Haojun Liao 已提交
200
  assert(index < pArray->size);
S
tarray  
Shengliang Guan 已提交
201

H
Haojun Liao 已提交
202
  void* d = TARRAY_GET_ELEM(pArray, index);
S
tarray  
Shengliang Guan 已提交
203

H
Haojun Liao 已提交
204
  return *(void**)d;
H
hjxilinx 已提交
205 206
}

S
tarray  
Shengliang Guan 已提交
207
void* taosArrayGetLast(const SArray* pArray) { return TARRAY_GET_ELEM(pArray, pArray->size - 1); }
H
Haojun Liao 已提交
208

L
Liu Jicong 已提交
209
size_t taosArrayGetSize(const SArray* pArray) {
S
Shengliang Guan 已提交
210 211 212
  if (pArray == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
213
  return pArray->size;
S
Shengliang Guan 已提交
214
}
H
more  
hzcheng 已提交
215

216 217 218 219 220
void taosArraySetSize(SArray* pArray, size_t size) {
  assert(size <= pArray->capacity);
  pArray->size = size;
}

H
hjxilinx 已提交
221
void* taosArrayInsert(SArray* pArray, size_t index, void* pData) {
H
more  
hzcheng 已提交
222
  if (pArray == NULL || pData == NULL) {
H
hjxilinx 已提交
223
    return NULL;
H
more  
hzcheng 已提交
224 225 226
  }

  if (index >= pArray->size) {
H
hjxilinx 已提交
227
    return taosArrayPush(pArray, pData);
H
more  
hzcheng 已提交
228 229 230
  }

  if (pArray->size >= pArray->capacity) {
H
hjxilinx 已提交
231
    int32_t ret = taosArrayResize(pArray);
S
tarray  
Shengliang Guan 已提交
232

H
hjxilinx 已提交
233 234 235
    if (ret < 0) {
      return NULL;
    }
H
more  
hzcheng 已提交
236 237 238 239
  }

  void* dst = TARRAY_GET_ELEM(pArray, index);

S
Shengliang Guan 已提交
240 241
  int32_t remain = (int32_t)(pArray->size - index);
  memmove((char*)dst + pArray->elemSize, (char*)dst, pArray->elemSize * remain);
H
more  
hzcheng 已提交
242 243 244
  memcpy(dst, pData, pArray->elemSize);

  pArray->size += 1;
S
tarray  
Shengliang Guan 已提交
245

H
hjxilinx 已提交
246
  return dst;
H
more  
hzcheng 已提交
247 248
}

H
Hongze Cheng 已提交
249
void taosArraySet(SArray* pArray, size_t index, void* pData) {
H
refact  
Hongze Cheng 已提交
250 251 252 253
  assert(index < pArray->size);
  memcpy(TARRAY_GET_ELEM(pArray, index), pData, pArray->elemSize);
}

L
Liu Jicong 已提交
254 255 256
void taosArrayPopFrontBatch(SArray* pArray, size_t cnt) {
  assert(cnt <= pArray->size);
  pArray->size = pArray->size - cnt;
L
Liu Jicong 已提交
257
  if (pArray->size == 0 || cnt == 0) {
L
Liu Jicong 已提交
258 259
    return;
  }
L
Liu Jicong 已提交
260
  memmove(pArray->pData, (char*)pArray->pData + cnt * pArray->elemSize, pArray->size * pArray->elemSize);
L
Liu Jicong 已提交
261 262
}

L
Liu Jicong 已提交
263 264 265 266 267
void taosArrayPopTailBatch(SArray* pArray, size_t cnt) {
  assert(cnt <= pArray->size);
  pArray->size = pArray->size - cnt;
}

268 269
void taosArrayRemove(SArray* pArray, size_t index) {
  assert(index < pArray->size);
S
tarray  
Shengliang Guan 已提交
270

271 272 273 274
  if (index == pArray->size - 1) {
    taosArrayPop(pArray);
    return;
  }
S
tarray  
Shengliang Guan 已提交
275

276
  size_t remain = pArray->size - index - 1;
S
tarray  
Shengliang Guan 已提交
277 278
  memmove((char*)pArray->pData + index * pArray->elemSize, (char*)pArray->pData + (index + 1) * pArray->elemSize,
          remain * pArray->elemSize);
279 280 281
  pArray->size -= 1;
}

H
Haojun Liao 已提交
282 283 284 285 286 287 288 289
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;
290 291
}

H
Haojun Liao 已提交
292
SArray* taosArrayDup(const SArray* pSrc) {
H
hjxilinx 已提交
293
  assert(pSrc != NULL);
S
tarray  
Shengliang Guan 已提交
294 295

  if (pSrc->size == 0) {  // empty array list
H
hjxilinx 已提交
296 297
    return taosArrayInit(8, pSrc->elemSize);
  }
S
tarray  
Shengliang Guan 已提交
298

H
hjxilinx 已提交
299
  SArray* dst = taosArrayInit(pSrc->size, pSrc->elemSize);
S
tarray  
Shengliang Guan 已提交
300

H
hjxilinx 已提交
301 302 303 304 305
  memcpy(dst->pData, pSrc->pData, pSrc->elemSize * pSrc->size);
  dst->size = pSrc->size;
  return dst;
}

weixin_48148422's avatar
weixin_48148422 已提交
306
void taosArrayClear(SArray* pArray) {
S
Shengliang Guan 已提交
307
  if (pArray == NULL) return;
weixin_48148422's avatar
weixin_48148422 已提交
308 309 310
  pArray->size = 0;
}

D
dapan1121 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323 324
void taosArrayClearEx(SArray* pArray, void (*fp)(void*)) {
  if (pArray == NULL) return;
  if (fp == NULL) {
    pArray->size = 0;
    return;
  }

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

  pArray->size = 0;
}

R
root 已提交
325 326 327 328 329 330 331 332 333 334 335 336 337 338
void taosArrayClearP(SArray* pArray, FDelete fp) {
  if (pArray == NULL) return;
  if (fp == NULL) {
    pArray->size = 0;
    return;
  }

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

  pArray->size = 0;
}

H
Hongze Cheng 已提交
339 340
void* taosArrayDestroy(SArray* pArray) {
  if (pArray) {
wafwerar's avatar
wafwerar 已提交
341 342
    taosMemoryFree(pArray->pData);
    taosMemoryFree(pArray);
H
more  
hzcheng 已提交
343 344
  }

H
Hongze Cheng 已提交
345
  return NULL;
H
more  
hzcheng 已提交
346
}
weixin_48148422's avatar
weixin_48148422 已提交
347

348
void taosArrayDestroyP(SArray* pArray, FDelete fp) {
L
Liu Jicong 已提交
349 350 351 352 353
  if (pArray) {
    for (int32_t i = 0; i < pArray->size; i++) {
      fp(*(void**)TARRAY_GET_ELEM(pArray, i));
    }
    taosArrayDestroy(pArray);
354 355 356 357
  }
}

void taosArrayDestroyEx(SArray* pArray, FDelete fp) {
H
Haojun Liao 已提交
358 359 360 361
  if (pArray == NULL) {
    return;
  }

H
Haojun Liao 已提交
362
  if (fp == NULL) {
H
Haojun Liao 已提交
363 364
    taosArrayDestroy(pArray);
    return;
H
Haojun Liao 已提交
365 366
  }

S
tarray  
Shengliang Guan 已提交
367
  for (int32_t i = 0; i < pArray->size; ++i) {
H
Haojun Liao 已提交
368 369 370 371 372 373
    fp(TARRAY_GET_ELEM(pArray, i));
  }

  taosArrayDestroy(pArray);
}

374
void taosArraySort(SArray* pArray, __compar_fn_t compar) {
weixin_48148422's avatar
weixin_48148422 已提交
375 376 377
  assert(pArray != NULL);
  assert(compar != NULL);

wafwerar's avatar
wafwerar 已提交
378
  taosSort(pArray->pData, pArray->size, pArray->elemSize, compar);
weixin_48148422's avatar
weixin_48148422 已提交
379 380
}

S
tarray  
Shengliang Guan 已提交
381
void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t comparFn, int32_t flags) {
382
  assert(pArray != NULL && comparFn != NULL);
weixin_48148422's avatar
weixin_48148422 已提交
383 384
  assert(key != NULL);

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

S
tarray  
Shengliang Guan 已提交
388
int32_t taosArraySearchIdx(const SArray* pArray, const void* key, __compar_fn_t comparFn, int32_t flags) {
L
Liu Jicong 已提交
389
  void* item = taosArraySearch(pArray, key, comparFn, flags);
L
Liu Jicong 已提交
390
  return item == NULL ? -1 : (int32_t)((char*)item - (char*)pArray->pData) / pArray->elemSize;
L
Liu Jicong 已提交
391 392
}

393
void taosArraySortString(SArray* pArray, __compar_fn_t comparFn) {
weixin_48148422's avatar
weixin_48148422 已提交
394
  assert(pArray != NULL);
wafwerar's avatar
wafwerar 已提交
395
  taosSort(pArray->pData, pArray->size, pArray->elemSize, comparFn);
weixin_48148422's avatar
weixin_48148422 已提交
396 397
}

S
tarray  
Shengliang Guan 已提交
398 399
static int32_t taosArrayPartition(SArray* pArray, int32_t i, int32_t j, __ext_compar_fn_t fn, const void* userData) {
  void* key = taosArrayGetP(pArray, i);
400
  while (i < j) {
S
tarray  
Shengliang Guan 已提交
401 402 403 404 405
    while (i < j && fn(taosArrayGetP(pArray, j), key, userData) >= 0) {
      j--;
    }
    if (i < j) {
      void* a = taosArrayGetP(pArray, j);
406 407
      taosArraySet(pArray, i, &a);
    }
S
tarray  
Shengliang Guan 已提交
408 409 410
    while (i < j && fn(taosArrayGetP(pArray, i), key, userData) <= 0) {
      i++;
    }
411
    if (i < j) {
S
tarray  
Shengliang Guan 已提交
412
      void* a = taosArrayGetP(pArray, i);
413 414 415
      taosArraySet(pArray, j, &a);
    }
  }
S
tarray  
Shengliang Guan 已提交
416
  taosArraySet(pArray, i, &key);
417 418 419
  return i;
}

dengyihao's avatar
dengyihao 已提交
420
static void taosArrayQuicksortImpl(SArray* pArray, int32_t low, int32_t high, __ext_compar_fn_t fn, const void* param) {
421
  if (low < high) {
S
tarray  
Shengliang Guan 已提交
422
    int32_t idx = taosArrayPartition(pArray, low, high, fn, param);
dengyihao's avatar
dengyihao 已提交
423 424
    taosArrayQuicksortImpl(pArray, low, idx - 1, fn, param);
    taosArrayQuicksortImpl(pArray, idx + 1, high, fn, param);
S
tarray  
Shengliang Guan 已提交
425
  }
426 427
}

S
tarray  
Shengliang Guan 已提交
428
static void taosArrayQuickSort(SArray* pArray, __ext_compar_fn_t fn, const void* param) {
429
  if (pArray->size <= 1) {
430
    return;
S
tarray  
Shengliang Guan 已提交
431
  }
dengyihao's avatar
dengyihao 已提交
432
  taosArrayQuicksortImpl(pArray, 0, (int32_t)(taosArrayGetSize(pArray) - 1), fn, param);
433
}
S
tarray  
Shengliang Guan 已提交
434 435

static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void* param) {
436
  if (pArray->size <= 1) {
437
    return;
S
tarray  
Shengliang Guan 已提交
438 439 440
  }
  for (int32_t i = 1; i <= pArray->size - 1; ++i) {
    for (int32_t j = i; j > 0; --j) {
441
      if (fn(taosArrayGetP(pArray, j), taosArrayGetP(pArray, j - 1), param) == -1) {
S
tarray  
Shengliang Guan 已提交
442 443
        void* a = taosArrayGetP(pArray, j);
        void* b = taosArrayGetP(pArray, j - 1);
444 445 446 447 448 449 450
        taosArraySet(pArray, j - 1, &a);
        taosArraySet(pArray, j, &b);
      } else {
        break;
      }
    }
  }
451
  return;
S
tarray  
Shengliang Guan 已提交
452 453
}

454
SArray* taosArrayDeepCopy(const SArray* pSrc, FCopy deepCopy) {
D
dapan1121 已提交
455 456 457
  if (NULL == pSrc) {
    return NULL;
  }
L
Liu Jicong 已提交
458 459
  ASSERT(pSrc->elemSize == sizeof(void*));
  SArray* pArray = taosArrayInit(pSrc->size, sizeof(void*));
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
  for (int32_t i = 0; i < pSrc->size; i++) {
    void* clone = deepCopy(taosArrayGetP(pSrc, i));
    taosArrayPush(pArray, &clone);
  }
  return pArray;
}

int32_t taosEncodeArray(void** buf, const SArray* pArray, FEncode encode) {
  int32_t tlen = 0;
  int32_t sz = pArray->size;
  tlen += taosEncodeFixedI32(buf, sz);
  for (int32_t i = 0; i < sz; i++) {
    void* data = taosArrayGetP(pArray, i);
    tlen += encode(buf, data);
  }
  return tlen;
}

void* taosDecodeArray(const void* buf, SArray** pArray, FDecode decode, int32_t dataSz) {
  int32_t sz;
  buf = taosDecodeFixedI32(buf, &sz);
  *pArray = taosArrayInit(sz, sizeof(void*));
  for (int32_t i = 0; i < sz; i++) {
    void* data = taosMemoryCalloc(1, dataSz);
    buf = decode(buf, data);
L
Liu Jicong 已提交
485
    taosArrayPush(*pArray, &data);
486 487 488 489
  }
  return (void*)buf;
}

490
// todo remove it
S
tarray  
Shengliang Guan 已提交
491 492 493 494
// order array<type *>
void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void* param) {
  taosArrayGetSize(pArray) > 8 ? taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param);
}
L
Liu Jicong 已提交
495

dengyihao's avatar
dengyihao 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
void taosArraySwap(SArray* a, SArray* b) {
  if (a == NULL || b == NULL) return;
  size_t t = a->size;
  a->size = b->size;
  b->size = t;

  uint32_t cap = a->capacity;
  a->capacity = b->capacity;
  b->capacity = cap;

  uint32_t elem = a->elemSize;
  a->elemSize = b->elemSize;
  b->elemSize = elem;

  void* data = a->pData;
  a->pData = b->pData;
  b->pData = data;
}