Merge branch 'dev'
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
import os
|
||||
Import('env', 'build_type', 'prefix', 'version_info')
|
||||
|
||||
ucore_env = env.Clone()
|
||||
|
||||
#substitute @version_xx@ strings
|
||||
subst_version_info = dict(('@' + key + '@', version_info[key]) for key in version_info)
|
||||
ucore_env.Substfile('ucore_version.c.in', SUBST_DICT = subst_version_info)
|
||||
|
||||
headers = ucore_env.Glob('*.h')
|
||||
|
||||
#install targets
|
||||
|
||||
ucore_env.Alias('install',
|
||||
ucore_env.InstallPerm(os.path.join(prefix, 'include', 'ucore'), headers, 0644))
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#ifndef IO_MUX_H_
|
||||
#define IO_MUX_H_
|
||||
|
||||
#include "ucore_timers.h"
|
||||
|
||||
#define MUX_EV_READ (1 << 0x00)
|
||||
#define MUX_EV_WRITE (1 << 0x01)
|
||||
//#define MUX_EV_EXCEPT (1 << 0x02)
|
||||
#define MUX_EV_MASK (MUX_EV_READ | MUX_EV_WRITE )
|
||||
|
||||
/**
|
||||
* mux implementation to use
|
||||
*/
|
||||
enum IOMUX_TYPE {
|
||||
IOMUX_TYPE_DEFAULT = 0,
|
||||
IOMUX_TYPE_SELECT,
|
||||
IOMUX_TYPE_EPOLL
|
||||
};
|
||||
|
||||
/** Opaque struct */
|
||||
struct IOMux;
|
||||
struct IOMuxFD;
|
||||
typedef void (*iomux_cb)(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event);
|
||||
|
||||
/** Represents a watched file descriptor */
|
||||
struct IOMuxFD {
|
||||
/** The file descriptor */
|
||||
int fd;
|
||||
/** The events to watch for, MUX_EV_XX mask */
|
||||
unsigned int what;
|
||||
/** callback to call on an event */
|
||||
iomux_cb callback;
|
||||
/** values available to the caller. These will bbe passed
|
||||
* back on the callback */
|
||||
void *cookie_ptr;
|
||||
int cookie_int;
|
||||
int cookie_int2;
|
||||
};
|
||||
|
||||
/** Creates a new IOMux.
|
||||
*/
|
||||
struct IOMux *iomux_create(enum IOMUX_TYPE type);
|
||||
|
||||
/** Deletes the IOMux and frees its resources.
|
||||
* Can not be called from within a callback */
|
||||
void iomux_delete(struct IOMux *mux);
|
||||
|
||||
/** Runs the event loop of the mux
|
||||
* returns if the number of file descriptors and timers are 0 or
|
||||
* an error occurs */
|
||||
int iomux_run(struct IOMux *mux);
|
||||
|
||||
/* Adds a file descriptor to the watch set,
|
||||
* returns 0 on success, an errno value on error */
|
||||
int iomux_register_fd(struct IOMux *mux, struct IOMuxFD *fd);
|
||||
|
||||
/** Removes the file descriptor*/
|
||||
int iomux_unregister_fd(struct IOMux *mux, struct IOMuxFD *fd);
|
||||
|
||||
/** Updates the events to watch for in fd->what
|
||||
* returns 0 on success, an errno value on error */
|
||||
int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd);
|
||||
|
||||
|
||||
/**
|
||||
* Convenience macro for setting the new event
|
||||
*/
|
||||
#define iomux_set_event(mux, fd, what)\
|
||||
({\
|
||||
(fd)->what = (what);\
|
||||
iomux_update_events((mux), (fd));\
|
||||
})
|
||||
|
||||
/**
|
||||
* Convenience macro for clearing the new event
|
||||
*/
|
||||
#define iomux_clear_event(mux, fd, what)\
|
||||
({\
|
||||
(fd)->what &= ~(what);\
|
||||
iomux_update_events((mux), (fd));\
|
||||
})
|
||||
/**
|
||||
* Convenience macro for adding the new event to the existing events
|
||||
*/
|
||||
#define iomux_add_event(mux, fd, what)\
|
||||
({\
|
||||
(fd)->what &= (what);\
|
||||
iomux_update_events((mux), (fd));\
|
||||
})
|
||||
|
||||
/** Returns a UCTimer instance tied to this mux.
|
||||
* Used to schedule timers within this mux.
|
||||
*/
|
||||
struct UCTimers *iomux_get_timers(struct IOMux *mux);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#ifndef IO_MUX_IMPL_H_
|
||||
#define IO_MUX_IMPL_H_
|
||||
|
||||
#include "iomux.h"
|
||||
#include "ucore_timers.h"
|
||||
/** struct for IOMux implementations */
|
||||
struct IOMux {
|
||||
|
||||
/* TImer instance */
|
||||
struct UCTimers timers;
|
||||
|
||||
/* Current time. Updated before calling run_impl, and updated
|
||||
* by iomux_timers_run
|
||||
*/
|
||||
struct timeval now;
|
||||
|
||||
/* Used by mux implementations to hold their own data/instance */
|
||||
void *instance;
|
||||
|
||||
/** Run one iteration of the mux.
|
||||
* The mux implementation must honor the timeout, if given.
|
||||
* The mux implementation must call iomux_timers_run after the
|
||||
* polling has occured (or if it's polling times out)
|
||||
*
|
||||
* @param mux The IOMux instance
|
||||
* @param timeout absolute time of a timeout - after which timers should run.
|
||||
* If timeout is NULL, no timeout should be set on the poll.
|
||||
*/
|
||||
int (*run_impl)(struct IOMux *mux, struct timeval *timeout);
|
||||
|
||||
/* Deallocate the instance specific part of the IOMux */
|
||||
void (*delete_impl)(struct IOMux *mux);
|
||||
|
||||
/** Register an IOMuxFD for events*/
|
||||
int (*register_fd_impl)(struct IOMux *mux, struct IOMuxFD *fd);
|
||||
/** Unregister an IOMuxFD */
|
||||
int (*unregister_fd_impl)(struct IOMux *mux, struct IOMuxFD *fd);
|
||||
/** Update an IOMuxFD (due to its events ('what') has changed*/
|
||||
int (*update_events_impl)(struct IOMux *mux, struct IOMuxFD *fd);
|
||||
};
|
||||
|
||||
int iomux_select_init(struct IOMux *mux);
|
||||
int iomux_epoll_init(struct IOMux *mux);
|
||||
int iomux_timers_run(struct IOMux *mux);
|
||||
|
||||
#endif
|
||||
|
||||
-741
@@ -1,741 +0,0 @@
|
||||
/* $NetBSD: tree.h,v 1.16 2008/03/21 13:07:15 ad Exp $ */
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _SYS_TREE_H_
|
||||
#define _SYS_TREE_H_
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
int rbe_color; /* node color */ \
|
||||
}
|
||||
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_COLOR(elm, field) (elm)->field.rbe_color
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(elm, parent, field) do { \
|
||||
RB_PARENT(elm, field) = parent; \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
RB_COLOR(elm, field) = RB_RED; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_SET_BLACKRED(black, red, field) do { \
|
||||
RB_COLOR(black, field) = RB_BLACK; \
|
||||
RB_COLOR(red, field) = RB_RED; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
|
||||
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_NEXT(struct type *); \
|
||||
attr struct type *name##_RB_PREV(struct type *); \
|
||||
attr struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
\
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_GENERATE_STATIC(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
|
||||
attr void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = RB_PARENT(elm, field)) != NULL && \
|
||||
RB_COLOR(parent, field) == RB_RED) { \
|
||||
gparent = RB_PARENT(parent, field); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
attr void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)) \
|
||||
!= NULL) \
|
||||
RB_COLOR(oleft, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)) \
|
||||
!= NULL) \
|
||||
RB_COLOR(oright, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_LEFT(head, tmp, oright, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
RB_COLOR(elm, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
attr struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (RB_PARENT(elm, field) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (RB_PARENT(old, field)) { \
|
||||
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
|
||||
RB_LEFT(RB_PARENT(old, field), field) = elm;\
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
|
||||
RB_AUGMENT(RB_PARENT(old, field)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
RB_PARENT(RB_LEFT(old, field), field) = elm; \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = RB_PARENT(left, field)) != NULL); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
attr struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
attr struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the first node greater than or equal to the search key */ \
|
||||
attr struct type * \
|
||||
name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *res = NULL; \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) { \
|
||||
res = tmp; \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
} \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (res); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
{ \
|
||||
if (RB_LEFT(elm, field)) { \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
while (RB_RIGHT(elm, field)) \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
attr struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#define RB_FOREACH_REVERSE(x, name, head) \
|
||||
for ((x) = RB_MAX(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_PREV(x))
|
||||
|
||||
#endif /* _SYS_TREE_H_ */
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef UC_BACKTRACE_H_
|
||||
#define UC_BACKTRACE_H_
|
||||
|
||||
#define UC_BACTRACE_STDERR uc_backtrace_fd(3)
|
||||
|
||||
void uc_backtrace_fd(int fd);
|
||||
|
||||
#endif
|
||||
@@ -1,81 +0,0 @@
|
||||
#ifndef BITEVEC_H_
|
||||
#define BITEVEC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bitvec {
|
||||
//storage for the bits
|
||||
unsigned long *vec;
|
||||
//length of the above vec. (Not the number of bits !)
|
||||
size_t vec_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Evaluates the length required for a bitvec to store nbit bits.
|
||||
*/
|
||||
#define BITVEC_VEC_LEN(nbits) ((nbits/(sizeof(unsigned long)*CHAR_BIT)) + (nbits % (sizeof(unsigned long)*CHAR_BIT) == 0 ? 0 : 1))
|
||||
|
||||
/**
|
||||
* Use as :
|
||||
* unsigned long v[10];
|
||||
* struct bitvec v = BITVEC_STATIC_INIT(v);
|
||||
*/
|
||||
#define BITVEC_STATIC_INIT(vec_data)\
|
||||
{\
|
||||
vec_data,\
|
||||
sizeof vec_data/sizeof vec_data[0]}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a newly malloced bitvec, capable of storing at least nbits bits
|
||||
* All bits are initially zero.
|
||||
*
|
||||
*/
|
||||
struct bitvec *bitvec_new(size_t nbits);
|
||||
|
||||
/** free a bitvec previously allocated by bitvec_new
|
||||
*/
|
||||
void bitvec_free(struct bitvec *v);
|
||||
|
||||
//Note that accessing a bit beyond the nbits originally initialized
|
||||
//for the given bitvec is undedefined
|
||||
|
||||
/** Sets bit no. b */
|
||||
void set_bit(struct bitvec *v,int b);
|
||||
|
||||
/** Clears bit no. b*/
|
||||
void clear_bit(struct bitvec *v,int b);
|
||||
|
||||
/** Gets the current value (0 or 1) of bit no. b*/
|
||||
int get_bit(const struct bitvec *v,int b);
|
||||
|
||||
/** Sets all bits to zero */
|
||||
void clear_all(struct bitvec *v);
|
||||
|
||||
/** Sets all bits to one */
|
||||
void set_all(struct bitvec *v);
|
||||
|
||||
/** Initialize bits from a array of ints, each array element maps to one bit.
|
||||
* The bits are initialized from the int array so zero maps to zero and non-zero maps to one.
|
||||
* e..g to set the 5 first bits, to 01110:
|
||||
* int a[] = {0,1,1,1,0};
|
||||
* set_bits_from_array(v,a,5);
|
||||
* */
|
||||
void set_bits_from_array(struct bitvec *v,char *array,size_t array_len);
|
||||
|
||||
// The _s ("secure") versions does boundary checking and assert() if they
|
||||
// try to access a bit out of bounds.
|
||||
|
||||
void set_bit_s(struct bitvec *v,int b);
|
||||
|
||||
void clear_bit_s(struct bitvec *v,int b);
|
||||
|
||||
int get_bit_s(const struct bitvec *v,int b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,83 +0,0 @@
|
||||
#ifndef UCORE_BUFFER_H_
|
||||
#define UCORE_BUFFER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** A GBuf is a growing reference counted buffer.
|
||||
* The buffer is dynamically allocated, and can grow
|
||||
* as you append data to it. Reference counting takes care
|
||||
* of automatically freeing the GBuf and its buffer when it
|
||||
* reaches 0
|
||||
*/
|
||||
typedef struct GBuf GBuf;
|
||||
struct GBuf {
|
||||
/** Allocated buffer length.*/
|
||||
size_t len;
|
||||
/** Used space in the buffer */
|
||||
size_t used;
|
||||
/** Reference count */
|
||||
size_t ref_cnt;
|
||||
/** The data */
|
||||
void *buf;
|
||||
};
|
||||
|
||||
/** Allocatea new GBuf.
|
||||
*
|
||||
* @param initsz Intial capacity of the GBuf
|
||||
* @return New GBuf, or NULL if allocation fails,
|
||||
* The returned GBuf will have ref_cnt=1
|
||||
*/
|
||||
GBuf* uc_new_gbuf(size_t initsz);
|
||||
|
||||
/** Increment the reference count of the GBuf.
|
||||
*
|
||||
* @param buf Bufffer
|
||||
*/
|
||||
void uc_gbuf_ref(GBuf *buf);
|
||||
|
||||
/** Decrement the reference count of the GBuf, free it if ref_cnt reaches 0
|
||||
*
|
||||
* @param buf Bufffer
|
||||
*/
|
||||
void uc_gbuf_unref(GBuf *buf);
|
||||
|
||||
/** Append data to the GBuf.
|
||||
* Data is coped into the buffer, starting at &buf->data[used]
|
||||
* The GBuf automatically grows if needed.
|
||||
*
|
||||
* @param buf buffer to append to
|
||||
* @param data data to copy to the GBuf
|
||||
* @param len length of @data to copy
|
||||
* @return 0 on success, -1 on failure when allocation fails if he buffer
|
||||
* needs to grow
|
||||
*/
|
||||
int uc_gbuf_append(GBuf *buf,void *data,size_t len);
|
||||
|
||||
/** Expand the capacity of the GBuf.
|
||||
*
|
||||
* @param buf buffer to grow
|
||||
* @return 0 on success, -1 on failure when allocation fails
|
||||
*/
|
||||
int uc_gbuf_grow(GBuf *buf, size_t addlen);
|
||||
|
||||
/** Remaining unised space of the GBuf.
|
||||
* @param buff buffer
|
||||
* @return length of unused space
|
||||
*/
|
||||
size_t uc_gbuf_remaining(const GBuf *buf)
|
||||
{
|
||||
return buf->len - buf->used;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef UCORE_HASH_H_
|
||||
#define UCORE_HASH_H_
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint32_t
|
||||
uc_crc32(const uint8_t *buf, size_t len);
|
||||
|
||||
uint32_t
|
||||
uc_djbhash(const char *str);
|
||||
|
||||
unsigned int
|
||||
uc_elfhash(const char *str, unsigned int len);
|
||||
|
||||
uint64_t
|
||||
uc_hash64shift(uint64_t key);
|
||||
|
||||
uint32_t
|
||||
uc_hashuint(uint32_t a);
|
||||
|
||||
uint32_t
|
||||
uc_murmurmash2(const void *key, int len, uint32_t seed );
|
||||
|
||||
uint32_t
|
||||
uc_pjwhash(const char *str,size_t len);
|
||||
|
||||
uint32_t
|
||||
uc_sax_hash(void *key, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef UCORE_HEAPSORT_H_
|
||||
#define UCORE_HEAPSORT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
///compare function. Needs only to return < 0 if
|
||||
//the first element is less than the second
|
||||
typedef int (*uc_hs_cmp)(const void *, const void *);
|
||||
|
||||
void
|
||||
uc_heapsort(void *base, size_t count, size_t width,
|
||||
uc_hs_cmp cmp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,252 +0,0 @@
|
||||
#ifndef UCORE_LOGGING_H_
|
||||
#define UCORE_LOGGING_H_
|
||||
|
||||
/** Logging functions.
|
||||
* All logging functions except uc_log_init are thread safe,
|
||||
* so logging can be performed from any thread after the logging
|
||||
* system have been initialized.
|
||||
*
|
||||
* The logging system has the concept of 'modules'. Modules are defined
|
||||
* by the application, and would match the logical parts of an application.
|
||||
* uc_log_init() tells the logging library about these modules, and would normally
|
||||
* be used like:
|
||||
*
|
||||
* enum {
|
||||
* POLLER,
|
||||
* DB,
|
||||
* IO
|
||||
*};
|
||||
*
|
||||
* struct uc_log_module modules[] = {
|
||||
* {
|
||||
* .id = POLLER,
|
||||
* .short_name = "POLLER",
|
||||
* .long_name = "Poller thread",
|
||||
* .log_level = UC_LL_DEBUG,
|
||||
* },
|
||||
* {
|
||||
* .id = DB,
|
||||
* .short_name = "DB",
|
||||
* .long_name = "Database handler",
|
||||
* .log_level == UC_LL_DEBUG
|
||||
* },
|
||||
* {
|
||||
* .id = IO,
|
||||
* .short_name = "IO",
|
||||
* .long_name = "I/O worker",
|
||||
* .log_level == UC_LL_DEBUG
|
||||
* }
|
||||
* };
|
||||
* struct uc_log_modules m = {
|
||||
* .mods = modules,
|
||||
* .cnt = ARRAY_SIZE(modules)
|
||||
* };
|
||||
*
|
||||
* uc_log_init(&m);
|
||||
*
|
||||
* So the application defines 3 modules logging
|
||||
* will be categorized by.
|
||||
* Note that the values (the enum in this case)
|
||||
* defining all the .id memmbers of uc_log_module
|
||||
* must start at 0 and be concecutive.
|
||||
*
|
||||
* Now, the database code in the application can do
|
||||
* logging as e.g.
|
||||
*
|
||||
* UC_LOGF(UC_LL_INFO, DB, "connecting to server %s\n", ip);
|
||||
*
|
||||
* And the resulting log line will include the short_name
|
||||
* modules[DB].short_name
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** The log levels defined by ucore logging*/
|
||||
enum UC_LOG_LEVEL {
|
||||
UC_LL_NONE = 0,
|
||||
UC_LL_DEBUG = 1,
|
||||
UC_LL_INFO = 3,
|
||||
UC_LL_WARNING = 5,
|
||||
UC_LL_ERROR = 7,
|
||||
};
|
||||
|
||||
/** A destination for the logging messages*/
|
||||
enum UC_LOG_DESTINATION {
|
||||
/** Logs using the unix syslog system */
|
||||
UC_LDEST_SYSLOG,
|
||||
|
||||
/** Prints log messages to stderr. */
|
||||
UC_LDEST_STDERR,
|
||||
|
||||
/** Prints log messages to a file */
|
||||
UC_LDEST_FILE,
|
||||
};
|
||||
|
||||
/** A module of a program, that will perform logging.
|
||||
* This is used group logging from parts of a larger program,
|
||||
* and allow the log message to identigy which module the
|
||||
* log message originates from
|
||||
*/
|
||||
struct uc_log_module {
|
||||
/** The id of the log module.
|
||||
* This is the id one specifies in the various log
|
||||
* functions/macros*/
|
||||
int id;
|
||||
|
||||
/** A short name for the module.
|
||||
* This will appear in log messages */
|
||||
const char *short_name;
|
||||
/** A longer description for the log module*/
|
||||
const char *long_name;
|
||||
/** The log level of this module. Only
|
||||
* log statements with a level >= the log_level
|
||||
* are actually logged */
|
||||
int log_level;
|
||||
};
|
||||
|
||||
/* A collection of struct uc_log_module */
|
||||
struct uc_log_modules {
|
||||
/* Pointer to the first element of the array */
|
||||
struct uc_log_module *mods;
|
||||
/** The number of elements in the mods array. */
|
||||
int cnt;
|
||||
};
|
||||
|
||||
struct uc_log_destination;
|
||||
|
||||
|
||||
/* Returns a string representation of the log level.
|
||||
*
|
||||
* @param ll The log level
|
||||
* @return String representation of the log level. (This will be a string literal)
|
||||
*/
|
||||
const char *uc_ll_2_str(enum UC_LOG_LEVEL l);
|
||||
|
||||
/* creates a new uc_log_destination for printing on stderr.
|
||||
*
|
||||
* @param log_level log level of this destination. only log messages
|
||||
* with a log level >= the log level of the destination are actually logged.
|
||||
* @param log_location whether to log info about the source file and line number
|
||||
* in a log message.
|
||||
*
|
||||
* @return An opaque uc_log_destination that can be added as a destination to
|
||||
* the ucore logging system
|
||||
*/
|
||||
struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location);
|
||||
|
||||
/* creates a new uc_log_destination for logging to syslog
|
||||
*
|
||||
* @param ident The ident as used in the syslog openlog() funcion
|
||||
* @param facility The facility as used in the syslog openlog() function()
|
||||
* @param log_level log level of this destination. only log messages
|
||||
* with a log level >= the log level of the destination are actually logged.
|
||||
* @param log_location whether to log info about the source file and line number
|
||||
* in a log message.
|
||||
* @return An opaque uc_log_destination that can be added as a destination to
|
||||
* the ucore logging system
|
||||
*/
|
||||
struct uc_log_destination *uc_log_new_syslog(const char *ident, int facility, int log_level, int log_location);
|
||||
|
||||
/* creates a new uc_log_destination for printing on stderr.
|
||||
*
|
||||
* @param log_level log level of this destination. only log messages
|
||||
* with a log level >= the log level of the destination are actually logged.
|
||||
* @param log_location whether to log info about the source file and line number
|
||||
* in a log message.
|
||||
* @param return An opaque uc_log_destination that can be added as a destination to
|
||||
* the ucore logging system
|
||||
*/
|
||||
struct uc_log_destination *uc_log_new_file(const char *filename, int log_level, int log_location);
|
||||
|
||||
/** Add a uc_log_destination to the logging system.
|
||||
*
|
||||
* @param dest The uc_log_destination to add.
|
||||
*/
|
||||
void uc_log_add_destination(struct uc_log_destination *dest);
|
||||
|
||||
/** Remove a log destination.
|
||||
* Note that this does not free the destination, it can be readded later.
|
||||
* For file destination, the log file is NOT closed.
|
||||
*
|
||||
* @param dest The uc_log_destination to remove.
|
||||
*/
|
||||
void uc_log_remove_destination(struct uc_log_destination *dest);
|
||||
|
||||
/** Remove and free a destination.
|
||||
* This frees the memory allocated to the destination. For
|
||||
* UC_LDEST_FILE the log file is closed.
|
||||
*
|
||||
* If the destination is not already removed, it will be removed first,
|
||||
* there's no need to call uc_log_remove_destination first.
|
||||
* The destination cannot be used again after this function has been called.
|
||||
*
|
||||
* @param dest The destination to delete.
|
||||
*/
|
||||
void uc_log_delete_destination(struct uc_log_destination *dest);
|
||||
|
||||
/** Change the log level of a module.
|
||||
*
|
||||
* @param module The module to change, matched against the id member of a struct uc_log_module
|
||||
* @param level The log level for this module
|
||||
*
|
||||
* @return 0 on success, non-zero if the module was not found.
|
||||
*/
|
||||
int uc_log_module_set_loglevel(int module, enum UC_LOG_LEVEL level);
|
||||
|
||||
/** Closes and re-opens all the UC_LDEST_FILE log destinations.
|
||||
* Intended for use when a log file is rotated externally.
|
||||
*
|
||||
* @param return 0 on success, non-zero if an error occured when re-opening a file.
|
||||
*/
|
||||
int uc_log_reopen_files(void);
|
||||
|
||||
/** Init the logging system. This function must be called before performing any other
|
||||
* logging action.
|
||||
*
|
||||
* @param user_struct containing an array of all the modules defined by the application.
|
||||
*/
|
||||
void uc_log_init(struct uc_log_modules *user_modules);
|
||||
|
||||
void uc_logf(int log_level, int module, int raw,
|
||||
const char *file, int line, const char *fmt, ...)
|
||||
__attribute__((format(printf, 6, 7)));
|
||||
|
||||
#ifdef DEBUG
|
||||
# define UC_DEBUGF(mod, fmt, ...)\
|
||||
uc_logf(UC_LL_DEBUG, mod,0 , __FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
# define UC_DEBUGFR(mod, fmt, ...)\
|
||||
uc_logf(UC_LL_DEBUG, mod,1 , , __LINE__, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
# define UC_DEBUGF(mod, fmt, ...)
|
||||
# define UC_DEBUGFR(mod, fmt, ...)
|
||||
#endif
|
||||
|
||||
/** Main macro that should be used for logging.
|
||||
*
|
||||
* For log messages with UC_LL_DEBUG, the UC_DEBUGF() macro can be used,
|
||||
* UC_DEBUGF will only be compiled in if the DEBUG macro is defined
|
||||
*
|
||||
* @param lvl log level of this log message
|
||||
* @param mod module id of this log messagex.
|
||||
* @param fmt printf style format string
|
||||
* @param ... printf style arguments
|
||||
*/
|
||||
#define UC_LOGF(lvl, mod, fmt, ...) \
|
||||
uc_logf(lvl, mod, 0, __FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
|
||||
/** Raw logging ,Like UC_LOGF, but only prints the supplied
|
||||
* data, not timestamp, log level etc.
|
||||
*/
|
||||
#define UC_LOGFR(lvl, mod, fmt, ...) \
|
||||
uc_logf(lvl, mod, 1, __FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef UCORE_MATH_H_
|
||||
#define UCORE_MATH_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint32_t
|
||||
uc_gcd_32(uint32_t a, uint32_t b);
|
||||
|
||||
uint64_t
|
||||
uc_gcd_64(uint64_t a, uint64_t b);
|
||||
|
||||
uint32_t
|
||||
uc_phi_32(uint32_t N);
|
||||
|
||||
uint64_t
|
||||
uc_phi_64(uint64_t N);
|
||||
|
||||
static inline uint32_t
|
||||
uc_nextpow2(uint32_t x)
|
||||
{
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
x++;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef UCORE_MERSENNE_TWISTER_H
|
||||
#define UCORE_MERSENNE_TWISTER_H
|
||||
|
||||
|
||||
/** Context used for the PRNG*/
|
||||
#define MT_RAND_N 624
|
||||
typedef struct {
|
||||
unsigned int x[MT_RAND_N];
|
||||
int i;
|
||||
} MTRand;
|
||||
|
||||
/** Initialize a Mersenne Twister PRNG context.
|
||||
* @param seed Starter seed for the PRNG
|
||||
* @param r context for the PRNG
|
||||
*/
|
||||
void mtsrand(int seed, MTRand *r);
|
||||
|
||||
/** Generate a new random number.
|
||||
* Generated range is 0 to UINT_MAX
|
||||
*
|
||||
* @param r context for the PRNG
|
||||
* @return A pseudo random number
|
||||
*/
|
||||
unsigned int mtrand(MTRand *r);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
#ifndef UCORE_PACK_H_
|
||||
#define UCORE_PACK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef __GNUC__
|
||||
# define UC_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
# define UC_INLINE inline
|
||||
#endif
|
||||
|
||||
/** Functions for serializing/de-serializing integers to and from
|
||||
* byte arrays.
|
||||
* These functions are independant of the host endian. Only
|
||||
* thing to care about is the endian format of the data in
|
||||
* the byte array.
|
||||
*/
|
||||
|
||||
|
||||
/** Serialize a uint16_t to a byte array in little endian format.
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 2.
|
||||
*/
|
||||
static UC_INLINE void uc_pack_16_le(uint16_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v;
|
||||
r[1] = v >> 8;
|
||||
}
|
||||
|
||||
/** De-serialize a uint16_t from a byte array in little endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 2.
|
||||
* @param return The deserialized integer from the byte array.
|
||||
*/
|
||||
static UC_INLINE uint16_t uc_unpack_16_le(const uint8_t *r)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = r[0];
|
||||
v |= r[1] << 8;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint32_t to a 3 byte(24 bits) array in little endian format.
|
||||
* Only the bottom 24 bits of the uint32_t are used.
|
||||
*
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 3.
|
||||
*/
|
||||
static UC_INLINE void uc_pack_24_le(uint32_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v;
|
||||
r[1] = v >> 8;
|
||||
r[2] = v >> 16;
|
||||
}
|
||||
|
||||
/** De-serialize a uint32_t from a 3 byte (24 bit) byte array in little endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 3.
|
||||
* @param return The deserialized integer from the byte array.
|
||||
*/
|
||||
static UC_INLINE uint32_t uc_unpack_24_le(const uint8_t *r)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = r[0];
|
||||
v |= r[1] << 8;
|
||||
v |= r[2] << 16;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint32_t to a byte array in little endian format.
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 4.
|
||||
*/
|
||||
static UC_INLINE void uc_pack_32_le(uint32_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v;
|
||||
r[1] = v >> 8;
|
||||
r[2] = v >> 16;
|
||||
r[3] = v >> 24;
|
||||
}
|
||||
|
||||
/** De-serialize a uint32_t from a byte array in little endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 4.
|
||||
* @param return The deserialized integer from the byte array.
|
||||
*/
|
||||
static UC_INLINE uint32_t uc_unpack_32_le(const uint8_t *r)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = r[0];
|
||||
v |= r[1] << 8;
|
||||
v |= r[2] << 16;
|
||||
v |= r[3] << 24;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint64_t to a byte array in little endian format.
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 8
|
||||
*/
|
||||
static UC_INLINE void uc_pack_64_le(uint64_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v;
|
||||
r[1] = v >> 8;
|
||||
r[2] = v >> 16;
|
||||
r[3] = v >> 24;
|
||||
r[4] = v >> 32ULL;
|
||||
r[5] = v >> 40ULL;
|
||||
r[6] = v >> 48ULL;
|
||||
r[7] = v >> 56ULL;
|
||||
}
|
||||
|
||||
/** De-serialize a uint64_t from a byte array in little endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 8.
|
||||
* @param return The deserialized integer from the byte array
|
||||
*/
|
||||
static UC_INLINE uint64_t uc_unpack_64_le(const uint8_t *r)
|
||||
{
|
||||
uint64_t v;
|
||||
|
||||
v = r[0];
|
||||
v |= r[1] << 8;
|
||||
v |= r[2] << 16;
|
||||
v |= (uint32_t)r[3] << 24;
|
||||
v |= (uint64_t)r[4] << 32ULL;
|
||||
v |= (uint64_t)r[5] << 40ULL;
|
||||
v |= (uint64_t)r[6] << 48ULL;
|
||||
v |= (uint64_t)r[7] << 56ULL;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint16_t to a byte array in big endian format.
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 2.
|
||||
*/
|
||||
static UC_INLINE void uc_pack_16_be(uint32_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v >> 8;
|
||||
r[1] = v;
|
||||
}
|
||||
|
||||
/** De-serialize a uint16_t from a byte array in big endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 2.
|
||||
* @param return The deserialized integer from the byte array
|
||||
*/
|
||||
static UC_INLINE uint16_t uc_unpack_16_be(const uint8_t *r)
|
||||
{
|
||||
uint16_t v;
|
||||
|
||||
v = r[0] << 8;
|
||||
v |= r[1];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint32_t to a 3 byte(24 bits) array in big endian format.
|
||||
* Only the bottom 24 bits of the uint32_t are used.
|
||||
*
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 3.
|
||||
*/
|
||||
static UC_INLINE void uc_pack_24_be(uint32_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v >> 16;
|
||||
r[1] = v >> 8;
|
||||
r[2] = v;
|
||||
}
|
||||
|
||||
/** De-serialize a uint32_t from a 3 byte (24 bit) byte array in big endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 3.
|
||||
* @param return The deserialized integer from the byte array.
|
||||
*/
|
||||
static UC_INLINE uint32_t uc_unpack_24_be(const uint8_t *r)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = r[0] << 16;
|
||||
v |= r[1] << 8;
|
||||
v |= r[2];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint32_t to a byte array in big endian format.
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 4.
|
||||
*/
|
||||
static UC_INLINE void uc_pack_32_be(uint32_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v >> 24;
|
||||
r[1] = v >> 16;
|
||||
r[2] = v >> 8;
|
||||
r[3] = v;
|
||||
}
|
||||
|
||||
/** De-serialize a uint32_t from a byte array in big endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 4.
|
||||
* @param return The deserialized integer from the byte array
|
||||
*/
|
||||
static UC_INLINE uint32_t uc_unpack_32_be(const uint8_t *r)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = r[0] << 24;
|
||||
v |= r[1] << 16;
|
||||
v |= r[2] << 8;
|
||||
v |= r[3];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Serialize a uint16_t to a byte array in big endian format.
|
||||
* @param v The value to serialize
|
||||
* @param r The byte array to place the integer in. Must be at least of size 8
|
||||
*/
|
||||
static UC_INLINE void uc_pack_64_be(uint64_t v, uint8_t *r)
|
||||
{
|
||||
r[0] = v >> 56ULL;
|
||||
r[1] = v >> 48ULL;
|
||||
r[2] = v >> 40ULL;
|
||||
r[3] = v >> 32ULL;
|
||||
r[4] = v >> 24;
|
||||
r[5] = v >> 16;
|
||||
r[6] = v >> 8;
|
||||
r[7] = v;
|
||||
}
|
||||
|
||||
/** De-serialize a uint64_t from a byte array in big endian format.
|
||||
* @param r The byte array to containing the integer in. Must be at least of size 4.
|
||||
* @param return The deserialized integer from the byte array
|
||||
*/
|
||||
static UC_INLINE uint64_t uc_unpack_64_be(const uint8_t *r)
|
||||
{
|
||||
uint64_t v;
|
||||
|
||||
v = (uint64_t)r[0] << 56ULL;
|
||||
v |= (uint64_t)r[1] << 48ULL;
|
||||
v |= (uint64_t)r[2] << 40ULL;
|
||||
v |= (uint64_t)r[3] << 32ULL;
|
||||
v |= (uint32_t)r[4] << 24;
|
||||
v |= r[5] << 16;
|
||||
v |= r[6] << 8;
|
||||
v |= r[7];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef UC_INLINE
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef RBTREE_H_
|
||||
#define RBTREE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum RBColor RBColor;
|
||||
enum RBColor {
|
||||
Red,
|
||||
Black
|
||||
};
|
||||
|
||||
typedef struct RBNode RBNode;
|
||||
struct RBNode {
|
||||
unsigned char color; //Red/Black
|
||||
RBNode *parent;
|
||||
RBNode *right;
|
||||
RBNode *left;
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef struct RBTree RBTree;
|
||||
struct RBTree {
|
||||
RBNode *node;
|
||||
int (*compare)(const void *a, const void *b);
|
||||
};
|
||||
|
||||
void uc_rb_remove(RBTree *root, RBNode *node);
|
||||
RBNode *uc_rb_find(RBTree *root, const void *val);
|
||||
RBNode *uc_rb_insert(RBTree *root, RBNode *child);
|
||||
RBNode *uc_rb_first(const RBTree *root);
|
||||
RBNode *uc_rb_next(RBNode *node);
|
||||
RBNode *uc_rb_last(const RBTree *root);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef UCORE_READ_FILE_H_
|
||||
#define UCORE_READ_FILE_H_y
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/** Read the content of a file.
|
||||
* The returned char* is malloced memory and must be freed by the caller.
|
||||
* The content is terminated by a nul byte, regardless of whether the content
|
||||
* is binary or text. The returned length does not include this nul byte.
|
||||
*
|
||||
* @param file_name name of the file
|
||||
* @param length Returned length of the content read
|
||||
* @param max Fail if the read content length is greater than max.
|
||||
* @return The content read from the file, or NULL if something failed
|
||||
* (inspect errno to see why it failed)
|
||||
*/
|
||||
char *
|
||||
uc_read_file(const char *file_name, size_t *length, size_t max);
|
||||
|
||||
#endif
|
||||
@@ -1,70 +0,0 @@
|
||||
#ifndef SALLOC_H_
|
||||
#define SALLOC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/** Sequntial memory allocator
|
||||
*
|
||||
* Allocates bigger chunks of memory at a time, to save the amount of malloc call,
|
||||
* and enables you to free all that memory in one sweep.
|
||||
*
|
||||
* This means that once allocated, a piece of memory obtained from the
|
||||
* allocator cannot be free'd individually, only the entire SAlloc can be free'd.
|
||||
*
|
||||
* Memory is allocated using the underlying malloc() in chunk sizes.
|
||||
* Once a particular SAlloc has given out all memory in a chunk, a new chunk
|
||||
* is allocated again, using the underlying malloc().
|
||||
*
|
||||
*/
|
||||
|
||||
/** Opaque handle to a SAlloc */
|
||||
typedef struct SAlloc SAlloc;
|
||||
|
||||
/** Create a new SAlloc with the given size for each chunk.
|
||||
* e.g. uc_new_salloc(sizeof(struct Foo) * 1000); will immedeatly
|
||||
* allocate memory to hold 1000 struct Foo's. Once all that memory is
|
||||
* handed out from this SAlloc, another piece of memory is allocaterd
|
||||
* for another 1000 struct Foo's.. All these memory pieces are released
|
||||
* when the uc_free_salloc() is called.
|
||||
*
|
||||
* @param chunksz Size of each piece of memory block allocated.
|
||||
* @return A new handle for a SAlloc, or NULL.
|
||||
*/
|
||||
SAlloc *uc_new_salloc(size_t chunksz);
|
||||
|
||||
/** Allocate memory from a SAlloc.
|
||||
* @param sz size of the memory. This must be <= the chunksz the SAlloc was
|
||||
* created with.
|
||||
* @return The new memory, or NULL if sz > chunksz or an underlying
|
||||
* malloc call fails.
|
||||
*/
|
||||
void * uc_s_alloc(SAlloc *p,size_t sz);
|
||||
|
||||
/** Just like uc_s_alloc, but zero out the memory before returning it.
|
||||
*/
|
||||
void * uc_s_allocz(SAlloc *p,size_t sz);
|
||||
/** Free the SAlloc and all memory associated with this SAlloc.
|
||||
* The SAlloc is not usable any more after this call.
|
||||
*
|
||||
* @param p The SAlloc to free.
|
||||
*/
|
||||
void uc_free_salloc(SAlloc *p);
|
||||
|
||||
/** Reset this SAlloc, effectivly releasing all the memory obtained.
|
||||
* The SAlloc is still usable after this call.
|
||||
* The actual memory previously allocated from this SAlloc is cached,
|
||||
* and will be reused by subsequent uc_s_alloc calls.
|
||||
*
|
||||
* @param p The SAlloc to reset.
|
||||
*/
|
||||
void uc_reset_salloc(SAlloc *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef SEQ_H_
|
||||
#define SEQ_H_
|
||||
#include <stdint.h>
|
||||
|
||||
// Check if a is before b, taking care of wrap arounds
|
||||
static inline int seq_before(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (int32_t)(a - b) < 0;
|
||||
}
|
||||
|
||||
// check if a is before b, taking care of wrap arounds
|
||||
#define seq_after(a, b) before(b, a)
|
||||
|
||||
//check if a is between b or c
|
||||
static inline int seqbetween(uint32_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
return c - b >= a - b;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
#ifndef UCORE_STRING_H_
|
||||
#define UCORE_STRING_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
size_t
|
||||
uc_base64_enc(const unsigned char *data,size_t len,unsigned char *result);
|
||||
size_t
|
||||
uc_base64_dec(const unsigned char *data, size_t len, unsigned char *result);
|
||||
|
||||
char*
|
||||
uc_hex_encode(const uint8_t *in, size_t len, char *out);
|
||||
uint8_t*
|
||||
uc_hex_decode(const char *in, size_t maxlen,uint8_t *out);
|
||||
char*
|
||||
uc_hex_encode_delim(const uint8_t *in, size_t inlen, char *out, int outlen, char *delim);
|
||||
|
||||
void
|
||||
uc_str_tolower(char *s);
|
||||
void
|
||||
uc_str_toupper(char *s);
|
||||
|
||||
#define UC_BCD_LEN(ascii_len) ((ascii_len) / 2 + ((ascii_len) % 2))
|
||||
#define UC_ASCII_LEN(bcd_len) ((bcd_len) * 2 + 1)
|
||||
|
||||
size_t
|
||||
uc_ascii2bcd(const char *ascii, unsigned char *bcdout, unsigned char filler);
|
||||
size_t
|
||||
uc_bcd2ascii(const unsigned char *bcd, size_t bcdlen, char *asciiout);
|
||||
|
||||
char*
|
||||
uc_sprintb(char *result, unsigned int value);
|
||||
char*
|
||||
uc_sprintbc(char *result, unsigned char value);
|
||||
char*
|
||||
uc_sprintbll(char *result, unsigned long long value);
|
||||
char*
|
||||
uc_sprintbs(char *result, unsigned short value);
|
||||
|
||||
int
|
||||
getfields(char *str, char **args, int max, int mflag, const char *set);
|
||||
|
||||
//ocnvert bytes to a human representable test, (i.e. 12kB, 160 MB 1.78 GB etc.
|
||||
///result should be at least of size 12,
|
||||
///returns the result argument
|
||||
char *
|
||||
uc_human_bytesz(uint64_t bytes, char *result, size_t result_len);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,248 +0,0 @@
|
||||
#ifndef _THREADQUEUE_H_
|
||||
#define _THREADQUEUE_H_ 1
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**
|
||||
* @defgroup ThreadQueue ThreadQueue
|
||||
* @{
|
||||
*
|
||||
* Little API for waitable queues, typically used for passing messages
|
||||
* between threads.
|
||||
*
|
||||
* @author Nils O. Selåsdal <NOS@Utel.no>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A thread message used to add and retrieve messages
|
||||
* from in a queue.
|
||||
* An application must not touch this struct
|
||||
* when a message is present (i.e. it has been added
|
||||
* to a queue, but not retrieved yet) in a queue.
|
||||
*
|
||||
*/
|
||||
struct uc_threadmsg{
|
||||
/**
|
||||
* A message type the application can use to
|
||||
* discriminate different messages.
|
||||
* A negative value will cause a uc_threadmsg to
|
||||
* be added to the head of a queue.
|
||||
*/
|
||||
long msgtype;
|
||||
|
||||
/**
|
||||
* Internal pointer used by the uc_thread_queue.
|
||||
* Applications must not use this member.
|
||||
*/
|
||||
struct uc_threadmsg *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function for the walk and destroy functions.
|
||||
*/
|
||||
typedef void (*uc_thread_queue_walk_func) (struct uc_threadmsg *msg);
|
||||
|
||||
|
||||
/**
|
||||
* A ThreadQueue
|
||||
*
|
||||
*
|
||||
* You should threat this struct as opaque never ever access any of
|
||||
* the variables in this struct.
|
||||
* You have been warned.
|
||||
*
|
||||
* The uc_thread_queue_ functions only deal with struct uc_threadmsg
|
||||
* structs.
|
||||
* In order for the message passing to be useful, more data needs to be
|
||||
* associated with a message, it's up to the application to manage this.
|
||||
* One way is to e.g. add the struct uc_threadmsg as the first member
|
||||
* of a larger struct, and recover the larger struct after getting a
|
||||
* struct uc_threadmsg out of the queue. e.g.
|
||||
*
|
||||
* @code
|
||||
* struct my_msg {
|
||||
* struct uc_threadmsg tmsg;
|
||||
* int foo;
|
||||
* char bar[32];
|
||||
* };
|
||||
*
|
||||
* struct my_msg *msg = malloc(sizeof *msg);
|
||||
* msg->tmsg.msgtype = MSGTYP1;
|
||||
* ...
|
||||
* uc_thread_queue_add(queue, &msg->tmsg);
|
||||
*
|
||||
* The receiver end does e.g.
|
||||
*
|
||||
* struct uc_threadmsg *tmsg;
|
||||
* uc_thread_queue_get(queue, NULL, &tmsg);
|
||||
* switch(tmsg->msgtype) {
|
||||
* case MYMSG1; {
|
||||
* struct my_msg *msg = (struct my_msg*)tmsg;
|
||||
* ...
|
||||
* free(msg);
|
||||
* break
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct uc_threadqueue {
|
||||
/**
|
||||
* Number of elements in the queue.
|
||||
* Use #threadqueue_length to read it.
|
||||
*/
|
||||
long num_elements;
|
||||
|
||||
/** Max number of elements this queue will hold */
|
||||
long max_elements;
|
||||
/**
|
||||
* Mutex for the queue.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
/**
|
||||
* Condition variable for readers on the queue.
|
||||
*/
|
||||
pthread_cond_t read_cond;
|
||||
/**
|
||||
* Condition variable for writers on the queue (if the queue is full).
|
||||
*/
|
||||
pthread_cond_t write_cond;
|
||||
/**
|
||||
* Number of threads blocking on writing to the queue
|
||||
*/
|
||||
long num_read_waiters;
|
||||
/**
|
||||
* Number of threads blocking on reading from the queue
|
||||
*/
|
||||
long num_write_waiters;
|
||||
|
||||
/**
|
||||
* Internal pointers for the messages in the queue.
|
||||
*/
|
||||
struct uc_threadmsg *first,**last;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a queue.
|
||||
*
|
||||
* thread_queue_init initializes a new threadqueue. A new queue must always
|
||||
* be initialized before it is used.
|
||||
* A max number of elements the queue will hold must be given.
|
||||
* Adding more elements than a queue will hold will e.g. cause
|
||||
* uc_thread_queue_add to block until space becomes available.
|
||||
*
|
||||
* @param queue Pointer to the queue that should be initialized
|
||||
* @param max_elements Max number of elements this queue can hold.
|
||||
*
|
||||
* @return 0 on success EINVAL if queue is NULL or max_elements <= 0, or
|
||||
* another errno value if pthread_ functions fails
|
||||
*/
|
||||
int uc_thread_queue_init(struct uc_threadqueue *queue, long max_elements);
|
||||
|
||||
/**
|
||||
* Adds a message to a queue
|
||||
*
|
||||
* thread_queue_add adds a "message" to the specified queue.
|
||||
* It is up to the application to manage the data and memory indicated by the
|
||||
* struct uc_threadmsg.
|
||||
* The struct uc_threadmsg is assumed to be an intrusive pointer,
|
||||
* e.g. it can be the first member of a larger struct actually containing the
|
||||
* data to be passed over.
|
||||
*
|
||||
* Nothing is copied so the application must keep track on (de)allocation of the pointers.
|
||||
* A message type can also be also specified, to e.g. help discriminate
|
||||
* messages when messages are received.
|
||||
*
|
||||
* If the message_type member of @msg is negative, the message is added to
|
||||
* the front of the queue, i.e. it can be considered a "priority" message.
|
||||
*
|
||||
* @param queue Pointer to the queue on where the message should be added.
|
||||
* @param data the "message".
|
||||
* @return 0 on succes ENOMEM if out of memory EINVAL if queue is NULL, or other
|
||||
* errno values if pthread functions failed.
|
||||
*/
|
||||
int uc_thread_queue_add(struct uc_threadqueue *queue, struct uc_threadmsg *msg);
|
||||
|
||||
/**
|
||||
* Gets a message from a queue
|
||||
*
|
||||
* thread_queue_get gets a message from the specified queue, it will block
|
||||
* the caling thread untill a message arrives, or the (optional) timeout occurs.
|
||||
* If timeout is NULL, there will be no timeout, and thread_queue_get will wait
|
||||
* untill a message arrives.
|
||||
*
|
||||
* struct timespec is defined as:
|
||||
* @code
|
||||
* struct timespec {
|
||||
* long tv_sec; // seconds
|
||||
* long tv_nsec; // nanoseconds
|
||||
* };
|
||||
* @endcode
|
||||
*
|
||||
* @param queue Pointer to the queue to wait on for a message.
|
||||
* @param timeout timeout on how long to wait on a message, or NULL for no timeout
|
||||
* @param msg pointer where the uc_threadmsg* is stored
|
||||
*
|
||||
* @return 0 on success EINVAL if queue is NULL ETIMEDOUT if timeout occurs
|
||||
*/
|
||||
int uc_thread_queue_get(struct uc_threadqueue *queue, const struct timespec *timeout, struct uc_threadmsg **msg);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the length of a queue
|
||||
*
|
||||
* threadqueue_length returns the number of messages waiting in the queue
|
||||
*
|
||||
* @param queue Pointer to the queue for which to get the length
|
||||
* @return the length(number of pending messages) in the queue
|
||||
*/
|
||||
long uc_thread_queue_length( struct uc_threadqueue *queue );
|
||||
|
||||
/**
|
||||
* Destroy the queue.
|
||||
*
|
||||
* If free_func is != NULL, free_func will be called for every item, allowing you to free
|
||||
* the item.
|
||||
* You cannot call this if there are someone currently adding or getting messages
|
||||
* from the queue.
|
||||
* After a queue have been cleaned, it cannot be used again untill #thread_queue_init
|
||||
* has been called on the queue.
|
||||
*
|
||||
* @param queue Pointer to the queue that should be cleaned
|
||||
* @param free_func pointer to function that will be called for each item.
|
||||
* The function must not in anyway interact with the queue.
|
||||
* @return 0 on success EINVAL if queue is NULL EBUSY if someone is holding any locks on the queue
|
||||
*/
|
||||
int uc_thread_queue_destroy(struct uc_threadqueue *queue, uc_thread_queue_walk_func free_func);
|
||||
|
||||
/**
|
||||
* Walk the elements of the queue, intended for debugging
|
||||
*
|
||||
* The supplied function will be called for each item in the queue, internal queue
|
||||
* locks are held while the function is called, so the supplied function must not
|
||||
* interact with the queue, else deadlock occors.
|
||||
*
|
||||
* @param queue Pointer to the queue to walk
|
||||
* @param free_func pointer to function that will be called for each item.
|
||||
* The function must not in anyway interact with the queue.
|
||||
* @return 0 on success
|
||||
*/
|
||||
int uc_thread_queue_walk(struct uc_threadqueue *queue, uc_thread_queue_walk_func walk_func);
|
||||
|
||||
/**
|
||||
* @}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
#ifndef UCORE_TIMERS_H_
|
||||
#define UCORE_TIMERS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/time.h>
|
||||
#include "ucore_rbtree.h"
|
||||
|
||||
|
||||
struct UCTimer;
|
||||
struct UCTimers;
|
||||
|
||||
//timer states
|
||||
enum {
|
||||
//not running
|
||||
UC_TIMER_INACTIVE = 0,
|
||||
//running
|
||||
UC_TIMER_ACTIVE = 1,
|
||||
//running and pending to be fired in this run of uc_timers_run
|
||||
UC_TIMER_PENDING = 2
|
||||
};
|
||||
|
||||
typedef void (*uc_timer_cb)(struct UCTimers *timers, struct UCTimer *timer);
|
||||
struct UCTimer {
|
||||
//internal members
|
||||
RBNode rb_node; //the RBNode will hold a data pointer to the
|
||||
//the UCTimer it's a member of. We might get rid of that member, and use CONTAINER_OF
|
||||
//to find the UCTimer from a RBNode
|
||||
//
|
||||
//absolute time when the timer should be fired
|
||||
struct timeval timeout;
|
||||
size_t seq; //needed to keep timeout unique
|
||||
//as the rbtree can only handle unique values
|
||||
unsigned char state;
|
||||
TAILQ_ENTRY(UCTimer) ready_entry; //entry in ready_list in UCTimers
|
||||
|
||||
//callback function
|
||||
uc_timer_cb callback;
|
||||
|
||||
//user data for the callback
|
||||
void *cookie_ptr;
|
||||
int cookie_int;
|
||||
int cookie_int2;
|
||||
};
|
||||
|
||||
|
||||
struct UCTimers {
|
||||
RBTree timers;
|
||||
size_t seq; //used to generate unique timers
|
||||
TAILQ_HEAD(, UCTimer) ready_list; //pending timers to be fired while inside uc_timers_run
|
||||
};
|
||||
|
||||
|
||||
void uc_timer_remove(struct UCTimers *timers, struct UCTimer *timer);
|
||||
void uc_timers_init(struct UCTimers *t);
|
||||
void uc_timer_add(struct UCTimers *timers, struct UCTimer *timer, int sec, int usec);
|
||||
void uc_timer_remove(struct UCTimers *timers, struct UCTimer *timer);
|
||||
int uc_timers_first(const struct UCTimers *timers, struct timeval *first);
|
||||
size_t uc_timer_count(const struct UCTimers *timers);
|
||||
int uc_timer_running(const struct UCTimer *timer);
|
||||
int uc_timers_run(struct UCTimers *timers, const struct timeval *now);
|
||||
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef UCORE_UTILS_H_
|
||||
#define UCORE_UTILS_H_
|
||||
#include <stddef.h>
|
||||
|
||||
//Gnerate a compiler error if the compile time
|
||||
//constant expression fails
|
||||
#define STATIC_ASSERT(expr) \
|
||||
do { \
|
||||
enum { assert_static__ = 1/(expr) }; \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TRACEF(fmt, ...)\
|
||||
do { \
|
||||
fprintf(stderr, "%s:%s(%d)" fmt, __FILE__, __FUNCTION__, __LINE,__VA_ARGS__);\
|
||||
} while(0)
|
||||
#else
|
||||
#define TRACEF(fmt, ...)
|
||||
#endif
|
||||
|
||||
//MAX of a and b
|
||||
#define UC_MAX(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
//min of a and b
|
||||
#define UC_MIN(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
|
||||
|
||||
//given 'ptr' as a pointer to a struct 'member',
|
||||
//find the struct that ptr is the member of, where
|
||||
//'type' is the type of the containing struct
|
||||
//e.g.
|
||||
//struct foo {
|
||||
// int i;
|
||||
// struct bar zap;
|
||||
//};
|
||||
// ...
|
||||
//struct bar *p = ..; //the local p is a pointer to
|
||||
//a 'zap' member inside a struct foo.
|
||||
//give us the struct foo*:
|
||||
//struct foo *f = CONTAINER_OF(p, struct foo, zap);
|
||||
#define CONTAINER_OF(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type, member) ); })
|
||||
|
||||
#define UC_ALIGN(val,align) (((val)+(align)-1UL)&~((align)-1UL))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
const int ucore_version_major = @version_major@;
|
||||
const int ucore_version_minor = @version_minor@;
|
||||
const int ucore_version_patch = @version_patch@;
|
||||
|
||||
const char ucore_version_str[] = "@version_major@.@version_minor@.@version_patch@.@version_revision@";
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#ifndef UCORE_VERSION_H_
|
||||
#define UCORE_VERSION_H_
|
||||
/**
|
||||
* @mainpage
|
||||
* @htmlonly
|
||||
* <pre>
|
||||
* Copyright (c) 2002-2012 Nils O. Selåsdal <NOS@Utel.no>.
|
||||
* All rights reserved, all wrongs reversed.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
* </pre>
|
||||
* @endhtmlonly
|
||||
*/
|
||||
|
||||
/* Major version of the ucore library*/
|
||||
extern const int ucore_version_major;
|
||||
/* Minor version of the ucore library*/
|
||||
extern const int ucore_version_minor;
|
||||
/* Patch version of the ucore library*/
|
||||
extern const int ucore_version_patch;
|
||||
|
||||
/** The version number as a string.
|
||||
* Might contain non-numeric suffix indicating
|
||||
* e.g. development version or similar*/
|
||||
extern const char ucore_version_str[];
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user