aboutsummaryrefslogtreecommitdiffstats
path: root/epan/to_str.c
diff options
context:
space:
mode:
authorEd Warnicke <hagbard@physics.rutgers.edu>2001-04-01 02:47:56 +0000
committerEd Warnicke <hagbard@physics.rutgers.edu>2001-04-01 02:47:56 +0000
commitc17e3b00c6396ec52a6ca39441dabcaa97a4365d (patch)
treeaa445c8e30cfee75054eb46e14d58c1e7789ffd7 /epan/to_str.c
parent3b6554c069c6d607b343415f5e78794e2010d350 (diff)
Moved various to_str files from packet.{c,h} to a separate
to_str.{c,h}. Resolved strange situation where ipx_addr_to_str was declared in packet.h but defined in packet-ipx.c by moving ipx_addr_to_str, ipxnet_to_str_punct, and ipxnet_to_str from packet-ipx.{c,h} to to_str.{c,h} svn path=/trunk/; revision=3219
Diffstat (limited to 'epan/to_str.c')
-rw-r--r--epan/to_str.c443
1 files changed, 443 insertions, 0 deletions
diff --git a/epan/to_str.c b/epan/to_str.c
new file mode 100644
index 0000000000..111a06265a
--- /dev/null
+++ b/epan/to_str.c
@@ -0,0 +1,443 @@
+/* to_str.h
+ * Routines for utilities to convert various other types to strings.
+ *
+ * $Id: to_str.c,v 1.1 2001/04/01 02:47:55 hagbard Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef NEED_INET_V6DEFS_H
+# include "inet_v6defs.h"
+#endif
+
+#include "to_str.h"
+#include "resolv.h"
+#include "pint.h"
+#include <stdio.h>
+#include <time.h>
+
+/* Wrapper for the most common case of asking
+ * for a string using a colon as the hex-digit separator.
+ */
+
+gchar *
+ether_to_str(const guint8 *ad)
+{
+ return ether_to_str_punct(ad, ':');
+}
+
+/* Places char punct in the string as the hex-digit separator.
+ * If punct is '\0', no punctuation is applied (and thus
+ * the resulting string is 5 bytes shorter)
+ */
+gchar *
+ether_to_str_punct(const guint8 *ad, char punct) {
+ static gchar str[3][18];
+ static gchar *cur;
+ gchar *p;
+ int i;
+ guint32 octet;
+ static const gchar hex_digits[16] = "0123456789abcdef";
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+ p = &cur[18];
+ *--p = '\0';
+ i = 5;
+ for (;;) {
+ octet = ad[i];
+ *--p = hex_digits[octet&0xF];
+ octet >>= 4;
+ *--p = hex_digits[octet&0xF];
+ if (i == 0)
+ break;
+ if (punct)
+ *--p = punct;
+ i--;
+ }
+ return p;
+}
+
+gchar *
+ip_to_str(const guint8 *ad) {
+ static gchar str[3][16];
+ static gchar *cur;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+ ip_to_str_buf(ad, cur);
+ return cur;
+}
+
+void
+ip_to_str_buf(const guint8 *ad, gchar *buf)
+{
+ gchar *p;
+ int i;
+ guint32 octet;
+ guint32 digit;
+ gboolean saw_nonzero;
+
+ p = buf;
+ i = 0;
+ for (;;) {
+ saw_nonzero = FALSE;
+ octet = ad[i];
+ digit = octet/100;
+ if (digit != 0) {
+ *p++ = digit + '0';
+ saw_nonzero = TRUE;
+ }
+ octet %= 100;
+ digit = octet/10;
+ if (saw_nonzero || digit != 0)
+ *p++ = digit + '0';
+ digit = octet%10;
+ *p++ = digit + '0';
+ if (i == 3)
+ break;
+ *p++ = '.';
+ i++;
+ }
+ *p = '\0';
+}
+
+gchar *
+ip6_to_str(struct e_in6_addr *ad) {
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+ static gchar buf[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
+ return buf;
+}
+
+gchar*
+ipx_addr_to_str(guint32 net, const guint8 *ad)
+{
+ static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
+ static gchar *cur;
+ char *name;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ name = get_ether_name_if_known(ad);
+
+ if (name) {
+ sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
+ }
+ else {
+ sprintf(cur, "%s.%s", get_ipxnet_name(net), ether_to_str_punct(ad, '\0'));
+ }
+ return cur;
+}
+
+gchar*
+ipxnet_to_string(const guint8 *ad)
+{
+ guint32 addr = pntohl(ad);
+ return ipxnet_to_str_punct(addr, ' ');
+}
+
+gchar *
+ipxnet_to_str_punct(const guint32 ad, char punct)
+{
+ static gchar str[3][12];
+ static gchar *cur;
+ gchar *p;
+ int i;
+ guint32 octet;
+ static const gchar hex_digits[16] = "0123456789ABCDEF";
+ static const guint32 octet_mask[4] =
+ { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+ p = &cur[12];
+ *--p = '\0';
+ i = 3;
+ for (;;) {
+ octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
+ *--p = hex_digits[octet&0xF];
+ octet >>= 4;
+ *--p = hex_digits[octet&0xF];
+ if (i == 0)
+ break;
+ if (punct)
+ *--p = punct;
+ i--;
+ }
+ return p;
+}
+
+
+#define PLURALIZE(n) (((n) > 1) ? "s" : "")
+#define COMMA(do_it) ((do_it) ? ", " : "")
+
+gchar *
+time_secs_to_str(guint32 time)
+{
+ static gchar str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
+ static gchar *cur, *p;
+ int hours, mins, secs;
+ int do_comma;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ if (time == 0) {
+ sprintf(cur, "0 time");
+ return cur;
+ }
+
+ secs = time % 60;
+ time /= 60;
+ mins = time % 60;
+ time /= 60;
+ hours = time % 24;
+ time /= 24;
+
+ p = cur;
+ if (time != 0) {
+ sprintf(p, "%u day%s", time, PLURALIZE(time));
+ p += strlen(p);
+ do_comma = 1;
+ } else
+ do_comma = 0;
+ if (hours != 0) {
+ sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
+ p += strlen(p);
+ do_comma = 1;
+ } else
+ do_comma = 0;
+ if (mins != 0) {
+ sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
+ p += strlen(p);
+ do_comma = 1;
+ } else
+ do_comma = 0;
+ if (secs != 0)
+ sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
+ return cur;
+}
+
+static const char *mon_names[12] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+};
+
+gchar *
+abs_time_to_str(struct timeval *abs_time)
+{
+ struct tm *tmp;
+ static gchar *cur;
+ static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ tmp = localtime(&abs_time->tv_sec);
+ sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
+ mon_names[tmp->tm_mon],
+ tmp->tm_mday,
+ tmp->tm_year + 1900,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (long)abs_time->tv_usec/100);
+
+ return cur;
+}
+
+#define REL_TIME_LEN (1+10+1+6+1)
+
+void
+display_signed_time(gchar *buf, int buflen, gint32 sec, gint32 usec)
+{
+ char *sign;
+
+ /* If the microseconds part of the time stamp is negative,
+ print its absolute value and, if the seconds part isn't
+ (the seconds part should be zero in that case), stick
+ a "-" in front of the entire time stamp. */
+ sign = "";
+ if (usec < 0) {
+ usec = -usec;
+ if (sec >= 0)
+ sign = "-";
+ }
+ snprintf(buf, buflen, "%s%d.%06d", sign, sec, usec);
+}
+
+gchar *
+rel_time_to_str(struct timeval *rel_time)
+{
+ static gchar *cur;
+ static char str[3][REL_TIME_LEN];
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ display_signed_time(cur, REL_TIME_LEN, rel_time->tv_sec,
+ rel_time->tv_usec);
+ return cur;
+}
+
+/* Generate, into "buf", a string showing the bits of a bitfield.
+ Return a pointer to the character after that string. */
+char *
+decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+{
+ int i;
+ guint32 bit;
+ char *p;
+
+ i = 0;
+ p = buf;
+ bit = 1 << (width - 1);
+ for (;;) {
+ if (mask & bit) {
+ /* This bit is part of the field. Show its value. */
+ if (val & bit)
+ *p++ = '1';
+ else
+ *p++ = '0';
+ } else {
+ /* This bit is not part of the field. */
+ *p++ = '.';
+ }
+ bit >>= 1;
+ i++;
+ if (i >= width)
+ break;
+ if (i % 4 == 0)
+ *p++ = ' ';
+ }
+ strcpy(p, " = ");
+ p += 3;
+ return p;
+}
+
+/* Generate a string describing a Boolean bitfield (a one-bit field that
+ says something is either true of false). */
+const char *
+decode_boolean_bitfield(guint32 val, guint32 mask, int width,
+ const char *truedesc, const char *falsedesc)
+{
+ static char buf[1025];
+ char *p;
+
+ p = decode_bitfield_value(buf, val, mask, width);
+ if (val & mask)
+ strcpy(p, truedesc);
+ else
+ strcpy(p, falsedesc);
+ return buf;
+}
+
+/* Generate a string describing a numeric bitfield (an N-bit field whose
+ value is just a number). */
+const char *
+decode_numeric_bitfield(guint32 val, guint32 mask, int width,
+ const char *fmt)
+{
+ static char buf[1025];
+ char *p;
+ int shift = 0;
+
+ /* Compute the number of bits we have to shift the bitfield right
+ to extract its value. */
+ while ((mask & (1<<shift)) == 0)
+ shift++;
+
+ p = decode_bitfield_value(buf, val, mask, width);
+ sprintf(p, fmt, (val & mask) >> shift);
+ return buf;
+}
+
+
+