pax_global_header00006660000000000000000000000064131765602730014524gustar00rootroot0000000000000052 comment=0a38e85c9cde1e099ca3bf70083bd00f89c3e5b6 iniparser-4.1/000077500000000000000000000000001317656027300133645ustar00rootroot00000000000000iniparser-4.1/.gitignore000066400000000000000000000002301317656027300153470ustar00rootroot00000000000000### Ignore all files created by make # *.a *.o *.so *.so.* /example/iniexample /example/parse # Autogenerate source file /test/AllTests.c /test/testrun iniparser-4.1/.travis.yml000066400000000000000000000002021317656027300154670ustar00rootroot00000000000000language: c env: - ENV_CC=clang - ENV_CC=clang++ - ENV_CC=gcc - ENV_CC=g++ script: CC=$ENV_CC make && CC=$ENV_CC make check iniparser-4.1/AUTHORS000066400000000000000000000003661317656027300144410ustar00rootroot00000000000000Author: Nicolas Devillard This tiny library has received countless contributions and I have not kept track of all the people who contributed. Let them be thanked for their ideas, code, suggestions, corrections, enhancements! iniparser-4.1/FAQ-en.md000066400000000000000000000031321317656027300147140ustar00rootroot00000000000000# iniparser FAQ # ## Is iniparser thread safe ? Starting from version 4, iniparser is designed to be thread-safe, provided you surround it with your own mutex logic. The choice to not add thread safety inside the library has been made to provide more freedom for the developer, especially when dealing with their own custom reading logic e.g. acquiring the mutex, reading entries with iniparser, then releasing the mutex. ## Your build system isn't portable, let me help you... We have received countless contributions from distrib people to modify the Makefile into what they think is the "standard", which we had to reject. The default, standard Makefile for Debian bears absolutely no relationship with the one from SuSE or RedHat and there is no possible way to merge them all. A build system is something so specific to each environment that it is completely pointless to try and push anything that claims to be standard. The provided Makefile in this project is purely here to have something to play with quickly. ## iniparser_dump() is slow The dumping functions are based on fprintf, which can turn out to be surprisingly slow on some embedded platforms. You can replace fprintf by a combined use of sprintf and fwrite, or you can use setvbuf() to change buffering parameters to accomodate fprintf(). Something like: setvbuf(f, NULL, _IOFBF, 0); ## iniparser does not compile with my C++ compiler! See the docs: iniparser is a C library. C++ is quite a different language, despite the promises of compatibility. You will have to modify iniparser quite heavily to make it work with a C++ compiler. Good luck! iniparser-4.1/FAQ-zhcn.md000066400000000000000000000025541317656027300152630ustar00rootroot00000000000000# iniparser FAQ # ## iniparser线程安全吗 ? 从版本4开始,iniparser被设计成线程安全的,你需要围绕它处理你自己的互斥逻辑。 选择不在库中添加线程安全,是为开发者提供更多的自由,特别是在处理他们自己的读 逻辑。如获取互斥锁,用iniparser阅读条目,然后释放互斥体。 ## 你的构建系统不可移植,让我来帮助你... 我们已经收到了来各地的开发人员的无数贡献,将Makefile修改为他们认为是“标准”的 内容,但是我们不得不拒绝。 默认情况下,Debian的标准Makefile与SuSE或RedHat完 全没有关系,没有可能的方式将它们全部合并。 构建系统对于每个环境来说都是特别的, 尝试推动任何声称是标准的东西是完全没有意义的。 在这个项目中提供的Makefile纯粹 是为了快速的把库跑起来。 ## iniparser_dump() 速度慢 dump函数是基于fprintf的,在嵌入式平台上它可能导致很慢。你可以把fprintf换成 sprintf和fwrite的组合,或者可以使用setvbfu()来改变fprintf的缓存参数。比如: setvbuf(f, NULL, _IOFBF, 0); ## 用我的c++编译器不能编译iniparser! 看文档:iniparser是一个C库。虽然C++兼容C,但它却是另外一门语言。让iniparser在 C++编译器下工作,会是一份繁重的工作。祝你好运! iniparser-4.1/INSTALL000066400000000000000000000005411317656027300144150ustar00rootroot00000000000000 iniParser installation instructions ----------------------------------- - Modify the Makefile to suit your environment. - Type 'make' to make the library. - Type 'make check' to make the test program. - Type 'test/iniexample' to launch the test program. - Type 'test/parse' to launch torture tests. Enjoy! N. Devillard Wed Mar 2 21:14:17 CET 2011 iniparser-4.1/LICENSE000066400000000000000000000020731317656027300143730ustar00rootroot00000000000000Copyright (c) 2000-2011 by Nicolas Devillard. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. iniparser-4.1/Makefile000066400000000000000000000030161317656027300150240ustar00rootroot00000000000000# # iniparser Makefile # .PHONY: example # Compiler settings CC ?= gcc CFLAGS += -fPIC -Wall -Wextra -ansi -pedantic ifndef DEBUG ADDITIONAL_CFLAGS ?= -O2 else ADDITIONAL_CFLAGS ?= -g endif CFLAGS += ${ADDITIONAL_CFLAGS} # Ar settings to build the library AR ?= ar ARFLAGS = rcv SHLD = ${CC} ${CFLAGS} LDSHFLAGS = -shared -Wl,-Bsymbolic LDFLAGS += -Wl,-rpath -Wl,/usr/lib -Wl,-rpath,/usr/lib # .so.0 is for version 3.x, .so.1 is 4.x SO_TARGET ?= libiniparser.so.1 # Set RANLIB to ranlib on systems that require it (Sun OS < 4, Mac OSX) # RANLIB = ranlib RANLIB = true RM ?= rm -f # Implicit rules SUFFIXES = .o .c .h .a .so .sl COMPILE.c ?= $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c ifndef V QUIET_AR = @echo "AR $@"; QUIET_CC = @echo "CC $@"; QUIET_LINK = @echo "LINK $@"; QUIET_RANLIB = @echo "RANLIB $@"; endif .c.o: $(QUIET_CC)$(COMPILE.c) $(OUTPUT_OPTION) $< SRCS = src/iniparser.c \ src/dictionary.c OBJS = $(SRCS:.c=.o) default: libiniparser.a $(SO_TARGET) libiniparser.a: $(OBJS) $(QUIET_AR)$(AR) $(ARFLAGS) $@ $^ $(QUIET_RANLIB)$(RANLIB) $@ $(SO_TARGET): $(OBJS) $(QUIET_LINK)$(SHLD) $(LDSHFLAGS) $(LDFLAGS) -o $(SO_TARGET) $(OBJS) \ -Wl,-soname=`basename $(SO_TARGET)` clean: $(RM) $(OBJS) @(cd test ; $(MAKE) clean) veryclean: $(RM) $(OBJS) libiniparser.a $(SO_TARGET) rm -rf ./html ; mkdir html cd example ; $(MAKE) veryclean cd test ; $(MAKE) veryclean docs: @(cd doc ; $(MAKE)) check: $(SO_TARGET) @(cd test ; $(MAKE)) example: libiniparser.a @(cd example ; $(MAKE)) iniparser-4.1/README.md000066400000000000000000000025071317656027300146470ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/ndevilla/iniparser.svg?branch=master)](https://travis-ci.org/ndevilla/iniparser) # Iniparser 4 # ## I - Overview This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory open the file html/index.html with any HTML-capable browser. Key features : - Small : around 1500 sloc inside 4 files (2 .c and 2 .h) - Portable : no dependancies, written in `-ansi -pedantic` C89 - Fully reintrant : easy to make it thread-safe (just surround library calls by mutex) ## II - Building project A simple `make` at the root of the project should be enough to get the static (i.e. `libiniparser.a`) and shared (i.e. `libiniparser.so.0`) libraries compiled. You should consider trying the following rules too : - `make check` : run the unitary tests - `make example` : compile the example, run it with `./example/iniexample` ## III - License This software is released under MIT License. See LICENSE for full informations ## IV - Versions Current version is 4.1. Version 4.0 introduces breaking changes in the api. Older versions 3.1 and 3.2 with the legacy api are available as tags. ## V - FAQ See [FAQ-en.md](FAQ-en.md) in this directory for answers to Frequently Asked Questions. 还有简化中国翻译在[FAQ-zhcn.md](FAQ-zhcn.md). iniparser-4.1/doc/000077500000000000000000000000001317656027300141315ustar00rootroot00000000000000iniparser-4.1/doc/Makefile000066400000000000000000000004231317656027300155700ustar00rootroot00000000000000# # 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 iniparser-4.1/doc/iniparser.dox000066400000000000000000000043201317656027300166400ustar00rootroot00000000000000PROJECT_NAME = iniparser PROJECT_NUMBER = 4.1 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 iniparser-4.1/doc/iniparser.main000066400000000000000000000156161317656027300170040ustar00rootroot00000000000000 /** @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). */ iniparser-4.1/example/000077500000000000000000000000001317656027300150175ustar00rootroot00000000000000iniparser-4.1/example/Makefile000066400000000000000000000006321317656027300164600ustar00rootroot00000000000000# # iniparser tests Makefile # CC ?= gcc CFLAGS += -g -I../src LFLAGS += -L.. -liniparser AR ?= ar ARFLAGS += rcv RM ?= rm -f default: all all: iniexample parse iniexample: iniexample.c $(CC) $(CFLAGS) -o iniexample iniexample.c -I../src -L.. -liniparser parse: parse.c $(CC) $(CFLAGS) -o parse parse.c -I../src -L.. -liniparser clean veryclean: $(RM) iniexample example.ini parse iniparser-4.1/example/iniexample.c000066400000000000000000000044511317656027300173220ustar00rootroot00000000000000#include #include #include #include #include "iniparser.h" void create_example_ini_file(void); int parse_ini_file(char * ini_name); int main(int argc, char * argv[]) { int status ; if (argc<2) { create_example_ini_file(); status = parse_ini_file("example.ini"); } else { status = parse_ini_file(argv[1]); } return status ; } void create_example_ini_file(void) { FILE * ini ; if ((ini=fopen("example.ini", "w"))==NULL) { fprintf(stderr, "iniparser: cannot create example.ini\n"); return ; } fprintf(ini, "#\n" "# This is an example of ini file\n" "#\n" "\n" "[Pizza]\n" "\n" "Ham = yes ;\n" "Mushrooms = TRUE ;\n" "Capres = 0 ;\n" "Cheese = Non ;\n" "\n" "\n" "[Wine]\n" "\n" "Grape = Cabernet Sauvignon ;\n" "Year = 1989 ;\n" "Country = Spain ;\n" "Alcohol = 12.5 ;\n" "\n"); fclose(ini); } int parse_ini_file(char * ini_name) { dictionary * ini ; /* Some temporary variables to hold query results */ int b ; int i ; double d ; const char * s ; ini = iniparser_load(ini_name); if (ini==NULL) { fprintf(stderr, "cannot parse file: %s\n", ini_name); return -1 ; } iniparser_dump(ini, stderr); /* Get pizza attributes */ printf("Pizza:\n"); b = iniparser_getboolean(ini, "pizza:ham", -1); printf("Ham: [%d]\n", b); b = iniparser_getboolean(ini, "pizza:mushrooms", -1); printf("Mushrooms: [%d]\n", b); b = iniparser_getboolean(ini, "pizza:capres", -1); printf("Capres: [%d]\n", b); b = iniparser_getboolean(ini, "pizza:cheese", -1); printf("Cheese: [%d]\n", b); /* Get wine attributes */ printf("Wine:\n"); s = iniparser_getstring(ini, "wine:grape", NULL); printf("Grape: [%s]\n", s ? s : "UNDEF"); i = iniparser_getint(ini, "wine:year", -1); printf("Year: [%d]\n", i); s = iniparser_getstring(ini, "wine:country", NULL); printf("Country: [%s]\n", s ? s : "UNDEF"); d = iniparser_getdouble(ini, "wine:alcohol", -1.0); printf("Alcohol: [%g]\n", d); iniparser_freedict(ini); return 0 ; } iniparser-4.1/example/parse.c000066400000000000000000000006311317656027300162750ustar00rootroot00000000000000#include #include #include #include #include "iniparser.h" int main(int argc, char * argv[]) { dictionary * ini ; char * ini_name ; if (argc<2) { ini_name = "twisted.ini"; } else { ini_name = argv[1] ; } ini = iniparser_load(ini_name); iniparser_dump(ini, stdout); iniparser_freedict(ini); return 0 ; } iniparser-4.1/example/twisted-errors.ini000066400000000000000000000001341317656027300205130ustar00rootroot00000000000000# # All of these should trigger syntax errors # [section] hello world hello \ world a + b ; iniparser-4.1/example/twisted-genhuge.py000066400000000000000000000003741317656027300205000ustar00rootroot00000000000000# -*- coding: utf-8 -*- import os import sys if __name__=="__main__": f=open('twisted-massive.ini', 'w') for i in range(100): f.write('[%03d]\n' % i) for j in range(100): f.write('key-%03d=1;\n' % j) f.close() iniparser-4.1/example/twisted-ofkey.ini000066400000000000000000000143701317656027300203230ustar00rootroot00000000000000# Stress testing buffers for overflows [long] # Shitload key size aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1 iniparser-4.1/example/twisted-ofval.ini000066400000000000000000000123311317656027300203100ustar00rootroot00000000000000# Shitload data size [long] a=\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890; iniparser-4.1/example/twisted.ini000066400000000000000000000023271317656027300172070ustar00rootroot00000000000000# # Twisted.ini # This file is meant for regression tests # Different blank settings around the equal sign [blanks] a=1 b=1; c=1; comment d=1# comment e =1 f =1; g =1; comment h =1# comment i= 1 j= 1; k= 1; comment l= 1# comment m = 1 n = 1; o = 1; comment p = 1# comment q=1 ; r=1 ; comment s=1 ;comment t=1 #comment # Empty values [empty] a = '' b = "" c = '' ; d = "" ; e = '' ; comment f = "" ; comment g = h = ; i = ; comment j = # comment k= l=; m=;comment n=# # Peculiar values [peculiar] a=';'; b='#'# c=';';comment d='#'#comment e=\; f=\# g=\;comment h=\#comment i=;; j=## k=;;;;;;;;;; l=########## # Quotes [quotes] s1=' s2='' s3=''' s4='''' d1=" d2="" d3=""" d4="""" m1='"' m2="'" h1=hello'world h2='hello'world h3='hello'world' h4=hello"world h5="hello"world h6="hello"world" # Section names [a] [ b] [c ] [ d ] [ begin end ] [ open[ ] # Multi-line inputs [multi] a = begin\ end b = begin \ end c = begin \ end d = 1\ 2\ 3\ 4 e = 1 \ 2 \ 3 \ 4 f = 1 ; \ hidden = because of the preceding backslash multi-lining the comment ; visible = 1 g = 1 #\ and now this comment is hidden too \ and this one too h = 1 multi \ line \ key = 1 multi \ line \ key = \ multi \ line \ value ; # end of file iniparser-4.1/html/000077500000000000000000000000001317656027300143305ustar00rootroot00000000000000iniparser-4.1/html/doxygen.css000066400000000000000000000173471317656027300165330ustar00rootroot00000000000000/* The standard CSS for doxygen */ body, table, div, p, dl { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; font-size: 12px; } /* @group Heading Levels */ h1 { text-align: center; font-size: 150%; } h2 { font-size: 120%; } h3 { font-size: 100%; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd, p.starttd { margin-top: 2px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } /* @end */ caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab{ background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; padding: 2px; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #153788; font-weight: normal; text-decoration: none; } .contents a:visited { color: #1b77c5; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #6666cc; color: #ffffff; border: 1px double #9295C2; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code { color: #3030f0; } a.codeRef { color: #3030f0; } /* @end */ dl.el { margin-left: -1cm; } .fragment { font-family: monospace, fixed; font-size: 105%; } pre.fragment { border: 1px solid #CCCCCC; background-color: #f5f5f5; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; word-wrap: break-word; font-size: 9pt; line-height: 125%; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } div.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background: white; color: black; margin-right: 20px; margin-left: 20px; } td.indexkey { background-color: #e8eef2; font-weight: bold; border: 1px solid #CCCCCC; margin: 2px 0px 2px 0; padding: 2px 10px; } td.indexvalue { background-color: #e8eef2; border: 1px solid #CCCCCC; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #f0f0f0; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } div.center { text-align: center; margin-top: 0px; margin-bottom: 0px; padding: 0px; } div.center img { border: 0px; } img.footer { border: 0px; vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } /* @end */ .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #84b0c7; } th.dirtab { background: #e8eef2; font-weight: bold; } hr { height: 0px; border: none; border-top: 1px solid #666; } hr.footer { height: 1px; } /* @group Member Descriptions */ .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #FAFAFA; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memItemRight, .memTemplParams { border-top: 1px solid #ccc; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memTemplParams { color: #606060; white-space: nowrap; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #606060; font-weight: normal; margin-left: 3px; } .memnav { background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .memitem { padding: 0; margin-bottom: 10px; } .memname { white-space: nowrap; font-weight: bold; margin-left: 6px; } .memproto { border-top: 1px solid #84b0c7; border-left: 1px solid #84b0c7; border-right: 1px solid #84b0c7; padding: 0; background-color: #d5e1e8; font-weight: bold; /* firefox specific markup */ background-image: -moz-linear-gradient(rgba(228, 233, 245, 1.0) 0%, rgba(193, 205, 232, 1.0) 100%); -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 8px; -moz-border-radius-topleft: 8px; /* webkit specific markup */ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(228, 233, 245, 1.0)), to(rgba(193, 205, 232, 1.0))); -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 8px; -webkit-border-top-left-radius: 8px; } .memdoc { border-bottom: 1px solid #84b0c7; border-left: 1px solid #84b0c7; border-right: 1px solid #84b0c7; padding: 2px 5px; background-color: #eef3f5; border-top-width: 0; /* firefox specific markup */ -moz-border-radius-bottomleft: 8px; -moz-border-radius-bottomright: 8px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; /* webkit specific markup */ -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } /* @end */ /* @group Directory (tree) */ /* for the tree view */ .ftvtree { font-family: sans-serif; margin: 0.5em; } /* these are for tree view when used as main index */ .directory { font-size: 9pt; font-weight: bold; } .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } /* The following two styles can be used to replace the root node title with an image of your choice. Simply uncomment the next two styles, specify the name of your image and be sure to set 'height' to the proper pixel height of your image. */ /* .directory h3.swap { height: 61px; background-repeat: no-repeat; background-image: url("yourimage.gif"); } .directory h3.swap span { display: none; } */ .directory > h3 { margin-top: 0; } .directory p { margin: 0px; white-space: nowrap; } .directory div { display: none; margin: 0px; } .directory img { vertical-align: -30%; } /* these are for tree view when not used as main index */ .directory-alt { font-size: 100%; font-weight: bold; } .directory-alt h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } .directory-alt > h3 { margin-top: 0; } .directory-alt p { margin: 0px; white-space: nowrap; } .directory-alt div { display: none; margin: 0px; } .directory-alt img { vertical-align: -30%; } /* @end */ address { font-style: normal; color: #333; } table.doxtable { border-collapse:collapse; } table.doxtable td, table.doxtable th { border: 1px solid #153788; padding: 3px 7px 2px; } table.doxtable th { background-color: #254798; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; text-align:left; } iniparser-4.1/html/doxygen.png000066400000000000000000000024011317656027300165100ustar00rootroot00000000000000PNG  IHDRd-ok>gAMAOX2tEXtSoftwareAdobe ImageReadyqe<]PLTEǾ"&ﶻޠ{ԍ눙נED9hg]_X<@:#mhU1tRNSvIDATxbC: d#h` @X",***LK.], X@t b @BD6%""  % B:Hf@ RPy"K`\PbC(!II!h(!Cąl!0[X\J\$TM(>a$S @ Ш@R.$LJBRAG1 (FPhhT%!`&q%u P    CT$B|Wl!B`R$( @A%%@,(%$RPmB U`1IYB  99\1 yCCCf"[N'=TGȒl8^K5<SRɤ%@@  b1qAXH&BR y nP4A j>  t!+(.WQA2MU܂ `1%`19F< 3cZ`e!\ D+. 83!lYYA -6EJV @XXX 4 @86`RdB4I " "@xrʌHA`f ȰC"XV0C b@2H ȓ p)!( 04)(%R $Tʀbb,s@7 Ѱ?f֗\PIx!I"Ȉ3 QYt^^gv- }>WJOAV`$&#88\FF SFJ$ƀƊ 4 - Hf ?5 k1d, ."FˀI"4Hgx|fm)))9. aMD& X@t b @%DK.], X@t b @d`ɽSOIENDB`iniparser-4.1/html/globals_func.html000066400000000000000000000047431317656027300176640ustar00rootroot00000000000000 iniparser: Data Fields
 
