streamlet-examples/streamlet-common.h
branchv_0
changeset 67 0766d298eb1c
parent 66 8a8b6434e4bb
child 69 52f837fbb216
equal deleted inserted replaced
66:8a8b6434e4bb 67:0766d298eb1c
    21 #include <vector>
    21 #include <vector>
    22 #include <string>
    22 #include <string>
    23 #include <sstream>
    23 #include <sstream>
    24 #include <codecvt>
    24 #include <codecvt>
    25 #include <locale>
    25 #include <locale>
       
    26 #include <regex>
    26 
    27 
    27 #include "../src/StreamletMsg.h"
    28 #include "../src/StreamletMsg.h"
    28 
    29 
    29 /**
    30 /**
    30  * Unlike the protocol and the message format,
    31  * Unlike the protocol and the message format,
    34  */
    35  */
    35 
    36 
    36 using S = relpipe::in::filesystem::StreamletMsg;
    37 using S = relpipe::in::filesystem::StreamletMsg;
    37 
    38 
    38 class Streamlet {
    39 class Streamlet {
    39 private:
    40 protected:
    40 
    41 
    41 	class Message {
    42 	class Message {
    42 	public:
    43 	public:
    43 		int code;
    44 		int code;
    44 		std::vector<std::wstring> parameters;
    45 		std::vector<std::wstring> parameters;
    56 		}
    57 		}
    57 
    58 
    58 		Message(int code, std::wstring p1, std::wstring p2) : code(code), parameters({p1, p2}) {
    59 		Message(int code, std::wstring p1, std::wstring p2) : code(code), parameters({p1, p2}) {
    59 		}
    60 		}
    60 	};
    61 	};
       
    62 
       
    63 private:
    61 
    64 
    62 	static const char SEPARATOR = '\0';
    65 	static const char SEPARATOR = '\0';
    63 
    66 
    64 	int readInt() {
    67 	int readInt() {
    65 		return std::stoi(readString());
    68 		return std::stoi(readString());
    89 		Message m;
    92 		Message m;
    90 		m.code = readInt();
    93 		m.code = readInt();
    91 		int count = readInt();
    94 		int count = readInt();
    92 		for (int i = 0; i < count; i++) m.parameters.push_back(readString());
    95 		for (int i = 0; i < count; i++) m.parameters.push_back(readString());
    93 		return m;
    96 		return m;
       
    97 	}
       
    98 
       
    99 	/**
       
   100 	 * The std::wsmatch contains only references to original string,
       
   101 	 * so we need to copy it in order to make it persistent and independent from variables that may evaporate.
       
   102 	 */
       
   103 	void copyMatches(std::wsmatch& source, std::vector<std::wstring>& destination) {
       
   104 		for (std::wstring s : source) destination.emplace_back(s);
    94 	}
   105 	}
    95 
   106 
    96 	void processMessages() {
   107 	void processMessages() {
    97 		while (true) {
   108 		while (true) {
    98 			Message m = read();
   109 			Message m = read();
   126 
   137 
   127 	class Option {
   138 	class Option {
   128 	public:
   139 	public:
   129 		std::wstring name;
   140 		std::wstring name;
   130 		std::wstring value;
   141 		std::wstring value;
       
   142 		std::vector<std::wstring> nameMatch;
       
   143 		std::vector<std::wstring> valueMatch;
       
   144 
       
   145 		Option(std::wstring name, std::wstring value) : name(name), value(value) {
       
   146 		}
   131 	};
   147 	};
   132 
   148 
   133 	std::vector<std::wstring> versionsSupported;
   149 	std::vector<std::wstring> versionsSupported;
   134 	std::vector<AttributeMetadata> inputAttributes;
   150 	std::vector<AttributeMetadata> inputAttributes;
   135 	std::vector<std::wstring> outputAttributeAliases;
   151 	std::vector<std::wstring> outputAttributeAliases;
   199 	virtual std::wstring getAlias(int index, const std::wstring& defaultValue) {
   215 	virtual std::wstring getAlias(int index, const std::wstring& defaultValue) {
   200 		if (outputAttributeAliases.size() > index) return outputAttributeAliases[index];
   216 		if (outputAttributeAliases.size() > index) return outputAttributeAliases[index];
   201 		else return defaultValue;
   217 		else return defaultValue;
   202 	}
   218 	}
   203 
   219 
       
   220 	virtual std::vector<Option> getOptions(std::wstring name) {
       
   221 		std::vector<Option> result;
       
   222 		for (Option o : options) if (o.name == name) result.push_back(o);
       
   223 		return result;
       
   224 	}
       
   225 
       
   226 	virtual std::vector<Option> getOptions(std::wregex namePattern) {
       
   227 		std::vector<Option> result;
       
   228 		std::wsmatch nameMatch;
       
   229 		for (Option o : options) if (std::regex_match(o.name, nameMatch, namePattern)) {
       
   230 				copyMatches(nameMatch, o.nameMatch);
       
   231 				result.push_back(o);
       
   232 			}
       
   233 		return result;
       
   234 	}
       
   235 
       
   236 	virtual std::vector<Option> getOptions(std::wregex namePattern, std::wregex valuePattern) {
       
   237 		// TODO: support multiple modes: 
       
   238 		//   a) throw an exception if valuePattern does not match
       
   239 		//   b) return option even if valuePattern does not match (valueMatch will be empty)
       
   240 		//   c) skip options with value not matching (current behavior)
       
   241 		std::wsmatch nameMatch;
       
   242 		std::wsmatch valueMatch;
       
   243 		std::vector<Option> result;
       
   244 		for (Option o : options) if (std::regex_match(o.name, nameMatch, namePattern) && std::regex_match(o.value, valueMatch, valuePattern)) {
       
   245 				copyMatches(nameMatch, o.nameMatch);
       
   246 				copyMatches(valueMatch, o.valueMatch);
       
   247 				result.push_back(o);
       
   248 			}
       
   249 		return result;
       
   250 	}
       
   251 
   204 	virtual std::vector<AttributeMetadata> getOutputAttributesMetadata() = 0;
   252 	virtual std::vector<AttributeMetadata> getOutputAttributesMetadata() = 0;
   205 	virtual std::vector<OutputAttribute> getOutputAttributes() = 0;
   253 	virtual std::vector<OutputAttribute> getOutputAttributes() = 0;
   206 
   254 
   207 public:
   255 public:
   208 
   256 
   211 
   259 
   212 	int run() {
   260 	int run() {
   213 		try {
   261 		try {
   214 			processMessages();
   262 			processMessages();
   215 			return 0;
   263 			return 0;
       
   264 		} catch (std::exception& e) {
       
   265 			write({S::STREAMLET_ERROR, L"xxxx", L"Exception in streamlet: " + convertor.from_bytes(e.what())}); // FIXME: correct error codes
       
   266 			return 1;
   216 		} catch (...) {
   267 		} catch (...) {
       
   268 			write({S::STREAMLET_ERROR, L"xxxx", L"Unknown exception in streamlet."}); // FIXME: correct error codes
   217 			return 1;
   269 			return 1;
   218 		}
   270 		}
   219 	}
   271 	}
   220 };
   272 };
   221 
   273 
   223 const std::wstring Streamlet::INTEGER = L"integer";
   275 const std::wstring Streamlet::INTEGER = L"integer";
   224 const std::wstring Streamlet::STRING = L"string";
   276 const std::wstring Streamlet::STRING = L"string";
   225 
   277 
   226 #define STREAMLET_RUN(clazz) \
   278 #define STREAMLET_RUN(clazz) \
   227 int main(int argc, char** argv) { \
   279 int main(int argc, char** argv) { \
       
   280 	setlocale(LC_ALL, ""); \
   228 	clazz s; \
   281 	clazz s; \
   229 	return s.run(); \
   282 	return s.run(); \
   230 }
   283 }