Initial version of asn1c
[com/asn1c.git] / libasn1parser / asn1p_class.c
diff --git a/libasn1parser/asn1p_class.c b/libasn1parser/asn1p_class.c
new file mode 100644 (file)
index 0000000..cbe9480
--- /dev/null
@@ -0,0 +1,319 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "asn1parser.h"
+#include "asn1p_class.h"
+
+asn1p_ioc_table_t *
+asn1p_ioc_table_new() {
+    asn1p_ioc_table_t *it = calloc(1, sizeof(*it));
+    assert(it);
+    return it;
+}
+
+void
+asn1p_ioc_table_add(asn1p_ioc_table_t *it, asn1p_ioc_row_t *row) {
+    assert(it);
+
+    asn1p_ioc_row_t **new_rows =
+        realloc(it->row, (it->rows + 1) * sizeof(it->row[0]));
+    assert(new_rows);
+    it->row = new_rows;
+    it->row[it->rows++] = row;
+}
+
+void
+asn1p_ioc_table_append(asn1p_ioc_table_t *it, asn1p_ioc_table_t *src) {
+
+    if(!src || !it) return;
+
+    for(size_t i = 0; i < src->rows; i++) {
+        asn1p_ioc_table_add(it, asn1p_ioc_row_clone(src->row[i]));
+    }
+}
+
+void
+asn1p_ioc_table_free(asn1p_ioc_table_t *it) {
+    if(it) {
+        for(size_t i = 0; i < it->rows; i++) {
+            asn1p_ioc_row_delete(it->row[i]);
+        }
+        free(it->row);
+        free(it);
+    }
+}
+
+size_t
+asn1p_ioc_table_max_identifier_length(asn1p_ioc_table_t *it) {
+    size_t max_length = 0;
+    if(it) {
+        for(size_t i = 0; i < it->rows; i++) {
+            size_t len = asn1p_ioc_row_max_identifier_length(it->row[i]);
+            if(len > max_length) max_length = len;
+        }
+    }
+    return max_length;
+}
+
+size_t
+asn1p_ioc_row_max_identifier_length(asn1p_ioc_row_t *row) {
+    size_t max_length = 0;
+    if(row) {
+        for(size_t i = 0; i < row->columns; i++) {
+            if(row->column[i].value) {
+                size_t len = strlen(row->column[i].value->Identifier);
+                if(len > max_length) max_length = len;
+            }
+        }
+    }
+    return max_length;
+}
+
+asn1p_ioc_row_t *
+asn1p_ioc_row_new(asn1p_expr_t *oclass) {
+       asn1p_ioc_row_t *row;
+       asn1p_expr_t *field;
+       int columns = 0;
+
+       assert(oclass->expr_type == A1TC_CLASSDEF);
+
+       row = calloc(1, sizeof *row);
+       if(!row) return NULL;
+
+       TQ_FOR(field, &oclass->members, next)
+               columns++;
+
+       row->column = calloc(columns, sizeof *row->column);
+       if(!row->column) {
+               free(row);
+               return NULL;
+       }
+       row->columns = columns;
+
+       columns = 0;
+       TQ_FOR(field, &oclass->members, next) {
+               row->column[columns].field = field;
+               row->column[columns].value = NULL;
+               columns++;
+       }
+
+       return row;
+}
+
+asn1p_ioc_row_t *
+asn1p_ioc_row_clone(asn1p_ioc_row_t *src) {
+       asn1p_ioc_row_t *row;
+
+       row = calloc(1, sizeof *row);
+       if(!row) return NULL;
+
+       row->column = calloc(src->columns, sizeof *src->column);
+       if(!row->column) {
+               free(row);
+               return NULL;
+       }
+       row->columns = src->columns;
+
+       for(size_t i = 0; i < src->columns; i++) {
+               row->column[i].field = src->column[i].field;
+               row->column[i].value = 0;
+               if(src->column[i].value) {
+                       row->column[i].value = asn1p_expr_clone(src->column[i].value, 0);
+               }
+               row->column[i].new_ref = 1;
+       }
+
+       return row;
+}
+
+void
+asn1p_ioc_row_delete(asn1p_ioc_row_t *row) {
+       if(row) {
+               if(row->column) {
+                       for(size_t i = 0; i < row->columns; i++) {
+                               if(!row->column[i].new_ref && row->column[i].value) {
+                                       /* 
+                                        * Field 'reference' comes from asn1fix_cws.c :
+                                        * TQ_FIRST(&cell->field->members)->reference
+                                        * so it should not be freed here.
+                                        */
+                                       row->column[i].value->reference = NULL;
+                               }
+                               asn1p_expr_free(row->column[i].value);
+                       }
+                       free(row->column);
+               }
+               free(row);
+       }
+}
+
+int
+asn1p_ioc_row_match(const asn1p_ioc_row_t *a, const asn1p_ioc_row_t *b) {
+    assert(a && b);
+
+    if(a->columns != b->columns)
+        return -1;  /* Bad! */
+
+    for(size_t i = 0; i < a->columns; i++) {
+        assert(a->column[i].field);
+        assert(b->column[i].field);
+        if(strcmp(a->column[i].field->Identifier,
+                  b->column[i].field->Identifier)
+           != 0) {
+            return -1;  /* Bad! */
+        }
+        if((a->column[i].value && !b->column[i].value)
+           || (!a->column[i].value && b->column[i].value)) {
+            return 1;   /* Not match */
+        }
+        if(a->column[i].value && b->column[i].value) {
+            if(asn1p_expr_compare(a->column[i].value, b->column[i].value)
+               != 0) {
+                return 1;   /* Not match */
+            }
+        }
+    }
+
+    return 0;
+}
+
+struct asn1p_ioc_cell_s *
+asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *row, const char *fieldname) {
+       for(size_t i = 0; i < row->columns; i++) {
+               if(strcmp(row->column[i].field->Identifier, fieldname) == 0)
+                       return &row->column[i];
+       }
+       errno = ESRCH;
+       return NULL;
+}
+
+asn1p_wsyntx_chunk_t *
+asn1p_wsyntx_chunk_new() {
+       asn1p_wsyntx_chunk_t *wc;
+
+       wc = calloc(1, sizeof(*wc));
+
+       return wc;
+}
+
+void
+asn1p_wsyntx_chunk_free(asn1p_wsyntx_chunk_t *wc) {
+       if(wc) {
+               switch(wc->type) {
+               case WC_LITERAL:
+               case WC_WHITESPACE:
+               case WC_FIELD:
+                       free(wc->content.token); break;
+               case WC_OPTIONALGROUP:
+                       asn1p_wsyntx_free(wc->content.syntax);
+                       break;
+               }
+               free(wc);
+       }
+}
+
+asn1p_wsyntx_chunk_t *
+asn1p_wsyntx_chunk_clone(asn1p_wsyntx_chunk_t *wc) {
+       asn1p_wsyntx_chunk_t *nc;
+
+       nc = asn1p_wsyntx_chunk_new();
+       if(nc) {
+               nc->type = wc->type;
+               switch(wc->type) {
+               case WC_LITERAL:
+               case WC_WHITESPACE:
+               case WC_FIELD:
+                       nc->content.token = malloc(strlen(wc->content.token)+1);
+                       strcpy(nc->content.token, wc->content.token);
+                       break;
+               case WC_OPTIONALGROUP:
+                       nc->content.syntax = asn1p_wsyntx_clone(wc->content.syntax);
+                       break;
+               }
+       }
+
+       return nc;
+}
+
+asn1p_wsyntx_t *
+asn1p_wsyntx_new() {
+       asn1p_wsyntx_t *wx;
+
+       wx = calloc(1, sizeof(*wx));
+       if(wx) {
+               TQ_INIT(&(wx->chunks));
+       }
+
+       return wx;
+}
+
+void
+asn1p_wsyntx_free(asn1p_wsyntx_t *wx) {
+       if(wx) {
+               asn1p_wsyntx_chunk_t *wc;
+               while((wc = TQ_REMOVE(&(wx->chunks), next)))
+                       asn1p_wsyntx_chunk_free(wc);
+               free(wx);
+       }
+}
+
+asn1p_wsyntx_t *
+asn1p_wsyntx_clone(asn1p_wsyntx_t *wx) {
+       asn1p_wsyntx_t *nw;
+
+       nw = asn1p_wsyntx_new();
+       if(nw) {
+               asn1p_wsyntx_chunk_t *wc;
+               asn1p_wsyntx_chunk_t *nc;
+               TQ_FOR(wc, &(wx->chunks), next) {
+                       nc = asn1p_wsyntx_chunk_clone(wc);
+                       if(nc) {
+                               TQ_ADD(&(nw->chunks), nc, next);
+                       } else {
+                               asn1p_wsyntx_free(nw);
+                               return NULL;
+                       }
+               }
+       }
+
+       return nw;
+}
+
+asn1p_wsyntx_chunk_t *
+asn1p_wsyntx_chunk_fromstring(char *token, int do_copy) {
+       asn1p_wsyntx_chunk_t *wc;
+
+       if(do_copy) {
+               static asn1p_wsyntx_chunk_t tmp;
+               tmp.type = WC_LITERAL;
+               tmp.content.token = token;
+               wc = asn1p_wsyntx_chunk_clone(&tmp);
+       } else {
+               wc = asn1p_wsyntx_chunk_new();
+               if(wc) {
+                       wc->type = WC_LITERAL;
+                       wc->content.token = token;
+               }
+       }
+
+       return wc;
+}
+
+
+asn1p_wsyntx_chunk_t *
+asn1p_wsyntx_chunk_fromsyntax(asn1p_wsyntx_t *syntax) {
+       asn1p_wsyntx_chunk_t *wc;
+
+       wc = asn1p_wsyntx_chunk_new();
+       if(wc) {
+               wc->type = WC_OPTIONALGROUP;
+               wc->content.syntax = syntax;
+               syntax->parent = wc;
+       }
+
+       return wc;
+}
+