Remove libinih from codebase and add it as a dependency instead.

main
Kevin Backhouse 3 years ago
parent 13ecfbc233
commit a4164ce866
No known key found for this signature in database
GPG Key ID: 9DD01852EE40366E

@ -41,7 +41,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libexpat1-dev zlib1g-dev libbrotli-dev
sudo apt-get install -y libexpat1-dev zlib1g-dev libbrotli-dev libinih-dev
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

@ -20,7 +20,7 @@ jobs:
fail-fast: false
matrix:
# arch suffering this issue: https://github.com/abseil/abseil-cpp/issues/709
container_image: ["fedora:latest", "debian:10", "archlinux:base", "ubuntu:20.04", "tgagor/centos-stream:2.0.11", "alpine:3.13"]
container_image: ["fedora:latest", "debian:11", "archlinux:base", "ubuntu:22.04", "tgagor/centos:stream9", "alpine:3.17"]
compiler: [g++, clang++]
build_type: [Release, Debug]
shared_libraries: [ON, OFF]

@ -50,7 +50,6 @@ jobs:
run: |
cd build-base_linux
cmake --install .
tree install
- name: Test
run: |

@ -26,6 +26,7 @@ jobs:
- name: install dependencies
run: |
brew install ninja
brew install inih
pushd /tmp
curl -LO https://github.com/google/googletest/archive/release-1.8.0.tar.gz
tar xzf release-1.8.0.tar.gz

@ -21,6 +21,7 @@ jobs:
- name: install dependencies
run: |
brew install ninja
brew install inih
pushd /tmp
curl -LO https://github.com/google/googletest/archive/release-1.8.0.tar.gz
tar xzf release-1.8.0.tar.gz

@ -115,6 +115,7 @@ jobs:
update: true
install: >-
base-devel
git
pacboy: >-
cc:p
gcc-libs:p
@ -128,6 +129,8 @@ jobs:
zlib:p
brotli:p
curl:p
meson:p
libinih:p
- name: Build
run: |
@ -150,7 +153,7 @@ jobs:
matrix:
build_type: [Release]
shared_libraries: [ON]
platform: [x64]
platform: [x86_64]
name: Cygwin ${{matrix.platform}} - BuildType:${{matrix.build_type}} - SHARED:${{matrix.shared_libraries}}
env:
SHELLOPTS: igncr
@ -180,6 +183,17 @@ jobs:
libbrotlicommon1
libbrotlidec1
libbrotli-devel
meson
ccache
- name: Build and install inih
run: |
git clone https://github.com/benhoyt/inih.git inih_build && \
cd inih_build && \
git checkout r56 && \
meson --buildtype=plain --prefix=/usr builddir && \
meson compile -C builddir && \
meson install -C builddir
- name: Build
run: |

@ -103,6 +103,7 @@ jobs:
- name: install dependencies
run: |
brew install ninja
brew install inih
pushd /tmp
curl -LO https://github.com/google/googletest/archive/release-1.8.0.tar.gz
tar xzf release-1.8.0.tar.gz

