diff options
author | João Valverde <j@v6e.pt> | 2023-04-17 16:39:00 +0100 |
---|---|---|
committer | João Valverde <j@v6e.pt> | 2023-04-19 16:16:28 +0100 |
commit | 1ff7b8303781819fdaeb01be4b40ca6aa77d9cc5 (patch) | |
tree | bc792a09c4407243be70b284cb09770e2d54a5bc /epan/ftypes | |
parent | 7595af96a08744392b1ff2a866c1d86ef6b7099e (diff) |
ftypes: Add a hash/equal method
Add methods to make fvalues hashable with GHashTable.
Diffstat (limited to 'epan/ftypes')
-rw-r--r-- | epan/ftypes/ftype-bytes.c | 15 | ||||
-rw-r--r-- | epan/ftypes/ftype-double.c | 16 | ||||
-rw-r--r-- | epan/ftypes/ftype-guid.c | 7 | ||||
-rw-r--r-- | epan/ftypes/ftype-ieee-11073-float.c | 26 | ||||
-rw-r--r-- | epan/ftypes/ftype-integer.c | 61 | ||||
-rw-r--r-- | epan/ftypes/ftype-ipv4.c | 9 | ||||
-rw-r--r-- | epan/ftypes/ftype-ipv6.c | 12 | ||||
-rw-r--r-- | epan/ftypes/ftype-none.c | 1 | ||||
-rw-r--r-- | epan/ftypes/ftype-protocol.c | 8 | ||||
-rw-r--r-- | epan/ftypes/ftype-string.c | 11 | ||||
-rw-r--r-- | epan/ftypes/ftype-time.c | 8 | ||||
-rw-r--r-- | epan/ftypes/ftypes-int.h | 2 | ||||
-rw-r--r-- | epan/ftypes/ftypes.c | 13 | ||||
-rw-r--r-- | epan/ftypes/ftypes.h | 6 |
14 files changed, 186 insertions, 9 deletions
diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c index 280e0613a8..5973a85c4c 100644 --- a/epan/ftypes/ftype-bytes.c +++ b/epan/ftypes/ftype-bytes.c @@ -571,6 +571,12 @@ cmp_matches(const fvalue_t *fv, const ws_regex_t *regex, gboolean *matches) return FT_OK; } +static guint +bytes_hash(const fvalue_t *fv) +{ + return g_bytes_hash(fv->value.bytes); +} + static gboolean bytes_is_zero(const fvalue_t *fv) { @@ -617,6 +623,7 @@ ftype_register_bytes(void) cmp_contains, cmp_matches, + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -653,6 +660,7 @@ ftype_register_bytes(void) cmp_contains, NULL, /* cmp_matches */ + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -689,6 +697,7 @@ ftype_register_bytes(void) cmp_contains, cmp_matches, + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -725,6 +734,7 @@ ftype_register_bytes(void) cmp_contains, cmp_matches, + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -761,6 +771,7 @@ ftype_register_bytes(void) cmp_contains, cmp_matches, + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -797,6 +808,7 @@ ftype_register_bytes(void) cmp_contains, NULL, /* cmp_matches */ + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -833,6 +845,7 @@ ftype_register_bytes(void) cmp_contains, NULL, /* cmp_matches */ + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -869,6 +882,7 @@ ftype_register_bytes(void) cmp_contains, NULL, /* cmp_matches */ + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -905,6 +919,7 @@ ftype_register_bytes(void) cmp_contains, cmp_matches, + bytes_hash, /* hash */ bytes_is_zero, /* is_zero */ NULL, /* is_negative */ len, diff --git a/epan/ftypes/ftype-double.c b/epan/ftypes/ftype-double.c index 48c567a493..2f5f2c67d6 100644 --- a/epan/ftypes/ftype-double.c +++ b/epan/ftypes/ftype-double.c @@ -148,6 +148,12 @@ val_is_negative(const fvalue_t *fv_a) return fv_a->value.floating < 0; } +static guint +val_hash(const fvalue_t *fv) +{ + return g_double_hash(&fv->value.floating); +} + void ftype_register_double(void) { @@ -175,10 +181,11 @@ ftype_register_double(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + val_hash, /* hash */ val_is_zero, /* is_zero */ val_is_negative, /* is_negative */ - NULL, - NULL, + NULL, /* len */ + NULL, /* slice */ NULL, /* bitwise_and */ val_unary_minus, /* unary_minus */ val_add, /* add */ @@ -211,10 +218,11 @@ ftype_register_double(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + val_hash, /* hash */ val_is_zero, /* is_zero */ val_is_negative, /* is_negative */ - NULL, - NULL, + NULL, /* len */ + NULL, /* slice */ NULL, /* bitwise_and */ val_unary_minus, /* unary_minus */ val_add, /* add */ diff --git a/epan/ftypes/ftype-guid.c b/epan/ftypes/ftype-guid.c index f884da38ab..2a983e625a 100644 --- a/epan/ftypes/ftype-guid.c +++ b/epan/ftypes/ftype-guid.c @@ -94,6 +94,12 @@ cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp) return FT_OK; } +static guint +value_hash(const fvalue_t *fv) +{ + return guid_hash(&fv->value.guid); +} + void ftype_register_guid(void) { @@ -121,6 +127,7 @@ ftype_register_guid(void) NULL, NULL, /* cmp_matches */ + value_hash, /* hash */ NULL, NULL, NULL, diff --git a/epan/ftypes/ftype-ieee-11073-float.c b/epan/ftypes/ftype-ieee-11073-float.c index bdeed362a6..6fa2fdaa12 100644 --- a/epan/ftypes/ftype-ieee-11073-float.c +++ b/epan/ftypes/ftype-ieee-11073-float.c @@ -461,6 +461,13 @@ sfloat_ieee_11073_is_zero(const fvalue_t *a) return a->value.sfloat_ieee_11073 == 0; } +static guint +sfloat_ieee_11073_hash(const fvalue_t *fv) +{ + gint64 value = fv->value.sfloat_ieee_11073; + return g_int64_hash(&value); +} + /*============================================================================*/ static void @@ -873,6 +880,13 @@ float_ieee_11073_is_zero(const fvalue_t *a) return a->value.float_ieee_11073 == 0; } +static guint +float_ieee_11073_hash(const fvalue_t *fv) +{ + gint64 value = fv->value.float_ieee_11073; + return g_int64_hash(&value); +} + /*============================================================================*/ void @@ -927,11 +941,12 @@ Example: 114 is 0x0072 NULL, /* cmp_contains */ NULL, /* cmp_matches */ - sfloat_ieee_11073_is_zero, /* is_zero */ - NULL, /* is_negative */ - NULL, /* len */ - NULL, /* slice */ - NULL, /* bitwise_and */ + sfloat_ieee_11073_hash, /* hash */ + sfloat_ieee_11073_is_zero, /* is_zero */ + NULL, /* is_negative */ + NULL, /* len */ + NULL, /* slice */ + NULL, /* bitwise_and */ NULL, /* unary_minus */ NULL, /* add */ NULL, /* subtract */ @@ -990,6 +1005,7 @@ Example: 36.4 is 0xFF00016C NULL, /* cmp_contains */ NULL, /* cmp_matches */ + float_ieee_11073_hash, /* hash */ float_ieee_11073_is_zero, /* is_zero */ NULL, /* is_negative */ NULL, /* len */ diff --git a/epan/ftypes/ftype-integer.c b/epan/ftypes/ftype-integer.c index ee9d9df3e4..cf15fc197a 100644 --- a/epan/ftypes/ftype-integer.c +++ b/epan/ftypes/ftype-integer.c @@ -639,6 +639,13 @@ uint_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err return FT_OK; } +static guint +uint_hash(const fvalue_t *fv) +{ + gint64 val = fv->value.uinteger; + return g_int64_hash(&val); +} + static gboolean uint_is_zero(const fvalue_t *fv) { @@ -673,6 +680,13 @@ uint64_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **e return FT_OK; } +static guint +uint64_hash(const fvalue_t *fv) +{ + gint64 val = fv->value.uinteger64; + return g_int64_hash(&val); +} + static gboolean uint64_is_zero(const fvalue_t *fv) { @@ -707,6 +721,13 @@ sint_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err return FT_OK; } +static guint +sint_hash(const fvalue_t *fv) +{ + gint64 val = fv->value.sinteger; + return g_int64_hash(&val); +} + static gboolean sint_is_zero(const fvalue_t *fv) { @@ -733,6 +754,13 @@ sint64_bitwise_and(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **e return FT_OK; } +static guint +sint64_hash(const fvalue_t *fv) +{ + gint64 val = fv->value.sinteger64; + return g_int64_hash(&val); +} + static gboolean sint64_is_zero(const fvalue_t *fv) { @@ -1144,6 +1172,18 @@ boolean_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp) return FT_OK; } +static guint +boolean_hash(const fvalue_t *fv) +{ + int val; + + if (fv->value.uinteger64) + val = 1; + else + val = 0; + return g_int_hash(&val); +} + /* EUI64-specific */ static gboolean eui64_from_literal(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) @@ -1221,6 +1261,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1256,6 +1297,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1291,6 +1333,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1326,6 +1369,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1361,6 +1405,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1396,6 +1441,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint64_hash, /* hash */ uint64_is_zero, /* is_zero */ uint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1431,6 +1477,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint64_hash, /* hash */ uint64_is_zero, /* is_zero */ uint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1466,6 +1513,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint64_hash, /* hash */ uint64_is_zero, /* is_zero */ uint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1501,6 +1549,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint64_hash, /* hash */ uint64_is_zero, /* is_zero */ uint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1536,6 +1585,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint_hash, /* hash */ sint_is_zero, /* is_zero */ sint_is_negative, /* is_negative */ NULL, /* len */ @@ -1571,6 +1621,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint_hash, /* hash */ sint_is_zero, /* is_zero */ sint_is_negative, /* is_negative */ NULL, /* len */ @@ -1606,6 +1657,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint_hash, /* hash */ sint_is_zero, /* is_zero */ sint_is_negative, /* is_negative */ NULL, /* len */ @@ -1641,6 +1693,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint_hash, /* hash */ sint_is_zero, /* is_zero */ sint_is_negative, /* is_negative */ NULL, /* len */ @@ -1676,6 +1729,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint64_hash, /* hash */ sint64_is_zero, /* is_zero */ sint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1711,6 +1765,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint64_hash, /* hash */ sint64_is_zero, /* is_zero */ sint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1746,6 +1801,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint64_hash, /* hash */ sint64_is_zero, /* is_zero */ sint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1781,6 +1837,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + sint64_hash, /* hash */ sint64_is_zero, /* is_zero */ sint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1816,6 +1873,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + boolean_hash, /* hash */ uint64_is_zero, /* is_zero */ uint64_is_negative, /* is_negative */ NULL, /* len */ @@ -1852,6 +1910,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1888,6 +1947,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint_hash, /* hash */ uint_is_zero, /* is_zero */ uint_is_negative, /* is_negative */ NULL, /* len */ @@ -1924,6 +1984,7 @@ ftype_register_integers(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + uint64_hash, /* hash */ uint64_is_zero, /* is_zero */ uint64_is_negative, /* is_negative */ NULL, /* len */ diff --git a/epan/ftypes/ftype-ipv4.c b/epan/ftypes/ftype-ipv4.c index 73161a3b6e..9b02821d68 100644 --- a/epan/ftypes/ftype-ipv4.c +++ b/epan/ftypes/ftype-ipv4.c @@ -152,6 +152,14 @@ slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length) g_byte_array_append(bytes, data, length); } +static guint +ipv4_hash(const fvalue_t *fv) +{ + gint64 val1 = fv->value.ipv4.addr; + gint64 val2 = fv->value.ipv4.nmask; + return g_int64_hash(&val1) ^ g_int64_hash(&val2); +} + static gboolean is_zero(const fvalue_t *fv_a) { @@ -185,6 +193,7 @@ ftype_register_ipv4(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + ipv4_hash, is_zero, NULL, NULL, diff --git a/epan/ftypes/ftype-ipv6.c b/epan/ftypes/ftype-ipv6.c index 20c402743f..65e20f5c35 100644 --- a/epan/ftypes/ftype-ipv6.c +++ b/epan/ftypes/ftype-ipv6.c @@ -178,6 +178,17 @@ slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length) g_byte_array_append(bytes, data, length); } +static guint +ipv6_hash(const fvalue_t *fv) +{ + struct _ipv6 { + gint64 val[2]; + } *addr = (struct _ipv6 *)&fv->value.ipv6.addr; + gint64 mask = fv->value.ipv6.prefix; + + return g_int64_hash(&addr[0]) ^ g_int64_hash(&addr[1]) ^ g_int64_hash(&mask); +} + static gboolean is_zero(const fvalue_t *fv_a) { @@ -211,6 +222,7 @@ ftype_register_ipv6(void) NULL, /* XXX, cmp_contains, needed? ipv4 doesn't support it */ NULL, /* cmp_matches */ + ipv6_hash, is_zero, NULL, NULL, diff --git a/epan/ftypes/ftype-none.c b/epan/ftypes/ftype-none.c index 462466daeb..909fcba6aa 100644 --- a/epan/ftypes/ftype-none.c +++ b/epan/ftypes/ftype-none.c @@ -38,6 +38,7 @@ ftype_register_none(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + NULL, /* hash */ NULL, /* is_zero */ NULL, /* is_negative */ NULL, /* len */ diff --git a/epan/ftypes/ftype-protocol.c b/epan/ftypes/ftype-protocol.c index f1274066e1..8e5f6f4ba6 100644 --- a/epan/ftypes/ftype-protocol.c +++ b/epan/ftypes/ftype-protocol.c @@ -351,6 +351,13 @@ cmp_matches(const fvalue_t *fv, const ws_regex_t *regex, gboolean *matches) return FT_OK; } +static guint +val_hash(const fvalue_t *fv) +{ + const protocol_value_t *value = &fv->value.protocol; + return g_direct_hash(value->tvb) ^ g_int_hash(&value->length) ^ g_str_hash(value->proto_string); +} + static gboolean is_zero(const fvalue_t *fv) { @@ -385,6 +392,7 @@ ftype_register_tvbuff(void) cmp_contains, cmp_matches, + val_hash, is_zero, NULL, len, diff --git a/epan/ftypes/ftype-string.c b/epan/ftypes/ftype-string.c index 4010eac057..195267f7aa 100644 --- a/epan/ftypes/ftype-string.c +++ b/epan/ftypes/ftype-string.c @@ -112,6 +112,12 @@ val_from_charconst(fvalue_t *fv, unsigned long num, gchar **err_msg) return TRUE; } +static guint +string_hash(const fvalue_t *fv) +{ + return g_str_hash(wmem_strbuf_get_str(fv->value.strbuf)); +} + static gboolean string_is_zero(const fvalue_t *fv) { @@ -203,6 +209,7 @@ ftype_register_string(void) cmp_contains, cmp_matches, + string_hash, /* hash */ string_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -238,6 +245,7 @@ ftype_register_string(void) cmp_contains, /* cmp_contains */ cmp_matches, + string_hash, /* hash */ string_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -273,6 +281,7 @@ ftype_register_string(void) cmp_contains, /* cmp_contains */ cmp_matches, + string_hash, /* hash */ string_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -308,6 +317,7 @@ ftype_register_string(void) cmp_contains, /* cmp_contains */ cmp_matches, + string_hash, /* hash */ string_is_zero, /* is_zero */ NULL, /* is_negative */ len, @@ -343,6 +353,7 @@ ftype_register_string(void) cmp_contains, /* cmp_contains */ cmp_matches, + string_hash, /* hash */ string_is_zero, /* is_zero */ NULL, /* is_negative */ len, diff --git a/epan/ftypes/ftype-time.c b/epan/ftypes/ftype-time.c index e35d426784..d2508a2cba 100644 --- a/epan/ftypes/ftype-time.c +++ b/epan/ftypes/ftype-time.c @@ -412,6 +412,12 @@ relative_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype return rel_time_to_secs_str(scope, &fv->value.time); } +static guint +time_hash(const fvalue_t *fv) +{ + return nstime_hash(&fv->value.time); +} + static gboolean time_is_zero(const fvalue_t *fv) { @@ -473,6 +479,7 @@ ftype_register_time(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + time_hash, /* hash */ time_is_zero, /* is_zero */ NULL, /* is_negative */ NULL, @@ -508,6 +515,7 @@ ftype_register_time(void) NULL, /* cmp_contains */ NULL, /* cmp_matches */ + time_hash, /* hash */ time_is_zero, /* is_zero */ time_is_negative, /* is_negative */ NULL, diff --git a/epan/ftypes/ftypes-int.h b/epan/ftypes/ftypes-int.h index 2286879698..af7c7a9ae6 100644 --- a/epan/ftypes/ftypes-int.h +++ b/epan/ftypes/ftypes-int.h @@ -85,6 +85,7 @@ typedef enum ft_result (*FvalueMatches)(const fvalue_t*, const ws_regex_t*, gboo typedef gboolean (*FvalueIs)(const fvalue_t*); typedef guint (*FvalueLen)(fvalue_t*); +typedef guint (*FvalueHashFunc)(const fvalue_t *); typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint offset, guint length); typedef enum ft_result (*FvalueUnaryOp)(fvalue_t *, const fvalue_t*, gchar **); typedef enum ft_result (*FvalueBinaryOp)(fvalue_t *, const fvalue_t*, const fvalue_t*, gchar **); @@ -137,6 +138,7 @@ struct _ftype_t { FvalueContains cmp_contains; FvalueMatches cmp_matches; + FvalueHashFunc hash; FvalueIs is_zero; FvalueIs is_negative; FvalueLen len; diff --git a/epan/ftypes/ftypes.c b/epan/ftypes/ftypes.c index c25a259914..d206286f49 100644 --- a/epan/ftypes/ftypes.c +++ b/epan/ftypes/ftypes.c @@ -1163,6 +1163,19 @@ fvalue_unary_minus(const fvalue_t *fv, char **err_msg) return result; } +guint +fvalue_hash(const fvalue_t *fv) +{ + ws_assert(fv->ftype->hash); + return fv->ftype->hash(fv); +} + +gboolean +fvalue_equal(const fvalue_t *a, const fvalue_t *b) +{ + return fvalue_eq(a, b) == FT_TRUE; +} + /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h index dbeba9f9f0..ef6b827e45 100644 --- a/epan/ftypes/ftypes.h +++ b/epan/ftypes/ftypes.h @@ -502,6 +502,12 @@ fvalue_divide(const fvalue_t *a, const fvalue_t *b, gchar **err_msg); fvalue_t* fvalue_modulo(const fvalue_t *a, const fvalue_t *b, gchar **err_msg); +guint +fvalue_hash(const fvalue_t *fv); + +gboolean +fvalue_equal(const fvalue_t *a, const fvalue_t *b); + #ifdef __cplusplus } #endif /* __cplusplus */ |