2 * Routines for utilities to convert various other types to strings.
4 * $Id: to_str.c,v 1.1 2001/04/01 02:47:55 hagbard Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef NEED_SNPRINTF_H
31 # include "snprintf.h"
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
38 #ifdef HAVE_SYS_TYPES_H
39 # include <sys/types.h>
42 #ifdef HAVE_ARPA_INET_H
43 #include <arpa/inet.h>
46 #ifdef NEED_INET_V6DEFS_H
47 # include "inet_v6defs.h"
56 /* Wrapper for the most common case of asking
57 * for a string using a colon as the hex-digit separator.
61 ether_to_str(const guint8 *ad)
63 return ether_to_str_punct(ad, ':');
66 /* Places char punct in the string as the hex-digit separator.
67 * If punct is '\0', no punctuation is applied (and thus
68 * the resulting string is 5 bytes shorter)
71 ether_to_str_punct(const guint8 *ad, char punct) {
72 static gchar str[3][18];
77 static const gchar hex_digits[16] = "0123456789abcdef";
79 if (cur == &str[0][0]) {
81 } else if (cur == &str[1][0]) {
91 *--p = hex_digits[octet&0xF];
93 *--p = hex_digits[octet&0xF];
104 ip_to_str(const guint8 *ad) {
105 static gchar str[3][16];
108 if (cur == &str[0][0]) {
110 } else if (cur == &str[1][0]) {
115 ip_to_str_buf(ad, cur);
120 ip_to_str_buf(const guint8 *ad, gchar *buf)
126 gboolean saw_nonzero;
140 if (saw_nonzero || digit != 0)
153 ip6_to_str(struct e_in6_addr *ad) {
154 #ifndef INET6_ADDRSTRLEN
155 #define INET6_ADDRSTRLEN 46
157 static gchar buf[INET6_ADDRSTRLEN];
159 inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
164 ipx_addr_to_str(guint32 net, const guint8 *ad)
166 static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
170 if (cur == &str[0][0]) {
172 } else if (cur == &str[1][0]) {
178 name = get_ether_name_if_known(ad);
181 sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
184 sprintf(cur, "%s.%s", get_ipxnet_name(net), ether_to_str_punct(ad, '\0'));
190 ipxnet_to_string(const guint8 *ad)
192 guint32 addr = pntohl(ad);
193 return ipxnet_to_str_punct(addr, ' ');
197 ipxnet_to_str_punct(const guint32 ad, char punct)
199 static gchar str[3][12];
204 static const gchar hex_digits[16] = "0123456789ABCDEF";
205 static const guint32 octet_mask[4] =
206 { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
208 if (cur == &str[0][0]) {
210 } else if (cur == &str[1][0]) {
219 octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
220 *--p = hex_digits[octet&0xF];
222 *--p = hex_digits[octet&0xF];
233 #define PLURALIZE(n) (((n) > 1) ? "s" : "")
234 #define COMMA(do_it) ((do_it) ? ", " : "")
237 time_secs_to_str(guint32 time)
239 static gchar str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
240 static gchar *cur, *p;
241 int hours, mins, secs;
244 if (cur == &str[0][0]) {
246 } else if (cur == &str[1][0]) {
253 sprintf(cur, "0 time");
266 sprintf(p, "%u day%s", time, PLURALIZE(time));
272 sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
278 sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
284 sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
288 static const char *mon_names[12] = {
304 abs_time_to_str(struct timeval *abs_time)
308 static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
310 if (cur == &str[0][0]) {
312 } else if (cur == &str[1][0]) {
318 tmp = localtime(&abs_time->tv_sec);
319 sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
320 mon_names[tmp->tm_mon],
326 (long)abs_time->tv_usec/100);
331 #define REL_TIME_LEN (1+10+1+6+1)
334 display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 usec)
338 /* If the microseconds part of the time stamp is negative,
339 print its absolute value and, if the seconds part isn't
340 (the seconds part should be zero in that case), stick
341 a "-" in front of the entire time stamp. */
348 snprintf(buf, buflen, "%s%d.%06d", sign, sec, usec);
352 rel_time_to_str(struct timeval *rel_time)
355 static char str[3][REL_TIME_LEN];
357 if (cur == &str[0][0]) {
359 } else if (cur == &str[1][0]) {
365 display_signed_time(cur, REL_TIME_LEN, rel_time->tv_sec,
370 /* Generate, into "buf", a string showing the bits of a bitfield.
371 Return a pointer to the character after that string. */
373 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
381 bit = 1 << (width - 1);
384 /* This bit is part of the field. Show its value. */
390 /* This bit is not part of the field. */
405 /* Generate a string describing a Boolean bitfield (a one-bit field that
406 says something is either true of false). */
408 decode_boolean_bitfield(guint32 val, guint32 mask, int width,
409 const char *truedesc, const char *falsedesc)
411 static char buf[1025];
414 p = decode_bitfield_value(buf, val, mask, width);
418 strcpy(p, falsedesc);
422 /* Generate a string describing a numeric bitfield (an N-bit field whose
423 value is just a number). */
425 decode_numeric_bitfield(guint32 val, guint32 mask, int width,
428 static char buf[1025];
432 /* Compute the number of bits we have to shift the bitfield right
433 to extract its value. */
434 while ((mask & (1<<shift)) == 0)
437 p = decode_bitfield_value(buf, val, mask, width);
438 sprintf(p, fmt, (val & mask) >> shift);