aboutsummaryrefslogtreecommitdiffstats
path: root/epan/uat.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/uat.c')
-rw-r--r--epan/uat.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/epan/uat.c b/epan/uat.c
new file mode 100644
index 0000000000..41c911b90e
--- /dev/null
+++ b/epan/uat.c
@@ -0,0 +1,285 @@
+/*
+ * uat.c
+ *
+ * User Accessible Tables
+ * Mantain an array of user accessible data strucures
+ *
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include <glib.h>
+#include <epan/emem.h>
+#include <epan/filesystem.h>
+
+#include "uat-int.h"
+
+static GPtrArray* all_uats = NULL;
+
+void uat_init(void) {
+ all_uats = g_ptr_array_new();
+}
+
+uat_t* uat_start(const char* name,
+ size_t size,
+ char* filename,
+ void** data_ptr,
+ guint* num_items_ptr,
+ uat_copy_cb_t copy_cb,
+ uat_update_cb_t update_cb,
+ uat_free_cb_t free_cb) {
+
+ uat_t* uat = g_malloc(sizeof(uat_t));
+ g_ptr_array_add(all_uats,uat);
+
+ g_assert(name && size && filename && data_ptr && num_items_ptr);
+
+ uat->name = g_strdup(name);
+ uat->record_size = size;
+ uat->filename = g_strdup(filename);
+ uat->user_ptr = data_ptr;
+ uat->nrows_p = num_items_ptr;
+ uat->copy_cb = copy_cb;
+ uat->update_cb = update_cb;
+ uat->free_cb = free_cb;
+
+ uat->fields = NULL;
+ uat->ncols = 0;
+ uat->user_data = g_array_new(FALSE,FALSE,uat->record_size);
+ uat->finalized = FALSE;
+ uat->rep = NULL;
+ uat->free_rep = NULL;
+
+ return uat;
+}
+
+void uat_add_field(uat_t* uat,
+ const char* name,
+ uat_text_mode_t mode,
+ uat_fld_chk_cb_t chk_cb,
+ uat_fld_set_cb_t set_cb,
+ uat_fld_tostr_cb_t tostr_cb) {
+
+ uat_fld_t* f = g_malloc(sizeof(uat_fld_t));
+
+ g_assert( name && set_cb && tostr_cb && (! uat->finalized )
+ && (mode == PT_TXTMOD_STRING || mode == PT_TXTMOD_HEXBYTES) );
+
+ f->name = g_strdup(name);
+ f->mode = mode;
+ f->chk_cb = chk_cb;
+ f->set_cb = set_cb;
+ f->tostr_cb = tostr_cb;
+
+ f->rep = NULL;
+ f->free_rep = NULL;
+ f->colnum = uat->ncols;
+ f->next = NULL;
+
+ uat->ncols++;
+
+ if (uat->fields) {
+ uat_fld_t* c;
+ for (c = uat->fields; c->next; c = c->next) ;
+ c->next = f;
+ } else {
+ uat->fields = f;
+ }
+}
+
+void uat_finalize(uat_t* uat) {
+ UAT_UPDATE(uat);
+ uat->finalized = TRUE;
+}
+
+uat_t* uat_new(const char* uat_name,
+ size_t size,
+ char* filename,
+ void** data_ptr,
+ guint* numitems_ptr,
+ uat_copy_cb_t copy_cb,
+ uat_update_cb_t update_cb,
+ uat_free_cb_t free_cb,
+ ...) {
+ uat_t* uat = uat_start(uat_name, size, filename, data_ptr, numitems_ptr, copy_cb, update_cb, free_cb);
+ va_list ap;
+ char* name;
+ uat_text_mode_t mode;
+ uat_fld_chk_cb_t chk_cb;
+ uat_fld_set_cb_t set_cb;
+ uat_fld_tostr_cb_t tostr_cb;
+ va_start(ap,free_cb);
+
+ name = va_arg(ap,char*);
+
+ do {
+ mode = va_arg(ap,uat_text_mode_t);
+ chk_cb = va_arg(ap,uat_fld_chk_cb_t);
+ set_cb = va_arg(ap,uat_fld_set_cb_t);
+ tostr_cb = va_arg(ap,uat_fld_tostr_cb_t);
+
+ uat_add_field(uat, name, mode, chk_cb, set_cb, tostr_cb);
+
+ name = va_arg(ap,char*);
+ } while (name);
+
+ va_end(ap);
+
+ uat_finalize(uat);
+
+ return uat;
+}
+
+void* uat_add_record(uat_t* uat, const void* data) {
+ void* rec;
+
+ g_assert( uat->finalized );
+
+ g_array_append_vals (uat->user_data, data, 1);
+
+ rec = uat->user_data->data + (uat->record_size * (uat->user_data->len-1));
+
+ if (uat->copy_cb) {
+ uat->copy_cb(rec, data, uat->record_size);
+ }
+
+
+ UAT_UPDATE(uat);
+
+ return rec;
+}
+
+void uat_remove_record_idx(uat_t* uat, guint idx) {
+
+ g_assert( uat->finalized && idx < uat->user_data->len);
+
+ g_array_remove_index(uat->user_data, idx);
+
+ UAT_UPDATE(uat);
+
+}
+
+
+gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
+ gchar* pers_fname = get_persconffile_path(uat->filename,for_writing);
+
+ if (! file_exists(pers_fname)) {
+ gchar* data_fname = get_datafile_path(uat->filename);
+
+ if (file_exists(data_fname)) {
+ return data_fname;
+ }
+ }
+
+ return pers_fname;
+}
+
+static void putfld(FILE* fp, void* rec, uat_fld_t* f) {
+ guint fld_len;
+ char* fld_ptr;
+
+ f->tostr_cb(rec,&fld_ptr,&fld_len);
+
+ switch(f->mode){
+ case PT_TXTMOD_STRING: {
+ guint i;
+
+ putc('"',fp);
+
+ for(i=0;i<fld_len;i++) {
+ char c = fld_ptr[i];
+
+ if (c == '"') {
+ fputs("\134\042",fp);
+ } else if (isprint(c)) {
+ putc(c,fp);
+ } else {
+ fprintf(fp,"\\x%.2x",c);
+ }
+ }
+
+ putc('"',fp);
+ return;
+ }
+ case PT_TXTMOD_HEXBYTES: {
+ guint i;
+
+ for(i=0;i<fld_len;i++) {
+ fprintf(fp,"%.2x",fld_ptr[i]);
+ }
+
+ return;
+ }
+ default:
+ g_assert_not_reached();
+ }
+}
+
+gboolean uat_save(uat_t* uat, char** error) {
+ guint i;
+ gchar* fname = uat_get_actual_filename(uat,TRUE);
+ FILE* fp = fopen(fname,"w");
+
+
+ if (!fp) {
+ *error = ep_strdup_printf("uat_save: error opening '%s': %s",fname,strerror(errno));
+ return FALSE;
+ }
+
+ *error = NULL;
+
+ for ( i = 0 ; i < uat->user_data->len - 1 ; i++ ) {
+ void* rec = uat->user_data->data + (uat->record_size * (uat->user_data->len-1));
+ uat_fld_t* f;
+
+ f = uat->fields;
+
+ putfld(fp, rec, f);
+
+ while (( f = f->next )) {
+ fputs(",",fp);
+ putfld(fp, rec, f);
+ }
+
+ fputs("\n",fp);
+ }
+
+ fclose(fp);
+
+ return TRUE;
+}
+
+void uat_destroy(uat_t* uat) {
+ g_ptr_array_remove(all_uats,uat);
+
+}
+
+void* uat_dup(uat_t* uat, guint* len_p) {
+ guint size = (uat->record_size * uat->user_data->len);
+ *len_p = size;
+ return size ? g_memdup(uat->user_data->data,size) : NULL ;
+}
+
+void* uat_se_dup(uat_t* uat, guint* len_p) {
+ guint size = (uat->record_size * uat->user_data->len);
+ *len_p = size;
+ return size ? se_memdup(uat->user_data->data,size) : NULL ;
+}
+
+void uat_cleanup(void) {
+
+ while( all_uats->len ) {
+ uat_destroy((uat_t*)all_uats->pdata);
+ }
+
+ g_ptr_array_free(all_uats,TRUE);
+}
+