wrapper printf function that filters according to user preferences
Asked Answered
J

3

30

My program writes to a log and to stdout. Every message, however, has a certain priority and the user specifies in Preferences which priorities go to which stream (log or stdout).

unsigned short PRIO_HIGH = 0x0001;
unsigned short PRIO_NORMAL = 0x0002;
unsigned short PRIO_LOW = 0x0004;

The preferences is handled by some flags:

unsigned short PRIO_LOG = (PRIO_HIGH | PRIO_NORMAL);
unsigned short PRIO_STD = (PRIO_HIGH);

The write_log function should work with the same parameters as the printf function, with the added parameter of unsigned short priority.

write_log((PRIO_NORMAL|PRIO_LOW), "HELLO %s, take %d", "World", 1);

(Even if PRIO_NORMAL|PRIO_LOW makes little sense...)

Checking the flags is easy: if(priority & PRIO_LOG) (Returns >1 if any flag is set in both arguments)

I cannot however find out how I would go about passing the string literal and the format arguments to the printf function. Can anyone help or give me a pointer (possible to an alternative method that achieves the same effect)? It would be much appreciated.

Joycelynjoye answered 4/10, 2009 at 13:7 Comment(0)
E
72

You want to call vprintf() instead of printf() using the variable arguments "varargs" capabilities of C.

#include <stdarg.h>

int write_log(int priority, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    if(priority & PRIO_LOG)
            vprintf(format, args);

    va_end(args);
}

For more information, see something along the lines of this.

Egalitarian answered 4/10, 2009 at 13:15 Comment(1)
In Visual C++ you can use _____VA_ARGS_____ instead. Reference: msdn.microsoft.com/en-us/library/ms177415(v=vs.110).aspxLaquitalar
M
11

I think Jeff's idea is the way to go, but you can also accomplish this with a macro without using vprintf. This might require gcc:

#define write_log(priority,format,args...)        \
                  if (priority & PRIO_LOG) {      \ 
                      printf(format, ## args);    \
                  }

Check here for info about how this works.

Marquettamarquette answered 4/10, 2009 at 18:42 Comment(0)
D
4

If you want the PRIO_* definitions to be used as bit (using | and &), you must give each one of them its own bit:

unsigned short PRIO_HIGH = 0x0001;
unsigned short PRIO_NORMAL = 0x0002;
unsigned short PRIO_LOW = 0x0004;

The macro can be improved by using the do { } while (0) notation. It makes the calls to write_log act more like a statement.

#define write_log(priority,format,args...) do { \
    if (priority & PRIO_LOG) { \
        printf(format, ## args); \
    } while(0)
Deaf answered 5/10, 2009 at 15:45 Comment(1)
Sorry, Type. I did it like that in my source of course. thanks for the pointing out! +1 for a keen eye.Joycelynjoye

© 2022 - 2024 — McMap. All rights reserved.