GithubHelp home page GithubHelp logo

c-ridgway / cpp-feather-ini-parser Goto Github PK

View Code? Open in Web Editor NEW
48.0 6.0 14.0 48 KB

Header only, simple, fast, templated - portable INI parser for ANSI C++.

License: MIT License

C++ 100.00%
portable-ini-parser cpp c-plus-plus ini-parser header-only easy fast

cpp-feather-ini-parser's Introduction

feather-ini-parser

Intuitive, fast, lightweight, header, portable INI parser for ANSI C++.

Methods

Statement Return Type
ini(filename, doParse, parseFlags) constructor
ini(ini) copy constructor
ini.parse(parseFlags) bool
ini.save(filename, saveFlags) bool
ini.set(section, key, value) bool
ini.get(section, key, def) string
ini.getAs<type>(section, key, def = type()) type
ini.create(section) bool
ini.select(section) bool
ini.set(key, value) bool
ini.get(key, def) string
ini.getAs<type>(key, def = type()) type
ini.clear() bool
ini[section][key] string&
ini[section] keys_t&

Flags

Flag Effect
PARSE_COMMENTS_ALL Parses comments // and #
PARSE_COMMENTS_SLASH Parses comment //
PARSE_COMMENTS_HASH Parses comment #
SAVE_PRUNE Removes all empty sections/keys
SAVE_PADDING_SECTIONS Appends a blank line under each section
SAVE_SPACE_SECTIONS '[ Section ]' instead of '[Section]'
SAVE_SPACE_KEYS 'key = value' instead of 'key=value'
SAVE_TAB_KEYS ' key=value' instead of 'key=value'
SAVE_SEMICOLON_KEYS 'key=value;' instead of 'key=value'

Example

Requires C++11: -std=c++11 or -std=c++14 or -std=c++20 or ...

#include "INI.h"
//#define FINI_WIDE_SUPPORT
...

// Set global parsing/saving options
INI::PARSE_FLAGS = INI::PARSE_COMMENTS_ALL | INI::PARSE_COMMENTS_SLASH | INI::PARSE_COMMENTS_HASH;
INI::SAVE_FLAGS = INI::SAVE_PRUNE | INI::SAVE_PADDING_SECTIONS | INI::SAVE_SPACE_SECTIONS | INI::SAVE_SPACE_KEYS | INI::SAVE_TAB_KEYS | INI::SAVE_SEMICOLON_KEYS;

INI ini("file.ini", true);  // Assign ini file and parse

ini.create("Section 0");
ini.select("Section 0");
ini.set("Key2", "Value");
ini.get("Key1", "DefaultValue");

ini.set("Section 0", "Key1", std::to_string(11.12));
cout << ini.getAs<float>("Section 2", "Key1") << endl; // Return as float

ini["Section 0"]["Key1"] = "Changed";

// Save with formatting
ini.save("test.ini");

// Loop through sections, keys and values
for(auto i: ini.sections) {
   cout << "[" << i.first << "]" << endl;

   //for(auto j = i.second->begin(); j != i.second->end(); j++)
   for(auto j: *i.second) {
      cout << "  " << j.first << "=" << j.second << endl;
   }
}

More

Please see the example .cpp file and Code::Blocks .cbp project for a compilable GCC and VSC++ example. Further examples include enabling wide char support.

cpp-feather-ini-parser's People

Contributors

tstenner avatar turbine1991 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

cpp-feather-ini-parser's Issues

parse()'s reading logic flawed

Take this file as an example:

[Desktop Entry]
Version=1.0
Type=Application
Name=Strawberry
GenericName=Strawberry Music Player
Comment=Plays music
Exec=strawberry %U
TryExec=strawberry
Icon=strawberry
Terminal=false
Categories=AudioVideo;Player;Qt;Audio;
StartupNotify=false
MimeType=x-content/audio-player;application/ogg;application/x-ogg;application/x-ogm-audio;audio/flac;audio/aac;audio/mp4;audio/mpeg;audio/mpegurl;audio/ogg;audio/vorbis;audio/vnd.rn-realaudio;audio/x-wav;audio/x-flac;audio/x-oggflac;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-wma;audio/x-musepack;audio/x-pn-realaudio;audio/x-scpls;audio/x-speex;video/x-ms-asf;

It's a perfectly valid desktop file (and therefore ini file), however cpp-feather-ini-parser's parse() function will get stuck in an infinite loop while trying to read that file's last line.

While looking into this within the scope of linuxdeploy/linuxdeploy#39, it turned out that the line buffer size is too small, causing the reading loop to break.

You shouldn't "assume" a maximum line size, that's never a good idea. Instead, the lines should be parsed using e.g., std::getline(istream& is, string& line), which will read characters into line until a newline character is found. That way, a buffer size doesn't have to be assumed, and files with very long lines will be parsed just fine. It might be slightly slower, but I don't think that this matters. Also, it'll be more memory efficient.

Just replace fini_char_t line[FINI_BUFFER_SIZE]; while(!file.eof()) {...} with std::string line; while (std::getline(file, line)) {...}. You could probably also use a vector<your_char_t> and the C version of getline(), or a std::wstring.

Reporting failure to parse (instead of segfaulting)

