001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.vfs;
031:
032: import com.caucho.util.FreeList;
033:
034: import java.io.IOException;
035:
036: /**
037: * Pooled temporary byte buffer.
038: */
039: public class TempBuffer {
040: private static FreeList<TempBuffer> _freeList = new FreeList<TempBuffer>(
041: 32);
042: public static final int SIZE = 16 * 1024;
043:
044: TempBuffer _next;
045: final byte[] _buf;
046: int _offset;
047: int _length;
048: int _bufferCount;
049:
050: /**
051: * Create a new TempBuffer.
052: */
053: public TempBuffer(int size) {
054: _buf = new byte[size];
055: }
056:
057: /**
058: * Allocate a TempBuffer, reusing one if available.
059: */
060: public static TempBuffer allocate() {
061: TempBuffer next = _freeList.allocate();
062:
063: if (next == null)
064: return new TempBuffer(SIZE);
065:
066: next._next = null;
067:
068: next._offset = 0;
069: next._length = 0;
070: next._bufferCount = 0;
071:
072: return next;
073: }
074:
075: /**
076: * Clears the buffer.
077: */
078: public void clear() {
079: _next = null;
080:
081: _offset = 0;
082: _length = 0;
083: _bufferCount = 0;
084: }
085:
086: /**
087: * Returns the buffer's underlying byte array.
088: */
089: public final byte[] getBuffer() {
090: return _buf;
091: }
092:
093: /**
094: * Returns the number of bytes in the buffer.
095: */
096: public final int getLength() {
097: return _length;
098: }
099:
100: /**
101: * Sets the number of bytes used in the buffer.
102: */
103: public final void setLength(int length) {
104: _length = length;
105: }
106:
107: public final int getCapacity() {
108: return _buf.length;
109: }
110:
111: public int getAvailable() {
112: return _buf.length - _length;
113: }
114:
115: public final TempBuffer getNext() {
116: return _next;
117: }
118:
119: public final void setNext(TempBuffer next) {
120: _next = next;
121: }
122:
123: public int write(byte[] buf, int offset, int length) {
124: byte[] this Buf = _buf;
125: int this Length = _length;
126:
127: if (this Buf.length - this Length < length)
128: length = this Buf.length - this Length;
129:
130: System.arraycopy(buf, offset, this Buf, this Length, length);
131:
132: _length = this Length + length;
133:
134: return length;
135: }
136:
137: public static TempBuffer copyFromStream(ReadStream is)
138: throws IOException {
139: TempBuffer head = TempBuffer.allocate();
140: TempBuffer tail = head;
141: int len;
142:
143: while ((len = is.readAll(tail._buf, 0, tail._buf.length)) == tail._buf.length) {
144: TempBuffer buf = TempBuffer.allocate();
145: tail._length = len;
146: tail._next = buf;
147: tail = buf;
148: }
149:
150: if (len == 0 && head == tail)
151: return null; // XXX: TempBuffer leak of _head?
152: else if (len == 0) {
153: for (TempBuffer ptr = head; ptr.getNext() != null; ptr = ptr
154: .getNext()) {
155: TempBuffer next = ptr.getNext();
156:
157: if (next.getNext() == null) {
158: TempBuffer.free(next);
159: next = null;
160: ptr._next = null;
161: }
162: }
163: } else
164: tail._length = len;
165:
166: return head;
167: }
168:
169: /**
170: * Frees a single buffer.
171: */
172: public static void free(TempBuffer buf) {
173: buf._next = null;
174:
175: if (buf._buf.length == SIZE)
176: _freeList.free(buf);
177: }
178:
179: public static void freeAll(TempBuffer buf) {
180: while (buf != null) {
181: TempBuffer next = buf._next;
182: buf._next = null;
183: if (buf._buf.length == SIZE)
184: _freeList.free(buf);
185: buf = next;
186: }
187: }
188: }
|