This patch add the for_each_line macro based on a strline_r()
function (similar to strtok_r()), that is also part of this patch.
This strline_r() function is tolerant with respect to line endings,
it supports CR-only, CRLF, and LF-only and any combinations thereof
(note that a CRLF is always detected as a single line break).

Similar to for_each_non_empty_line (the former for_each_line) where
the 'save' pointer needed to be initialised by a call to strtok_r(),
the new for_each_line macro expects, that the 'save' pointer has been
initialised by a call to strline_r(). Also note, that
for_each_line/strline_r and for_each_non_empty_line/strtok_r may use
the 'save' pointer differently, so calls to them can not be mixed.

Sponsored-by: On-Waves ehf
---
 openbsc/src/libmgcp/mgcp_protocol.c |   32 ++++++++++++++++++++++++++++++++
 openbsc/tests/mgcp/mgcp_test.c      |   35 +++++++++++++++++++++++++++++++++++
 openbsc/tests/mgcp/mgcp_test.ok     |   13 +++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/openbsc/src/libmgcp/mgcp_protocol.c 
b/openbsc/src/libmgcp/mgcp_protocol.c
index c040ab1..19a6f53 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -40,6 +40,38 @@
        for (line = strtok_r(NULL, "\r\n", &save); line;\
             line = strtok_r(NULL, "\r\n", &save))
 
+#define for_each_line(line, save)                      \
+       for (line = strline_r(NULL, &save); line;\
+            line = strline_r(NULL, &save))
+
+char *strline_r(char *str, char **saveptr)
+{
+       char *result;
+
+       if (str)
+               *saveptr = str;
+
+       result = *saveptr;
+
+       if (*saveptr != NULL) {
+               *saveptr = strpbrk(*saveptr, "\r\n");
+
+               if (*saveptr != NULL) {
+                       char *eos = *saveptr;
+
+                       if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
+                               (*saveptr)++;
+                       (*saveptr)++;
+                       if ((*saveptr)[0] == '\0')
+                               *saveptr = NULL;
+
+                       *eos = '\0';
+               }
+       }
+
+       return result;
+}
+
 /* Assume audio frame length of 20ms */
 #define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 #define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index d36aaa8..362f029 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -25,6 +25,40 @@
 #include <string.h>
 #include <limits.h>
 
+char *strline_r(char *str, char **saveptr);
+
+const char *strline_test_data =
+    "one CR\r"
+    "two CR\r"
+    "\r"
+    "one CRLF\r\n"
+    "two CRLF\r\n"
+    "\r\n"
+    "one LF\n"
+    "two LF\n"
+    "\n"
+    "mixed (4 lines)\r\r\n\n\r\n";
+
+#define EXPECTED_NUMBER_OF_LINES 13
+
+static void test_strline(void)
+{
+       char *save = NULL;
+       char *line;
+       char buf[2048];
+       int counter = 0;
+
+       strncpy(buf, strline_test_data, sizeof(buf));
+
+       for (line = strline_r(buf, &save); line;
+            line = strline_r(NULL, &save)) {
+               printf("line: '%s'\n", line);
+               counter++;
+       }
+
+       OSMO_ASSERT(counter == EXPECTED_NUMBER_OF_LINES);
+}
+
 #define AUEP1  "AUEP 158663169 ds/e1-1/[email protected] MGCP 1.0\r\n"
 #define AUEP1_RET "200 158663169 OK\r\n"
 #define AUEP2  "AUEP 18983213 ds/e1-2/[email protected] MGCP 1.0\r\n"
@@ -463,6 +497,7 @@ int main(int argc, char **argv)
 {
        osmo_init_logging(&log_info);
 
+       test_strline();
        test_messages();
        test_retransmission();
        test_packet_loss_calc();
diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok
index 5666424..429e0df 100644
--- a/openbsc/tests/mgcp/mgcp_test.ok
+++ b/openbsc/tests/mgcp/mgcp_test.ok
@@ -1,3 +1,16 @@
+line: 'one CR'
+line: 'two CR'
+line: ''
+line: 'one CRLF'
+line: 'two CRLF'
+line: ''
+line: 'one LF'
+line: 'two LF'
+line: ''
+line: 'mixed (4 lines)'
+line: ''
+line: ''
+line: ''
 Testing AUEP1
 Testing AUEP2
 Testing MDCX1
-- 
1.7.9.5


Reply via email to