diff options
Diffstat (limited to 'epan/ftypes/ftypes.c')
-rw-r--r-- | epan/ftypes/ftypes.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/epan/ftypes/ftypes.c b/epan/ftypes/ftypes.c new file mode 100644 index 0000000000..7234008d53 --- /dev/null +++ b/epan/ftypes/ftypes.c @@ -0,0 +1,410 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> + +/* Keep track of ftype_t's via their ftenum number */ +static ftype_t* type_list[FT_NUM_TYPES]; + +/* Space for quickly allocating/de-allocating fvalue_t's */ +static GMemChunk *gmc_fvalue = NULL; + +/* These are the ftype registration functions that need to be called. + * This list and the initialization function could be produced + * via a script, like the dissector registration, but there's so few + * that I don't mind doing it by hand for now. */ +void ftype_register_bytes(void); +void ftype_register_double(void); +void ftype_register_integers(void); +void ftype_register_ipv4(void); +void ftype_register_none(void); +void ftype_register_string(void); +void ftype_register_time(void); +void ftype_register_tvbuff(void); + +/* Initialize the ftype module. */ +void +ftypes_initialize(void) +{ + ftype_register_bytes(); + ftype_register_double(); + ftype_register_integers(); + ftype_register_ipv4(); + ftype_register_none(); + ftype_register_string(); + ftype_register_time(); + ftype_register_tvbuff(); + + if (gmc_fvalue) + g_mem_chunk_destroy(gmc_fvalue); + + gmc_fvalue = g_mem_chunk_new("gmc_fvalue", sizeof(fvalue_t), + 200 * sizeof(fvalue_t), G_ALLOC_AND_FREE); +} + +void +ftypes_cleanup(void) +{ + if (gmc_fvalue) + g_mem_chunk_destroy(gmc_fvalue); +} + + + +/* Each ftype_t is registered via this function */ +void +ftype_register(enum ftenum ftype, ftype_t *ft) +{ + /* Check input */ + g_assert(ftype >= 0); + g_assert(ftype < FT_NUM_TYPES); + + /* Don't re-register. */ + g_assert(type_list[ftype] == NULL); + + type_list[ftype] = ft; +} + +/* Given an ftenum number, return an ftype_t* */ +static ftype_t* +ftype_lookup(enum ftenum ftype) +{ + ftype_t* result; + + /* Check input */ + g_assert(ftype >= 0); + g_assert(ftype < FT_NUM_TYPES); + + result = type_list[ftype]; + + /* Check output. */ + g_assert(result != NULL); + + return result; +} + + +/* Returns a string representing the name of the type. Useful + * for glossary production. */ +const char* +ftype_name(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->name; +} + +const char* +ftype_pretty_name(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->pretty_name; +} + +int +ftype_length(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->wire_size; +} + +gboolean +ftype_can_slice(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->slice ? TRUE : FALSE; +} + +gboolean +ftype_can_eq(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->cmp_eq ? TRUE : FALSE; +} + +gboolean +ftype_can_ne(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->cmp_ne ? TRUE : FALSE; +} + +gboolean +ftype_can_gt(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->cmp_gt ? TRUE : FALSE; +} + +gboolean +ftype_can_ge(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->cmp_ge ? TRUE : FALSE; +} + +gboolean +ftype_can_lt(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->cmp_lt ? TRUE : FALSE; +} + +gboolean +ftype_can_le(enum ftenum ftype) +{ + ftype_t *ft; + + ft = ftype_lookup(ftype); + return ft->cmp_le ? TRUE : FALSE; +} + +/* ---------------------------------------------------------- */ + +/* Allocate and initialize an fvalue_t, given an ftype */ +fvalue_t* +fvalue_new(ftenum_t ftype) +{ + fvalue_t *fv; + ftype_t *ft; + FvalueNewFunc new_value; + + fv = g_mem_chunk_alloc(gmc_fvalue); + + ft = ftype_lookup(ftype); + fv->ftype = ft; + + new_value = ft->new_value; + if (new_value) { + new_value(fv); + } + + return fv; +} + +/* Free all memory used by an fvalue_t */ +void +fvalue_free(fvalue_t *fv) +{ + FvalueFreeFunc free_value; + + free_value = fv->ftype->free_value; + if (free_value) { + free_value(fv); + } + + g_mem_chunk_free(gmc_fvalue, fv); +} + + + +fvalue_t* +fvalue_from_string(ftenum_t ftype, char *s, LogFunc log) +{ + fvalue_t *fv; + + fv = fvalue_new(ftype); + if (fv->ftype->val_from_string) { + if (fv->ftype->val_from_string(fv, s, log)) { + return fv; + } + } + else { + log("\"%s\" cannot be converted to %s.", + s, ftype_pretty_name(ftype)); + } + fvalue_free(fv); + return NULL; +} + +const char* +fvalue_type_name(fvalue_t *fv) +{ + return fv->ftype->name; +} + + +guint +fvalue_length(fvalue_t *fv) +{ + if (fv->ftype->len) + return fv->ftype->len(fv); + else + return fv->ftype->wire_size; +} + +/* Returns a new FT_BYTES fvalue_t* if possible, otherwise NULL */ +fvalue_t* +fvalue_slice(fvalue_t *fv, gint start, gint end) +{ + GByteArray *bytes; + guint data_length, abs_end; + guint offset=0, length=0; + fvalue_t *new_fv; + + if (!fv->ftype->slice) { + return NULL; + } + + data_length = fvalue_length(fv); + bytes = g_byte_array_new(); + + /* Find absolute start position (offset) */ + if (start < 0) { + start = data_length + start; + if (start < 0) { + offset = 0; + } + else { + offset = start; + } + } + else { + offset = start; + } + + /* Limit the offset value */ + if (offset > data_length) { + offset = data_length; + } + + /* Find absolute end position (abs_end) */ + if (end < 0) { + end = data_length + end; + if (end < 0) { + abs_end = 0; + } + else { + abs_end = end; + } + } + else { + abs_end = end; + } + + /* Limit the abs_end value */ + if (abs_end > data_length) { + abs_end = data_length; + } + + /* Does end position occur *after* start position? */ + if (abs_end > offset) { + length = abs_end - offset; + fv->ftype->slice(fv, bytes, offset, length); + } + + new_fv = fvalue_new(FT_BYTES); + fvalue_set(new_fv, bytes, TRUE); + return new_fv; +} + + +void +fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(fv->ftype->set_value); + fv->ftype->set_value(fv, value, already_copied); +} + +void +fvalue_set_integer(fvalue_t *fv, guint32 value) +{ + g_assert(fv->ftype->set_value_integer); + fv->ftype->set_value_integer(fv, value); +} + +void +fvalue_set_floating(fvalue_t *fv, gdouble value) +{ + g_assert(fv->ftype->set_value_floating); + fv->ftype->set_value_floating(fv, value); +} + + +gpointer +fvalue_get(fvalue_t *fv) +{ + g_assert(fv->ftype->get_value); + return fv->ftype->get_value(fv); +} + +guint32 +fvalue_get_integer(fvalue_t *fv) +{ + g_assert(fv->ftype->get_value_integer); + return fv->ftype->get_value_integer(fv); +} + +double +fvalue_get_floating(fvalue_t *fv) +{ + g_assert(fv->ftype->get_value_floating); + return fv->ftype->get_value_floating(fv); +} + +gboolean +fvalue_eq(fvalue_t *a, fvalue_t *b) +{ + /* XXX - check compatibility of a and b */ + g_assert(a->ftype->cmp_eq); + return a->ftype->cmp_eq(a, b); +} + +gboolean +fvalue_ne(fvalue_t *a, fvalue_t *b) +{ + /* XXX - check compatibility of a and b */ + g_assert(a->ftype->cmp_ne); + return a->ftype->cmp_ne(a, b); +} + +gboolean +fvalue_gt(fvalue_t *a, fvalue_t *b) +{ + /* XXX - check compatibility of a and b */ + g_assert(a->ftype->cmp_gt); + return a->ftype->cmp_gt(a, b); +} + +gboolean +fvalue_ge(fvalue_t *a, fvalue_t *b) +{ + /* XXX - check compatibility of a and b */ + g_assert(a->ftype->cmp_ge); + return a->ftype->cmp_ge(a, b); +} + +gboolean +fvalue_lt(fvalue_t *a, fvalue_t *b) +{ + /* XXX - check compatibility of a and b */ + g_assert(a->ftype->cmp_lt); + return a->ftype->cmp_lt(a, b); +} + +gboolean +fvalue_le(fvalue_t *a, fvalue_t *b) +{ + /* XXX - check compatibility of a and b */ + g_assert(a->ftype->cmp_le); + return a->ftype->cmp_le(a, b); +} |