提交 ff8e38d3 编写于 作者: H Hongze Cheng

Merge branch '3.0' of https://github.com/taosdata/TDengine into feat/alter_pages_buffer

...@@ -23,7 +23,7 @@ extern "C" { ...@@ -23,7 +23,7 @@ extern "C" {
#endif #endif
TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param); TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param);
bool taosDestoryThread(TdThread* pthread); bool taosDestroyThread(TdThread* pthread);
bool taosThreadRunning(TdThread* pthread); bool taosThreadRunning(TdThread* pthread);
typedef void *(*ThreadFp)(void *param); typedef void *(*ThreadFp)(void *param);
......
...@@ -3097,6 +3097,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) { ...@@ -3097,6 +3097,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
STagScanInfo* pInfo = pOperator->info; STagScanInfo* pInfo = pOperator->info;
SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[0]; SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[0];
SSDataBlock* pRes = pInfo->pRes; SSDataBlock* pRes = pInfo->pRes;
blockDataCleanup(pRes);
int32_t size = taosArrayGetSize(pInfo->pTableList->pTableList); int32_t size = taosArrayGetSize(pInfo->pTableList->pTableList);
if (size == 0) { if (size == 0) {
......
...@@ -584,7 +584,7 @@ int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, TSKEY ekey, int32_t ma ...@@ -584,7 +584,7 @@ int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, TSKEY ekey, int32_t ma
assert(numOfRes >= numOfRows); assert(numOfRes >= numOfRows);
} else { // reach the end of data } else { // reach the end of data
if ((ekey1 < pFillInfo->currentKey && FILL_IS_ASC_FILL(pFillInfo)) || if ((ekey1 < pFillInfo->currentKey && FILL_IS_ASC_FILL(pFillInfo)) ||
(ekey1 > pFillInfo->currentKey && !FILL_IS_ASC_FILL(pFillInfo))) { (ekey1 >= pFillInfo->currentKey && !FILL_IS_ASC_FILL(pFillInfo))) {
return 0; return 0;
} }
numOfRes = taosTimeCountInterval(ekey1, pFillInfo->currentKey, pFillInfo->interval.sliding, numOfRes = taosTimeCountInterval(ekey1, pFillInfo->currentKey, pFillInfo->interval.sliding,
......
...@@ -1251,12 +1251,12 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { ...@@ -1251,12 +1251,12 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) {
} }
} }
} else if (type == TSDB_DATA_TYPE_FLOAT) { } else if (type == TSDB_DATA_TYPE_FLOAT) {
double prev = 0; float prev = 0;
GET_TYPED_DATA(prev, double, type, &pBuf->v); GET_TYPED_DATA(prev, float, type, &pBuf->v);
double val = GET_DOUBLE_VAL(tval); float val = GET_DOUBLE_VAL(tval);
if ((prev < val) ^ isMinFunc) { if ((prev < val) ^ isMinFunc) {
*(double*)&pBuf->v = val; *(float*)&pBuf->v = val;
} }
if (pCtx->subsidiaries.num > 0) { if (pCtx->subsidiaries.num > 0) {
......
...@@ -31,7 +31,7 @@ TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param) { ...@@ -31,7 +31,7 @@ TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param) {
return pthread; return pthread;
} }
bool taosDestoryThread(TdThread* pthread) { bool taosDestroyThread(TdThread* pthread) {
if (pthread == NULL) return false; if (pthread == NULL) return false;
if (taosThreadRunning(pthread)) { if (taosThreadRunning(pthread)) {
taosThreadCancel(*pthread); taosThreadCancel(*pthread);
......
...@@ -795,12 +795,34 @@ if $data81 != 4 then ...@@ -795,12 +795,34 @@ if $data81 != 4 then
endi endi
# desc fill query # desc fill query
print asc fill query
sql select _wstart,count(*) from m_fl_tb0 where ts>='2018-9-17 9:0:0' and ts<='2018-9-17 9:11:00' interval(1m) fill(value,10) order by _wstart asc;
if $rows != 12 then
return -1
endi
if $data00 != @18-09-17 09:00:00.000@ then
return -1
endi
if $data01 != 1 then
return -1
endi
print desc fill query print desc fill query
sql select count(*) from m_fl_tb0 where ts>='2018-9-17 9:0:0' and ts<='2018-9-17 9:11:00' interval(1m) fill(value,10); sql select _wstart,count(*) from m_fl_tb0 where ts>='2018-9-17 9:0:0' and ts<='2018-9-17 9:11:00' interval(1m) fill(value,10) order by _wstart desc;
if $rows != 12 then if $rows != 12 then
return -1 return -1
endi endi
if $data00 != @18-09-17 09:11:00.000@ then
return -1
endi
if $data01 != 10 then
return -1
endi
print =====================> aggregation + arithmetic + fill, need to add cases TODO print =====================> aggregation + arithmetic + fill, need to add cases TODO
#sql select avg(cpu_taosd) - first(cpu_taosd) from dn1 where ts<'2020-11-13 11:00:00' and ts>'2020-11-13 10:50:00' interval(10s) fill(value, 99) #sql select avg(cpu_taosd) - first(cpu_taosd) from dn1 where ts<'2020-11-13 11:00:00' and ts>'2020-11-13 10:50:00' interval(10s) fill(value, 99)
#sql select count(*), first(k), avg(k), avg(k)-first(k) from tm0 where ts>'2020-1-1 1:1:1' and ts<'2020-1-1 1:02:59' interval(10s) fill(value, 99); #sql select count(*), first(k), avg(k), avg(k)-first(k) from tm0 where ts>'2020-1-1 1:1:1' and ts<'2020-1-1 1:02:59' interval(10s) fill(value, 99);
......
/*
* 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/>.
*/
#ifndef __SHELL_AUTO__
#define __SHELL_AUTO__
#define TAB_KEY 0x09
// press tab key
void pressTabKey(SShellCmd* cmd);
// press othr key
void pressOtherKey(char c);
// init shell auto funciton , shell start call once
bool shellAutoInit();
// set conn
void shellSetConn(TAOS* conn);
// exit shell auto funciton, shell exit call once
void shellAutoExit();
// callback autotab module
void callbackAutoTab(char* sqlstr, TAOS* pSql, bool usedb);
// introduction
void printfIntroduction();
#endif
...@@ -102,6 +102,16 @@ typedef struct { ...@@ -102,6 +102,16 @@ typedef struct {
#endif #endif
} SShellObj; } SShellObj;
typedef struct {
char *buffer;
char *command;
uint32_t commandSize;
uint32_t bufferSize;
uint32_t cursorOffset;
uint32_t screenOffset;
uint32_t endOffset;
} SShellCmd;
// shellArguments.c // shellArguments.c
int32_t shellParseArgs(int32_t argc, char* argv[]); int32_t shellParseArgs(int32_t argc, char* argv[]);
......
/*
* 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/>.
*/
#ifndef __TRIE__
#define __TRIE__
//
// The prefix search tree is a efficient storage words and search words tree, it support 95 visible ascii code character
//
#define FIRST_ASCII 40 // first visiable char is '0'
#define LAST_ASCII 122 // last visilbe char is 'z'
// capacity save char is 95
#define CHAR_CNT (LAST_ASCII - FIRST_ASCII + 1)
#define MAX_WORD_LEN 256 // max insert word length
// define STire
#define TIRE_TREE 0
#define TIRE_LIST 1
typedef struct STireNode {
struct STireNode** d;
bool end; // record end flag
}STireNode;
typedef struct StrName {
char * name;
struct StrName * next;
}StrName;
typedef struct STire {
char type; // see define TIRE_
STireNode root;
StrName * head;
StrName * tail;
int count; // all count
int ref;
}STire;
typedef struct SMatchNode {
char* word;
struct SMatchNode* next;
}SMatchNode;
typedef struct SMatch {
SMatchNode* head;
SMatchNode* tail; // append node to tail
int count;
char pre[MAX_WORD_LEN];
}SMatch;
// ----------- interface -------------
// create prefix search tree, return value call freeTire to free
STire* createTire(char type);
// destroy prefix search tree
void freeTire(STire* tire);
// add a new word
bool insertWord(STire* tire, char* word);
// add a new word
bool deleteWord(STire* tire, char* word);
// match prefix words, if match is not NULL , put all item to match and return match
SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match);
// get all items from tires tree
SMatch* enumAll(STire* tire);
// free match result
void freeMatch(SMatch* match);
#endif
此差异已折叠。
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define __USE_XOPEN #define __USE_XOPEN
#include "shellInt.h" #include "shellInt.h"
#include "shellAuto.h"
#define LEFT 1 #define LEFT 1
#define RIGHT 2 #define RIGHT 2
...@@ -23,20 +24,11 @@ ...@@ -23,20 +24,11 @@
#define PSIZE shell.info.promptSize #define PSIZE shell.info.promptSize
#define SHELL_INPUT_MAX_COMMAND_SIZE 10000 #define SHELL_INPUT_MAX_COMMAND_SIZE 10000
typedef struct {
char *buffer;
char *command;
uint32_t commandSize;
uint32_t bufferSize;
uint32_t cursorOffset;
uint32_t screenOffset;
uint32_t endOffset;
} SShellCmd;
static int32_t shellCountPrefixOnes(uint8_t c); static int32_t shellCountPrefixOnes(uint8_t c);
static void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
static void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width); static void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
static void shellInsertChar(SShellCmd *cmd, char *c, int size);
static void shellBackspaceChar(SShellCmd *cmd); static void shellBackspaceChar(SShellCmd *cmd);
static void shellClearLineBefore(SShellCmd *cmd); static void shellClearLineBefore(SShellCmd *cmd);
static void shellClearLineAfter(SShellCmd *cmd); static void shellClearLineAfter(SShellCmd *cmd);
...@@ -51,8 +43,10 @@ static void shellUpdateBuffer(SShellCmd *cmd); ...@@ -51,8 +43,10 @@ static void shellUpdateBuffer(SShellCmd *cmd);
static int32_t shellIsReadyGo(SShellCmd *cmd); static int32_t shellIsReadyGo(SShellCmd *cmd);
static void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width); static void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width);
static void shellResetCommand(SShellCmd *cmd, const char s[]); static void shellResetCommand(SShellCmd *cmd, const char s[]);
static void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos); void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
static void shellShowOnScreen(SShellCmd *cmd); void shellShowOnScreen(SShellCmd *cmd);
void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
void shellInsertChar(SShellCmd *cmd, char *c, int size);
int32_t shellCountPrefixOnes(uint8_t c) { int32_t shellCountPrefixOnes(uint8_t c) {
uint8_t mask = 127; uint8_t mask = 127;
...@@ -107,8 +101,11 @@ void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) { ...@@ -107,8 +101,11 @@ void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) {
/* update the values */ /* update the values */
cmd->commandSize += size; cmd->commandSize += size;
cmd->cursorOffset += size; cmd->cursorOffset += size;
cmd->screenOffset += taosWcharWidth(wc); for (int i = 0; i < size; i++) {
cmd->endOffset += taosWcharWidth(wc); taosMbToWchar(&wc, c + i, size);
cmd->screenOffset += taosWcharWidth(wc);
cmd->endOffset += taosWcharWidth(wc);
}
#ifdef WINDOWS #ifdef WINDOWS
#else #else
shellShowOnScreen(cmd); shellShowOnScreen(cmd);
...@@ -209,6 +206,15 @@ void shellPositionCursorHome(SShellCmd *cmd) { ...@@ -209,6 +206,15 @@ void shellPositionCursorHome(SShellCmd *cmd) {
} }
} }
void positionCursorMiddle(SShellCmd *cmd) {
if (cmd->endOffset > 0) {
shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE);
cmd->cursorOffset = cmd->commandSize/2;
cmd->screenOffset = cmd->endOffset/2;
shellShowOnScreen(cmd);
}
}
void shellPositionCursorEnd(SShellCmd *cmd) { void shellPositionCursorEnd(SShellCmd *cmd) {
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
...@@ -464,7 +470,12 @@ int32_t shellReadCommand(char *command) { ...@@ -464,7 +470,12 @@ int32_t shellReadCommand(char *command) {
utf8_array[k] = c; utf8_array[k] = c;
} }
shellInsertChar(&cmd, utf8_array, count); shellInsertChar(&cmd, utf8_array, count);
pressOtherKey(c);
} else if (c == TAB_KEY) {
// press TAB key
pressTabKey(&cmd);
} else if (c < '\033') { } else if (c < '\033') {
pressOtherKey(c);
// Ctrl keys. TODO: Implement ctrl combinations // Ctrl keys. TODO: Implement ctrl combinations
switch (c) { switch (c) {
case 0: case 0:
...@@ -519,8 +530,12 @@ int32_t shellReadCommand(char *command) { ...@@ -519,8 +530,12 @@ int32_t shellReadCommand(char *command) {
case 21: // Ctrl + U; case 21: // Ctrl + U;
shellClearLineBefore(&cmd); shellClearLineBefore(&cmd);
break; break;
case 23: // Ctrl + W;
positionCursorMiddle(&cmd);
break;
} }
} else if (c == '\033') { } else if (c == '\033') {
pressOtherKey(c);
c = taosGetConsoleChar(); c = taosGetConsoleChar();
switch (c) { switch (c) {
case '[': case '[':
...@@ -597,9 +612,11 @@ int32_t shellReadCommand(char *command) { ...@@ -597,9 +612,11 @@ int32_t shellReadCommand(char *command) {
break; break;
} }
} else if (c == 0x7f) { } else if (c == 0x7f) {
pressOtherKey(c);
// press delete key // press delete key
shellBackspaceChar(&cmd); shellBackspaceChar(&cmd);
} else { } else {
pressOtherKey(c);
shellInsertChar(&cmd, &c, 1); shellInsertChar(&cmd, &c, 1);
} }
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define _XOPEN_SOURCE #define _XOPEN_SOURCE
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "shellInt.h" #include "shellInt.h"
#include "shellAuto.h"
static bool shellIsEmptyCommand(const char *cmd); static bool shellIsEmptyCommand(const char *cmd);
static int32_t shellRunSingleCommand(char *command); static int32_t shellRunSingleCommand(char *command);
...@@ -193,6 +194,9 @@ void shellRunSingleCommandImp(char *command) { ...@@ -193,6 +194,9 @@ void shellRunSingleCommandImp(char *command) {
fprintf(stdout, "Database changed.\r\n\r\n"); fprintf(stdout, "Database changed.\r\n\r\n");
fflush(stdout); fflush(stdout);
// call back auto tab module
callbackAutoTab(command, pSql, true);
taos_free_result(pSql); taos_free_result(pSql);
return; return;
...@@ -217,6 +221,9 @@ void shellRunSingleCommandImp(char *command) { ...@@ -217,6 +221,9 @@ void shellRunSingleCommandImp(char *command) {
taos_free_result(pSql); taos_free_result(pSql);
et = taosGetTimestampUs(); et = taosGetTimestampUs();
printf("Query OK, %d of %d rows affected (%.6fs)\r\n", num_rows_affacted, num_rows_affacted, (et - st) / 1E6); printf("Query OK, %d of %d rows affected (%.6fs)\r\n", num_rows_affacted, num_rows_affacted, (et - st) / 1E6);
// call auto tab
callbackAutoTab(command, pSql, false);
} }
printf("\r\n"); printf("\r\n");
...@@ -1053,6 +1060,7 @@ int32_t shellExecute() { ...@@ -1053,6 +1060,7 @@ int32_t shellExecute() {
} }
#endif #endif
shellSetConn(shell.conn);
shellReadHistory(); shellReadHistory();
if (pArgs->commands != NULL || pArgs->file[0] != 0) { if (pArgs->commands != NULL || pArgs->file[0] != 0) {
...@@ -1098,6 +1106,7 @@ int32_t shellExecute() { ...@@ -1098,6 +1106,7 @@ int32_t shellExecute() {
#ifdef WEBSOCKET #ifdef WEBSOCKET
if (!shell.args.restful && !shell.args.cloud) { if (!shell.args.restful && !shell.args.cloud) {
#endif #endif
printfIntroduction();
shellGetGrantInfo(); shellGetGrantInfo();
#ifdef WEBSOCKET #ifdef WEBSOCKET
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define __USE_XOPEN #define __USE_XOPEN
#include "shellInt.h" #include "shellInt.h"
#include "shellAuto.h"
SShellObj shell = {0}; SShellObj shell = {0};
...@@ -70,5 +71,9 @@ int main(int argc, char *argv[]) { ...@@ -70,5 +71,9 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} }
return shellExecute(); // support port feature
shellAutoInit();
int32_t ret = shellExecute();
shellAutoExit();
return ret;
} }
/*
* 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/>.
*/
#define __USE_XOPEN
#include "os.h"
#include "shellTire.h"
// ----------- interface -------------
// create prefix search tree
STire* createTire(char type) {
STire* tire = taosMemoryMalloc(sizeof(STire));
memset(tire, 0, sizeof(STire));
tire->ref = 1; // init is 1
tire->type = type;
tire->root.d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *));
return tire;
}
// free tire node
void freeTireNode(STireNode* node) {
if (node == NULL)
return ;
// nest free sub node on array d
if(node->d) {
for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(node->d[i]);
}
taosMemoryFree(node->d);
}
// free self
taosMemoryFree(node);
}
// destroy prefix search tree
void freeTire(STire* tire) {
// free nodes
for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(tire->root.d[i]);
}
taosMemoryFree(tire->root.d);
// free from list
StrName * item = tire->head;
while (item) {
StrName * next = item->next;
// free string
taosMemoryFree(item->name);
// free node
taosMemoryFree(item);
// move next
item = next;
}
tire->head = tire->tail = NULL;
// free tire
taosMemoryFree(tire);
}
// insert a new word to list
bool insertToList(STire* tire, char* word) {
StrName * p = (StrName *)taosMemoryMalloc(sizeof(StrName));
p->name = strdup(word);
p->next = NULL;
if(tire->head == NULL) {
tire->head = p;
tire->tail = p;
}else {
tire->tail->next = p;
tire->tail = p;
}
return true;
}
// insert a new word to tree
bool insertToTree(STire* tire, char* word, int len) {
int m = 0;
STireNode ** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) {
return false;
}
if (nodes[m] == NULL) {
// no pointer
STireNode* p = (STireNode* )taosMemoryMalloc(sizeof(STireNode));
memset(p, 0, sizeof(STireNode));
nodes[m] = p;
if (i == len - 1) {
// is end
p->end = true;
break;
}
}
if (nodes[m]->d == NULL) {
// malloc d
nodes[m]->d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *));
}
// move to next node
nodes = nodes[m]->d;
}
// add count
tire->count += 1;
return true;
}
// insert a new word
bool insertWord(STire* tire, char* word) {
int len = strlen(word);
if (len >= MAX_WORD_LEN) {
return false;
}
switch (tire->type) {
case TIRE_TREE:
return insertToTree(tire, word, len);
case TIRE_LIST:
return insertToList(tire, word);
default:
break;
}
return false;
}
// delete one word from list
bool deleteFromList(STire* tire, char* word) {
StrName * item = tire->head;
while (item) {
if (strcmp(item->name, word) == 0) {
// found, reset empty to delete
item->name[0] = 0;
}
// move next
item = item->next;
}
return true;
}
// delete one word from tree
bool deleteFromTree(STire* tire, char* word, int len) {
int m = 0;
bool del = false;
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII;
if (m < 0 || m >= CHAR_CNT) {
return false;
}
if (nodes[m] == NULL) {
// no found
return false;
} else {
// not null
if(i == len - 1) {
// this is last, only set end false , not free node
nodes[m]->end = false;
del = true;
break;
}
}
if(nodes[m]->d == NULL)
break;
// move to next node
nodes = nodes[m]->d;
}
// reduce count
if (del) {
tire->count -= 1;
}
return del;
}
// insert a new word
bool deleteWord(STire* tire, char* word) {
int len = strlen(word);
if (len >= MAX_WORD_LEN) {
return false;
}
switch (tire->type) {
case TIRE_TREE:
return deleteFromTree(tire, word, len);
case TIRE_LIST:
return deleteFromList(tire, word);
default:
break;
}
return false;
}
void addWordToMatch(SMatch* match, char* word){
// malloc new
SMatchNode* node = (SMatchNode* )taosMemoryMalloc(sizeof(SMatchNode));
memset(node, 0, sizeof(SMatchNode));
node->word = strdup(word);
// append to match
if (match->head == NULL) {
match->head = match->tail = node;
} else {
match->tail->next = node;
match->tail = node;
}
match->count += 1;
}
// enum all words from node
void enumAllWords(STireNode** nodes, char* prefix, SMatch* match) {
STireNode * c;
char word[MAX_WORD_LEN];
int len = strlen(prefix);
for (int i = 0; i < CHAR_CNT; i++) {
c = nodes[i];
if (c == NULL) {
// chain end node
continue;
} else {
// combine word string
memset(word, 0, sizeof(word));
strcpy(word, prefix);
word[len] = FIRST_ASCII + i; // append current char
// chain middle node
if (c->end) {
// have end flag
addWordToMatch(match, word);
}
// nested call next layer
if (c->d)
enumAllWords(c->d, word, match);
}
}
}
// match prefix from list
void matchPrefixFromList(STire* tire, char* prefix, SMatch* match) {
StrName * item = tire->head;
int len = strlen(prefix);
while (item) {
if ( strncmp(item->name, prefix, len) == 0) {
// prefix matched
addWordToMatch(match, item->name);
}
// move next
item = item->next;
}
}
// match prefix words, if match is not NULL , put all item to match and return match
void matchPrefixFromTree(STire* tire, char* prefix, SMatch* match) {
SMatch* root = match;
int m = 0;
STireNode* c = 0;
int len = strlen(prefix);
if (len >= MAX_WORD_LEN) {
return;
}
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = prefix[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) {
return;
}
// match
c = nodes[m];
if (c == NULL) {
// arrive end
break;
}
// previous items already matched
if (i == len - 1) {
// malloc match if not pass by param match
if (root == NULL) {
root = (SMatch* )taosMemoryMalloc(sizeof(SMatch));
memset(root, 0, sizeof(SMatch));
strcpy(root->pre, prefix);
}
// prefix is match to end char
if (c->d)
enumAllWords(c->d, prefix, root);
} else {
// move to next node continue match
if(c->d == NULL)
break;
nodes = c->d;
}
}
// return
return ;
}
SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match) {
if(match == NULL) {
match = (SMatch* )taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch));
}
switch (tire->type) {
case TIRE_TREE:
matchPrefixFromTree(tire, prefix, match);
case TIRE_LIST:
matchPrefixFromList(tire, prefix, match);
default:
break;
}
// return if need
if (match->count == 0) {
freeMatch(match);
match = NULL;
}
return match;
}
// get all items from tires tree
void enumFromList(STire* tire, SMatch* match) {
StrName * item = tire->head;
while (item) {
if (item->name[0] != 0) {
// not delete
addWordToMatch(match, item->name);
}
// move next
item = item->next;
}
}
// get all items from tires tree
void enumFromTree(STire* tire, SMatch* match) {
char pre[2] ={0, 0};
STireNode* c;
// enum first layer
for (int i = 0; i < CHAR_CNT; i++) {
pre[0] = FIRST_ASCII + i;
// each node
c = tire->root.d[i];
if (c == NULL) {
// this branch no data
continue;
}
// this branch have data
if(c->end)
addWordToMatch(match, pre);
else
matchPrefix(tire, pre, match);
}
}
// get all items from tires tree
SMatch* enumAll(STire* tire) {
SMatch* match = (SMatch* )taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch));
switch (tire->type) {
case TIRE_TREE:
enumFromTree(tire, match);
case TIRE_LIST:
enumFromList(tire, match);
default:
break;
}
// return if need
if (match->count == 0) {
freeMatch(match);
match = NULL;
}
return match;
}
// free match result
void freeMatchNode(SMatchNode* node) {
// first free next
if (node->next)
freeMatchNode(node->next);
// second free self
if (node->word)
taosMemoryFree(node->word);
taosMemoryFree(node);
}
// free match result
void freeMatch(SMatch* match) {
// first free next
if (match->head) {
freeMatchNode(match->head);
}
// second free self
taosMemoryFree(match);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册