123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- //
- // KSLogger.h
- //
- // Created by Karl Stenerud on 11-06-25.
- //
- // Copyright (c) 2011 Karl Stenerud. All rights reserved.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall remain in place
- // in this source code.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- /**
- * KSLogger
- * ========
- *
- * Prints log entries to the console consisting of:
- * - Level (Error, Warn, Info, Debug, Trace)
- * - File
- * - Line
- * - Function
- * - Message
- *
- * Allows setting the minimum logging level in the preprocessor.
- *
- * Works in C or Objective-C contexts, with or without ARC, using CLANG or GCC.
- *
- *
- * =====
- * USAGE
- * =====
- *
- * Set the log level in your "Preprocessor Macros" build setting. You may choose
- * TRACE, DEBUG, INFO, WARN, ERROR. If nothing is set, it defaults to ERROR.
- *
- * Example: KSLogger_Level=WARN
- *
- * Anything below the level specified for KSLogger_Level will not be compiled
- * or printed.
- *
- *
- * Next, include the header file:
- *
- * #include "KSLogger.h"
- *
- *
- * Next, call the logger functions from your code (using objective-c strings
- * in objective-C files and regular strings in regular C files):
- *
- * Code:
- * KSLOG_ERROR(@"Some error message");
- *
- * Prints:
- * 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): -[SomeFunction]: Some error message
- *
- * Code:
- * KSLOG_INFO(@"Info about %@", someObject);
- *
- * Prints:
- * 2011-07-16 05:44:05.239 TestApp[4473:f803] INFO : SomeClass.m (20): -[SomeFunction]: Info about <NSObject: 0xb622840>
- *
- *
- * The "BASIC" versions of the macros behave exactly like NSLog() or printf(),
- * except they respect the KSLogger_Level setting:
- *
- * Code:
- * KSLOGBASIC_ERROR(@"A basic log entry");
- *
- * Prints:
- * 2011-07-16 05:44:05.916 TestApp[4473:f803] A basic log entry
- *
- *
- * NOTE: In C files, use "" instead of @"" in the format field. Logging calls
- * in C files do not print the NSLog preamble:
- *
- * Objective-C version:
- * KSLOG_ERROR(@"Some error message");
- *
- * 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): -[SomeFunction]: Some error message
- *
- * C version:
- * KSLOG_ERROR("Some error message");
- *
- * ERROR: SomeClass.c (21): SomeFunction(): Some error message
- *
- *
- * =============
- * LOCAL LOGGING
- * =============
- *
- * You can control logging messages at the local file level using the
- * "KSLogger_LocalLevel" define. Note that it must be defined BEFORE
- * including KSLogger.h
- *
- * The KSLOG_XX() and KSLOGBASIC_XX() macros will print out based on the LOWER
- * of KSLogger_Level and KSLogger_LocalLevel, so if KSLogger_Level is DEBUG
- * and KSLogger_LocalLevel is TRACE, it will print all the way down to the trace
- * level for the local file where KSLogger_LocalLevel was defined, and to the
- * debug level everywhere else.
- *
- * Example:
- *
- * // KSLogger_LocalLevel, if defined, MUST come BEFORE including KSLogger.h
- * #define KSLogger_LocalLevel TRACE
- * #import "KSLogger.h"
- *
- *
- * ===============
- * IMPORTANT NOTES
- * ===============
- *
- * The C logger changes its behavior depending on the value of the preprocessor
- * define KSLogger_CBufferSize.
- *
- * If KSLogger_CBufferSize is > 0, the C logger will behave in an async-safe
- * manner, calling write() instead of printf(). Any log messages that exceed the
- * length specified by KSLogger_CBufferSize will be truncated.
- *
- * If KSLogger_CBufferSize == 0, the C logger will use printf(), and there will
- * be no limit on the log message length.
- *
- * KSLogger_CBufferSize can only be set as a preprocessor define, and will
- * default to 1024 if not specified during compilation.
- */
- // ============================================================================
- #pragma mark - (internal) -
- // ============================================================================
- #ifndef HDR_KSLogger_h
- #define HDR_KSLogger_h
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include <stdbool.h>
- #ifdef __OBJC__
- #import <CoreFoundation/CoreFoundation.h>
- void i_kslog_logObjC(const char* level,
- const char* file,
- int line,
- const char* function,
- CFStringRef fmt, ...);
- void i_kslog_logObjCBasic(CFStringRef fmt, ...);
- #define i_KSLOG_FULL(LEVEL,FILE,LINE,FUNCTION,FMT,...) i_kslog_logObjC(LEVEL,FILE,LINE,FUNCTION,(__bridge CFStringRef)FMT,##__VA_ARGS__)
- #define i_KSLOG_BASIC(FMT, ...) i_kslog_logObjCBasic((__bridge CFStringRef)FMT,##__VA_ARGS__)
- #else // __OBJC__
- void i_kslog_logC(const char* level,
- const char* file,
- int line,
- const char* function,
- const char* fmt, ...);
- void i_kslog_logCBasic(const char* fmt, ...);
- #define i_KSLOG_FULL i_kslog_logC
- #define i_KSLOG_BASIC i_kslog_logCBasic
- #endif // __OBJC__
- /* Back up any existing defines by the same name */
- #ifdef KS_NONE
- #define KSLOG_BAK_NONE KS_NONE
- #undef KS_NONE
- #endif
- #ifdef ERROR
- #define KSLOG_BAK_ERROR ERROR
- #undef ERROR
- #endif
- #ifdef WARN
- #define KSLOG_BAK_WARN WARN
- #undef WARN
- #endif
- #ifdef INFO
- #define KSLOG_BAK_INFO INFO
- #undef INFO
- #endif
- #ifdef DEBUG
- #define KSLOG_BAK_DEBUG DEBUG
- #undef DEBUG
- #endif
- #ifdef TRACE
- #define KSLOG_BAK_TRACE TRACE
- #undef TRACE
- #endif
- #define KSLogger_Level_None 0
- #define KSLogger_Level_Error 10
- #define KSLogger_Level_Warn 20
- #define KSLogger_Level_Info 30
- #define KSLogger_Level_Debug 40
- #define KSLogger_Level_Trace 50
- #define KS_NONE KSLogger_Level_None
- #define ERROR KSLogger_Level_Error
- #define WARN KSLogger_Level_Warn
- #define INFO KSLogger_Level_Info
- #define DEBUG KSLogger_Level_Debug
- #define TRACE KSLogger_Level_Trace
- #ifndef KSLogger_Level
- #define KSLogger_Level KSLogger_Level_Error
- #endif
- #ifndef KSLogger_LocalLevel
- #define KSLogger_LocalLevel KSLogger_Level_None
- #endif
- #define a_KSLOG_FULL(LEVEL, FMT, ...) \
- i_KSLOG_FULL(LEVEL, \
- __FILE__, \
- __LINE__, \
- __PRETTY_FUNCTION__, \
- FMT, \
- ##__VA_ARGS__)
- // ============================================================================
- #pragma mark - API -
- // ============================================================================
- /** Set the filename to log to.
- *
- * @param filename The file to write to (NULL = write to stdout).
- *
- * @param overwrite If true, overwrite the log file.
- */
- bool kslog_setLogFilename(const char* filename, bool overwrite);
- /** Clear the log file. */
- bool kslog_clearLogFile(void);
- /** Tests if the logger would print at the specified level.
- *
- * @param LEVEL The level to test for. One of:
- * KSLogger_Level_Error,
- * KSLogger_Level_Warn,
- * KSLogger_Level_Info,
- * KSLogger_Level_Debug,
- * KSLogger_Level_Trace,
- *
- * @return TRUE if the logger would print at the specified level.
- */
- #define KSLOG_PRINTS_AT_LEVEL(LEVEL) \
- (KSLogger_Level >= LEVEL || KSLogger_LocalLevel >= LEVEL)
- /** Log a message regardless of the log settings.
- * Normal version prints out full context. Basic version prints directly.
- *
- * @param FMT The format specifier, followed by its arguments.
- */
- #define KSLOG_ALWAYS(FMT, ...) a_KSLOG_FULL("FORCE", FMT, ##__VA_ARGS__)
- #define KSLOGBASIC_ALWAYS(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
- /** Log an error.
- * Normal version prints out full context. Basic version prints directly.
- *
- * @param FMT The format specifier, followed by its arguments.
- */
- #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Error)
- #define KSLOG_ERROR(FMT, ...) a_KSLOG_FULL("ERROR", FMT, ##__VA_ARGS__)
- #define KSLOGBASIC_ERROR(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
- #else
- #define KSLOG_ERROR(FMT, ...)
- #define KSLOGBASIC_ERROR(FMT, ...)
- #endif
- /** Log a warning.
- * Normal version prints out full context. Basic version prints directly.
- *
- * @param FMT The format specifier, followed by its arguments.
- */
- #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Warn)
- #define KSLOG_WARN(FMT, ...) a_KSLOG_FULL("WARN ", FMT, ##__VA_ARGS__)
- #define KSLOGBASIC_WARN(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
- #else
- #define KSLOG_WARN(FMT, ...)
- #define KSLOGBASIC_WARN(FMT, ...)
- #endif
- /** Log an info message.
- * Normal version prints out full context. Basic version prints directly.
- *
- * @param FMT The format specifier, followed by its arguments.
- */
- #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Info)
- #define KSLOG_INFO(FMT, ...) a_KSLOG_FULL("INFO ", FMT, ##__VA_ARGS__)
- #define KSLOGBASIC_INFO(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
- #else
- #define KSLOG_INFO(FMT, ...)
- #define KSLOGBASIC_INFO(FMT, ...)
- #endif
- /** Log a debug message.
- * Normal version prints out full context. Basic version prints directly.
- *
- * @param FMT The format specifier, followed by its arguments.
- */
- #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Debug)
- #define KSLOG_DEBUG(FMT, ...) a_KSLOG_FULL("DEBUG", FMT, ##__VA_ARGS__)
- #define KSLOGBASIC_DEBUG(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
- #else
- #define KSLOG_DEBUG(FMT, ...)
- #define KSLOGBASIC_DEBUG(FMT, ...)
- #endif
- /** Log a trace message.
- * Normal version prints out full context. Basic version prints directly.
- *
- * @param FMT The format specifier, followed by its arguments.
- */
- #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Trace)
- #define KSLOG_TRACE(FMT, ...) a_KSLOG_FULL("TRACE", FMT, ##__VA_ARGS__)
- #define KSLOGBASIC_TRACE(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
- #else
- #define KSLOG_TRACE(FMT, ...)
- #define KSLOGBASIC_TRACE(FMT, ...)
- #endif
- // ============================================================================
- #pragma mark - (internal) -
- // ============================================================================
- /* Put everything back to the way we found it. */
- #undef ERROR
- #ifdef KSLOG_BAK_ERROR
- #define ERROR KSLOG_BAK_ERROR
- #undef KSLOG_BAK_ERROR
- #endif
- #undef WARNING
- #ifdef KSLOG_BAK_WARN
- #define WARNING KSLOG_BAK_WARN
- #undef KSLOG_BAK_WARN
- #endif
- #undef INFO
- #ifdef KSLOG_BAK_INFO
- #define INFO KSLOG_BAK_INFO
- #undef KSLOG_BAK_INFO
- #endif
- #undef DEBUG
- #ifdef KSLOG_BAK_DEBUG
- #define DEBUG KSLOG_BAK_DEBUG
- #undef KSLOG_BAK_DEBUG
- #endif
- #undef TRACE
- #ifdef KSLOG_BAK_TRACE
- #define TRACE KSLOG_BAK_TRACE
- #undef KSLOG_BAK_TRACE
- #endif
- #ifdef __cplusplus
- }
- #endif
- #endif // HDR_KSLogger_h
|