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 }