src/GuileHandler.h
branchv_0
changeset 1 9179406ab3b3
parent 0 f36bf14d45cb
child 2 7fb4d2c70e8c
equal deleted inserted replaced
0:f36bf14d45cb 1:9179406ab3b3
    24 #include <sstream>
    24 #include <sstream>
    25 #include <locale>
    25 #include <locale>
    26 #include <codecvt>
    26 #include <codecvt>
    27 #include <regex>
    27 #include <regex>
    28 
    28 
       
    29 #include <libguile.h>
       
    30 
    29 #include <relpipe/reader/typedefs.h>
    31 #include <relpipe/reader/typedefs.h>
    30 #include <relpipe/reader/TypeId.h>
    32 #include <relpipe/reader/TypeId.h>
    31 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
    33 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
    32 #include <relpipe/reader/handlers/AttributeMetadata.h>
    34 #include <relpipe/reader/handlers/AttributeMetadata.h>
    33 
    35 
    44 using namespace relpipe::reader;
    46 using namespace relpipe::reader;
    45 using namespace relpipe::reader::handlers;
    47 using namespace relpipe::reader::handlers;
    46 
    48 
    47 class GuileHandler : public RelationalReaderStringHadler {
    49 class GuileHandler : public RelationalReaderStringHadler {
    48 private:
    50 private:
       
    51 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
       
    52 
    49 	shared_ptr<writer::RelationalWriter> relationalWriter;
    53 	shared_ptr<writer::RelationalWriter> relationalWriter;
    50 
    54 
    51 	wregex relationNameRegEx;
    55 	wregex relationNameRegEx;
    52 
    56 
    53 	vector<AttributeMetadata> currentMetadata;
    57 	vector<AttributeMetadata> currentMetadata;
    54 	vector<string_t> currentRecord;
    58 	vector<string_t> currentRecord;
    55 	integer_t currentAttributeIndex = 0;
    59 	integer_t currentAttributeIndex = 0;
    56 	boolean_t includeCurrentRecord = false;
    60 	boolean_t includeCurrentRecord = false;
    57 	boolean_t filterCurrentRelation = false;
    61 	boolean_t filterCurrentRelation = false;
       
    62 	string_t guileCode;
       
    63 
       
    64 	SCM toGuileSymbol(const string_t& name) {
       
    65 		return scm_string_to_symbol(scm_from_locale_string(convertor.to_bytes(name).c_str()));
       
    66 	}
       
    67 
       
    68 	SCM toGuileString(const string_t& value) {
       
    69 		return scm_from_locale_string(convertor.to_bytes(value).c_str());
       
    70 	}
       
    71 	
       
    72 	SCM toGuileInteger(const string_t& value) {
       
    73 		return scm_from_uint64(stoul(value));
       
    74 	}
       
    75 	
       
    76 	SCM toGuileBoolean(const string_t& value) {
       
    77 		return value == L"true" ? SCM_BOOL_T : SCM_BOOL_F;
       
    78 	}
       
    79 
       
    80 	void defineGuileVariable(const string_t& name, TypeId type, const string_t& value) {
       
    81 		// TODO: RelationalReaderValueHadler?
       
    82 		switch (type) {
       
    83 			case TypeId::BOOLEAN:
       
    84 				scm_define(toGuileSymbol(name), toGuileBoolean(value));
       
    85 				break;
       
    86 			case TypeId::INTEGER:
       
    87 				scm_define(toGuileSymbol(name), toGuileInteger(value));
       
    88 				break;
       
    89 			case TypeId::STRING:
       
    90 				scm_define(toGuileSymbol(name), toGuileString(value));
       
    91 				break;
       
    92 			default:
       
    93 				throw cli::RelpipeCLIException(L"Unsupported type in defineGuileVariable()", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR);
       
    94 		}
       
    95 	}
       
    96 
       
    97 	void undefineGuileVariable(const string_t& name, TypeId type, const string_t& value) {
       
    98 		scm_define(toGuileSymbol(name), scm_make_undefined_variable()); // undefined != (define n)
       
    99 	}
    58 
   100 
    59 public:
   101 public:
    60 
   102 
    61 	GuileHandler(ostream& output, const vector<string_t>& arguments) {
   103 	GuileHandler(ostream& output, const vector<string_t>& arguments) {
    62 		relationalWriter.reset(writer::Factory::create(output));
   104 		relationalWriter.reset(writer::Factory::create(output));
    63 
   105 
    64 		// TODO: options and parser
   106 		// TODO: options and parser
    65 		if (arguments.size() == 1) {
   107 		if (arguments.size() == 2) {
    66 			relationNameRegEx = wregex(arguments[0]);
   108 			relationNameRegEx = wregex(arguments[0]);
       
   109 			guileCode = arguments[1];
    67 		} else {
   110 		} else {
    68 			throw cli::RelpipeCLIException(L"Usage: relpipe-tr-guile <relationNameRegExp>", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
   111 			throw cli::RelpipeCLIException(L"Usage: relpipe-tr-guile <relationNameRegExp>", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
    69 		}
   112 		}
    70 	}
   113 	}
    71 
   114 
    72 	void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
   115 	void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
    73 		currentMetadata = attributes;
   116 		currentMetadata = attributes;
    74 		// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
   117 		// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
    75 		vector<writer::AttributeMetadata> writerMetadata;
   118 		vector<writer::AttributeMetadata> writerMetadata;
    76 		for (AttributeMetadata readerMetadata : attributes) {
   119 		for (AttributeMetadata readerMetadata : attributes) {
       
   120 
    77 			writerMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
   121 			writerMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
    78 		}
   122 		}
    79 		
   123 
    80 		currentRecord.resize(attributes.size());
   124 		currentRecord.resize(attributes.size());
    81 		filterCurrentRelation = regex_match(name, relationNameRegEx);
   125 		filterCurrentRelation = regex_match(name, relationNameRegEx);
    82 
   126 
    83 		relationalWriter->startRelation(name, writerMetadata, true);
   127 		relationalWriter->startRelation(name, writerMetadata, true);
    84 	}
   128 	}
    87 		if (filterCurrentRelation) {
   131 		if (filterCurrentRelation) {
    88 			// TODO: evaluate condition and updates in Guile
   132 			// TODO: evaluate condition and updates in Guile
    89 			currentRecord[currentAttributeIndex] = value;
   133 			currentRecord[currentAttributeIndex] = value;
    90 			includeCurrentRecord = false;
   134 			includeCurrentRecord = false;
    91 
   135 
       
   136 			// TODO: remove, just a demo code
       
   137 			defineGuileVariable(L"hello", TypeId::STRING, L"world");
       
   138 			defineGuileVariable(L"a", TypeId::INTEGER, L"123");
       
   139 			defineGuileVariable(L"b", TypeId::INTEGER, L"456");
       
   140 			defineGuileVariable(L"tr", TypeId::BOOLEAN, L"true");
       
   141 			defineGuileVariable(L"fa", TypeId::BOOLEAN, L"false");
       
   142 
       
   143 			//integer_t guileResult = scm_to_uint64(scm_eval_string(toGuileString(guileCode)));
       
   144 			//std::wcerr << "result from Guile: " << guileResult << std::endl;
       
   145 			
       
   146 			includeCurrentRecord = scm_to_bool(scm_eval_string(toGuileString(guileCode)));
       
   147 			//scm_shell(0, nullptr);
       
   148 			// --------
       
   149 			
       
   150 
    92 			currentAttributeIndex++;
   151 			currentAttributeIndex++;
    93 
   152 
    94 			if (currentAttributeIndex > 0 && currentAttributeIndex % currentMetadata.size() == 0) {
   153 			if (currentAttributeIndex > 0 && currentAttributeIndex % currentMetadata.size() == 0) {
    95 				if (includeCurrentRecord) for (string_t v : currentRecord) relationalWriter->writeAttribute(v);
   154 				if (includeCurrentRecord) for (string_t v : currentRecord) relationalWriter->writeAttribute(v);
    96 				includeCurrentRecord = false;
   155 				includeCurrentRecord = false;
    97 			}
   156 			}
    98 
   157 
    99 			currentAttributeIndex = currentAttributeIndex % currentMetadata.size();
   158 			currentAttributeIndex = currentAttributeIndex % currentMetadata.size();
   100 		} else {
   159 		} else {
       
   160 
   101 			relationalWriter->writeAttribute(value);
   161 			relationalWriter->writeAttribute(value);
   102 		}
   162 		}
   103 	}
   163 	}
   104 
   164 
   105 	void endOfPipe() {
   165 	void endOfPipe() {