common.c
changeset 8 4d38ccbeb93e
parent 2 69f8c0acaac7
child 11 082bfaf38cf0
--- a/common.c	Thu Jun 05 23:04:28 2008 +0300
+++ b/common.c	Fri Jun 06 03:24:22 2008 +0300
@@ -3,6 +3,7 @@
 #include <stdarg.h>
 #include <errno.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "common.h"
 
@@ -52,3 +53,98 @@
     fprintf(stderr, "\n");
     exit(EXIT_FAILURE);
 }
+
+int parse_hostport (char *hostport, char **host, char **port) {
+    char *c;
+
+    char brace = 0, colon = 0;
+
+    *host = *port = NULL;
+
+    for (c = hostport; *c != '\0'; c++) {
+        if (isspace(*c))
+            continue;
+
+        switch (*c) {
+            case '[':
+                if (c > hostport) {
+                    error("parse_hostport: %c must be first char, if any: %s", *c, hostport);
+                    return -1;
+                }
+                
+                brace = *c;
+                break;
+
+            case ']':
+                if (!brace) {
+                    error("parse_hostport: %c without matching brace: %s", *c, hostport);
+                    return -1;
+                }
+
+                if (!*host) {
+                    error("parse_hostport: empty hostname: %s", hostport);
+                    return -1;
+                }
+
+                brace = 0;
+                break;
+            
+            case ':':
+                if (brace) {
+                    // colons inside braces are left as-is
+                    continue;
+                }
+
+                if (!*host) {
+                    error("parse_hostport: colon before hostname: %s", hostport);
+                    return -1;
+                }
+
+                if (*port) {
+                    error("parse_hostport: colon after port: %s", hostport);
+                    return -1;
+                }
+
+                if (colon) {
+                    error("parse_hostport: too many colons: %s", hostport);
+                    return -1;
+                };
+
+                // finished parsing the host part, move on to the port part
+                colon = ':';
+                *c = '\0';
+                break;
+
+            default:
+                if (!*host) {
+                    // first char of the host
+                    *host = c;
+
+                } else if (colon && !*port) {
+                    // first char of the port
+                    *port = c;
+
+                } // else a part of either, don't care about it
+
+                break;
+        }
+    }
+
+    if (!*host) {
+        error("parse_hostport: missing hostname: %s", hostport);
+        return -1;
+    }
+
+    if (brace) {
+        error("parse_hostport: missing close-brace for %c: %s", brace, hostport);
+        return -1;
+    }
+
+    if (colon && !*port) {
+        error("parse_hostport: missing port: %s", hostport);
+        return -1;
+    }
+
+    return 0;
+}
+