TDengine/source/util/src/tarray.c

532 lines
13 KiB
C
Raw Normal View History

2020-03-04 05:58:56 +00:00
/*
* 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/>.
*/
2022-02-28 02:15:07 +00:00
#define _DEFAULT_SOURCE
2020-03-04 05:58:56 +00:00
#include "tarray.h"
#include "tcoding.h"
2020-03-04 05:58:56 +00:00
// todo refactor API
SArray* taosArrayInit(size_t size, size_t elemSize) {
2023-01-24 14:54:09 +00:00
if (elemSize == 0) {
terrno = TSDB_CODE_INVALID_PARA;
return NULL;
}
2020-03-04 05:58:56 +00:00
if (size < TARRAY_MIN_SIZE) {
size = TARRAY_MIN_SIZE;
}
2022-03-25 16:29:53 +00:00
SArray* pArray = taosMemoryMalloc(sizeof(SArray));
2020-03-04 05:58:56 +00:00
if (pArray == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
2020-03-04 05:58:56 +00:00
return NULL;
}
2021-09-07 09:06:07 +00:00
pArray->size = 0;
2022-03-25 16:29:53 +00:00
pArray->pData = taosMemoryCalloc(size, elemSize);
2020-03-04 05:58:56 +00:00
if (pArray->pData == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
2022-03-25 16:29:53 +00:00
taosMemoryFree(pArray);
2020-03-04 05:58:56 +00:00
return NULL;
}
pArray->capacity = size;
pArray->elemSize = elemSize;
return pArray;
}
2023-02-20 02:12:27 +00:00
SArray* taosArrayInit_s(size_t elemSize, size_t initialSize) {
2023-01-17 01:43:33 +00:00
SArray* pArray = taosMemoryMalloc(sizeof(SArray));
if (pArray == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
2023-01-17 02:24:19 +00:00
pArray->size = initialSize;
2023-01-17 01:43:33 +00:00
pArray->pData = taosMemoryCalloc(initialSize, elemSize);
if (pArray->pData == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
taosMemoryFree(pArray);
return NULL;
}
pArray->capacity = initialSize;
pArray->elemSize = elemSize;
return pArray;
}
2020-03-08 14:19:41 +00:00
static int32_t taosArrayResize(SArray* pArray) {
2020-03-04 05:58:56 +00:00
size_t size = pArray->capacity;
size = (size << 1u);
2022-03-25 16:29:53 +00:00
void* tmp = taosMemoryRealloc(pArray->pData, size * pArray->elemSize);
2020-03-08 14:19:41 +00:00
if (tmp == NULL) { // reallocate failed, the original buffer remains
return -1;
2020-03-04 05:58:56 +00:00
}
pArray->pData = tmp;
pArray->capacity = size;
2022-02-28 02:15:07 +00:00
2020-03-08 14:32:23 +00:00
return 0;
2020-03-04 05:58:56 +00:00
}
2021-12-13 05:58:54 +00:00
int32_t taosArrayEnsureCap(SArray* pArray, size_t newCap) {
if (newCap > pArray->capacity) {
2021-01-08 10:17:37 +00:00
size_t tsize = (pArray->capacity << 1u);
2021-12-13 05:58:54 +00:00
while (newCap > tsize) {
2021-01-08 10:17:37 +00:00
tsize = (tsize << 1u);
}
2022-03-25 16:29:53 +00:00
pArray->pData = taosMemoryRealloc(pArray->pData, tsize * pArray->elemSize);
2021-01-08 10:17:37 +00:00
if (pArray->pData == NULL) {
2021-12-13 05:58:54 +00:00
return -1;
2020-03-08 14:19:41 +00:00
}
2021-01-08 10:17:37 +00:00
pArray->capacity = tsize;
2020-03-04 05:58:56 +00:00
}
2021-12-13 05:58:54 +00:00
return 0;
}
2022-02-28 02:15:07 +00:00
void* taosArrayAddBatch(SArray* pArray, const void* pData, int32_t nEles) {
2022-04-20 13:36:55 +00:00
if (pData == NULL) {
2021-12-13 05:58:54 +00:00
return NULL;
}
2022-02-28 02:15:07 +00:00
if (taosArrayEnsureCap(pArray, pArray->size + nEles) != 0) {
2021-12-13 05:58:54 +00:00
return NULL;
}
2020-03-04 05:58:56 +00:00
void* dst = TARRAY_GET_ELEM(pArray, pArray->size);
2021-01-08 10:17:37 +00:00
memcpy(dst, pData, pArray->elemSize * nEles);
2020-03-04 05:58:56 +00:00
2021-01-08 10:17:37 +00:00
pArray->size += nEles;
2020-03-04 05:58:56 +00:00
return dst;
}
2022-02-28 02:15:07 +00:00
void taosArrayRemoveDuplicate(SArray* pArray, __compar_fn_t comparFn, void (*fp)(void*)) {
size_t size = pArray->size;
if (size <= 1) {
return;
}
int32_t pos = 0;
2022-02-28 02:15:07 +00:00
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);
memset(TARRAY_GET_ELEM(pArray, i), 0, pArray->elemSize);
pos += 1;
} else {
pos += 1;
}
}
}
if (fp != NULL) {
for (int32_t i = pos + 1; i < pArray->size; ++i) {
2023-03-28 01:27:48 +00:00
void* p = taosArrayGet(pArray, i);
fp(p);
}
}
pArray->size = pos + 1;
}
2021-05-13 02:54:28 +00:00
void* taosArrayAddAll(SArray* pArray, const SArray* pInput) {
if (pInput) {
return taosArrayAddBatch(pArray, pInput->pData, (int32_t)taosArrayGetSize(pInput));
} else {
return NULL;
}
2021-05-13 02:54:28 +00:00
}
2022-11-22 02:10:23 +00:00
void* taosArrayReserve(SArray* pArray, int32_t num) {
if (taosArrayEnsureCap(pArray, pArray->size + num) != 0) {
return NULL;
}
void* dst = TARRAY_GET_ELEM(pArray, pArray->size);
pArray->size += num;
2022-11-29 07:13:19 +00:00
memset(dst, 0, num * pArray->elemSize);
2022-11-22 02:10:23 +00:00
return dst;
}
2020-04-21 11:44:17 +00:00
void* taosArrayPop(SArray* pArray) {
if (pArray->size == 0) {
2020-04-21 11:44:17 +00:00
return NULL;
2020-03-04 05:58:56 +00:00
}
2023-01-24 14:54:09 +00:00
2020-03-04 05:58:56 +00:00
pArray->size -= 1;
2020-04-21 11:44:17 +00:00
return TARRAY_GET_ELEM(pArray, pArray->size);
2020-03-04 05:58:56 +00:00
}
void* taosArrayGet(const SArray* pArray, size_t index) {
if (NULL == pArray) {
return NULL;
}
2023-01-24 14:54:09 +00:00
if (index >= pArray->size) {
2023-08-09 06:10:40 +00:00
uError("index is out of range, current:%" PRIzu " max:%d", index, pArray->capacity);
2023-01-24 14:54:09 +00:00
return NULL;
}
2020-03-04 05:58:56 +00:00
return TARRAY_GET_ELEM(pArray, index);
}
void* taosArrayGetP(const SArray* pArray, size_t index) {
2023-01-24 14:54:09 +00:00
void** p = taosArrayGet(pArray, index);
if (p == NULL) {
return NULL;
}
return *p;
2020-03-08 14:19:41 +00:00
}
2023-01-16 09:55:25 +00:00
void* taosArrayGetLast(const SArray* pArray) {
if (pArray->size == 0) {
return NULL;
}
return TARRAY_GET_ELEM(pArray, pArray->size - 1);
}
2020-11-09 08:24:25 +00:00
2022-07-01 08:25:11 +00:00
size_t taosArrayGetSize(const SArray* pArray) {
2022-02-09 10:28:11 +00:00
if (pArray == NULL) {
return 0;
}
2022-11-29 08:28:12 +00:00
return TARRAY_SIZE(pArray);
2022-02-09 10:28:11 +00:00
}
2020-03-04 05:58:56 +00:00
2023-05-17 08:46:10 +00:00
void* taosArrayInsert(SArray* pArray, size_t index, const void* pData) {
2020-03-04 05:58:56 +00:00
if (pArray == NULL || pData == NULL) {
2020-03-08 14:19:41 +00:00
return NULL;
2020-03-04 05:58:56 +00:00
}
if (index >= pArray->size) {
2020-03-08 14:19:41 +00:00
return taosArrayPush(pArray, pData);
2020-03-04 05:58:56 +00:00
}
if (pArray->size >= pArray->capacity) {
2020-03-08 14:19:41 +00:00
int32_t ret = taosArrayResize(pArray);
2022-02-28 02:15:07 +00:00
2020-03-08 14:19:41 +00:00
if (ret < 0) {
return NULL;
}
2020-03-04 05:58:56 +00:00
}
void* dst = TARRAY_GET_ELEM(pArray, index);
2020-08-03 11:12:27 +00:00
int32_t remain = (int32_t)(pArray->size - index);
memmove((char*)dst + pArray->elemSize, (char*)dst, pArray->elemSize * remain);
2020-03-04 05:58:56 +00:00
memcpy(dst, pData, pArray->elemSize);
pArray->size += 1;
2022-02-28 02:15:07 +00:00
2020-03-08 14:19:41 +00:00
return dst;
2020-03-04 05:58:56 +00:00
}
2020-12-01 10:42:07 +00:00
void taosArraySet(SArray* pArray, size_t index, void* pData) {
2023-04-27 07:33:04 +00:00
ASSERT(index < pArray->size);
2020-12-01 09:10:30 +00:00
memcpy(TARRAY_GET_ELEM(pArray, index), pData, pArray->elemSize);
}
2021-12-10 02:30:57 +00:00
void taosArrayPopFrontBatch(SArray* pArray, size_t cnt) {
2023-04-28 06:12:17 +00:00
if (cnt > pArray->size) {
cnt = pArray->size;
}
2021-12-10 02:30:57 +00:00
pArray->size = pArray->size - cnt;
2022-07-28 07:30:11 +00:00
if (pArray->size == 0 || cnt == 0) {
2021-12-10 02:30:57 +00:00
return;
}
2021-12-13 10:33:30 +00:00
memmove(pArray->pData, (char*)pArray->pData + cnt * pArray->elemSize, pArray->size * pArray->elemSize);
2021-12-10 02:30:57 +00:00
}
2021-12-11 09:17:21 +00:00
void taosArrayPopTailBatch(SArray* pArray, size_t cnt) {
2023-04-27 07:33:04 +00:00
if (cnt >= pArray->size) {
cnt = pArray->size;
}
2021-12-11 09:17:21 +00:00
pArray->size = pArray->size - cnt;
}
void taosArrayRemove(SArray* pArray, size_t index) {
2023-04-27 07:33:04 +00:00
ASSERT(index < pArray->size);
2022-02-28 02:15:07 +00:00
if (index == pArray->size - 1) {
taosArrayPop(pArray);
return;
}
2022-02-28 02:15:07 +00:00
size_t remain = pArray->size - index - 1;
2022-02-28 02:15:07 +00:00
memmove((char*)pArray->pData + index * pArray->elemSize, (char*)pArray->pData + (index + 1) * pArray->elemSize,
remain * pArray->elemSize);
pArray->size -= 1;
}
2022-11-27 07:27:37 +00:00
void taosArrayRemoveBatch(SArray* pArray, size_t index, size_t num, FDelete fp) {
ASSERT(index + num <= pArray->size);
if (fp) {
for (int32_t i = 0; i < num; i++) {
fp(taosArrayGet(pArray, index + i));
}
}
memmove((char*)pArray->pData + index * pArray->elemSize, (char*)pArray->pData + (index + num) * pArray->elemSize,
(pArray->size - index - num) * pArray->elemSize);
pArray->size -= num;
}
2021-02-03 10:29:40 +00:00
SArray* taosArrayFromList(const void* src, size_t size, size_t elemSize) {
2023-01-24 14:54:09 +00:00
if (elemSize <= 0) {
terrno = TSDB_CODE_INVALID_PARA;
return NULL;
}
2021-02-03 10:29:40 +00:00
2023-01-24 14:54:09 +00:00
SArray* pDst = taosArrayInit(size, elemSize);
2021-02-03 10:29:40 +00:00
memcpy(pDst->pData, src, elemSize * size);
pDst->size = size;
return pDst;
}
2022-11-28 08:13:18 +00:00
SArray* taosArrayDup(const SArray* pSrc, __array_item_dup_fn_t fn) {
2023-04-13 05:26:28 +00:00
if (NULL == pSrc) {
return NULL;
}
2023-08-09 06:10:40 +00:00
2023-04-13 05:26:28 +00:00
if (pSrc->size == 0) { // empty array list
2020-04-10 07:06:20 +00:00
return taosArrayInit(8, pSrc->elemSize);
}
2022-02-28 02:15:07 +00:00
2020-04-10 07:06:20 +00:00
SArray* dst = taosArrayInit(pSrc->size, pSrc->elemSize);
2022-02-28 02:15:07 +00:00
2022-11-28 08:13:18 +00:00
if (fn == NULL) {
memcpy(dst->pData, pSrc->pData, pSrc->elemSize * pSrc->size);
} else {
ASSERT(pSrc->elemSize == sizeof(void*));
2022-11-29 07:13:19 +00:00
for (int32_t i = 0; i < pSrc->size; ++i) {
2022-11-28 08:13:18 +00:00
void* p = fn(taosArrayGetP(pSrc, i));
2022-11-29 07:13:19 +00:00
memcpy(((char*)dst->pData) + i * dst->elemSize, &p, dst->elemSize);
2022-11-28 08:13:18 +00:00
}
}
2020-04-10 07:06:20 +00:00
dst->size = pSrc->size;
2022-11-28 08:13:18 +00:00
2020-04-10 07:06:20 +00:00
return dst;
}
2020-05-09 03:54:51 +00:00
void taosArrayClear(SArray* pArray) {
2022-02-09 10:28:11 +00:00
if (pArray == NULL) return;
2020-05-09 03:54:51 +00:00
pArray->size = 0;
}
2022-04-12 11:10:52 +00:00
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;
}
2023-08-09 06:10:40 +00:00
void taosArrayClearP(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));
// }
if (pArray) {
for (int32_t i = 0; i < pArray->size; i++) {
fp(*(void**)TARRAY_GET_ELEM(pArray, i));
}
}
taosArrayClear(pArray);
}
2022-04-12 11:10:52 +00:00
2021-01-07 08:31:16 +00:00
void* taosArrayDestroy(SArray* pArray) {
if (pArray) {
2022-03-25 16:29:53 +00:00
taosMemoryFree(pArray->pData);
taosMemoryFree(pArray);
2020-03-04 05:58:56 +00:00
}
2021-01-07 08:31:16 +00:00
return NULL;
2020-03-04 05:58:56 +00:00
}
2020-04-21 11:44:17 +00:00
void taosArrayDestroyP(SArray* pArray, FDelete fp) {
2022-09-16 06:36:01 +00:00
if (pArray) {
for (int32_t i = 0; i < pArray->size; i++) {
fp(*(void**)TARRAY_GET_ELEM(pArray, i));
}
taosArrayDestroy(pArray);
}
}
void taosArrayDestroyEx(SArray* pArray, FDelete fp) {
2020-11-09 12:00:28 +00:00
if (pArray == NULL) {
return;
}
2020-11-09 08:24:25 +00:00
if (fp == NULL) {
2020-11-13 03:48:53 +00:00
taosArrayDestroy(pArray);
return;
2020-11-09 08:24:25 +00:00
}
2022-02-28 02:15:07 +00:00
for (int32_t i = 0; i < pArray->size; ++i) {
2020-11-09 08:24:25 +00:00
fp(TARRAY_GET_ELEM(pArray, i));
}
taosArrayDestroy(pArray);
}
void taosArraySort(SArray* pArray, __compar_fn_t compar) {
2022-07-01 03:54:21 +00:00
taosSort(pArray->pData, pArray->size, pArray->elemSize, compar);
2020-04-21 11:44:17 +00:00
}
2022-02-28 02:15:07 +00:00
void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t comparFn, int32_t flags) {
2020-12-01 08:19:07 +00:00
return taosbsearch(key, pArray->pData, pArray->size, pArray->elemSize, comparFn, flags);
2020-04-23 07:11:44 +00:00
}
2022-02-28 02:15:07 +00:00
int32_t taosArraySearchIdx(const SArray* pArray, const void* key, __compar_fn_t comparFn, int32_t flags) {
2021-12-11 09:17:21 +00:00
void* item = taosArraySearch(pArray, key, comparFn, flags);
2022-01-11 07:40:10 +00:00
return item == NULL ? -1 : (int32_t)((char*)item - (char*)pArray->pData) / pArray->elemSize;
2021-12-11 09:17:21 +00:00
}
2022-02-28 02:15:07 +00:00
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);
while (i < j) {
2022-02-28 02:15:07 +00:00
while (i < j && fn(taosArrayGetP(pArray, j), key, userData) >= 0) {
j--;
}
if (i < j) {
void* a = taosArrayGetP(pArray, j);
taosArraySet(pArray, i, &a);
}
2022-02-28 02:15:07 +00:00
while (i < j && fn(taosArrayGetP(pArray, i), key, userData) <= 0) {
i++;
}
if (i < j) {
2022-02-28 02:15:07 +00:00
void* a = taosArrayGetP(pArray, i);
taosArraySet(pArray, j, &a);
}
}
2022-02-28 02:15:07 +00:00
taosArraySet(pArray, i, &key);
return i;
}
2022-10-08 08:36:19 +00:00
static void taosArrayQuicksortImpl(SArray* pArray, int32_t low, int32_t high, __ext_compar_fn_t fn, const void* param) {
if (low < high) {
2022-02-28 02:15:07 +00:00
int32_t idx = taosArrayPartition(pArray, low, high, fn, param);
2022-10-08 08:36:19 +00:00
taosArrayQuicksortImpl(pArray, low, idx - 1, fn, param);
taosArrayQuicksortImpl(pArray, idx + 1, high, fn, param);
2022-02-28 02:15:07 +00:00
}
}
2022-02-28 02:15:07 +00:00
static void taosArrayQuickSort(SArray* pArray, __ext_compar_fn_t fn, const void* param) {
if (pArray->size <= 1) {
return;
2022-02-28 02:15:07 +00:00
}
2022-10-08 08:36:19 +00:00
taosArrayQuicksortImpl(pArray, 0, (int32_t)(taosArrayGetSize(pArray) - 1), fn, param);
}
2022-02-28 02:15:07 +00:00
static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void* param) {
if (pArray->size <= 1) {
return;
2022-02-28 02:15:07 +00:00
}
2023-03-28 01:27:48 +00:00
2022-02-28 02:15:07 +00:00
for (int32_t i = 1; i <= pArray->size - 1; ++i) {
for (int32_t j = i; j > 0; --j) {
if (fn(taosArrayGetP(pArray, j), taosArrayGetP(pArray, j - 1), param) == -1) {
2022-02-28 02:15:07 +00:00
void* a = taosArrayGetP(pArray, j);
void* b = taosArrayGetP(pArray, j - 1);
taosArraySet(pArray, j - 1, &a);
taosArraySet(pArray, j, &b);
} else {
break;
}
}
}
2022-02-28 02:15:07 +00:00
}
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, int8_t sver) {
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, sver);
2022-04-20 13:36:55 +00:00
taosArrayPush(*pArray, &data);
}
return (void*)buf;
}
// todo remove it
2022-02-28 02:15:07 +00:00
// order array<type *>
void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void* param) {
2023-04-27 05:36:09 +00:00
taosqsort(pArray->pData, pArray->size, pArray->elemSize, param, fn);
2023-08-09 06:10:40 +00:00
// taosArrayGetSize(pArray) > 8 ? taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param);
2022-02-28 02:15:07 +00:00
}
2022-04-27 07:16:57 +00:00
2023-03-28 03:24:12 +00:00
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;
}