aboutsummaryrefslogtreecommitdiffstats
path: root/wsutil
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2021-09-16 16:04:11 +0100
committerJoão Valverde <j@v6e.pt>2021-09-16 20:55:03 +0100
commit8c4a479c52c7c4abdef7eb82fd0c2d704cd14c0e (patch)
tree0990798dfe9182bbecc5a020871a93ce837b4349 /wsutil
parentcc1e5b83349d837fe442883842170230fc7a400c (diff)
Move more numerical functions to wsutil/to_str.h
Diffstat (limited to 'wsutil')
-rw-r--r--wsutil/to_str.c193
-rw-r--r--wsutil/to_str.h17
2 files changed, 210 insertions, 0 deletions
diff --git a/wsutil/to_str.c b/wsutil/to_str.c
index cd035fe17d..a503794c59 100644
--- a/wsutil/to_str.c
+++ b/wsutil/to_str.c
@@ -19,7 +19,16 @@
#include <wsutil/utf8_entities.h>
#include <wsutil/wslog.h>
+#include <wsutil/inet_addr.h>
+#include <wsutil/pint.h>
+/*
+ * If a user _does_ pass in a too-small buffer, this is probably
+ * going to be too long to fit. However, even a partial string
+ * starting with "[Buf" should provide enough of a clue to be
+ * useful.
+ */
+#define BUF_TOO_SMALL_ERR "[Buffer too small]"
static const char fast_strings[][4] = {
"0", "1", "2", "3", "4", "5", "6", "7",
@@ -446,6 +455,190 @@ int64_to_str_back(char *ptr, gint64 value)
return ptr;
}
+static int
+guint32_to_str_buf_len(const guint32 u)
+{
+ /* ((2^32)-1) == 2147483647 */
+ if (u >= 1000000000)return 10;
+ if (u >= 100000000) return 9;
+ if (u >= 10000000) return 8;
+ if (u >= 1000000) return 7;
+ if (u >= 100000) return 6;
+ if (u >= 10000) return 5;
+ if (u >= 1000) return 4;
+ if (u >= 100) return 3;
+ if (u >= 10) return 2;
+
+ return 1;
+}
+
+void
+guint32_to_str_buf(guint32 u, gchar *buf, int buf_len)
+{
+ int str_len = guint32_to_str_buf_len(u)+1;
+
+ gchar *bp = &buf[str_len];
+
+ if (buf_len < str_len) {
+ (void) g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
+ return;
+ }
+
+ *--bp = '\0';
+
+ uint_to_str_back(bp, u);
+}
+
+static int
+guint64_to_str_buf_len(const guint64 u)
+{
+ /* ((2^64)-1) == 18446744073709551615 */
+
+ if (u >= G_GUINT64_CONSTANT(10000000000000000000)) return 20;
+ if (u >= G_GUINT64_CONSTANT(1000000000000000000)) return 19;
+ if (u >= G_GUINT64_CONSTANT(100000000000000000)) return 18;
+ if (u >= G_GUINT64_CONSTANT(10000000000000000)) return 17;
+ if (u >= G_GUINT64_CONSTANT(1000000000000000)) return 16;
+ if (u >= G_GUINT64_CONSTANT(100000000000000)) return 15;
+ if (u >= G_GUINT64_CONSTANT(10000000000000)) return 14;
+ if (u >= G_GUINT64_CONSTANT(1000000000000)) return 13;
+ if (u >= G_GUINT64_CONSTANT(100000000000)) return 12;
+ if (u >= G_GUINT64_CONSTANT(10000000000)) return 11;
+ if (u >= G_GUINT64_CONSTANT(1000000000)) return 10;
+ if (u >= G_GUINT64_CONSTANT(100000000)) return 9;
+ if (u >= G_GUINT64_CONSTANT(10000000)) return 8;
+ if (u >= G_GUINT64_CONSTANT(1000000)) return 7;
+ if (u >= G_GUINT64_CONSTANT(100000)) return 6;
+ if (u >= G_GUINT64_CONSTANT(10000)) return 5;
+ if (u >= G_GUINT64_CONSTANT(1000)) return 4;
+ if (u >= G_GUINT64_CONSTANT(100)) return 3;
+ if (u >= G_GUINT64_CONSTANT(10)) return 2;
+
+ return 1;
+}
+
+void
+guint64_to_str_buf(guint64 u, gchar *buf, int buf_len)
+{
+ int str_len = guint64_to_str_buf_len(u)+1;
+
+ gchar *bp = &buf[str_len];
+
+ if (buf_len < str_len) {
+ (void) g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
+ return;
+ }
+
+ *--bp = '\0';
+
+ uint64_to_str_back(bp, u);
+}
+
+/*
+ This function is very fast and this function is called a lot.
+ XXX update the address_to_str stuff to use this function.
+ */
+void
+ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
+{
+ register gchar const *p;
+ register gchar *b=buf;
+
+ if (buf_len < WS_INET_ADDRSTRLEN) {
+ (void) g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
+ return;
+ }
+
+ p=fast_strings[*ad++];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b++='.';
+
+ p=fast_strings[*ad++];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b++='.';
+
+ p=fast_strings[*ad++];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b++='.';
+
+ p=fast_strings[*ad];
+ do {
+ *b++=*p;
+ p++;
+ } while(*p);
+ *b=0;
+}
+
+int
+ip6_to_str_buf(const ws_in6_addr *addr, gchar *buf, int buf_size)
+{
+ gchar addr_buf[WS_INET6_ADDRSTRLEN];
+ int len;
+
+ /* slightly more efficient than ip6_to_str_buf_with_pfx(addr, buf, buf_size, NULL) */
+ len = (int)g_strlcpy(buf, ws_inet_ntop6(addr, addr_buf, sizeof(addr_buf)), buf_size); /* this returns len = strlen(addr_buf) */
+
+ if (len > buf_size - 1) { /* size minus nul terminator */
+ len = (int)g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_size); /* Let the unexpected value alert user */
+ }
+ return len;
+}
+
+int
+ip6_to_str_buf_with_pfx(const ws_in6_addr *addr, gchar *buf, int buf_size, const char *prefix)
+{
+ int bytes; /* the number of bytes which would be produced if the buffer was large enough. */
+ gchar addr_buf[WS_INET6_ADDRSTRLEN];
+ int len;
+
+ if (prefix == NULL)
+ prefix = "";
+ bytes = g_snprintf(buf, buf_size, "%s%s", prefix, ws_inet_ntop6(addr, addr_buf, sizeof(addr_buf)));
+ len = bytes - 1;
+
+ if (len > buf_size - 1) { /* size minus nul terminator */
+ len = (int)g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_size); /* Let the unexpected value alert user */
+ }
+ return len;
+}
+
+gchar *
+ipxnet_to_str_punct(wmem_allocator_t *allocator, const guint32 ad, const char punct)
+{
+ gchar *buf = (gchar *)wmem_alloc(allocator, 12);
+
+ *dword_to_hex_punct(buf, ad, punct) = '\0';
+ return buf;
+}
+
+#define WS_EUI64_STRLEN 24
+
+gchar *
+eui64_to_str(wmem_allocator_t *scope, const guint64 ad) {
+ gchar *buf, *tmp;
+ guint8 *p_eui64;
+
+ p_eui64=(guint8 *)wmem_alloc(NULL, 8);
+ buf=(gchar *)wmem_alloc(scope, WS_EUI64_STRLEN);
+
+ /* Copy and convert the address to network byte order. */
+ *(guint64 *)(void *)(p_eui64) = pntoh64(&(ad));
+
+ tmp = bytes_to_hexstr_punct(buf, p_eui64, 8, ':');
+ *tmp = '\0'; /* NULL terminate */
+ wmem_free(NULL, p_eui64);
+ return buf;
+}
+
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
diff --git a/wsutil/to_str.h b/wsutil/to_str.h
index 0ad18b972d..d43141dc7c 100644
--- a/wsutil/to_str.h
+++ b/wsutil/to_str.h
@@ -15,6 +15,7 @@
#include <ws_symbol_export.h>
#include <wsutil/wmem/wmem.h>
+#include <wsutil/inet_ipv6.h>
#ifdef __cplusplus
extern "C" {
@@ -279,6 +280,22 @@ WS_DLL_PUBLIC char *int_to_str_back(char *ptr, gint32 value);
*/
WS_DLL_PUBLIC char *int64_to_str_back(char *ptr, gint64 value);
+WS_DLL_PUBLIC void guint32_to_str_buf(guint32 u, gchar *buf, int buf_len);
+
+WS_DLL_PUBLIC void guint64_to_str_buf(guint64 u, gchar *buf, int buf_len);
+
+WS_DLL_PUBLIC void ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len);
+
+/* Returns length of the result. */
+WS_DLL_PUBLIC int ip6_to_str_buf(const ws_in6_addr *ad, gchar *buf, int buf_size);
+
+/* Returns length of the result. Takes a prefix to be inserted before the address. */
+WS_DLL_PUBLIC int ip6_to_str_buf_with_pfx(const ws_in6_addr *ad, gchar *buf, int buf_size, const char *prefix);
+
+WS_DLL_PUBLIC gchar *ipxnet_to_str_punct(wmem_allocator_t *scope, const guint32 ad, const char punct);
+
+WS_DLL_PUBLIC gchar *eui64_to_str(wmem_allocator_t *scope, const guint64 ad);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */