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

CharChopper.cxx

00001 /*
00002  * Copyright (C) 1991-9 Eric M. Hopper <hopper@omnifarious.mn.org>
00003  * 
00004  *     This program is free software; you can redistribute it and/or modify it
00005  *     under the terms of the GNU Lesser General Public License as published
00006  *     by the Free Software Foundation; either version 2 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, but
00010  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *     Lesser General Public License for more details.
00013  * 
00014  *     You should have received a copy of the GNU Lesser General Public
00015  *     License along with this program; if not, write to the Free Software
00016  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* $Header: /home/hopper/src/cvs/C++/StrMod/CharChopper.cxx,v 1.7 2002/02/05 22:50:06 hopper Exp $ */
00020 
00021 // For a log, see Changelog
00022 //
00023 // Revision 1.1  1996/09/02 23:28:22  hopper
00024 // Added CharChopper class so users would have a simple class that would
00025 // break up and recombine streams using whatever character they chose as
00026 // a separator.
00027 //
00028 
00029 #ifdef __GNUG__
00030 #  pragma implementation "CharChopper.h"
00031 #endif
00032 
00033 #include <StrMod/CharChopper.h>
00034 #include <StrMod/StrChunk.h>
00035 #include <StrMod/ChunkIterator.h>
00036 #include <StrMod/StrChunkPtrT.h>
00037 #include <StrMod/GroupChunk.h>
00038 #include <StrMod/StrSubChunk.h>
00039 #include <StrMod/PreAllocBuffer.h>
00040 #include <StrMod/DynamicBuffer.h>
00041 #include <algorithm>
00042 #include <cassert>
00043 
00044 namespace strmod {
00045 namespace strmod {
00046 
00047 const STR_ClassIdent CharChopper::identifier(26UL);
00048 
00049 void CharChopper::addChunk(const StrChunkPtr &chnk)
00050 {
00051    bool iscurdata = false;
00052 
00053    if (chnk.GetPtr() == curdata_.GetPtr())
00054    {
00055       curdata_->resize(usedsize_);
00056       iscurdata = true;
00057    }
00058    else if (curdata_)
00059    {
00060       addChunk(curdata_);
00061    }
00062    if (outgoing_)
00063    {
00064       if (!groupdata_)
00065       {
00066          if (outgoing_->AreYouA(GroupChunk::identifier))
00067          {
00068             groupdata_ = static_cast<GroupChunk *>(outgoing_.GetPtr());
00069          }
00070          else
00071          {
00072             groupdata_ = new GroupChunk;
00073             groupdata_->push_back(outgoing_);
00074             outgoing_ = groupdata_;
00075          }
00076          groupdata_->push_back(chnk);
00077       }
00078       else
00079       {
00080          assert(outgoing_.GetPtr() == groupdata_.GetPtr());
00081          groupdata_->push_back(chnk);
00082       }
00083    }
00084    else  // (!outgoing_)
00085    {
00086       if (groupdata_)
00087       {
00088          groupdata_.ReleasePtr();
00089       }
00090       outgoing_ = chnk;
00091    }
00092    if (iscurdata)
00093    {
00094       curdata_.ReleasePtr();
00095    }
00096 }
00097 
00098 void CharChopper::processIncoming()
00099 {
00100    assert(incoming_);
00101    assert(!outgoing_ready_);
00102    checkIncoming();
00103    assert(incoming_is_bc_ != INMaybe);
00104 
00105    unsigned int inlen = incoming_->Length();
00106 
00107    if (inlen <= 0)
00108    {
00109       addChunk(incoming_);
00110       zeroIncoming();
00111    }
00112    else
00113    {
00114       char buf[16];
00115       size_t count = 0;
00116       bool foundchar = false;
00117 
00118       {
00119          StrChunk::const_iterator end = incoming_->end();
00120          for (StrChunk::const_iterator i = incoming_->begin();
00121               !foundchar && i != end; ++i)
00122          {
00123             if (count < 16)
00124             {
00125                buf[count] = *i;
00126             }
00127             count++;  // To include character when we find it.
00128             if (*i == chopchar_)
00129             {
00130                foundchar = true;
00131             }
00132          }
00133       }
00134       assert((count >= inlen) || foundchar);
00135       if ((incoming_is_bc_ == INYes) && (count <= 16))
00136       {
00137          if (!curdata_)
00138          {
00139             if (foundchar)
00140             {
00141                curdata_ = new PreAllocBuffer<16>;
00142                curdata_->resize(count);
00143             }
00144             else
00145             {
00146                curdata_ = new DynamicBuffer(32);
00147             }
00148             memcpy(curdata_->getVoidP(), buf, count);
00149             usedsize_ = count;
00150          }
00151          else
00152          {
00153             unsigned int curlen = curdata_->Length();
00154             size_t usedshadow = usedsize_;
00155             if (curlen < (usedshadow + count))
00156             {
00157                if (foundchar)
00158                {
00159                   curlen = usedshadow + count;
00160                }
00161                else
00162                {
00163                   curlen = std::max(usedshadow + usedshadow / 2, usedshadow + count);
00164                }
00165                curdata_->resize(curlen);
00166             }
00167             memcpy(curdata_->getCharP() + usedshadow, buf, count);
00168             usedsize_ = usedshadow = (usedshadow + count);
00169          }
00170       }
00171       else // count > 16 || incoming_ isn't a DBStrChunk so buf can't be used.
00172       {
00173          if (count >= inlen)
00174          {
00175             addChunk(incoming_);
00176          }
00177          else
00178          {
00179             addChunk(new StrSubChunk(incoming_, LinearExtent(0, count)));
00180          }
00181       }
00182       if (count >= inlen)
00183       {
00184          zeroIncoming();
00185       }
00186       else
00187       {
00188          replaceIncoming(new StrSubChunk(incoming_,
00189                                          LinearExtent(count, inlen)));
00190       }
00191       if (foundchar && curdata_)
00192       {
00193          addChunk(curdata_);
00194       }
00195       outgoing_ready_ = foundchar;
00196    }
00197 }
00198 
00199 };  // End namespace strmod
00200 };  // End namespace strmod

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