Namespaced parser so it wouldn't collide with SimpleCLI
Stupid compiler. I tried this before but it didn't work because it would have the parser.c file cached without a way to clear the cache.
This commit is contained in:
parent
fc751a261f
commit
47342ea053
|
@ -9,9 +9,7 @@
|
||||||
|
|
||||||
#include <Arduino.h> // millis(), delay()
|
#include <Arduino.h> // millis(), delay()
|
||||||
|
|
||||||
extern "C" {
|
#include "parser.h" // parse_lines
|
||||||
#include "parser.h" // parse_lines
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace duckparser {
|
namespace duckparser {
|
||||||
// ====== PRIVATE ===== //
|
// ====== PRIVATE ===== //
|
||||||
|
|
|
@ -1,318 +0,0 @@
|
||||||
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */
|
|
||||||
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
#include <stdlib.h> // malloc
|
|
||||||
#include <string.h> // strlen
|
|
||||||
#include <stdbool.h> // bool
|
|
||||||
|
|
||||||
// My own implementation, because the default one in ctype.h make problems on older ESP8266 SDKs
|
|
||||||
char to_lower(char c) {
|
|
||||||
if ((c >= 65) && (c <= 90)) {
|
|
||||||
return (char)(c + 32);
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(const char* user_str, size_t user_str_len, const char* templ_str, int case_sensetive) {
|
|
||||||
if (user_str == templ_str) return COMPARE_EQUAL;
|
|
||||||
|
|
||||||
// null check string pointers
|
|
||||||
if (!user_str || !templ_str) return COMPARE_UNEQUAL;
|
|
||||||
|
|
||||||
// string lengths
|
|
||||||
size_t str_len = user_str_len; // strlen(user_str);
|
|
||||||
size_t key_len = strlen(templ_str);
|
|
||||||
|
|
||||||
// when same length, it there is no need to check for slashes or commas
|
|
||||||
if (str_len == key_len) {
|
|
||||||
for (size_t i = 0; i < key_len; i++) {
|
|
||||||
if (case_sensetive == COMPARE_CASE_SENSETIVE) {
|
|
||||||
if (user_str[i] != templ_str[i]) return COMPARE_UNEQUAL;
|
|
||||||
} else {
|
|
||||||
if (to_lower(user_str[i]) != to_lower(templ_str[i])) return COMPARE_UNEQUAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return COMPARE_EQUAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// string can't be longer than templ_str (but can be smaller because of '/' and ',')
|
|
||||||
if (str_len > key_len) return COMPARE_UNEQUAL;
|
|
||||||
|
|
||||||
unsigned int res_i = 0;
|
|
||||||
unsigned int a = 0;
|
|
||||||
unsigned int b = 0;
|
|
||||||
unsigned int res = 1;
|
|
||||||
|
|
||||||
while (a < str_len && b < key_len) {
|
|
||||||
if (templ_str[b] == '/') {
|
|
||||||
// skip slash in templ_str
|
|
||||||
++b;
|
|
||||||
} else if (templ_str[b] == ',') {
|
|
||||||
// on comma increment res_i and reset str-index
|
|
||||||
++b;
|
|
||||||
a = 0;
|
|
||||||
++res_i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compare character
|
|
||||||
if (case_sensetive == COMPARE_CASE_SENSETIVE) {
|
|
||||||
if (user_str[a] != templ_str[b]) res = 0;
|
|
||||||
} else {
|
|
||||||
if (to_lower(user_str[a]) != to_lower(templ_str[b])) res = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// comparison incorrect or string checked until the end and templ_str not checked until the end
|
|
||||||
if (!res || ((a == str_len - 1) &&
|
|
||||||
(templ_str[b + 1] != ',') &&
|
|
||||||
(templ_str[b + 1] != '/') &&
|
|
||||||
(templ_str[b + 1] != '\0'))) {
|
|
||||||
// fast forward to next comma
|
|
||||||
while (b < key_len && templ_str[b] != ',') b++;
|
|
||||||
res = 1;
|
|
||||||
} else {
|
|
||||||
// otherwise icrement indices
|
|
||||||
++a;
|
|
||||||
++b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// comparison correct AND string checked until the end AND templ_str checked until the end
|
|
||||||
if (res && (a == str_len) &&
|
|
||||||
((templ_str[b] == ',') ||
|
|
||||||
(templ_str[b] == '/') ||
|
|
||||||
(templ_str[b] == '\0'))) return COMPARE_EQUAL; // res_i
|
|
||||||
|
|
||||||
return COMPARE_UNEQUAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Word Node ===== //
|
|
||||||
word_node* word_node_create(const char* str, size_t len) {
|
|
||||||
word_node* n = (word_node*)malloc(sizeof(word_node));
|
|
||||||
|
|
||||||
n->str = str;
|
|
||||||
n->len = len;
|
|
||||||
n->next = NULL;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
word_node* word_node_destroy(word_node* n) {
|
|
||||||
if (n) {
|
|
||||||
free(n);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
word_node* word_node_destroy_rec(word_node* n) {
|
|
||||||
if (n) {
|
|
||||||
word_node_destroy_rec(n->next);
|
|
||||||
word_node_destroy(n);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Word List ===== //
|
|
||||||
word_list* word_list_create() {
|
|
||||||
word_list* l = (word_list*)malloc(sizeof(word_list));
|
|
||||||
|
|
||||||
l->first = NULL;
|
|
||||||
l->last = NULL;
|
|
||||||
l->size = 0;
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
word_list* word_list_destroy(word_list* l) {
|
|
||||||
if (l) {
|
|
||||||
word_node_destroy_rec(l->first);
|
|
||||||
free(l);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void word_list_push(word_list* l, word_node* n) {
|
|
||||||
if (l && n) {
|
|
||||||
if (l->last) {
|
|
||||||
l->last->next = n;
|
|
||||||
} else {
|
|
||||||
l->first = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
l->last = n;
|
|
||||||
++l->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
word_node* word_list_get(word_list* l, size_t i) {
|
|
||||||
if (!l) return NULL;
|
|
||||||
|
|
||||||
size_t j;
|
|
||||||
word_node* h = l->first;
|
|
||||||
|
|
||||||
for (j = 0; j < i && h; ++j) {
|
|
||||||
h = h->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Line Node ==== //
|
|
||||||
line_node* line_node_create(const char* str, size_t len) {
|
|
||||||
line_node* n = (line_node*)malloc(sizeof(line_node));
|
|
||||||
|
|
||||||
n->str = str;
|
|
||||||
n->len = len;
|
|
||||||
n->words = NULL;
|
|
||||||
n->next = NULL;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
word_node* line_node_destroy(line_node* n) {
|
|
||||||
if (n) {
|
|
||||||
word_list_destroy(n->words);
|
|
||||||
free(n);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
word_node* line_node_destroy_rec(line_node* n) {
|
|
||||||
if (n) {
|
|
||||||
line_node_destroy_rec(n->next);
|
|
||||||
line_node_destroy(n);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Line List ===== //
|
|
||||||
line_list* line_list_create() {
|
|
||||||
line_list* l = (line_list*)malloc(sizeof(line_list));
|
|
||||||
|
|
||||||
l->first = NULL;
|
|
||||||
l->last = NULL;
|
|
||||||
l->size = 0;
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
line_list* line_list_destroy(line_list* l) {
|
|
||||||
if (l) {
|
|
||||||
line_node_destroy_rec(l->first);
|
|
||||||
free(l);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void line_list_push(line_list* l, line_node* n) {
|
|
||||||
if (l && n) {
|
|
||||||
if (l->last) {
|
|
||||||
l->last->next = n;
|
|
||||||
} else {
|
|
||||||
l->first = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
l->last = n;
|
|
||||||
++l->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
line_node* line_list_get(line_list* l, size_t i) {
|
|
||||||
if (!l) return NULL;
|
|
||||||
|
|
||||||
size_t j;
|
|
||||||
line_node* h = l->first;
|
|
||||||
|
|
||||||
for (j = 0; j < i && h; ++j) {
|
|
||||||
h = h->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Parser ===== //
|
|
||||||
word_list* parse_words(const char* str, size_t len) {
|
|
||||||
word_list* l = word_list_create();
|
|
||||||
|
|
||||||
if (len == 0) return l;
|
|
||||||
|
|
||||||
// Go through string and look for space to split it into words
|
|
||||||
word_node* n = NULL;
|
|
||||||
|
|
||||||
size_t i = 0; // current index
|
|
||||||
size_t j = 0; // start index of word
|
|
||||||
|
|
||||||
int escaped = 0;
|
|
||||||
int ignore_space = 0;
|
|
||||||
|
|
||||||
for (i = 0; i <= len; ++i) {
|
|
||||||
if ((str[i] == '\\') && (escaped == 0)) {
|
|
||||||
escaped = 1;
|
|
||||||
} else if ((str[i] == '"') && (escaped == 0)) {
|
|
||||||
ignore_space = !ignore_space;
|
|
||||||
} else if ((i == len) || ((str[i] == ' ') && (ignore_space == 0) && (escaped == 0))) {
|
|
||||||
size_t k = i - j; // length of word
|
|
||||||
|
|
||||||
// for every word, add to list
|
|
||||||
if (k > 0) {
|
|
||||||
n = word_node_create(&str[j], k);
|
|
||||||
word_list_push(l, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
j = i + 1; // reset start index of word
|
|
||||||
} else if (escaped == 1) {
|
|
||||||
escaped = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
line_list* parse_lines(const char* str, size_t len) {
|
|
||||||
line_list* l = line_list_create();
|
|
||||||
|
|
||||||
if (len == 0) return l;
|
|
||||||
|
|
||||||
// Go through string and look for \r and \n to split it into lines
|
|
||||||
line_node* n = NULL;
|
|
||||||
|
|
||||||
size_t stri = 0; // current index
|
|
||||||
size_t ls = 0; // start index of line
|
|
||||||
|
|
||||||
bool escaped = false;
|
|
||||||
bool in_quotes = false;
|
|
||||||
bool delimiter = false;
|
|
||||||
bool linebreak = false;
|
|
||||||
bool endofline = false;
|
|
||||||
|
|
||||||
for (stri = 0; stri <= len; ++stri) {
|
|
||||||
char prev = stri > 0 ? str[stri-1] : 0;
|
|
||||||
char curr = str[stri];
|
|
||||||
char next = str[stri+1];
|
|
||||||
|
|
||||||
escaped = prev == '\\';
|
|
||||||
|
|
||||||
// disabled because ducky script isn't using quotes
|
|
||||||
// in_quotes = (curr == '"' && !escaped) ? !in_quotes : in_quotes;
|
|
||||||
// delimiter = !in_quotes && !escaped && curr == ';' && next == ';';
|
|
||||||
|
|
||||||
linebreak = !in_quotes && (curr == '\r' || curr == '\n');
|
|
||||||
|
|
||||||
endofline = stri == len || curr == '\0';
|
|
||||||
|
|
||||||
if (linebreak || endofline || delimiter) {
|
|
||||||
size_t llen = stri - ls; // length of line
|
|
||||||
|
|
||||||
// for every line, parse_words and add to list
|
|
||||||
//if (llen > 0) {
|
|
||||||
n = line_node_create(&str[ls], llen);
|
|
||||||
n->words = parse_words(&str[ls], llen);
|
|
||||||
line_list_push(l, n);
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (delimiter) ++stri;
|
|
||||||
|
|
||||||
ls = stri+1; // reset start index of line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
|
|
@ -0,0 +1,320 @@
|
||||||
|
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc
|
||||||
|
#include <string.h> // strlen
|
||||||
|
#include <stdbool.h> // bool
|
||||||
|
|
||||||
|
namespace duckparser {
|
||||||
|
// My own implementation, because the default one in ctype.h make problems on older ESP8266 SDKs
|
||||||
|
char to_lower(char c) {
|
||||||
|
if ((c >= 65) && (c <= 90)) {
|
||||||
|
return (char)(c + 32);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare(const char* user_str, size_t user_str_len, const char* templ_str, int case_sensetive) {
|
||||||
|
if (user_str == templ_str) return COMPARE_EQUAL;
|
||||||
|
|
||||||
|
// null check string pointers
|
||||||
|
if (!user_str || !templ_str) return COMPARE_UNEQUAL;
|
||||||
|
|
||||||
|
// string lengths
|
||||||
|
size_t str_len = user_str_len; // strlen(user_str);
|
||||||
|
size_t key_len = strlen(templ_str);
|
||||||
|
|
||||||
|
// when same length, it there is no need to check for slashes or commas
|
||||||
|
if (str_len == key_len) {
|
||||||
|
for (size_t i = 0; i < key_len; i++) {
|
||||||
|
if (case_sensetive == COMPARE_CASE_SENSETIVE) {
|
||||||
|
if (user_str[i] != templ_str[i]) return COMPARE_UNEQUAL;
|
||||||
|
} else {
|
||||||
|
if (to_lower(user_str[i]) != to_lower(templ_str[i])) return COMPARE_UNEQUAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return COMPARE_EQUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// string can't be longer than templ_str (but can be smaller because of '/' and ',')
|
||||||
|
if (str_len > key_len) return COMPARE_UNEQUAL;
|
||||||
|
|
||||||
|
unsigned int res_i = 0;
|
||||||
|
unsigned int a = 0;
|
||||||
|
unsigned int b = 0;
|
||||||
|
unsigned int res = 1;
|
||||||
|
|
||||||
|
while (a < str_len && b < key_len) {
|
||||||
|
if (templ_str[b] == '/') {
|
||||||
|
// skip slash in templ_str
|
||||||
|
++b;
|
||||||
|
} else if (templ_str[b] == ',') {
|
||||||
|
// on comma increment res_i and reset str-index
|
||||||
|
++b;
|
||||||
|
a = 0;
|
||||||
|
++res_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare character
|
||||||
|
if (case_sensetive == COMPARE_CASE_SENSETIVE) {
|
||||||
|
if (user_str[a] != templ_str[b]) res = 0;
|
||||||
|
} else {
|
||||||
|
if (to_lower(user_str[a]) != to_lower(templ_str[b])) res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparison incorrect or string checked until the end and templ_str not checked until the end
|
||||||
|
if (!res || ((a == str_len - 1) &&
|
||||||
|
(templ_str[b + 1] != ',') &&
|
||||||
|
(templ_str[b + 1] != '/') &&
|
||||||
|
(templ_str[b + 1] != '\0'))) {
|
||||||
|
// fast forward to next comma
|
||||||
|
while (b < key_len && templ_str[b] != ',') b++;
|
||||||
|
res = 1;
|
||||||
|
} else {
|
||||||
|
// otherwise icrement indices
|
||||||
|
++a;
|
||||||
|
++b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparison correct AND string checked until the end AND templ_str checked until the end
|
||||||
|
if (res && (a == str_len) &&
|
||||||
|
((templ_str[b] == ',') ||
|
||||||
|
(templ_str[b] == '/') ||
|
||||||
|
(templ_str[b] == '\0'))) return COMPARE_EQUAL; // res_i
|
||||||
|
|
||||||
|
return COMPARE_UNEQUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Word Node ===== //
|
||||||
|
word_node* word_node_create(const char* str, size_t len) {
|
||||||
|
word_node* n = (word_node*)malloc(sizeof(word_node));
|
||||||
|
|
||||||
|
n->str = str;
|
||||||
|
n->len = len;
|
||||||
|
n->next = NULL;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
word_node* word_node_destroy(word_node* n) {
|
||||||
|
if (n) {
|
||||||
|
free(n);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
word_node* word_node_destroy_rec(word_node* n) {
|
||||||
|
if (n) {
|
||||||
|
word_node_destroy_rec(n->next);
|
||||||
|
word_node_destroy(n);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Word List ===== //
|
||||||
|
word_list* word_list_create() {
|
||||||
|
word_list* l = (word_list*)malloc(sizeof(word_list));
|
||||||
|
|
||||||
|
l->first = NULL;
|
||||||
|
l->last = NULL;
|
||||||
|
l->size = 0;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
word_list* word_list_destroy(word_list* l) {
|
||||||
|
if (l) {
|
||||||
|
word_node_destroy_rec(l->first);
|
||||||
|
free(l);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void word_list_push(word_list* l, word_node* n) {
|
||||||
|
if (l && n) {
|
||||||
|
if (l->last) {
|
||||||
|
l->last->next = n;
|
||||||
|
} else {
|
||||||
|
l->first = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->last = n;
|
||||||
|
++l->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
word_node* word_list_get(word_list* l, size_t i) {
|
||||||
|
if (!l) return NULL;
|
||||||
|
|
||||||
|
size_t j;
|
||||||
|
word_node* h = l->first;
|
||||||
|
|
||||||
|
for (j = 0; j < i && h; ++j) {
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Line Node ==== //
|
||||||
|
line_node* line_node_create(const char* str, size_t len) {
|
||||||
|
line_node* n = (line_node*)malloc(sizeof(line_node));
|
||||||
|
|
||||||
|
n->str = str;
|
||||||
|
n->len = len;
|
||||||
|
n->words = NULL;
|
||||||
|
n->next = NULL;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
word_node* line_node_destroy(line_node* n) {
|
||||||
|
if (n) {
|
||||||
|
word_list_destroy(n->words);
|
||||||
|
free(n);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
word_node* line_node_destroy_rec(line_node* n) {
|
||||||
|
if (n) {
|
||||||
|
line_node_destroy_rec(n->next);
|
||||||
|
line_node_destroy(n);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Line List ===== //
|
||||||
|
line_list* line_list_create() {
|
||||||
|
line_list* l = (line_list*)malloc(sizeof(line_list));
|
||||||
|
|
||||||
|
l->first = NULL;
|
||||||
|
l->last = NULL;
|
||||||
|
l->size = 0;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_list* line_list_destroy(line_list* l) {
|
||||||
|
if (l) {
|
||||||
|
line_node_destroy_rec(l->first);
|
||||||
|
free(l);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_list_push(line_list* l, line_node* n) {
|
||||||
|
if (l && n) {
|
||||||
|
if (l->last) {
|
||||||
|
l->last->next = n;
|
||||||
|
} else {
|
||||||
|
l->first = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->last = n;
|
||||||
|
++l->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line_node* line_list_get(line_list* l, size_t i) {
|
||||||
|
if (!l) return NULL;
|
||||||
|
|
||||||
|
size_t j;
|
||||||
|
line_node* h = l->first;
|
||||||
|
|
||||||
|
for (j = 0; j < i && h; ++j) {
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Parser ===== //
|
||||||
|
word_list* parse_words(const char* str, size_t len) {
|
||||||
|
word_list* l = word_list_create();
|
||||||
|
|
||||||
|
if (len == 0) return l;
|
||||||
|
|
||||||
|
// Go through string and look for space to split it into words
|
||||||
|
word_node* n = NULL;
|
||||||
|
|
||||||
|
size_t i = 0; // current index
|
||||||
|
size_t j = 0; // start index of word
|
||||||
|
|
||||||
|
int escaped = 0;
|
||||||
|
int ignore_space = 0;
|
||||||
|
|
||||||
|
for (i = 0; i <= len; ++i) {
|
||||||
|
if ((str[i] == '\\') && (escaped == 0)) {
|
||||||
|
escaped = 1;
|
||||||
|
} else if ((str[i] == '"') && (escaped == 0)) {
|
||||||
|
ignore_space = !ignore_space;
|
||||||
|
} else if ((i == len) || ((str[i] == ' ') && (ignore_space == 0) && (escaped == 0))) {
|
||||||
|
size_t k = i - j; // length of word
|
||||||
|
|
||||||
|
// for every word, add to list
|
||||||
|
if (k > 0) {
|
||||||
|
n = word_node_create(&str[j], k);
|
||||||
|
word_list_push(l, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
j = i + 1; // reset start index of word
|
||||||
|
} else if (escaped == 1) {
|
||||||
|
escaped = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_list* parse_lines(const char* str, size_t len) {
|
||||||
|
line_list* l = line_list_create();
|
||||||
|
|
||||||
|
if (len == 0) return l;
|
||||||
|
|
||||||
|
// Go through string and look for \r and \n to split it into lines
|
||||||
|
line_node* n = NULL;
|
||||||
|
|
||||||
|
size_t stri = 0; // current index
|
||||||
|
size_t ls = 0; // start index of line
|
||||||
|
|
||||||
|
bool escaped = false;
|
||||||
|
bool in_quotes = false;
|
||||||
|
bool delimiter = false;
|
||||||
|
bool linebreak = false;
|
||||||
|
bool endofline = false;
|
||||||
|
|
||||||
|
for (stri = 0; stri <= len; ++stri) {
|
||||||
|
char prev = stri > 0 ? str[stri-1] : 0;
|
||||||
|
char curr = str[stri];
|
||||||
|
char next = str[stri+1];
|
||||||
|
|
||||||
|
escaped = prev == '\\';
|
||||||
|
|
||||||
|
// disabled because ducky script isn't using quotes
|
||||||
|
// in_quotes = (curr == '"' && !escaped) ? !in_quotes : in_quotes;
|
||||||
|
// delimiter = !in_quotes && !escaped && curr == ';' && next == ';';
|
||||||
|
|
||||||
|
linebreak = !in_quotes && (curr == '\r' || curr == '\n');
|
||||||
|
|
||||||
|
endofline = stri == len || curr == '\0';
|
||||||
|
|
||||||
|
if (linebreak || endofline || delimiter) {
|
||||||
|
size_t llen = stri - ls; // length of line
|
||||||
|
|
||||||
|
// for every line, parse_words and add to list
|
||||||
|
//if (llen > 0) {
|
||||||
|
n = line_node_create(&str[ls], llen);
|
||||||
|
n->words = parse_words(&str[ls], llen);
|
||||||
|
line_list_push(l, n);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (delimiter) ++stri;
|
||||||
|
|
||||||
|
ls = stri+1; // reset start index of line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,57 +10,59 @@
|
||||||
#define COMPARE_CASE_INSENSETIVE 0
|
#define COMPARE_CASE_INSENSETIVE 0
|
||||||
#define COMPARE_CASE_SENSETIVE 1
|
#define COMPARE_CASE_SENSETIVE 1
|
||||||
|
|
||||||
int compare(const char* user_str, size_t user_str_len, const char* templ_str, int case_sensetive);
|
namespace duckparser {
|
||||||
|
int compare(const char* user_str, size_t user_str_len, const char* templ_str, int case_sensetive);
|
||||||
|
|
||||||
typedef struct word_node {
|
typedef struct word_node {
|
||||||
const char * str;
|
const char * str;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct word_node* next;
|
struct word_node* next;
|
||||||
} word_node;
|
} word_node;
|
||||||
|
|
||||||
typedef struct word_list {
|
typedef struct word_list {
|
||||||
struct word_node* first;
|
struct word_node* first;
|
||||||
struct word_node* last;
|
struct word_node* last;
|
||||||
size_t size;
|
size_t size;
|
||||||
} word_list;
|
} word_list;
|
||||||
|
|
||||||
typedef struct line_node {
|
typedef struct line_node {
|
||||||
const char * str;
|
const char * str;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct word_list* words;
|
struct word_list* words;
|
||||||
struct line_node* next;
|
struct line_node* next;
|
||||||
} line_node;
|
} line_node;
|
||||||
|
|
||||||
typedef struct line_list {
|
typedef struct line_list {
|
||||||
struct line_node* first;
|
struct line_node* first;
|
||||||
struct line_node* last;
|
struct line_node* last;
|
||||||
size_t size;
|
size_t size;
|
||||||
} line_list;
|
} line_list;
|
||||||
|
|
||||||
// ===== Word Node ===== //
|
// ===== Word Node ===== //
|
||||||
word_node* word_node_create(const char* str, size_t len);
|
word_node* word_node_create(const char* str, size_t len);
|
||||||
word_node* word_node_destroy(word_node* n);
|
word_node* word_node_destroy(word_node* n);
|
||||||
word_node* word_node_destroy_rec(word_node* n);
|
word_node* word_node_destroy_rec(word_node* n);
|
||||||
|
|
||||||
// ===== Word List ===== //
|
// ===== Word List ===== //
|
||||||
word_list* word_list_create();
|
word_list* word_list_create();
|
||||||
word_list* word_list_destroy(word_list* l);
|
word_list* word_list_destroy(word_list* l);
|
||||||
|
|
||||||
void word_list_push(word_list* l, word_node* n);
|
void word_list_push(word_list* l, word_node* n);
|
||||||
word_node* word_list_get(word_list* l, size_t i);
|
word_node* word_list_get(word_list* l, size_t i);
|
||||||
|
|
||||||
// ===== Line Node ==== //
|
// ===== Line Node ==== //
|
||||||
line_node* line_node_create(const char* str, size_t len);
|
line_node* line_node_create(const char* str, size_t len);
|
||||||
word_node* line_node_destroy(line_node* n);
|
word_node* line_node_destroy(line_node* n);
|
||||||
word_node* line_node_destroy_rec(line_node* n);
|
word_node* line_node_destroy_rec(line_node* n);
|
||||||
|
|
||||||
// ===== Line List ===== //
|
// ===== Line List ===== //
|
||||||
line_list* line_list_create();
|
line_list* line_list_create();
|
||||||
line_list* line_list_destroy(line_list* l);
|
line_list* line_list_destroy(line_list* l);
|
||||||
|
|
||||||
void line_list_push(line_list* l, line_node* n);
|
void line_list_push(line_list* l, line_node* n);
|
||||||
line_node* line_list_get(line_list* l, size_t i);
|
line_node* line_list_get(line_list* l, size_t i);
|
||||||
|
|
||||||
// ===== Parser ===== //
|
// ===== Parser ===== //
|
||||||
word_list* parse_words(const char* str, size_t len);
|
word_list* parse_words(const char* str, size_t len);
|
||||||
line_list* parse_lines(const char* str, size_t len);
|
line_list* parse_lines(const char* str, size_t len);
|
||||||
|
}
|
Loading…
Reference in New Issue