src/lib/INIReader.cpp
branchv_0
changeset 1 3876a9c56a66
parent 0 16c7fa9b7c49
child 2 f031a4dc7c52
equal deleted inserted replaced
0:16c7fa9b7c49 1:3876a9c56a66
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    16  */
    16  */
    17 
    17 
    18 #include <vector>
    18 #include <vector>
       
    19 #include <regex>
    19 
    20 
    20 #include "INIReader.h"
    21 #include "INIReader.h"
    21 
    22 
    22 class INIReaderImpl : public INIReader {
    23 class INIReaderImpl : public INIReader {
    23 private:
    24 private:
    31 	void addHandler(INIContentHandler* handler) override {
    32 	void addHandler(INIContentHandler* handler) override {
    32 		handlers.push_back(handler);
    33 		handlers.push_back(handler);
    33 	}
    34 	}
    34 
    35 
    35 	void process() override {
    36 	void process() override {
    36 		
    37 
    37 		// TODO: real parser instead of demo data
    38 		for (INIContentHandler* handler : handlers) handler->startDocument();
    38 		for (INIContentHandler* handler : handlers) {
    39 
    39 			handler->startDocument();
    40 		std::regex whitespacePattrern("\\s*");
    40 			
    41 		std::regex commentPattrern("\\s*(;|#)\\s*(.*)");
    41 			handler->entry("key-0", "outside sections");
    42 		std::regex sectionPattrern("\\s*\\[\\s*([^\\]]+)\\s*\\]\\s*");
    42 			
    43 		std::regex entryQuotesPattrern("\\s*([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?\\s*=\\s*\"([^']+)\"\\s*((;|#)\\s*(.*))?");
    43 			handler->startSection("section-1");
    44 		std::regex entryApostrophesPattrern("\\s*([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?\\s*=\\s*'([^']+)'\\s*((;|#)\\s*(.*))?");
    44 			handler->entry("key-1", "in section 1");
    45 		std::regex entryPlainPattrern("\\s*([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?\\s*=\\s*(.*)");
    45 			handler->entry("key-2", "in section 1");
    46 
    46 			handler->entry("key-3", "in section 1");
    47 		std::smatch match;
    47 			
    48 		std::string section;
    48 			handler->startSection("nested-section-1-1");
    49 		std::string line;
    49 			handler->entry("key-1", "in nested section 1-1");
    50 
    50 			handler->entry("key-2", "in nested section 1-1");
    51 		while (std::getline(input, line)) {
    51 			handler->endSection();
    52 
    52 			
    53 			if (std::regex_match(line, match, whitespacePattrern)) {
    53 			handler->endSection();
    54 				// TODO: support also whitespace
    54 			
    55 			} else if (std::regex_match(line, match, commentPattrern)) {
    55 			handler->startSection("section-2");
    56 				// TODO: support also comments + emit also the comment style (;/#)
    56 			handler->entry("key-1", "in section 2");
    57 			} else if (std::regex_match(line, match, sectionPattrern)) {
    57 			handler->endSection();
    58 				if (section.size()) for (INIContentHandler* handler : handlers) handler->endSection();
    58 			
    59 				section = match[1];
    59 			handler->entry("key-666", "outside sections again; this normally would not happen, but should be supported");
    60 				for (INIContentHandler* handler : handlers) handler->startSection(section);
    60 			
    61 			} else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern)) {
    61 			handler->endDocument();
    62 				// TODO: support also comments + emit also the comment style (;/#)
       
    63 				// TODO: emit also the quote style ('/"/) and surrounding whitespace
       
    64 				for (INIContentHandler* handler : handlers) handler->entry(match[1], match[3], match[4]);
       
    65 			} else if (std::regex_match(line, match, entryPlainPattrern)) {
       
    66 				for (INIContentHandler* handler : handlers) handler->entry(match[1], match[3], match[4]);
       
    67 			} else {
       
    68 				// TODO: warning, error, or support unknown content
       
    69 			}
       
    70 
       
    71 			// TODO: probably switch to state-machine approach instead of regular expressions
       
    72 			// TODO: warning/error handler
       
    73 			// TODO: support also multiline content (\ + \n)
       
    74 			// TODO: support also quoted or multiline keys?
       
    75 			// TODO: support also escaped characters
       
    76 			// TODO: support also Java .properties and manifest.mf formats?
       
    77 			// TODO: support also nested sections – hierarchy
       
    78 			// TODO: support also option for alternative key-value separator (: instead of =)
       
    79 			// TODO: support also other encodings (currently only UTF-8 is supported)
       
    80 			// TODO: emit line numbers and/or event order?
    62 		}
    81 		}
    63 		
    82 
       
    83 		if (section.size()) for (INIContentHandler* handler : handlers) handler->endSection();
       
    84 
       
    85 		for (INIContentHandler* handler : handlers) handler->endDocument();
    64 	}
    86 	}
    65 };
    87 };
    66 
    88 
    67 INIReader* INIReader::create(std::istream& input) {
    89 INIReader* INIReader::create(std::istream& input) {
    68 	return new INIReaderImpl(input);
    90 	return new INIReaderImpl(input);