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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 * If a user _does_ pass in a too-small buffer, this is probably
40 * going to be too long to fit. However, even a partial string
41 * starting with "[Buf" should provide enough of a clue to be
44 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
47 byte_to_hex(char *out, guint32 dword) {
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 *out++ = hex_digits[(dword >> 4) & 0xF];
59 *out++ = hex_digits[dword & 0xF];
64 word_to_hex(char *out, guint16 word) {
65 out = byte_to_hex(out, word >> 8);
66 out = byte_to_hex(out, word);
71 word_to_hex_npad(char *out, guint16 word) {
72 static const gchar hex_digits[16] =
73 { '0', '1', '2', '3', '4', '5', '6', '7',
74 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
77 *out++ = hex_digits[(word >> 12) & 0xF];
79 *out++ = hex_digits[(word >> 8) & 0xF];
81 *out++ = hex_digits[(word >> 4) & 0xF];
82 *out++ = hex_digits[word & 0xF];
87 dword_to_hex(char *out, guint32 dword) {
88 out = byte_to_hex(out, dword >> 24);
89 out = byte_to_hex(out, dword >> 16);
90 out = byte_to_hex(out, dword >> 8);
91 out = byte_to_hex(out, dword);
96 dword_to_hex_punct(char *out, guint32 dword, char punct) {
97 out = byte_to_hex(out, dword >> 24);
99 out = byte_to_hex(out, dword >> 16);
101 out = byte_to_hex(out, dword >> 8);
103 out = byte_to_hex(out, dword);
108 * This does *not* null-terminate the string. It returns a pointer
109 * to the position in the string following the last character it
110 * puts there, so that the caller can either put the null terminator
111 * in or can append more stuff to the buffer.
113 * There needs to be at least len * 2 bytes left in the buffer.
116 bytes_to_hexstr(char *out, const guint8 *ad, guint32 len) {
120 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
122 for (i = 0; i < len; i++)
123 out = byte_to_hex(out, ad[i]);
128 * This does *not* null-terminate the string. It returns a pointer
129 * to the position in the string following the last character it
130 * puts there, so that the caller can either put the null terminator
131 * in or can append more stuff to the buffer.
133 * There needs to be at least len * 3 - 1 bytes left in the buffer.
136 bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct) {
140 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
142 out = byte_to_hex(out, ad[0]);
143 for (i = 1; i < len; i++) {
145 out = byte_to_hex(out, ad[i]);
150 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
151 * digits at at a time, with a specified punctuation character between
154 * If punct is '\0', no punctuation is applied (and thus
155 * the resulting string is (len-1) bytes shorter)
158 bytestring_to_str(const guint8 *ad, const guint32 len, const char punct) {
163 REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
165 /* XXX, Old code was using int as iterator... Why len is guint32 anyway?! (darkjames) */
166 if ( ((int) len) < 0)
177 buf=ep_alloc(buflen);
180 bytes_to_hexstr_punct(buf, ad, len, punct);
182 bytes_to_hexstr(buf, ad, len);
184 buf[buflen-1] = '\0';
188 /* Max string length for displaying byte string. */
189 #define MAX_BYTE_STR_LEN 48
192 bytes_to_str(const guint8 *bd, int bd_len) {
198 REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
200 cur=ep_alloc(MAX_BYTE_STR_LEN+3+1);
201 if (bd_len <= 0) { cur[0] = '\0'; return cur; }
203 if (bd_len > MAX_BYTE_STR_LEN/2) { /* bd_len > 24 */
205 bd_len = MAX_BYTE_STR_LEN/2;
208 cur_ptr = bytes_to_hexstr(cur, bd, bd_len); /* max MAX_BYTE_STR_LEN bytes */
211 cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
213 *cur_ptr = '\0'; /* 1 byte */
217 /* Turn an array of bytes into a string showing the bytes in hex with
218 * punct as a bytes separator.
221 bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
227 return bytes_to_str(bd, bd_len);
229 cur=ep_alloc(MAX_BYTE_STR_LEN+3+1);
230 if (bd_len <= 0) { cur[0] = '\0'; return cur; }
232 if (bd_len > MAX_BYTE_STR_LEN/3) { /* bd_len > 16 */
234 bd_len = MAX_BYTE_STR_LEN/3;
237 cur_ptr = bytes_to_hexstr_punct(cur, bd, bd_len, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
240 *cur_ptr++ = punct; /* 1 byte */
241 cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
249 guint32_to_str_buf_len(const guint32 u) {
250 if (u >= 1000000000)return 10;
251 if (u >= 100000000) return 9;
252 if (u >= 10000000) return 8;
253 if (u >= 1000000) return 7;
254 if (u >= 100000) return 6;
255 if (u >= 10000) return 5;
256 if (u >= 1000) return 4;
257 if (u >= 100) return 3;
258 if (u >= 10) return 2;
263 static const char * const fast_strings[] = {
264 "0", "1", "2", "3", "4", "5", "6", "7",
265 "8", "9", "10", "11", "12", "13", "14", "15",
266 "16", "17", "18", "19", "20", "21", "22", "23",
267 "24", "25", "26", "27", "28", "29", "30", "31",
268 "32", "33", "34", "35", "36", "37", "38", "39",
269 "40", "41", "42", "43", "44", "45", "46", "47",
270 "48", "49", "50", "51", "52", "53", "54", "55",
271 "56", "57", "58", "59", "60", "61", "62", "63",
272 "64", "65", "66", "67", "68", "69", "70", "71",
273 "72", "73", "74", "75", "76", "77", "78", "79",
274 "80", "81", "82", "83", "84", "85", "86", "87",
275 "88", "89", "90", "91", "92", "93", "94", "95",
276 "96", "97", "98", "99", "100", "101", "102", "103",
277 "104", "105", "106", "107", "108", "109", "110", "111",
278 "112", "113", "114", "115", "116", "117", "118", "119",
279 "120", "121", "122", "123", "124", "125", "126", "127",
280 "128", "129", "130", "131", "132", "133", "134", "135",
281 "136", "137", "138", "139", "140", "141", "142", "143",
282 "144", "145", "146", "147", "148", "149", "150", "151",
283 "152", "153", "154", "155", "156", "157", "158", "159",
284 "160", "161", "162", "163", "164", "165", "166", "167",
285 "168", "169", "170", "171", "172", "173", "174", "175",
286 "176", "177", "178", "179", "180", "181", "182", "183",
287 "184", "185", "186", "187", "188", "189", "190", "191",
288 "192", "193", "194", "195", "196", "197", "198", "199",
289 "200", "201", "202", "203", "204", "205", "206", "207",
290 "208", "209", "210", "211", "212", "213", "214", "215",
291 "216", "217", "218", "219", "220", "221", "222", "223",
292 "224", "225", "226", "227", "228", "229", "230", "231",
293 "232", "233", "234", "235", "236", "237", "238", "239",
294 "240", "241", "242", "243", "244", "245", "246", "247",
295 "248", "249", "250", "251", "252", "253", "254", "255"
299 guint32_to_str_buf(guint32 u, gchar *buf, int buf_len) {
300 int str_len = guint32_to_str_buf_len(u)+1;
302 gchar *bp = &buf[str_len];
305 if (buf_len < str_len) {
306 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
313 p = fast_strings[100 + (u % 100)];
321 if (bp != buf) /* ugly, fixme! */
322 *--bp = (u % 10) | '0';
326 guint32_to_str(const guint32 u) {
327 int str_len = 16; /* guint32_to_str_buf_len(u)+1; */
329 gchar *bp = ep_alloc(str_len);
330 guint32_to_str_buf(u, bp, str_len);
335 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
336 #define COMMA(do_it) ((do_it) ? ", " : "")
339 * Maximum length of a string showing days/hours/minutes/seconds.
340 * (Does not include the terminating '\0'.)
341 * Includes space for a '-' sign for any negative components.
342 * -12345 days, 12 hours, 12 minutes, 12.123 seconds
344 #define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
347 * Convert a value in seconds and fractions of a second to a string,
348 * giving time in days, hours, minutes, and seconds, and put the result
350 * "is_nsecs" says that "frac" is microseconds if true and milliseconds
352 * If time is negative, add a '-' to all non-null components.
355 time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
358 int hours, mins, secs;
359 const gchar *msign = "";
360 gboolean do_comma = FALSE;
362 if(time_val == G_MININT32) { /* That Which Shall Not Be Negated */
363 ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
368 time_val = -time_val;
372 secs = time_val % 60;
374 mins = time_val % 60;
376 hours = time_val % 24;
380 ep_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
385 ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
390 ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
394 if (secs != 0 || frac != 0) {
397 ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
399 ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
401 ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
406 time_secs_to_str(const gint32 time_val)
410 buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
413 ep_strbuf_append(buf, "0 seconds");
417 time_secs_to_str_buf(time_val, 0, FALSE, buf);
422 time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
425 int hours, mins, secs;
426 gboolean do_comma = FALSE;
428 secs = time_val % 60;
430 mins = time_val % 60;
432 hours = time_val % 24;
436 ep_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
440 ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
444 ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
447 if (secs != 0 || frac != 0) {
450 ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
452 ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
454 ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
459 time_secs_to_str_unsigned(const guint32 time_val)
463 buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
466 ep_strbuf_append(buf, "0 seconds");
470 time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
476 time_msecs_to_str(gint32 time_val)
481 buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
484 ep_strbuf_append(buf, "0 seconds");
489 /* oops we got passed a negative time */
491 msecs = time_val % 1000;
495 msecs = time_val % 1000;
499 time_secs_to_str_buf(time_val, msecs, FALSE, buf);
503 static const char *mon_names[12] = {
518 static const gchar *get_zonename(struct tm *tmp) {
519 #if defined(HAVE_TM_ZONE)
522 if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
525 # if defined(HAVE_TZNAME)
526 return tzname[tmp->tm_isdst];
528 # elif defined(_WIN32)
529 /* Windows C Runtime: */
530 /* _tzname is encoded using the "system default ansi code page" */
531 /* ("which is not necessarily the same as the C library locale"). */
532 /* So: _tzname must be converted to UTF8 before use. */
533 /* Alternative: use Windows GetTimeZoneInformation() to get the */
534 /* timezone name in UTF16 and convert same to UTF8. */
535 /* XXX: the result is that the timezone name will be based upon the */
536 /* system code page (iow: the charset of the system). */
537 /* Since Wireshark is not internationalized, it would seem more */
538 /* correct to show the timezone name in English, no matter what */
539 /* the system code page, but I don't how to do that (or if it's */
540 /* really even possible). */
541 /* In any case converting to UTF8 presumably at least keeps GTK */
542 /* happy. (A bug was reported wherein Wireshark crashed in GDK */
543 /* on a "Japanese version of Windows XP" when trying to copy */
544 /* the date/time string (containing a copy of _tz_name) to the */
548 static char *ws_tzname[2] = {NULL, NULL};
550 /* The g_malloc'd value returned from g_locale_to_utf8() is */
551 /* cached for all further use so there's no need to ever */
552 /* g_free() that value. */
553 if (ws_tzname[tmp->tm_isdst] == NULL) {
554 ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
555 if (ws_tzname[tmp->tm_isdst] == NULL) {
556 ws_tzname[tmp->tm_isdst] = "???";
559 return ws_tzname[tmp->tm_isdst];
562 return tmp->tm_isdst ? "?DT" : "?ST";
569 abs_time_to_str(const nstime_t *abs_time, const absolute_time_display_e fmt,
572 struct tm *tmp = NULL;
573 const char *zonename = "???";
577 /* calling localtime() on MSVC 2005 with huge values causes it to crash */
578 /* XXX - find the exact value that still does work */
579 /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
580 if(abs_time->secs > 2000000000) {
586 case ABSOLUTE_TIME_UTC:
587 case ABSOLUTE_TIME_DOY_UTC:
588 tmp = gmtime(&abs_time->secs);
592 case ABSOLUTE_TIME_LOCAL:
593 tmp = localtime(&abs_time->secs);
595 zonename = get_zonename(tmp);
602 case ABSOLUTE_TIME_DOY_UTC:
604 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld %s",
610 (long)abs_time->nsecs,
613 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld",
619 (long)abs_time->nsecs);
623 case ABSOLUTE_TIME_UTC:
624 case ABSOLUTE_TIME_LOCAL:
626 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld %s",
627 mon_names[tmp->tm_mon],
633 (long)abs_time->nsecs,
636 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld",
637 mon_names[tmp->tm_mon],
643 (long)abs_time->nsecs);
648 buf = ep_strdup("Not representable");
653 abs_time_secs_to_str(const time_t abs_time, const absolute_time_display_e fmt,
656 struct tm *tmp = NULL;
657 const char *zonename = "???";
661 /* calling localtime() on MSVC 2005 with huge values causes it to crash */
662 /* XXX - find the exact value that still does work */
663 /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
664 if(abs_time > 2000000000) {
670 case ABSOLUTE_TIME_UTC:
671 case ABSOLUTE_TIME_DOY_UTC:
672 tmp = gmtime(&abs_time);
676 case ABSOLUTE_TIME_LOCAL:
677 tmp = localtime(&abs_time);
679 zonename = get_zonename(tmp);
686 case ABSOLUTE_TIME_DOY_UTC:
688 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d %s",
696 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d",
705 case ABSOLUTE_TIME_UTC:
706 case ABSOLUTE_TIME_LOCAL:
708 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d %s",
709 mon_names[tmp->tm_mon],
717 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d",
718 mon_names[tmp->tm_mon],
728 buf = ep_strdup("Not representable");
733 display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
734 const to_str_time_res_t units)
736 /* If the fractional part of the time stamp is negative,
737 print its absolute value and, if the seconds part isn't
738 (the seconds part should be zero in that case), stick
739 a "-" in front of the entire time stamp. */
753 case TO_STR_TIME_RES_T_SECS:
754 g_snprintf(buf, buflen, "%d", sec);
757 case TO_STR_TIME_RES_T_DSECS:
758 g_snprintf(buf, buflen, "%d.%01d", sec, frac);
761 case TO_STR_TIME_RES_T_CSECS:
762 g_snprintf(buf, buflen, "%d.%02d", sec, frac);
765 case TO_STR_TIME_RES_T_MSECS:
766 g_snprintf(buf, buflen, "%d.%03d", sec, frac);
769 case TO_STR_TIME_RES_T_USECS:
770 g_snprintf(buf, buflen, "%d.%06d", sec, frac);
773 case TO_STR_TIME_RES_T_NSECS:
774 g_snprintf(buf, buflen, "%d.%09d", sec, frac);
781 display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
782 const to_str_time_res_t units)
786 elapsed_secs = difftime(sec,(time_t)0);
788 /* This code copied from display_signed_time; keep it in case anyone
789 is looking at captures from before 1970 (???).
790 If the fractional part of the time stamp is negative,
791 print its absolute value and, if the seconds part isn't
792 (the seconds part should be zero in that case), stick
793 a "-" in front of the entire time stamp. */
796 if (elapsed_secs >= 0) {
807 case TO_STR_TIME_RES_T_SECS:
808 g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
811 case TO_STR_TIME_RES_T_DSECS:
812 g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
815 case TO_STR_TIME_RES_T_CSECS:
816 g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
819 case TO_STR_TIME_RES_T_MSECS:
820 g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
823 case TO_STR_TIME_RES_T_USECS:
824 g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
827 case TO_STR_TIME_RES_T_NSECS:
828 g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
834 * Display a relative time as days/hours/minutes/seconds.
837 rel_time_to_str(const nstime_t *rel_time)
843 buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
845 /* If the nanoseconds part of the time stamp is negative,
846 print its absolute value and, if the seconds part isn't
847 (the seconds part should be zero in that case), stick
848 a "-" in front of the entire time stamp. */
849 time_val = (gint) rel_time->secs;
850 nsec = rel_time->nsecs;
851 if (time_val == 0 && nsec == 0) {
852 ep_strbuf_append(buf, "0.000000000 seconds");
857 ep_strbuf_append_c(buf, '-');
860 * We assume here that "rel_time->secs" is negative
861 * or zero; if it's not, the time stamp is bogus,
862 * with a positive seconds and negative microseconds.
864 time_val = (gint) -rel_time->secs;
867 time_secs_to_str_buf(time_val, nsec, TRUE, buf);
871 #define REL_TIME_SECS_LEN (1+10+1+9+1)
874 * Display a relative time as seconds.
877 rel_time_to_secs_str(const nstime_t *rel_time)
881 buf=ep_alloc(REL_TIME_SECS_LEN);
883 display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
884 rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
889 * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
890 * with the length in bits of no_of_bits based on value.
895 decode_bits_in_field(const gint bit_offset, const gint no_of_bits, const guint64 value)
897 guint64 mask = 0,tmp;
903 mask = mask << (no_of_bits-1);
905 /* prepare the string */
908 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
910 g_strlcat(str, " ", 256);
912 g_strlcat(str, ".", 256);
915 /* read the bits for the int */
916 for(i=0;i<no_of_bits;i++){
918 g_strlcat(str, " ", 256);
921 g_strlcat(str, " ", 256);
926 g_strlcat(str, "1", 256);
928 g_strlcat(str, "0", 256);
935 g_strlcat(str, " ", 256);
937 g_strlcat(str, ".", 256);
942 /* Generate, into "buf", a string showing the bits of a bitfield.
943 Return a pointer to the character after that string. */
944 /*XXX this needs a buf_len check */
946 other_decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
954 bit = 1 << (width - 1);
957 /* This bit is part of the field. Show its value. */
963 /* This bit is not part of the field. */
978 decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
982 p = other_decode_bitfield_value(buf, val, mask, width);
988 /* Generate a string describing a Boolean bitfield (a one-bit field that
989 says something is either true of false). */
991 decode_boolean_bitfield(const guint32 val, const guint32 mask, const int width,
992 const char *truedesc, const char *falsedesc)
997 buf=ep_alloc(1025); /* is this a bit overkill? */
998 p = decode_bitfield_value(buf, val, mask, width);
1000 strcpy(p, truedesc);
1002 strcpy(p, falsedesc);
1006 /* Generate a string describing a numeric bitfield (an N-bit field whose
1007 value is just a number). */
1009 decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width,
1016 buf=ep_alloc(1025); /* isnt this a bit overkill? */
1017 /* Compute the number of bits we have to shift the bitfield right
1018 to extract its value. */
1019 while ((mask & (1<<shift)) == 0)
1022 p = decode_bitfield_value(buf, val, mask, width);
1023 g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
1028 This function is very fast and this function is called a lot.
1029 XXX update the ep_address_to_str stuff to use this function.
1032 ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
1034 register gchar const *p;
1035 register gchar *b=buf;
1037 if (buf_len < MAX_IP_STR_LEN) {
1038 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
1042 p=fast_strings[*ad++];
1049 p=fast_strings[*ad++];
1056 p=fast_strings[*ad++];
1063 p=fast_strings[*ad];
1071 gchar* guid_to_str(const e_guid_t *guid) {
1074 buf=ep_alloc(GUID_STR_LEN);
1075 return guid_to_str_buf(guid, buf, GUID_STR_LEN);
1078 gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
1079 char *tempptr = buf;
1081 if (buf_len < GUID_STR_LEN) {
1082 g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
1087 tempptr = dword_to_hex(tempptr, guid->data1); /* 8 bytes */
1088 *tempptr++ = '-'; /* 1 byte */
1089 tempptr = word_to_hex(tempptr, guid->data2); /* 4 bytes */
1090 *tempptr++ = '-'; /* 1 byte */
1091 tempptr = word_to_hex(tempptr, guid->data3); /* 4 bytes */
1092 *tempptr++ = '-'; /* 1 byte */
1093 tempptr = bytes_to_hexstr(tempptr, &guid->data4[0], 2); /* 4 bytes */
1094 *tempptr++ = '-'; /* 1 byte */
1095 tempptr = bytes_to_hexstr(tempptr, &guid->data4[2], 6); /* 12 bytes */