Generated on Wed Mar 2 22:04:59 2011 for iniparser by  doxygen 1.6.3
iniparser-4.1/html/index.html000066400000000000000000000224541317656027300163340ustar00rootroot00000000000000 iniparser: iniparser documentation

iniparser documentation

4.0

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.

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:

    [Section Name]
	

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:

    Key = value ; comment
	

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:

    Hello = "this is a long string value" ; comment
    Hello = this is a long string value ; comment
	

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 (\).

    Multiple = Line 1 \
    Line 2 \
    Line 3 \
    Line 4 ; comment
    

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)

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:

    #include "iniparser.h"

And link your program with the iniparser library by adding -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.

Library reference

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

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:

    [Section]
    Keyword = value ; comment
	

is converted to the following key pair:

    ("section:keyword", "value")
	

This means that if you want to retrieve the value that was stored in the section called Pizza, in the keyword Cheese, you would make a request to the dictionary for "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 dictionary structure. This latter object should remain opaque to the user and only accessed through the following accessor functions:

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:

    iniparser_set(ini, "section", NULL);
    iniparser_set(ini, "section:key1", NULL);
    iniparser_set(ini, "section:key2", NULL);
    

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.

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.

Authors

Nicolas Devillard (ndevilla AT free DOT fr).

Generated on Sun Jun 12 19:07:18 2016 for iniparser by  doxygen 1.8.11
iniparser-4.1/html/iniparser_8h.html000066400000000000000000000672651317656027300176310ustar00rootroot00000000000000 iniparser: iniparser.h File Reference

iniparser.h File Reference

Parser for ini files. More...

Functions

int iniparser_getnsec (dictionary *d)
 Get number of sections in a dictionary.
char * iniparser_getsecname (dictionary *d, int n)
 Get name for section n in a dictionary.
void iniparser_dump_ini (dictionary *d, FILE *f)
 Save a dictionary to a loadable ini file.
void iniparser_dump (dictionary *d, FILE *f)
 Dump a dictionary to an opened file pointer.
char * iniparser_getstring (dictionary *d, char *key, char *def)
 Get the string associated to a key.
int iniparser_getint (dictionary *d, char *key, int notfound)
 Get the string associated to a key, convert to an int.
double iniparser_getdouble (dictionary *d, char *key, double notfound)
 Get the string associated to a key, convert to a double.
int iniparser_getboolean (dictionary *d, char *key, int notfound)
 Get the string associated to a key, convert to a boolean.
int iniparser_set (dictionary *ini, char *entry, char *val)
 Set an entry in a dictionary.
void iniparser_unset (dictionary *ini, char *entry)
 Delete an entry in a dictionary.
int iniparser_find_entry (dictionary *ini, char *entry)
 Finds out if a given entry exists in a dictionary.
dictionary * iniparser_load (char *ininame)
 Parse an ini file and return an allocated dictionary object.
void iniparser_freedict (dictionary *d)
 Free all memory associated to an ini dictionary.

Detailed Description

Parser for ini files.

Author:
N. Devillard
Date:
Sep 2007
Version:
3.0

Function Documentation

void iniparser_dump ( dictionary *  d,
FILE *  f 
)

Dump a dictionary to an opened file pointer.

Parameters:
d Dictionary to dump.
f Opened file pointer to dump to.
Returns:
void

This function prints out the contents of a dictionary, one element by line, onto the provided file pointer. It is OK to specify stderr or stdout as output files. This function is meant for debugging purposes mostly.

void iniparser_dump_ini ( dictionary *  d,
FILE *  f 
)

Save a dictionary to a loadable ini file.

Parameters:
d Dictionary to dump
f Opened file pointer to dump to
Returns:
void

This function dumps a given dictionary into a loadable ini file. It is Ok to specify stderr or stdout as output files.

int iniparser_find_entry ( dictionary *  ini,
char *  entry 
)

Finds out if a given entry exists in a dictionary.

Parameters:
ini Dictionary to search
entry Name of the entry to look for
Returns:
integer 1 if entry exists, 0 otherwise

Finds out if a given entry exists in the dictionary. Since sections are stored as keys with NULL associated values, this is the only way of querying for the presence of sections in a dictionary.

void iniparser_freedict ( dictionary *  d  ) 

Free all memory associated to an ini dictionary.

Parameters:
d Dictionary to free
Returns:
void

Free all memory associated to an ini dictionary. It is mandatory to call this function before the dictionary object gets out of the current context.

int iniparser_getboolean ( dictionary *  d,
char *  key,
int  notfound 
)

Get the string associated to a key, convert to a boolean.

Parameters:
d Dictionary to search
key Key string to look for
notfound Value to return in case of error
Returns:
integer

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.

A true boolean is found if one of the following is matched:

  • A string starting with 'y'
  • A string starting with 'Y'
  • A string starting with 't'
  • A string starting with 'T'
  • A string starting with '1'

A false boolean is found if one of the following is matched:

  • A string starting with 'n'
  • A string starting with 'N'
  • A string starting with 'f'
  • A string starting with 'F'
  • A string starting with '0'

The notfound value returned if no boolean is identified, does not necessarily have to be 0 or 1.

double iniparser_getdouble ( dictionary *  d,
char *  key,
double  notfound 
)

Get the string associated to a key, convert to a double.

Parameters:
d Dictionary to search
key Key string to look for
notfound Value to return in case of error
Returns:
double

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.

int iniparser_getint ( dictionary *  d,
char *  key,
int  notfound 
)

Get the string associated to a key, convert to an int.

Parameters:
d Dictionary to search
key Key string to look for
notfound Value to return in case of error
Returns:
integer

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.

Supported values for integers include the usual C notation so decimal, octal (starting with 0) and hexadecimal (starting with 0x) are supported. Examples:

  • "42" -> 42
  • "042" -> 34 (octal -> decimal)
  • "0x42" -> 66 (hexa -> decimal)

Warning: the conversion may overflow in various ways. Conversion is totally outsourced to strtol(), see the associated man page for overflow handling.

Credits: Thanks to A. Becker for suggesting strtol()

int iniparser_getnsec ( dictionary *  d  ) 

Get number of sections in a dictionary.

Parameters:
d Dictionary to examine
Returns:
int Number of sections found in dictionary

This function returns the number of sections found in a dictionary. The test to recognize sections is done on the string stored in the dictionary: a section name is given as "section" whereas a key is stored as "section:key", thus the test looks for entries that do not contain a colon.

This clearly fails in the case a section name contains a colon, but this should simply be avoided.

This function returns -1 in case of error.

char* iniparser_getsecname ( dictionary *  d,
int  n 
)

Get name for section n in a dictionary.

Parameters:
d Dictionary to examine
n Section number (from 0 to nsec-1).
Returns:
Pointer to char string

This function locates the n-th section in a dictionary and returns its name as a pointer to a string statically allocated inside the dictionary. Do not free or modify the returned string!

This function returns NULL in case of error.

char* iniparser_getstring ( dictionary *  d,
char *  key,
char *  def 
)

Get the string associated to a key.

Parameters:
d Dictionary to search
key Key string to look for
def Default value to return if key not found.
Returns:
pointer to statically allocated character string

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the pointer passed as 'def' is returned. The returned char pointer is pointing to a string allocated in the dictionary, do not free or modify it.

dictionary* iniparser_load ( char *  ininame  ) 

Parse an ini file and return an allocated dictionary object.

Parameters:
ininame Name of the ini file to read.
Returns:
Pointer to newly allocated dictionary

This is the parser for ini files. This function is called, providing the name of the file to be read. It returns a dictionary object that should not be accessed directly, but through accessor functions instead.

The returned dictionary must be freed using iniparser_freedict().

int iniparser_set ( dictionary *  ini,
char *  entry,
char *  val 
)

Set an entry in a dictionary.

Parameters:
ini Dictionary to modify.
entry Entry to modify (entry name)
val New value to associate to the entry.
Returns:
int 0 if Ok, -1 otherwise.

If the given entry can be found in the dictionary, it is modified to contain the provided value. If it cannot be found, -1 is returned. It is Ok to set val to NULL.