First, thanks for making this it checks the boxes that I need that the various other INI libs didn't. However, I have two issues: one functional the othor a bug.

For the functional issue

The parse function/ini class has no way of indicating if the given file is invalid/has errors. For example if a line has no '=' then that line should have an error. Current functionality has it just ignore that line.

For the bug

I did not add a Section to the file at first. To my understanding this is valid formatting for INI files where key/value pairs can come before any section declarations and will either have no section or default to the section named "" (empty string). Regardless of whether you want to support that, the current bug is that leaving off the section results in a segmentation fault as the parse function tries to store a key/value pair into a section that doesn't exist.

The ini file I made was like so:

id=2dk53l89mn3n7JdY801264Kds0H```

The relivant line of the segfault error in valgrind was:
```==9642==    by 0x4E632BA: INI<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::parse(std::istream&) (INI.h:334)

INI.h:334
(*current)[key] = value;

Suggestions

I wasn't sure if a pull request was welcome. I'll likely try implementing the following myself in a fork if I don't hear back from you.

My suggestion is the creation of a "" Section at the beginning of parse and setting it to the "current" member variable. Possibly removing the "" Section at the end if no value pairs were added to it.

I also suggest some sort of error code int that is set to certain values when a parse fails in different ways with 0 being the default/success code and provide either direct access to the variable or a getter function.

Thank you.

iterating keys & values in a only one section?

Hi, your lib is awesome, but i have an question how do you can iterate the values from ONE section no the whole file itself, i see your example of iterating but only iterates the values and keys from all sections in the file, and only i need iterate from one section, i can make iterate from that code sample simply using an 'if' but the lib will kept iterating until they reach final of the file wasting cpu cycles.

Thanks..

Crash on DOS-style CR+LF line endings

The parser crashes on empty lines with CR+LF ending. The reason is this code below:
if (!(fini_strlen(line) >= 2 && line[0] == '/' && line[1] == '/')) //Ignore comment
An empty line with CR+LF will have strlen == 2 and therefore it tries to parse the line.
Later in the code you have
skey = fini_strtok(line, _T("="));
svalue = fini_strtok(NULL, _T("\n"));
which will result in skey: "" and svalue: NULL
When the parser tries to access svalue, for example calling strlen, the program will throw an exception, trying to dereference the NULL pointer.

the project need object enumeration support ?

the library does not have a function to list section
no function to list items of section.
how about deque style access for spesific nth item ie ini[0] to access #0th elements name may be.
and how about listing of spesific sections items only which microsofts implementation has but is not cross platform directly so it too is useless alot.

Key/Val pairs not allocated in copy construction?

Hello, I was experimenting with feather INI when I came across an issue related to the copy constructor. The Key/Value pairs are in a dynamically allocated map, but I don't see the copy constructor making a new copy (i.e. allocating a new map). Thus when the original is deleted, the key/val pairs of the copy are also deallocated. The following scenario illustrates the problem. In my environment, it crashes in Debug mode, and prints no key/val pairs in Release mode:

#include <feather_ini/INI.h>
#include <iostream>

void printIni(INI<> & ini) { // Reference, copy constructor not called
	for (auto & section : ini.sections) {
		std::cout << "[" << section.first << "]" << std::endl;
		auto & keyValMap = *(section.second);
		for (auto & keyVal : keyValMap) {
			std::cout << keyVal.first << "=" << keyVal.second << std::endl;
		}
	}
}

int main(int argc, char * argv[]) {
	auto origIni = new INI<>("C:\\Windows\\system.ini", true);
	std::cout << "Original: ==============================" << std::endl;
	printIni(*origIni);

	auto copyIni = new INI<>(*origIni);
	delete origIni; // This deletes the key/val pairs shared by orig and copy

	std::cout << std::endl;
	std::cout << "Copy: ==============================" << std::endl;
	// Only displays the sections, not the key/val pairs, or crashes
	printIni(*copyIni);
}

The library is handing

The config file parsing is hanging in case the line length exceeds the 128 bytes length specified as the value of FINI_BUFFER_SIZE. Increase the buffer size to make it more practical or change the way the config file is read to prevent hanging.

wrong results / crashes without sections

I found three bugs, two related to sections:

  • ini.select("section") only changes the section when that section actually exists, otherwise keys from the previously selected section are returned
  • ini.select("section") in an empty ini file causes a crash as soon as pt.get() is called
  • calling pt.get("section", "key") crashes when there's no section
#include "INI.h"
#include <iostream>

void test(std::string str) {
	INI<> ini((void*) str.c_str(), str.length(), true);
	std::cout << ini.get("exists", "foo", 0) << std::endl;
	std::cout << ini.get("doesntexist", "foo", 0) << std::endl;
	ini.select("exists");
	std::cout << ini.get("foo", 0) << std::endl;
	ini.select("doesntexist");
	std::cout << ini.get("foo", 0) << std::endl;
}

int main(int argc, char** argv) {
	// Prints "1 0 1 1", should be "1 0 1 0"
	test("[exists]\nfoo=1");
	// Prints "0 0 Segmentation fault"
	test("");
	// segfaults immediately in the constructor
	test("foo=1");
	return 0;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.