00001
00002
00003
00004
00005 #include "mbl_read_props.h"
00006 #include <vsl/vsl_indent.h>
00007 #include <vcl_sstream.h>
00008 #include <vcl_iostream.h>
00009 #include <vcl_string.h>
00010 #include <vcl_cctype.h>
00011
00012 #include <mbl/mbl_parse_block.h>
00013 #include <mbl/mbl_exception.h>
00014
00015
00016
00017
00018
00019 vcl_string mbl_read_props_type::get_required_property(const vcl_string &prop)
00020 {
00021 mbl_read_props_type::iterator it = this->find(prop);
00022 if (it==this->end())
00023 mbl_exception_error(mbl_exception_missing_property(prop));
00024 vcl_string result = it->second;
00025 this->erase(it);
00026 return result;
00027 }
00028
00029
00030
00031
00032
00033 vcl_string mbl_read_props_type::get_optional_property(const vcl_string &prop,
00034 const vcl_string &def_value )
00035 {
00036 vcl_string result(def_value);
00037 mbl_read_props_type::iterator it = this->find(prop);
00038 if (it!=this->end())
00039 {
00040 result = it->second;
00041 this->erase(it);
00042 }
00043 return result;
00044 }
00045
00046
00047 void mbl_read_props_print(vcl_ostream &afs, mbl_read_props_type props)
00048 {
00049 typedef vcl_map<vcl_string, vcl_string>::iterator ITER;
00050 afs << vsl_indent() << "{\n";
00051 vsl_indent_inc(afs);
00052 for (ITER i = props.begin(); i != props.end(); ++i)
00053 afs << vsl_indent() << (*i).first << ": " << (*i).second << '\n';
00054 vsl_indent_dec(afs);
00055 afs << vsl_indent() << "}\n";
00056 }
00057
00058
00059 static void strip_trailing_ws(vcl_string &s)
00060 {
00061 int p=s.length()-1;
00062 while (p>0 && vcl_isspace(s[p])) --p;
00063 s.erase(p+1);
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 mbl_read_props_type mbl_read_props(vcl_istream &afs)
00079 {
00080 if (!afs) return mbl_read_props_type();
00081
00082 vcl_string label, str1;
00083
00084 while ( afs>>vcl_ws, !afs.eof() )
00085 {
00086 afs >> label;
00087 if (label.substr(0,2) =="//")
00088 {
00089
00090 vcl_getline( afs, str1 );
00091 }
00092 else break;
00093 }
00094
00095 bool need_closing_brace = false;
00096
00097 if (label[0] == '{')
00098 {
00099 need_closing_brace = true;
00100 label.erase(0,1);
00101 }
00102
00103 mbl_read_props_type props;
00104
00105 if ( label.empty() )
00106 {
00107 afs >> vcl_ws;
00108
00109
00110
00111
00112
00113
00114
00115
00116 afs >> label;
00117
00118
00119
00120 }
00121
00122 vcl_string last_label( label );
00123
00124 do
00125 {
00126 if ( label.substr(0,2) =="//" )
00127 {
00128
00129 vcl_getline(afs, str1);
00130 }
00131 else if ( need_closing_brace && label[0] == '}' )
00132 {
00133
00134 return props;
00135 }
00136 else if ( !label.empty() )
00137 {
00138 if ( label.size() > 1 &&
00139 label[label.size() -1] == ':' )
00140 {
00141 label.erase( label.size() -1, 1 );
00142 afs >> vcl_ws;
00143 vcl_getline(afs, str1);
00144
00145 if ( str1.substr(0,1) == "{" )
00146 {
00147 str1 = mbl_parse_block(afs, true);
00148 }
00149
00150 strip_trailing_ws(str1);
00151 props[label] = str1;
00152 last_label = label;
00153 }
00154 else if ( label.substr(0,1) == "{" )
00155 {
00156 vcl_string block = mbl_parse_block( afs, true );
00157 if ( block.substr(0,2) != "{}" )
00158 {
00159 vcl_string prop = props[ last_label ];
00160 prop += "\n";
00161 prop += block;
00162 props[ last_label ] = prop;
00163 }
00164 }
00165 else
00166 {
00167 char c;
00168 afs >> vcl_ws;
00169 afs >> c;
00170
00171 if (c != ':')
00172 {
00173 vcl_getline(afs, str1);
00174
00175
00176
00177
00178 for (int i=-1; i<256; ++i)
00179 {
00180 char c= i<0 ? '&' : char(i); vcl_string s(1,c);
00181 if (i>=32 && i<127 && c!='<')
00182 continue;
00183
00184 vcl_ostringstream os; os << "&#" << (i<0?int(c):i) << ';';
00185 vcl_string::size_type pos;
00186
00187 while ((pos=str1.find(s)) != vcl_string::npos)
00188 str1.replace(pos,1,os.str());
00189
00190 while ((pos=label.find(s)) != vcl_string::npos)
00191 label.replace(pos,1,os.str());
00192 }
00193 mbl_exception_warning(
00194 mbl_exception_read_props_parse_error( vcl_string(
00195 "Could not find colon ':' separator while reading line ")
00196 + label + " " + str1) );
00197 return props;
00198 }
00199 }
00200 }
00201
00202 afs >> vcl_ws >> label;
00203 }
00204
00205 while ( !afs.eof() );
00206
00207 if ( need_closing_brace && label != "}" )
00208 mbl_exception_warning(
00209 mbl_exception_read_props_parse_error( vcl_string(
00210 "Unexpected end of file while "
00211 "looking for '}'. Last read string = \"")
00212 + label +'"') );
00213
00214 return props;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 mbl_read_props_type mbl_read_props_ws(vcl_istream &afs)
00235 {
00236 if (!afs) return mbl_read_props_type();
00237
00238 vcl_string label, str1;
00239
00240 while ( afs>>vcl_ws, !afs.eof() )
00241 {
00242 afs >> label;
00243 if (label.substr(0,2) =="//")
00244 {
00245
00246 vcl_getline( afs, str1 );
00247 }
00248 else break;
00249 }
00250
00251 bool need_closing_brace = false;
00252
00253 if (label[0] == '{')
00254 {
00255 need_closing_brace = true;
00256 label.erase(0,1);
00257 }
00258
00259 mbl_read_props_type props;
00260
00261 if ( label.empty() )
00262 {
00263 afs >> vcl_ws;
00264
00265
00266
00267
00268
00269
00270
00271
00272 afs >> label;
00273
00274
00275
00276 }
00277
00278 vcl_string last_label( label );
00279
00280 do
00281 {
00282 if ( label.substr(0,2) =="//" )
00283 {
00284
00285 vcl_getline(afs, str1);
00286 }
00287 else if ( need_closing_brace && label[0] == '}' )
00288 {
00289
00290 return props;
00291 }
00292 else if ( !label.empty() )
00293 {
00294 if ( label.size() > 1 &&
00295 label[label.size() -1] == ':' )
00296 {
00297 label.erase( label.size() -1, 1 );
00298
00299 char brace;
00300 afs >> vcl_ws >> brace;
00301
00302 if (brace == '{')
00303 str1 = mbl_parse_block(afs, true);
00304 else
00305 {
00306 afs.putback(brace);
00307 afs >> str1;
00308 }
00309
00310
00311 strip_trailing_ws(str1);
00312 props[label] = str1;
00313 last_label = label;
00314 }
00315 else if ( label.substr(0,1) == "{" )
00316 {
00317 vcl_string block = mbl_parse_block( afs, true );
00318 if ( block.substr(0,2) != "{}" )
00319 {
00320 vcl_string prop = props[ last_label ];
00321 prop += " ";
00322 prop += block;
00323 props[ last_label ] = prop;
00324 }
00325 }
00326 else
00327 {
00328 char c;
00329 afs >> vcl_ws;
00330 afs >> c;
00331
00332 if (c != ':')
00333 {
00334 vcl_getline(afs, str1);
00335
00336
00337
00338
00339 for (int i=-1; i<256; ++i)
00340 {
00341 char c= i<0 ? '&' : char(i); vcl_string s(1,c);
00342 if (i>=32 && i<127 && c!='<')
00343 continue;
00344
00345 vcl_ostringstream os; os << "&#" << (i<0?int(c):i) << ';';
00346 vcl_string::size_type pos;
00347
00348 while ((pos=str1.find(s)) != vcl_string::npos)
00349 str1.replace(pos,1,os.str());
00350
00351 while ((pos=label.find(s)) != vcl_string::npos)
00352 label.replace(pos,1,os.str());
00353 }
00354 mbl_exception_warning(
00355 mbl_exception_read_props_parse_error( vcl_string(
00356 "Could not find colon ':' separator while reading line ")
00357 + label + " " + str1) );
00358 return props;
00359 }
00360 }
00361 }
00362
00363 afs >> vcl_ws >> label;
00364 }
00365
00366 while ( !afs.eof() );
00367
00368 if ( need_closing_brace && label != "}" )
00369 mbl_exception_warning(
00370 mbl_exception_read_props_parse_error( vcl_string(
00371 "Unexpected end of file while "
00372 "looking for '}'. Last read string = \"")
00373 + label + '"') );
00374
00375 return props;
00376 }
00377
00378
00379
00380
00381
00382 mbl_read_props_type mbl_read_props_merge(const mbl_read_props_type& a,
00383 const mbl_read_props_type& b,
00384 bool first_overrides)
00385 {
00386 mbl_read_props_type output;
00387
00388 mbl_read_props_type::const_iterator a_it = a.begin();
00389 mbl_read_props_type::const_iterator b_it = b.begin();
00390
00391
00392 while (a_it != a.end() || b_it != b.end())
00393 {
00394 if (a_it == a.end())
00395 output.insert(*(b_it++));
00396 else if (b_it == b.end())
00397 output.insert(*(a_it++));
00398 else if (a_it->first < b_it->first)
00399 output.insert(*(a_it++));
00400 else if (a_it->first > b_it->first)
00401 output.insert(*(b_it++));
00402 else
00403 {
00404 if (first_overrides)
00405 output.insert(*a_it);
00406 else
00407 output.insert(*b_it);
00408 ++a_it; ++b_it;
00409 }
00410 }
00411 return output;
00412 }
00413
00414
00415
00416 void mbl_read_props_look_for_unused_props(
00417 const vcl_string & function_name,
00418 const mbl_read_props_type &props,
00419 const mbl_read_props_type &ignore)
00420 {
00421 mbl_read_props_type p2(props);
00422
00423
00424 for (mbl_read_props_type::const_iterator it=ignore.begin();
00425 it != ignore.end(); ++it)
00426 p2.erase(it->first);
00427
00428 if (!p2.empty())
00429 {
00430
00431 vcl_ostringstream ss;
00432 mbl_read_props_print(ss, p2);
00433 mbl_exception_error(mbl_exception_unused_props(function_name, ss.str()));
00434 }
00435 }
00436