src/lib/INIReader.cpp
author František Kučera <franta-hg@frantovo.cz>
Sat, 28 Nov 2020 00:46:40 +0100
branchv_0
changeset 26 b1f6fa3a6555
parent 25 b9067d2812e5
child 27 e9aad9dd823a
permissions -rw-r--r--
TODO comments
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, version 3 of the License.
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
#include <vector>
1
3876a9c56a66 simple INI parser based on regular expressions
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    19
#include <regex>
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    20
#include <sstream>
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    21
#include <stdexcept>
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
#include "INIReader.h"
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    25
namespace relpipe {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    26
namespace in {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    27
namespace ini {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    28
namespace lib {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    29
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
class INIReaderImpl : public INIReader {
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
private:
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
	std::istream& input;
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
	std::vector<INIContentHandler*> handlers;
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    34
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    35
	/** 
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    36
	 * By default, we ignore all leading whitespace on continuing lines.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    37
	 * If there should be some spaces or tabs, they should be placed on the previous line before the „\“.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    38
	 * If a line break is desired, it should be written as \n (escaped) or the value should be quoted in " or '.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    39
	 * 
26
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    40
	 * TODO: several options:
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    41
	 *  - enabled, disabled
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    42
	 *  - if disabled, then: keep backslash, trim backslash, escape backslash
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    43
	 *    (keep requires support in some further unescaping phase, or it will cause an error)
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    44
	 *  - keep or trim the line end
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    45
	 *  - keep or trim the leading spaces
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    46
	 *  - allow comments interleaved with continuing lines (the freaky systemd syntax)
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    47
	 * 
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    48
	 * Related specifications:
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    49
	 *  - https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Properties.html
26
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
    50
	 *  - https://www.freedesktop.org/software/systemd/man/systemd.syntax.html
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    51
	 */
23
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
    52
	bool trimLeadingSpacesOnContinuingLines = true;
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    53
24
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    54
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    55
	/**
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    56
	 * Some dialects or configuration files in general does not support sections.
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    57
	 * Then a line, that looks like an INI section, should be interpreted as a key
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    58
	 * (or error, if does not have a proper key-value separator).
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    59
	 */
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    60
	bool allowSections = true;
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    61
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    62
	/**
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    63
	 * KDE uses some weird INI dialect that allows [section][x] syntax where „x“ is kind of „tag“ that signalizes some properties of given section.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    64
	 * Line „[section_1][$i]“ means that the „section_1“ is „locked“.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    65
	 * We may emit this information somehow later, but for now, it is just ignored.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    66
	 * 
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    67
	 * TODO: Is „section tag“ right name?
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    68
	 * 
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    69
	 * Related specifications:
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    70
	 *  - https://userbase.kde.org/KDE_System_Administration/Configuration_Files#Lock_Down
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    71
	 */
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    72
	bool allowSectionTags = true;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    73
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    74
	/**
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    75
	 * If whole key is „aaa[bbb]“ then „aaa“ is considered to be the key and „bbb“ the sub-key.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    76
	 * No \[ escaping is currently supported, so the key might not contain the bracket character.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    77
	 * 
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    78
	 * Related specifications:
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    79
	 *  - https://userbase.kde.org/KDE_System_Administration/Configuration_Files#Shell_Expansion
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    80
	 *  - https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s05.html
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    81
	 */
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    82
	bool allowSubKeys = true;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    83
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    84
	/**
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    85
	 * Classic INI uses „key=value“ syntax.
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    86
	 * But some other formats/dialects might use key:value.
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    87
	 * 
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    88
	 * Only single character separators are supported.
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    89
	 * If multiple separators should be recognized (e.g. both „=“ and „:“), this string will contain all of them,
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    90
	 * i.e. „:=“ does not mean that the „key:=value“ syntax, but „key=value“ or „key:value“.
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    91
	 */
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    92
	std::string keyValueSeparators = "=";
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
    93
21
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    94
	/**
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    95
	 * Classic INI uses „; comment“ syntax.
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    96
	 * But many existing files contain „# comment“ lines.
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    97
	 * 
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    98
	 * Only single character separators are supported (works same as keyValueSeparators).
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    99
	 */
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   100
	std::string commentSeparators = ";#";
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   101
22
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   102
	/**
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   103
	 * INI often support both "quotes" and 'apostrophes' styles.
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   104
	 * But some dialects may support only one of them or not support quoting at all.
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   105
	 * 
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   106
	 * In such case e.g. „key="some value"“ would mean that the value is „"value"“ (including the quotes).
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   107
	 * Thus it is important to allow disabling quote recognizing (which is done by setting this parameter to empty string).
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   108
	 * 
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   109
	 * Only single character quotes are supported (works same as keyValueSeparators).
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   110
	 */
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   111
	std::string quotes = "\"'";
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   112
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   113
	int lineNumber = 1;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   114
	int eventNumber = 0;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   115
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   116
	/**
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   117
	 * Should be always used instead of input.peek().
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   118
	 * Skips \r.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   119
	 */
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   120
	char peek() {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   121
		// In 2020 there is no need to manually return the carriage. However some legacy systems still do it.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   122
		char ch = input.peek();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   123
		if (ch == '\r') {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   124
			input.get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   125
			ch = input.peek();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   126
		}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   127
		return ch;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   128
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   129
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   130
	/**
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   131
	 * Should be always used instead of input.get().
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   132
	 * Counts the lines and skips \r.
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   133
	 */
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   134
	char get() {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   135
		char ch = input.get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   136
		if (ch == '\n') lineNumber++;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   137
		else if (ch == '\r') ch = get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   138
		return ch;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   139
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   140
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   141
	std::string readSpacesAndTabs() {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   142
		std::stringstream result;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   143
		for (char ch = peek(); input.good() && (ch == ' ' || ch == '\t'); ch = peek()) result.put(get());
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   144
		return result.str();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   145
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   146
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   147
	std::string readAllWhitespace() {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   148
		std::stringstream result;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   149
		for (char ch = peek(); input.good() && (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); ch = peek()) result.put(get());
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   150
		return result.str();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   151
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   152
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   153
	void processContinuingLine(std::stringstream& result) {
23
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   154
		if (trimLeadingSpacesOnContinuingLines) readSpacesAndTabs();
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   155
		else result.put('\n');
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   156
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   157
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   158
	std::string readUntil(const char until, bool* found = nullptr) {
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   159
		return readUntil(std::string(1, until), found);
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   160
	}
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   161
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   162
	std::string readUntil(const std::string& until, bool* found = nullptr) {
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   163
		std::stringstream result;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   164
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   165
		for (char ch = peek(); input.good() && !oneOf(ch, until); ch = peek()) {
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   166
			if (ch == '\\') {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   167
				get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   168
				ch = get();
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   169
				if (oneOf(ch, until) && ch == '\n') processContinuingLine(result);
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   170
				else if (oneOf(ch, until)) result.put(ch);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   171
				else if (ch == std::istream::traits_type::eof()) break;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   172
				else result.put('\\').put(ch);
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   173
				// unescaping is done in two phases:
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   174
				// here we unescape just the \n (LF)
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   175
				// other escape sequences are leaved untouched and will be processed in later phases, see see UnescapingINIHandler
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   176
			} else {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   177
				ch = get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   178
				result.put(ch);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   179
			}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   180
		}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   181
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   182
		if (oneOf(peek(), until)) {
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   183
			get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   184
			if (found) *found = true;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   185
		} else {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   186
			if (found) *found = false;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   187
		}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   188
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   189
		return result.str();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   190
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   191
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   192
	std::string readToken(const char until, char* quote = nullptr, bool* found = nullptr) {
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   193
		return readToken(std::string(1, until), quote, found);
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   194
	}
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   195
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   196
	std::string readToken(const std::string& until, char* quote = nullptr, bool* found = nullptr) {
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   197
		std::string result;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   198
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   199
		char ch = peek();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   200
		if (isQuote(ch)) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   201
			if (quote) *quote = ch;
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   202
			result = readUntil(std::string(1, get()), found);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   203
		} else {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   204
			if (quote) *quote = 0;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   205
			result = readUntil(until, found);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   206
		}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   207
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   208
		return result;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   209
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   210
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   211
	std::string readTokenAndEatTerminator(char until, char* quote = nullptr, bool* found = nullptr) {
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   212
		return readTokenAndEatTerminator(std::string(1, until), quote, found);
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   213
	}
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   214
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   215
	std::string readTokenAndEatTerminator(const std::string& until, char* quote = nullptr, bool* found = nullptr) {
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   216
		std::string result = readToken(until, quote, found);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   217
		if (*quote) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   218
			readAllWhitespace();
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   219
			if (!oneOf(get(), until)) throw std::logic_error(std::string("missing „") + until + "“ after quoted section name");
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   220
		}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   221
		return result;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   222
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   223
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   224
	bool isComment(char ch) {
21
b35baebf5005 prepare for multiple and configurable comment separators (e.g. „; comment“ and „# comment“)
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   225
		return oneOf(ch, commentSeparators);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   226
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   227
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   228
	bool isQuote(char ch) {
22
29d673a54ecf prepare for multiple and configurable quotes (e.g. „key="value"“ and „key='value'“ or disabling quote support at all)
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   229
		return oneOf(ch, quotes);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   230
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   231
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   232
	/**
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   233
	 * @param ch character to be evaluated
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   234
	 * @param options list of options (characters)
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   235
	 * @return whether ch is one of options
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   236
	 */
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   237
	bool oneOf(char ch, const std::string& options) {
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   238
		return options.find(ch) != std::string::npos;
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   239
	}
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   240
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   241
	std::string trim(std::string s) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   242
		return std::regex_replace(s, std::regex("^\\s+|\\s+$"), "");
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   243
	}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   244
23
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   245
	/**
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   246
	 * TODO: use a common method
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   247
	 */
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   248
	bool parseBoolean(const std::string& value) {
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   249
		if (value == "true") return true;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   250
		else if (value == "false") return false;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   251
		else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   252
	}
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   253
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   254
	void setDialect(const std::string& name) {
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   255
		if (name == "default-ini") {
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   256
			// already set
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   257
		} else if (name == "java-properties") {
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   258
			trimLeadingSpacesOnContinuingLines = true;
24
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   259
			allowSections = false;
23
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   260
			allowSectionTags = false;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   261
			allowSubKeys = false;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   262
			commentSeparators = "#";
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   263
			keyValueSeparators = "=:";
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   264
			quotes = "";
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   265
			// TODO: enable unicode unescaping
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   266
		} else {
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   267
			throw std::invalid_argument(std::string("Unsupported INI dialect: ") + name);
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   268
		}
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   269
	}
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   270
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   271
public:
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   272
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   273
	INIReaderImpl(std::istream& input) : input(input) {
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   274
	}
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   275
23
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   276
	void setOption(const std::string& uri, const std::string& value) override {
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   277
		if (uri == "trim-continuing-lines") trimLeadingSpacesOnContinuingLines = parseBoolean(value); // TODO: continuing lines modes (enum), not just boolean
24
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   278
		else if (uri == "allow-sections") allowSections = parseBoolean(value);
23
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   279
		else if (uri == "allow-section-tags") allowSectionTags = parseBoolean(value);
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   280
		else if (uri == "allow-sub-keys") allowSubKeys = parseBoolean(value);
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   281
		else if (uri == "comment-separators") commentSeparators = value;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   282
		else if (uri == "key-value-separators") keyValueSeparators = value;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   283
		else if (uri == "quotes") quotes = value;
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   284
		else if (uri == "dialect") setDialect(value);
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   285
		else throw std::invalid_argument(std::string("Invalid parser option: „") + uri + "“ with value: „" + value + "“");
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   286
	}
b497140b0b63 enable configuring the parser from CLI: --parser-option
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   287
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   288
	void addHandler(INIContentHandler* handler) override {
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   289
		handlers.push_back(handler);
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   290
	}
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   291
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   292
	void process() override {
1
3876a9c56a66 simple INI parser based on regular expressions
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   293
		for (INIContentHandler* handler : handlers) handler->startDocument();
3876a9c56a66 simple INI parser based on regular expressions
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   294
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   295
		bool inSection = false;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   296
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   297
		while (input.good()) { // TODO: condition
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   298
			{
19
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   299
				INIContentHandler::WhitespaceEvent event;
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   300
				event.lineNumber = lineNumber;
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   301
				std::string whitespace = readAllWhitespace();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   302
				if (whitespace.size()) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   303
					event.eventNumber = ++eventNumber;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   304
					event.whitespace = whitespace;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   305
					for (INIContentHandler* handler : handlers) handler->whitespace(event);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   306
				}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   307
			}
1
3876a9c56a66 simple INI parser based on regular expressions
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   308
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   309
			bool found;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   310
			char quote;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   311
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   312
			char ch = peek();
2
f031a4dc7c52 add options: --enable-sections --enable-subkeys --enable-comments --enable-line-numbers --enable-event-numbers
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   313
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   314
			if (ch == std::istream::traits_type::eof()) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   315
				break;
24
07e0a2edf3bc add --parser-option allow-sections (Java .properties have no sections)
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   316
			} else if (ch == '[' && allowSections) {
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   317
				if (inSection) for (INIContentHandler* handler : handlers) handler->endSection();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   318
				inSection = true;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   319
				INIContentHandler::SectionStartEvent event;
6
fb717cfbfea1 improved support for comments and whitespace
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
   320
				event.lineNumber = lineNumber;
fb717cfbfea1 improved support for comments and whitespace
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
   321
				event.eventNumber = ++eventNumber;
19
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   322
				get();
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   323
				readAllWhitespace();
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   324
				event.name = readTokenAndEatTerminator(']', &quote, &found);
25
b9067d2812e5 trim section names if not in quotes
František Kučera <franta-hg@frantovo.cz>
parents: 24
diff changeset
   325
				if (!quote) event.name = trim(event.name);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   326
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   327
				readSpacesAndTabs();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   328
				if (allowSectionTags && peek() == '[') {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   329
					get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   330
					event.tag = readTokenAndEatTerminator(']', &quote, &found);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   331
				}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   332
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   333
				readSpacesAndTabs();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   334
				ch = peek();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   335
				if (isComment(ch)) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   336
					get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   337
					readSpacesAndTabs();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   338
					event.comment = readUntil('\n', &found);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   339
				} else if (ch == '\n') {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   340
					get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   341
				} else {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   342
					throw std::logic_error(std::string("unexpected content after the section: '") + event.name + "'");
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   343
				}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   344
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   345
				for (INIContentHandler* handler : handlers) handler->startSection(event);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   346
			} else if (isComment(ch)) {
6
fb717cfbfea1 improved support for comments and whitespace
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
   347
				INIContentHandler::CommentEvent event;
fb717cfbfea1 improved support for comments and whitespace
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
   348
				event.lineNumber = lineNumber;
fb717cfbfea1 improved support for comments and whitespace
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
   349
				event.eventNumber = ++eventNumber;
19
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   350
				get();
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   351
				readSpacesAndTabs();
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   352
				event.comment = readUntil('\n', &found);
6
fb717cfbfea1 improved support for comments and whitespace
František Kučera <franta-hg@frantovo.cz>
parents: 4
diff changeset
   353
				for (INIContentHandler* handler : handlers) handler->comment(event);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   354
			} else {
19
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   355
				INIContentHandler::EntryEvent event;
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   356
				event.lineNumber = lineNumber;
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   357
				event.eventNumber = ++eventNumber;
967f73af64a4 start event numbers with 1
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   358
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   359
				std::string fullKey = readToken(keyValueSeparators, &quote, &found);
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   360
				if (!found) throw std::logic_error(std::string("missing = after key: '") + fullKey + "'");
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   361
				if (!quote) fullKey = trim(fullKey);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   362
				readSpacesAndTabs();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   363
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   364
				if (quote) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   365
					ch = get();
20
9187f0439ca9 prepare for multiple and configurable key-value separators (e.g. key=value and key:value)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   366
					if (oneOf(ch, keyValueSeparators)) readSpacesAndTabs();
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   367
					else throw std::logic_error(std::string("missing = after quoted key: '") + fullKey + "'");
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   368
				}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   369
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   370
				std::string value = readToken('\n', &quote, &found);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   371
				if (!quote) value = trim(value);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   372
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   373
				event.key = fullKey;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   374
				event.fullKey = fullKey;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   375
				event.value = value;
14
ea431c469403 multi-line support: quoted and apostrophed
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   376
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   377
				if (allowSubKeys) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   378
					std::smatch match;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   379
					if (std::regex_match(fullKey, match, std::regex("([^\\[]+)\\[([^\\[]+)\\]"))) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   380
						event.key = match[1];
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   381
						event.subKey = match[2];
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   382
						event.fullKey = fullKey;
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   383
					}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   384
				}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   385
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   386
				if (quote) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   387
					readSpacesAndTabs();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   388
					ch = peek();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   389
					if (isComment(ch)) {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   390
						get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   391
						readSpacesAndTabs();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   392
						event.comment = readUntil('\n', &found);
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   393
					} else if (ch == '\n') {
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   394
						get();
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   395
					} else {
26
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
   396
						// TODO: optional support for multiple tokens in a single entry?
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
   397
						// modes: array, concatenate
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
   398
						// some-array-1 = "item 1" "item 2" 'item 3' item 4
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
   399
						// some-array-2 = "item 1" "item 2" 'item 3' item_4 item_5
b1f6fa3a6555 TODO comments
František Kučera <franta-hg@frantovo.cz>
parents: 25
diff changeset
   400
						// some-bash-style-string-value = "this "will' be' concatenated → this will be concatenated
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   401
						throw std::logic_error(std::string("unexpected content after the quoted value: key='") + fullKey + "' value='" + event.value + "'");
14
ea431c469403 multi-line support: quoted and apostrophed
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   402
					}
ea431c469403 multi-line support: quoted and apostrophed
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   403
				}
ea431c469403 multi-line support: quoted and apostrophed
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   404
2
f031a4dc7c52 add options: --enable-sections --enable-subkeys --enable-comments --enable-line-numbers --enable-event-numbers
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   405
				for (INIContentHandler* handler : handlers) handler->entry(event);
1
3876a9c56a66 simple INI parser based on regular expressions
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   406
			}
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   407
		}
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   408
		// TODO: error at the end, catch premature/unexpected EOF
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   409
		// TODO: unescape + trim values + ignore \r
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   410
		// TODO: count lines
2
f031a4dc7c52 add options: --enable-sections --enable-subkeys --enable-comments --enable-line-numbers --enable-event-numbers
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   411
		if (inSection) for (INIContentHandler* handler : handlers) handler->endSection();
1
3876a9c56a66 simple INI parser based on regular expressions
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   412
		for (INIContentHandler* handler : handlers) handler->endDocument();
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   413
	}
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   414
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   415
	// General feautres:
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   416
	// TODO: warning/error handler
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   417
	// TODO: support also escaped characters
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   418
	// TODO: support also Java .properties and manifest.mf formats?
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   419
	// TODO: support also nested sections – hierarchy
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   420
	// TODO: support also nested keys e.g. key.sub.subsub.subsubsub=value – translate them to nested sections
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   421
	// TODO: support also option for alternative key-value separator (: instead of =)
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   422
	// TODO: support also other encodings (currently only UTF-8 is supported)
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   423
	// TODO: better exceptions
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   424
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   425
	// Lossless conversions:
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   426
	// TODO: emit also the quote style ('/"/)
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   427
	// TODO: emit also the comment style (;/#) ?
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   428
	// TODO: emit also the whitespace before key name, around =, after "values"/'values', around [sections] ?
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   429
	// TODO: emit also the line-end type (LF/CRLF) ?
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   430
0
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   431
};
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   432
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   433
INIReader* INIReader::create(std::istream& input) {
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   434
	return new INIReaderImpl(input);
16c7fa9b7c49 project and parser skeleton + output demo data
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   435
}
16
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   436
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   437
}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   438
}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   439
}
db994a2ddffa new INI parser
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   440
}