src/YAMLCommand.h
branchv_0
changeset 1 8d2d8f4077af
parent 0 66a454290286
child 2 d68192f0e960
equal deleted inserted replaced
0:66a454290286 1:8d2d8f4077af
     1 /**
     1 /**
     2  * Relational pipes
     2  * Relational pipes
     3  * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
     3  * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
     4  *
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 3 of the License.
     7  * the Free Software Foundation, version 3 of the License.
     8  *
     8  *
    19 #include <cstdlib>
    19 #include <cstdlib>
    20 #include <iostream>
    20 #include <iostream>
    21 #include <memory>
    21 #include <memory>
    22 #include <vector>
    22 #include <vector>
    23 
    23 
       
    24 #include <yaml.h>
       
    25 
    24 #include <relpipe/writer/RelationalWriter.h>
    26 #include <relpipe/writer/RelationalWriter.h>
    25 #include <relpipe/writer/typedefs.h>
    27 #include <relpipe/writer/typedefs.h>
    26 
    28 
    27 namespace relpipe {
    29 namespace relpipe {
    28 namespace in {
    30 namespace in {
    30 
    32 
    31 class YAMLCommand {
    33 class YAMLCommand {
    32 private:
    34 private:
    33 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
    35 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
    34 
    36 
       
    37 	class YAMLEvent {
       
    38 	private:
       
    39 		yaml_event_t event;
       
    40 	public:
       
    41 
       
    42 		YAMLEvent(yaml_event_t event) : event(event) {
       
    43 		}
       
    44 
       
    45 		virtual ~YAMLEvent() {
       
    46 			yaml_event_delete(&event);
       
    47 		}
       
    48 
       
    49 		const yaml_event_type_t getType() const {
       
    50 			return event.type;
       
    51 		}
       
    52 
       
    53 		const yaml_event_t* getEvent() const {
       
    54 			return &event;
       
    55 		}
       
    56 
       
    57 		YAMLEvent(const YAMLEvent&) = delete;
       
    58 		YAMLEvent& operator=(const YAMLEvent&) = delete;
       
    59 	};
       
    60 
       
    61 	class YAMLParser {
       
    62 	private:
       
    63 		yaml_parser_t yamlParser;
       
    64 		std::istream* input = nullptr;
       
    65 
       
    66 		static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) {
       
    67 			std::istream* input = ((YAMLParser*) instance)->input;
       
    68 			input->read((char*) buffer, size);
       
    69 			*length = input->gcount();
       
    70 			return (input->good() || input->eof()) ? 1 : 0;
       
    71 		}
       
    72 	public:
       
    73 
       
    74 		YAMLParser() {
       
    75 			yaml_parser_initialize(&yamlParser);
       
    76 		}
       
    77 
       
    78 		virtual ~YAMLParser() {
       
    79 			yaml_parser_delete(&yamlParser);
       
    80 		}
       
    81 
       
    82 		YAMLParser(const YAMLParser&) = delete;
       
    83 		YAMLParser& operator=(const YAMLParser&) = delete;
       
    84 
       
    85 		void setInput(std::istream* input) {
       
    86 			this->input = input;
       
    87 			yaml_parser_set_input(&yamlParser, readFromInput, (void*) this);
       
    88 		}
       
    89 
       
    90 		YAMLEvent* next() {
       
    91 			yaml_event_t event;
       
    92 			int result = yaml_parser_parse(&yamlParser, &event);
       
    93 			return result == 1 && event.type != yaml_event_type_e::YAML_NO_EVENT ? new YAMLEvent(event) : nullptr; // 1 = OK in yaml.h; YAML_NO_EVENT = end
       
    94 		}
       
    95 	};
       
    96 
       
    97 	YAMLParser parser;
       
    98 
       
    99 	using YAMLEvent_p = std::shared_ptr<YAMLEvent>;
       
   100 
       
   101 	enum class Mode {
       
   102 		ROOT,
       
   103 		RELATIONS_SEQUENCE,
       
   104 		MAPPING,
       
   105 		MAP_KEY
       
   106 	};
       
   107 
       
   108 	std::vector<Mode> mode;
       
   109 
       
   110 	/**
       
   111 	 * Both YAML and XML strings are in UTF-8.
       
   112 	 */
       
   113 	const char* y2x(yaml_char_t* value) {
       
   114 		return value ? (const char*) value : "";
       
   115 	}
       
   116 
    35 public:
   117 public:
    36 
   118 
       
   119 	YAMLCommand() {
       
   120 	}
       
   121 
       
   122 	virtual ~YAMLCommand() {
       
   123 	}
       
   124 
    37 	void process(std::istream& input, std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
   125 	void process(std::istream& input, std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
       
   126 		parser.setInput(&input);
       
   127 
    38 		std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
   128 		std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
    39 		attributesMetadata.push_back(relpipe::writer::AttributeMetadata{L"todo", relpipe::writer::TypeId::STRING});
   129 		attributesMetadata.push_back(relpipe::writer::AttributeMetadata{L"todo", relpipe::writer::TypeId::STRING});
    40 		writer->startRelation(L"YAML", attributesMetadata, true);
   130 		writer->startRelation(L"YAML", attributesMetadata, true);
       
   131 
       
   132 		mode.push_back(Mode::ROOT);
       
   133 		std::string itemName;
       
   134 
       
   135 		writer->writeAttribute(L"before cycle");
       
   136 		for (YAMLEvent_p event = YAMLEvent_p(parser.next()); event; event = YAMLEvent_p(parser.next())) {
       
   137 
       
   138 			if (event->getType() == YAML_NO_EVENT) { writer->writeAttribute(L"YAML_NO_EVENT");
       
   139 			} else if (event->getType() == YAML_STREAM_START_EVENT) { writer->writeAttribute(L"YAML_STREAM_START_EVENT");
       
   140 			} else if (event->getType() == YAML_STREAM_END_EVENT) { writer->writeAttribute(L"YAML_STREAM_END_EVENT");
       
   141 			} else if (event->getType() == YAML_DOCUMENT_START_EVENT) { writer->writeAttribute(L"YAML_DOCUMENT_START_EVENT");
       
   142 			} else if (event->getType() == YAML_DOCUMENT_END_EVENT) { writer->writeAttribute(L"YAML_DOCUMENT_END_EVENT");
       
   143 			} else if (event->getType() == YAML_ALIAS_EVENT) { writer->writeAttribute(L"YAML_ALIAS_EVENT");
       
   144 			} else if (event->getType() == YAML_SCALAR_EVENT) { writer->writeAttribute(L"YAML_SCALAR_EVENT");
       
   145 			} else if (event->getType() == YAML_SEQUENCE_START_EVENT) { writer->writeAttribute(L"YAML_SEQUENCE_START_EVENT");
       
   146 			} else if (event->getType() == YAML_SEQUENCE_END_EVENT) { writer->writeAttribute(L"YAML_SEQUENCE_END_EVENT");
       
   147 			} else if (event->getType() == YAML_MAPPING_START_EVENT) { writer->writeAttribute(L"YAML_MAPPING_START_EVENT");
       
   148 			} else if (event->getType() == YAML_MAPPING_END_EVENT) { writer->writeAttribute(L"YAML_MAPPING_END_EVENT");
       
   149 			} else { writer->writeAttribute(L"else???");
       
   150 				// TODO: unsupported type?
       
   151 			}
       
   152 		}
       
   153 		writer->writeAttribute(L"after cycle");
    41 	}
   154 	}
    42 };
   155 };
    43 
   156 
    44 }
   157 }
    45 }
   158 }