Quadcap Embeddable Database

com/quadcap/sql/io/DataOutputStream.java

Go to the documentation of this file.
00001 package com.quadcap.sql.io; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.*; 00042 00043 import java.io.DataOutput; 00044 import java.io.IOException; 00045 import java.io.OutputStream; 00046 00047 import com.quadcap.util.Debug; 00048 import com.quadcap.util.Util; 00049 00050 /** 00051 * This class implements data output somewhat more efficiently than 00052 * the JDK version. It also implements buffering and counting, 00053 * to help us avoid extra layers of stream classes. 00054 * 00055 * 4/2/03: XX What JDK version? this hasn't been examined recently... 00056 * 00057 * @author Stan Bailes 00058 */ 00059 public class DataOutputStream extends OutputStream implements DataOutput { 00060 static final int MAX = 4096; 00061 OutputStream out; 00062 byte[] buf = new byte[MAX]; 00063 byte[] tbuf = new byte[16]; 00064 Object[] bufs = null; 00065 int bufsCnt = 0; 00066 int pos = 0; 00067 int siz = -1; 00068 int count = 0; 00069 00070 public DataOutputStream(OutputStream out) { 00071 this.out = out; 00072 } 00073 00074 public void reset(OutputStream out) { 00075 this.out = out; 00076 bufsCnt = 0; 00077 pos = 0; 00078 count = 0; 00079 siz = -1; 00080 if (bufs != null && bufs.length > 0) { 00081 buf = (byte[])bufs[0]; 00082 } 00083 } 00084 00085 final Object[] resize(Object[] array, int size) { 00086 Object[] narray = new Object[size]; 00087 System.arraycopy(array, 0, narray, 0, array.length); 00088 return narray; 00089 } 00090 00091 public final void writeBuf() throws IOException { 00092 //#ifdef DEBUG 00093 if (trace) Debug.println("writeBuf(), buf = " + buf + ", bufsCnt = " + 00094 bufsCnt); 00095 //#endif 00096 00097 if (out != null) { 00098 //#ifdef DEBUG 00099 if (trace) Debug.println("-----------------------------write:\n " + 00100 Util.strBytes(buf, 0, MAX)); 00101 //#endif 00102 out.write(buf, 0, MAX); 00103 count += MAX; 00104 } else { 00105 if (bufs == null) { 00106 bufs = new Object[8]; 00107 } else if (bufsCnt+1 >= bufs.length) { 00108 bufs = resize(bufs, bufsCnt * 2); 00109 } 00110 bufs[bufsCnt++] = buf; 00111 buf = (byte[])bufs[bufsCnt]; 00112 if (buf == null) { 00113 buf = new byte[MAX]; 00114 bufs[bufsCnt] = buf; 00115 } 00116 } 00117 pos = 0; 00118 } 00119 00120 public final void write(int c) throws IOException { 00121 //#ifdef DEBUG 00122 if (trace) Debug.println("[" + pos + "]: write(" + c + ")"); 00123 //#endif 00124 if (pos >= MAX) { 00125 writeBuf(); 00126 } 00127 buf[pos++] = (byte)c; 00128 } 00129 00130 public final void write(byte[] b) throws IOException { 00131 write(b, 0, b.length); 00132 } 00133 00134 public final void write(byte[] b, int off, int len) throws IOException { 00135 //#ifdef DEBUG 00136 if (trace) { 00137 Debug.println("[" + pos + "]: write(" + 00138 Util.strBytes(b, off, len) + ")"); 00139 } 00140 //#endif 00141 if (out != null && len > MAX) { 00142 flush(); 00143 out.write(b, off, len); 00144 count += len; 00145 return; 00146 } 00147 int npos = pos + len; 00148 while (npos >= MAX) { 00149 final int slen = MAX - pos; 00150 System.arraycopy(b, off, buf, pos, slen); 00151 writeBuf(); 00152 len -= slen; 00153 off += slen; 00154 npos = pos + len; 00155 } 00156 if (len > 0) { 00157 System.arraycopy(b, off, buf, pos, len); 00158 pos = npos; 00159 } 00160 } 00161 00162 public final void writeBoolean(boolean v) throws IOException { 00163 write(v ? 1 : 0); 00164 } 00165 00166 public final void writeByte(int v) throws IOException { 00167 //#ifdef DEBUG 00168 if (trace) Debug.println("writeByte(" + v + ")"); 00169 //#endif 00170 if (pos >= MAX) writeBuf(); 00171 buf[pos++] = (byte)v; 00172 } 00173 00174 //#ifdef SMALLDB 00175 public void writeLong(long v) throws IOException { 00176 while (true) { 00177 if (pos >= MAX) writeBuf(); 00178 if ((v & 0xffffffffffffff80L) != 0) { 00179 buf[pos++] = (byte)(0x80 + (v & 0x7f)); 00180 v >>>= 7; 00181 } else { 00182 buf[pos++] = (byte)(v & 0x7f); 00183 break; 00184 } 00185 } 00186 } 00187 public void writeInt(int v) throws IOException { 00188 //#ifdef DEBUG 00189 if (trace) Debug.println("[" + pos + "].writeInt(" + v + ")"); 00190 //#endif 00191 while (true) { 00192 if (pos >= MAX) writeBuf(); 00193 if ((v & 0xffffff80) != 0) { 00194 buf[pos++] = (byte)(0x80 + (v & 0x7f)); 00195 v >>>= 7; 00196 } else { 00197 buf[pos++] = (byte)(v & 0x7f); 00198 break; 00199 } 00200 } 00201 } 00202 00203 public void writeShort(int v) throws IOException { 00204 writeInt(v); 00205 } 00206 public void writeChar(int v) throws IOException { 00207 writeInt(v); 00208 } 00209 00210 //#else 00211 //- public final void writeShort(int v) throws IOException { 00212 //#ifdef DEBUG 00213 //- if (trace) Debug.println("writeShort(" + v + ")"); 00214 //#endif 00215 //- if (pos + 1 >= MAX) { 00216 //- if (pos >= MAX) writeBuf(); 00217 //- buf[pos++] = (byte)((v >>> 8) & 0xFF); 00218 //- if (pos >= MAX) writeBuf(); 00219 //- buf[pos++] = (byte)((v >>> 0) & 0xFF); 00220 //- } else { 00221 //- buf[pos++] = (byte)((v >>> 8) & 0xFF); 00222 //- buf[pos++] = (byte)((v >>> 0) & 0xFF); 00223 //- } 00224 //- } 00225 //- 00226 //- public final void writeChar(int v) throws IOException { 00227 //- writeShort(v); 00228 //- } 00229 //- 00230 //- public final void writeInt(int v) throws IOException { 00231 //#ifdef DEBUG 00232 //- if (trace) Debug.println("writeInt(" + v + ") " + 00233 //- Util.hexBytes(Util.bytes(v))); 00234 //#endif 00235 //- tbuf[0] = (byte)((v >>> 24) & 0xFF); 00236 //- tbuf[1] = (byte)((v >>> 16) & 0xFF); 00237 //- tbuf[2] = (byte)((v >>> 8 ) & 0xFF); 00238 //- tbuf[3] = (byte)((v >>> 0 ) & 0xFF); 00239 //- write(tbuf, 0, 4); 00240 //- } 00241 //- 00242 //- public final void writeLong(long v) throws IOException { 00243 //#ifdef DEBUG 00244 //- if (trace) Debug.println("writeLong(" + v + ")"); 00245 //#endif 00246 //- 00247 //- tbuf[0] = (byte)((v >>> 56) & 0xFF); 00248 //- tbuf[1] = (byte)((v >>> 48) & 0xFF); 00249 //- tbuf[2] = (byte)((v >>> 40) & 0xFF); 00250 //- tbuf[3] = (byte)((v >>> 32) & 0xFF); 00251 //- tbuf[4] = (byte)((v >>> 24) & 0xFF); 00252 //- tbuf[5] = (byte)((v >>> 16) & 0xFF); 00253 //- tbuf[6] = (byte)((v >>> 8 ) & 0xFF); 00254 //- tbuf[7] = (byte)((v >>> 0 ) & 0xFF); 00255 //- write(tbuf, 0, 8); 00256 //- } 00257 //#endif 00258 00259 public final void writeFloat(float v) throws IOException { 00260 writeInt(Float.floatToIntBits(v)); 00261 } 00262 00263 public final void writeDouble(double v) throws IOException { 00264 writeLong(Double.doubleToLongBits(v)); 00265 } 00266 00267 public final void writeBytes(String s) throws IOException { 00268 //#ifdef DEBUG 00269 if (trace) Debug.println("writeBytes(" + s + ")"); 00270 //#endif 00271 int len = s.length(); 00272 int off = 0; 00273 while (len + pos >= MAX) { 00274 int slen = MAX - pos; 00275 s.getBytes(off, off + slen, buf, pos); 00276 writeBuf(); 00277 off += slen; 00278 len -= slen; 00279 } 00280 if (len > 0) { 00281 s.getBytes(off, len, buf, pos); 00282 pos += len; 00283 } 00284 } 00285 00286 public final void writeChars(String s) throws IOException { 00287 //#ifdef DEBUG 00288 if (trace) Debug.println("writeChars(" + s + ")"); 00289 //#endif 00290 final int len = s.length(); 00291 for (int i = 0 ; i < len ; i++) { 00292 int v = s.charAt(i); 00293 writeChar(v); 00294 } 00295 } 00296 00297 public final void writeUTF(String str) throws IOException { 00298 throw new IOException("UTF write not implemented"); 00299 } 00300 00301 public final void flush() throws IOException { 00302 if (out != null) { 00303 //#ifdef DEBUG 00304 if (trace) Debug.println("flush, pos = " + pos); 00305 //#endif 00306 if (pos > 0) { 00307 //#ifdef DEBUG 00308 if (trace) Debug.println("flush(" + pos + "): " + 00309 Util.strBytes(buf, 0, pos)); 00310 //#endif 00311 out.write(buf, 0, pos); 00312 count += pos; 00313 pos = 0; 00314 } 00315 out.flush(); 00316 } 00317 } 00318 00319 public final void close() throws IOException { 00320 flush(); 00321 if (out != null) out.close(); 00322 } 00323 00324 public int size() { 00325 int s = bufsCnt * MAX + pos; 00326 if (siz >= 0) { 00327 if (s > siz) siz = -1; 00328 else s = siz; 00329 } 00330 return s; 00331 } 00332 00333 public final void setCount(int count) { 00334 this.count = count; 00335 } 00336 00337 public final int getCount() { 00338 if (out == null) { 00339 return count; 00340 } else { 00341 return count + size(); 00342 } 00343 } 00344 00345 public final void setPosition(int p) { 00346 //#ifdef DEBUG 00347 if (trace) Debug.println("setPosition(" + p + ")"); 00348 //#endif 00349 int s = size(); 00350 if (p < s && s > siz) siz = s; 00351 bufsCnt = p / MAX; 00352 pos = p % MAX; 00353 if (bufs != null) { 00354 buf = (byte[])bufs[bufsCnt]; 00355 } 00356 } 00357 00358 public final int getPosition() { 00359 return size(); 00360 } 00361 00362 public byte[] toByteArray() { 00363 int len = size(); 00364 setPosition(len); 00365 byte[] ret = new byte[len]; 00366 int p = 0; 00367 for (int i = 0; i < bufsCnt; i++) { 00368 byte[] b = (byte[])bufs[i]; 00369 System.arraycopy(b, 0, ret, p, Math.min(MAX, len)); 00370 p += MAX; 00371 len -= MAX; 00372 } 00373 if (buf != null) { 00374 System.arraycopy(buf, 0, ret, p, pos); 00375 } 00376 return ret; 00377 } 00378 00379 //#ifdef DEBUG 00380 public static void test1() throws IOException { 00381 FileOutputStream fos = new FileOutputStream("dos.out"); 00382 ObjectOutputStream oos = new ObjectOutputStream(fos); 00383 byte[] bufx = new byte[2000]; 00384 for (int i = 0; i < bufx.length; i++) { 00385 bufx[i] = (byte)(i & 0xff); 00386 } 00387 int cnt = 0; 00388 for (int i = 1; i < bufx.length; i++) { 00389 oos.write(bufx, 0, i); 00390 cnt += i; 00391 if (cnt != oos.getCount()) throw new RuntimeException("bad count, i = " + i); 00392 oos.flush(); 00393 00394 } 00395 oos.flush(); 00396 fos.close(); 00397 00398 FileInputStream fis = new FileInputStream("dos.out"); 00399 BufferedInputStream bis = new BufferedInputStream(fis); 00400 for (int i = 1; i < bufx.length; i++) { 00401 bis.read(bufx, 0, i); 00402 for (int j = 0; j < i; j++) { 00403 if ((bufx[j] & 0xff)!= (j&0xff)) { 00404 throw new RuntimeException("bad, i = " + i + ", j = " + j); 00405 } 00406 } 00407 } 00408 fis.close(); 00409 } 00410 00411 00412 00413 public static void main(String args[]) { 00414 try { 00415 // ObjectOutputStream out = new ObjectOutputStream(); 00416 // out.setPosition(6); 00417 // out.writeInt(0xaabbccdd); 00418 // out.setPosition(0); 00419 // out.writeInt(0xffeeddcc); 00420 // for (int i = 0; i < 2000; i++) { 00421 // out.writeInt(i); 00422 // } 00423 // out.setPosition(0); 00424 // out.writeInt(0x11223344); 00425 // out.writeInt(0x55667788); 00426 // System.out.println(Util.strBytes(out.toByteArray())); 00427 test1(); 00428 } catch (Throwable t) { 00429 Debug.print(t); 00430 } 00431 } 00432 00433 boolean trace = false; 00434 public void setTrace(boolean t) { 00435 this.trace = t; 00436 } 00437 //#endif 00438 }