Created
September 4, 2012 17:07
-
-
Save LadyNamedLaura/3623568 to your computer and use it in GitHub Desktop.
aasprintf: alloca based asprintf
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
#include <alloca.h> | |
#include <stdio.h> | |
#pragma once | |
/* | |
* (v)aasprintf macro: | |
* alloca based asprintf | |
* | |
* usage: | |
* char *aasprintf(int length, char* fmt, ...) | |
* char *vaasprintf(int length, char* fmt, va_list ap) | |
* | |
* length is the length of the buffer to initially allocate, | |
* if the resulting string is longer, a larger buffer wil get allocated. | |
* | |
* all arguments exept length and ap are side_effect safe. | |
* | |
* currently up to 10 parameters alowed, to extend this, extend __ARG_STORE_ELEMENTS_* and __ARG_GET_LIST_TO_*. | |
*/ | |
#define aasprintf(length, ...) ({\ | |
int __TMPVAR(len) = 0;\ | |
char* __TMPVAR(buffer) = alloca(length);\ | |
__ARG_STORE_ELEMENTS(ARGCOUNT(__VA_ARGS__),__VA_ARGS__)\ | |
__TMPVAR(len) = snprintf(__TMPVAR(buffer), length, __ARG_GET_LIST_TO(ARGCOUNT(__VA_ARGS__))); \ | |
if (__TMPVAR(len) >= length){\ | |
__TMPVAR(buffer) = alloca(__TMPVAR(len)+1); \ | |
__TMPVAR(len) = snprintf(__TMPVAR(buffer), __TMPVAR(len)+1, __ARG_GET_LIST_TO(ARGCOUNT(__VA_ARGS__))); \ | |
}\ | |
__TMPVAR(len)>=0?__TMPVAR(buffer): NULL; }) | |
#define vaasprintf(length, fmt, ap) ({\ | |
int __TMPVAR(len) = 0;\ | |
char* __TMPVAR(buffer) = alloca(length), __TMPVAR(format) = (fmt);\ | |
va_list __TMPVAR(arglist);\ | |
va_copy(__TMPVAR(arglist),ap);\ | |
__TMPVAR(len) = vsnprintf(__TMPVAR(buffer), length, __TMPVAR(format), __TMPVAR(arglist));\ | |
va_end(__TMPVAR(arglist));\ | |
if (__TMPVAR(len) >= length){\ | |
__TMPVAR(buffer) = alloca(__TMPVAR(len)+1); \ | |
va_copy(__TMPVAR(arglist),ap);\ | |
__TMPVAR(len) = snprintf(__TMPVAR(buffer), __TMPVAR(len)+1, __TMPVAR(format), __TMPVAR(arglist)); \ | |
va_end(__TMPVAR(arglist));\ | |
}\ | |
__TMPVAR(len)>=0?__TMPVAR(buffer): NULL; }) | |
#define __cat(a,b) a ## b | |
#define cat(a,b) __cat(a,b) | |
#define __TMPVAR(id) cat(cat(__tmpvar_,id), cat(_line,__LINE__)) | |
#define ARGCOUNT(...) __ARGCOUNT(__VA_ARGS__, 63,62,61,60,59,58,57,56,55,54,53,52,51,50,\ | |
49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,\ | |
25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) | |
#define __ARGCOUNT(...) __GET_ARG64(__VA_ARGS__) | |
#define __GET_ARG64(_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,_30,\ | |
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,\ | |
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,\ | |
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,\ | |
_61,_62,_63,N,...) N | |
#define __ARG_STORE_ELEMENTS(max,...) cat(__ARG_STORE_ELEMENTS_,max)(__VA_ARGS__) | |
#define __ARG_GET_LIST_TO(max) cat(__ARG_GET_LIST_TO_,max)() | |
#define __ARG_STORE(arg, id) typeof(arg) __TMPVAR(cat(arglist_,id)) = (arg); | |
#define __ARG_STORE_ELEMENTS_1(N) __ARG_STORE(N, 1) | |
#define __ARG_STORE_ELEMENTS_2(N,...) __ARG_STORE(N,2) __ARG_STORE_ELEMENTS_1(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_3(N,...) __ARG_STORE(N,3) __ARG_STORE_ELEMENTS_2(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_4(N,...) __ARG_STORE(N,4) __ARG_STORE_ELEMENTS_3(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_5(N,...) __ARG_STORE(N,5) __ARG_STORE_ELEMENTS_4(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_6(N,...) __ARG_STORE(N,6) __ARG_STORE_ELEMENTS_5(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_7(N,...) __ARG_STORE(N,7) __ARG_STORE_ELEMENTS_6(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_8(N,...) __ARG_STORE(N,8) __ARG_STORE_ELEMENTS_7(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_9(N,...) __ARG_STORE(N,9) __ARG_STORE_ELEMENTS_8(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_10(N,...) __ARG_STORE(N,10) __ARG_STORE_ELEMENTS_9(__VA_ARGS__) | |
#define __ARG_STORE_ELEMENTS_11(N,...) __ARG_STORE(N,11) __ARG_STORE_ELEMENTS_10(__VA_ARGS__) | |
#define __ARG_GET_LIST_TO_1() __TMPVAR(arglist_1) | |
#define __ARG_GET_LIST_TO_2() __TMPVAR(arglist_2), __ARG_GET_LIST_TO_1() | |
#define __ARG_GET_LIST_TO_3() __TMPVAR(arglist_3), __ARG_GET_LIST_TO_2() | |
#define __ARG_GET_LIST_TO_4() __TMPVAR(arglist_4), __ARG_GET_LIST_TO_3() | |
#define __ARG_GET_LIST_TO_5() __TMPVAR(arglist_5), __ARG_GET_LIST_TO_4() | |
#define __ARG_GET_LIST_TO_6() __TMPVAR(arglist_6), __ARG_GET_LIST_TO_5() | |
#define __ARG_GET_LIST_TO_7() __TMPVAR(arglist_7), __ARG_GET_LIST_TO_6() | |
#define __ARG_GET_LIST_TO_8() __TMPVAR(arglist_8), __ARG_GET_LIST_TO_7() | |
#define __ARG_GET_LIST_TO_9() __TMPVAR(arglist_9), __ARG_GET_LIST_TO_8() | |
#define __ARG_GET_LIST_TO_10() __TMPVAR(arglist_10), __ARG_GET_LIST_TO_9() | |
#define __ARG_GET_LIST_TO_11() __TMPVAR(arglist_11), __ARG_GET_LIST_TO_10() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
just to explain how it works:
becomes: