Cross-Platform Way to Get Line Number of an Ini File Where Given Option Was Found

How to read config file entries from an INI file

What I came up with:

std::wifstream file(L"\\Windows\\myini.ini");
if (file)
{
bool section=false;
while (!file.eof())
{
WCHAR _line[256];
file.getline(_line, ELEMENTS(_line));
std::wstringstream lineStm(_line);
std::wstring &line=lineStm.str();
if (line.empty()) continue;

switch (line[0])
{
// new header
case L'[':
{
std::wstring header;
for (size_t i=1; i<line.length(); i++)
{
if (line[i]!=L']')
header.push_back(line[i]);
else
break;
}
if (header==L"Section")
section=true;
else
section=false;
}
break;
// comments
case ';':
case ' ':
case '#':
break;
// var=value
default:
{
if (!section) continue;

std::wstring name, dummy, value;
lineStm >> name >> dummy;
ws(lineStm);
WCHAR _value[256];
lineStm.getline(_value, ELEMENTS(_value));
value=_value;
}
}
}
}

c++ boost parse ini file when containing multikeys

Your input is simply not an INI file, as INI files do not permit duplicate values. You can write your own parser, e.g. using the code I wrote here:¹

  • Cross-platform way to get line number of an INI file where given option was found

If you replace the section_t map

typedef std::map<textnode_t, textnode_t>    section_t;

with multimap:

typedef std::multimap<textnode_t, textnode_t>    section_t;

you can parse repeated keys:

[section_1]
key_1=value_1
key_1=value_2
key_n=value_n
[section_2]
key1=value_1
key2=value_2
key_n=value_1
key_n=value_2
[section_n]

See full code here: https://gist.github.com/sehe/068b1ae81547b98a3cec02a530f220df

¹ or Learning Boost.Spirit: parsing INI and http://coliru.stacked-crooked.com/view?id=cd1d516ae0b19bd6f9af1e3f1b132211-0d2159870a1c6cb0cd1457b292b97230 and possibly others

iterate over ini file on c++, probably using boost::property_tree::ptree?

To answer your question directly: of course iterating a property tree is possible. In fact it's trivial:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

int main()
{
using boost::property_tree::ptree;
ptree pt;

read_ini("input.txt", pt);

for (auto& section : pt)
{
std::cout << '[' << section.first << "]\n";
for (auto& key : section.second)
std::cout << key.first << "=" << key.second.get_value<std::string>() << "\n";
}
}

This results in output like:

[Cat1]
name1=100 #skipped
name2=200 \#not \\skipped
name3=dhfj dhjgfd
[Cat_2]
UsagePage=9
Usage=19
Offset=0x1204
[Cat_3]
UsagePage=12
Usage=39
Offset=0x12304

I've written a very full-featured Inifile parser using boost-spirit before:

  • Cross-platform way to get line number of an INI file where given option was found

It supports comments (single line and block), quotes, escapes etc.

(as a bonus, it optionally records the exact source locations of all the parsed elements, which was the subject of that question).

For your purpose, though, I think I'd recomment Boost Property Tree.

how do i find the location where a Spirit parser matched?

You can use qi::raw[] to get the source iterator pair spanning a match.

There's a convenient helper iter_pos in Qi Repository that you can use to directly get a source iterator without using qi::raw[].

Also, with some semantic action trickery you can get both:

raw[ identifier [ do_something_with_attribute(_1) ] ]
[do_something_with_iterators(_1)]

In fact,

raw[ identifier [ _val = _1 ] ] [do_something_with_iterators(_1)]

would be close to "natural behaviour".

Extra Mile

To get file name/line/column values you can either do some iterator arithmetics or use the line_pos_iterator adaptor:

#include <boost/spirit/include/support_line_pos_iterator.hpp>

This has some accessor functions that help with line number/column tracking. You can probably find a few answers of mine on here with examples.

storing line numbers of expressions with boost.spirit 2

As per the mailing list, Spirit.Classic positional iterators can also be used with Spirit 2.

There is also an article on an iter_pos-parser on the Spirit-blog.

I will update when i had time to test.

How can I find the php.ini file used by the command line?

Just run php --ini and look for Loaded Configuration File in the output for the location of php.ini used by your CLI.

Puppet - remove ini_setting completely

Using the Augeas type:

augeas { 'remove_ini_header':
incl => '/etc/example.ini',
lens => 'IniFile.lns_loose',
changes => 'rm section[. = "header"]',
}

To break this down a bit, first I used the built-in IniFile.lns_loose lens (i.e. a "generic" loose parsing of INI files) and augtool to see the current state of the tree:

$ augtool -t "IniFile.lns_loose incl /etc/example.ini"
augtool> print /files/etc/example.ini
/files/etc/example.ini
/files/etc/example.ini/section = "header"
/files/etc/example.ini/section/ip = "'1.1.1.1'"
/files/etc/example.ini/section/hostname = "'myserver'"
/files/etc/example.ini/section/port = "80"

The entire section is in one part of the tree, so calling rm for that section will delete the entire subtree.

To match the header section, you need to search for nodes called section where the value (the right hand side) is header. The [. = "header"] part of the command is a path expression that filters for nodes with the value header.

What is the easiest way to parse an INI File in C++?

You can use the Windows API functions, such as GetPrivateProfileString() and GetPrivateProfileInt().



Related Topics



Leave a reply



Submit