void iniparser_unset ( dictionary *  ini,
char *  entry 
)

Delete an entry in a dictionary.

Parameters:
ini Dictionary to modify
entry Entry to delete (entry name)
Returns:
void

If the given entry can be found, it is deleted from the dictionary.

Generated on Wed Mar 2 22:04:59 2011 for iniparser by  doxygen 1.6.3
iniparser-4.1/html/iniparser_8main.html000066400000000000000000000015351317656027300203120ustar00rootroot00000000000000 iniparser: iniparser.main File Reference

iniparser.main File Reference

Generated on Wed Mar 2 22:04:59 2011 for iniparser by  doxygen 1.6.3
iniparser-4.1/html/tab_b.gif000066400000000000000000000000431317656027300160630ustar00rootroot00000000000000GIF89a,D;iniparser-4.1/html/tab_l.gif000066400000000000000000000013021317656027300160740ustar00rootroot00000000000000GIF89a ,薴ŝɯͻ, ,@P`H$!%CqVe2XJ(Ġ+3 2$ kv-u*"}|}|~q(" $f 'l(&&$r & !){rƲεҽͼиP?Bm A%V܈!k/Đ;^$Ɩ#Mf)f͇(WLK҄ I)L:eD Cx*4 Uh %A^NKbeXkx!2t !5t]$%X.i[]YfEkg`:zҞ;}jaaM׸c瞽vۺ8ȋ'?9積G_>yu_ߞ]zw߭Ǿm浏G~თ/>٫|W}v;iniparser-4.1/html/tab_r.gif000066400000000000000000000050311317656027300161050ustar00rootroot00000000000000GIF89a,薴ŝɯͻ,,@pH,Ȥrl:ШtJZجv h d@L"F:򑐌$9 (8&Nz (GFB^!˨)WVl)1 w̥.wY0Ib|Hpf:e pJ}Ȧ6nz 80%"8v~ @JЂMBІ:D'ZPKF ּ&16юz HGJRb L5Җ0LgJӚ#(e>Ӟ@ PJԢHMRԦ:PTJժ&5;%Uծz` XJVCjYֶp\Uxͫ^׾i)$Mb:v, ಘͬf7z hGKҚMjWֺ*$SPͭnwm +Mr:E?9Zͮv9" xKbLz^A|ͯ0/LN(; n0'LaJ0{/{ؘG|(SCr. v1wc6@LdHNd/PLeOXp|+s2L_153M5t3_:wsgʹπp?/FFЎt!-JҖ1NӞuA-Pԝ>53UWծ4cYZѶsA׀5,aƶ3=e3~-3Sc6mo2Mq>7ӭn$D~7,y1m}v\/N3#S\gu-mO0C\'_S^|.c.0ל49~s=3d:u)?F;ˮW|;W)vt˽w|=xA;iniparser-4.1/html/tabs.css000066400000000000000000000034641317656027300160020ustar00rootroot00000000000000/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ DIV.tabs { float : left; width : 100%; background : url("tab_b.gif") repeat-x bottom; margin-bottom : 4px; } DIV.tabs UL { margin : 0px; padding-left : 10px; list-style : none; } DIV.tabs LI, DIV.tabs FORM { display : inline; margin : 0px; padding : 0px; } DIV.tabs FORM { float : right; } DIV.tabs A { float : left; background : url("tab_r.gif") no-repeat right top; border-bottom : 1px solid #84B0C7; font-size : 80%; font-weight : bold; text-decoration : none; } DIV.tabs A:hover { background-position: 100% -150px; } DIV.tabs A:link, DIV.tabs A:visited, DIV.tabs A:active, DIV.tabs A:hover { color: #1A419D; } DIV.tabs SPAN { float : left; display : block; background : url("tab_l.gif") no-repeat left top; padding : 5px 9px; white-space : nowrap; } DIV.tabs #MSearchBox { float : right; display : inline; font-size : 1em; } DIV.tabs TD { font-size : 80%; font-weight : bold; text-decoration : none; } /* Commented Backslash Hack hides rule from IE5-Mac \*/ DIV.tabs SPAN {float : none;} /* End IE5-Mac hack */ DIV.tabs A:hover SPAN { background-position: 0% -150px; } DIV.tabs LI.current A { background-position: 100% -150px; border-width : 0px; } DIV.tabs LI.current SPAN { background-position: 0% -150px; padding-bottom : 6px; } DIV.navpath { background : none; border : none; border-bottom : 1px solid #84B0C7; text-align : center; margin : 2px; padding : 2px; } iniparser-4.1/src/000077500000000000000000000000001317656027300141535ustar00rootroot00000000000000iniparser-4.1/src/dictionary.c000066400000000000000000000272211317656027300164700ustar00rootroot00000000000000/*-------------------------------------------------------------------------*/ /** @file dictionary.c @author N. Devillard @brief Implements a dictionary for string variables. This module implements a simple dictionary object, i.e. a list of string/string associations. This object is useful to store e.g. informations retrieved from a configuration file (ini files). */ /*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- Includes ---------------------------------------------------------------------------*/ #include "dictionary.h" #include #include #include #include /** Maximum value size for integers and doubles. */ #define MAXVALSZ 1024 /** Minimal allocated number of entries in a dictionary */ #define DICTMINSZ 128 /** Invalid key token */ #define DICT_INVALID_KEY ((char*)-1) /*--------------------------------------------------------------------------- Private functions ---------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /** @brief Duplicate a string @param s String to duplicate @return Pointer to a newly allocated string, to be freed with free() This is a replacement for strdup(). This implementation is provided for systems that do not have it. */ /*--------------------------------------------------------------------------*/ static char * xstrdup(const char * s) { char * t ; size_t len ; if (!s) return NULL ; len = strlen(s) + 1 ; t = (char*) malloc(len) ; if (t) { memcpy(t, s, len) ; } return t ; } /*-------------------------------------------------------------------------*/ /** @brief Double the size of the dictionary @param d Dictionary to grow @return This function returns non-zero in case of failure */ /*--------------------------------------------------------------------------*/ static int dictionary_grow(dictionary * d) { char ** new_val ; char ** new_key ; unsigned * new_hash ; new_val = (char**) calloc(d->size * 2, sizeof *d->val); new_key = (char**) calloc(d->size * 2, sizeof *d->key); new_hash = (unsigned*) calloc(d->size * 2, sizeof *d->hash); if (!new_val || !new_key || !new_hash) { /* An allocation failed, leave the dictionary unchanged */ if (new_val) free(new_val); if (new_key) free(new_key); if (new_hash) free(new_hash); return -1 ; } /* Initialize the newly allocated space */ memcpy(new_val, d->val, d->size * sizeof(char *)); memcpy(new_key, d->key, d->size * sizeof(char *)); memcpy(new_hash, d->hash, d->size * sizeof(unsigned)); /* Delete previous data */ free(d->val); free(d->key); free(d->hash); /* Actually update the dictionary */ d->size *= 2 ; d->val = new_val; d->key = new_key; d->hash = new_hash; return 0 ; } /*--------------------------------------------------------------------------- Function codes ---------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /** @brief Compute the hash key for a string. @param key Character string to use for key. @return 1 unsigned int on at least 32 bits. This hash function has been taken from an Article in Dr Dobbs Journal. This is normally a collision-free function, distributing keys evenly. The key is stored anyway in the struct so that collision can be avoided by comparing the key itself in last resort. */ /*--------------------------------------------------------------------------*/ unsigned dictionary_hash(const char * key) { size_t len ; unsigned hash ; size_t i ; if (!key) return 0 ; len = strlen(key); for (hash=0, i=0 ; i>6) ; } hash += (hash <<3); hash ^= (hash >>11); hash += (hash <<15); return hash ; } /*-------------------------------------------------------------------------*/ /** @brief Create a new dictionary object. @param size Optional initial size of the dictionary. @return 1 newly allocated dictionary objet. This function allocates a new dictionary object of given size and returns it. If you do not know in advance (roughly) the number of entries in the dictionary, give size=0. */ /*-------------------------------------------------------------------------*/ dictionary * dictionary_new(size_t size) { dictionary * d ; /* If no size was specified, allocate space for DICTMINSZ */ if (sizesize = size ; d->val = (char**) calloc(size, sizeof *d->val); d->key = (char**) calloc(size, sizeof *d->key); d->hash = (unsigned*) calloc(size, sizeof *d->hash); } return d ; } /*-------------------------------------------------------------------------*/ /** @brief Delete a dictionary object @param d dictionary object to deallocate. @return void Deallocate a dictionary object and all memory associated to it. */ /*--------------------------------------------------------------------------*/ void dictionary_del(dictionary * d) { ssize_t i ; if (d==NULL) return ; for (i=0 ; isize ; i++) { if (d->key[i]!=NULL) free(d->key[i]); if (d->val[i]!=NULL) free(d->val[i]); } free(d->val); free(d->key); free(d->hash); free(d); return ; } /*-------------------------------------------------------------------------*/ /** @brief Get a value from a dictionary. @param d dictionary object to search. @param key Key to look for in the dictionary. @param def Default value to return if key not found. @return 1 pointer to internally allocated character string. This function locates a key in a dictionary and returns a pointer to its value, or the passed 'def' pointer if no such key can be found in dictionary. The returned character pointer points to data internal to the dictionary object, you should not try to free it or modify it. */ /*--------------------------------------------------------------------------*/ const char * dictionary_get(const dictionary * d, const char * key, const char * def) { unsigned hash ; ssize_t i ; hash = dictionary_hash(key); for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; /* Compare hash */ if (hash==d->hash[i]) { /* Compare string, to avoid hash collisions */ if (!strcmp(key, d->key[i])) { return d->val[i] ; } } } return def ; } /*-------------------------------------------------------------------------*/ /** @brief Set a value in a dictionary. @param d dictionary object to modify. @param key Key to modify or add. @param val Value to add. @return int 0 if Ok, anything else otherwise If the given key is found in the dictionary, the associated value is replaced by the provided one. If the key cannot be found in the dictionary, it is added to it. It is Ok to provide a NULL value for val, but NULL values for the dictionary or the key are considered as errors: the function will return immediately in such a case. Notice that if you dictionary_set a variable to NULL, a call to dictionary_get will return a NULL value: the variable will be found, and its value (NULL) is returned. In other words, setting the variable content to NULL is equivalent to deleting the variable from the dictionary. It is not possible (in this implementation) to have a key in the dictionary without value. This function returns non-zero in case of failure. */ /*--------------------------------------------------------------------------*/ int dictionary_set(dictionary * d, const char * key, const char * val) { ssize_t i ; unsigned hash ; if (d==NULL || key==NULL) return -1 ; /* Compute hash for this key */ hash = dictionary_hash(key) ; /* Find if value is already in dictionary */ if (d->n>0) { for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; if (hash==d->hash[i]) { /* Same hash value */ if (!strcmp(key, d->key[i])) { /* Same key */ /* Found a value: modify and return */ if (d->val[i]!=NULL) free(d->val[i]); d->val[i] = (val ? xstrdup(val) : NULL); /* Value has been modified: return */ return 0 ; } } } } /* Add a new value */ /* See if dictionary needs to grow */ if (d->n==d->size) { /* Reached maximum size: reallocate dictionary */ if (dictionary_grow(d) != 0) return -1; } /* Insert key in the first empty slot. Start at d->n and wrap at d->size. Because d->n < d->size this will necessarily terminate. */ for (i=d->n ; d->key[i] ; ) { if(++i == d->size) i = 0; } /* Copy key */ d->key[i] = xstrdup(key); d->val[i] = (val ? xstrdup(val) : NULL) ; d->hash[i] = hash; d->n ++ ; return 0 ; } /*-------------------------------------------------------------------------*/ /** @brief Delete a key in a dictionary @param d dictionary object to modify. @param key Key to remove. @return void This function deletes a key in a dictionary. Nothing is done if the key cannot be found. */ /*--------------------------------------------------------------------------*/ void dictionary_unset(dictionary * d, const char * key) { unsigned hash ; ssize_t i ; if (key == NULL || d == NULL) { return; } hash = dictionary_hash(key); for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; /* Compare hash */ if (hash==d->hash[i]) { /* Compare string, to avoid hash collisions */ if (!strcmp(key, d->key[i])) { /* Found key */ break ; } } } if (i>=d->size) /* Key not found */ return ; free(d->key[i]); d->key[i] = NULL ; if (d->val[i]!=NULL) { free(d->val[i]); d->val[i] = NULL ; } d->hash[i] = 0 ; d->n -- ; return ; } /*-------------------------------------------------------------------------*/ /** @brief Dump a dictionary to an opened file pointer. @param d Dictionary to dump @param f Opened file pointer. @return void Dumps a dictionary onto an opened file pointer. Key pairs are printed out as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as output file pointers. */ /*--------------------------------------------------------------------------*/ void dictionary_dump(const dictionary * d, FILE * out) { ssize_t i ; if (d==NULL || out==NULL) return ; if (d->n<1) { fprintf(out, "empty dictionary\n"); return ; } for (i=0 ; isize ; i++) { if (d->key[i]) { fprintf(out, "%20s\t[%s]\n", d->key[i], d->val[i] ? d->val[i] : "UNDEF"); } } return ; } iniparser-4.1/src/dictionary.h000066400000000000000000000147671317656027300165100ustar00rootroot00000000000000 /*-------------------------------------------------------------------------*/ /** @file dictionary.h @author N. Devillard @brief Implements a dictionary for string variables. This module implements a simple dictionary object, i.e. a list of string/string associations. This object is useful to store e.g. informations retrieved from a configuration file (ini files). */ /*--------------------------------------------------------------------------*/ #ifndef _DICTIONARY_H_ #define _DICTIONARY_H_ /*--------------------------------------------------------------------------- Includes ---------------------------------------------------------------------------*/ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /*--------------------------------------------------------------------------- New types ---------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /** @brief Dictionary object This object contains a list of string/string associations. Each association is identified by a unique string key. Looking up values in the dictionary is speeded up by the use of a (hopefully collision-free) hash function. */ /*-------------------------------------------------------------------------*/ typedef struct _dictionary_ { int n ; /** Number of entries in dictionary */ ssize_t size ; /** Storage size */ char ** val ; /** List of string values */ char ** key ; /** List of string keys */ unsigned * hash ; /** List of hash values for keys */ } dictionary ; /*--------------------------------------------------------------------------- Function prototypes ---------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /** @brief Compute the hash key for a string. @param key Character string to use for key. @return 1 unsigned int on at least 32 bits. This hash function has been taken from an Article in Dr Dobbs Journal. This is normally a collision-free function, distributing keys evenly. The key is stored anyway in the struct so that collision can be avoided by comparing the key itself in last resort. */ /*--------------------------------------------------------------------------*/ unsigned dictionary_hash(const char * key); /*-------------------------------------------------------------------------*/ /** @brief Create a new dictionary object. @param size Optional initial size of the dictionary. @return 1 newly allocated dictionary objet. This function allocates a new dictionary object of given size and returns it. If you do not know in advance (roughly) the number of entries in the dictionary, give size=0. */ /*--------------------------------------------------------------------------*/ dictionary * dictionary_new(size_t size); /*-------------------------------------------------------------------------*/ /** @brief Delete a dictionary object @param d dictionary object to deallocate. @return void Deallocate a dictionary object and all memory associated to it. */ /*--------------------------------------------------------------------------*/ void dictionary_del(dictionary * vd); /*-------------------------------------------------------------------------*/ /** @brief Get a value from a dictionary. @param d dictionary object to search. @param key Key to look for in the dictionary. @param def Default value to return if key not found. @return 1 pointer to internally allocated character string. This function locates a key in a dictionary and returns a pointer to its value, or the passed 'def' pointer if no such key can be found in dictionary. The returned character pointer points to data internal to the dictionary object, you should not try to free it or modify it. */ /*--------------------------------------------------------------------------*/ const char * dictionary_get(const dictionary * d, const char * key, const char * def); /*-------------------------------------------------------------------------*/ /** @brief Set a value in a dictionary. @param d dictionary object to modify. @param key Key to modify or add. @param val Value to add. @return int 0 if Ok, anything else otherwise If the given key is found in the dictionary, the associated value is replaced by the provided one. If the key cannot be found in the dictionary, it is added to it. It is Ok to provide a NULL value for val, but NULL values for the dictionary or the key are considered as errors: the function will return immediately in such a case. Notice that if you dictionary_set a variable to NULL, a call to dictionary_get will return a NULL value: the variable will be found, and its value (NULL) is returned. In other words, setting the variable content to NULL is equivalent to deleting the variable from the dictionary. It is not possible (in this implementation) to have a key in the dictionary without value. This function returns non-zero in case of failure. */ /*--------------------------------------------------------------------------*/ int dictionary_set(dictionary * vd, const char * key, const char * val); /*-------------------------------------------------------------------------*/ /** @brief Delete a key in a dictionary @param d dictionary object to modify. @param key Key to remove. @return void This function deletes a key in a dictionary. Nothing is done if the key cannot be found. */ /*--------------------------------------------------------------------------*/ void dictionary_unset(dictionary * d, const char * key); /*-------------------------------------------------------------------------*/ /** @brief Dump a dictionary to an opened file pointer. @param d Dictionary to dump @param f Opened file pointer. @return void Dumps a dictionary onto an opened file pointer. Key pairs are printed out as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as output file pointers. */ /*--------------------------------------------------------------------------*/ void dictionary_dump(const dictionary * d, FILE * out); #ifdef __cplusplus } #endif #endif iniparser-4.1/src/iniparser.c000066400000000000000000000626701317656027300163260ustar00rootroot00000000000000 /*-------------------------------------------------------------------------*/ /** @file iniparser.c @author N. Devillard @brief Parser for ini files. */ /*--------------------------------------------------------------------------*/ /*---------------------------- Includes ------------------------------------*/ #include #include #include "iniparser.h" /*---------------------------- Defines -------------------------------------*/ #define ASCIILINESZ (1024) #define INI_INVALID_KEY ((char*)-1) /*--------------------------------------------------------------------------- Private to this module ---------------------------------------------------------------------------*/ /** * This enum stores the status for each parsed line (internal use only). */ typedef enum _line_status_ { LINE_UNPROCESSED, LINE_ERROR, LINE_EMPTY, LINE_COMMENT, LINE_SECTION, LINE_VALUE } line_status ; /*-------------------------------------------------------------------------*/ /** @brief Convert a string to lowercase. @param in String to convert. @param out Output buffer. @param len Size of the out buffer. @return ptr to the out buffer or NULL if an error occured. This function convert a string into lowercase. At most len - 1 elements of the input string will be converted. */ /*--------------------------------------------------------------------------*/ static const char * strlwc(const char * in, char *out, unsigned len) { unsigned i ; if (in==NULL || out == NULL || len==0) return NULL ; i=0 ; while (in[i] != '\0' && i < len-1) { out[i] = (char)tolower((int)in[i]); i++ ; } out[i] = '\0'; return out ; } /*-------------------------------------------------------------------------*/ /** @brief Duplicate a string @param s String to duplicate @return Pointer to a newly allocated string, to be freed with free() This is a replacement for strdup(). This implementation is provided for systems that do not have it. */ /*--------------------------------------------------------------------------*/ static char * xstrdup(const char * s) { char * t ; size_t len ; if (!s) return NULL ; len = strlen(s) + 1 ; t = (char*) malloc(len) ; if (t) { memcpy(t, s, len) ; } return t ; } /*-------------------------------------------------------------------------*/ /** @brief Remove blanks at the beginning and the end of a string. @param str String to parse and alter. @return unsigned New size of the string. */ /*--------------------------------------------------------------------------*/ static unsigned strstrip(char * s) { char *last = NULL ; char *dest = s; if (s==NULL) return 0; last = s + strlen(s); while (isspace((int)*s) && *s) s++; while (last > s) { if (!isspace((int)*(last-1))) break ; last -- ; } *last = (char)0; memmove(dest,s,last - s + 1); return last - s; } /*-------------------------------------------------------------------------*/ /** @brief Default error callback for iniparser: wraps `fprintf(stderr, ...)`. */ /*--------------------------------------------------------------------------*/ static int default_error_callback(const char *format, ...) { int ret; va_list argptr; va_start(argptr, format); ret = vfprintf(stderr, format, argptr); va_end(argptr); return ret; } static int (*iniparser_error_callback)(const char*, ...) = default_error_callback; /*-------------------------------------------------------------------------*/ /** @brief Configure a function to receive the error messages. @param errback Function to call. By default, the error will be printed on stderr. If a null pointer is passed as errback the error callback will be switched back to default. */ /*--------------------------------------------------------------------------*/ void iniparser_set_error_callback(int (*errback)(const char *, ...)) { if (errback) { iniparser_error_callback = errback; } else { iniparser_error_callback = default_error_callback; } } /*-------------------------------------------------------------------------*/ /** @brief Get number of sections in a dictionary @param d Dictionary to examine @return int Number of sections found in dictionary This function returns the number of sections found in a dictionary. The test to recognize sections is done on the string stored in the dictionary: a section name is given as "section" whereas a key is stored as "section:key", thus the test looks for entries that do not contain a colon. This clearly fails in the case a section name contains a colon, but this should simply be avoided. This function returns -1 in case of error. */ /*--------------------------------------------------------------------------*/ int iniparser_getnsec(const dictionary * d) { int i ; int nsec ; if (d==NULL) return -1 ; nsec=0 ; for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; if (strchr(d->key[i], ':')==NULL) { nsec ++ ; } } return nsec ; } /*-------------------------------------------------------------------------*/ /** @brief Get name for section n in a dictionary. @param d Dictionary to examine @param n Section number (from 0 to nsec-1). @return Pointer to char string This function locates the n-th section in a dictionary and returns its name as a pointer to a string statically allocated inside the dictionary. Do not free or modify the returned string! This function returns NULL in case of error. */ /*--------------------------------------------------------------------------*/ const char * iniparser_getsecname(const dictionary * d, int n) { int i ; int foundsec ; if (d==NULL || n<0) return NULL ; foundsec=0 ; for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; if (strchr(d->key[i], ':')==NULL) { foundsec++ ; if (foundsec>n) break ; } } if (foundsec<=n) { return NULL ; } return d->key[i] ; } /*-------------------------------------------------------------------------*/ /** @brief Dump a dictionary to an opened file pointer. @param d Dictionary to dump. @param f Opened file pointer to dump to. @return void This function prints out the contents of a dictionary, one element by line, onto the provided file pointer. It is OK to specify @c stderr or @c stdout as output files. This function is meant for debugging purposes mostly. */ /*--------------------------------------------------------------------------*/ void iniparser_dump(const dictionary * d, FILE * f) { int i ; if (d==NULL || f==NULL) return ; for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; if (d->val[i]!=NULL) { fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); } else { fprintf(f, "[%s]=UNDEF\n", d->key[i]); } } return ; } /*-------------------------------------------------------------------------*/ /** @brief Save a dictionary to a loadable ini file @param d Dictionary to dump @param f Opened file pointer to dump to @return void This function dumps a given dictionary into a loadable ini file. It is Ok to specify @c stderr or @c stdout as output files. */ /*--------------------------------------------------------------------------*/ void iniparser_dump_ini(const dictionary * d, FILE * f) { int i ; int nsec ; const char * secname ; if (d==NULL || f==NULL) return ; nsec = iniparser_getnsec(d); if (nsec<1) { /* No section in file: dump all keys as they are */ for (i=0 ; isize ; i++) { if (d->key[i]==NULL) continue ; fprintf(f, "%s = %s\n", d->key[i], d->val[i]); } return ; } for (i=0 ; isize ; j++) { if (d->key[j]==NULL) continue ; if (!strncmp(d->key[j], keym, seclen+1)) { fprintf(f, "%-30s = %s\n", d->key[j]+seclen+1, d->val[j] ? d->val[j] : ""); } } fprintf(f, "\n"); return ; } /*-------------------------------------------------------------------------*/ /** @brief Get the number of keys in a section of a dictionary. @param d Dictionary to examine @param s Section name of dictionary to examine @return Number of keys in section */ /*--------------------------------------------------------------------------*/ int iniparser_getsecnkeys(const dictionary * d, const char * s) { int seclen, nkeys ; char keym[ASCIILINESZ+1]; int j ; nkeys = 0; if (d==NULL) return nkeys; if (! iniparser_find_entry(d, s)) return nkeys; seclen = (int)strlen(s); strlwc(s, keym, sizeof(keym)); keym[seclen] = ':'; for (j=0 ; jsize ; j++) { if (d->key[j]==NULL) continue ; if (!strncmp(d->key[j], keym, seclen+1)) nkeys++; } return nkeys; } /*-------------------------------------------------------------------------*/ /** @brief Get the number of keys in a section of a dictionary. @param d Dictionary to examine @param s Section name of dictionary to examine @param keys Already allocated array to store the keys in @return The pointer passed as `keys` argument or NULL in case of error This function queries a dictionary and finds all keys in a given section. The keys argument should be an array of pointers which size has been determined by calling `iniparser_getsecnkeys` function prior to this one. Each pointer in the returned char pointer-to-pointer is pointing to a string allocated in the dictionary; do not free or modify them. */ /*--------------------------------------------------------------------------*/ const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys) { int i, j, seclen ; char keym[ASCIILINESZ+1]; if (d==NULL || keys==NULL) return NULL; if (! iniparser_find_entry(d, s)) return NULL; seclen = (int)strlen(s); strlwc(s, keym, sizeof(keym)); keym[seclen] = ':'; i = 0; for (j=0 ; jsize ; j++) { if (d->key[j]==NULL) continue ; if (!strncmp(d->key[j], keym, seclen+1)) { keys[i] = d->key[j]; i++; } } return keys; } /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key @param d Dictionary to search @param key Key string to look for @param def Default value to return if key not found. @return pointer to statically allocated character string This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the pointer passed as 'def' is returned. The returned char pointer is pointing to a string allocated in the dictionary, do not free or modify it. */ /*--------------------------------------------------------------------------*/ const char * iniparser_getstring(const dictionary * d, const char * key, const char * def) { const char * lc_key ; const char * sval ; char tmp_str[ASCIILINESZ+1]; if (d==NULL || key==NULL) return def ; lc_key = strlwc(key, tmp_str, sizeof(tmp_str)); sval = dictionary_get(d, lc_key, def); return sval ; } /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to an long int @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return long integer This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. Supported values for integers include the usual C notation so decimal, octal (starting with 0) and hexadecimal (starting with 0x) are supported. Examples: "42" -> 42 "042" -> 34 (octal -> decimal) "0x42" -> 66 (hexa -> decimal) Warning: the conversion may overflow in various ways. Conversion is totally outsourced to strtol(), see the associated man page for overflow handling. Credits: Thanks to A. Becker for suggesting strtol() */ /*--------------------------------------------------------------------------*/ long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound) { const char * str ; str = iniparser_getstring(d, key, INI_INVALID_KEY); if (str==INI_INVALID_KEY) return notfound ; return strtol(str, NULL, 0); } /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to an int @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return integer This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. Supported values for integers include the usual C notation so decimal, octal (starting with 0) and hexadecimal (starting with 0x) are supported. Examples: "42" -> 42 "042" -> 34 (octal -> decimal) "0x42" -> 66 (hexa -> decimal) Warning: the conversion may overflow in various ways. Conversion is totally outsourced to strtol(), see the associated man page for overflow handling. Credits: Thanks to A. Becker for suggesting strtol() */ /*--------------------------------------------------------------------------*/ int iniparser_getint(const dictionary * d, const char * key, int notfound) { return (int)iniparser_getlongint(d, key, notfound); } /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to a double @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return double This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. */ /*--------------------------------------------------------------------------*/ double iniparser_getdouble(const dictionary * d, const char * key, double notfound) { const char * str ; str = iniparser_getstring(d, key, INI_INVALID_KEY); if (str==INI_INVALID_KEY) return notfound ; return atof(str); } /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to a boolean @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return integer This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. A true boolean is found if one of the following is matched: - A string starting with 'y' - A string starting with 'Y' - A string starting with 't' - A string starting with 'T' - A string starting with '1' A false boolean is found if one of the following is matched: - A string starting with 'n' - A string starting with 'N' - A string starting with 'f' - A string starting with 'F' - A string starting with '0' The notfound value returned if no boolean is identified, does not necessarily have to be 0 or 1. */ /*--------------------------------------------------------------------------*/ int iniparser_getboolean(const dictionary * d, const char * key, int notfound) { int ret ; const char * c ; c = iniparser_getstring(d, key, INI_INVALID_KEY); if (c==INI_INVALID_KEY) return notfound ; if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { ret = 1 ; } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { ret = 0 ; } else { ret = notfound ; } return ret; } /*-------------------------------------------------------------------------*/ /** @brief Finds out if a given entry exists in a dictionary @param ini Dictionary to search @param entry Name of the entry to look for @return integer 1 if entry exists, 0 otherwise Finds out if a given entry exists in the dictionary. Since sections are stored as keys with NULL associated values, this is the only way of querying for the presence of sections in a dictionary. */ /*--------------------------------------------------------------------------*/ int iniparser_find_entry(const dictionary * ini, const char * entry) { int found=0 ; if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { found = 1 ; } return found ; } /*-------------------------------------------------------------------------*/ /** @brief Set an entry in a dictionary. @param ini Dictionary to modify. @param entry Entry to modify (entry name) @param val New value to associate to the entry. @return int 0 if Ok, -1 otherwise. If the given entry can be found in the dictionary, it is modified to contain the provided value. If it cannot be found, the entry is created. It is Ok to set val to NULL. */ /*--------------------------------------------------------------------------*/ int iniparser_set(dictionary * ini, const char * entry, const char * val) { char tmp_str[ASCIILINESZ+1]; return dictionary_set(ini, strlwc(entry, tmp_str, sizeof(tmp_str)), val) ; } /*-------------------------------------------------------------------------*/ /** @brief Delete an entry in a dictionary @param ini Dictionary to modify @param entry Entry to delete (entry name) @return void If the given entry can be found, it is deleted from the dictionary. */ /*--------------------------------------------------------------------------*/ void iniparser_unset(dictionary * ini, const char * entry) { char tmp_str[ASCIILINESZ+1]; dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str))); } /*-------------------------------------------------------------------------*/ /** @brief Load a single line from an INI file @param input_line Input line, may be concatenated multi-line input @param section Output space to store section @param key Output space to store key @param value Output space to store value @return line_status value */ /*--------------------------------------------------------------------------*/ static line_status iniparser_line( const char * input_line, char * section, char * key, char * value) { line_status sta ; char * line = NULL; size_t len ; line = xstrdup(input_line); len = strstrip(line); sta = LINE_UNPROCESSED ; if (len<1) { /* Empty line */ sta = LINE_EMPTY ; } else if (line[0]=='#' || line[0]==';') { /* Comment line */ sta = LINE_COMMENT ; } else if (line[0]=='[' && line[len-1]==']') { /* Section name */ sscanf(line, "[%[^]]", section); strstrip(section); strlwc(section, section, len); sta = LINE_SECTION ; } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2) { /* Usual key=value with quotes, with or without comments */ strstrip(key); strlwc(key, key, len); /* Don't strip spaces from values surrounded with quotes */ sta = LINE_VALUE ; } else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { /* Usual key=value without quotes, with or without comments */ strstrip(key); strlwc(key, key, len); strstrip(value); /* * sscanf cannot handle '' or "" as empty values * this is done here */ if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { value[0]=0 ; } sta = LINE_VALUE ; } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 || sscanf(line, "%[^=] %[=]", key, value) == 2) { /* * Special cases: * key= * key=; * key=# */ strstrip(key); strlwc(key, key, len); value[0]=0 ; sta = LINE_VALUE ; } else { /* Generate syntax error */ sta = LINE_ERROR ; } free(line); return sta ; } /*-------------------------------------------------------------------------*/ /** @brief Parse an ini file and return an allocated dictionary object @param ininame Name of the ini file to read. @return Pointer to newly allocated dictionary This is the parser for ini files. This function is called, providing the name of the file to be read. It returns a dictionary object that should not be accessed directly, but through accessor functions instead. The returned dictionary must be freed using iniparser_freedict(). */ /*--------------------------------------------------------------------------*/ dictionary * iniparser_load(const char * ininame) { FILE * in ; char line [ASCIILINESZ+1] ; char section [ASCIILINESZ+1] ; char key [ASCIILINESZ+1] ; char tmp [(ASCIILINESZ * 2) + 1] ; char val [ASCIILINESZ+1] ; int last=0 ; int len ; int lineno=0 ; int errs=0; int mem_err=0; dictionary * dict ; if ((in=fopen(ininame, "r"))==NULL) { iniparser_error_callback("iniparser: cannot open %s\n", ininame); return NULL ; } dict = dictionary_new(0) ; if (!dict) { fclose(in); return NULL ; } memset(line, 0, ASCIILINESZ); memset(section, 0, ASCIILINESZ); memset(key, 0, ASCIILINESZ); memset(val, 0, ASCIILINESZ); last=0 ; while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { lineno++ ; len = (int)strlen(line)-1; if (len<=0) continue; /* Safety check against buffer overflows */ if (line[len]!='\n' && !feof(in)) { iniparser_error_callback( "iniparser: input line too long in %s (%d)\n", ininame, lineno); dictionary_del(dict); fclose(in); return NULL ; } /* Get rid of \n and spaces at end of line */ while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) { line[len]=0 ; len-- ; } if (len < 0) { /* Line was entirely \n and/or spaces */ len = 0; } /* Detect multi-line */ if (line[len]=='\\') { /* Multi-line value */ last=len ; continue ; } else { last=0 ; } switch (iniparser_line(line, section, key, val)) { case LINE_EMPTY: case LINE_COMMENT: break ; case LINE_SECTION: mem_err = dictionary_set(dict, section, NULL); break ; case LINE_VALUE: sprintf(tmp, "%s:%s", section, key); mem_err = dictionary_set(dict, tmp, val); break ; case LINE_ERROR: iniparser_error_callback( "iniparser: syntax error in %s (%d):\n-> %s\n", ininame, lineno, line); errs++ ; break; default: break ; } memset(line, 0, ASCIILINESZ); last=0; if (mem_err<0) { iniparser_error_callback("iniparser: memory allocation failure\n"); break ; } } if (errs) { dictionary_del(dict); dict = NULL ; } fclose(in); return dict ; } /*-------------------------------------------------------------------------*/ /** @brief Free all memory associated to an ini dictionary @param d Dictionary to free @return void Free all memory associated to an ini dictionary. It is mandatory to call this function before the dictionary object gets out of the current context. */ /*--------------------------------------------------------------------------*/ void iniparser_freedict(dictionary * d) { dictionary_del(d); } iniparser-4.1/src/iniparser.h000066400000000000000000000323201317656027300163200ustar00rootroot00000000000000 /*-------------------------------------------------------------------------*/ /** @file iniparser.h @author N. Devillard @brief Parser for ini files. */ /*--------------------------------------------------------------------------*/ #ifndef _INIPARSER_H_ #define _INIPARSER_H_ /*--------------------------------------------------------------------------- Includes ---------------------------------------------------------------------------*/ #include #include #include /* * The following #include is necessary on many Unixes but not Linux. * It is not needed for Windows platforms. * Uncomment it if needed. */ /* #include */ #include "dictionary.h" #ifdef __cplusplus extern "C" { #endif /*-------------------------------------------------------------------------*/ /** @brief Configure a function to receive the error messages. @param errback Function to call. By default, the error will be printed on stderr. If a null pointer is passed as errback the error callback will be switched back to default. */ /*--------------------------------------------------------------------------*/ void iniparser_set_error_callback(int (*errback)(const char *, ...)); /*-------------------------------------------------------------------------*/ /** @brief Get number of sections in a dictionary @param d Dictionary to examine @return int Number of sections found in dictionary This function returns the number of sections found in a dictionary. The test to recognize sections is done on the string stored in the dictionary: a section name is given as "section" whereas a key is stored as "section:key", thus the test looks for entries that do not contain a colon. This clearly fails in the case a section name contains a colon, but this should simply be avoided. This function returns -1 in case of error. */ /*--------------------------------------------------------------------------*/ int iniparser_getnsec(const dictionary * d); /*-------------------------------------------------------------------------*/ /** @brief Get name for section n in a dictionary. @param d Dictionary to examine @param n Section number (from 0 to nsec-1). @return Pointer to char string This function locates the n-th section in a dictionary and returns its name as a pointer to a string statically allocated inside the dictionary. Do not free or modify the returned string! This function returns NULL in case of error. */ /*--------------------------------------------------------------------------*/ const char * iniparser_getsecname(const dictionary * d, int n); /*-------------------------------------------------------------------------*/ /** @brief Save a dictionary to a loadable ini file @param d Dictionary to dump @param f Opened file pointer to dump to @return void This function dumps a given dictionary into a loadable ini file. It is Ok to specify @c stderr or @c stdout as output files. */ /*--------------------------------------------------------------------------*/ void iniparser_dump_ini(const dictionary * d, FILE * f); /*-------------------------------------------------------------------------*/ /** @brief Save a dictionary section to a loadable ini file @param d Dictionary to dump @param s Section name of dictionary to dump @param f Opened file pointer to dump to @return void This function dumps a given section of a given dictionary into a loadable ini file. It is Ok to specify @c stderr or @c stdout as output files. */ /*--------------------------------------------------------------------------*/ void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f); /*-------------------------------------------------------------------------*/ /** @brief Dump a dictionary to an opened file pointer. @param d Dictionary to dump. @param f Opened file pointer to dump to. @return void This function prints out the contents of a dictionary, one element by line, onto the provided file pointer. It is OK to specify @c stderr or @c stdout as output files. This function is meant for debugging purposes mostly. */ /*--------------------------------------------------------------------------*/ void iniparser_dump(const dictionary * d, FILE * f); /*-------------------------------------------------------------------------*/ /** @brief Get the number of keys in a section of a dictionary. @param d Dictionary to examine @param s Section name of dictionary to examine @return Number of keys in section */ /*--------------------------------------------------------------------------*/ int iniparser_getsecnkeys(const dictionary * d, const char * s); /*-------------------------------------------------------------------------*/ /** @brief Get the number of keys in a section of a dictionary. @param d Dictionary to examine @param s Section name of dictionary to examine @param keys Already allocated array to store the keys in @return The pointer passed as `keys` argument or NULL in case of error This function queries a dictionary and finds all keys in a given section. The keys argument should be an array of pointers which size has been determined by calling `iniparser_getsecnkeys` function prior to this one. Each pointer in the returned char pointer-to-pointer is pointing to a string allocated in the dictionary; do not free or modify them. */ /*--------------------------------------------------------------------------*/ const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys); /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key @param d Dictionary to search @param key Key string to look for @param def Default value to return if key not found. @return pointer to statically allocated character string This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the pointer passed as 'def' is returned. The returned char pointer is pointing to a string allocated in the dictionary, do not free or modify it. */ /*--------------------------------------------------------------------------*/ const char * iniparser_getstring(const dictionary * d, const char * key, const char * def); /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to an int @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return integer This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. Supported values for integers include the usual C notation so decimal, octal (starting with 0) and hexadecimal (starting with 0x) are supported. Examples: - "42" -> 42 - "042" -> 34 (octal -> decimal) - "0x42" -> 66 (hexa -> decimal) Warning: the conversion may overflow in various ways. Conversion is totally outsourced to strtol(), see the associated man page for overflow handling. Credits: Thanks to A. Becker for suggesting strtol() */ /*--------------------------------------------------------------------------*/ int iniparser_getint(const dictionary * d, const char * key, int notfound); /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to an long int @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return integer This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. Supported values for integers include the usual C notation so decimal, octal (starting with 0) and hexadecimal (starting with 0x) are supported. Examples: - "42" -> 42 - "042" -> 34 (octal -> decimal) - "0x42" -> 66 (hexa -> decimal) Warning: the conversion may overflow in various ways. Conversion is totally outsourced to strtol(), see the associated man page for overflow handling. */ /*--------------------------------------------------------------------------*/ long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound); /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to a double @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return double This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. */ /*--------------------------------------------------------------------------*/ double iniparser_getdouble(const dictionary * d, const char * key, double notfound); /*-------------------------------------------------------------------------*/ /** @brief Get the string associated to a key, convert to a boolean @param d Dictionary to search @param key Key string to look for @param notfound Value to return in case of error @return integer This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. A true boolean is found if one of the following is matched: - A string starting with 'y' - A string starting with 'Y' - A string starting with 't' - A string starting with 'T' - A string starting with '1' A false boolean is found if one of the following is matched: - A string starting with 'n' - A string starting with 'N' - A string starting with 'f' - A string starting with 'F' - A string starting with '0' The notfound value returned if no boolean is identified, does not necessarily have to be 0 or 1. */ /*--------------------------------------------------------------------------*/ int iniparser_getboolean(const dictionary * d, const char * key, int notfound); /*-------------------------------------------------------------------------*/ /** @brief Set an entry in a dictionary. @param ini Dictionary to modify. @param entry Entry to modify (entry name) @param val New value to associate to the entry. @return int 0 if Ok, -1 otherwise. If the given entry can be found in the dictionary, it is modified to contain the provided value. If it cannot be found, the entry is created. It is Ok to set val to NULL. */ /*--------------------------------------------------------------------------*/ int iniparser_set(dictionary * ini, const char * entry, const char * val); /*-------------------------------------------------------------------------*/ /** @brief Delete an entry in a dictionary @param ini Dictionary to modify @param entry Entry to delete (entry name) @return void If the given entry can be found, it is deleted from the dictionary. */ /*--------------------------------------------------------------------------*/ void iniparser_unset(dictionary * ini, const char * entry); /*-------------------------------------------------------------------------*/ /** @brief Finds out if a given entry exists in a dictionary @param ini Dictionary to search @param entry Name of the entry to look for @return integer 1 if entry exists, 0 otherwise Finds out if a given entry exists in the dictionary. Since sections are stored as keys with NULL associated values, this is the only way of querying for the presence of sections in a dictionary. */ /*--------------------------------------------------------------------------*/ int iniparser_find_entry(const dictionary * ini, const char * entry) ; /*-------------------------------------------------------------------------*/ /** @brief Parse an ini file and return an allocated dictionary object @param ininame Name of the ini file to read. @return Pointer to newly allocated dictionary This is the parser for ini files. This function is called, providing the name of the file to be read. It returns a dictionary object that should not be accessed directly, but through accessor functions instead. The returned dictionary must be freed using iniparser_freedict(). */ /*--------------------------------------------------------------------------*/ dictionary * iniparser_load(const char * ininame); /*-------------------------------------------------------------------------*/ /** @brief Free all memory associated to an ini dictionary @param d Dictionary to free @return void Free all memory associated to an ini dictionary. It is mandatory to call this function before the dictionary object gets out of the current context. */ /*--------------------------------------------------------------------------*/ void iniparser_freedict(dictionary * d); #ifdef __cplusplus } #endif #endif iniparser-4.1/test/000077500000000000000000000000001317656027300143435ustar00rootroot00000000000000iniparser-4.1/test/CuTest.c000066400000000000000000000203201317656027300157130ustar00rootroot00000000000000#include #include #include #include #include #include #include "CuTest.h" /*-------------------------------------------------------------------------* * CuStr *-------------------------------------------------------------------------*/ char* CuStrAlloc(int size) { char* newStr = (char*) malloc( sizeof(char) * (size) ); return newStr; } char* CuStrCopy(const char* old) { int len = strlen(old); char* newStr = CuStrAlloc(len + 1); strcpy(newStr, old); return newStr; } /*-------------------------------------------------------------------------* * CuString *-------------------------------------------------------------------------*/ void CuStringInit(CuString* str) { str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; } CuString* CuStringNew(void) { CuString* str = (CuString*) malloc(sizeof(CuString)); str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; return str; } void CuStringDelete(CuString *str) { if (!str) return; free(str->buffer); free(str); } void CuStringResize(CuString* str, int newSize) { str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); str->size = newSize; } void CuStringAppend(CuString* str, const char* text) { int length; if (text == NULL) { text = "NULL"; } length = strlen(text); if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); str->length += length; strcat(str->buffer, text); } void CuStringAppendChar(CuString* str, char ch) { char text[2]; text[0] = ch; text[1] = '\0'; CuStringAppend(str, text); } void CuStringAppendFormat(CuString* str, const char* format, ...) { va_list argp; char buf[HUGE_STRING_LEN]; va_start(argp, format); vsprintf(buf, format, argp); va_end(argp); CuStringAppend(str, buf); } void CuStringInsert(CuString* str, const char* text, int pos) { int length = strlen(text); if (pos > str->length) pos = str->length; if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); str->length += length; memcpy(str->buffer + pos, text, length); } /*-------------------------------------------------------------------------* * CuTest *-------------------------------------------------------------------------*/ void CuTestInit(CuTest* t, const char* name, TestFunction function) { t->name = CuStrCopy(name); t->failed = 0; t->ran = 0; t->message = NULL; t->function = function; t->jumpBuf = NULL; } CuTest* CuTestNew(const char* name, TestFunction function) { CuTest* tc = CU_ALLOC(CuTest); CuTestInit(tc, name, function); return tc; } void CuTestDelete(CuTest *t) { if (!t) return; free(t->name); free(t); } void CuTestRun(CuTest* tc) { jmp_buf buf; tc->jumpBuf = &buf; if (setjmp(buf) == 0) { tc->ran = 1; (tc->function)(tc); } tc->jumpBuf = 0; } static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) { char buf[HUGE_STRING_LEN]; sprintf(buf, "%s:%d: ", file, line); CuStringInsert(string, buf, 0); tc->failed = 1; tc->message = string->buffer; if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); } void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) { CuString string; CuStringInit(&string); if (message2 != NULL) { CuStringAppend(&string, message2); CuStringAppend(&string, ": "); } CuStringAppend(&string, message); CuFailInternal(tc, file, line, &string); } void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) { if (condition) return; CuFail_Line(tc, file, line, NULL, message); } void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) { CuString string; if ((expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strcmp(expected, actual) == 0)) { return; } CuStringInit(&string); if (message != NULL) { CuStringAppend(&string, message); CuStringAppend(&string, ": "); } CuStringAppend(&string, "expected <"); CuStringAppend(&string, expected); CuStringAppend(&string, "> but was <"); CuStringAppend(&string, actual); CuStringAppend(&string, ">"); CuFailInternal(tc, file, line, &string); } void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected <%d> but was <%d>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertLongIntEquals_LineMsg(CuTest *tc, const char *file, int line, const char *message, long int expected, long int actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected <%ld> but was <%ld>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta) { char buf[STRING_MAX]; if (fabs(expected - actual) <= delta) return; sprintf(buf, "expected <%f> but was <%f>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const void* expected, const void* actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); CuFail_Line(tc, file, line, message, buf); } /*-------------------------------------------------------------------------* * CuSuite *-------------------------------------------------------------------------*/ void CuSuiteInit(CuSuite* testSuite) { testSuite->count = 0; testSuite->failCount = 0; memset(testSuite->list, 0, sizeof(testSuite->list)); } CuSuite* CuSuiteNew(void) { CuSuite* testSuite = CU_ALLOC(CuSuite); CuSuiteInit(testSuite); return testSuite; } void CuSuiteDelete(CuSuite *testSuite) { unsigned int n; for (n=0; n < MAX_TEST_CASES; n++) { if (testSuite->list[n]) { CuTestDelete(testSuite->list[n]); } } free(testSuite); } void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) { assert(testSuite->count < MAX_TEST_CASES); testSuite->list[testSuite->count] = testCase; testSuite->count++; } void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) { int i; for (i = 0 ; i < testSuite2->count ; ++i) { CuTest* testCase = testSuite2->list[i]; CuSuiteAdd(testSuite, testCase); } } void CuSuiteRun(CuSuite* testSuite) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuTestRun(testCase); if (testCase->failed) { testSuite->failCount += 1; } } } void CuSuiteSummary(CuSuite* testSuite, CuString* summary) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuStringAppend(summary, testCase->failed ? "F" : "."); } CuStringAppend(summary, "\n\n"); } void CuSuiteDetails(CuSuite* testSuite, CuString* details) { int i; int failCount = 0; if (testSuite->failCount == 0) { int passCount = testSuite->count - testSuite->failCount; const char* testWord = passCount == 1 ? "test" : "tests"; CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); } else { if (testSuite->failCount == 1) CuStringAppend(details, "There was 1 failure:\n"); else CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; if (testCase->failed) { failCount++; CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); } } CuStringAppend(details, "\n!!!FAILURES!!!\n"); CuStringAppendFormat(details, "Runs: %d ", testSuite->count); CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); } } iniparser-4.1/test/CuTest.h000066400000000000000000000106001317656027300157200ustar00rootroot00000000000000#ifndef CU_TEST_H #define CU_TEST_H #include #include #define CUTEST_VERSION "CuTest 1.5" /* CuString */ char* CuStrAlloc(int size); char* CuStrCopy(const char* old); #define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) #define HUGE_STRING_LEN 8192 #define STRING_MAX 256 #define STRING_INC 256 typedef struct { int length; int size; char* buffer; } CuString; void CuStringInit(CuString* str); CuString* CuStringNew(void); void CuStringRead(CuString* str, const char* path); void CuStringAppend(CuString* str, const char* text); void CuStringAppendChar(CuString* str, char ch); void CuStringAppendFormat(CuString* str, const char* format, ...); void CuStringInsert(CuString* str, const char* text, int pos); void CuStringResize(CuString* str, int newSize); void CuStringDelete(CuString* str); /* CuTest */ typedef struct CuTest CuTest; typedef void (*TestFunction)(CuTest *); struct CuTest { char* name; TestFunction function; int failed; int ran; const char* message; jmp_buf *jumpBuf; }; void CuTestInit(CuTest* t, const char* name, TestFunction function); CuTest* CuTestNew(const char* name, TestFunction function); void CuTestRun(CuTest* tc); void CuTestDelete(CuTest *t); /* Internal versions of assert functions -- use the public versions */ void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual); void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual); void CuAssertLongIntEquals_LineMsg(CuTest *tc, const char *file, int line, const char *message, long int expected, long int actual); void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta); void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const void* expected, const void* actual); /* public assert functions */ #define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) #define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) #define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) #define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertLongIntEquals(tc,ex,ac) CuAssertLongIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertLongIntEquals_Msg(tc,ms,ex,ac) CuAssertLongIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) #define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) #define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) #define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) /* CuSuite */ #define MAX_TEST_CASES 1024 #define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) typedef struct { int count; CuTest* list[MAX_TEST_CASES]; int failCount; } CuSuite; void CuSuiteInit(CuSuite* testSuite); CuSuite* CuSuiteNew(void); void CuSuiteDelete(CuSuite *testSuite); void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); void CuSuiteRun(CuSuite* testSuite); void CuSuiteSummary(CuSuite* testSuite, CuString* summary); void CuSuiteDetails(CuSuite* testSuite, CuString* details); #endif /* CU_TEST_H */ iniparser-4.1/test/CuTest_license.txt000066400000000000000000000026751317656027300200270ustar00rootroot00000000000000NOTE The license is based on the zlib/libpng license. For more details see http://www.opensource.org/licenses/zlib-license.html. The intent of the license is to: - keep the license as simple as possible - encourage the use of CuTest in both free and commercial applications and libraries - keep the source code together - give credit to the CuTest contributors for their work If you ship CuTest in source form with your source distribution, the following license document must be included with it in unaltered form. If you find CuTest useful we would like to hear about it. LICENSE Copyright (c) 2003 Asim Jalis This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. iniparser-4.1/test/Makefile000066400000000000000000000012611317656027300160030ustar00rootroot00000000000000CC ?= gcc ifndef V QUIET_CC = @echo "CC $@"; QUIET_MAKE_TESTS = @echo "GN Alltests.c"; endif DEPS = $(shell ls ../src/*.[ch]) SRC = $(shell ls *.c | sed 's/AllTests.c//') OBJ = $(SRC:.c=.o) INCLUDE = -I../src CFLAGS += -pipe -ansi -pedantic -Wall -Wextra -g LDFLAGS += all: check check: testrun @./testrun testrun: AllTests.o $(OBJ) $(QUIET_CC)$(CC) -o $@ AllTests.o $(OBJ) $(LDFLAGS) AllTests.o: $(OBJ) $(QUIET_MAKE_TESTS)./make-tests.sh > AllTests.c $(QUIET_CC)$(CC) -c -o AllTests.o AllTests.c $(CFLAGS) $(INCLUDE) %.o: %.c $(DEPS) $(QUIET_CC)$(CC) -c -o $@ $< $(CFLAGS) $(INCLUDE) clean veryclean: rm -rf AllTests.c rm -rf $(OBJ) AllTests.o rm -rf testrun iniparser-4.1/test/make-tests.sh000077500000000000000000000017571317656027300167710ustar00rootroot00000000000000#!/usr/bin/env bash # Auto generate single AllTests file for CuTest. # Searches through all *.c files in the current directory. # Prints to stdout. # Author: Asim Jalis # Date: 01/08/2003 if test $# -eq 0 ; then FILES=*.c ; else FILES=$* ; fi echo ' /* This is auto-generated code. Edit at your own peril. */ #include #include #include "CuTest.h" ' cat $FILES | grep '^void Test' | sed -e 's/(.*$//' \ -e 's/$/(CuTest*);/' \ -e 's/^/extern /' echo \ ' void RunAllTests(void) { CuString *output = CuStringNew(); CuSuite* suite = CuSuiteNew(); ' cat $FILES | grep '^void Test' | sed -e 's/^void //' \ -e 's/(.*$//' \ -e 's/^/ SUITE_ADD_TEST(suite, /' \ -e 's/$/);/' echo \ ' CuSuiteRun(suite); CuSuiteSummary(suite, output); CuSuiteDetails(suite, output); printf("%s\n", output->buffer); CuStringDelete(output); CuSuiteDelete(suite); } int main(void) { RunAllTests(); return 0; } ' iniparser-4.1/test/ressources/000077500000000000000000000000001317656027300165405ustar00rootroot00000000000000iniparser-4.1/test/ressources/bad_ini/000077500000000000000000000000001317656027300201255ustar00rootroot00000000000000iniparser-4.1/test/ressources/bad_ini/ends_well.ini000066400000000000000000000001411317656027300225760ustar00rootroot00000000000000# # This dict contains an error but ends up with a correct entry # [section] error is here a = b iniparser-4.1/test/ressources/bad_ini/twisted-errors.ini000066400000000000000000000001341317656027300236210ustar00rootroot00000000000000# # All of these should trigger syntax errors # [section] hello world hello \ world a + b ; iniparser-4.1/test/ressources/bad_ini/twisted-ofkey.ini000066400000000000000000000143701317656027300234310ustar00rootroot00000000000000# Stress testing buffers for overflows [long] # Shitload key size aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1 iniparser-4.1/test/ressources/bad_ini/twisted-ofval.ini000066400000000000000000000123311317656027300234160ustar00rootroot00000000000000# Shitload data size [long] a=\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890; iniparser-4.1/test/ressources/good_ini/000077500000000000000000000000001317656027300203275ustar00rootroot00000000000000iniparser-4.1/test/ressources/good_ini/empty.ini000066400000000000000000000000001317656027300221540ustar00rootroot00000000000000iniparser-4.1/test/ressources/good_ini/spaced.ini000066400000000000000000000000451317656027300222660ustar00rootroot00000000000000 iniparser-4.1/test/ressources/good_ini/spaced2.ini000066400000000000000000000002311317656027300223450ustar00rootroot00000000000000 # spaced2.ini [blanks] a=1 b=1; c=1; comment d=1# comment iniparser-4.1/test/ressources/good_ini/twisted.ini000066400000000000000000000023271317656027300225170ustar00rootroot00000000000000# # Twisted.ini # This file is meant for regression tests # Different blank settings around the equal sign [blanks] a=1 b=1; c=1; comment d=1# comment e =1 f =1; g =1; comment h =1# comment i= 1 j= 1; k= 1; comment l= 1# comment m = 1 n = 1; o = 1; comment p = 1# comment q=1 ; r=1 ; comment s=1 ;comment t=1 #comment # Empty values [empty] a = '' b = "" c = '' ; d = "" ; e = '' ; comment f = "" ; comment g = h = ; i = ; comment j = # comment k= l=; m=;comment n=# # Peculiar values [peculiar] a=';'; b='#'# c=';';comment d='#'#comment e=\; f=\# g=\;comment h=\#comment i=;; j=## k=;;;;;;;;;; l=########## # Quotes [quotes] s1=' s2='' s3=''' s4='''' d1=" d2="" d3=""" d4="""" m1='"' m2="'" h1=hello'world h2='hello'world h3='hello'world' h4=hello"world h5="hello"world h6="hello"world" # Section names [a] [ b] [c ] [ d ] [ begin end ] [ open[ ] # Multi-line inputs [multi] a = begin\ end b = begin \ end c = begin \ end d = 1\ 2\ 3\ 4 e = 1 \ 2 \ 3 \ 4 f = 1 ; \ hidden = because of the preceding backslash multi-lining the comment ; visible = 1 g = 1 #\ and now this comment is hidden too \ and this one too h = 1 multi \ line \ key = 1 multi \ line \ key = \ multi \ line \ value ; # end of file iniparser-4.1/test/test_dictionary.c000066400000000000000000000137471317656027300177270ustar00rootroot00000000000000#include #include #include "CuTest.h" /* We need to directly insert the .c file in order to test the */ /* static functions as well */ #include "dictionary.c" void Test_xstrdup(CuTest *tc) { size_t i; char *dup_str; const char *strings[] = { "", "test", " " }; char *string_very_long; /* NULL test */ CuAssertPtrEquals(tc, NULL, xstrdup(NULL)); for (i = 0 ; i < sizeof(strings) / sizeof(char *) ; ++i) { dup_str = xstrdup(strings[i]); CuAssertStrEquals(tc, strings[i], dup_str); free(dup_str); } /* test a overflowing string */ string_very_long = (char*) malloc(10 * 1024); memset(string_very_long, '#', 10 * 1024); string_very_long[10 * 1024 - 1] = '\0'; dup_str = xstrdup(string_very_long); CuAssertStrEquals(tc, string_very_long, dup_str); free(string_very_long); free(dup_str); } void Test_dictionary_grow(CuTest *tc) { unsigned i; dictionary *dic; dic = dictionary_new(DICTMINSZ); CuAssertPtrNotNull(tc, dic); CuAssertIntEquals(tc, 0, dic->n); CuAssertIntEquals(tc, DICTMINSZ, dic->size); for (i = 1 ; i < 10 ; ++i) { CuAssertIntEquals(tc, 0, dictionary_grow(dic)); CuAssertIntEquals(tc, 0, dic->n); CuAssertIntEquals(tc, (1 << i) * DICTMINSZ, dic->size); } } void Test_dictionary_hash(CuTest *tc) { /* NULL test */ CuAssertIntEquals(tc, 0, dictionary_hash(NULL)); } void Test_dictionary_growing(CuTest *tc) { int i, j; char sec_name[32]; char key_name[64]; dictionary *dic; dic = dictionary_new(DICTMINSZ); CuAssertPtrNotNull(tc, dic); CuAssertIntEquals(tc, 0, dic->n); /* Makes the dictionary grow */ for (i = 1 ; i < 101; ++i) { sprintf(sec_name, "sec%d", i); CuAssertIntEquals(tc, 0, dictionary_set(dic, sec_name, "")); for (j = 1 ; j < 11; ++j) { sprintf(key_name, "%s:key%d", sec_name, j); CuAssertIntEquals(tc, 0, dictionary_set(dic, key_name, "dummy_value")); CuAssertIntEquals(tc, i + (i - 1) * 10 + j, dic->n); } } /* Shrink the dictionary */ for (i = 100 ; i > 0; --i) { sprintf(sec_name, "sec%d", i); for (j = 10 ; j > 0; --j) { sprintf(key_name, "%s:key%d", sec_name, j); dictionary_unset(dic, key_name); } dictionary_unset(dic, sec_name); CuAssertIntEquals(tc, (i - 1) * (11), dic->n); } dictionary_del(dic); } static char *get_dump(dictionary *d) { FILE *fd; char *dump_buff; int dump_size; /* Dump the dictionary in temporary file */ fd = tmpfile(); if (fd == NULL) return NULL; dictionary_dump(d, fd); /* Retrieve the dump file */ dump_size = ftell(fd); if (dump_size == -1) { fclose(fd); return NULL; } rewind(fd); dump_buff = (char*) calloc(1, dump_size + 1); if (dump_buff == NULL) { fclose(fd); return NULL; } if (fread(dump_buff, 1, dump_size, fd) != (size_t)dump_size) { fclose(fd); return NULL; } fclose(fd); return dump_buff; } void Test_dictionary_unset(CuTest *tc) { int i, j; char sec_name[32]; char key_name[64]; dictionary *dic1; dictionary *dic2; char *dic1_dump; char *dic2_dump; /* try dummy unsets */ dictionary_unset(NULL, NULL); dictionary_unset(NULL, key_name); /* Generate two similar dictionaries */ dic1 = dictionary_new(DICTMINSZ); CuAssertPtrNotNull(tc, dic1); for (i = 1 ; i < 10; ++i) { sprintf(sec_name, "sec%d", i); dictionary_set(dic1, sec_name, ""); for (j = 1 ; j < 10; ++j) { sprintf(key_name, "%s:key%d", sec_name, j); dictionary_set(dic1, key_name, "dummy_value"); } } dic2 = dictionary_new(DICTMINSZ); CuAssertPtrNotNull(tc, dic2); for (i = 1 ; i < 10; ++i) { sprintf(sec_name, "sec%d", i); dictionary_set(dic2, sec_name, ""); for (j = 1 ; j < 10; ++j) { sprintf(key_name, "%s:key%d", sec_name, j); dictionary_set(dic2, key_name, "dummy_value"); } } /* Make sure the dictionaries are the same */ dic1_dump = get_dump(dic1); dic2_dump = get_dump(dic2); CuAssertStrEquals(tc, dic1_dump, dic2_dump); free(dic1_dump); free(dic2_dump); /* Those tests should not change the dictionary */ dictionary_unset(dic2, NULL); dictionary_unset(dic2, "bad_key"); /* dic1 and dic2 must still be the same */ dic1_dump = get_dump(dic1); dic2_dump = get_dump(dic2); CuAssertStrEquals(tc, dic1_dump, dic2_dump); free(dic1_dump); free(dic2_dump); } void Test_dictionary_dump(CuTest *tc) { int i, j; char sec_name[32]; char key_name[64]; dictionary *dic; char *dump_buff; const char dump_real[] = "\ sec1\t[]\n\ sec1:key1\t[dummy_value]\n\ sec1:key2\t[dummy_value]\n\ sec1:key3\t[dummy_value]\n\ sec1:key4\t[dummy_value]\n\ sec2\t[]\n\ sec2:key1\t[dummy_value]\n\ sec2:key2\t[dummy_value]\n\ sec2:key3\t[dummy_value]\n\ sec2:key4\t[dummy_value]\n\ "; dic = dictionary_new(DICTMINSZ); CuAssertPtrNotNull(tc, dic); /* Try dummy values */ dictionary_dump(NULL, NULL); dictionary_dump(dic, NULL); /* Try with empty dictionary first */ dump_buff = get_dump(dic); CuAssertStrEquals(tc, "empty dictionary\n", dump_buff); free(dump_buff); /* Populate the dictionary */ for (i = 1 ; i < 3; ++i) { sprintf(sec_name, "sec%d", i); dictionary_set(dic, sec_name, ""); for (j = 1 ; j < 5; ++j) { sprintf(key_name, "%s:key%d", sec_name, j); dictionary_set(dic, key_name, "dummy_value"); } } /* Check the dump file */ dump_buff = get_dump(dic); CuAssertStrEquals(tc, dump_real, dump_buff); free(dump_buff); dictionary_del(dic); } iniparser-4.1/test/test_iniparser.c000066400000000000000000000565421317656027300175560ustar00rootroot00000000000000#include #include #include #include #include #include #include "CuTest.h" #include "dictionary.h" /* We need to directly insert the .c file in order to test the */ /* static functions as well */ #include "iniparser.c" #define GOOD_INI_PATH "ressources/good_ini" #define BAD_INI_PATH "ressources/bad_ini" /* Tool function to create and populate a generic non-empty dictionary */ static dictionary * generate_dictionary(unsigned sections, unsigned entries_per_section) { unsigned i, j ; dictionary * dic; char sec_name[32]; char key_name[64]; char key_value[32]; dic = dictionary_new(sections + sections * entries_per_section); if (dic == NULL) return NULL; /* Insert the sections */ for (i = 0; i < sections; ++i) { sprintf(sec_name, "sec%d", i); dictionary_set(dic, sec_name, ""); for (j = 0; j < entries_per_section; ++j) { /* Populate the section with the entries */ sprintf(key_name, "%s:key%d", sec_name, j); sprintf(key_value, "value-%d/%d", i, j); dictionary_set(dic, key_name, key_value); } } return dic; } void Test_iniparser_strlwc(CuTest *tc) { char out_buffer[128]; /* NULL ptr as input */ CuAssertPtrEquals(tc, NULL, strlwc(NULL, NULL, 0)); CuAssertPtrEquals(tc, NULL, strlwc(NULL, out_buffer, sizeof (out_buffer))); CuAssertPtrEquals(tc, NULL, strlwc("", NULL, sizeof (out_buffer))); CuAssertPtrEquals(tc, NULL, strlwc("", out_buffer, 0)); CuAssertPtrEquals(tc, NULL, strlwc(NULL, NULL, 0)); /* empty string */ CuAssertStrEquals(tc, "", strlwc("", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, " ", strlwc(" ", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, "test", strlwc("test", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, "test", strlwc("TEST", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, "test", strlwc("TeSt", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, "test test", strlwc("TEST TEST", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, "very long string !!!!!!!", strlwc("very long string !!!!!!!", out_buffer, sizeof (out_buffer))); CuAssertStrEquals(tc, "cutted string", strlwc("cutted string<---here", out_buffer, 14)); /* test using same buffer as input and output */ strcpy(out_buffer, "OVERWRITE ME !"); CuAssertPtrNotNull(tc, strlwc(out_buffer, out_buffer, sizeof(out_buffer))); CuAssertStrEquals(tc, "overwrite me !", out_buffer); } void Test_iniparser_strstrip(CuTest *tc) { /* First element in the array is the expected stripping result */ const char *strings_empty[] = { "", " ", "\n\n\n\n", "\t\t\t\t", "\n \t\n\t\n " }; const char *strings_test[] = { "test", "test ", "test ", " test", " test ", "\ttest\t", "\ttest\n" }; const char *test_with_spaces = "I am a test with\tspaces."; char stripped[ASCIILINESZ+1]; char error_msg[128]; unsigned i; /* NULL ptr as input */ strstrip(NULL); /* empty string */ for (i = 0 ; i < sizeof (strings_empty) / sizeof (char *) ; ++i) { strcpy(stripped, strings_empty[i]); strstrip(stripped); sprintf(error_msg, "Bad stripping : strstrip(\"%s\") ==> \"%s\"", strings_empty[i], stripped); CuAssertStrEquals_Msg(tc, error_msg, stripped, strings_empty[0]); } /* test string */ for (i = 0 ; i < sizeof (strings_test) / sizeof (char *) ; ++i) { strcpy(stripped, strings_test[i]); strstrip(stripped); sprintf(error_msg, "Bad stripping : strstrip(\"%s\") ==> \"%s\"", strings_test[i], stripped); CuAssertStrEquals_Msg(tc, error_msg, strings_test[0], stripped); } strcpy(stripped, "."); strstrip(stripped); CuAssertStrEquals(tc, ".", stripped); /* string containing spaces */ strcpy(stripped, test_with_spaces); strstrip(stripped); CuAssertStrEquals(tc, test_with_spaces, stripped); } void Test_iniparser_getnsec(CuTest *tc) { int i; char sec_name[32]; dictionary *dic; /* NULL test */ CuAssertIntEquals(tc, -1, iniparser_getnsec(NULL)); /* Empty dictionary */ dic = dictionary_new(10); CuAssertIntEquals(tc, 0, iniparser_getnsec(dic)); dictionary_del(dic); /* Regular dictionary */ dic = generate_dictionary(512, 0); CuAssertIntEquals(tc, 512, iniparser_getnsec(dic)); /* Check after removing sections */ for (i = 1; i < 512; ++i) { sprintf(sec_name, "sec%d", i); dictionary_unset(dic, sec_name); CuAssertIntEquals(tc, 512 - i, iniparser_getnsec(dic)); } dictionary_del(dic); /* Mix sections and regular keys */ dic = generate_dictionary(10, 512); CuAssertIntEquals(tc, 10, iniparser_getnsec(dic)); dictionary_del(dic); } void Test_iniparser_getsecname(CuTest *tc) { unsigned i; char sec_name[32]; dictionary *dic; /* NULL test */ CuAssertTrue(tc, iniparser_getsecname(NULL, 0) == NULL); /* Empty dictionary */ dic = dictionary_new(10); CuAssertPtrEquals(tc, NULL, iniparser_getsecname(dic, 0)); dictionary_del(dic); /* Sections without entries dictionary */ dic = generate_dictionary(100, 0); for (i = 0; i < 100; ++i) { sprintf(sec_name, "sec%d", i); CuAssertStrEquals(tc, sec_name, iniparser_getsecname(dic, i)); } dictionary_del(dic); /* Generic dictionary */ dic = generate_dictionary(10, 100); for (i = 0; i < 10; ++i) { sprintf(sec_name, "sec%d", i); CuAssertStrEquals(tc, sec_name, iniparser_getsecname(dic, i)); } dictionary_del(dic); } void Test_iniparser_getseckeys(CuTest *tc) { unsigned i; char key_name[64]; dictionary *dic; int nkeys; const char * keys[10]; /* At most 10 elements per section */ /* NULL test */ CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, NULL, NULL)); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, "dummy", NULL)); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, "dummy", keys)); /* Empty dictionary */ dic = dictionary_new(10); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, NULL, keys)); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "dummy", keys)); dictionary_del(dic); /* Generic dictionary */ dic = generate_dictionary(100, 10); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, NULL, keys)); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "dummy", keys)); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "sec0", NULL)); nkeys = iniparser_getsecnkeys(dic, "sec42"); CuAssertIntEquals(tc, nkeys, 10); CuAssertPtrEquals(tc, keys, iniparser_getseckeys(dic, "sec42", keys)); for (i = 0; i < 10; ++i) { sprintf(key_name, "sec42:key%d", i); CuAssertStrEquals(tc, key_name, keys[i]); } /* Remove some keys to make the dictionary more real */ dictionary_unset(dic, "sec42"); dictionary_unset(dic, "sec99:key9"); dictionary_unset(dic, "sec0:key0"); dictionary_unset(dic, "sec0:key1"); dictionary_unset(dic, "sec0:key2"); CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "sec42", keys)); nkeys = iniparser_getsecnkeys(dic, "Sec99"); CuAssertIntEquals(tc, nkeys, 9); CuAssertPtrEquals(tc, keys, iniparser_getseckeys(dic, "Sec99", keys)); for (i = 0; i < 9; ++i) { sprintf(key_name, "sec99:key%d", i); CuAssertStrEquals(tc, key_name, keys[i]); } nkeys = iniparser_getsecnkeys(dic, "sec0"); CuAssertIntEquals(tc, nkeys, 7); CuAssertPtrEquals(tc, keys, iniparser_getseckeys(dic, "sec0", keys)); for (i = 0; i < 7; ++i) { sprintf(key_name, "sec0:key%d", i + 3); CuAssertStrEquals(tc, key_name, keys[i]); } dictionary_del(dic); } void Test_iniparser_getstring(CuTest *tc) { dictionary *dic; /* NULL test */ CuAssertPtrEquals(tc, NULL, iniparser_getstring(NULL, NULL, NULL)); CuAssertPtrEquals(tc, NULL, iniparser_getstring(NULL, "dummy", NULL)); /* Check the def return element */ dic = dictionary_new(10); CuAssertPtrEquals(tc, NULL, iniparser_getstring(dic, "dummy", NULL)); CuAssertStrEquals(tc, "def", iniparser_getstring(dic, NULL, "def")); CuAssertStrEquals(tc, "def", iniparser_getstring(dic, "dummy", "def")); dictionary_del(dic); /* Generic dictionary */ dic = generate_dictionary(100, 10); CuAssertStrEquals(tc, "value-0/0", iniparser_getstring(dic, "sec0:key0", NULL)); CuAssertStrEquals(tc, "value-42/5", iniparser_getstring(dic, "sec42:key5", NULL)); CuAssertStrEquals(tc, "value-99/9", iniparser_getstring(dic, "sec99:key9", NULL)); dictionary_del(dic); } void Test_iniparser_getint(CuTest *tc) { unsigned i; char key_name[64]; dictionary *dic; const struct { int num; const char *value; } good_val[] = { { 0, "0" }, { 1, "1" }, { -1, "-1" }, { 1000, "1000" }, { 077, "077" }, { -01000, "-01000" }, { 0xFFFF, "0xFFFF" }, { -0xFFFF, "-0xFFFF" }, { 0x4242, "0x4242" }, { 0, NULL} /* must be last */ }; const char *bad_val[] = { "", "notanumber", "0x", "k2000", " ", "0xG1" }; /* NULL test */ CuAssertIntEquals(tc, -42, iniparser_getint(NULL, NULL, -42)); CuAssertIntEquals(tc, -42, iniparser_getint(NULL, "dummy", -42)); /* Check the def return element */ dic = dictionary_new(10); CuAssertIntEquals(tc, 42, iniparser_getint(dic, "dummy", 42)); CuAssertIntEquals(tc, 0xFFFF, iniparser_getint(dic, NULL, 0xFFFF)); CuAssertIntEquals(tc, -0xFFFF, iniparser_getint(dic, "dummy", -0xFFFF)); dictionary_del(dic); /* Generic dictionary */ dic = dictionary_new(10); for (i = 0; good_val[i].value != NULL; ++i) { sprintf(key_name, "int:value%d", i); dictionary_set(dic, key_name, good_val[i].value); } for (i = 0; good_val[i].value != NULL; ++i) { sprintf(key_name, "int:value%d", i); CuAssertIntEquals(tc, good_val[i].num, iniparser_getint(dic, key_name, 0)); } dictionary_del(dic); /* Test bad names */ dic = dictionary_new(10); for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { sprintf(key_name, "int:bad%d", i); dictionary_set(dic, key_name, bad_val[i]); } for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { sprintf(key_name, "int:bad%d", i); CuAssertIntEquals(tc, 0, iniparser_getint(dic, key_name, 0)); } dictionary_del(dic); } void Test_iniparser_getlongint(CuTest *tc) { unsigned i; char key_name[64]; dictionary *dic; const struct { long int num; const char *value; } good_val[] = { { 0, "0" }, { 1, "1" }, { -1, "-1" }, { 1000, "1000" }, { 077, "077" }, { -01000, "-01000" }, { 0x7FFFFFFFFFFFFFFF, "0x7FFFFFFFFFFFFFFF" }, { -0x7FFFFFFFFFFFFFFF, "-0x7FFFFFFFFFFFFFFF" }, { 0x4242, "0x4242" }, { 0, NULL} /* must be last */ }; const char *bad_val[] = { "", "notanumber", "0x", "k2000", " ", "0xG1" }; /* NULL test */ CuAssertLongIntEquals(tc, -42, iniparser_getlongint(NULL, NULL, -42)); CuAssertLongIntEquals(tc, -42, iniparser_getlongint(NULL, "dummy", -42)); /* Check the def return element */ dic = dictionary_new(10); CuAssertLongIntEquals(tc, 42, iniparser_getlongint(dic, "dummy", 42)); CuAssertLongIntEquals(tc, 0x7FFFFFFFFFFFFFFF, iniparser_getlongint(dic, NULL, 0x7FFFFFFFFFFFFFFF)); CuAssertLongIntEquals(tc, -0x7FFFFFFFFFFFFFFF, iniparser_getlongint(dic, "dummy", -0x7FFFFFFFFFFFFFFF)); dictionary_del(dic); /* Generic dictionary */ dic = dictionary_new(10); for (i = 0; good_val[i].value != NULL; ++i) { sprintf(key_name, "longint:value%d", i); dictionary_set(dic, key_name, good_val[i].value); } for (i = 0; good_val[i].value != NULL; ++i) { sprintf(key_name, "longint:value%d", i); CuAssertLongIntEquals(tc, good_val[i].num, iniparser_getlongint(dic, key_name, 0)); } dictionary_del(dic); /* Test bad names */ dic = dictionary_new(10); for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { sprintf(key_name, "longint:bad%d", i); dictionary_set(dic, key_name, bad_val[i]); } for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { sprintf(key_name, "longint:bad%d", i); CuAssertLongIntEquals(tc, 0, iniparser_getlongint(dic, key_name, 0)); } dictionary_del(dic); } void Test_iniparser_getdouble(CuTest *tc) { dictionary *dic; /* NULL test */ CuAssertDblEquals(tc, -42, iniparser_getdouble(NULL, NULL, -42), 0); CuAssertDblEquals(tc, 4.2, iniparser_getdouble(NULL, "dummy", 4.2), 0); /* Check the def return element */ dic = dictionary_new(10); CuAssertDblEquals(tc, 3.1415, iniparser_getdouble(dic, "dummy", 3.1415), 0); CuAssertDblEquals(tc, 0xFFFFFFFF, iniparser_getdouble(dic, NULL, 0xFFFFFFFF), 0); CuAssertDblEquals(tc, -0xFFFFFFFF, iniparser_getdouble(dic, "dummy", -0xFFFFFFFF), 0); /* Insert some values */ dictionary_set(dic, "double", ""); dictionary_set(dic, "double:good0", "0"); dictionary_set(dic, "double:good1", "-0"); dictionary_set(dic, "double:good2", "1.0"); dictionary_set(dic, "double:good3", "3.1415"); dictionary_set(dic, "double:good4", "6.6655957"); dictionary_set(dic, "double:good5", "-123456789.123456789"); /* Add dummy stuff too */ dictionary_set(dic, "double:bad0", "foo"); /* Get back the values */ CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:good0", 0xFF), 0); CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:good1", 0xFF), 0); CuAssertDblEquals(tc, 1.0, iniparser_getdouble(dic, "double:good2", 0xFF), 0); CuAssertDblEquals(tc, 3.1415, iniparser_getdouble(dic, "double:good3", 0xFF), 0); CuAssertDblEquals(tc, 6.6655957, iniparser_getdouble(dic, "double:good4", 0xFF), 0); CuAssertDblEquals(tc, -123456789.123456789, iniparser_getdouble(dic, "double:good5", 0xFF), 0); CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:bad0", 42.42), 0); dictionary_del(dic); } void Test_iniparser_getboolean(CuTest *tc) { unsigned i; char key_name[64]; dictionary *dic; const char *token_true[] = { "1", "true", "t", "TRUE", "T", "yes", "y", "YES" "Y", NULL }; const char *token_false[] = { "0", "false", "f", "FALSE", "F", "no", "n", "NO", "N", NULL }; /* NULL test */ CuAssertIntEquals(tc, 1, iniparser_getboolean(NULL, NULL, 1)); CuAssertIntEquals(tc, 1, iniparser_getboolean(NULL, "dummy", 1)); /* Check the def return element */ dic = dictionary_new(10); CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, "dummy", 1)); CuAssertIntEquals(tc, 0, iniparser_getboolean(dic, NULL, 0)); CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, "dummy", 1)); for (i = 0; token_true[i] != NULL; ++i) { sprintf(key_name, "bool:true%d", i); iniparser_set(dic, key_name, token_true[i]); } for (i = 0; token_false[i] != NULL; ++i) { sprintf(key_name, "bool:false%d", i); iniparser_set(dic, key_name, token_false[i]); } for (i = 0; token_true[i] != NULL; ++i) { sprintf(key_name, "bool:true%d", i); CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, key_name, 0)); } for (i = 0; token_false[i] != NULL; ++i) { sprintf(key_name, "bool:false%d", i); CuAssertIntEquals(tc, 0, iniparser_getboolean(dic, key_name, 1)); } /* Test bad boolean */ iniparser_set(dic, "bool:bad0", ""); iniparser_set(dic, "bool:bad1", "m'kay"); iniparser_set(dic, "bool:bad2", "42"); iniparser_set(dic, "bool:bad3", "_true"); CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad0", 0xFF)); CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad1", 0xFF)); CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad2", 0xFF)); CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad3", 0xFF)); dictionary_del(dic); } void Test_iniparser_line(CuTest *tc) { char section [ASCIILINESZ+1] ; char key [ASCIILINESZ+1] ; char val [ASCIILINESZ+1] ; /* Test empty line */ CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line("", section, key, val)); CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line(" ", section, key, val)); CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line("\t", section, key, val)); /* Test valid syntax */ CuAssertIntEquals(tc, LINE_SECTION, iniparser_line("[s]", section, key, val)); CuAssertStrEquals(tc, "s", section); CuAssertIntEquals(tc, LINE_SECTION, iniparser_line("[ section ]", section, key, val)); CuAssertStrEquals(tc, "section", section); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("k=1", section, key, val)); CuAssertStrEquals(tc, "k", key); CuAssertStrEquals(tc, "1", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = 0x42", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, "0x42", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key= value with spaces", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, "value with spaces", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("k =_!<>''", section, key, val)); CuAssertStrEquals(tc, "k", key); CuAssertStrEquals(tc, "_!<>''", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("empty_value =", section, key, val)); CuAssertStrEquals(tc, "empty_value", key); CuAssertStrEquals(tc, "", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("empty_value = \t\n", section, key, val)); CuAssertStrEquals(tc, "empty_value", key); CuAssertStrEquals(tc, "", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key =\tval # comment", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, "val", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key \n\n = \n val", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, "val", val); CuAssertIntEquals(tc, LINE_COMMENT, iniparser_line(";comment", section, key, val)); CuAssertIntEquals(tc, LINE_COMMENT, iniparser_line(" # comment", section, key, val)); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = \" do_not_strip \"", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, " do_not_strip ", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = ' '", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, " ", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = \"\"", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, "", val); CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = ''", section, key, val)); CuAssertStrEquals(tc, "key", key); CuAssertStrEquals(tc, "", val); /* Test syntax error */ CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("empty_value", section, key, val)); CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("not finished\\", section, key, val)); CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("0x42 / 0b101010", section, key, val)); } void Test_iniparser_load(CuTest *tc) { DIR *dir; struct dirent *curr; struct stat curr_stat; dictionary *dic; char ini_path[256]; /* Dummy tests */ dic = iniparser_load("/you/shall/not/path"); CuAssertPtrEquals(tc, NULL, dic); /* Test all the good .ini files */ dir = opendir(GOOD_INI_PATH); CuAssertPtrNotNullMsg(tc, "Cannot open good .ini conf directory", dir); for (curr = readdir(dir); curr != NULL; curr = readdir(dir)) { sprintf(ini_path, "%s/%s", GOOD_INI_PATH, curr->d_name); stat(ini_path, &curr_stat); if (S_ISREG(curr_stat.st_mode)) { dic = iniparser_load(ini_path); CuAssertPtrNotNullMsg(tc, ini_path, dic); dictionary_del(dic); } } closedir(dir); /* Test all the bad .ini files */ dir = opendir(BAD_INI_PATH); CuAssertPtrNotNullMsg(tc, "Cannot open bad .ini conf directory", dir); for (curr = readdir(dir); curr != NULL; curr = readdir(dir)) { sprintf(ini_path, "%s/%s", BAD_INI_PATH, curr->d_name); stat(ini_path, &curr_stat); if (S_ISREG(curr_stat.st_mode)) { dic = iniparser_load(ini_path); CuAssertPtrEquals_Msg(tc, ini_path, NULL, dic); dictionary_del(dic); } } closedir(dir); } void Test_dictionary_wrapper(CuTest *tc) { dictionary *dic; dic = dictionary_new(10); CuAssertIntEquals(tc, -1, iniparser_set(dic, NULL, NULL)); CuAssertIntEquals(tc, -1, iniparser_set(NULL, "section", "value")); CuAssertIntEquals(tc, 0, iniparser_set(dic, "section", NULL)); CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", "value")); CuAssertStrEquals(tc, "value", iniparser_getstring(dic, "section:key", NULL)); /* reset the key's value*/ CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", NULL)); CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section:key", "dummy")); CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", "value")); CuAssertStrEquals(tc, "value", iniparser_getstring(dic, "section:key", NULL)); iniparser_unset(dic, "section:key"); CuAssertStrEquals(tc, "dummy", iniparser_getstring(dic, "section:key", "dummy")); CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section", "dummy")); CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", NULL)); CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key1", NULL)); CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key2", NULL)); iniparser_unset(dic, "section"); CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section", NULL)); iniparser_freedict(dic); } static char _last_error[1024]; static int _error_callback(const char *format, ...) { int ret; va_list argptr; va_start(argptr, format); ret = vsprintf(_last_error, format, argptr); va_end(argptr); return ret; } void Test_iniparser_error_callback(CuTest *tc) { dictionary *dic; /* Specify our custom error_callback */ iniparser_set_error_callback(_error_callback); /* Trigger an error and check it was written on the right output */ dic = iniparser_load("/path/to/nowhere.ini"); CuAssertPtrEquals(tc, NULL, dic); CuAssertStrEquals(tc, "iniparser: cannot open /path/to/nowhere.ini\n", _last_error); /* Reset erro_callback */ _last_error[0] = '\0'; iniparser_set_error_callback(NULL); /* Make sure custom callback is no more called */ dic = iniparser_load("/path/to/nowhere.ini"); CuAssertPtrEquals(tc, NULL, dic); CuAssertStrEquals(tc, "", _last_error); }