Created
September 16, 2015 20:36
-
-
Save psobko/7ff9da838b981a97d7b5 to your computer and use it in GitHub Desktop.
DLogVars() - Log up to 28 expressions in DLog format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Logger.h | |
// Logger | |
// | |
// Created by psobko on 9/16/15. | |
// Copyright (c) 2015 psobko. All rights reserved. | |
// | |
#ifndef Logger_Logger_h | |
#define Logger_Logger_h | |
#ifndef DEBUG_LEVEL | |
#define DEBUG_LEVEL 0 | |
#endif | |
#if DEBUG | |
#define DLog(fmt, ...) if(DEBUG_LEVEL) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) | |
#define DLogVars(...) if(DEBUG_LEVEL) DLog(@"Printing Variables");CALL_MACRO_X_FOR_EACH(LOG_EXPR, ##__VA_ARGS__) | |
#else | |
#define DLog(...) | |
#endif | |
//Expression Logging | |
//Copyright (c) 2008-2010, Vincent Gable. | |
//http://vincentgable.com | |
//based off http://www.dribin.org/dave/blog/archives/2008/09/22/convert_to_nsstring/ | |
static BOOL TypeCodeIsCharArray(const char *typeCode){ | |
size_t len = strlen(typeCode); | |
if(len <= 2) | |
return NO; | |
size_t lastCharOffset = len - 1; | |
size_t secondToLastCharOffset = lastCharOffset - 1 ; | |
BOOL isCharArray = typeCode[0] == '[' && | |
typeCode[secondToLastCharOffset] == 'c' && typeCode[lastCharOffset] == ']'; | |
for(int i = 1; i < secondToLastCharOffset; i++) | |
isCharArray = isCharArray && isdigit(typeCode[i]); | |
return isCharArray; | |
} | |
//since BOOL is #defined as a signed char, we treat the value as | |
//a BOOL if it is exactly YES or NO, and a char otherwise. | |
static NSString* VTPGStringFromBoolOrCharValue(BOOL boolOrCharvalue) { | |
if(boolOrCharvalue == YES) | |
return @"YES"; | |
if(boolOrCharvalue == NO) | |
return @"NO"; | |
return [NSString stringWithFormat:@"'%c'", boolOrCharvalue]; | |
} | |
static NSString *VTPGStringFromFourCharCodeOrUnsignedInt32(FourCharCode fourcc) { | |
return [NSString stringWithFormat:@"%u ('%c%c%c%c')", | |
fourcc, | |
(fourcc >> 24) & 0xFF, | |
(fourcc >> 16) & 0xFF, | |
(fourcc >> 8) & 0xFF, | |
fourcc & 0xFF]; | |
} | |
static NSString *StringFromNSDecimalWithCurrentLocal(NSDecimal dcm) { | |
return NSDecimalString(&dcm, [NSLocale currentLocale]); | |
} | |
NSString * VTPG_DDToStringFromTypeAndValue(const char * typeCode, void * value) { | |
#define IF_TYPE_MATCHES_INTERPRET_WITH(typeToMatch,func) \ | |
if (strcmp(typeCode, @encode(typeToMatch)) == 0) \ | |
return (func)(*(typeToMatch*)value) | |
#if TARGET_OS_IPHONE | |
IF_TYPE_MATCHES_INTERPRET_WITH(CGPoint,NSStringFromCGPoint); | |
IF_TYPE_MATCHES_INTERPRET_WITH(CGSize,NSStringFromCGSize); | |
IF_TYPE_MATCHES_INTERPRET_WITH(CGRect,NSStringFromCGRect); | |
#else | |
IF_TYPE_MATCHES_INTERPRET_WITH(NSPoint,NSStringFromPoint); | |
IF_TYPE_MATCHES_INTERPRET_WITH(NSSize,NSStringFromSize); | |
IF_TYPE_MATCHES_INTERPRET_WITH(NSRect,NSStringFromRect); | |
#endif | |
IF_TYPE_MATCHES_INTERPRET_WITH(NSRange,NSStringFromRange); | |
IF_TYPE_MATCHES_INTERPRET_WITH(Class,NSStringFromClass); | |
IF_TYPE_MATCHES_INTERPRET_WITH(SEL,NSStringFromSelector); | |
IF_TYPE_MATCHES_INTERPRET_WITH(BOOL,VTPGStringFromBoolOrCharValue); | |
IF_TYPE_MATCHES_INTERPRET_WITH(NSDecimal,StringFromNSDecimalWithCurrentLocal); | |
#define IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(typeToMatch,formatString) \ | |
if (strcmp(typeCode, @encode(typeToMatch)) == 0) \ | |
return [NSString stringWithFormat:(formatString), (*(typeToMatch*)value)] | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(CFStringRef,@"%@"); //CFStringRef is toll-free bridged to NSString* | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(CFArrayRef,@"%@"); //CFArrayRef is toll-free bridged to NSArray* | |
IF_TYPE_MATCHES_INTERPRET_WITH(FourCharCode, VTPGStringFromFourCharCodeOrUnsignedInt32); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(long long,@"%lld"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(unsigned long long,@"%llu"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(float,@"%f"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(double,@"%f"); | |
#if __has_feature(objc_arc) | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(__unsafe_unretained id,@"%@"); | |
#else /* not __has_feature(objc_arc) */ | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(id,@"%@"); | |
#endif | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(short,@"%hi"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(unsigned short,@"%hu"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(int,@"%i"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(unsigned, @"%u"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(long,@"%li"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(long double,@"%Lf"); //WARNING on older versions of OS X, @encode(long double) == @encode(double) | |
//C-strings | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(char*, @"%s"); | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(const char*, @"%s"); | |
if(TypeCodeIsCharArray(typeCode)) | |
return [NSString stringWithFormat:@"%s", (char*)value]; | |
IF_TYPE_MATCHES_INTERPRET_WITH_FORMAT(void*,@"(void*)%p"); | |
//This is a hack to print out CLLocationCoordinate2D, without needing to #import <CoreLocation/CoreLocation.h> | |
//A CLLocationCoordinate2D is a struct made up of 2 doubles. | |
//We detect it by hard-coding the result of @encode(CLLocationCoordinate2D). | |
//We get at the fields by treating it like an array of doubles, which it is identical to in memory. | |
if(strcmp(typeCode, "{?=dd}")==0)//@encode(CLLocationCoordinate2D) | |
return [NSString stringWithFormat:@"{latitude=%g,longitude=%g}",((double*)value)[0],((double*)value)[1]]; | |
//we don't know how to convert this typecode into an NSString | |
return nil; | |
} | |
//Variadic ForEach Macro | |
#define _GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, N, ...) N | |
#define _fe_0(_call, ...) | |
#define _fe_1(_call, x) _call(x) | |
#define _fe_2(_call, x, ...) _call(x) _fe_1(_call, __VA_ARGS__) | |
#define _fe_3(_call, x, ...) _call(x) _fe_2(_call, __VA_ARGS__) | |
#define _fe_4(_call, x, ...) _call(x) _fe_3(_call, __VA_ARGS__) | |
#define _fe_5(_call, x, ...) _call(x) _fe_4(_call, __VA_ARGS__) | |
#define _fe_6(_call, x, ...) _call(x) _fe_5(_call, __VA_ARGS__) | |
#define _fe_7(_call, x, ...) _call(x) _fe_6(_call, __VA_ARGS__) | |
#define _fe_8(_call, x, ...) _call(x) _fe_7(_call, __VA_ARGS__) | |
#define _fe_9(_call, x, ...) _call(x) _fe_8(_call, __VA_ARGS__) | |
#define _fe_10(_call, x, ...) _call(x) _fe_9(_call, __VA_ARGS__) | |
#define _fe_11(_call, x, ...) _call(x) _fe_10(_call, __VA_ARGS__) | |
#define _fe_12(_call, x, ...) _call(x) _fe_11(_call, __VA_ARGS__) | |
#define _fe_13(_call, x, ...) _call(x) _fe_12(_call, __VA_ARGS__) | |
#define _fe_14(_call, x, ...) _call(x) _fe_13(_call, __VA_ARGS__) | |
#define _fe_15(_call, x, ...) _call(x) _fe_14(_call, __VA_ARGS__) | |
#define _fe_16(_call, x, ...) _call(x) _fe_15(_call, __VA_ARGS__) | |
#define _fe_17(_call, x, ...) _call(x) _fe_16(_call, __VA_ARGS__) | |
#define _fe_18(_call, x, ...) _call(x) _fe_17(_call, __VA_ARGS__) | |
#define _fe_19(_call, x, ...) _call(x) _fe_18(_call, __VA_ARGS__) | |
#define _fe_20(_call, x, ...) _call(x) _fe_19(_call, __VA_ARGS__) | |
#define _fe_21(_call, x, ...) _call(x) _fe_20(_call, __VA_ARGS__) | |
#define _fe_22(_call, x, ...) _call(x) _fe_21(_call, __VA_ARGS__) | |
#define _fe_23(_call, x, ...) _call(x) _fe_22(_call, __VA_ARGS__) | |
#define _fe_24(_call, x, ...) _call(x) _fe_23(_call, __VA_ARGS__) | |
#define _fe_25(_call, x, ...) _call(x) _fe_24(_call, __VA_ARGS__) | |
#define _fe_26(_call, x, ...) _call(x) _fe_25(_call, __VA_ARGS__) | |
#define _fe_27(_call, x, ...) _call(x) _fe_26(_call, __VA_ARGS__) | |
#define _fe_28(_call, x, ...) _call(x) _fe_27(_call, __VA_ARGS__) | |
#define CALL_MACRO_X_FOR_EACH(x, ...) \ | |
_GET_NTH_ARG("ignored", ##__VA_ARGS__, \ | |
_fe_28, _fe_27, _fe_26, _fe_25, _fe_24, _fe_23, _fe_22, _fe_21, _fe_20, _fe_19, _fe_18, _fe_17, _fe_16, _fe_15, _fe_14, _fe_13, _fe_12, _fe_11, _fe_10, _fe_9, _fe_8, _fe_7, _fe_6, _fe_5, _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(x, ##__VA_ARGS__) | |
#define LOG_EXPR(_X_) do{\ | |
__typeof__(_X_) _Y_ = (_X_);\ | |
const char * _TYPE_CODE_ = @encode(__typeof__(_X_));\ | |
NSString *_STR_ = VTPG_DDToStringFromTypeAndValue(_TYPE_CODE_, &_Y_);\ | |
if(_STR_)\ | |
NSLog(@"%s = %@", #_X_, _STR_);\ | |
else\ | |
NSLog(@"Unknown _TYPE_CODE_: %s for expression %s in function %s, file %s, line %d", _TYPE_CODE_, #_X_, __func__, __FILE__, __LINE__);\ | |
}while(0); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment