From: ornse01 Date: Mon, 9 Jan 2012 08:09:00 +0000 (+0000) Subject: copy httpheaderlexer from bchan. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=3acaef9e75d0db10e4f47467662bd616c86bd3dc;p=bbk%2Fbchanf.git copy httpheaderlexer from bchan. git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@335 20a0b8eb-f62a-4a12-8fe1-b598822500fb --- diff --git a/src/http/http_headerlexer.c b/src/http/http_headerlexer.c new file mode 100644 index 0000000..72d6843 --- /dev/null +++ b/src/http/http_headerlexer.c @@ -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 +#include +#include + +#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 index 0000000..bd2067b --- /dev/null +++ b/src/http/http_headerlexer.h @@ -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 + +#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 index 0000000..8c75f25 --- /dev/null +++ b/src/http/test_http_headerlexer.c @@ -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 +#include +#include + +#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"); +}