Skip to content

Commit

Permalink
Add visibility symbols (#134)
Browse files Browse the repository at this point in the history
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:
mesonbuild/wrapdb#340 (comment)
  • Loading branch information
Tachi107 authored Mar 23, 2022
1 parent a52c070 commit 5a31af9
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 19 deletions.
41 changes: 31 additions & 10 deletions cpp/INIReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,52 +15,73 @@
#include <map>
#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
// for simplicity here rather than speed, but it should be pretty decent.)
class INIReader
{
public:
// Construct INIReader and parse given filename. See ini.h for more info
// 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
// 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
// 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.
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;

// Get a string value from INI file, returning default_value if not found,
// 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;

// 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").
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
// default_value if not found or not a valid floating point value
// 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
// 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).
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
// 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.
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:
int _error;
Expand Down
29 changes: 25 additions & 4 deletions ini.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ extern "C" {
#define INI_HANDLER_LINENO 0
#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. */
#if INI_HANDLER_LINENO
typedef int (*ini_handler)(void* user, const char* section,
Expand All @@ -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
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
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
filename. Used for implementing custom or string-based I/O (see also
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);

/* 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
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
configparser. If allowed, ini_parse() will call the handler with the same
Expand Down
27 changes: 22 additions & 5 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ project('inih',
#### options ####
arg_static = []
distro_install = get_option('distro_install')
extra_args = []

if distro_install
pkg = import('pkgconfig')
Expand Down Expand Up @@ -55,15 +56,26 @@ else
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 ####
inc_inih = include_directories('.')

lib_inih = library('inih',
['ini.c'],
include_directories : inc_inih,
c_args : arg_static,
c_args : [arg_static, extra_args],
install : distro_install,
soversion : '0'
soversion : '0',
gnu_symbol_visibility: 'hidden'
)

if distro_install
Expand All @@ -72,12 +84,13 @@ if distro_install
pkg.generate(lib_inih,
name : 'inih',
description : 'simple .INI file parser',
extra_cflags : extra_args,
)
endif

inih_dep = declare_dependency(
link_with : lib_inih,
compile_args : arg_static,
compile_args : arg_static + extra_args,
include_directories : inc_inih
)

Expand All @@ -88,10 +101,12 @@ if get_option('with_INIReader')

lib_INIReader = library('INIReader',
['cpp/INIReader.cpp'],
cpp_args : extra_args,
include_directories : inc_INIReader,
dependencies : inih_dep,
install : distro_install,
soversion : '0'
soversion : '0',
gnu_symbol_visibility: 'hidden'
)

if distro_install
Expand All @@ -100,11 +115,13 @@ if get_option('with_INIReader')
pkg.generate(lib_INIReader,
name : 'INIReader',
description : 'simple .INI file parser for C++',
extra_cflags : extra_args,
)
endif

INIReader_dep = declare_dependency(
link_with : lib_INIReader,
include_directories : inc_INIReader
include_directories : inc_INIReader,
compile_args : extra_args
)
endif

0 comments on commit 5a31af9

Please sign in to comment.