Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add libini #428

Merged
merged 2 commits into from
Apr 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,9 @@ if(WITH_LOCAL_BACKEND)
list(APPEND LIBS_TO_LINK ${LIBRT_LIBRARIES})
endif()

option(WITH_LOCAL_CONFIG "Read local context attributes from /etc/libiio.ini" OFF)
option(WITH_LOCAL_CONFIG "Read local context attributes from /etc/libiio.ini" ON)
if (WITH_LOCAL_CONFIG)
find_library(LIBINI_LIBRARIES ini)
find_path(LIBINI_INCLUDE_DIR ini.h)
if (NOT LIBINI_LIBRARIES OR NOT LIBINI_INCLUDE_DIR)
message(SEND_ERROR "WITH_LOCAL_CONFIG option requires libini to be installed")
else()
include_directories(${LIBINI_INCLUDE_DIR})
list(APPEND LIBS_TO_LINK ${LIBINI_LIBRARIES})
endif()
list(APPEND LIBIIO_CFILES ./libini/libini.c)
endif()
endif()

Expand Down
2 changes: 1 addition & 1 deletion README_BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Cmake Options | Default | Description |
`WITH_DOC` | OFF | Generate documentation with Doxygen |
`WITH_MAN` | OFF | Generate and install man pages |
`WITH_TESTS` | ON | Build the test programs |
`WITH_LOCAL_CONFIG` | OFF | Read local context attributes from /etc/libiio.ini |
`WITH_LOCAL_CONFIG` | ON | Read local context attributes from /etc/libiio.ini |
`ENABLE_PACKAGING` | OFF | Create .deb/.rpm/.tar.gz via 'make package' |
`INSTALL_UDEV_RULE` | ON | Install a udev rule for detection of USB devices |

Expand Down
502 changes: 502 additions & 0 deletions libini/LICENSE.txt

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions libini/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Libini is a simple library to read INI configuration files.

https://github.com/pcercuei/libini
91 changes: 91 additions & 0 deletions libini/ini.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* libini - Library to read INI configuration files
*
* Copyright (C) 2014 Paul Cercueil <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/

#ifndef __INI_H
#define __INI_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _WIN32
# ifdef LIBINI_EXPORTS
# define __api __declspec(dllexport)
# else
# define __api __declspec(dllimport)
# endif
#elif __GNUC__ >= 4
# define __api __attribute__((visibility ("default")))
#else
# define __api
#endif

#include <stdlib.h>

struct INI;

__api struct INI *ini_open(const char *file);
__api struct INI *ini_open_mem(const char *buf, size_t len);

__api void ini_close(struct INI *ini);

/* Jump to the next section.
* if 'name' is set, the pointer passed as argument
* points to the name of the section. 'name_len' is set to the length
* of the char array.
* XXX: the pointer will be invalid as soon as ini_close() is called.
*
* Returns:
* -EIO if an error occured while reading the file,
* 0 if no more section can be found,
* 1 otherwise.
*/
__api int ini_next_section(struct INI *ini,
const char **name, size_t *name_len);

/* Read a key/value pair.
* 'key' and 'value' must be valid pointers. The pointers passed as arguments
* will point to the key and value read. 'key_len' and 'value_len' are
* set to the length of their respective char arrays.
* XXX: the pointers will be invalid as soon as ini_close() is called.
*
* Returns:
* -EIO if an error occured while reading the file,
* 0 if no more key/value pairs can be found,
* 1 otherwise.
*/
__api int ini_read_pair(struct INI *ini,
const char **key, size_t *key_len,
const char **value, size_t *value_len);

/* Set the read head to a specified offset. */
__api void ini_set_read_pointer(struct INI *ini, const char *pointer);

/* Get the number of the line that contains the specified address.
*
* Returns:
* -EINVAL if the pointer points outside the INI string,
* The line number otherwise.
*/
__api int ini_get_line_number(struct INI *ini, const char *pointer);

#ifdef __cplusplus
}
#endif

#undef __api