@ -1217,7 +1217,7 @@ Update your system and install the build tools and dependencies (zlib, expat, gt
```bash
$ sudo apt --yes update
$ sudo apt install --yes build-essential git clang ccache python3 libxml2-utils cmake python3 libexpat1-dev libz-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgtest-dev google-mock
$ sudo apt install --yes build-essential git clang ccache python3 libxml2-utils cmake python3 libexpat1-dev libz-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgtest-dev google-mock libinih-dev
```
For users of other platforms, the script <exiv2dir>/ci/install_dependencies.sh has code used to configure many platforms. The code in that file is a useful guide to configuring your platform.

@ -20,6 +20,17 @@ debian_build_gtest() {
cd ..
}
# Centos doesn't have a working version of the inih library, so we need to build it ourselves.
centos_build_inih() {
[-d inih_build ] || git clone https://github.com/benhoyt/inih.git inih_build
cd inih_build
git checkout r56
meson --buildtype=plain builddir
meson compile -C builddir
meson install -C builddir
cd ..
}
# workaround for really bare-bones Archlinux containers:
if [ -x "$(command -v pacman)" ]; then
pacman --noconfirm -Sy
@ -30,39 +41,46 @@ distro_id=$(grep '^ID=' /etc/os-release|awk -F = '{print $2}'|sed 's/\"//g')
case "$distro_id" in
'fedora')
dnf -y --refresh install gcc-c++ clang cmake make expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel gtest-devel which dos2unix glibc-langpack-en diffutils
dnf -y --refresh install gcc-c++ clang cmake make expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel gtest-devel which dos2unix glibc-langpack-en diffutils inih-devel
;;
'debian')
apt-get update
apt-get install -y cmake g++ clang make libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgtest-dev libxml2-utils
apt-get install -y cmake g++ clang make libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgtest-dev libxml2-utils libinih-dev
debian_build_gtest
;;
'arch')
pacman --noconfirm -Syu
pacman --noconfirm --needed -S gcc clang cmake make expat zlib brotli libssh curl gtest dos2unix which diffutils
pacman --noconfirm --needed -S gcc clang cmake make expat zlib brotli libssh curl gtest dos2unix which diffutils libinih
;;
'ubuntu')
apt-get update
apt-get install -y cmake g++ clang make libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgtest-dev google-mock libxml2-utils
apt-get install -y cmake g++ clang make libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgtest-dev google-mock libxml2-utils libinih-dev
debian_build_gtest
;;
'alpine')
apk update
apk add gcc g++ clang cmake make expat-dev zlib-dev brotli-dev libssh-dev curl-dev gtest gtest-dev gmock libintl gettext-dev which dos2unix bash libxml2-utils diffutils
apk add gcc g++ clang cmake make expat-dev zlib-dev brotli-dev libssh-dev curl-dev gtest gtest-dev gmock libintl gettext-dev which dos2unix bash libxml2-utils diffutils inih-dev inih-inireader-dev
;;
'rhel')
dnf clean all
dnf -y install gcc-c++ clang cmake make expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel which dos2unix inih-devel
;;
'centos'|'rhel')
'centos')
dnf clean all
dnf -y install gcc-c++ clang cmake make expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel which dos2unix
dnf -y install gcc-c++ clang cmake make expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel which dos2unix git
dnf -y --enablerepo=crb install meson
centos_build_inih
;;
'opensuse-tumbleweed')
zypper --non-interactive refresh
zypper --non-interactive install gcc-c++ clang cmake make libexpat-devel zlib-devel libbrotli-devel libssh-devel curl libcurl-devel git which dos2unix libxml2-tools
zypper --non-interactive install gcc-c++ clang cmake make libexpat-devel zlib-devel libbrotli-devel libssh-devel curl libcurl-devel git which dos2unix libxml2-tools libinih-devel
pushd /tmp
curl -LO https://github.com/google/googletest/archive/release-1.8.0.tar.gz
tar xzf release-1.8.0.tar.gz

