[glibutil] Initial commit

This commit is contained in:
Slava Monich
2014-12-27 22:19:06 +02:00
commit bb8244c997
16 changed files with 1310 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
*~
debian/files
debian/libglibutil-dev.debhelper.log
debian/libglibutil-dev.substvars
debian/libglibutil-dev
debian/libglibutil.debhelper.log
debian/libglibutil.postinst.debhelper
debian/libglibutil.postrm.debhelper
debian/libglibutil.substvars
debian/libglibutil
debian/tmp
documentation.list
installroot
build
RPMS

190
Makefile Normal file
View File

@@ -0,0 +1,190 @@
# -*- Mode: makefile-gmake -*-
.PHONY: clean all debug release
#
# Required packages
#
PKGS = glib-2.0
#
# Default target
#
all: debug release pkgconfig
#
# Library version
#
VERSION_MAJOR = 1
VERSION_MINOR = 0
VERSION_RELEASE = 0
NAME = glibutil
LIB_NAME = lib$(NAME)
LIB_DEV_SYMLINK = $(LIB_NAME).so
LIB_SYMLINK1 = $(LIB_DEV_SYMLINK).$(VERSION_MAJOR)
LIB_SYMLINK2 = $(LIB_SYMLINK1).$(VERSION_MINOR)
LIB_SONAME = $(LIB_SYMLINK1)
LIB = $(LIB_SONAME).$(VERSION_MINOR).$(VERSION_RELEASE)
#
# Sources
#
SRC = gutil_log.c
#
# Directories
#
SRC_DIR = src
INCLUDE_DIR = include
BUILD_DIR = build
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
#
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(INCLUDE_DIR)
BASE_FLAGS = -fPIC
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
-MMD -MP $(shell pkg-config --cflags $(PKGS))
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
$(shell pkg-config --libs $(PKGS))
DEBUG_FLAGS = -g
RELEASE_FLAGS =
ifndef KEEP_SYMBOLS
KEEP_SYMBOLS = 0
endif
ifneq ($(KEEP_SYMBOLS),0)
RELEASE_FLAGS += -g
endif
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
#
# Files
#
PKGCONFIG = $(BUILD_DIR)/$(LIB_NAME).pc
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
#
# Dependencies
#
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(DEPS)),)
-include $(DEPS)
endif
endif
$(DEBUG_OBJS) $(DEBUG_LIB): | $(DEBUG_BUILD_DIR)
$(RELEASE_OBJS) $(RELEASE_LIB): | $(RELEASE_BUILD_DIR)
#
# Rules
#
DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
debug: $(DEBUG_LIB) $(DEBUG_LINK)
release: $(RELEASE_LIB) $(RELEASE_LINK)
pkgconfig: $(PKGCONFIG)
clean:
rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
rm -fr $(BUILD_DIR) RPMS installroot
rm -fr debian/tmp debian/libglibutil debian/libglibutil-dev
rm -f documentation.list debian/files debian/*.substvars
rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
$(GEN_DIR):
mkdir -p $@
$(DEBUG_BUILD_DIR):
mkdir -p $@
$(RELEASE_BUILD_DIR):
mkdir -p $@
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
$(DEBUG_LIB): $(DEBUG_OBJS)
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@
$(RELEASE_LIB): $(RELEASE_OBJS)
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@
ifeq ($(KEEP_SYMBOLS),0)
strip $@
endif
$(DEBUG_LINK):
ln -sf $(LIB) $@
$(RELEASE_LINK):
ln -sf $(LIB) $@
$(PKGCONFIG): $(LIB_NAME).pc.in
sed -e 's/\[version\]/'$(VERSION_MAJOR).$(VERSION_MINOR)/g $< > $@
#
# Install
#
INSTALL_PERM = 644
INSTALL_OWNER = $(shell id -u)
INSTALL_GROUP = $(shell id -g)
INSTALL = install
INSTALL_DIRS = $(INSTALL) -d
INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
INSTALL_PKGCONFIG_DIR = $(DESTDIR)/usr/lib/pkgconfig
INSTALL_ALIAS = $(INSTALL_LIB_DIR)/$(LIB_SHORTCUT)
install: $(INSTALL_LIB_DIR)
$(INSTALL_FILES) $(RELEASE_LIB) $(INSTALL_LIB_DIR)
ln -sf $(LIB) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
install-dev: install $(INSTALL_INCLUDE_DIR) $(INSTALL_PKGCONFIG_DIR)
$(INSTALL_FILES) $(INCLUDE_DIR)/*.h $(INSTALL_INCLUDE_DIR)
$(INSTALL_FILES) $(PKGCONFIG) $(INSTALL_PKGCONFIG_DIR)
ln -sf $(LIB_SYMLINK1) $(INSTALL_LIB_DIR)/$(LIB_DEV_SYMLINK)
$(INSTALL_LIB_DIR):
$(INSTALL_DIRS) $@
$(INSTALL_INCLUDE_DIR):
$(INSTALL_DIRS) $@
$(INSTALL_PKGCONFIG_DIR):
$(INSTALL_DIRS) $@

1
README Normal file
View File

@@ -0,0 +1 @@
Library of glib utilities.

5
debian/changelog vendored Normal file
View File

@@ -0,0 +1,5 @@
libglibutil (1.0.0) unstable; urgency=low
* Initial release
-- Slava Monich <slava.monich@jolla.com> Sat, 27 Dec 2014 22:36:32 +0200

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
5

18
debian/control vendored Normal file
View File

@@ -0,0 +1,18 @@
Source: libglibutil
Section: libs
Priority: optional
Maintainer: Slava Monich <slava.monich@jolla.com>
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0)
Standards-Version: 3.8.4
Package: libglibutil
Section: libs
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Library of glib utilities
Package: libglibutil-dev
Section: libdevel
Architecture: any
Depends: libglibutil (= ${binary:Version}), ${misc:Depends}
Description: Development files for libglibutil

29
debian/copyright vendored Normal file
View File

@@ -0,0 +1,29 @@
Copyright (C) 2014-2015 Jolla Ltd.
Contact: Slava Monich <slava.monich@jolla.com>
You may use this file under the terms of BSD license as follows:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Jolla Ltd nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

3
debian/libglibutil-dev.install vendored Normal file
View File

@@ -0,0 +1,3 @@
debian/tmp/usr/lib/libglibutil.so usr/lib
include/*.h usr/include/glibutil
build/libglibutil.pc usr/lib/pkgconfig

1
debian/libglibutil.install vendored Normal file
View File

@@ -0,0 +1 @@
debian/tmp/usr/lib/libglibutil.so.* usr/lib

11
debian/rules vendored Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
override_dh_auto_install:
dh_auto_install -- install-dev
%:
dh $@

343
include/gutil_log.h Normal file
View File

@@ -0,0 +1,343 @@
/*
* Copyright (C) 2014-2015 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUTIL_LOG_H
#define GUTIL_LOG_H
#include "gutil_types.h"
#include <stdarg.h>
G_BEGIN_DECLS
/* Log levels */
#define GLOG_LEVEL_ALWAYS (-2)
#define GLOG_LEVEL_INHERIT (-1)
#define GLOG_LEVEL_NONE (0)
#define GLOG_LEVEL_ERR (1)
#define GLOG_LEVEL_WARN (2)
#define GLOG_LEVEL_INFO (3)
#define GLOG_LEVEL_DEBUG (4)
#define GLOG_LEVEL_VERBOSE (5)
/* Allow these to be redefined */
#ifndef GLOG_LEVEL_MAX
# ifdef DEBUG
# define GLOG_LEVEL_MAX GLOG_LEVEL_VERBOSE
# else
# define GLOG_LEVEL_MAX GLOG_LEVEL_DEBUG
# endif
#endif /* GLOG_LEVEL_MAX */
#ifndef GLOG_LEVEL_DEFAULT
# ifdef DEBUG
# define GLOG_LEVEL_DEFAULT GLOG_LEVEL_DEBUG
# else
# define GLOG_LEVEL_DEFAULT GLOG_LEVEL_INFO
# endif
#endif /* GLOG_LEVEL_DEFAULT */
/* Do we need a separate log level for ASSERTs? */
#ifndef GLOG_LEVEL_ASSERT
# ifdef DEBUG
# define GLOG_LEVEL_ASSERT GLOG_LEVEL_ERR
# else
/* No asserts in release build */
# define GLOG_LEVEL_ASSERT (GLOG_LEVEL_MAX+1)
# endif
#endif
/* Log module */
struct glog_module {
const char* name; /* Name (used as prefix) */
const GLogModule* parent; /* Parent log module (optional) */
void* reserved; /* Reserved for future expansion */
const int max_level; /* Maximum level defined at compile time */
int level; /* Current log level */
int flags; /* Flags (should be zero) */
int reserved2; /* Reserved for future expansion */
};
/* Command line parsing helper. Option format is [module]:level
* where level can be either a number or log level name ("none", err etc.) */
gboolean
gutil_log_parse_option(
const char* opt, /* String to parse */
GLogModule** modules, /* Known modules */
int count, /* Number of known modules */
GError** error); /* Optional error message */
/* Set log type by name ("syslog", "stdout" or "glib"). This is also
* primarily for parsing command line options */
gboolean
gutil_log_set_type(
const char* type,
const char* default_name);
const char*
gutil_log_get_type(
void);
/* Generates the string containg description of log levels and list of
* log modules. The caller must deallocate the string with g_free */
char*
gutil_log_description(
GLogModule** modules, /* Known modules */
int count); /* Number of known modules */
/* Logging function */
void
gutil_log(
const GLogModule* module, /* Calling module (NULL for default) */
int level, /* Message log level */
const char* format, /* Message format */
...) G_GNUC_PRINTF(3,4); /* Followed by arguments */
void
gutil_logv(
const GLogModule* module,
int level,
const char* format,
va_list va);
/* Check if logging is enabled for the specified log level */
gboolean
gutil_log_enabled(
const GLogModule* module,
int level);
/* Known log types */
extern const char GLOG_TYPE_STDOUT[];
extern const char GLOG_TYPE_STDERR[];
extern const char GLOG_TYPE_GLIB[];
extern const char GLOG_TYPE_CUSTOM[];
extern const char GLOG_TYPE_SYSLOG[];
/* Available log handlers */
#define GUTIL_DEFINE_LOG_FN(fn) void fn(const char* name, int level, \
const char* format, va_list va)
GUTIL_DEFINE_LOG_FN(gutil_log_stdout);
GUTIL_DEFINE_LOG_FN(gutil_log_stderr);
GUTIL_DEFINE_LOG_FN(gutil_log_glib);
GUTIL_DEFINE_LOG_FN(gutil_log_syslog);
/* Log configuration */
#define GLOG_MODULE_DECL(m) extern GLogModule m;
GLOG_MODULE_DECL(gutil_log_default)
typedef GUTIL_DEFINE_LOG_FN((*GLogProc));
extern GLogProc gutil_log_func;
extern gboolean gutil_log_timestamp; /* Only affects stdout and stderr */
/* Log module (optional) */
#define GLOG_MODULE_DEFINE_(var,name) \
GLogModule var = {name, NULL, NULL, \
GLOG_LEVEL_MAX, GLOG_LEVEL_INHERIT, 0, 0}
#define GLOG_MODULE_DEFINE2_(var,name,parent) \
GLogModule var = {name, &(parent), NULL, \
GLOG_LEVEL_MAX, GLOG_LEVEL_INHERIT, 0, 0}
#ifdef GLOG_MODULE_NAME
extern GLogModule GLOG_MODULE_NAME;
# define GLOG_MODULE_CURRENT (&GLOG_MODULE_NAME)
# define GLOG_MODULE_DEFINE(name) \
GLOG_MODULE_DEFINE_(GLOG_MODULE_NAME,name)
# define GLOG_MODULE_DEFINE2(name,parent) \
GLOG_MODULE_DEFINE2_(GLOG_MODULE_NAME,name,parent)
#else
# define GLOG_MODULE_CURRENT NULL
#endif
/* Logging macros */
#define GLOG_NOTHING ((void)0)
#define GLOG_ENABLED(level) gutil_log_enabled(GLOG_MODULE_CURRENT,level)
#define GERRMSG(err) (((err) && (err)->message) ? (err)->message : \
"Unknown error")
#if !defined(GLOG_VARARGS) && defined(__GNUC__)
# define GLOG_VARARGS
#endif
#ifndef GLOG_VARARGS
# define GLOG_VA_NONE(x) static inline void GUTIL_##x(const char* f, ...) {}
# define GLOG_VA(x) static inline void GUTIL_##x(const char* f, ...) { \
if (f && f[0]) { \
va_list va; va_start(va,f); \
gutil_logv(GLOG_MODULE_CURRENT, GLOG_LEVEL_##x, f, va); \
va_end(va); \
} \
}
#endif /* GLOG_VARARGS */
#define GUTIL_LOG_ANY (GLOG_LEVEL_MAX >= GLOG_LEVEL_NONE)
#define GUTIL_LOG_ERR (GLOG_LEVEL_MAX >= GLOG_LEVEL_ERR)
#define GUTIL_LOG_WARN (GLOG_LEVEL_MAX >= GLOG_LEVEL_WARN)
#define GUTIL_LOG_INFO (GLOG_LEVEL_MAX >= GLOG_LEVEL_INFO)
#define GUTIL_LOG_DEBUG (GLOG_LEVEL_MAX >= GLOG_LEVEL_DEBUG)
#define GUTIL_LOG_VERBOSE (GLOG_LEVEL_MAX >= GLOG_LEVEL_VERBOSE)
#define GUTIL_LOG_ASSERT (GLOG_LEVEL_MAX >= GLOG_LEVEL_ASSERT)
#if GUTIL_LOG_ASSERT
void
gutil_log_assert(
const GLogModule* module, /* Calling module (NULL for default) */
int level, /* Assert log level */
const char* expr, /* Assert expression */
const char* file, /* File name */
int line); /* Line number */
# define GASSERT(expr) ((expr) ? GLOG_NOTHING : \
gutil_log_assert(GLOG_MODULE_CURRENT, GLOG_LEVEL_ASSERT, \
#expr, __FILE__, __LINE__))
# define GVERIFY(expr) GASSERT(expr)
# define GVERIFY_FALSE(expr) GASSERT(!(expr))
# define GVERIFY_EQ(expr,val) GASSERT((expr) == (val))
# define GVERIFY_NE(expr,val) GASSERT((expr) != (val))
# define GVERIFY_GE(expr,val) GASSERT((expr) >= (val))
# define GVERIFY_GT(expr,val) GASSERT((expr) > (val))
# define GVERIFY_LE(expr,val) GASSERT((expr) <= (val))
# define GVERIFY_LT(expr,val) GASSERT((expr) < (val))
#else
# define GASSERT(expr)
# define GVERIFY(expr) (expr)
# define GVERIFY_FALSE(expr) (expr)
# define GVERIFY_EQ(expr,val) (expr)
# define GVERIFY_NE(expr,val) (expr)
# define GVERIFY_GE(expr,val) (expr)
# define GVERIFY_GT(expr,val) (expr)
# define GVERIFY_LE(expr,val) (expr)
# define GVERIFY_LT(expr,val) (expr)
#endif
#ifdef GLOG_VARARGS
# if GUTIL_LOG_ERR
# define GERR(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_ERR, f, ##args)
# define GERR_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_ERR, "%s() " f, __FUNCTION__, ##args)
# else
# define GERR(f,args...) GLOG_NOTHING
# define GERR_(f,args...) GLOG_NOTHING
# endif /* GUTIL_LOG_ERR */
#else
# define GERR_ GERR
# if GUTIL_LOG_ERR
GLOG_VA(ERR)
# else
GLOG_VA_NONE(ERR)
# endif /* GUTIL_LOG_ERR */
#endif /* GLOG_VARARGS */
#ifdef GLOG_VARARGS
# if GUTIL_LOG_WARN
# define GWARN(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_WARN, f, ##args)
# define GWARN_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_WARN, "%s() " f, __FUNCTION__, ##args)
# else
# define GWARN(f,args...) GLOG_NOTHING
# define GWARN_(f,args...) GLOG_NOTHING
# endif /* GUTIL_LOGL_WARN */
#else
# define GWARN_ GWARN
# if GUTIL_LOG_WARN
GLOG_VA(WARN)
# else
GLOG_VA_NONE(WARN)
# endif /* GUTIL_LOGL_WARN */
# endif /* GLOG_VARARGS */
#ifdef GLOG_VARARGS
# if GUTIL_LOG_INFO
# define GINFO(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_INFO, f, ##args)
# define GINFO_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_INFO, "%s() " f, __FUNCTION__, ##args)
# else
# define GINFO(f,args...) GLOG_NOTHING
# define GINFO_(f,args...) GLOG_NOTHING
# endif /* GUTIL_LOG_INFO */
#else
# define GINFO_ GINFO
# if GUTIL_LOG_INFO
GLOG_VA(INFO)
# else
GLOG_VA_NONE(INFO)
# endif /* GUTIL_LOG_INFO */
#endif /* GLOG_VARARGS */
#ifdef GLOG_VARARGS
# if GUTIL_LOG_DEBUG
# define GDEBUG(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_DEBUG, f, ##args)
# define GDEBUG_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_DEBUG, "%s() " f, __FUNCTION__, ##args)
# else
# define GDEBUG(f,args...) GLOG_NOTHING
# define GDEBUG_(f,args...) GLOG_NOTHING
# endif /* GUTIL_LOG_DEBUG */
#else
# define GDEBUG_ GDEBUG
# if GUTIL_LOG_DEBUG
GLOG_VA(DEBUG)
# else
GLOG_VA_NONE(DEBUG)
# endif /* GUTIL_LOG_DEBUG */
#endif /* GLOG_VARARGS */
#ifdef GLOG_VARARGS
# if GUTIL_LOG_VERBOSE
# define GVERBOSE(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_VERBOSE, f, ##args)
# define GVERBOSE_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
GLOG_LEVEL_VERBOSE, "%s() " f, __FUNCTION__, ##args)
# else
# define GVERBOSE(f,args...) GLOG_NOTHING
# define GVERBOSE_(f,args...) GLOG_NOTHING
# endif /* GUTIL_LOG_VERBOSE */
#else
# define GVERBOSE_ GVERBOSE
# if GUTIL_LOG_VERBOSE
GLOG_VA(VERBOSE)
# else
GLOG_VA_NONE(VERBOSE)
# endif /* GUTIL_LOG_VERBOSE */
#endif /* GLOG_VARARGS */
G_END_DECLS
#endif /* GUTIL_LOG_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

59
include/gutil_macros.h Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2014-2015 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUTIL_MACROS_H
#define GUTIL_MACROS_H
#include <gutil_types.h>
#define G_CAST(address,type,field) \
((type *)((guint8*)(address) - G_STRUCT_OFFSET(type,field)))
#define G_ALIGN2(value) (((value)+1) & ~1)
#define G_ALIGN4(value) (((value)+3) & ~3)
#define G_ALIGN8(value) (((value)+7) & ~7)
#ifdef __GNUC__
# define G_PACKED __attribute__((packed))
#else
# define G_PACKED
#endif
#endif /* GUTIL_MACROS_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

51
include/gutil_types.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2014-2015 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUTIL_TYPES_H
#define GUTIL_TYPES_H
#include <glib.h>
#include <glib-object.h>
#include <string.h>
#include <stdio.h>
typedef struct glog_module GLogModule;
#endif /* GUTIL_TYPES_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

10
libglibutil.pc.in Normal file
View File

@@ -0,0 +1,10 @@
name=glibutil
libdir=/usr/lib
includedir=/usr/include
Name: libglibutil
Description: Library of glib utilities
Version: [version]
Requires: glib-2.0
Libs: -L${libdir} -l${name}
Cflags: -I${includedir} -I${includedir}/${name}

46
rpm/libglibutil.spec Normal file
View File

@@ -0,0 +1,46 @@
Name: libglibutil
Version: 1.0
Release: 0
Summary: Library of glib utilities
Group: Development/Libraries
License: BSD
URL: https://github.com/nemomobile/libglibutil
Source: %{name}-%{version}.tar.bz2
BuildRequires: glib2-devel >= 2.0
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
%description
Provides glib utility functions and macros
%package devel
Summary: Development library for %{name}
Requires: %{name} = %{version}
Requires: pkgconfig
%description devel
This package contains the development library for %{name}.
%prep
%setup -q
%build
make KEEP_SYMBOLS=1 release pkgconfig
%install
rm -rf %{buildroot}
make install-dev DESTDIR=%{buildroot}
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root,-)
%{_libdir}/%{name}.so.*
%files devel
%defattr(-,root,root,-)
%{_libdir}/pkgconfig/*.pc
%{_libdir}/%{name}.so
%{_includedir}/glibutil/*.h

527
src/gutil_log.c Normal file
View File

@@ -0,0 +1,527 @@
/*
* Copyright (C) 2014-2015 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gutil_log.h"
#if defined(DEBUG) && defined(_WIN32)
# include <windows.h>
#endif
#ifndef GLOG_SYSLOG
# ifdef unix
# define GLOG_SYSLOG 1
# else
# define GLOG_SYSLOG 0
# endif
#endif /* GLOG_SYSLOG */
#ifndef GLOG_GLIB
# define GLOG_GLIB 1
#endif /* GLOG_GLIB */
/* Allows timestamps in stdout log */
gboolean gutil_log_timestamp = TRUE;
/* Log configuration */
GLogProc gutil_log_func = gutil_log_stdout;
GLogModule gutil_log_default = {
NULL, /* name */
NULL, /* parent */
NULL, /* reserved */
GLOG_LEVEL_MAX, /* max_level */
GLOG_LEVEL_DEFAULT, /* level */
0 /* flags */
};
/* Log level descriptions */
static const struct _gutil_log_level {
const char* name;
const char* description;
} gutil_log_levels [] = {
{ "none", "Disable log output" },
{ "error", "Errors only"},
{ "warning", "From warning level to errors" },
{ "info", "From information level to errors" },
{ "debug", "From debug messages to errors" },
{ "verbose", "From verbose trace messages to errors" }
};
const char GLOG_TYPE_STDOUT[] = "stdout";
const char GLOG_TYPE_STDERR[] = "stderr";
const char GLOG_TYPE_CUSTOM[] = "custom";
#if GLOG_GLIB
const char GLOG_TYPE_GLIB[] = "glib";
#endif
#if GLOG_SYSLOG
const char GLOG_TYPE_SYSLOG[] = "syslog";
#endif
G_STATIC_ASSERT(G_N_ELEMENTS(gutil_log_levels) > GLOG_LEVEL_MAX);
G_STATIC_ASSERT(G_N_ELEMENTS(gutil_log_levels) > GLOG_LEVEL_DEFAULT);
/**
* Formats the string into the given buffer (most commonly allocated
* on caller's stack). If formatted string fits into the provided buffer,
* returns pointer to the given buffer. If formatted string is too long
* to fit into the provided buffer, allocates a new one and returns pointer
* to it.
*/
static
char*
gutil_log_format(
char* buf,
int bufsize,
const char* format,
va_list va)
{
int size, nchars = -1;
char* buffer;
if (buf) {
size = bufsize;
buffer = buf;
} else {
size = MAX(100,bufsize);
buffer = g_malloc(size);
}
while (buffer) {
/* Try to print in the allocated space. */
va_list va2;
G_VA_COPY(va2, va);
nchars = g_vsnprintf(buffer, size, format, va2);
va_end(va2);
/* Return the string or try again with more space. */
if (nchars >= 0) {
if (nchars < size) break;
size = nchars+1; /* Precisely what is needed */
} else {
size *= 2; /* Twice the old size */
}
if (buffer != buf) g_free(buffer);
buffer = g_malloc(size);
}
return buffer;
}
/* Forward output to stdout or stderr */
void
gutil_log_stdio(
FILE* out,
const char* name,
int level,
const char* format,
va_list va)
{
char t[32];
char buf[512];
const char* prefix = "";
char* msg;
if (gutil_log_timestamp) {
time_t now;
time(&now);
strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S ", localtime(&now));
} else {
t[0] = 0;
}
switch (level) {
case GLOG_LEVEL_WARN: prefix = "WARNING: "; break;
case GLOG_LEVEL_ERR: prefix = "ERROR: "; break;
default: break;
}
msg = gutil_log_format(buf, sizeof(buf), format, va);
#if defined(DEBUG) && defined(_WIN32)
{
char s[1023];
if (name) {
g_snprintf(s, sizeof(s), "%s[%s] %s%s\n", t, name, prefix, msg);
} else {
g_snprintf(s, sizeof(s), "%s%s%s\n", t, prefix, msg);
}
OutputDebugStringA(s);
}
#endif
if (name) {
fprintf(out, "%s[%s] %s%s\n", t, name, prefix, msg);
} else {
fprintf(out, "%s%s%s\n", t, prefix, msg);
}
if (msg != buf) g_free(msg);
}
void
gutil_log_stdout(
const char* name,
int level,
const char* format,
va_list va)
{
gutil_log_stdio(stdout, name, level, format, va);
}
void
gutil_log_stderr(
const char* name,
int level,
const char* format,
va_list va)
{
gutil_log_stdio(stderr, name, level, format, va);
}
/* Formards output to syslog */
#if GLOG_SYSLOG
#include <syslog.h>
void
gutil_log_syslog(
const char* name,
int level,
const char* format,
va_list va)
{
int priority;
const char* prefix = NULL;
switch (level) {
default:
case GLOG_LEVEL_INFO:
priority = LOG_NOTICE;
break;
case GLOG_LEVEL_VERBOSE:
priority = LOG_DEBUG;
break;
case GLOG_LEVEL_DEBUG:
priority = LOG_INFO;
break;
case GLOG_LEVEL_WARN:
priority = LOG_WARNING;
prefix = "WARNING! ";
break;
case GLOG_LEVEL_ERR:
priority = LOG_ERR;
prefix = "ERROR! ";
break;
}
if (name || prefix) {
char buf[512];
g_vsnprintf(buf, sizeof(buf), format, va);
if (!prefix) prefix = "";
if (name) {
syslog(priority, "[%s] %s%s", name, prefix, buf);
} else {
syslog(priority, "%s%s", prefix, buf);
}
} else {
vsyslog(priority, format, va);
}
}
#endif /* GLOG_SYSLOG */
/* Forwards output to g_logv */
#if GLOG_GLIB
void
gutil_log_glib(
const char* name,
int level,
const char* format,
va_list va)
{
GLogLevelFlags flags;
switch (level) {
default:
case GLOG_LEVEL_INFO: flags = G_LOG_LEVEL_MESSAGE; break;
case GLOG_LEVEL_VERBOSE: flags = G_LOG_LEVEL_DEBUG; break;
case GLOG_LEVEL_DEBUG: flags = G_LOG_LEVEL_INFO; break;
case GLOG_LEVEL_WARN: flags = G_LOG_LEVEL_WARNING; break;
case GLOG_LEVEL_ERR: flags = G_LOG_LEVEL_CRITICAL; break;
}
g_logv(name, flags, format, va);
}
#endif /* GLOG_GLIB */
/* Logging function */
void
gutil_logv_r(
const GLogModule* module,
int level,
const char* prefix,
const char* format,
va_list va)
{
if (module->parent && module->level == GLOG_LEVEL_INHERIT) {
gutil_logv_r(module->parent, level, prefix, format, va);
} else {
const int max_level = (module->level == GLOG_LEVEL_INHERIT) ?
gutil_log_default.level : module->level;
if (level > GLOG_LEVEL_NONE && level <= max_level) {
GLogProc log = gutil_log_func;
if (G_LIKELY(log)) {
log(prefix, level, format, va);
}
}
}
}
void
gutil_logv(
const GLogModule* module,
int level,
const char* format,
va_list va)
{
if (level != GLOG_LEVEL_NONE && gutil_log_func) {
if (!module) module = &gutil_log_default;
if (G_UNLIKELY(level == GLOG_LEVEL_ALWAYS)) {
GLogProc log = gutil_log_func;
if (G_LIKELY(log)) {
if (level == GLOG_LEVEL_ALWAYS) {
log(module->name, level, format, va);
}
}
} else {
gutil_logv_r(module, level, module->name, format, va);
}
}
}
void
gutil_log(
const GLogModule* module,
int level,
const char* format,
...)
{
va_list va;
va_start(va, format);
gutil_logv(module, level, format, va);
va_end(va);
}
void
gutil_log_assert(
const GLogModule* module,
int level,
const char* expr,
const char* file,
int line)
{
gutil_log(module, level, "Assert %s failed at %s:%d\r", expr, file, line);
}
/**
* Check if logging is enabled for the specified log level
*/
static
gboolean
gutil_log_enabled_r(
const GLogModule* module,
int level)
{
if (module->parent && module->level == GLOG_LEVEL_INHERIT) {
return gutil_log_enabled_r(module->parent, level);
} else {
const int max_level = (module->level == GLOG_LEVEL_INHERIT) ?
gutil_log_default.level : module->level;
return (level > GLOG_LEVEL_NONE && level <= max_level);
}
}
gboolean
gutil_log_enabled(
const GLogModule* module,
int level)
{
if (gutil_log_func) {
if (level == GLOG_LEVEL_ALWAYS) {
return TRUE;
} else if (level > GLOG_LEVEL_NONE) {
if (!module) module = &gutil_log_default;
return gutil_log_enabled_r(module, level);
}
}
return FALSE;
}
/* gutil_log_parse_option helper */
static
int
gutil_log_parse_level(
const char* str,
GError** error)
{
if (str && str[0]) {
guint i;
const size_t len = strlen(str);
if (len == 1) {
const char* valid_numbers = "012345";
const char* number = strchr(valid_numbers, str[0]);
if (number) {
return number - valid_numbers;
}
}
for (i=0; i<G_N_ELEMENTS(gutil_log_levels); i++) {
if (!strncmp(gutil_log_levels[i].name, str, len)) {
return i;
}
}
}
if (error) {
*error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Invalid log level '%s'", str);
}
return -1;
}
/**
* Command line parsing helper. Option format is [module:]level where level
* can be either a number or log level name ("none", "error", etc.)
*/
gboolean
gutil_log_parse_option(
const char* opt,
GLogModule** modules,
int count,
GError** error)
{
const char* sep = strchr(opt, ':');
if (sep) {
const int modlevel = gutil_log_parse_level(sep+1, error);
if (modlevel >= 0) {
int i;
const size_t namelen = sep - opt;
for (i=0; i<count; i++) {
if (!g_ascii_strncasecmp(modules[i]->name, opt, namelen) &&
strlen(modules[i]->name) == namelen) {
modules[i]->level = modlevel;
return TRUE;
}
}
if (error) {
*error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Unknown log module '%.*s'", (int)namelen, opt);
}
}
} else {
const int deflevel = gutil_log_parse_level(opt, error);
if (deflevel >= 0) {
gutil_log_default.level = deflevel;
return TRUE;
}
}
return FALSE;
}
/**
* Generates the string containg description of log levels and list of
* log modules. The caller must deallocate the string with g_free
*/
char*
gutil_log_description(
GLogModule** modules, /* Known modules */
int count) /* Number of known modules */
{
int i;
GString* desc = g_string_sized_new(128);
g_string_append(desc, "Log Levels:\n");
for (i=0; i<=GLOG_LEVEL_VERBOSE; i++) {
g_string_append_printf(desc, " %d, ", i);
g_string_append_printf(desc, "%-8s ", gutil_log_levels[i].name);
g_string_append(desc, gutil_log_levels[i].description);
if (i == GLOG_LEVEL_DEFAULT) g_string_append(desc, " (default)");
g_string_append(desc, "\n");
}
if (modules) {
g_string_append(desc, "\nLog Modules:\n");
for (i=0; i<count; i++) {
g_string_append_printf(desc, " %s\n", modules[i]->name);
}
}
return g_string_free(desc, FALSE);
}
gboolean
gutil_log_set_type(
const char* type,
const char* default_name)
{
#if GLOG_SYSLOG
if (!g_ascii_strcasecmp(type, GLOG_TYPE_SYSLOG)) {
if (gutil_log_func != gutil_log_syslog) {
openlog(NULL, LOG_PID | LOG_CONS, LOG_USER);
}
gutil_log_default.name = NULL;
gutil_log_func = gutil_log_syslog;
return TRUE;
}
if (gutil_log_func == gutil_log_syslog) {
closelog();
}
#endif /* GLOG_SYSLOG */
gutil_log_default.name = default_name;
if (!g_ascii_strcasecmp(type, GLOG_TYPE_STDOUT)) {
gutil_log_func = gutil_log_stdout;
return TRUE;
} if (!g_ascii_strcasecmp(type, GLOG_TYPE_STDERR)) {
gutil_log_func = gutil_log_stderr;
return TRUE;
#if GLOG_GLIB
} else if (!g_ascii_strcasecmp(type, GLOG_TYPE_GLIB)) {
gutil_log_func = gutil_log_glib;
return TRUE;
#endif /* GLOG_GLIB */
}
return FALSE;
}
const char*
gutil_log_get_type()
{
return (gutil_log_func == gutil_log_stdout) ? GLOG_TYPE_STDOUT :
(gutil_log_func == gutil_log_stderr) ? GLOG_TYPE_STDERR :
#if GLOG_SYSLOG
(gutil_log_func == gutil_log_syslog) ? GLOG_TYPE_SYSLOG :
#endif /* GLOG_SYSLOG */
#if GLOG_GLIB
(gutil_log_func == gutil_log_glib) ? GLOG_TYPE_GLIB :
#endif /* GLOG_GLIB */
GLOG_TYPE_CUSTOM;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/