All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bson.io.PoolOutputBuffer Maven / Gradle / Ivy

There is a newer version: 5.10
Show newest version
// PoolOutputBuffer.java

/**
 *      Copyright (C) 2008 10gen Inc.
 *
 *   Licensed 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.bson.io;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

public class PoolOutputBuffer extends OutputBuffer {

	public static final int BUF_SIZE = 1024 * 16;

	public PoolOutputBuffer() {
		reset();
	}

	public void reset() {
		_cur.reset();
		_end.reset();

		for (int i = 0; i < _fromPool.size(); i++)
			_extra.done(_fromPool.get(i));
		_fromPool.clear();
	}

	@Override
	public int getPosition() {
		return _cur.pos();
	}

	@Override
	public void setPosition(int position) {
		_cur.reset(position);
	}

	@Override
	public void seekEnd() {
		_cur.reset(_end);
	}

	@Override
	public void seekStart() {
		_cur.reset();
	}

	@Override
	public int size() {
		return _end.pos();
	}

	@Override
	public void write(byte[] b) {
		write(b, 0, b.length);
	}

	@Override
	public void write(byte[] b, int off, int len) {
		while (len > 0) {
			byte[] bs = _cur();
			int space = Math.min(bs.length - _cur.y, len);
			System.arraycopy(b, off, bs, _cur.y, space);
			_cur.inc(space);
			len -= space;
			off += space;
			_afterWrite();
		}
	}

	@Override
	public void write(int b) {
		byte[] bs = _cur();
		bs[_cur.getAndInc()] = (byte) (b & 0xFF);
		_afterWrite();
	}

	void _afterWrite() {

		if (_cur.pos() < _end.pos()) {
			// we're in the middle of the total space
			// just need to make sure we're not at the end of a buffer
			if (_cur.y == BUF_SIZE) _cur.nextBuffer();
			return;
		}

		_end.reset(_cur);

		if (_end.y < BUF_SIZE) return;

		_fromPool.add(_extra.get());
		_end.nextBuffer();
		_cur.reset(_end);
	}

	byte[] _cur() {
		return _get(_cur.x);
	}

	byte[] _get(int z) {
		if (z < 0) return _mine;
		return _fromPool.get(z);
	}

	@Override
	public int pipe(final OutputStream out) throws IOException {

		if (out == null) throw new NullPointerException("out is null");

		int total = 0;

		for (int i = -1; i < _fromPool.size(); i++) {
			final byte[] b = _get(i);
			final int amt = _end.len(i);
			out.write(b, 0, amt);
			total += amt;
		}

		return total;
	}

	static class Position {
		Position() {
			reset();
		}

		void reset() {
			x = -1;
			y = 0;
		}

		void reset(Position other) {
			x = other.x;
			y = other.y;
		}

		void reset(int pos) {
			x = (pos / BUF_SIZE) - 1;
			y = pos % BUF_SIZE;
		}

		int pos() {
			return ((x + 1) * BUF_SIZE) + y;
		}

		int getAndInc() {
			return y++;
		}

		void inc(int amt) {
			y += amt;
			if (y > BUF_SIZE) throw new IllegalArgumentException("something is wrong");
		}

		void nextBuffer() {
			if (y != BUF_SIZE) throw new IllegalArgumentException("broken");
			x++;
			y = 0;
		}

		int len(int which) {
			if (which < x) return BUF_SIZE;
			return y;
		}

		@Override
		public String toString() {
			return x + "," + y;
		}

		int x; // which buffer -1 == _mine
		int y; // position in buffer
	}

	public String asAscii() {
		if (_fromPool.size() > 0) return super.asString();

		final int m = size();
		final char c[] = m < _chars.length ? _chars : new char[m];

		for (int i = 0; i < m; i++)
			c[i] = (char) _mine[i];

		return new String(c, 0, m);
	}

	@Override
	public String asString(String encoding) throws UnsupportedEncodingException {

		if (_fromPool.size() > 0) return super.asString(encoding);

		if (encoding.equals(DEFAULT_ENCODING_1) || encoding.equals(DEFAULT_ENCODING_2)) {
			try {
				return _encoding.decode(_mine, 0, size());
			} catch (IOException ioe) {
				// we failed, fall back
			}
		}
		return new String(_mine, 0, size(), encoding);
	}

	final byte[] _mine = new byte[BUF_SIZE];
	final char[] _chars = new char[BUF_SIZE];
	final List _fromPool = new ArrayList();
	final UTF8Encoding _encoding = new UTF8Encoding();

	private static final String DEFAULT_ENCODING_1 = "UTF-8";
	private static final String DEFAULT_ENCODING_2 = "UTF8";

	private final Position _cur = new Position();
	private final Position _end = new Position();

	private static org.bson.util.SimplePool _extra = new org.bson.util.SimplePool((1024 * 1024 * 10) / BUF_SIZE) {

		@Override
		protected byte[] createNew() {
			return new byte[BUF_SIZE];
		}

	};
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy