#define MAX_KEY_LENGTH 15
#define MAX_VALUE_LENGTH 127
#define MAX_MESSAGE_LENGTH 81920

#define SIZE 400

int tree[400][400]; //使用邻接矩阵代表树

typedef struct entity{
int type;
int KeyLenH;
int KeyLenL;
int ValLenH;
int ValLenL;
char KeyStr[16];
char ValStr[128];
} entity;

entity pool[SIZE]; //使用数组存储所有的entity
int NumOfEntity;

entity * getNewNode(){ //得到新的节点,并初始化为0
pool[NumOfEntity].type = 0;
pool[NumOfEntity].KeyLenH = 0;
pool[NumOfEntity].KeyLenL = 0;
pool[NumOfEntity].ValLenH = 0;
pool[NumOfEntity].ValLenL = 0;
for(int i = 0; i < 16; i++) {
pool[NumOfEntity].KeyStr[i] = 0;
}

for(int i = 0; i < 128; i++) {
pool[NumOfEntity].ValStr[i] = 0;
}
return &pool[NumOfEntity++];
}

char inputStr[MAX_MESSAGE_LENGTH];
int curPos;

void init(char in[], int len){ //保存input字符串,并将所有全局变量初始化为0
NumOfEntity = 0;
curPos = 0;

for(int i = 0; i < SIZE; i++){
inputStr[i] = in[i];
}
inputStr[len] = 0;

for(int i = 0; i < SIZE; i++){
tree[i][0] = 0;
}
}

void buildTree(int father){ //将输入数组展开成一棵树, 参数father是当前的父节点
//现将固定的信息保存起来,如type,key长度,key值,以及val的长度
int type = inputStr[curPos++];
int index = NumOfEntity;
entity * newNode = getNewNode();
newNode->type = type;
newNode->KeyLenH = inputStr[curPos++];
newNode->KeyLenL = inputStr[curPos++];
int keyLen = newNode->KeyLenH * 256 + newNode->KeyLenL;
for(int i = 0; i < keyLen; i++){
newNode->KeyStr[i] = inputStr[curPos++];
}

newNode->ValLenH = inputStr[curPos++];
newNode->ValLenL = inputStr[curPos++];
int ValLen = newNode->ValLenH * 256 + newNode->ValLenL;

//根据不同情况处理Val:
if(type == 1){ //如果是type1,直接copy string
for(int i = 0; i < ValLen; i++){
newNode->ValStr[i] = inputStr[curPos++];
}

if(father != -1){ //将此节点加入邻接矩阵,根节点没有父亲,所以不需要对根节点进行此操作
tree[father][0]++;
tree[father][tree[father][0]] = index;
}
}
if(type == 2){ //如果是type2,将其所有的子节点都buildTree
for(int i = 0; i < ValLen; i++){
buildTree(index);
}
if(father != -1){ //将此节点加入邻接矩阵,根节点没有父亲,所以不需要对根节点进行此操作
tree[father][0]++;
tree[father][tree[father][0]] = index;
}
}
}

void parse(char in[MAX_MESSAGE_LENGTH], int size){
init(in, size); //在parse的时候进行初始化
buildTree(-1); //将输入字符串展开为一棵树
}


bool isSame(char str1[], char str2[]){ //判断字符串是否想同
int i = 0;
for(i = 0; str1[i] && str2[i]; i++){
if(str1[i] != str2[i]) return false;
}
if(str1[i] || str2[i]) return false;
return true;
}

int getIndex(char str[]){ //搜索整个pool,找到指定key的节点
for(int i = 0; i < NumOfEntity; i++){
if(isSame(pool[i].KeyStr, str)){
return i;
}
}
}

void set(char targetkey[MAX_KEY_LENGTH + 1], char newvalue[MAX_VALUE_LENGTH + 1]){
int index = getIndex(targetkey); //找到目标节点的index
int i = 0;
for(i = 0; i < newvalue[i]; i++){ //修改其ValStr
pool[index].ValStr[i] = newvalue[i];
}
pool[index].ValStr[i] = 0; //修改Val长度
pool[index].ValLenH = i/256;
pool[index].ValLenL = i%256;
}

int getLen(char str[]){ //计算字符串长度
int i = 0;
for(i = 0; str[i]; i++){
;
}
return i;
}

void add(char parentkey[MAX_KEY_LENGTH + 1], char childkey[MAX_KEY_LENGTH + 1], char childvalue[MAX_VALUE_LENGTH + 1]){
int father = getIndex(parentkey); //得到父亲的index
int child = NumOfEntity; //孩子是新创建的,所以index是NumOfEntity
entity * newNode = getNewNode();

//将所有信息赋值给孩子
newNode->type = 1;
int KeyLen = getLen(childkey);
int ValLen = getLen(childvalue);
newNode->KeyLenH = KeyLen/256;
newNode->KeyLenL = KeyLen%256;
for(int i = 0; i < KeyLen; i++){
newNode->KeyStr[i] = childkey[i];
}

newNode->ValLenH = ValLen/256;
newNode->ValLenL = ValLen%256;

for(int i = 0; i < ValLen; i++){
newNode->ValStr[i] = childvalue[i];
}

//更新父亲相关的信息:树结构,父亲的Val长度
tree[father][0]++;
tree[father][tree[father][0]] = child;
pool[father].ValLenL++;
}
void erase(char targetkey[MAX_KEY_LENGTH + 1]){
int child = getIndex(targetkey); //找到孩子的index
//找到父亲的index
int father = -1;
int pos = 0;
for(int i = 0; i < NumOfEntity; i++){
int N = tree[i][0];
for(int j = 1; j <= N; j++){
if(tree[i][j] == child){
father = i;
pos = j;
goto deleteNode;
}
}
}
deleteNode:
//在邻接矩阵中,在代表父亲的一行中,将孩子的index去掉,并更新tree和父亲节点的信息
int N = tree[father][0];
for(int i = pos + 1; i <= N; i++){
tree[father][i - 1] = tree[father][i];
}
tree[father][0]--;
pool[father].ValLenL--;
}

int outPos; //统计输出长度
void compress(int index, char out[]){
//保存固定信息: 类型、key长度、key值、val长度
entity * node = &pool[index];
out[outPos++] = node->type;
out[outPos++] = node->KeyLenH;
out[outPos++] = node->KeyLenL;
int KeyLen = node->KeyLenH * 256 + node->KeyLenL;
for(int i = 0; i < KeyLen; i++){
out[outPos++] = node->KeyStr[i];
}
out[outPos++] = node->ValLenH;
out[outPos++] = node->ValLenL;
int ValLen = node->ValLenH * 256 + node->ValLenL;

//根据不同的type,处理val
if(node->type == 1){//如果是type1, 直接进行string copy
for(int i = 0; i < ValLen; i++){
out[outPos++] = node->ValStr[i];
}
}
if(node->type == 2){ //如果是type2, 压缩其所有孩子
int N = tree[index][0];
for(int i = 1; i <= N; i++){
compress(tree[index][i], out);
}
}
}

int generate(char targekey[MAX_KEY_LENGTH + 1], char out[MAX_MESSAGE_LENGTH]){
outPos = 0;
int index = getIndex(targekey); //找到目标节点
compress(index, out); //将树压缩成输入字符串
return outPos;
}