source: libcfa/src/parseconfig.cfa @ 6604ea1

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

Added optional validation step when parsing values

  • Property mode set to 100644
File size: 3.1 KB
Line 
1#include <fstream.hfa>
2#include <parseargs.hfa>
3#include "parseconfig.hfa"
4
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
23struct KVPairs {
24        int size, max_size;
25        * [ char *, char * ] data;
26};
27void ?{}( KVPairs & kvp ) with ( kvp ) {        // default constructor
28        size = 0; max_size = 0; data = 0p;
29}
30void ?{}( KVPairs & kvp, int size ) {           // initialization
31        kvp.[ size, max_size ] = [ 0, size ];
32        kvp.data = alloc( size );
33}
34void ^?{}( KVPairs & kvp ) with ( kvp ) {       // destructor
35        free( data );
36        size = 0; max_size = 0; data = 0p;
37}
38
39void add_kv_pair( KVPairs kv_pairs, char * k, char * v ) with ( kv_pairs ) {
40        if ( size == max_size ) {
41                max_size *= 2;
42                data = resize( data, max_size );
43        }
44
45        data[size] = [ k, v ];
46        ++size;
47}
48
49bool comments( ifstream & in, char * name ) {
50        while () {
51                in | name;
52          if ( fail( in ) ) return true;
53          if ( name[0] != '#' ) break;
54                in | nl;        // ignore remainder of line
55        } // for
56        return false;
57} // comments
58
59// Parse configuration from a file formatted in shell style
60KVPairs & parse_shell_config_format( const char * config_file, size_t num_entries ) {
61        KVPairs kv_pairs = { num_entries };
62
63        ifstream in;
64        try {
65                open( in, config_file );                                                        // open the configuration file for input
66
67                while () {
68                        char * key;
69                        char * value;
70                  if ( comments( in, key ) ) break;                     // eof ?
71                        // Should we just overwrite duplicate config entries? Having a hash map would make this much easier
72                        in | value;
73
74                        add_kv_pair( kv_pairs, key, value );
75
76                  if ( fail( in ) ) break;
77                        in | nl; // ignore remainder of line
78                } // for
79        } catch( Open_Failure * ex; ex->istream == &in ) {
80                exit | "Error: could not open input file \"" | config_file | "\"";
81        } // try
82        close( in );
83
84        return kv_pairs;
85}
86
87// Parse configuration values from intermediate format
88void parse_config( const char * config_file, config_entry entries[], size_t num_entries ) {
89        KVPairs kv_pairs = parse_shell_config_format( config_file, num_entries );
90
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;
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
108                                break;
109                        }
110
111                        serr | "Value '" | src_value | "' for key '" | src_key | "' could not be parsed";
112                }
113        }
114} // processConfigFile
115
116
117// Local Variables: //
118// tab-width: 4 //
119// compile-command: "cfa parseconfig.cfa" //
120// End: //
Note: See TracBrowser for help on using the repository browser.