libshevek
src/iostring.hh
00001 /* iostring.hh - Read and write strings in parts.
00002  * Copyright 2007-2008 Bas Wijnen <wijnen@debian.org>
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation, either version 3 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #ifndef SHEVEK_IOSTRING_HH
00019 #define SHEVEK_IOSTRING_HH
00020 
00021 #include <string>
00022 #include <stack>
00023 #include <sstream>
00024 #include <glibmm.h>
00025 
00026 namespace shevek
00027 {
00029 
00032         class istring
00033         {
00034                 // The data to parse.
00035                 Glib::ustring data;
00036                 // Pointer to data still to be parsed.
00037                 std::stack <Glib::ustring::size_type> pos;
00038 
00039                 // Read a variable.
00040                 template <typename T>
00041                 bool read_var (Glib::ustring const &format, T &ret, Glib::ustring::size_type &inpos);
00042 
00043                 // Read away whitespace.
00044                 void del_whitespace ();
00045 
00046                 // Check for a constant.
00047                 bool read_const (Glib::ustring const &format, Glib::ustring::size_type &inpos);
00048         public:
00049                 // Constructors: fill data and make one stack level.
00051                 istring () { pos.push (0); }
00053                 istring (Glib::ustring const &str) { init (str); }
00055                 void init (Glib::ustring const &str)
00056                 { data = str; while (!pos.empty ()) pos.pop (); pos.push (0); }
00057 
00058                 // Stack functions.
00060                 void push () { pos.push (pos.top ()); }
00062 
00065                 int pop (bool keep = false);
00067                 void reset () { pos.top () = 0; }
00068 
00070                 Glib::ustring rest () const { return data.substr (pos.top ()); }
00071 
00073                 void skip (Glib::ustring::size_type p) { pos.top () += p; }
00074 
00076                 bool operator() (Glib::ustring const &format)
00077                 {
00078                         push ();
00079                         Glib::ustring::size_type inpos = 0;
00080                         bool ret = read_const (format, inpos)
00081                                 && inpos == format.size ();
00082                         pop (ret);
00083                         return ret;
00084                 }
00085 
00087                 template <typename T1>
00088                 bool operator() (Glib::ustring const &format, T1 &arg1)
00089                 {
00090                         push ();
00091                         Glib::ustring::size_type inpos = 0;
00092                         bool ret = read_const (format, inpos)
00093                                 && read_var (format, arg1, inpos)
00094                                 && read_const (format, inpos)
00095                                 && inpos == format.size ();
00096                         pop (ret);
00097                         return ret;
00098                 }
00099 
00101                 template <typename T1, typename T2>
00102                 bool operator() (Glib::ustring const &format, T1 &arg1,
00103                                 T2 &arg2)
00104                 {
00105                         push ();
00106                         Glib::ustring::size_type inpos = 0;
00107                         bool ret = read_const (format, inpos)
00108                                 && read_var (format, arg1, inpos)
00109                                 && read_const (format, inpos)
00110                                 && read_var (format, arg2, inpos)
00111                                 && read_const (format, inpos)
00112                                 && inpos == format.size ();
00113                         pop (ret);
00114                         return ret;
00115                 }
00116 
00118                 template <typename T1, typename T2, typename T3>
00119                 bool operator() (Glib::ustring const &format, T1 &arg1,
00120                                 T2 &arg2, T3 &arg3)
00121                 {
00122                         push ();
00123                         Glib::ustring::size_type inpos = 0;
00124                         bool ret = read_const (format, inpos)
00125                                 && read_var (format, arg1, inpos)
00126                                 && read_const (format, inpos)
00127                                 && read_var (format, arg2, inpos)
00128                                 && read_const (format, inpos)
00129                                 && read_var (format, arg3, inpos)
00130                                 && read_const (format, inpos)
00131                                 && inpos == format.size ();
00132                         pop (ret);
00133                         return ret;
00134                 }
00135 
00137                 template <typename T1, typename T2, typename T3, typename T4>
00138                 bool operator() (Glib::ustring const &format, T1 &arg1,
00139                                 T2 &arg2, T3 &arg3, T4 &arg4)
00140                 {
00141                         push ();
00142                         Glib::ustring::size_type inpos = 0;
00143                         bool ret = read_const (format, inpos)
00144                                 && read_var (format, arg1, inpos)
00145                                 && read_const (format, inpos)
00146                                 && read_var (format, arg2, inpos)
00147                                 && read_const (format, inpos)
00148                                 && read_var (format, arg3, inpos)
00149                                 && read_const (format, inpos)
00150                                 && read_var (format, arg4, inpos)
00151                                 && read_const (format, inpos)
00152                                 && inpos == format.size ();
00153                         pop (ret);
00154                         return ret;
00155                 }
00156 
00158                 template <typename T1, typename T2, typename T3, typename T4,
00159                          typename T5>
00160                 bool operator() (Glib::ustring const &format, T1 &arg1,
00161                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5)
00162                 {
00163                         push ();
00164                         Glib::ustring::size_type inpos = 0;
00165                         bool ret = read_const (format, inpos)
00166                                 && read_var (format, arg1, inpos)
00167                                 && read_const (format, inpos)
00168                                 && read_var (format, arg2, inpos)
00169                                 && read_const (format, inpos)
00170                                 && read_var (format, arg3, inpos)
00171                                 && read_const (format, inpos)
00172                                 && read_var (format, arg4, inpos)
00173                                 && read_const (format, inpos)
00174                                 && read_var (format, arg5, inpos)
00175                                 && read_const (format, inpos)
00176                                 && inpos == format.size ();
00177                         pop (ret);
00178                         return ret;
00179                 }
00180 
00182                 template <typename T1, typename T2, typename T3, typename T4,
00183                          typename T5, typename T6>
00184                 bool operator() (Glib::ustring const &format, T1 &arg1,
00185                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5,
00186                                 T6 &arg6)
00187                 {
00188                         push ();
00189                         Glib::ustring::size_type inpos = 0;
00190                         bool ret = read_const (format, inpos)
00191                                 && read_var (format, arg1, inpos)
00192                                 && read_const (format, inpos)
00193                                 && read_var (format, arg2, inpos)
00194                                 && read_const (format, inpos)
00195                                 && read_var (format, arg3, inpos)
00196                                 && read_const (format, inpos)
00197                                 && read_var (format, arg4, inpos)
00198                                 && read_const (format, inpos)
00199                                 && read_var (format, arg5, inpos)
00200                                 && read_const (format, inpos)
00201                                 && read_var (format, arg6, inpos)
00202                                 && read_const (format, inpos)
00203                                 && inpos == format.size ();
00204                         pop (ret);
00205                         return ret;
00206                 }
00207 
00209                 template <typename T1, typename T2, typename T3, typename T4,
00210                          typename T5, typename T6, typename T7>
00211                 bool operator() (Glib::ustring const &format, T1 &arg1,
00212                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5,
00213                                 T6 &arg6, T7 &arg7)
00214                 {
00215                         push ();
00216                         Glib::ustring::size_type inpos = 0;
00217                         bool ret = read_const (format, inpos)
00218                                 && read_var (format, arg1, inpos)
00219                                 && read_const (format, inpos)
00220                                 && read_var (format, arg2, inpos)
00221                                 && read_const (format, inpos)
00222                                 && read_var (format, arg3, inpos)
00223                                 && read_const (format, inpos)
00224                                 && read_var (format, arg4, inpos)
00225                                 && read_const (format, inpos)
00226                                 && read_var (format, arg5, inpos)
00227                                 && read_const (format, inpos)
00228                                 && read_var (format, arg6, inpos)
00229                                 && read_const (format, inpos)
00230                                 && read_var (format, arg7, inpos)
00231                                 && read_const (format, inpos)
00232                                 && inpos == format.size ();
00233                         pop (ret);
00234                         return ret;
00235                 }
00236 
00238                 template <typename T1, typename T2, typename T3, typename T4,
00239                          typename T5, typename T6, typename T7, typename T8>
00240                 bool operator() (Glib::ustring const &format, T1 &arg1,
00241                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5,
00242                                 T6 &arg6, T7 &arg7, T8 &arg8)
00243                 {
00244                         push ();
00245                         Glib::ustring::size_type inpos = 0;
00246                         bool ret = read_const (format, inpos)
00247                                 && read_var (format, arg1, inpos)
00248                                 && read_const (format, inpos)
00249                                 && read_var (format, arg2, inpos)
00250                                 && read_const (format, inpos)
00251                                 && read_var (format, arg3, inpos)
00252                                 && read_const (format, inpos)
00253                                 && read_var (format, arg4, inpos)
00254                                 && read_const (format, inpos)
00255                                 && read_var (format, arg5, inpos)
00256                                 && read_const (format, inpos)
00257                                 && read_var (format, arg6, inpos)
00258                                 && read_const (format, inpos)
00259                                 && read_var (format, arg7, inpos)
00260                                 && read_const (format, inpos)
00261                                 && read_var (format, arg8, inpos)
00262                                 && read_const (format, inpos)
00263                                 && inpos == format.size ();
00264                         pop (ret);
00265                         return ret;
00266                 }
00267 
00269 
00272                 template <typename T>
00273                 static T direct (Glib::ustring const &data,
00274                                 Glib::ustring const &format,
00275                                 T def = T ())
00276                 {
00277                         T ret;
00278                         istring tmp (data);
00279                         if (!tmp (format, ret))
00280                                 ret = def;
00281                         return ret;
00282                 }
00283         };
00284 
00286 
00289         template <typename T>
00290         bool istring::read_var (Glib::ustring const &format, T &ret,
00291                         Glib::ustring::size_type &inpos)
00292         {
00293                 ++inpos;
00294                 std::istringstream s (data.substr (pos.top ()));
00295                 s >> ret;
00296                 std::streampos p = s.tellg ();
00297                 if (!s || p < 0)
00298                         return false;
00299                 pos.top () += p;
00300                 return true;
00301         }
00302 
00304         template <> bool istring::read_var <double> (Glib::ustring const &format, double &ret, Glib::ustring::size_type &inpos);
00305 
00307         template <> bool istring::read_var <float> (Glib::ustring const &format, float &ret, Glib::ustring::size_type &inpos);
00308 
00310         template <> bool istring::read_var <Glib::ustring> (Glib::ustring const &format, Glib::ustring &ret, Glib::ustring::size_type &inpos);
00311 
00313         template <> bool istring::read_var <int> (Glib::ustring const &format, int &ret, Glib::ustring::size_type &inpos);
00314 
00316         template <> bool istring::read_var <unsigned> (Glib::ustring const &format, unsigned &ret, Glib::ustring::size_type &inpos);
00317 
00319 
00322         class ostring
00323         {
00324                 Glib::ustring data;
00325                 Glib::ustring format;
00326                 Glib::ustring::size_type pos;
00327                 void write_const ();
00328                 template <typename T> void write_var (T const &a,
00329                                 Glib::ustring const &flags,
00330                                 unsigned width, unsigned precision);
00331                 template <typename T> void write_var_raw (T const &a);
00332                 ostring &init (Glib::ustring const &f);
00333                 // If you get a linker error to this line, you have tried to insert a std::string into a shevek::ostring.
00334                 // Fix the program by turning it into a Glib::ustring first, or by using a shevek::rostring instead.
00335                 template <typename T> ostring &operator ()(T const &a) { write_const (); write_var_raw (a); return *this; }
00336                 ostring &operator ()();
00337         public:
00339                 operator Glib::ustring () const { return data; }
00341                 Glib::ustring operator+ (Glib::ustring const &that) const { return data + that; }
00343                 friend std::ostream &operator<< (std::ostream &s, ostring const &o) { return s << o.data; }
00345                 ostring (Glib::ustring const &fmt) { init (fmt)(); }
00347                 template <typename T1>
00348                 ostring (Glib::ustring const &fmt, T1 const &a1)
00349                 { init (fmt)(a1)(); }
00351                 template <typename T1, typename T2>
00352                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2)
00353                 { init (fmt)(a1)(a2)(); }
00355                 template <typename T1, typename T2, typename T3>
00356                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00357                                 T3 const &a3)
00358                 { init (fmt)(a1)(a2)(a3)(); }
00360                 template <typename T1, typename T2, typename T3, typename T4>
00361                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00362                                 T3 const &a3, T4 const &a4)
00363                 { init (fmt)(a1)(a2)(a3)(a4)(); }
00365                 template <typename T1, typename T2, typename T3, typename T4,
00366                          typename T5>
00367                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00368                                 T3 const &a3, T4 const &a4, T5 const &a5)
00369                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(); }
00371                 template <typename T1, typename T2, typename T3, typename T4,
00372                          typename T5, typename T6>
00373                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00374                                 T3 const &a3, T4 const &a4, T5 const &a5,
00375                                 T6 const &a6)
00376                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(); }
00378                 template <typename T1, typename T2, typename T3, typename T4,
00379                          typename T5, typename T6, typename T7>
00380                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00381                                 T3 const &a3, T4 const &a4, T5 const &a5,
00382                                 T6 const &a6, T7 const &a7)
00383                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(a7)(); }
00385                 template <typename T1, typename T2, typename T3, typename T4,
00386                          typename T5, typename T6, typename T7 ,typename T8>
00387                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00388                                 T3 const &a3, T4 const &a4, T5 const &a5,
00389                                 T6 const &a6, T7 const &a7, T8 const &a8)
00390                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(); }
00392                 template <typename T1, typename T2, typename T3, typename T4,
00393                          typename T5, typename T6, typename T7 ,typename T8,
00394                          typename T9>
00395                 ostring (Glib::ustring const &fmt, T1 const &a1, T2 const &a2,
00396                                 T3 const &a3, T4 const &a4, T5 const &a5,
00397                                 T6 const &a6, T7 const &a7, T8 const &a8,
00398                                 T9 const &a9)
00399                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(); }
00400         };
00401 
00403 
00405         template <typename T> void ostring::write_var_raw (T const &a)
00406         {
00407                 unsigned width = 0, precision = 0;
00408                 Glib::ustring flags;
00409                 while (pos < format.size ()
00410                                 && (format[pos] < 'a' || format[pos] > 'z')
00411                                 && (format[pos] < 'A' || format[pos] > 'Z')
00412                                 && (format[pos] < '1' || format[pos] > '9'))
00413                         flags += format[pos++];
00414                 while (pos < format.size () && format[pos] >= '0'
00415                                 && format[pos] <= '9')
00416                 {
00417                         width *= 10;
00418                         width += format[pos++] - '0';
00419                 }
00420                 if (pos < format.size () && format[pos] == '.')
00421                 {
00422                         ++pos;
00423                         while (pos < format.size () && format[pos] >= '0'
00424                                         && format[pos] <= '9')
00425                         {
00426                                 precision *= 10;
00427                                 precision += format[pos++] - '0';
00428                         }
00429                 }
00430                 return write_var (a, flags, width, precision);
00431         }
00432 
00434 
00436         template <typename T> void ostring::write_var (T const &a,
00437                         Glib::ustring const &flags,
00438                         unsigned width, unsigned precision)
00439         {
00440                 (void)flags;
00441                 (void)width;
00442                 (void)precision;
00443                 if (pos < format.size ())
00444                         ++pos;
00445                 std::ostringstream s;
00446                 s << a;
00447                 data += s.str ();
00448         }
00449 
00451         template <> void ostring::write_var <unsigned short> (unsigned short const &a, Glib::ustring const &flags, unsigned width, unsigned precision);
00453         template <> void ostring::write_var <short> (short const &a, Glib::ustring const &flags, unsigned width, unsigned precision);
00455         template <> void ostring::write_var <unsigned> (unsigned const &a, Glib::ustring const &flags, unsigned width, unsigned precision);
00457         template <> void ostring::write_var <int> (int const &a, Glib::ustring const &flags, unsigned width, unsigned precision);
00459         template <> void ostring::write_var <Glib::ustring> (Glib::ustring const &a, Glib::ustring const &flags, unsigned width, unsigned precision);
00460 
00462 
00465         template <> void ostring::write_var_raw <std::string> (std::string const &a);
00466         template <> bool istring::read_var <std::string> (Glib::ustring const &format, std::string &ret, Glib::ustring::size_type &inpos);
00467 
00469         class ristring
00470         {
00471                 // The data to parse.
00472                 std::string data;
00473                 // Pointer to data still to be parsed.
00474                 std::stack <std::string::size_type> pos;
00475 
00476                 // Read a variable.
00477                 template <typename T>
00478                 bool read_var (std::string const &format, T &ret, std::string::size_type &inpos);
00479 
00480                 // Read away whitespace.
00481                 void del_whitespace ();
00482 
00483                 // Check for a constant.
00484                 bool read_const (std::string const &format, std::string::size_type &inpos);
00485         public:
00486                 // Constructors: fill data and make one stack level.
00488                 ristring () { pos.push (0); }
00490                 ristring (std::string const &str) { init (str); }
00492                 void init (std::string const &str) { data = str; while (!pos.empty ()) pos.pop (); pos.push (0); }
00493 
00494                 // Stack functions.
00496                 void push () { pos.push (pos.top ()); }
00498 
00501                 int pop (bool keep = false);
00503                 void reset () { pos.top () = 0; }
00504 
00506                 std::string rest () const { return data.substr (pos.top ()); }
00507 
00509                 void skip (std::string::size_type p) { pos.top () += p; }
00510 
00512                 bool operator() (std::string const &format)
00513                 {
00514                         push ();
00515                         std::string::size_type inpos = 0;
00516                         bool ret = read_const (format, inpos)
00517                                 && inpos == format.size ();
00518                         pop (ret);
00519                         return ret;
00520                 }
00521 
00523                 template <typename T1>
00524                 bool operator() (std::string const &format, T1 &arg1)
00525                 {
00526                         push ();
00527                         std::string::size_type inpos = 0;
00528                         bool ret = read_const (format, inpos)
00529                                 && read_var (format, arg1, inpos)
00530                                 && read_const (format, inpos)
00531                                 && inpos == format.size ();
00532                         pop (ret);
00533                         return ret;
00534                 }
00535 
00537                 template <typename T1, typename T2>
00538                 bool operator() (std::string const &format, T1 &arg1,
00539                                 T2 &arg2)
00540                 {
00541                         push ();
00542                         std::string::size_type inpos = 0;
00543                         bool ret = read_const (format, inpos)
00544                                 && read_var (format, arg1, inpos)
00545                                 && read_const (format, inpos)
00546                                 && read_var (format, arg2, inpos)
00547                                 && read_const (format, inpos)
00548                                 && inpos == format.size ();
00549                         pop (ret);
00550                         return ret;
00551                 }
00552 
00554                 template <typename T1, typename T2, typename T3>
00555                 bool operator() (std::string const &format, T1 &arg1,
00556                                 T2 &arg2, T3 &arg3)
00557                 {
00558                         push ();
00559                         std::string::size_type inpos = 0;
00560                         bool ret = read_const (format, inpos)
00561                                 && read_var (format, arg1, inpos)
00562                                 && read_const (format, inpos)
00563                                 && read_var (format, arg2, inpos)
00564                                 && read_const (format, inpos)
00565                                 && read_var (format, arg3, inpos)
00566                                 && read_const (format, inpos)
00567                                 && inpos == format.size ();
00568                         pop (ret);
00569                         return ret;
00570                 }
00571 
00573                 template <typename T1, typename T2, typename T3, typename T4>
00574                 bool operator() (std::string const &format, T1 &arg1,
00575                                 T2 &arg2, T3 &arg3, T4 &arg4)
00576                 {
00577                         push ();
00578                         std::string::size_type inpos = 0;
00579                         bool ret = read_const (format, inpos)
00580                                 && read_var (format, arg1, inpos)
00581                                 && read_const (format, inpos)
00582                                 && read_var (format, arg2, inpos)
00583                                 && read_const (format, inpos)
00584                                 && read_var (format, arg3, inpos)
00585                                 && read_const (format, inpos)
00586                                 && read_var (format, arg4, inpos)
00587                                 && read_const (format, inpos)
00588                                 && inpos == format.size ();
00589                         pop (ret);
00590                         return ret;
00591                 }
00592 
00594                 template <typename T1, typename T2, typename T3, typename T4,
00595                          typename T5>
00596                 bool operator() (std::string const &format, T1 &arg1,
00597                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5)
00598                 {
00599                         push ();
00600                         std::string::size_type inpos = 0;
00601                         bool ret = read_const (format, inpos)
00602                                 && read_var (format, arg1, inpos)
00603                                 && read_const (format, inpos)
00604                                 && read_var (format, arg2, inpos)
00605                                 && read_const (format, inpos)
00606                                 && read_var (format, arg3, inpos)
00607                                 && read_const (format, inpos)
00608                                 && read_var (format, arg4, inpos)
00609                                 && read_const (format, inpos)
00610                                 && read_var (format, arg5, inpos)
00611                                 && read_const (format, inpos)
00612                                 && inpos == format.size ();
00613                         pop (ret);
00614                         return ret;
00615                 }
00616 
00618                 template <typename T1, typename T2, typename T3, typename T4,
00619                          typename T5, typename T6>
00620                 bool operator() (std::string const &format, T1 &arg1,
00621                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5,
00622                                 T6 &arg6)
00623                 {
00624                         push ();
00625                         std::string::size_type inpos = 0;
00626                         bool ret = read_const (format, inpos)
00627                                 && read_var (format, arg1, inpos)
00628                                 && read_const (format, inpos)
00629                                 && read_var (format, arg2, inpos)
00630                                 && read_const (format, inpos)
00631                                 && read_var (format, arg3, inpos)
00632                                 && read_const (format, inpos)
00633                                 && read_var (format, arg4, inpos)
00634                                 && read_const (format, inpos)
00635                                 && read_var (format, arg5, inpos)
00636                                 && read_const (format, inpos)
00637                                 && read_var (format, arg6, inpos)
00638                                 && read_const (format, inpos)
00639                                 && inpos == format.size ();
00640                         pop (ret);
00641                         return ret;
00642                 }
00643 
00645                 template <typename T1, typename T2, typename T3, typename T4,
00646                          typename T5, typename T6, typename T7>
00647                 bool operator() (std::string const &format, T1 &arg1,
00648                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5,
00649                                 T6 &arg6, T7 &arg7)
00650                 {
00651                         push ();
00652                         std::string::size_type inpos = 0;
00653                         bool ret = read_const (format, inpos)
00654                                 && read_var (format, arg1, inpos)
00655                                 && read_const (format, inpos)
00656                                 && read_var (format, arg2, inpos)
00657                                 && read_const (format, inpos)
00658                                 && read_var (format, arg3, inpos)
00659                                 && read_const (format, inpos)
00660                                 && read_var (format, arg4, inpos)
00661                                 && read_const (format, inpos)
00662                                 && read_var (format, arg5, inpos)
00663                                 && read_const (format, inpos)
00664                                 && read_var (format, arg6, inpos)
00665                                 && read_const (format, inpos)
00666                                 && read_var (format, arg7, inpos)
00667                                 && read_const (format, inpos)
00668                                 && inpos == format.size ();
00669                         pop (ret);
00670                         return ret;
00671                 }
00672 
00674                 template <typename T1, typename T2, typename T3, typename T4,
00675                          typename T5, typename T6, typename T7, typename T8>
00676                 bool operator() (std::string const &format, T1 &arg1,
00677                                 T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5,
00678                                 T6 &arg6, T7 &arg7, T8 &arg8)
00679                 {
00680                         push ();
00681                         std::string::size_type inpos = 0;
00682                         bool ret = read_const (format, inpos)
00683                                 && read_var (format, arg1, inpos)
00684                                 && read_const (format, inpos)
00685                                 && read_var (format, arg2, inpos)
00686                                 && read_const (format, inpos)
00687                                 && read_var (format, arg3, inpos)
00688                                 && read_const (format, inpos)
00689                                 && read_var (format, arg4, inpos)
00690                                 && read_const (format, inpos)
00691                                 && read_var (format, arg5, inpos)
00692                                 && read_const (format, inpos)
00693                                 && read_var (format, arg6, inpos)
00694                                 && read_const (format, inpos)
00695                                 && read_var (format, arg7, inpos)
00696                                 && read_const (format, inpos)
00697                                 && read_var (format, arg8, inpos)
00698                                 && read_const (format, inpos)
00699                                 && inpos == format.size ();
00700                         pop (ret);
00701                         return ret;
00702                 }
00703 
00705 
00708                 template <typename T>
00709                 static T direct (std::string const &data,
00710                                 std::string const &format,
00711                                 T def = T ())
00712                 {
00713                         T ret;
00714                         istring tmp (data);
00715                         if (!tmp (format, ret))
00716                                 ret = def;
00717                         return ret;
00718                 }
00719         };
00720 
00722 
00725         template <typename T>
00726         bool ristring::read_var (std::string const &format, T &ret,
00727                         std::string::size_type &inpos)
00728         {
00729                 ++inpos;
00730                 std::istringstream s (data.substr (pos.top ()));
00731                 s >> ret;
00732                 std::streampos p = s.tellg ();
00733                 if (!s || p < 0)
00734                         return false;
00735                 pos.top () += p;
00736                 return true;
00737         }
00738 
00740         template <>
00741         bool ristring::read_var <double> (std::string const &format,
00742                         double &ret, std::string::size_type &inpos);
00743 
00745         template <>
00746         bool ristring::read_var <float> (std::string const &format,
00747                         float &ret, std::string::size_type &inpos);
00748 
00750         template <>
00751         bool ristring::read_var <std::string> (std::string const &format,
00752                         std::string &ret, std::string::size_type &inpos);
00753 
00755         template <>
00756         bool ristring::read_var <int> (std::string const &format,
00757                         int &ret, std::string::size_type &inpos);
00758 
00760         template <>
00761         bool ristring::read_var <unsigned> (std::string const &format,
00762                         unsigned &ret, std::string::size_type &inpos);
00763 
00765         class rostring
00766         {
00767                 std::string data;
00768                 std::string format;
00769                 std::string::size_type pos;
00770                 void write_const ();
00771                 template <typename T> void write_var (T const &a,
00772                                 std::string const &flags,
00773                                 unsigned width, unsigned precision);
00774                 template <typename T> void write_var_raw (T const &a);
00775                 rostring &init (std::string const &f);
00776                 template <typename T> rostring &operator ()(T const &a)
00777                 { write_const (); write_var_raw (a); return *this; }
00778                 rostring &operator ()();
00779         public:
00781                 operator std::string () const { return data; }
00783                 std::string operator+ (std::string const &that) const { return data + that; }
00785                 friend std::ostream &operator<< (std::ostream &s, rostring const &o) { return s << o.data; }
00787                 rostring (std::string const &fmt)
00788                 { init (fmt)(); }
00790                 template <typename T1>
00791                 rostring (std::string const &fmt, T1 const &a1)
00792                 { init (fmt)(a1)(); }
00794                 template <typename T1, typename T2>
00795                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2)
00796                 { init (fmt)(a1)(a2)(); }
00798                 template <typename T1, typename T2, typename T3>
00799                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3)
00800                 { init (fmt)(a1)(a2)(a3)(); }
00802                 template <typename T1, typename T2, typename T3, typename T4>
00803                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4)
00804                 { init (fmt)(a1)(a2)(a3)(a4)(); }
00806                 template <typename T1, typename T2, typename T3, typename T4, typename T5>
00807                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5)
00808                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(); }
00810                 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
00811                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6)
00812                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(); }
00814                 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
00815                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6, T7 const &a7)
00816                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(a7)(); }
00818                 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 ,typename T8>
00819                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6, T7 const &a7, T8 const &a8)
00820                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(); }
00822                 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 ,typename T8, typename T9>
00823                 rostring (std::string const &fmt, T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6, T7 const &a7, T8 const &a8, T9 const &a9)
00824                 { init (fmt)(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(); }
00825         };
00826 
00828 
00830         template <typename T> void rostring::write_var_raw (T const &a)
00831         {
00832                 unsigned width = 0, precision = 0;
00833                 std::string flags;
00834                 while (pos < format.size ()
00835                                 && (format[pos] < 'a' || format[pos] > 'z')
00836                                 && (format[pos] < 'A' || format[pos] > 'Z')
00837                                 && (format[pos] < '1' || format[pos] > '9'))
00838                         flags += format[pos++];
00839                 while (pos < format.size () && format[pos] >= '0'
00840                                 && format[pos] <= '9')
00841                 {
00842                         width *= 10;
00843                         width += format[pos++] - '0';
00844                 }
00845                 if (pos < format.size () && format[pos] == '.')
00846                 {
00847                         ++pos;
00848                         while (pos < format.size () && format[pos] >= '0'
00849                                         && format[pos] <= '9')
00850                         {
00851                                 precision *= 10;
00852                                 precision += format[pos++] - '0';
00853                         }
00854                 }
00855                 return write_var (a, flags, width, precision);
00856         }
00857 
00859 
00861         template <typename T> void rostring::write_var (T const &a, std::string const &flags, unsigned width, unsigned precision)
00862         {
00863                 (void)flags;
00864                 (void)width;
00865                 (void)precision;
00866                 if (pos < format.size ())
00867                         ++pos;
00868                 std::ostringstream s;
00869                 s << a;
00870                 data += s.str ();
00871         }
00872 
00874 
00876         template <> void rostring::write_var <unsigned> (unsigned const &a, std::string const &flags, unsigned width, unsigned precision);
00878 
00880         template <> void rostring::write_var <int> (int const &a, std::string const &flags, unsigned width, unsigned precision);
00881 
00883 
00886         template <> void rostring::write_var_raw <Glib::ustring> (Glib::ustring const &a);
00887         template <> bool ristring::read_var <Glib::ustring> (std::string const &format, Glib::ustring &ret, std::string::size_type &inpos);
00888 }
00889 
00890 #endif