using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.InteropServices; namespace EPocalipse.IFilter { /// /// Implements a TextReader that reads from an IFilter. /// public class FilterReader : TextReader { IFilter _filter; private bool _done; private STAT_CHUNK _currentChunk; private bool _currentChunkValid; private char[] _charsLeftFromLastRead; public override void Close() { Dispose(true); GC.SuppressFinalize(this); } ~FilterReader() { Dispose(false); } protected override void Dispose(bool disposing) { if (_filter!=null) Marshal.ReleaseComObject(_filter); } public override int Read(char[] array, int offset, int count) { int endOfChunksCount=0; int charsRead=0; while (!_done && charsRead1) _done=true; //That's it. no more chuncks available } if (_currentChunkValid) { uint bufLength=(uint)(count-charsRead); if (bufLength<8192) bufLength=8192; //Read ahead char[] buffer=new char[bufLength]; IFilterReturnCode res=_filter.GetText(ref bufLength, buffer); buffer[bufLength++] = ' '; if (res==IFilterReturnCode.S_OK || res==IFilterReturnCode.FILTER_S_LAST_TEXT) { int cRead=(int)bufLength; if (cRead+charsRead>count) { int charsLeft=(cRead+charsRead-count); _charsLeftFromLastRead=new char[charsLeft]; Array.Copy(buffer, cRead-charsLeft, _charsLeftFromLastRead, 0, charsLeft); cRead-=charsLeft; } else _charsLeftFromLastRead=null; Array.Copy(buffer, 0, array, offset+charsRead, cRead); charsRead+=cRead; } if (res==IFilterReturnCode.FILTER_S_LAST_TEXT || res==IFilterReturnCode.FILTER_E_NO_MORE_TEXT) _currentChunkValid=false; } } return charsRead; } public FilterReader(string fileName) { _filter=FilterLoader.LoadAndInitIFilter(fileName); if (_filter==null) throw new ArgumentException("no filter defined for "+fileName); } } }