@ -0,0 +1,43 @@
set(inih_LIBRARY_NAMES "inih" "libinih")
set(inih_inireader_LIBRARY_NAMES "INIReader" "libINIReader")
find_path(inih_INCLUDE_DIR
NAMES "ini.h"
DOC "inih include directory")
find_path(inih_inireader_INCLUDE_DIR
NAMES "INIReader.h"
DOC "INIReader include directory")
find_library(inih_LIBRARY
NAMES ${inih_LIBRARY_NAMES}
DOC "inih library")
find_library(inih_inireader_LIBRARY
NAMES ${inih_inireader_LIBRARY_NAMES}
DOC "inih library")
mark_as_advanced(inih_INCLUDE_DIR)
mark_as_advanced(inih_LIBRARY)
mark_as_advanced(inih_inireader_INCLUDE_DIR)
mark_as_advanced(inih_inireader_LIBRARY)
find_package_handle_standard_args(inih REQUIRED_VARS inih_LIBRARY inih_INCLUDE_DIR)
if(inih_FOUND)
set(inih_INCLUDE_DIRS "${inih_INCLUDE_DIR}")
set(inih_LIBRARIES "${inih_LIBRARY}")
if(NOT TARGET inih::libinih)
add_library(inih::libinih INTERFACE IMPORTED)
endif()
set_property(TARGET inih::libinih PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${inih_INCLUDE_DIRS}")
set_property(TARGET inih::libinih PROPERTY INTERFACE_LINK_LIBRARIES "${inih_LIBRARIES}")
set(inih_inireader_INCLUDE_DIRS "${inih_inireader_INCLUDE_DIR}")
set(inih_inireader_LIBRARIES "${inih_inireader_LIBRARY}")
if(NOT TARGET inih::inireader)
add_library(inih::inireader INTERFACE IMPORTED)
endif()
set_property(TARGET inih::inireader PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${inih_inireader_INCLUDE_DIRS}")
set_property(TARGET inih::inireader PROPERTY INTERFACE_LINK_LIBRARIES "${inih_inireader_LIBRARIES}")
endif()

@ -76,6 +76,14 @@ if( ICONV_FOUND )
message ( "-- Iconv_LIBRARIES : " ${Iconv_LIBRARIES} )
endif()
find_package(inih)
if( inih_FOUND )
message ( "-- inih_INCLUDE_DIRS : " ${inih_INCLUDE_DIRS} )
message ( "-- inih_LIBRARIES : " ${inih_LIBRARIES} )
message ( "-- inih_inireader_INCLUDE_DIRS : " ${inih_inireader_INCLUDE_DIRS} )
message ( "-- inih_inireader_LIBRARIES : " ${inih_inireader_LIBRARIES} )
endif()
if( BUILD_WITH_CCACHE )
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)

@ -25,6 +25,8 @@ class Exiv2Conan(ConanFile):
self.requires('brotli/1.0.9')
self.requires('inih/55')
if self.options.webready:
self.requires('libcurl/7.85.0')

@ -21,7 +21,6 @@
#include "exiv2/gifimage.hpp"
#include "exiv2/http.hpp"
#include "exiv2/image.hpp"
#include "exiv2/ini.hpp"
#include "exiv2/iptc.hpp"
#include "exiv2/jp2image.hpp"
#include "exiv2/jpgimage.hpp"

@ -1,193 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later AND BSD-3-Clause
// Read an INI file into easy-to-access name/value pairs.
// inih and INIReader are released under the New BSD license (see LICENSE.txt).
// Go to the project home page for more info:
//
// https://github.com/benhoyt/inih
#ifndef __INIREADER_H__
#define __INIREADER_H__
#include "exiv2lib_export.h"
#include "config.h"
#include <map>
#include <string>
namespace Exiv2 {
#ifndef __INI_H__
#define __INI_H__
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif
//! @brief typedef for prototype of handler function.
using ini_handler = int (*)(void* user, const char* section, const char* name, const char* value);
//! Typedef for prototype of fgets-style reader function.
using ini_reader = char* (*)(char* str, int num, void* stream);
/*!
@brief Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's configparser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
@param filename path to file
@param handler user defined handler
@param user void pointer passed to user handler
@return 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
@return 0 on success
*/
int ini_parse(const char* filename, ini_handler handler, void* user);
/*! @brief Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that.
@param file open "C" file
@param handler user defined handler
@param user void pointer passed to user handler
*/
int ini_parse_file(FILE* file, ini_handler handler, void* user);
/*! @brief Same as ini_parse(), but takes an ini_reader function pointer instead of
filename. Used for implementing custom or string-based I/O.
@param reader magic
@param stream more magic
@param handler user defined handler
@param user void pointer passed to user handler
@return 0 on success
*/
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, void* user);
/*! @brief Nonzero to allow multi-line value parsing, in the style of Python's
configparser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed.
*/
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
#endif
/*! @brief Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See http://code.google.com/p/inih/issues/detail?id=21
*/
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
/*! @brief Nonzero to allow inline comments (with valid inline comment characters
specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
Python 3.2+ configparser behaviour.
*/
#ifndef INI_ALLOW_INLINE_COMMENTS
#define INI_ALLOW_INLINE_COMMENTS 1
#endif
#ifndef INI_INLINE_COMMENT_PREFIXES
#define INI_INLINE_COMMENT_PREFIXES ";"
#endif
//! @brief Nonzero to use stack, zero to use heap (malloc/free).
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
#endif
//! @brief Stop parsing on first error (default is to keep parsing).
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
#endif
//! @brief Maximum line length for any line in INI file.
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
#endif
#ifdef __cplusplus
}
#endif
#endif /* __INI_H__ */
/*! @brief Read an INI file into easy-to-access name/value pairs. (Note that I've gone
for simplicity here rather than speed, but it should be pretty decent.)
*/
class EXIV2API INIReader {
public:
/*! @brief Construct INIReader and parse given filename. See ini.h for more info
about the parsing.
*/
explicit INIReader(const std::string& filename);
/*! @brief Return the result of ini_parse(), i.e., 0 on success, line number of
first error on parse error, or -1 on file open error.
*/
[[nodiscard]] int ParseError() const;
/*! @brief Get a string value from INI file, returning default_value if not found.
@param section name of section
@param name name of key
@param default_value default if not found
@return value
*/
std::string Get(const std::string& section, const std::string& name, const std::string& default_value);
/*! @brief Get an integer (long) value from INI file, returning default_value if
not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2").
@param section name of section
@param name name of key
@param default_value default if not found
@return value
*/
long GetInteger(const std::string& section, const std::string& name, long default_value);
/*! @brief Get a real (floating point double) value from INI file, returning
default_value if not found or not a valid floating point value
according to strtod().
@param section name of section
@param name name of key
@param default_value default if not found
@return value
*/
double GetReal(const std::string& section, const std::string& name, double default_value);
/*! @brief Get a boolean value from INI file, returning default_value if not found or if
not a valid true/false value. Valid true values are "true", "yes", "on", "1",
and valid false values are "false", "no", "off", "0" (not case sensitive).
@param section name of section
@param name name of key
@param default_value default if not found
@return value
*/
bool GetBoolean(const std::string& section, const std::string& name, bool default_value);
private:
int _error; //!< status
std::map<std::string, std::string> _values; //!< values from file
static std::string MakeKey(const std::string& section,
const std::string& name); //!< return key encoded from section/name
static int ValueHandler(void* user, const char* section, const char* name,
const char* value); //!< value handler
};
} // namespace Exiv2
#endif // __INIREADER_H__

