TDengine/source/util/src/tarray.c

518 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
SArray* taosArrayInit(size_t size, size_t elemSize) {
2020-03-04 05:58:56 +00:00
assert(elemSize > 0);
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) {
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) {
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;
}
2020-03-08 14:19:41 +00:00
static int32_t taosArrayResize(SArray* pArray) {
2020-03-04 05:58:56 +00:00
assert(pArray->size >= pArray->capacity);
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 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;
2022-02-28 02:15:07 +00:00
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;
}
2021-09-06 08:49:52 +00:00
assert(i == pData[numOfElems - 1] + 1 && i <= size);
int32_t srcIndex = pData[numOfElems - 1] + 1;
2021-09-06 08:49:52 +00:00
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));
}
pArray->size -= numOfElems;
}
2022-02-28 02:15:07 +00:00
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;
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);
pos += 1;
} else {
pos += 1;
}
}
}
if (fp != NULL) {
2022-02-28 02:15:07 +00:00
for (int32_t i = pos + 1; i < pArray->size; ++i) {
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) {
2022-02-28 02:15:07 +00:00
return taosArrayAddBatch(pArray, pInput->pData, (int32_t)taosArrayGetSize(pInput));
2021-05-13 02:54:28 +00:00
}
2020-04-21 11:44:17 +00:00
void* taosArrayPop(SArray* pArray) {
2022-02-28 02:15:07 +00:00
assert(pArray != NULL);
if (pArray->size == 0) {
2020-04-21 11:44:17 +00:00
return NULL;
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) {
2020-03-04 05:58:56 +00:00
assert(index < pArray->size);
return TARRAY_GET_ELEM(pArray, index);
}
void* taosArrayGetP(const SArray* pArray, size_t index) {
2020-06-05 08:13:14 +00:00
assert(index < pArray->size);
2022-02-28 02:15:07 +00:00
2020-06-05 08:13:14 +00:00
void* d = TARRAY_GET_ELEM(pArray, index);
2022-02-28 02:15:07 +00:00
2020-06-05 08:13:14 +00:00
return *(void**)d;
2020-03-08 14:19:41 +00:00
}
2022-02-28 02:15:07 +00:00
void* taosArrayGetLast(const SArray* pArray) { return TARRAY_GET_ELEM(pArray, pArray->size - 1); }
2020-11-09 08:24:25 +00:00
2022-02-09 10:28:11 +00:00
size_t taosArrayGetSize(const SArray* pArray) {
if (pArray == NULL) {
return 0;
}
return pArray->size;
}
2020-03-04 05:58:56 +00:00
void taosArraySetSize(SArray* pArray, size_t size) {
assert(size <= pArray->capacity);
pArray->size = size;
}
2020-03-08 14:19:41 +00:00
void* taosArrayInsert(SArray* pArray, size_t index, 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) {
2020-12-01 09:10:30 +00:00
assert(index < pArray->size);
memcpy(TARRAY_GET_ELEM(pArray, index), pData, pArray->elemSize);
}
2021-12-10 02:30:57 +00:00
void taosArrayPopFrontBatch(SArray* pArray, size_t cnt) {
assert(cnt <= pArray->size);
pArray->size = pArray->size - cnt;
2022-02-28 02:15:07 +00:00
if (pArray->size == 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) {
assert(cnt <= pArray->size);
pArray->size = pArray->size - cnt;
}
void taosArrayRemove(SArray* pArray, size_t index) {
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;
}
2021-02-03 10:29:40 +00:00
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;
}
2021-01-17 14:50:23 +00:00
SArray* taosArrayDup(const SArray* pSrc) {
2020-04-10 07:06:20 +00:00
assert(pSrc != NULL);
2022-02-28 02:15:07 +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
2020-04-10 07:06:20 +00:00
memcpy(dst->pData, pSrc->pData, pSrc->elemSize * pSrc->size);
dst->size = pSrc->size;
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;
}
2022-04-25 03:45:32 +00:00
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;
}
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) {
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) {
2020-04-21 11:44:17 +00:00
assert(pArray != NULL);
assert(compar != NULL);
qsort(pArray->pData, pArray->size, pArray->elemSize, compar);
}
2022-02-28 02:15:07 +00:00
void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t comparFn, int32_t flags) {
2020-05-23 09:34:15 +00:00
assert(pArray != NULL && comparFn != NULL);
2020-04-21 11:44:17 +00:00
assert(key != NULL);
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
}
2020-05-23 09:34:15 +00:00
void taosArraySortString(SArray* pArray, __compar_fn_t comparFn) {
2020-04-23 07:11:44 +00:00
assert(pArray != NULL);
2020-05-23 09:34:15 +00:00
qsort(pArray->pData, pArray->size, pArray->elemSize, comparFn);
2020-04-23 07:11:44 +00:00
}
2022-02-28 02:15:07 +00:00
char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t comparFn, int32_t flags) {
2020-04-23 07:11:44 +00:00
assert(pArray != NULL);
assert(key != NULL);
2020-12-01 08:19:07 +00:00
void* p = taosbsearch(&key, pArray->pData, pArray->size, pArray->elemSize, comparFn, flags);
2020-04-23 07:11:44 +00:00
if (p == NULL) {
return NULL;
}
return *(char**)p;
}
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-02-28 02:15:07 +00:00
static void taosArrayQuicksortHelper(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);
taosArrayQuicksortHelper(pArray, low, idx - 1, fn, param);
taosArrayQuicksortHelper(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
}
taosArrayQuicksortHelper(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
}
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;
}
}
}
return;
2022-02-28 02:15:07 +00:00
}
SArray* taosArrayDeepCopy(const SArray* pSrc, FCopy deepCopy) {
2022-04-20 13:36:55 +00:00
ASSERT(pSrc->elemSize == sizeof(void*));
SArray* pArray = taosArrayInit(pSrc->size, sizeof(void*));
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);
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) {
taosArrayGetSize(pArray) > 8 ? taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param);
}
// TODO(yihaoDeng) add order array<type>
2022-04-27 07:16:57 +00:00
//
char* taosShowStrArray(const SArray* pArray) {
int32_t sz = pArray->size;
int32_t tlen = 0;
for (int32_t i = 0; i < sz; i++) {
tlen += strlen(taosArrayGetP(pArray, i)) + 1;
}
char* res = taosMemoryCalloc(1, tlen);
char* buf = res;
for (int32_t i = 0; i < sz; i++) {
char* str = taosArrayGetP(pArray, i);
int32_t len = strlen(str);
memcpy(buf, str, len);
buf += len;
if (i != sz - 1) *buf = ',';
}
return res;
}