namespace OSMDatastructure; public static class ByteConverter { #region Node /* * Node Byteform: * +-------------------------------+ * | Latitude | Longitude | ConnectionSize| connection | * |---------------+---------------+---------------+---------------+ * | 4 bytes | 4 bytes | 4 bytes | ConnectionSize| * | float | float | int | Connection | * +---------------+---------------+ */ public static byte[] GetBytes(Node node) { byte[] latitudeBytes = BitConverter.GetBytes(node.lat); byte[] longitudeBytes = BitConverter.GetBytes(node.lon); Connection[] connections = node.GetConnections(); Dictionary connectionsBytes = new (); int byteArraySize = latitudeBytes.Length + longitudeBytes.Length; foreach (Connection connection in connections) { byte[] connectionBytes = ByteConverter.GetBytes(connection); byte[] connectionSizeBytes = BitConverter.GetBytes(connectionBytes.Length); connectionsBytes.Add(connectionSizeBytes, connectionBytes); byteArraySize += connectionSizeBytes.Length + connectionBytes.Length; } byte[] retByteArray = new byte[byteArraySize]; int offset = 0; Array.Copy(latitudeBytes, 0, retByteArray, offset, latitudeBytes.Length); offset += latitudeBytes.Length; Array.Copy(longitudeBytes, 0, retByteArray, offset, longitudeBytes.Length); offset += longitudeBytes.Length; foreach (KeyValuePair connectionBytes in connectionsBytes) { Array.Copy(connectionBytes.Key, 0, retByteArray, offset, connectionBytes.Key.Length); offset += connectionBytes.Key.Length; Array.Copy(connectionBytes.Value, 0, retByteArray, offset, connectionBytes.Value.Length); offset += connectionBytes.Value.Length; } return retByteArray; } public static Node ToNode(byte[] bytes) { int offset = 0; float lat = BitConverter.ToSingle(bytes, offset); offset += sizeof(float); float lon = BitConverter.ToSingle(bytes, offset); offset += sizeof(float); Node retNode = new Node(lat, lon); while (offset < bytes.Length) { int size = BitConverter.ToInt32(bytes, offset); offset += sizeof(int); byte[] connectionBytes = new byte[size]; Array.Copy(bytes, offset, connectionBytes, 0, size); retNode.AddConnection(ByteConverter.ToConnection(connectionBytes)); offset += connectionBytes.Length; } return retNode; } #endregion #region Connection /* * Connection Byteform: * +---------------+---------------+ * | endId | endLatitude | endLongitude | tagBytes | tag | value | * |---------------+---------------+---------------+---------------+---------------+---------------+ * | 8 bytes | 4 bytes | 4 bytes | 4 bytes | 1 byte | 1 byte | * | ulong | float | float | int | | | * +---------------+---------------+ */ public static byte[] GetBytes(Connection connection) { byte[] endIdBytes = BitConverter.GetBytes(connection.endNodeId); byte[] endLatBytes = BitConverter.GetBytes(connection.endNodeCoordinates.lat); byte[] endLonBytes = BitConverter.GetBytes(connection.endNodeCoordinates.lon); Dictionary connectionTags = connection.GetTags(); byte[] tagBytes = BitConverter.GetBytes(connectionTags.Count * 2); int byteArraySize = endIdBytes.Length + endLatBytes.Length + endLonBytes.Length + tagBytes.Length + connectionTags.Count * 2; byte[] retBytes = new byte[byteArraySize]; int offset = 0; Array.Copy(endIdBytes, 0, retBytes, offset, endIdBytes.Length); offset += endIdBytes.Length; Array.Copy(endLatBytes, 0, retBytes, offset, endLatBytes.Length); offset += endLatBytes.Length; Array.Copy(endLonBytes, 0 , retBytes, offset, endLonBytes.Length); offset += endLonBytes.Length; Array.Copy(tagBytes, 0, retBytes, offset, tagBytes.Length); offset += tagBytes.Length; foreach (KeyValuePair tagKv in connectionTags) { retBytes[offset] = (byte)tagKv.Key; offset++; retBytes[offset] = (byte)tagKv.Value; offset++; } return retBytes; } public static Connection ToConnection(byte[] bytes) { int offset = 0; ulong endId = BitConverter.ToUInt64(bytes, offset); offset += sizeof(ulong); float endLat = BitConverter.ToSingle(bytes, offset); offset += sizeof(float); float endLon = BitConverter.ToSingle(bytes, offset); offset += sizeof(float); Connection retConnection = new Connection(endId, new Coordinates(endLat, endLon)); int tagBytes = BitConverter.ToInt32(bytes, offset); offset += sizeof(int); while (offset < bytes.Length) { byte key = bytes[offset]; byte value = bytes[offset + 1]; retConnection.AddTag(key, value); offset += 2; } return retConnection; } #endregion #region Region /* * Region Byteform: * +---------------+---------------+---------------+ * | regionHash | nodeBytes | nodeId | node | * |---------------+---------------+---------------+---------------+ * | 8 bytes | 4 bytes | 8 bytes | nodeBytes | * | ulong | int | ulong | Node | * +---------------+---------------+---------------+ */ public static byte[] GetBytes(Region region) { byte[] regionHashBytes = BitConverter.GetBytes(region.regionHash); int byteArraySize = regionHashBytes.Length; Dictionary nodesBytes = new(); foreach(KeyValuePair nodeKv in region.GetNodes()) { byte[] nodeIdBytes = BitConverter.GetBytes(nodeKv.Key); byte[] nodeBytes = GetBytes(nodeKv.Value); nodesBytes.Add(nodeIdBytes, nodeBytes); byteArraySize += sizeof(int) + nodeIdBytes.Length + nodeBytes.Length; } byte[] retBytes = new byte[byteArraySize]; int offset = 0; Array.Copy(regionHashBytes, 0, retBytes, offset, regionHashBytes.Length); offset += regionHashBytes.Length; foreach (KeyValuePair nodeByteKv in nodesBytes) { Array.Copy(BitConverter.GetBytes(nodeByteKv.Value.Length), 0, retBytes, offset, sizeof(int)); offset += sizeof(int); Array.Copy(nodeByteKv.Key, 0, retBytes, offset, nodeByteKv.Key.Length); offset += nodeByteKv.Key.Length; Array.Copy(nodeByteKv.Value, 0, retBytes, offset, nodeByteKv.Value.Length); offset += nodeByteKv.Value.Length; } return retBytes; } public static Region ToRegion(byte[] bytes) { int offset = 0; ulong regionHash = BitConverter.ToUInt64(bytes, offset); offset += sizeof(ulong); Region retRegion = new Region(regionHash); while (offset < bytes.Length) { int nodeBytesAmount = BitConverter.ToInt32(bytes, offset); offset += sizeof(int); ulong nodeId = BitConverter.ToUInt64(bytes, offset); offset += sizeof(ulong); byte[] nodeBytes = new byte[nodeBytesAmount]; Array.Copy(bytes, offset, nodeBytes, 0, nodeBytesAmount); retRegion.AddNode(nodeId, ByteConverter.ToNode(nodeBytes)); offset += nodeBytes.Length; } return retRegion; } #endregion }