ggformat.h (3841B)
1 #pragma once 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 /* 7 * prototypes of the functions you should be calling 8 */ 9 10 template< typename... Rest > 11 size_t ggformat( char * buf, size_t len, const char * fmt, const Rest & ... rest ); 12 13 template< typename... Rest > 14 bool ggprint_to_file( FILE * file, const char * fmt, const Rest & ... rest ); 15 16 template< typename... Rest > 17 bool ggprint( const char * fmt, const Rest & ... rest ); 18 19 /* 20 * structures and functions used for formatting specific data types 21 */ 22 23 struct FormatOpts { 24 enum NumberFormat { DECIMAL, HEX, BINARY }; 25 26 int width = -1; 27 int precision = -1; 28 bool plus_sign = false; 29 bool left_align = false; 30 bool zero_pad = false; 31 NumberFormat number_format = DECIMAL; 32 }; 33 34 struct FormatBuffer { 35 FormatBuffer( char * b, size_t c ) { 36 buf = b; 37 capacity = c; 38 len = 0; 39 } 40 41 char * buf; 42 size_t capacity; 43 size_t len; 44 }; 45 46 /* 47 * format implementations for primitive types 48 */ 49 50 void format( FormatBuffer * fb, signed char x, const FormatOpts & opts ); 51 void format( FormatBuffer * fb, short x, const FormatOpts & opts ); 52 void format( FormatBuffer * fb, int x, const FormatOpts & opts ); 53 void format( FormatBuffer * fb, long x, const FormatOpts & opts ); 54 void format( FormatBuffer * fb, long long x, const FormatOpts & opts ); 55 void format( FormatBuffer * fb, unsigned char x, const FormatOpts & opts ); 56 void format( FormatBuffer * fb, unsigned short x, const FormatOpts & opts ); 57 void format( FormatBuffer * fb, unsigned int x, const FormatOpts & opts ); 58 void format( FormatBuffer * fb, unsigned long x, const FormatOpts & opts ); 59 void format( FormatBuffer * fb, unsigned long long x, const FormatOpts & opts ); 60 void format( FormatBuffer * fb, double x, const FormatOpts & opts ); 61 void format( FormatBuffer * fb, bool x, const FormatOpts & opts ); 62 void format( FormatBuffer * fb, char x, const FormatOpts & opts ); 63 void format( FormatBuffer * fb, const char * x, const FormatOpts & opts = FormatOpts() ); 64 65 /* 66 * nasty implementation details that have to go in the header 67 */ 68 69 #include "intrinsics.h" 70 #include "platform_io.h" 71 #include "platform_pragmas.h" 72 73 FormatOpts parse_formatopts( const char * fmt, size_t len ); 74 void ggformat_impl( FormatBuffer * fb, const char * fmt ); 75 bool ggformat_find( const char * str, size_t * start, size_t * one_past_end ); 76 void ggformat_literals( FormatBuffer * fb, const char * literals, size_t len ); 77 78 PRAGMA_DISABLE_OPTIMISATIONS(); 79 80 template< typename T, typename... Rest > 81 void ggformat_impl( FormatBuffer * fb, const char * fmt, const T & first, const Rest & ... rest ) { 82 size_t start, one_past_end; 83 bool has_fmt = ggformat_find( fmt, &start, &one_past_end ); 84 ASSERT( has_fmt ); 85 86 ggformat_literals( fb, fmt, start ); 87 88 FormatOpts opts = parse_formatopts( fmt + start + 1, one_past_end - start - 1 ); 89 format( fb, first, opts ); 90 91 ggformat_impl( fb, fmt + one_past_end + 1, rest... ); 92 } 93 94 template< typename... Rest > 95 size_t ggformat( char * buf, size_t len, const char * fmt, const Rest & ... rest ) { 96 FormatBuffer fb( buf, len ); 97 ggformat_impl( &fb, fmt, rest... ); 98 return fb.len; 99 } 100 101 template< typename... Rest > 102 bool ggprint_to_file( FILE * file, const char * fmt, const Rest & ... rest ) { 103 char buf[ 4096 ]; 104 FormatBuffer fb( buf, sizeof( buf ) ); 105 ggformat_impl( &fb, fmt, rest... ); 106 107 if( fb.len < fb.capacity ) { 108 size_t written = fwrite( buf, 1, fb.len, file ); 109 return written == fb.len; 110 } 111 112 char * large_buf = ( char * ) malloc( fb.len + 1 ); 113 ASSERT( large_buf != NULL ); 114 FormatBuffer new_fb( large_buf, fb.len + 1 ); 115 ggformat_impl( &new_fb, fmt, rest... ); 116 size_t written = fwrite( large_buf, 1, fb.len, file ); 117 free( large_buf ); 118 119 return written == fb.len; 120 } 121 122 template< typename... Rest > 123 bool ggprint( const char * fmt, const Rest & ... rest ) { 124 return ggprint_to_file( stdout, fmt, rest... ); 125 } 126 127 PRAGMA_ENABLE_OPTIMISATIONS();