3 * Testy, Virtual(-izable) Buffer of guint8*'s
5 * "Testy" -- the buffer gets mad when an attempt to access data
6 * beyond the bounds of the buffer. An exception is thrown.
8 * "Virtual" -- the buffer can have its own data, can use a subset of
9 * the data of a backing tvbuff, or can be a composite of
12 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
14 * Code to convert IEEE floating point formats to native floating point
15 * derived from code Copyright (c) Ashok Narayanan, 2000
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
42 #include "wsutil/pint.h"
43 #include "wsutil/sign_ext.h"
44 #include "wsutil/unicode-utils.h"
45 #include "wsutil/nstime.h"
47 #include "tvbuff-int.h"
51 #include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
52 #include "exceptions.h"
55 * Just make sure we include the prototype for strptime as well 55
56 * (needed for glibc 2.2) but make sure we do this only if not 56
60 /*#ifdef NEED_STRPTIME_H*/
62 #include "wsutil/strptime.h"
67 _tvb_get_bits64(tvbuff_t *tvb, guint bit_offset, const gint total_no_of_bits);
70 _tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset);
72 static inline const guint8*
73 ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length);
75 static inline guint8 *
76 tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length);
79 tvb_new(const struct tvb_ops *ops)
82 gsize size = ops->tvb_size;
84 g_assert(size >= sizeof(*tvb));
86 tvb = (tvbuff_t *) g_slice_alloc(size);
90 tvb->initialized = FALSE;
93 tvb->reported_length = 0;
94 tvb->real_data = NULL;
102 tvb_free_internal(tvbuff_t *tvb)
106 DISSECTOR_ASSERT(tvb);
108 if (tvb->ops->tvb_free)
109 tvb->ops->tvb_free(tvb);
111 size = tvb->ops->tvb_size;
113 g_slice_free1(size, tvb);
116 /* XXX: just call tvb_free_chain();
117 * Not removed so that existing dissectors using tvb_free() need not be changed.
118 * I'd argue that existing calls to tvb_free() should have actually beeen
119 * calls to tvb_free_chain() although the calls were OK as long as no
120 * subsets, etc had been created on the tvb. */
122 tvb_free(tvbuff_t *tvb)
128 tvb_free_chain(tvbuff_t *tvb)
131 DISSECTOR_ASSERT(tvb);
133 next_tvb = tvb->next;
134 tvb_free_internal(tvb);
140 tvb_new_chain(tvbuff_t *parent, tvbuff_t *backing)
142 tvbuff_t *tvb = tvb_new_proxy(backing);
144 tvb_add_to_chain(parent, tvb);
149 tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child)
151 tvbuff_t *tmp = child;
153 DISSECTOR_ASSERT(parent);
154 DISSECTOR_ASSERT(child);
160 tmp->next = parent->next;
166 * Check whether that offset goes more than one byte past the
169 * If not, return 0; otherwise, return exception
172 validate_offset(const tvbuff_t *tvb, const guint abs_offset)
174 if (G_LIKELY(abs_offset <= tvb->length))
176 else if (abs_offset <= tvb->reported_length)
178 else if (tvb->flags & TVBUFF_FRAGMENT)
179 return FragmentBoundsError;
181 return ReportedBoundsError;
185 compute_offset(const tvbuff_t *tvb, const gint offset, guint *offset_ptr)
188 /* Positive offset - relative to the beginning of the packet. */
189 if ((guint) offset <= tvb->length) {
190 *offset_ptr = offset;
191 } else if ((guint) offset <= tvb->reported_length) {
193 } else if (tvb->flags & TVBUFF_FRAGMENT) {
194 return FragmentBoundsError;
196 return ReportedBoundsError;
200 /* Negative offset - relative to the end of the packet. */
201 if ((guint) -offset <= tvb->length) {
202 *offset_ptr = tvb->length + offset;
203 } else if ((guint) -offset <= tvb->reported_length) {
205 } else if (tvb->flags & TVBUFF_FRAGMENT) {
206 return FragmentBoundsError;
208 return ReportedBoundsError;
216 compute_offset_and_remaining(const tvbuff_t *tvb, const gint offset, guint *offset_ptr, guint *rem_len)
220 exception = compute_offset(tvb, offset, offset_ptr);
222 *rem_len = tvb->length - *offset_ptr;
227 /* Computes the absolute offset and length based on a possibly-negative offset
228 * and a length that is possible -1 (which means "to the end of the data").
229 * Returns integer indicating whether the offset is in bounds (0) or
230 * not (exception number). The integer ptrs are modified with the new offset and length.
231 * No exception is thrown.
233 * XXX - we return success (0), if the offset is positive and right
234 * after the end of the tvbuff (i.e., equal to the length). We do this
235 * so that a dissector constructing a subset tvbuff for the next protocol
236 * will get a zero-length tvbuff, not an exception, if there's no data
237 * left for the next protocol - we want the next protocol to be the one
238 * that gets an exception, so the error is reported as an error in that
239 * protocol rather than the containing protocol. */
241 check_offset_length_no_exception(const tvbuff_t *tvb,
242 const gint offset, gint const length_val,
243 guint *offset_ptr, guint *length_ptr)
248 DISSECTOR_ASSERT(offset_ptr);
249 DISSECTOR_ASSERT(length_ptr);
251 /* Compute the offset */
252 exception = compute_offset(tvb, offset, offset_ptr);
256 if (length_val < -1) {
257 /* XXX - ReportedBoundsError? */
261 /* Compute the length */
262 if (length_val == -1)
263 *length_ptr = tvb->length - *offset_ptr;
265 *length_ptr = length_val;
268 * Compute the offset of the first byte past the length.
270 end_offset = *offset_ptr + *length_ptr;
273 * Check for an overflow
275 if (end_offset < *offset_ptr)
278 return validate_offset(tvb, end_offset);
281 /* Checks (+/-) offset and length and throws an exception if
282 * either is out of bounds. Sets integer ptrs to the new offset
285 check_offset_length(const tvbuff_t *tvb,
286 const gint offset, gint const length_val,
287 guint *offset_ptr, guint *length_ptr)
291 exception = check_offset_length_no_exception(tvb, offset, length_val, offset_ptr, length_ptr);
297 tvb_check_offset_length(const tvbuff_t *tvb,
298 const gint offset, gint const length_val,
299 guint *offset_ptr, guint *length_ptr)
301 check_offset_length(tvb, offset, length_val, offset_ptr, length_ptr);
304 static const unsigned char left_aligned_bitmask[] = {
316 tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits)
318 tvbuff_t *sub_tvb = NULL;
321 guint8 left, right, remaining_bits, *buf;
324 DISSECTOR_ASSERT(tvb && tvb->initialized);
326 byte_offset = bit_offset >> 3;
327 left = bit_offset % 8; /* for left-shifting */
328 right = 8 - left; /* for right-shifting */
330 if (no_of_bits == -1) {
331 datalen = _tvb_captured_length_remaining(tvb, byte_offset);
334 datalen = no_of_bits >> 3;
335 remaining_bits = no_of_bits % 8;
336 if (remaining_bits) {
341 /* already aligned -> shortcut */
342 if ((left == 0) && (remaining_bits == 0)) {
343 return tvb_new_subset(tvb, byte_offset, datalen, -1);
346 DISSECTOR_ASSERT(datalen>0);
348 /* if at least one trailing byte is available, we must use the content
349 * of that byte for the last shift (i.e. tvb_get_ptr() must use datalen + 1
350 * if non extra byte is available, the last shifted byte requires
353 if (_tvb_captured_length_remaining(tvb, byte_offset) > datalen) {
354 data = ensure_contiguous(tvb, byte_offset, datalen + 1); /* tvb_get_ptr */
356 /* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
357 buf = (guint8 *)g_malloc(datalen);
359 /* shift tvb data bit_offset bits to the left */
360 for (i = 0; i < datalen; i++)
361 buf[i] = (data[i] << left) | (data[i+1] >> right);
363 data = ensure_contiguous(tvb, byte_offset, datalen); /* tvb_get_ptr() */
365 /* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
366 buf = (guint8 *)g_malloc(datalen);
368 /* shift tvb data bit_offset bits to the left */
369 for (i = 0; i < (datalen-1); i++)
370 buf[i] = (data[i] << left) | (data[i+1] >> right);
371 buf[datalen-1] = data[datalen-1] << left; /* set last octet */
373 buf[datalen-1] &= left_aligned_bitmask[remaining_bits];
375 sub_tvb = tvb_new_child_real_data(tvb, buf, datalen, datalen);
376 tvb_set_free_cb(sub_tvb, g_free);
382 tvb_generic_clone_offset_len(tvbuff_t *tvb, guint offset, guint len)
384 tvbuff_t *cloned_tvb;
386 guint8 *data = (guint8 *) g_malloc(len);
388 tvb_memcpy(tvb, data, offset, len);
390 cloned_tvb = tvb_new_real_data(data, len, len);
391 tvb_set_free_cb(cloned_tvb, g_free);
397 tvb_clone_offset_len(tvbuff_t *tvb, guint offset, guint len)
399 if (tvb->ops->tvb_clone) {
400 tvbuff_t *cloned_tvb;
402 cloned_tvb = tvb->ops->tvb_clone(tvb, offset, len);
407 return tvb_generic_clone_offset_len(tvb, offset, len);
411 tvb_clone(tvbuff_t *tvb)
413 return tvb_clone_offset_len(tvb, 0, tvb->length);
417 tvb_captured_length(const tvbuff_t *tvb)
419 DISSECTOR_ASSERT(tvb && tvb->initialized);
424 /* For tvbuff internal use */
426 _tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
428 guint abs_offset, rem_length;
431 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
439 tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
441 guint abs_offset, rem_length;
444 DISSECTOR_ASSERT(tvb && tvb->initialized);
446 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
454 tvb_ensure_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
456 guint abs_offset, rem_length;
459 DISSECTOR_ASSERT(tvb && tvb->initialized);
461 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
465 if (rem_length == 0) {
467 * This routine ensures there's at least one byte available.
468 * There aren't any bytes available, so throw the appropriate
471 if (abs_offset >= tvb->reported_length) {
472 if (tvb->flags & TVBUFF_FRAGMENT) {
473 THROW(FragmentBoundsError);
475 THROW(ReportedBoundsError);
486 /* Validates that 'length' bytes are available starting from
487 * offset (pos/neg). Does not throw an exception. */
489 tvb_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
491 guint abs_offset, abs_length;
494 DISSECTOR_ASSERT(tvb && tvb->initialized);
496 exception = check_offset_length_no_exception(tvb, offset, length, &abs_offset, &abs_length);
503 /* Validates that 'length' bytes are available starting from
504 * offset (pos/neg). Throws an exception if they aren't. */
506 tvb_ensure_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
508 guint real_offset, end_offset;
510 DISSECTOR_ASSERT(tvb && tvb->initialized);
513 * -1 doesn't mean "until end of buffer", as that's pointless
514 * for this routine. We must treat it as a Really Large Positive
515 * Number, so that we throw an exception; we throw
516 * ReportedBoundsError, as if it were past even the end of a
517 * reassembled packet, and past the end of even the data we
520 * We do the same with other negative lengths.
523 THROW(ReportedBoundsError);
526 /* XXX: Below this point could be replaced with a call to
527 * check_offset_length with no functional change, however this is a
528 * *very* hot path and check_offset_length is not well-optimized for
529 * this case, so we eat some code duplication for a lot of speedup. */
532 /* Positive offset - relative to the beginning of the packet. */
533 if ((guint) offset <= tvb->length) {
534 real_offset = offset;
535 } else if ((guint) offset <= tvb->reported_length) {
537 } else if (tvb->flags & TVBUFF_FRAGMENT) {
538 THROW(FragmentBoundsError);
540 THROW(ReportedBoundsError);
544 /* Negative offset - relative to the end of the packet. */
545 if ((guint) -offset <= tvb->length) {
546 real_offset = tvb->length + offset;
547 } else if ((guint) -offset <= tvb->reported_length) {
549 } else if (tvb->flags & TVBUFF_FRAGMENT) {
550 THROW(FragmentBoundsError);
552 THROW(ReportedBoundsError);
557 * Compute the offset of the first byte past the length.
559 end_offset = real_offset + length;
562 * Check for an overflow
564 if (end_offset < real_offset)
567 if (G_LIKELY(end_offset <= tvb->length))
569 else if (end_offset <= tvb->reported_length)
571 else if (tvb->flags & TVBUFF_FRAGMENT)
572 THROW(FragmentBoundsError);
574 THROW(ReportedBoundsError);
578 tvb_offset_exists(const tvbuff_t *tvb, const gint offset)
583 DISSECTOR_ASSERT(tvb && tvb->initialized);
585 exception = compute_offset(tvb, offset, &abs_offset);
589 /* compute_offset only throws an exception on >, not >= because of the
590 * comment above check_offset_length_no_exception, but here we want the
591 * opposite behaviour so we check ourselves... */
592 if (abs_offset < tvb->length) {
601 tvb_reported_length(const tvbuff_t *tvb)
603 DISSECTOR_ASSERT(tvb && tvb->initialized);
605 return tvb->reported_length;
609 tvb_reported_length_remaining(const tvbuff_t *tvb, const gint offset)
614 DISSECTOR_ASSERT(tvb && tvb->initialized);
616 exception = compute_offset(tvb, offset, &abs_offset);
620 if (tvb->reported_length >= abs_offset)
621 return tvb->reported_length - abs_offset;
626 /* Set the reported length of a tvbuff to a given value; used for protocols
627 * whose headers contain an explicit length and where the calling
628 * dissector's payload may include padding as well as the packet for
630 * Also adjusts the data length. */
632 tvb_set_reported_length(tvbuff_t *tvb, const guint reported_length)
634 DISSECTOR_ASSERT(tvb && tvb->initialized);
636 if (reported_length > tvb->reported_length)
637 THROW(ReportedBoundsError);
639 tvb->reported_length = reported_length;
640 if (reported_length < tvb->length)
641 tvb->length = reported_length;
645 tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const guint counter)
647 if (tvb->ops->tvb_offset)
648 return tvb->ops->tvb_offset(tvb, counter);
650 DISSECTOR_ASSERT_NOT_REACHED();
655 tvb_offset_from_real_beginning(const tvbuff_t *tvb)
657 return tvb_offset_from_real_beginning_counter(tvb, 0);
660 static inline const guint8*
661 ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length, int *pexception)
663 guint abs_offset, abs_length;
666 exception = check_offset_length_no_exception(tvb, offset, length, &abs_offset, &abs_length);
669 *pexception = exception;
674 * We know that all the data is present in the tvbuff, so
675 * no exceptions should be thrown.
678 return tvb->real_data + abs_offset;
680 if (tvb->ops->tvb_get_ptr)
681 return tvb->ops->tvb_get_ptr(tvb, abs_offset, abs_length);
683 DISSECTOR_ASSERT_NOT_REACHED();
687 static inline const guint8*
688 ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length)
693 p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
695 DISSECTOR_ASSERT(exception > 0);
701 static inline const guint8*
702 fast_ensure_contiguous(tvbuff_t *tvb, const gint offset, const guint length)
707 DISSECTOR_ASSERT(tvb && tvb->initialized);
708 /* We don't check for overflow in this fast path so we only handle simple types */
709 DISSECTOR_ASSERT(length <= 8);
711 if (offset < 0 || !tvb->real_data) {
712 return ensure_contiguous(tvb, offset, length);
716 end_offset = u_offset + length;
718 if (end_offset <= tvb->length) {
719 return tvb->real_data + u_offset;
722 if (end_offset > tvb->reported_length) {
723 if (tvb->flags & TVBUFF_FRAGMENT) {
724 THROW(FragmentBoundsError);
726 THROW(ReportedBoundsError);
735 static inline const guint8*
736 guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, guchar *found_needle)
738 gchar tmp[256] = { 0 };
739 const guint8 *haystack_end;
744 haystack_end = haystack + haystacklen;
745 while (haystack < haystack_end) {
746 if (tmp[*haystack]) {
748 *found_needle = *haystack;
759 /************** ACCESSORS **************/
762 tvb_memcpy(tvbuff_t *tvb, void *target, const gint offset, size_t length)
764 guint abs_offset, abs_length;
766 DISSECTOR_ASSERT(tvb && tvb->initialized);
769 * XXX - we should eliminate the "length = -1 means 'to the end
770 * of the tvbuff'" convention, and use other means to achieve
771 * that; this would let us eliminate a bunch of checks for
772 * negative lengths in cases where the protocol has a 32-bit
775 * Allowing -1 but throwing an assertion on other negative
776 * lengths is a bit more work with the length being a size_t;
777 * instead, we check for a length <= 2^31-1.
779 DISSECTOR_ASSERT(length <= 0x7FFFFFFF);
780 check_offset_length(tvb, offset, (gint) length, &abs_offset, &abs_length);
782 if (tvb->real_data) {
783 return memcpy(target, tvb->real_data + abs_offset, abs_length);
786 if (tvb->ops->tvb_memcpy)
787 return tvb->ops->tvb_memcpy(tvb, target, abs_offset, abs_length);
789 /* XXX, fallback to slower method */
791 DISSECTOR_ASSERT_NOT_REACHED();
797 * XXX - this doesn't treat a length of -1 as an error.
798 * If it did, this could replace some code that calls
799 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
802 * "composite_get_ptr()" depends on -1 not being
803 * an error; does anything else depend on this routine treating -1 as
804 * meaning "to the end of the buffer"?
806 * If scope is NULL, memory is allocated with g_malloc() and user must
807 * explicitly free it with g_free().
808 * If scope is not NULL, memory is allocated with the corresponding pool
812 tvb_memdup(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, size_t length)
814 guint abs_offset, abs_length;
817 DISSECTOR_ASSERT(tvb && tvb->initialized);
819 check_offset_length(tvb, offset, (gint) length, &abs_offset, &abs_length);
821 duped = wmem_alloc(scope, abs_length);
822 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
828 tvb_get_ptr(tvbuff_t *tvb, const gint offset, const gint length)
830 return ensure_contiguous(tvb, offset, length);
833 /* ---------------- */
835 tvb_get_guint8(tvbuff_t *tvb, const gint offset)
839 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint8));
844 tvb_get_ntohs(tvbuff_t *tvb, const gint offset)
848 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
853 tvb_get_ntoh24(tvbuff_t *tvb, const gint offset)
857 ptr = fast_ensure_contiguous(tvb, offset, 3);
862 tvb_get_ntohl(tvbuff_t *tvb, const gint offset)
866 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
871 tvb_get_ntoh40(tvbuff_t *tvb, const gint offset)
875 ptr = fast_ensure_contiguous(tvb, offset, 5);
880 tvb_get_ntohi40(tvbuff_t *tvb, const gint offset)
884 ret = ws_sign_ext64(tvb_get_ntoh40(tvb, offset), 40);
890 tvb_get_ntoh48(tvbuff_t *tvb, const gint offset)
894 ptr = fast_ensure_contiguous(tvb, offset, 6);
899 tvb_get_ntohi48(tvbuff_t *tvb, const gint offset)
903 ret = ws_sign_ext64(tvb_get_ntoh48(tvb, offset), 48);
909 tvb_get_ntoh56(tvbuff_t *tvb, const gint offset)
913 ptr = fast_ensure_contiguous(tvb, offset, 7);
918 tvb_get_ntohi56(tvbuff_t *tvb, const gint offset)
922 ret = ws_sign_ext64(tvb_get_ntoh56(tvb, offset), 56);
928 tvb_get_ntoh64(tvbuff_t *tvb, const gint offset)
932 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
937 * Stuff for IEEE float handling on platforms that don't have IEEE
938 * format as the native floating-point format.
940 * For now, we treat only the VAX as such a platform.
942 * XXX - other non-IEEE boxes that can run UNIX include some Crays,
943 * and possibly other machines.
945 * It appears that the official Linux port to System/390 and
946 * zArchitecture uses IEEE format floating point (not a
949 * I don't know whether there are any other machines that
950 * could run Wireshark and that don't use IEEE format.
951 * As far as I know, all of the main commercial microprocessor
952 * families on which OSes that support Wireshark can run
953 * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
964 #define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
965 #define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
966 #define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
968 #define IEEE_SP_SIGN_MASK 0x80000000
969 #define IEEE_SP_EXPONENT_MASK 0x7F800000
970 #define IEEE_SP_MANTISSA_MASK 0x007FFFFF
971 #define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
973 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
974 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
975 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
978 ieee_float_is_zero(const guint32 w)
980 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
984 get_ieee_float(const guint32 w)
990 sign = w & IEEE_SP_SIGN_MASK;
991 exponent = w & IEEE_SP_EXPONENT_MASK;
992 mantissa = w & IEEE_SP_MANTISSA_MASK;
994 if (ieee_float_is_zero(w)) {
995 /* number is zero, unnormalized, or not-a-number */
1000 * XXX - how to handle this?
1002 if (IEEE_SP_INFINITY == exponent) {
1004 * number is positive or negative infinity, or a special value
1006 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1010 exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1011 IEEE_SP_MANTISSA_WIDTH;
1012 mantissa |= IEEE_SP_IMPLIED_BIT;
1015 return -mantissa * pow(2, exponent);
1017 return mantissa * pow(2, exponent);
1022 * We assume that if you don't have IEEE floating-point, you have a
1023 * compiler that understands 64-bit integral quantities.
1025 #define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
1026 #define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
1027 #define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1029 #define IEEE_DP_SIGN_MASK G_GINT64_CONSTANT(0x8000000000000000)
1030 #define IEEE_DP_EXPONENT_MASK G_GINT64_CONSTANT(0x7FF0000000000000)
1031 #define IEEE_DP_MANTISSA_MASK G_GINT64_CONSTANT(0x000FFFFFFFFFFFFF)
1032 #define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
1034 #define IEEE_DP_IMPLIED_BIT (G_GINT64_CONSTANT(1) << IEEE_DP_MANTISSA_WIDTH)
1035 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1036 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1039 ieee_double_is_zero(const guint64 w)
1041 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1045 get_ieee_double(const guint64 w)
1051 sign = w & IEEE_DP_SIGN_MASK;
1052 exponent = w & IEEE_DP_EXPONENT_MASK;
1053 mantissa = w & IEEE_DP_MANTISSA_MASK;
1055 if (ieee_double_is_zero(w)) {
1056 /* number is zero, unnormalized, or not-a-number */
1061 * XXX - how to handle this?
1063 if (IEEE_DP_INFINITY == exponent) {
1065 * number is positive or negative infinity, or a special value
1067 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1071 exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1072 IEEE_DP_MANTISSA_WIDTH;
1073 mantissa |= IEEE_DP_IMPLIED_BIT;
1076 return -mantissa * pow(2, exponent);
1078 return mantissa * pow(2, exponent);
1083 * Fetches an IEEE single-precision floating-point number, in
1084 * big-endian form, and returns a "float".
1086 * XXX - should this be "double", in case there are IEEE single-
1087 * precision numbers that won't fit in some platform's native
1091 tvb_get_ntohieee_float(tvbuff_t *tvb, const int offset)
1094 return get_ieee_float(tvb_get_ntohl(tvb, offset));
1101 ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1102 return ieee_fp_union.f;
1107 * Fetches an IEEE double-precision floating-point number, in
1108 * big-endian form, and returns a "double".
1111 tvb_get_ntohieee_double(tvbuff_t *tvb, const int offset)
1125 #ifdef WORDS_BIGENDIAN
1126 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1127 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1129 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1130 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1133 return get_ieee_double(ieee_fp_union.dw);
1135 return ieee_fp_union.d;
1140 tvb_get_letohs(tvbuff_t *tvb, const gint offset)
1144 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
1145 return pletoh16(ptr);
1149 tvb_get_letoh24(tvbuff_t *tvb, const gint offset)
1153 ptr = fast_ensure_contiguous(tvb, offset, 3);
1154 return pletoh24(ptr);
1158 tvb_get_letohl(tvbuff_t *tvb, const gint offset)
1162 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1163 return pletoh32(ptr);
1167 tvb_get_letoh40(tvbuff_t *tvb, const gint offset)
1171 ptr = fast_ensure_contiguous(tvb, offset, 5);
1172 return pletoh40(ptr);
1176 tvb_get_letohi40(tvbuff_t *tvb, const gint offset)
1180 ret = ws_sign_ext64(tvb_get_letoh40(tvb, offset), 40);
1186 tvb_get_letoh48(tvbuff_t *tvb, const gint offset)
1190 ptr = fast_ensure_contiguous(tvb, offset, 6);
1191 return pletoh48(ptr);
1195 tvb_get_letohi48(tvbuff_t *tvb, const gint offset)
1199 ret = ws_sign_ext64(tvb_get_letoh48(tvb, offset), 48);
1205 tvb_get_letoh56(tvbuff_t *tvb, const gint offset)
1209 ptr = fast_ensure_contiguous(tvb, offset, 7);
1210 return pletoh56(ptr);
1214 tvb_get_letohi56(tvbuff_t *tvb, const gint offset)
1218 ret = ws_sign_ext64(tvb_get_letoh56(tvb, offset), 56);
1224 tvb_get_letoh64(tvbuff_t *tvb, const gint offset)
1228 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
1229 return pletoh64(ptr);
1233 * Fetches an IEEE single-precision floating-point number, in
1234 * little-endian form, and returns a "float".
1236 * XXX - should this be "double", in case there are IEEE single-
1237 * precision numbers that won't fit in some platform's native
1241 tvb_get_letohieee_float(tvbuff_t *tvb, const int offset)
1244 return get_ieee_float(tvb_get_letohl(tvb, offset));
1251 ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1252 return ieee_fp_union.f;
1257 * Fetches an IEEE double-precision floating-point number, in
1258 * little-endian form, and returns a "double".
1261 tvb_get_letohieee_double(tvbuff_t *tvb, const int offset)
1275 #ifdef WORDS_BIGENDIAN
1276 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1277 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1279 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1280 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1283 return get_ieee_double(ieee_fp_union.dw);
1285 return ieee_fp_union.d;
1290 validate_single_byte_ascii_encoding(const guint encoding)
1292 const guint enc = encoding & ~ENC_STR_MASK;
1298 case ENC_3GPP_TS_23_038_7BITS:
1300 REPORT_DISSECTOR_BUG("Invalid string encoding type passed to tvb_get_string_XXX");
1305 /* make sure something valid was set */
1307 REPORT_DISSECTOR_BUG("No string encoding type passed to tvb_get_string_XXX");
1311 tvb_get_string_bytes(tvbuff_t *tvb, const gint offset, const gint length,
1312 const guint encoding, GByteArray *bytes, gint *endoff)
1314 const gchar *ptr = (gchar*) tvb_get_raw_string(wmem_packet_scope(), tvb, offset, length);
1315 const gchar *begin = ptr;
1316 const gchar *end = NULL;
1317 GByteArray* retval = NULL;
1321 validate_single_byte_ascii_encoding(encoding);
1323 if (endoff) *endoff = 0;
1325 while (*begin == ' ') begin++;
1327 if (*begin && bytes) {
1328 if (hex_str_to_bytes_encoding(begin, bytes, &end, encoding, FALSE)) {
1329 if (bytes->len > 0) {
1330 if (endoff) *endoff = offset + (gint)(end - ptr);
1340 /* converts a broken down date representation, relative to UTC,
1341 * to a timestamp; it uses timegm() if it's available.
1342 * Copied from Glib source gtimer.c
1345 mktime_utc (struct tm *tm)
1350 static const gint days_before[] =
1352 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
1357 if (tm->tm_mon < 0 || tm->tm_mon > 11)
1360 retval = (tm->tm_year - 70) * 365;
1361 retval += (tm->tm_year - 68) / 4;
1362 retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
1364 if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
1367 retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec;
1369 retval = timegm (tm);
1370 #endif /* !HAVE_TIMEGM */
1375 /* support hex-encoded time values? */
1377 tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length,
1378 const guint encoding, nstime_t *ns, gint *endoff)
1380 const gchar *begin = (gchar*) tvb_get_raw_string(wmem_packet_scope(), tvb, offset, length);
1381 const gchar *ptr = begin;
1382 const gchar *end = NULL;
1384 nstime_t* retval = NULL;
1389 gboolean matched = FALSE;
1393 validate_single_byte_ascii_encoding(encoding);
1395 DISSECTOR_ASSERT(ns);
1397 memset(&tm, 0, sizeof(tm));
1402 while (*ptr == ' ') ptr++;
1405 /* note: sscanf is known to be inconsistent across platforms with respect
1406 to whether a %n is counted as a return value or not, so we have to use
1408 if ((encoding & ENC_ISO_8601_DATE_TIME) == ENC_ISO_8601_DATE_TIME) {
1409 /* TODO: using sscanf this many times is probably slow; might want
1410 to parse it by hand in the future */
1411 /* 2014-04-07T05:41:56+00:00 */
1412 if (sscanf(ptr, "%d-%d-%d%*c%d:%d:%d%c%d:%d%n",
1426 /* no seconds is ok */
1427 else if (sscanf(ptr, "%d-%d-%d%*c%d:%d%c%d:%d%n",
1440 /* 2007-04-05T14:30:56Z */
1441 else if (sscanf(ptr, "%d-%d-%d%*c%d:%d:%dZ%n",
1454 /* 2007-04-05T14:30Z no seconds is ok */
1455 else if (sscanf(ptr, "%d-%d-%d%*c%d:%dZ%n",
1470 end = ptr + num_chars;
1472 if (tm.tm_year > 1900) tm.tm_year -= 1900;
1473 if (sign == '-') off_hr = -off_hr;
1476 else if (encoding & ENC_ISO_8601_DATE) {
1478 if (sscanf(ptr, "%d-%d-%d%n",
1485 end = ptr + num_chars;
1487 if (tm.tm_year > 1900) tm.tm_year -= 1900;
1490 else if (encoding & ENC_ISO_8601_TIME) {
1492 if (sscanf(ptr, "%d:%d:%d%n",
1498 /* what should we do about day/month/year? */
1499 /* setting it to "now" for now */
1500 time_t time_now = time(NULL);
1501 struct tm *tm_now = gmtime(&time_now);
1502 tm.tm_year = tm_now->tm_year;
1503 tm.tm_mon = tm_now->tm_mon;
1504 tm.tm_mday = tm_now->tm_mday;
1505 end = ptr + num_chars;
1510 else if (encoding & ENC_RFC_822 || encoding & ENC_RFC_1123) {
1511 if (encoding & ENC_RFC_822) {
1512 /* this will unfortunately match ENC_RFC_1123 style
1513 strings too, partially - probably need to do this the long way */
1514 end = strptime(ptr, "%a, %d %b %y %H:%M:%S", &tm);
1515 if (!end) end = strptime(ptr, "%a, %d %b %y %H:%M", &tm);
1516 if (!end) end = strptime(ptr, "%d %b %y %H:%M:%S", &tm);
1517 if (!end) end = strptime(ptr, "%d %b %y %H:%M", &tm);
1519 else if (encoding & ENC_RFC_1123) {
1520 end = strptime(ptr, "%a, %d %b %Y %H:%M:%S", &tm);
1521 if (!end) end = strptime(ptr, "%a, %d %b %Y %H:%M", &tm);
1522 if (!end) end = strptime(ptr, "%d %b %Y %H:%M:%S", &tm);
1523 if (!end) end = strptime(ptr, "%d %b %Y %H:%M", &tm);
1527 if (*end == ' ') end++;
1528 if (g_ascii_strncasecmp(end, "UT", 2) == 0)
1532 else if (g_ascii_strncasecmp(end, "GMT", 3) == 0)
1536 else if (sscanf(end, "%c%2d%2d%n",
1544 if (sign == '-') off_hr = -off_hr;
1550 ns->secs = mktime_utc (&tm);
1552 ns->secs += (off_hr * 3600) + (off_min * 60);
1553 else if (off_hr < 0)
1554 ns->secs -= ((-off_hr) * 3600) + (off_min * 60);
1557 *endoff = (gint)(offset + (end - begin));
1563 /* Fetch an IPv4 address, in network byte order.
1564 * We do *not* convert them to host byte order; we leave them in
1565 * network byte order. */
1567 tvb_get_ipv4(tvbuff_t *tvb, const gint offset)
1572 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1573 memcpy(&addr, ptr, sizeof addr);
1577 /* Fetch an IPv6 address. */
1579 tvb_get_ipv6(tvbuff_t *tvb, const gint offset, struct e_in6_addr *addr)
1583 ptr = ensure_contiguous(tvb, offset, sizeof(*addr));
1584 memcpy(addr, ptr, sizeof *addr);
1589 tvb_get_ntohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
1591 const guint8 *ptr = ensure_contiguous(tvb, offset, GUID_LEN);
1593 guid->data1 = pntoh32(ptr + 0);
1594 guid->data2 = pntoh16(ptr + 4);
1595 guid->data3 = pntoh16(ptr + 6);
1596 memcpy(guid->data4, ptr + 8, sizeof guid->data4);
1600 tvb_get_letohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
1602 const guint8 *ptr = ensure_contiguous(tvb, offset, GUID_LEN);
1604 guid->data1 = pletoh32(ptr + 0);
1605 guid->data2 = pletoh16(ptr + 4);
1606 guid->data3 = pletoh16(ptr + 6);
1607 memcpy(guid->data4, ptr + 8, sizeof guid->data4);
1611 * NOTE: to support code written when proto_tree_add_item() took a
1612 * gboolean as its last argument, with FALSE meaning "big-endian"
1613 * and TRUE meaning "little-endian", we treat any non-zero value of
1614 * "representation" as meaning "little-endian".
1617 tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const guint representation)
1619 if (representation) {
1620 tvb_get_letohguid(tvb, offset, guid);
1622 tvb_get_ntohguid(tvb, offset, guid);
1626 static const guint8 bit_mask8[] = {
1638 /* Get 1 - 8 bits */
1640 tvb_get_bits8(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits)
1642 return (guint8)_tvb_get_bits64(tvb, bit_offset, no_of_bits);
1645 /* Get 9 - 16 bits */
1647 tvb_get_bits16(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits,const guint encoding _U_)
1649 /* note that encoding has no meaning here, as the tvb is considered to contain an octet array */
1650 return (guint16)_tvb_get_bits64(tvb, bit_offset, no_of_bits);
1653 /* Get 1 - 32 bits */
1655 tvb_get_bits32(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits, const guint encoding _U_)
1657 /* note that encoding has no meaning here, as the tvb is considered to contain an octet array */
1658 return (guint32)_tvb_get_bits64(tvb, bit_offset, no_of_bits);
1661 /* Get 1 - 64 bits */
1663 tvb_get_bits64(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits, const guint encoding _U_)
1665 /* note that encoding has no meaning here, as the tvb is considered to contain an octet array */
1666 return _tvb_get_bits64(tvb, bit_offset, no_of_bits);
1669 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
1670 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
1671 * Offset should be given in bits from the start of the tvb.
1672 * The function tolerates requests for more than 64 bits, but will only return the least significant 64 bits.
1675 _tvb_get_bits64(tvbuff_t *tvb, guint bit_offset, const gint total_no_of_bits)
1678 guint octet_offset = bit_offset >> 3;
1679 guint8 required_bits_in_first_octet = 8 - (bit_offset % 8);
1681 if(required_bits_in_first_octet > total_no_of_bits)
1683 /* the required bits don't extend to the end of the first octet */
1684 guint8 right_shift = required_bits_in_first_octet - total_no_of_bits;
1685 value = (tvb_get_guint8(tvb, octet_offset) >> right_shift) & bit_mask8[total_no_of_bits % 8];
1689 guint8 remaining_bit_length = total_no_of_bits;
1691 /* get the bits up to the first octet boundary */
1693 required_bits_in_first_octet %= 8;
1694 if(required_bits_in_first_octet != 0)
1696 value = tvb_get_guint8(tvb, octet_offset) & bit_mask8[required_bits_in_first_octet];
1697 remaining_bit_length -= required_bits_in_first_octet;
1700 /* take the biggest words, shorts or octets that we can */
1701 while (remaining_bit_length > 7)
1703 switch (remaining_bit_length >> 4)
1706 /* 8 - 15 bits. (note that 0 - 7 would have dropped out of the while() loop) */
1708 value += tvb_get_guint8(tvb, octet_offset);
1709 remaining_bit_length -= 8;
1716 value += tvb_get_ntohs(tvb, octet_offset);
1717 remaining_bit_length -= 16;
1725 value += tvb_get_ntohl(tvb, octet_offset);
1726 remaining_bit_length -= 32;
1731 /* 64 bits (or more???) */
1732 value = tvb_get_ntoh64(tvb, octet_offset);
1733 remaining_bit_length -= 64;
1738 /* get bits from any partial octet at the tail */
1739 if(remaining_bit_length)
1741 value <<= remaining_bit_length;
1742 value += (tvb_get_guint8(tvb, octet_offset) >> (8 - remaining_bit_length));
1747 /* Get 1 - 32 bits (should be deprecated as same as tvb_get_bits32??) */
1749 tvb_get_bits(tvbuff_t *tvb, const guint bit_offset, const gint no_of_bits, const guint encoding _U_)
1751 /* note that encoding has no meaning here, as the tvb is considered to contain an octet array */
1752 return (guint32)_tvb_get_bits64(tvb, bit_offset, no_of_bits);
1756 tvb_find_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
1759 const guint8 *result;
1761 ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr() */
1763 result = (const guint8 *) memchr(ptr, needle, limit);
1767 return (gint) ((result - ptr) + abs_offset);
1770 /* Find first occurrence of needle in tvbuff, starting at offset. Searches
1771 * at most maxlength number of bytes; if maxlength is -1, searches to
1773 * Returns the offset of the found needle, or -1 if not found.
1774 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1775 * in that case, -1 will be returned if the boundary is reached before
1776 * finding needle. */
1778 tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 needle)
1780 const guint8 *result;
1785 DISSECTOR_ASSERT(tvb && tvb->initialized);
1787 check_offset_length(tvb, offset, -1, &abs_offset, &tvbufflen);
1789 /* Only search to end of tvbuff, w/o throwing exception. */
1790 if (maxlength == -1) {
1791 /* No maximum length specified; search to end of tvbuff. */
1794 else if (tvbufflen < (guint) maxlength) {
1795 /* Maximum length goes past end of tvbuff; search to end
1800 /* Maximum length doesn't go past end of tvbuff; search
1805 /* If we have real data, perform our search now. */
1806 if (tvb->real_data) {
1807 result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
1808 if (result == NULL) {
1812 return (gint) (result - tvb->real_data);
1816 if (tvb->ops->tvb_find_guint8)
1817 return tvb->ops->tvb_find_guint8(tvb, abs_offset, limit, needle);
1819 return tvb_find_guint8_generic(tvb, offset, limit, needle);
1823 tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
1826 const guint8 *result;
1828 ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr */
1830 result = guint8_pbrk(ptr, limit, needles, found_needle);
1834 return (gint) ((result - ptr) + abs_offset);
1837 /* Find first occurrence of any of the needles in tvbuff, starting at offset.
1838 * Searches at most maxlength number of bytes; if maxlength is -1, searches
1840 * Returns the offset of the found needle, or -1 if not found.
1841 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1842 * in that case, -1 will be returned if the boundary is reached before
1843 * finding needle. */
1845 tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 *needles, guchar *found_needle)
1847 const guint8 *result;
1852 DISSECTOR_ASSERT(tvb && tvb->initialized);
1854 check_offset_length(tvb, offset, -1, &abs_offset, &tvbufflen);
1856 /* Only search to end of tvbuff, w/o throwing exception. */
1857 if (maxlength == -1) {
1858 /* No maximum length specified; search to end of tvbuff. */
1861 else if (tvbufflen < (guint) maxlength) {
1862 /* Maximum length goes past end of tvbuff; search to end
1867 /* Maximum length doesn't go past end of tvbuff; search
1872 /* If we have real data, perform our search now. */
1873 if (tvb->real_data) {
1874 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles, found_needle);
1875 if (result == NULL) {
1879 return (gint) (result - tvb->real_data);
1883 if (tvb->ops->tvb_pbrk_guint8)
1884 return tvb->ops->tvb_pbrk_guint8(tvb, abs_offset, limit, needles, found_needle);
1886 return tvb_pbrk_guint8_generic(tvb, abs_offset, limit, needles, found_needle);
1889 /* Find size of stringz (NUL-terminated string) by looking for terminating
1890 * NUL. The size of the string includes the terminating NUL.
1892 * If the NUL isn't found, it throws the appropriate exception.
1895 tvb_strsize(tvbuff_t *tvb, const gint offset)
1897 guint abs_offset, junk_length;
1900 DISSECTOR_ASSERT(tvb && tvb->initialized);
1902 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1903 nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1904 if (nul_offset == -1) {
1906 * OK, we hit the end of the tvbuff, so we should throw
1909 * Did we hit the end of the captured data, or the end
1910 * of the actual data? If there's less captured data
1911 * than actual data, we presumably hit the end of the
1912 * captured data, otherwise we hit the end of the actual
1915 if (tvb->length < tvb->reported_length) {
1918 if (tvb->flags & TVBUFF_FRAGMENT) {
1919 THROW(FragmentBoundsError);
1921 THROW(ReportedBoundsError);
1925 return (nul_offset - abs_offset) + 1;
1928 /* UTF-16/UCS-2 version of tvb_strsize */
1929 /* Returns number of bytes including the (two-bytes) null terminator */
1931 tvb_unicode_strsize(tvbuff_t *tvb, const gint offset)
1936 DISSECTOR_ASSERT(tvb && tvb->initialized);
1939 /* Endianness doesn't matter when looking for null */
1940 uchar = tvb_get_ntohs(tvb, offset + i);
1942 } while(uchar != 0);
1947 /* Find length of string by looking for end of string ('\0'), up to
1948 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1950 * Returns -1 if 'maxlength' reached before finding EOS. */
1952 tvb_strnlen(tvbuff_t *tvb, const gint offset, const guint maxlength)
1955 guint abs_offset, junk_length;
1957 DISSECTOR_ASSERT(tvb && tvb->initialized);
1959 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1961 result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1963 if (result_offset == -1) {
1967 return result_offset - abs_offset;
1972 * Implement strneql etc
1976 * Call strncmp after checking if enough chars left, returning 0 if
1977 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1980 tvb_strneql(tvbuff_t *tvb, const gint offset, const gchar *str, const size_t size)
1984 ptr = ensure_contiguous_no_exception(tvb, offset, (gint)size, NULL);
1987 int cmp = strncmp((const char *)ptr, str, size);
1990 * Return 0 if equal, -1 otherwise.
1992 return (cmp == 0 ? 0 : -1);
1995 * Not enough characters in the tvbuff to match the
2003 * Call g_ascii_strncasecmp after checking if enough chars left, returning
2004 * 0 if it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2007 tvb_strncaseeql(tvbuff_t *tvb, const gint offset, const gchar *str, const size_t size)
2011 ptr = ensure_contiguous_no_exception(tvb, offset, (gint)size, NULL);
2014 int cmp = g_ascii_strncasecmp((const char *)ptr, str, size);
2017 * Return 0 if equal, -1 otherwise.
2019 return (cmp == 0 ? 0 : -1);
2022 * Not enough characters in the tvbuff to match the
2030 * Call memcmp after checking if enough chars left, returning 0 if
2031 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2034 tvb_memeql(tvbuff_t *tvb, const gint offset, const guint8 *str, size_t size)
2038 ptr = ensure_contiguous_no_exception(tvb, offset, (gint) size, NULL);
2041 int cmp = memcmp(ptr, str, size);
2044 * Return 0 if equal, -1 otherwise.
2046 return (cmp == 0 ? 0 : -1);
2049 * Not enough characters in the tvbuff to match the
2057 * Format the data in the tvb from offset for length ...
2060 tvb_format_text(tvbuff_t *tvb, const gint offset, const gint size)
2065 len = (size > 0) ? size : 0;
2067 ptr = ensure_contiguous(tvb, offset, size);
2068 return format_text(ptr, len);
2072 * Format the data in the tvb from offset for length ...
2075 tvb_format_text_wsp(tvbuff_t *tvb, const gint offset, const gint size)
2080 len = (size > 0) ? size : 0;
2082 ptr = ensure_contiguous(tvb, offset, size);
2083 return format_text_wsp(ptr, len);
2087 * Like "tvb_format_text()", but for null-padded strings; don't show
2088 * the null padding characters as "\000".
2091 tvb_format_stringzpad(tvbuff_t *tvb, const gint offset, const gint size)
2093 const guint8 *ptr, *p;
2097 len = (size > 0) ? size : 0;
2099 ptr = ensure_contiguous(tvb, offset, size);
2100 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2102 return format_text(ptr, stringlen);
2106 * Like "tvb_format_text_wsp()", but for null-padded strings; don't show
2107 * the null padding characters as "\000".
2110 tvb_format_stringzpad_wsp(tvbuff_t *tvb, const gint offset, const gint size)
2112 const guint8 *ptr, *p;
2116 len = (size > 0) ? size : 0;
2118 ptr = ensure_contiguous(tvb, offset, size);
2119 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2121 return format_text_wsp(ptr, stringlen);
2124 /* Unicode REPLACEMENT CHARACTER */
2125 #define UNREPL 0x00FFFD
2128 * All string functions below take a scope as an argument.
2131 * If scope is NULL, memory is allocated with g_malloc() and user must
2132 * explicitly free it with g_free().
2133 * If scope is not NULL, memory is allocated with the corresponding pool
2136 * All functions throw an exception if the tvbuff ends before the string
2141 * Given a tvbuff, an offset, and a length, treat the string of bytes
2142 * referred to by them as an ASCII string, with all bytes with the
2143 * high-order bit set being invalid, and return a pointer to a
2146 * Octets with the highest bit set will be converted to the Unicode
2147 * REPLACEMENT CHARACTER.
2150 tvb_get_ascii_string(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length)
2155 ptr = ensure_contiguous(tvb, offset, length);
2157 str = wmem_strbuf_sized_new(scope, length+1, 0);
2159 while (length > 0) {
2163 wmem_strbuf_append_c(str, ch);
2165 wmem_strbuf_append_unichar(str, UNREPL);
2170 return (guint8 *) wmem_strbuf_finalize(str);
2174 * Given a tvbuff, an offset, and a length, treat the string of bytes
2175 * referred to by them as a UTF-8 string, and return a pointer to that
2178 * XXX - should map invalid UTF-8 sequences to UNREPL.
2181 tvb_get_utf_8_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length)
2185 tvb_ensure_bytes_exist(tvb, offset, length); /* make sure length = -1 fails */
2186 strbuf = (guint8 *)wmem_alloc(scope, length + 1);
2187 tvb_memcpy(tvb, strbuf, offset, length);
2188 strbuf[length] = '\0';
2193 * Given a tvbuff, an offset, and a length, treat the string of bytes
2194 * referred to by them as a raw string, and return a pointer to that
2195 * string. This means a null is appended at the end, but no replacement
2196 * checking is done otherwise. Currently tvb_get_utf_8_string() does
2197 * not replace either, but it might in the future.
2199 * Also, this one allows a length of -1 to mean get all, but does not
2200 * allow a negative offset.
2202 static inline guint8 *
2203 tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length)
2206 gint abs_length = length;
2208 DISSECTOR_ASSERT(offset >= 0);
2209 DISSECTOR_ASSERT(abs_length >= -1);
2212 abs_length = tvb->length - offset;
2214 tvb_ensure_bytes_exist(tvb, offset, abs_length);
2215 strbuf = (guint8 *)wmem_alloc(scope, abs_length + 1);
2216 tvb_memcpy(tvb, strbuf, offset, abs_length);
2217 strbuf[abs_length] = '\0';
2222 * Given a tvbuff, an offset, and a length, treat the string of bytes
2223 * referred to by them as an ISO 8859/1 string, with all bytes with the
2224 * high-order bit set being invalid, and return a pointer to a UTF-8
2228 tvb_get_string_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length)
2233 ptr = ensure_contiguous(tvb, offset, length);
2235 str = wmem_strbuf_sized_new(scope, length+1, 0);
2237 while (length > 0) {
2241 wmem_strbuf_append_c(str, ch);
2244 * Note: we assume here that the code points
2245 * 0x80-0x9F are used for C1 control characters,
2246 * and thus have the same value as the corresponding
2247 * Unicode code points.
2249 wmem_strbuf_append_unichar(str, ch);
2255 return (guint8 *) wmem_strbuf_finalize(str);
2259 * Given a tvbuff, an offset, and a length, and a translation table,
2260 * treat the string of bytes referred to by them as a string encoded
2261 * using one octet per character, with octets with the high-order bit
2262 * clear being ASCII and octets with the high-order bit set being
2263 * mapped by the translation table to 2-byte Unicode Basic Multilingual
2264 * Plane characters (including REPLACEMENT CHARACTER), and return a
2265 * pointer to a UTF-8 string.
2268 tvb_get_string_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length, const gunichar2 table[0x80])
2273 ptr = ensure_contiguous(tvb, offset, length);
2275 str = wmem_strbuf_sized_new(scope, length+1, 0);
2277 while (length > 0) {
2281 wmem_strbuf_append_c(str, ch);
2283 wmem_strbuf_append_unichar(str, table[ch-0x80]);
2288 return (guint8 *) wmem_strbuf_finalize(str);
2292 * Given a tvbuff, and offset, and a length, treat the string of bytes
2293 * referred to by them as a UCS-2 encoded string containing characters
2294 * from the Basic Multilingual Plane (plane 0) of Unicode, return a
2295 * pointer to a UTF-8 string.
2297 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
2299 * Specify length in bytes.
2301 * XXX - should map lead and trail surrogate values to REPLACEMENT
2302 * CHARACTERs (0xFFFD)?
2303 * XXX - if there are an odd number of bytes, should put a
2304 * REPLACEMENT CHARACTER at the end.
2306 static wmem_strbuf_t *
2307 tvb_extract_ucs_2_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2310 gint i; /* Byte counter for tvbuff */
2311 wmem_strbuf_t *strbuf;
2314 ptr = ensure_contiguous(tvb, offset, length);
2316 strbuf = wmem_strbuf_sized_new(scope, length+1, 0);
2318 for(i = 0; i + 1 < length; i += 2) {
2319 if (encoding == ENC_BIG_ENDIAN){
2320 uchar = pntoh16(ptr + i);
2322 uchar = pletoh16(ptr + i);
2324 wmem_strbuf_append_unichar(strbuf, uchar);
2328 * XXX - if i < length, this means we were handed an odd
2329 * number of bytes, so we're not a valid UCS-2 string.
2335 tvb_get_ucs_2_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2337 wmem_strbuf_t *strbuf;
2339 /*tvb_ensure_bytes_exist(tvb, offset, length); xhecked in the called routine */
2340 strbuf = tvb_extract_ucs_2_string(scope, tvb, offset, length, encoding);
2341 return (gchar*)wmem_strbuf_finalize(strbuf);
2345 * Given a tvbuff, and offset, and a length, treat the string of bytes
2346 * referred to by them as a UTF-16 encoded string, return a pointer to
2349 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
2351 * Specify length in bytes.
2353 * XXX - should map surrogate errors to REPLACEMENT CHARACTERs (0xFFFD).
2354 * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
2355 * XXX - if there are an odd number of bytes, should put a
2356 * REPLACEMENT CHARACTER at the end.
2358 static wmem_strbuf_t *
2359 tvb_extract_utf_16_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2361 wmem_strbuf_t *strbuf;
2362 gunichar2 uchar2, lead_surrogate;
2364 gint i; /* Byte counter for tvbuff */
2367 /* make sure length = -1 fails */
2369 THROW(ReportedBoundsError);
2372 ptr = ensure_contiguous(tvb, offset, length);
2374 strbuf = wmem_strbuf_sized_new(scope, length+1, 0);
2376 for(i = 0; i + 1 < length; i += 2) {
2377 if (encoding == ENC_BIG_ENDIAN)
2378 uchar2 = pletoh16(ptr + i);
2380 uchar2 = pletoh16(ptr + i);
2382 if (IS_LEAD_SURROGATE(uchar2)) {
2384 * Lead surrogate. Must be followed by
2385 * a trail surrogate.
2388 if (i + 1 >= length) {
2390 * Oops, string ends with a lead surrogate.
2391 * Ignore this for now.
2392 * XXX - insert "substitute" character?
2393 * Report the error in some other
2398 lead_surrogate = uchar2;
2399 if (encoding == ENC_BIG_ENDIAN)
2400 uchar2 = pletoh16(ptr + i);
2402 uchar2 = pletoh16(ptr + i);
2403 if (IS_TRAIL_SURROGATE(uchar2)) {
2404 /* Trail surrogate. */
2405 uchar = SURROGATE_VALUE(lead_surrogate, uchar2);
2406 wmem_strbuf_append_unichar(strbuf, uchar);
2409 * Not a trail surrogate.
2410 * Ignore the entire pair.
2411 * XXX - insert "substitute" character?
2412 * Report the error in some other
2418 if (IS_TRAIL_SURROGATE(uchar2)) {
2420 * Trail surrogate without a preceding
2421 * lead surrogate. Ignore it.
2422 * XXX - insert "substitute" character?
2423 * Report the error in some other
2429 * Non-surrogate; just append it.
2431 wmem_strbuf_append_unichar(strbuf, uchar2);
2437 * XXX - if i < length, this means we were handed an odd
2438 * number of bytes, so we're not a valid UTF-16 string.
2444 tvb_get_utf_16_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2446 wmem_strbuf_t *strbuf;
2448 /*tvb_ensure_bytes_exist(tvb, offset, length); checked in the called routine */
2449 strbuf = tvb_extract_utf_16_string(scope, tvb, offset, length, encoding);
2450 return (gchar*)wmem_strbuf_finalize(strbuf);
2454 * Given a tvbuff, and offset, and a length, treat the string of bytes
2455 * referred to by them as a UCS-4 encoded string, return a pointer to
2458 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
2460 * Specify length in bytes
2462 * XXX - should map lead and trail surrogate values to a "substitute"
2464 * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
2465 * XXX - if the number of bytes isn't a multiple of 4, should put a
2466 * REPLACEMENT CHARACTER at the end.
2468 static wmem_strbuf_t *
2469 tvb_extract_ucs_4_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2472 gint i; /* Byte counter for tvbuff */
2473 wmem_strbuf_t *strbuf;
2476 /* make sure length = -1 fails */
2478 THROW(ReportedBoundsError);
2481 ptr = ensure_contiguous(tvb, offset, length);
2483 strbuf = wmem_strbuf_sized_new(scope, length+1, 0);
2485 for(i = 0; i + 3 < length; i += 4) {
2486 if (encoding == ENC_BIG_ENDIAN)
2487 uchar = pletoh16(ptr + i);
2489 uchar = pletoh16(ptr + i);
2491 wmem_strbuf_append_unichar(strbuf, uchar);
2495 * XXX - if i < length, this means we were handed a number
2496 * of bytes that's not a multiple of 4, so we're not a valid
2503 tvb_get_ucs_4_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2505 wmem_strbuf_t *strbuf;
2507 /*tvb_ensure_bytes_exist(tvb, offset, length); checked in the called routine*/
2508 strbuf = tvb_extract_ucs_4_string(scope, tvb, offset, length, encoding);
2509 return (gchar*)wmem_strbuf_finalize(strbuf);
2517 #define GN_BYTE_MASK ((1 << bits) - 1)
2519 #define GN_CHAR_ALPHABET_SIZE 128
2521 #define GN_CHAR_ESCAPE 0x1b
2523 static const gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
2525 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
2527 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
2528 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
2529 0x394, '_', 0x3a6, 0x393, 0x39b, 0x3a9, 0x3a0, 0x3a8,
2530 0x3a3, 0x398, 0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
2531 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
2532 '(', ')', '*', '+', ',', '-', '.', '/',
2533 '0', '1', '2', '3', '4', '5', '6', '7',
2534 '8', '9', ':', ';', '<', '=', '>', '?',
2535 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
2536 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
2537 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
2538 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
2539 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
2540 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
2541 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
2542 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
2546 char_is_escape(unsigned char value)
2548 return (value == GN_CHAR_ESCAPE);
2552 char_def_alphabet_ext_decode(unsigned char value)
2556 case 0x0a: return 0x0c; /* form feed */
2557 case 0x14: return '^';
2558 case 0x28: return '{';
2559 case 0x29: return '}';
2560 case 0x2f: return '\\';
2561 case 0x3c: return '[';
2562 case 0x3d: return '~';
2563 case 0x3e: return ']';
2564 case 0x40: return '|';
2565 case 0x65: return 0x20ac; /* euro */
2566 default: return UNREPL; /* invalid character */
2571 char_def_alphabet_decode(unsigned char value)
2573 if (value < GN_CHAR_ALPHABET_SIZE)
2575 return gsm_default_alphabet[value];
2584 handle_ts_23_038_char(wmem_strbuf_t *strbuf, guint8 code_point,
2585 gboolean saw_escape)
2589 if (char_is_escape(code_point)) {
2591 * XXX - if saw_escape is TRUE here, then this is
2592 * the case where we escape to "another extension table",
2593 * but TS 128 038 V11.0 doesn't specify such an extension
2599 * Have we seen an escape?
2603 uchar = char_def_alphabet_ext_decode(code_point);
2605 uchar = char_def_alphabet_decode(code_point);
2607 wmem_strbuf_append_unichar(strbuf, uchar);
2613 tvb_get_ts_23_038_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
2614 const gint bit_offset, gint no_of_chars)
2616 wmem_strbuf_t *strbuf;
2617 gint char_count; /* character counter for tvbuff */
2618 gint in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
2619 guint8 in_byte, out_byte, rest = 0x00;
2620 gboolean saw_escape = FALSE;
2625 DISSECTOR_ASSERT(tvb && tvb->initialized);
2627 bits = bit_offset & 0x07;
2632 length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
2633 ptr = ensure_contiguous(tvb, in_offset, length);
2635 strbuf = wmem_strbuf_sized_new(scope, no_of_chars+1, 0);
2636 for(char_count = 0; char_count < no_of_chars;) {
2637 /* Get the next byte from the string. */
2642 * Combine the bits we've accumulated with bits from
2643 * that byte to make a 7-bit code point.
2645 out_byte = ((in_byte & GN_BYTE_MASK) << (7 - bits)) | rest;
2648 * Leftover bits used in that code point.
2650 rest = in_byte >> bits;
2653 * If we don't start from 0th bit, we shouldn't go to the
2654 * next char. Under *out_num we have now 0 and under Rest -
2655 * _first_ part of the char.
2657 if (char_count || (bits == 7)) {
2658 saw_escape = handle_ts_23_038_char(strbuf, out_byte,
2664 * After reading 7 octets we have read 7 full characters
2665 * but we have 7 bits as well. This is the next character.
2667 if ((bits == 1) && (char_count < no_of_chars)) {
2668 saw_escape = handle_ts_23_038_char(strbuf, rest,
2679 * Escape not followed by anything.
2681 * XXX - for now, show the escape as a REPLACEMENT
2684 wmem_strbuf_append_unichar(strbuf, UNREPL);
2687 return (gchar*)wmem_strbuf_finalize(strbuf);
2691 tvb_get_ascii_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
2692 const gint bit_offset, gint no_of_chars)
2694 wmem_strbuf_t *strbuf;
2695 gint char_count; /* character counter for tvbuff */
2696 gint in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
2697 guint8 in_byte, out_byte, rest = 0x00;
2702 DISSECTOR_ASSERT(tvb && tvb->initialized);
2704 bits = bit_offset & 0x07;
2709 length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
2710 ptr = ensure_contiguous(tvb, in_offset, length);
2712 strbuf = wmem_strbuf_sized_new(scope, no_of_chars+1, 0);
2713 for(char_count = 0; char_count < no_of_chars;) {
2714 /* Get the next byte from the string. */
2719 * Combine the bits we've accumulated with bits from
2720 * that byte to make a 7-bit code point.
2722 out_byte = (in_byte >> (8 - bits)) | rest;
2725 * Leftover bits used in that code point.
2727 rest = (in_byte << (bits - 1)) & 0x7f;
2730 * If we don't start from 0th bit, we shouldn't go to the
2731 * next char. Under *out_num we have now 0 and under Rest -
2732 * _first_ part of the char.
2734 if (char_count || (bits == 7)) {
2735 wmem_strbuf_append_c(strbuf, out_byte);
2740 * After reading 7 octets we have read 7 full characters
2741 * but we have 7 bits as well. This is the next character.
2743 if ((bits == 1) && (char_count < no_of_chars)) {
2744 wmem_strbuf_append_c(strbuf, rest);
2752 return (gchar*)wmem_strbuf_finalize(strbuf);
2756 * Given a tvbuff, an offset, a length, and an encoding, allocate a
2757 * buffer big enough to hold a non-null-terminated string of that length
2758 * at that offset, plus a trailing '\0', copy into the buffer the
2759 * string as converted from the appropriate encoding to UTF-8, and
2760 * return a pointer to the string.
2763 tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset,
2764 const gint length, const guint encoding)
2769 DISSECTOR_ASSERT(tvb && tvb->initialized);
2771 /* make sure length = -1 fails */
2773 THROW(ReportedBoundsError);
2776 switch (encoding & ENC_CHARENCODING_MASK) {
2781 * For now, we treat bogus values as meaning
2782 * "ASCII" rather than reporting an error,
2783 * for the benefit of old dissectors written
2784 * when the last argument to proto_tree_add_item()
2785 * was a gboolean for the byte order, not an
2786 * encoding value, and passed non-zero values
2787 * other than TRUE to mean "little-endian".
2789 strbuf = tvb_get_ascii_string(scope, tvb, offset, length);
2794 * XXX - should map lead and trail surrogate value code
2795 * points to a "substitute" UTF-8 character?
2796 * XXX - should map code points > 10FFFF to REPLACEMENT
2799 strbuf = tvb_get_utf_8_string(scope, tvb, offset, length);
2803 strbuf = tvb_get_utf_16_string(scope, tvb, offset, length,
2804 encoding & ENC_LITTLE_ENDIAN);
2808 strbuf = tvb_get_ucs_2_string(scope, tvb, offset, length,
2809 encoding & ENC_LITTLE_ENDIAN);
2813 strbuf = tvb_get_ucs_4_string(scope, tvb, offset, length,
2814 encoding & ENC_LITTLE_ENDIAN);
2817 case ENC_ISO_8859_1:
2819 * ISO 8859-1 printable code point values are equal
2820 * to the equivalent Unicode code point value, so
2821 * no translation table is needed.
2823 strbuf = tvb_get_string_8859_1(scope, tvb, offset, length);
2826 case ENC_ISO_8859_2:
2827 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_2);
2830 case ENC_ISO_8859_3:
2831 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_3);
2834 case ENC_ISO_8859_4:
2835 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_4);
2838 case ENC_ISO_8859_5:
2839 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_5);
2842 case ENC_ISO_8859_6:
2843 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_6);
2846 case ENC_ISO_8859_7:
2847 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_7);
2850 case ENC_ISO_8859_8:
2851 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_8);
2854 case ENC_ISO_8859_9:
2855 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_9);
2858 case ENC_ISO_8859_10:
2859 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_10);
2862 case ENC_ISO_8859_11:
2863 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_11);
2866 case ENC_ISO_8859_13:
2867 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_13);
2870 case ENC_ISO_8859_14:
2871 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_14);
2874 case ENC_ISO_8859_15:
2875 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_15);
2878 case ENC_ISO_8859_16:
2879 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_16);
2882 case ENC_WINDOWS_1250:
2883 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1250);
2887 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_mac_roman);
2891 strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp437);
2894 case ENC_3GPP_TS_23_038_7BITS:
2896 gint bit_offset = offset << 3;
2897 gint no_of_chars = (length << 3) / 7;
2898 strbuf = tvb_get_ts_23_038_7bits_string(scope, tvb, bit_offset, no_of_chars);
2902 case ENC_ASCII_7BITS:
2904 gint bit_offset = offset << 3;
2905 gint no_of_chars = (length << 3) / 7;
2906 strbuf = tvb_get_ascii_7bits_string(scope, tvb, bit_offset, no_of_chars);
2912 * XXX - do the copy and conversion in one pass.
2914 * XXX - multiple "dialects" of EBCDIC?
2916 tvb_ensure_bytes_exist(tvb, offset, length); /* make sure length = -1 fails */
2917 strbuf = (guint8 *)wmem_alloc(scope, length + 1);
2919 ptr = ensure_contiguous(tvb, offset, length);
2920 memcpy(strbuf, ptr, length);
2921 EBCDIC_to_ASCII(strbuf, length);
2923 strbuf[length] = '\0';
2930 * This is like tvb_get_string_enc(), except that it handles null-padded
2933 * Currently, string values are stored as UTF-8 null-terminated strings,
2934 * so nothing needs to be done differently for null-padded strings; we
2935 * could save a little memory by not storing the null padding.
2937 * If we ever store string values differently, in a fashion that doesn't
2938 * involve null termination, that might change.
2941 tvb_get_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset,
2942 const gint length, const guint encoding)
2944 return tvb_get_string_enc(scope, tvb, offset, length, encoding);
2948 * These routines are like the above routines, except that they handle
2949 * null-terminated strings. They find the length of that string (and
2950 * throw an exception if the tvbuff ends before we find the null), and
2951 * also return through a pointer the length of the string, in bytes,
2952 * including the terminating null (the terminating null being 2 bytes
2953 * for UCS-2 and UTF-16, 4 bytes for UCS-4, and 1 byte for other
2957 tvb_get_ascii_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp)
2963 size = tvb_strsize(tvb, offset);
2964 str = wmem_strbuf_sized_new(scope, size+1, 0);
2966 ptr = ensure_contiguous(tvb, offset, size);
2968 for (i = 0; i < size; i++) {
2972 wmem_strbuf_append_c(str, ch);
2974 wmem_strbuf_append_unichar(str, UNREPL);
2977 /* No need to append '\0' - we processed the NUL in the loop above. */
2982 return (guint8 *) wmem_strbuf_finalize(str);
2986 tvb_get_utf_8_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp)
2991 size = tvb_strsize(tvb, offset);
2992 strptr = (guint8 *)wmem_alloc(scope, size);
2993 tvb_memcpy(tvb, strptr, offset, size);
3000 tvb_get_stringz_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp)
3004 /* XXX, convertion between signed/unsigned integer */
3005 *lengthp = size = tvb_strsize(tvb, offset);
3007 return tvb_get_string_8859_1(scope, tvb, offset, size);
3011 tvb_get_stringz_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp, const gunichar2 table[0x80])
3015 /* XXX, convertion between signed/unsigned integer */
3016 *lengthp = size = tvb_strsize(tvb, offset);
3018 return tvb_get_string_unichar2(scope, tvb, offset, size, table);
3022 * Given a tvbuff and an offset, with the offset assumed to refer to
3023 * a null-terminated string, find the length of that string (and throw
3024 * an exception if the tvbuff ends before we find the null), ensure that
3025 * the TVB is flat, and return a pointer to the string (in the TVB).
3026 * Also return the length of the string (including the terminating null)
3027 * through a pointer.
3029 * As long as we aren't using composite TVBs, this saves the cycles used
3030 * (often unnecessariliy) in allocating a buffer and copying the string into
3031 * it. (If we do start using composite TVBs, we may want to replace this
3032 * function with the _ephemeral version.)
3035 tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
3038 const guint8 *strptr;
3040 size = tvb_strsize(tvb, offset);
3041 strptr = ensure_contiguous(tvb, offset, size);
3048 tvb_get_ucs_2_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
3050 gint size; /* Number of bytes in string */
3051 wmem_strbuf_t *strbuf;
3053 size = tvb_unicode_strsize(tvb, offset);
3055 strbuf = tvb_extract_ucs_2_string(scope, tvb, offset, size, encoding);
3060 return (gchar*)wmem_strbuf_finalize(strbuf);
3064 tvb_get_utf_16_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
3067 wmem_strbuf_t *strbuf;
3069 size = tvb_unicode_strsize(tvb, offset);
3071 strbuf = tvb_extract_utf_16_string(scope, tvb, offset, size, encoding);
3076 return (gchar*)wmem_strbuf_finalize(strbuf);
3080 tvb_get_ucs_4_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
3083 gint size; /* Number of bytes in string */
3084 wmem_strbuf_t *strbuf;
3088 /* Endianness doesn't matter when looking for null */
3089 uchar = tvb_get_ntohl(tvb, offset + size);
3091 } while(uchar != 0);
3093 strbuf = tvb_extract_ucs_4_string(scope, tvb, offset, size, encoding);
3096 *lengthp = size; /* Number of *bytes* processed */
3098 return (gchar*)wmem_strbuf_finalize(strbuf);
3102 tvb_get_stringz_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
3107 DISSECTOR_ASSERT(tvb && tvb->initialized);
3109 switch (encoding & ENC_CHARENCODING_MASK) {
3114 * For now, we treat bogus values as meaning
3115 * "ASCII" rather than reporting an error,
3116 * for the benefit of old dissectors written
3117 * when the last argument to proto_tree_add_item()
3118 * was a gboolean for the byte order, not an
3119 * encoding value, and passed non-zero values
3120 * other than TRUE to mean "little-endian".
3122 strptr = tvb_get_ascii_stringz(scope, tvb, offset, lengthp);
3127 * XXX - should map all invalid UTF-8 sequences
3128 * to a "substitute" UTF-8 character.
3129 * XXX - should map code points > 10FFFF to REPLACEMENT
3132 strptr = tvb_get_utf_8_stringz(scope, tvb, offset, lengthp);
3136 strptr = tvb_get_utf_16_stringz(scope, tvb, offset, lengthp,
3137 encoding & ENC_LITTLE_ENDIAN);
3141 strptr = tvb_get_ucs_2_stringz(scope, tvb, offset, lengthp,
3142 encoding & ENC_LITTLE_ENDIAN);
3146 strptr = tvb_get_ucs_4_stringz(scope, tvb, offset, lengthp,
3147 encoding & ENC_LITTLE_ENDIAN);
3150 case ENC_ISO_8859_1:
3152 * ISO 8859-1 printable code point values are equal
3153 * to the equivalent Unicode code point value, so
3154 * no translation table is needed.
3156 strptr = tvb_get_stringz_8859_1(scope, tvb, offset, lengthp);
3159 case ENC_ISO_8859_2:
3160 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_2);
3163 case ENC_ISO_8859_3:
3164 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_3);
3167 case ENC_ISO_8859_4:
3168 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_4);
3171 case ENC_ISO_8859_5:
3172 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_5);
3175 case ENC_ISO_8859_6:
3176 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_6);
3179 case ENC_ISO_8859_7:
3180 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_7);
3183 case ENC_ISO_8859_8:
3184 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_8);
3187 case ENC_ISO_8859_9:
3188 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_9);
3191 case ENC_ISO_8859_10:
3192 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_10);
3195 case ENC_ISO_8859_11:
3196 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_11);
3199 case ENC_ISO_8859_13:
3200 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_13);
3203 case ENC_ISO_8859_14:
3204 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_14);
3207 case ENC_ISO_8859_15:
3208 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_15);
3211 case ENC_ISO_8859_16:
3212 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_16);
3215 case ENC_WINDOWS_1250:
3216 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1250);
3220 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_mac_roman);
3224 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp437);
3227 case ENC_3GPP_TS_23_038_7BITS:
3228 REPORT_DISSECTOR_BUG("TS 23.038 7bits has no null character and doesn't support null-terminated strings");
3231 case ENC_ASCII_7BITS:
3232 REPORT_DISSECTOR_BUG("tvb_get_stringz_enc function with ENC_ASCII_7BITS not implemented yet");
3237 * XXX - do the copy and conversion in one pass.
3239 * XXX - multiple "dialects" of EBCDIC?
3241 size = tvb_strsize(tvb, offset);
3242 strptr = (guint8 *)wmem_alloc(scope, size);
3243 tvb_memcpy(tvb, strptr, offset, size);
3244 EBCDIC_to_ASCII(strptr, size);
3253 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
3254 * no more than bufsize number of bytes, including terminating NUL, to buffer.
3255 * Returns length of string (not including terminating NUL), or -1 if the string was
3256 * truncated in the buffer due to not having reached the terminating NUL.
3257 * In this way, it acts like g_snprintf().
3259 * bufsize MUST be greater than 0.
3261 * When processing a packet where the remaining number of bytes is less
3262 * than bufsize, an exception is not thrown if the end of the packet
3263 * is reached before the NUL is found. If no NUL is found before reaching
3264 * the end of the short packet, -1 is still returned, and the string
3265 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
3266 * at the correct spot, terminating the string.
3268 * *bytes_copied will contain the number of bytes actually copied,
3269 * including the terminating-NUL.
3272 _tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer, gint *bytes_copied)
3277 gboolean decreased_max = FALSE;
3279 /* Only read to end of tvbuff, w/o throwing exception. */
3280 check_offset_length(tvb, offset, -1, &abs_offset, &len);
3282 /* There must at least be room for the terminating NUL. */
3283 DISSECTOR_ASSERT(bufsize != 0);
3285 /* If there's no room for anything else, just return the NUL. */
3292 /* check_offset_length() won't throw an exception if we're
3293 * looking at the byte immediately after the end of the tvbuff. */
3295 THROW(ReportedBoundsError);
3298 /* This should not happen because check_offset_length() would
3299 * have already thrown an exception if 'offset' were out-of-bounds.
3301 DISSECTOR_ASSERT(len != -1);
3304 * If we've been passed a negative number, bufsize will
3307 DISSECTOR_ASSERT(bufsize <= G_MAXINT);
3309 if ((guint)len < bufsize) {
3311 decreased_max = TRUE;
3317 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
3318 /* If NUL wasn't found, copy the data and return -1 */
3319 if (stringlen == -1) {
3320 tvb_memcpy(tvb, buffer, abs_offset, limit);
3321 if (decreased_max) {
3323 /* Add 1 for the extra NUL that we set at buffer[limit],
3324 * pretending that it was copied as part of the string. */
3325 *bytes_copied = limit + 1;
3328 *bytes_copied = limit;
3333 /* Copy the string to buffer */
3334 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
3335 *bytes_copied = stringlen + 1;
3339 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
3340 * no more than bufsize number of bytes, including terminating NUL, to buffer.
3341 * Returns length of string (not including terminating NUL), or -1 if the string was
3342 * truncated in the buffer due to not having reached the terminating NUL.
3343 * In this way, it acts like g_snprintf().
3345 * When processing a packet where the remaining number of bytes is less
3346 * than bufsize, an exception is not thrown if the end of the packet
3347 * is reached before the NUL is found. If no NUL is found before reaching
3348 * the end of the short packet, -1 is still returned, and the string
3349 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
3350 * at the correct spot, terminating the string.
3353 tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8 *buffer)
3357 DISSECTOR_ASSERT(tvb && tvb->initialized);
3359 return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
3362 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
3363 * have a terminating NUL. If the string was truncated when copied into buffer,
3364 * a NUL is placed at the end of buffer to terminate it.
3367 tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer)
3369 gint len, bytes_copied;
3371 DISSECTOR_ASSERT(tvb && tvb->initialized);
3373 len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
3376 buffer[bufsize - 1] = 0;
3377 return bytes_copied - 1;
3385 * Given a tvbuff, an offset into the tvbuff, and a length that starts
3386 * at that offset (which may be -1 for "all the way to the end of the
3387 * tvbuff"), find the end of the (putative) line that starts at the
3388 * specified offset in the tvbuff, going no further than the specified
3391 * Return the length of the line (not counting the line terminator at
3392 * the end), or, if we don't find a line terminator:
3394 * if "deseg" is true, return -1;
3396 * if "deseg" is false, return the amount of data remaining in
3399 * Set "*next_offset" to the offset of the character past the line
3400 * terminator, or past the end of the buffer if we don't find a line
3401 * terminator. (It's not set if we return -1.)
3404 tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset, const gboolean desegment)
3409 guchar found_needle = 0;
3411 DISSECTOR_ASSERT(tvb && tvb->initialized);
3414 len = _tvb_captured_length_remaining(tvb, offset);
3416 * XXX - what if "len" is still -1, meaning "offset is past the
3417 * end of the tvbuff"?
3419 eob_offset = offset + len;
3422 * Look either for a CR or an LF.
3424 eol_offset = tvb_pbrk_guint8(tvb, offset, len, "\r\n", &found_needle);
3425 if (eol_offset == -1) {
3427 * No CR or LF - line is presumably continued in next packet.
3431 * Tell our caller we saw no EOL, so they can
3432 * try to desegment and get the entire line
3438 * Pretend the line runs to the end of the tvbuff.
3440 linelen = eob_offset - offset;
3442 *next_offset = eob_offset;
3446 * Find the number of bytes between the starting offset
3449 linelen = eol_offset - offset;
3454 if (found_needle == '\r') {
3456 * Yes - is it followed by an LF?
3458 if (eol_offset + 1 >= eob_offset) {
3460 * Dunno - the next byte isn't in this
3465 * We'll return -1, although that
3466 * runs the risk that if the line
3467 * really *is* terminated with a CR,
3468 * we won't properly dissect this
3471 * It's probably more likely that
3472 * the line ends with CR-LF than
3473 * that it ends with CR by itself.
3479 * Well, we can at least look at the next
3482 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
3484 * It's an LF; skip over the CR.
3492 * Return the offset of the character after the last
3493 * character in the line, skipping over the last character
3494 * in the line terminator.
3497 *next_offset = eol_offset + 1;
3503 * Given a tvbuff, an offset into the tvbuff, and a length that starts
3504 * at that offset (which may be -1 for "all the way to the end of the
3505 * tvbuff"), find the end of the (putative) line that starts at the
3506 * specified offset in the tvbuff, going no further than the specified
3509 * However, treat quoted strings inside the buffer specially - don't
3510 * treat newlines in quoted strings as line terminators.
3512 * Return the length of the line (not counting the line terminator at
3513 * the end), or the amount of data remaining in the buffer if we don't
3514 * find a line terminator.
3516 * Set "*next_offset" to the offset of the character past the line
3517 * terminator, or past the end of the buffer if we don't find a line
3521 tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len, gint *next_offset)
3523 gint cur_offset, char_offset;
3529 DISSECTOR_ASSERT(tvb && tvb->initialized);
3532 len = _tvb_captured_length_remaining(tvb, offset);
3534 * XXX - what if "len" is still -1, meaning "offset is past the
3535 * end of the tvbuff"?
3537 eob_offset = offset + len;
3539 cur_offset = offset;
3543 * Is this part of the string quoted?
3547 * Yes - look only for the terminating quote.
3549 char_offset = tvb_find_guint8(tvb, cur_offset, len,
3553 * Look either for a CR, an LF, or a '"'.
3555 char_offset = tvb_pbrk_guint8(tvb, cur_offset, len, "\r\n\"", &c);
3557 if (char_offset == -1) {
3559 * Not found - line is presumably continued in
3561 * We pretend the line runs to the end of the tvbuff.
3563 linelen = eob_offset - offset;
3565 *next_offset = eob_offset;
3571 * We're processing a quoted string.
3572 * We only looked for ", so we know it's a ";
3573 * as we're processing a quoted string, it's a
3583 * Un-quoted "; it begins a quoted
3589 * It's a CR or LF; we've found a line
3592 * Find the number of bytes between the
3593 * starting offset and the CR or LF.
3595 linelen = char_offset - offset;
3602 * Yes; is it followed by an LF?
3604 if (char_offset + 1 < eob_offset &&
3605 tvb_get_guint8(tvb, char_offset + 1)
3608 * Yes; skip over the CR.
3615 * Return the offset of the character after
3616 * the last character in the line, skipping
3617 * over the last character in the line
3618 * terminator, and quit.
3621 *next_offset = char_offset + 1;
3627 * Step past the character we found.
3629 cur_offset = char_offset + 1;
3630 if (cur_offset >= eob_offset) {
3632 * The character we found was the last character
3633 * in the tvbuff - line is presumably continued in
3635 * We pretend the line runs to the end of the tvbuff.
3637 linelen = eob_offset - offset;
3639 *next_offset = eob_offset;
3647 * Copied from the mgcp dissector. (This function should be moved to /epan )
3648 * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
3649 * character following offset or offset + maxlength -1 whichever
3653 * tvb - The tvbuff in which we are skipping whitespace.
3654 * offset - The offset in tvb from which we begin trying to skip whitespace.
3655 * maxlength - The maximum distance from offset that we may try to skip
3658 * Returns: The position in tvb of the first non-whitespace
3659 * character following offset or offset + maxlength -1 whichever
3663 tvb_skip_wsp(tvbuff_t *tvb, const gint offset, const gint maxlength)
3665 gint counter = offset;
3669 DISSECTOR_ASSERT(tvb && tvb->initialized);
3671 /* Get the length remaining */
3672 /*tvb_len = tvb_captured_length(tvb);*/
3673 tvb_len = tvb->length;
3675 end = offset + maxlength;
3681 /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
3682 for (counter = offset;
3684 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
3685 tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
3692 tvb_skip_wsp_return(tvbuff_t *tvb, const gint offset) {
3693 gint counter = offset;
3696 for(counter = offset; counter > 0 &&
3697 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
3698 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
3704 tvb_skip_guint8(tvbuff_t *tvb, int offset, const int maxlength, const guint8 ch)
3708 DISSECTOR_ASSERT(tvb && tvb->initialized);
3710 /* Get the length remaining */
3711 /*tvb_len = tvb_captured_length(tvb);*/
3712 tvb_len = tvb->length;
3714 end = offset + maxlength;
3718 while (offset < end) {
3719 guint8 tempch = tvb_get_guint8(tvb, offset);
3730 * Format a bunch of data from a tvbuff as bytes, returning a pointer
3731 * to the string with the formatted data, with "punct" as a byte
3735 tvb_bytes_to_ep_str_punct(tvbuff_t *tvb, const gint offset, const gint len, const gchar punct)
3737 return bytes_to_ep_str_punct(ensure_contiguous(tvb, offset, len), len, punct);
3742 * Given a tvbuff, an offset into the tvbuff, and a length that starts
3743 * at that offset (which may be -1 for "all the way to the end of the
3744 * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either
3745 * the low or high half byte, formating the digits according to an input digit set,
3746 * if NUll a default digit set of 0-9 returning "?" for overdecadic digits will be used.
3747 * A pointer to the packet scope allocated string will be returned.
3748 * Note a tvbuff content of 0xf is considered a 'filler' and will end the conversion.
3750 static dgt_set_t Dgt1_9_bcd = {
3752 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f*/
3753 '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?','?'
3757 tvb_bcd_dig_to_wmem_packet_str(tvbuff_t *tvb, const gint offset, const gint len, dgt_set_t *dgt, gboolean skip_first)
3763 gint t_offset = offset;
3765 DISSECTOR_ASSERT(tvb && tvb->initialized);
3771 /*length = tvb_captured_length(tvb);*/
3772 length = tvb->length;
3773 if (length < offset) {
3777 length = offset + len;
3779 digit_str = (char *)wmem_alloc(wmem_packet_scope(), (length - offset)*2+1);
3781 while (t_offset < length) {
3783 octet = tvb_get_guint8(tvb,t_offset);
3785 digit_str[i] = dgt->out[octet & 0x0f];
3791 * unpack second value in byte
3795 if (octet == 0x0f) /* odd number bytes - hit filler */
3798 digit_str[i] = dgt->out[octet & 0x0f];
3809 * Format a bunch of data from a tvbuff as bytes, returning a pointer
3810 * to the string with the formatted data.
3813 tvb_bytes_to_ep_str(tvbuff_t *tvb, const gint offset, const gint len)
3815 return bytes_to_ep_str(ensure_contiguous(tvb, offset, len), len);
3818 /* Find a needle tvbuff within a haystack tvbuff. */
3820 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const gint haystack_offset)
3822 guint haystack_abs_offset, haystack_abs_length;
3823 const guint8 *haystack_data;
3824 const guint8 *needle_data;
3825 const guint needle_len = needle_tvb->length;
3826 const guint8 *location;
3828 DISSECTOR_ASSERT(haystack_tvb && haystack_tvb->initialized);
3830 if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
3834 /* Get pointers to the tvbuffs' data. */
3835 haystack_data = ensure_contiguous(haystack_tvb, 0, -1);
3836 needle_data = ensure_contiguous(needle_tvb, 0, -1);
3838 check_offset_length(haystack_tvb, haystack_offset, -1,
3839 &haystack_abs_offset, &haystack_abs_length);
3841 location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
3842 needle_data, needle_len);
3845 return (gint) (location - haystack_data);
3852 tvb_raw_offset(tvbuff_t *tvb)
3854 return ((tvb->raw_offset==-1) ? (tvb->raw_offset = tvb_offset_from_real_beginning(tvb)) : tvb->raw_offset);
3858 tvb_set_fragment(tvbuff_t *tvb)
3860 tvb->flags |= TVBUFF_FRAGMENT;
3864 tvb_get_ds_tvb(tvbuff_t *tvb)
3866 return(tvb->ds_tvb);
3870 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3875 * indent-tabs-mode: t
3878 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
3879 * :indentSize=8:tabSize=8:noTabs=false: