Skip to content

Commit

Permalink
Switched to version 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ndevilla committed Mar 3, 2011
1 parent 88c50b7 commit 455b6e1
Show file tree
Hide file tree
Showing 19 changed files with 1,748 additions and 29 deletions.
6 changes: 4 additions & 2 deletions AUTHORS
@@ -1,4 +1,6 @@
Author: Nicolas Devillard <ndevilla@free.fr> Author: Nicolas Devillard <ndevilla@free.fr>


Many thanks to the many people who contributed ideas, code, suggestions, This tiny library has received countless contributions and I have
corrections, enhancements. not kept track of all the people who contributed. Let them be thanked
for their ideas, code, suggestions, corrections, enhancements!

2 changes: 1 addition & 1 deletion INSTALL
Expand Up @@ -12,4 +12,4 @@ iniParser installation instructions


Enjoy! Enjoy!
N. Devillard N. Devillard
Thu Jan 3 19:36:38 CET 2008 Wed Mar 2 21:14:17 CET 2011
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,4 +1,4 @@
Copyright (c) 2000-2007 by Nicolas Devillard. Copyright (c) 2000-2011 by Nicolas Devillard.
MIT License MIT License


Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
Expand Down
6 changes: 3 additions & 3 deletions README
@@ -1,6 +1,6 @@


Welcome to iniParser -- version 3.0b (beta) Welcome to iniParser -- version 3.0
released 03 Jan 2008 released 02 Mar 2011


This modules offers parsing of ini files from the C level. This modules offers parsing of ini files from the C level.
See a complete documentation in HTML format, from this directory See a complete documentation in HTML format, from this directory
Expand All @@ -9,4 +9,4 @@ open the file html/index.html with any HTML-capable browser.
Enjoy! Enjoy!


N.Devillard N.Devillard
Thu Jan 3 19:36:31 CET 2008 Wed Mar 2 21:46:14 CET 2011
16 changes: 16 additions & 0 deletions doc/Makefile
@@ -0,0 +1,16 @@
#
# iniparser doc Makefile
#

all: html

html:
doxygen iniparser.dox
rm -f ../html/annotated.html
rm -f ../html/classes.html
rm -f ../html/doxygen.gif
rm -f ../html/files.html
rm -f ../html/functions.html
rm -f ../html/globals.html
rm -f ../html/iniparser_main.html

81 changes: 81 additions & 0 deletions doc/iniparser.dox
@@ -0,0 +1,81 @@
PROJECT_NAME = iniparser
PROJECT_NUMBER = 3.0
OUTPUT_DIRECTORY = ..
OUTPUT_LANGUAGE = English
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
HIDE_UNDOC_MEMBERS = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
INTERNAL_DOCS = NO
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
VERBATIM_HEADERS = NO
SHOW_INCLUDE_FILES = NO
JAVADOC_AUTOBRIEF = NO
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 4
ENABLED_SECTIONS =
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
ALIASES =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = YES
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
INPUT = iniparser.main ../src
FILE_PATTERNS = iniparser.h
RECURSIVE = NO
EXCLUDE =
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
IMAGE_PATH =
INPUT_FILTER =
FILTER_SOURCE_FILES = NO
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
DISABLE_INDEX = YES
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250

GENERATE_LATEX = NO
GENERATE_RTF = NO
GENERATE_MAN = NO

ENABLE_PREPROCESSING = NO
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = NO
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
PERL_PATH = /usr/bin/perl
HAVE_DOT = NO
SEARCHENGINE = NO
208 changes: 208 additions & 0 deletions doc/iniparser.main
@@ -0,0 +1,208 @@

/**

@mainpage iniparser documentation


@section welcome Introduction

iniParser is a simple C library offering ini file parsing services.
The library is pretty small (less than 1500 lines of C) and robust, and
does not depend on any other external library to compile. It is written
in ANSI C and should compile on most platforms without difficulty.


@section inidef What is an ini file?

An ini file is an ASCII file describing simple parameters
(character strings, integers, floating-point values or booleans)
in an explicit format, easy to use and modify for users.

An ini file is segmented into Sections, declared by the following
syntax:

@verbatim
[Section Name]
@endverbatim

i.e. the section name enclosed in square brackets, alone on a
line. Sections names are allowed to contain any character but
square brackets or linefeeds.

In any section are zero or more variables, declared with the
following syntax:

@verbatim
Key = value ; comment
@endverbatim

The key is any string (possibly containing blanks). The value is
any character on the right side of the equal sign. Values can be
given enclosed with quotes. If no quotes are present, the value is
understood as containing all characters between the first and the
last non-blank characters before the comment. The following
declarations are identical:

@verbatim
Hello = "this is a long string value" ; comment
Hello = this is a long string value ; comment
@endverbatim

The semicolon and comment at the end of the line are optional. If
there is a comment, it starts from the first character after the
semicolon up to the end of the line.

Multi-line values can be provided by ending the line with a
backslash (\).

@verbatim
Multiple = Line 1 \
Line 2 \
Line 3 \
Line 4 ; comment
@endverbatim

This would yield: "multiple" <- "Line1 Line2 Line3 Line4"

Comments in an ini file are:

- Lines starting with a hash sign
- Blank lines (only blanks or tabs)
- Comments given on value lines after the semicolon (if present)


@section install Compiling/installing the library

Edit the Makefile to indicate the C compiler you want to use, the
options to provide to compile ANSI C, and possibly the options to pass
to the ar program on your machine to build a library (.a) from a set
of object (.o) files.

Defaults are set for the gcc compiler and the standard ar library
builder.

Type 'make', that should do it.

To use the library in your programs, add the following line on top
of your module:

@code
#include "iniparser.h"
@endcode

And link your program with the iniparser library by adding
@c -liniparser.a to the compile line.

See the file test/initest.c for an example.

iniparser is an ANSI C library. If you want to compile it
with a C++ compiler you will likely run into compatibility
issues. Headers probably have to include the extern "C"
hack and function prototypes will want to add some const
here and there to keep the compiler happy. This job is left
to the reader as there are too many C++ compilers around, each
with its own requirements as to what represents acceptable
C code in a C++ environment. You have been warned.


@section reference Library reference

The library is completely documented in its header file. On-line
documentation has been generated and can be consulted here:

- iniparser.h



@section usage Using the parser

Comments are discarded by the parser. Then sections are
identified, and in each section a new entry is created for every
keyword found. The keywords are stored with the following syntax:

@verbatim
[Section]
Keyword = value ; comment
@endverbatim

is converted to the following key pair:

@verbatim
("section:keyword", "value")
@endverbatim

This means that if you want to retrieve the value that was stored
in the section called @c Pizza, in the keyword @c Cheese,
you would make a request to the dictionary for
@c "pizza:cheese". All section and keyword names are converted
to lowercase before storage in the structure. The value side is
conserved as it has been parsed, though.

Section names are also stored in the structure. They are stored
using as key the section name, and a NULL associated value. They
can be queried through iniparser_find_entry().

To launch the parser, use the function called iniparser_load(), which
takes an input file name and returns a newly allocated @e dictionary
structure. This latter object should remain opaque to the user and only
accessed through the following accessor functions:

- iniparser_getstring()
- iniparser_getint()
- iniparser_getdouble()
- iniparser_getboolean()

Finally, discard this structure using iniparser_freedict().

All values parsed from the ini file are stored as strings. The
accessors are just converting these strings to the requested type on
the fly, but you could basically perform this conversion by yourself
after having called the string accessor.

Notice that iniparser_getboolean() will return an integer (0 or 1),
trying to make sense of what was found in the file. Strings starting
with "y", "Y", "t", "T" or "1" are considered true values (return 1),
strings starting with "n", "N", "f", "F", "0" are considered false
(return 0). This allows some flexibility in handling of boolean
answers.

If you want to add extra information into the structure that was not
present in the ini file, you can use iniparser_set() to insert a
string.

If you want to add a section to the structure, add a key
with a NULL value. Example:
@verbatim
iniparser_set(ini, "section", NULL);
iniparser_set(ini, "section:key1", NULL);
iniparser_set(ini, "section:key2", NULL);
@endverbatim


@section implementation A word about the implementation

The dictionary structure is a pretty simple dictionary
implementation which might find some uses in other applications.
If you are curious, look into the source.


@section defects Known defects

The dictionary structure is extremely unefficient for searching
as keys are sorted in the same order as they are read from the
ini file, which is convenient when dumping back to a file. The
simplistic first-approach linear search implemented there can
become a bottleneck if you have a very large number of keys.

People who need to load large amounts of data from an ini file
should definitely turn to more appropriate solutions: sqlite3 or
similar. There are otherwise many other dictionary implementations
available on the net to replace this one.


@section authors Authors

Nicolas Devillard (ndevilla AT free DOT fr).


*/

