Siena Simplification Library Documentation (v. 1.1.5) |
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
Copyright © 2001-2004 University of Colorado.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". This documentation is authored and maintained by Matthew J. Rutherford |