src/lib/INIReader.cpp
branchv_0
changeset 6 fb717cfbfea1
parent 4 d9b047731e18
child 9 be61125d8ed1
equal deleted inserted replaced
5:d70ea23682aa 6:fb717cfbfea1
    37 
    37 
    38 		for (INIContentHandler* handler : handlers) handler->startDocument();
    38 		for (INIContentHandler* handler : handlers) handler->startDocument();
    39 
    39 
    40 		std::regex whitespacePattrern("\\s*");
    40 		std::regex whitespacePattrern("\\s*");
    41 		std::regex commentPattrern("\\s*(;|#)\\s*(.*)");
    41 		std::regex commentPattrern("\\s*(;|#)\\s*(.*)");
    42 		std::regex sectionPattrern("\\s*\\[\\s*([^\\]]+)\\s*\\]\\s*");
    42 		std::regex sectionPattrern("\\s*\\[\\s*([^\\]]+)\\s*\\]\\s*((;|#)\\s*(.*))?");
    43 		std::regex entryQuotesPattrern(/***/"\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*\"([^']+)\"\\s*((;|#)\\s*(.*))?");
    43 		std::regex entryQuotesPattrern(/***/"\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*\"([^']+)\"\\s*((;|#)\\s*(.*))?");
    44 		std::regex entryApostrophesPattrern("\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*'([^']+)'\\s*((;|#)\\s*(.*))?");
    44 		std::regex entryApostrophesPattrern("\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*'([^']+)'\\s*((;|#)\\s*(.*))?");
    45 		std::regex entryPlainPattrern("\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*(.*)");
    45 		std::regex entryPlainPattrern("\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*(.*)");
    46 
    46 
    47 		std::smatch match;
    47 		std::smatch match;
    53 
    53 
    54 		while (std::getline(input, line)) {
    54 		while (std::getline(input, line)) {
    55 			lineNumber++;
    55 			lineNumber++;
    56 
    56 
    57 			if (std::regex_match(line, match, whitespacePattrern)) {
    57 			if (std::regex_match(line, match, whitespacePattrern)) {
    58 				// TODO: support also whitespace
    58 				INIContentHandler::WhitespaceEvent event;
       
    59 				event.lineNumber = lineNumber;
       
    60 				event.eventNumber = ++eventNumber;
       
    61 				event.whitespace = match[0];
       
    62 				for (INIContentHandler* handler : handlers) handler->whitespace(event);
    59 			} else if (std::regex_match(line, match, commentPattrern)) {
    63 			} else if (std::regex_match(line, match, commentPattrern)) {
    60 				// TODO: support also comments + emit also the comment style (;/#)
    64 				INIContentHandler::CommentEvent event;
       
    65 				event.lineNumber = lineNumber;
       
    66 				event.eventNumber = ++eventNumber;
       
    67 				event.comment = match[2];
       
    68 				for (INIContentHandler* handler : handlers) handler->comment(event);
    61 			} else if (std::regex_match(line, match, sectionPattrern)) {
    69 			} else if (std::regex_match(line, match, sectionPattrern)) {
    62 				if (inSection) for (INIContentHandler* handler : handlers) handler->endSection();
    70 				if (inSection) for (INIContentHandler* handler : handlers) handler->endSection();
    63 				inSection = true;
    71 				inSection = true;
    64 				INIContentHandler::SectionStartEvent event;
    72 				INIContentHandler::SectionStartEvent event;
    65 				event.lineNumber = lineNumber;
    73 				event.lineNumber = lineNumber;
    66 				event.eventNumber = ++eventNumber;
    74 				event.eventNumber = ++eventNumber;
    67 				event.name = match[1];
    75 				event.name = match[1];
    68 				// TODO: support also comments + emit also the comment style (;/#)
    76 				event.comment = match[4];
    69 				for (INIContentHandler* handler : handlers) handler->startSection(event);
    77 				for (INIContentHandler* handler : handlers) handler->startSection(event);
    70 			} else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern) || std::regex_match(line, match, entryPlainPattrern)) {
    78 			} else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern) || std::regex_match(line, match, entryPlainPattrern)) {
    71 				INIContentHandler::EntryEvent event;
    79 				INIContentHandler::EntryEvent event;
    72 				event.lineNumber = lineNumber;
    80 				event.lineNumber = lineNumber;
    73 				event.eventNumber = ++eventNumber;
    81 				event.eventNumber = ++eventNumber;
    74 				event.key = match[2];
    82 				event.key = match[2];
    75 				event.subKey = match[4];
    83 				event.subKey = match[4];
    76 				event.fullKey = match[1];
    84 				event.fullKey = match[1];
    77 				event.value = match[5];
    85 				event.value = match[5];
    78 				if (match.size() == 9) event.comment = match[8];
    86 				if (match.size() == 9) event.comment = match[8];
    79 				// TODO: emit also the quote style ('/"/) and surrounding whitespace
       
    80 				for (INIContentHandler* handler : handlers) handler->entry(event);
    87 				for (INIContentHandler* handler : handlers) handler->entry(event);
    81 			} else {
    88 			} else {
    82 				// TODO: warning, error, or support unknown content
    89 				// TODO: warning, error, or support unknown content
    83 			}
    90 			}
    84 
    91 
    85 			// TODO: probably switch to state-machine approach instead of regular expressions
    92 			// General feautres:
       
    93 			// TODO: probably switch to state-machine approach instead of regular expressions or use an existing library
    86 			// TODO: warning/error handler
    94 			// TODO: warning/error handler
    87 			// TODO: support also multiline content (\ + \n)
    95 			// TODO: support also multiline content (\ + \n)
    88 			// TODO: support also quoted or multiline keys?
    96 			// TODO: support also quoted or multiline keys?
    89 			// TODO: support also escaped characters
    97 			// TODO: support also escaped characters
    90 			// TODO: support also Java .properties and manifest.mf formats?
    98 			// TODO: support also Java .properties and manifest.mf formats?
    91 			// TODO: support also nested sections – hierarchy
    99 			// TODO: support also nested sections – hierarchy
    92 			// TODO: support also nested keys e.g. key.sub.subsub.subsubsub=value – translate them to nested sections
   100 			// TODO: support also nested keys e.g. key.sub.subsub.subsubsub=value – translate them to nested sections
    93 			// TODO: support also option for alternative key-value separator (: instead of =)
   101 			// TODO: support also option for alternative key-value separator (: instead of =)
    94 			// TODO: support also other encodings (currently only UTF-8 is supported)
   102 			// TODO: support also other encodings (currently only UTF-8 is supported)
       
   103 			
       
   104 			// Lossless conversions:
       
   105 			// TODO: emit also the quote style ('/"/)
       
   106 			// TODO: emit also the comment style (;/#) ?
       
   107 			// TODO: emit also the whitespace before key name, around =, after "values"/'values', around [sections] ?
       
   108 			// TODO: emit also the line-end type (LF/CRLF) ?
    95 		}
   109 		}
    96 
   110 
    97 		if (inSection) for (INIContentHandler* handler : handlers) handler->endSection();
   111 		if (inSection) for (INIContentHandler* handler : handlers) handler->endSection();
    98 
   112 
    99 		for (INIContentHandler* handler : handlers) handler->endDocument();
   113 		for (INIContentHandler* handler : handlers) handler->endDocument();