summaryrefslogtreecommitdiff
path: root/chardev.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chardev.cpp')
-rw-r--r--chardev.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/chardev.cpp b/chardev.cpp
new file mode 100644
index 0000000..1d587b9
--- /dev/null
+++ b/chardev.cpp
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: Unlicense
+ */
+
+#include "chardev.hpp"
+
+#include <cstring>
+#include <cstdlib>
+
+static bool startsWith(const char* str, const char* pattern)
+{
+ const size_t pattern_len = strlen(pattern);
+ const size_t str_len = strlen(str);
+ if (str_len < pattern_len) {
+ return false;
+ }
+ return 0 == memcmp(str, pattern, pattern_len);
+}
+
+static CharDev parseTcp(const char* path)
+{
+ // We need to make sure there is at least one more ':' delimiter in the
+ // string
+ const char* rest = strchr(path + (sizeof "tcp:") - 1, ':');
+ if (rest == nullptr) {
+ return CharDev::Invalid(path);
+ }
+ const char* port_str;
+ // Find last ':' before string ends, i.e. when strchr returns NULL
+ do {
+ port_str = rest + 1;
+ rest = strchr(port_str, ':');
+ } while (rest);
+ const unsigned long port = strtoul(port_str, nullptr, 0);
+ if (port <= UINT16_MAX) {
+ path += (sizeof "tcp:") - 1;
+ return CharDev::Tcp(path, port_str - 1 - path, port);
+ }
+ return CharDev::Invalid(path);
+}
+
+CharDev CharDev::Parse(const char* path)
+{
+ if (0 == strcmp(path, "pty")) {
+ return CharDev::Pty();
+ }
+ if (startsWith(path, "tcp:")) {
+ return parseTcp(path);
+ }
+ return CharDev::Invalid(path);
+}