0

It's a pity that there are a lot similar macros(both name and function) in the code below. How to simplify the similar macros?

The difference between the similar macros are the string tags, say [PROC_E] indicats it's an error message for the module named PROC while [SERVICE_E] indicats it's an error message for the module named SERVICE.

#include <stdio.h>
#include <type_traits>
#include <mutex>
#include <stdarg.h>

typedef enum 
{
    NONE,
    DEBUG,
    WARNING,
    ERROR,
}log_level_em;

class SimpleLog
{
private:
    SimpleLog() = default;
    SimpleLog(const SimpleLog&) = delete;
    SimpleLog& operator=(const SimpleLog&) = delete;
public:
    static SimpleLog& get_instance()
    {
        static SimpleLog logger;
        return logger;
    }

    void set_block_level(log_level_em level)
    {
        block_level = level;
    }

    bool block_log(log_level_em level)
    {
        return static_cast<std::underlying_type<log_level_em>::type>(level) <= \
               static_cast<std::underlying_type<log_level_em>::type>(block_level);
    }

    void log_output(log_level_em level, const char* fmt, ...)
    {
        if(block_log(level))
        {
            return;
        }

        va_list args;
        va_start(args, fmt);
        {
            std::unique_lock<std::mutex> lock{mtx};
            vprintf(fmt, args);
        }
        va_end(args);
    }

    log_level_em block_level{NONE};
    std::mutex mtx;
};

#define LOG_SET_LEVEL(lvl)                          \
do{                                                 \
    SimpleLog::get_instance().set_block_level(lvl); \
} while(false);

// Define the LOG_COMMON macro to accept variadic parameters
#define LOG_COMMON(log_level, fmt, ...)                                        \
do{                                                                            \
    SimpleLog::get_instance().log_output(log_level, "[%s] [%s:%d] " fmt "\n",  \
                             __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
} while(false);

// All the macros call LOG_COMMON
#define CAM_LOG_ERROR(fmt, ...)   LOG_COMMON(ERROR,   "[CAM_E] "  fmt, ##__VA_ARGS__)
#define CAM_LOG_WARNING(fmt, ...) LOG_COMMON(WARNING, "[CAM_W] " fmt, ##__VA_ARGS__)
#define CAM_LOG_DEBUG(fmt, ...)   LOG_COMMON(DEBUG,   "[CAM_D] " fmt, ##__VA_ARGS__)

#define PROC_LOG_ERROR(fmt, ...)   LOG_COMMON(ERROR,   "[PROC_E] " fmt, ##__VA_ARGS__)
#define PROC_LOG_WARNING(fmt, ...) LOG_COMMON(WARNING, "[PROC_W] " fmt, ##__VA_ARGS__)
#define PROC_LOG_DEBUG(fmt, ...)   LOG_COMMON(DEBUG,   "[PROC_D] " fmt, ##__VA_ARGS__)

#define SERVICE_LOG_ERROR(fmt, ...)   LOG_COMMON(ERROR,   "[SERVICE_E] " fmt, ##__VA_ARGS__)
#define SERVICE_LOG_WARNING(fmt, ...) LOG_COMMON(WARNING, "[SERVICE_W] " fmt, ##__VA_ARGS__)
#define SERVICE_LOG_DEBUG(fmt, ...)   LOG_COMMON(DEBUG,   "[SERVICE_D] " fmt, ##__VA_ARGS__)

int main() {
    LOG_SET_LEVEL(DEBUG);

    CAM_LOG_ERROR("the fd(%d) can't be opened!", 5);
    CAM_LOG_WARNING("this is a warning from %s !", "message processing thread");
    PROC_LOG_ERROR("this is a warning from %s !", "message processing thread");
    PROC_LOG_DEBUG("this message should not be seen");
    SERVICE_LOG_WARNING("failed to run function");
    return 0;
}

10
  • 1
    Why did I have to scroll your code block to see any macros in a question about macros? Why do I have to read your code to find out what the differences are?
    – JaMiT
    Commented May 25 at 3:37
  • 1
    What sort of result are you looking for? The easy answer is "don't use macros".
    – JaMiT
    Commented May 25 at 3:38
  • @JaMiT Sorry, I have followed your advice to modify the question.
    – John
    Commented May 25 at 3:52
  • 1
    There isn't really a way to simplify the macros without adding more macros to deal with the fixed text, e.g. "[CAM_E] " and so on. Unless you want to turn those into preprocessing tokens and paste them with ##. Either way you are not really going to reduce or simplify the macros. Commented May 25 at 4:09
  • 1
    @Jean-BaptisteYunès Sounds a good idea. How to achieve that goal? Macros call the cam_log_* functions?
    – John
    Commented May 30 at 8:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.