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*"); |
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; |
48 std::string section; |
48 bool inSection = false; |
49 std::string line; |
49 std::string line; |
|
50 int lineNumber = 0; |
|
51 int eventNumber = 0; |
|
52 |
50 |
53 |
51 while (std::getline(input, line)) { |
54 while (std::getline(input, line)) { |
|
55 lineNumber++; |
52 |
56 |
53 if (std::regex_match(line, match, whitespacePattrern)) { |
57 if (std::regex_match(line, match, whitespacePattrern)) { |
54 // TODO: support also whitespace |
58 // TODO: support also whitespace |
55 } else if (std::regex_match(line, match, commentPattrern)) { |
59 } else if (std::regex_match(line, match, commentPattrern)) { |
56 // TODO: support also comments + emit also the comment style (;/#) |
60 // TODO: support also comments + emit also the comment style (;/#) |
57 } else if (std::regex_match(line, match, sectionPattrern)) { |
61 } else if (std::regex_match(line, match, sectionPattrern)) { |
58 if (section.size()) for (INIContentHandler* handler : handlers) handler->endSection(); |
62 if (inSection) for (INIContentHandler* handler : handlers) handler->endSection(); |
59 section = match[1]; |
63 INIContentHandler::SectionStartEvent event; |
60 for (INIContentHandler* handler : handlers) handler->startSection(section); |
64 event.lineNumber = lineNumber; |
61 } else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern)) { |
65 event.eventNumber = ++eventNumber; |
|
66 event.name = match[1]; |
62 // TODO: support also comments + emit also the comment style (;/#) |
67 // TODO: support also comments + emit also the comment style (;/#) |
|
68 for (INIContentHandler* handler : handlers) handler->startSection(event); |
|
69 } else if (std::regex_match(line, match, entryQuotesPattrern) || std::regex_match(line, match, entryApostrophesPattrern) || std::regex_match(line, match, entryPlainPattrern)) { |
|
70 INIContentHandler::EntryEvent event; |
|
71 event.lineNumber = lineNumber; |
|
72 event.eventNumber = ++eventNumber; |
|
73 event.key = match[2]; |
|
74 event.subKey = match[4]; |
|
75 event.fullKey = match[1]; |
|
76 event.value = match[5]; |
|
77 if (match.size() == 9) event.comment = match[8]; |
63 // TODO: emit also the quote style ('/"/) and surrounding whitespace |
78 // TODO: emit also the quote style ('/"/) and surrounding whitespace |
64 for (INIContentHandler* handler : handlers) handler->entry(match[1], match[3], match[4]); |
79 for (INIContentHandler* handler : handlers) handler->entry(event); |
65 } else if (std::regex_match(line, match, entryPlainPattrern)) { |
|
66 for (INIContentHandler* handler : handlers) handler->entry(match[1], match[3], match[4]); |
|
67 } else { |
80 } else { |
68 // TODO: warning, error, or support unknown content |
81 // TODO: warning, error, or support unknown content |
69 } |
82 } |
70 |
83 |
71 // TODO: probably switch to state-machine approach instead of regular expressions |
84 // TODO: probably switch to state-machine approach instead of regular expressions |
75 // TODO: support also escaped characters |
88 // TODO: support also escaped characters |
76 // TODO: support also Java .properties and manifest.mf formats? |
89 // TODO: support also Java .properties and manifest.mf formats? |
77 // TODO: support also nested sections – hierarchy |
90 // TODO: support also nested sections – hierarchy |
78 // TODO: support also option for alternative key-value separator (: instead of =) |
91 // TODO: support also option for alternative key-value separator (: instead of =) |
79 // TODO: support also other encodings (currently only UTF-8 is supported) |
92 // TODO: support also other encodings (currently only UTF-8 is supported) |
80 // TODO: emit line numbers and/or event order? |
|
81 } |
93 } |
82 |
94 |
83 if (section.size()) for (INIContentHandler* handler : handlers) handler->endSection(); |
95 if (inSection) for (INIContentHandler* handler : handlers) handler->endSection(); |
84 |
96 |
85 for (INIContentHandler* handler : handlers) handler->endDocument(); |
97 for (INIContentHandler* handler : handlers) handler->endDocument(); |
86 } |
98 } |
87 }; |
99 }; |
88 |
100 |