medfall

A super great game engine
Log | Files | Refs

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();