Go to the documentation of this file.00001
00002 #include "mbl_read_multi_props.h"
00003
00004
00005
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 #include <vcl_iterator.h>
00013
00014 #include <mbl/mbl_parse_block.h>
00015 #include <mbl/mbl_exception.h>
00016
00017 void mbl_read_multi_props_print(vcl_ostream &afs, mbl_read_multi_props_type props)
00018 {
00019 typedef mbl_read_multi_props_type::iterator ITER;
00020 afs << vsl_indent() << "{\n";
00021 vsl_indent_inc(afs);
00022 for (ITER i = props.begin(); i != props.end(); ++i)
00023 afs << vsl_indent() << (*i).first << ": " << (*i).second << '\n';
00024 vsl_indent_dec(afs);
00025 afs << vsl_indent() << "}\n";
00026 }
00027
00028
00029 static void strip_trailing_ws(vcl_string &s)
00030 {
00031 int p=s.length()-1;
00032 while (p>0 && vcl_isspace(s[p])) --p;
00033 s.erase(p+1);
00034 }
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 mbl_read_multi_props_type mbl_read_multi_props_ws(vcl_istream &afs)
00053 {
00054 if (!afs) return mbl_read_multi_props_type();
00055
00056 vcl_string label, str1;
00057
00058 while ( afs>>vcl_ws, !afs.eof() )
00059 {
00060 afs >> label;
00061 if (label.substr(0,2) =="//")
00062 {
00063
00064 vcl_getline( afs, str1 );
00065 }
00066 else break;
00067 }
00068
00069 bool need_closing_brace = false;
00070
00071 if (label[0] == '{')
00072 {
00073 need_closing_brace = true;
00074 label.erase(0,1);
00075 }
00076
00077 mbl_read_multi_props_type props;
00078
00079 if ( label.empty() )
00080 {
00081 afs >> vcl_ws;
00082
00083
00084
00085
00086
00087
00088
00089
00090 afs >> label;
00091
00092
00093
00094 }
00095
00096 typedef mbl_read_multi_props_type::iterator ITER;
00097 vcl_string last_label( label );
00098 ITER last_label_iter = props.end();
00099
00100 do
00101 {
00102 if ( label.substr(0,2) =="//" )
00103 {
00104
00105 vcl_getline(afs, str1);
00106 }
00107 else if ( need_closing_brace && label[0] == '}' )
00108 {
00109
00110 return props;
00111 }
00112 else if ( !label.empty() )
00113 {
00114 if ( label.size() > 1 &&
00115 label[label.size() -1] == ':' )
00116 {
00117 label.erase( label.size() -1, 1 );
00118 afs >> vcl_ws >> str1;
00119
00120 if ( str1.substr(0,1) == "{" )
00121 str1 = mbl_parse_block(afs, true);
00122
00123 strip_trailing_ws(str1);
00124 last_label_iter = props.insert(vcl_make_pair(label, str1));
00125 last_label = label;
00126 }
00127 else if ( label.substr(0,1) == "{" )
00128 {
00129 vcl_string block = mbl_parse_block( afs, true );
00130 if ( block.substr(0,2) != "{}" )
00131 {
00132 if (last_label_iter == props.end())
00133 {
00134 props.insert(vcl_make_pair(last_label, str1));
00135 last_label_iter = props.insert(vcl_make_pair(last_label, vcl_string(" ")+block));
00136 }
00137 else
00138 {
00139 last_label_iter->second += " ";
00140 last_label_iter->second += block;
00141 }
00142 }
00143 }
00144 else
00145 {
00146 char c;
00147 afs >> vcl_ws;
00148 afs >> c;
00149
00150 if (c != ':')
00151 {
00152 vcl_getline(afs, str1);
00153
00154
00155
00156
00157 for (int i=-1; i<256; ++i)
00158 {
00159 char c= i<0 ? '&' : char(i); vcl_string s(1,c);
00160 if (i>=32 && i<127 && c!='<')
00161 continue;
00162
00163 vcl_ostringstream os; os << "&#" << (i<0?int(c):i) << ';';
00164 vcl_string::size_type pos;
00165
00166 while ((pos=str1.find(s)) != vcl_string::npos)
00167 str1.replace(pos,1,os.str());
00168
00169 while ((pos=label.find(s)) != vcl_string::npos)
00170 label.replace(pos,1,os.str());
00171 }
00172 mbl_exception_warning(
00173 mbl_exception_read_props_parse_error( vcl_string(
00174 "Could not find colon ':' separator while reading line ")
00175 + label + " " + str1) );
00176 return props;
00177 }
00178 }
00179 }
00180
00181 afs >> vcl_ws >> label;
00182 }
00183
00184 while ( !afs.eof() );
00185
00186 if ( need_closing_brace && label != "}" )
00187 mbl_exception_warning(
00188 mbl_exception_read_props_parse_error( vcl_string(
00189 "Unexpected end of file while "
00190 "looking for '}'. Last read string = \"")
00191 + label + '"') );
00192
00193 return props;
00194 }
00195
00196
00197
00198
00199
00200 mbl_read_multi_props_type mbl_read_multi_props_merge(const mbl_read_multi_props_type& a,
00201 const mbl_read_multi_props_type& b,
00202 bool first_overrides)
00203 {
00204 mbl_read_multi_props_type output;
00205
00206 mbl_read_multi_props_type::const_iterator a_it = a.begin();
00207 mbl_read_multi_props_type::const_iterator b_it = b.begin();
00208
00209
00210 while (a_it != a.end() || b_it != b.end())
00211 {
00212 if (a_it == a.end())
00213 output.insert(*(b_it++));
00214 else if (b_it == b.end())
00215 output.insert(*(a_it++));
00216 else if (a_it->first < b_it->first)
00217 output.insert(*(a_it++));
00218 else if (a_it->first > b_it->first)
00219 output.insert(*(b_it++));
00220 else
00221 {
00222 if (first_overrides)
00223 output.insert(*a_it);
00224 else
00225 output.insert(*b_it);
00226 ++a_it; ++b_it;
00227 }
00228 }
00229 return output;
00230 }
00231
00232
00233
00234 void mbl_read_multi_props_look_for_unused_props(
00235 const vcl_string & function_name,
00236 const mbl_read_multi_props_type &props,
00237 const mbl_read_multi_props_type &ignore)
00238 {
00239 mbl_read_multi_props_type p2(props);
00240
00241
00242 for (mbl_read_multi_props_type::const_iterator it=ignore.begin();
00243 it != ignore.end(); ++it)
00244 p2.erase(it->first);
00245
00246 if (!p2.empty())
00247 {
00248 vcl_ostringstream ss;
00249 mbl_read_multi_props_print(ss, p2);
00250 mbl_exception_error(mbl_exception_unused_props(function_name, ss.str()));
00251 }
00252 }
00253
00254
00255
00256
00257
00258
00259 vcl_string mbl_read_multi_props_type::get_required_property(const vcl_string& label)
00260 {
00261 vcl_pair<mbl_read_multi_props_type::iterator, mbl_read_multi_props_type::iterator>
00262 its = this->equal_range(label);
00263 if (its.first==its.second)
00264 mbl_exception_error(mbl_exception_missing_property(label));
00265 else if (vcl_distance(its.first, its.second) > 1)
00266 mbl_exception_error(mbl_exception_read_props_parse_error(
00267 vcl_string("Property label \"") + label + "\" occurs more than once.") );
00268
00269 vcl_string s = its.first->second;
00270 this->erase(its.first);
00271 return s;
00272 }
00273
00274
00275
00276
00277
00278
00279 vcl_string mbl_read_multi_props_type::get_optional_property(
00280 const vcl_string& label, const vcl_string& default_prop )
00281 {
00282 vcl_pair<mbl_read_multi_props_type::iterator, mbl_read_multi_props_type::iterator>
00283 its = this->equal_range(label);
00284 if (its.first==its.second) return default_prop;
00285 else if (vcl_distance(its.first, its.second) > 1)
00286 mbl_exception_error(mbl_exception_read_props_parse_error(
00287 vcl_string("Property label \"") + label + "\" occurs more than once.") );
00288
00289 vcl_string s = its.first->second;
00290 this->erase(its.first);
00291 return s;
00292 }
00293
00294
00295
00296
00297 void mbl_read_multi_props_type::get_required_properties(
00298 const vcl_string& label,
00299 vcl_vector<vcl_string>& values,
00300 const unsigned nmax,
00301 const unsigned nmin)
00302 {
00303 values.clear();
00304
00305 mbl_read_multi_props_type::iterator beg = this->lower_bound(label);
00306 mbl_read_multi_props_type::iterator fin = this->upper_bound(label);
00307 if (beg==fin)
00308 mbl_exception_error(mbl_exception_missing_property(label));
00309 for (mbl_read_multi_props_type::iterator it=beg; it!=fin; ++it)
00310 {
00311 values.push_back(it->second);
00312 }
00313
00314 const unsigned nval = values.size();
00315 if (nval<nmin)
00316 {
00317 const vcl_string msg = "property label \"" + label + "\" occurs too few times.";
00318 mbl_exception_error(mbl_exception_read_props_parse_error(msg));
00319 }
00320 if (nval>nmax)
00321 {
00322 const vcl_string msg = "property label \"" + label + "\" occurs too many times.";
00323 mbl_exception_error(mbl_exception_read_props_parse_error(msg));
00324 }
00325
00326 this->erase(beg, fin);
00327 }
00328
00329
00330
00331
00332 void mbl_read_multi_props_type::get_optional_properties(
00333 const vcl_string& label,
00334 vcl_vector<vcl_string>& values,
00335 const unsigned nmax)
00336 {
00337 values.clear();
00338
00339 mbl_read_multi_props_type::iterator beg = this->lower_bound(label);
00340 mbl_read_multi_props_type::iterator fin = this->upper_bound(label);
00341
00342 for (mbl_read_multi_props_type::iterator it=beg; it!=fin; ++it)
00343 {
00344 values.push_back(it->second);
00345 }
00346
00347 const unsigned nval = values.size();
00348 if (nval>nmax)
00349 {
00350 const vcl_string msg = "property label \"" + label + "\" occurs too many times.";
00351 mbl_exception_error(mbl_exception_read_props_parse_error(msg));
00352 }
00353
00354 this->erase(beg, fin);
00355 }