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);
|
|
}
|
|
}
|
|
}
|