#endif /* __INI_H */
251 changes: 251 additions & 0 deletions libini/libini.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/*
* libini - Library to read INI configuration files
*
* Copyright (C) 2014 Paul Cercueil <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/

#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#include "ini.h"

struct INI {
const char *buf, *end, *curr;
bool free_buf_on_exit;
};

static struct INI *_ini_open_mem(const char *buf,
size_t len, bool free_buf_on_exit)
{
struct INI *ini = malloc(sizeof(*ini));
if (!ini) {
errno = ENOMEM;
return NULL;
}

ini->buf = ini->curr = buf;
ini->end = buf + len;
ini->free_buf_on_exit = free_buf_on_exit;
return ini;
}

struct INI *ini_open_mem(const char *buf, size_t len)
{
return _ini_open_mem(buf, len, false);
}

struct INI *ini_open(const char *file)
{
FILE *f;
char *buf, *ptr;
size_t len, left;
struct INI *ini = NULL;
int ret = 0;

f = fopen(file, "r");
if (!f) {
ret = -errno;
goto err_set_errno;
}

fseek(f, 0, SEEK_END);
len = ftell(f);

if (!len) {
ret = -EINVAL;
goto error_fclose;
}

buf = malloc(len);
if (!buf) {
ret = -ENOMEM;
goto error_fclose;
}

rewind(f);

for (left = len, ptr = buf; left; ) {
size_t tmp = fread(ptr, 1, left, f);
if (tmp == 0) {
if (feof(f))
break;

ret = -ferror(f);
free(buf);
goto error_fclose;
}

left -= tmp;
ptr += tmp;
}

ini = _ini_open_mem(buf, len - left, true);
if (!ini)
ret = -errno;

error_fclose:
fclose(f);
err_set_errno:
errno = -ret;
return ini;
}

void ini_close(struct INI *ini)
{
if (ini->free_buf_on_exit)
free((char *) ini->buf);
free(ini);
}

static bool skip_comments(struct INI *ini)
{
const char *curr = ini->curr;
const char *end = ini->end;

while (curr != end) {
if (*curr == '\r' || *curr == '\n')
curr++;
else if (*curr == '#')
do { curr++; } while (curr != end && *curr != '\n');
else
break;
}

ini->curr = curr;
return curr == end;
}

static bool skip_line(struct INI *ini)
{
const char *curr = ini->curr;
const char *end = ini->end;

for (; curr != end && *curr != '\n'; curr++);
if (curr == end) {
ini->curr = end;
return true;
} else {
ini->curr = curr + 1;
return false;
}
}

int ini_next_section(struct INI *ini, const char **name, size_t *name_len)
{
const char *_name;
if (ini->curr == ini->end)
return 0; /* EOF: no more sections */

if (ini->curr == ini->buf) {
if (skip_comments(ini) || *ini->curr != '[')
return -EIO;
} else while (*ini->curr != '[' && !skip_line(ini));

if (ini->curr == ini->end)
return 0; /* EOF: no more sections */

_name = ++ini->curr;
do {
ini->curr++;
if (ini->curr == ini->end || *ini->curr == '\n')
return -EIO;
} while (*ini->curr != ']');


if (name && name_len) {
*name = _name;
*name_len = ini->curr - _name;
}

ini->curr++;
return 1;
}

int ini_read_pair(struct INI *ini,
const char **key, size_t *key_len,
const char **value, size_t *value_len)
{
size_t _key_len = 0;
const char *_key, *_value, *curr, *end = ini->end;

if (skip_comments(ini))
return 0;
curr = _key = ini->curr;

if (*curr == '[')
return 0;

while (true) {
curr++;

if (curr == end || *curr == '\n') {
return -EIO;

} else if (*curr == '=') {
const char *tmp = curr;
_key_len = curr - _key;
for (tmp = curr - 1; tmp > ini->curr &&
(*tmp == ' ' || *tmp == '\t'); tmp--)
_key_len--;
curr++;
break;
}
}

/* Skip whitespaces. */
while (curr != end && (*curr == ' ' || *curr == '\t')) curr++;
if (curr == end)
return -EIO;

_value = curr;

while (curr != end && *curr != '\n') curr++;
if (curr == end)
return -EIO;

*value = _value;
*value_len = curr - _value - (*(curr - 1) == '\r');
*key = _key;
*key_len = _key_len;

ini->curr = ++curr;
return 1;
}

void ini_set_read_pointer(struct INI *ini, const char *pointer)
{
if ((uintptr_t) pointer < (uintptr_t) ini->buf)
ini->curr = ini->buf;
else if ((uintptr_t) pointer > (uintptr_t) ini->end)
ini->curr = ini->end;
else
ini->curr = pointer;
}

int ini_get_line_number(struct INI *ini, const char *pointer)
{
int line = 1;
const char *it;

if ((uintptr_t) pointer < (uintptr_t) ini->buf)
return -EINVAL;
if ((uintptr_t) pointer > (uintptr_t) ini->end)
return -EINVAL;

for (it = ini->buf; (uintptr_t) it < (uintptr_t) pointer; it++)
line += (*it == '\n');

return line;
}
7 changes: 4 additions & 3 deletions local.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include "debug.h"
#include "iio-private.h"
#include "sort.h"
#ifdef WITH_LOCAL_CONFIG
#include "libini/ini.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

does clang-format have a preference for #include "headers" to be added after #include <headers>?
maybe it's a slightly better idea to move all this block after this;

but we can leave it as is for now;

#endif


#include <dirent.h>
#include <errno.h>
Expand All @@ -39,9 +43,6 @@
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef WITH_LOCAL_CONFIG
#include <ini.h>
#endif

#define DEFAULT_TIMEOUT_MS 1000

Expand Down