summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-10-31 15:37:45 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-10-31 15:37:45 +0100
commita2fb4bb24bc986988372e7a122660273578819b4 (patch)
tree56e9527f37be6c425dbd7f60ed5ea066a7a635ac /src
parent935d4a59bd44068c60f471f5cb336fc17f93b6dd (diff)
owfd: rtsp: add tokenizer
The tokenizer does what the name says: Split a line into tokens. This will be useful for more advanced header-lines where we need to split them up so we can parse them. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/rtsp.h4
-rw-r--r--src/rtsp_tokenizer.c176
2 files changed, 180 insertions, 0 deletions
diff --git a/src/rtsp.h b/src/rtsp.h
index 798b827..1ffcdc3 100644
--- a/src/rtsp.h
+++ b/src/rtsp.h
@@ -102,6 +102,10 @@ void owfd_rtsp_decoder_flush(struct owfd_rtsp_decoder *dec);
int owfd_rtsp_decoder_feed(struct owfd_rtsp_decoder *dec,
const char *buf, size_t len);
+/* rtsp tokenizer */
+
+ssize_t owfd_rtsp_tokenize(const char *line, char **out);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/rtsp_tokenizer.c b/src/rtsp_tokenizer.c
new file mode 100644
index 0000000..1f3b6a1
--- /dev/null
+++ b/src/rtsp_tokenizer.c
@@ -0,0 +1,176 @@
+/*
+ * OpenWFD - Open-Source Wifi-Display Implementation
+ *
+ * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "shared.h"
+#include "rtsp.h"
+
+ssize_t owfd_rtsp_tokenize(const char *line, char **out)
+{
+ char *t, *dst, c, prev, last_c;
+ const char *src;
+ size_t l, num, len;
+ bool quoted, escaped;
+
+ /* we need at most twice as much space for all the terminating 0s */
+ len = strlen(line);
+ l = len * 2 + 1;
+ if (l <= len)
+ return -ENOMEM;
+
+ t = malloc(l);
+ if (!t)
+ return -ENOMEM;
+
+ /* set t[0]=0 in case strlen(line)==0 */
+ *t = 0;
+
+ num = 0;
+ src = line;
+ dst = t;
+ quoted = 0;
+ escaped = 0;
+ prev = 0;
+ last_c = 0;
+
+ for ( ; *src; ++src) {
+ c = *src;
+ prev = last_c;
+ last_c = c;
+
+ if (quoted) {
+ if (escaped) {
+ if (c == '\\') {
+ *dst++ = '\\';
+ } else if (c == '"') {
+ *dst++ = '"';
+ } else if (c == 'n') {
+ *dst++ = '\n';
+ } else if (c == 'r') {
+ *dst++ = '\r';
+ } else if (c == 't') {
+ *dst++ = '\t';
+ } else if (c == 'a') {
+ *dst++ = '\a';
+ } else if (c == 'f') {
+ *dst++ = '\f';
+ } else if (c == 'v') {
+ *dst++ = '\v';
+ } else if (c == 'b') {
+ *dst++ = '\b';
+ } else if (c == 'e') {
+ *dst++ = 0x1b; /* ESC */
+ } else if (c == '0' || c == 0) {
+ /* drop binary zero escape "\0" */
+ --dst;
+ } else {
+ *dst++ = c;
+ }
+
+ escaped = 0;
+ } else {
+ if (c == '"') {
+ *dst++ = 0;
+ ++num;
+ quoted = 0;
+ last_c = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ } else if (c == 0) {
+ /* skip */
+ } else {
+ *dst++ = c;
+ }
+ }
+ } else {
+ if (c == '"') {
+ if (prev) {
+ *dst++ = 0;
+ ++num;
+ }
+
+ quoted = 1;
+ escaped = 0;
+ last_c = 0;
+ } else if (c == 0) {
+ /* skip */
+ } else if (c == ' ') {
+ if (prev) {
+ *dst++ = 0;
+ ++num;
+ }
+ last_c = 0;
+ } else if (c == '(' ||
+ c == ')' ||
+ c == '[' ||
+ c == ']' ||
+ c == '{' ||
+ c == '}' ||
+ c == '<' ||
+ c == '>' ||
+ c == '@' ||
+ c == ',' ||
+ c == ';' ||
+ c == ':' ||
+ c == '\\' ||
+ c == '/' ||
+ c == '?' ||
+ c == '=') {
+ if (prev) {
+ *dst++ = 0;
+ ++num;
+ }
+
+ *dst++ = c;
+ *dst++ = 0;
+ ++num;
+ last_c = 0;
+ } else if (c <= 31 || c == 127) {
+ /* ignore CTLs */
+ if (prev) {
+ *dst++ = 0;
+ ++num;
+ }
+ last_c = 0;
+ } else {
+ *dst++ = c;
+ }
+ }
+ }
+
+ prev = last_c;
+
+ if (prev) {
+ *dst++ = 0;
+ ++num;
+ }
+
+ *out = t;
+ return num;
+}