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