Advertisement
Geometrian

Flat Array to `va_list` Workaround

Apr 13th, 2015
488
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.92 KB | None | 0 0
  1. #include <cstdarg>
  2. #include <cstdio>
  3. #include <cstring>
  4.  
  5. #ifdef _MSC_VER
  6.     #pragma warning(disable:4996)
  7. #endif
  8.  
  9.  
  10. inline static void assert(bool condition,char const* msg) {
  11.     if (!condition) printf("%s",msg);
  12. }
  13.  
  14. inline static void printf_buffer(char const*__restrict format_string, char*__restrict argument_buffer) {
  15.     int num_chars = 0;
  16.     PARSE_CHAR:
  17.         switch (*format_string) {
  18.             case '\0': return;
  19.             case '%': {
  20.                 int i = 1;
  21.                 char c;
  22.                 PARSE_SPECIFIER:
  23.                     c = format_string[i++];
  24.                     switch (c) {
  25.                         case 'd': case 'i':
  26.                         case 'u': case 'o': case 'x': case 'X':
  27.                         case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': case 'a': case 'A':
  28.                         case 'c': case 's': case 'p':
  29.                             goto PRINT_SPECIFIER;
  30.                         case 'n':
  31.                             assert(i==2,"\"%%n\" must contain no intermediary characters!");
  32.                             **reinterpret_cast<int**>(argument_buffer) = num_chars;
  33.                             argument_buffer += sizeof(int*);
  34.                             goto DONE_SPECIFIER;
  35.                         case '%':
  36.                             assert(i==2,"\"%%%%\" must contain no intermediary characters!");
  37.                             putchar('%'); ++num_chars;
  38.                             goto DONE_SPECIFIER;
  39.                         case '\0': assert(false,"Expected specifier before end of string!");
  40.                         default: goto PARSE_SPECIFIER;
  41.                     }
  42.                 PRINT_SPECIFIER: {
  43.                     char* temp = new char[i+1];
  44.                     strncpy(temp,format_string,i); temp[i]='\0';
  45.                     #define PRINTBRK(TYPE) num_chars+=printf(temp,*reinterpret_cast<TYPE*>(argument_buffer)); argument_buffer+=sizeof(TYPE); break;
  46.                     switch (c) {
  47.                         case 'd': case 'i': PRINTBRK(int)
  48.                         case 'u': case 'o': case 'x': case 'X': PRINTBRK(unsigned int)
  49.                         case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': case 'a': case 'A': PRINTBRK(double)
  50.                         case 'c': PRINTBRK(char)
  51.                         case 's': PRINTBRK(char const*)
  52.                         case 'p': PRINTBRK(void*)
  53.                         default: assert(false,"Implementation error!");
  54.                     }
  55.                     #undef PRINTBRK
  56.                     delete [] temp;
  57.                 }
  58.                 DONE_SPECIFIER:
  59.                     format_string += i;
  60.                     break;
  61.             }
  62.             default:
  63.                 putchar(*format_string); ++format_string; ++num_chars;
  64.                 break;
  65.         }
  66.         goto PARSE_CHAR;
  67. }
  68.  
  69. template <typename type> inline static void insert(char buffer[], size_t* i, type value) {
  70.     memcpy(buffer+*i,&value, sizeof(type));
  71.     *i += sizeof(type);
  72. }
  73.  
  74. int main(int /*argc*/, char* /*argv*/[]) {
  75.     char buffer[512];
  76.     size_t i = 0;
  77.  
  78.     int num_chars;
  79.     insert<double>(buffer,&i, 3.14);
  80.     insert<double>(buffer,&i, 3.14f); //Note: when calling a variadic function; floats get promoted to doubles!  So, be sure we pass in a double.
  81.     insert<int*>(buffer,&i, &num_chars);
  82.     insert<int>(buffer,&i, 12345);
  83.     insert<char const*>(buffer,&i, "Hello world!");
  84.  
  85.     PrintFormatString("double: %2.4f, float: %+2.4f, getting characters: ->%n, percent: %%, int: %10d, string: \"%s\"\n",buffer);
  86.     printf("Printed %d characters before the marked point:\n",num_chars);
  87.     for (int i=0;i<num_chars;++i) printf(" "); printf("<-");
  88.     getchar();
  89.  
  90.     return 0;
  91. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement