Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
ndevilla
committed
Mar 3, 2011
1 parent
88c50b7
commit 455b6e1
Showing
19 changed files
with
1,748 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -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! | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -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 | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -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). | |||
|
|||
|
|||
*/ |
Oops, something went wrong.
455b6e1
There was a problem hiding this comment.
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 *
tochar *
?455b6e1
There was a problem hiding this comment.
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.
455b6e1
There was a problem hiding this comment.
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 tochar *
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.455b6e1
There was a problem hiding this comment.
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:
455b6e1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. :-)