org.apache.mina.util.byteaccess.CompositeByteArrayRelativeWriter Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.mina.util.byteaccess;
import org.apache.mina.core.buffer.IoBuffer;
/**
* Provides restricted, relative, write-only access to the bytes in a
* CompositeByteArray
.
*
* Using this interface has the advantage that it can be automatically
* determined when a component ByteArray
can no longer be written
* to, and thus components can be automatically flushed. This makes it easier to
* use pooling for underlying ByteArray
s.
*
* By providing an appropriate Expander
it is also possible to
* automatically add more backing storage as more data is written.
*
*
* TODO: Get flushing working.
*
* @author Apache MINA Project
*/
public class CompositeByteArrayRelativeWriter extends CompositeByteArrayRelativeBase implements IoRelativeWriter {
/**
* An object that knows how to expand a CompositeByteArray
.
*/
public interface Expander {
/**
* Expand a ByteBuffer by minSize bytes
* @param cba The ByteBuffer to expand
* @param minSize The new added size
*/
void expand(CompositeByteArray cba, int minSize);
}
/**
* No-op expander. The overridden method does nothing.
*
*/
public static class NopExpander implements Expander {
/**
* {@inheritDoc}
*/
@Override
public void expand(CompositeByteArray cba, int minSize) {
// Do nothing.
}
}
/**
* Expands the supplied {@link CompositeByteArray} by the number of
* bytes provided in the constructor
*
*/
public static class ChunkedExpander implements Expander {
private final ByteArrayFactory baf;
private final int newComponentSize;
/**
* Creates a new ChunkedExpander instance
*
* @param baf The byte array factory
* @param newComponentSize The new size
*/
public ChunkedExpander(ByteArrayFactory baf, int newComponentSize) {
this.baf = baf;
this.newComponentSize = newComponentSize;
}
/**
* {@inheritDoc}
*/
@Override
public void expand(CompositeByteArray cba, int minSize) {
int remaining = minSize;
while (remaining > 0) {
ByteArray component = baf.create(newComponentSize);
cba.addLast(component);
remaining -= newComponentSize;
}
}
}
/**
* An object that knows how to flush a ByteArray
.
*/
public interface Flusher {
/**
* Flush a byte array
*
* @param ba The byte array to flush
*/
void flush(ByteArray ba);
}
/**
* The expander to use when the array underflows.
*/
private final Expander expander;
/**
* The flusher to use when flushing component ByteArray
s.
*/
private final Flusher flusher;
/**
* Whether or not to automatically flush a component once the cursor moves
* past it.
*/
private final boolean autoFlush;
/**
*
* Creates a new instance of CompositeByteArrayRelativeWriter.
*
* @param cba
* The CompositeByteArray to use to back this class
* @param expander
* The expander. Will increase the size of the internal ByteArray
* @param flusher
* Flushed the ByteArray when necessary
* @param autoFlush
* Should this class automatically flush?
*/
public CompositeByteArrayRelativeWriter(CompositeByteArray cba, Expander expander, Flusher flusher,
boolean autoFlush) {
super(cba);
this.expander = expander;
this.flusher = flusher;
this.autoFlush = autoFlush;
}
private void prepareForAccess(int size) {
int underflow = cursor.getIndex() + size - last();
if (underflow > 0) {
expander.expand(cba, underflow);
}
}
/**
* Flush to the current index.
*/
public void flush() {
flushTo(cursor.getIndex());
}
/**
* Flush to the given index.
*
* @param index The end position
*/
public void flushTo(int index) {
ByteArray removed = cba.removeTo(index);
flusher.flush(removed);
}
/**
* {@inheritDoc}
*/
@Override
public void skip(int length) {
cursor.skip(length);
}
@Override
protected void cursorPassedFirstComponent() {
if (autoFlush) {
flushTo(cba.first() + cba.getFirst().length());
}
}
/**
* {@inheritDoc}
*/
@Override
public void put(byte b) {
prepareForAccess(1);
cursor.put(b);
}
/**
* {@inheritDoc}
*/
@Override
public void put(IoBuffer bb) {
prepareForAccess(bb.remaining());
cursor.put(bb);
}
/**
* {@inheritDoc}
*/
@Override
public void putShort(short s) {
prepareForAccess(2);
cursor.putShort(s);
}
/**
* {@inheritDoc}
*/
@Override
public void putInt(int i) {
prepareForAccess(4);
cursor.putInt(i);
}
/**
* {@inheritDoc}
*/
@Override
public void putLong(long l) {
prepareForAccess(8);
cursor.putLong(l);
}
/**
* {@inheritDoc}
*/
@Override
public void putFloat(float f) {
prepareForAccess(4);
cursor.putFloat(f);
}
/**
* {@inheritDoc}
*/
@Override
public void putDouble(double d) {
prepareForAccess(8);
cursor.putDouble(d);
}
/**
* {@inheritDoc}
*/
@Override
public void putChar(char c) {
prepareForAccess(2);
cursor.putChar(c);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy