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