diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config index 67f8ea0..3343d68 100644 --- a/.nuget/NuGet.Config +++ b/.nuget/NuGet.Config @@ -1,4 +1,5 @@  + diff --git a/MaxMind.Db.Benchmark/MaxMind.Db.Benchmark.csproj b/MaxMind.Db.Benchmark/MaxMind.Db.Benchmark.csproj index 3c024ce..698601b 100644 --- a/MaxMind.Db.Benchmark/MaxMind.Db.Benchmark.csproj +++ b/MaxMind.Db.Benchmark/MaxMind.Db.Benchmark.csproj @@ -58,8 +58,8 @@ - False - ..\packages\Newtonsoft.Json.6.0.5\lib\net40\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.6.0.8\lib\net40\Newtonsoft.Json.dll + True diff --git a/MaxMind.Db.Benchmark/Program.cs b/MaxMind.Db.Benchmark/Program.cs index 95d8caf..87d92fa 100644 --- a/MaxMind.Db.Benchmark/Program.cs +++ b/MaxMind.Db.Benchmark/Program.cs @@ -1,29 +1,33 @@ -using System; +#region + +using System; using System.Net; +#endregion + namespace MaxMind.Db.Benchmark { - class Program + internal class Program { - static void Main(string[] args) + private static void Main(string[] args) { using (var reader = new Reader("GeoLite2-City.mmdb", FileAccessMode.MemoryMapped)) { var count = 100000; var rand = new Random(); var start = DateTime.Now; - for (int i = 0; i < count; i++) + for (var i = 0; i < count; i++) { var ip = new IPAddress(rand.Next(int.MaxValue)); - if (i % 50000 == 0) + if (i%50000 == 0) Console.WriteLine(i + " " + ip); var resp = reader.Find(ip); } var stop = DateTime.Now; - Console.WriteLine("Requests per second: " + count / (stop - start).TotalSeconds); + Console.WriteLine("Requests per second: " + count/(stop - start).TotalSeconds); } } } -} +} \ No newline at end of file diff --git a/MaxMind.Db.Benchmark/Properties/AssemblyInfo.cs b/MaxMind.Db.Benchmark/Properties/AssemblyInfo.cs index 033f40d..74c8989 100644 --- a/MaxMind.Db.Benchmark/Properties/AssemblyInfo.cs +++ b/MaxMind.Db.Benchmark/Properties/AssemblyInfo.cs @@ -1,10 +1,14 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +#region + +using System.Reflection; using System.Runtime.InteropServices; +#endregion + // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. + [assembly: AssemblyTitle("Test")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -17,9 +21,11 @@ // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. + [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM + [assembly: Guid("44f6ab62-9326-4383-9954-1357a8160621")] // Version information for an assembly consists of the following four values: @@ -32,5 +38,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] + [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/MaxMind.Db.Benchmark/packages.config b/MaxMind.Db.Benchmark/packages.config index 3d97f00..d6d4ee5 100644 --- a/MaxMind.Db.Benchmark/packages.config +++ b/MaxMind.Db.Benchmark/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/MaxMind.Db.Test/DecoderTest.cs b/MaxMind.Db.Test/DecoderTest.cs index 8e3d2b2..69123d4 100644 --- a/MaxMind.Db.Test/DecoderTest.cs +++ b/MaxMind.Db.Test/DecoderTest.cs @@ -1,4 +1,6 @@ -using System; +#region + +using System; using System.Collections.Generic; using System.IO; using System.Numerics; @@ -7,6 +9,8 @@ using Newtonsoft.Json.Linq; using NUnit.Framework; +#endregion + namespace MaxMind.Db.Test { [TestFixture] @@ -15,13 +19,15 @@ public class DecoderTest [Test] public void TestUInt16() { - var uint16s = new Dictionary(); + var uint16s = new Dictionary + { + {0, new byte[] {0xa0}}, + {(1 << 8) - 1, new[] {(byte) 0xa1, (byte) 0xff}}, + {500, new byte[] {0xa2, 0x1, 0xf4}}, + {10872, new byte[] {0xa2, 0x2a, 0x78}}, + {ushort.MaxValue, new[] {(byte) 0xa2, (byte) 0xff, (byte) 0xff}} + }; - uint16s.Add(0, new byte[] { (byte)0xa0 }); - uint16s.Add((1 << 8) - 1, new byte[] { (byte)0xa1, (byte)0xff }); - uint16s.Add(500, new byte[] { (byte)0xa2, 0x1, (byte)0xf4 }); - uint16s.Add(10872, new byte[] { (byte)0xa2, 0x2a, 0x78 }); - uint16s.Add(UInt16.MaxValue, new byte[] { (byte)0xa2, (byte)0xff, (byte)0xff }); TestTypeDecoding(uint16s); } @@ -29,15 +35,17 @@ public void TestUInt16() [Test] public void TestUInt32() { - var uint32s = new Dictionary(); + var uint32s = new Dictionary + { + {0, new[] {(byte) 0xc0}}, + {(1 << 8) - 1, new[] {(byte) 0xc1, (byte) 0xff}}, + {500, new byte[] {0xc2, 0x1, 0xf4}}, + {10872, new byte[] {0xc2, 0x2a, 0x78}}, + {(1 << 16) - 1, new[] {(byte) 0xc2, (byte) 0xff, (byte) 0xff}}, + {(1 << 24) - 1, new[] {(byte) 0xc3, (byte) 0xff, (byte) 0xff, (byte) 0xff}}, + {uint.MaxValue, new[] {(byte) 0xc4, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}} + }; - uint32s.Add((long)0, new byte[] { (byte)0xc0 }); - uint32s.Add((long)((1 << 8) - 1), new byte[] { (byte)0xc1, (byte)0xff }); - uint32s.Add((long)500, new byte[] { (byte)0xc2, 0x1, (byte)0xf4 }); - uint32s.Add((long)10872, new byte[] { (byte)0xc2, 0x2a, 0x78 }); - uint32s.Add((long)((1 << 16) - 1), new byte[] { (byte)0xc2, (byte)0xff, (byte)0xff }); - uint32s.Add((long)((1 << 24) - 1), new byte[] { (byte)0xc3, (byte)0xff, (byte)0xff, (byte)0xff }); - uint32s.Add(UInt32.MaxValue, new byte[] { (byte)0xc4, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }); TestTypeDecoding(uint32s); } @@ -45,20 +53,22 @@ public void TestUInt32() [Test] public void TestInt32s() { - var int32s = new Dictionary(); - - int32s.Add(0, new byte[] { 0x0, 0x1 }); - int32s.Add(-1, new byte[] { 0x4, 0x1, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }); - int32s.Add((2 << 7) - 1, new byte[] { 0x1, 0x1, (byte)0xff }); - int32s.Add(1 - (2 << 7), new byte[] { 0x4, 0x1, (byte)0xff, (byte)0xff, (byte)0xff, 0x1 }); - int32s.Add(500, new byte[] { 0x2, 0x1, 0x1, (byte)0xf4 }); - int32s.Add(-500, new byte[] { 0x4, 0x1, (byte)0xff, (byte)0xff, (byte)0xfe, 0xc }); - int32s.Add((2 << 15) - 1, new byte[] { 0x2, 0x1, (byte)0xff, (byte)0xff }); - int32s.Add(1 - (2 << 15), new byte[] { 0x4, 0x1, (byte)0xff, (byte)0xff, 0x0, 0x1 }); - int32s.Add((2 << 23) - 1, new byte[] { 0x3, 0x1, (byte)0xff, (byte)0xff, (byte)0xff }); - int32s.Add(1 - (2 << 23), new byte[] { 0x4, 0x1, (byte)0xff, 0x0, 0x0, 0x1 }); - int32s.Add(int.MaxValue, new byte[] { 0x4, 0x1, 0x7f, (byte)0xff, (byte)0xff, (byte)0xff }); - int32s.Add(-int.MaxValue, new byte[] { 0x4, 0x1, (byte)0x80, 0x0, 0x0, 0x1 }); + var int32s = new Dictionary + { + {0, new byte[] {0x0, 0x1}}, + {-1, new byte[] {0x4, 0x1, 0xff, 0xff, 0xff, 0xff}}, + {(2 << 7) - 1, new byte[] {0x1, 0x1, 0xff}}, + {1 - (2 << 7), new byte[] {0x4, 0x1, 0xff, 0xff, 0xff, 0x1}}, + {500, new byte[] {0x2, 0x1, 0x1, 0xf4}}, + {-500, new byte[] {0x4, 0x1, 0xff, 0xff, 0xfe, 0xc}}, + {(2 << 15) - 1, new byte[] {0x2, 0x1, 0xff, 0xff}}, + {1 - (2 << 15), new byte[] {0x4, 0x1, 0xff, 0xff, 0x0, 0x1}}, + {(2 << 23) - 1, new byte[] {0x3, 0x1, 0xff, 0xff, 0xff}}, + {1 - (2 << 23), new byte[] {0x4, 0x1, 0xff, 0x0, 0x0, 0x1}}, + {int.MaxValue, new byte[] {0x4, 0x1, 0x7f, 0xff, 0xff, 0xff}}, + {-int.MaxValue, new byte[] {0x4, 0x1, 0x80, 0x0, 0x0, 0x1}} + }; + TestTypeDecoding(int32s); } @@ -66,22 +76,24 @@ public void TestInt32s() [Test] public void TestInt64s() { - var int64s = new Dictionary(); + var int64s = new Dictionary + { + {0L, new byte[] {0x0, 0x2}}, + {500L, new byte[] {0x2, 0x2, 0x1, 0xf4}}, + {10872, new byte[] {0x2, 0x2, 0x2a, 0x78}} + }; - int64s.Add(0L, new byte[] { 0x0, 0x2 }); - int64s.Add(500L, new byte[] { 0x2, 0x2, 0x1, 0xf4 }); - int64s.Add(10872, new byte[] { 0x2, 0x2, 0x2a, 0x78 }); - for (int power = 1; power < 8; power++) + for (var power = 1; power < 8; power++) { - var key = Int64Pow(2, 8 * power) - 1; + var key = Int64Pow(2, 8*power) - 1; var value = new byte[2 + power]; - value[0] = (byte)power; + value[0] = (byte) power; value[1] = 0x2; - for (int i = 2; i < value.Length; i++) + for (var i = 2; i < value.Length; i++) { - value[i] = (byte)0xff; + value[i] = 0xff; } int64s.Add(key, value); @@ -90,7 +102,7 @@ public void TestInt64s() TestTypeDecoding(int64s); } - static long Int64Pow(long x, int pow) + private static long Int64Pow(long x, int pow) { long ret = 1; while (pow != 0) @@ -106,21 +118,23 @@ static long Int64Pow(long x, int pow) [Test] public void TestBigIntegers() { - var bigInts = new Dictionary(); - bigInts.Add(new BigInteger(0), new byte[] { 0x0, 0x3 }); - bigInts.Add(new BigInteger(500), new byte[] { 0x2, 0x3, 0x1, 0xf4 }); - bigInts.Add(new BigInteger(10872), new byte[] { 0x2, 0x3, 0x2a, 0x78 }); + var bigInts = new Dictionary + { + {new BigInteger(0), new byte[] {0x0, 0x3}}, + {new BigInteger(500), new byte[] {0x2, 0x3, 0x1, 0xf4}}, + {new BigInteger(10872), new byte[] {0x2, 0x3, 0x2a, 0x78}} + }; - for (int power = 1; power <= 16; power++) + for (var power = 1; power <= 16; power++) { - var key = BigInteger.Pow(new BigInteger(2), 8 * power) - 1; + var key = BigInteger.Pow(new BigInteger(2), 8*power) - 1; var value = new byte[2 + power]; - value[0] = (byte)power; + value[0] = (byte) power; value[1] = 0x3; - for (int i = 2; i < value.Length; i++) + for (var i = 2; i < value.Length; i++) { - value[i] = (byte)0xff; + value[i] = 0xff; } bigInts.Add(key, value); @@ -132,15 +146,17 @@ public void TestBigIntegers() [Test] public void TestDoubles() { - var doubles = new Dictionary(); - doubles.Add(0.0, new byte[] { 0x68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }); - doubles.Add(0.5, new byte[] { 0x68, 0x3F, (byte)0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }); - doubles.Add(3.14159265359, new byte[] { 0x68, 0x40, 0x9, 0x21, (byte)0xFB, 0x54, 0x44, 0x2E, (byte)0xEA }); - doubles.Add(123.0, new byte[] { 0x68, 0x40, 0x5E, (byte)0xC0, 0x0, 0x0, 0x0, 0x0, 0x0 }); - doubles.Add(1073741824.12457, new byte[] { 0x68, 0x41, (byte)0xD0, 0x0, 0x0, 0x0, 0x7, (byte)0xF8, (byte)0xF4 }); - doubles.Add(-0.5, new byte[] { 0x68, (byte)0xBF, (byte)0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }); - doubles.Add(-3.14159265359, new byte[] { 0x68, (byte)0xC0, 0x9, 0x21, (byte)0xFB, 0x54, 0x44, 0x2E, (byte)0xEA }); - doubles.Add(-1073741824.12457, new byte[] { 0x68, (byte)0xC1, (byte)0xD0, 0x0, 0x0, 0x0, 0x7, (byte)0xF8, (byte)0xF4 }); + var doubles = new Dictionary + { + {0.0, new byte[] {0x68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, + {0.5, new byte[] {0x68, 0x3F, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, + {3.14159265359, new byte[] {0x68, 0x40, 0x9, 0x21, 0xFB, 0x54, 0x44, 0x2E, 0xEA}}, + {123.0, new byte[] {0x68, 0x40, 0x5E, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0}}, + {1073741824.12457, new byte[] {0x68, 0x41, 0xD0, 0x0, 0x0, 0x0, 0x7, 0xF8, 0xF4}}, + {-0.5, new byte[] {0x68, 0xBF, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, + {-3.14159265359, new byte[] {0x68, 0xC0, 0x9, 0x21, 0xFB, 0x54, 0x44, 0x2E, 0xEA}}, + {-1073741824.12457, new byte[] {0x68, 0xC1, 0xD0, 0x0, 0x0, 0x0, 0x7, 0xF8, 0xF4}} + }; TestTypeDecoding(doubles); } @@ -148,16 +164,18 @@ public void TestDoubles() [Test] public void TestFloats() { - var floats = new Dictionary(); - floats.Add((float)0.0, new byte[] { 0x4, 0x8, 0x0, 0x0, 0x0, 0x0 }); - floats.Add((float)1.0, new byte[] { 0x4, 0x8, 0x3F, (byte)0x80, 0x0, 0x0 }); - floats.Add((float)1.1, new byte[] { 0x4, 0x8, 0x3F, (byte)0x8C, (byte)0xCC, (byte)0xCD }); - floats.Add((float)3.14, new byte[] { 0x4, 0x8, 0x40, 0x48, (byte)0xF5, (byte)0xC3 }); - floats.Add((float)9999.99, new byte[] { 0x4, 0x8, 0x46, 0x1C, 0x3F, (byte)0xF6 }); - floats.Add((float)-1.0, new byte[] { 0x4, 0x8, (byte)0xBF, (byte)0x80, 0x0, 0x0 }); - floats.Add((float)-1.1, new byte[] { 0x4, 0x8, (byte)0xBF, (byte)0x8C, (byte)0xCC, (byte)0xCD }); - floats.Add((float)-3.14, new byte[] { 0x4, 0x8, (byte)0xC0, 0x48, (byte)0xF5, (byte)0xC3 }); - floats.Add((float)-9999.99, new byte[] { 0x4, 0x8, (byte)0xC6, 0x1C, 0x3F, (byte)0xF6 }); + var floats = new Dictionary + { + {(float) 0.0, new byte[] {0x4, 0x8, 0x0, 0x0, 0x0, 0x0}}, + {(float) 1.0, new byte[] {0x4, 0x8, 0x3F, 0x80, 0x0, 0x0}}, + {(float) 1.1, new byte[] {0x4, 0x8, 0x3F, 0x8C, 0xCC, 0xCD}}, + {(float) 3.14, new byte[] {0x4, 0x8, 0x40, 0x48, 0xF5, 0xC3}}, + {(float) 9999.99, new byte[] {0x4, 0x8, 0x46, 0x1C, 0x3F, 0xF6}}, + {(float) -1.0, new byte[] {0x4, 0x8, 0xBF, 0x80, 0x0, 0x0}}, + {(float) -1.1, new byte[] {0x4, 0x8, 0xBF, 0x8C, 0xCC, 0xCD}}, + {(float) -3.14, new byte[] {0x4, 0x8, 0xC0, 0x48, 0xF5, 0xC3}}, + {(float) -9999.99, new byte[] {0x4, 0x8, 0xC6, 0x1C, 0x3F, 0xF6}} + }; TestTypeDecoding(floats); } @@ -165,18 +183,20 @@ public void TestFloats() [Test] public void TestPointers() { - var pointers = new Dictionary(); - - pointers.Add((long)0, new byte[] { 0x20, 0x0 }); - pointers.Add((long)5, new byte[] { 0x20, 0x5 }); - pointers.Add((long)10, new byte[] { 0x20, 0xa }); - pointers.Add((long)((1 << 10) - 1), new byte[] { 0x23, (byte)0xff, }); - pointers.Add((long)3017, new byte[] { 0x28, 0x3, (byte)0xc9 }); - pointers.Add((long)((1 << 19) - 5), new byte[] { 0x2f, (byte)0xf7, (byte)0xfb }); - pointers.Add((long)((1 << 19) + (1 << 11) - 1), new byte[] { 0x2f, (byte)0xff, (byte)0xff }); - pointers.Add((long)((1 << 27) - 2), new byte[] { 0x37, (byte)0xf7, (byte)0xf7, (byte)0xfe }); - pointers.Add((((long)1) << 27) + (1 << 19) + (1 << 11) - 1, new byte[] { 0x37, (byte)0xff, (byte)0xff, (byte)0xff }); - pointers.Add((((long)1) << 31) - 1, new byte[] { 0x38, (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff }); + var pointers = new Dictionary + { + {0, new byte[] {0x20, 0x0}}, + {5, new byte[] {0x20, 0x5}}, + {10, new byte[] {0x20, 0xa}}, + {(1 << 10) - 1, new byte[] {0x23, 0xff}}, + {3017, new byte[] {0x28, 0x3, 0xc9}}, + {(1 << 19) - 5, new byte[] {0x2f, 0xf7, 0xfb}}, + {(1 << 19) + (1 << 11) - 1, new byte[] {0x2f, 0xff, 0xff}}, + {(1 << 27) - 2, new byte[] {0x37, 0xf7, 0xf7, 0xfe}}, + {(((long) 1) << 27) + (1 << 19) + (1 << 11) - 1, new byte[] {0x37, 0xff, 0xff, 0xff}}, + {(((long) 1) << 31) - 1, new byte[] {0x38, 0x7f, 0xff, 0xff, 0xff}} + }; + TestTypeDecoding(pointers); } @@ -191,24 +211,24 @@ private static Dictionary Strings() { var strings = new Dictionary(); - AddTestString(strings, (byte)0x40, ""); - AddTestString(strings, (byte)0x41, "1"); - AddTestString(strings, (byte)0x43, "人"); - AddTestString(strings, (byte)0x43, "123"); - AddTestString(strings, (byte)0x5b, "123456789012345678901234567"); - AddTestString(strings, (byte)0x5c, "1234567890123456789012345678"); - AddTestString(strings, new byte[] { 0x5d, 0x0 }, "12345678901234567890123456789"); - AddTestString(strings, new byte[] { 0x5d, 0x1 }, "123456789012345678901234567890"); - - AddTestString(strings, new byte[] { 0x5e, 0x0, (byte)0xd7 }, new string('x', 500)); - AddTestString(strings, new byte[] { 0x5e, 0x6, (byte)0xb3 }, new string('x', 2000)); - AddTestString(strings, new byte[] { 0x5f, 0x0, 0x10, 0x53, }, new string('x', 70000)); + AddTestString(strings, 0x40, ""); + AddTestString(strings, 0x41, "1"); + AddTestString(strings, 0x43, "人"); + AddTestString(strings, 0x43, "123"); + AddTestString(strings, 0x5b, "123456789012345678901234567"); + AddTestString(strings, 0x5c, "1234567890123456789012345678"); + AddTestString(strings, new byte[] {0x5d, 0x0}, "12345678901234567890123456789"); + AddTestString(strings, new byte[] {0x5d, 0x1}, "123456789012345678901234567890"); + + AddTestString(strings, new byte[] {0x5e, 0x0, 0xd7}, new string('x', 500)); + AddTestString(strings, new byte[] {0x5e, 0x6, 0xb3}, new string('x', 2000)); + AddTestString(strings, new byte[] {0x5f, 0x0, 0x10, 0x53}, new string('x', 70000)); return strings; } private static void AddTestString(Dictionary tests, byte ctrl, string str) { - AddTestString(tests, new byte[] { ctrl }, str); + AddTestString(tests, new[] {ctrl}, str); } private static void AddTestString(Dictionary tests, byte[] ctrl, string str) @@ -224,10 +244,8 @@ private static void AddTestString(Dictionary tests, byte[] ctrl, [Test] public void TestBooleans() { - var booleans = new Dictionary(); + var booleans = new Dictionary {{false, new byte[] {0x0, 0x7}}, {true, new byte[] {0x1, 0x7}}}; - booleans.Add(false, new byte[] { 0x0, 0x7 }); - booleans.Add(true, new byte[] { 0x1, 0x7 }); TestTypeDecoding(booleans); } @@ -239,9 +257,9 @@ public void TestBytes() var strings = Strings(); - foreach (string s in strings.Keys) + foreach (var s in strings.Keys) { - byte[] ba = strings[s]; + var ba = strings[s]; ba[0] ^= 0xc0; bytes.Add(Encoding.UTF8.GetBytes(s), ba); @@ -256,52 +274,60 @@ public void TestMaps() var maps = new Dictionary(); var empty = new JObject(); - maps.Add(empty, new byte[] { (byte)0xe0 }); + maps.Add(empty, new[] {(byte) 0xe0}); - var one = new JObject(); - one.Add("en", "Foo"); - maps.Add(one, new byte[] { (byte) 0xe1, /* en */0x42, 0x65, 0x6e, - /* Foo */0x43, 0x46, 0x6f, 0x6f }); + var one = new JObject {{"en", "Foo"}}; + maps.Add(one, new byte[] + { + 0xe1, /* en */0x42, 0x65, 0x6e, + /* Foo */0x43, 0x46, 0x6f, 0x6f + }); var two = new JObject(); two.Add("en", "Foo"); two.Add("zh", "人"); - maps.Add(two, new byte[] { (byte) 0xe2, - /* en */ - 0x42, 0x65, 0x6e, - /* Foo */ - 0x43, 0x46, 0x6f, 0x6f, - /* zh */ - 0x42, 0x7a, 0x68, - /* 人 */ - 0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba }); - - var nested = new JObject(); - nested.Add("name", two); - - maps.Add(nested, new byte[] { (byte) 0xe1, /* name */ - 0x44, 0x6e, 0x61, 0x6d, 0x65, (byte) 0xe2,/* en */ - 0x42, 0x65, 0x6e, - /* Foo */ - 0x43, 0x46, 0x6f, 0x6f, - /* zh */ - 0x42, 0x7a, 0x68, - /* 人 */ - 0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba }); + maps.Add(two, new byte[] + { + 0xe2, + /* en */ + 0x42, 0x65, 0x6e, + /* Foo */ + 0x43, 0x46, 0x6f, 0x6f, + /* zh */ + 0x42, 0x7a, 0x68, + /* 人 */ + 0x43, 0xe4, 0xba, 0xba + }); + + var nested = new JObject {{"name", two}}; + + maps.Add(nested, new byte[] + { + 0xe1, /* name */ + 0x44, 0x6e, 0x61, 0x6d, 0x65, 0xe2, /* en */ + 0x42, 0x65, 0x6e, + /* Foo */ + 0x43, 0x46, 0x6f, 0x6f, + /* zh */ + 0x42, 0x7a, 0x68, + /* 人 */ + 0x43, 0xe4, 0xba, 0xba + }); var guess = new JObject(); - var languages = new JArray(); - languages.Add("en"); - languages.Add("zh"); + var languages = new JArray {"en", "zh"}; guess.Add("languages", languages); - maps.Add(guess, new byte[] { (byte) 0xe1,/* languages */ - 0x49, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, - /* array */ - 0x2, 0x4, - /* en */ - 0x42, 0x65, 0x6e, - /* zh */ - 0x42, 0x7a, 0x68 }); + maps.Add(guess, new byte[] + { + 0xe1, /* languages */ + 0x49, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, + /* array */ + 0x2, 0x4, + /* en */ + 0x42, 0x65, 0x6e, + /* zh */ + 0x42, 0x7a, 0x68 + }); TestTypeDecoding(maps); } @@ -311,38 +337,40 @@ public void TestArrays() { var arrays = new Dictionary(); - var f1 = new JArray(); - f1.Add("Foo"); - arrays.Add(f1, new byte[] { 0x1, 0x4, - /* Foo */ - 0x43, 0x46, 0x6f, 0x6f }); - - var f2 = new JArray(); - f2.Add("Foo"); - f2.Add("人"); - arrays.Add(f2, new byte[] { 0x2, 0x4, - /* Foo */ - 0x43, 0x46, 0x6f, 0x6f, - /* 人 */ - 0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba }); + var f1 = new JArray {"Foo"}; + arrays.Add(f1, new byte[] + { + 0x1, 0x4, + /* Foo */ + 0x43, 0x46, 0x6f, 0x6f + }); + + var f2 = new JArray {"Foo", "人"}; + arrays.Add(f2, new byte[] + { + 0x2, 0x4, + /* Foo */ + 0x43, 0x46, 0x6f, 0x6f, + /* 人 */ + 0x43, 0xe4, 0xba, 0xba + }); var empty = new JArray(); - arrays.Add(empty, new byte[] { 0x0, 0x4 }); + arrays.Add(empty, new byte[] {0x0, 0x4}); TestTypeDecoding(arrays); } private static void TestTypeDecoding(Dictionary tests) { - foreach (KeyValuePair entry in tests) + foreach (var entry in tests) { var expect = entry.Key; var input = entry.Value; using (var stream = new ThreadLocal(() => new MemoryStream(input))) { - var decoder = new Decoder(stream, 0); - decoder.PointerTestHack = true; + var decoder = new Decoder(stream, 0) {PointerTestHack = true}; var jToken = decoder.Decode(0).Node; if (jToken is JRaw) diff --git a/MaxMind.Db.Test/MaxMind.Db.Test.csproj b/MaxMind.Db.Test/MaxMind.Db.Test.csproj index aea6110..90b48ce 100644 --- a/MaxMind.Db.Test/MaxMind.Db.Test.csproj +++ b/MaxMind.Db.Test/MaxMind.Db.Test.csproj @@ -34,8 +34,8 @@ - False ..\packages\Newtonsoft.Json.6.0.8\lib\net40\Newtonsoft.Json.dll + True False diff --git a/MaxMind.Db.Test/PointerTest.cs b/MaxMind.Db.Test/PointerTest.cs index 9aa733e..64d4385 100644 --- a/MaxMind.Db.Test/PointerTest.cs +++ b/MaxMind.Db.Test/PointerTest.cs @@ -1,17 +1,20 @@ -using System.Threading; +#region + +using System.IO; +using System.Threading; +using NUnit.Framework; + +#endregion namespace MaxMind.Db.Test { - using System.IO; - using NUnit.Framework; - [TestFixture] public class PointerTest { [Test] public void TestWithPointers() { - var path = Path.Combine(new[] { "..", "..", "TestData", "MaxMind-DB", "test-data", "maps-with-pointers.raw" }); + var path = Path.Combine("..", "..", "TestData", "MaxMind-DB", "test-data", "maps-with-pointers.raw"); var stream = new ThreadLocal(() => new MemoryStream(File.ReadAllBytes(path))); using (stream) { @@ -37,4 +40,4 @@ public void TestWithPointers() } } } -} +} \ No newline at end of file diff --git a/MaxMind.Db.Test/Properties/AssemblyInfo.cs b/MaxMind.Db.Test/Properties/AssemblyInfo.cs index 0bccff4..c73a368 100644 --- a/MaxMind.Db.Test/Properties/AssemblyInfo.cs +++ b/MaxMind.Db.Test/Properties/AssemblyInfo.cs @@ -1,10 +1,14 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +#region + +using System.Reflection; using System.Runtime.InteropServices; +#endregion + // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. + [assembly: AssemblyTitle("MaxMind.MaxMindDb.Test")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -17,9 +21,11 @@ // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. + [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM + [assembly: Guid("cac31299-2158-48e9-919f-993468e3f87e")] // Version information for an assembly consists of the following four values: @@ -32,5 +38,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] + [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/MaxMind.Db.Test/ReaderTest.cs b/MaxMind.Db.Test/ReaderTest.cs index 19eccad..d6d768b 100644 --- a/MaxMind.Db.Test/ReaderTest.cs +++ b/MaxMind.Db.Test/ReaderTest.cs @@ -1,14 +1,17 @@ -using System; +#region + +using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Numerics; +using Newtonsoft.Json.Linq; +using NUnit.Framework; + +#endregion namespace MaxMind.Db.Test { - using System.Linq; - using Newtonsoft.Json.Linq; - using NUnit.Framework; - [TestFixture] public class ReaderTest { @@ -17,9 +20,9 @@ public class ReaderTest [Test] public void Test() { - foreach (var recordSize in new long[] { 24, 28, 32 }) + foreach (var recordSize in new long[] {24, 28, 32}) { - foreach (var ipVersion in new[] { 4, 6 }) + foreach (var ipVersion in new[] {4, 6}) { var file = Path.Combine(TestDataRoot, "MaxMind-DB-test-ipv" + ipVersion + "-" + recordSize + ".mmdb"); var reader = new Reader(file); @@ -43,12 +46,12 @@ public void Test() [Test] public void TestStream() { - foreach (var recordSize in new long[] { 24, 28, 32 }) + foreach (var recordSize in new long[] {24, 28, 32}) { - foreach (var ipVersion in new[] { 4, 6 }) + foreach (var ipVersion in new[] {4, 6}) { var file = Path.Combine(TestDataRoot, "MaxMind-DB-test-ipv" + ipVersion + "-" + recordSize + ".mmdb"); - using (StreamReader streamReader = new StreamReader(file)) + using (var streamReader = new StreamReader(file)) { using (var reader = new Reader(streamReader.BaseStream)) { @@ -69,7 +72,8 @@ public void TestStream() } [Test] - [ExpectedException(typeof(InvalidDatabaseException), ExpectedMessage = "zero bytes left in the stream", MatchType = MessageMatch.Contains)] + [ExpectedException(typeof (InvalidDatabaseException), ExpectedMessage = "zero bytes left in the stream", + MatchType = MessageMatch.Contains)] public void TestEmptyStream() { using (var stream = new MemoryStream()) @@ -93,12 +97,11 @@ public void TestDecodingTypes() { using (var reader = new Reader(Path.Combine(TestDataRoot, "MaxMind-DB-test-decoder.mmdb"))) { - var record = reader.Find("::1.1.1.0"); Assert.That(record.Value("boolean"), Is.True); - Assert.That(record.Value("bytes"), Is.EquivalentTo(new byte[] { 0, 0, 0, 42 })); + Assert.That(record.Value("bytes"), Is.EquivalentTo(new byte[] {0, 0, 0, 42})); Assert.That(record.Value("utf8_string"), Is.EqualTo("unicode! ☯ - ♫")); @@ -129,7 +132,7 @@ public void TestDecodingTypes() Assert.That(record.Value("int32"), Is.EqualTo(-268435456)); Assert.That(record.Value("uint16"), Is.EqualTo(100)); Assert.That(record.Value("uint32"), Is.EqualTo(268435456)); - Assert.That(record.Value("uint64"), Is.EqualTo(1152921504606846976)); + Assert.That(record.Value("uint64"), Is.EqualTo(1152921504606846976)); Assert.That(record["uint128"].ToObject(), Is.EqualTo(BigInteger.Parse("1329227995784915872903807060280344576"))); } @@ -157,15 +160,16 @@ public void TestZeros() Assert.AreEqual(0, record.Value("double"), 0.000000001); Assert.AreEqual(0, record.Value("float"), 0.000001); Assert.That(record.Value("int32"), Is.EqualTo(0)); - Assert.That(record.Value("uint16"), Is.EqualTo(0)); - Assert.That(record.Value("uint32"), Is.EqualTo(0)); - Assert.That(record.Value("uint64"), Is.EqualTo(0)); + Assert.That(record.Value("uint16"), Is.EqualTo(0)); + Assert.That(record.Value("uint32"), Is.EqualTo(0)); + Assert.That(record.Value("uint64"), Is.EqualTo(0)); Assert.That(record["uint128"].ToObject(), Is.EqualTo(new BigInteger(0))); } } [Test] - [ExpectedException(typeof(InvalidDatabaseException), ExpectedMessage = "contains bad data", MatchType = MessageMatch.Contains)] + [ExpectedException(typeof (InvalidDatabaseException), ExpectedMessage = "contains bad data", + MatchType = MessageMatch.Contains)] public void TestBrokenDatabase() { using (var reader = new Reader(Path.Combine(TestDataRoot, "GeoIP2-City-Test-Broken-Double-Format.mmdb"))) @@ -175,7 +179,8 @@ public void TestBrokenDatabase() } [Test] - [ExpectedException(typeof(InvalidDatabaseException), ExpectedMessage = "search tree is corrupt", MatchType = MessageMatch.Contains)] + [ExpectedException(typeof (InvalidDatabaseException), ExpectedMessage = "search tree is corrupt", + MatchType = MessageMatch.Contains)] public void TestBrokenSearchTreePointer() { using (var reader = new Reader(Path.Combine(TestDataRoot, "MaxMind-DB-test-broken-pointers-24.mmdb"))) @@ -185,7 +190,8 @@ public void TestBrokenSearchTreePointer() } [Test] - [ExpectedException(typeof(InvalidDatabaseException), ExpectedMessage = "data section contains bad data", MatchType = MessageMatch.Contains)] + [ExpectedException(typeof (InvalidDatabaseException), ExpectedMessage = "data section contains bad data", + MatchType = MessageMatch.Contains)] public void TestBrokenDataPointer() { using (var reader = new Reader(Path.Combine(TestDataRoot, "MaxMind-DB-test-broken-pointers-24.mmdb"))) @@ -198,56 +204,59 @@ private void TestIPV6(Reader reader, string file) { TestAddresses(reader, file, - new[] { "::1:ffff:ffff", "::2:0:0", "::2:0:40", "::2:0:50", "::2:0:58" }, + new[] {"::1:ffff:ffff", "::2:0:0", "::2:0:40", "::2:0:50", "::2:0:58"}, new Dictionary - { - {"::2:0:1", "::2:0:0"}, - {"::2:0:33", "::2:0:0"}, - {"::2:0:39", "::2:0:0"}, - {"::2:0:41", "::2:0:40"}, - {"::2:0:49", "::2:0:40"}, - {"::2:0:52", "::2:0:50"}, - {"::2:0:57", "::2:0:50"}, - {"::2:0:59", "::2:0:58"} - }, - new[] { "1.1.1.33", "255.254.253.123", "89fa::" } + { + {"::2:0:1", "::2:0:0"}, + {"::2:0:33", "::2:0:0"}, + {"::2:0:39", "::2:0:0"}, + {"::2:0:41", "::2:0:40"}, + {"::2:0:49", "::2:0:40"}, + {"::2:0:52", "::2:0:50"}, + {"::2:0:57", "::2:0:50"}, + {"::2:0:59", "::2:0:58"} + }, + new[] {"1.1.1.33", "255.254.253.123", "89fa::"} ); - } private void TestIPV4(Reader reader, string file) { TestAddresses(reader, file, - Enumerable.Range(0, 5).Select(i => "1.1.1." + (int)Math.Pow(2, 1)), + Enumerable.Range(0, 5).Select(i => "1.1.1." + (int) Math.Pow(2, 1)), new Dictionary { - {"1.1.1.3", "1.1.1.2"}, - {"1.1.1.5", "1.1.1.4"}, - {"1.1.1.7", "1.1.1.4"}, - {"1.1.1.9", "1.1.1.8"}, - {"1.1.1.15", "1.1.1.8"}, - {"1.1.1.17", "1.1.1.16"}, - {"1.1.1.31", "1.1.1.16"} - }, - new[] { "1.1.1.33", "255.254.253.123" }); + {"1.1.1.3", "1.1.1.2"}, + {"1.1.1.5", "1.1.1.4"}, + {"1.1.1.7", "1.1.1.4"}, + {"1.1.1.9", "1.1.1.8"}, + {"1.1.1.15", "1.1.1.8"}, + {"1.1.1.17", "1.1.1.16"}, + {"1.1.1.31", "1.1.1.16"} + }, + new[] {"1.1.1.33", "255.254.253.123"}); } - private void TestAddresses(Reader reader, string file, IEnumerable singleAddresses, Dictionary pairs, IEnumerable nullAddresses) + private void TestAddresses(Reader reader, string file, IEnumerable singleAddresses, + Dictionary pairs, IEnumerable nullAddresses) { foreach (var address in singleAddresses) { - Assert.That(reader.Find(address).Value("ip"), Is.EqualTo(address), string.Format("Did not find expected data record for {0} in {1}", address, file)); + Assert.That(reader.Find(address).Value("ip"), Is.EqualTo(address), + string.Format("Did not find expected data record for {0} in {1}", address, file)); } foreach (var address in pairs.Keys) { - Assert.That(reader.Find(address).Value("ip"), Is.EqualTo(pairs[address]), string.Format("Did not find expected data record for {0} in {1}", address, file)); + Assert.That(reader.Find(address).Value("ip"), Is.EqualTo(pairs[address]), + string.Format("Did not find expected data record for {0} in {1}", address, file)); } foreach (var address in nullAddresses) { - Assert.That(reader.Find(address), Is.Null, string.Format("Did not find expected data record for {0} in {1}", address, file)); + Assert.That(reader.Find(address), Is.Null, + string.Format("Did not find expected data record for {0} in {1}", address, file)); } } @@ -265,4 +274,4 @@ private void TestMetadata(Reader reader, int ipVersion) Assert.That(metadata.Description["zh"], Is.EqualTo("Test Database Chinese")); } } -} +} \ No newline at end of file diff --git a/MaxMind.Db.Test/ThreadingTest.cs b/MaxMind.Db.Test/ThreadingTest.cs index 2ebb709..792ebe9 100644 --- a/MaxMind.Db.Test/ThreadingTest.cs +++ b/MaxMind.Db.Test/ThreadingTest.cs @@ -1,10 +1,14 @@ -using System; +#region + +using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Threading.Tasks; using NUnit.Framework; -using System.IO; + +#endregion namespace MaxMind.Db.Test { @@ -33,7 +37,6 @@ public void TestParallelFor(FileAccessMode mode) } var ips = ipsAndResults.Keys.ToArray(); - var start = DateTime.Now; Parallel.For(0, ips.Length, i => { var ipAddress = ips[i]; @@ -41,9 +44,9 @@ public void TestParallelFor(FileAccessMode mode) var resultString = result.ToString(); var expectedString = ipsAndResults[ipAddress]; if (resultString != expectedString) - throw new Exception(string.Format("Non-matching result. Expected {0}, found {1}", expectedString, resultString)); + throw new Exception(string.Format("Non-matching result. Expected {0}, found {1}", expectedString, + resultString)); }); - var stop = DateTime.Now; } } diff --git a/MaxMind.Db.Test/packages.config b/MaxMind.Db.Test/packages.config index 7955881..e7522a4 100644 --- a/MaxMind.Db.Test/packages.config +++ b/MaxMind.Db.Test/packages.config @@ -1,5 +1,5 @@  - - + + \ No newline at end of file diff --git a/MaxMind.Db/Decoder.cs b/MaxMind.Db/Decoder.cs index 8f10219..8988cdc 100644 --- a/MaxMind.Db/Decoder.cs +++ b/MaxMind.Db/Decoder.cs @@ -1,37 +1,57 @@ -using System; +#region + +using System; using System.IO; +using System.Linq; using System.Numerics; using System.Text; using System.Threading; using Newtonsoft.Json.Linq; +#endregion + namespace MaxMind.Db { /// - /// Enumeration representing the types of objects read from the database + /// Enumeration representing the types of objects read from the database /// internal enum ObjectType { - Extended, Pointer, Utf8String, Double, Bytes, Uint16, Uint32, Map, Int32, Uint64, Uint128, Array, Container, EndMarker, Boolean, Float + Extended, + Pointer, + Utf8String, + Double, + Bytes, + Uint16, + Uint32, + Map, + Int32, + Uint64, + Uint128, + Array, + Container, + EndMarker, + Boolean, + Float } /// - /// A data structure to store an object read from the database + /// A data structure to store an object read from the database /// internal class Result { /// - /// The object read from the database + /// The object read from the database /// internal JToken Node { get; set; } /// - /// The offset + /// The offset /// internal int Offset { get; set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The node. /// The offset. @@ -43,21 +63,20 @@ internal Result(JToken node, int offset) } /// - /// Given a stream, this class decodes the object graph at a particular location + /// Given a stream, this class decodes the object graph at a particular location /// internal class Decoder { - private readonly ThreadLocal _stream; - private readonly int _pointerBase = -1; + private readonly int _pointerBase; - private readonly int[] _pointerValueOffset = { 0, 0, 1 << 11, (1 << 19) + ((1) << 11), 0 }; + private readonly int[] _pointerValueOffset = {0, 0, 1 << 11, (1 << 19) + ((1) << 11), 0}; internal bool PointerTestHack { get; set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The stream. /// The base address in the stream. @@ -68,7 +87,7 @@ internal Decoder(ThreadLocal stream, int pointerBase) } /// - /// Decodes the object at the specified offset. + /// Decodes the object at the specified offset. /// /// The offset. /// An object containing the data read from the stream @@ -76,9 +95,9 @@ internal Result Decode(int offset) { if (offset >= _stream.Value.Length) throw new InvalidDatabaseException("The MaxMind DB file's data section contains bad data: " - + "pointer larger than the database."); + + "pointer larger than the database."); - byte ctrlByte = ReadOne(offset); + var ctrlByte = ReadOne(offset); offset++; var type = FromControlByte(ctrlByte); @@ -98,36 +117,36 @@ internal Result Decode(int offset) if (type == ObjectType.Extended) { int nextByte = ReadOne(offset); - int typeNum = nextByte + 7; + var typeNum = nextByte + 7; if (typeNum < 8) throw new InvalidDatabaseException( - "Something went horribly wrong in the decoder. An extended type " - + "resolved to a type number < 8 (" + typeNum - + ")"); - type = (ObjectType)typeNum; + "Something went horribly wrong in the decoder. An extended type " + + "resolved to a type number < 8 (" + typeNum + + ")"); + type = (ObjectType) typeNum; offset++; } - int[] sizeArray = SizeFromCtrlByte(ctrlByte, offset); - int size = sizeArray[0]; + var sizeArray = SizeFromCtrlByte(ctrlByte, offset); + var size = sizeArray[0]; offset = sizeArray[1]; return DecodeByType(type, offset, size); } /// - /// Reads the one. + /// Reads the one. /// /// The position. /// private byte ReadOne(int position) { _stream.Value.Seek(position, SeekOrigin.Begin); - return (byte)_stream.Value.ReadByte(); + return (byte) _stream.Value.ReadByte(); } /// - /// Reads the many. + /// Reads the many. /// /// The position. /// The size. @@ -141,7 +160,7 @@ private byte[] ReadMany(int position, int size) } /// - /// Decodes the type of the by. + /// Decodes the type of the by. /// /// The type. /// The offset. @@ -150,8 +169,8 @@ private byte[] ReadMany(int position, int size) /// Unable to handle type! private Result DecodeByType(ObjectType type, int offset, int size) { - int newOffset = offset + size; - byte[] buffer = ReadMany(offset, size); + var newOffset = offset + size; + var buffer = ReadMany(offset, size); switch (type) { @@ -185,51 +204,51 @@ private Result DecodeByType(ObjectType type, int offset, int size) } /// - /// Froms the control byte. + /// Froms the control byte. /// /// The attribute. /// private ObjectType FromControlByte(byte b) { - int p = b >> 5; - return (ObjectType)p; + var p = b >> 5; + return (ObjectType) p; } /// - /// Sizes from control byte. + /// Sizes from control byte. /// /// The control byte. /// The offset. /// private int[] SizeFromCtrlByte(byte ctrlByte, int offset) { - int size = ctrlByte & 0x1f; - int bytesToRead = size < 29 ? 0 : size - 28; + var size = ctrlByte & 0x1f; + var bytesToRead = size < 29 ? 0 : size - 28; if (size == 29) { - byte[] buffer = ReadMany(offset, bytesToRead); - int i = DecodeInteger(buffer); + var buffer = ReadMany(offset, bytesToRead); + var i = DecodeInteger(buffer); size = 29 + i; } else if (size == 30) { - byte[] buffer = ReadMany(offset, bytesToRead); - int i = DecodeInteger(buffer); + var buffer = ReadMany(offset, bytesToRead); + var i = DecodeInteger(buffer); size = 285 + i; } else if (size > 30) { - byte[] buffer = ReadMany(offset, bytesToRead); - int i = DecodeInteger(buffer) & (0x0FFFFFFF >> (32 - (8 * bytesToRead))); + var buffer = ReadMany(offset, bytesToRead); + var i = DecodeInteger(buffer) & (0x0FFFFFFF >> (32 - (8*bytesToRead))); size = 65821 + i; } - return new[] { size, offset + bytesToRead }; + return new[] {size, offset + bytesToRead}; } /// - /// Decodes the boolean. + /// Decodes the boolean. /// /// The size of the structure. /// @@ -243,12 +262,12 @@ private JValue DecodeBoolean(int size) return new JValue(true); default: throw new InvalidDatabaseException("The MaxMind DB file's data section contains bad data: " - + "invalid size of boolean."); + + "invalid size of boolean."); } } /// - /// Decodes the double. + /// Decodes the double. /// /// The buffer. /// @@ -263,7 +282,7 @@ private JValue DecodeDouble(byte[] buffer) } /// - /// Decodes the float. + /// Decodes the float. /// /// The buffer. /// @@ -271,13 +290,13 @@ private JValue DecodeFloat(byte[] buffer) { if (buffer.Length != 4) throw new InvalidDatabaseException("The MaxMind DB file's data section contains bad data: " - + "invalid size of float."); + + "invalid size of float."); Array.Reverse(buffer); return new JValue(BitConverter.ToSingle(buffer, 0)); } /// - /// Decodes the string. + /// Decodes the string. /// /// The buffer. /// @@ -287,7 +306,7 @@ private JValue DecodeString(byte[] buffer) } /// - /// Decodes the map. + /// Decodes the map. /// /// The size. /// The offset. @@ -296,12 +315,12 @@ private Result DecodeMap(int size, int offset) { var obj = new JObject(); - for (int i = 0; i < size; i++) + for (var i = 0; i < size; i++) { - Result left = Decode(offset); + var left = Decode(offset); var key = left.Node; offset = left.Offset; - Result right = Decode(offset); + var right = Decode(offset); var value = right.Node; offset = right.Offset; obj.Add(key.Value(), value); @@ -311,22 +330,18 @@ private Result DecodeMap(int size, int offset) } /// - /// Decodes the long. + /// Decodes the long. /// /// The buffer. /// private JValue DecodeLong(byte[] buffer) { - long integer = 0; - for (int i = 0; i < buffer.Length; i++) - { - integer = (integer << 8) | buffer[i]; - } + long integer = buffer.Aggregate(0, (current, t) => (current << 8) | t); return new JValue(integer); } /// - /// Decodes the integer. + /// Decodes the integer. /// /// The buffer. /// @@ -336,7 +351,7 @@ private JValue DecodeIntegerToJValue(byte[] buffer) } /// - /// Decodes the array. + /// Decodes the array. /// /// The size. /// The offset. @@ -345,7 +360,7 @@ private Result DecodeArray(int size, int offset) { var array = new JArray(); - for (int i = 0; i < size; i++) + for (var i = 0; i < size; i++) { var r = Decode(offset); offset = r.Offset; @@ -356,22 +371,18 @@ private Result DecodeArray(int size, int offset) } /// - /// Decodes the uint64. + /// Decodes the uint64. /// /// The buffer. /// private JValue DecodeUInt64(byte[] buffer) { - UInt64 integer = 0; - for (int i = 0; i < buffer.Length; i++) - { - integer = (integer << 8) | buffer[i]; - } + ulong integer = buffer.Aggregate(0, (current, t) => (current << 8) | t); return new JValue(integer); } /// - /// Decodes the big integer. + /// Decodes the big integer. /// /// The buffer. /// @@ -380,14 +391,14 @@ private JToken DecodeBigInteger(byte[] buffer) Array.Reverse(buffer); //Pad with a 0 in case we're on a byte boundary - Array.Resize(ref buffer, buffer.Length+1); + Array.Resize(ref buffer, buffer.Length + 1); buffer[buffer.Length - 1] = 0x0; return new JValue(new BigInteger(buffer)); } /// - /// Decodes the pointer. + /// Decodes the pointer. /// /// The control byte. /// The offset. @@ -395,16 +406,16 @@ private JToken DecodeBigInteger(byte[] buffer) /// private int DecodePointer(int ctrlByte, int offset, out int outOffset) { - int pointerSize = ((ctrlByte >> 3) & 0x3) + 1; - int b = pointerSize == 4 ? 0 : ctrlByte & 0x7; - byte[] buffer = ReadMany(offset, pointerSize); - int packed = DecodeInteger(b, buffer); + var pointerSize = ((ctrlByte >> 3) & 0x3) + 1; + var b = pointerSize == 4 ? 0 : ctrlByte & 0x7; + var buffer = ReadMany(offset, pointerSize); + var packed = DecodeInteger(b, buffer); outOffset = offset + pointerSize; return packed + _pointerBase + _pointerValueOffset[pointerSize]; } /// - /// Decodes the integer. + /// Decodes the integer. /// /// The buffer. /// @@ -414,19 +425,14 @@ internal static int DecodeInteger(byte[] buffer) } /// - /// Decodes the integer. + /// Decodes the integer. /// /// The base value. /// The buffer. /// internal static int DecodeInteger(int baseValue, byte[] buffer) { - int integer = baseValue; - for (int i = 0; i < buffer.Length; i++) - { - integer = (integer << 8) | buffer[i]; - } - return integer; + return buffer.Aggregate(baseValue, (current, t) => (current << 8) | t); } } } \ No newline at end of file diff --git a/MaxMind.Db/InvalidDatabaseException.cs b/MaxMind.Db/InvalidDatabaseException.cs index ed2efe3..5de2709 100644 --- a/MaxMind.Db/InvalidDatabaseException.cs +++ b/MaxMind.Db/InvalidDatabaseException.cs @@ -1,31 +1,37 @@ -using System; +#region + +using System; + +#endregion namespace MaxMind.Db { /// - /// Thrown when the MaxMind database file is incorrectly formatted + /// Thrown when the MaxMind database file is incorrectly formatted /// public class InvalidDatabaseException : ApplicationException { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// A message that describes the error. public InvalidDatabaseException(string message) : base(message) { - } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception. If the parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception. + /// + /// The exception that is the cause of the current exception. If the + /// parameter is not a null reference, the current exception is raised in a catch + /// block that handles the inner exception. + /// public InvalidDatabaseException(string message, Exception innerException) : base(message, innerException) { - } } } \ No newline at end of file diff --git a/MaxMind.Db/MaxMind.Db.csproj b/MaxMind.Db/MaxMind.Db.csproj index 8acb0b5..e9781db 100644 --- a/MaxMind.Db/MaxMind.Db.csproj +++ b/MaxMind.Db/MaxMind.Db.csproj @@ -73,8 +73,8 @@ - False ..\packages\Newtonsoft.Json.6.0.8\lib\net40\Newtonsoft.Json.dll + True diff --git a/MaxMind.Db/Metadata.cs b/MaxMind.Db/Metadata.cs index c6fbbf8..3b3c0dc 100644 --- a/MaxMind.Db/Metadata.cs +++ b/MaxMind.Db/Metadata.cs @@ -1,24 +1,28 @@ -using System; +#region + +using System; using System.Collections; using System.Collections.Generic; using Newtonsoft.Json; +#endregion + namespace MaxMind.Db { /// - /// Data about the database file itself + /// Data about the database file itself /// [JsonObject(MemberSerialization.OptIn)] public class Metadata { /// - /// The major version number for the MaxMind DB binary format used by the database. + /// The major version number for the MaxMind DB binary format used by the database. /// [JsonProperty("binary_format_major_version")] public int BinaryFormatMajorVersion { get; private set; } /// - /// The minor version number for the MaxMind DB binary format used by the database. + /// The minor version number for the MaxMind DB binary format used by the database. /// [JsonProperty("binary_format_minor_version")] public int BinaryFormatMinorVersion { get; private set; } @@ -27,37 +31,34 @@ public class Metadata internal long BuildEpoch { get; private set; } /// - /// The date-time of the database build. + /// The date-time of the database build. /// [JsonIgnore] public DateTime BuildDate { - get - { - return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(BuildEpoch); - } + get { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(BuildEpoch); } } /// - /// The MaxMind DB database type. + /// The MaxMind DB database type. /// [JsonProperty("database_type")] public string DatabaseType { get; private set; } /// - /// A map from locale codes to the database description in that language. + /// A map from locale codes to the database description in that language. /// [JsonProperty("description")] public Hashtable Description { get; private set; } /// - /// The IP version that the database supports. This will be 4 or 6. + /// The IP version that the database supports. This will be 4 or 6. /// [JsonProperty("ip_version")] public int IPVersion { get; private set; } /// - /// A list of locale codes for languages that the database supports. + /// A list of locale codes for languages that the database supports. /// [JsonProperty("languages")] public List Languages { get; private set; } @@ -71,18 +72,12 @@ public DateTime BuildDate [JsonIgnore] internal int NodeByteSize { - get - { - return RecordSize / 4; - } + get { return RecordSize/4; } } internal int SearchTreeSize { - get - { - return NodeCount * this.NodeByteSize; - } + get { return NodeCount*NodeByteSize; } } } -} +} \ No newline at end of file diff --git a/MaxMind.Db/Properties/AssemblyInfo.cs b/MaxMind.Db/Properties/AssemblyInfo.cs index e637bca..e5dc559 100644 --- a/MaxMind.Db/Properties/AssemblyInfo.cs +++ b/MaxMind.Db/Properties/AssemblyInfo.cs @@ -1,10 +1,15 @@ -using System.Reflection; +#region + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +#endregion + // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. + [assembly: AssemblyTitle("MaxMind.Db")] [assembly: AssemblyDescription(".NET reader for the MaxMind DB file format")] [assembly: AssemblyConfiguration("")] @@ -17,9 +22,11 @@ // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. + [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM + [assembly: Guid("044a98c5-0d88-4273-a769-ef4c72cf1bd9")] // Version information for an assembly consists of the following four values: @@ -32,6 +39,7 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] + [assembly: AssemblyVersion("1.0.0")] [assembly: AssemblyFileVersion("1.0.0")] -[assembly: InternalsVisibleTo("MaxMind.Db.Test")] +[assembly: InternalsVisibleTo("MaxMind.Db.Test")] \ No newline at end of file diff --git a/MaxMind.Db/Reader.cs b/MaxMind.Db/Reader.cs index 94755d9..2148cd3 100644 --- a/MaxMind.Db/Reader.cs +++ b/MaxMind.Db/Reader.cs @@ -1,4 +1,6 @@ -using System; +#region + +using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Linq; @@ -7,39 +9,46 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; +#endregion + namespace MaxMind.Db { /// - /// An enumeration specifying the API to use to read the database + /// An enumeration specifying the API to use to read the database /// public enum FileAccessMode { /// - /// Open the file in memory mapped mode. Does not load into real memory. + /// Open the file in memory mapped mode. Does not load into real memory. /// MemoryMapped, + /// - /// Load the file into memory. + /// Load the file into memory. /// Memory } /// - /// Given a MaxMind DB file, this class will retrieve information about an IP address + /// Given a MaxMind DB file, this class will retrieve information about an IP address /// public class Reader : IDisposable { /// - /// The metadata for the open database. + /// The metadata for the open database. /// /// - /// The metadata. + /// The metadata. /// public Metadata Metadata { get; private set; } private const int DataSectionSeparatorSize = 16; - private readonly byte[] _metadataStartMarker = { 0xAB, 0xCD, 0xEF, 77, 97, 120, 77, 105, 110, 100, 46, 99, 111, 109 }; + private readonly byte[] _metadataStartMarker = + { + 0xAB, 0xCD, 0xEF, 77, 97, 120, 77, 105, 110, 100, 46, 99, 111, + 109 + }; private readonly string _fileName; @@ -47,7 +56,8 @@ public class Reader : IDisposable private readonly MemoryMappedFile _memoryMappedFile; - private int _ipV4Start = 0; + private int _ipV4Start; + private int IPv4Start { get @@ -56,8 +66,8 @@ private int IPv4Start { return _ipV4Start; } - int node = 0; - for (int i = 0; i < 96 && node < Metadata.NodeCount; i++) + var node = 0; + for (var i = 0; i < 96 && node < Metadata.NodeCount; i++) { node = ReadNode(node, 0); } @@ -66,7 +76,7 @@ private int IPv4Start } } - private static readonly Object FileLocker = new Object(); + private static readonly object FileLocker = new object(); private readonly ThreadLocal _stream; @@ -74,13 +84,15 @@ private int IPv4Start /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The file. - public Reader(string file) : this(file, FileAccessMode.MemoryMapped) { } + public Reader(string file) : this(file, FileAccessMode.MemoryMapped) + { + } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The MaxMind DB file. /// The mode by which to access the DB file. @@ -112,14 +124,14 @@ public Reader(string file, FileAccessMode mode) if (mode == FileAccessMode.Memory) { - byte[] fileBytes = File.ReadAllBytes(_fileName); + var fileBytes = File.ReadAllBytes(_fileName); _stream = new ThreadLocal(() => new MemoryStream(fileBytes, false)); } else { _stream = new ThreadLocal(() => { - var fileLength = (int)new FileInfo(file).Length; + var fileLength = (int) new FileInfo(file).Length; return _memoryMappedFile.CreateViewStream(0, fileLength, MemoryMappedFileAccess.Read); }); } @@ -128,12 +140,12 @@ public Reader(string file, FileAccessMode mode) } /// - /// Initialize with Stream. + /// Initialize with Stream. /// /// The stream to use. It will be used from its current position. public Reader(Stream stream) { - byte[] fileBytes = null; + byte[] fileBytes; using (var memoryStream = new MemoryStream()) { @@ -143,7 +155,8 @@ public Reader(Stream stream) if (fileBytes.Length == 0) { - throw new InvalidDatabaseException("There are zero bytes left in the stream. Perhaps you need to reset the stream's position."); + throw new InvalidDatabaseException( + "There are zero bytes left in the stream. Perhaps you need to reset the stream's position."); } _stream = new ThreadLocal(() => new MemoryStream(fileBytes, false)); @@ -160,7 +173,7 @@ private void InitMetaData() } /// - /// Finds the data related to the specified address. + /// Finds the data related to the specified address. /// /// The IP address. /// An object containing the IP related data @@ -170,7 +183,7 @@ public JToken Find(string ipAddress) } /// - /// Finds the data related to the specified address. + /// Finds the data related to the specified address. /// /// The IP address. /// An object containing the IP related data @@ -187,8 +200,8 @@ private JToken ResolveDataPointer(int pointer) if (resolved >= _stream.Value.Length) { throw new InvalidDatabaseException( - "The MaxMind Db file's search tree is corrupt: " - + "contains pointer larger than the database."); + "The MaxMind Db file's search tree is corrupt: " + + "contains pointer larger than the database."); } return Decoder.Decode(resolved).Node; @@ -196,19 +209,19 @@ private JToken ResolveDataPointer(int pointer) private int FindAddressInTree(IPAddress address) { - byte[] rawAddress = address.GetAddressBytes(); + var rawAddress = address.GetAddressBytes(); - int bitLength = rawAddress.Length * 8; - int record = StartNode(bitLength); + var bitLength = rawAddress.Length*8; + var record = StartNode(bitLength); - for (int i = 0; i < bitLength; i++) + for (var i = 0; i < bitLength; i++) { if (record >= Metadata.NodeCount) { break; } - byte b = rawAddress[i / 8]; - int bit = 1 & (b >> 7 - (i % 8)); + var b = rawAddress[i/8]; + var bit = 1 & (b >> 7 - (i%8)); record = ReadNode(record, bit); } if (record == Metadata.NodeCount) @@ -216,7 +229,7 @@ record = ReadNode(record, bit); // record is empty return 0; } - else if (record > Metadata.NodeCount) + if (record > Metadata.NodeCount) { // record is a data pointer return record; @@ -245,10 +258,10 @@ private T Deserialize(JToken value) private int FindMetadataStart() { - _fileSize = (int)_stream.Value.Length; + _fileSize = (int) _stream.Value.Length; var buffer = new byte[_metadataStartMarker.Length]; - for (int i = (_fileSize - _metadataStartMarker.Length); i > 0; i--) + for (var i = (_fileSize - _metadataStartMarker.Length); i > 0; i--) { _stream.Value.Seek(i, SeekOrigin.Begin); _stream.Value.Read(buffer, 0, buffer.Length); @@ -260,13 +273,13 @@ private int FindMetadataStart() } throw new InvalidDatabaseException( - "Could not find a MaxMind Db metadata marker in this file (" - + _fileName + "). Is this a valid MaxMind Db file?"); + "Could not find a MaxMind Db metadata marker in this file (" + + _fileName + "). Is this a valid MaxMind Db file?"); } private int ReadNode(int nodeNumber, int index) { - var baseOffset = nodeNumber * Metadata.NodeByteSize; + var baseOffset = nodeNumber*Metadata.NodeByteSize; var size = Metadata.RecordSize; @@ -274,32 +287,32 @@ private int ReadNode(int nodeNumber, int index) { case 24: { - byte[] buffer = ReadMany(baseOffset + index * 3, 3); + var buffer = ReadMany(baseOffset + index*3, 3); return Decoder.DecodeInteger(buffer); } case 28: { - byte middle = ReadOne(baseOffset + 3); - middle = (index == 0) ? (byte)(middle >> 4) : (byte)(0x0F & middle); + var middle = ReadOne(baseOffset + 3); + middle = (index == 0) ? (byte) (middle >> 4) : (byte) (0x0F & middle); - byte[] buffer = ReadMany(baseOffset + index * 4, 3); + var buffer = ReadMany(baseOffset + index*4, 3); return Decoder.DecodeInteger(middle, buffer); } case 32: { - byte[] buffer = ReadMany(baseOffset + index * 4, 4); + var buffer = ReadMany(baseOffset + index*4, 4); return Decoder.DecodeInteger(buffer); } } throw new InvalidDatabaseException("Unknown record size: " - + size); + + size); } private byte ReadOne(int position) { _stream.Value.Seek(position, SeekOrigin.Begin); - return (byte)_stream.Value.ReadByte(); + return (byte) _stream.Value.ReadByte(); } private byte[] ReadMany(int position, int size) @@ -311,7 +324,7 @@ private byte[] ReadMany(int position, int size) } /// - /// Release resources back to the system. + /// Release resources back to the system. /// public void Dispose() { @@ -320,4 +333,4 @@ public void Dispose() _memoryMappedFile.Dispose(); } } -} +} \ No newline at end of file diff --git a/MaxMind.Db/packages.config b/MaxMind.Db/packages.config index c4dd611..d6d4ee5 100644 --- a/MaxMind.Db/packages.config +++ b/MaxMind.Db/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/releasenotes.md b/releasenotes.md index a3d8f62..e9b6335 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,5 +1,12 @@ # Release Nodes # +## 1.0.1 (2015-05-08) ## + +* Improved the exception thrown when the constructor for `Reader` is called + with an empty stream. +* Updated Newtonsoft.Json dependency to 6.0.8. +* Minor code cleanup. + ## 1.0.0 (2014-09-29) ## * First production release.