KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > Buffer


1 /*
2    Copyright (C) 2002 MySQL AB
3
4       This program is free software; you can redistribute it and/or modify
5       it under the terms of the GNU General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8
9       This program is distributed in the hope that it will be useful,
10       but WITHOUT ANY WARRANTY; without even the implied warranty of
11       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12       GNU General Public License for more details.
13
14       You should have received a copy of the GNU General Public License
15       along with this program; if not, write to the Free Software
16       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18  */

19 package com.mysql.jdbc;
20
21 import java.io.UnsupportedEncodingException JavaDoc;
22
23 import java.sql.SQLException JavaDoc;
24
25
26 /**
27  * Buffer contains code to read and write packets from/to the MySQL server.
28  *
29  * @version $Id: Buffer.java,v 1.15.2.12 2004/01/07 01:36:34 mmatthew Exp $
30  * @author Mark Matthews
31  */

32 class Buffer {
33     static final int NO_LENGTH_LIMIT = -1;
34     static final long NULL_LENGTH = -1;
35     private byte[] byteBuffer;
36     private boolean wasMultiPacket = false;
37     private int bufLength = 0;
38     private int position = 0;
39     private int sendLength = 0;
40
41     Buffer(byte[] buf) {
42         this.byteBuffer = buf;
43         setBufLength(buf.length);
44     }
45
46     Buffer(int size) {
47         this.byteBuffer = new byte[size];
48         setBufLength(this.byteBuffer.length);
49         this.position = MysqlIO.HEADER_LENGTH;
50     }
51
52     /**
53      * Sets the array of bytes to use as a buffer to read from.
54      *
55      * @param byteBuffer the array of bytes to use as a buffer
56      */

57     public void setByteBuffer(byte[] byteBuffer) {
58         this.byteBuffer = byteBuffer;
59     }
60
61     /**
62      * Returns the array of bytes this Buffer is using to read from.
63      *
64      * @return byte array being read from
65      */

66     public byte[] getByteBuffer() {
67         return this.byteBuffer;
68     }
69
70     /**
71      * Set the current position to write to/ read from
72      *
73      * @param position the position (0-based index)
74      */

75     public void setPosition(int position) {
76         this.position = position;
77     }
78
79     /**
80      * Returns the current position to write to/ read from
81      *
82      * @return the current position to write to/ read from
83      */

84     public int getPosition() {
85         return this.position;
86     }
87
88     /**
89      * Sets whether this packet was part of a multipacket
90      *
91      * @param flag was this packet part of a multipacket?
92      */

93     public void setWasMultiPacket(boolean flag) {
94         wasMultiPacket = flag;
95     }
96
97     /**
98      * Skip over a length-encoded string
99      *
100      * @return The position past the end of the string
101      */

102     public int fastSkipLenString() {
103         long len = this.readFieldLength();
104
105         position += len;
106
107         return (int) len; // this is safe, as this is only
108
}
109
110     /**
111      * Was this packet part of a multipacket?
112      *
113      * @return was this packet part of a multipacket?
114      */

115     public boolean wasMultiPacket() {
116         return wasMultiPacket;
117     }
118
119     protected final byte[] getBufferSource() {
120         return byteBuffer;
121     }
122
123     final byte[] getBytes(int len) {
124         byte[] b = new byte[len];
125         System.arraycopy(this.byteBuffer, this.position, b, 0, len);
126         this.position += len; // update cursor
127

128         return b;
129     }
130
131     // 2000-06-05 Changed
132
final boolean isLastDataPacket() {
133         return ((getBufLength() < 9) && ((this.byteBuffer[0] & 0xff) == 254));
134     }
135
136     final void clear() {
137         this.position = MysqlIO.HEADER_LENGTH;
138     }
139
140     final void dump() {
141         StringUtils.dumpAsHex(this.byteBuffer, getBufLength());
142     }
143
144     final void dumpHeader() {
145         for (int i = 0; i < MysqlIO.HEADER_LENGTH; i++) {
146             String JavaDoc hexVal = Integer.toHexString((int) this.byteBuffer[i] & 0xff);
147
148             if (hexVal.length() == 1) {
149                 hexVal = "0" + hexVal;
150             }
151
152             System.out.print(hexVal + " ");
153         }
154     }
155
156     final void dumpNBytes(int start, int nBytes) {
157         StringBuffer JavaDoc asciiBuf = new StringBuffer JavaDoc();
158
159         for (int i = start;
160                 (i < (start + nBytes)) && (i < this.byteBuffer.length); i++) {
161             String JavaDoc hexVal = Integer.toHexString((int) this.byteBuffer[i] & 0xff);
162
163             if (hexVal.length() == 1) {
164                 hexVal = "0" + hexVal;
165             }
166
167             System.out.print(hexVal + " ");
168
169             if ((this.byteBuffer[i] > 32) && (this.byteBuffer[i] < 127)) {
170                 asciiBuf.append((char) this.byteBuffer[i]);
171             } else {
172                 asciiBuf.append(".");
173             }
174
175             asciiBuf.append(" ");
176         }
177
178         System.out.println(" " + asciiBuf.toString());
179     }
180
181     final void ensureCapacity(int additionalData) throws SQLException JavaDoc {
182         if ((this.position + additionalData) > getBufLength()) {
183             if ((this.position + additionalData) < this.byteBuffer.length) {
184                 // byteBuffer.length is != getBufLength() all of the time
185
// due to re-using of packets (we don't shrink them)
186
//
187
// If we can, don't re-alloc, just set buffer length
188
// to size of current buffer
189
setBufLength(this.byteBuffer.length);
190             } else {
191                 //
192
// Otherwise, re-size, and pad so we can avoid
193
// allocing again in the near future
194
//
195
int newLength = (int) (this.byteBuffer.length * 1.25);
196
197                 if (newLength < (this.byteBuffer.length + additionalData)) {
198                     newLength = this.byteBuffer.length
199                         + (int) (additionalData * 1.25);
200                 }
201
202                 if (newLength < this.byteBuffer.length) {
203                     newLength = this.byteBuffer.length + additionalData;
204                 }
205
206                 byte[] newBytes = new byte[newLength];
207
208                 System.arraycopy(this.byteBuffer, 0, newBytes, 0,
209                     this.byteBuffer.length);
210                 this.byteBuffer = newBytes;
211                 setBufLength(this.byteBuffer.length);
212             }
213         }
214     }
215
216     final long newReadLength() {
217         int sw = this.byteBuffer[this.position++] & 0xff;
218
219         switch (sw) {
220         case 251:
221             return (long) 0;
222
223         case 252:
224             return (long) readInt();
225
226         case 253:
227             return (long) readLongInt();
228
229         case 254: // changed for 64 bit lengths
230
return (long) readLongLong();
231
232         default:
233             return (long) sw;
234         }
235     }
236
237     final byte readByte() {
238         return this.byteBuffer[this.position++];
239     }
240
241     final long readFieldLength() {
242         int sw = this.byteBuffer[this.position++] & 0xff;
243
244         switch (sw) {
245         case 251:
246             return NULL_LENGTH;
247
248         case 252:
249             return (long) readInt();
250
251         case 253:
252             return (long) readLongInt();
253
254         case 254:
255             return readLongLong();
256
257         default:
258             return (long) sw;
259         }
260     }
261
262     // 2000-06-05 Changed
263
final int readInt() {
264         byte[] b = this.byteBuffer; // a little bit optimization
265

266         return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8);
267     }
268
269     final byte[] readLenByteArray(int offset) {
270         long len = this.readFieldLength();
271
272         if (len == NULL_LENGTH) {
273             return null;
274         }
275
276         if (len == 0) {
277             return new byte[0];
278         }
279
280         this.position += offset;
281
282         return getBytes((int) len);
283     }
284
285     final long readLength() {
286         int sw = this.byteBuffer[this.position++] & 0xff;
287
288         switch (sw) {
289         case 251:
290             return (long) 0;
291
292         case 252:
293             return (long) readInt();
294
295         case 253:
296             return (long) readLongInt();
297
298         case 254:
299             return (long) readLong();
300
301         default:
302             return (long) sw;
303         }
304     }
305
306     // 2000-06-05 Fixed
307
final long readLong() {
308         byte[] b = this.byteBuffer;
309
310         return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
311         | ((b[this.position++] & 0xff) << 16)
312         | ((b[this.position++] & 0xff) << 24);
313     }
314
315     // 2000-06-05 Changed
316
final int readLongInt() {
317         byte[] b = this.byteBuffer;
318
319         return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
320         | ((b[this.position++] & 0xff) << 16);
321     }
322
323     // 2000-06-05 Fixed
324
final long readLongLong() {
325         byte[] b = this.byteBuffer;
326
327         return (long) (b[this.position++] & 0xff)
328         | ((long) (b[this.position++] & 0xff) << 8)
329         | ((long) (b[this.position++] & 0xff) << 16)
330         | ((long) (b[this.position++] & 0xff) << 24)
331         | ((long) (b[this.position++] & 0xff) << 32)
332         | ((long) (b[this.position++] & 0xff) << 40)
333         | ((long) (b[this.position++] & 0xff) << 48)
334         | ((long) (b[this.position++] & 0xff) << 56);
335     }
336
337     //
338
// Read a null-terminated string
339
//
340
// To avoid alloc'ing a new byte array, we
341
// do this by hand, rather than calling getNullTerminatedBytes()
342
//
343
final String JavaDoc readString() {
344         int i = this.position;
345         int len = 0;
346         int maxLen = getBufLength();
347         
348         while ((i < maxLen) && (this.byteBuffer[i] != 0)) {
349             len++;
350             i++;
351         }
352
353         String JavaDoc s = new String JavaDoc(this.byteBuffer, this.position, len);
354         this.position += (len + 1); // update cursor
355

356         return s;
357     }
358     
359     final String JavaDoc readString(String JavaDoc encoding) throws SQLException JavaDoc {
360         int i = this.position;
361         int len = 0;
362         int maxLen = getBufLength();
363         
364         while ((i < maxLen) && (this.byteBuffer[i] != 0)) {
365             len++;
366             i++;
367         }
368
369         this.position += (len + 1); // update cursor
370

371         try {
372             return new String JavaDoc(this.byteBuffer, this.position, len, encoding);
373             
374         } catch (UnsupportedEncodingException JavaDoc uEE) {
375             throw new SQLException JavaDoc("Unsupported character encoding '" + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
376         }
377     }
378
379     final int readnBytes() {
380         int sw = this.byteBuffer[this.position++] & 0xff;
381
382         switch (sw) {
383         case 1:
384             return this.byteBuffer[this.position++] & 0xff;
385
386         case 2:
387             return this.readInt();
388
389         case 3:
390             return this.readLongInt();
391
392         case 4:
393             return (int) this.readLong();
394
395         default:
396             return 255;
397         }
398     }
399
400     final void writeByte(byte b) throws SQLException JavaDoc {
401         ensureCapacity(1);
402
403         this.byteBuffer[this.position++] = b;
404     }
405
406     // Write a byte array
407
final void writeBytesNoNull(byte[] bytes) throws SQLException JavaDoc {
408         int len = bytes.length;
409         ensureCapacity(len);
410         System.arraycopy(bytes, 0, this.byteBuffer, this.position, len);
411         this.position += len;
412     }
413
414     // Write a byte array with the given offset and length
415
final void writeBytesNoNull(byte[] bytes, int offset, int length)
416         throws SQLException JavaDoc {
417         ensureCapacity(length);
418         System.arraycopy(bytes, offset, this.byteBuffer, this.position, length);
419         this.position += length;
420     }
421
422     final void writeDouble(double d) {
423         long l = Double.doubleToLongBits(d);
424         writeLongLong(l);
425     }
426
427     final void writeFloat(float f) {
428         int i = Float.floatToIntBits(f);
429         byte[] b = this.byteBuffer;
430         b[this.position++] = (byte) (i & 0xff);
431         b[this.position++] = (byte) (i >>> 8);
432         b[this.position++] = (byte) (i >>> 16);
433         b[this.position++] = (byte) (i >>> 24);
434     }
435
436     // 2000-06-05 Changed
437
final void writeInt(int i) {
438         byte[] b = this.byteBuffer;
439         b[this.position++] = (byte) (i & 0xff);
440         b[this.position++] = (byte) (i >>> 8);
441     }
442
443     // 2000-06-05 Changed
444
final void writeLong(long i) {
445         byte[] b = this.byteBuffer;
446         b[this.position++] = (byte) (i & 0xff);
447         b[this.position++] = (byte) (i >>> 8);
448         b[this.position++] = (byte) (i >>> 16);
449         b[this.position++] = (byte) (i >>> 24);
450     }
451
452     // 2000-06-05 Changed
453
final void writeLongInt(int i) {
454         byte[] b = this.byteBuffer;
455         b[this.position++] = (byte) (i & 0xff);
456         b[this.position++] = (byte) (i >>> 8);
457         b[this.position++] = (byte) (i >>> 16);
458     }
459
460     final void writeLongLong(long i) {
461         byte[] b = this.byteBuffer;
462         b[this.position++] = (byte) (i & 0xff);
463         b[this.position++] = (byte) (i >>> 8);
464         b[this.position++] = (byte) (i >>> 16);
465         b[this.position++] = (byte) (i >>> 24);
466         b[this.position++] = (byte) (i >>> 32);
467         b[this.position++] = (byte) (i >>> 40);
468         b[this.position++] = (byte) (i >>> 48);
469         b[this.position++] = (byte) (i >>> 56);
470     }
471
472     // Write null-terminated string
473
final void writeString(String JavaDoc s) throws SQLException JavaDoc {
474         ensureCapacity(s.length() + 1);
475         
476         writeStringNoNull(s);
477         this.byteBuffer[this.position++] = 0;
478     }
479
480     // Write string, with no termination
481
final void writeStringNoNull(String JavaDoc s) throws SQLException JavaDoc {
482         int len = s.length();
483         ensureCapacity(len);
484         System.arraycopy(s.getBytes(), 0, byteBuffer, position, len);
485         position += len;
486
487         // for (int i = 0; i < len; i++)
488
// {
489
// this.byteBuffer[this.position++] = (byte)s.charAt(i);
490
// }
491
}
492
493     // Write a String using the specified character
494
// encoding
495
final void writeStringNoNull(String JavaDoc s, String JavaDoc encoding, SingleByteCharsetConverter converter)
496         throws UnsupportedEncodingException JavaDoc, SQLException JavaDoc {
497         byte[] b = null;
498         
499         if (converter != null) {
500             b = converter.toBytes(s);
501         } else {
502             b = StringUtils.getBytes(s, encoding);
503         }
504
505         int len = b.length;
506         ensureCapacity(len);
507         System.arraycopy(b, 0, this.byteBuffer, this.position, len);
508         this.position += len;
509     }
510
511     void setBufLength(int bufLength) {
512         this.bufLength = bufLength;
513     }
514
515     int getBufLength() {
516         return bufLength;
517     }
518
519     void setSendLength(int sendLength) {
520         this.sendLength = sendLength;
521     }
522 }
523
Popular Tags