aboutsummaryrefslogtreecommitdiff
path: root/deps/sysobj_early/src
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-11-01 12:15:13 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-11-13 14:11:23 -0800
commit0830d5ca73ee0e198a4efdc18336fd8afb508f02 (patch)
treedb60f72f1135790e8e2c62df6d52f0da3148b17b /deps/sysobj_early/src
parentc6073b029a271eb623d156d834d24781ae636f31 (diff)
util_ids: fix, update
Fixes https://github.com/lpereira/hardinfo/issues/476 Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'deps/sysobj_early/src')
-rw-r--r--deps/sysobj_early/src/util_ids.c153
1 files changed, 139 insertions, 14 deletions
diff --git a/deps/sysobj_early/src/util_ids.c b/deps/sysobj_early/src/util_ids.c
index 00ff63c5..b24dba59 100644
--- a/deps/sysobj_early/src/util_ids.c
+++ b/deps/sysobj_early/src/util_ids.c
@@ -25,6 +25,9 @@
#include <ctype.h>
#define ids_msg(msg, ...) fprintf (stderr, "[%s] " msg "\n", __FUNCTION__, ##__VA_ARGS__) /**/
+static int ids_tracing = 0;
+void ids_trace_start() { ids_tracing = 1; }
+void ids_trace_stop() { ids_tracing = 0; }
ids_query *ids_query_new(const gchar *qpath) {
ids_query *s = g_new0(ids_query, 1);
@@ -37,6 +40,13 @@ void ids_query_free(ids_query *s) {
g_free(s);
}
+void ids_query_result_cpy(ids_query_result *dest, ids_query_result *src) {
+ if (!dest || !src) return;
+ memcpy(dest, src, sizeof(ids_query_result));
+ for(int i = 0; dest->results[i]; i++)
+ dest->results[i] = dest->_strs + (src->results[i] - src->_strs);
+}
+
/* c001 < C 01 */
//TODO: compare more than the first char
static int ids_cmp(const char *s1, const char *s2) {
@@ -49,6 +59,23 @@ static int ids_cmp(const char *s1, const char *s2) {
return cmp;
}
+static void ids_query_result_set_str(ids_query_result *ret, int tabs, gchar *p) {
+ if (!p) {
+ ret->results[tabs] = p;
+ } else {
+ if (tabs == 0) {
+ ret->results[tabs] = ret->_strs;
+ strncpy(ret->results[tabs], p, IDS_LOOKUP_BUFF_SIZE-1);
+ } else {
+ ret->results[tabs] = ret->results[tabs-1] + strlen(ret->results[tabs-1]) + 1;
+ strncpy(ret->results[tabs], p, IDS_LOOKUP_BUFF_SIZE-1);
+ }
+ }
+ /* all following strings become invalid */
+ while(tabs < IDS_LOOKUP_MAX_DEPTH)
+ ret->results[++tabs] = NULL;
+}
+
/* Given a qpath "/X/Y/Z", find names as:
* X <name> ->result[0]
* \tY <name> ->result[1]
@@ -59,6 +86,7 @@ static int ids_cmp(const char *s1, const char *s2) {
* - arm.ids "<implementer>/<part>"
* - sdio.ids "<vendor>/<device>", "C <class>"
* - usb.ids "<vendor>/<device>", "C <class>" etc
+ * - edid.ids "<3letter_vendor>"
*/
long scan_ids_file(const gchar *file, const gchar *qpath, ids_query_result *result, long start_offset) {
gchar **qparts = NULL;
@@ -119,8 +147,10 @@ long scan_ids_file(const gchar *file, const gchar *qpath, ids_query_result *resu
if (tabs >= qdepth) continue; /* too deep */
if (tabs != 0 && !ret.results[tabs-1])
continue; /* not looking at this depth, yet */
+ if (ret.results[tabs])
+ goto ids_lookup_done; /* answered at this level */
- //ids_msg("looking at (%d) %s...", tabs, p);
+ if (ids_tracing) ids_msg("[%s] looking at (%d) %s...", file, tabs, p);
if (g_str_has_prefix(p, qparts[tabs])
&& isspace(*(p + qpartlen[tabs])) ) {
@@ -128,33 +158,34 @@ long scan_ids_file(const gchar *file, const gchar *qpath, ids_query_result *resu
p += qpartlen[tabs];
while(isspace((unsigned char)*p)) p++; /* ffwd */
- if (tabs == 0) {
- last_root_fpos = fpos;
- ret.results[tabs] = ret._strs;
- strncpy(ret.results[tabs], p, IDS_LOOKUP_BUFF_SIZE-1);
- } else {
- ret.results[tabs] = ret.results[tabs-1] + strlen(ret.results[tabs-1]) + 1;
- strncpy(ret.results[tabs], p, IDS_LOOKUP_BUFF_SIZE-1);
+ if (tabs == 0) last_root_fpos = fpos;
+ ids_query_result_set_str(&ret, tabs, p);
+
+ if (ids_tracing) {
+ int i = 0;
+ for(; i < IDS_LOOKUP_MAX_DEPTH; i++) {
+ if (!qparts[i]) break;
+ ids_msg(" ...[%d]: %s\t--> %s", i, qparts[i], ret.results[i]);
+ }
}
continue;
}
if (ids_cmp(p, qparts[tabs]) == 1) {
- //ids_msg("will not be found p = %s (%d) qparts[tabs] = %s", p, qparts[tabs]);
+ if (ids_tracing)
+ ids_msg("will not be found qparts[tabs] = %s, p = %s", qparts[tabs], p);
goto ids_lookup_done; /* will not be found */
}
} /* for each line */
ids_lookup_done:
- //ids_msg("bailed at line %ld...", line);
+ if (ids_tracing)
+ ids_msg("bailed at line %ld...", line);
fclose(fd);
if (result) {
- memcpy(result, &ret, sizeof(ids_query_result));
- for(int i = 0; result->results[i]; i++)
- result->results[i] = result->_strs + (ret.results[i] - ret._strs);
-
+ ids_query_result_cpy(result, &ret);
return last_root_fpos;
}
return last_root_fpos;
@@ -187,3 +218,97 @@ int query_list_count_found(ids_query_list query_list) {
}
return count;
}
+
+static gchar *split_loc_default(const char *line) {
+ return g_utf8_strchr(line, -1, ' ');
+}
+
+GSList *ids_file_all_get_all(const gchar *file, split_loc_function split_loc_func) {
+ GSList *ret = NULL;
+ gchar buff[IDS_LOOKUP_BUFF_SIZE] = "";
+ gchar *p = NULL, *name = NULL;
+
+ FILE *fd;
+ int tabs = 0, tabs_last = 0;
+ long fpos, line = -1;
+
+ fd = fopen(file, "r");
+ if (!fd) {
+ ids_msg("file could not be read: %s", file);
+ return ret;
+ }
+
+ ids_query_result *working = g_new0(ids_query_result, 1);
+ gchar **qparts = g_new0(gchar*, IDS_LOOKUP_MAX_DEPTH + 1);
+ for(tabs = IDS_LOOKUP_MAX_DEPTH-1; tabs>=0; tabs--)
+ qparts[tabs] = g_malloc0(IDS_LOOKUP_BUFF_SIZE);
+ tabs = 0;
+
+ if (!split_loc_func) split_loc_func = split_loc_default;
+
+ for (fpos = ftell(fd); fgets(buff, IDS_LOOKUP_BUFF_SIZE, fd); fpos = ftell(fd)) {
+ p = strchr(buff, '\n');
+ if (!p)
+ ids_msg("line longer than IDS_LOOKUP_BUFF_SIZE (%d), file: %s, offset: %ld", IDS_LOOKUP_BUFF_SIZE, file, fpos);
+ line++;
+
+ /* line ends at comment */
+ p = strchr(buff, '#');
+ if (p) *p = 0;
+ /* trim trailing white space */
+ if (!p) p = buff + strlen(buff);
+ p--;
+ while(p > buff && isspace((unsigned char)*p)) p--;
+ *(p+1) = 0;
+ p = buff;
+
+ if (buff[0] == 0) continue; /* empty line */
+ if (buff[0] == '\n') continue; /* empty line */
+
+ /* scan for fields */
+ tabs = 0;
+ while(*p == '\t') { tabs++; p++; }
+
+ if (tabs >= IDS_LOOKUP_MAX_DEPTH) continue; /* too deep */
+ if (tabs > tabs_last + 1) {
+ /* jump too big, there's a qpath part that is "" */
+ ids_msg("jump too big from depth %d to %d, file: %s, offset: %ld", tabs_last, tabs, file, fpos);
+ continue;
+ }
+
+ name = split_loc_func(p);
+ if (!name) {
+ ids_msg("expected name/value split not found, file: %s, offset: %ld", file, fpos);
+ continue;
+ }
+ *name = 0; name++; /* split ptr is the first char of split string */
+ g_strstrip(p);
+ g_strstrip(name);
+
+ // now p = id, name = name
+ // ids_msg("p: %s -- name: %s", p, name);
+
+ strncpy(qparts[tabs], p, IDS_LOOKUP_BUFF_SIZE-1);
+ ids_query_result_set_str(working, tabs, name);
+ if (tabs < tabs_last)
+ for(;tabs_last > tabs; tabs_last--) {
+ qparts[tabs_last][0] = 0;
+ working->results[tabs_last] = NULL;
+ }
+
+ ids_query *found = ids_query_new(NULL);
+ ids_query_result_cpy(&found->result, working);
+ found->qpath = g_strjoinv("/", qparts);
+ p = found->qpath + strlen(found->qpath) - 1;
+ while(*p == '/') { *p = 0; p--; }
+ ret = g_slist_append(ret, found);
+
+ tabs_last = tabs;
+ } /* for each line */
+
+ fclose(fd);
+ g_strfreev(qparts);
+ ids_query_result_free(working);
+
+ return ret;
+}