refactor constraint matrix handling

This commit is contained in:
Lev Walkin 2017-08-07 20:10:05 -07:00
parent 494fb707a7
commit 4dcf8367d9
10 changed files with 177 additions and 88 deletions

View File

@ -318,24 +318,22 @@ asn1c_get_information_object_set_reference_from_constraint(
return val->value.reference;
}
typedef struct asn1c_ioc_table_s {
} asn1c_ioc_table_t;
static asn1c_ioc_table_t *
asn1c_construct_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) {
(void)arg;
static asn1p_ioc_table_t *
asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) {
(void)objset_ref;
(void)objset;
asn1c_ioc_table_t *itable = NULL;
itable = calloc(1, sizeof(*itable));
assert(itable);
return itable;
if(objset->ioc_table) {
return objset->ioc_table;
} else {
FATAL("Information Object Set %s contains no objects at line %d",
objset->Identifier, objset->_lineno);
errno = EINVAL;
return NULL;
}
};
static asn1c_ioc_table_t *
asn1c_construct_ioc_table(arg_t *arg) {
static asn1p_ioc_table_t *
asn1c_get_ioc_table(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *memb;
asn1p_expr_t *objset = 0;
@ -369,7 +367,7 @@ asn1c_construct_ioc_table(arg_t *arg) {
return NULL;
}
return asn1c_construct_ioc_table_from_objset(arg, objset_ref, objset);
return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset);
}
int
@ -378,11 +376,11 @@ asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
asn1p_expr_t *v;
int comp_mode = 0; /* {root,ext=1,root,root,...} */
int saved_target = arg->target->target;
asn1c_ioc_table_t *itable = NULL;
asn1p_ioc_table_t *itable = NULL;
DEPENDENCIES;
itable = asn1c_construct_ioc_table(arg);
itable = asn1c_get_ioc_table(arg);
if(!itable && errno != 0) {
return -1;
}

View File

