Siena Simplification Library Documentation (v. 1.1.5)

ssimp_types.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 //  This file is part of Siena, a wide-area event notification system.
00004 //  See http://www.cs.colorado.edu/serl/siena/
00005 //
00006 //  Authors: See the file AUTHORS for full details.
00007 //
00008 //  Copyright (C) 2002-2004 University of Colorado
00009 //
00010 //  This program is free software; you can redistribute it and/or
00011 //  modify it under the terms of the GNU General Public License
00012 //  as published by the Free Software Foundation; either version 2
00013 //  of the License, or (at your option) any later version.
00014 //
00015 //  This program is distributed in the hope that it will be useful,
00016 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //  GNU General Public License for more details.
00019 //
00020 //  You should have received a copy of the GNU General Public License
00021 //  along with this program; if not, write to the Free Software
00022 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
00023 //  USA, or send email to serl@cs.colorado.edu.
00024 //
00025 // $Id: ssimp_types.h,v 1.9 2008-08-21 15:34:10 carzanig Exp $
00026 //
00027 #ifndef SIMP_TYPES_H
00028 #define SIMP_TYPES_H
00029 
00030 #include <map>
00031 #include <set>
00032 #include <sstream>
00033 #include <string>
00034 #include "siena/simplify.h"
00035 
00036 namespace ssimp {
00037 
00048 class Constraint : public siena::constraint
00049 {
00050   class Value
00051   {
00052   public:
00053     Value( bool b )
00054       : m_type( siena::bool_id ), m_bool( b ),
00055         m_bytesize( sizeof( siena::type_id ) + sizeof( bool ) ) {}
00056 
00057     Value( double d )
00058       : m_type( siena::double_id ), m_double( d ),
00059         m_bytesize( sizeof( siena::type_id ) + sizeof( double ) ) {}
00060 
00061     Value( int i )
00062       : m_type( siena::int_id ), m_int( i ),
00063         m_bytesize( sizeof( siena::type_id ) + sizeof( int ) ) {}
00064 
00065     Value( const std::string& s )
00066       : m_type( siena::string_id ), m_string( s ),
00067         m_bytesize( sizeof( siena::type_id ) + s.length() ) {}
00068 
00069     Value()
00070       : m_type( siena::anytype_id ), m_int( 0 ),
00071         m_bytesize( sizeof( siena::type_id ) ) {}
00072 
00073     Value( const Value& v )
00074     {
00075       m_type = v.m_type;
00076       switch( m_type )
00077         {
00078         case siena::bool_id: m_bool = v.m_bool; break;
00079         case siena::double_id: m_double = v.m_double; break;
00080         case siena::anytype_id:
00081         case siena::int_id: m_int = v.m_int; break;
00082         default: m_string = v.m_string;
00083         }
00084       m_bytesize = v.m_bytesize;
00085     }
00086 
00087     const Value& operator= ( const Value& v )
00088     {
00089       m_type = v.m_type;
00090       switch( m_type )
00091         {
00092         case siena::bool_id: m_bool = v.m_bool; break;
00093         case siena::double_id: m_double = v.m_double; break;
00094         case siena::anytype_id:
00095         case siena::int_id: m_int = v.m_int; break;
00096         default: m_string = v.m_string;
00097         }
00098       m_bytesize = v.m_bytesize;
00099       return (*this);
00100     }
00101 
00102     bool operator== ( const Value& v ) const
00103     {
00104       if( m_type != v.m_type ) { return false; }
00105       switch( m_type )
00106         {
00107         case siena::bool_id: return m_bool == v.m_bool;
00108         case siena::double_id: return m_double == v.m_double;
00109         case siena::int_id: return m_int == v.m_int;
00110         case siena::anytype_id: return true;
00111         default: return m_string == v.m_string;
00112         }
00113     }
00114 
00115     bool operator< ( const Value& v ) const
00116     {
00117       if( m_type != v.m_type ) { return m_type < v.m_type; }
00118       switch( m_type )
00119         {
00120         case siena::bool_id: return m_bool < v.m_bool;
00121         case siena::double_id: return m_double < v.m_double;
00122         case siena::int_id: return m_int < v.m_int;
00123         case siena::anytype_id: return false;
00124         default: return m_string < v.m_string;
00125         }
00126     }
00127 
00128     bool operator> ( const Value& v ) const
00129     {
00130       if( m_type != v.m_type ) { return m_type > v.m_type; }
00131       switch( m_type )
00132         {
00133         case siena::bool_id: return m_bool > v.m_bool;
00134         case siena::double_id: return m_double > v.m_double;
00135         case siena::int_id: return m_int > v.m_int;
00136         case siena::anytype_id: return false;
00137         default: return m_string > v.m_string;
00138         }
00139     }
00140 
00141     bool operator<= ( const Value& v ) const
00142     {
00143       if( m_type != v.m_type ) { return m_type <= v.m_type; }
00144       switch( m_type )
00145         {
00146         case siena::bool_id: return m_bool <= v.m_bool;
00147         case siena::double_id: return m_double <= v.m_double;
00148         case siena::int_id: return m_int <= v.m_int;
00149         case siena::anytype_id: return true;
00150         default: return m_string <= v.m_string;
00151         }
00152     }
00153 
00154     bool operator>= ( const Value& v ) const
00155     {
00156       if( m_type != v.m_type ) { return m_type >= v.m_type; }
00157       switch( m_type )
00158         {
00159         case siena::bool_id: return m_bool >= v.m_bool;
00160         case siena::double_id: return m_double >= v.m_double;
00161         case siena::int_id: return m_int >= v.m_int;
00162         case siena::anytype_id: return true;
00163         default: return m_string >= v.m_string;
00164         }
00165     }
00166 
00167     bool operator!= ( const Value& v ) const
00168     {
00169       if( m_type != v.m_type ) { return true; }
00170       switch( m_type )
00171         {
00172         case siena::bool_id: return m_bool != v.m_bool;
00173         case siena::double_id: return m_double != v.m_double;
00174         case siena::int_id: return m_int != v.m_int;
00175         case siena::anytype_id: return false;
00176         default: return m_string != v.m_string;
00177         }
00178     }
00179 
00180     size_t bytesize() const { return m_bytesize; }
00181 
00182     siena::type_id m_type;
00183     union
00184     {
00185       bool m_bool;
00186       double m_double;
00187       int m_int;
00188     };
00189     std::string m_string;
00190     size_t m_bytesize;
00191   };
00192 
00193 public:
00197   Constraint( const std::string& name, siena::operator_id op, siena::bool_t b )
00198     : m_name( name ), m_op( op ), m_value( b ),
00199       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00200 
00204   Constraint( const std::string& name, siena::operator_id op, siena::double_t d )
00205     : m_name( name ), m_op( op ), m_value( d ),
00206       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00207 
00211   Constraint( const std::string& name, siena::operator_id op, siena::int_t i )
00212     : m_name( name ), m_op( op ), m_value( (int)i ),
00213       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00214 
00218   Constraint( const std::string& name, siena::operator_id op, const std::string& s )
00219     : m_name( name ), m_op( op ), m_value( s ),
00220       m_bytesize( name.length() + sizeof( siena::operator_id ) + m_value.bytesize() ) {}
00221 
00224   Constraint( const std::string& name )
00225     : m_name( name ), m_op(siena::any_id), m_value(),
00226       m_bytesize( name.length() + sizeof( siena::operator_id ) ) {}
00227 
00230   Constraint( const Constraint& c )
00231     : m_name( c.m_name ), m_op( c.m_op ), m_value( c.m_value ),
00232       m_bytesize( c.m_bytesize ) {}
00233 
00236   const Constraint& operator=( const Constraint& c )
00237   {
00238     m_name = c.m_name; m_op = c.m_op;
00239     m_value = c.m_value; m_bytesize = c.m_bytesize;
00240     return *this;
00241   }
00242 
00248   bool operator==( const Constraint& c ) const
00249   { return m_name == c.m_name && m_op == c.m_op && m_value == c.m_value; }
00250 
00256   bool operator<( const Constraint& c ) const
00257   {
00258     if( m_name != c.m_name ) { return m_name < c.m_name; }
00259     else if( m_op != c.m_op ) { return m_op < c.m_op; }
00260     else { return m_value < c.m_value; }
00261   }
00262 
00263   ~Constraint() {}
00264 
00270   siena::bool_t bool_value() const
00271   { return m_value.m_bool; }
00272 
00278   siena::double_t double_value() const
00279   { return m_value.m_double; }
00280 
00287   size_t bytesize() const
00288   { return m_bytesize; }
00289 
00295   siena::int_t int_value() const
00296   { return m_value.m_int; }
00297 
00300   siena::string_t name() const
00301   { return siena::string_t( m_name.c_str(), m_name.length() ); }
00302 
00305   siena::operator_id op() const
00306   { return m_op; }
00307 
00311   std::ostream& sff(std::ostream& out) const;
00312 
00316   std::string str() const;
00317 
00323   siena::string_t string_value() const
00324   { return siena::string_t( m_value.m_string.c_str(), m_value.m_string.length() ); }
00325 
00328   siena::type_id type() const
00329   { return m_value.m_type; }
00330 
00331 private:
00332   std::string           m_name;
00333   siena::operator_id    m_op;
00334   Value                 m_value;
00335   size_t                m_bytesize;
00336 };
00337 
00342 template<bool Simplify> class TFilter : public siena::filter
00343 {
00344 public:
00347   class Iterator : public siena::filter::iterator
00348   {
00349   public:
00350     Iterator( std::set<Constraint>::iterator begin, std::set<Constraint>::iterator end )
00351       : m_end( end ), m_index( begin ) {}
00352 
00353     ~Iterator() {}
00354 
00355     siena::bool_t bool_value() const
00356     { return (*m_index).bool_value(); }
00357 
00358     siena::double_t double_value() const
00359     { return (*m_index).double_value(); }
00360 
00361     siena::int_t int_value() const
00362     { return (*m_index).int_value(); }
00363 
00364     siena::string_t name() const
00365     { return (*m_index).name(); }
00366 
00367     bool next()
00368     {
00369       if( m_index == m_end || ++m_index == m_end ) { return false; }
00370       else { return true; }
00371     }
00372 
00373     siena::operator_id op() const
00374     { return (*m_index).op(); }
00375 
00376     std::ostream& sff(std::ostream& out) const;
00377 
00378     std::string str() const
00379     { return (*m_index).str(); }
00380 
00381     siena::string_t string_value() const
00382     { return (*m_index).string_value(); }
00383 
00384     siena::type_id type() const
00385     { return (*m_index).type(); }
00386 
00387   private:
00388     std::set<Constraint>::iterator m_end;
00389     std::set<Constraint>::iterator m_index;
00390   };
00391 
00392   TFilter()
00393     : m_conflicted( false ), m_bytesize( 0 ) {}
00394 
00395   ~TFilter() {}
00396 
00397   TFilter( const TFilter& f )
00398     : m_conflicted( f.m_conflicted ), m_constraints( f.m_constraints ),
00399       m_bytesize( f.m_bytesize ) {}
00400 
00401   const TFilter& operator=( const TFilter& f )
00402   {
00403     m_conflicted = f.m_conflicted;
00404     m_constraints = f.m_constraints;
00405     m_bytesize = f.m_bytesize;
00406     return (*this);
00407   }
00408 
00409   bool operator<( const TFilter& f ) const
00410   { 
00411     /*
00412      * not sure that the extra test with the size is necessary...
00413      */
00414     if( m_constraints.size() != f.m_constraints.size() )
00415       { return m_constraints.size() < f.m_constraints.size(); }
00416     return m_constraints < f.m_constraints;
00417   }
00418 
00419   bool operator== ( const TFilter& f ) const
00420   { return m_constraints == f.m_constraints; }
00421 
00422   void add( const Constraint& c )
00423   {
00424     if( Simplify )
00425       {
00426         // once a filter is conflicted there is no point in adding
00427         // constraints to it.
00428         if( m_conflicted )
00429           {
00430             return;
00431           }
00432         std::set<Constraint>::iterator i = m_constraints.begin(); 
00433         while ( i != m_constraints.end() )
00434           {
00435             if( conflicting( (*i), c ) )
00436               {
00437                 m_conflicted = true;
00438                 m_constraints.clear();
00439                 m_bytesize = 0;
00440                 return;
00441               }
00442             if( siena::covers( c, (*i) ) )
00443               {
00444                 return;
00445               }
00446             if( siena::covers( (*i), c ) )
00447               {
00448                 m_bytesize -= (*i).bytesize();
00449                 m_constraints.erase( i++ );
00450               }
00451             else 
00452               {
00453                 ++i;
00454               }
00455           }
00456       }
00457     if( m_constraints.insert( c ).second )
00458       {
00459         m_bytesize += c.bytesize();
00460       }
00461   }
00462 
00463   Iterator* first() const
00464   {
00465     if( m_constraints.empty() )  { return NULL; }
00466     return new Iterator( m_constraints.begin(), m_constraints.end() );
00467   }
00468 
00469   const std::set<Constraint>& getConstraints() const
00470   { return m_constraints; }
00471 
00472   size_t bytesize() const { return m_bytesize; }
00473 
00474   std::ostream& sff(std::ostream& out) const
00475   {
00476     std::set<Constraint>::const_iterator i;
00477     for( i = m_constraints.begin(); i != m_constraints.end(); ++i )
00478       {
00479         if( i != m_constraints.begin() )
00480           {
00481             out <<  ", ";
00482           }
00483         (*i).sff(out);
00484       }
00485     return out;
00486   }
00487 
00488   int size() const { return m_constraints.size(); }
00489 
00490   std::string str() const
00491   {
00492     std::ostringstream oss;
00493     oss << "[Filter: constraints={";
00494     std::set<Constraint>::const_iterator i;
00495     for( i = m_constraints.begin(); i != m_constraints.end(); ++i )
00496       {
00497         if( i != m_constraints.begin() )
00498           {
00499             oss <<  ",";
00500           }
00501         oss <<  (*i).str();
00502       }
00503     oss << "}]";
00504     return oss.str();
00505   }
00506 
00507 private:
00508   bool                  m_conflicted;
00509   std::set<Constraint>  m_constraints;
00510   size_t                m_bytesize;
00511 };
00512 
00515 typedef TFilter<false> BasicFilter;
00518 typedef TFilter<true> SimplifyingFilter;
00519 
00524 template<bool Simplify> class TPredicate : public siena::predicate
00525 {
00526 public:
00527   typedef TFilter<Simplify> filter_type;
00528   typedef typename filter_type::Iterator filter_iterator;
00529   typedef typename std::set<filter_type>::iterator filter_set_iterator;
00530   typedef typename std::set<filter_type>::const_iterator const_filter_set_iterator;
00531 
00534   class Iterator : public siena::predicate::iterator
00535   {
00536   public:
00537     Iterator( filter_set_iterator begin, filter_set_iterator end )
00538       : m_end( end ), m_index( begin ) {}
00539 
00540     filter_iterator* first() const
00541     { return (*m_index).first(); }
00542 
00543     ~Iterator() {}
00544 
00545     bool next()
00546     {
00547       if( m_index == m_end || ++m_index == m_end ) { return false; }
00548       else { return true; }
00549     }
00550 
00551     std::string str() const
00552     { return (*m_index).str(); }
00553 
00554   private:
00555     filter_set_iterator m_end;
00556     filter_set_iterator m_index;
00557   };
00558 
00559   TPredicate() : m_bytesize( 0 ) {}
00560 
00561   TPredicate( const TPredicate& p )
00562     : m_filters( p.m_filters ), m_bytesize( p.m_bytesize ) {}
00563 
00564   ~TPredicate() {}
00565 
00566   const TPredicate& operator= ( const TPredicate& p )
00567   {
00568     m_filters = p.m_filters;
00569     m_bytesize = p.m_bytesize;
00570     return *this;
00571   }
00572 
00573   bool operator== ( const TPredicate& p ) const
00574   { return m_filters == p.m_filters; }
00575 
00576   void add( const TPredicate& p );
00577 
00578   void add( const filter_type& f );
00579 
00580   void clear()
00581   { m_bytesize = 0; m_filters.clear(); }
00582 
00583   Iterator* first() const
00584   {
00585     if( m_filters.empty() ) { return NULL; }
00586     return new Iterator( m_filters.begin(), m_filters.end() );
00587   }
00588 
00589   size_t bytesize() const
00590   { return m_bytesize; }
00591 
00592   const std::set<filter_type>& getFilters() const
00593   { return m_filters; }
00594 
00595   std::ostream& sff(std::ostream& out) const;
00596 
00597   int size()  const
00598   { return m_filters.size(); }
00599 
00600   std::string str() const;
00601 private:
00602   std::set<filter_type> m_filters;
00603   size_t                m_bytesize;
00604 };
00605 
00606 template<bool Simplify> inline void TPredicate<Simplify> :: add( const TPredicate<Simplify>& p )
00607 {
00608   const_filter_set_iterator i;
00609   for( i = p.m_filters.begin(); i != p.m_filters.end(); ++i )
00610     {
00611       add( *i );
00612     }
00613 }
00614 
00615 template<bool Simplify> inline void TPredicate<Simplify> :: add( const TPredicate<Simplify>::filter_type& f )
00616 {
00617   if( Simplify )
00618     {
00619       // no point in adding empty filters
00620       if( ! f.size() )
00621         {
00622           return;
00623         }
00624       filter_set_iterator i = m_filters.begin();
00625       while ( i != m_filters.end() )
00626         {
00627           if( siena::covers( (*i), f ) )
00628             {
00629               return;
00630             }
00631           if( siena::covers( f, (*i) ) )
00632             {
00633               m_bytesize -= (*i).bytesize();
00634               m_filters.erase( i++ );
00635             }
00636           else
00637             {
00638               ++i;
00639             }
00640         }
00641     }
00642   if( m_filters.insert( f ).second )
00643     {
00644       m_bytesize += f.bytesize();
00645     }
00646 }
00647 
00648 template<bool Simplify> inline std::ostream& TPredicate<Simplify> :: sff(std::ostream& out) const
00649 {
00650   const_filter_set_iterator i;
00651   for( i = m_filters.begin(); i != m_filters.end(); ++i )
00652     {
00653       if( i != m_filters.begin() )
00654         {
00655           out << std::endl << " | ";
00656         }
00657       (*i).sff(out);
00658     }
00659   return out;
00660 }
00661 
00662 template<bool Simplify> inline std::string TPredicate<Simplify> :: str() const
00663 {
00664   std::ostringstream oss;
00665   oss << "[Predicate: bytesize=" << m_bytesize << ",filters={";
00666   const_filter_set_iterator i;
00667   for( i = m_filters.begin(); i != m_filters.end(); ++i )
00668     {
00669       if( i != m_filters.begin() )
00670         {
00671           oss <<  ",";
00672         }
00673       oss <<  (*i).str();
00674     }
00675   oss << "}]";
00676   return oss.str();
00677 }
00678 
00681 typedef TPredicate<false> BasicPredicate;
00682 
00685 typedef TPredicate<true> SimplifyingPredicate;
00686 
00689 class Message : public siena::message
00690 {
00691 public:
00694   class Value
00695   {
00696   public:
00697     Value(bool b) : type(siena::bool_id), b_value(b) { }
00698     Value(double d) : type(siena::double_id), d_value(d) { }
00699     Value(int i) : type(siena::int_id), i_value(i) { }
00700     Value(std::string s) : type(siena::string_id), s_value(s) { }
00701 
00702     Value( const Value& v )
00703     {
00704       type = v.type;
00705       switch( v.type )
00706         {
00707         case siena::bool_id: b_value = v.b_value; break;
00708         case siena::double_id: d_value = v.d_value; break;
00709         case siena::int_id: i_value = v.i_value; break;
00710         default: s_value = v.s_value;
00711         }
00712     }
00713 
00714     const Value& operator= ( const Value& v )
00715     {
00716       type = v.type;
00717       switch( v.type )
00718         {
00719         case siena::bool_id: b_value = v.b_value; break;
00720         case siena::double_id: d_value = v.d_value; break;
00721         case siena::int_id: i_value = v.i_value; break;
00722         default: s_value = v.s_value;
00723         }
00724       return *this;
00725     }
00726 
00727     size_t bytesize() const;
00728 
00729     std::string str() const;
00730 
00731     siena::type_id type;
00732     union
00733     {
00734       bool b_value;
00735       double d_value;
00736       int i_value;
00737     };
00738     std::string s_value;
00739   };
00740 
00744   class Iterator : public siena::message::iterator
00745   {
00746     std::map<std::string,Value>::const_iterator m_itr;
00747     std::map<std::string,Value>::const_iterator m_end;
00748   public:
00749     Iterator( std::map<std::string,Value>::const_iterator itr,
00750               std::map<std::string,Value>::const_iterator end )
00751       : m_itr( itr ), m_end( end ) {}
00752     
00753     ~Iterator() {}
00754 
00755     siena::bool_t bool_value() const
00756     {
00757       if( (*m_itr).second.type != siena::bool_id ) { return false; }
00758       return (*m_itr).second.b_value;
00759     }
00760 
00761     siena::double_t double_value() const
00762     {
00763       if( (*m_itr).second.type != siena::double_id ) { return 0.0; }
00764       return (*m_itr).second.d_value;
00765     }
00766 
00767     siena::int_t int_value() const
00768     {
00769       if( (*m_itr).second.type != siena::int_id ) { return 0; }
00770       return (*m_itr).second.i_value;
00771     }
00772 
00773     siena::string_t string_value() const
00774     {
00775       return siena::string_t( (*m_itr).second.s_value.c_str(), 
00776                               (*m_itr).second.s_value.length() );
00777     }
00778 
00779     siena::type_id type() const
00780     { return (*m_itr).second.type; }
00781 
00782     siena::string_t name() const
00783     { return siena::string_t( (*m_itr).first.c_str(), (*m_itr).first.length() ); }
00784 
00785     bool next()
00786     {
00787       if( m_itr == m_end )
00788         {
00789           return false;
00790         }
00791       return ++m_itr != m_end;
00792     }
00793   };
00794 
00797   Message() {}
00798 
00801   Message( const Message& m ) : m_attrMap( m.m_attrMap ) {}
00802 
00803   ~Message() {}
00804 
00807   const Message& operator= ( const Message& m )
00808   { m_attrMap = m.m_attrMap; return (*this); }
00809 
00813   void add( const std::string& name, bool val )
00814   {
00815     m_attrMap.insert(make_pair(name, Value(val)));
00816   }
00817 
00821   void add( const std::string& name, double val )
00822   {
00823     m_attrMap.insert(make_pair(name, Value(val)));
00824   }
00825 
00829   void add( const std::string& name, int val )
00830   {
00831     m_attrMap.insert(make_pair(name, Value(val)));
00832   }
00833     
00837   void add( const std::string& name, const std::string& val )
00838   {
00839     m_attrMap.insert(make_pair(name, Value(val)));
00840   }
00841 
00845   bool contains( const siena::string_t& name ) const
00846   { return m_attrMap.find( std::string( name.begin, name.length() ) ) != m_attrMap.end(); }
00847 
00851   siena::message::iterator* first() const
00852   {
00853     if( m_attrMap.size() == 0 ) { return NULL; }
00854     return new Message::Iterator( m_attrMap.begin(), m_attrMap.end() );
00855   }
00856 
00862   siena::attribute* find( const siena::string_t& name ) const
00863   {
00864     std::map<std::string,Value>::const_iterator itr = m_attrMap.find( std::string( name.begin, name.length() ) );
00865     if( itr != m_attrMap.end() )
00866       {
00867         return new Message::Iterator( itr, m_attrMap.end() );
00868       }
00869     else
00870       {
00871         return NULL;
00872       }
00873   }
00874 
00877   const std::map<std::string,Value>& getAttributes() const
00878   { return m_attrMap; }
00879 
00882   size_t bytesize() const;
00883 
00886   int size() const
00887   { return m_attrMap.size(); }
00888 
00893   std::string str() const;
00894 private:
00895   std::map<std::string,Value> m_attrMap;
00896 };
00897 
00898 } // ssimp namespace
00899 
00900 inline std::ostream& operator<< ( std::ostream& out, 
00901                                   const ssimp::Constraint& c )
00902 { return out << c.str(); }
00903 
00904 template<bool Simplify> inline std::ostream& operator<<( std::ostream& out, const ssimp::TFilter<Simplify>& f )
00905 { return out << f.str(); }
00906 
00907 template<bool Simplify> inline std::ostream& operator<<( std::ostream& out, const ssimp::TPredicate<Simplify>& p )
00908 { return out << p.str(); }
00909 
00910 inline std::ostream& operator<< ( std::ostream& out, const ssimp::Message& m )
00911 { return out << m.str(); }
00912 
00913 #endif // SIMP_TYPES_H