#include #include #include "parseconfig.hfa" struct KVPairs { int size, max_size; * [ char *, char * ] data; }; void ?{}( VLA & vla ) with ( vla ) { // default constructor size = 0; max_size = 0; data = 0p; } void ?{}( VLA & vla, int size, char fill = ['\0', '\0'] ) { // initialization vla.[ size, max_size, data ] = [ 0, max_size, alloc( size, fill ) ]; } void ?{}( VLA & vla, VLA val ) with( val ) { // copy, deep vla.[ size, max_size, data ] = [ size, max_size, alloc( size, data ) ]; } void ^?{}( VLA & vla ) with ( vla ) { // destructor free( data ); size = 0; max_size = 0; data = 0p; } void add_kv_pair( KVPairs kv_pairs, char * k, char * v ) with( kv_pairs ) { if ( size == max_size ) { max_size = max_size * 2; data = resize( data, max_size ); } data[size] = [ k, v ]; ++size; } bool comments( ifstream & in, char * name ) { while () { in | name; if ( fail( in ) ) return true; if ( name[0] != '#' ) break; in | nl; // ignore remainder of line } // for return false; } // comments // Process the configuration file to set the simulation parameters. void parse_config( const char * config_file, config_entry entries[], size_t num_entries ) { KVPairs kv_pairs{ num_entries }; ifstream in; try { open( in, config_file ); // open the configuration file for input while () { char * key; char * value; if ( comments( in, key ) ) break; // eof ? // Should we just overwrite duplicate config entries? Having a hash map would make this much easier in | value; add_kv_pair( kv_pairs, key, value ); if ( fail( in ) ) break; in | nl; // ignore remainder of line } // for } catch( Open_Failure * ex; ex->istream == &in ) { exit | "Error: could not open input file \"" | config_file | "\""; } // try close( in ); // *** WE MUST ALLOW SOME SORT OF VALIDATION FUNCTIONALITY TOO!!! *** int entries_so_far = 0; for ( i; kv_pairs.size ) { if ( entries_so_far == num_entries ) break; char * src_key, * src_value; [ src_key, src_value ] = kv_pairs.data[i]; for ( j; num_entries ) { if ( strcmp( src_key, entries[j].key ) != 0 ) continue; if ( entries[j].parse( src_value, entries[j].variable ) ) { ++entries_so_far; break; } serr | "Value " | src_value | " for key " | dest_key | " could not be parsed"; } } } // processConfigFile //----------------------------------------------------------------------------- // Typed argument parsing bool parse( const char * arg, const char * & value ) { value = arg; return true; } bool parse( const char * arg, int & value ) { char * end; int r = strtoll( arg, &end, 10 ); if ( *end != '\0' ) return false; value = r; return true; } bool parse( const char * arg, unsigned & value ) { char * end; unsigned long long int r = strtoull( arg, &end, 10 ); if ( *end != '\0' ) return false; if ( r > (unsigned)MAX ) return false; value = r; return true; } bool parse( const char * arg, unsigned long & value ) { char * end; unsigned long long int r = strtoull( arg, &end, 10 ); if ( *end != '\0' ) return false; if ( r > (unsigned long)MAX ) return false; value = r; return true; } bool parse( const char * arg, unsigned long long & value ) { char * end; unsigned long long int r = strtoull( arg, &end, 10 ); if ( *end != '\0' ) return false; if ( r > (unsigned long long)MAX ) return false; value = r; return true; } bool parse( const char * arg, float & value ) { char * end; float r = strtof( arg, &end ); if ( *end != '\0' ) return false; value = r; return true; } bool parse( const char * arg, double & value ) { char * end; double r = strtod( arg, &end ); if ( *end != '\0' ) return false; value = r; return true; } // Local Variables: // // tab-width: 4 // // compile-command: "cfa parseconfig.cfa" // // End: //