5 comments on commit 455b6e1

@LeSpocky
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason to change all these parameters from const char * to char *?

@ndevilla
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pure question of philosophy.

Over the last 15 years the only consequence I have ever seen after the introduction of 'const' to C is the need to overcast in function calls to stop the compiler from whining. In effect it has just doubled the number of C data types and forced me to think of things I would have preferred not to know, but it has never ever helped me avoid a bug.

Some better argumenters will tell you that showing your constness is exhibiting a bit of your implementation to your customers, possibly preventing you from better coding later. I would not be so patient. I am just tired of having to cast from const to non-const or shutting up compiler warnings for something that absolutely never gained me anything. This madness has come from C++ where types are made to punish developers and keep them away from ever finishing their software. Let it go back there and rot away.

If I want to inform the users of my function that it does not modify its parameters, I state it in the documentation above but most of the time it is so obvious it is not even necessary. Let me take some examples:

The glibc man page for fopen() courageously informs you that fopen() will not modify the file name you dared put into its hands, but just open the file as advertized. Thanks.

strstr() will take two const char * parameters, just to give you this warm feeling that your strings will be safe with it, and it returns a good old non-const char * that is a pointer to the substring you searched. A non-const pointer to a const char zone? Does that make sense? More importantly: why would I care?

The mental gymnastic needed to understand the real meaning of atrocities like const * char p vs const char * p is so preposterous it is not even funny. And it is a good thing there are no references in C.

And I would not really care if const was not infectious. Once you started introducing it in your code you are forced to think about a million things you never even imagined before, which in the end will not get your software any better but will have consumed enough brain matter and sanity points to make you cry yourself to sleep every night.

tl;dr: Life is too short for const.

@LeSpocky
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your points, let me explain why I asked. We used the 3.0b version of this library. After update to 3.0 we get lots of compiler warnings and even errors, because the interface of iniparser changed. Our parameters which were const char * before are not accepted anymore by the iniparser functions. We would need to cast our stuff to char * in lots of places now. My quick and dirty workaround is to patch iniparser back to the old interface, you maybe have seen this in my fork here.

@ndevilla
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you using a C++ compiler to compile C code?

When passing a char* where a const char* is expected, most C compilers do not complain because there is no reason to. The const is only there to remind you of the contract (I will not modify the string you passed me) so passing any string will work, immutable or not. C++ compilers have been given the task of monitoring all data type conversions and raise flags every time you do it implicitly, because implicit conversion is rarely what you want. In C++ this is particularly important as some dumbass may have defined two functions with the same name only differing in parameter constness, and you have no way to know which one will be called.

Your options might be:

  • Fork this library and maintain the few const needed to compile it with a C++ compiler (done)
  • Compile this library in your project with a C compiler and link it against C++ code (more efforts in the build process but more consistency in each language)
  • Get in a time-machine and destroy all attempts at creating C++.

@LeSpocky
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you using a C++ compiler to compile C code?

Maybe. According to CMake I compile iniparser itself as C and as shared library. Our own shared lib linking iniparser is compiled as C++ (but seems to be C I guess, it's not my code) and that could be the problem. However for the moment I'll stick to the fork and the few patches because this is the quickest way to get our work done. O:-)

Thanks for your explanations. :-)

Please sign in to comment.