Merge pull request #17235 from taosdata/feat/TD-17777-V30

feat(shell): Supported the word completed by press Tab key for 3.0
This commit is contained in:
Shengliang Guan 2022-10-09 17:01:56 +08:00 committed by GitHub
commit 1c106bfd1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 873 additions and 1032 deletions

View File

@ -24,7 +24,7 @@ void pressTabKey(SShellCmd* cmd);
// press othr key // press othr key
void pressOtherKey(char c); void pressOtherKey(char c);
// init shell auto funciton , shell start call once // init shell auto funciton , shell start call once
bool shellAutoInit(); bool shellAutoInit();
// set conn // set conn

View File

@ -16,68 +16,65 @@
#ifndef __TRIE__ #ifndef __TRIE__
#define __TRIE__ #define __TRIE__
// //
// The prefix search tree is a efficient storage words and search words tree, it support 95 visible ascii code character // 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 FIRST_ASCII 40 // first visiable char is '0'
#define LAST_ASCII 122 // last visilbe char is 'z' #define LAST_ASCII 122 // last visilbe char is 'z'
// capacity save char is 95 // capacity save char is 95
#define CHAR_CNT (LAST_ASCII - FIRST_ASCII + 1) #define CHAR_CNT (LAST_ASCII - FIRST_ASCII + 1)
#define MAX_WORD_LEN 256 // max insert word length #define MAX_WORD_LEN 256 // max insert word length
// define STire // define STire
#define TIRE_TREE 0 #define TIRE_TREE 0
#define TIRE_LIST 1 #define TIRE_LIST 1
typedef struct STireNode { typedef struct STireNode {
struct STireNode** d; struct STireNode** d;
bool end; // record end flag bool end; // record end flag
}STireNode; } STireNode;
typedef struct StrName { typedef struct StrName {
char * name; char* name;
struct StrName * next; struct StrName* next;
}StrName; } StrName;
typedef struct STire { typedef struct STire {
char type; // see define TIRE_ char type; // see define TIRE_
STireNode root; STireNode root;
StrName * head; StrName* head;
StrName * tail; StrName* tail;
int count; // all count int count; // all count
int ref; int ref;
}STire; } STire;
typedef struct SMatchNode { typedef struct SMatchNode {
char* word; char* word;
struct SMatchNode* next; struct SMatchNode* next;
}SMatchNode; } SMatchNode;
typedef struct SMatch { typedef struct SMatch {
SMatchNode* head; SMatchNode* head;
SMatchNode* tail; // append node to tail SMatchNode* tail; // append node to tail
int count; int count;
char pre[MAX_WORD_LEN]; char pre[MAX_WORD_LEN];
}SMatch; } SMatch;
// ----------- interface ------------- // ----------- interface -------------
// create prefix search tree, return value call freeTire to free // create prefix search tree, return value call freeTire to free
STire* createTire(char type); STire* createTire(char type);
// destroy prefix search tree // destroy prefix search tree
void freeTire(STire* tire); void freeTire(STire* tire);
// add a new word // add a new word
bool insertWord(STire* tire, char* word); bool insertWord(STire* tire, char* word);
// add a new word // add a new word
bool deleteWord(STire* tire, char* word); bool deleteWord(STire* tire, char* word);
// match prefix words, if match is not NULL , put all item to match and return match // match prefix words, if match is not NULL , put all item to match and return match

File diff suppressed because it is too large Load Diff

View File

