View Javadoc
1   //////////////////////////////////////////////////////////////////////////////
2   // dexterIM - Instant Messaging Framework
3   // Copyright (C) 2003  Christoph Walcher
4   //
5   // This program is free software; you can redistribute it and/or modify
6   // it under the terms of the GNU General Public License as published by
7   // the Free Software Foundation; either version 2 of the License, or
8   // (at your option) any later version.
9   //
10  // This program is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  // GNU General Public License for more details.
14  //
15  // You should have received a copy of the GNU General Public License
16  // along with this program; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  //////////////////////////////////////////////////////////////////////////////
19  package net.sf.dexterim.oscar;
20  
21  import net.sf.dexterim.oscar.entity.ByteBased;
22  import net.sf.dexterim.oscar.entity.DWord;
23  import net.sf.dexterim.oscar.entity.Word;
24  
25  
26  /***
27   * @author Christoph Walcher
28   */
29  class DynamicByteBuffer extends OscarByteBuffer {
30  
31  	private byte[] data;
32  	private int position;
33  	private int fill;
34  	
35  	public DynamicByteBuffer() {
36  		this(32);
37  	}
38  	
39  	public DynamicByteBuffer(int initialSize) {
40  		this.data = new byte[initialSize];
41  		this.position = 0;
42  		this.fill = 0;
43  	}
44  	
45  	/***
46  	 * @param data
47  	 */
48  	public DynamicByteBuffer(byte[] data) {
49  		this.data = data;
50  		this.position = 0;
51  		this.fill = data.length;
52  	}
53  
54  	/***
55  	 * @see net.sf.dexterim.oscar.OscarByteBuffer#position(int)
56  	 */
57  	public int position(int position) {
58  		if (position < 0 || position >= data.length) {
59  			reallocateArray(position);
60  			this.fill = position;
61  		}
62  		
63  		int oldPosition = this.position;
64  		this.position = position;
65  		
66  		return oldPosition;
67  	}
68  
69  	/*** 
70  	 * @see net.sf.dexterim.oscar.OscarByteBuffer#position()
71  	 */
72  	public int position() {
73  		return position;
74  	}
75  
76  	public int size() {
77  		return data.length;
78  	}
79  
80  	public int fill() {
81  		return fill;
82  	}
83  
84  	public int strip() {
85  		return this.fill = position;
86  	}
87  	
88  	private void adjustFill() {
89  		if (this.position > this.fill) {
90  			this.fill = this.position;
91  		}
92  	}
93  	
94  	/***
95  	 * @see net.sf.dexterim.oscar.OscarByteBuffer#getWord()
96  	 */
97  	public Word getWord() {
98  		Word returnValue = new Word(data[position], data[position+1]);
99  		
100 		position+=returnValue.getLength();
101 		
102 		return returnValue;
103 	}
104 	
105 	/***
106 	 * @see net.sf.dexterim.oscar.OscarByteBuffer#getDWord()
107 	 */
108 	public DWord getDWord() {
109 		byte[] targetArray = new byte[4];
110 		System.arraycopy(data, position, targetArray, 0, targetArray.length);
111 		
112 		position+=targetArray.length;
113 		return new DWord(targetArray);
114 	}
115 
116 	/***
117 	 * @see net.sf.dexterim.oscar.OscarByteBuffer#getByte()
118 	 */
119 	public int getByte() {
120 		return data[position++];
121 	}
122 
123 	public OscarByteBuffer write(ByteBased source) {
124 		if (position + source.getLength() > data.length) {
125 			reallocateArray(data.length + source.getLength());
126 		}
127 		
128 		byte sourceArray[] = source.toByteArray();
129 		System.arraycopy(sourceArray, 0, data, position, sourceArray.length);
130 		
131 		position+=sourceArray.length;
132 		
133 		adjustFill();
134 		
135 		return this;
136 	}
137 	
138 	/*** Writes a OscarByteBuffer. Uses a single System.arraycopy call.
139 	 * @see net.sf.dexterim.oscar.OscarByteBuffer#write(net.sf.dexterim.oscar.OscarByteBuffer)
140 	 */
141 	public OscarByteBuffer write(OscarByteBuffer buffer) {
142 		byte[] source = buffer.slice();
143 		
144 		if (position + source.length > data.length) {
145 			reallocateArray(data.length + source.length);
146 		}
147 		
148 		System.arraycopy(source, 0, data, position, source.length);
149 		position+=source.length;
150 		
151 		adjustFill();
152 		
153 		return this;
154 	}
155 
156 	public OscarByteBuffer write(byte source) {
157 		if (position + 1 > data.length) {
158 			reallocateArray(data.length + 1);
159 		}
160 		
161 		data[position++] = source;
162 		
163 		adjustFill();
164 		
165 		return this;
166 	}
167 	
168 	/***
169 	 * @param i
170 	 */
171 	private void reallocateArray(int newSize) {
172 		byte newData[] = new byte[newSize];
173 		
174 		System.arraycopy(this.data, 0, newData, 0, this.data.length);
175 		
176 		this.data = newData;
177 	}
178 
179 	/***
180 	 * @see net.sf.dexterim.oscar.OscarByteBuffer#array()
181 	 */
182 	public byte[] array() {
183 		return data;
184 	}
185 
186 	/*** 
187 	 * Allocates a new Array with position entries and returns this new
188 	 * Array. Modifications done to return value will not be reflected in
189 	 * DynamicByteBuffer instance.
190 	 * @return new allocated array containing data up to position
191 	 */
192 	public byte[] slice() {
193 		byte slice[] = new byte[fill];
194 		
195 		System.arraycopy(data, 0, slice, 0, position);
196 		
197 		return slice;
198 	}
199 }