src/lib/INIReader.cpp
branchv_0
changeset 28 596a724fbb83
parent 27 e9aad9dd823a
child 34 7eb3dcacba7b
equal deleted inserted replaced
27:e9aad9dd823a 28:596a724fbb83
    19 #include <regex>
    19 #include <regex>
    20 #include <sstream>
    20 #include <sstream>
    21 #include <stdexcept>
    21 #include <stdexcept>
    22 
    22 
    23 #include "INIReader.h"
    23 #include "INIReader.h"
       
    24 #include "uri.h"
    24 
    25 
    25 namespace relpipe {
    26 namespace relpipe {
    26 namespace in {
    27 namespace in {
    27 namespace ini {
    28 namespace ini {
    28 namespace lib {
    29 namespace lib {
    42 		}
    43 		}
    43 
    44 
    44 	};
    45 	};
    45 
    46 
    46 	std::vector<ConfiguredUnescapingProcessor> unescapingProcessors;
    47 	std::vector<ConfiguredUnescapingProcessor> unescapingProcessors;
       
    48 
       
    49 	class ConfiguredDialect {
       
    50 	public:
       
    51 		std::shared_ptr<Dialect> dialect;
       
    52 		const std::string uri;
       
    53 
       
    54 		ConfiguredDialect(std::shared_ptr<Dialect> dialect, const std::string uri) : dialect(dialect), uri(uri) {
       
    55 		}
       
    56 
       
    57 	};
       
    58 
       
    59 	std::vector<ConfiguredDialect> dialects;
    47 
    60 
    48 	/** 
    61 	/** 
    49 	 * By default, we ignore all leading whitespace on continuing lines.
    62 	 * By default, we ignore all leading whitespace on continuing lines.
    50 	 * If there should be some spaces or tabs, they should be placed on the previous line before the „\“.
    63 	 * If there should be some spaces or tabs, they should be placed on the previous line before the „\“.
    51 	 * If a line break is desired, it should be written as \n (escaped) or the value should be quoted in " or '.
    64 	 * If a line break is desired, it should be written as \n (escaped) or the value should be quoted in " or '.
   268 		if (value == "true") return true;
   281 		if (value == "true") return true;
   269 		else if (value == "false") return false;
   282 		else if (value == "false") return false;
   270 		else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
   283 		else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
   271 	}
   284 	}
   272 
   285 
   273 	void setDialect(const std::string& name) {
   286 	void setDialect(const std::string& uri) {
   274 		if (name == "default-ini") {
   287 		for (ConfiguredDialect& d : dialects) {
   275 			// already set
   288 			if (d.uri == uri) {
   276 		} else if (name == "java-properties") {
   289 				d.dialect->apply(*this);
   277 			trimLeadingSpacesOnContinuingLines = true;
   290 				return;
   278 			allowSections = false;
   291 			}
   279 			allowSectionTags = false;
   292 		}
   280 			allowSubKeys = false;
   293 		throw std::invalid_argument(std::string("Unsupported INI dialect: ") + uri);
   281 			commentSeparators = "#";
       
   282 			keyValueSeparators = "=:";
       
   283 			quotes = "";
       
   284 			// TODO: enable unicode unescaping
       
   285 		} else {
       
   286 			throw std::invalid_argument(std::string("Unsupported INI dialect: ") + name);
       
   287 		}
       
   288 	}
   294 	}
   289 
   295 
   290 	bool setUnescaping(const std::string& uri, const std::string& value) {
   296 	bool setUnescaping(const std::string& uri, const std::string& value) {
   291 		for (ConfiguredUnescapingProcessor& p : unescapingProcessors) {
   297 		for (ConfiguredUnescapingProcessor& p : unescapingProcessors) {
   292 			if (p.uri == uri) {
   298 			if (p.uri == uri) {
   301 
   307 
   302 	INIReaderImpl(std::istream& input) : input(input) {
   308 	INIReaderImpl(std::istream& input) : input(input) {
   303 	}
   309 	}
   304 
   310 
   305 	void setOption(const std::string& uri, const std::string& value) override {
   311 	void setOption(const std::string& uri, const std::string& value) override {
   306 		if (uri == "trim-continuing-lines") trimLeadingSpacesOnContinuingLines = parseBoolean(value); // TODO: continuing lines modes (enum), not just boolean
   312 		if (uri == option::TrimContinuingLines) trimLeadingSpacesOnContinuingLines = parseBoolean(value); // TODO: continuing lines modes (enum), not just boolean
   307 		else if (uri == "allow-sections") allowSections = parseBoolean(value);
   313 		else if (uri == option::AllowSections) allowSections = parseBoolean(value);
   308 		else if (uri == "allow-section-tags") allowSectionTags = parseBoolean(value);
   314 		else if (uri == option::AllowSectionTags) allowSectionTags = parseBoolean(value);
   309 		else if (uri == "allow-sub-keys") allowSubKeys = parseBoolean(value);
   315 		else if (uri == option::AllowSubKeys) allowSubKeys = parseBoolean(value);
   310 		else if (uri == "comment-separators") commentSeparators = value;
   316 		else if (uri == option::CommentSeparators) commentSeparators = value;
   311 		else if (uri == "key-value-separators") keyValueSeparators = value;
   317 		else if (uri == option::KeyValueSeparators) keyValueSeparators = value;
   312 		else if (uri == "quotes") quotes = value;
   318 		else if (uri == option::Quotes) quotes = value;
   313 		else if (uri == "dialect") setDialect(value);
   319 		else if (uri == option::Dialect) setDialect(value);
   314 		else if (setUnescaping(uri, value));
   320 		else if (setUnescaping(uri, value));
   315 		else throw std::invalid_argument(std::string("Invalid parser option: „") + uri + "“ with value: „" + value + "“");
   321 		else throw std::invalid_argument(std::string("Invalid parser option: „") + uri + "“ with value: „" + value + "“");
   316 	}
   322 	}
   317 
   323 
   318 	void addHandler(INIContentHandler* handler) override {
   324 	void addHandler(INIContentHandler* handler) override {
   319 		handlers.push_back(handler);
   325 		handlers.push_back(handler);
   320 	}
   326 	}
   321 
   327 
   322 	void addUnescapingProcessor(std::shared_ptr<UnescapingProcessor> processor, const std::string uri, bool enabledByDefault) override {
   328 	void addUnescapingProcessor(std::shared_ptr<UnescapingProcessor> processor, const std::string uri, bool enabledByDefault) override {
   323 		unescapingProcessors.push_back({processor, uri, enabledByDefault});
   329 		unescapingProcessors.push_back({processor, uri, enabledByDefault});
       
   330 	}
       
   331 
       
   332 	void addDialect(std::shared_ptr<Dialect> dialect, const std::string uri, bool enabledByDefault) override {
       
   333 		dialects.push_back({dialect, uri});
       
   334 		if (enabledByDefault) dialect->apply(*this);
   324 	}
   335 	}
   325 
   336 
   326 	void process() override {
   337 	void process() override {
   327 		for (INIContentHandler* handler : handlers) handler->startDocument();
   338 		for (INIContentHandler* handler : handlers) handler->startDocument();
   328 
   339