001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.mime4j.util;
021
022
023 /**
024 * A resizable byte array.
025 */
026 public final class ByteArrayBuffer implements ByteSequence {
027
028 private byte[] buffer;
029 private int len;
030
031 public ByteArrayBuffer(int capacity) {
032 super();
033 if (capacity < 0) {
034 throw new IllegalArgumentException("Buffer capacity may not be negative");
035 }
036 this.buffer = new byte[capacity];
037 }
038
039 public ByteArrayBuffer(byte[] bytes, boolean dontCopy) {
040 this(bytes, bytes.length, dontCopy);
041 }
042
043 public ByteArrayBuffer(byte[] bytes, int len, boolean dontCopy) {
044 if (bytes == null)
045 throw new IllegalArgumentException();
046 if (len < 0 || len > bytes.length)
047 throw new IllegalArgumentException();
048
049 if (dontCopy) {
050 this.buffer = bytes;
051 } else {
052 this.buffer = new byte[len];
053 System.arraycopy(bytes, 0, this.buffer, 0, len);
054 }
055
056 this.len = len;
057 }
058
059 private void expand(int newlen) {
060 byte newbuffer[] = new byte[Math.max(this.buffer.length << 1, newlen)];
061 System.arraycopy(this.buffer, 0, newbuffer, 0, this.len);
062 this.buffer = newbuffer;
063 }
064
065 public void append(final byte[] b, int off, int len) {
066 if (b == null) {
067 return;
068 }
069 if ((off < 0) || (off > b.length) || (len < 0) ||
070 ((off + len) < 0) || ((off + len) > b.length)) {
071 throw new IndexOutOfBoundsException();
072 }
073 if (len == 0) {
074 return;
075 }
076 int newlen = this.len + len;
077 if (newlen > this.buffer.length) {
078 expand(newlen);
079 }
080 System.arraycopy(b, off, this.buffer, this.len, len);
081 this.len = newlen;
082 }
083
084 public void append(int b) {
085 int newlen = this.len + 1;
086 if (newlen > this.buffer.length) {
087 expand(newlen);
088 }
089 this.buffer[this.len] = (byte)b;
090 this.len = newlen;
091 }
092
093 public void clear() {
094 this.len = 0;
095 }
096
097 public byte[] toByteArray() {
098 byte[] b = new byte[this.len];
099 if (this.len > 0) {
100 System.arraycopy(this.buffer, 0, b, 0, this.len);
101 }
102 return b;
103 }
104
105 public byte byteAt(int i) {
106 if (i < 0 || i >= this.len)
107 throw new IndexOutOfBoundsException();
108
109 return this.buffer[i];
110 }
111
112 public int capacity() {
113 return this.buffer.length;
114 }
115
116 public int length() {
117 return this.len;
118 }
119
120 public byte[] buffer() {
121 return this.buffer;
122 }
123
124 public int indexOf(byte b) {
125 return indexOf(b, 0, this.len);
126 }
127
128 public int indexOf(byte b, int beginIndex, int endIndex) {
129 if (beginIndex < 0) {
130 beginIndex = 0;
131 }
132 if (endIndex > this.len) {
133 endIndex = this.len;
134 }
135 if (beginIndex > endIndex) {
136 return -1;
137 }
138 for (int i = beginIndex; i < endIndex; i++) {
139 if (this.buffer[i] == b) {
140 return i;
141 }
142 }
143 return -1;
144 }
145
146 public void setLength(int len) {
147 if (len < 0 || len > this.buffer.length) {
148 throw new IndexOutOfBoundsException();
149 }
150 this.len = len;
151 }
152
153 public void remove(int off, int len) {
154 if ((off < 0) || (off > this.len) || (len < 0) ||
155 ((off + len) < 0) || ((off + len) > this.len)) {
156 throw new IndexOutOfBoundsException();
157 }
158 if (len == 0) {
159 return;
160 }
161 int remaining = this.len - off - len;
162 if (remaining > 0) {
163 System.arraycopy(this.buffer, off + len, this.buffer, off, remaining);
164 }
165 this.len -= len;
166 }
167
168 public boolean isEmpty() {
169 return this.len == 0;
170 }
171
172 public boolean isFull() {
173 return this.len == this.buffer.length;
174 }
175
176 @Override
177 public String toString() {
178 return new String(toByteArray());
179 }
180
181 }