OSDN Git Service

copy httpheaderlexer from bchan.
authorornse01 <ornse01@users.sourceforge.jp>
Mon, 9 Jan 2012 08:09:00 +0000 (08:09 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Mon, 9 Jan 2012 08:09:00 +0000 (08:09 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@335 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/http/http_headerlexer.c [new file with mode: 0644]
src/http/http_headerlexer.h [new file with mode: 0644]
src/http/test_http_headerlexer.c [new file with mode: 0644]

diff --git a/src/http/http_headerlexer.c b/src/http/http_headerlexer.c
new file mode 100644 (file)
index 0000000..72d6843
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * httpheaderlexer.c
+ *
+ * Copyright (c) 2011 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include    "httpheaderlexer.h"
+
+#include       <basic.h>
+#include       <bstdlib.h>
+#include       <bstdio.h>
+
+#ifdef BCHAN_CONFIG_DEBUG
+# define DP(arg) printf arg
+# define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
+#else
+# define DP(arg) /**/
+# define DP_ER(msg, err) /**/
+#endif
+
+#if 0
+#define DP_STATE(arg) printf arg
+#else
+#define DP_STATE(arg) /**/
+#endif
+
+EXPORT VOID httpheaderlexer_inputchar(httpheaderlexer_t *lexer, UB ch, HTTPHEADERLEXER_RESULT_T *result)
+{
+       *result = HTTPHEADERLEXER_RESULT_NONE;
+
+       switch (lexer->state) {
+       case HTTPHEADERLEXER_STATE_SEARCH_HEADER:
+               DP_STATE(("state = SEARCH_HEADER: %c[%02x]\n", ch, ch));
+               if (ch == '\r') {
+                       lexer->state = HTTPHEADERLEXER_STATE_SEARCH_HEADER_CR;
+                       break;
+               }
+               if ((ch == ' ')&&(ch = '\t')) {
+                       lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE_LWS;
+                       *result = HTTPHEADERLEXER_RESULT_LWS;
+                       /* TODO: return value in "LWS CRLF LWS". */
+                       break;
+               }
+               /* TODO: handling error charactors for "token" */
+               lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDNAME;
+               *result = HTTPHEADERLEXER_RESULT_FIELDNAME;
+               break;
+       case HTTPHEADERLEXER_STATE_SEARCH_HEADER_CR:
+               DP_STATE(("state = SEARCH_HEADER_CR: %c[%02x]\n", ch, ch));
+               if (ch == '\n') {
+                       lexer->state = HTTPHEADERLEXER_STATE_READ_VALUE_MESSAGE;
+                       *result = HTTPHEADERLEXER_RESULT_MESSAGEHEADER_END;
+                       break;
+               }
+               /* TODO: below error case. */
+               if ((ch == ' ')&&(ch = '\t')) {
+                       lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE_LWS;
+                       *result = HTTPHEADERLEXER_RESULT_LWS;
+                       break;
+               }
+               lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDNAME;
+               *result = HTTPHEADERLEXER_RESULT_FIELDNAME;
+               break;
+       case HTTPHEADERLEXER_STATE_READ_HEADER_FIELDNAME:
+               DP_STATE(("state = READ_HEADER_FIELDNAME: %c[%02x]\n", ch, ch));
+               if (ch == '\r') {
+                       lexer->state = HTTPHEADERLEXER_STATE_HERDER_CR;
+                       break;
+               }
+               if (ch == ':') {
+                       lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE;
+                       *result = HTTPHEADERLEXER_RESULT_FIELDNAME_END;
+                       break;
+               }
+               /* TODO: handling error charactors for "token" */
+               *result = HTTPHEADERLEXER_RESULT_FIELDNAME;
+               break;
+       case HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE:
+               DP_STATE(("state = READ_HEADER_FIELDVALUE: %c[%02x]\n", ch, ch));
+               if (ch == '\r') {
+                       lexer->state = HTTPHEADERLEXER_STATE_HERDER_CR;
+                       break;
+               }
+               if ((ch == ' ')&&(ch = '\t')) {
+                       lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE_LWS;
+                       *result = HTTPHEADERLEXER_RESULT_LWS;
+                       break;
+               }
+               *result = HTTPHEADERLEXER_RESULT_FIELDCONTENT;
+               break;
+       case HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE_LWS:
+               DP_STATE(("state = READ_HEADER_FIELDVALUE_LWS: %c[%02x]\n", ch, ch));
+               if (ch == '\r') {
+                       lexer->state = HTTPHEADERLEXER_STATE_HERDER_CR;
+                       break;
+               }
+               if ((ch != ' ')&&(ch != '\t')) {
+                       lexer->state = HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE;
+                       *result = HTTPHEADERLEXER_RESULT_FIELDCONTENT;
+                       break;
+               }
+               break;
+       case HTTPHEADERLEXER_STATE_HERDER_CR:
+               DP_STATE(("state = HERDER_CR: %c[%02x]\n", ch, ch));
+               if (ch == '\n') {
+                       lexer->state = HTTPHEADERLEXER_STATE_SEARCH_HEADER;
+               }
+               break;
+       case HTTPHEADERLEXER_STATE_READ_VALUE_MESSAGE:
+               DP_STATE(("state = READ_VALUE_MESSAGE: %c[%02x]\n", ch, ch));
+               break;
+       }
+       return;
+}
+
+EXPORT W httpheaderlexer_initialize(httpheaderlexer_t *lexer)
+{
+       lexer->state = HTTPHEADERLEXER_STATE_SEARCH_HEADER;
+       return 0;
+}
+
+EXPORT VOID httpheaderlexer_finalize(httpheaderlexer_t *lexer)
+{
+}
diff --git a/src/http/http_headerlexer.h b/src/http/http_headerlexer.h
new file mode 100644 (file)
index 0000000..bd2067b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * httpheaderlexer.h
+ *
+ * Copyright (c) 2011 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include    <basic.h>
+
+#ifndef __HTTPHEADERLEXER_H__
+#define __HTTPHEADERLEXER_H__
+
+/* see rfc2616 4.2 Message Headers. */
+
+struct httpheaderlexer_t_ {
+       enum {
+               HTTPHEADERLEXER_STATE_SEARCH_HEADER,
+               HTTPHEADERLEXER_STATE_SEARCH_HEADER_CR,
+               HTTPHEADERLEXER_STATE_READ_HEADER_FIELDNAME,
+               HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE,
+               HTTPHEADERLEXER_STATE_READ_HEADER_FIELDVALUE_LWS,
+               HTTPHEADERLEXER_STATE_HERDER_CR,
+               HTTPHEADERLEXER_STATE_READ_VALUE_MESSAGE,
+       } state;
+};
+typedef struct httpheaderlexer_t_ httpheaderlexer_t;
+
+/* should implement field-value? but difficult. */
+enum HTTPHEADERLEXER_RESULT_T_ {
+       HTTPHEADERLEXER_RESULT_NONE,
+       HTTPHEADERLEXER_RESULT_FIELDNAME,
+       HTTPHEADERLEXER_RESULT_FIELDNAME_END,
+       HTTPHEADERLEXER_RESULT_FIELDCONTENT,
+       HTTPHEADERLEXER_RESULT_LWS,
+       HTTPHEADERLEXER_RESULT_MESSAGEHEADER_END,
+};
+typedef enum HTTPHEADERLEXER_RESULT_T_ HTTPHEADERLEXER_RESULT_T;
+
+IMPORT W httpheaderlexer_initialize(httpheaderlexer_t *lexer);
+IMPORT VOID httpheaderlexer_finalize(httpheaderlexer_t *lexer);
+IMPORT VOID httpheaderlexer_inputchar(httpheaderlexer_t *lexer, UB ch, HTTPHEADERLEXER_RESULT_T *result);
+
+#endif
diff --git a/src/http/test_http_headerlexer.c b/src/http/test_http_headerlexer.c
new file mode 100644 (file)
index 0000000..8c75f25
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * test_httpheaderlexer.c
+ *
+ * Copyright (c) 2011 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include    <btron/btron.h>
+#include    <bstdio.h>
+#include    <tcode.h>
+
+#include    "test.h"
+
+#include    "httpheaderlexer.h"
+
+LOCAL UB test_httpheaderlexer_testdata_01[] = {
+"ABCDEF: afgce\r
+BCDERF:   aaaa bbb \r
+XYZ:  qwer\r
+   AAA\r
+LMNOPQ: aaa\r
+\r
+AAABBBCCC
+DDDEEEFFF"
+};
+
+LOCAL TEST_RESULT test_httpheaderlexer_1()
+{
+       httpheaderlexer_t lexer;
+       W i,err,len;
+       HTTPHEADERLEXER_RESULT_T hr;
+
+       len = strlen(test_httpheaderlexer_testdata_01);
+
+       err = httpheaderlexer_initialize(&lexer);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+
+       for (i = 0; i < len; i++) {
+               httpheaderlexer_inputchar(&lexer, test_httpheaderlexer_testdata_01[i], &hr);
+               switch (hr) {
+               case HTTPHEADERLEXER_RESULT_NONE:
+                       printf("NONE\n");
+                       break;
+               case HTTPHEADERLEXER_RESULT_FIELDNAME:
+                       printf("FIELDNAME\n");
+                       break;
+               case HTTPHEADERLEXER_RESULT_FIELDNAME_END:
+                       printf("FIELDNAME_END\n");
+                       break;
+               case HTTPHEADERLEXER_RESULT_FIELDCONTENT:
+                       printf("FIELDCONTENT\n");
+                       break;
+               case HTTPHEADERLEXER_RESULT_LWS:
+                       printf("LWS\n");
+                       break;
+               case HTTPHEADERLEXER_RESULT_MESSAGEHEADER_END:
+                       printf("MESSAGEHEADER_END\n");
+                       break;
+               }
+       }
+
+       httpheaderlexer_finalize(&lexer);
+
+       return TEST_RESULT_PASS;
+}
+
+LOCAL TEST_RESULT test_httpheaderlexer_2()
+{
+       httpheaderlexer_t lexer;
+       W err;
+       HTTPHEADERLEXER_RESULT_T hr;
+       TEST_RESULT result = TEST_RESULT_PASS;
+
+#define check_result_2(info, e, r) \
+       if (e != r) { \
+               result = TEST_RESULT_FAIL; \
+               printf("test expected = %d, result = %d, fail = %s", e, r, info); \
+       }
+
+       err = httpheaderlexer_initialize(&lexer);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+
+       httpheaderlexer_inputchar(&lexer, 'A', &hr);
+       check_result_2("A", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'B', &hr);
+       check_result_2("B", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'C', &hr);
+       check_result_2("C", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, ':', &hr);
+       check_result_2(":", HTTPHEADERLEXER_RESULT_FIELDNAME_END, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_LWS, hr);
+       httpheaderlexer_inputchar(&lexer, 'a', &hr);
+       check_result_2("a", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'b', &hr);
+       check_result_2("b", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'c', &hr);
+       check_result_2("c", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, '\r', &hr);
+       check_result_2("[CR]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\n', &hr);
+       check_result_2("[LF]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, 'D', &hr);
+       check_result_2("D", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'E', &hr);
+       check_result_2("E", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'F', &hr);
+       check_result_2("F", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, ':', &hr);
+       check_result_2(":", HTTPHEADERLEXER_RESULT_FIELDNAME_END, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_LWS, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, 'a', &hr);
+       check_result_2("a", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_LWS, hr);
+       httpheaderlexer_inputchar(&lexer, 'b', &hr);
+       check_result_2("b", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'b', &hr);
+       check_result_2("b", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_LWS, hr);
+       httpheaderlexer_inputchar(&lexer, '\r', &hr);
+       check_result_2("[CR]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\n', &hr);
+       check_result_2("[LF]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, 'X', &hr);
+       check_result_2("X", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'Y', &hr);
+       check_result_2("Y", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'Z', &hr);
+       check_result_2("Z", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, ':', &hr);
+       check_result_2(":", HTTPHEADERLEXER_RESULT_FIELDNAME_END, hr);
+       httpheaderlexer_inputchar(&lexer, 'x', &hr);
+       check_result_2("x", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'y', &hr);
+       check_result_2("y", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'z', &hr);
+       check_result_2("z", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, '\r', &hr);
+       check_result_2("[CR]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\n', &hr);
+       check_result_2("[LF]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_LWS, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, 'A', &hr);
+       check_result_2("A", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'A', &hr);
+       check_result_2("A", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'A', &hr);
+       check_result_2("A", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, '\r', &hr);
+       check_result_2("[CR]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\n', &hr);
+       check_result_2("[LF]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, 'L', &hr);
+       check_result_2("L", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'M', &hr);
+       check_result_2("M", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, 'N', &hr);
+       check_result_2("N", HTTPHEADERLEXER_RESULT_FIELDNAME, hr);
+       httpheaderlexer_inputchar(&lexer, ':', &hr);
+       check_result_2(":", HTTPHEADERLEXER_RESULT_FIELDNAME_END, hr);
+       httpheaderlexer_inputchar(&lexer, ' ', &hr);
+       check_result_2("[SP]", HTTPHEADERLEXER_RESULT_LWS, hr);
+       httpheaderlexer_inputchar(&lexer, 'l', &hr);
+       check_result_2("l", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'm', &hr);
+       check_result_2("m", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, 'n', &hr);
+       check_result_2("n", HTTPHEADERLEXER_RESULT_FIELDCONTENT, hr);
+       httpheaderlexer_inputchar(&lexer, '\r', &hr);
+       check_result_2("[CR]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\n', &hr);
+       check_result_2("[LF]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\r', &hr);
+       check_result_2("[CR]", HTTPHEADERLEXER_RESULT_NONE, hr);
+       httpheaderlexer_inputchar(&lexer, '\n', &hr);
+       check_result_2("[LF]", HTTPHEADERLEXER_RESULT_MESSAGEHEADER_END, hr);
+
+       httpheaderlexer_finalize(&lexer);
+
+       return result;
+}
+
+LOCAL VOID test_httpheaderlexer_printresult(TEST_RESULT (*proc)(), B *test_name)
+{
+       TEST_RESULT result;
+
+       printf("test_httpheaderlexer: %s\n", test_name);
+       printf("---------------------------------------------\n");
+       result = proc();
+       if (result == TEST_RESULT_PASS) {
+               printf("--pass---------------------------------------\n");
+       } else {
+               printf("--fail---------------------------------------\n");
+       }
+       printf("---------------------------------------------\n");
+}
+
+EXPORT VOID test_httpheaderlexer_main()
+{
+       test_httpheaderlexer_printresult(test_httpheaderlexer_1, "test_httpheaderlexer_1");
+       test_httpheaderlexer_printresult(test_httpheaderlexer_2, "test_httpheaderlexer_2");
+}