--- /dev/null
+/*
+ * 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)
+{
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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");
+}