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
How Do Sizeof(Arr)/Sizeof(Arr[0]) Work
Where Is the Lock for a Std::Atomic
Using Namespace Std; in a Header File
Any Reason to Overload Global New and Delete
Differencebetween "New" and "Malloc" and "Calloc" in C++
(C/C++) How to Generate Executable File That Can Run on Both Windows and Linux
Implementing Sse 4.2's Crc32C in Software
Printing All Environment Variables in C/C++
Is the Order of Iterating Through Std::Map Known (And Guaranteed by the Standard)
How to Update an Existing Element of Std::Set
Array Initialization Use Const Variable in C++
How to Build a Graphical User Interface in C++
Generate Sha256 with Openssl and C++
Algorithm for Finding the Smallest Power of Two That's Greater or Equal to a Given Value
Execute a Process from Memory Within Another Process
Using Float Gives "Call to Overloaded Function Is Ambiguous" Error