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); |