aboutsummaryrefslogtreecommitdiffstats
path: root/epan/ftypes/ftypes.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/ftypes/ftypes.c')
-rw-r--r--epan/ftypes/ftypes.c410
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);
+}