Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

CPipeFindSync.cpp

Go to the documentation of this file.
00001 
00032 #include "stdafx.h"
00033 #include "CPipeFindSync.h"
00034 
00044 AxPipe::Stock::CPipeFindSync *
00045 AxPipe::Stock::CPipeFindSync::Init(const void *p, size_t cb, bool fInvert, int iSkipTo) {
00046     m_pPattern = (const unsigned char *)p;
00047     m_cbPattern = cb;
00048     m_iNext = 0;
00049     if (m_fSkipAfterSync = ((m_iSkipTo = iSkipTo) < 0)) {
00050         m_iSkipTo = -m_iSkipTo;
00051     }
00052     m_iInvert = fInvert ? 0xff : 0;
00053 
00054     return this;
00055 }
00058 void AxPipe::Stock::CPipeFindSync::PumpBuf(size_t cbBuf) {
00059     if (cbBuf) {
00060         CSeg *pBufSeg = new CSeg(m_pPattern, cbBuf);
00061         for (size_t i = 0; i < cbBuf; i++) {
00062             pBufSeg->PtrWr()[i] ^= m_iInvert;
00063         }
00064         Pump(pBufSeg);
00065         pBufSeg = NULL;
00066     }
00067 }
00068 
00073 void AxPipe::Stock::CPipeFindSync::Out(AxPipe::CSeg *pSeg) {
00074     // Already matched the right number of patterns?
00075     if (!m_iSkipTo) {
00076         if (m_fSkipAfterSync) {
00077             // Already skipping
00078             pSeg->Release();
00079         } else {
00080             // We've already matched the required number, so let's send it onwards
00081             Pump(pSeg);
00082         }
00083         return;
00084     }
00085     // Step one byte at a time, attempting to find a match. The pattern buffer
00086     // serves a dual purpose - to record previously seen, and matched, bytes
00087     // and of course to serve as the comparison to find matches. The idea is that
00088     // we do not need to store previous matched bytes, since they by definition
00089     // must be a part of the pattern - otherwise they should be output or skipped.
00090     // m_iNext keeps track of the next byte we want to match in the pattern.
00091     const unsigned char *pData = pSeg->PtrRd();
00092     size_t cbDataRemain = pSeg->Len();  // Can't be zero
00093     size_t iPrevBuf = m_iNext;          // Number of old bytes from previous segment(s)
00094     size_t iOutPrevBuf = 0;             // Number of old bytes not part of buffer after this seg
00095 
00096     // While more data to compare against the pattern
00097     while (cbDataRemain--) {
00098         // If we still have a pattern match
00099         if (*pData++ == (m_pPattern[m_iNext] ^ m_iInvert)) {
00100             m_iNext++;
00101             if (m_iNext == m_cbPattern) {
00102                 // If we've matched the entire pattern - bingo!
00103                 if (--m_iSkipTo) {
00104                     // Still not zero. Must match more patterns.
00105                     m_iNext = 0;
00106                 } else {
00107                     // Now we've found the right number of syncs.
00108                     // Reduce the length so that data including and after this found sync
00109                     // is not part of the segment to pump. This is calculated by first reducing
00110                     // the length by cbDataRemain (these are the bytes after the sync).
00111                     // Then we either reduce by a whole sync length, or by the partial length
00112                     // we had to start with.
00113                     // cbDataRemain is only updated to the start of the matched sequence
00114                     if (m_fSkipAfterSync) {
00115                         // Pump what we've got so far, and start skipping....
00116                         Pump(pSeg->Len(pSeg->Len() - (cbDataRemain + (m_cbPattern - iPrevBuf))));
00117                     } else {
00118                         // Drop all up until the start of this sequence, then start...
00119                         PumpBuf(iPrevBuf);
00120                         Pump(pSeg->Drop(pSeg->Len() - (cbDataRemain + (m_cbPattern - iPrevBuf))));
00121                     }
00122                     return;
00123                 }
00124             }
00125         } else {
00126             if (m_iNext) {
00127                 for (size_t i = 0; i < m_iNext; i++) {
00128                     if (iPrevBuf) {
00129                         iPrevBuf--;
00130                         iOutPrevBuf++;
00131                     }
00132                     if (i && (memcmp(m_pPattern, &m_pPattern[i], m_iNext - i) == 0)) {
00133                         break;
00134                     }
00135                 }
00136                 m_iNext -= i;
00137                 continue;
00138             }
00139         }
00140     }
00141     if (m_fSkipAfterSync) {
00142         // Pump 'i' bytes that were buffered, but no match.
00143         PumpBuf(iOutPrevBuf);
00144 
00145         // Pump the whole segment, except for newly buffered bytes, if any.
00146         Pump(pSeg->Len(pSeg->Len() - (m_iNext - iPrevBuf)));
00147     } else {
00148         // We're to skip before sync, and since we've exhausted this seg,
00149         // we just drop it.
00150         pSeg->Release();
00151     }
00152 }

Generated on Mon Feb 2 13:19:18 2004 for AxPipe by doxygen 1.3.5