OSDN Git Service

implement lexer for 2ch bbs common data format.
authorornse01 <ornse01@users.sourceforge.jp>
Sun, 1 May 2011 09:32:43 +0000 (09:32 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Sun, 1 May 2011 09:32:43 +0000 (09:32 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchan/trunk@250 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/psvlexer.c [new file with mode: 0644]
src/psvlexer.h [new file with mode: 0644]
src/test_psvlexer.c [new file with mode: 0644]

diff --git a/src/psvlexer.c b/src/psvlexer.c
new file mode 100644 (file)
index 0000000..9639cb8
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * psvlexer.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    "psvlexer.h"
+
+#include       <basic.h>
+#include       <bstdio.h>
+#include       <bstring.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
+
+/* Parenthesis-Separeted Values */
+
+EXPORT VOID psvlexer_inputchar(psvlexer_t *lexer, UB *ch, W ch_len, psvlexer_result_t **result, W *result_len)
+{
+       switch (lexer->state) {
+       case PSVLEXER_STATE_READ_VALUE:
+               if ((ch[0] == '<')&&(ch_len == 1)) {
+                       lexer->state = PSVLEXER_STATE_LSTN;
+                       *result = NULL;
+                       *result_len = 0;
+               } else if ((ch[0] == '\n')&&(ch_len == 1)) {
+                       lexer->buffer[0].type = PSVLEXER_RESULT_FIELDEND;
+                       *result = lexer->buffer;
+                       *result_len = 1;
+               } else {
+                       lexer->buffer[0].type = PSVLEXER_RESULT_VALUE;
+                       memcpy(lexer->buffer[0].str, ch, ch_len);
+                       lexer->buffer[0].len = ch_len;
+                       *result = lexer->buffer;
+                       *result_len = 1;
+               }
+               break;
+       case PSVLEXER_STATE_LSTN:
+               if ((ch[0] == '>')&&(ch_len == 1)) {
+                       lexer->state = PSVLEXER_STATE_READ_VALUE;
+                       lexer->buffer[0].type = PSVLEXER_RESULT_SEPARATION;
+                       *result = lexer->buffer;
+                       *result_len = 1;
+               } else if ((ch[0] == '\n')&&(ch_len == 1)) {
+                       lexer->state = PSVLEXER_STATE_READ_VALUE;
+                       lexer->buffer[0].type = PSVLEXER_RESULT_VALUE;
+                       lexer->buffer[0].str[0] = '<';
+                       lexer->buffer[0].len = 1;
+                       lexer->buffer[1].type = PSVLEXER_RESULT_FIELDEND;
+                       *result = lexer->buffer;
+                       *result_len = 2;
+               } else if ((ch[0] == '<')&&(ch_len == 1)) {
+                       lexer->buffer[0].type = PSVLEXER_RESULT_VALUE;
+                       lexer->buffer[0].str[0] = '<';
+                       lexer->buffer[0].len = 1;
+                       *result = lexer->buffer;
+                       *result_len = 1;
+               } else {
+                       lexer->state = PSVLEXER_STATE_READ_VALUE;
+                       lexer->buffer[0].type = PSVLEXER_RESULT_VALUE;
+                       lexer->buffer[0].str[0] = '<';
+                       lexer->buffer[0].len = 1;
+                       lexer->buffer[1].type = PSVLEXER_RESULT_VALUE;
+                       memcpy(lexer->buffer[1].str, ch, ch_len);
+                       lexer->buffer[1].len = ch_len;
+                       *result = lexer->buffer;
+                       *result_len = 2;
+               }
+               break;
+       }
+}
+
+EXPORT VOID psvlexer_endinput(psvlexer_t *lexer, psvlexer_result_t **result, W *result_len)
+{
+       switch (lexer->state) {
+       case PSVLEXER_STATE_READ_VALUE:
+               lexer->buffer[0].type = PSVLEXER_RESULT_FIELDEND;
+               *result = lexer->buffer;
+               *result_len = 1;
+               break;
+       case PSVLEXER_STATE_LSTN:
+               lexer->state = PSVLEXER_STATE_READ_VALUE;
+               lexer->buffer[0].type = PSVLEXER_RESULT_VALUE;
+               lexer->buffer[0].str[0] = '<';
+               lexer->buffer[0].len = 1;
+               lexer->buffer[1].type = PSVLEXER_RESULT_FIELDEND;
+               *result = lexer->buffer;
+               *result_len = 2;
+               break;
+       }
+}
+
+EXPORT W psvlexer_initialize(psvlexer_t *lexer)
+{
+       lexer->state = PSVLEXER_STATE_READ_VALUE;
+       return 0;
+}
+
+EXPORT VOID psvlexer_finalize(psvlexer_t *lexer)
+{
+}
diff --git a/src/psvlexer.h b/src/psvlexer.h
new file mode 100644 (file)
index 0000000..3178e71
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * psvlexer.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 __PSVLEXER_H__
+#define __PSVLEXER_H__
+
+struct psvlexer_result_t_ {
+       enum {
+               PSVLEXER_RESULT_VALUE,
+               PSVLEXER_RESULT_SEPARATION,
+               PSVLEXER_RESULT_FIELDEND,
+               PSVLEXER_RESULT_ERROR,
+       } type;
+       UB str[2];
+       W len;
+};
+typedef struct psvlexer_result_t_ psvlexer_result_t;
+
+struct psvlexer_t_ {
+       enum {
+               PSVLEXER_STATE_READ_VALUE,
+               PSVLEXER_STATE_LSTN,
+       } state;
+        psvlexer_result_t buffer[2];
+};
+typedef struct psvlexer_t_ psvlexer_t;
+
+IMPORT W psvlexer_initialize(psvlexer_t *lexer);
+IMPORT VOID psvlexer_finalize(psvlexer_t *lexer);
+IMPORT VOID psvlexer_inputchar(psvlexer_t *lexer, UB *ch, W ch_len, psvlexer_result_t **result, W *result_len);
+IMPORT VOID psvlexer_endinput(psvlexer_t *lexer, psvlexer_result_t **result, W *result_len);
+
+#endif
diff --git a/src/test_psvlexer.c b/src/test_psvlexer.c
new file mode 100644 (file)
index 0000000..e1cc4af
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * test_psvlexer.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    <bstdlib.h>
+#include    <bstring.h>
+
+#include    "test.h"
+
+#include    "psvlexer.h"
+
+#if 0
+# define DUMP_RESULT(arg) printf arg
+#else
+# define DUMP_RESULT(arg) /**/
+#endif
+
+struct testpsvlexer_result_t_ {
+       UB *str;
+       W len;
+};
+typedef struct testpsvlexer_result_t_ testpsvlexer_result_t;
+
+LOCAL W testpsvlexer_result_append(testpsvlexer_result_t *testresult, UB *apd, W apd_len)
+{
+       UB *str;
+
+       str = realloc(testresult->str, testresult->len + apd_len + 1);
+       if (str == NULL) {
+               return -1;
+       }
+       testresult->str = str;
+
+       memcpy(testresult->str + testresult->len, apd, apd_len);
+       testresult->len += apd_len;
+       testresult->str[testresult->len] = '\0';
+
+       return 0;
+}
+
+LOCAL W testpsvlexer_result_inputresult(testpsvlexer_result_t *testresult, psvlexer_result_t *result)
+{
+       W i;
+
+       switch (result->type) {
+       case PSVLEXER_RESULT_VALUE:
+               DUMP_RESULT(("type = VALUE: "));
+               for (i = 0; i < result->len; i++) {
+                       DUMP_RESULT(("%c", result->str[i]));
+               }
+               DUMP_RESULT(("\n"));
+               return testpsvlexer_result_append(testresult, result->str, result->len);
+       case PSVLEXER_RESULT_SEPARATION:
+               DUMP_RESULT(("type = SEPARATION\n"));
+               return testpsvlexer_result_append(testresult, "<>", 2);
+       case PSVLEXER_RESULT_FIELDEND:
+               DUMP_RESULT(("type = FIELDEND\n"));
+               return testpsvlexer_result_append(testresult, "\n", 1);
+       case PSVLEXER_RESULT_ERROR:
+               DUMP_RESULT(("type = ERROR\n"));
+               return 0;
+       default:
+               DUMP_RESULT(("error type value\n"));
+               return 0;
+       }
+
+       return 0;
+}
+
+LOCAL W testpsvlexer_result_inputresultarray(testpsvlexer_result_t *testresult, psvlexer_result_t *result, W result_len)
+{
+       W i, err;
+       for (i = 0; i < result_len; i++) {
+               err = testpsvlexer_result_inputresult(testresult, result + i);
+               if (err < 0) {
+                       return err;
+               }
+       }
+       return 0;
+}
+
+LOCAL Bool testpsvlexer_result_compaire(testpsvlexer_result_t *testresult, UB *expected, W expected_len)
+{
+       if (testresult->len != expected_len) {
+               return False;
+       }
+       if (strncmp(testresult->str, expected, expected_len) != 0) {
+               return False;
+       }
+       return True;
+}
+
+LOCAL W testpsvlexer_result_initialize(testpsvlexer_result_t *testresult)
+{
+       testresult->str = malloc(sizeof(UB));
+       if (testresult->str == NULL) {
+               return -1;
+       }
+       testresult->str[0] = '\0';
+       testresult->len = 0;
+       return 0;
+}
+
+LOCAL VOID testpsvlexer_result_finalize(testpsvlexer_result_t *testresult)
+{
+       free(testresult->str);
+}
+
+LOCAL UB test_psvlexer_testdata01[] = "aaa<>bbb<>ccc<>\nddd<>eee<>fff\n";
+LOCAL UB test_psvlexer_testdata02[] = "<aa<>b<b<>cc<<>dd<\n";
+
+LOCAL TEST_RESULT test_psvlexer_common(UB *test, W test_len)
+{
+       psvlexer_t lexer;
+       psvlexer_result_t *result;
+       testpsvlexer_result_t testresult;
+       W i, err, result_len;
+       TEST_RESULT ret = TEST_RESULT_PASS;
+       Bool ok;
+
+       err = psvlexer_initialize(&lexer);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+
+       err = testpsvlexer_result_initialize(&testresult);
+       if (err < 0) {
+               psvlexer_finalize(&lexer);
+               return TEST_RESULT_FAIL;
+       }
+
+       for (i = 0; i < test_len; i++) {
+               psvlexer_inputchar(&lexer, test + i, 1, &result, &result_len);
+               err = testpsvlexer_result_inputresultarray(&testresult, result, result_len);
+               if (err < 0) {
+                       ret = TEST_RESULT_FAIL;
+               }
+       }
+       ok = testpsvlexer_result_compaire(&testresult, test, test_len);
+       if (ok == False) {
+               ret = TEST_RESULT_FAIL;
+       }
+
+       testpsvlexer_result_finalize(&testresult);
+       psvlexer_finalize(&lexer);
+
+       return ret;
+}
+
+LOCAL TEST_RESULT test_psvlexer_1()
+{
+       return test_psvlexer_common(test_psvlexer_testdata01, strlen(test_psvlexer_testdata01));
+}
+
+LOCAL TEST_RESULT test_psvlexer_2()
+{
+       return test_psvlexer_common(test_psvlexer_testdata02, strlen(test_psvlexer_testdata02));
+}
+
+LOCAL VOID test_psvlexer_printresult(TEST_RESULT (*proc)(), B *test_name)
+{
+       TEST_RESULT result;
+
+       printf("test_psvlexer: %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_psvlexer_main()
+{
+       test_psvlexer_printresult(test_psvlexer_1, "test_psvlexer_1");
+       test_psvlexer_printresult(test_psvlexer_2, "test_psvlexer_2");
+}