]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Add more databoard reading utilities to ByteFileReader
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 8 Nov 2021 12:03:22 +0000 (14:03 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 8 Nov 2021 12:03:22 +0000 (14:03 +0200)
Also add writeDynamicUInt32(byte[] out, int offset, int length) to
Endian class for more direct writing of data to optimize custom
serializer implementations.

Change MappingBase.browseConfiguration to use THashMap.forEachValue
instead of Collection.iterator() for a tighter implementation.

gitlab #772

bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/Endian.java
bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java
bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/MappingBase.java

index 57c98bc4d36f8f1a69ace056a819d2cb390de58b..8d87aca4b2615f4c844b729ffa5c7341d988e5aa 100644 (file)
@@ -71,6 +71,50 @@ public class Endian {
                }       
        }
 
+       /**
+        * Write UInt32 with dynamic encoding (1-5 bytes).
+        * 
+        * @param out
+        * @param length
+        * @throws IOException
+        */
+       public static void writeDynamicUInt32(byte[] out, int offset, int length) throws IOException {
+               if(length < 0x80) {
+                       out[offset] = (byte)length;
+               }
+               else {
+                       length -= 0x80;
+                       if(length < 0x4000) {
+                               out[offset]   = (byte) ((length&0x3f) | 0x80);
+                               out[offset+1] = (byte) ((length>>>6) );
+                       }
+                       else {
+                               length -= 0x4000;
+                               if(length < 0x200000) {
+                                       out[offset]   = (byte) ((length&0x1f) | 0xc0);
+                                       out[offset+1] = (byte) ((length>>>5)&0xff);
+                                       out[offset+2] = (byte) ((length>>>13)&0xff);
+                               }
+                               else {
+                                       length -= 0x200000;
+                                       if(length < 0x10000000) {
+                                               out[offset]   = (byte) ((length&0x0f) | 0xe0);
+                                               out[offset+1] = (byte) ((length>>>4)&0xff);
+                                               out[offset+2] = (byte) ((length>>>12)&0xff);
+                                               out[offset+3] = (byte) ((length>>>20)&0xff);
+                                       }
+                                       else {
+                                               length -= 0x10000000;
+                                               out[offset]   = (byte) ((length&0x07) | 0xf0);
+                                               out[offset+1] = (byte) ((length>>>3)&0xff);
+                                               out[offset+2] = (byte) ((length>>>11)&0xff);
+                                               out[offset+3] = (byte) ((length>>>19)&0xff);
+                                               out[offset+4] = (byte) ((length>>>27)&0xff);
+                                       }
+                               }
+                       }
+               }
+       }
 
        public static int readDynamicUInt32(DataInput in) throws IOException {
                int length = in.readByte()&0xff; 
index 3a76a911a0d3c269c4c72cf5053b742aa8579432..e550740438b938fd28605bab4b36912b3d603b0c 100644 (file)
@@ -145,6 +145,43 @@ public class ByteFileReader implements Closeable {
                
        }
 
+       /**
+        * @param result the output buffer to read into
+        * @param off the offset in <code>result</code> to start reading to
+        * @param len the maximum amount of data to read
+        * @return the actual amount of bytes read or -1 if EOF was reached
+        * @throws IOException
+        */
+       protected final int safeBytes(byte[] result, int off, int len) throws IOException {
+               int has = size-byteIndex;
+               if(len>= has) {
+                       ReadableByteChannel c = channel;
+                       ByteBuffer bb = byteBuffer;
+                       System.arraycopy(bytes, byteIndex, result, off, has);
+                       ByteBuffer bb2 = ByteBuffer.wrap(result);
+                       bb2.position(off+has);
+                       // For some peculiar reason this seems to avoid OOM with large blocks as compared to c.read(bb2
+                       while(has < len) {
+                               int todo = Math.min(len-has, 65536);
+                               bb2.limit(off+has+todo);
+                               int got = c.read(bb2);
+                               if(got == -1) throw new IOException("Unexpected end-of-file");
+                               has += got; 
+                               // For some unknown reason this is needed!
+                               // Spec indicates that read would increment position but it does not.
+                               bb2.position(off+has);
+                       }
+                       size = c.read(bb);
+                       bb.position(0);
+                       byteIndex = 0;
+                       return has;
+               } else {
+                       System.arraycopy(bytes, byteIndex, result, 0, len);
+                       byteIndex += len;
+                       return len;
+               }
+       }
+
        final protected int getByte() throws IOException {
            int has = size-byteIndex;
            int result;
@@ -248,6 +285,30 @@ public class ByteFileReader implements Closeable {
 
        }
 
+       public long safeLong() throws IOException {
+               int msi = safeInt();
+               int lsi = safeInt();
+               return ((long) msi << 32) | ((long) lsi & 0xffffffffL);
+       }
+
+       public boolean getBoolean() throws IOException {
+               return getByte() != 0; 
+       }
+
+       public String readString() throws IOException {
+               int nameLen = getDynamicUInt32();
+               if (nameLen == 0)
+                       return "";
+               String result;
+               if (byteIndex+nameLen < size) {
+                       result = utf(bytes, byteIndex, byteIndex + nameLen);
+                       byteIndex += nameLen;
+               } else {
+                       result = utf(safeBytes(nameLen), 0, nameLen);
+               }
+               return result;
+       }
+
        final protected int getSize() {
                return size;
        }
index 9f557eccf9943a9b8a6aaa02736ef799a04a6918..e9185e6393246bb1c7ae6ff606b5cbcb2fdfca71 100644 (file)
@@ -104,9 +104,13 @@ abstract public class MappingBase<T extends ComponentBase<T>> {
             THashMap<String, T> configurationByUid,
             T configuration) {
         configurationByUid.put(configuration.uid, configuration);
-        for(T child : configuration.getChildren()) {
-            browseConfiguration(configurationByUid, child);
-            child.parent = configuration;
+        THashMap<String, T> children = configuration.getChildMap();
+        if (children != null) {
+            children.forEachValue(child -> {
+                browseConfiguration(configurationByUid, child);
+                child.parent = configuration;
+                return true;
+            });
         }
     }