You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "haruhiko nishi (JIRA)" <ji...@apache.org> on 2009/09/09 17:00:58 UTC
[jira] Commented: (IO-218) Introduce new filter input stream with
replacement facilities
[ https://issues.apache.org/jira/browse/IO-218?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12753115#action_12753115 ]
haruhiko nishi commented on IO-218:
-----------------------------------
Hi I'm also working on a Stream that can handle pattern replacement.
{code:title=ByteArrayInputStream.java|borderStyle=solid}
public class ByteArrayReplaceInputStream extends InputStream {
private byte[] buf;
private int count;
private PatternList.PatternListIterator itr;
private Map<PatternList.PatternEntry,Integer> counter=new IdentityHashMap<PatternList.PatternEntry,Integer>();
private int pos;
private int mark=0;
public ByteArrayReplaceInputStream(byte[] buf,PatternList list) {
this.itr=list.iterator();
this.buf=new byte[buf.length];
ByteBuffer byteBuffer=ByteBuffer.wrap(buf,0,buf.length);
itr.readLock();
try{
match(byteBuffer,itr.next(),0,byteBuffer.limit());
}finally{
itr.readUnlock();
}
}
private void write(ByteBuffer buffer){
byte[] byteArray=new byte[buffer.remaining()];
buffer.get(byteArray);
write(byteArray);
}
private void write(byte[] b){
int newcount=count+b.length;
if(newcount > buf.length){
byte newbuf[]=new byte[Math.max(buf.length<<1,newcount)];
System.arraycopy(buf,0,newbuf,0,count);
buf=newbuf;
}
System.arraycopy(b,0,buf,count,b.length);
count=newcount;
}
private final void match(ByteBuffer src,PatternList.PatternEntry pattern,int start,int end) {
if(pattern.isSingle())
single(src,pattern,start,end);
else
around(src,pattern,start,end);
}
private int count(PatternList.PatternEntry pattern){
Integer count=counter.get(pattern);
if(count==null)
count=counter.put(pattern,1);
else
count=counter.put(pattern,count+1);
return count==null ? 0 : count;
}
private boolean isPatternValid(PatternList.PatternEntry pattern){
Integer count=counter.get(pattern);
if(count==null)
return 0<=pattern.getMaxOccurence();
else
return count<pattern.getMaxOccurence();
}
private final void around(ByteBuffer src,PatternList.PatternEntry patternEntry,int start,int end){
if(start<0 || start>end || end>src.limit())
throw new IndexOutOfBoundsException("start:"+start+" end:"+end);
int pos=start;
int limit_org=end;
int mark=0;
boolean flag=false;
int j=pos;
Pattern pattern=patternEntry.getPattern();
while(isPatternValid(patternEntry) && j<=limit_org-pattern.length()) {
boolean found=true;
int cur=j;
for(int i=0;i<pattern.length();i++){
if(src.get(cur+i)!=pattern.get(i)){
found=false;
break;
}
}
if(found){
if(flag=!flag){
j=mark=cur+pattern.length();
pattern=pattern.swap();
}else{
src.position(pos).limit(mark);
j=cur+pattern.length();
if(itr.hasNext())
match(src,itr.next(),pos,src.limit());
else
write(src);
pattern=pattern.swap();
src.position(mark).limit(cur);
if(src.remaining()>0){
ByteBuffer target=src.slice();
int size=target.remaining();
byte[] array=new byte[size];
target.get(array);
array=patternEntry.replace(count(patternEntry),array);
write(array);
}
pos=src.position(src.limit()).position();
src.limit(limit_org);
}
}
if(!found){
int k=cur+pattern.length();
if(k>=src.limit())
break;
j +=pattern.skip(src.get(k) & 0xff);
}
}
src.position(pos);
if(itr.hasNext())
match(src,itr.next(),pos,src.limit());
else
write(src);
itr.previous();
}
private void single(ByteBuffer src,PatternList.PatternEntry patternEntry,int start,int end){
if(start<0 || start>end || end>src.limit())
throw new IndexOutOfBoundsException("start:"+start+" end:"+end);
int pos=start;
int limit_org=end;
int j=pos;
Pattern pattern=patternEntry.getPattern();
while(isPatternValid(patternEntry) && j<=limit_org-pattern.length()) {
boolean found=true;
int cur=j;
for(int i=0;i<pattern.length();i++){
if(src.get(cur+i)!=pattern.get(i)){
found=false;
break;
}
}
if(found){
src.position(pos).limit(cur);
j=cur+pattern.length();
if(itr.hasNext())
single(src,itr.next(),pos,src.limit());
else
write(src);
src.position(cur).limit(j);
if(src.remaining()>0){
ByteBuffer target=src.slice();
int size=target.remaining();
byte[] array=new byte[size];
target.get(array);
write(patternEntry.replace(count(patternEntry),array));
}
pos=src.position(src.limit()).position();
src.limit(limit_org);
}
if(!found){
int k=cur+pattern.length();
if(k>=src.limit())
break;
j +=pattern.skip(src.get(k) & 0xff);
}
}
src.position(pos);
if(itr.hasNext())
single(src,itr.next(),pos,src.limit());
else
write(src);
itr.previous();
}
@Override
public synchronized int read(){
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
@Override
public synchronized int read(byte b[], int off, int len){
if (b == null)
throw new NullPointerException();
else if(off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException();
if (pos >= count)
return -1;
if(pos + len > count)
len=count - pos;
if (len <= 0)
return 0;
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public synchronized long skip(long n){
if(pos +n>count){
n=count - pos;
}
if(n<0)
return 0;
pos +=n;
return n;
}
public synchronized int avaiable(){
return count - pos;
}
public boolean markSupported(){
return true;
}
public synchronized void mark(int readAheadLimit){
mark=pos;
}
public synchronized void reset(){
pos=mark;
}
public void close() throws IOException{
}
}
{code}
> Introduce new filter input stream with replacement facilities
> -------------------------------------------------------------
>
> Key: IO-218
> URL: https://issues.apache.org/jira/browse/IO-218
> Project: Commons IO
> Issue Type: Improvement
> Components: Filters
> Affects Versions: 1.4
> Environment: all environments
> Reporter: Denis Zhdanov
> Fix For: 1.4, 2.0
>
> Attachments: ReplaceFilterInputStream.java, ReplaceFilterInputStreamTest.java
>
> Original Estimate: 120h
> Remaining Estimate: 120h
>
> It seems convenient to have a FilterInputStream that allows to apply predefined repalcement rules against the read data.
> For example we may want to configure the following replacements:
> {noformat}
> {1, } -> {7, 8}
> {1} -> {9}
> {3, 2} -> {}
> {noformat}
> and apply them to the input like
> {noformat}
> {4, 3, 2, 1, 2, 1, 3}
> {noformat}
> in order to get a result like
> {noformat}
> {4, 7, 8, 9, 3}
> {noformat}
> I created the class that allows to do that and attached it to this ticket. Unit test class at junit4 format is attached as well.
> So, the task is to review the provided classes, consider if it's worth to add them to commons-io distribution and perform the inclusion in the case of possible result.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.