259 lines
8.6 KiB
C#
259 lines
8.6 KiB
C#
using System.Text;
|
|
|
|
namespace OsmXmlToRegionConverter;
|
|
|
|
public static class Extensions
|
|
{
|
|
public static T[] SubArray<T>(this T[] array, int offset, int length)
|
|
{
|
|
T[] result = new T[length];
|
|
Buffer.BlockCopy(array, offset, result, 0, length);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public class ByteConverter
|
|
{
|
|
|
|
private enum ContentType : byte
|
|
{
|
|
Node = 0,
|
|
Coordinates = 1,
|
|
Edge = 2,
|
|
TmpNode = 3,
|
|
TmpWay = 4,
|
|
Region = 5,
|
|
TagManager = 6
|
|
}
|
|
|
|
public static HashSet<object> GetObjectsFromBytes(byte[] bytes)
|
|
{
|
|
HashSet<object> ret = new HashSet<object>();
|
|
while (bytes.Length > 0)
|
|
{
|
|
ContentType contentType = (ContentType)bytes[0];
|
|
switch (contentType)
|
|
{
|
|
case ContentType.Node:
|
|
int edgeCount = BitConverter.ToInt32(bytes, 1);
|
|
int byteSizeNode = Node.ByteSizeEmpty + 1 + edgeCount * Edge.ByteSize; //+1 for contenttype of coordinates
|
|
ret.Add(Node.FromBytes(bytes.SubArray(1, byteSizeNode)));
|
|
bytes = bytes.SubArray(1 + byteSizeNode, bytes.Length - 1 - byteSizeNode); //-1 for overflow
|
|
break;
|
|
case ContentType.Coordinates:
|
|
ret.Add(Coordinates.FromBytes(bytes.SubArray(1, Coordinates.ByteSize)));
|
|
bytes = bytes.SubArray(1 + Coordinates.ByteSize, bytes.Length - 1 - Coordinates.ByteSize);
|
|
break;
|
|
case ContentType.Edge:
|
|
ret.Add(Edge.FromBytes(bytes.SubArray(1, Edge.ByteSize)));
|
|
bytes = bytes.SubArray(1 + Edge.ByteSize, bytes.Length - 1 - Edge.ByteSize);
|
|
break;
|
|
case ContentType.TmpNode:
|
|
ret.Add(TmpNode.FromBytes(bytes.SubArray(1, TmpNode.ByteSize + 1))); //+1 for contenttype of coordinates
|
|
bytes = bytes.SubArray(1 + TmpNode.ByteSize + 1, bytes.Length - 1 - (TmpNode.ByteSize + 1));
|
|
break;
|
|
case ContentType.TmpWay:
|
|
int byteSizeTmpWay = BitConverter.ToInt32(bytes, 1);
|
|
ret.Add(TmpWay.FromBytes(bytes.SubArray(1, byteSizeTmpWay)));
|
|
bytes = bytes.SubArray(1 + byteSizeTmpWay, bytes.Length - 1 - byteSizeTmpWay);
|
|
break;
|
|
case ContentType.TagManager:
|
|
int totalBytesTagManager = BitConverter.ToInt32(bytes, 1);
|
|
ret.Add(TagManager.FromBytes(bytes.SubArray(1 + sizeof(int), totalBytesTagManager)));
|
|
bytes = bytes.SubArray(1 + sizeof(int) + totalBytesTagManager, bytes.Length - 1 - sizeof(int) - totalBytesTagManager);
|
|
break;
|
|
default:
|
|
throw new Exception("Unknown Type");
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
public static byte[] GetBytes(Node n)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
b.Write((byte)ContentType.Node);
|
|
b.Write(n.edges.Count);
|
|
b.Write((byte)ContentType.Node);
|
|
b.Write(n.id);
|
|
b.Write(GetBytes(n.coordinates));
|
|
foreach(Edge e in n.edges)
|
|
b.Write(GetBytes(e));
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(Coordinates c)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
b.Write((byte)ContentType.Coordinates);
|
|
b.Write(c.latitude);
|
|
b.Write(c.longitude);
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(Edge e)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
b.Write((byte)ContentType.Edge);
|
|
b.Write(e.wayId);
|
|
b.Write(e.neighborId);
|
|
b.Write(e.neighborRegion);
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(TmpNode tn)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
b.Write((byte)ContentType.TmpNode);
|
|
b.Write(tn.id);
|
|
b.Write(GetBytes(tn.coordinates));
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(TmpWay tw)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
b.Write((byte)ContentType.TmpWay);
|
|
HashSet<byte[]> tagBytesSet = new HashSet<byte[]>();
|
|
int totalTagBytes = 0;
|
|
foreach (Tag tag in tw.tags)
|
|
{
|
|
byte[] tagBytes = GetBytes(tag);
|
|
totalTagBytes += tagBytes.Length;
|
|
tagBytesSet.Add(tagBytes);
|
|
}
|
|
|
|
b.Write(sizeof(ulong) + sizeof(int) + tw.wayNodeIds.Length * sizeof(ulong) + totalTagBytes);
|
|
b.Write(tw.id);
|
|
b.Write(tw.wayNodeIds.Length);
|
|
foreach (ulong wayNodeId in tw.wayNodeIds)
|
|
b.Write(wayNodeId);
|
|
foreach (byte[] tagBytes in tagBytesSet)
|
|
b.Write(tagBytes);
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(Region r)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
b.Write((byte)ContentType.Region);
|
|
b.Write(r.GetNodes().Length);
|
|
b.Write(r.regionHash);
|
|
foreach (Node n in r.GetNodes())
|
|
b.Write(GetBytes(n));
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(Tag tag)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
byte[] valueBytes;
|
|
if (tag.value is ulong valueUlong)
|
|
{
|
|
valueBytes = BitConverter.GetBytes(valueUlong);
|
|
}else if (tag.value is byte valueByte)
|
|
{
|
|
valueBytes = new[] { valueByte };
|
|
}else if (tag.value is bool valueBool)
|
|
{
|
|
valueBytes = BitConverter.GetBytes(valueBool);
|
|
}else if (tag.value is string valueString)
|
|
{
|
|
valueBytes = Encoding.ASCII.GetBytes(valueString);
|
|
}else if (tag.value is int valueInt)
|
|
{
|
|
valueBytes = BitConverter.GetBytes(valueInt);
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentException($"Unknown type {tag.value.GetType()}");
|
|
}
|
|
b.Write(sizeof(byte) + valueBytes.Length);
|
|
b.Write((byte)tag.key);
|
|
b.Write(valueBytes);
|
|
}
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
|
|
public static byte[] GetBytes(TagManager t)
|
|
{
|
|
using (MemoryStream m = new MemoryStream())
|
|
{
|
|
using (BinaryWriter b = new BinaryWriter(m))
|
|
{
|
|
HashSet<byte[]> wayBytesSet = new HashSet<byte[]>();
|
|
int totalBytes = 0;
|
|
foreach (KeyValuePair<ulong, HashSet<Tag>> way in t.wayTags)
|
|
{
|
|
HashSet<byte[]> tagBytesSet = new HashSet<byte[]>();
|
|
tagBytesSet.Add(BitConverter.GetBytes(way.Key));
|
|
int totalWayBytes = sizeof(ulong);
|
|
|
|
foreach (Tag tag in way.Value)
|
|
{
|
|
byte[] tagBytes = GetBytes(tag);
|
|
totalWayBytes += tagBytes.Length;
|
|
tagBytesSet.Add(tagBytes);
|
|
}
|
|
|
|
wayBytesSet.Add(BitConverter.GetBytes(totalWayBytes));
|
|
foreach (byte[] bytes in tagBytesSet)
|
|
{
|
|
wayBytesSet.Add(bytes);
|
|
}
|
|
|
|
totalBytes += sizeof(int) + totalWayBytes;
|
|
}
|
|
|
|
b.Write(totalBytes);
|
|
foreach (byte[] bytes in wayBytesSet)
|
|
{
|
|
b.Write(bytes);
|
|
}
|
|
}
|
|
|
|
return m.ToArray();
|
|
}
|
|
}
|
|
} |