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