convert data and metadata v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Wed, 23 Dec 2020 18:22:55 +0100
branchv_0
changeset 1 af15c47f77ae
parent 0 c52ca92aa593
child 2 6839c85a9621
convert data and metadata
src/YAMLHandler.h
--- a/src/YAMLHandler.h	Wed Dec 23 17:15:34 2020 +0100
+++ b/src/YAMLHandler.h	Wed Dec 23 18:22:55 2020 +0100
@@ -35,15 +35,31 @@
 
 class YAMLHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
 private:
+	const char ESC = '\\';
+	const char Q = '"';
 	std::ostream& output;
 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // we generate YAML always in UTF-8 like XML?
 	std::vector<relpipe::reader::handlers::AttributeMetadata> currentAttributes;
 	size_t currentAttributeIndex = 0;
+	bool firstRecord;
 
-	void writeYamlValue(const relpipe::common::type::StringX& value) {
-		// TODO: escaping
-		output << convertor.to_bytes(value);
+	std::string escape(const relpipe::common::type::StringX& value) {
+		std::stringstream result;
+		result.put(Q);
+		for (char ch : convertor.to_bytes(value)) {
+			if (ch == Q) result.put(ESC).put(ch);
+			else result.put(ch);
+		}
+		result.put(Q);
+		return result.str();
 	}
+
+	std::string indent(int level) {
+		std::stringstream result;
+		for (int i = 0; i < level; i++) result << "  ";
+		return result.str();
+	}
+
 public:
 
 	YAMLHandler(std::ostream& output) : output(output) {
@@ -51,16 +67,30 @@
 
 	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
 		currentAttributes = attributes;
+		currentAttributeIndex = 0;
+		output << escape(name);
+		output << ":" << std::endl;
+		output << indent(1) << R"("attribute-metadata":)" << std::endl;
+		for (auto am : attributes) output << indent(2) << R"(- "name": )" << escape(am.getAttributeName()) << std::endl << indent(2) << R"(  "type": )" << escape(am.getTypeName()) << std::endl;
+		firstRecord = true;
 	}
 
 	void attribute(const relpipe::common::type::StringX& value) override {
+		if (firstRecord) {
+			output << indent(1) << R"("record":)" << std::endl;
+			firstRecord = false;
+		}
+
 		if (currentAttributeIndex % currentAttributes.size() == 0) {
 			currentAttributeIndex = 0;
-			
+			output << indent(2) << "- ";
 		} else {
-			
+			output << indent(2) << "  ";
 		}
 
+		output << escape(currentAttributes[currentAttributeIndex].getAttributeName()) << ": ";
+		output << escape(value) << std::endl;
+
 		currentAttributeIndex++;
 	}