public class Parser\r
{\r
#region type definitions\r
- protected enum Protocol : int\r
+ public enum Protocol : int\r
{ \r
Nmea = 0,\r
Ubx,\r
}\r
\r
- protected delegate bool TrialParser(\r
+ public delegate bool TrialParser(\r
byte[] sentence, out UnknownPacket packet);\r
- protected delegate int Searcher(byte[] input, int offset);\r
+ public delegate int SyncSearcher(byte[] input, int offset);\r
\r
- #endregion\r
-\r
- #region fields\r
- private byte[] buffer = new byte[0];\r
- private List<UnknownPacket> packets = new List<UnknownPacket>();\r
-\r
- private static readonly Protocol[] protocols;\r
- private static readonly TrialParser[] parsers;\r
- private static readonly Searcher[] searchers;\r
+ protected struct ParserFunctions\r
+ {\r
+ public TrialParser TryParse;\r
+ public SyncSearcher SearchSyncFrom;\r
+ public ParserFunctions(TrialParser parser, SyncSearcher searcher)\r
+ {\r
+ TryParse = parser;\r
+ SearchSyncFrom = searcher;\r
+ }\r
+ }\r
\r
+ \r
private struct SyncIndex\r
{\r
public int Index;\r
Protocol = protocol;\r
}\r
}\r
- \r
+\r
+ #endregion\r
+\r
+ #region fields\r
+ private byte[] buffer = new byte[0];\r
+ private List<UnknownPacket> packets = new List<UnknownPacket>();\r
+\r
+ private static Dictionary<Protocol, ParserFunctions> functions =\r
+ new Dictionary<Protocol, ParserFunctions>();\r
+\r
#endregion\r
\r
#region constructors\r
static Parser()\r
{\r
- protocols = Enum.GetValues(typeof(Protocol)) as Protocol[];\r
-\r
- parsers = new TrialParser[protocols.Length];\r
- parsers[(int)Protocol.Nmea] = Nmea.Parser.TryParse;\r
- parsers[(int)Protocol.Ubx] = Ubx.Parser.TryParse;\r
+ Bind(Protocol.Nmea,\r
+ Nmea.Parser.TryParse, Nmea.Parser.SearchSyncFrom);\r
\r
- searchers = new Searcher[protocols.Length];\r
- searchers[(int)Protocol.Nmea] = Nmea.Parser.SearchSyncFrom;\r
- searchers[(int)Protocol.Ubx] = Ubx.Parser.SearchSyncFrom;\r
+ Bind(Protocol.Ubx, Ubx.Parser.TryParse, Ubx.Parser.SearchSyncFrom);\r
}\r
\r
public Parser()\r
public void Push(byte[] fragment)\r
{\r
Join(fragment);\r
- ParseBuffer(protocols);\r
+ ParseBuffer(functions);\r
}\r
\r
public UnknownPacket Peek()\r
\r
public static bool TryParse(byte[] sentence, out UnknownPacket packet)\r
{\r
- foreach (Protocol p in protocols)\r
+ foreach (Protocol p in functions.Keys)\r
{\r
- if (parsers[(int)p](sentence, out packet))\r
+ if (functions[p].TryParse(sentence, out packet))\r
{\r
return true;\r
}\r
packet = null;\r
return false;\r
}\r
+\r
+ public static void Bind(Protocol protocol,\r
+ TrialParser parser, SyncSearcher searcher)\r
+ {\r
+ functions[protocol] = new ParserFunctions(parser, searcher);\r
+ }\r
+\r
+ public static void Unbind(Protocol protocol)\r
+ {\r
+ functions.Remove(protocol);\r
+ }\r
#endregion\r
\r
#region protected methods\r
buffer = joined;\r
}\r
\r
- protected void ParseBuffer(Protocol[] protocols)\r
- { \r
- List<SyncIndex> foundList = new List<SyncIndex>();\r
- List<SyncIndex> fullFoundList = new List<SyncIndex>();\r
+ protected void ParseBuffer(\r
+ Dictionary<Protocol, ParserFunctions> functions)\r
+ {\r
+ Comparison<SyncIndex> sorter = delegate(SyncIndex a, SyncIndex b)\r
+ {\r
+ return a.Index - b.Index;\r
+ };\r
+ List<SyncIndex> found = new List<SyncIndex>();\r
int offset = 0;\r
while (offset < buffer.Length)\r
{\r
- foreach (Protocol p in protocols)\r
+ foreach (Protocol p in functions.Keys)\r
{\r
- int index = searchers[(int)p](buffer, offset);\r
+ int index = functions[p].SearchSyncFrom(buffer, offset);\r
if (index >= 0)\r
{\r
- foundList.Add(new SyncIndex(index, p));\r
+ SyncIndex s = new SyncIndex(index, p);\r
+ if (!found.Contains(s))\r
+ {\r
+ found.Add(s);\r
+ }\r
}\r
}\r
- if (foundList.Count == 0)\r
+ if (found.Count == 0)\r
{\r
if (offset == 0)\r
{\r
}\r
return;\r
}\r
- foundList.Sort(\r
- delegate(SyncIndex a, SyncIndex b)\r
- {\r
- return a.Index - b.Index;\r
- });\r
- int firstSync = foundList[0].Index;\r
- byte[] synced = Substring(buffer, firstSync);\r
+ found.Sort(sorter);\r
+ SyncIndex first = found[0];\r
+ byte[] synced = Substring(buffer, first.Index);\r
UnknownPacket packet = null;\r
- if (parsers[(int)foundList[0].Protocol](synced, out packet))\r
+ if (functions[first.Protocol].TryParse(synced, out packet))\r
{\r
- if (firstSync > 0)\r
+ if (first.Index > 0)\r
{\r
- packets.Add(new UnknownPacket(buffer, firstSync));\r
+ packets.Add(new UnknownPacket(buffer, first.Index));\r
}\r
packets.Add(packet);\r
buffer = Substring(synced, packet.Raw.Length);\r
- ParseBuffer(protocols);\r
+ ParseBuffer(functions);\r
return;\r
}\r
- fullFoundList.AddRange(foundList);\r
- offset = foundList[0].Index + 1;\r
- foundList.RemoveAt(0);\r
-\r
+ offset = first.Index + 1;\r
+ found.RemoveAt(0);\r
}\r
}\r
\r
#endregion\r
\r
#region fields\r
- private static readonly Protocol[] protocols =\r
- new Protocol[] { Protocol.Ubx };\r
+ private static readonly \r
+ Dictionary<Protocol, ParserFunctions> functions;\r
private static Dictionary<Packet.MessageID, TrialParser> parsers;\r
private static readonly Encoding ascii = Encoding.ASCII;\r
\r
#region constructors\r
static Parser()\r
{\r
+ functions = new Dictionary<Protocol, ParserFunctions>();\r
+ functions.Add(Protocol.Ubx, \r
+ new ParserFunctions(TryParse, SearchSyncFrom));\r
+\r
parsers = new Dictionary<Packet.MessageID, TrialParser>();\r
parsers[Packet.MessageID.NavClock] = NavClock.TryParse;\r
parsers[Packet.MessageID.NavPosEcef] = NavPosEcef.TryParse;\r
public new void Push(byte[] fragment)\r
{\r
Join(fragment);\r
- ParseBuffer(protocols);\r
+ ParseBuffer(functions);\r
+ }\r
+\r
+ public static void AddParser(Packet.MessageID id, TrialParser parser)\r
+ {\r
+ parsers[id] = parser;\r
+ }\r
+\r
+ public static void RemoveParser(Packet.MessageID id)\r
+ {\r
+ parsers.Remove(id);\r
}\r
\r
- public new static bool TryParse(byte[] sentence, out UnknownPacket packet)\r
+ public new static bool TryParse(\r
+ byte[] sentence, out UnknownPacket packet)\r
{\r
packet = null;\r
if (sentence.Length < 8)\r
Raw = new byte[length];\r
Array.Copy(sentence, Raw, Raw.Length);\r
}\r
+\r
#endregion\r
\r
#region properties\r
get;\r
protected set;\r
}\r
+\r
#endregion\r
}\r
}\r
using NUnit.Framework;\r
using Yubeshi;\r
using Yubeshi.Nmea;\r
-using P = YubeshiTest.Nmea.SamplePackets;\r
+using P = YubeshiTest.NmeaTest.SamplePackets;\r
\r
-namespace YubeshiTest.Nmea\r
+namespace YubeshiTest.NmeaTest\r
{\r
\r
class PacketTest\r
public void GpDtmTest()\r
{\r
UnknownPacket packet;\r
- Assert.AreEqual(true, GpDtm.TryParse(P.GpDtm, out packet));\r
+ Assert.IsTrue(GpDtm.TryParse(P.GpDtm, out packet));\r
GpGga p = packet as GpGga;\r
}\r
\r
public void GpGgaTest()\r
{\r
UnknownPacket packet;\r
- Assert.AreEqual(true, GpGga.TryParse(P.GpGga, out packet));\r
+ Assert.IsTrue(GpGga.TryParse(P.GpGga, out packet));\r
GpGga p = packet as GpGga;\r
Assert.AreEqual(new TimeSpan(0, 9, 27, 25, 0), p.TimeOfFix);\r
Assert.AreEqual(2837.11399, p.Position.Latitude * 60.0);\r
using System.Text;\r
using NUnit.Framework;\r
using Yubeshi.Nmea;\r
-using P = YubeshiTest.Nmea.SamplePackets;\r
+using P = YubeshiTest.NmeaTest.SamplePackets;\r
\r
-namespace YubeshiTest.Nmea\r
+namespace YubeshiTest.NmeaTest\r
{\r
\r
class ParserTest\r
{ \r
Yubeshi.UnknownPacket p;\r
\r
- Assert.AreEqual(false, Parser.TryParse(P.Dummy, out p));\r
- Assert.AreEqual(null, p);\r
+ Assert.IsFalse(Parser.TryParse(P.Dummy, out p));\r
+ Assert.IsNull(p);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.GpDtm, out p));\r
- Assert.AreEqual(typeof(GpDtm), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.GpDtm, out p));\r
+ Assert.IsTrue(p is GpDtm);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.GpGga, out p));\r
- Assert.AreEqual(typeof(GpGga), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.GpGga, out p));\r
+ Assert.IsTrue(p is GpGga);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.GpGll, out p));\r
- Assert.AreEqual(typeof(GpGll), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.GpGll, out p));\r
+ Assert.IsTrue(p is GpGll);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.GpGrs, out p));\r
- Assert.AreEqual(typeof(GpGrs), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.GpGrs, out p));\r
+ Assert.IsTrue(p is GpGrs);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.GpGsa, out p));\r
- Assert.AreEqual(typeof(GpGsa), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.GpGsa, out p));\r
+ Assert.IsTrue(p is GpGsa);\r
}\r
\r
[Test]\r
using System.Collections.Generic;\r
using System.Text;\r
\r
-namespace YubeshiTest.Nmea\r
+namespace YubeshiTest.NmeaTest\r
{\r
public class SamplePackets\r
{\r
{\r
noise[i] = (byte)(i & 0x7F | 0x80);\r
}\r
- noise[52, -1] = Nmea.SamplePackets.Dummy;\r
- noise[79, -1] = Ubx.SamplePackets.Dummy;\r
+ noise[52, -1] = NmeaTest.SamplePackets.Dummy;\r
+ noise[79, -1] = UbxTest.SamplePackets.Dummy;\r
}\r
\r
[Test]\r
UnknownPacket p;\r
\r
OctetString data = noise;\r
- data += Nmea.SamplePackets.GpDtm;\r
- data += Ubx.SamplePackets.NavClock;\r
+ data += NmeaTest.SamplePackets.GpDtm;\r
+ data += UbxTest.SamplePackets.NavClock;\r
data += noise;\r
\r
parser.Push(data);\r
--- /dev/null
+/*\r
+ * Yubeshi GPS Parser\r
+ *\r
+ * This software is distributed under a zlib-style license.\r
+ * See license.txt for more information.\r
+ */\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using Yubeshi;\r
+using Yubeshi.Ubx;\r
+\r
+namespace YubeshiTest.UbxTest\r
+{\r
+ class MyPacket : Unknown\r
+ {\r
+ #region constructors\r
+\r
+ public MyPacket(byte[] sentence, int length)\r
+ : base(sentence, length)\r
+ {\r
+ ID = (MessageID)0xFFFF;\r
+ \r
+ Content =BitConverter.ToUInt32(sentence, 6 + 0);\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region properties\r
+ public uint Content\r
+ {\r
+ get;\r
+ set;\r
+ }\r
+ #endregion\r
+\r
+ #region public methods\r
+ public static bool TryParse(byte[] sentence, out UnknownPacket packet)\r
+ {\r
+ return TryParse(sentence, out packet, (MessageID)0xFFFF, 4, Build);\r
+ }\r
+ #endregion\r
+\r
+ #region private methods\r
+\r
+ private static Packet Build(byte[] sentence, int length)\r
+ {\r
+ return new MyPacket(sentence, length);\r
+ }\r
+ #endregion\r
+ }\r
+}\r
using NUnit.Framework;\r
using Yubeshi;\r
using Yubeshi.Ubx;\r
-using P = YubeshiTest.Ubx.SamplePackets;\r
+using P = YubeshiTest.UbxTest.SamplePackets;\r
\r
-namespace YubeshiTest.Ubx\r
+namespace YubeshiTest.UbxTest\r
{\r
\r
class NavPacketTest\r
public void NavClockTest()\r
{\r
UnknownPacket packet;\r
- Assert.AreEqual(true, NavClock.TryParse(P.NavClock, out packet));\r
+ Assert.IsTrue(NavClock.TryParse(P.NavClock, out packet));\r
NavClock p = packet as NavClock;\r
}\r
\r
public void NavPosEcefTest()\r
{\r
UnknownPacket p;\r
- Assert.AreEqual(true, NavPosEcef.TryParse(P.NavPosEcef, out p));\r
+ Assert.IsTrue(NavPosEcef.TryParse(P.NavPosEcef, out p));\r
}\r
\r
[Test]\r
public void NavSolTest()\r
{\r
UnknownPacket packet;\r
- Assert.AreEqual(true, NavSol.TryParse(P.NavSol, out packet));\r
+ Assert.IsTrue(NavSol.TryParse(P.NavSol, out packet));\r
NavSol p = packet as NavSol;\r
Assert.AreEqual(-3961181.33, p.Position.X);\r
Assert.AreEqual(3346187.67, p.Position.Y);\r
using System.Text;\r
using NUnit.Framework;\r
using Yubeshi.Ubx;\r
-using P = YubeshiTest.Ubx.SamplePackets;\r
+using P = YubeshiTest.UbxTest.SamplePackets;\r
\r
-namespace YubeshiTest.Ubx\r
+namespace YubeshiTest.UbxTest\r
{\r
\r
class ParserTest\r
{\r
Yubeshi.UnknownPacket p;\r
\r
- Assert.AreEqual(false, Parser.TryParse(P.Dummy, out p));\r
- Assert.AreEqual(null, p);\r
+ Assert.IsFalse(Parser.TryParse(P.Dummy, out p));\r
+ Assert.IsNull(p);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.NavClock, out p));\r
- Assert.AreEqual(typeof(NavClock), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.NavClock, out p));\r
+ Assert.IsTrue(p is NavClock);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.NavPosEcef, out p));\r
- Assert.AreEqual(typeof(NavPosEcef), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.NavPosEcef, out p));\r
+ Assert.IsTrue(p is NavPosEcef);\r
\r
- Assert.AreEqual(true, Parser.TryParse(P.NavSol, out p));\r
- Assert.AreEqual(typeof(NavSol), p.GetType());\r
+ Assert.IsTrue(Parser.TryParse(P.NavSol, out p));\r
+ Assert.IsTrue(p is NavSol);\r
\r
}\r
+\r
+ [Test]\r
+ public void AddParser()\r
+ {\r
+ Yubeshi.UnknownPacket p;\r
+\r
+ Assert.IsFalse(Parser.TryParse(P.UserDefined, out p));\r
+ Assert.IsNull(p);\r
+\r
+ Parser.AddParser((Packet.MessageID)0xFFFF, MyPacket.TryParse);\r
+\r
+ Assert.IsTrue(Parser.TryParse(P.UserDefined, out p));\r
+ Assert.IsTrue(p is MyPacket);\r
+ Assert.AreEqual(0x04030201, (p as MyPacket).Content);\r
+\r
+ Parser.RemoveParser((Packet.MessageID)0xFFFF);\r
+\r
+ Assert.IsFalse(Parser.TryParse(P.UserDefined, out p));\r
+ Assert.IsNull(p);\r
+ }\r
}\r
}\r
using System.Collections.Generic;\r
using System.Text;\r
\r
-namespace YubeshiTest.Ubx\r
+namespace YubeshiTest.UbxTest\r
{\r
public class SamplePackets\r
{\r
public static readonly byte[] Dummy;\r
+ public static readonly byte[] UserDefined;\r
+\r
public static readonly byte[] NavClock;\r
public static readonly byte[] NavPosEcef;\r
public static readonly byte[] NavSol;\r
0xFF, 0xFF\r
};\r
\r
+ UserDefined = new byte[] {\r
+ 0xB5, 0x62, 0xFF, 0xFF, 0x04, 0x00,\r
+ 0x01, 0x02, 0x03, 0x04, \r
+ 0xFF, 0xFF\r
+ };\r
+\r
NavClock = new byte[]{\r
0xB5, 0x62, 0x01, 0x22, 0x14, 0x00, \r
0x70, 0xAA, 0xB4, 0x12, \r
<Compile Include="NmeaTest\SamplePackets.cs" />\r
<Compile Include="ParserTest.cs" />\r
<Compile Include="Properties\AssemblyInfo.cs" />\r
+ <Compile Include="UbxTest\MyPacket.cs" />\r
<Compile Include="UbxTest\NavPacketTest.cs" />\r
<Compile Include="UbxTest\ParserTest.cs" />\r
<Compile Include="UbxTest\SamplePackets.cs" />\r