diff -r 3876a9c56a66 -r f031a4dc7c52 src/lib/INIReader.cpp --- a/src/lib/INIReader.cpp Sat Nov 21 20:09:18 2020 +0100 +++ b/src/lib/INIReader.cpp Sun Nov 22 00:44:00 2020 +0100 @@ -40,30 +40,43 @@ std::regex whitespacePattrern("\\s*"); std::regex commentPattrern("\\s*(;|#)\\s*(.*)"); std::regex sectionPattrern("\\s*\\[\\s*([^\\]]+)\\s*\\]\\s*"); - std::regex entryQuotesPattrern("\\s*([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?\\s*=\\s*\"([^']+)\"\\s*((;|#)\\s*(.*))?"); - std::regex entryApostrophesPattrern("\\s*([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?\\s*=\\s*'([^']+)'\\s*((;|#)\\s*(.*))?"); - std::regex entryPlainPattrern("\\s*([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?\\s*=\\s*(.*)"); + std::regex entryQuotesPattrern(/***/"\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*\"([^']+)\"\\s*((;|#)\\s*(.*))?"); + std::regex entryApostrophesPattrern("\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*'([^']+)'\\s*((;|#)\\s*(.*))?"); + std::regex entryPlainPattrern("\\s*(([^=\\]]+?[^=\\s\\]]*)(\\[([^\\]]+)\\])?)\\s*=\\s*(.*)"); std::smatch match; - std::string section; + bool inSection = false; std::string line; + int lineNumber = 0; + int eventNumber = 0; + while (std::getline(input, line)) { + lineNumber++; if (std::regex_match(line, match, whitespacePattrern)) { // TODO: support also whitespace } else if (std::regex_match(line, match, commentPattrern)) { // TODO: support also comments + emit also the comment style (;/#) } else if (std::regex_match(line, match, sectionPattrern)) { - if (section.size()) for (INIContentHandler* handler : handlers) handler->endSection(); - section = match[1]; - for (INIContentHandler* handler : handlers) handler->startSection(section); - } else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern)) { + if (inSection) for (INIContentHandler* handler : handlers) handler->endSection(); + INIContentHandler::SectionStartEvent event; + event.lineNumber = lineNumber; + event.eventNumber = ++eventNumber; + event.name = match[1]; // TODO: support also comments + emit also the comment style (;/#) + for (INIContentHandler* handler : handlers) handler->startSection(event); + } else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern) || std::regex_match(line, match, entryPlainPattrern)) { + INIContentHandler::EntryEvent event; + event.lineNumber = lineNumber; + event.eventNumber = ++eventNumber; + event.key = match[2]; + event.subKey = match[4]; + event.fullKey = match[1]; + event.value = match[5]; + if (match.size() == 9) event.comment = match[8]; // TODO: emit also the quote style ('/"/) and surrounding whitespace - for (INIContentHandler* handler : handlers) handler->entry(match[1], match[3], match[4]); - } else if (std::regex_match(line, match, entryPlainPattrern)) { - for (INIContentHandler* handler : handlers) handler->entry(match[1], match[3], match[4]); + for (INIContentHandler* handler : handlers) handler->entry(event); } else { // TODO: warning, error, or support unknown content } @@ -77,10 +90,9 @@ // TODO: support also nested sections – hierarchy // TODO: support also option for alternative key-value separator (: instead of =) // TODO: support also other encodings (currently only UTF-8 is supported) - // TODO: emit line numbers and/or event order? } - if (section.size()) for (INIContentHandler* handler : handlers) handler->endSection(); + if (inSection) for (INIContentHandler* handler : handlers) handler->endSection(); for (INIContentHandler* handler : handlers) handler->endDocument(); }