@ -22,414 +22,405 @@
// create prefix search tree // create prefix search tree
STire* createTire(char type) { STire* createTire(char type) {
STire* tire = taosMemoryMalloc(sizeof(STire)); STire* tire = taosMemoryMalloc(sizeof(STire));
memset(tire, 0, sizeof(STire)); memset(tire, 0, sizeof(STire));
tire->ref = 1; // init is 1 tire->ref = 1; // init is 1
tire->type = type; tire->type = type;
tire->root.d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *)); tire->root.d = (STireNode**)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode*));
return tire; return tire;
} }
// free tire node // free tire node
void freeTireNode(STireNode* node) { void freeTireNode(STireNode* node) {
if (node == NULL) if (node == NULL) return;
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 // nest free sub node on array d
taosMemoryFree(node); 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 // destroy prefix search tree
void freeTire(STire* tire) { void freeTire(STire* tire) {
// free nodes // free nodes
for (int i = 0; i < CHAR_CNT; i++) { for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(tire->root.d[i]); freeTireNode(tire->root.d[i]);
} }
taosMemoryFree(tire->root.d); taosMemoryFree(tire->root.d);
// free from list // free from list
StrName * item = tire->head; StrName* item = tire->head;
while (item) { while (item) {
StrName * next = item->next; StrName* next = item->next;
// free string // free string
taosMemoryFree(item->name); taosMemoryFree(item->name);
// free node // free node
taosMemoryFree(item); taosMemoryFree(item);
// move next // move next
item = next; item = next;
} }
tire->head = tire->tail = NULL; tire->head = tire->tail = NULL;
// free tire // free tire
taosMemoryFree(tire); taosMemoryFree(tire);
} }
// insert a new word to list // insert a new word to list
bool insertToList(STire* tire, char* word) { bool insertToList(STire* tire, char* word) {
StrName * p = (StrName *)taosMemoryMalloc(sizeof(StrName)); StrName* p = (StrName*)taosMemoryMalloc(sizeof(StrName));
p->name = strdup(word); p->name = strdup(word);
p->next = NULL; p->next = NULL;
if(tire->head == NULL) {
tire->head = p;
tire->tail = p;
}else {
tire->tail->next = p;
tire->tail = p;
}
return true; 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 // insert a new word to tree
bool insertToTree(STire* tire, char* word, int len) { bool insertToTree(STire* tire, char* word, int len) {
int m = 0; int m = 0;
STireNode ** nodes = tire->root.d; STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII; m = word[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) { if (m < 0 || m > CHAR_CNT) {
return false; 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 if (nodes[m] == NULL) {
tire->count += 1; // no pointer
return true; 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 // insert a new word
bool insertWord(STire* tire, char* word) { bool insertWord(STire* tire, char* word) {
int len = strlen(word); int len = strlen(word);
if (len >= MAX_WORD_LEN) { 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; 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 // delete one word from list
bool deleteFromList(STire* tire, char* word) { bool deleteFromList(STire* tire, char* word) {
StrName * item = tire->head; StrName* item = tire->head;
while (item) { while (item) {
if (strcmp(item->name, word) == 0) { if (strcmp(item->name, word) == 0) {
// found, reset empty to delete // found, reset empty to delete
item->name[0] = 0; item->name[0] = 0;
}
// move next
item = item->next;
} }
return true;
// move next
item = item->next;
}
return true;
} }
// delete one word from tree // delete one word from tree
bool deleteFromTree(STire* tire, char* word, int len) { bool deleteFromTree(STire* tire, char* word, int len) {
int m = 0; int m = 0;
bool del = false; bool del = false;
STireNode** nodes = tire->root.d; STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII; m = word[i] - FIRST_ASCII;
if (m < 0 || m >= CHAR_CNT) { if (m < 0 || m >= CHAR_CNT) {
return false; 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 (nodes[m] == NULL) {
if (del) { // no found
tire->count -= 1; return false;
}
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 { } else {
match->tail->next = node; // not null
match->tail = node; if (i == len - 1) {
// this is last, only set end false , not free node
nodes[m]->end = false;
del = true;
break;
}
} }
match->count += 1;
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 // enum all words from node
void enumAllWords(STireNode** nodes, char* prefix, SMatch* match) { void enumAllWords(STireNode** nodes, char* prefix, SMatch* match) {
STireNode * c; STireNode* c;
char word[MAX_WORD_LEN]; char word[MAX_WORD_LEN];
int len = strlen(prefix); int len = strlen(prefix);
for (int i = 0; i < CHAR_CNT; i++) { for (int i = 0; i < CHAR_CNT; i++) {
c = nodes[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 == NULL) {
if (c->end) { // chain end node
// have end flag continue;
addWordToMatch(match, word); } else {
} // combine word string
// nested call next layer memset(word, 0, sizeof(word));
if (c->d) strcpy(word, prefix);
enumAllWords(c->d, word, match); 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 // match prefix from list
void matchPrefixFromList(STire* tire, char* prefix, SMatch* match) { void matchPrefixFromList(STire* tire, char* prefix, SMatch* match) {
StrName * item = tire->head; StrName* item = tire->head;
int len = strlen(prefix); int len = strlen(prefix);
while (item) { while (item) {
if ( strncmp(item->name, prefix, len) == 0) { if (strncmp(item->name, prefix, len) == 0) {
// prefix matched // prefix matched
addWordToMatch(match, item->name); addWordToMatch(match, item->name);
}
// move next
item = item->next;
} }
// move next
item = item->next;
}
} }
// match prefix words, if match is not NULL , put all item to match and return match // match prefix words, if match is not NULL , put all item to match and return match
void matchPrefixFromTree(STire* tire, char* prefix, SMatch* match) { void matchPrefixFromTree(STire* tire, char* prefix, SMatch* match) {
SMatch* root = match; SMatch* root = match;
int m = 0; int m = 0;
STireNode* c = 0; STireNode* c = 0;
int len = strlen(prefix); int len = strlen(prefix);
if (len >= MAX_WORD_LEN) { if (len >= MAX_WORD_LEN) {
return; 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;
} }
STireNode** nodes = tire->root.d; // match
for (int i = 0; i < len; i++) { c = nodes[m];
m = prefix[i] - FIRST_ASCII; if (c == NULL) {
if (m < 0 || m > CHAR_CNT) { // arrive end
return; break;
}
// 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 // previous items already matched
return ; 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) { SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match) {
if(match == NULL) { if (match == NULL) {
match = (SMatch* )taosMemoryMalloc(sizeof(SMatch)); match = (SMatch*)taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch)); memset(match, 0, sizeof(SMatch));
} }
switch (tire->type) { switch (tire->type) {
case TIRE_TREE: case TIRE_TREE:
matchPrefixFromTree(tire, prefix, match); matchPrefixFromTree(tire, prefix, match);
case TIRE_LIST: case TIRE_LIST:
matchPrefixFromList(tire, prefix, match); matchPrefixFromList(tire, prefix, match);
default: default:
break; break;
} }
// return if need // return if need
if (match->count == 0) { if (match->count == 0) {
freeMatch(match); freeMatch(match);
match = NULL; match = NULL;
} }
return match; return match;
} }
// get all items from tires tree // get all items from tires tree
void enumFromList(STire* tire, SMatch* match) { void enumFromList(STire* tire, SMatch* match) {
StrName * item = tire->head; StrName* item = tire->head;
while (item) { while (item) {
if (item->name[0] != 0) { if (item->name[0] != 0) {
// not delete // not delete
addWordToMatch(match, item->name); addWordToMatch(match, item->name);
}
// move next
item = item->next;
} }
// move next
item = item->next;
}
} }
// get all items from tires tree // get all items from tires tree
void enumFromTree(STire* tire, SMatch* match) { void enumFromTree(STire* tire, SMatch* match) {
char pre[2] ={0, 0}; char pre[2] = {0, 0};
STireNode* c; 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 // enum first layer
if(c->end) for (int i = 0; i < CHAR_CNT; i++) {
addWordToMatch(match, pre); pre[0] = FIRST_ASCII + i;
else
matchPrefix(tire, pre, match); // 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 // get all items from tires tree
SMatch* enumAll(STire* tire) { SMatch* enumAll(STire* tire) {
SMatch* match = (SMatch* )taosMemoryMalloc(sizeof(SMatch)); SMatch* match = (SMatch*)taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch)); memset(match, 0, sizeof(SMatch));
switch (tire->type) { switch (tire->type) {
case TIRE_TREE: case TIRE_TREE:
enumFromTree(tire, match); enumFromTree(tire, match);
case TIRE_LIST: case TIRE_LIST:
enumFromList(tire, match); enumFromList(tire, match);
default: default:
break; break;
} }
// return if need // return if need
if (match->count == 0) { if (match->count == 0) {
freeMatch(match); freeMatch(match);
match = NULL; match = NULL;
} }
return match; return match;
} }
// free match result // free match result
void freeMatchNode(SMatchNode* node) { void freeMatchNode(SMatchNode* node) {
// first free next // first free next
if (node->next) if (node->next) freeMatchNode(node->next);
freeMatchNode(node->next);
// second free self // second free self
if (node->word) if (node->word) taosMemoryFree(node->word);
taosMemoryFree(node->word); taosMemoryFree(node);
taosMemoryFree(node);
} }
// free match result // free match result
void freeMatch(SMatch* match) { void freeMatch(SMatch* match) {
// first free next // first free next
if (match->head) { if (match->head) {
freeMatchNode(match->head); freeMatchNode(match->head);
} }
// second free self // second free self
taosMemoryFree(match); taosMemoryFree(match);
} }