Humble Framework for SkyOS


Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

HBuffer.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/pig/Humble/HBuffer.h 3     2/04/05 10:45a Neusel $
00004 **
00005 ****************************************************************************/
00012 #ifndef HBUFFER_H
00013     #define HBUFFER_H
00014 
00024 template <uint32 BUF_LEN>
00025 class HBuffer : public HObjNoCopy
00026     {
00027     typedef HObjNoCopy  base_class;
00028     static StringPtr    ClassName(void) { return "HBuffer"; }
00029 /*  ----------------------------------------------------------------------
00030     VARIABLES
00031     ----------------------------------------------------------------------  */
00032 protected:
00033     uint32              m_uBytes;       
00034     uint32              m_uRead;        
00035     uint32              m_uWrite;       
00036     uint8               m_data[BUF_LEN];
00037 /*  ----------------------------------------------------------------------
00038     CTOR / DTOR
00039     ----------------------------------------------------------------------  */
00040 public:
00041     HBuffer(void)
00042         { (void) Reset(); }
00043 
00044     virtual
00045     ~HBuffer(void)
00046         { 
00047 #if __DEBUG__
00048         if (m_uBytes)
00049             DEBUG_LOG("~HBuffer() => %lu bytes still in buffer\n", m_uBytes);
00050 #endif
00051         (void) Reset();
00052         }
00053 /*  ----------------------------------------------------------------------
00054     METHODS
00055     ----------------------------------------------------------------------  */
00056 public:
00064     ErrCode
00065     Find(uint8 xWanted, uint32 & uOffset) const
00066         {
00067         const uint32    uSize = GetDataBytes();
00068 
00069         for (uOffset = 0; uOffset < uSize; ++uOffset)
00070             if (GetAt(uOffset) == xWanted)
00071                 {
00072                 DEBUG_LOG(  "HBuffer::Find() => found 0x%02X at %lu\n",
00073                             xWanted, uOffset);
00074                 return HError::NoError();   // Found it, so quit looking for it...
00075                 }
00076                         
00077         return HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00078         }
00086     ErrCode
00087     FindLast(const uint8 xWanted, uint32 & uOffset) const
00088         {
00089         ErrCode     ec = HError::NoError();
00090         
00091         uOffset = GetDataBytes();
00092 
00093         while (uOffset > 0)
00094             if (GetAt(--uOffset) == xWanted)
00095                 return ec;  // found it, so quit looking for it...
00096             
00097         return HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00098         }
00106     ErrCode
00107     Read(Ptr pBuf, const uint32 uBufLen)
00108         {
00109         ErrCode     ec = HError::NoError();
00110 
00111         DEBUG_CHECK(uBufLen > 0 && uBufLen < MB(16));
00112         
00113         if (uBufLen <= GetDataBytes())
00114             {
00115             if ((m_uRead + uBufLen) <= BUF_LEN) // true if trivial "no wrap" case
00116                 {
00117                 DEBUG_LOG(  "HBuffer::Read() => copied %lu bytes from buffer, starting at %lu\n",
00118                             uBufLen, m_uRead);      
00119                 ASSERT(m_uRead < BUF_LEN);
00120                 MEM_COPY(pBuf, &m_data[m_uRead], uBufLen);
00121                 m_uRead += uBufLen;
00122                 }
00123             else
00124                 {
00125                 //
00126                 //  It will be necessary to "wrap" the read:
00127                 //
00128                 //                          m_uRead BEFORE
00129                 //                          v
00130                 //  +------------+----//----+--------------+
00131                 //  |            |          |              |
00132                 //  | BLOCK "B"  |  (free)  |   BLOCK "A"  |
00133                 //  |            |          |              |
00134                 //  +------------+----//----+--------------+
00135                 //               ^
00136                 //               m_uRead AFTER
00137                 //
00138                 const uint32    uBlockA = (m_uRead < BUF_LEN) ? BUF_LEN - m_uRead : 0;
00139                 const uint32    uBlockB = uBufLen - uBlockA;
00140 
00141                 if (uBlockA > 0)
00142                     {
00143                     ASSERT(m_uRead < BUF_LEN);
00144                     MEM_COPY(pBuf, &m_data[m_uRead], uBlockA);
00145                     DEBUG_LOG(  "HBuffer::Read(#1) => copied %lu bytes from buffer, starting at %lu\n",
00146                                 uBlockA, m_uRead);      
00147                     }
00148                                         
00149                 if (uBlockB > 0)
00150                     {
00151                     PtrData pc = reinterpret_cast<PtrData>( pBuf );
00152 
00153                     DEBUG_LOG(  "HBuffer::Read(#2) => copied %lu bytes from buffer\n",
00154                                 uBlockB);       
00155                     ASSERT(uBlockA < BUF_LEN);
00156                     MEM_COPY(&pc[uBlockA], m_data, uBlockB);
00157                     }
00158 
00159                 m_uRead = uBlockB;
00160                 ASSERT(m_uRead < BUF_LEN);
00161                 ASSERT((uBlockA + uBlockB) == uBufLen);
00162                 }
00163             
00164             ASSERT(uBufLen <= m_uBytes);
00165             m_uBytes -= uBufLen;
00166             }
00167         else
00168             ec = HError::Set(ERR_BUFFER_UNDERFLOW, __FILE__, __LINE__);
00169         
00170         return ec;
00171         }
00180     ErrCode
00181     ReadLine(TextPtr psz, const int32 nMaxLen, bool bChomp = true)
00182         {
00183         ErrCode     ec = HError::NoError();
00184         
00185         if (GOOD_PTR(psz) && nMaxLen > 0)
00186             {
00187             uint32  uOffset = 0;
00188             
00189             if (Find('\n', uOffset) == NO_ERROR)
00190                 {
00191                 ASSERT(uOffset < GetDataBytes());
00192 
00193                 ec = Read(reinterpret_cast<PtrData>(psz), uOffset + 1);
00194                 if (ec == NO_ERROR)
00195                     {
00196                     psz[uOffset] = '\0';    // make sure it's terminated
00197                     if (bChomp && uOffset > 0)  // don't chomp if nothing read
00198                         {
00199                         //
00200                         //  This loop looks a little weird because if the entire
00201                         //  string is chomped, uLast will wrap past zero.  Since
00202                         //  it's unsigned, it will go hugely positive (instead
00203                         //  of negative) so the exit condition will trigger.
00204                         //
00205                         for (uint32 uLast = uOffset; uLast <= uOffset; --uLast)
00206                             {
00207                             if (isspace(psz[uLast]))
00208                                 psz[uLast] = '\0';
00209                             else
00210                                 break;
00211                             }
00212                         }
00213                     }
00214                 }
00215             else
00216                 ec = HError::Set(ERR_BUFFER_UNDERFLOW, __FILE__, __LINE__);
00217             }
00218         else
00219             ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00220         
00221         return ec;  
00222         }
00231     ErrCode
00232     Reset(void)
00233         {
00234         m_uBytes = m_uRead = m_uWrite = 0;
00235         return Zero();
00236         }
00244     ErrCode
00245     Write(PtrConst pBuf, uint32 uDataLen)
00246         {
00247         ErrCode     ec = HError::NoError();
00248         
00249         DEBUG_CHECK(uDataLen < MB(16));
00250         
00251         if (uDataLen > GetFreeBytes())
00252             ec = HError::Set(ERR_BUFFER_OVERFLOW, __FILE__, __LINE__);
00253         else if (uDataLen > 0)
00254             {   
00255             DEBUG_CHECK(uDataLen < MB(16));
00256             if ((m_uWrite + uDataLen) < BUF_LEN)    // true if trivial "no wrapping" case 
00257                 {
00258                 ASSERT(m_uWrite < BUF_LEN);
00259                 DEBUG_LOG(  "HBuffer::Write() => writing %lu bytes beginning at offset %lu\n",
00260                             uDataLen, m_uWrite);        
00261 
00262                 MEM_COPY(&m_data[m_uWrite], pBuf, uDataLen);
00263                 m_uWrite += uDataLen;
00264                 }
00265             else    // have to wrap
00266                 {
00267                 //
00268                 //  It will be necessary to "wrap" the write:
00269                 //
00270                 //                          m_uWrite BEFORE
00271                 //                          v
00272                 //  +------------+----//----+--------------+
00273                 //  |            |          |              |
00274                 //  | BLOCK "B"  |  (free)  |   BLOCK "A"  |
00275                 //  |            |          |              |
00276                 //  +------------+----//----+--------------+
00277                 //               ^
00278                 //               m_uWrite AFTER
00279                 //
00280                 const uint32    uBlockA = (m_uWrite < BUF_LEN) ? BUF_LEN - m_uWrite : 0;
00281                 const uint32    uBlockB = uDataLen - uBlockA;
00282                 
00283                 if (uBlockA > 0)
00284                     {
00285                     ASSERT(m_uWrite < BUF_LEN);
00286                     MEM_COPY(&m_data[m_uWrite], pBuf, uBlockA );
00287                     DEBUG_LOG(  "HBuffer::Write(#1) => copied %lu bytes to buffer, starting at %lu\n",
00288                                 uBlockA, m_uWrite);     
00289                     }
00290 
00291                 if (uBlockB > 0)
00292                     {
00293                     PtrDataConst    pc = reinterpret_cast<PtrDataConst>( pBuf );
00294                     
00295                     ASSERT(uBlockA < BUF_LEN);
00296                     MEM_COPY(m_data, &pc[uBlockA], uBlockB );
00297                     DEBUG_LOG("HBuffer::Write(#2) => copied %lu bytes to buffer\n", uBlockB);       
00298                     }
00299 
00300                 m_uWrite = uBlockB;
00301                 ASSERT(m_uWrite < BUF_LEN);
00302                 ASSERT((uBlockA + uBlockB) == uDataLen);
00303                 }
00304                 
00305             m_uBytes += uDataLen;
00306             ASSERT(m_uBytes <= BUF_LEN);
00307             }
00308 
00309         return ec;
00310         }
00318     ErrCode
00319     WriteLine(StringPtr pstr, int32 nMaxLen = -1)
00320         {
00321         ErrCode     ec = HError::NoError();
00322         uint32      uBytes = (nMaxLen >= 0) ? uint32(nMaxLen) : STR_LEN(pstr);
00323         
00324         if (uBytes <= GetFreeBytes())
00325             {
00326             if (GOOD_PTR(pstr) && uBytes > 0)
00327                 {
00328                 if ((ec = Write(pstr, uBytes)) == NO_ERROR)
00329                     ec = Write("\n", 1);
00330                 }               
00331             else
00332                 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00333             }
00334         else
00335             ec = HError::Set(ERR_BUFFER_OVERFLOW, __FILE__, __LINE__);
00336             
00337         return ec;  
00338         }
00339 /*  ----------------------------------------------------------------------
00340     GETTERS & SETTERS
00341     ----------------------------------------------------------------------  */
00342 public:
00349     uint8
00350     GetAt(const uint32 uOffset) const
00351         {
00352         uint8       xVal = 0xFF;
00353         
00354         if (uOffset < GetDataBytes())
00355             {
00356             ASSERT( m_uWrite != m_uRead );
00357             
00358             if (m_uWrite > m_uRead)
00359                 xVal = m_data[ m_uRead + uOffset ];
00360             else if (m_uWrite < m_uRead)
00361                 {
00362                 if ((m_uRead + uOffset) < BUF_LEN) // true if offset in first chunk
00363                     xVal = m_data[ m_uRead + uOffset ];
00364                 else    // it's in the second chunk
00365                     xVal = m_data[ uOffset - (BUF_LEN - m_uRead) ];
00366                 }
00367             }
00368 
00369         return xVal;
00370         }
00376         uint32          GetSize(void) const
00377                             { return BUF_LEN; }
00383         inline uint32   GetDataBytes(void) const
00384                             { return m_uBytes; }
00390         inline uint32   GetFreeBytes(void) const
00391                             { return BUF_LEN - m_uBytes; }
00392 /*  ----------------------------------------------------------------------
00393     INLINES
00394     ----------------------------------------------------------------------  */
00398     inline bool         CanRead(uint32 uWanted = 1) const
00399                             { return (m_uBytes >= uWanted); }
00402     inline bool         IsEmpty(void) const
00403                             { return (m_uBytes == 0); }
00406     inline ErrCode      Zero(void)
00407                             { 
00408                             (void) MEM_ZERO(m_data, sizeof(m_data)); 
00409                             return HError::NoError();
00410                             }
00411 /*  ----------------------------------------------------------------------
00412     OPERATORS
00413     ----------------------------------------------------------------------  */
00414     inline uint8        operator [] (uint32 udx) const
00415                             { return GetAt(udx); }
00416     };
00417 #endif  // HBASE_H
00418 /****************************************************************************
00419 **
00420 **  $History: HBuffer.h $
00421  * 
00422  * *****************  Version 3  *****************
00423  * User: Neusel       Date: 2/04/05    Time: 10:45a
00424  * Updated in $/SkyOS.root/pig/Humble
00425  * 
00426  * *****************  Version 2  *****************
00427  * User: Neusel       Date: 12/10/04   Time: 3:57p
00428  * Updated in $/SkyOS.root/pig/Humble
00429  * 20041210
00430  * 
00431  * *****************  Version 1  *****************
00432  * User: Neusel       Date: 12/08/04   Time: 5:06p
00433  * Created in $/SkyOS.root/pig/Humble
00434  * 20041208
00435  * 
00436  * *****************  Version 1  *****************
00437  * User: Neusel       Date: 11/30/04   Time: 1:01p
00438  * Created in $/SkyOS.root/pig/Humble
00439  * Released as HUMBLE_VER 20041130.
00440 **
00441 **  -------------------------------------------------------------------------
00442 **
00443 **  End of HTemlate.h
00444 **
00445 ****************************************************************************/