Merge branch 'dev'
This commit is contained in:
@@ -0,0 +1,162 @@
|
|||||||
|
#ifndef UC_DSTR_H_
|
||||||
|
#define UC_DSTR_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** A managed C-string, using dynalically allocated memory for the string.
|
||||||
|
*
|
||||||
|
* The .str member might not always be nul terminated,
|
||||||
|
* Normally, use uc_dstr_str() to retreive the managed string
|
||||||
|
* instead of accessing ->str directly.
|
||||||
|
*
|
||||||
|
* Normally, let the DSTR manage the nul terminator as manually adding
|
||||||
|
* a nul byte and potintially adding more data to the DStr would append
|
||||||
|
* it after that nul terminator.
|
||||||
|
*/
|
||||||
|
struct DStr {
|
||||||
|
/** Length of the managed string.*/
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
//internal fields:
|
||||||
|
size_t allocated;
|
||||||
|
char *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UC_DSTR_STATIC_INIT {0, 0, NULL}
|
||||||
|
|
||||||
|
/** Initialize a DStr.
|
||||||
|
* Note that str->str will be NULL after initialization.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void uc_dstr_init(struct DStr *str);
|
||||||
|
|
||||||
|
/** Destroy/free the string.
|
||||||
|
* (Frees str->str, not str itself)
|
||||||
|
*/
|
||||||
|
void uc_dstr_destroy(struct DStr *str);
|
||||||
|
|
||||||
|
/** Copy a DStr
|
||||||
|
*
|
||||||
|
* @param dest destination string to copy to, must not contain an existing string
|
||||||
|
* @param src DStr to copy
|
||||||
|
*
|
||||||
|
* @return 0 if success, != 0 if allocation fails
|
||||||
|
*/
|
||||||
|
int uc_dstr_copy(struct DStr *dest, const struct DStr *src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the available/unused tail bytes in the string.
|
||||||
|
*/
|
||||||
|
size_t uc_dstr_available(const struct DStr *str);
|
||||||
|
|
||||||
|
/** Ensure the DStr have room for least 'len' bytes,
|
||||||
|
* allocating room if needed.
|
||||||
|
*
|
||||||
|
* This includes the length of the existing string,
|
||||||
|
* to ensure e.g an additional 10 bytes can be appended,
|
||||||
|
* one would do uc_dstr_ensure(str, str->len + 10)
|
||||||
|
*
|
||||||
|
* @return 0 on success (!= 0 if an allocation fail)
|
||||||
|
*/
|
||||||
|
int uc_dstr_ensure(struct DStr *str, size_t total);
|
||||||
|
|
||||||
|
/** Reset the DStr, setting its length to 0
|
||||||
|
*/
|
||||||
|
void uc_dstr_reset(struct DStr *str);
|
||||||
|
|
||||||
|
/** nul terminate the DStr */
|
||||||
|
void uc_dstr_terminate(struct DStr *str);
|
||||||
|
|
||||||
|
/** Retreive the managed string, the returned string
|
||||||
|
* is always nul terminated. The DStr will still be managing
|
||||||
|
* the returned char *.
|
||||||
|
*/
|
||||||
|
char *uc_dstr_str(struct DStr *str);
|
||||||
|
|
||||||
|
/** Reserve len bytes for appending to the dstr
|
||||||
|
* you must fill in a string in the 0-len range of
|
||||||
|
* the returned pointer.
|
||||||
|
*
|
||||||
|
* @param len bytes to reseve
|
||||||
|
* @return poiinter to the start of the data to append
|
||||||
|
*/
|
||||||
|
char *uc_dstr_put(struct DStr *str, size_t len);
|
||||||
|
|
||||||
|
/** Append a string, filtering out characters.
|
||||||
|
* e.g. pass in the ctype.h isdigit as the is_x function
|
||||||
|
* to append only the digits in the supplied string.
|
||||||
|
*
|
||||||
|
* @param s string to append
|
||||||
|
* @param is_x ctype.h compatible function to use as a filter.
|
||||||
|
* @return number of chars appended
|
||||||
|
*/
|
||||||
|
size_t uc_dstr_put_str_filter(struct DStr *str, const char *s, int (*is_x)(int c));
|
||||||
|
|
||||||
|
/* Append a string of the give size.
|
||||||
|
* (The nul terminator is not appended)
|
||||||
|
*
|
||||||
|
* @param s string to append
|
||||||
|
* @param len bytes to append (not including the nul terminator)
|
||||||
|
* @return 0 on success (!= 0 if an allocation fail)
|
||||||
|
*/
|
||||||
|
int uc_dstr_put_str_sz(struct DStr *str, const char *s, size_t len);
|
||||||
|
|
||||||
|
/* Append a string.
|
||||||
|
* (The nul terminator is not appended)
|
||||||
|
*
|
||||||
|
* @return 0 on success (!= 0 if an allocation fail)
|
||||||
|
*/
|
||||||
|
int uc_dstr_put_str(struct DStr *str, const char *s);
|
||||||
|
|
||||||
|
/* Append a single char.
|
||||||
|
*
|
||||||
|
* @return 0 on success (!= 0 if an allocation fail)
|
||||||
|
*/
|
||||||
|
int uc_dstr_put_char(struct DStr *str, char c);
|
||||||
|
|
||||||
|
/* Make the DStr take ownership of the given dynamically allocated string.
|
||||||
|
* Any existing string in the DStr is freed.
|
||||||
|
*/
|
||||||
|
void uc_dstr_own(struct DStr *str, char *s);
|
||||||
|
|
||||||
|
/** Release the managed string.
|
||||||
|
* The caller is now responsible for managing/free'ing the returned string.
|
||||||
|
* The DStr is considered empty afterwards.
|
||||||
|
*
|
||||||
|
* @return The dynamically allocated string that was managed.
|
||||||
|
*/
|
||||||
|
char *uc_dstr_steal(struct DStr *str);
|
||||||
|
|
||||||
|
/** Swap the A and B DStr */
|
||||||
|
void uc_str_swap(struct DStr *a, struct DStr *b);
|
||||||
|
|
||||||
|
/** Replace all occurences in the DStr
|
||||||
|
* (This may be used to replace any embedded nul bytes too)
|
||||||
|
*
|
||||||
|
* @param f char to find
|
||||||
|
* @param r char to replace with
|
||||||
|
*/
|
||||||
|
size_t uc_dstr_replace(struct DStr *str, char f, char r);
|
||||||
|
|
||||||
|
/** Remove leading and trailing spaces in the DStr
|
||||||
|
* Spaces are the ascii ones: " \t\r\v\t\n"
|
||||||
|
*/
|
||||||
|
void uc_dstr_trim(struct DStr *str);
|
||||||
|
|
||||||
|
/** Append formatted string (just as sprintf)*/
|
||||||
|
int uc_dstr_sprintf(struct DStr *str, const char *fmt, ...) __attribute__((format(printf,2,3)));
|
||||||
|
|
||||||
|
/** va_list variant */
|
||||||
|
int uc_dstr_vsprintf(struct DStr *str, const char *fmt, va_list ap_)__attribute__((format(printf,2,0)));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef UC_HEAPSORT_H_
|
||||||
|
#define UC_HEAPSORT_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
///compare function. Needs only to return < 0 if
|
||||||
|
//a is less tan b
|
||||||
|
typedef int (*uc_hs_cmp)(const void *a, const void *b, void *cookie);
|
||||||
|
//swap function, must swap around element a and b
|
||||||
|
typedef void (*uc_hs_swp)(void *a, void *b);
|
||||||
|
|
||||||
|
/** Sort an array.
|
||||||
|
* @param base start of array
|
||||||
|
* @param count number of elements in array
|
||||||
|
* @param width size of each element
|
||||||
|
* @param cmp compare function
|
||||||
|
* @param swap swap function
|
||||||
|
* @param cookie user pointer passed back to compare function
|
||||||
|
*/
|
||||||
|
void uc_heapsort(void *base, size_t count, size_t width,
|
||||||
|
uc_hs_cmp cmp, uc_hs_swp swap, void *cookie);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -14,15 +14,15 @@
|
|||||||
|
|
||||||
//MAX of a and b
|
//MAX of a and b
|
||||||
#define UC_MAX(a,b) \
|
#define UC_MAX(a,b) \
|
||||||
({ __typeof__ (a) _a = (a); \
|
({ __typeof__ (a) _amx = (a); \
|
||||||
__typeof__ (b) _b = (b); \
|
__typeof__ (b) _bmx = (b); \
|
||||||
_a > _b ? _a : _b; })
|
_amx > _bmx ? _amx : _bmx; })
|
||||||
|
|
||||||
//min of a and b
|
//min of a and b
|
||||||
#define UC_MIN(a,b) \
|
#define UC_MIN(a,b) \
|
||||||
({ __typeof__ (a) _a = (a); \
|
({ __typeof__ (a) _amn = (a); \
|
||||||
__typeof__ (b) _b = (b); \
|
__typeof__ (b) _bmn = (b); \
|
||||||
_a < _b ? _a : _b; })
|
_amn < _bmn ? _amn : _bmn; })
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -3,6 +3,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "ucore/buffer.h"
|
#include "ucore/buffer.h"
|
||||||
|
#include "ucore/utils.h"
|
||||||
|
|
||||||
GBuf*
|
GBuf*
|
||||||
uc_new_gbuf(size_t initsz)
|
uc_new_gbuf(size_t initsz)
|
||||||
@@ -48,7 +49,7 @@ uc_gbuf_append(GBuf *buf,const void *data,size_t len)
|
|||||||
unsigned char *gbuf;
|
unsigned char *gbuf;
|
||||||
|
|
||||||
if (buf->len - buf->used < len)
|
if (buf->len - buf->used < len)
|
||||||
if (uc_gbuf_grow(buf, len + len/2))
|
if (uc_gbuf_grow(buf, len + UC_MAX(UC_MIN(8U,len/2),256U)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
gbuf = buf->buf;
|
gbuf = buf->buf;
|
||||||
|
|||||||
+281
@@ -0,0 +1,281 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ucore/dstr.h"
|
||||||
|
#include "ucore/utils.h"
|
||||||
|
|
||||||
|
void uc_dstr_init(struct DStr *str)
|
||||||
|
{
|
||||||
|
str->len = 0;
|
||||||
|
str->allocated = 0;
|
||||||
|
str->str = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_dstr_destroy(struct DStr *str)
|
||||||
|
{
|
||||||
|
free(str->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_copy(struct DStr *dest, const struct DStr *src)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
uc_dstr_init(dest);
|
||||||
|
if (src->allocated == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = uc_dstr_put(dest, src->len);
|
||||||
|
if (s == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+1 to copy a potential nul terminator, uc_dstr_put
|
||||||
|
//guarantees we have room for it.
|
||||||
|
memcpy(s, src->str, UC_MIN(src->len + 1, src->allocated));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uc_dstr_available(const struct DStr *str)
|
||||||
|
{
|
||||||
|
return str->allocated - str->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_ensure(struct DStr *str, size_t total)
|
||||||
|
{
|
||||||
|
if (str->allocated < total) {
|
||||||
|
//allocate a minimum no. of bytes, and one
|
||||||
|
//additional for the common case of nul terminating
|
||||||
|
//the string
|
||||||
|
size_t new_len = UC_MAX(7U, total) + 1;
|
||||||
|
char *new_str = realloc(str->str, new_len);
|
||||||
|
|
||||||
|
if (new_str == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
str->str = new_str;
|
||||||
|
str->allocated = new_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_dstr_reset(struct DStr *str)
|
||||||
|
{
|
||||||
|
str->len = 0;
|
||||||
|
if (str->str) {
|
||||||
|
str->str[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_dstr_terminate(struct DStr *str)
|
||||||
|
{
|
||||||
|
uc_dstr_ensure(str, str->len + 1);
|
||||||
|
str->str[str->len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uc_dstr_str(struct DStr *str)
|
||||||
|
{
|
||||||
|
uc_dstr_terminate(str);
|
||||||
|
|
||||||
|
return str->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uc_dstr_put(struct DStr *str, size_t len)
|
||||||
|
{
|
||||||
|
char *start;
|
||||||
|
|
||||||
|
if (uc_dstr_ensure(str, str->len + len) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = str->str + str->len;
|
||||||
|
str->len += len;
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uc_dstr_put_str_filter(struct DStr *str, const char *s, int (*is_x)(int c))
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
size_t i;
|
||||||
|
size_t idx = 0;
|
||||||
|
|
||||||
|
if (uc_dstr_ensure(str, str->len + len) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (is_x(s[i])) {
|
||||||
|
str->str[str->len + idx]= s[i];
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str->len += idx;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_put_str_sz(struct DStr *str, const char *s, size_t len)
|
||||||
|
{
|
||||||
|
char *start = uc_dstr_put(str, len);
|
||||||
|
|
||||||
|
if (start == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(start, s, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_put_str(struct DStr *str, const char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
|
||||||
|
return uc_dstr_put_str_sz(str, s ,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_put_char(struct DStr *str, char c)
|
||||||
|
{
|
||||||
|
char *start = uc_dstr_put(str, 1);
|
||||||
|
|
||||||
|
if (start == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*start = c;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_dstr_own(struct DStr *str, char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
|
||||||
|
if (str->str) {
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
str->len = len;
|
||||||
|
str->allocated = len + 1;
|
||||||
|
str->str = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uc_dstr_steal(struct DStr *str)
|
||||||
|
{
|
||||||
|
char *s = str->str;
|
||||||
|
|
||||||
|
uc_dstr_init(str);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_str_swap(struct DStr *a, struct DStr *b)
|
||||||
|
{
|
||||||
|
struct DStr tmp;
|
||||||
|
|
||||||
|
tmp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uc_dstr_replace(struct DStr *str, char f, char r)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
if (str->len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < str->len; i++) {
|
||||||
|
if (str->str[i] == f) {
|
||||||
|
str->str[i] = r;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_dstr_trim(struct DStr *str)
|
||||||
|
{
|
||||||
|
size_t spaces;
|
||||||
|
|
||||||
|
uc_dstr_terminate(str);
|
||||||
|
|
||||||
|
//spaces at the start
|
||||||
|
spaces = strspn(str->str, " \t\n\v\f\r");
|
||||||
|
if (spaces > 0) {
|
||||||
|
memmove(str->str, str->str + spaces, str->len - spaces);
|
||||||
|
str->len -= spaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
//spaces at the end
|
||||||
|
if (str->len > 0) {
|
||||||
|
size_t idx = str->len - 1;
|
||||||
|
do {
|
||||||
|
if (strchr(" \t\n\v\f\r", str->str[idx]) == NULL) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
str->len--;
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
|
} while (idx != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_sprintf(struct DStr *str, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
rc = uc_dstr_vsprintf(str, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_dstr_vsprintf(struct DStr *str, const char *fmt, va_list ap_)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int rc;
|
||||||
|
int available;
|
||||||
|
int needed;
|
||||||
|
|
||||||
|
rc = uc_dstr_ensure(str, str->len + 1);
|
||||||
|
if (rc != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
available = uc_dstr_available(str);
|
||||||
|
|
||||||
|
va_copy(ap, ap_);
|
||||||
|
needed = vsnprintf(str->str + str->len, available, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (needed <= 0) {
|
||||||
|
return needed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needed >= available) {
|
||||||
|
rc = uc_dstr_ensure(str, str->len + needed);
|
||||||
|
if (rc != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
available = uc_dstr_available(str);
|
||||||
|
|
||||||
|
va_copy(ap, ap_);
|
||||||
|
needed = vsnprintf(str->str + str->len, available, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
str->len += needed;
|
||||||
|
|
||||||
|
return needed;
|
||||||
|
}
|
||||||
|
|
||||||
+1
-7
@@ -89,14 +89,8 @@ int uc_set_ip_dscp(int fd, unsigned int dscp)
|
|||||||
int val;
|
int val;
|
||||||
|
|
||||||
//only 6 bits for dscp
|
//only 6 bits for dscp
|
||||||
if (dscp > 63) {
|
val = (dscp & 0x3f) << 2;
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = dscp << 2;
|
|
||||||
|
|
||||||
return setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val);
|
return setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "ucore/heapsort.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
uc_sift(unsigned char *base, size_t start, size_t count, size_t width,
|
||||||
|
uc_hs_cmp cmp, uc_hs_swp swap, void *cookie)
|
||||||
|
{
|
||||||
|
size_t root = start, child;
|
||||||
|
|
||||||
|
while ((root * 2 + 1) < count) {
|
||||||
|
child = root * 2 + 1;
|
||||||
|
if (child < (count - 1)) {
|
||||||
|
int rc = cmp(&base[child * width], &base[(child + 1) * width], cookie);
|
||||||
|
if (rc < 0) {
|
||||||
|
child++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp(&base[root * width], &base[child * width], cookie) < 0) {
|
||||||
|
swap(base + root * width, base + child * width);
|
||||||
|
root = child;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uc_heapsort(void *base_, size_t count, size_t width,
|
||||||
|
uc_hs_cmp cmp, uc_hs_swp swap, void *cookie)
|
||||||
|
{
|
||||||
|
long start;
|
||||||
|
long end;
|
||||||
|
unsigned char *base = base_;
|
||||||
|
|
||||||
|
if (count == 0 || width == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = count / 2 - 1,
|
||||||
|
end = count - 1;
|
||||||
|
|
||||||
|
while (start >= 0) {
|
||||||
|
uc_sift(base, start, count, width, cmp, swap, cookie);
|
||||||
|
start--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (end > 0) {
|
||||||
|
swap(base + end * width, base);
|
||||||
|
uc_sift(base, 0, end, width, cmp, swap, cookie);
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
#include <check.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <ucore/dstr.h>
|
||||||
|
#include <ucore/utils.h>
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST (test_dstr_basics)
|
||||||
|
struct DStr str;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
rc = uc_dstr_put_str(&str, "Hello");
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_int_eq(str.len, 5);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "Hello");
|
||||||
|
|
||||||
|
rc = uc_dstr_put_char(&str, '!');
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_int_eq(str.len, 6);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "Hello!");
|
||||||
|
|
||||||
|
rc = uc_dstr_put_str_sz(&str, " World 12345678", 13);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_int_eq(str.len, 19);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "Hello! World 123456");
|
||||||
|
|
||||||
|
uc_dstr_reset(&str);
|
||||||
|
ck_assert_int_eq(str.len, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "");
|
||||||
|
|
||||||
|
uc_dstr_reset(&str);
|
||||||
|
ck_assert_int_gt(uc_dstr_available(&str), 0);
|
||||||
|
|
||||||
|
s = uc_dstr_put(&str, 2);
|
||||||
|
fail_if(s == NULL);
|
||||||
|
s[0] = '1';
|
||||||
|
s[1] = '2';
|
||||||
|
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "12");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
|
||||||
|
//just test that this doesn't crash:
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_dstr_own_steal)
|
||||||
|
struct DStr str;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
uc_dstr_own(&str, strdup("Hello !"));
|
||||||
|
ck_assert_int_eq(str.len, 7);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "Hello !");
|
||||||
|
|
||||||
|
s = uc_dstr_steal(&str);
|
||||||
|
ck_assert_str_eq(s, "Hello !");
|
||||||
|
ck_assert_int_eq(str.len, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "");
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_dstr_trim)
|
||||||
|
struct DStr str = UC_DSTR_STATIC_INIT;
|
||||||
|
|
||||||
|
uc_dstr_put_str(&str, " \t \nHello !\r\n");
|
||||||
|
uc_dstr_trim(&str);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "Hello !");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
|
||||||
|
uc_dstr_put_str(&str, " ");
|
||||||
|
|
||||||
|
uc_dstr_trim(&str);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
|
||||||
|
uc_dstr_trim(&str);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_dstr_replace)
|
||||||
|
struct DStr str;
|
||||||
|
size_t rc;
|
||||||
|
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
uc_dstr_put_str(&str, "-1-2-3-4-5-");
|
||||||
|
rc = uc_dstr_replace(&str, '-',' ');
|
||||||
|
ck_assert_int_eq(rc, 6);
|
||||||
|
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), " 1 2 3 4 5 ");
|
||||||
|
rc = uc_dstr_replace(&str, 'X','2');
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), " 1 2 3 4 5 ");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_dstr_filter)
|
||||||
|
struct DStr str;
|
||||||
|
size_t rc;
|
||||||
|
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
uc_dstr_put_str(&str, "AB:");
|
||||||
|
rc = uc_dstr_put_str_filter(&str, "1:2,3 4 ", isdigit);
|
||||||
|
ck_assert_int_eq(rc, 4);
|
||||||
|
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "AB:1234");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_dstr_sprintf)
|
||||||
|
struct DStr str;
|
||||||
|
size_t rc;
|
||||||
|
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
rc = uc_dstr_sprintf(&str, "%d-%d-%d", 1, 2, 3);
|
||||||
|
ck_assert_int_gt(rc, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "1-2-3");
|
||||||
|
|
||||||
|
rc = uc_dstr_sprintf(&str, " Another, bigger %s.", "string");
|
||||||
|
ck_assert_int_gt(rc, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(&str), "1-2-3 Another, bigger string.");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_dstr_copy)
|
||||||
|
struct DStr str;
|
||||||
|
struct DStr copy;
|
||||||
|
size_t rc;
|
||||||
|
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
rc = uc_dstr_put_str(&str, "123");
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
rc = uc_dstr_copy(©, &str);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(©), uc_dstr_str(&str));
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
uc_dstr_destroy(©);
|
||||||
|
uc_dstr_init(&str);
|
||||||
|
uc_dstr_init(©);
|
||||||
|
|
||||||
|
rc = uc_dstr_copy(©, &str);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_str_eq(uc_dstr_str(©), "");
|
||||||
|
|
||||||
|
uc_dstr_destroy(&str);
|
||||||
|
uc_dstr_destroy(©);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
Suite *dstr_suite(void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create("dstr");
|
||||||
|
TCase *tc = tcase_create("dstr tests");
|
||||||
|
tcase_add_test(tc, test_dstr_basics);
|
||||||
|
tcase_add_test(tc, test_dstr_own_steal);
|
||||||
|
tcase_add_test(tc, test_dstr_trim);
|
||||||
|
tcase_add_test(tc, test_dstr_replace);
|
||||||
|
tcase_add_test(tc, test_dstr_filter);
|
||||||
|
tcase_add_test(tc, test_dstr_sprintf);
|
||||||
|
tcase_add_test(tc, test_dstr_copy);
|
||||||
|
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#include <check.h>
|
||||||
|
#include <ucore/utils.h>
|
||||||
|
#include <ucore/heapsort.h>
|
||||||
|
|
||||||
|
struct Stuff {
|
||||||
|
char text[11];
|
||||||
|
int order;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void swap_stuff(void *a_, void *b_)
|
||||||
|
{
|
||||||
|
struct Stuff *a = a_;
|
||||||
|
struct Stuff *b = b_;
|
||||||
|
struct Stuff tmp;
|
||||||
|
|
||||||
|
tmp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_stuff(const void *a_, const void *b_, void *cookie)
|
||||||
|
{
|
||||||
|
const struct Stuff *a = a_;
|
||||||
|
const struct Stuff *b = b_;
|
||||||
|
(void)cookie;
|
||||||
|
if (a->order < b->order)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_stuff(const struct Stuff *s, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
printf("%s:%d\n", s[i].text, s[i].order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_stuff_array(const struct Stuff *a, const struct Stuff *b, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (strcmp(a[i].text, b[i].text) != 0)
|
||||||
|
return -1;
|
||||||
|
if (a[i].order != b[i].order)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST (test_heapsort_odd)
|
||||||
|
struct Stuff unordered[] = {
|
||||||
|
{"2", 2},
|
||||||
|
{"1", 1},
|
||||||
|
{"4", 4},
|
||||||
|
{"5", 5},
|
||||||
|
{"3", 3},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stuff ordered[] = {
|
||||||
|
{"1", 1},
|
||||||
|
{"2", 2},
|
||||||
|
{"3", 3},
|
||||||
|
{"4", 4},
|
||||||
|
{"5", 5},
|
||||||
|
};
|
||||||
|
|
||||||
|
uc_heapsort(unordered, ARRAY_SIZE(unordered), sizeof(struct Stuff),
|
||||||
|
cmp_stuff, swap_stuff, NULL);
|
||||||
|
print_stuff(unordered, ARRAY_SIZE(unordered));
|
||||||
|
fail_if(cmp_stuff_array(unordered, ordered, ARRAY_SIZE(unordered)) != 0);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_heapsort_even)
|
||||||
|
struct Stuff unordered[] = {
|
||||||
|
{"1", 1},
|
||||||
|
{"7", 7},
|
||||||
|
{"3", 3},
|
||||||
|
{"4", 4},
|
||||||
|
{"6", 6},
|
||||||
|
{"2", 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stuff ordered[] = {
|
||||||
|
{"1", 1},
|
||||||
|
{"2", 2},
|
||||||
|
{"3", 3},
|
||||||
|
{"4", 4},
|
||||||
|
{"6", 6},
|
||||||
|
{"7", 7},
|
||||||
|
};
|
||||||
|
|
||||||
|
uc_heapsort(unordered, ARRAY_SIZE(unordered), sizeof(struct Stuff),
|
||||||
|
cmp_stuff, swap_stuff, NULL);
|
||||||
|
fail_if(cmp_stuff_array(unordered, ordered, ARRAY_SIZE(unordered)) != 0);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_heapsort_zero)
|
||||||
|
struct Stuff unordered[] = {
|
||||||
|
{"1", 1},
|
||||||
|
{"7", 7},
|
||||||
|
{"3", 3},
|
||||||
|
{"4", 4},
|
||||||
|
{"6", 6},
|
||||||
|
{"2", 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stuff same[] = {
|
||||||
|
{"1", 1},
|
||||||
|
{"7", 7},
|
||||||
|
{"3", 3},
|
||||||
|
{"4", 4},
|
||||||
|
{"6", 6},
|
||||||
|
{"2", 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
uc_heapsort(unordered, 0, sizeof(struct Stuff),
|
||||||
|
cmp_stuff, swap_stuff, NULL);
|
||||||
|
fail_if(cmp_stuff_array(unordered, same, ARRAY_SIZE(unordered)) != 0);
|
||||||
|
|
||||||
|
uc_heapsort(unordered, ARRAY_SIZE(unordered), 0,
|
||||||
|
cmp_stuff, swap_stuff, NULL);
|
||||||
|
fail_if(cmp_stuff_array(unordered, same, ARRAY_SIZE(unordered)) != 0);
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
Suite *heapsort_suite(void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create("heapsort");
|
||||||
|
TCase *tc = tcase_create("heapsort tests");
|
||||||
|
tcase_add_test(tc, test_heapsort_odd);
|
||||||
|
tcase_add_test(tc, test_heapsort_even);
|
||||||
|
tcase_add_test(tc, test_heapsort_zero);
|
||||||
|
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
+5
-1
@@ -27,6 +27,8 @@ extern Suite *sprintb_suite(void);
|
|||||||
extern Suite *strv_suite(void);
|
extern Suite *strv_suite(void);
|
||||||
extern Suite *ratelimit_suite(void);
|
extern Suite *ratelimit_suite(void);
|
||||||
extern Suite *htable_suite(void);
|
extern Suite *htable_suite(void);
|
||||||
|
extern Suite *heapsort_suite(void);
|
||||||
|
extern Suite *dstr_suite(void);
|
||||||
|
|
||||||
static suite_func suites[] = {
|
static suite_func suites[] = {
|
||||||
bitvec_suite,
|
bitvec_suite,
|
||||||
@@ -48,7 +50,9 @@ static suite_func suites[] = {
|
|||||||
ratelimit_suite,
|
ratelimit_suite,
|
||||||
htable_suite,
|
htable_suite,
|
||||||
clock_suite,
|
clock_suite,
|
||||||
threadqueue_suite
|
threadqueue_suite,
|
||||||
|
heapsort_suite,
|
||||||
|
dstr_suite
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
Reference in New Issue
Block a user