001: package com.quadcap.sql.io;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.*;
042:
043: import java.io.DataOutput;
044: import java.io.IOException;
045: import java.io.OutputStream;
046:
047: import com.quadcap.util.Debug;
048: import com.quadcap.util.Util;
049:
050: /**
051: * This class implements data output somewhat more efficiently than
052: * the JDK version. It also implements buffering and counting,
053: * to help us avoid extra layers of stream classes.
054: *
055: * 4/2/03: XX What JDK version? this hasn't been examined recently...
056: *
057: * @author Stan Bailes
058: */
059: public class DataOutputStream extends OutputStream implements
060: DataOutput {
061: static final int MAX = 4096;
062: OutputStream out;
063: byte[] buf = new byte[MAX];
064: byte[] tbuf = new byte[16];
065: Object[] bufs = null;
066: int bufsCnt = 0;
067: int pos = 0;
068: int siz = -1;
069: int count = 0;
070:
071: public DataOutputStream(OutputStream out) {
072: this .out = out;
073: }
074:
075: public void reset(OutputStream out) {
076: this .out = out;
077: bufsCnt = 0;
078: pos = 0;
079: count = 0;
080: siz = -1;
081: if (bufs != null && bufs.length > 0) {
082: buf = (byte[]) bufs[0];
083: }
084: }
085:
086: final Object[] resize(Object[] array, int size) {
087: Object[] narray = new Object[size];
088: System.arraycopy(array, 0, narray, 0, array.length);
089: return narray;
090: }
091:
092: public final void writeBuf() throws IOException {
093: //#ifdef DEBUG
094: if (trace)
095: Debug.println("writeBuf(), buf = " + buf + ", bufsCnt = "
096: + bufsCnt);
097: //#endif
098:
099: if (out != null) {
100: //#ifdef DEBUG
101: if (trace)
102: Debug.println("-----------------------------write:\n "
103: + Util.strBytes(buf, 0, MAX));
104: //#endif
105: out.write(buf, 0, MAX);
106: count += MAX;
107: } else {
108: if (bufs == null) {
109: bufs = new Object[8];
110: } else if (bufsCnt + 1 >= bufs.length) {
111: bufs = resize(bufs, bufsCnt * 2);
112: }
113: bufs[bufsCnt++] = buf;
114: buf = (byte[]) bufs[bufsCnt];
115: if (buf == null) {
116: buf = new byte[MAX];
117: bufs[bufsCnt] = buf;
118: }
119: }
120: pos = 0;
121: }
122:
123: public final void write(int c) throws IOException {
124: //#ifdef DEBUG
125: if (trace)
126: Debug.println("[" + pos + "]: write(" + c + ")");
127: //#endif
128: if (pos >= MAX) {
129: writeBuf();
130: }
131: buf[pos++] = (byte) c;
132: }
133:
134: public final void write(byte[] b) throws IOException {
135: write(b, 0, b.length);
136: }
137:
138: public final void write(byte[] b, int off, int len)
139: throws IOException {
140: //#ifdef DEBUG
141: if (trace) {
142: Debug.println("[" + pos + "]: write("
143: + Util.strBytes(b, off, len) + ")");
144: }
145: //#endif
146: if (out != null && len > MAX) {
147: flush();
148: out.write(b, off, len);
149: count += len;
150: return;
151: }
152: int npos = pos + len;
153: while (npos >= MAX) {
154: final int slen = MAX - pos;
155: System.arraycopy(b, off, buf, pos, slen);
156: writeBuf();
157: len -= slen;
158: off += slen;
159: npos = pos + len;
160: }
161: if (len > 0) {
162: System.arraycopy(b, off, buf, pos, len);
163: pos = npos;
164: }
165: }
166:
167: public final void writeBoolean(boolean v) throws IOException {
168: write(v ? 1 : 0);
169: }
170:
171: public final void writeByte(int v) throws IOException {
172: //#ifdef DEBUG
173: if (trace)
174: Debug.println("writeByte(" + v + ")");
175: //#endif
176: if (pos >= MAX)
177: writeBuf();
178: buf[pos++] = (byte) v;
179: }
180:
181: //#ifdef SMALLDB
182: public void writeLong(long v) throws IOException {
183: while (true) {
184: if (pos >= MAX)
185: writeBuf();
186: if ((v & 0xffffffffffffff80L) != 0) {
187: buf[pos++] = (byte) (0x80 + (v & 0x7f));
188: v >>>= 7;
189: } else {
190: buf[pos++] = (byte) (v & 0x7f);
191: break;
192: }
193: }
194: }
195:
196: public void writeInt(int v) throws IOException {
197: //#ifdef DEBUG
198: if (trace)
199: Debug.println("[" + pos + "].writeInt(" + v + ")");
200: //#endif
201: while (true) {
202: if (pos >= MAX)
203: writeBuf();
204: if ((v & 0xffffff80) != 0) {
205: buf[pos++] = (byte) (0x80 + (v & 0x7f));
206: v >>>= 7;
207: } else {
208: buf[pos++] = (byte) (v & 0x7f);
209: break;
210: }
211: }
212: }
213:
214: public void writeShort(int v) throws IOException {
215: writeInt(v);
216: }
217:
218: public void writeChar(int v) throws IOException {
219: writeInt(v);
220: }
221:
222: //#else
223: //- public final void writeShort(int v) throws IOException {
224: //#ifdef DEBUG
225: //- if (trace) Debug.println("writeShort(" + v + ")");
226: //#endif
227: //- if (pos + 1 >= MAX) {
228: //- if (pos >= MAX) writeBuf();
229: //- buf[pos++] = (byte)((v >>> 8) & 0xFF);
230: //- if (pos >= MAX) writeBuf();
231: //- buf[pos++] = (byte)((v >>> 0) & 0xFF);
232: //- } else {
233: //- buf[pos++] = (byte)((v >>> 8) & 0xFF);
234: //- buf[pos++] = (byte)((v >>> 0) & 0xFF);
235: //- }
236: //- }
237: //-
238: //- public final void writeChar(int v) throws IOException {
239: //- writeShort(v);
240: //- }
241: //-
242: //- public final void writeInt(int v) throws IOException {
243: //#ifdef DEBUG
244: //- if (trace) Debug.println("writeInt(" + v + ") " +
245: //- Util.hexBytes(Util.bytes(v)));
246: //#endif
247: //- tbuf[0] = (byte)((v >>> 24) & 0xFF);
248: //- tbuf[1] = (byte)((v >>> 16) & 0xFF);
249: //- tbuf[2] = (byte)((v >>> 8 ) & 0xFF);
250: //- tbuf[3] = (byte)((v >>> 0 ) & 0xFF);
251: //- write(tbuf, 0, 4);
252: //- }
253: //-
254: //- public final void writeLong(long v) throws IOException {
255: //#ifdef DEBUG
256: //- if (trace) Debug.println("writeLong(" + v + ")");
257: //#endif
258: //-
259: //- tbuf[0] = (byte)((v >>> 56) & 0xFF);
260: //- tbuf[1] = (byte)((v >>> 48) & 0xFF);
261: //- tbuf[2] = (byte)((v >>> 40) & 0xFF);
262: //- tbuf[3] = (byte)((v >>> 32) & 0xFF);
263: //- tbuf[4] = (byte)((v >>> 24) & 0xFF);
264: //- tbuf[5] = (byte)((v >>> 16) & 0xFF);
265: //- tbuf[6] = (byte)((v >>> 8 ) & 0xFF);
266: //- tbuf[7] = (byte)((v >>> 0 ) & 0xFF);
267: //- write(tbuf, 0, 8);
268: //- }
269: //#endif
270:
271: public final void writeFloat(float v) throws IOException {
272: writeInt(Float.floatToIntBits(v));
273: }
274:
275: public final void writeDouble(double v) throws IOException {
276: writeLong(Double.doubleToLongBits(v));
277: }
278:
279: public final void writeBytes(String s) throws IOException {
280: //#ifdef DEBUG
281: if (trace)
282: Debug.println("writeBytes(" + s + ")");
283: //#endif
284: int len = s.length();
285: int off = 0;
286: while (len + pos >= MAX) {
287: int slen = MAX - pos;
288: s.getBytes(off, off + slen, buf, pos);
289: writeBuf();
290: off += slen;
291: len -= slen;
292: }
293: if (len > 0) {
294: s.getBytes(off, len, buf, pos);
295: pos += len;
296: }
297: }
298:
299: public final void writeChars(String s) throws IOException {
300: //#ifdef DEBUG
301: if (trace)
302: Debug.println("writeChars(" + s + ")");
303: //#endif
304: final int len = s.length();
305: for (int i = 0; i < len; i++) {
306: int v = s.charAt(i);
307: writeChar(v);
308: }
309: }
310:
311: public final void writeUTF(String str) throws IOException {
312: throw new IOException("UTF write not implemented");
313: }
314:
315: public final void flush() throws IOException {
316: if (out != null) {
317: //#ifdef DEBUG
318: if (trace)
319: Debug.println("flush, pos = " + pos);
320: //#endif
321: if (pos > 0) {
322: //#ifdef DEBUG
323: if (trace)
324: Debug.println("flush(" + pos + "): "
325: + Util.strBytes(buf, 0, pos));
326: //#endif
327: out.write(buf, 0, pos);
328: count += pos;
329: pos = 0;
330: }
331: out.flush();
332: }
333: }
334:
335: public final void close() throws IOException {
336: flush();
337: if (out != null)
338: out.close();
339: }
340:
341: public int size() {
342: int s = bufsCnt * MAX + pos;
343: if (siz >= 0) {
344: if (s > siz)
345: siz = -1;
346: else
347: s = siz;
348: }
349: return s;
350: }
351:
352: public final void setCount(int count) {
353: this .count = count;
354: }
355:
356: public final int getCount() {
357: if (out == null) {
358: return count;
359: } else {
360: return count + size();
361: }
362: }
363:
364: public final void setPosition(int p) {
365: //#ifdef DEBUG
366: if (trace)
367: Debug.println("setPosition(" + p + ")");
368: //#endif
369: int s = size();
370: if (p < s && s > siz)
371: siz = s;
372: bufsCnt = p / MAX;
373: pos = p % MAX;
374: if (bufs != null) {
375: buf = (byte[]) bufs[bufsCnt];
376: }
377: }
378:
379: public final int getPosition() {
380: return size();
381: }
382:
383: public byte[] toByteArray() {
384: int len = size();
385: setPosition(len);
386: byte[] ret = new byte[len];
387: int p = 0;
388: for (int i = 0; i < bufsCnt; i++) {
389: byte[] b = (byte[]) bufs[i];
390: System.arraycopy(b, 0, ret, p, Math.min(MAX, len));
391: p += MAX;
392: len -= MAX;
393: }
394: if (buf != null) {
395: System.arraycopy(buf, 0, ret, p, pos);
396: }
397: return ret;
398: }
399:
400: //#ifdef DEBUG
401: public static void test1() throws IOException {
402: FileOutputStream fos = new FileOutputStream("dos.out");
403: ObjectOutputStream oos = new ObjectOutputStream(fos);
404: byte[] bufx = new byte[2000];
405: for (int i = 0; i < bufx.length; i++) {
406: bufx[i] = (byte) (i & 0xff);
407: }
408: int cnt = 0;
409: for (int i = 1; i < bufx.length; i++) {
410: oos.write(bufx, 0, i);
411: cnt += i;
412: if (cnt != oos.getCount())
413: throw new RuntimeException("bad count, i = " + i);
414: oos.flush();
415:
416: }
417: oos.flush();
418: fos.close();
419:
420: FileInputStream fis = new FileInputStream("dos.out");
421: BufferedInputStream bis = new BufferedInputStream(fis);
422: for (int i = 1; i < bufx.length; i++) {
423: bis.read(bufx, 0, i);
424: for (int j = 0; j < i; j++) {
425: if ((bufx[j] & 0xff) != (j & 0xff)) {
426: throw new RuntimeException("bad, i = " + i
427: + ", j = " + j);
428: }
429: }
430: }
431: fis.close();
432: }
433:
434: public static void main(String args[]) {
435: try {
436: // ObjectOutputStream out = new ObjectOutputStream();
437: // out.setPosition(6);
438: // out.writeInt(0xaabbccdd);
439: // out.setPosition(0);
440: // out.writeInt(0xffeeddcc);
441: // for (int i = 0; i < 2000; i++) {
442: // out.writeInt(i);
443: // }
444: // out.setPosition(0);
445: // out.writeInt(0x11223344);
446: // out.writeInt(0x55667788);
447: // System.out.println(Util.strBytes(out.toByteArray()));
448: test1();
449: } catch (Throwable t) {
450: Debug.print(t);
451: }
452: }
453:
454: boolean trace = false;
455:
456: public void setTrace(boolean t) {
457: this .trace = t;
458: }
459: //#endif
460: }
|