package graphrep;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.logging.Logger;

public class GraphRepBinaryReader implements GraphRepReader {
    private static Logger log = Logger.getLogger("tourenplaner");

    private static final int version = 2;

    // fileformat is:
    // nodecount
    // edgecount
    // (nodecount) * (lat lon height rank)
    // (edgecount) * (source trgt dist mult)
    // (edgecount) * (mappingInToOut)
    // (nodecount+1) * (offsetIn)
    // (nodecount+1) * (offsetOut)

    @Override
    public GraphRep createGraphRep(InputStream in) throws IOException {

        // 8388608 Bytes = 8 MB
        BufferedInputStream bin = new BufferedInputStream(in, 8388608);
        DataInputStream din = new DataInputStream(bin);
        // Check the first 4 bytes to see if it's a ToureNPlaner Graphfile
        byte[] magic = new byte[4];
        din.readFully(magic);
        String magicString = new String(magic, Charset.forName("UTF-8"));
        if (!magicString.equals("TPG\n")) {
            throw new IOException("The given stream does not contain a ToureNPlaner Graphfile");
        }
        // Check whether we got the same version
        int realVersion = din.readInt();
        if (realVersion != version) {
            throw new IOException("Wrong file format version, expected " + version + " got " + realVersion);
        }

        int nodeCount = din.readInt();
        int edgeCount = din.readInt();

        GraphRep graphRep = new GraphRep(nodeCount, edgeCount);


        log.info("Reading " + nodeCount + " nodes and " + edgeCount + " edges ...");
        int lat, lon;
        int height;
        int rank;
        // Read nodes
        for (int i = 0; i < nodeCount; i++) {
            lat = din.readInt();
            lon = din.readInt();
            height = din.readInt();
            rank = din.readInt();
            graphRep.setNodeData(i, lat, lon, height);
            graphRep.setNodeRank(i, rank);
        }

        // temporary values for edges
        int src, trgt, dist, euclidianDist;
        int shortcuttedEdge1, shortcuttedEdge2;
        // Read edges
        for (int i = 0; i < edgeCount; i++) {
            src = din.readInt();
            trgt = din.readInt();
            dist = din.readInt();
            euclidianDist = din.readInt();
            shortcuttedEdge1 = din.readInt();
            shortcuttedEdge2 = din.readInt();
            graphRep.setEdgeData(i, src, trgt, dist, euclidianDist);
            graphRep.setShortcutData(i, shortcuttedEdge1, shortcuttedEdge2);
        }

        // Read mappingInToOut
        final int[] mappingInToOut = new int[edgeCount];
        for (int i = 0; i < edgeCount; i++) {
            mappingInToOut[i] = din.readInt();
        }
        graphRep.setMappingInToOut(mappingInToOut);

        // Read offsetIn
        final int[] offsetIn = new int[nodeCount + 1];
        for (int i = 0; i < nodeCount + 1; i++) {
            offsetIn[i] = din.readInt();
        }
        graphRep.setOffsetIn(offsetIn);

        // Read offsetOut
        final int[] offsetOut = new int[nodeCount + 1];
        for (int i = 0; i < nodeCount + 1; i++) {
            offsetOut[i] = din.readInt();
        }
        graphRep.setOffsetOut(offsetOut);

        in.close();
        log.info("successfully created offset of InEdges");
        // choose the NNSearcher here
        // DumbNN uses linear search and is slow.
        // HashNN should be faster but needs more RAM
        log.info("Start creating NNSearcher");
        graphRep.searcher = new HashNN(graphRep);
        System.gc();
        log.info("Graph loaded");
        return graphRep;
    }
}

@@ -128,32 +128,114 @@
 io.InputStream;%0A
+import java.nio.ByteBuffer;%0Aimport java.nio.ByteOrder;%0Aimport java.nio.IntBuffer;%0A
 import java.nio.
@@ -1714,17 +1714,16 @@
 ount);%0A%0A
-%0A
         
@@ -1798,16 +1798,387 @@
 s ...%22);
+%0A%0A        // read all the nodes in a byte array, wrap this array in a bytebuffer, set the byte order to Big endian and%0A        // then look at this buffer as if it were an int buffer%0A        byte%5B%5D temp = new byte%5BnodeCount * 4 * 4%5D;%0A        din.read(temp, 0, nodeCount * 4 * 4);%0A        IntBuffer tempbb = ByteBuffer.wrap(temp).order(ByteOrder.BIG_ENDIAN).asIntBuffer();
 %0A       
@@ -2312,34 +2312,33 @@
       lat = 
-din.readIn
+tempbb.ge
 t();%0A       
@@ -2344,34 +2344,33 @@
       lon = 
-din.readIn
+tempbb.ge
 t();%0A       
@@ -2379,34 +2379,33 @@
    height = 
-din.readIn
+tempbb.ge
 t();%0A       
@@ -2416,26 +2416,25 @@
  rank = 
-din.readIn
+tempbb.ge
 t();%0A   
@@ -2531,32 +2531,204 @@
 nk);%0A        %7D%0A%0A
+        temp = new byte%5BedgeCount * 6 * 4%5D;%0A        din.read(temp, 0, edgeCount * 6 * 4);%0A        tempbb = ByteBuffer.wrap(temp).order(ByteOrder.BIG_ENDIAN).asIntBuffer();%0A
         // tempo
@@ -2927,26 +2927,25 @@
   src = 
-din.readIn
+tempbb.ge
 t();%0A   
@@ -2956,34 +2956,33 @@
      trgt = 
-din.readIn
+tempbb.ge
 t();%0A       
@@ -2989,34 +2989,33 @@
      dist = 
-din.readIn
+tempbb.ge
 t();%0A       
@@ -3031,34 +3031,33 @@
 idianDist = 
-din.readIn
+tempbb.ge
 t();%0A       
@@ -3080,26 +3080,25 @@
 Edge1 = 
-din.readIn
+tempbb.ge
 t();%0A   
@@ -3125,26 +3125,25 @@
 Edge2 = 
-din.readIn
+tempbb.ge
 t();%0A   

read nodes and edges from a binarydump into a bytebuffer - faster but takes more memory while reading (maybe read in blocks in the future?)