2 * Routines for utilities to convert various other types to strings.
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "wmem/wmem.h"
33 #include "to_str-int.h"
35 #include <wsutil/pint.h>
38 * If a user _does_ pass in a too-small buffer, this is probably
39 * going to be too long to fit. However, even a partial string
40 * starting with "[Buf" should provide enough of a clue to be
43 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
46 low_nibble_of_octet_to_hex(guint8 oct)
48 /* At least one version of Apple's C compiler/linker is buggy, causing
49 a complaint from the linker about the "literal C string section"
50 not ending with '\0' if we initialize a 16-element "char" array with
51 a 16-character string, the fact that initializing such an array with
52 such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
53 '\0' byte in the string nonwithstanding. */
54 static const gchar hex_digits[16] =
55 { '0', '1', '2', '3', '4', '5', '6', '7',
56 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
58 return hex_digits[oct & 0xF];
62 byte_to_hex(char *out, guint32 dword)
64 *out++ = low_nibble_of_octet_to_hex(dword >> 4);
65 *out++ = low_nibble_of_octet_to_hex(dword);
70 word_to_hex(char *out, guint16 word)
72 out = byte_to_hex(out, word >> 8);
73 out = byte_to_hex(out, word);
78 word_to_hex_punct(char *out, guint16 word, char punct)
80 out = byte_to_hex(out, word >> 8);
82 out = byte_to_hex(out, word);
87 word_to_hex_npad(char *out, guint16 word)
90 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 12));
92 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 8));
94 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 4));
95 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 0));
100 dword_to_hex(char *out, guint32 dword)
102 out = word_to_hex(out, dword >> 16);
103 out = word_to_hex(out, dword);
108 dword_to_hex_punct(char *out, guint32 dword, char punct)
110 out = word_to_hex_punct(out, dword >> 16, punct);
112 out = word_to_hex_punct(out, dword, punct);
117 qword_to_hex(char *out, guint64 qword)
119 out = dword_to_hex(out, (guint32)(qword >> 32));
120 out = dword_to_hex(out, (guint32)(qword & 0xffffffff));
125 qword_to_hex_punct(char *out, guint64 qword, char punct)
127 out = dword_to_hex_punct(out, (guint32)(qword >> 32), punct);
129 out = dword_to_hex_punct(out, (guint32)(qword & 0xffffffff), punct);
134 * This does *not* null-terminate the string. It returns a pointer
135 * to the position in the string following the last character it
136 * puts there, so that the caller can either put the null terminator
137 * in or can append more stuff to the buffer.
139 * There needs to be at least len * 2 bytes left in the buffer.
142 bytes_to_hexstr(char *out, const guint8 *ad, guint32 len)
147 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
149 for (i = 0; i < len; i++)
150 out = byte_to_hex(out, ad[i]);
155 * This does *not* null-terminate the string. It returns a pointer
156 * to the position in the string following the last character it
157 * puts there, so that the caller can either put the null terminator
158 * in or can append more stuff to the buffer.
160 * There needs to be at least len * 3 - 1 bytes left in the buffer.
163 bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct)
168 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
170 out = byte_to_hex(out, ad[0]);
171 for (i = 1; i < len; i++) {
173 out = byte_to_hex(out, ad[i]);
178 /* Max string length for displaying byte string. */
179 #define MAX_BYTE_STR_LEN 48
181 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
182 * digits at at a time, with a specified punctuation character between
185 * If punct is '\0', no punctuation is applied (and thus
186 * the resulting string is (len-1) bytes shorter)
189 bytestring_to_str(wmem_allocator_t *scope, const guint8 *ad, const guint32 len, const char punct)
192 guint32 buflen = len;
197 return bytes_to_str(scope, ad, len);
200 REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
203 return wmem_strdup(scope, "");
205 buf=(gchar *)wmem_alloc(scope, MAX_BYTE_STR_LEN+3+1);
206 if (buflen > MAX_BYTE_STR_LEN/3) { /* bd_len > 16 */
208 buflen = MAX_BYTE_STR_LEN/3;
211 buf_ptr = bytes_to_hexstr_punct(buf, ad, buflen, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
214 *buf_ptr++ = punct; /* 1 byte */
215 buf_ptr = g_stpcpy(buf_ptr, "..."); /* 3 bytes */
223 bytes_to_str(wmem_allocator_t *scope, const guint8 *bd, int bd_len)
230 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
232 cur=(gchar *)wmem_alloc(scope, MAX_BYTE_STR_LEN+3+1);
233 if (bd_len <= 0) { cur[0] = '\0'; return cur; }
235 if (bd_len > MAX_BYTE_STR_LEN/2) { /* bd_len > 24 */
237 bd_len = MAX_BYTE_STR_LEN/2;
240 cur_ptr = bytes_to_hexstr(cur, bd, bd_len); /* max MAX_BYTE_STR_LEN bytes */
243 cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
245 *cur_ptr = '\0'; /* 1 byte */
250 guint32_to_str_buf_len(const guint32 u)
252 /* ((2^32)-1) == 2147483647 */
253 if (u >= 1000000000)return 10;
254 if (u >= 100000000) return 9;
255 if (u >= 10000000) return 8;
256 if (u >= 1000000) return 7;
257 if (u >= 100000) return 6;
258 if (u >= 10000) return 5;
259 if (u >= 1000) return 4;
260 if (u >= 100) return 3;
261 if (u >= 10) return 2;
267 guint64_to_str_buf_len(const guint64 u)
269 /* ((2^64)-1) == 18446744073709551615 */
271 if (u >= G_GUINT64_CONSTANT(10000000000000000000)) return 20;
272 if (u >= G_GUINT64_CONSTANT(1000000000000000000)) return 19;
273 if (u >= G_GUINT64_CONSTANT(100000000000000000)) return 18;
274 if (u >= G_GUINT64_CONSTANT(10000000000000000)) return 17;
275 if (u >= G_GUINT64_CONSTANT(1000000000000000)) return 16;
276 if (u >= G_GUINT64_CONSTANT(100000000000000)) return 15;
277 if (u >= G_GUINT64_CONSTANT(10000000000000)) return 14;
278 if (u >= G_GUINT64_CONSTANT(1000000000000)) return 13;
279 if (u >= G_GUINT64_CONSTANT(100000000000)) return 12;
280 if (u >= G_GUINT64_CONSTANT(10000000000)) return 11;
281 if (u >= G_GUINT64_CONSTANT(1000000000)) return 10;
282 if (u >= G_GUINT64_CONSTANT(100000000)) return 9;
283 if (u >= G_GUINT64_CONSTANT(10000000)) return 8;
284 if (u >= G_GUINT64_CONSTANT(1000000)) return 7;
285 if (u >= G_GUINT64_CONSTANT(100000)) return 6;
286 if (u >= G_GUINT64_CONSTANT(10000)) return 5;
287 if (u >= G_GUINT64_CONSTANT(1000)) return 4;
288 if (u >= G_GUINT64_CONSTANT(100)) return 3;
289 if (u >= G_GUINT64_CONSTANT(10)) return 2;
294 static const char fast_strings[][4] = {
295 "0", "1", "2", "3", "4", "5", "6", "7",
296 "8", "9", "10", "11", "12", "13", "14", "15",
297 "16", "17", "18", "19", "20", "21", "22", "23",
298 "24", "25", "26", "27", "28", "29", "30", "31",
299 "32", "33", "34", "35", "36", "37", "38", "39",
300 "40", "41", "42", "43", "44", "45", "46", "47",
301 "48", "49", "50", "51", "52", "53", "54", "55",
302 "56", "57", "58", "59", "60", "61", "62", "63",
303 "64", "65", "66", "67", "68", "69", "70", "71",
304 "72", "73", "74", "75", "76", "77", "78", "79",
305 "80", "81", "82", "83", "84", "85", "86", "87",
306 "88", "89", "90", "91", "92", "93", "94", "95",
307 "96", "97", "98", "99", "100", "101", "102", "103",
308 "104", "105", "106", "107", "108", "109", "110", "111",
309 "112", "113", "114", "115", "116", "117", "118", "119",
310 "120", "121", "122", "123", "124", "125", "126", "127",
311 "128", "129", "130", "131", "132", "133", "134", "135",
312 "136", "137", "138", "139", "140", "141", "142", "143",
313 "144", "145", "146", "147", "148", "149", "150", "151",
314 "152", "153", "154", "155", "156", "157", "158", "159",
315 "160", "161", "162", "163", "164", "165", "166", "167",
316 "168", "169", "170", "171", "172", "173", "174", "175",
317 "176", "177", "178", "179", "180", "181", "182", "183",
318 "184", "185", "186", "187", "188", "189", "190", "191",
319 "192", "193", "194", "195", "196", "197", "198", "199",
320 "200", "201", "202", "203", "204", "205", "206", "207",
321 "208", "209", "210", "211", "212", "213", "214", "215",
322 "216", "217", "218", "219", "220", "221", "222", "223",
323 "224", "225", "226", "227", "228", "229", "230", "231",
324 "232", "233", "234", "235", "236", "237", "238", "239",
325 "240", "241", "242", "243", "244", "245", "246", "247",
326 "248", "249", "250", "251", "252", "253", "254", "255"
330 guint32_to_str_buf(guint32 u, gchar *buf, int buf_len)
332 int str_len = guint32_to_str_buf_len(u)+1;
334 gchar *bp = &buf[str_len];
336 if (buf_len < str_len) {
337 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
343 uint_to_str_back(bp, u);
347 guint64_to_str_buf(guint64 u, gchar *buf, int buf_len)
349 int str_len = guint64_to_str_buf_len(u)+1;
351 gchar *bp = &buf[str_len];
353 if (buf_len < str_len) {
354 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
360 uint64_to_str_back(bp, u);
363 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
364 #define COMMA(do_it) ((do_it) ? ", " : "")
367 * Maximum length of a string showing days/hours/minutes/seconds.
368 * (Does not include the terminating '\0'.)
369 * Includes space for a '-' sign for any negative components.
370 * -12345 days, 12 hours, 12 minutes, 12.123 seconds
372 #define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
375 * Convert a value in seconds and fractions of a second to a string,
376 * giving time in days, hours, minutes, and seconds, and put the result
378 * "is_nsecs" says that "frac" is microseconds if true and milliseconds
380 * If time is negative, add a '-' to all non-null components.
383 time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
386 int hours, mins, secs;
387 const gchar *msign = "";
388 gboolean do_comma = FALSE;
390 if(time_val == G_MININT32) { /* That Which Shall Not Be Negated */
391 wmem_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
396 time_val = -time_val;
400 secs = time_val % 60;
402 mins = time_val % 60;
404 hours = time_val % 24;
408 wmem_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
413 wmem_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
418 wmem_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
422 if (secs != 0 || frac != 0) {
425 wmem_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
427 wmem_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
429 wmem_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
434 time_secs_to_str(wmem_allocator_t *scope, const gint32 time_val)
439 return wmem_strdup(scope, "0 seconds");
442 buf = wmem_strbuf_sized_new(scope, TIME_SECS_LEN+1, TIME_SECS_LEN+1);
444 time_secs_to_str_buf(time_val, 0, FALSE, buf);
446 return wmem_strbuf_finalize(buf);
450 time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
453 int hours, mins, secs;
454 gboolean do_comma = FALSE;
456 secs = time_val % 60;
458 mins = time_val % 60;
460 hours = time_val % 24;
464 wmem_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
468 wmem_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
472 wmem_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
475 if (secs != 0 || frac != 0) {
478 wmem_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
480 wmem_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
482 wmem_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
487 time_secs_to_str_unsigned(wmem_allocator_t *scope, const guint32 time_val)
492 return wmem_strdup(scope, "0 seconds");
495 buf = wmem_strbuf_sized_new(scope, TIME_SECS_LEN+1, TIME_SECS_LEN+1);
497 time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
499 return wmem_strbuf_finalize(buf);
504 time_msecs_to_str(wmem_allocator_t *scope, gint32 time_val)
510 return wmem_strdup(scope, "0 seconds");
513 buf = wmem_strbuf_sized_new(scope, TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
516 /* oops we got passed a negative time */
518 msecs = time_val % 1000;
522 msecs = time_val % 1000;
526 time_secs_to_str_buf(time_val, msecs, FALSE, buf);
528 return wmem_strbuf_finalize(buf);
531 static const char mon_names[12][4] = {
547 get_zonename(struct tm *tmp)
549 #if defined(HAVE_TM_ZONE)
552 if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
555 # if defined(HAVE_TZNAME)
556 return tzname[tmp->tm_isdst];
558 # elif defined(_WIN32)
559 /* Windows C Runtime: */
560 /* _tzname is encoded using the "system default ansi code page" */
561 /* ("which is not necessarily the same as the C library locale"). */
562 /* So: _tzname must be converted to UTF8 before use. */
563 /* Alternative: use Windows GetTimeZoneInformation() to get the */
564 /* timezone name in UTF16 and convert same to UTF8. */
565 /* XXX: the result is that the timezone name will be based upon the */
566 /* system code page (iow: the charset of the system). */
567 /* Since Wireshark is not internationalized, it would seem more */
568 /* correct to show the timezone name in English, no matter what */
569 /* the system code page, but I don't how to do that (or if it's */
570 /* really even possible). */
571 /* In any case converting to UTF8 presumably at least keeps GTK */
572 /* happy. (A bug was reported wherein Wireshark crashed in GDK */
573 /* on a "Japanese version of Windows XP" when trying to copy */
574 /* the date/time string (containing a copy of _tz_name) to the */
578 static char *ws_tzname[2] = {NULL, NULL};
580 /* The g_malloc'd value returned from g_locale_to_utf8() is */
581 /* cached for all further use so there's no need to ever */
582 /* g_free() that value. */
583 if (ws_tzname[tmp->tm_isdst] == NULL) {
584 ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
585 if (ws_tzname[tmp->tm_isdst] == NULL) {
586 ws_tzname[tmp->tm_isdst] = "???";
589 return ws_tzname[tmp->tm_isdst];
592 return tmp->tm_isdst ? "?DT" : "?ST";
599 abs_time_to_str(wmem_allocator_t *scope, const nstime_t *abs_time, const absolute_time_display_e fmt,
602 struct tm *tmp = NULL;
603 const char *zonename = "???";
609 case ABSOLUTE_TIME_UTC:
610 case ABSOLUTE_TIME_DOY_UTC:
611 tmp = gmtime(&abs_time->secs);
615 case ABSOLUTE_TIME_LOCAL:
616 tmp = localtime(&abs_time->secs);
618 zonename = get_zonename(tmp);
625 case ABSOLUTE_TIME_DOY_UTC:
627 buf = wmem_strdup_printf(scope,
628 "%04d/%03d:%02d:%02d:%02d.%09ld %s",
634 (long)abs_time->nsecs,
637 buf = wmem_strdup_printf(scope,
638 "%04d/%03d:%02d:%02d:%02d.%09ld",
644 (long)abs_time->nsecs);
648 case ABSOLUTE_TIME_UTC:
649 case ABSOLUTE_TIME_LOCAL:
651 buf = wmem_strdup_printf(scope,
652 "%s %2d, %d %02d:%02d:%02d.%09ld %s",
653 mon_names[tmp->tm_mon],
659 (long)abs_time->nsecs,
662 buf = wmem_strdup_printf(scope,
663 "%s %2d, %d %02d:%02d:%02d.%09ld",
664 mon_names[tmp->tm_mon],
670 (long)abs_time->nsecs);
675 buf = wmem_strdup(scope, "Not representable");
680 abs_time_secs_to_str(wmem_allocator_t *scope, const time_t abs_time, const absolute_time_display_e fmt,
683 struct tm *tmp = NULL;
684 const char *zonename = "???";
689 case ABSOLUTE_TIME_UTC:
690 case ABSOLUTE_TIME_DOY_UTC:
691 tmp = gmtime(&abs_time);
695 case ABSOLUTE_TIME_LOCAL:
696 tmp = localtime(&abs_time);
698 zonename = get_zonename(tmp);
705 case ABSOLUTE_TIME_DOY_UTC:
707 buf = wmem_strdup_printf(scope,
708 "%04d/%03d:%02d:%02d:%02d %s",
716 buf = wmem_strdup_printf(scope,
717 "%04d/%03d:%02d:%02d:%02d",
726 case ABSOLUTE_TIME_UTC:
727 case ABSOLUTE_TIME_LOCAL:
729 buf = wmem_strdup_printf(scope,
730 "%s %2d, %d %02d:%02d:%02d %s",
731 mon_names[tmp->tm_mon],
739 buf = wmem_strdup_printf(scope,
740 "%s %2d, %d %02d:%02d:%02d",
741 mon_names[tmp->tm_mon],
751 buf = wmem_strdup(scope, "Not representable");
756 display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
757 const to_str_time_res_t units)
759 /* this buffer is not NUL terminated */
760 gint8 num_buf[16]; /* max: '-2147483648', '.1000000000' */
761 gint8 *num_end = &num_buf[16];
768 /* If the fractional part of the time stamp is negative,
769 print its absolute value and, if the seconds part isn't
770 (the seconds part should be zero in that case), stick
771 a "-" in front of the entire time stamp. */
781 num_ptr = int_to_str_back(num_end, sec);
783 num_len = MIN((int) (num_end - num_ptr), buflen);
784 memcpy(buf, num_ptr, num_len);
789 case TO_STR_TIME_RES_T_SECS:
795 case TO_STR_TIME_RES_T_DSECS:
796 num_ptr = uint_to_str_back_len(num_end, frac, 1);
799 case TO_STR_TIME_RES_T_CSECS:
800 num_ptr = uint_to_str_back_len(num_end, frac, 2);
803 case TO_STR_TIME_RES_T_MSECS:
804 num_ptr = uint_to_str_back_len(num_end, frac, 3);
807 case TO_STR_TIME_RES_T_USECS:
808 num_ptr = uint_to_str_back_len(num_end, frac, 6);
811 case TO_STR_TIME_RES_T_NSECS:
812 num_ptr = uint_to_str_back_len(num_end, frac, 9);
820 num_len = MIN((int) (num_end - num_ptr), buflen);
821 memcpy(buf, num_ptr, num_len);
826 /* need to NUL terminate, we know that buffer had at least 1 byte */
834 display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
835 const to_str_time_res_t units)
839 elapsed_secs = difftime(sec,(time_t)0);
841 /* This code copied from display_signed_time; keep it in case anyone
842 is looking at captures from before 1970 (???).
843 If the fractional part of the time stamp is negative,
844 print its absolute value and, if the seconds part isn't
845 (the seconds part should be zero in that case), stick
846 a "-" in front of the entire time stamp. */
849 if (elapsed_secs >= 0) {
860 case TO_STR_TIME_RES_T_SECS:
861 g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
864 case TO_STR_TIME_RES_T_DSECS:
865 g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
868 case TO_STR_TIME_RES_T_CSECS:
869 g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
872 case TO_STR_TIME_RES_T_MSECS:
873 g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
876 case TO_STR_TIME_RES_T_USECS:
877 g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
880 case TO_STR_TIME_RES_T_NSECS:
881 g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
887 * Display a relative time as days/hours/minutes/seconds.
890 rel_time_to_str(wmem_allocator_t *scope, const nstime_t *rel_time)
896 /* If the nanoseconds part of the time stamp is negative,
897 print its absolute value and, if the seconds part isn't
898 (the seconds part should be zero in that case), stick
899 a "-" in front of the entire time stamp. */
900 time_val = (gint) rel_time->secs;
901 nsec = rel_time->nsecs;
902 if (time_val == 0 && nsec == 0) {
903 return wmem_strdup(scope, "0.000000000 seconds");
906 buf = wmem_strbuf_sized_new(scope, 1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
910 wmem_strbuf_append_c(buf, '-');
913 * We assume here that "rel_time->secs" is negative
914 * or zero; if it's not, the time stamp is bogus,
915 * with a positive seconds and negative microseconds.
917 time_val = (gint) -rel_time->secs;
920 time_secs_to_str_buf(time_val, nsec, TRUE, buf);
922 return wmem_strbuf_finalize(buf);
925 #define REL_TIME_SECS_LEN (1+10+1+9+1)
928 * Display a relative time as seconds.
931 rel_time_to_secs_str(wmem_allocator_t *scope, const nstime_t *rel_time)
935 buf=(gchar *)wmem_alloc(scope, REL_TIME_SECS_LEN);
937 display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
938 rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
943 * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
944 * with the length in bits of no_of_bits based on value.
949 decode_bits_in_field(const guint bit_offset, const gint no_of_bits, const guint64 value)
951 guint64 mask = 0,tmp;
957 mask = mask << (no_of_bits-1);
959 /* Prepare the string, 256 pos for the bits and zero termination, + 64 for the spaces */
960 str=(char *)wmem_alloc0(wmem_packet_scope(), 256+64);
961 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
970 /* read the bits for the int */
971 for(i=0;i<no_of_bits;i++){
1004 This function is very fast and this function is called a lot.
1005 XXX update the address_to_str stuff to use this function.
1008 ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
1010 register gchar const *p;
1011 register gchar *b=buf;
1013 if (buf_len < MAX_IP_STR_LEN) {
1014 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
1018 p=fast_strings[*ad++];
1025 p=fast_strings[*ad++];
1032 p=fast_strings[*ad++];
1039 p=fast_strings[*ad];
1048 guid_to_str(wmem_allocator_t *scope, const e_guid_t *guid)
1052 buf=(gchar *)wmem_alloc(scope, GUID_STR_LEN);
1053 return guid_to_str_buf(guid, buf, GUID_STR_LEN);
1057 guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len)
1059 char *tempptr = buf;
1061 if (buf_len < GUID_STR_LEN) {
1062 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
1067 tempptr = dword_to_hex(tempptr, guid->data1); /* 8 bytes */
1068 *tempptr++ = '-'; /* 1 byte */
1069 tempptr = word_to_hex(tempptr, guid->data2); /* 4 bytes */
1070 *tempptr++ = '-'; /* 1 byte */
1071 tempptr = word_to_hex(tempptr, guid->data3); /* 4 bytes */
1072 *tempptr++ = '-'; /* 1 byte */
1073 tempptr = bytes_to_hexstr(tempptr, &guid->data4[0], 2); /* 4 bytes */
1074 *tempptr++ = '-'; /* 1 byte */
1075 tempptr = bytes_to_hexstr(tempptr, &guid->data4[2], 6); /* 12 bytes */
1082 eui64_to_str(wmem_allocator_t *scope, const guint64 ad) {
1086 p_eui64=(guint8 *)wmem_alloc(NULL, 8);
1087 buf=(gchar *)wmem_alloc(scope, EUI64_STR_LEN);
1089 /* Copy and convert the address to network byte order. */
1090 *(guint64 *)(void *)(p_eui64) = pntoh64(&(ad));
1092 tmp = bytes_to_hexstr_punct(buf, p_eui64, 8, ':');
1093 *tmp = '\0'; /* NULL terminate */
1094 wmem_free(NULL, p_eui64);
1099 port_type_to_str (port_type type)
1102 case PT_NONE: return "NONE";
1103 case PT_SCTP: return "SCTP";
1104 case PT_TCP: return "TCP";
1105 case PT_UDP: return "UDP";
1106 case PT_DCCP: return "DCCP";
1107 case PT_IPX: return "IPX";
1108 case PT_NCP: return "NCP";
1109 case PT_EXCHG: return "FC EXCHG";
1110 case PT_DDP: return "DDP";
1111 case PT_SBCCS: return "FICON SBCCS";
1112 case PT_IDP: return "IDP";
1113 case PT_TIPC: return "TIPC";
1114 case PT_USB: return "USB";
1115 case PT_I2C: return "I2C";
1116 case PT_IBQP: return "IBQP";
1117 case PT_BLUETOOTH: return "BLUETOOTH";
1118 case PT_TDMOP: return "TDMOP";
1119 default: return "[Unknown]";
1124 oct_to_str_back(char *ptr, guint32 value)
1127 *(--ptr) = '0' + (value & 0x7);
1136 oct64_to_str_back(char *ptr, guint64 value)
1139 *(--ptr) = '0' + (value & 0x7);
1148 hex_to_str_back(char *ptr, int len, guint32 value)
1151 *(--ptr) = low_nibble_of_octet_to_hex(value);
1169 hex64_to_str_back(char *ptr, int len, guint64 value)
1172 *(--ptr) = low_nibble_of_octet_to_hex(value & 0xF);
1190 uint_to_str_back(char *ptr, guint32 value)
1198 while (value >= 10) {
1199 p = fast_strings[100 + (value % 100)];
1208 *(--ptr) = (value) | '0';
1214 uint64_to_str_back(char *ptr, guint64 value)
1222 while (value >= 10) {
1223 p = fast_strings[100 + (value % 100)];
1231 /* value will be 0..9, so using '& 0xF' is safe, and faster than '% 10' */
1233 *(--ptr) = (value & 0xF) | '0';
1239 uint_to_str_back_len(char *ptr, guint32 value, int len)
1243 new_ptr = uint_to_str_back(ptr, value);
1245 /* substract from len number of generated characters */
1246 len -= (int)(ptr - new_ptr);
1248 /* pad remaining with '0' */
1259 uint64_to_str_back_len(char *ptr, guint64 value, int len)
1263 new_ptr = uint64_to_str_back(ptr, value);
1265 /* substract from len number of generated characters */
1266 len -= (int)(ptr - new_ptr);
1268 /* pad remaining with '0' */
1279 int_to_str_back(char *ptr, gint32 value)
1282 ptr = uint_to_str_back(ptr, -value);
1285 ptr = uint_to_str_back(ptr, value);
1291 int64_to_str_back(char *ptr, gint64 value)
1294 ptr = uint64_to_str_back(ptr, -value);
1297 ptr = uint64_to_str_back(ptr, value);
1303 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1308 * indent-tabs-mode: t
1311 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1312 * :indentSize=8:tabSize=8:noTabs=false: