package com.yahoo.dtf.streaming; import java.io.IOException; import com.yahoo.dtf.exception.ParseException; /** * @dtf.feature Repeat Stream Type * @dtf.feature.group DTF Properties * * @dtf.feature.desc * <p> * The repeat stream type generates a sequence of data that repeats the pattern * you specified till it has generated the desired size. * </p> * <p> * Using the repeat streaming property is as simple as referencing the property * like so: * </p> * <pre> * ${dtf.stream(repeat,1024,ABC)} * </pre> * <p> * The previous property defines a repeat stream of data that has 1024 bytes in * length and will repeat the string ABC until the desired length has been * reached. The data generated can always be re-generated using the same seed. * This means you only have to store the size & seed to be able to do data * validation later on and not have to save the data itself. * </p> */ public class RepeatInputStream extends DTFInputStream { private int BUFFER_SIZE = 32*1024; private String _pattern = null; private int _read = 0; private int _patternLength = 0; private byte[] _buffer = null; public RepeatInputStream(long size, String[] args) throws ParseException { // save the signature incase we need to serialize this super(size, args); if ( args.length > 0 ) _pattern = args[0]; _patternLength = _pattern.length(); // for small data streams no need to create buffers that are larger // than our original data if ( size < BUFFER_SIZE ) BUFFER_SIZE = (int)size; _buffer = new byte[BUFFER_SIZE]; for (int i = 0; i < BUFFER_SIZE; i++) _buffer[i] = (byte)_pattern.charAt(i % _patternLength); } @Override public int read() throws IOException { if ( _read >= getSize() ) return -1; return _buffer[_read++ % BUFFER_SIZE]; } @Override public int read(byte[] buffer, int offset, int length) { if ( _read >= getSize() ) return -1; int diff = (int)(getSize() - _read); int onlyread = length; if ( diff < onlyread ) onlyread = diff; int totalread = 0; int read = 0; while ( totalread < onlyread ) { int start = _read % BUFFER_SIZE; read = BUFFER_SIZE - start; if ( totalread + read > onlyread ) read = onlyread - totalread; System.arraycopy(_buffer, start, buffer, totalread + offset, read); totalread += read; _read += read; } return totalread; } @Override public int read(byte[] buffer) throws IOException { int length = buffer.length; if ( buffer.length > (getSize()-_read) ) length = (int)(getSize() - _read); return read(buffer,0,length); } public String getAsString() throws ParseException { return super.getAsString(); } @Override public synchronized void reset() throws IOException { _read = 0; } }