1
0
mirror of https://github.com/benhoyt/inih.git synced 2025-01-28 22:52:54 +08:00

Add visibility symbols (#134)

They are required to properly build DLLs on Windows, and improve the
quality of shared objects on Linux.
See https://gcc.gnu.org/wiki/Visibility for details.

This issue was first discovered here:
https://github.com/mesonbuild/wrapdb/pull/340#issuecomment-1075102565
This commit is contained in:
Andrea Pappacoda 2022-03-23 20:30:27 +01:00 committed by GitHub
parent a52c0705c0
commit 5a31af99c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 19 deletions

View File

@ -15,6 +15,27 @@
#include <map> #include <map>
#include <string> #include <string>
// Visibility symbols, required for Windows DLLs
#ifndef INI_API
#if defined _WIN32 || defined __CYGWIN__
# ifdef INI_SHARED_LIB
# ifdef INI_SHARED_LIB_BUILDING
# define INI_API __declspec(dllexport)
# else
# define INI_API __declspec(dllimport)
# endif
# else
# define INI_API
# endif
#else
# if defined(__GNUC__) && __GNUC__ >= 4
# define INI_API __attribute__ ((visibility ("default")))
# else
# define INI_API
# endif
#endif
#endif
// Read an INI file into easy-to-access name/value pairs. (Note that I've gone // 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.) // for simplicity here rather than speed, but it should be pretty decent.)
class INIReader class INIReader
@ -22,45 +43,45 @@ class INIReader
public: public:
// Construct INIReader and parse given filename. See ini.h for more info // Construct INIReader and parse given filename. See ini.h for more info
// about the parsing. // about the parsing.
explicit INIReader(const std::string& filename); INI_API explicit INIReader(const std::string& filename);
// Construct INIReader and parse given buffer. See ini.h for more info // Construct INIReader and parse given buffer. See ini.h for more info
// about the parsing. // about the parsing.
explicit INIReader(const char *buffer, size_t buffer_size); INI_API explicit INIReader(const char *buffer, size_t buffer_size);
// Return the result of ini_parse(), i.e., 0 on success, line number of // 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. // first error on parse error, or -1 on file open error.
int ParseError() const; INI_API int ParseError() const;
// Get a string value from INI file, returning default_value if not found. // Get a string value from INI file, returning default_value if not found.
std::string Get(const std::string& section, const std::string& name, INI_API std::string Get(const std::string& section, const std::string& name,
const std::string& default_value) const; const std::string& default_value) const;
// Get a string value from INI file, returning default_value if not found, // Get a string value from INI file, returning default_value if not found,
// empty, or contains only whitespace. // empty, or contains only whitespace.
std::string GetString(const std::string& section, const std::string& name, INI_API std::string GetString(const std::string& section, const std::string& name,
const std::string& default_value) const; const std::string& default_value) const;
// Get an integer (long) value from INI file, returning default_value if // 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"). // not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2").
long GetInteger(const std::string& section, const std::string& name, long default_value) const; INI_API long GetInteger(const std::string& section, const std::string& name, long default_value) const;
// Get a real (floating point double) value from INI file, returning // Get a real (floating point double) value from INI file, returning
// default_value if not found or not a valid floating point value // default_value if not found or not a valid floating point value
// according to strtod(). // according to strtod().
double GetReal(const std::string& section, const std::string& name, double default_value) const; INI_API double GetReal(const std::string& section, const std::string& name, double default_value) const;
// Get a boolean value from INI file, returning default_value if not found or if // 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", // 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). // and valid false values are "false", "no", "off", "0" (not case sensitive).
bool GetBoolean(const std::string& section, const std::string& name, bool default_value) const; INI_API bool GetBoolean(const std::string& section, const std::string& name, bool default_value) const;
// Return true if the given section exists (section must contain at least // Return true if the given section exists (section must contain at least
// one name=value pair). // one name=value pair).
bool HasSection(const std::string& section) const; INI_API bool HasSection(const std::string& section) const;
// Return true if a value exists with the given section and field names. // Return true if a value exists with the given section and field names.
bool HasValue(const std::string& section, const std::string& name) const; INI_API bool HasValue(const std::string& section, const std::string& name) const;
private: private:
int _error; int _error;

29
ini.h
View File

@ -26,6 +26,27 @@ extern "C" {
#define INI_HANDLER_LINENO 0 #define INI_HANDLER_LINENO 0
#endif #endif
/* Visibility symbols, required for Windows DLLs */
#ifndef INI_API
#if defined _WIN32 || defined __CYGWIN__
# ifdef INI_SHARED_LIB
# ifdef INI_SHARED_LIB_BUILDING
# define INI_API __declspec(dllexport)
# else
# define INI_API __declspec(dllimport)
# endif
# else
# define INI_API
# endif
#else
# if defined(__GNUC__) && __GNUC__ >= 4
# define INI_API __attribute__ ((visibility ("default")))
# else
# define INI_API
# endif
#endif
#endif
/* Typedef for prototype of handler function. */ /* Typedef for prototype of handler function. */
#if INI_HANDLER_LINENO #if INI_HANDLER_LINENO
typedef int (*ini_handler)(void* user, const char* section, typedef int (*ini_handler)(void* user, const char* section,
@ -52,22 +73,22 @@ typedef char* (*ini_reader)(char* str, int num, void* stream);
stop on first error), -1 on file open error, or -2 on memory allocation stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero). error (only when INI_USE_STACK is zero).
*/ */
int ini_parse(const char* filename, ini_handler handler, void* user); INI_API int ini_parse(const char* filename, ini_handler handler, void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't /* 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. */ close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file, ini_handler handler, void* user); INI_API int ini_parse_file(FILE* file, ini_handler handler, void* user);
/* Same as ini_parse(), but takes an ini_reader function pointer instead of /* Same as ini_parse(), but takes an ini_reader function pointer instead of
filename. Used for implementing custom or string-based I/O (see also filename. Used for implementing custom or string-based I/O (see also
ini_parse_string). */ ini_parse_string). */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, INI_API int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user); void* user);
/* Same as ini_parse(), but takes a zero-terminated string with the INI data /* Same as ini_parse(), but takes a zero-terminated string with the INI data
instead of a file. Useful for parsing INI data from a network socket or instead of a file. Useful for parsing INI data from a network socket or
already in memory. */ already in memory. */
int ini_parse_string(const char* string, ini_handler handler, void* user); INI_API int ini_parse_string(const char* string, ini_handler handler, void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's /* 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 configparser. If allowed, ini_parse() will call the handler with the same

View File

@ -6,6 +6,7 @@ project('inih',
#### options #### #### options ####
arg_static = [] arg_static = []
distro_install = get_option('distro_install') distro_install = get_option('distro_install')
extra_args = []
if distro_install if distro_install
pkg = import('pkgconfig') pkg = import('pkgconfig')
@ -55,15 +56,26 @@ else
endif endif
endif endif
if host_machine.system() == 'windows'
lib = get_option('default_library')
if lib == 'both'
error('default_library=both is not supported on Windows')
elif lib == 'shared'
extra_args += '-DINI_SHARED_LIB'
add_project_arguments('-DINI_SHARED_LIB_BUILDING', language: ['c', 'cpp'])
endif
endif
#### inih #### #### inih ####
inc_inih = include_directories('.') inc_inih = include_directories('.')
lib_inih = library('inih', lib_inih = library('inih',
['ini.c'], ['ini.c'],
include_directories : inc_inih, include_directories : inc_inih,
c_args : arg_static, c_args : [arg_static, extra_args],
install : distro_install, install : distro_install,
soversion : '0' soversion : '0',
gnu_symbol_visibility: 'hidden'
) )
if distro_install if distro_install
@ -72,12 +84,13 @@ if distro_install
pkg.generate(lib_inih, pkg.generate(lib_inih,
name : 'inih', name : 'inih',
description : 'simple .INI file parser', description : 'simple .INI file parser',
extra_cflags : extra_args,
) )
endif endif
inih_dep = declare_dependency( inih_dep = declare_dependency(
link_with : lib_inih, link_with : lib_inih,
compile_args : arg_static, compile_args : arg_static + extra_args,
include_directories : inc_inih include_directories : inc_inih
) )
@ -88,10 +101,12 @@ if get_option('with_INIReader')
lib_INIReader = library('INIReader', lib_INIReader = library('INIReader',
['cpp/INIReader.cpp'], ['cpp/INIReader.cpp'],
cpp_args : extra_args,
include_directories : inc_INIReader, include_directories : inc_INIReader,
dependencies : inih_dep, dependencies : inih_dep,
install : distro_install, install : distro_install,
soversion : '0' soversion : '0',
gnu_symbol_visibility: 'hidden'
) )
if distro_install if distro_install
@ -100,11 +115,13 @@ if get_option('with_INIReader')
pkg.generate(lib_INIReader, pkg.generate(lib_INIReader,
name : 'INIReader', name : 'INIReader',
description : 'simple .INI file parser for C++', description : 'simple .INI file parser for C++',
extra_cflags : extra_args,
) )
endif endif
INIReader_dep = declare_dependency( INIReader_dep = declare_dependency(
link_with : lib_INIReader, link_with : lib_INIReader,
include_directories : inc_INIReader include_directories : inc_INIReader,
compile_args : extra_args
) )
endif endif