Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

StreamSplitter.h

00001 #ifndef _STR_StreamSplitter_H_  // -*-c++-*-
00002 
00003 /*
00004  * Copyright 1991-2002 Eric M. Hopper <hopper@omnifarious.org>
00005  * 
00006  *     This program is free software; you can redistribute it and/or modify it
00007  *     under the terms of the GNU Lesser General Public License as published
00008  *     by the Free Software Foundation; either version 2 of the License, or
00009  *     (at your option) any later version.
00010  * 
00011  *     This program is distributed in the hope that it will be useful, but
00012  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *     Lesser General Public License for more details.
00015  * 
00016  *     You should have received a copy of the GNU Lesser General Public
00017  *     License along with this program; if not, write to the Free Software
00018  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #ifdef __GNUG__
00022 #  pragma interface
00023 #endif
00024 
00025 /* $Header: /home/hopper/src/cvs/C++/StrMod/StrMod/StreamSplitter.h,v 1.11 2002/08/29 00:58:05 hopper Exp $ */
00026 
00027 // For a change log see ../ChangeLog
00028 
00029 //! author="Eric Hopper" lib=StrMod
00030 
00031 #include <cstddef>  // NULL
00032 #ifndef _STR_STR_ClassIdent_H_
00033 #   include <StrMod/STR_ClassIdent.h>
00034 #endif
00035 #ifndef _STR_StrChunkPtr_H_
00036 #   include <StrMod/StrChunkPtr.h>
00037 #endif
00038 #ifndef _STR_StreamModule_H_
00039 #   include <StrMod/StreamModule.h>
00040 #endif
00041 
00042 #define _STR_StreamSplitter_H_
00043 
00044 namespace strmod {
00045 namespace strmod {
00046 
00047 /** \class StreamSplitterModule StreamSplitter.h StrMod/StreamSplitter.h
00048  * \brief This module is for treating two uni-directional streams as one
00049  * bi-directional stream.
00050  *
00051  * <p>SplitterModule's work this way:</p>
00052  * <pre>
00053  *              SideIn
00054  *  Module>---->--->-->--+
00055  *                       |       (bi-directional)
00056  *                      Splitter===>==<==>==<==>==<===Module
00057  *                       |      ^
00058  *  Module<----<---<--<--+      |
00059  *              SideOut         +--side SideBiDir
00060  * </pre>
00061  *
00062  *
00063  * <p>The SplitterModule takes three i/o streams, one that does both input and
00064  * output, one that does input, and one that does output, and connects them
00065  * together. They're connected in such a way as to cause the output of the
00066  * stream that does input and ouput goes into the stream that only takes input,
00067  * and the output of the stream that only does output goes to the input of the
00068  * combined stream.</p>
00069  *
00070  * <p>The SideOut plug is <b>never</b> writeable, and the SideIn plug is
00071  * <b>never</b> readable..</p>
00072  */
00073 class StreamSplitterModule : public StreamModule
00074 {
00075  public:
00076    static const STR_ClassIdent identifier;
00077 
00078    //! Create a splitter module who's plugs are connected to nothing.
00079    StreamSplitterModule();
00080    //! Delete splitter module and destroy all plugs it owns.
00081    virtual ~StreamSplitterModule();
00082 
00083    //! On what sides can a plug be created?
00084    enum Sides {
00085       SideIn,  //!< Only accepts input
00086       SideOut,  //!< Only produces output
00087       SideBiDir //!< Writing here goes out SideOut and reading comes from SideIn
00088    };
00089 
00090    inline virtual bool canCreate(int side) const;
00091    virtual bool deletePlug(Plug *plug);
00092    inline virtual bool ownsPlug(const Plug *p) const;
00093 
00094  protected:
00095    class SPPlug;
00096    friend class SPPlug;
00097    /* Not Doxygen yet. 
00098     * \brief This does most of the work.  It just forwards stuff to the other
00099     * plugs.
00100     */
00101    class SPPlug : public Plug {
00102       friend class StreamSplitterModule;
00103     public:
00104       static const STR_ClassIdent identifier;
00105 
00106       SPPlug(StreamSplitterModule &p, Sides s) : Plug(p), side_(s)           { }
00107       virtual ~SPPlug()                                                      { }
00108 
00109       inline StreamSplitterModule &getParent() const;
00110 
00111       virtual int side() const                          { return(side_); }
00112 
00113     protected:
00114       virtual const lcore::ClassIdent *i_GetIdent() const {
00115          return &identifier;
00116       }
00117 
00118       virtual const StrChunkPtr i_Read();
00119       virtual void i_Write(const StrChunkPtr &ptr);
00120 
00121       inline virtual bool needsNotifyReadable() const;
00122       inline virtual bool needsNotifyWriteable() const;
00123 
00124       virtual void otherIsReadable();
00125       virtual void otherIsWriteable();
00126 
00127       inline SPPlug *getReadPartner() const;
00128       inline SPPlug *getWritePartner() const;
00129 
00130     private:
00131       Sides side_;
00132    };
00133 
00134    virtual const lcore::ClassIdent *i_GetIdent() const  { return &identifier; }
00135 
00136    /** See base class.  This one sets the read/writeable flags on the other
00137     * plugs to be right.
00138     *
00139     * It calls the base class version after doing its work.
00140     */
00141    virtual void plugDisconnected(Plug *plug);
00142 
00143    virtual Plug *i_MakePlug(int side);
00144 
00145  private:
00146    struct {
00147       int inmade : 1;
00148       int outmade : 1;
00149       int bimade : 1;
00150    } flags_;
00151    SPPlug inplug_;
00152    SPPlug outplug_;
00153    SPPlug biplug_;
00154 };
00155 
00156 //-----------------------------inline functions--------------------------------
00157 
00158 bool StreamSplitterModule::canCreate(int side) const
00159 {
00160    switch (side) {
00161     case SideIn:
00162       return(flags_.inmade == 0);
00163     case SideOut:
00164       return(flags_.outmade == 0);
00165     case SideBiDir:
00166       return(flags_.bimade == 0);
00167     default:
00168       return(false);
00169    }
00170 }
00171 
00172 inline bool StreamSplitterModule::ownsPlug(const Plug *p) const
00173 {
00174    return((flags_.inmade && (&inplug_ == p))
00175           || (flags_.outmade && (&outplug_ == p))
00176           || (flags_.bimade && (&biplug_ == p)));
00177 }
00178 
00179 //--
00180 
00181 inline StreamSplitterModule &StreamSplitterModule::SPPlug::getParent() const
00182 {
00183    return(static_cast<StreamSplitterModule &>(Plug::getParent()));
00184 }
00185 
00186 inline bool StreamSplitterModule::SPPlug::needsNotifyReadable() const
00187 {
00188    return((side_ == SideIn) || (side_ == SideBiDir));
00189 }
00190 
00191 inline bool StreamSplitterModule::SPPlug::needsNotifyWriteable() const
00192 {
00193    return((side_ == SideOut) || (side_ == SideBiDir));
00194 }
00195 
00196 inline StreamSplitterModule::SPPlug *
00197 StreamSplitterModule::SPPlug::getReadPartner() const
00198 {
00199    switch (side_)
00200    {
00201     case SideOut:
00202       return(&(getParent().biplug_));
00203     case SideBiDir:
00204       return(&(getParent().inplug_));
00205     case SideIn:
00206     default:
00207       return(NULL);
00208    }
00209 }
00210 
00211 inline StreamSplitterModule::SPPlug *
00212 StreamSplitterModule::SPPlug::getWritePartner() const
00213 {
00214    switch (side_)
00215    {
00216     case SideIn:
00217       return(&(getParent().biplug_));
00218     case SideBiDir:
00219       return(&(getParent().outplug_));
00220     case SideOut:
00221     default:
00222       return(NULL);
00223    }
00224 }
00225 
00226 };  // namespace strmod
00227 };  // namespace strmod
00228 
00229 #endif

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1