@ -5,7 +5,7 @@ static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
const uint8_t *buf, const uint8_t *bend,
int optional_mode, const uint8_t **newpos);
static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, const uint8_t *buf, const uint8_t *bend);
static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_cell_s *cell, const uint8_t *buf, const uint8_t *bend);
static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf);
int
@ -51,9 +51,13 @@ asn1f_check_class_object(arg_t *arg) {
}
static int
_asn1f_is_ioc_row_duplicate(asn1p_ioc_row_t **rows, size_t count, asn1p_ioc_row_t *row) {
for(size_t i = 0; i < count; i++) {
switch(asn1p_ioc_row_match(rows[i], row)) {
_asn1f_is_ioc_row_duplicate(asn1p_ioc_table_t *it, asn1p_ioc_row_t *row) {
if(!it) {
return 0;
}
for(size_t i = 0; i < it->rows; i++) {
switch(asn1p_ioc_row_match(it->row[i], row)) {
default:
case -1:
return -1;
@ -72,37 +76,33 @@ struct parse_object_key {
asn1p_expr_t *eclass; /* CLASS */
};
/*
* Add to the IoC table if the row is unique.
*/
static int
_asn1f_add_row(arg_t *arg, asn1p_expr_t *expr, asn1p_ioc_row_t *row) {
void *new_rows_ptr;
_asn1f_add_unique_row(arg_t *arg, asn1p_expr_t *expr, asn1p_ioc_row_t *row) {
switch(_asn1f_is_ioc_row_duplicate(expr->object_class_matrix.row,
expr->object_class_matrix.rows, row)) {
case -1:
DEBUG("Found Information Object Duplicate in %s", expr->Identifier,
expr->_lineno);
return -1;
case 0:
/* Not a duplicate */
break;
case 1:
/* Proper duplicate detected; ignore */
asn1p_ioc_row_delete(row);
return 0;
if(expr->ioc_table == NULL) {
expr->ioc_table = asn1p_ioc_table_new();
} else {
/* Look for duplicates */
switch(_asn1f_is_ioc_row_duplicate(expr->ioc_table, row)) {
case -1:
DEBUG("Found Information Object Duplicate in %s", expr->Identifier,
expr->_lineno);
return -1;
case 0:
/* Not a duplicate */
break;
case 1:
/* Proper duplicate detected; ignore */
asn1p_ioc_row_delete(row);
return 0;
}
}
new_rows_ptr = realloc(expr->object_class_matrix.row,
(expr->object_class_matrix.rows + 1)
* sizeof(expr->object_class_matrix.row[0]));
assert(new_rows_ptr);
expr->object_class_matrix.row = new_rows_ptr;
expr->object_class_matrix.row[expr->object_class_matrix.rows] = row;
expr->object_class_matrix.rows++;
/* Propagate max identifier length */
if(expr->object_class_matrix.max_identifier_length
< row->max_identifier_length)
expr->object_class_matrix.max_identifier_length
= row->max_identifier_length;
asn1p_ioc_table_add(expr->ioc_table, row);
return 0;
}
@ -134,7 +134,7 @@ _asn1f_parse_object_cb(const uint8_t *buf, size_t size, void *keyp) {
}
/* Add object to a CLASS. */
if(_asn1f_add_row(arg, eclass, row) != 0)
if(_asn1f_add_unique_row(arg, eclass, row) != 0)
return -1;
/*
@ -146,7 +146,7 @@ _asn1f_parse_object_cb(const uint8_t *buf, size_t size, void *keyp) {
buf, buf + size, 0, 0);
assert(ret == 0);
if(_asn1f_add_row(arg, expr, row) != 0)
if(_asn1f_add_unique_row(arg, expr, row) != 0)
return -1;
return 0;
@ -342,7 +342,7 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
DEBUG("Reference %s satisfied by %s (%d)",
chunk->content.token,
buf, p - buf);
ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
ret = _asn1f_assign_cell_value(arg, cell, buf, p);
if(ret) return ret;
buf = p;
if(newpos) *newpos = buf;
@ -367,9 +367,8 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
static int
_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row,
struct asn1p_ioc_cell_s *cell, const uint8_t *buf,
const uint8_t *bend) {
_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_cell_s *cell,
const uint8_t *buf, const uint8_t *bend) {
asn1p_expr_t *expr = (asn1p_expr_t *)NULL;
char *p;
int new_ref = 1;
@ -481,12 +480,9 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row,
cell->value = expr;
cell->new_ref = new_ref;
size_t idLength = strlen(expr->Identifier);
if(row->max_identifier_length < idLength)
row->max_identifier_length = idLength;
if(expr->Identifier != p)
if(expr->Identifier != p) {
free(p);
}
return 0;
}

View File

@ -5,6 +5,62 @@
#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_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) {
@ -29,9 +85,6 @@ asn1p_ioc_row_new(asn1p_expr_t *oclass) {
columns = 0;
TQ_FOR(field, &oclass->members, next) {
size_t fieldIdLen = strlen(field->Identifier);
if(fieldIdLen > row->max_identifier_length)
row->max_identifier_length = fieldIdLen;
row->column[columns].field = field;
row->column[columns].value = NULL;
columns++;

View File

@ -15,12 +15,22 @@ typedef struct asn1p_ioc_row_s {
int new_ref;
} *column;
size_t columns;
size_t max_identifier_length;
} asn1p_ioc_row_t;
asn1p_ioc_row_t *asn1p_ioc_row_new(struct asn1p_expr_s *oclass);
size_t asn1p_ioc_row_max_identifier_length(asn1p_ioc_row_t *);
void asn1p_ioc_row_delete(asn1p_ioc_row_t *);
typedef struct asn1p_ioc_table_s {
asn1p_ioc_row_t **row;
size_t rows;
} asn1p_ioc_table_t;
asn1p_ioc_table_t *asn1p_ioc_table_new(void);
void asn1p_ioc_table_add(asn1p_ioc_table_t *, asn1p_ioc_row_t *row);
size_t asn1p_ioc_table_max_identifier_length(asn1p_ioc_table_t *);
void asn1p_ioc_table_free(asn1p_ioc_table_t *);
/*
* Match is similar to a comparison,
* but -1 means error and 1 means not equal. 0 is OK

View File

@ -345,12 +345,7 @@ asn1p_expr_free(asn1p_expr_t *expr) {
}
free(expr->specializations.pspec);
}
if(expr->object_class_matrix.row) {
for(size_t row = 0; row < expr->object_class_matrix.rows; row++) {
asn1p_ioc_row_delete(expr->object_class_matrix.row[row]);
}
free(expr->object_class_matrix.row);
}
asn1p_ioc_table_free(expr->ioc_table);
if(expr->data && expr->data_free)
expr->data_free(expr->data);

View File

@ -107,6 +107,7 @@ typedef enum asn1p_expr_type {
#include "asn1p_expr2uclass.h"
struct asn1p_module_s; /* Forward declaration */
struct asn1p_ioc_table_s; /* Forward declaration */
/*
* A named collection of types.
@ -178,12 +179,8 @@ typedef struct asn1p_expr_s {
*/
asn1p_wsyntx_t *with_syntax;
/* Information Object Class matrix, specific for this class */
struct asn1p_ioc_matrix_s {
asn1p_ioc_row_t **row;
size_t rows;
size_t max_identifier_length;
} object_class_matrix;
/* Information Object Class table, specific for a class or object set */
struct asn1p_ioc_table_s *ioc_table;
/*
* A tag.

View File

@ -776,19 +776,19 @@ asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1pri
if(flags & APF_PRINT_CLASS_MATRIX) do {
size_t col, maxidlen;
if(tc->object_class_matrix.rows == 0) {
if(tc->ioc_table == NULL) {
if(tc->expr_type == A1TC_CLASSDEF) {
safe_printf("\n-- Information Object Class table is empty");
}
break;
}
safe_printf("\n-- Information Object Set has %d entr%s:\n",
tc->object_class_matrix.rows,
tc->object_class_matrix.rows==1 ? "y" : "ies");
maxidlen = tc->object_class_matrix.max_identifier_length;
for(ssize_t r = -1; r < (ssize_t)tc->object_class_matrix.rows; r++) {
struct asn1p_ioc_row_s *row;
row = tc->object_class_matrix.row[r<0?0:r];
tc->ioc_table->rows,
tc->ioc_table->rows==1 ? "y" : "ies");
maxidlen = asn1p_ioc_table_max_identifier_length(tc->ioc_table);
for(ssize_t r = -1; r < (ssize_t)tc->ioc_table->rows; r++) {
asn1p_ioc_row_t *row;
row = tc->ioc_table->row[r<0?0:r];
if(r < 0) safe_printf("-- %s", r > 9 ? " " : "");
else safe_printf("-- [%*d]", r > 9 ? 2 : 1, r+1);
for(col = 0; col < row->columns; col++) {

View File

@ -20,9 +20,7 @@ BEGIN
siAttributeValue IA5String
}
Attributes ATTRIBUTE ::= { Names }
Names ATTRIBUTE ::= { rafService | rcfService }
Attributes ATTRIBUTE ::= { rafService | rcfService }
rafService ATTRIBUTE ::= { ID raf }
rcfService ATTRIBUTE ::= { ID rcf }

View File

@ -13,9 +13,7 @@ Attribute ::= SEQUENCE {
siAttributeValue IA5String
}
Attributes ATTRIBUTE ::= {Names}
Names ATTRIBUTE ::= {{ ID raf } | { ID rcf }}
Attributes ATTRIBUTE ::= {{ ID raf } | { ID rcf }}
rafService ATTRIBUTE ::= { ID raf }

View File

@ -0,0 +1,44 @@
ModuleAttributeClass { iso org(3) dod(6) internet(1) private(4) enterprise(1)
spelio(9363) software(1) asn1c(5) test(1) 98 }
DEFINITIONS ::=
BEGIN
ATTRIBUTE ::= CLASS {
&id RELATIVE-OID UNIQUE
} WITH SYNTAX { ID &id }
-- Information Object Set has 2 entries:
-- [&id]
-- [1] raf
-- [2] rcf
Attribute ::= SEQUENCE {
identifier ATTRIBUTE.&id ({Attributes}),
siAttributeValue IA5String
}
Attributes ATTRIBUTE ::= {{ ID raf } | { ID rcf }}
-- Information Object Set has 2 entries:
-- [&id]
-- [1] raf
-- [2] rcf
rafService ATTRIBUTE ::= { ID raf }
-- Information Object Set has 1 entry:
-- [&id]
-- [1] raf
rcfService ATTRIBUTE ::= { ID rcf }
-- Information Object Set has 1 entry:
-- [&id]
-- [1] rcf
raf RELATIVE-OID ::= {3 2 1}
rcf RELATIVE-OID ::= {3 2 2}
END