@ -72,6 +72,9 @@ target_include_directories(path-test PRIVATE
install( TARGETS metacopy RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
target_link_libraries( ini-test PRIVATE inih::libinih )
target_link_libraries( ini-test PRIVATE inih::inireader )
if( EXPAT_FOUND )
add_executable( geotag geotag.cpp)
list(APPEND APPLICATIONS geotag)

@ -9,6 +9,7 @@ Config loaded from : 'initest.ini' version=6, name=Bob Smith, email=bob@smith.co
*/
// Example that shows simple usage of the INIReader class
#include <INIReader.h>
#include <exiv2/exiv2.hpp>
#include <iostream>
@ -20,7 +21,7 @@ int main() {
#endif
const char* ini = "ini-test.ini";
Exiv2::INIReader reader(ini);
INIReader reader(ini);
if (reader.ParseError() < 0) {
std::cerr << "Can't load '" << ini << "'" << std::endl;

@ -57,7 +57,6 @@ set(PUBLIC_HEADERS
../include/exiv2/http.hpp
../include/exiv2/image.hpp
../include/exiv2/image_types.hpp
../include/exiv2/ini.hpp
../include/exiv2/iptc.hpp
../include/exiv2/jp2image.hpp
../include/exiv2/jpgimage.hpp
@ -101,7 +100,6 @@ add_library( exiv2lib
gifimage.cpp
http.cpp
image.cpp
ini.cpp
iptc.cpp
jp2image.cpp
jpgimage.cpp
@ -250,6 +248,13 @@ if( ICONV_FOUND )
target_link_libraries( exiv2lib PRIVATE Iconv::Iconv )
endif()
if( inih_FOUND )
target_link_libraries( exiv2lib_int PRIVATE inih::libinih )
target_link_libraries( exiv2lib_int PRIVATE inih::inireader )
target_link_libraries( exiv2lib PRIVATE inih::libinih )
target_link_libraries( exiv2lib PRIVATE inih::inireader )
endif()
write_basic_package_version_file(exiv2ConfigVersion.cmake COMPATIBILITY ExactVersion)
install(TARGETS exiv2lib EXPORT exiv2Config

@ -1,239 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later AND BSD-3-Clause
// Read an INI file into easy-to-access name/value pairs.
// inih and INIReader are released under the New BSD license (see LICENSE.txt).
// Go to the project home page for more info:
//
// https://github.com/benhoyt/inih
#include "ini.hpp"
#include <algorithm>
#include <cctype>
#include <cstdlib>
using std::string;
using namespace Exiv2;
#include <cstring>
#if !INI_USE_STACK
#include <cstdlib>
#endif
#define MAX_SECTION 50
#define MAX_NAME 50
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s) {
char* p = s + strlen(s);
while (p > s && isspace(static_cast<unsigned char>(*--p)))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s) {
while (*s && isspace(static_cast<unsigned char>(*s)))
s++;
return const_cast<char*>(s);
}
/* Return pointer to first char (of chars) or inline comment in given string,
or pointer to null at end of string if neither found. Inline comment must
be prefixed by a whitespace character to register as a comment. */
static char* find_chars_or_comment(const char* s, const char* chars) {
#if INI_ALLOW_INLINE_COMMENTS
int was_space = 0;
while (*s && (!chars || !strchr(chars, *s)) && !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
was_space = isspace(static_cast<unsigned char>(*s));
s++;
}
#else
while (*s && (!chars || !strchr(chars, *s))) {
s++;
}
#endif
return const_cast<char*>(s);
}
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
static char* strncpy0(char* dest, const char* src, size_t size) {
memcpy(dest, src, size);
dest[size - 1] = '\0';
return dest;
}
/* See documentation in header file. */
int Exiv2::ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, void* user) {
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
char line[INI_MAX_LINE];
#else
char* line;
#endif
char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = "";
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
#if !INI_USE_STACK
line = (char*)malloc(INI_MAX_LINE);
if (!line) {
return -2;
}
#endif
/* Scan through stream line by line */
while (reader(line, INI_MAX_LINE, stream)) {
lineno++;
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && static_cast<unsigned char>(start[0]) == 0xEF && static_cast<unsigned char>(start[1]) == 0xBB &&
static_cast<unsigned char>(start[2]) == 0xBF) {
start += 3;
}
#endif
start = lskip(rstrip(start));
if (*start == ';' || *start == '#') {
/* Per Python configparser, allow both ; and # comments at the
start of a line */
}
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
/* Non-blank line with leading whitespace, treat as continuation
of previous name's value (as per Python configparser). */
if (!handler(user, section, prev_name, start) && !error)
error = lineno;
}
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_chars_or_comment(start + 1, "]");
if (*end == ']') {
*end = '\0';
strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0';
} else if (!error) {
/* No ']' found on section line */
error = lineno;
}
} else if (*start) {
/* Not a comment, must be a name[=:]value pair */
end = find_chars_or_comment(start, "=:");
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
value = lskip(end + 1);
#if INI_ALLOW_INLINE_COMMENTS
end = find_chars_or_comment(value, nullptr);
if (*end)
*end = '\0';
#endif
rstrip(value);
/* Valid name[=:]value pair found, call handler */
strncpy0(prev_name, name, sizeof(prev_name));
if (!handler(user, section, name, value) && !error)
error = lineno;
} else if (!error) {
/* No '=' or ':' found on name[=:]value line */
error = lineno;
}
}
#if INI_STOP_ON_FIRST_ERROR
if (error)
break;
#endif
}
#if !INI_USE_STACK
free(line);
#endif
return error;
}
/* See documentation in header file. */
int Exiv2::ini_parse_file(FILE* file, ini_handler handler, void* user) {
return Exiv2::ini_parse_stream(reinterpret_cast<ini_reader>(fgets), file, handler, user);
}
/* See documentation in header file. */
int Exiv2::ini_parse(const char* filename, ini_handler handler, void* user) {
FILE* file;
int error;
file = fopen(filename, "r");
if (!file)
return -1;
error = Exiv2::ini_parse_file(file, handler, user);
fclose(file);
return error;
}
INIReader::INIReader(const std::string& filename) {
_error = ini_parse(filename.c_str(), ValueHandler, this);
}
int INIReader::ParseError() const {
return _error;
}
string INIReader::Get(const string& section, const string& name, const string& default_value) {
string key = MakeKey(section, name);
return _values.count(key) ? _values[key] : default_value;
}
long INIReader::GetInteger(const string& section, const string& name, long default_value) {
string valstr = Get(section, name, "");
const char* value = valstr.c_str();
char* end;
// This parses "1234" (decimal) and also "0x4D2" (hex)
long n = std::strtol(value, &end, 0);
return end > value ? n : default_value;
}
double INIReader::GetReal(const string& section, const string& name, double default_value) {
string valstr = Get(section, name, "");
const char* value = valstr.c_str();
char* end;
double n = strtod(value, &end);
return end > value ? n : default_value;
}
bool INIReader::GetBoolean(const string& section, const string& name, bool default_value) {
string valstr = Get(section, name, "");
// Convert to lower case to make string comparisons case-insensitive
std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1")
return true;
if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0")
return false;
return default_value;
}
string INIReader::MakeKey(const string& section, const string& name) {
string key = section + "=" + name;
// Convert to lower case to make section/name lookups case-insensitive
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
return key;
}
int INIReader::ValueHandler(void* user, const char* section, const char* name, const char* value) {
auto reader = static_cast<INIReader*>(user);
string key = MakeKey(section, name);
if (!reader->_values[key].empty())
reader->_values[key] += "\n";
reader->_values[key] += value;
return 1;
}

@ -7,7 +7,6 @@
// included header files
#include "config.h"
#include "ini.hpp"
#include "makernote_int.hpp"
#include "safe_op.hpp"
#include "tiffcomposite_int.hpp"
@ -16,6 +15,7 @@
#include "utils.hpp"
// + standard includes
#include <INIReader.h>
#include <array>
#include <filesystem>
#include <iostream>
@ -81,7 +81,7 @@ std::string getExiv2ConfigPath() {
std::string readExiv2Config(const std::string& section, const std::string& value, const std::string& def) {
std::string result = def;
Exiv2::INIReader reader(Exiv2::Internal::getExiv2ConfigPath());
INIReader reader(Exiv2::Internal::getExiv2ConfigPath());
if (reader.ParseError() == 0) {
result = reader.Get(section, value, def);
}

@ -42,6 +42,8 @@ target_link_libraries(unit_tests
GTest::gtest
GTest::gtest_main
std::filesystem
inih::libinih
inih::inireader
)
# ZLIB is used in exiv2lib_int.

Loading…
Cancel
Save