#define GETX(X) ({ \
int x = (X)*2; \
x; \
})
void main()
{
printf("%d\n", GETX(56));
}
This example shows hot to return value from GETX(), which really is expression. Works in GCC :)
вторник, 4 марта 2014 г.
How to return value from C macro
Usually I use variable name in C macro as out parameter (it's standard way in Tcl, for example). But there is another way, something like in functional languages, with expression. See:
вторник, 4 февраля 2014 г.
Debug messages support for C, ver 2
This C module support debug/logging system with custom levels of messages. Suppressing of some level/levels are possible via DBG_LEVEL macro variable. Each custom level is created with DBG_LEVEL_ALIAS() macro. USer can define own print/dump implementations via DBG_PRN_IMPL/DBG_DUMP_IMPL.
#ifndef __DBG_H
#define __DBG_H
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#define DBG_LEVEL_ALIAS(L) (1<<(L))
#ifndef DBG_LEVEL
#define DBG_LEVEL 0
#endif
#ifndef DBG_LEVEL_FMT
#define DBG_LEVEL_FMT "%s: "
#endif
#define _DBG_PRN_IMPL_L(L, F, ...) printf(F, L, __VA_ARGS__)
#define _DBG_PRN_IMPL(F, ...) printf(F, __VA_ARGS__)
#define _DBG_DUMP_IMPL_L(L, p, sz) do { \
int i; \
for (i=0; i<(sz); i++) { \
if (0 == i%16) { \
DBG_PRN_IMPL("", "%s%s%08" PRIXPTR ": %02X "/*"%s%s%08lX: %02X "*/, i?"\n":"", \
16*i/16 + (uintptr_t)p, (uint8_t)(p)[i]); \
} else if (0 == (i-7)%16) { \
DBG_PRN_IMPL("", "%s%02X|", (uint8_t)(p)[i]); \
} else { \
DBG_PRN_IMPL("", "%s%02X ", (uint8_t)(p)[i]); \
} \
} \
DBG_PRN_IMPL("", "%s%s", "\n"); \
} while (0)
#define _DBG_DUMP_IMPL(p, sz) do { \
int i; \
for (i=0; i<(sz); i++) { \
if (0 == i%16) { \
DBG_PRN_IMPL("%s%08" PRIXPTR ": %02X "/*"%s%08lX: %02X "*/, i?"\n":"", \
16*i/16 + (uintptr_t)p, (uint8_t)(p)[i]); \
} else if (0 == (i-7)%16) { \
DBG_PRN_IMPL("%02X|", (uint8_t)(p)[i]); \
} else { \
DBG_PRN_IMPL("%02X ", (uint8_t)(p)[i]); \
} \
} \
DBG_PRN_IMPL("%s", "\n"); \
} while (0)
#ifdef DBG_LEVEL_IS_ARG
#ifndef DBG_PRN_IMPL
#define DBG_PRN_IMPL _DBG_PRN_IMPL_L
#endif
#ifndef DBG_DUMP_IMPL
#define DBG_DUMP_IMPL _DBG_DUMP_IMPL_L
#endif
#define DBG_PRN(L, F, ...) if ((DBG_LEVEL) & (L)) DBG_PRN_IMPL(#L, DBG_LEVEL_FMT F, __VA_ARGS__)
#define DBG_DUMP(L, ...) if ((DBG_LEVEL) & (L)) DBG_DUMP_IMPL(#L, __VA_ARGS__)
#else
#ifndef DBG_PRN_IMPL
#define DBG_PRN_IMPL _DBG_PRN_IMPL
#endif
#ifndef DBG_DUMP_IMPL
#define DBG_DUMP_IMPL _DBG_DUMP_IMPL
#endif
#define DBG_PRN(L, ...) if ((DBG_LEVEL) & (L)) DBG_PRN_IMPL(__VA_ARGS__)
#define DBG_DUMP(L, ...) if ((DBG_LEVEL) & (L)) DBG_DUMP_IMPL(__VA_ARGS__)
#endif
/// Print without level
#define DBG_PRN_UL(L, F, ...) if ((DBG_LEVEL) & (L)) DBG_PRN_IMPL("", "%s" F, __VA_ARGS__)
#endif /* EOF */
Usage:
#include <string.h>
// use level name as 1st argument of out DBG_PRN_IMPL
#define DBG_LEVEL_IS_ARG
#define DBG_LEVEL_FMT "[%s] "
#include "dbg.h"
// define levels
#define HARDWARE_LEVEL DBG_LEVEL_ALIAS(1)
#define WRAPPER_LEVEL DBG_LEVEL_ALIAS(2)
#define APP_LEVEL DBG_LEVEL_ALIAS(3)
#undef DBG_LEVEL
#define DBG_LEVEL (HARDWARE_LEVEL|APP_LEVEL)
void main() {
char dim[] = "0123456789Hello World!";
DBG_PRN(HARDWARE_LEVEL, "There %d\n", 1);
DBG_PRN(WRAPPER_LEVEL, "There %d\n", 2);
DBG_PRN(APP_LEVEL, "There %d\n", 3);
DBG_DUMP(APP_LEVEL, dim, strlen(dim));
DBG_PRN_UL(APP_LEVEL, "%s\n", "Done.");
}
Output:
[HARDWARE_LEVEL] There 1 [APP_LEVEL] There 3 0022FEF5: 30 31 32 33 34 35 36 37 38|39 48 65 6C 6C 6F 20 0022FF05: 57 6F 72 6C 64 21 Done.
воскресенье, 2 февраля 2014 г.
Dithering algorithm implemented for IMSH
Today I implemented Dithering algorithms for IMSH (IMage SHell) - see Project WiKi - Dithering. They are: general purpose (see matrixes in imsh.scm library) and special purpose: Atkinson, Floyd-Steinberg, Ordered, Random, General Sierra, General Sierra Two Rows, General Sierra Low, General Floyd-Steinberg, General False Floyd-Steinberg, General Jarvis, General Stucki, General Atkinson, General Burkes.
суббота, 21 декабря 2013 г.
Thread-Safe Circular Queue
Often in data processing applications are needed circular queue implemented in thread-safe way. This is the such implementation without any mutex, locks and so on:
/**
* @file cqueue.h
* @defgroup cqueue Circular queue support
* @{
* @brief Fast circular queue support
*/
#ifndef _CQUEUE_H
#define _CQUEUE_H
/** It's possible to use another (wrapper) structure or structure with another
name for cqueue implementation. CQUEUE_STRUCT_IMPL should be defined as name
of such structure in this case before to include cqueue.h. This structure
must have members:
- unsigned integer "size"
- integer "rpos"
- integer "wpos"
- integer "rwrap"
- integer "wwrap"
- any other custom fields
*/
#ifdef CQUEUE_STRUCT_IMPL
typedef CQUEUE_STRUCT_IMPL cqueue_t;
#else
/// Circular queue
typedef struct cqueue_t {
/// Capacity of queue
unsigned int size;
/// Reader position
int rpos;
/// Writer position
int wpos;
/// Reader wrapping flag
unsigned char rwrap;
/// Writer wrapping flag
unsigned char wwrap;
} cqueue_t;
#endif
/** Initializer for circular queue structure instance. Additional args are
needs if separate implementation struct is used */
#define CQUEUE_INITIALIZER(SIZE, ...) { \
.size = (SIZE), \
.rpos = 0, \
.wpos = 0, \
.wwrap = 0, \
.rwrap = 0, \
__VA_ARGS__ }
/// Init. function for queue structure instance
#define CQUEUE_INIT(Q, SIZE) do { \
(Q)->size = (SIZE); \
(Q)->rpos = (Q)->wpos = 0; \
(Q)->wwrap = (Q)->rwrap = 0; \
} while (0)
/// Reset circular queue into initial state
#define CQUEUE_RESET(Q) CQUEUE_INIT(Q, (Q)->size)
/// General position incrementing
#define CQUEUE_INCR(Q, PPOS, PWRAP) do { \
*(PPOS) = *(PPOS) +1; \
if (*(PPOS) == (Q)->size) { \
*(PWRAP) ^= 1; \
*(PPOS) = 0; \
} \
} while (0)
/// Reader position (for user-side)
#define CQUEUE_RPOS(Q) ((Q)->rpos)
/// Writer position (for user-side)
#define CQUEUE_WPOS(Q) ((Q)->wpos)
/// Reader position incrementing
#define CQUEUE_INCR_R(Q) do { \
CQUEUE_INCR(Q, &((Q)->rpos), &((Q)->rwrap)); \
} while (0)
/// Writer position incrementing
#define CQUEUE_INCR_W(Q) do { \
CQUEUE_INCR(Q, &((Q)->wpos), &((Q)->wwrap)); \
} while (0)
/// Test of circular queue fullness
#define CQUEUE_IS_FULL(Q) \
((Q)->wpos == (Q)->rpos && (Q)->rwrap != (Q)->wwrap)
/// Test of circular queue emptiness
#define CQUEUE_IS_EMPTY(Q) \
((Q)->wpos == (Q)->rpos && (Q)->rwrap == (Q)->wwrap)
/// Number of free slots in circular queue
#define CQUEUE_NFREE(Q) \
((Q)->rwrap == (Q)->wwrap ? \
((Q)->size - (Q)->wpos + (Q)->rpos) : \
((Q)->rpos - (Q)->wpos))
/// Number of used slots in circular queue
#define CQUEUE_LEN(Q) \
((Q)->rwrap != (Q)->wwrap ? \
((Q)->size - (Q)->rpos + (Q)->wpos) : \
((Q)->wpos - (Q)->rpos))
#endif
/// @}
USe doxygen to gen documentation of this module (it's only one .h-file).
Подписаться на:
Сообщения (Atom)