source: libcfa/src/parseconfig.cfa @ 930609e2

ADTast-experimentalenumforall-pointer-decayjacob/cs343-translationpthread-emulationqualifiedEnum
Last change on this file since 930609e2 was 930609e2, checked in by Jacob Prud'homme <jafprudhomme@…>, 3 years ago

Added some basic examples of validation functions

And rearranged the ordering of some declarations to avoid errors

  • Property mode set to 100644
File size: 3.6 KB
RevLine 
[1896c1f]1#include <fstream.hfa>
[8f01cb04]2#include <parseargs.hfa>
[16f9aca]3#include "parseconfig.hfa"
4
[80ae121]5
6// *********************************** exceptions ***********************************
7
8
9EHM_VIRTUAL_TABLE(Validation_Failure, Validation_Failure_main_table);
10void ?{}( Validation_Failure & this, config_entry & entry ) with ( entry ) {
11        this.virtual_table = &Validation_Failure_main_table;
12        this.key = key;
13        this.variable = variable;
14}
15void throwValidation_Failure( config_entry & entry ) {
16        Validation_Failure exc = { entry };
17}
18
19
20// *********************************** main code ***********************************
21
22
[5e0e488]23struct KVPairs {
24        int size, max_size;
25        * [ char *, char * ] data;
26};
[58ebd78]27void ?{}( KVPairs & kvp ) with ( kvp ) {        // default constructor
[5e0e488]28        size = 0; max_size = 0; data = 0p;
29}
[58ebd78]30void ?{}( KVPairs & kvp, int size ) {           // initialization
31        kvp.[ size, max_size ] = [ 0, size ];
32        kvp.data = alloc( size );
[5e0e488]33}
[58ebd78]34void ^?{}( KVPairs & kvp ) with ( kvp ) {       // destructor
[5e0e488]35        free( data );
36        size = 0; max_size = 0; data = 0p;
37}
38
[58ebd78]39void add_kv_pair( KVPairs kv_pairs, char * k, char * v ) with ( kv_pairs ) {
[5e0e488]40        if ( size == max_size ) {
[58ebd78]41                max_size *= 2;
[5e0e488]42                data = resize( data, max_size );
43        }
44
45        data[size] = [ k, v ];
46        ++size;
47}
48
[2c2d32b]49bool comments( ifstream & in, char * name ) {
[181ef73]50        while () {
[1896c1f]51                in | name;
52          if ( fail( in ) ) return true;
[2c2d32b]53          if ( name[0] != '#' ) break;
[1896c1f]54                in | nl;        // ignore remainder of line
[16f9aca]55        } // for
56        return false;
57} // comments
58
[33800ac8]59// Parse configuration from a file formatted in shell style
[58ebd78]60KVPairs & parse_shell_config_format( const char * config_file, size_t num_entries ) {
61        KVPairs kv_pairs = { num_entries };
[5e0e488]62
[4df8fef5]63        ifstream in;
[c2016b6]64        try {
[4df8fef5]65                open( in, config_file );                                                        // open the configuration file for input
[16f9aca]66
[ff3be413]67                while () {
[4df8fef5]68                        char * key;
69                        char * value;
70                  if ( comments( in, key ) ) break;                     // eof ?
[ff3be413]71                        // Should we just overwrite duplicate config entries? Having a hash map would make this much easier
[1896c1f]72                        in | value;
[d5cfc7e]73
74                        add_kv_pair( kv_pairs, key, value );
75
[1896c1f]76                  if ( fail( in ) ) break;
77                        in | nl; // ignore remainder of line
[16f9aca]78                } // for
[1896c1f]79        } catch( Open_Failure * ex; ex->istream == &in ) {
[4df8fef5]80                exit | "Error: could not open input file \"" | config_file | "\"";
[16f9aca]81        } // try
[ff3be413]82        close( in );
[e7e5b81]83
[33800ac8]84        return kv_pairs;
85}
86
[58ebd78]87// Parse configuration values from intermediate format
[33800ac8]88void parse_config( const char * config_file, config_entry entries[], size_t num_entries ) {
[58ebd78]89        KVPairs kv_pairs = parse_shell_config_format( config_file, num_entries );
[33800ac8]90
[e7e5b81]91        int entries_so_far = 0;
92        for ( i; kv_pairs.size ) {
93          if ( entries_so_far == num_entries ) break;
94
95                char * src_key, * src_value;
96                [ src_key, src_value ] = kv_pairs.data[i];
97
98                for ( j; num_entries ) {
99                  if ( strcmp( src_key, entries[j].key ) != 0 ) continue;
100                        if ( entries[j].parse( src_value, entries[j].variable ) ) {
101                                ++entries_so_far;
[6604ea1]102
103                                // Validate the parsed data, if necessary
104                                if ( entries[j].validate != 0p ) {
105                                        if ( !entries[j].validate( entries[j].variable ) ) throwValidation_Failure( entries[j] );
106                                }
107
[e7e5b81]108                                break;
109                        }
110
[58ebd78]111                        serr | "Value '" | src_value | "' for key '" | src_key | "' could not be parsed";
[e7e5b81]112                }
113        }
[16f9aca]114} // processConfigFile
115
[e7e5b81]116
[930609e2]117// *********************************** validation ***********************************
118
119
120forall(T | arithmetic( T ))
121bool is_nonnegative( T & value ) {
122        T zero_val = 0;
123        return value >= zero_val;
124}
125
126forall(T | arithmetic( T ))
127bool is_positive( T & value ) {
128        T zero_val = 0;
129        return value > zero_val;
130}
131
132forall(T | arithmetic( T ))
133bool is_nonpositive( T & value ) {
134        T zero_val = 0;
135        return value <= zero_val;
136}
137
138forall(T | arithmetic( T ))
139bool is_negative( T & value ) {
140        T zero_val = 0;
141        return value < zero_val;
142}
143
144
[16f9aca]145// Local Variables: //
146// tab-width: 4 //
147// compile-command: "cfa parseconfig.cfa" //
148// End: //
Note: See TracBrowser for help on using the repository browser.