/* * Copyright (c) 2019 TAOS Data, Inc. * * 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 . */ #include "indexFstUtil.h" #include "indexFstCommon.h" // A sentinel value used to indicate an empty final state const CompiledAddr EMPTY_ADDRESS = 0; /// A sentinel value used to indicate an invalid state. const CompiledAddr NONE_ADDRESS = 1; // This version number is written to every finite state transducer created by // this crate. When a finite state transducer is read, its version number is // checked against this value. const uint64_t VERSION = 3; // The threshold (in number of transitions) at which an index is created for // a node's transitions. This speeds up lookup time at the expense of FST size const uint64_t TRANS_INDEX_THRESHOLD = 32; uint8_t packSize(uint64_t n) { if (n < (1u << 8)) { return 1; } else if (n < (1u << 16)) { return 2; } else if (n < (1u << 24)) { return 3; } else if (n < ((uint64_t)(1) << 32)) { return 4; } else if (n < ((uint64_t)(1) << 40)) { return 5; } else if (n < ((uint64_t)(1) << 48)) { return 6; } else if (n < ((uint64_t)(1) << 56)) { return 7; } else { return 8; } } uint64_t unpackUint64(uint8_t* ch, uint8_t sz) { uint64_t n = 0; for (uint8_t i = 0; i < sz; i++) { // n = n | (ch[i] << (8 * i)); } return n; } uint8_t packDeltaSize(CompiledAddr nodeAddr, CompiledAddr transAddr) { if (transAddr == EMPTY_ADDRESS) { return packSize(EMPTY_ADDRESS); } else { return packSize(nodeAddr - transAddr); } } CompiledAddr unpackDelta(char* data, uint64_t len, uint64_t nodeAddr) { uint64_t delta = unpackUint64(data, len); // delta_add = u64_to_usize if (delta == EMPTY_ADDRESS) { return EMPTY_ADDRESS; } else { return nodeAddr - delta; } } // fst slice func // FstSlice fstSliceCreate(uint8_t* data, uint64_t len) { FstString* str = (FstString*)taosMemoryMalloc(sizeof(FstString)); str->ref = 1; str->len = len; str->data = taosMemoryMalloc(len * sizeof(uint8_t)); if (data != NULL) { memcpy(str->data, data, len); } FstSlice s = {.str = str, .start = 0, .end = len - 1}; return s; } // just shallow copy FstSlice fstSliceCopy(FstSlice* s, int32_t start, int32_t end) { FstString* str = s->str; atomic_add_fetch_32(&str->ref, 1); FstSlice t = {.str = str, .start = start + s->start, .end = end + s->start}; return t; } FstSlice fstSliceDeepCopy(FstSlice* s, int32_t start, int32_t end) { int32_t tlen = end - start + 1; int32_t slen; uint8_t* data = fstSliceData(s, &slen); assert(tlen <= slen); uint8_t* buf = taosMemoryMalloc(sizeof(uint8_t) * tlen); memcpy(buf, data + start, tlen); FstString* str = taosMemoryMalloc(sizeof(FstString)); str->data = buf; str->len = tlen; str->ref = 1; FstSlice ans; ans.str = str; ans.start = 0; ans.end = tlen - 1; return ans; } bool fstSliceIsEmpty(FstSlice* s) { return s->str == NULL || s->str->len == 0 || s->start < 0 || s->end < 0; } uint8_t* fstSliceData(FstSlice* s, int32_t* size) { FstString* str = s->str; if (size != NULL) { *size = s->end - s->start + 1; } return str->data + s->start; } void fstSliceDestroy(FstSlice* s) { FstString* str = s->str; int32_t ref = atomic_sub_fetch_32(&str->ref, 1); if (ref == 0) { taosMemoryFree(str->data); taosMemoryFree(str); s->str = NULL; } } int fstSliceCompare(FstSlice* a, FstSlice* b) { int32_t alen, blen; uint8_t* aBuf = fstSliceData(a, &alen); uint8_t* bBuf = fstSliceData(b, &blen); uint32_t i, j; for (i = 0, j = 0; i < alen && j < blen; i++, j++) { uint8_t x = aBuf[i]; uint8_t y = bBuf[j]; if (x == y) { continue; } else if (x < y) { return -1; } else { return 1; }; } if (i < alen) { return 1; } else if (j < blen) { return -1; } else { return 0; } } // FstStack* fstStackCreate(size_t elemSize, StackFreeElem freeFn) { // FstStack *s = taosMemoryCalloc(1, sizeof(FstStack)); // if (s == NULL) { return NULL; } // s-> // s->freeFn // //} // void *fstStackPush(FstStack *s, void *elem); // void *fstStackTop(FstStack *s); // size_t fstStackLen(FstStack *s); // void *fstStackGetAt(FstStack *s, size_t i); // void fstStackDestory(FstStack *);