# Doxygen will generate a detailed section even if there is only a brief
# description.
-ALWAYS_DETAILED_SEC = NO
+ALWAYS_DETAILED_SEC = YES
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
-MAX_INITIALIZER_LINES = 30
+MAX_INITIALIZER_LINES = 0
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.
-HTML_TIMESTAMP = YES
+HTML_TIMESTAMP = NO
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
-CLASS_GRAPH = YES
+CLASS_GRAPH = NO
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
-COLLABORATION_GRAPH = YES
+COLLABORATION_GRAPH = NO
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
-GROUP_GRAPHS = YES
+GROUP_GRAPHS = NO
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
/**
* @mainpage
*
- * @section libusual Introduction.
+ * @section libusual libusual
*
* libusual is utility library.
*
+ * Unlike APR or GLIB which create their own API world, libusual
+ * tries to use standardized API's whenever possible.
+ *
+ * Goals for portability APIs:
+ * - Follow modern POSIX, BSD, glibc. Make the APIs available everywhere.
+ * - If compat is impossible, allow the user code to compile - eg. UNIX
+ * sockets on win32.
+ * - Assume cooparating user:
+ * - libusual needs to implement only API that are used and useful. No need try to provide full POSIX.
+ * - user code survives gracefully when libusual provides less functionality.
+ *
+ * Goals for new APIs:
+ * - Simple, clear API
+ * - Simple, clear implementation.
+ * - It is preferable to have simple code which can be copied and modified
+ * for some special case than complex code that tries to handle
+ * everything at once.
*
* @section modules Module list.
*
+#CC = i586-mingw32msvc-gcc
CFLAGS = -O -g
-CPPFLAGS = -I../.. -DUSUAL -DUSE_INTERNAL_REGEX
+CPPFLAGS = -I../..
+DEFS = -DUSUAL -DUSE_INTERNAL_REGEX
LDFLAGS = -g
LIBS = ../libusual.a
$(CC) $(DEFS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
testregex.libc: testregex.c
- $(CC) $(CFLAGS) -o $@ $<
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
clean:
#endif
#define getline(x) xgetline(x)
+#include <usual/signal.h>
#ifdef USUAL
#include <usual/regex.h>
#else
/*
- * Crit-bit tree / binary radix tree.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ *
+ * Crit-bit tree / binary radix tree.
+ */
#ifndef _USUAL_CBTREE_H_
#define _USUAL_CBTREE_H_
#include <usual/cxalloc.h>
-/* returns length of the key */
+/** returns length of the key */
typedef unsigned int (*cbtree_getkey_func)(void *ctx, void *obj, const void **dst_p);
-/* walk */
+/** walk over tree */
typedef bool (*cbtree_walker_func)(void *ctx, void *obj);
+/** Handle to tree */
struct CBTree;
+/**
+ * Create new tree.
+ *
+ * @param obj_key_cb callback to get the key for a object
+ * @param obj_free_cb callback to free the object when tree node is freed (optional)
+ * @param cb_ctx extra pointer passed to callbacks
+ * @param cx memory context where from allocate
+ */
struct CBTree *cbtree_create(cbtree_getkey_func obj_key_cb,
cbtree_walker_func obj_free_cb,
void *cb_ctx,
CxMem *cx);
+/**
+ * frees all resources allocated.
+ * If obj_free_cb is non-NULL, it will be called per each object.
+ */
void cbtree_destroy(struct CBTree *tree);
+/** Inserts new node to tree */
bool cbtree_insert(struct CBTree *tree, void *obj) _MUSTCHECK;
+
+/** Removed node from tree.
+ * If obj_free_cb is non-NULL, it will be called for the object.
+ *
+ * @returns true if key was found, false otherwise.
+ */
bool cbtree_delete(struct CBTree *tree, const void *key, unsigned klen);
+/**
+ * Lookup a key.
+ *
+ * @returns object pointer if found, NULL ohterwise
+ */
void *cbtree_lookup(struct CBTree *tree, const void *key, unsigned klen);
+/** Walk over tree */
bool cbtree_walk(struct CBTree *tree, cbtree_walker_func cb_func, void *cb_arg);
#endif
/*
- * Config file parser.
- *
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ * Config file parser.
+ */
#ifndef _USUAL_CFPARSER_H_
#define _USUAL_CFPARSER_H_
#include <usual/base.h>
-/*
- * Simple line-by-line parser
+/**
+ * @name Simple line-by-line parser
+ * @{
*/
+/**
+ * Parsed line type.
+ */
enum CfKeyType {
- CF_SECT,
- CF_KEY
+ CF_SECT, /**< Section */
+ CF_KEY /**< Parameter */
};
+/** Callback signarure for @ref parse_ini_file() */
typedef bool (*cf_handler_f)(void *arg, enum CfKeyType, const char *key, const char *val);
+/**
+ * Simple parser, launches callback for each line
+ */
bool parse_ini_file(const char *fn, cf_handler_f user_handler, void *arg) _MUSTCHECK;
-/*
- * Fancier one.
+/* @} */
+
+/**
+ * @name Complex parser with variable setting.
+ * @{
*/
+/**
+ * Callback for section initialization
+ */
typedef void *(*cf_create_target_f)(void *top_arg, const char *sect_name);
+
+/**
+ * Callback for setting a variable
+ */
typedef bool (*cf_setter_f)(void *dst_p, const char *value);
+/**
+ * Parameter description
+ */
struct CfKey {
+ /** Parameter name */
const char *key_name;
+ /** Setter function, called wit absolute pointer */
cf_setter_f set_fn;
+ /** Flags: CF_VAL_ABS, CF_VAL_REL */
int flags;
+ /** Absolute or relative offset */
uintptr_t key_ofs;
+ /** Default value as string */
const char *def_value;
};
-/* abs or relative pointer */
+/** The pointer is relative to base */
#define CF_VAL_REL 1
+/** The pointer is absolute */
#define CF_VAL_ABS 2
+/**
+ * Section description
+ */
struct CfSect {
+ /** Section name */
const char *sect_name;
+ /** Section creation function (optional) */
cf_create_target_f create_target_fn;
+ /** Key list */
const struct CfKey *key_list;
};
-bool load_ini_file(const char *fn, const struct CfSect *sect_list, void *top_arg) _MUSTCHECK;
-
+/** Setter for string */
bool cf_set_str(void *dst, const char *value);
+/** Setter for int */
bool cf_set_int(void *dst, const char *value);
+/** Setter for time-usec */
bool cf_set_time_usec(void *dst, const char *value);
+/** Setter for time-double */
bool cf_set_time_double(void *dst, const char *value);
/* before using them do: #define CF_REL_BASE struct Foo */
+/* later: #undef CF_REL_BASE */
+
+/** Integer with offset relative to struct referenced in CF_REL_BASE */
#define CF_REL_INT(x) cf_set_int, CF_VAL_REL, offsetof(CF_REL_BASE, x)
+
+/** String with offset relative to struct referenced in CF_REL_BASE */
#define CF_REL_STR(x) cf_set_str, CF_VAL_REL, offsetof(CF_REL_BASE, x)
+
+/** Integer offset relative to struct referenced in CF_REL_BASE */
#define CF_REL_BOOL(x) cf_set_int, CF_VAL_REL, offsetof(CF_REL_BASE, x)
+
+/** Integer offset relative to struct referenced in CF_REL_BASE */
#define CF_REL_TIME_USEC(x) cf_set_time_usec, CF_VAL_REL, offsetof(CF_REL_BASE, x)
+
+/** Integer offset relative to struct referenced in CF_REL_BASE */
#define CF_REL_TIME_DOUBLE(x) cf_set_time_double, CF_VAL_REL, offsetof(CF_REL_BASE, x)
-/* later: #undef CF_REL_BASE */
+/** Integer with absolute pointer */
#define CF_ABS_INT(x) cf_set_int, CF_VAL_ABS, (uintptr_t)&(x)
+
+/** String with absolute pointer */
#define CF_ABS_STR(x) cf_set_str, CF_VAL_ABS, (uintptr_t)&(x)
+
+/** Bool with absolute pointer */
#define CF_ABS_BOOL(x) cf_set_int, CF_VAL_ABS, (uintptr_t)&(x)
+
+/** Time in seconds stored in usec_t */
#define CF_ABS_TIME_USEC(x) cf_set_time_usec, CF_VAL_ABS, (uintptr_t)&(x)
+
+/** Time in second as double */
#define CF_ABS_TIME_DOUBLE(x) cf_set_time_double, CF_VAL_ABS, (uintptr_t)&(x)
+/**
+ * Main entry point
+ */
+bool load_ini_file(const char *fn, const struct CfSect *sect_list, void *top_arg) _MUSTCHECK;
+
+/* @} */
+
#endif
/*
- * CRC32.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/**
+ * @file
+ *
+ * CRC32 checksum.
+ */
#ifndef _USUAL_CRC32_H_
#define _USUAL_CRC32_H_
#include <usual/base.h>
+/** Calculate CRC32 checksum */
uint32_t calc_crc32(const void *data, size_t len, uint32_t init);
#endif
+/*
+ * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * @file
+ *
+ * Extra allocators for cxalloc.
+ */
#ifndef _USUAL_CXEXTRA_H_
#define _USUAL_CXEXTRA_H_
#include <usual/cxalloc.h>
-/* wraps another allocator, exits on allocation failure */
+/** Allocator that exits on error. .ctx should be pointer to actual allocator */
extern const struct CxOps cx_nofail_ops;
-/* nofail for libc */
+/** nofail for libc */
extern CxMem cx_libc_nofail;
-/*
+/**
* Creates allocator that pools all memory together,
* without keeping track of single objects, to be
* freed all together in one shot.
*/
CxMem *cx_new_pool(CxMem *parent);
-/*
+/**
* Creates allocator that remebers all allocations done
* under it and allows all of it to be freed together.
*
#include <usual/base.h>
+/**
+ * Read a pid from pidfile and send a signal to it.
+ */
bool signal_pidfile(const char *pidfile, int sig);
/**
/*
- * Endianess comversion macros.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
+/**
+ * @file
+ *
+ * Endianess conversion macros.
+ *
+ * @section endian_swap Swap value
+ *
+ * Signature:
+ * - uintX fn(uintX)
+ *
* Always swap:
- * bswap16, bswap32, bswap64
+ * - bswap16, bswap32, bswap64
*
* Host <> LE/BE
- * htobe16, htobe32, htobe64
- * htole16, htole32, htole64
- * be16toh, be32toh, be64toh
- * le16toh, le32toh, le64toh
+ * - htobe16, htobe32, htobe64
+ * - htole16, htole32, htole64
+ * - be16toh, be32toh, be64toh
+ * - le16toh, le32toh, le64toh
+ *
+ * @section endian_dec Read value from memory
+ *
+ * Signature:
+ * - uintX dec(const void *p)
+ *
+ * Variants:
+ * - le16dec, le32dec, le64dec
+ * - be16dec, be32dec, be64dec
+ *
+ * @section endian_enc Write value to memory
*
- * Read LE/BE -> Host:
- * le16dec, le32dec, le64dec
- * be16dec, be32dec, be64dec
+ * Signature:
+ * - void enc(void *p, uintX val)
*
- * Write Host -> LE/BE:
- * le16enc, le32enc, le64enc
- * be16enc, be32enc, be64enc
+ * Variants:
+ * - le16enc, le32enc, le64enc
+ * - be16enc, be32enc, be64enc
*/
#ifndef _USUAL_ENDIAN_H_
/*
- * event.h - libevent compatible event loop.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/**
+ * @file
+ * libevent compat.
+ *
+ * This module adds few functions to older libevent versions,
+ * or provides it's own libevent-compatible event loop
+ * for cases where performance and features of full libevent
+ * are not needed.
+ */
#ifndef _USUAL_EVENT_H_
#define _USUAL_EVENT_H_
#include <event.h>
-/* make event_base_new() always available */
#ifndef HAVE_EVENT_BASE_NEW
+/** Compat: make sure event_base_new() always available */
static inline struct event_base *event_base_new(void)
{
return event_init();
}
#endif
-/* libevent 1.3 does not have event_loopbreak() */
#ifndef HAVE_EVENT_LOOPBREAK
+/** Compat: dummy event_loopbreak for libevent 1.3 */
static inline void event_loopbreak(void) { }
#endif
#include <usual/list.h>
#include <usual/time.h>
-/*
+/**
* Flags for event_set() / event_assign():
* EV_READ, EV_WRITE, EV_SIGNAL, EV_PERSIST
*
EV_PERSIST = 16,
};
-/* Flags for event_loop() */
+/** Flags for event_loop() */
enum EventLoopType {
EVLOOP_ONCE = 1,
EVLOOP_NONBLOCK = 2,
};
-/* event_base contents are not open */
+/** Event context. event_base contents are not open */
struct event_base;
-/* user callback signature */
+/** user callback signature */
typedef void (*uevent_cb_f)(int fd, short flags, void *arg);
-/* macros to read fd and signal values */
+/** Read fd value from struct event */
#define EVENT_FD(ev) ((ev)->fd)
+/** Read signal value from struct event */
#define EVENT_SIGNAL(ev) ((ev)->fd)
-/*
- * Our event structure.
+/**
+ * Event structure for internal event loop.
*
* Although the struct is open, no direct accesses should be done.
- * Thus also the fields are incompat with libevent.
+ * Thus also the fields are incompatible with libevent.
*/
struct event {
/* node for fd or signal lists */
/*
- * File access utils.
- *
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/**
+ * @file
+ *
+ * File access utils.
+ */
#ifndef _USUAL_FILEUTIL_H_
#define _USUAL_FILEUTIL_H_
#include <stdio.h>
+/** Info about mapped file */
struct MappedFile {
int fd;
unsigned len;
void *ptr;
};
+/** Signature for per-line callback */
typedef void (*procline_cb)(void *arg, const char *line, ssize_t len);
+/** Read file into memory */
void *load_file(const char *fn, size_t *len_p);
+/** Loop over lines in file */
bool foreach_line(const char *fn, procline_cb proc_line, void *arg);
+/** Get file size */
ssize_t file_size(const char *fn);
+/** Map file into memory */
int map_file(struct MappedFile *m, const char *fname, int rw) _MUSTCHECK;
+
+/** Unmap previously mapped file */
void unmap_file(struct MappedFile *m);
#if !defined(HAVE_GETLINE)
#define getline(a,b,c) compat_getline(a,b,c)
+
+/**
+ * Compat: Read line from file
+ */
int getline(char **line_p, size_t *size_p, void *f);
+
#endif
/*
- * Logging for unix service.
- *
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/**
+ * @file
+ *
+ * Logging framework for unix services.
+ *
+ *
+ * Supported outputs:
+ * - syslog
+ * - log file
+ * - stderr
+ *
+ * @section logging_prefix Logging context
+ *
+ * It is possible to pass context info to all logging calls
+ * and later add details to log lines or to filter based on it.
+ *
+ * Each call references 2 macros:
+ * - LOG_CONTEXT_DEF - which can define/call any variables
+ * - LOG_CONTEXT - which should return a pointer variable.
+ *
+ * Later, global callback function \ref logging_prefix_cb
+ * will get this pointer with destination buffer and can either
+ * add more info for log line or tell to skip logging this message.
+ */
#ifndef _USUAL_LOGGING_H_
#define _USUAL_LOGGING_H_
#include <usual/base.h>
-/* way to pass context info for prefix function */
+/* internal log levels */
+enum LogLevel {
+ LG_FATAL = 0,
+ LG_ERROR = 1,
+ LG_WARNING = 2,
+ LG_INFO = 3,
+ LG_DEBUG = 4,
+ LG_NOISE = 5,
+};
+#ifndef LOG_CONTEXT_DEF
+/** Example: Prepare dummy context pointer */
#define LOG_CONTEXT_DEF void *_log_ctx = NULL
+#endif
+#ifndef LOG_CONTEXT
+/** Example: Reference dummy context pointer */
#define LOG_CONTEXT _log_ctx
+#endif
-/*
+/**
+ * Signature for logging_prefix_cb. Return value is either added string length in dst
+ * or negative value to skip logging.
+ */
+typedef int (*logging_prefix_fn_t)(enum LogLevel lev, void *ctx, char *dst, unsigned int dstlen);
+
+/**
+ * Optional global callback for each log line.
+ *
+ * It can either add info to log message or skip logging it.
+ */
+extern logging_prefix_fn_t logging_prefix_cb;
+
+/**
+ * Global verbosity level.
+ *
* 0 - show only info level msgs (default)
* 1 - show debug msgs (log_debug)
* 2 - show noise msgs (log_noise)
*/
extern int cf_verbose;
-/* If logging to stdout is allowed (default: 1) */
-/* daemon.c turns this off if goes to background */
+/**
+ * Toggle logging to stderr. Default: 1.
+ * daemon.c turns this off if goes to background
+ */
extern int cf_quiet;
-/* logfile location, default NULL */
+/**
+ * Logfile location, default NULL
+ */
extern const char *cf_logfile;
-/* ident for syslog, if NULL syslog is disabled (default) */
+/**
+ * ident for syslog, if NULL syslog is disabled (default)
+ */
extern const char *cf_syslog_ident;
/*
- * Quick API overview:
- *
- * void log_error(const char *s, ...);
- * void log_warning(const char *s, ...);
- * void log_info(const char *s, ...);
- * void log_debug(const char *s, ...);
- * void log_noise(const char *s, ...);
- * void fatal(const char *s, ...);
- * void fatal_perror(const char *s, ...);
- * void die(const char *s, ...);
- *
- * close_logfile(void);
+ * Internal API.
*/
+/* non-fatal logging */
+void log_generic(enum LogLevel level, void *ctx, const char *s, ...) _PRINTF(3, 4);
+
+/* this is also defined in base.h for Assert() */
+void log_fatal(const char *file, int line, const char *func, bool show_perror,
+ void *ctx, const char *s, ...) _PRINTF(6, 7);
+
/*
- * Internal logging function.
+ * Public API
*/
-enum LogLevel {
- LG_FATAL = 0,
- LG_ERROR = 1,
- LG_WARNING = 2,
- LG_INFO = 3,
- LG_DEBUG = 4,
- LG_NOISE = 5,
-};
-void log_generic(enum LogLevel level, void *ctx, const char *s, ...) _PRINTF(3, 4);
-/* macros for plain logging */
-#define log_error(args...) do { LOG_CONTEXT_DEF; \
- log_generic(LG_ERROR, LOG_CONTEXT, ## args); \
+/** Log error message */
+#define log_error(fmt, args...) do { LOG_CONTEXT_DEF; \
+ log_generic(LG_ERROR, LOG_CONTEXT, fmt, ## args); \
} while (0)
-#define log_warning(args...) do { LOG_CONTEXT_DEF; \
- log_generic(LG_WARNING, LOG_CONTEXT, ## args); \
+
+/** Log warning message */
+#define log_warning(fmt, args...) do { LOG_CONTEXT_DEF; \
+ log_generic(LG_WARNING, LOG_CONTEXT, fmt, ## args); \
} while (0)
-#define log_info(args...) do { LOG_CONTEXT_DEF; \
- log_generic(LG_INFO, LOG_CONTEXT, ## args); \
+
+/** Log info message */
+#define log_info(fmt, args...) do { LOG_CONTEXT_DEF; \
+ log_generic(LG_INFO, LOG_CONTEXT, fmt, ## args); \
} while (0)
-/* move printf arg setup out-of-line for debug macros */
-#define log_debug(args...) do { LOG_CONTEXT_DEF; \
+/** Log debug message */
+#define log_debug(fmt, args...) do { LOG_CONTEXT_DEF; \
if (unlikely(cf_verbose > 0)) \
- log_generic(LG_DEBUG, LOG_CONTEXT, ## args); \
+ log_generic(LG_DEBUG, LOG_CONTEXT, fmt, ## args); \
} while (0)
-#define log_noise(args...) do { LOG_CONTEXT_DEF; \
+
+/** Log debug noise */
+#define log_noise(fmt, args...) do { LOG_CONTEXT_DEF; \
if (unlikely(cf_verbose > 1)) \
- log_generic(LG_NOISE, LOG_CONTEXT, ## args); \
+ log_generic(LG_NOISE, LOG_CONTEXT, fmt, ## args); \
} while (0)
-/* this is also defined in base.h for Assert() */
-void log_fatal(const char *file, int line, const char *func, bool show_perror,
- void *ctx, const char *s, ...) _PRINTF(6, 7);
-
-/* fatal loggers should also log location */
-#define fatal(args...) do { LOG_CONTEXT_DEF; \
- log_fatal(__FILE__, __LINE__, __func__, false, LOG_CONTEXT, ## args); \
+/** Log and die. It also logs source location */
+#define fatal(fmt, args...) do { LOG_CONTEXT_DEF; \
+ log_fatal(__FILE__, __LINE__, __func__, false, LOG_CONTEXT, fmt, ## args); \
exit(1); } while (0)
-#define fatal_perror(args...) do { LOG_CONTEXT_DEF; \
- log_fatal(__FILE__, __LINE__, __func__, true, LOG_CONTEXT, ## args); \
+
+/** Log strerror and die. Error message also includes strerror(errno) */
+#define fatal_perror(fmt, args...) do { LOG_CONTEXT_DEF; \
+ log_fatal(__FILE__, __LINE__, __func__, true, LOG_CONTEXT, fmt, ## args); \
exit(1); } while (0)
-/* less verbose fatal() */
-#define die(args...) do { LOG_CONTEXT_DEF; \
+/** Less verbose fatal() */
+#define die(fmt, args...) do { LOG_CONTEXT_DEF; \
log_generic(LG_FATAL, LOG_CONTEXT, ## args); \
exit(1); } while (0)
+/**
+ * Close open logfiles and syslog.
+ *
+ * Useful when rotating log files.
+ */
void reset_logging(void);
-/* optional function to fill prefix. returns prefix len or < 0 to skip logging */
-typedef int (*logging_prefix_fn_t)(enum LogLevel lev, void *ctx, char *dst, unsigned int dstlen);
-extern logging_prefix_fn_t logging_prefix_cb;
-
#endif
+/*
+ * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/** @file
+ *
+ * Minimal dict.
+ */
+
#ifndef _USUAL_MDICT_H_
#define _USUAL_MDICT_H_
#include <usual/cxalloc.h>
#include <usual/mbuf.h>
+/** Dict reference */
struct MDict;
+/** Create new emtpy dict */
struct MDict *mdict_new(CxMem *cx);
-void mdict_free(struct MDict *dict);
-bool mdict_urldecode(struct MDict *dict, const char *str, unsigned len);
-bool mdict_urlencode(struct MDict *dict, struct MBuf *dst);
+/** Free dict */
+void mdict_free(struct MDict *dict);
+/** Get value as MBuf from string */
const struct MBuf *mdict_get_buf(struct MDict *dict, const char *key, unsigned klen);
+
+/** Get value from dict */
const char *mdict_get_str(struct MDict *dict, const char *key, unsigned klen);
+
+/** Put string to dict */
bool mdict_put_str(struct MDict *dict, const char *key, unsigned klen, const char *val, unsigned vlen);
+/** Signature for walker callback */
typedef bool (*mdict_walker_f)(void *arg, const struct MBuf *k, const struct MBuf *v);
+
+/** Walk over dict */
bool mdict_walk(struct MDict *dict, mdict_walker_f cb_func, void *cb_arg);
/*
* Simple API that calculates strlen inline.
*/
+/** Get value from dict */
static inline const char *mdict_get(struct MDict *dict, const char *key)
{
return mdict_get_str(dict, key, strlen(key));
}
+/** Put zero-terminated key and value to dict */
static inline bool mdict_put(struct MDict *dict, const char *key, const char *val)
{
unsigned klen = strlen(key);
return mdict_put_str(dict, key, klen, val, vlen);
}
+/** Put MBuf to dict */
static inline bool mdict_put_buf(struct MDict *dict, const char *key, const struct MBuf *buf)
{
unsigned klen = strlen(key);
return mdict_put_str(dict, key, klen, val, vlen);
}
+/** Urldecode string and add keys with values to dict */
+bool mdict_urldecode(struct MDict *dict, const char *str, unsigned len);
+
+/** Urlencode dict to string */
+bool mdict_urlencode(struct MDict *dict, struct MBuf *dst);
+
#endif
/*
- * Random stuff that does not fit elsewhere.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ * Random stuff that does not fit elsewhere.
+ */
#ifndef _USUAL_MISC_H_
#define _USUAL_MISC_H_
| ((unsigned int)(unsigned char)(c) << 8) \
| ((unsigned int)(unsigned char)(d)))
#else
+/** Four-byte identifier as integer */
#define FOURCC(a,b,c,d) \
( ((unsigned int)(unsigned char)(a)) \
| ((unsigned int)(unsigned char)(b) << 8) \
| ((unsigned int)(unsigned char)(d) << 24))
#endif
+/** Checks if integer has only one bit set */
static inline int is_power_of_2(int n)
{
return (n > 0) && !(n & (n - 1));
* Single-eval and type-safe rol/ror
*/
+/** Rotate 16-bit int to left */
static inline uint16_t rol16(uint16_t v, int s)
{
return (v << s) | (v >> (16 - s));
}
+/** Rotate 32-bit int to left */
static inline uint32_t rol32(uint32_t v, int s)
{
return (v << s) | (v >> (32 - s));
}
+/** Rotate 64-bit int to left */
static inline uint64_t rol64(uint64_t v, int s)
{
return (v << s) | (v >> (64 - s));
}
-#define ror16(v, s) rol16(v, (16 - (s)))
-#define ror32(v, s) rol32(v, (32 - (s)))
-#define ror64(v, s) rol64(v, (64 - (s)))
+/** Rotate 16-bit int to right */
+static inline uint16_t ror16(uint16_t v, int s) { return rol16(v, 16 - s); }
+/** Rotate 32-bit int to right */
+static inline uint32_t ror32(uint32_t v, int s) { return rol32(v, 32 - s); }
+/** Rotate 64-bit int to right */
+static inline uint64_t ror64(uint64_t v, int s) { return rol64(v, 64 - s); }
#endif
/*
- * Async Postgres connection.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ *
+ * Async Postgres connection framework.
+ */
#ifndef _USUAL_PGSOCKET_H_
#define _USUAL_PGSOCKET_H_
#include <libpq-fe.h>
+/**
+ * Event types reported to user handler function.
+ */
enum PgEvent {
+ /** Connection establishing finished */
PGS_CONNECT_OK,
+ /** Connection establishing failed */
PGS_CONNECT_FAILED,
+ /** Got result from query either resultset or DB error */
PGS_RESULT_OK,
+ /** Query execution failed */
PGS_RESULT_BAD,
+ /** Wakeup from timed sleep */
PGS_TIMEOUT,
};
typedef void (*pgs_handler_f)(struct PgSocket *pgs, void *arg, enum PgEvent dbev, PGresult *res);
+/** Create PgSocket.
+ *
+ * It does not launch connection yet, use \ref pgs_connect() for that.
+ *
+ * @param connstr libpq connect string
+ * @param fn callback function for event handling
+ * @param arg extra context for callback
+ * @return Initialized PgSocket structure
+ */
struct PgSocket *pgs_create(const char *connstr, pgs_handler_f fn, void *arg);
+
+/** Release PgSocket */
void pgs_free(struct PgSocket *db);
+/** Change the event base for PgSocket */
void pgs_set_event_base(struct PgSocket *pgs, struct event_base *base);
+/** Launch connection */
void pgs_connect(struct PgSocket *db);
+
+/** Drop connection */
void pgs_disconnect(struct PgSocket *db);
+/** Send simple query */
void pgs_send_query_simple(struct PgSocket *db, const char *query);
+
+/** Send extended query, args from varargs */
void pgs_send_query_params(struct PgSocket *db, const char *query, int nargs, ...);
+
+/** Send extended query, args from list */
void pgs_send_query_params_list(struct PgSocket *db, const char *query, int nargs, const char *argv[]);
+/** Ignore the connection for specified time */
void pgs_sleep(struct PgSocket *db, double timeout);
+
+/** Disconnect, sleep, reconnect */
void pgs_reconnect(struct PgSocket *db, double timeout);
+/** Does PgSocket have established connection */
int pgs_connection_valid(struct PgSocket *db);
+/** Return underlying Postgres connection */
PGconn *pgs_get_connection(struct PgSocket *db);
bool pgs_waiting_for_reply(struct PgSocket *db);
/*
- * Pthreads compat.
- *
* Copyright (c) 2007-2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ *
+ * Pthreads compat for win32.
+ */
#ifndef _USUAL_PTHREAD_H_
#define _USUAL_PTHREAD_H_
/*
- * Small POSIX-only regex engine.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* POSIX regular expession API, provided by either libc or internally.
*
* The internal regex engine is only activated if OS does not provide
- * @ref regex_links "<regex.h>" (eg. Windows) or if
+ * @ref uregex_links "<regex.h>" (eg. Windows) or if
* --with-internal-regex is used when configuring @ref libusual.
*
- * @section uregex Internal regex features.
+ * @section uregex Features of internal regex (uregex).
*
* Simple recursive matcher, only features are small size
- * and POSIX compatibility.
+ * and POSIX compatibility. Supports both Extended Regular Expressions (ERE)
+ * and Basic Regular Expressions (BRE).
*
+ * @section uregex_syntax Supported syntax
* @code
- * ERE syntax: . * ^ $ [] [[:cname:]] () {} | + ?
- * BRE syntax: . * ^ $ [] [[:cname:]] \(\) \{\} \1-9
+ * Both: . * ^ $ [] [[:cname:]]
+ * ERE: () {} | + ?
+ * BRE: \(\) \{\} \1-9
* @endcode
*
* With REG_RELAXED_SYNTAX, following common escapes will be available:
* leftmost-longest to all elements. It skips the combinatorics to turn it
* into guaranteed-longest match.
*
- * @section skip Skipped POSIX features
+ * @section uregex_skip Skipped POSIX features
* - collation classes: [[. .]]
* - equivalence classes: [[= =]]
* - char ranges by locale order: [a-z] (byte order will be used)
* - multi-byte chars: UTF-8
*
- * @section globaldefs Global defines
+ * @section uregex_globaldefs Global defines
* - USUAL_RELAXED_REGEX
* - USE_INTERNAL_REGEX
*
- * @section regex_links Compatibility
+ * @section uregex_links Compatibility
*
* - <a href="http://www.opengroup.org/onlinepubs/9699919799/basedefs/regex.h.html">
* POSIX-2008 <regex.h> spec</a> - by default uRegex run in mode where only
/* @} */
/**
- * @name Non-standard defines for regcomp()
+ * @name Non-standard flags for regcomp()
* @{
*/
/**
* Dont permute groups in attempt to get longest match.
*
- * May give minor speed win at the expense of strict POSIX compat.
+ * May give minor speed win at the expense of strict
+ * POSIX compatibility.
*/
#define REG_RELAXED_MATCHING (1 << 15)
#define regerror(a,b,c,d) usual_regerror(a,b,c,d)
#define regfree(a) usual_regfree(a)
-/* public functions */
-
/**
* Compile regex.
*
* @param rx Pre-allocated @ref regex_t structure to fill.
* @param re Regex as zero-terminated string.
- * @param flags See bove for regcomp() flags.
+ * @param flags See above for regcomp() flags.
*/
int regcomp(regex_t *rx, const char *re, int flags);
/**
- * Execute regex on string.
+ * Execute regex on a string.
*
- * @param rx Regex previously filled by regcomp()
+ * @param rx Regex previously initialized with regcomp()
* @param str Zero-terminated string to match
- * @param nmatch number of matches in pmatch
+ * @param nmatch Number of matches in pmatch
* @param pmatch Array of matches.
* @param eflags Execution flags. Supported flags: @ref REG_NOTBOL, @ref REG_NOTEOL
*/
/**
* Free resources allocated by regcomp().
- * \param rx Regex previously filled by regcomp()
+ * @param rx Regex previously filled by regcomp()
*/
void regfree(regex_t *rx);
/*
- * libusual - Utility library for C
- *
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ *
+ * EINTR-safe I/O functions.
+ */
#ifndef _USUAL_SAFEIO_H_
#define _USUAL_SAFEIO_H_
#include <usual/socket.h>
+/** read */
int safe_read(int fd, void *buf, int len) _MUSTCHECK;
+/** write */
int safe_write(int fd, const void *buf, int len) _MUSTCHECK;
+/** recv */
int safe_recv(int fd, void *buf, int len, int flags) _MUSTCHECK;
+/** send */
int safe_send(int fd, const void *buf, int len, int flags) _MUSTCHECK;
+/** close */
int safe_close(int fd);
+/** recvmsg */
int safe_recvmsg(int fd, struct msghdr *msg, int flags) _MUSTCHECK;
+/** sendmsg */
int safe_sendmsg(int fd, const struct msghdr *msg, int flags) _MUSTCHECK;
+/** connect */
int safe_connect(int fd, const struct sockaddr *sa, socklen_t sa_len) _MUSTCHECK;
+/** accept */
int safe_accept(int fd, struct sockaddr *sa, socklen_t *sa_len) _MUSTCHECK;
#endif
/*
- * Theme include for signals.
- *
* Copyright (c) 2009 Marko Kreen
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ * Signals compat.
+ *
+ * general
+ * - sigaction() -> signal()
+ *
+ * win32:
+ * - SIGALRM, alarm(), signal(SIGALRM), sigaction(SIGALRM)
+ * - kill(pid, 0)
+ */
#ifndef _USUAL_SIGNAL_H_
#define _USUAL_SIGNAL_H_
#ifdef WIN32
#define SIGALRM 1023
+#define SIGBUS 1022
unsigned alarm(unsigned);
int kill(int pid, int sig);
sa.sa_flags = sa.sa_mask = 0;
sigaction(SIGALRM, &sa, &oldsa);
return oldsa.sa_handler;
+ } else if (sig == SIGBUS) {
+ return NULL;
}
return signal(sig, func);
}
/*
- * Theme include for sockets.
- *
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
*
* Permission to use, copy, modify, and/or distribute this software for any
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/** @file
+ *
+ * Socket compat, few utils.
+ *
+ * Socket headers included:
+ * - win32: <winsock2.h>
+ * - win32: <ws2tcpip.h>
+ * - <sys/socket.h>
+ * - <sys/poll.h>
+ * - <sys/un.h>
+ * - <netinet/in.h>
+ * - <netinet/tcp.h>
+ * - <arpa/inet.h>
+ * - <fcntl.h>
+ * - <poll.h>
+ */
#ifndef _USUAL_SOCKET_H_
#define _USUAL_SOCKET_H_
#include <arpa/inet.h>
#endif
-/*
- * Some systems (Solaris) does not define INADDR_NONE
- */
#ifndef INADDR_NONE
+/** Compat: Some systems (Solaris) does not define INADDR_NONE */
#define INADDR_NONE ((unsigned long) -1)
#endif
+/**
+ * Usual socket setup.
+ *
+ * - Disallow SIGPIPE
+ * - Set close-on-exec flag
+ * - Call \ref socket_set_nonblocking() with given flag
+ */
bool socket_setup(int sock, bool non_block);
+
+/**
+ * Flip sockets non-blocking flag
+ */
bool socket_set_nonblocking(int sock, bool non_block);
+
+/**
+ * Set sockets keepalive flags.
+ *
+ * @param fd TCP socket
+ * @param onoff Whether to set keepalive on or off.
+ * @param keepidle How long the socket must be idle before keepalive packets are sent
+ * @param keepintvl How big period between consecutive keepalive packets.
+ * @param keepcnt How many keepalive packets to send before considering socket dead.
+ */
bool socket_set_keepalive(int fd, int onoff, int keepidle, int keepintvl, int keepcnt);
+/**
+ * Convert struct sockaddr to stirng.
+ *
+ * Supports: ipv4, ipv5, unix sockets.
+ */
const char *sa2str(const struct sockaddr *sa, char *buf, int buflen);
#ifndef HAVE_INET_NTOP
#define inet_ntop(a,b,c,d) compat_inet_ntop(a,b,c,d)
+/** Compat: inet_ntop() */
const char *inet_ntop(int af, const void *src, char *dst, int cnt);
#endif
#ifndef HAVE_GETPEEREID
#define getpeereid(a,b,c) compat_getpeereid(a,b,c)
+/** Get user id of UNIX socket peer */
int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p);
#endif
short revents;
};
typedef unsigned long nfds_t;
+/** Compat: select-based poll() */
int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms);
#endif
#ifdef WIN32
-int win32_socketpair(int d, int typ, int proto, int sv[2]);
#define socketpair(a,b,c,d) win32_socketpair(a,b,c,d)
+/** Compat: socketpair() for win32 */
+int socketpair(int d, int typ, int proto, int sv[2]);
#endif
#endif