regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / ftypes / ftypes.c
blob2097e09ce315c5425d770540e200c898520d0366
1 /*
2 * Wireshark - Network traffic analyzer
3 * By Gerald Combs <gerald@wireshark.org>
4 * Copyright 2001 Gerald Combs
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 #include "config.h"
11 #include "ftypes-int.h"
13 #include <wsutil/ws_assert.h>
15 /* Keep track of ftype_t's via their ftenum number */
16 const ftype_t* type_list[FT_ENUM_SIZE + 1];
18 /* Initialize the ftype module. */
19 void
20 ftypes_initialize(void)
22 ftype_register_bytes();
23 ftype_register_double();
24 ftype_register_ieee_11073_float();
25 ftype_register_integers();
26 ftype_register_ipv4();
27 ftype_register_ipv6();
28 ftype_register_guid();
29 ftype_register_none();
30 ftype_register_string();
31 ftype_register_time();
32 ftype_register_tvbuff();
35 void
36 ftypes_register_pseudofields(void)
38 static int proto_ftypes;
40 proto_ftypes = proto_register_protocol(
41 "Wireshark Field/Fundamental Types",
42 "Wireshark FTypes",
43 "_ws.ftypes");
45 ftype_register_pseudofields_bytes(proto_ftypes);
46 ftype_register_pseudofields_double(proto_ftypes);
47 ftype_register_pseudofields_ieee_11073_float(proto_ftypes);
48 ftype_register_pseudofields_integer(proto_ftypes);
49 ftype_register_pseudofields_ipv4(proto_ftypes);
50 ftype_register_pseudofields_ipv6(proto_ftypes);
51 ftype_register_pseudofields_guid(proto_ftypes);
52 ftype_register_pseudofields_none(proto_ftypes);
53 ftype_register_pseudofields_string(proto_ftypes);
54 ftype_register_pseudofields_time(proto_ftypes);
55 ftype_register_pseudofields_tvbuff(proto_ftypes);
57 proto_set_cant_toggle(proto_ftypes);
60 /* Each ftype_t is registered via this function */
61 void
62 ftype_register(enum ftenum ftype, const ftype_t *ft)
64 /* Check input */
65 ws_assert(ftype < FT_NUM_TYPES);
66 ws_assert(ftype == ft->ftype);
68 /* Don't re-register. */
69 ws_assert(type_list[ftype] == NULL);
71 type_list[ftype] = ft;
75 /* from README.dissector:
76 Note that the formats used must all belong to the same list as defined below:
77 - FT_INT8, FT_INT16, FT_INT24 and FT_INT32, FT_CHAR, FT_UINT8, FT_UINT16,
78 FT_UINT24, FT_UINT32, FT_IPXNET, FT_FRAMENUM, FT_INT40, FT_INT48, FT_INT56
79 FT_INT64, FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64 and FT_EUI64
80 - FT_ABSOLUTE_TIME and FT_RELATIVE_TIME
81 - FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, FT_STRINGZTRUNC, and FT_AX25
82 - FT_FLOAT, FT_DOUBLE, FT_IEEE_11073_SFLOAT and FT_IEEE_11073_FLOAT
83 - FT_BYTES, FT_UINT_BYTES, FT_ETHER, FT_VINES and FT_FCWWN
84 - FT_OID, FT_REL_OID and FT_SYSTEM_ID
86 We thus divide the types into equivalence classes of compatible types.
87 The same field abbreviation can be used by more than one field, even of
88 different types, so long as the types are compatible.
90 This function returns the canonical representative of a type. It can
91 be used to check if two fields are compatible.
93 XXX - Currently epan/dfilter/semcheck.c has its own implementation of
94 compatible types.
96 static enum ftenum
97 same_ftype(const enum ftenum ftype)
99 switch (ftype) {
100 case FT_INT8:
101 case FT_INT16:
102 case FT_INT24:
103 case FT_INT32:
104 case FT_CHAR:
105 case FT_UINT8:
106 case FT_UINT16:
107 case FT_UINT24:
108 case FT_UINT32:
109 case FT_IPXNET:
110 case FT_FRAMENUM:
111 case FT_INT40:
112 case FT_INT48:
113 case FT_INT56:
114 case FT_INT64:
115 case FT_UINT40:
116 case FT_UINT48:
117 case FT_UINT56:
118 case FT_UINT64:
119 case FT_EUI64: /* Really byte strings, but in ZigBee are stored in reverse order / Little-Endian so treated as integer */
120 return FT_UINT64;
122 case FT_STRING:
123 case FT_STRINGZ:
124 case FT_UINT_STRING:
125 case FT_STRINGZPAD:
126 case FT_STRINGZTRUNC:
127 case FT_AX25:
128 return FT_STRING;
130 case FT_FLOAT:
131 case FT_DOUBLE:
132 return FT_DOUBLE;
134 case FT_BYTES:
135 case FT_UINT_BYTES:
136 case FT_ETHER:
137 case FT_VINES:
138 case FT_FCWWN:
139 return FT_BYTES;
141 case FT_OID:
142 case FT_REL_OID:
143 case FT_SYSTEM_ID:
144 /* XXX - dfilter/semcheck.c treats this group as compatible with BYTES */
145 return FT_OID;
147 /* XXX: the following are unique for now */
148 case FT_IPv4:
149 case FT_IPv6:
150 case FT_IEEE_11073_SFLOAT: /* XXX - should be able to compare with DOUBLE (#19011) */
151 case FT_IEEE_11073_FLOAT: /* XXX - should be able to compare with DOUBLE */
153 /* everything else is unique */
154 /* XXX - README.dissector claims the time types are compatible. */
155 default:
156 return ftype;
160 /* given two types, are they similar - for example can two
161 * duplicate fields be registered of these two types. */
162 bool
163 ftype_similar_types(const enum ftenum ftype_a, const enum ftenum ftype_b)
165 return (same_ftype(ftype_a) == same_ftype(ftype_b));
168 /* Returns a string representing the name of the type. Useful
169 * for glossary production. */
170 const char*
171 ftype_name(enum ftenum ftype)
173 const ftype_t *ft;
174 const char *s = "(null)";
176 FTYPE_LOOKUP(ftype, ft);
177 switch (ft->ftype) {
178 case FT_NONE: s = "FT_NONE"; break;
179 case FT_PROTOCOL: s = "FT_PROTOCOL"; break;
180 case FT_BOOLEAN: s = "FT_BOOLEAN"; break;
181 case FT_CHAR: s = "FT_CHAR"; break;
182 case FT_UINT8: s = "FT_UINT8"; break;
183 case FT_UINT16: s = "FT_UINT16"; break;
184 case FT_UINT24: s = "FT_UINT24"; break;
185 case FT_UINT32: s = "FT_UINT32"; break;
186 case FT_UINT40: s = "FT_UINT40"; break;
187 case FT_UINT48: s = "FT_UINT48"; break;
188 case FT_UINT56: s = "FT_UINT56"; break;
189 case FT_UINT64: s = "FT_UINT64"; break;
190 case FT_INT8: s = "FT_INT8"; break;
191 case FT_INT16: s = "FT_INT16"; break;
192 case FT_INT24: s = "FT_INT24"; break;
193 case FT_INT32: s = "FT_INT32"; break;
194 case FT_INT40: s = "FT_INT40"; break;
195 case FT_INT48: s = "FT_INT48"; break;
196 case FT_INT56: s = "FT_INT56"; break;
197 case FT_INT64: s = "FT_INT64"; break;
198 case FT_IEEE_11073_SFLOAT: s = "FT_IEEE_11073_SFLOAT"; break;
199 case FT_IEEE_11073_FLOAT: s = "FT_IEEE_11073_FLOAT"; break;
200 case FT_FLOAT: s = "FT_FLOAT"; break;
201 case FT_DOUBLE: s = "FT_DOUBLE"; break;
202 case FT_ABSOLUTE_TIME: s = "FT_ABSOLUTE_TIME"; break;
203 case FT_RELATIVE_TIME: s = "FT_RELATIVE_TIME"; break;
204 case FT_STRING: s = "FT_STRING"; break;
205 case FT_STRINGZ: s = "FT_STRINGZ"; break;
206 case FT_UINT_STRING: s = "FT_UINT_STRING"; break;
207 case FT_ETHER: s = "FT_ETHER"; break;
208 case FT_BYTES: s = "FT_BYTES"; break;
209 case FT_UINT_BYTES: s = "FT_UINT_BYTES"; break;
210 case FT_IPv4: s = "FT_IPv4"; break;
211 case FT_IPv6: s = "FT_IPv6"; break;
212 case FT_IPXNET: s = "FT_IPXNET"; break;
213 case FT_FRAMENUM: s = "FT_FRAMENUM"; break;
214 case FT_GUID: s = "FT_GUID"; break;
215 case FT_OID: s = "FT_OID"; break;
216 case FT_EUI64: s = "FT_EUI64"; break;
217 case FT_AX25: s = "FT_AX25"; break;
218 case FT_VINES: s = "FT_VINES"; break;
219 case FT_REL_OID: s = "FT_REL_OID"; break;
220 case FT_SYSTEM_ID: s = "FT_SYSTEM_ID"; break;
221 case FT_STRINGZPAD: s = "FT_STRINGZPAD"; break;
222 case FT_FCWWN: s = "FT_FCWWN"; break;
223 case FT_STRINGZTRUNC: s = "FT_STRINGZTRUNC"; break;
224 case FT_NUM_TYPES: s = "FT_NUM_TYPES"; break;
225 case FT_SCALAR: s = "FT_SCALAR"; break;
227 return s;
230 const char*
231 ftype_pretty_name(enum ftenum ftype)
233 const ftype_t *ft;
234 const char *s = "(null)";
236 FTYPE_LOOKUP(ftype, ft);
237 switch (ft->ftype) {
238 case FT_NONE: s = "Label"; break;
239 case FT_PROTOCOL: s = "Protocol"; break;
240 case FT_BOOLEAN: s = "Boolean"; break;
241 case FT_CHAR: s = "Character (8 bits)"; break;
242 case FT_UINT8: s = "Unsigned integer (8 bits)"; break;
243 case FT_UINT16: s = "Unsigned integer (16 bits)"; break;
244 case FT_UINT24: s = "Unsigned integer (24 bits)"; break;
245 case FT_UINT32: s = "Unsigned integer (32 bits)"; break;
246 case FT_UINT40: s = "Unsigned integer (40 bits)"; break;
247 case FT_UINT48: s = "Unsigned integer (48 bits)"; break;
248 case FT_UINT56: s = "Unsigned integer (56 bits)"; break;
249 case FT_UINT64: s = "Unsigned integer (64 bits)"; break;
250 case FT_INT8: s = "Signed integer (8 bits)"; break;
251 case FT_INT16: s = "Signed integer (16 bits)"; break;
252 case FT_INT24: s = "Signed integer (24 bits)"; break;
253 case FT_INT32: s = "Signed integer (32 bits)"; break;
254 case FT_INT40: s = "Signed integer (40 bits)"; break;
255 case FT_INT48: s = "Signed integer (48 bits)"; break;
256 case FT_INT56: s = "Signed integer (56 bits)"; break;
257 case FT_INT64: s = "Signed integer (64 bits)"; break;
258 case FT_IEEE_11073_SFLOAT: s = "IEEE-11073 floating point (16-bit)"; break;
259 case FT_IEEE_11073_FLOAT: s = "IEEE-11073 Floating point (32-bit)"; break;
260 case FT_FLOAT: s = "Floating point (single-precision)"; break;
261 case FT_DOUBLE: s = "Floating point (double-precision)"; break;
262 case FT_ABSOLUTE_TIME: s = "Date and time"; break;
263 case FT_RELATIVE_TIME: s = "Time offset"; break;
264 case FT_STRING: s = "Character string"; break;
265 case FT_STRINGZ: s = "Character string"; break;
266 case FT_UINT_STRING: s = "Character string"; break;
267 case FT_ETHER: s = "Ethernet or other MAC address"; break;
268 case FT_BYTES: s = "Byte sequence"; break;
269 case FT_UINT_BYTES: s = "Byte sequence"; break;
270 case FT_IPv4: s = "IPv4 address"; break;
271 case FT_IPv6: s = "IPv6 address"; break;
272 case FT_IPXNET: s = "IPX network number"; break;
273 case FT_FRAMENUM: s = "Frame number"; break;
274 case FT_GUID: s = "Globally Unique Identifier"; break;
275 case FT_OID: s = "ASN.1 object identifier"; break;
276 case FT_EUI64: s = "EUI64 address"; break;
277 case FT_AX25: s = "AX.25 address"; break;
278 case FT_VINES: s = "VINES address"; break;
279 case FT_REL_OID: s = "ASN.1 relative object identifier"; break;
280 case FT_SYSTEM_ID: s = "OSI System-ID"; break;
281 case FT_STRINGZPAD: s = "Character string"; break;
282 case FT_FCWWN: s = "Fibre Channel WWN"; break;
283 case FT_STRINGZTRUNC: s = "Character string"; break;
284 case FT_NUM_TYPES: s = "(num types)"; break;
285 case FT_SCALAR: s = "Scalar"; break;
287 return s;
291 ftype_wire_size(enum ftenum ftype)
293 const ftype_t *ft;
295 FTYPE_LOOKUP(ftype, ft);
296 return ft->wire_size;
299 bool
300 ftype_can_length(enum ftenum ftype)
302 const ftype_t *ft;
304 FTYPE_LOOKUP(ftype, ft);
305 return ft->len ? true : false;
308 bool
309 ftype_can_slice(enum ftenum ftype)
311 const ftype_t *ft;
313 FTYPE_LOOKUP(ftype, ft);
314 return ft->slice ? true : false;
317 bool
318 ftype_can_eq(enum ftenum ftype)
320 const ftype_t *ft;
322 FTYPE_LOOKUP(ftype, ft);
323 return ft->compare != NULL;
326 bool
327 ftype_can_cmp(enum ftenum ftype)
329 const ftype_t *ft;
331 FTYPE_LOOKUP(ftype, ft);
332 return ft->compare != NULL;
335 bool
336 ftype_can_bitwise_and(enum ftenum ftype)
338 const ftype_t *ft;
340 FTYPE_LOOKUP(ftype, ft);
341 return ft->bitwise_and ? true : false;
344 bool
345 ftype_can_unary_minus(enum ftenum ftype)
347 const ftype_t *ft;
349 FTYPE_LOOKUP(ftype, ft);
350 return ft->unary_minus != NULL;
353 bool
354 ftype_can_add(enum ftenum ftype)
356 const ftype_t *ft;
358 FTYPE_LOOKUP(ftype, ft);
359 return ft->add != NULL;
362 bool
363 ftype_can_subtract(enum ftenum ftype)
365 const ftype_t *ft;
367 FTYPE_LOOKUP(ftype, ft);
368 return ft->subtract != NULL;
371 bool
372 ftype_can_multiply(enum ftenum ftype)
374 const ftype_t *ft;
376 FTYPE_LOOKUP(ftype, ft);
377 return ft->multiply != NULL;
380 bool
381 ftype_can_divide(enum ftenum ftype)
383 const ftype_t *ft;
385 FTYPE_LOOKUP(ftype, ft);
386 return ft->divide != NULL;
389 bool
390 ftype_can_modulo(enum ftenum ftype)
392 const ftype_t *ft;
394 FTYPE_LOOKUP(ftype, ft);
395 return ft->modulo != NULL;
398 bool
399 ftype_can_contains(enum ftenum ftype)
401 const ftype_t *ft;
403 FTYPE_LOOKUP(ftype, ft);
404 return ft->contains ? true : false;
407 bool
408 ftype_can_matches(enum ftenum ftype)
410 const ftype_t *ft;
412 FTYPE_LOOKUP(ftype, ft);
413 return ft->matches ? true : false;
416 bool
417 ftype_can_is_zero(enum ftenum ftype)
419 const ftype_t *ft;
421 FTYPE_LOOKUP(ftype, ft);
422 return ft->is_zero ? true : false;
425 bool
426 ftype_can_is_negative(enum ftenum ftype)
428 const ftype_t *ft;
430 FTYPE_LOOKUP(ftype, ft);
431 return ft->is_negative ? true : false;
434 bool
435 ftype_can_val_to_sinteger(enum ftenum ftype)
437 const ftype_t *ft;
439 FTYPE_LOOKUP(ftype, ft);
440 /* We first convert to 64 bit and then check for overflow. */
441 return ft->val_to_sinteger64 ? true : false;
444 bool
445 ftype_can_val_to_uinteger(enum ftenum ftype)
447 const ftype_t *ft;
449 FTYPE_LOOKUP(ftype, ft);
450 /* We first convert to 64 bit and then check for overflow. */
451 return ft->val_to_uinteger64 ? true : false;
454 bool
455 ftype_can_val_to_sinteger64(enum ftenum ftype)
457 const ftype_t *ft;
459 FTYPE_LOOKUP(ftype, ft);
460 return ft->val_to_sinteger64 ? true : false;
463 bool
464 ftype_can_val_to_uinteger64(enum ftenum ftype)
466 const ftype_t *ft;
468 FTYPE_LOOKUP(ftype, ft);
469 return ft->val_to_uinteger64 ? true : false;
472 bool
473 ftype_can_val_to_double(enum ftenum ftype)
475 const ftype_t *ft;
477 FTYPE_LOOKUP(ftype, ft);
478 /* We first convert to 64 bit and then check for overflow. */
479 return ft->val_to_double ? true : false;
482 /* ---------------------------------------------------------- */
484 /* Allocate and initialize an fvalue_t, given an ftype */
485 fvalue_t*
486 fvalue_new(ftenum_t ftype)
488 fvalue_t *fv;
489 const ftype_t *ft;
490 FvalueNewFunc new_value;
492 fv = g_slice_new(fvalue_t);
494 FTYPE_LOOKUP(ftype, ft);
495 fv->ftype = ft;
497 new_value = ft->new_value;
498 if (new_value) {
499 new_value(fv);
502 return fv;
505 fvalue_t*
506 fvalue_dup(const fvalue_t *fv_orig)
508 fvalue_t *fv_new;
509 FvalueCopyFunc copy_value;
511 fv_new = g_slice_new(fvalue_t);
512 fv_new->ftype = fv_orig->ftype;
513 copy_value = fv_new->ftype->copy_value;
514 if (copy_value != NULL) {
515 /* deep copy */
516 copy_value(fv_new, fv_orig);
518 else {
519 /* shallow copy */
520 memcpy(&fv_new->value, &fv_orig->value, sizeof(fv_orig->value));
523 return fv_new;
526 void
527 fvalue_init(fvalue_t *fv, ftenum_t ftype)
529 const ftype_t *ft;
530 FvalueNewFunc new_value;
532 FTYPE_LOOKUP(ftype, ft);
533 fv->ftype = ft;
535 new_value = ft->new_value;
536 if (new_value) {
537 new_value(fv);
541 void
542 fvalue_cleanup(fvalue_t *fv)
544 if (!fv->ftype->free_value)
545 return;
546 fv->ftype->free_value(fv);
549 void
550 fvalue_free(fvalue_t *fv)
552 fvalue_cleanup(fv);
553 g_slice_free(fvalue_t, fv);
556 fvalue_t*
557 fvalue_from_literal(ftenum_t ftype, const char *s, bool allow_partial_value, char **err_msg)
559 fvalue_t *fv;
560 bool ok = false;
562 fv = fvalue_new(ftype);
563 if (fv->ftype->val_from_literal) {
564 ok = fv->ftype->val_from_literal(fv, s, allow_partial_value, err_msg);
566 if (ok) {
567 /* Success */
568 if (err_msg != NULL)
569 *err_msg = NULL;
570 return fv;
572 else {
573 if (err_msg != NULL && *err_msg == NULL) {
574 *err_msg = ws_strdup_printf("\"%s\" cannot be converted to %s.",
575 s, ftype_pretty_name(ftype));
578 fvalue_free(fv);
579 return NULL;
582 fvalue_t*
583 fvalue_from_string(ftenum_t ftype, const char *str, size_t len, char **err_msg)
585 fvalue_t *fv;
587 fv = fvalue_new(ftype);
588 if (fv->ftype->val_from_string && fv->ftype->val_from_string(fv, str, len, err_msg)) {
589 /* Success */
590 if (err_msg != NULL)
591 *err_msg = NULL;
592 return fv;
594 else {
595 if (err_msg != NULL && *err_msg == NULL) {
596 *err_msg = ws_strdup_printf("%s cannot be converted from a string (\"%s\").",
597 ftype_pretty_name(ftype), str);
600 fvalue_free(fv);
601 return NULL;
604 fvalue_t*
605 fvalue_from_charconst(ftenum_t ftype, unsigned long num, char **err_msg)
607 fvalue_t *fv;
609 fv = fvalue_new(ftype);
610 if (fv->ftype->val_from_charconst && fv->ftype->val_from_charconst(fv, num, err_msg)) {
611 /* Success */
612 if (err_msg != NULL)
613 *err_msg = NULL;
614 return fv;
616 else {
617 if (err_msg != NULL && *err_msg == NULL) {
618 if (num <= 0x7f && g_ascii_isprint(num)) {
619 *err_msg = ws_strdup_printf("Character constant '%c' (0x%lx) cannot be converted to %s.",
620 (int)num, num, ftype_pretty_name(ftype));
622 else {
623 *err_msg = ws_strdup_printf("Character constant 0x%lx cannot be converted to %s.",
624 num, ftype_pretty_name(ftype));
628 fvalue_free(fv);
629 return NULL;
632 fvalue_t*
633 fvalue_from_sinteger64(ftenum_t ftype, const char *s, int64_t num, char **err_msg)
635 fvalue_t *fv;
637 fv = fvalue_new(ftype);
638 if (fv->ftype->val_from_sinteger64 && fv->ftype->val_from_sinteger64(fv, s, num, err_msg)) {
639 /* Success */
640 if (err_msg != NULL)
641 *err_msg = NULL;
642 return fv;
644 else {
645 if (err_msg != NULL && *err_msg == NULL) {
646 *err_msg = ws_strdup_printf("Integer %"PRId64" cannot be converted to %s.",
647 num, ftype_pretty_name(ftype));
650 fvalue_free(fv);
651 return NULL;
654 fvalue_t*
655 fvalue_from_uinteger64(ftenum_t ftype, const char *s, uint64_t num, char **err_msg)
657 fvalue_t *fv;
659 fv = fvalue_new(ftype);
660 if (fv->ftype->val_from_uinteger64 && fv->ftype->val_from_uinteger64(fv, s, num, err_msg)) {
661 /* Success */
662 if (err_msg != NULL)
663 *err_msg = NULL;
664 return fv;
666 else {
667 if (err_msg != NULL && *err_msg == NULL) {
668 *err_msg = ws_strdup_printf("Unsigned integer 0x%"PRIu64" cannot be converted to %s.",
669 num, ftype_pretty_name(ftype));
672 fvalue_free(fv);
673 return NULL;
676 fvalue_t*
677 fvalue_from_floating(ftenum_t ftype, const char *s, double num, char **err_msg)
679 fvalue_t *fv;
681 fv = fvalue_new(ftype);
682 if (fv->ftype->val_from_double && fv->ftype->val_from_double(fv, s, num, err_msg)) {
683 /* Success */
684 if (err_msg != NULL)
685 *err_msg = NULL;
686 return fv;
688 else {
689 if (err_msg != NULL && *err_msg == NULL) {
690 *err_msg = ws_strdup_printf("Double %g cannot be converted to %s.",
691 num, ftype_pretty_name(ftype));
694 fvalue_free(fv);
695 return NULL;
698 ftenum_t
699 fvalue_type_ftenum(const fvalue_t *fv)
701 return fv->ftype->ftype;
704 const char*
705 fvalue_type_name(const fvalue_t *fv)
707 return ftype_name(fv->ftype->ftype);
711 size_t
712 fvalue_length2(fvalue_t *fv)
714 if (!fv->ftype->len) {
715 ws_critical("fv->ftype->len is NULL");
716 return 0;
718 return fv->ftype->len(fv);
721 char *
722 fvalue_to_string_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype, int field_display)
724 if (fv->ftype->val_to_string_repr == NULL) {
725 /* no value-to-string-representation function, so the value cannot be represented */
726 return NULL;
729 return fv->ftype->val_to_string_repr(scope, fv, rtype, field_display);
732 enum ft_result
733 fvalue_to_uinteger(const fvalue_t *fv, uint32_t *repr)
735 uint64_t val;
736 enum ft_result res = fv->ftype->val_to_uinteger64(fv, &val);
737 if (res != FT_OK)
738 return res;
739 if (val > UINT32_MAX)
740 return FT_OVERFLOW;
742 *repr = (uint32_t)val;
743 return FT_OK;
746 enum ft_result
747 fvalue_to_sinteger(const fvalue_t *fv, int32_t *repr)
749 int64_t val;
750 enum ft_result res = fv->ftype->val_to_sinteger64(fv, &val);
751 if (res != FT_OK)
752 return res;
753 if (val > INT32_MAX)
754 return FT_OVERFLOW;
755 if (val < INT32_MIN)
756 return FT_UNDERFLOW;
758 *repr = (int32_t)val;
759 return FT_OK;
762 enum ft_result
763 fvalue_to_uinteger64(const fvalue_t *fv, uint64_t *repr)
765 if (!fv->ftype->val_to_uinteger64) {
766 return FT_BADARG;
768 return fv->ftype->val_to_uinteger64(fv, repr);
771 enum ft_result
772 fvalue_to_sinteger64(const fvalue_t *fv, int64_t *repr)
774 if (!fv->ftype->val_to_sinteger64) {
775 return FT_BADARG;
777 return fv->ftype->val_to_sinteger64(fv, repr);
780 enum ft_result
781 fvalue_to_double(const fvalue_t *fv, double *repr)
783 /* We should be able to test this earlier (e.g., in semantic check)
784 * but there are non-compatible fields that share the same abbrev
785 * so we have to check it on each fvalue.
787 if (!fv->ftype->val_to_double) {
788 return FT_BADARG;
790 return fv->ftype->val_to_double(fv, repr);
793 typedef struct {
794 fvalue_t *fv;
795 void *ptr;
796 bool slice_failure;
797 } slice_data_t;
799 static bool
800 compute_drnode(size_t field_length, drange_node *drnode, size_t *offset_ptr, size_t *length_ptr)
802 ssize_t start_offset;
803 ssize_t length = 0;
804 ssize_t end_offset = 0;
805 drange_node_end_t ending;
807 start_offset = drange_node_get_start_offset(drnode);
808 ending = drange_node_get_ending(drnode);
810 /* Check for negative start */
811 if (start_offset < 0) {
812 start_offset = field_length + start_offset;
813 if (start_offset < 0) {
814 return false;
818 /* Check the end type and set the length */
820 if (ending == DRANGE_NODE_END_T_TO_THE_END) {
821 length = field_length - start_offset;
822 if (length <= 0) {
823 return false;
826 else if (ending == DRANGE_NODE_END_T_LENGTH) {
827 length = drange_node_get_length(drnode);
828 if (start_offset + length > (int) field_length) {
829 return false;
832 else if (ending == DRANGE_NODE_END_T_OFFSET) {
833 end_offset = drange_node_get_end_offset(drnode);
834 if (end_offset < 0) {
835 end_offset = field_length + end_offset;
836 if (end_offset < start_offset) {
837 return false;
839 } else if (end_offset >= (int) field_length) {
840 return false;
842 length = end_offset - start_offset + 1;
844 else {
845 ws_assert_not_reached();
848 *offset_ptr = start_offset;
849 *length_ptr = length;
850 return true;
853 static void
854 slice_func(void * data, void * user_data)
856 drange_node *drnode = (drange_node *)data;
857 slice_data_t *slice_data = (slice_data_t *)user_data;
858 size_t start_offset;
859 size_t length = 0;
860 fvalue_t *fv;
862 if (slice_data->slice_failure) {
863 return;
866 fv = slice_data->fv;
867 if (!compute_drnode((unsigned)fvalue_length2(fv), drnode, &start_offset, &length)) {
868 slice_data->slice_failure = true;
869 return;
872 ws_assert(length > 0);
873 fv->ftype->slice(fv, slice_data->ptr, (unsigned)start_offset, (unsigned)length);
876 static fvalue_t *
877 slice_string(fvalue_t *fv, drange_t *d_range)
879 slice_data_t slice_data;
880 fvalue_t *new_fv;
882 slice_data.fv = fv;
883 slice_data.ptr = wmem_strbuf_create(NULL);
884 slice_data.slice_failure = false;
886 /* XXX - We could make some optimizations here based on
887 * drange_has_total_length() and
888 * drange_get_max_offset().
891 drange_foreach_drange_node(d_range, slice_func, &slice_data);
893 new_fv = fvalue_new(FT_STRING);
894 fvalue_set_strbuf(new_fv, slice_data.ptr);
895 return new_fv;
898 static fvalue_t *
899 slice_bytes(fvalue_t *fv, drange_t *d_range)
901 slice_data_t slice_data;
902 fvalue_t *new_fv;
904 slice_data.fv = fv;
905 slice_data.ptr = g_byte_array_new();
906 slice_data.slice_failure = false;
908 /* XXX - We could make some optimizations here based on
909 * drange_has_total_length() and
910 * drange_get_max_offset().
913 drange_foreach_drange_node(d_range, slice_func, &slice_data);
915 new_fv = fvalue_new(FT_BYTES);
916 fvalue_set_byte_array(new_fv, slice_data.ptr);
917 return new_fv;
920 /* Returns a new slice fvalue_t* if possible, otherwise NULL */
921 fvalue_t*
922 fvalue_slice(fvalue_t *fv, drange_t *d_range)
924 if (FT_IS_STRING(fvalue_type_ftenum(fv))) {
925 return slice_string(fv, d_range);
927 return slice_bytes(fv, d_range);
930 void
931 fvalue_set_bytes(fvalue_t *fv, GBytes *value)
933 ws_assert(fv->ftype->ftype == FT_BYTES ||
934 fv->ftype->ftype == FT_UINT_BYTES ||
935 fv->ftype->ftype == FT_OID ||
936 fv->ftype->ftype == FT_REL_OID ||
937 fv->ftype->ftype == FT_SYSTEM_ID ||
938 fv->ftype->ftype == FT_VINES ||
939 fv->ftype->ftype == FT_ETHER ||
940 fv->ftype->ftype == FT_FCWWN);
941 ws_assert(fv->ftype->set_value.set_value_bytes);
942 fv->ftype->set_value.set_value_bytes(fv, value);
945 void
946 fvalue_set_byte_array(fvalue_t *fv, GByteArray *value)
948 GBytes *bytes = g_byte_array_free_to_bytes(value);
949 fvalue_set_bytes(fv, bytes);
950 g_bytes_unref(bytes);
953 void
954 fvalue_set_bytes_data(fvalue_t *fv, const void *data, size_t size)
956 GBytes *bytes = g_bytes_new(data, size);
957 fvalue_set_bytes(fv, bytes);
958 g_bytes_unref(bytes);
961 void
962 fvalue_set_fcwwn(fvalue_t *fv, const uint8_t *value)
964 GBytes *bytes = g_bytes_new(value, FT_FCWWN_LEN);
965 fvalue_set_bytes(fv, bytes);
966 g_bytes_unref(bytes);
969 void
970 fvalue_set_ax25(fvalue_t *fv, const uint8_t *value)
972 wmem_strbuf_t *buf = wmem_strbuf_new(NULL, NULL);
973 for (size_t i = 0; i < FT_AX25_ADDR_LEN - 1; i++) {
974 if (value[i] != 0x40) {
975 /* ignore space-padding */
976 wmem_strbuf_append_c(buf, value[i] >> 1);
979 /* Ignore C-bit and reserved bits, and end of address bits. */
980 uint8_t ssid = (value[FT_AX25_ADDR_LEN - 1] >> 1) & 0x0f;
981 if (ssid != 0) {
982 wmem_strbuf_append_printf(buf, "-%u", ssid);
984 fvalue_set_strbuf(fv, buf);
987 void
988 fvalue_set_vines(fvalue_t *fv, const uint8_t *value)
990 GBytes *bytes = g_bytes_new(value, FT_VINES_ADDR_LEN);
991 fvalue_set_bytes(fv, bytes);
992 g_bytes_unref(bytes);
995 void
996 fvalue_set_ether(fvalue_t *fv, const uint8_t *value)
998 GBytes *bytes = g_bytes_new(value, FT_ETHER_LEN);
999 fvalue_set_bytes(fv, bytes);
1000 g_bytes_unref(bytes);
1003 void
1004 fvalue_set_guid(fvalue_t *fv, const e_guid_t *value)
1006 ws_assert(fv->ftype->ftype == FT_GUID);
1007 ws_assert(fv->ftype->set_value.set_value_guid);
1008 fv->ftype->set_value.set_value_guid(fv, value);
1011 void
1012 fvalue_set_time(fvalue_t *fv, const nstime_t *value)
1014 ws_assert(FT_IS_TIME(fv->ftype->ftype));
1015 ws_assert(fv->ftype->set_value.set_value_time);
1016 fv->ftype->set_value.set_value_time(fv, value);
1019 void
1020 fvalue_set_string(fvalue_t *fv, const char *value)
1022 wmem_strbuf_t *buf = wmem_strbuf_new(NULL, value);
1023 fvalue_set_strbuf(fv, buf);
1026 void
1027 fvalue_set_strbuf(fvalue_t *fv, wmem_strbuf_t *value)
1029 if (value->allocator != NULL) {
1030 /* XXX Can this condition be relaxed? */
1031 ws_critical("Fvalue strbuf allocator must be NULL");
1033 ws_assert(FT_IS_STRING(fv->ftype->ftype));
1034 ws_assert(fv->ftype->set_value.set_value_strbuf);
1035 fv->ftype->set_value.set_value_strbuf(fv, value);
1038 void
1039 fvalue_set_protocol(fvalue_t *fv, tvbuff_t *value, const char *name, int length)
1041 ws_assert(fv->ftype->ftype == FT_PROTOCOL);
1042 ws_assert(fv->ftype->set_value.set_value_protocol);
1043 fv->ftype->set_value.set_value_protocol(fv, value, name, length);
1046 void
1047 fvalue_set_protocol_length(fvalue_t *fv, int length)
1049 ws_assert(fv->ftype->ftype == FT_PROTOCOL);
1050 protocol_value_t *proto = &fv->value.protocol;
1051 proto->length = length;
1054 void
1055 fvalue_set_uinteger(fvalue_t *fv, uint32_t value)
1057 ws_assert(fv->ftype->ftype == FT_IEEE_11073_SFLOAT ||
1058 fv->ftype->ftype == FT_IEEE_11073_FLOAT ||
1059 fv->ftype->ftype == FT_CHAR ||
1060 fv->ftype->ftype == FT_UINT8 ||
1061 fv->ftype->ftype == FT_UINT16 ||
1062 fv->ftype->ftype == FT_UINT24 ||
1063 fv->ftype->ftype == FT_UINT32 ||
1064 fv->ftype->ftype == FT_IPXNET ||
1065 fv->ftype->ftype == FT_FRAMENUM);
1066 ws_assert(fv->ftype->set_value.set_value_uinteger);
1067 fv->ftype->set_value.set_value_uinteger(fv, value);
1070 void
1071 fvalue_set_sinteger(fvalue_t *fv, int32_t value)
1073 ws_assert(fv->ftype->ftype == FT_INT8 ||
1074 fv->ftype->ftype == FT_INT16 ||
1075 fv->ftype->ftype == FT_INT24 ||
1076 fv->ftype->ftype == FT_INT32);
1077 ws_assert(fv->ftype->set_value.set_value_sinteger);
1078 fv->ftype->set_value.set_value_sinteger(fv, value);
1081 void
1082 fvalue_set_uinteger64(fvalue_t *fv, uint64_t value)
1084 ws_assert(fv->ftype->ftype == FT_UINT40 ||
1085 fv->ftype->ftype == FT_UINT48 ||
1086 fv->ftype->ftype == FT_UINT56 ||
1087 fv->ftype->ftype == FT_UINT64 ||
1088 fv->ftype->ftype == FT_BOOLEAN ||
1089 fv->ftype->ftype == FT_EUI64);
1090 ws_assert(fv->ftype->set_value.set_value_uinteger64);
1091 fv->ftype->set_value.set_value_uinteger64(fv, value);
1094 void
1095 fvalue_set_sinteger64(fvalue_t *fv, int64_t value)
1097 ws_assert(fv->ftype->ftype == FT_INT40 ||
1098 fv->ftype->ftype == FT_INT48 ||
1099 fv->ftype->ftype == FT_INT56 ||
1100 fv->ftype->ftype == FT_INT64);
1101 ws_assert(fv->ftype->set_value.set_value_sinteger64);
1102 fv->ftype->set_value.set_value_sinteger64(fv, value);
1105 void
1106 fvalue_set_floating(fvalue_t *fv, double value)
1108 ws_assert(fv->ftype->ftype == FT_FLOAT ||
1109 fv->ftype->ftype == FT_DOUBLE);
1110 ws_assert(fv->ftype->set_value.set_value_floating);
1111 fv->ftype->set_value.set_value_floating(fv, value);
1114 void
1115 fvalue_set_ipv4(fvalue_t *fv, const ipv4_addr_and_mask *value)
1117 ws_assert(fv->ftype->ftype == FT_IPv4);
1118 ws_assert(fv->ftype->set_value.set_value_ipv4);
1119 fv->ftype->set_value.set_value_ipv4(fv, value);
1122 void
1123 fvalue_set_ipv6(fvalue_t *fv, const ipv6_addr_and_prefix *value)
1125 ws_assert(fv->ftype->ftype == FT_IPv6);
1126 ws_assert(fv->ftype->set_value.set_value_ipv6);
1127 fv->ftype->set_value.set_value_ipv6(fv, value);
1130 GBytes *
1131 fvalue_get_bytes(fvalue_t *fv)
1133 ws_assert(fv->ftype->ftype == FT_BYTES ||
1134 fv->ftype->ftype == FT_UINT_BYTES ||
1135 fv->ftype->ftype == FT_VINES ||
1136 fv->ftype->ftype == FT_ETHER ||
1137 fv->ftype->ftype == FT_OID ||
1138 fv->ftype->ftype == FT_REL_OID ||
1139 fv->ftype->ftype == FT_SYSTEM_ID ||
1140 fv->ftype->ftype == FT_FCWWN ||
1141 fv->ftype->ftype == FT_IPv6);
1142 ws_assert(fv->ftype->get_value.get_value_bytes);
1143 return fv->ftype->get_value.get_value_bytes(fv);
1146 size_t
1147 fvalue_get_bytes_size(fvalue_t *fv)
1149 GBytes *bytes = fvalue_get_bytes(fv);
1150 size_t size = g_bytes_get_size(bytes);
1151 g_bytes_unref(bytes);
1152 return size;
1155 const void *
1156 fvalue_get_bytes_data(fvalue_t *fv)
1158 GBytes *bytes = fvalue_get_bytes(fv);
1159 const void *data = g_bytes_get_data(bytes, NULL);
1160 g_bytes_unref(bytes);
1161 return data;
1164 const e_guid_t *
1165 fvalue_get_guid(fvalue_t *fv)
1167 ws_assert(fv->ftype->ftype == FT_GUID);
1168 ws_assert(fv->ftype->get_value.get_value_guid);
1169 return fv->ftype->get_value.get_value_guid(fv);
1172 const nstime_t *
1173 fvalue_get_time(fvalue_t *fv)
1175 ws_assert(FT_IS_TIME(fv->ftype->ftype));
1176 ws_assert(fv->ftype->get_value.get_value_time);
1177 return fv->ftype->get_value.get_value_time(fv);
1180 const char *
1181 fvalue_get_string(fvalue_t *fv)
1183 return wmem_strbuf_get_str(fvalue_get_strbuf(fv));
1186 const wmem_strbuf_t *
1187 fvalue_get_strbuf(fvalue_t *fv)
1189 ws_assert(FT_IS_STRING(fv->ftype->ftype));
1190 ws_assert(fv->ftype->get_value.get_value_strbuf);
1191 return fv->ftype->get_value.get_value_strbuf(fv);
1194 tvbuff_t *
1195 fvalue_get_protocol(fvalue_t *fv)
1197 ws_assert(fv->ftype->ftype == FT_PROTOCOL);
1198 ws_assert(fv->ftype->get_value.get_value_protocol);
1199 return fv->ftype->get_value.get_value_protocol(fv);
1202 uint32_t
1203 fvalue_get_uinteger(fvalue_t *fv)
1205 ws_assert(fv->ftype->ftype == FT_IEEE_11073_SFLOAT ||
1206 fv->ftype->ftype == FT_IEEE_11073_FLOAT ||
1207 fv->ftype->ftype == FT_CHAR ||
1208 fv->ftype->ftype == FT_UINT8 ||
1209 fv->ftype->ftype == FT_UINT16 ||
1210 fv->ftype->ftype == FT_UINT24 ||
1211 fv->ftype->ftype == FT_UINT32 ||
1212 fv->ftype->ftype == FT_IPXNET ||
1213 fv->ftype->ftype == FT_FRAMENUM);
1214 ws_assert(fv->ftype->get_value.get_value_uinteger);
1215 return fv->ftype->get_value.get_value_uinteger(fv);
1218 int32_t
1219 fvalue_get_sinteger(fvalue_t *fv)
1221 ws_assert(fv->ftype->ftype == FT_INT8 ||
1222 fv->ftype->ftype == FT_INT16 ||
1223 fv->ftype->ftype == FT_INT24 ||
1224 fv->ftype->ftype == FT_INT32);
1225 ws_assert(fv->ftype->get_value.get_value_sinteger);
1226 return fv->ftype->get_value.get_value_sinteger(fv);
1229 uint64_t
1230 fvalue_get_uinteger64(fvalue_t *fv)
1232 ws_assert(fv->ftype->ftype == FT_UINT40 ||
1233 fv->ftype->ftype == FT_UINT48 ||
1234 fv->ftype->ftype == FT_UINT56 ||
1235 fv->ftype->ftype == FT_UINT64 ||
1236 fv->ftype->ftype == FT_BOOLEAN ||
1237 fv->ftype->ftype == FT_EUI64);
1238 ws_assert(fv->ftype->get_value.get_value_uinteger64);
1239 return fv->ftype->get_value.get_value_uinteger64(fv);
1242 int64_t
1243 fvalue_get_sinteger64(fvalue_t *fv)
1245 ws_assert(fv->ftype->ftype == FT_INT40 ||
1246 fv->ftype->ftype == FT_INT48 ||
1247 fv->ftype->ftype == FT_INT56 ||
1248 fv->ftype->ftype == FT_INT64);
1249 ws_assert(fv->ftype->get_value.get_value_sinteger64);
1250 return fv->ftype->get_value.get_value_sinteger64(fv);
1253 double
1254 fvalue_get_floating(fvalue_t *fv)
1256 ws_assert(fv->ftype->ftype == FT_FLOAT ||
1257 fv->ftype->ftype == FT_DOUBLE);
1258 ws_assert(fv->ftype->get_value.get_value_floating);
1259 return fv->ftype->get_value.get_value_floating(fv);
1262 const ipv4_addr_and_mask *
1263 fvalue_get_ipv4(fvalue_t *fv)
1265 ws_assert(fv->ftype->ftype == FT_IPv4);
1266 ws_assert(fv->ftype->get_value.get_value_ipv4);
1267 return fv->ftype->get_value.get_value_ipv4(fv);
1270 const ipv6_addr_and_prefix *
1271 fvalue_get_ipv6(fvalue_t *fv)
1273 ws_assert(fv->ftype->ftype == FT_IPv6);
1274 ws_assert(fv->ftype->get_value.get_value_ipv6);
1275 return fv->ftype->get_value.get_value_ipv6(fv);
1278 ft_bool_t
1279 fvalue_eq(const fvalue_t *a, const fvalue_t *b)
1281 int cmp;
1282 enum ft_result res;
1284 ws_assert(a->ftype->compare);
1285 res = a->ftype->compare(a, b, &cmp);
1286 if (res != FT_OK)
1287 return -res;
1288 return cmp == 0 ? FT_TRUE : FT_FALSE;
1291 ft_bool_t
1292 fvalue_ne(const fvalue_t *a, const fvalue_t *b)
1294 int cmp;
1295 enum ft_result res;
1297 ws_assert(a->ftype->compare);
1298 res = a->ftype->compare(a, b, &cmp);
1299 if (res != FT_OK)
1300 return -res;
1301 return cmp != 0 ? FT_TRUE : FT_FALSE;
1304 ft_bool_t
1305 fvalue_gt(const fvalue_t *a, const fvalue_t *b)
1307 int cmp;
1308 enum ft_result res;
1310 ws_assert(a->ftype->compare);
1311 res = a->ftype->compare(a, b, &cmp);
1312 if (res != FT_OK)
1313 return -res;
1314 return cmp > 0 ? FT_TRUE : FT_FALSE;
1317 ft_bool_t
1318 fvalue_ge(const fvalue_t *a, const fvalue_t *b)
1320 int cmp;
1321 enum ft_result res;
1323 ws_assert(a->ftype->compare);
1324 res = a->ftype->compare(a, b, &cmp);
1325 if (res != FT_OK)
1326 return -res;
1327 return cmp >= 0 ? FT_TRUE : FT_FALSE;
1330 ft_bool_t
1331 fvalue_lt(const fvalue_t *a, const fvalue_t *b)
1333 int cmp;
1334 enum ft_result res;
1336 ws_assert(a->ftype->compare);
1337 res = a->ftype->compare(a, b, &cmp);
1338 if (res != FT_OK)
1339 return -res;
1340 return cmp < 0 ? FT_TRUE : FT_FALSE;
1343 ft_bool_t
1344 fvalue_le(const fvalue_t *a, const fvalue_t *b)
1346 int cmp;
1347 enum ft_result res;
1349 ws_assert(a->ftype->compare);
1350 res = a->ftype->compare(a, b, &cmp);
1351 if (res != FT_OK)
1352 return -res;
1353 return cmp <= 0 ? FT_TRUE : FT_FALSE;
1356 ft_bool_t
1357 fvalue_contains(const fvalue_t *a, const fvalue_t *b)
1359 bool yes;
1360 enum ft_result res;
1362 ws_assert(a->ftype->contains);
1363 res = a->ftype->contains(a, b, &yes);
1364 if (res != FT_OK)
1365 return -res;
1366 return yes ? FT_TRUE : FT_FALSE;
1369 ft_bool_t
1370 fvalue_matches(const fvalue_t *a, const ws_regex_t *re)
1372 bool yes;
1373 enum ft_result res;
1375 ws_assert(a->ftype->matches);
1376 res = a->ftype->matches(a, re, &yes);
1377 if (res != FT_OK)
1378 return -res;
1379 return yes ? FT_TRUE : FT_FALSE;
1382 ft_bool_t
1383 fvalue_is_zero(const fvalue_t *a)
1385 return a->ftype->is_zero(a) ? FT_TRUE : FT_FALSE;
1388 ft_bool_t
1389 fvalue_is_negative(const fvalue_t *a)
1391 return a->ftype->is_negative(a) ? FT_TRUE : FT_FALSE;
1394 static fvalue_t *
1395 _fvalue_binop(FvalueBinaryOp op, const fvalue_t *a, const fvalue_t *b, char **err_msg)
1397 fvalue_t *result;
1399 result = fvalue_new(a->ftype->ftype);
1400 if (op(result, a, b, err_msg) != FT_OK) {
1401 fvalue_free(result);
1402 return NULL;
1404 return result;
1407 fvalue_t *
1408 fvalue_bitwise_and(const fvalue_t *a, const fvalue_t *b, char **err_msg)
1410 /* XXX - check compatibility of a and b */
1411 ws_assert(a->ftype->bitwise_and);
1412 return _fvalue_binop(a->ftype->bitwise_and, a, b, err_msg);
1415 fvalue_t *
1416 fvalue_add(const fvalue_t *a, const fvalue_t *b, char **err_msg)
1418 /* XXX - check compatibility of a and b */
1419 ws_assert(a->ftype->add);
1420 return _fvalue_binop(a->ftype->add, a, b, err_msg);
1423 fvalue_t *
1424 fvalue_subtract(const fvalue_t *a, const fvalue_t *b, char **err_msg)
1426 /* XXX - check compatibility of a and b */
1427 ws_assert(a->ftype->subtract);
1428 return _fvalue_binop(a->ftype->subtract, a, b, err_msg);
1431 fvalue_t *
1432 fvalue_multiply(const fvalue_t *a, const fvalue_t *b, char **err_msg)
1434 /* XXX - check compatibility of a and b */
1435 ws_assert(a->ftype->multiply);
1436 return _fvalue_binop(a->ftype->multiply, a, b, err_msg);
1439 fvalue_t *
1440 fvalue_divide(const fvalue_t *a, const fvalue_t *b, char **err_msg)
1442 /* XXX - check compatibility of a and b */
1443 ws_assert(a->ftype->divide);
1444 return _fvalue_binop(a->ftype->divide, a, b, err_msg);
1447 fvalue_t *
1448 fvalue_modulo(const fvalue_t *a, const fvalue_t *b, char **err_msg)
1450 /* XXX - check compatibility of a and b */
1451 ws_assert(a->ftype->modulo);
1452 return _fvalue_binop(a->ftype->modulo, a, b, err_msg);
1455 fvalue_t*
1456 fvalue_unary_minus(const fvalue_t *fv, char **err_msg)
1458 fvalue_t *result;
1460 ws_assert(fv->ftype->unary_minus);
1462 result = fvalue_new(fv->ftype->ftype);
1463 if (fv->ftype->unary_minus(result, fv, err_msg) != FT_OK) {
1464 fvalue_free(result);
1465 return NULL;
1467 return result;
1470 unsigned
1471 fvalue_hash(const fvalue_t *fv)
1473 ws_assert(fv->ftype->hash);
1474 return fv->ftype->hash(fv);
1477 bool
1478 fvalue_equal(const fvalue_t *a, const fvalue_t *b)
1480 return fvalue_eq(a, b) == FT_TRUE;
1484 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1486 * Local variables:
1487 * c-basic-offset: 8
1488 * tab-width: 8
1489 * indent-tabs-mode: t
1490 * End:
1492 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1493 * :indentSize=8:tabSize=8:noTabs=false: