diff options
Diffstat (limited to 'epan/ftypes')
-rw-r--r-- | epan/ftypes/.cvsignore | 4 | ||||
-rw-r--r-- | epan/ftypes/Makefile.am | 52 | ||||
-rw-r--r-- | epan/ftypes/ftype-bytes.c | 386 | ||||
-rw-r--r-- | epan/ftypes/ftype-double.c | 133 | ||||
-rw-r--r-- | epan/ftypes/ftype-integer.c | 417 | ||||
-rw-r--r-- | epan/ftypes/ftype-ipv4.c | 114 | ||||
-rw-r--r-- | epan/ftypes/ftype-none.c | 20 | ||||
-rw-r--r-- | epan/ftypes/ftype-string.c | 198 | ||||
-rw-r--r-- | epan/ftypes/ftype-time.c | 78 | ||||
-rw-r--r-- | epan/ftypes/ftype-tvbuff.c | 84 | ||||
-rw-r--r-- | epan/ftypes/ftypes-int.h | 60 | ||||
-rw-r--r-- | epan/ftypes/ftypes.c | 410 | ||||
-rw-r--r-- | epan/ftypes/ftypes.h | 197 |
13 files changed, 2153 insertions, 0 deletions
diff --git a/epan/ftypes/.cvsignore b/epan/ftypes/.cvsignore new file mode 100644 index 0000000000..601c4fbff4 --- /dev/null +++ b/epan/ftypes/.cvsignore @@ -0,0 +1,4 @@ +.cvsignore +.deps +Makefile +Makefile.in diff --git a/epan/ftypes/Makefile.am b/epan/ftypes/Makefile.am new file mode 100644 index 0000000000..3af23be17c --- /dev/null +++ b/epan/ftypes/Makefile.am @@ -0,0 +1,52 @@ +# Makefile.am +# Automake file for the GTK interface routines for Ethereal +# +# $Id: Makefile.am,v 1.1 2001/02/01 20:21:19 gram Exp $ +# +# Ethereal - Network traffic analyzer +# By Gerald Combs <gerald@zing.org> +# Copyright 1998 Gerald Combs +# +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# We produce an archive library. In the future, when libethereal is a +# shared library, this will be linked into libethereal. While libethereal +# is an archive library, any executable linking against libethereal will +# also need to link against libftypes. +noinst_LIBRARIES = libftypes.a + +CLEANFILES = \ + libftypes.a \ + *~ + +INCLUDES = -I$(srcdir)/../.. + +libftypes_a_SOURCES = \ + ftypes.c \ + ftypes.h \ + ftypes-int.h \ + ftype-bytes.c \ + ftype-double.c \ + ftype-integer.c \ + ftype-ipv4.c \ + ftype-none.c \ + ftype-string.c \ + ftype-time.c \ + ftype-tvbuff.c + +#EXTRA_DIST = \ +# Makefile.nmake + diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c new file mode 100644 index 0000000000..726bbbd707 --- /dev/null +++ b/epan/ftypes/ftype-bytes.c @@ -0,0 +1,386 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> +#include <string.h> +#include <ctype.h> +#include "resolv.h" + +#define ETHER_LEN 6 +#define IPv6_LEN 16 + +static void +ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length, + gboolean little_endian) +{ + /* XXX */ + g_assert_not_reached(); +} + + +static void +bytes_fvalue_new(fvalue_t *fv) +{ + fv->value.bytes = NULL; +} + +void +bytes_fvalue_free(fvalue_t *fv) +{ + if (fv->value.bytes) { + g_byte_array_free(fv->value.bytes, TRUE); + } +} + + +static void +bytes_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(already_copied); + fv->value.bytes = value; +} + +static void +common_fvalue_set(fvalue_t *fv, guint8* data, guint len) +{ + fv->value.bytes = g_byte_array_new(); + g_byte_array_append(fv->value.bytes, data, len); +} + +static void +ether_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(!already_copied); + common_fvalue_set(fv, value, ETHER_LEN); +} + +static void +ipv6_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(!already_copied); + common_fvalue_set(fv, value, IPv6_LEN); +} + +static gpointer +value_get(fvalue_t *fv) +{ + return fv->value.bytes->data; +} + +static gboolean +is_byte_sep(guint8 c) +{ + return (c == '-' || c == ':' || c == '.'); +} + +static gboolean +val_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + GByteArray *bytes; + guint8 val; + char *p, *q, *punct; + char two_digits[3]; + char one_digit[2]; + gboolean fail = FALSE; + + bytes = g_byte_array_new(); + + p = s; + while (*p) { + q = p+1; + if (*q && isxdigit(*p) && isxdigit(*q)) { + two_digits[0] = *p; + two_digits[1] = *q; + two_digits[2] = '\0'; + + val = (guint8) strtoul(two_digits, NULL, 16); + g_byte_array_append(bytes, &val, 1); + punct = q + 1; + if (*punct) { + if (is_byte_sep(*punct)) { + p = punct + 1; + continue; + } + else { + fail = TRUE; + break; + } + } + else { + p = punct; + continue; + } + } + else if (*q && isxdigit(*p) && is_byte_sep(*q)) { + one_digit[0] = *p; + one_digit[1] = '\0'; + + val = (guint8) strtoul(one_digit, NULL, 16); + g_byte_array_append(bytes, &val, 1); + p = q + 1; + continue; + } + else if (!*q && isxdigit(*p)) { + one_digit[0] = *p; + one_digit[1] = '\0'; + + val = (guint8) strtoul(one_digit, NULL, 16); + g_byte_array_append(bytes, &val, 1); + p = q; + continue; + } + else { + fail = TRUE; + break; + } + } + + if (fail) { + g_byte_array_free(bytes, TRUE); + return FALSE; + } + + fv->value.bytes = bytes; + + + return TRUE; +} + +static gboolean +ether_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + guint8 *mac; + + if (val_from_string(fv, s, log)) { + return TRUE; + } + + mac = get_ether_addr(s); + if (!mac) { + return FALSE; + } + + ether_fvalue_set(fv, mac, FALSE); + return TRUE; +} + +static gboolean +ipv6_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + guint8 buffer[16]; + + if (!get_host_ipaddr6(s, (struct e_in6_addr*)buffer)) { + return FALSE; + } + + ipv6_fvalue_set(fv, buffer, FALSE); + return TRUE; +} + +static guint +len(fvalue_t *fv) +{ + return fv->value.bytes->len; +} + +static void +slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length) +{ + guint8* data; + + data = fv->value.bytes->data + offset; + + g_byte_array_append(bytes, data, length); +} + + +static gboolean +cmp_eq(fvalue_t *fv_a, fvalue_t *fv_b) +{ + GByteArray *a = fv_a->value.bytes; + GByteArray *b = fv_b->value.bytes; + + if (a->len != b->len) { + return FALSE; + } + + return (memcmp(a->data, b->data, a->len) == 0); +} + + +static gboolean +cmp_ne(fvalue_t *fv_a, fvalue_t *fv_b) +{ + GByteArray *a = fv_a->value.bytes; + GByteArray *b = fv_b->value.bytes; + + if (a->len != b->len) { + return FALSE; + } + + return (memcmp(a->data, b->data, a->len) != 0); +} + + +static gboolean +cmp_gt(fvalue_t *fv_a, fvalue_t *fv_b) +{ + GByteArray *a = fv_a->value.bytes; + GByteArray *b = fv_b->value.bytes; + + if (a->len > b->len) { + return TRUE; + } + + if (a->len < b->len) { + return FALSE; + } + + return (memcmp(a->data, b->data, a->len) > 0); +} + +static gboolean +cmp_ge(fvalue_t *fv_a, fvalue_t *fv_b) +{ + GByteArray *a = fv_a->value.bytes; + GByteArray *b = fv_b->value.bytes; + + if (a->len > b->len) { + return TRUE; + } + + if (a->len < b->len) { + return FALSE; + } + + return (memcmp(a->data, b->data, a->len) >= 0); +} + +static gboolean +cmp_lt(fvalue_t *fv_a, fvalue_t *fv_b) +{ + GByteArray *a = fv_a->value.bytes; + GByteArray *b = fv_b->value.bytes; + + if (a->len < b->len) { + return TRUE; + } + + if (a->len > b->len) { + return FALSE; + } + + return (memcmp(a->data, b->data, a->len) < 0); +} + +static gboolean +cmp_le(fvalue_t *fv_a, fvalue_t *fv_b) +{ + GByteArray *a = fv_a->value.bytes; + GByteArray *b = fv_b->value.bytes; + + if (a->len < b->len) { + return TRUE; + } + + if (a->len > b->len) { + return FALSE; + } + + return (memcmp(a->data, b->data, a->len) <= 0); +} + +void +ftype_register_bytes(void) +{ + + static ftype_t bytes_type = { + "FT_BYTES", + "sequence of bytes", + 0, + bytes_fvalue_new, + bytes_fvalue_free, + ftype_from_tvbuff, + val_from_string, + + bytes_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + + len, + slice, + }; + + static ftype_t ether_type = { + "FT_ETHER", + "Ethernet or other MAC address", + ETHER_LEN, + bytes_fvalue_new, + bytes_fvalue_free, + ftype_from_tvbuff, + ether_from_string, + + ether_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + + len, + slice, + }; + + static ftype_t ipv6_type = { + "FT_IPv6", + "IPv6 address", + IPv6_LEN, + bytes_fvalue_new, + bytes_fvalue_free, + ftype_from_tvbuff, + ipv6_from_string, + + ipv6_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + + len, + slice, + }; + + ftype_register(FT_BYTES, &bytes_type); + ftype_register(FT_ETHER, ðer_type); + ftype_register(FT_IPv6, &ipv6_type); +} diff --git a/epan/ftypes/ftype-double.c b/epan/ftypes/ftype-double.c new file mode 100644 index 0000000000..146794a597 --- /dev/null +++ b/epan/ftypes/ftype-double.c @@ -0,0 +1,133 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> +#include <stdlib.h> +#include <math.h> +#include <errno.h> + +static void +ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length, + gboolean little_endian) +{ + /* XXX */ + g_assert_not_reached(); +} + + +static void +double_fvalue_new(fvalue_t *fv) +{ + fv->value.floating = 0.0; +} + +static void +double_fvalue_set_floating(fvalue_t *fv, gdouble value) +{ + fv->value.floating = value; +} + +static double +value_get_floating(fvalue_t *fv) +{ + return fv->value.floating; +} + +static gboolean +val_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + char *endptr = NULL; + + fv->value.floating = strtod(s, &endptr); + + if (endptr == s || *endptr != '\0') { + /* This isn't a valid number. */ + log("\"%s\" is not a valid number.", s); + return FALSE; + } + if (errno == ERANGE) { + if (fv->value.floating == 0) { + log("\"%s\" causes floating-point underflow.", s); + } + else if (fv->value.floating == HUGE_VAL) { + log("\"%s\" causes floating-point overflow.", s); + } + else { + log("\"%s\" is not a valid floating-point number.", s); + } + return FALSE; + } + + return TRUE; +} + + +static gboolean +cmp_eq(fvalue_t *a, fvalue_t *b) +{ + return a->value.floating == b->value.floating; +} + +static gboolean +cmp_ne(fvalue_t *a, fvalue_t *b) +{ + return a->value.floating != b->value.floating; +} + +static gboolean +cmp_gt(fvalue_t *a, fvalue_t *b) +{ + return a->value.floating > b->value.floating; +} + +static gboolean +cmp_ge(fvalue_t *a, fvalue_t *b) +{ + return a->value.floating >= b->value.floating; +} + +static gboolean +cmp_lt(fvalue_t *a, fvalue_t *b) +{ + return a->value.floating < b->value.floating; +} + +static gboolean +cmp_le(fvalue_t *a, fvalue_t *b) +{ + return a->value.floating <= b->value.floating; +} + +void +ftype_register_double(void) +{ + + static ftype_t double_type = { + "FT_DOUBLE", + "floating point", + 0, + double_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + NULL, + double_fvalue_set_floating, + + NULL, + NULL, + value_get_floating, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + }; + + ftype_register(FT_DOUBLE, &double_type); +} diff --git a/epan/ftypes/ftype-integer.c b/epan/ftypes/ftype-integer.c new file mode 100644 index 0000000000..cef237c7ed --- /dev/null +++ b/epan/ftypes/ftype-integer.c @@ -0,0 +1,417 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#ifdef NEED_SNPRINTF_H +#include "snprintf.h" +#endif + +#include <stdlib.h> +#include <errno.h> +#include "ftypes-int.h" +#include "resolv.h" + + +static void +ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length, + gboolean little_endian) +{ + /* XXX */ + g_assert_not_reached(); +} + + +static void +int_fvalue_new(fvalue_t *fv) +{ + fv->value.integer = 0; +} + +static void +set_integer(fvalue_t *fv, guint32 value) +{ + fv->value.integer = value; +} + +static guint32 +get_integer(fvalue_t *fv) +{ + return fv->value.integer; +} + +static gboolean +val_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + char *endptr; + + fv->value.integer = strtoul(s, &endptr, 0); + + if (endptr == s || *endptr != '\0') { + /* This isn't a valid number. */ + log("\"%s\" is not a valid number.", s); + return FALSE; + } + if (errno == ERANGE) { + if (fv->value.integer == ULONG_MAX) { + log("\"%s\" causes an integer overflow.", s); + } + else { + log("\"%s\" is not an integer.", s); + } + return FALSE; + } + + return TRUE; +} + +static gboolean +ipxnet_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + guint32 val; + gboolean known; + + if (val_from_string(fv, s, log)) { + return TRUE; + } + + val = get_ipxnet_addr(s, &known); + if (known) { + fv->value.integer = val; + return TRUE; + } + + return FALSE; +} + +static gboolean +cmp_eq(fvalue_t *a, fvalue_t *b) +{ + return a->value.integer == b->value.integer; +} + +static gboolean +cmp_ne(fvalue_t *a, fvalue_t *b) +{ + return a->value.integer != b->value.integer; +} + +static gboolean +u_cmp_gt(fvalue_t *a, fvalue_t *b) +{ + return (int)a->value.integer > (int)b->value.integer; +} + +static gboolean +u_cmp_ge(fvalue_t *a, fvalue_t *b) +{ + return (int)a->value.integer >= (int)b->value.integer; +} + +static gboolean +u_cmp_lt(fvalue_t *a, fvalue_t *b) +{ + return (int)a->value.integer < (int)b->value.integer; +} + +static gboolean +u_cmp_le(fvalue_t *a, fvalue_t *b) +{ + return (int)a->value.integer <= (int)b->value.integer; +} + +static gboolean +s_cmp_gt(fvalue_t *a, fvalue_t *b) +{ + return a->value.integer > b->value.integer; +} + +static gboolean +s_cmp_ge(fvalue_t *a, fvalue_t *b) +{ + return a->value.integer >= b->value.integer; +} + +static gboolean +s_cmp_lt(fvalue_t *a, fvalue_t *b) +{ + return a->value.integer < b->value.integer; +} + +static gboolean +s_cmp_le(fvalue_t *a, fvalue_t *b) +{ + return a->value.integer <= b->value.integer; +} + +/* BOOLEAN-specific */ + +static void +boolean_fvalue_new(fvalue_t *fv) +{ + fv->value.integer = TRUE; +} + + + + + +void +ftype_register_integers(void) +{ + + static ftype_t uint8_type = { + "FT_UINT8", + "unsigned, 1 byte", + 1, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + u_cmp_gt, + u_cmp_ge, + u_cmp_lt, + u_cmp_le, + }; + static ftype_t uint16_type = { + "FT_UINT16", + "unsigned, 2 bytes", + 2, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + u_cmp_gt, + u_cmp_ge, + u_cmp_lt, + u_cmp_le, + }; + static ftype_t uint24_type = { + "FT_UINT24", + "unsigned, 3 bytes", + 3, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + u_cmp_gt, + u_cmp_ge, + u_cmp_lt, + u_cmp_le, + }; + static ftype_t uint32_type = { + "FT_UINT32", + "unsigned, 4 bytes", + 4, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + u_cmp_gt, + u_cmp_ge, + u_cmp_lt, + u_cmp_le, + }; + static ftype_t int8_type = { + "FT_INT8", + "signed, 1 byte", + 1, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + s_cmp_gt, + s_cmp_ge, + s_cmp_lt, + s_cmp_le, + }; + static ftype_t int16_type = { + "FT_INT16", + "signed, 2 bytes", + 2, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + s_cmp_gt, + s_cmp_ge, + s_cmp_lt, + s_cmp_le, + }; + static ftype_t int24_type = { + "FT_INT24", + "signed, 3 bytes", + 3, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + s_cmp_gt, + s_cmp_ge, + s_cmp_lt, + s_cmp_le, + }; + static ftype_t int32_type = { + "FT_INT32", + "signed, 4 bytes", + 4, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + s_cmp_gt, + s_cmp_ge, + s_cmp_lt, + s_cmp_le, + }; + static ftype_t boolean_type = { + "FT_BOOLEAN", + "Boolean", + 0, + boolean_fvalue_new, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + u_cmp_gt, + u_cmp_ge, + u_cmp_lt, + u_cmp_le, + }; + + static ftype_t ipxnet_type = { + "FT_IPXNET", + "IPX network number", + 4, + int_fvalue_new, + NULL, + ftype_from_tvbuff, + ipxnet_from_string, + + NULL, + set_integer, + NULL, + + NULL, + get_integer, + NULL, + + cmp_eq, + cmp_ne, + u_cmp_gt, + u_cmp_ge, + u_cmp_lt, + u_cmp_le, + }; + + + ftype_register(FT_UINT8, &uint8_type); + ftype_register(FT_UINT16, &uint16_type); + ftype_register(FT_UINT24, &uint24_type); + ftype_register(FT_UINT32, &uint32_type); + ftype_register(FT_INT8, &int8_type); + ftype_register(FT_INT16, &int16_type); + ftype_register(FT_INT24, &int24_type); + ftype_register(FT_INT32, &int32_type); + ftype_register(FT_BOOLEAN, &boolean_type); + ftype_register(FT_IPXNET, &ipxnet_type); +} diff --git a/epan/ftypes/ftype-ipv4.c b/epan/ftypes/ftype-ipv4.c new file mode 100644 index 0000000000..eae5677a25 --- /dev/null +++ b/epan/ftypes/ftype-ipv4.c @@ -0,0 +1,114 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> +#include "ipv4.h" +#include "resolv.h" + +static void +ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length, + gboolean little_endian) +{ + /* XXX */ + g_assert_not_reached(); +} + + + +static void +set_integer(fvalue_t *fv, guint32 value) +{ + ipv4_addr_set_net_order_addr(&(fv->value.ipv4), value); + ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32); +} + +static gpointer +value_get(fvalue_t *fv) +{ + return &(fv->value.ipv4); +} + +static gboolean +val_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + guint32 addr; + + if (!get_host_ipaddr(s, &addr)) { + log("\"%s\" is not a valid hostname or IPv4 address.", s); + return FALSE; + } + ipv4_addr_set_host_order_addr(&(fv->value.ipv4), addr); + /*ipv4_addr_set_netmask_bits(&node->value.ipv4, nmask_bits);*/ + ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32); + return TRUE; +} + +static gboolean +cmp_eq(fvalue_t *a, fvalue_t *b) +{ + return ipv4_addr_eq(&a->value.ipv4, &b->value.ipv4); +} + +static gboolean +cmp_ne(fvalue_t *a, fvalue_t *b) +{ + return ipv4_addr_ne(&a->value.ipv4, &b->value.ipv4); +} + +static gboolean +cmp_gt(fvalue_t *a, fvalue_t *b) +{ + return ipv4_addr_gt(&a->value.ipv4, &b->value.ipv4); +} + +static gboolean +cmp_ge(fvalue_t *a, fvalue_t *b) +{ + return ipv4_addr_ge(&a->value.ipv4, &b->value.ipv4); +} + +static gboolean +cmp_lt(fvalue_t *a, fvalue_t *b) +{ + return ipv4_addr_lt(&a->value.ipv4, &b->value.ipv4); +} + +static gboolean +cmp_le(fvalue_t *a, fvalue_t *b) +{ + return ipv4_addr_le(&a->value.ipv4, &b->value.ipv4); +} + +void +ftype_register_ipv4(void) +{ + + static ftype_t ipv4_type = { + "FT_IPv4", + "IPv4 address", + 4, + NULL, + NULL, + ftype_from_tvbuff, + val_from_string, + + NULL, + set_integer, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + }; + + ftype_register(FT_IPv4, &ipv4_type); +} diff --git a/epan/ftypes/ftype-none.c b/epan/ftypes/ftype-none.c new file mode 100644 index 0000000000..1bb64a3759 --- /dev/null +++ b/epan/ftypes/ftype-none.c @@ -0,0 +1,20 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> + + +void +ftype_register_none(void) +{ + + static ftype_t none_type = { + "FT_NONE", + "label", + 0, + }; + + ftype_register(FT_NONE, &none_type); +} diff --git a/epan/ftypes/ftype-string.c b/epan/ftypes/ftype-string.c new file mode 100644 index 0000000000..38ce87faa0 --- /dev/null +++ b/epan/ftypes/ftype-string.c @@ -0,0 +1,198 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> +#include <string.h> + +static void +ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length, + gboolean little_endian) +{ + /* XXX */ + g_assert_not_reached(); +} + + +static void +string_fvalue_new(fvalue_t *fv) +{ + fv->value.string = NULL; +} + +static void +string_fvalue_free(fvalue_t *fv) +{ + if (fv->value.string) { + g_free(fv->value.string); + } +} + +static void +string_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + if (already_copied) { + fv->value.string = value; + } + else { + fv->value.string = g_strdup(value); + } +} + +static gpointer +value_get(fvalue_t *fv) +{ + return fv->value.string; +} + +static gboolean +val_from_string(fvalue_t *fv, char *s, LogFunc log) +{ + fv->value.string = g_strdup(s); + return TRUE; +} + +static guint +len(fvalue_t *fv) +{ + return strlen(fv->value.string); +} + +static void +slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length) +{ + guint8* data; + + data = fv->value.string + offset; + + g_byte_array_append(bytes, data, length); +} + + +static gboolean +cmp_eq(fvalue_t *a, fvalue_t *b) +{ + return (strcmp(a->value.string, b->value.string) == 0); +} + +static gboolean +cmp_ne(fvalue_t *a, fvalue_t *b) +{ + return (strcmp(a->value.string, b->value.string) != 0); +} + +static gboolean +cmp_gt(fvalue_t *a, fvalue_t *b) +{ + return (strcmp(a->value.string, b->value.string) > 0); +} + +static gboolean +cmp_ge(fvalue_t *a, fvalue_t *b) +{ + return (strcmp(a->value.string, b->value.string) >= 0); +} + +static gboolean +cmp_lt(fvalue_t *a, fvalue_t *b) +{ + return (strcmp(a->value.string, b->value.string) < 0); +} + +static gboolean +cmp_le(fvalue_t *a, fvalue_t *b) +{ + return (strcmp(a->value.string, b->value.string) <= 0); +} + +void +ftype_register_string(void) +{ + + static ftype_t string_type = { + "FT_STRING", + "character string", + 0, + string_fvalue_new, + string_fvalue_free, + ftype_from_tvbuff, + val_from_string, + + string_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + + len, + slice, + }; + static ftype_t stringz_type = { + "FT_STRINGZ", + "character string", + 0, + string_fvalue_new, + string_fvalue_free, + ftype_from_tvbuff, + val_from_string, + + string_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + + len, + slice, + }; + static ftype_t uint_string_type = { + "FT_UINT_STRING", + "character string", + 0, + string_fvalue_new, + string_fvalue_free, + ftype_from_tvbuff, + val_from_string, + + string_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + + len, + slice, + }; + + ftype_register(FT_STRING, &string_type); + ftype_register(FT_STRINGZ, &stringz_type); + ftype_register(FT_UINT_STRING, &uint_string_type); +} diff --git a/epan/ftypes/ftype-time.c b/epan/ftypes/ftype-time.c new file mode 100644 index 0000000000..6eb2a3d4cb --- /dev/null +++ b/epan/ftypes/ftype-time.c @@ -0,0 +1,78 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> + +static void +ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length, + gboolean little_endian) +{ + /* XXX */ + g_assert_not_reached(); +} + + +static void +time_fvalue_new(fvalue_t *fv) +{ + fv->value.time.tv_sec = 0; + fv->value.time.tv_usec = 0; +} + +static void +time_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(!already_copied); + memcpy(&(fv->value.time), value, sizeof(struct timeval)); +} + +static gpointer +value_get(fvalue_t *fv) +{ + return &(fv->value.time); +} + +void +ftype_register_time(void) +{ + + static ftype_t abstime_type = { + "FT_ABSOLUTE_TIME", + "date/time", + 0, + time_fvalue_new, + NULL, + ftype_from_tvbuff, + NULL, + + time_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL + }; + static ftype_t reltime_type = { + "FT_RELATIVE_TIME", + "time offset", + 0, + time_fvalue_new, + NULL, + ftype_from_tvbuff, + NULL, + + time_fvalue_set, + NULL, + NULL, + + value_get, + NULL, + NULL + }; + + ftype_register(FT_ABSOLUTE_TIME, &abstime_type); + ftype_register(FT_RELATIVE_TIME, &reltime_type); +} diff --git a/epan/ftypes/ftype-tvbuff.c b/epan/ftypes/ftype-tvbuff.c new file mode 100644 index 0000000000..e9617ca607 --- /dev/null +++ b/epan/ftypes/ftype-tvbuff.c @@ -0,0 +1,84 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ftypes-int.h> +#include "gdebug.h" + +static void +value_new(fvalue_t *fv) +{ + fv->value.tvb = NULL; +} + + +static void +value_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(already_copied); + fv->value.tvb = value; +} + +static gpointer +value_get(fvalue_t *fv) +{ + return fv->value.tvb; +} + +static guint +len(fvalue_t *fv) +{ + if (fv->value.tvb) + return tvb_length(fv->value.tvb); + else + return 0; +} + +static void +slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length) +{ + guint8* data; + + if (fv->value.tvb) { + data = tvb_get_ptr(fv->value.tvb, offset, length); + g_byte_array_append(bytes, data, length); + } +} + +void +ftype_register_tvbuff(void) +{ + + static ftype_t protocol_type = { + "FT_PROTOCOL", + "protocol", + 0, + value_new, + NULL, + NULL, + NULL, + + value_set, + NULL, + NULL, + + value_get, + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + len, + slice, + + }; + + + ftype_register(FT_PROTOCOL, &protocol_type); +} diff --git a/epan/ftypes/ftypes-int.h b/epan/ftypes/ftypes-int.h new file mode 100644 index 0000000000..4e6ce75bee --- /dev/null +++ b/epan/ftypes/ftypes-int.h @@ -0,0 +1,60 @@ +#ifndef FTYPES_INT_H +#define FTYPES_INT_H + +#include "packet.h" +#include "ftypes.h" + +typedef void (*FtypeFromTvbuffFunc)(field_info*, tvbuff_t*, int, int, gboolean); +typedef void (*FvalueNewFunc)(fvalue_t*); +typedef void (*FvalueFreeFunc)(fvalue_t*); + +typedef gboolean (*FvalueFromString)(fvalue_t*, char*, LogFunc); + +typedef void (*FvalueSetFunc)(fvalue_t*, gpointer, gboolean); +typedef void (*FvalueSetIntegerFunc)(fvalue_t*, guint32); +typedef void (*FvalueSetFloatingFunc)(fvalue_t*, gdouble); + +typedef gpointer (*FvalueGetFunc)(fvalue_t*); +typedef guint32 (*FvalueGetIntegerFunc)(fvalue_t*); +typedef double (*FvalueGetFloatingFunc)(fvalue_t*); + +typedef gboolean (*FvalueCmp)(fvalue_t*, fvalue_t*); + +typedef guint (*FvalueLen)(fvalue_t*); +typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint, guint); + +struct _ftype_t { + const char *name; + const char *pretty_name; + int wire_size; + FvalueNewFunc new_value; + FvalueFreeFunc free_value; + FtypeFromTvbuffFunc from_tvbuff; + FvalueFromString val_from_string; + + /* could be union */ + FvalueSetFunc set_value; + FvalueSetIntegerFunc set_value_integer; + FvalueSetFloatingFunc set_value_floating; + + /* could be union */ + FvalueGetFunc get_value; + FvalueGetIntegerFunc get_value_integer; + FvalueGetFloatingFunc get_value_floating; + + FvalueCmp cmp_eq; + FvalueCmp cmp_ne; + FvalueCmp cmp_gt; + FvalueCmp cmp_ge; + FvalueCmp cmp_lt; + FvalueCmp cmp_le; + + FvalueLen len; + FvalueSlice slice; +}; + + +void +ftype_register(enum ftenum ftype, ftype_t *ft); + +#endif 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); +} diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h new file mode 100644 index 0000000000..1431f35427 --- /dev/null +++ b/epan/ftypes/ftypes.h @@ -0,0 +1,197 @@ +/* ftypes.h + * Definitions for field types + * + * $Id: ftypes.h,v 1.1 2001/02/01 20:21:19 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.org> + * Copyright 2001 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef FTYPES_H +#define FTYPES_H + +#include <glib.h> + + +/* field types */ +enum ftenum { + FT_NONE, /* used for text labels with no value */ + FT_PROTOCOL, + FT_BOOLEAN, /* TRUE and FALSE come from <glib.h> */ + FT_UINT8, + FT_UINT16, + FT_UINT24, /* really a UINT32, but displayed as 3 hex-digits if FD_HEX*/ + FT_UINT32, + FT_INT8, + FT_INT16, + FT_INT24, + FT_INT32, + FT_DOUBLE, + FT_ABSOLUTE_TIME, + FT_RELATIVE_TIME, + FT_STRING, + FT_STRINGZ, /* for use with proto_tree_add_item() */ + FT_UINT_STRING, /* for use with proto_tree_add_item() */ + FT_ETHER, + FT_BYTES, + FT_IPv4, + FT_IPv6, + FT_IPXNET, +/* FT_TEXT_ONLY,*/ /* non-filterable, used when converting ethereal + from old-style proto_tree to new-style proto_tree */ + FT_NUM_TYPES /* last item number plus one */ +}; + +typedef enum ftenum ftenum_t; +typedef struct _ftype_t ftype_t; + +/* Initialize the ftypes subsytem. Called once. */ +void +ftypes_initialize(void); + +/* Cleanup the ftypes subsystem. Called once. */ +void +ftypes_cleanup(void); + + +/* ---------------- FTYPE ----------------- */ + +/* Return a string representing the name of the type */ +const char* +ftype_name(ftenum_t ftype); + +/* Return a string presenting a "pretty" representation of the + * name of the type. The pretty name means more to the user than + * that "FT_*" name. */ +const char* +ftype_pretty_name(ftenum_t ftype); + +/* Returns length of field in packet, or 0 if not determinable/defined. */ +int +ftype_length(ftenum_t ftype); + +gboolean +ftype_can_slice(enum ftenum ftype); + +gboolean +ftype_can_eq(enum ftenum ftype); + +gboolean +ftype_can_ne(enum ftenum ftype); + +gboolean +ftype_can_gt(enum ftenum ftype); + +gboolean +ftype_can_ge(enum ftenum ftype); + +gboolean +ftype_can_lt(enum ftenum ftype); + +gboolean +ftype_can_le(enum ftenum ftype); + +/* ---------------- FVALUE ----------------- */ + +#include "ipv4.h" + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_WINSOCK_H +#include <winsock.h> +#endif + +#include "tvbuff.h" + +typedef struct { + ftype_t *ftype; + union { + /* Put a few basic types in here */ + gpointer pointer; + guint32 integer; + gdouble floating; + gchar *string; + GByteArray *bytes; + ipv4_addr ipv4; + guint8 ipv6[16]; + struct timeval time; + tvbuff_t *tvb; + } value; +} fvalue_t; + +fvalue_t* +fvalue_new(ftenum_t ftype); + +void +fvalue_free(fvalue_t *fv); + +typedef void (*LogFunc)(char*,...); + +fvalue_t* +fvalue_from_string(ftenum_t ftype, char *s, LogFunc log); + +const char* +fvalue_type_name(fvalue_t *fv); + +void +fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied); + +void +fvalue_set_integer(fvalue_t *fv, guint32 value); + +void +fvalue_set_floating(fvalue_t *fv, gdouble value); + +gpointer +fvalue_get(fvalue_t *fv); + +guint32 +fvalue_get_integer(fvalue_t *fv); + +double +fvalue_get_floating(fvalue_t *fv); + +gboolean +fvalue_eq(fvalue_t *a, fvalue_t *b); + +gboolean +fvalue_ne(fvalue_t *a, fvalue_t *b); + +gboolean +fvalue_gt(fvalue_t *a, fvalue_t *b); + +gboolean +fvalue_ge(fvalue_t *a, fvalue_t *b); + +gboolean +fvalue_lt(fvalue_t *a, fvalue_t *b); + +gboolean +fvalue_le(fvalue_t *a, fvalue_t *b); + +guint +fvalue_length(fvalue_t *fv); + +fvalue_t* +fvalue_slice(fvalue_t *fv, gint start, gint end); + +#endif /* ftypes.h */ |