#include "input.h" #include //Search trie, also get match length functdata* input_indexed_trie::longestPrefix(std::string key, int* len) { if (key.empty()) return nullptr; int p = 0, i = 0; functdata *r = nullptr; *len = 0; for (; i != (signed)key.length() - 1; ++i) { //std::cout<<"key["<> data) { //Sort input by strings std::sort(data.begin(), data.end(), [](std::pair a, std::pair b) {return a.first>b.first;}); for (auto i : data) { insert(i.first, i.second); } } //Clear data for key, leave extra paths void input_indexed_trie::fast_remove(std::string key) { if (key.empty()) return; int p = 0, i = 0; for (; i != (signed)key.length() - 1; ++i) { (key[i] &= 127) ? false : key[i] = 127; if (index[p][key[i]].first == 0) { return; //key is not in trie } p = index[p][key[i]].first; } //key (or a string with prefix key) is in trie delete (index[p][key[i]].second); index[p][key[i]].second = nullptr; } //NYI //Clear superfluous entries and possibly rebuild index void input_indexed_trie::reduce() { //no-op return; } //Find all (valid) terminal nodes downstream from key std::vector input_indexed_trie::allWithPrefix(std::string key) { if (key.empty()) return std::vector(); int p = 0, i = 0; for (; i != (signed)key.length() - 1; ++i) { (key[i] &= 127) ? false : key[i] = 127; if (index[p][key[i]].first == 0) { return std::vector(); //key is not in trie } p = index[p][key[i]].first; } std::vector tmp; if (index[p][key[i]].second) tmp.push_back(key); if (index[p][key[i]].first == 0) { return tmp; } p = index[p][key[i]].first; auto tmp2 = i_getNodes(p, key); tmp.insert(tmp.end(), tmp2.begin(), tmp2.end()); return tmp; } //Get descendents of node std::vector input_indexed_trie::i_getNodes(unsigned int p, std::string prefix) { //Depth-first (recursive) search std::vector retArray; for (unsigned char j = 0; j != 128; j++) { if (index[p][j].second) { //Terminal node, add to output retArray.push_back(prefix + static_cast(j)); } if (index[p][j].first) { //Node has children, recurse auto tmp = i_getNodes(index[p][j].first, prefix + static_cast(j)); retArray.insert(retArray.end(), tmp.begin(), tmp.end()); } } return retArray; } //FSM for input std::vector tokenizeInput(std::string in) { size_t word = 0; std::vector ret(1); int_fast16_t state = 1; bool inSpace = false; int_fast16_t states[10][5] = { // N, ', ", \, S, {1, 2, 3, 4, 0}, //Space {1, 2, 3, 4, 0}, //Normal {2, 1, 2, 5, 2,}, //'-quote {3, 3, 1, 6, 3,}, //"-quote {1, 1, 1, 1, 1,}, //Escape (normal) {2, 2, 2, 2, 2,}, //Escape ('-quote) {3, 3, 3, 3, 3,}, //Escape ("-quote) }; //Iterate characters and add to vector for (auto i : in) { //If we're at the end of a space-group then increase size of vector if (inSpace && (i != ' ')) { word++; ret.emplace_back(""); inSpace = false; } switch (i) { case '\'': //if in double-quote or any escape if (state == 3 || state > 3) { ret[word] += i; } state = states[state][1]; break; case '"': //if in single-quote or any escape if (state == 2 || state > 3) { ret[word] += i; } state = states[state][2]; break; case '\\': //If in an escape if (state > 3) { ret[word] += i; } state = states[state][3]; break; case ' ': //If in any kind of quote or escape if (state > 1) { ret[word] += i; } state = states[state][4]; break; default: //Always add normal characters ret[word] += i; state = states[state][0]; break; } if (!state) { inSpace = true; } } return ret; }