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

ADT ast-experimental enum forall-pointer-decay jacob/cs343-translation pthread-emulation qualifiedEnum
Last change on this file since 930609e2 was 930609e2, checked in by Jacob Prud'homme <jafprudhomme@…>, 4 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
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// *********************************** 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
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.