113 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| using System.IO;
 | |
| using System.Runtime.InteropServices;
 | |
| 
 | |
| namespace EPocalipse.IFilter
 | |
| {
 | |
|   /// <summary>
 | |
|   /// Implements a TextReader that reads from an IFilter. 
 | |
|   /// </summary>
 | |
|   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 && charsRead<count)
 | |
|       {
 | |
|         if (_charsLeftFromLastRead!=null)
 | |
|         {
 | |
|           int charsToCopy=(_charsLeftFromLastRead.Length<count-charsRead)?_charsLeftFromLastRead.Length:count-charsRead;
 | |
|           Array.Copy(_charsLeftFromLastRead,0, array, offset+charsRead, charsToCopy);
 | |
|           charsRead+=charsToCopy;
 | |
|           if (charsToCopy<_charsLeftFromLastRead.Length)
 | |
|           {
 | |
|             char[] tmp=new char[_charsLeftFromLastRead.Length-charsToCopy];
 | |
|             Array.Copy(_charsLeftFromLastRead, charsToCopy, tmp, 0, tmp.Length);
 | |
|             _charsLeftFromLastRead=tmp;
 | |
|           }
 | |
|           else
 | |
|             _charsLeftFromLastRead=null;
 | |
|           continue;
 | |
|         };
 | |
| 
 | |
|         if (!_currentChunkValid)
 | |
|         {
 | |
|           IFilterReturnCode res=_filter.GetChunk(out _currentChunk);
 | |
|           _currentChunkValid=(res==IFilterReturnCode.S_OK) && ((_currentChunk.flags & CHUNKSTATE.CHUNK_TEXT)!=0);
 | |
| 
 | |
|           if (res==IFilterReturnCode.FILTER_E_END_OF_CHUNKS)
 | |
|             endOfChunksCount++;
 | |
| 
 | |
|           if (endOfChunksCount>1)
 | |
|             _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);
 | |
|     }
 | |
|   }
 | |
| }
 |