2 * Routines for utilities to convert various other types to strings.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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 byte_to_hex(char *out, guint32 dword) {
47 /* At least one version of Apple's C compiler/linker is buggy, causing
48 a complaint from the linker about the "literal C string section"
49 not ending with '\0' if we initialize a 16-element "char" array with
50 a 16-character string, the fact that initializing such an array with
51 such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
52 '\0' byte in the string nonwithstanding. */
53 static const gchar hex_digits[16] =
54 { '0', '1', '2', '3', '4', '5', '6', '7',
55 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
57 *out++ = hex_digits[(dword >> 4) & 0xF];
58 *out++ = hex_digits[dword & 0xF];
63 word_to_hex(char *out, guint16 word) {
64 out = byte_to_hex(out, word >> 8);
65 out = byte_to_hex(out, word);
70 word_to_hex_npad(char *out, guint16 word) {
71 static const gchar hex_digits[16] =
72 { '0', '1', '2', '3', '4', '5', '6', '7',
73 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
76 *out++ = hex_digits[(word >> 12) & 0xF];
78 *out++ = hex_digits[(word >> 8) & 0xF];
80 *out++ = hex_digits[(word >> 4) & 0xF];
81 *out++ = hex_digits[word & 0xF];
86 dword_to_hex(char *out, guint32 dword) {
87 out = byte_to_hex(out, dword >> 24);
88 out = byte_to_hex(out, dword >> 16);
89 out = byte_to_hex(out, dword >> 8);
90 out = byte_to_hex(out, dword);
95 dword_to_hex_punct(char *out, guint32 dword, char punct) {
96 out = byte_to_hex(out, dword >> 24);
98 out = byte_to_hex(out, dword >> 16);
100 out = byte_to_hex(out, dword >> 8);
102 out = byte_to_hex(out, dword);
107 * This does *not* null-terminate the string. It returns a pointer
108 * to the position in the string following the last character it
109 * puts there, so that the caller can either put the null terminator
110 * in or can append more stuff to the buffer.
112 * There needs to be at least len * 2 bytes left in the buffer.
115 bytes_to_hexstr(char *out, const guint8 *ad, guint32 len) {
119 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
121 for (i = 0; i < len; i++)
122 out = byte_to_hex(out, ad[i]);
127 * This does *not* null-terminate the string. It returns a pointer
128 * to the position in the string following the last character it
129 * puts there, so that the caller can either put the null terminator
130 * in or can append more stuff to the buffer.
132 * There needs to be at least len * 3 - 1 bytes left in the buffer.
135 bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct) {
139 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
141 out = byte_to_hex(out, ad[0]);
142 for (i = 1; i < len; i++) {
144 out = byte_to_hex(out, ad[i]);
149 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
150 * digits at at a time, with a specified punctuation character between
153 * If punct is '\0', no punctuation is applied (and thus
154 * the resulting string is (len-1) bytes shorter)
157 bytestring_to_str(const guint8 *ad, const guint32 len, const char punct) {
162 REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
164 /* XXX, Old code was using int as iterator... Why len is guint32 anyway?! (darkjames) */
165 if ( ((int) len) < 0)
176 buf=(gchar *)ep_alloc(buflen);
179 bytes_to_hexstr_punct(buf, ad, len, punct);
181 bytes_to_hexstr(buf, ad, len);
183 buf[buflen-1] = '\0';
187 /* Max string length for displaying byte string. */
188 #define MAX_BYTE_STR_LEN 48
191 bytes_to_str(const guint8 *bd, int bd_len) {
197 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
199 cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
200 if (bd_len <= 0) { cur[0] = '\0'; return cur; }
202 if (bd_len > MAX_BYTE_STR_LEN/2) { /* bd_len > 24 */
204 bd_len = MAX_BYTE_STR_LEN/2;
207 cur_ptr = bytes_to_hexstr(cur, bd, bd_len); /* max MAX_BYTE_STR_LEN bytes */
210 cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
212 *cur_ptr = '\0'; /* 1 byte */
216 /* Turn an array of bytes into a string showing the bytes in hex with
217 * punct as a bytes separator.
220 bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
226 return bytes_to_str(bd, bd_len);
228 cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
229 if (bd_len <= 0) { cur[0] = '\0'; return cur; }
231 if (bd_len > MAX_BYTE_STR_LEN/3) { /* bd_len > 16 */
233 bd_len = MAX_BYTE_STR_LEN/3;
236 cur_ptr = bytes_to_hexstr_punct(cur, bd, bd_len, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
239 *cur_ptr++ = punct; /* 1 byte */
240 cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
248 guint32_to_str_buf_len(const guint32 u) {
249 if (u >= 1000000000)return 10;
250 if (u >= 100000000) return 9;
251 if (u >= 10000000) return 8;
252 if (u >= 1000000) return 7;
253 if (u >= 100000) return 6;
254 if (u >= 10000) return 5;
255 if (u >= 1000) return 4;
256 if (u >= 100) return 3;
257 if (u >= 10) return 2;
262 static const char const fast_strings[][4] = {
263 "0", "1", "2", "3", "4", "5", "6", "7",
264 "8", "9", "10", "11", "12", "13", "14", "15",
265 "16", "17", "18", "19", "20", "21", "22", "23",
266 "24", "25", "26", "27", "28", "29", "30", "31",
267 "32", "33", "34", "35", "36", "37", "38", "39",
268 "40", "41", "42", "43", "44", "45", "46", "47",
269 "48", "49", "50", "51", "52", "53", "54", "55",
270 "56", "57", "58", "59", "60", "61", "62", "63",
271 "64", "65", "66", "67", "68", "69", "70", "71",
272 "72", "73", "74", "75", "76", "77", "78", "79",
273 "80", "81", "82", "83", "84", "85", "86", "87",
274 "88", "89", "90", "91", "92", "93", "94", "95",
275 "96", "97", "98", "99", "100", "101", "102", "103",
276 "104", "105", "106", "107", "108", "109", "110", "111",
277 "112", "113", "114", "115", "116", "117", "118", "119",
278 "120", "121", "122", "123", "124", "125", "126", "127",
279 "128", "129", "130", "131", "132", "133", "134", "135",
280 "136", "137", "138", "139", "140", "141", "142", "143",
281 "144", "145", "146", "147", "148", "149", "150", "151",
282 "152", "153", "154", "155", "156", "157", "158", "159",
283 "160", "161", "162", "163", "164", "165", "166", "167",
284 "168", "169", "170", "171", "172", "173", "174", "175",
285 "176", "177", "178", "179", "180", "181", "182", "183",
286 "184", "185", "186", "187", "188", "189", "190", "191",
287 "192", "193", "194", "195", "196", "197", "198", "199",
288 "200", "201", "202", "203", "204", "205", "206", "207",
289 "208", "209", "210", "211", "212", "213", "214", "215",
290 "216", "217", "218", "219", "220", "221", "222", "223",
291 "224", "225", "226", "227", "228", "229", "230", "231",
292 "232", "233", "234", "235", "236", "237", "238", "239",
293 "240", "241", "242", "243", "244", "245", "246", "247",
294 "248", "249", "250", "251", "252", "253", "254", "255"
298 guint32_to_str_buf(guint32 u, gchar *buf, int buf_len) {
299 int str_len = guint32_to_str_buf_len(u)+1;
301 gchar *bp = &buf[str_len];
304 if (buf_len < str_len) {
305 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
312 p = fast_strings[100 + (u % 100)];
320 if (bp != buf) /* ugly, fixme! */
321 *--bp = (u % 10) | '0';
325 guint32_to_str(const guint32 u) {
326 int str_len = 16; /* guint32_to_str_buf_len(u)+1; */
328 gchar *bp = (gchar *)ep_alloc(str_len);
329 guint32_to_str_buf(u, bp, str_len);
334 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
335 #define COMMA(do_it) ((do_it) ? ", " : "")
338 * Maximum length of a string showing days/hours/minutes/seconds.
339 * (Does not include the terminating '\0'.)
340 * Includes space for a '-' sign for any negative components.
341 * -12345 days, 12 hours, 12 minutes, 12.123 seconds
343 #define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
346 * Convert a value in seconds and fractions of a second to a string,
347 * giving time in days, hours, minutes, and seconds, and put the result
349 * "is_nsecs" says that "frac" is microseconds if true and milliseconds
351 * If time is negative, add a '-' to all non-null components.
354 time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
357 int hours, mins, secs;
358 const gchar *msign = "";
359 gboolean do_comma = FALSE;
361 if(time_val == G_MININT32) { /* That Which Shall Not Be Negated */
362 ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
367 time_val = -time_val;
371 secs = time_val % 60;
373 mins = time_val % 60;
375 hours = time_val % 24;
379 ep_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
384 ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
389 ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
393 if (secs != 0 || frac != 0) {
396 ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
398 ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
400 ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
405 time_secs_to_str(const gint32 time_val)
409 buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
412 ep_strbuf_append(buf, "0 seconds");
416 time_secs_to_str_buf(time_val, 0, FALSE, buf);
421 time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
424 int hours, mins, secs;
425 gboolean do_comma = FALSE;
427 secs = time_val % 60;
429 mins = time_val % 60;
431 hours = time_val % 24;
435 ep_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
439 ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
443 ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
446 if (secs != 0 || frac != 0) {
449 ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
451 ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
453 ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
458 time_secs_to_str_unsigned(const guint32 time_val)
462 buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
465 ep_strbuf_append(buf, "0 seconds");
469 time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
475 time_msecs_to_str(gint32 time_val)
480 buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
483 ep_strbuf_append(buf, "0 seconds");
488 /* oops we got passed a negative time */
490 msecs = time_val % 1000;
494 msecs = time_val % 1000;
498 time_secs_to_str_buf(time_val, msecs, FALSE, buf);
502 static const char mon_names[12][4] = {
517 static const gchar *get_zonename(struct tm *tmp) {
518 #if defined(HAVE_TM_ZONE)
521 if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
524 # if defined(HAVE_TZNAME)
525 return tzname[tmp->tm_isdst];
527 # elif defined(_WIN32)
528 /* Windows C Runtime: */
529 /* _tzname is encoded using the "system default ansi code page" */
530 /* ("which is not necessarily the same as the C library locale"). */
531 /* So: _tzname must be converted to UTF8 before use. */
532 /* Alternative: use Windows GetTimeZoneInformation() to get the */
533 /* timezone name in UTF16 and convert same to UTF8. */
534 /* XXX: the result is that the timezone name will be based upon the */
535 /* system code page (iow: the charset of the system). */
536 /* Since Wireshark is not internationalized, it would seem more */
537 /* correct to show the timezone name in English, no matter what */
538 /* the system code page, but I don't how to do that (or if it's */
539 /* really even possible). */
540 /* In any case converting to UTF8 presumably at least keeps GTK */
541 /* happy. (A bug was reported wherein Wireshark crashed in GDK */
542 /* on a "Japanese version of Windows XP" when trying to copy */
543 /* the date/time string (containing a copy of _tz_name) to the */
547 static char *ws_tzname[2] = {NULL, NULL};
549 /* The g_malloc'd value returned from g_locale_to_utf8() is */
550 /* cached for all further use so there's no need to ever */
551 /* g_free() that value. */
552 if (ws_tzname[tmp->tm_isdst] == NULL) {
553 ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
554 if (ws_tzname[tmp->tm_isdst] == NULL) {
555 ws_tzname[tmp->tm_isdst] = "???";
558 return ws_tzname[tmp->tm_isdst];
561 return tmp->tm_isdst ? "?DT" : "?ST";
568 abs_time_to_str(const nstime_t *abs_time, const absolute_time_display_e fmt,
571 struct tm *tmp = NULL;
572 const char *zonename = "???";
575 #if (defined _WIN32) && (_MSC_VER < 1500)
576 /* calling localtime() on MSVC 2005 with huge values causes it to crash */
577 /* XXX - find the exact value that still does work */
578 /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
579 if(abs_time->secs > 2000000000) {
585 case ABSOLUTE_TIME_UTC:
586 case ABSOLUTE_TIME_DOY_UTC:
587 tmp = gmtime(&abs_time->secs);
591 case ABSOLUTE_TIME_LOCAL:
592 tmp = localtime(&abs_time->secs);
594 zonename = get_zonename(tmp);
601 case ABSOLUTE_TIME_DOY_UTC:
603 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld %s",
609 (long)abs_time->nsecs,
612 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld",
618 (long)abs_time->nsecs);
622 case ABSOLUTE_TIME_UTC:
623 case ABSOLUTE_TIME_LOCAL:
625 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld %s",
626 mon_names[tmp->tm_mon],
632 (long)abs_time->nsecs,
635 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld",
636 mon_names[tmp->tm_mon],
642 (long)abs_time->nsecs);
647 buf = ep_strdup("Not representable");
652 abs_time_secs_to_str(const time_t abs_time, const absolute_time_display_e fmt,
655 struct tm *tmp = NULL;
656 const char *zonename = "???";
659 #if (defined _WIN32) && (_MSC_VER < 1500)
660 /* calling localtime() on MSVC 2005 with huge values causes it to crash */
661 /* XXX - find the exact value that still does work */
662 /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
663 if(abs_time > 2000000000) {
669 case ABSOLUTE_TIME_UTC:
670 case ABSOLUTE_TIME_DOY_UTC:
671 tmp = gmtime(&abs_time);
675 case ABSOLUTE_TIME_LOCAL:
676 tmp = localtime(&abs_time);
678 zonename = get_zonename(tmp);
685 case ABSOLUTE_TIME_DOY_UTC:
687 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d %s",
695 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d",
704 case ABSOLUTE_TIME_UTC:
705 case ABSOLUTE_TIME_LOCAL:
707 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d %s",
708 mon_names[tmp->tm_mon],
716 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d",
717 mon_names[tmp->tm_mon],
727 buf = ep_strdup("Not representable");
732 display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
733 const to_str_time_res_t units)
735 /* If the fractional part of the time stamp is negative,
736 print its absolute value and, if the seconds part isn't
737 (the seconds part should be zero in that case), stick
738 a "-" in front of the entire time stamp. */
752 case TO_STR_TIME_RES_T_SECS:
753 g_snprintf(buf, buflen, "%d", sec);
756 case TO_STR_TIME_RES_T_DSECS:
757 g_snprintf(buf, buflen, "%d.%01d", sec, frac);
760 case TO_STR_TIME_RES_T_CSECS:
761 g_snprintf(buf, buflen, "%d.%02d", sec, frac);
764 case TO_STR_TIME_RES_T_MSECS:
765 g_snprintf(buf, buflen, "%d.%03d", sec, frac);
768 case TO_STR_TIME_RES_T_USECS:
769 g_snprintf(buf, buflen, "%d.%06d", sec, frac);
772 case TO_STR_TIME_RES_T_NSECS:
773 g_snprintf(buf, buflen, "%d.%09d", sec, frac);
780 display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
781 const to_str_time_res_t units)
785 elapsed_secs = difftime(sec,(time_t)0);
787 /* This code copied from display_signed_time; keep it in case anyone
788 is looking at captures from before 1970 (???).
789 If the fractional part of the time stamp is negative,
790 print its absolute value and, if the seconds part isn't
791 (the seconds part should be zero in that case), stick
792 a "-" in front of the entire time stamp. */
795 if (elapsed_secs >= 0) {
806 case TO_STR_TIME_RES_T_SECS:
807 g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
810 case TO_STR_TIME_RES_T_DSECS:
811 g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
814 case TO_STR_TIME_RES_T_CSECS:
815 g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
818 case TO_STR_TIME_RES_T_MSECS:
819 g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
822 case TO_STR_TIME_RES_T_USECS:
823 g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
826 case TO_STR_TIME_RES_T_NSECS:
827 g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
833 * Display a relative time as days/hours/minutes/seconds.
836 rel_time_to_str(const nstime_t *rel_time)
842 buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
844 /* If the nanoseconds part of the time stamp is negative,
845 print its absolute value and, if the seconds part isn't
846 (the seconds part should be zero in that case), stick
847 a "-" in front of the entire time stamp. */
848 time_val = (gint) rel_time->secs;
849 nsec = rel_time->nsecs;
850 if (time_val == 0 && nsec == 0) {
851 ep_strbuf_append(buf, "0.000000000 seconds");
856 ep_strbuf_append_c(buf, '-');
859 * We assume here that "rel_time->secs" is negative
860 * or zero; if it's not, the time stamp is bogus,
861 * with a positive seconds and negative microseconds.
863 time_val = (gint) -rel_time->secs;
866 time_secs_to_str_buf(time_val, nsec, TRUE, buf);
870 #define REL_TIME_SECS_LEN (1+10+1+9+1)
873 * Display a relative time as seconds.
876 rel_time_to_secs_str(const nstime_t *rel_time)
880 buf=(gchar *)ep_alloc(REL_TIME_SECS_LEN);
882 display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
883 rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
888 * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
889 * with the length in bits of no_of_bits based on value.
894 decode_bits_in_field(const guint bit_offset, const gint no_of_bits, const guint64 value)
896 guint64 mask = 0,tmp;
902 mask = mask << (no_of_bits-1);
904 /* Prepare the string, 256 pos for the bits and zero termination, + 64 for the spaces */
905 str=(char *)ep_alloc0(256+64);
906 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
915 /* read the bits for the int */
916 for(i=0;i<no_of_bits;i++){
948 /* Generate, into "buf", a string showing the bits of a bitfield.
949 Return a pointer to the character after that string. */
950 /*XXX this needs a buf_len check */
952 other_decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
960 bit = 1 << (width - 1);
963 /* This bit is part of the field. Show its value. */
969 /* This bit is not part of the field. */
984 decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
988 p = other_decode_bitfield_value(buf, val, mask, width);
994 /* Generate a string describing a Boolean bitfield (a one-bit field that
995 says something is either true or false). */
997 decode_boolean_bitfield(const guint32 val, const guint32 mask, const int width,
998 const char *truedesc, const char *falsedesc)
1003 buf=(char *)ep_alloc(1025); /* is this a bit overkill? */
1004 p = decode_bitfield_value(buf, val, mask, width);
1006 strcpy(p, truedesc);
1008 strcpy(p, falsedesc);
1012 /* Generate a string describing a numeric bitfield (an N-bit field whose
1013 value is just a number). */
1015 decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width,
1022 buf=(char *)ep_alloc(1025); /* isnt this a bit overkill? */
1023 /* Compute the number of bits we have to shift the bitfield right
1024 to extract its value. */
1025 while ((mask & (1<<shift)) == 0)
1028 p = decode_bitfield_value(buf, val, mask, width);
1029 g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
1034 This function is very fast and this function is called a lot.
1035 XXX update the ep_address_to_str stuff to use this function.
1038 ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
1040 register gchar const *p;
1041 register gchar *b=buf;
1043 if (buf_len < MAX_IP_STR_LEN) {
1044 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
1048 p=fast_strings[*ad++];
1055 p=fast_strings[*ad++];
1062 p=fast_strings[*ad++];
1069 p=fast_strings[*ad];
1077 gchar* guid_to_str(const e_guid_t *guid) {
1080 buf=(gchar *)ep_alloc(GUID_STR_LEN);
1081 return guid_to_str_buf(guid, buf, GUID_STR_LEN);
1084 gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
1085 char *tempptr = buf;
1087 if (buf_len < GUID_STR_LEN) {
1088 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
1093 tempptr = dword_to_hex(tempptr, guid->data1); /* 8 bytes */
1094 *tempptr++ = '-'; /* 1 byte */
1095 tempptr = word_to_hex(tempptr, guid->data2); /* 4 bytes */
1096 *tempptr++ = '-'; /* 1 byte */
1097 tempptr = word_to_hex(tempptr, guid->data3); /* 4 bytes */
1098 *tempptr++ = '-'; /* 1 byte */
1099 tempptr = bytes_to_hexstr(tempptr, &guid->data4[0], 2); /* 4 bytes */
1100 *tempptr++ = '-'; /* 1 byte */
1101 tempptr = bytes_to_hexstr(tempptr, &guid->data4[2], 6); /* 12 bytes */