Merge branch 'dev'
This commit is contained in:
+1
-1
@@ -73,7 +73,7 @@ env.SConsignFile()
|
|||||||
|
|
||||||
subdirs = [
|
subdirs = [
|
||||||
'src',
|
'src',
|
||||||
'include',
|
'include/ucore',
|
||||||
'test',
|
'test',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "iomux_impl.h"
|
#include <ucore/iomux_impl.h>
|
||||||
|
|
||||||
//epoll (linux specific) IO mux.
|
//epoll (linux specific) IO mux.
|
||||||
//We stuff the struct IOMuxFD pointer in the event.data.ptr slot
|
//We stuff the struct IOMuxFD pointer in the event.data.ptr slot
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "iomux_impl.h"
|
#include <ucore/iomux_impl.h>
|
||||||
|
|
||||||
|
|
||||||
//dispatchers for the IOMux implementations */
|
//dispatchers for the IOMux implementations */
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "iomux_impl.h"
|
#include <ucore/iomux_impl.h>
|
||||||
#include "ucore_utils.h"
|
#include <ucore/ucore_utils.h>
|
||||||
|
|
||||||
#define IOMUX_GROW_CHUNK (32)
|
#define IOMUX_GROW_CHUNK (32)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
static const uint8_t basecode[128] =
|
static const uint8_t basecode[128] =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
static const char basecode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
static const char basecode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
#define PAD '='
|
#define PAD '='
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
uc_ascii2bcd(const char *ascii, unsigned char *bcdout, unsigned char filler)
|
uc_ascii2bcd(const char *ascii, unsigned char *bcdout, unsigned char filler)
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "ucore_bitvec.h"
|
#include <ucore/ucore_bitvec.h>
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define likely(expr) __builtin_expect((expr), 1)
|
#define likely(expr) __builtin_expect((expr), 1)
|
||||||
|
|||||||
+44
-3
@@ -1,6 +1,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ucore_buffer.h"
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ucore/ucore_buffer.h>
|
||||||
|
|
||||||
GBuf*
|
GBuf*
|
||||||
uc_new_gbuf(size_t initsz)
|
uc_new_gbuf(size_t initsz)
|
||||||
@@ -43,7 +45,6 @@ uc_gbuf_unref(GBuf *buf)
|
|||||||
int
|
int
|
||||||
uc_gbuf_append(GBuf *buf,void *data,size_t len)
|
uc_gbuf_append(GBuf *buf,void *data,size_t len)
|
||||||
{
|
{
|
||||||
unsigned char *d = data;
|
|
||||||
unsigned char *gbuf;
|
unsigned char *gbuf;
|
||||||
|
|
||||||
if(buf->len - buf->used < len)
|
if(buf->len - buf->used < len)
|
||||||
@@ -51,12 +52,52 @@ uc_gbuf_append(GBuf *buf,void *data,size_t len)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
gbuf = buf->buf;
|
gbuf = buf->buf;
|
||||||
memcpy(gbuf + buf->used,d,len);
|
memcpy(gbuf + buf->used, data, len);
|
||||||
buf->used += len;
|
buf->used += len;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uc_gbuf_printf(GBuf *buf, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_list apc;
|
||||||
|
int rc = 0;
|
||||||
|
int remaining;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
//increment buffer if snprintf indicates the results were truncated
|
||||||
|
do {
|
||||||
|
|
||||||
|
va_copy(apc, ap);
|
||||||
|
char *gbuf;
|
||||||
|
|
||||||
|
remaining = uc_gbuf_remaining(buf);
|
||||||
|
if(rc >= remaining) {
|
||||||
|
if(uc_gbuf_grow(buf, buf->len + (rc - remaining) + 1)) {
|
||||||
|
rc = -1;
|
||||||
|
va_end(apc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
remaining = uc_gbuf_remaining(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
gbuf = buf->buf;
|
||||||
|
|
||||||
|
rc = vsnprintf(gbuf + buf->used, remaining, fmt, apc);
|
||||||
|
va_end(apc);
|
||||||
|
|
||||||
|
} while(rc >= remaining);
|
||||||
|
|
||||||
|
if(rc > 0)
|
||||||
|
buf->used += rc;
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
uc_gbuf_grow(GBuf *buf, size_t addlen)
|
uc_gbuf_grow(GBuf *buf, size_t addlen)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
static const uint32_t crc32_table[256] = {
|
static const uint32_t crc32_table[256] = {
|
||||||
0x0,0x4C11DB7,0x9823B6E,0xD4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,0x2608EDB8,0x22C9F00F,0x2F8AD6D6,
|
0x0,0x4C11DB7,0x9823B6E,0xD4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,0x2608EDB8,0x22C9F00F,0x2F8AD6D6,
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
uc_djbhash(const char *str)
|
uc_djbhash(const char *str)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
uc_elfhash(const char *str, uint32_t len)
|
uc_elfhash(const char *str, uint32_t len)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_math.h"
|
#include <ucore/ucore_math.h>
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
uc_gcd_32(uint32_t a, uint32_t b)
|
uc_gcd_32(uint32_t a, uint32_t b)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_math.h"
|
#include <ucore/ucore_math.h>
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
uc_gcd_64(uint64_t a, uint64_t b)
|
uc_gcd_64(uint64_t a, uint64_t b)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
getfields(char *str, char **args, int max, int mflag, const char *set)
|
getfields(char *str, char **args, int max, int mflag, const char *set)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
uc_hash64shift(uint64_t key)
|
uc_hash64shift(uint64_t key)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
uc_hashuint(uint32_t a)
|
uc_hashuint(uint32_t a)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ucore_heapsort.h"
|
#include <ucore/ucore_heapsort.h>
|
||||||
|
|
||||||
static void
|
static void
|
||||||
uc_sift(unsigned char *base, size_t start, size_t count, size_t width,
|
uc_sift(unsigned char *base, size_t start, size_t count, size_t width,
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
static const char hx_chars[] = "0123456789ABCDEF" ;
|
static const char hx_chars[] = "0123456789ABCDEF" ;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
char *
|
char *
|
||||||
uc_human_bytesz(uint64_t bytes, char *result, size_t result_len)
|
uc_human_bytesz(uint64_t bytes, char *result, size_t result_len)
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include "ucore_logging.h"
|
#include <ucore/ucore_logging.h>
|
||||||
|
|
||||||
|
|
||||||
struct uc_log_destination {
|
struct uc_log_destination {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*Copyright (c) 2004 Nils O. Selåsdal <NOS {on} Utel {dot} no> */
|
/*Copyright (c) 2004 Nils O. Selåsdal <NOS {on} Utel {dot} no> */
|
||||||
/*Straight forward attempt at a Mersenne Twister PRNG */
|
/*Straight forward attempt at a Mersenne Twister PRNG */
|
||||||
|
|
||||||
#include "ucore_mersenne_twister.h"
|
#include <ucore/ucore_mersenne_twister.h>
|
||||||
|
|
||||||
|
|
||||||
/*Beware , pollution. But the names are from the spec */
|
/*Beware , pollution. But the names are from the spec */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
// 'm' and 'r' are mixing constants generated offline.
|
// 'm' and 'r' are mixing constants generated offline.
|
||||||
// They're not really 'magic', they just happen to work well.
|
// They're not really 'magic', they just happen to work well.
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_math.h"
|
#include <ucore/ucore_math.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Euler's Totient Function is denoted by the Greek letter phi, and is defined as follows:
|
Euler's Totient Function is denoted by the Greek letter phi, and is defined as follows:
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_math.h"
|
#include <ucore/ucore_math.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Euler's Totient Function is denoted by the Greek letter phi, and is defined as follows:
|
Euler's Totient Function is denoted by the Greek letter phi, and is defined as follows:
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
uc_pjwhash(const char *str,size_t len)
|
uc_pjwhash(const char *str,size_t len)
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "ucore_rbtree.h"
|
#include <ucore/ucore_rbtree.h>
|
||||||
//modified from generated code of tree.h
|
//modified from generated code of tree.h
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "ucore_read_file.h"
|
#include <ucore/ucore_read_file.h>
|
||||||
|
|
||||||
#define CHUNK_SZ 1024
|
#define CHUNK_SZ 1024
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "ucore_salloc.h"
|
#include <ucore/ucore_salloc.h>
|
||||||
|
|
||||||
typedef struct Chunk Chunk;
|
typedef struct Chunk Chunk;
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_hash.h"
|
#include <ucore/ucore_hash.h>
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
uc_sax_hash(void *key, size_t len)
|
uc_sax_hash(void *key, size_t len)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
|
|
||||||
char*
|
char*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
char*
|
char*
|
||||||
uc_sprintbc(char *result, unsigned char value)
|
uc_sprintbc(char *result, unsigned char value)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
char*
|
char*
|
||||||
uc_sprintbll(char *result, unsigned long long value)
|
uc_sprintbll(char *result, unsigned long long value)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
char*
|
char*
|
||||||
uc_sprintbs(char *result, unsigned short value)
|
uc_sprintbs(char *result, unsigned short value)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
uc_str_tolower(char *s)
|
uc_str_tolower(char *s)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
uc_str_toupper(char *s)
|
uc_str_toupper(char *s)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "ucore_threadqueue.h"
|
#include <ucore/ucore_threadqueue.h>
|
||||||
|
|
||||||
|
|
||||||
int uc_thread_queue_init(struct uc_threadqueue *queue, long max_elements)
|
int uc_thread_queue_init(struct uc_threadqueue *queue, long max_elements)
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "ucore_timers.h"
|
#include <ucore/ucore_timers.h>
|
||||||
|
|
||||||
|
|
||||||
static int timers_cmp(const void *a_, const void *b_)
|
static int timers_cmp(const void *a_, const void *b_)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#include "ucore_backtrace.h"
|
#include <ucore/ucore_backtrace.h>
|
||||||
|
|
||||||
//note , compiling this without -rdynamic does not
|
//note , compiling this without -rdynamic does not
|
||||||
//translate addresses to function names. Use the addr2line in that case
|
//translate addresses to function names. Use the addr2line in that case
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "iomux.h"
|
#include <ucore/iomux.h>
|
||||||
|
|
||||||
extern struct IOMuxFD s_fd;
|
extern struct IOMuxFD s_fd;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "iomux.h"
|
#include <ucore/iomux.h>
|
||||||
|
|
||||||
extern struct IOMuxFD s_fd;
|
extern struct IOMuxFD s_fd;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "iomux.h"
|
#include <ucore/iomux.h>
|
||||||
|
|
||||||
|
|
||||||
#define BUFLEN (4098*66)
|
#define BUFLEN (4098*66)
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
#include "ucore_logging.h"
|
#include <ucore/ucore_logging.h>
|
||||||
#include "ucore_utils.h"
|
#include <ucore/ucore_utils.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
enum {
|
enum {
|
||||||
MAIN,
|
MAIN,
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ucore_salloc.h"
|
#include <ucore/ucore_salloc.h>
|
||||||
|
|
||||||
// Intended to be run under valgrind. Should show no errors
|
// Intended to be run under valgrind. Should show no errors
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "ucore_seq.h"
|
#include <ucore/ucore_seq.h>
|
||||||
|
|
||||||
|
|
||||||
void check_before(uint32_t a, uint32_t b)
|
void check_before(uint32_t a, uint32_t b)
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
|
|
||||||
START_TEST (test_2bcd_1234567890)
|
START_TEST (test_2bcd_1234567890)
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include "ucore_bitvec.h"
|
#include <ucore/ucore_bitvec.h>
|
||||||
|
|
||||||
|
|
||||||
START_TEST (test_bitvec_1)
|
START_TEST (test_bitvec_1)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include "ucore_utils.h"
|
#include <ucore/ucore_utils.h>
|
||||||
|
|
||||||
|
|
||||||
struct Inner {
|
struct Inner {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ucore_string.h"
|
#include <ucore/ucore_string.h>
|
||||||
|
|
||||||
|
|
||||||
START_TEST (test_uc_hex_encode_1)
|
START_TEST (test_uc_hex_encode_1)
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "ucore_logging.h"
|
#include <ucore/ucore_logging.h>
|
||||||
|
|
||||||
#define FILE_NAME "logfile_test.log"
|
#define FILE_NAME "logfile_test.log"
|
||||||
#define SUBDIR "log_subdir"
|
#define SUBDIR "log_subdir"
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include "ucore_pack.h"
|
#include <ucore/ucore_pack.h>
|
||||||
|
|
||||||
|
|
||||||
START_TEST (test_pack16_le_1)
|
START_TEST (test_pack16_le_1)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "ucore_read_file.h"
|
#include <ucore/ucore_read_file.h>
|
||||||
|
|
||||||
|
|
||||||
START_TEST (test_read_file_non_existing_file)
|
START_TEST (test_read_file_non_existing_file)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ucore_threadqueue.h"
|
#include <ucore/ucore_threadqueue.h>
|
||||||
|
|
||||||
struct thr_msg {
|
struct thr_msg {
|
||||||
struct uc_threadmsg msg;
|
struct uc_threadmsg msg;
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ucore_threadqueue.h"
|
#include <ucore/ucore_threadqueue.h>
|
||||||
|
|
||||||
struct uc_threadqueue queue;
|
struct uc_threadqueue queue;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user