@@ -28,24 +28,25 @@ public Block getRootBlock() {
2828 return rootBlock ;
2929 }
3030
31- public static FractalHeap read (SeekableByteChannel channel , long position , HdfDataFile hdfDataFile ) throws IOException {
32- FixedPointDatatype sizeOfOffsets = hdfDataFile .getSuperblock ().getFixedPointDatatypeForOffset ();
31+ public static FractalHeap read (SeekableByteChannel channel , long position , HdfDataFile hdfDataFile ) throws IOException , InvocationTargetException , InstantiationException , IllegalAccessException {
32+ FixedPointDatatype sizeOfOffset = hdfDataFile .getSuperblock ().getFixedPointDatatypeForOffset ();
33+ FixedPointDatatype sizeOfLength = hdfDataFile .getSuperblock ().getFixedPointDatatypeForLength ();
3334 channel .position (position );
3435 FractalHeapHeader header = readHeader (channel , hdfDataFile );
35- long rootAddress = header .addressRootBlock ;
36- short nrows = header .currentNumRowsRootIndirectBlock ;
37- long filteredSize = - 1 ;
38- int filterMask = 0 ;
36+ HdfFixedPoint rootAddress = header .addressRootBlock ;
37+ int nrows = header .currentNumRowsRootIndirectBlock ;
38+ HdfFixedPoint filteredSize = sizeOfLength . undefined () ;
39+ long filterMask = 0 ;
3940 if (header .hasFilters && nrows == 0 ) {
4041 filteredSize = header .filteredRootDirectSize ;
4142 filterMask = header .filterMaskRoot ;
4243 }
4344 long expectedBlockOffset = 0 ;
4445 Block root ;
4546 if (nrows == 0 ) {
46- root = readDirectBlock (reader , header , rootAddress , expectedBlockOffset , filteredSize , filterMask );
47+ root = readDirectBlock (channel , header , rootAddress , sizeOfOffset , expectedBlockOffset , filteredSize , filterMask );
4748 } else {
48- root = readIndirectBlock (reader , header , rootAddress , expectedBlockOffset , -1 , nrows );
49+ root = readIndirectBlock (channel , header , sizeOfOffset , sizeOfLength , rootAddress , expectedBlockOffset , -1 , nrows );
4950 }
5051 FractalHeap heap = new FractalHeap ();
5152 heap .header = header ;
@@ -55,11 +56,12 @@ public static FractalHeap read(SeekableByteChannel channel, long position, HdfDa
5556
5657 private static FractalHeapHeader readHeader (SeekableByteChannel channel , HdfDataFile hdfDataFile ) throws IOException , InvocationTargetException , InstantiationException , IllegalAccessException {
5758 FixedPointDatatype sizeOfOffset = hdfDataFile .getSuperblock ().getFixedPointDatatypeForOffset ();
58- FixedPointDatatype sizeOfLength = hdfDataFile .getSuperblock ().getFixedPointDatatypeForLength (). getSize () ;
59+ FixedPointDatatype sizeOfLength = hdfDataFile .getSuperblock ().getFixedPointDatatypeForLength ();
5960
6061 FractalHeapHeader h = new FractalHeapHeader ();
6162 ByteBuffer signatureBuffer = ByteBuffer .allocate (4 );
6263 channel .read (signatureBuffer );
64+ signatureBuffer .flip ();
6365 h .signature = new String (signatureBuffer .array (), StandardCharsets .US_ASCII );
6466 if (!Objects .equals (h .signature , "FRHP" )) {
6567 throw new IOException ("Invalid signature" );
@@ -70,6 +72,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
7072 if ( bytesRead != headerSize ) {
7173 throw new IllegalStateException ("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead );
7274 }
75+ headerBuffer .flip ();
7376
7477 h .version = headerBuffer .get ();
7578 h .heapIdLength = Short .toUnsignedInt (headerBuffer .getShort ());
@@ -105,6 +108,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
105108 if ( bytesRead != headerSize ) {
106109 throw new IllegalStateException ("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead );
107110 }
111+ headerBuffer .flip ();
108112 h .filteredRootDirectSize = HdfReadUtils .readHdfFixedPointFromBuffer (sizeOfLength , headerBuffer );
109113 h .filterMaskRoot = Integer .toUnsignedLong (headerBuffer .getInt ());
110114 }
@@ -114,6 +118,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
114118 if ( bytesRead != headerSize ) {
115119 throw new IllegalStateException ("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead );
116120 }
121+ headerBuffer .flip ();
117122 channel .read (headerBuffer );
118123 byte [] filterData = headerBuffer .array ();
119124 h .filterPipeline = parseFilterPipeline (filterData );
@@ -124,7 +129,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
124129 if ( bytesRead != headerSize ) {
125130 throw new IllegalStateException ("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead );
126131 }
127- channel . read ( headerBuffer );
132+ headerBuffer . flip ( );
128133 h .checksum = Integer .toUnsignedLong (headerBuffer .getInt ());
129134 h .offsetBytes = (h .maximumHeapSize + 7 ) / 8 ;
130135 double logVal = Math .log ((double ) h .maximumDirectBlockSize .getInstance (Long .class ) / h .startingBlockSize .getInstance (Long .class )) / Math .log (2 );
@@ -234,51 +239,59 @@ private static FilterPipeline parseFilterPipeline(byte[] data) throws IOExceptio
234239 return fp ;
235240 }
236241
237- private static Block readDirectBlock (HdfReader reader , FractalHeapHeader header , long address , long expectedBlockOffset , long filteredSize , int filterMask ) throws IOException {
238- long undefined = -1L ;
239- if (address == undefined ) {
242+ private static Block readDirectBlock (SeekableByteChannel channel , FractalHeapHeader header , HdfFixedPoint address , FixedPointDatatype sizeOfOffset , long expectedBlockOffset , HdfFixedPoint filteredSize , long filterMask ) throws IOException , InvocationTargetException , InstantiationException , IllegalAccessException {
243+ if (address .isUndefined ()) {
240244 throw new IOException ("Invalid direct block address" );
241245 }
242- reader .seek (address );
243- String sig = new String (reader .readBytes (4 ));
246+ channel .position (address .getInstance (Long .class ));
247+ //
248+ int headerSize = 4 + 1 + sizeOfOffset .getSize () + header .offsetBytes + (header .checksumDirect ? 4 : 0 );
249+ ByteBuffer headerBuffer = ByteBuffer .allocate (headerSize ).order (ByteOrder .LITTLE_ENDIAN );
250+ int bytesRead = channel .read (headerBuffer );
251+ if ( headerSize != bytesRead )
252+ throw new IllegalStateException ("Incorrect bytesRead: " + bytesRead + ": expected " + headerSize );
253+ headerBuffer .flip ();
254+ String sig = new String (Arrays .copyOfRange (headerBuffer .array (), 0 , 4 ), StandardCharsets .US_ASCII );
244255 if (!Objects .equals (sig , "FHDB" )) {
245256 throw new IOException ("Invalid direct block signature" );
246257 }
247- byte version = reader .readByte ();
258+ headerBuffer .position (4 );
259+ byte version = headerBuffer .get ();
248260 if (version != 0 ) {
249261 throw new IOException ("Unsupported version" );
250262 }
251- long heapHeader = reader . readVariableLong ( header . sizeOfOffsets );
252- if (heapHeader == undefined ) {
263+ HdfFixedPoint heapHeader = HdfReadUtils . readHdfFixedPointFromBuffer ( sizeOfOffset , headerBuffer );
264+ if (heapHeader . isUndefined () ) {
253265 throw new IOException ("Invalid heap header address in direct block" );
254266 }
255- long blockOffset = reader . readVariableLong ( header . offsetBytes );
256- if (blockOffset != expectedBlockOffset ) {
267+ HdfFixedPoint blockOffset = HdfReadUtils . readHdfFixedPointFromBuffer ( sizeOfOffset , headerBuffer );
268+ if (blockOffset . getInstance ( Long . class ) != expectedBlockOffset ) {
257269 throw new IOException ("Block offset mismatch" );
258270 }
259- int checksum = 0 ;
271+ headerBuffer .position (4 + 1 + sizeOfOffset .getSize ()+header .offsetBytes );
272+ long checksum = 0 ;
260273 if (header .checksumDirect ) {
261- checksum = reader . readInt ( ); // checksum, not verifying
274+ checksum = Integer . toUnsignedLong ( headerBuffer . getInt () ); // checksum, not verifying
262275 }
263- int headerSize = 4 + 1 + header .sizeOfOffsets + header .offsetBytes + (header .checksumDirect ? 4 : 0 );
264276 long blockSize = getBlockSize (header , expectedBlockOffset );
265277 long dataSize ;
266- // if (filteredSize != -1) {
267- // dataSize = filteredSize - headerSize;
268- // } else {
269- // dataSize = blockSize - headerSize;
270- // }
271- if (filteredSize != -1 ) {
272- dataSize = filteredSize ;
278+ if (!filteredSize .isUndefined ()) {
279+ dataSize = filteredSize .getInstance (Long .class );
273280 } else {
274281 dataSize = blockSize ;
275282 }
276283 if (dataSize < 0 ) {
277284 throw new IOException ("Invalid data size in direct block" );
278285 }
279- byte [] data = reader .readBytes ((int ) dataSize );
286+ headerBuffer = ByteBuffer .allocate ((int ) dataSize );
287+ bytesRead = channel .read (headerBuffer );
288+ if ( bytesRead != dataSize )
289+ throw new IllegalStateException ();
290+ headerBuffer .flip ();
291+
292+ byte [] data = headerBuffer .array ();
280293 DirectBlock db = new DirectBlock ();
281- db .blockOffset = blockOffset ;
294+ db .blockOffset = blockOffset . getInstance ( Long . class ) ;
282295 db .blockSize = blockSize ;
283296 db .data = data ;
284297 db .filterMask = filterMask ;
@@ -287,35 +300,17 @@ private static Block readDirectBlock(HdfReader reader, FractalHeapHeader header,
287300 return db ;
288301 }
289302
290- private static Block readIndirectBlock (HdfReader reader , FractalHeapHeader header , long address , long expectedBlockOffset , long iblockSize , short passedNrows ) throws IOException {
291- long undefined = -1L ;
292- if (address == undefined ) {
303+ private static Block readIndirectBlock (SeekableByteChannel channel , FractalHeapHeader header , FixedPointDatatype sizeOfOffset , FixedPointDatatype sizeOfLength , HdfFixedPoint address , long expectedBlockOffset , long iblockSize , int passedNrows ) throws IOException , InvocationTargetException , InstantiationException , IllegalAccessException {
304+ if (address .isUndefined ()) {
293305 throw new IOException ("Invalid indirect block address" );
294306 }
295- reader .seek (address );
296- String sig = new String (reader .readBytes (4 ));
297- if (!Objects .equals (sig , "FHIB" )) {
298- throw new IOException ("Invalid indirect block signature" );
299- }
300- byte version = reader .readByte ();
301- if (version != 0 ) {
302- throw new IOException ("Unsupported version" );
303- }
304- long heapHeader = reader .readVariableLong (header .sizeOfOffsets );
305- if (heapHeader == undefined ) {
306- throw new IOException ("Invalid heap header address in indirect block" );
307- }
308- long blockOffset = reader .readVariableLong (header .offsetBytes );
309- if (blockOffset != expectedBlockOffset ) {
310- throw new IOException ("Block offset mismatch" );
311- }
307+ channel .position (address .getInstance (Long .class ));
312308 IndirectBlock ib = new IndirectBlock ();
313- ib .blockOffset = blockOffset ;
314- ib .children = new ArrayList <>();
315- short nrows ;
309+ int nrows ;
310+ long startingBlockSize = header .startingBlockSize .getInstance (Long .class );
316311 if (iblockSize > 0 ) {
317312 long covered = 0 ;
318- long current = header . startingBlockSize ;
313+ long current = startingBlockSize ;
319314 int nr = 0 ;
320315 while (covered < iblockSize ) {
321316 covered += (long ) header .tableWidth * current ;
@@ -326,50 +321,90 @@ private static Block readIndirectBlock(HdfReader reader, FractalHeapHeader heade
326321 } else {
327322 nrows = passedNrows ;
328323 }
324+ int plusSize = 0 ;
329325 ib .nrows = nrows ;
326+ for (short r = 0 ; r < nrows ; r ++) {
327+ for (int c = 0 ; c < header .tableWidth ; c ++) {
328+ plusSize += sizeOfOffset .getSize ();
329+ boolean isDirect = r < header .maxDblockRows ;
330+ if (header .hasFilters && isDirect ) {
331+ plusSize += sizeOfLength .getSize ();
332+ plusSize += 4 ;
333+ }
334+ }
335+ }
336+ plusSize += 4 ; // checksum
337+
338+ int headerSize = 4 + 1 + sizeOfOffset .getSize () + header .offsetBytes + plusSize ;
339+ ByteBuffer headerBuffer = ByteBuffer .allocate (headerSize );
340+ int bytesRead = channel .read (headerBuffer );
341+ if ( headerSize != bytesRead )
342+ throw new IllegalStateException ("Incorrect bytesRead: " + bytesRead + ": expected " + headerSize );
343+ headerBuffer .flip ();
344+
345+ String sig = new String (Arrays .copyOfRange (headerBuffer .array (), 0 , 4 ), StandardCharsets .US_ASCII );
346+ if (!Objects .equals (sig , "FHIB" )) {
347+ throw new IOException ("Invalid indirect block signature" );
348+ }
349+ headerBuffer .position (4 );
350+ byte version = headerBuffer .get ();
351+ if (version != 0 ) {
352+ throw new IOException ("Unsupported version" );
353+ }
354+ HdfFixedPoint heapHeader = HdfReadUtils .readHdfFixedPointFromBuffer (sizeOfOffset , headerBuffer );
355+ if (heapHeader .isUndefined ()) {
356+ throw new IOException ("Invalid heap header address in indirect block" );
357+ }
358+ HdfFixedPoint blockOffset = HdfReadUtils .readHdfFixedPointFromBuffer (sizeOfOffset , headerBuffer );
359+ if (blockOffset .getInstance (Long .class ) != expectedBlockOffset ) {
360+ throw new IOException ("Block offset mismatch" );
361+ }
362+ headerBuffer .position (4 + 1 + sizeOfOffset .getSize () + header .offsetBytes );
363+ ib .blockOffset = blockOffset .getInstance (Long .class );
364+ ib .children = new ArrayList <>();
330365 List <ChildInfo > childInfos = new ArrayList <>();
331- long currentOffset = expectedBlockOffset ;
366+ long currentOffset = expectedBlockOffset ; // expectedBlockOffset;
332367 for (short r = 0 ; r < nrows ; r ++) {
333- long rowBlockSize = header . startingBlockSize * (1L << r );
368+ long rowBlockSize = startingBlockSize * (1L << r );
334369 for (int c = 0 ; c < header .tableWidth ; c ++) {
335- long childAddress = reader . readVariableLong ( header . sizeOfOffsets );
336- long childFilteredSize = - 1 ;
337- int childFilterMask = 0 ;
370+ HdfFixedPoint childAddress = HdfReadUtils . readHdfFixedPointFromBuffer ( sizeOfOffset , headerBuffer );
371+ HdfFixedPoint childFilteredSize = sizeOfOffset . undefined () ;
372+ long childFilterMask = 0 ;
338373 boolean isDirect = r < header .maxDblockRows ;
339374 if (header .hasFilters && isDirect ) {
340- childFilteredSize = reader . readVariableLong ( header . sizeOfLengths );
341- childFilterMask = reader . readInt ();
375+ childFilteredSize = HdfReadUtils . readHdfFixedPointFromBuffer ( sizeOfLength , headerBuffer );
376+ childFilterMask = headerBuffer . getInt ();
342377 }
343- if (childAddress != undefined ) {
344- long childBlockOffset = currentOffset ;
345- ChildInfo info = new ChildInfo (childAddress , childBlockOffset , isDirect , childFilteredSize , childFilterMask , rowBlockSize );
378+ if (!childAddress .isUndefined ()) {
379+ ChildInfo info = new ChildInfo (childAddress , currentOffset , isDirect , childFilteredSize , childFilterMask , rowBlockSize );
346380 childInfos .add (info );
347381 }
348382 currentOffset += rowBlockSize ;
349383 }
350384 }
351- ib .checksum = reader . readInt ( );
385+ ib .checksum = Integer . toUnsignedLong ( headerBuffer . getInt () );
352386 for (ChildInfo info : childInfos ) {
353- if (info .address != undefined ) {
387+ if (! info .address . isUndefined () ) {
354388 Block child ;
355389 if (info .isDirect ) {
356- child = readDirectBlock (reader , header , info .address , info .blockOffset , info .filteredSize , info .filterMask );
390+ child = readDirectBlock (channel , header , info .address , sizeOfOffset , info .blockOffset , info .filteredSize , info .filterMask );
357391 } else {
358- child = readIndirectBlock (reader , header , info .address , info .blockOffset , info .blockSize , (short ) 0 );
392+ child = readIndirectBlock (channel , header , sizeOfOffset , sizeOfLength , info .address , info .blockOffset , info .blockSize , (short ) 0 );
359393 }
360394 ib .children .add (child );
361395 }
362396 }
363397 return ib ;
364398 }
365399
366- private static long getBlockSize (FractalHeapHeader header , long blockOffset ) {
400+ private static long getBlockSize (FractalHeapHeader header , long blockOffset ) throws IOException , InvocationTargetException , InstantiationException , IllegalAccessException {
401+ long startingBlockSize = header .startingBlockSize .getInstance (Long .class );
367402 if (blockOffset == 0 && header .currentNumRowsRootIndirectBlock == 0 ) {
368- return header . startingBlockSize ;
403+ return startingBlockSize ;
369404 }
370- double arg = ((double ) blockOffset / (header .tableWidth * header .startingBlockSize )) + 1 ;
405+ double arg = ((double ) blockOffset / (header .tableWidth * header .startingBlockSize . getInstance ( Long . class ) )) + 1 ;
371406 int row = (int ) Math .floor (Math .log (arg ) / Math .log (2 ));
372- return header . startingBlockSize * (1L << row );
407+ return startingBlockSize * (1L << row );
373408 }
374409
375410 public byte [] getObject (ParsedHeapId heapId ) {
@@ -452,25 +487,25 @@ public static class DirectBlock extends Block {
452487 public int headerSize ;
453488 long blockSize ;
454489 byte [] data ;
455- int filterMask ;
456- int checksum ;
490+ long filterMask ;
491+ long checksum ;
457492 }
458493
459494 public static class IndirectBlock extends Block {
460- short nrows ;
495+ int nrows ;
461496 List <Block > children ;
462- int checksum ;
497+ long checksum ;
463498 }
464499
465500 private static class ChildInfo {
466- long address ;
501+ HdfFixedPoint address ;
467502 long blockOffset ;
468503 boolean isDirect ;
469- long filteredSize ;
470- int filterMask ;
504+ HdfFixedPoint filteredSize ;
505+ long filterMask ;
471506 long blockSize ;
472507
473- public ChildInfo (long address , long blockOffset , boolean isDirect , long filteredSize , int filterMask , long blockSize ) {
508+ public ChildInfo (HdfFixedPoint address , long blockOffset , boolean isDirect , HdfFixedPoint filteredSize , long filterMask , long blockSize ) {
474509 this .address = address ;
475510 this .blockOffset = blockOffset ;
476511 this .isDirect = isDirect ;
@@ -480,6 +515,21 @@ public ChildInfo(long address, long blockOffset, boolean isDirect, long filtered
480515 }
481516 }
482517
518+ // public static long readVariableLong(byte[] bytes, int size) {
519+ // long val = 0;
520+ // for (int i = 0; i < size; i++) {
521+ // val |= (bytes[i] & 0xFFL) << (8 * i);
522+ // }
523+ // // If the most significant bit is set, check if all bits are 1 (undefined address)
524+ // if (size < 8 && (val & (1L << (size * 8 - 1))) != 0) {
525+ // long mask = (1L << (size * 8)) - 1;
526+ // if (val == mask) {
527+ // return -1L; // Undefined address
528+ // }
529+ // }
530+ // return val;
531+ // }
532+ //
483533// private static class HdfReader {
484534// private final SeekableByteChannel channel;
485535//
0 commit comments