feat(shell): add port to 3.0 buld ok
This commit is contained in:
parent
d8e6fe25eb
commit
f1dd2d5675
|
@ -23,7 +23,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param);
|
||||
bool taosDestoryThread(TdThread* pthread);
|
||||
bool taosDestroyThread(TdThread* pthread);
|
||||
bool taosThreadRunning(TdThread* pthread);
|
||||
|
||||
typedef void *(*ThreadFp)(void *param);
|
||||
|
|
|
@ -31,7 +31,7 @@ TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param) {
|
|||
return pthread;
|
||||
}
|
||||
|
||||
bool taosDestoryThread(TdThread* pthread) {
|
||||
bool taosDestroyThread(TdThread* pthread) {
|
||||
if (pthread == NULL) return false;
|
||||
if (taosThreadRunning(pthread)) {
|
||||
taosThreadCancel(*pthread);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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);
|
||||
|
||||
|
||||
#endif
|
|
@ -102,6 +102,16 @@ typedef struct {
|
|||
#endif
|
||||
} 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
|
||||
int32_t shellParseArgs(int32_t argc, char* argv[]);
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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
|
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,7 @@
|
|||
|
||||
#define __USE_XOPEN
|
||||
#include "shellInt.h"
|
||||
#include "shellAuto.h"
|
||||
|
||||
#define LEFT 1
|
||||
#define RIGHT 2
|
||||
|
@ -23,20 +24,11 @@
|
|||
#define PSIZE shell.info.promptSize
|
||||
#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 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 shellInsertChar(SShellCmd *cmd, char *c, int size);
|
||||
|
||||
static void shellBackspaceChar(SShellCmd *cmd);
|
||||
static void shellClearLineBefore(SShellCmd *cmd);
|
||||
static void shellClearLineAfter(SShellCmd *cmd);
|
||||
|
@ -51,8 +43,10 @@ static void shellUpdateBuffer(SShellCmd *cmd);
|
|||
static int32_t shellIsReadyGo(SShellCmd *cmd);
|
||||
static void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width);
|
||||
static void shellResetCommand(SShellCmd *cmd, const char s[]);
|
||||
static void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
|
||||
static void shellShowOnScreen(SShellCmd *cmd);
|
||||
void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
|
||||
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) {
|
||||
uint8_t mask = 127;
|
||||
|
@ -107,8 +101,11 @@ void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) {
|
|||
/* update the values */
|
||||
cmd->commandSize += size;
|
||||
cmd->cursorOffset += size;
|
||||
cmd->screenOffset += taosWcharWidth(wc);
|
||||
cmd->endOffset += taosWcharWidth(wc);
|
||||
for (int i = 0; i < size; i++) {
|
||||
taosMbToWchar(&wc, c + i, size);
|
||||
cmd->screenOffset += taosWcharWidth(wc);
|
||||
cmd->endOffset += taosWcharWidth(wc);
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
#else
|
||||
shellShowOnScreen(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) {
|
||||
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
|
||||
|
||||
|
@ -464,7 +470,12 @@ int32_t shellReadCommand(char *command) {
|
|||
utf8_array[k] = c;
|
||||
}
|
||||
shellInsertChar(&cmd, utf8_array, count);
|
||||
pressOtherKey(c);
|
||||
} else if (c == TAB_KEY) {
|
||||
// press TAB key
|
||||
pressTabKey(&cmd);
|
||||
} else if (c < '\033') {
|
||||
pressOtherKey(c);
|
||||
// Ctrl keys. TODO: Implement ctrl combinations
|
||||
switch (c) {
|
||||
case 0:
|
||||
|
@ -519,8 +530,12 @@ int32_t shellReadCommand(char *command) {
|
|||
case 21: // Ctrl + U;
|
||||
shellClearLineBefore(&cmd);
|
||||
break;
|
||||
case 23: // Ctrl + W;
|
||||
positionCursorMiddle(&cmd);
|
||||
break;
|
||||
}
|
||||
} else if (c == '\033') {
|
||||
pressOtherKey(c);
|
||||
c = taosGetConsoleChar();
|
||||
switch (c) {
|
||||
case '[':
|
||||
|
@ -597,9 +612,11 @@ int32_t shellReadCommand(char *command) {
|
|||
break;
|
||||
}
|
||||
} else if (c == 0x7f) {
|
||||
pressOtherKey(c);
|
||||
// press delete key
|
||||
shellBackspaceChar(&cmd);
|
||||
} else {
|
||||
pressOtherKey(c);
|
||||
shellInsertChar(&cmd, &c, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define _XOPEN_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "shellInt.h"
|
||||
#include "shellAuto.h"
|
||||
|
||||
static bool shellIsEmptyCommand(const char *cmd);
|
||||
static int32_t shellRunSingleCommand(char *command);
|
||||
|
@ -193,6 +194,9 @@ void shellRunSingleCommandImp(char *command) {
|
|||
fprintf(stdout, "Database changed.\r\n\r\n");
|
||||
fflush(stdout);
|
||||
|
||||
// call back auto tab module
|
||||
callbackAutoTab(command, pSql, true);
|
||||
|
||||
taos_free_result(pSql);
|
||||
|
||||
return;
|
||||
|
@ -217,6 +221,9 @@ void shellRunSingleCommandImp(char *command) {
|
|||
taos_free_result(pSql);
|
||||
et = taosGetTimestampUs();
|
||||
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");
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#define __USE_XOPEN
|
||||
#include "shellInt.h"
|
||||
#include "shellAuto.h"
|
||||
|
||||
SShellObj shell = {0};
|
||||
|
||||
|
@ -70,5 +71,9 @@ int main(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return shellExecute();
|
||||
// support port feature
|
||||
shellAutoInit();
|
||||
int32_t ret = shellExecute();
|
||||
shellAutoExit();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* 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 "tire.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);
|
||||
}
|
Loading…
Reference in New Issue