Fix CID 1111806: it's not safe to check if "tag < sizeof(tag_to_type)" before
[metze/wireshark/wip.git] / epan / to_str.c
1 /* to_str.c
2  * Routines for utilities to convert various other types to strings.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <time.h>
30 #include <glib.h>
31
32 #include "emem.h"
33 #include "proto.h"
34 #include "to_str.h"
35 #include "strutil.h"
36
37 /*
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
41  * useful.
42  */
43 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
44
45 static inline char
46 low_nibble_of_octet_to_hex(guint8 oct)
47 {
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' };
57
58   return hex_digits[oct & 0xF];
59 }
60
61 static inline char *
62 byte_to_hex(char *out, guint32 dword) {
63   *out++ = low_nibble_of_octet_to_hex(dword >> 4);
64   *out++ = low_nibble_of_octet_to_hex(dword);
65   return out;
66 }
67
68 char *
69 word_to_hex(char *out, guint16 word) {
70   out = byte_to_hex(out, word >> 8);
71   out = byte_to_hex(out, word);
72   return out;
73 }
74
75 char *
76 word_to_hex_npad(char *out, guint16 word) {
77         if (word >= 0x1000)
78                 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 12));
79         if (word >= 0x0100)
80                 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 8));
81         if (word >= 0x0010)
82                 *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 4));
83         *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 0));
84         return out;
85 }
86
87 char *
88 dword_to_hex(char *out, guint32 dword) {
89   out = byte_to_hex(out, dword >> 24);
90   out = byte_to_hex(out, dword >> 16);
91   out = byte_to_hex(out, dword >>  8);
92   out = byte_to_hex(out, dword);
93   return out;
94 }
95
96 char *
97 dword_to_hex_punct(char *out, guint32 dword, char punct) {
98   out = byte_to_hex(out, dword >> 24);
99   *out++ = punct;
100   out = byte_to_hex(out, dword >> 16);
101   *out++ = punct;
102   out = byte_to_hex(out, dword >>  8);
103   *out++ = punct;
104   out = byte_to_hex(out, dword);
105   return out;
106 }
107
108 /*
109  * This does *not* null-terminate the string.  It returns a pointer
110  * to the position in the string following the last character it
111  * puts there, so that the caller can either put the null terminator
112  * in or can append more stuff to the buffer.
113  *
114  * There needs to be at least len * 2 bytes left in the buffer.
115  */
116 char *
117 bytes_to_hexstr(char *out, const guint8 *ad, guint32 len) {
118   guint32 i;
119
120   if (!ad)
121     REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
122
123   for (i = 0; i < len; i++)
124     out = byte_to_hex(out, ad[i]);
125   return out;
126 }
127
128 /*
129  * This does *not* null-terminate the string.  It returns a pointer
130  * to the position in the string following the last character it
131  * puts there, so that the caller can either put the null terminator
132  * in or can append more stuff to the buffer.
133  *
134  * There needs to be at least len * 3 - 1 bytes left in the buffer.
135  */
136 char *
137 bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct) {
138   guint32 i;
139
140   if (!ad)
141     REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
142
143   out = byte_to_hex(out, ad[0]);
144   for (i = 1; i < len; i++) {
145     *out++ = punct;
146     out = byte_to_hex(out, ad[i]);
147   }
148   return out;
149 }
150
151 /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
152  * digits at at a time, with a specified punctuation character between
153  * the bytes.
154  *
155  * If punct is '\0', no punctuation is applied (and thus
156  * the resulting string is (len-1) bytes shorter)
157  */
158 const gchar *
159 bytestring_to_str(const guint8 *ad, const guint32 len, const char punct) {
160   gchar *buf;
161   size_t       buflen;
162
163   if (!ad)
164     REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
165
166   /* XXX, Old code was using int as iterator... Why len is guint32 anyway?! (darkjames) */
167   if ( ((int) len) < 0)
168      return "";
169
170   if (!len)
171      return "";
172
173   if (punct)
174     buflen=len*3;
175   else
176     buflen=len*2 + 1;
177
178   buf=(gchar *)ep_alloc(buflen);
179
180   if (punct)
181     bytes_to_hexstr_punct(buf, ad, len, punct);
182   else
183     bytes_to_hexstr(buf, ad, len);
184
185   buf[buflen-1] = '\0';
186   return buf;
187 }
188
189 /* Max string length for displaying byte string.  */
190 #define MAX_BYTE_STR_LEN        48
191
192 gchar *
193 bytes_to_str(const guint8 *bd, int bd_len) {
194   gchar *cur;
195   gchar *cur_ptr;
196   int truncated = 0;
197
198   if (!bd)
199     REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
200
201   cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
202   if (bd_len <= 0) { cur[0] = '\0'; return cur; }
203
204   if (bd_len > MAX_BYTE_STR_LEN/2) {    /* bd_len > 24 */
205     truncated = 1;
206     bd_len = MAX_BYTE_STR_LEN/2;
207   }
208
209   cur_ptr = bytes_to_hexstr(cur, bd, bd_len);   /* max MAX_BYTE_STR_LEN bytes */
210
211   if (truncated)
212     cur_ptr = g_stpcpy(cur_ptr, "...");         /* 3 bytes */
213
214   *cur_ptr = '\0';                              /* 1 byte */
215   return cur;
216 }
217
218 /* Turn an array of bytes into a string showing the bytes in hex with
219  * punct as a bytes separator.
220  */
221 gchar *
222 bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
223   gchar *cur;
224   gchar *cur_ptr;
225   int truncated = 0;
226
227   if (!punct)
228     return bytes_to_str(bd, bd_len);
229
230   cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
231   if (bd_len <= 0) { cur[0] = '\0'; return cur; }
232
233   if (bd_len > MAX_BYTE_STR_LEN/3) {    /* bd_len > 16 */
234    truncated = 1;
235    bd_len = MAX_BYTE_STR_LEN/3;
236   }
237
238   cur_ptr = bytes_to_hexstr_punct(cur, bd, bd_len, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
239
240   if (truncated) {
241     *cur_ptr++ = punct;                         /* 1 byte */
242     cur_ptr    = g_stpcpy(cur_ptr, "...");      /* 3 bytes */
243   }
244
245   *cur_ptr = '\0';
246   return cur;
247 }
248
249 static int
250 guint32_to_str_buf_len(const guint32 u) {
251     if (u >= 1000000000)return 10;
252     if (u >= 100000000) return 9;
253     if (u >= 10000000)  return 8;
254     if (u >= 1000000)   return 7;
255     if (u >= 100000)    return 6;
256     if (u >= 10000)     return 5;
257     if (u >= 1000)      return 4;
258     if (u >= 100)       return 3;
259     if (u >= 10)        return 2;
260
261     return 1;
262 }
263
264 static const char fast_strings[][4] = {
265 "0", "1", "2", "3", "4", "5", "6", "7",
266 "8", "9", "10", "11", "12", "13", "14", "15",
267 "16", "17", "18", "19", "20", "21", "22", "23",
268 "24", "25", "26", "27", "28", "29", "30", "31",
269 "32", "33", "34", "35", "36", "37", "38", "39",
270 "40", "41", "42", "43", "44", "45", "46", "47",
271 "48", "49", "50", "51", "52", "53", "54", "55",
272 "56", "57", "58", "59", "60", "61", "62", "63",
273 "64", "65", "66", "67", "68", "69", "70", "71",
274 "72", "73", "74", "75", "76", "77", "78", "79",
275 "80", "81", "82", "83", "84", "85", "86", "87",
276 "88", "89", "90", "91", "92", "93", "94", "95",
277 "96", "97", "98", "99", "100", "101", "102", "103",
278 "104", "105", "106", "107", "108", "109", "110", "111",
279 "112", "113", "114", "115", "116", "117", "118", "119",
280 "120", "121", "122", "123", "124", "125", "126", "127",
281 "128", "129", "130", "131", "132", "133", "134", "135",
282 "136", "137", "138", "139", "140", "141", "142", "143",
283 "144", "145", "146", "147", "148", "149", "150", "151",
284 "152", "153", "154", "155", "156", "157", "158", "159",
285 "160", "161", "162", "163", "164", "165", "166", "167",
286 "168", "169", "170", "171", "172", "173", "174", "175",
287 "176", "177", "178", "179", "180", "181", "182", "183",
288 "184", "185", "186", "187", "188", "189", "190", "191",
289 "192", "193", "194", "195", "196", "197", "198", "199",
290 "200", "201", "202", "203", "204", "205", "206", "207",
291 "208", "209", "210", "211", "212", "213", "214", "215",
292 "216", "217", "218", "219", "220", "221", "222", "223",
293 "224", "225", "226", "227", "228", "229", "230", "231",
294 "232", "233", "234", "235", "236", "237", "238", "239",
295 "240", "241", "242", "243", "244", "245", "246", "247",
296 "248", "249", "250", "251", "252", "253", "254", "255"
297 };
298
299 char *uint_to_str_back(char *ptr, guint32 value);
300
301 void
302 guint32_to_str_buf(guint32 u, gchar *buf, int buf_len) {
303   int str_len = guint32_to_str_buf_len(u)+1;
304
305   gchar *bp = &buf[str_len];
306
307   if (buf_len < str_len) {
308     g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
309     return;
310   }
311
312   *--bp = '\0';
313
314   uint_to_str_back(bp, u);
315 }
316
317 gchar *
318 guint32_to_str(const guint32 u) {
319   int str_len = 16; /* guint32_to_str_buf_len(u)+1; */
320
321   gchar *bp = (gchar *)ep_alloc(str_len);
322   guint32_to_str_buf(u, bp, str_len);
323
324   return bp;
325 }
326
327 #define PLURALIZE(n)    (((n) > 1) ? "s" : "")
328 #define COMMA(do_it)    ((do_it) ? ", " : "")
329
330 /*
331  * Maximum length of a string showing days/hours/minutes/seconds.
332  * (Does not include the terminating '\0'.)
333  * Includes space for a '-' sign for any negative components.
334  * -12345 days, 12 hours, 12 minutes, 12.123 seconds
335  */
336 #define TIME_SECS_LEN   (10+1+4+2+2+5+2+2+7+2+2+7+4)
337
338 /*
339  * Convert a value in seconds and fractions of a second to a string,
340  * giving time in days, hours, minutes, and seconds, and put the result
341  * into a buffer.
342  * "is_nsecs" says that "frac" is microseconds if true and milliseconds
343  * if false.
344  * If time is negative, add a '-' to all non-null components.
345  */
346 static void
347 time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
348                            emem_strbuf_t *buf)
349 {
350   int hours, mins, secs;
351   const gchar *msign = "";
352   gboolean do_comma = FALSE;
353
354   if(time_val == G_MININT32) {  /* That Which Shall Not Be Negated */
355     ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
356     return;
357   }
358
359   if(time_val < 0){
360     time_val = -time_val;
361     msign = "-";
362   }
363
364   secs = time_val % 60;
365   time_val /= 60;
366   mins = time_val % 60;
367   time_val /= 60;
368   hours = time_val % 24;
369   time_val /= 24;
370
371   if (time_val != 0) {
372     ep_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
373     do_comma = TRUE;
374     msign="";
375   }
376   if (hours != 0) {
377     ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
378     do_comma = TRUE;
379     msign="";
380   }
381   if (mins != 0) {
382     ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
383     do_comma = TRUE;
384     msign="";
385   }
386   if (secs != 0 || frac != 0) {
387     if (frac != 0) {
388       if (is_nsecs)
389         ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
390       else
391         ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
392     } else
393       ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
394   }
395 }
396
397 gchar *
398 time_secs_to_str(const gint32 time_val)
399 {
400   emem_strbuf_t *buf;
401
402   buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
403
404   if (time_val == 0) {
405     ep_strbuf_append(buf, "0 seconds");
406     return buf->str;
407   }
408
409   time_secs_to_str_buf(time_val, 0, FALSE, buf);
410   return buf->str;
411 }
412
413 static void
414 time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
415                          emem_strbuf_t *buf)
416 {
417   int hours, mins, secs;
418   gboolean do_comma = FALSE;
419
420   secs = time_val % 60;
421   time_val /= 60;
422   mins = time_val % 60;
423   time_val /= 60;
424   hours = time_val % 24;
425   time_val /= 24;
426
427   if (time_val != 0) {
428     ep_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
429     do_comma = TRUE;
430   }
431   if (hours != 0) {
432     ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
433     do_comma = TRUE;
434   }
435   if (mins != 0) {
436     ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
437     do_comma = TRUE;
438   }
439   if (secs != 0 || frac != 0) {
440     if (frac != 0) {
441       if (is_nsecs)
442         ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
443       else
444         ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
445     } else
446       ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
447   }
448 }
449
450 gchar *
451 time_secs_to_str_unsigned(const guint32 time_val)
452 {
453   emem_strbuf_t *buf;
454
455   buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
456
457   if (time_val == 0) {
458     ep_strbuf_append(buf, "0 seconds");
459     return buf->str;
460   }
461
462   time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
463   return buf->str;
464 }
465
466
467 gchar *
468 time_msecs_to_str(gint32 time_val)
469 {
470   emem_strbuf_t *buf;
471   int msecs;
472
473   buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
474
475   if (time_val == 0) {
476     ep_strbuf_append(buf, "0 seconds");
477     return buf->str;
478   }
479
480   if(time_val<0){
481     /* oops we got passed a negative time */
482     time_val= -time_val;
483     msecs = time_val % 1000;
484     time_val /= 1000;
485     time_val= -time_val;
486   } else {
487     msecs = time_val % 1000;
488     time_val /= 1000;
489   }
490
491   time_secs_to_str_buf(time_val, msecs, FALSE, buf);
492   return buf->str;
493 }
494
495 static const char mon_names[12][4] = {
496         "Jan",
497         "Feb",
498         "Mar",
499         "Apr",
500         "May",
501         "Jun",
502         "Jul",
503         "Aug",
504         "Sep",
505         "Oct",
506         "Nov",
507         "Dec"
508 };
509
510 static const gchar *get_zonename(struct tm *tmp) {
511 #if defined(HAVE_TM_ZONE)
512         return tmp->tm_zone;
513 #else
514         if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
515                 return "???";
516         }
517 # if defined(HAVE_TZNAME)
518         return tzname[tmp->tm_isdst];
519
520 # elif defined(_WIN32)
521         /* Windows C Runtime:                                                 */
522         /*   _tzname is encoded using the "system default ansi code page"     */
523         /*     ("which is not necessarily the same as the C library locale"). */
524         /*     So: _tzname must be converted to UTF8 before use.              */
525         /*   Alternative: use Windows GetTimeZoneInformation() to get the     */
526         /*     timezone name in UTF16 and convert same to UTF8.               */
527         /*   XXX: the result is that the timezone name will be based upon the */
528         /*    system code page (iow: the charset of the system).              */
529         /*    Since Wireshark is not internationalized, it would seem more    */
530         /*    correct to show the timezone name in English, no matter what    */
531         /*    the system code page, but I don't how to do that (or if it's    */
532         /*    really even possible).                                          */
533         /*    In any case converting to UTF8 presumably at least keeps GTK    */
534         /*    happy. (A bug was reported wherein Wireshark crashed in GDK     */
535         /*    on a "Japanese version of Windows XP" when trying to copy       */
536         /*    the date/time string (containing a copy of _tz_name) to the     */
537         /*    clipboard).                                                     */
538
539         {
540                 static char *ws_tzname[2] = {NULL, NULL};
541
542                 /* The g_malloc'd value returned from g_locale_to_utf8() is   */
543                 /*  cached for all further use so there's no need to ever     */
544                 /*  g_free() that value.                                      */
545                 if (ws_tzname[tmp->tm_isdst] == NULL) {
546                         ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
547                         if (ws_tzname[tmp->tm_isdst] == NULL) {
548                                 ws_tzname[tmp->tm_isdst] = "???";
549                         }
550                 }
551                 return ws_tzname[tmp->tm_isdst];
552         }
553 # else
554         return tmp->tm_isdst ? "?DT" : "?ST";
555
556 # endif
557 #endif
558 }
559
560 gchar *
561 abs_time_to_str(const nstime_t *abs_time, const absolute_time_display_e fmt,
562    gboolean show_zone)
563 {
564         struct tm *tmp = NULL;
565         const char *zonename = "???";
566         gchar *buf = NULL;
567
568 #if (defined _WIN32) && (_MSC_VER < 1500)
569         /* calling localtime() on MSVC 2005 with huge values causes it to crash */
570         /* XXX - find the exact value that still does work */
571         /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
572         if(abs_time->secs > 2000000000) {
573             tmp = NULL;
574         } else
575 #endif
576         switch (fmt) {
577
578         case ABSOLUTE_TIME_UTC:
579         case ABSOLUTE_TIME_DOY_UTC:
580                 tmp = gmtime(&abs_time->secs);
581                 zonename = "UTC";
582                 break;
583
584         case ABSOLUTE_TIME_LOCAL:
585                 tmp = localtime(&abs_time->secs);
586                 if (tmp) {
587                         zonename = get_zonename(tmp);
588                 }
589                 break;
590         }
591         if (tmp) {
592                 switch (fmt) {
593
594                 case ABSOLUTE_TIME_DOY_UTC:
595                         if (show_zone) {
596                                 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld %s",
597                                     tmp->tm_year + 1900,
598                                     tmp->tm_yday + 1,
599                                     tmp->tm_hour,
600                                     tmp->tm_min,
601                                     tmp->tm_sec,
602                                     (long)abs_time->nsecs,
603                                     zonename);
604                         } else {
605                                 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld",
606                                     tmp->tm_year + 1900,
607                                     tmp->tm_yday + 1,
608                                     tmp->tm_hour,
609                                     tmp->tm_min,
610                                     tmp->tm_sec,
611                                     (long)abs_time->nsecs);
612                         }
613                         break;
614
615                 case ABSOLUTE_TIME_UTC:
616                 case ABSOLUTE_TIME_LOCAL:
617                         if (show_zone) {
618                                 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld %s",
619                                     mon_names[tmp->tm_mon],
620                                     tmp->tm_mday,
621                                     tmp->tm_year + 1900,
622                                     tmp->tm_hour,
623                                     tmp->tm_min,
624                                     tmp->tm_sec,
625                                     (long)abs_time->nsecs,
626                                     zonename);
627                         } else {
628                                 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld",
629                                     mon_names[tmp->tm_mon],
630                                     tmp->tm_mday,
631                                     tmp->tm_year + 1900,
632                                     tmp->tm_hour,
633                                     tmp->tm_min,
634                                     tmp->tm_sec,
635                                     (long)abs_time->nsecs);
636                         }
637                         break;
638                 }
639         } else
640                 buf = ep_strdup("Not representable");
641         return buf;
642 }
643
644 gchar *
645 abs_time_secs_to_str(const time_t abs_time, const absolute_time_display_e fmt,
646     gboolean show_zone)
647 {
648         struct tm *tmp = NULL;
649         const char *zonename = "???";
650         gchar *buf = NULL;
651
652 #if (defined _WIN32) && (_MSC_VER < 1500)
653         /* calling localtime() on MSVC 2005 with huge values causes it to crash */
654         /* XXX - find the exact value that still does work */
655         /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
656         if(abs_time > 2000000000) {
657             tmp = NULL;
658         } else
659 #endif
660         switch (fmt) {
661
662         case ABSOLUTE_TIME_UTC:
663         case ABSOLUTE_TIME_DOY_UTC:
664                 tmp = gmtime(&abs_time);
665                 zonename = "UTC";
666                 break;
667
668         case ABSOLUTE_TIME_LOCAL:
669                 tmp = localtime(&abs_time);
670                 if (tmp) {
671                         zonename = get_zonename(tmp);
672                 }
673                 break;
674         }
675         if (tmp) {
676                 switch (fmt) {
677
678                 case ABSOLUTE_TIME_DOY_UTC:
679                         if (show_zone) {
680                                 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d %s",
681                                     tmp->tm_year + 1900,
682                                     tmp->tm_yday + 1,
683                                     tmp->tm_hour,
684                                     tmp->tm_min,
685                                     tmp->tm_sec,
686                                     zonename);
687                         } else {
688                                 buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d",
689                                     tmp->tm_year + 1900,
690                                     tmp->tm_yday + 1,
691                                     tmp->tm_hour,
692                                     tmp->tm_min,
693                                     tmp->tm_sec);
694                         }
695                         break;
696
697                 case ABSOLUTE_TIME_UTC:
698                 case ABSOLUTE_TIME_LOCAL:
699                         if (show_zone) {
700                                 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d %s",
701                                     mon_names[tmp->tm_mon],
702                                     tmp->tm_mday,
703                                     tmp->tm_year + 1900,
704                                     tmp->tm_hour,
705                                     tmp->tm_min,
706                                     tmp->tm_sec,
707                                     zonename);
708                         } else {
709                                 buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d",
710                                     mon_names[tmp->tm_mon],
711                                     tmp->tm_mday,
712                                     tmp->tm_year + 1900,
713                                     tmp->tm_hour,
714                                     tmp->tm_min,
715                                     tmp->tm_sec);
716                         }
717                         break;
718                 }
719         } else
720                 buf = ep_strdup("Not representable");
721         return buf;
722 }
723
724 void
725 display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
726     const to_str_time_res_t units)
727 {
728         /* If the fractional part of the time stamp is negative,
729            print its absolute value and, if the seconds part isn't
730            (the seconds part should be zero in that case), stick
731            a "-" in front of the entire time stamp. */
732         if (frac < 0) {
733                 frac = -frac;
734                 if (sec >= 0) {
735                         if (buflen < 1) {
736                           return;
737                         }
738                         buf[0] = '-';
739                         buf++;
740                         buflen--;
741                 }
742         }
743         switch (units) {
744
745         case TO_STR_TIME_RES_T_SECS:
746                 g_snprintf(buf, buflen, "%d", sec);
747                 break;
748
749         case TO_STR_TIME_RES_T_DSECS:
750                 g_snprintf(buf, buflen, "%d.%01d", sec, frac);
751                 break;
752
753         case TO_STR_TIME_RES_T_CSECS:
754                 g_snprintf(buf, buflen, "%d.%02d", sec, frac);
755                 break;
756
757         case TO_STR_TIME_RES_T_MSECS:
758                 g_snprintf(buf, buflen, "%d.%03d", sec, frac);
759                 break;
760
761         case TO_STR_TIME_RES_T_USECS:
762                 g_snprintf(buf, buflen, "%d.%06d", sec, frac);
763                 break;
764
765         case TO_STR_TIME_RES_T_NSECS:
766                 g_snprintf(buf, buflen, "%d.%09d", sec, frac);
767                 break;
768         }
769 }
770
771
772 void
773 display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
774     const to_str_time_res_t units)
775 {
776         double elapsed_secs;
777
778         elapsed_secs = difftime(sec,(time_t)0);
779
780         /* This code copied from display_signed_time; keep it in case anyone
781            is looking at captures from before 1970 (???).
782            If the fractional part of the time stamp is negative,
783            print its absolute value and, if the seconds part isn't
784            (the seconds part should be zero in that case), stick
785            a "-" in front of the entire time stamp. */
786         if (frac < 0) {
787                 frac = -frac;
788                 if (elapsed_secs >= 0) {
789                         if (buflen < 1) {
790                           return;
791                         }
792                         buf[0] = '-';
793                         buf++;
794                         buflen--;
795                 }
796         }
797         switch (units) {
798
799         case TO_STR_TIME_RES_T_SECS:
800                 g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
801                 break;
802
803         case TO_STR_TIME_RES_T_DSECS:
804                 g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
805                 break;
806
807         case TO_STR_TIME_RES_T_CSECS:
808                 g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
809                 break;
810
811         case TO_STR_TIME_RES_T_MSECS:
812                 g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
813                 break;
814
815         case TO_STR_TIME_RES_T_USECS:
816                 g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
817                 break;
818
819         case TO_STR_TIME_RES_T_NSECS:
820                 g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
821                 break;
822         }
823 }
824
825 /*
826  * Display a relative time as days/hours/minutes/seconds.
827  */
828 gchar *
829 rel_time_to_str(const nstime_t *rel_time)
830 {
831         emem_strbuf_t *buf;
832         gint32 time_val;
833         gint32 nsec;
834
835         buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
836
837         /* If the nanoseconds part of the time stamp is negative,
838            print its absolute value and, if the seconds part isn't
839            (the seconds part should be zero in that case), stick
840            a "-" in front of the entire time stamp. */
841         time_val = (gint) rel_time->secs;
842         nsec = rel_time->nsecs;
843         if (time_val == 0 && nsec == 0) {
844                 ep_strbuf_append(buf, "0.000000000 seconds");
845                 return buf->str;
846         }
847         if (nsec < 0) {
848                 nsec = -nsec;
849                 ep_strbuf_append_c(buf, '-');
850
851                 /*
852                  * We assume here that "rel_time->secs" is negative
853                  * or zero; if it's not, the time stamp is bogus,
854                  * with a positive seconds and negative microseconds.
855                  */
856                 time_val = (gint) -rel_time->secs;
857         }
858
859         time_secs_to_str_buf(time_val, nsec, TRUE, buf);
860         return buf->str;
861 }
862
863 #define REL_TIME_SECS_LEN       (1+10+1+9+1)
864
865 /*
866  * Display a relative time as seconds.
867  */
868 gchar *
869 rel_time_to_secs_str(const nstime_t *rel_time)
870 {
871         gchar *buf;
872
873         buf=(gchar *)ep_alloc(REL_TIME_SECS_LEN);
874
875         display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
876             rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
877         return buf;
878 }
879
880 /*
881  * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
882  * with the length in bits of no_of_bits based on value.
883  * Ex: ..xx x...
884  */
885
886 char *
887 decode_bits_in_field(const guint bit_offset, const gint no_of_bits, const guint64 value)
888 {
889         guint64 mask = 0,tmp;
890         char *str;
891         int bit, str_p = 0;
892         int i;
893
894         mask = 1;
895         mask = mask << (no_of_bits-1);
896
897         /* Prepare the string, 256 pos for the bits and zero termination, + 64 for the spaces */
898         str=(char *)ep_alloc0(256+64);
899         for(bit=0;bit<((int)(bit_offset&0x07));bit++){
900                 if(bit&&(!(bit%4))){
901                         str[str_p] = ' ';
902                         str_p++;
903                 }
904                 str[str_p] = '.';
905                 str_p++;
906         }
907
908         /* read the bits for the int */
909         for(i=0;i<no_of_bits;i++){
910                 if(bit&&(!(bit%4))){
911                         str[str_p] = ' ';
912                         str_p++;
913                 }
914                 if(bit&&(!(bit%8))){
915                         str[str_p] = ' ';
916                         str_p++;
917                 }
918                 bit++;
919                 tmp = value & mask;
920                 if(tmp != 0){
921                         str[str_p] = '1';
922                         str_p++;
923                 } else {
924                         str[str_p] = '0';
925                         str_p++;
926                 }
927                 mask = mask>>1;
928         }
929
930         for(;bit%8;bit++){
931                 if(bit&&(!(bit%4))){
932                         str[str_p] = ' ';
933                         str_p++;
934                 }
935                 str[str_p] = '.';
936                 str_p++;
937         }
938         return str;
939 }
940
941 /* Generate, into "buf", a string showing the bits of a bitfield.
942    Return a pointer to the character after that string. */
943 /*XXX this needs a buf_len check */
944 char *
945 other_decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
946 {
947   int i;
948   guint32 bit;
949   char *p;
950
951   i = 0;
952   p = buf;
953   bit = 1 << (width - 1);
954   for (;;) {
955     if (mask & bit) {
956       /* This bit is part of the field.  Show its value. */
957       if (val & bit)
958         *p++ = '1';
959       else
960         *p++ = '0';
961     } else {
962       /* This bit is not part of the field. */
963       *p++ = '.';
964     }
965     bit >>= 1;
966     i++;
967     if (i >= width)
968       break;
969     if (i % 4 == 0)
970       *p++ = ' ';
971   }
972   *p = '\0';
973   return p;
974 }
975
976 char *
977 decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
978 {
979   char *p;
980
981   p = other_decode_bitfield_value(buf, val, mask, width);
982   p = g_stpcpy(p, " = ");
983
984   return p;
985 }
986
987 /* Generate a string describing a Boolean bitfield (a one-bit field that
988    says something is either true or false). */
989 const char *
990 decode_boolean_bitfield(const guint32 val, const guint32 mask, const int width,
991     const char *truedesc, const char *falsedesc)
992 {
993   char *buf;
994   char *p;
995
996   buf=(char *)ep_alloc(1025); /* is this a bit overkill? */
997   p = decode_bitfield_value(buf, val, mask, width);
998   if (val & mask)
999     strcpy(p, truedesc);
1000   else
1001     strcpy(p, falsedesc);
1002   return buf;
1003 }
1004
1005 /* Generate a string describing a numeric bitfield (an N-bit field whose
1006    value is just a number). */
1007 const char *
1008 decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width,
1009     const char *fmt)
1010 {
1011   char *buf;
1012   char *p;
1013   int shift = 0;
1014
1015   buf=(char *)ep_alloc(1025); /* isnt this a bit overkill? */
1016   /* Compute the number of bits we have to shift the bitfield right
1017      to extract its value. */
1018   while ((mask & (1<<shift)) == 0)
1019     shift++;
1020
1021   p = decode_bitfield_value(buf, val, mask, width);
1022   g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
1023   return buf;
1024 }
1025
1026 /*
1027  This function is very fast and this function is called a lot.
1028  XXX update the ep_address_to_str stuff to use this function.
1029 */
1030 void
1031 ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
1032 {
1033         register gchar const *p;
1034         register gchar *b=buf;
1035
1036         if (buf_len < MAX_IP_STR_LEN) {
1037                 g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
1038                 return;
1039         }
1040
1041         p=fast_strings[*ad++];
1042         do {
1043                 *b++=*p;
1044                 p++;
1045         } while(*p);
1046         *b++='.';
1047
1048         p=fast_strings[*ad++];
1049         do {
1050                 *b++=*p;
1051                 p++;
1052         } while(*p);
1053         *b++='.';
1054
1055         p=fast_strings[*ad++];
1056         do {
1057                 *b++=*p;
1058                 p++;
1059         } while(*p);
1060         *b++='.';
1061
1062         p=fast_strings[*ad];
1063         do {
1064                 *b++=*p;
1065                 p++;
1066         } while(*p);
1067         *b=0;
1068 }
1069
1070 gchar* guid_to_str(const e_guid_t *guid) {
1071   gchar *buf;
1072
1073   buf=(gchar *)ep_alloc(GUID_STR_LEN);
1074   return guid_to_str_buf(guid, buf, GUID_STR_LEN);
1075 }
1076
1077 gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
1078   char *tempptr = buf;
1079
1080   if (buf_len < GUID_STR_LEN) {
1081      g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
1082      return buf;
1083   }
1084
1085   /* 37 bytes */
1086   tempptr    = dword_to_hex(tempptr, guid->data1);              /*  8 bytes */
1087   *tempptr++ = '-';                                             /*  1 byte */
1088   tempptr    = word_to_hex(tempptr, guid->data2);               /*  4 bytes */
1089   *tempptr++ = '-';                                             /*  1 byte */
1090   tempptr    = word_to_hex(tempptr, guid->data3);               /*  4 bytes */
1091   *tempptr++ = '-';                                             /*  1 byte */
1092   tempptr    = bytes_to_hexstr(tempptr, &guid->data4[0], 2);    /*  4 bytes */
1093   *tempptr++ = '-';                                             /*  1 byte */
1094   tempptr    = bytes_to_hexstr(tempptr, &guid->data4[2], 6);    /* 12 bytes */
1095
1096   *tempptr   = '\0';
1097   return buf;
1098 }
1099
1100 const gchar* port_type_to_str (port_type type) {
1101         switch (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                 default:                        return "[Unknown]";
1119         }
1120 }
1121
1122 char *
1123 oct_to_str_back(char *ptr, guint32 value)
1124 {
1125         while (value) {
1126                 *(--ptr) = '0' + (value & 0x7);
1127                 value >>= 3;
1128         }
1129
1130         *(--ptr) = '0';
1131         return ptr;
1132 }
1133
1134 char *
1135 hex_to_str_back(char *ptr, int pad, guint32 value)
1136 {
1137         do {
1138                 *(--ptr) = low_nibble_of_octet_to_hex(value);
1139                 value >>= 4;
1140                 pad--;
1141         } while (value);
1142
1143         /* pad */
1144         while (pad > 0) {
1145                 *(--ptr) = '0';
1146                 pad--;
1147         }
1148
1149         *(--ptr) = 'x';
1150         *(--ptr) = '0';
1151
1152         return ptr;
1153 }
1154
1155 char *
1156 uint_to_str_back(char *ptr, guint32 value)
1157 {
1158         char const *p;
1159
1160         /* special case */
1161         if (value == 0)
1162                 *(--ptr) = '0';
1163
1164         while (value >= 10) {
1165                 p = fast_strings[100 + (value % 100)];
1166
1167                 value /= 100;
1168
1169                 *(--ptr) = p[2];
1170                 *(--ptr) = p[1];
1171         }
1172
1173         if (value)
1174                 *(--ptr) = (value) | '0';
1175
1176         return ptr;
1177 }
1178
1179 char *
1180 int_to_str_back(char *ptr, gint32 value)
1181 {
1182         if (value < 0) {
1183                 ptr = uint_to_str_back(ptr, -value);
1184                 *(--ptr) = '-';
1185         } else
1186                 ptr = uint_to_str_back(ptr, value);
1187
1188         return ptr;
1189 }
1190