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 if (afs.eof()) return mbl_read_props_type();
00252
00253 bool need_closing_brace = false;
00254
00255 if (label[0] == '{')
00256 {
00257 need_closing_brace = true;
00258 label.erase(0,1);
00259 }
00260
00261 mbl_read_props_type props;
00262
00263 if ( label.empty() )
00264 {
00265 afs >> vcl_ws;
00266
00267
00268
00269
00270
00271
00272
00273
00274 afs >> label;
00275
00276
00277
00278 }
00279
00280 vcl_string last_label( label );
00281
00282 do
00283 {
00284 if ( label.substr(0,2) =="//" )
00285 {
00286
00287 vcl_getline(afs, str1);
00288 }
00289 else if ( need_closing_brace && label[0] == '}' )
00290 {
00291
00292 return props;
00293 }
00294 else if ( !label.empty() )
00295 {
00296 if ( label.size() > 1 &&
00297 label[label.size() -1] == ':' )
00298 {
00299 label.erase( label.size() -1, 1 );
00300
00301 char brace;
00302 afs >> vcl_ws >> brace;
00303
00304 if (brace == '{')
00305 str1 = mbl_parse_block(afs, true);
00306 else
00307 {
00308 afs.putback(brace);
00309 afs >> str1;
00310 }
00311
00312
00313 strip_trailing_ws(str1);
00314 props[label] = str1;
00315 last_label = label;
00316 }
00317 else if ( label.substr(0,1) == "{" )
00318 {
00319 vcl_string block = mbl_parse_block( afs, true );
00320 if ( block.substr(0,2) != "{}" )
00321 {
00322 vcl_string prop = props[ last_label ];
00323 prop += " ";
00324 prop += block;
00325 props[ last_label ] = prop;
00326 }
00327 }
00328 else
00329 {
00330 char c;
00331 afs >> vcl_ws;
00332 afs >> c;
00333
00334 if (c != ':')
00335 {
00336 vcl_getline(afs, str1);
00337
00338
00339
00340
00341 for (int i=-1; i<256; ++i)
00342 {
00343 char c= i<0 ? '&' : char(i); vcl_string s(1,c);
00344 if (i>=32 && i<127 && c!='<')
00345 continue;
00346
00347 vcl_ostringstream os; os << "&#" << (i<0?int(c):i) << ';';
00348 vcl_string::size_type pos;
00349
00350 while ((pos=str1.find(s)) != vcl_string::npos)
00351 str1.replace(pos,1,os.str());
00352
00353 while ((pos=label.find(s)) != vcl_string::npos)
00354 label.replace(pos,1,os.str());
00355 }
00356 mbl_exception_warning(
00357 mbl_exception_read_props_parse_error( vcl_string(
00358 "Could not find colon ':' separator while reading line ")
00359 + label + " " + str1) );
00360 return props;
00361 }
00362 }
00363 }
00364
00365 afs >> vcl_ws >> label;
00366 }
00367
00368 while ( !afs.eof() );
00369
00370 if ( need_closing_brace && label != "}" )
00371 mbl_exception_warning(
00372 mbl_exception_read_props_parse_error( vcl_string(
00373 "Unexpected end of file while "
00374 "looking for '}'. Last read string = \"")
00375 + label + '"') );
00376
00377 return props;
00378 }
00379
00380
00381
00382
00383
00384 mbl_read_props_type mbl_read_props_merge(const mbl_read_props_type& a,
00385 const mbl_read_props_type& b,
00386 bool first_overrides)
00387 {
00388 mbl_read_props_type output;
00389
00390 mbl_read_props_type::const_iterator a_it = a.begin();
00391 mbl_read_props_type::const_iterator b_it = b.begin();
00392
00393
00394 while (a_it != a.end() || b_it != b.end())
00395 {
00396 if (a_it == a.end())
00397 output.insert(*(b_it++));
00398 else if (b_it == b.end())
00399 output.insert(*(a_it++));
00400 else if (a_it->first < b_it->first)
00401 output.insert(*(a_it++));
00402 else if (a_it->first > b_it->first)
00403 output.insert(*(b_it++));
00404 else
00405 {
00406 if (first_overrides)
00407 output.insert(*a_it);
00408 else
00409 output.insert(*b_it);
00410 ++a_it; ++b_it;
00411 }
00412 }
00413 return output;
00414 }
00415
00416
00417
00418 void mbl_read_props_look_for_unused_props(
00419 const vcl_string & function_name,
00420 const mbl_read_props_type &props,
00421 const mbl_read_props_type &ignore)
00422 {
00423 mbl_read_props_type p2(props);
00424
00425
00426 for (mbl_read_props_type::const_iterator it=ignore.begin();
00427 it != ignore.end(); ++it)
00428 p2.erase(it->first);
00429
00430 if (!p2.empty())
00431 {
00432
00433 vcl_ostringstream ss;
00434 mbl_read_props_print(ss, p2);
00435 mbl_exception_error(mbl_exception_unused_props(function_name, ss.str()));
00436 }
00437 }
00438