]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/BinaryMemory.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / binary / BinaryMemory.java
1 /*******************************************************************************
2  * Copyright (c) 2010, 2016 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.util.binary;
13
14 import java.io.DataInputStream;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.nio.ByteBuffer;
18
19 /**
20  * Rancom access memory blob
21  *
22  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
23  */
24 public class BinaryMemory implements RandomAccessBinary {
25
26         ByteBuffer buf;
27         long pointer;
28         /** the number of bytes added spare to the buffer when it is incremented */
29         int increment;
30         
31         /**
32          * New memory blob
33          */
34         public BinaryMemory() {
35                 buf = ByteBuffer.allocate(16);
36                 increment = 16;
37         }
38
39         /**
40          * New memory blob
41          */
42         public BinaryMemory(byte[] data) {
43                 this.buf = ByteBuffer.wrap(data);
44         }
45         
46         /**
47          * New memory blob
48          */
49         public BinaryMemory(byte[] data, int offset, int length) {
50                 this.buf = ByteBuffer.wrap(data, offset, length);
51         }
52         
53         /**
54          * New memory blob
55          */
56         public BinaryMemory(int initialSize) {
57                 buf = ByteBuffer.allocate(initialSize);
58                 increment = Math.max(16, initialSize);
59         }
60         
61         /**
62          * New memory blob
63          */
64         public BinaryMemory(int initialSize, int increment) {
65                 buf = ByteBuffer.allocate(initialSize);
66                 this.increment = increment;
67         }
68         
69         /**
70          * Assume an existing byte buffer
71          * 
72          * @param buf buffer
73          */
74         public BinaryMemory(ByteBuffer buf) {
75                 this.buf = buf;
76         }
77         
78         /**
79          * Get the backend byte buffer. The result may change if BinaryMemory is 
80          * written.
81          * 
82          * @return byte buffer
83          */
84         public ByteBuffer toByteBuffer() {
85                 return buf;
86         }
87         
88         @Override
89         public void close() throws IOException {
90         }
91
92         @Override
93         public boolean isOpen() {
94                 return true;
95         }
96         
97         @Override
98         public void flush() throws IOException {
99         }
100         
101         @Override
102         public void reset() throws IOException {
103         }
104
105         @Override
106         public byte readByte() {
107                 assertHasReadableBytes(1);              
108                 buf.position( (int) pointer );
109                 byte result = buf.get();
110                 pointer += 1;
111                 return result;
112         }
113         
114         int _read() {
115                 if (pointer >= buf.limit()) return -1;
116                 buf.position( (int) pointer );
117                 byte result = buf.get();
118                 pointer += 1;
119                 return result & 0xff;
120         }       
121         
122     public final String readLine() throws IOException {
123         StringBuffer input = new StringBuffer();
124         int c = -1;
125         boolean eol = false;
126
127         while (!eol) {
128             switch (c = _read()) {
129             case -1:
130             case '\n':
131                 eol = true;
132                 break;
133             case '\r':
134                 eol = true;
135                 long cur = position();
136                 if ((_read()) != '\n') {
137                     position(cur);
138                 }
139                 break;
140             default:
141                 input.append((char)c);
142                 break;
143             }
144         }
145
146         if ((c == -1) && (input.length() == 0)) {
147             return null;
148         }
149         return input.toString();
150     }   
151     
152     public final String readUTF() throws IOException {
153         return DataInputStream.readUTF(this);
154     }     
155         
156         @Override
157         public int readUnsignedByte() throws IOException {
158                 return readByte() & 0x000000ff;
159         }               
160
161         @Override
162         public boolean readBoolean() throws IOException {
163                 assertHasReadableBytes(1);              
164                 buf.position( (int) pointer );
165                 byte result = buf.get();
166                 pointer += 1;
167                 return result!=0;
168         }
169         
170         @Override
171         public void readFully(byte[] dst, int offset, int length) {
172                 assertHasReadableBytes(length);
173                 buf.position( (int) pointer );
174                 buf.get(dst, offset, length);
175                 pointer += length;
176         }
177
178         @Override
179         public void readFully(byte[] dst) {
180                 assertHasReadableBytes(dst.length);             
181                 buf.position( (int) pointer );
182                 buf.get(dst);
183                 pointer += dst.length;
184         }
185
186         @Override
187         public void readFully(ByteBuffer buf) {         
188                 int bytes = buf.remaining();
189                 assertHasReadableBytes( bytes );
190                 buf.position( (int) pointer );
191                 if (buf.hasArray()) {
192                         this.buf.get(buf.array(), buf.arrayOffset() + buf.position(), bytes);
193                         buf.position(buf.capacity());
194                 } else {
195                         buf.put(buf);
196                 }
197                 pointer += bytes;
198         }
199
200         @Override
201         public void readFully(ByteBuffer buf, int length) {
202                 assertHasReadableBytes(length);
203                 buf.position( (int) pointer );
204                 if (buf.hasArray()) {
205                         this.buf.get(buf.array(), buf.arrayOffset() + buf.position(), length);
206                         buf.position(buf.position() + length);
207                 } else {
208 //                      int len = Math.min( Math.min( buf.remaining(), this.buf.remaining() ), length);
209                         int len = length;
210                         int origLimit = this.buf.limit();
211                         try {
212                                 this.buf.limit(this.buf.position()+len);
213                                 buf.put(this.buf);
214                         } finally {
215                                 this.buf.limit(origLimit);
216                         }
217                 }
218                 pointer += length;
219         }
220
221         @Override
222         public double readDouble() {
223                 assertHasReadableBytes(8);
224                 buf.position( (int) pointer );
225                 double value = buf.getDouble();
226                 pointer += 8;
227                 return value;
228         }
229
230         @Override
231         public float readFloat() {
232                 assertHasReadableBytes(4);
233                 buf.position( (int) pointer );
234                 float result = buf.getFloat();
235                 pointer += 4;
236                 return result;
237         }
238
239         @Override
240         public int readInt() {
241                 assertHasReadableBytes(4);
242                 buf.position( (int) pointer );
243                 int value = buf.getInt();
244                 pointer += 4;
245                 return value;
246         }
247
248         @Override
249         public long readLong() {
250                 assertHasReadableBytes(8);
251                 buf.position( (int) pointer );
252                 long value = buf.getLong();
253                 pointer += 8;
254                 return value;
255         }
256
257         @Override
258         public short readShort() {
259                 assertHasReadableBytes(2);
260                 buf.position( (int) pointer );
261                 short result = buf.getShort();
262                 pointer += 2;
263                 return result;
264         }
265         
266         @Override
267         public char readChar() {
268                 assertHasReadableBytes(2);
269                 buf.position( (int) pointer );
270                 char result = buf.getChar();
271                 pointer += 2;
272                 return result;
273         }       
274         
275         @Override
276         public int readUnsignedShort() {
277                 assertHasReadableBytes(2);
278                 buf.position( (int) pointer );
279                 int result = buf.getShort() & 0xffff;
280                 pointer += 2;
281                 return result;
282         }       
283
284         @Override
285         public long length() {
286                 return buf.limit();
287         }
288         
289         @Override
290         public long position() {
291                 return pointer;
292         }
293         
294         @Override
295         public void position(long newPosition) throws IOException {
296                 this.pointer = newPosition;
297         }
298         
299         @Override
300         public void write(int b) throws IOException {
301                 assertHasWritableBytes(1);
302                 buf.position( (int) pointer );
303                 buf.put((byte) b);
304                 pointer += 1;
305         }
306         
307         @Override
308         public void writeByte(int b) throws IOException {
309                 assertHasWritableBytes(1);
310                 buf.position( (int) pointer );
311                 buf.put((byte) b);
312                 pointer += 1;
313         }       
314         
315         @Override
316         public void writeBoolean(boolean v) throws IOException {
317                 assertHasWritableBytes(1);
318                 buf.position( (int) pointer );
319                 buf.put( (byte) (v ? 1 : 0) );
320                 pointer += 1;
321         }
322
323         @Override
324         public void writeFully(ByteBuffer src) throws IOException {
325                 long bytes = src.remaining();
326                 assertHasWritableBytes( bytes );
327                 buf.position( (int) pointer );
328                 buf.put(src);
329                 pointer += bytes;
330         }
331
332         @Override
333         public void writeFully(ByteBuffer src, int length) throws IOException {
334                 assertHasWritableBytes(length);
335                 buf.position( (int) pointer );
336                 if (src.hasArray()) {
337                         byte[] array = src.array();
338                         buf.put(array, src.arrayOffset() + src.position(), length);
339                 } else {
340                         for (int i=0; i<length; i++)
341                                 buf.put(src.get());
342                 }
343                 pointer += length;
344         }
345
346         
347         public void put(InputStream is) throws IOException {
348                 long oldLen = length();
349                 while (is.available()>0) {
350                         int n = is.available();
351                         assertHasWritableBytes(n);
352                         byte buf[] = this.buf.array();
353                         n = is.read(buf, (int) pointer, n);                     
354                         pointer += n;
355                 }
356                 long newLen = length();
357                 if (newLen>oldLen & pointer<newLen) setLength(pointer);
358         }
359
360         @Override
361         public void write(byte[] src, int offset, int length) throws IOException {
362                 assertHasWritableBytes(length);
363                 buf.position( (int) pointer );
364                 buf.put(src, offset, length);
365                 pointer += length;
366         }
367
368         @Override
369         public void write(byte[] src) throws IOException {
370                 assertHasWritableBytes(src.length);
371                 buf.position( (int) pointer );
372                 buf.put(src);
373                 pointer += src.length;
374         }
375
376         @Override
377         public void writeDouble(double value) throws IOException {
378                 assertHasWritableBytes(8);
379                 buf.position( (int) pointer );
380                 buf.putDouble(value);
381                 pointer += 8;
382         }
383
384         @Override
385         public void writeFloat(float value) throws IOException {
386                 assertHasWritableBytes(4);
387                 buf.position( (int) pointer );
388                 buf.putFloat(value);
389                 pointer += 4;
390         }
391
392         @Override
393         public void writeInt(int value) throws IOException {
394                 assertHasWritableBytes(4);
395                 buf.position( (int) pointer );
396                 buf.putInt(value);
397                 pointer += 4;
398         }
399
400         @Override
401         public void writeLong(long value) throws IOException {
402                 assertHasWritableBytes(8);
403                 buf.position( (int) pointer );
404                 buf.putLong(value);
405                 pointer += 8;
406         }
407
408         @Override
409         public void writeShort(int value) throws IOException {
410                 assertHasWritableBytes(2);
411                 buf.position( (int) pointer );
412                 buf.putShort( (short) value);
413                 pointer += 2;
414         }
415         
416         @Override
417         public void writeChar(int value) throws IOException {
418                 assertHasWritableBytes(2);
419                 buf.position( (int) pointer );
420                 buf.putShort( (short) value);
421                 pointer += 2;
422         }       
423         
424         @Override
425         public void writeBytes(String s) throws IOException {
426                 int len = s.length();
427                 assertHasWritableBytes(len);
428                 buf.position( (int) pointer );
429                 for (int i = 0 ; i < len ; i++) {
430                     buf.put((byte)s.charAt(i));
431                 }
432                 pointer += len;
433         }       
434         
435         @Override
436         public void writeChars(String s) throws IOException {
437         int len = s.length();
438                 assertHasWritableBytes(len*2);
439         for (int i = 0 ; i < len ; i++) {
440             int v = s.charAt(i);
441             buf.put( (byte) ((v >>> 8) & 0xFF) ); 
442             buf.put( (byte) ((v >>> 0) & 0xFF) ); 
443         }
444                 pointer += len*2;
445         }
446         
447         @Override
448         public void writeUTF(String s) throws IOException {
449                 int len = UTF8.getModifiedUTF8EncodingByteLength(s);
450                 writeShort(len);
451                 UTF8.writeModifiedUTF(this, s);
452         }       
453
454         void assertHasReadableBytes(long count) {
455                 if (pointer + count > buf.limit())
456                         throw new IndexOutOfBoundsException();
457         }
458         
459         void assertHasWritableBytes(long count) 
460         throws IOException {
461                 if (pointer + count > buf.limit()) 
462                         setLength(pointer+count);
463         }
464
465
466         @Override
467         public void insertBytes(long bytes, ByteSide side) throws IOException {
468                 if (pointer<0) throw new IndexOutOfBoundsException();
469                 // 1. Increase length
470                 long oldLength = length();
471                 long newLength = Math.max(oldLength + bytes, pointer + bytes);
472                 // No need to allocate
473                 if (newLength<buf.capacity()) {
474                         // Update limit
475                         buf.limit((int)newLength);
476                         
477                         // No need to move bytes
478                         if (pointer>oldLength) return;
479                                 
480                         // Move bytes
481                         if (buf.hasArray()) {
482                                 System.arraycopy(buf.array(), (int) pointer, buf.array(), (int) (pointer+bytes), (int) (oldLength - pointer));
483                         } 
484                         else 
485                         {
486                                 byte[] b = new byte[(int) (oldLength - pointer)];
487                                 buf.position((int)pointer);
488                                 buf.get(b);
489                                 buf.position( (int) (pointer + bytes) );
490                                 buf.put(b);
491                         }
492                 } else
493                 // Need to reallocate
494                 {
495                         long inc = Math.max(increment, newLength / 4);          
496                         ByteBuffer oldBuf = buf;
497                         ByteBuffer newBuf = ByteBuffer.allocate((int) (newLength + inc));
498                         newBuf.limit((int)newLength);
499                         
500                         newBuf.position(0);
501                         oldBuf.position(0);
502
503                         // Copy left side
504                         oldBuf.get(newBuf.array(), 0, (int)pointer);
505                         
506                         // Copy right side
507                         if (pointer<oldLength) 
508                         oldBuf.get(newBuf.array(), (int)(pointer+bytes), (int)(oldLength-pointer));
509                         
510                         buf = newBuf;
511                 }
512                 
513         }
514         
515         @Override
516         public void removeBytes(long bytes, ByteSide side) throws IOException {
517                 long oldLength = length();
518                 long newLength = oldLength - bytes;
519                 if (pointer<0 || pointer>=length()) throw new IndexOutOfBoundsException();
520                 
521                 // move some bytes
522                 if (buf.hasArray()) {
523                         System.arraycopy(buf.array(), (int)(pointer+bytes), buf.array(), (int) pointer, (int) (newLength-pointer) ); 
524                 } else {
525                         byte[] b = new byte[(int) (oldLength-pointer)];
526                         buf.position((int) (pointer+bytes));
527                         buf.get(b);
528                         buf.position((int) (pointer));
529                         buf.put(b);
530                 }
531                 
532                 buf.limit( (int) newLength );
533         }
534
535         @Override
536         public void setLength(long newLength) throws IOException {
537                 int oldLength = (int) length();
538                 if (oldLength==newLength) return;
539                 if (newLength<=oldLength) {
540                         buf.limit((int)newLength);
541                 } else
542                 if (newLength<=buf.capacity()) {
543                         buf.limit((int)newLength);
544                 } else {
545                         ByteBuffer oldBuf = buf;
546                         long inc = Math.max(increment, newLength / 4);
547                         ByteBuffer newBuf = ByteBuffer.allocate((int) (newLength + inc));
548                         oldBuf.position(0);
549                         oldBuf.get(newBuf.array(), 0, oldLength);
550                         newBuf.limit((int)newLength);
551                         buf = newBuf;
552                 }               
553         }
554
555         @Override
556         public long skipBytes(long bytes) throws IOException {
557                 pointer += bytes;
558                 return bytes;
559         }
560
561         @Override
562         public int skipBytes(int bytes) throws IOException {
563                 pointer += bytes;
564                 return bytes;
565         }
566         
567         @Override
568         public String toString() {
569                 return "Mem("+length()+")";
570         }
571         
572 }
573