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