X Tutup
// NpgsqlTypes.NpgsqlTypesHelper.cs // // Author: // Glen Parker // // Copyright (C) 2004 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose, without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph and the following two paragraphs appear in all copies. // // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. // This file provides implementations of PostgreSQL specific data types that cannot // be mapped to standard .NET classes. using System; using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.NetworkInformation; using Npgsql; // Keep the xml comment warning quiet for this file. #pragma warning disable 1591 namespace NpgsqlTypes { /// /// Represents a PostgreSQL Point type /// public struct NpgsqlPoint : IEquatable { private Single _x; private Single _y; public NpgsqlPoint(Single x, Single y) { _x = x; _y = y; } public Single X { get { return _x; } set { _x = value; } } public Single Y { get { return _y; } set { _y = value; } } public bool Equals(NpgsqlPoint other) { return X == other.X && Y == other.Y; } public override bool Equals(object obj) { return obj != null && obj is NpgsqlPoint && Equals((NpgsqlPoint) obj); } public static bool operator ==(NpgsqlPoint x, NpgsqlPoint y) { return x.Equals(y); } public static bool operator !=(NpgsqlPoint x, NpgsqlPoint y) { return !(x == y); } public override int GetHashCode() { return X.GetHashCode() ^ PGUtil.RotateShift(Y.GetHashCode(), sizeof (int)/2); } } public struct NpgsqlBox : IEquatable { private NpgsqlPoint _upperRight; private NpgsqlPoint _lowerLeft; public NpgsqlBox(NpgsqlPoint upperRight, NpgsqlPoint lowerLeft) { _upperRight = upperRight; _lowerLeft = lowerLeft; } public NpgsqlBox(float Top, float Right, float Bottom, float Left) : this(new NpgsqlPoint(Right, Top), new NpgsqlPoint(Left, Bottom)) { } public NpgsqlPoint UpperRight { get { return _upperRight; } set { _upperRight = value; } } public NpgsqlPoint LowerLeft { get { return _lowerLeft; } set { _lowerLeft = value; } } public float Left { get { return LowerLeft.X; } } public float Right { get { return UpperRight.X; } } public float Bottom { get { return LowerLeft.Y; } } public float Top { get { return UpperRight.Y; } } public float Width { get { return Right - Left; } } public float Height { get { return Top - Bottom; } } public bool IsEmpty { get { return Width == 0 || Height == 0; } } public bool Equals(NpgsqlBox other) { return UpperRight == other.UpperRight && LowerLeft == other.LowerLeft; } public override bool Equals(object obj) { return obj != null && obj is NpgsqlBox && Equals((NpgsqlBox) obj); } public static bool operator ==(NpgsqlBox x, NpgsqlBox y) { return x.Equals(y); } public static bool operator !=(NpgsqlBox x, NpgsqlBox y) { return !(x == y); } public override int GetHashCode() { return Top.GetHashCode() ^ PGUtil.RotateShift(Right.GetHashCode(), sizeof (int)/4) ^ PGUtil.RotateShift(Bottom.GetHashCode(), sizeof (int)/2) ^ PGUtil.RotateShift(LowerLeft.GetHashCode(), sizeof (int)*3/4); } } /// /// Represents a PostgreSQL Line Segment type. /// public struct NpgsqlLSeg : IEquatable { public NpgsqlPoint Start; public NpgsqlPoint End; public NpgsqlLSeg(NpgsqlPoint start, NpgsqlPoint end) { Start = start; End = end; } public override String ToString() { return String.Format("({0}, {1})", Start, End); } public override int GetHashCode() { return Start.X.GetHashCode() ^ PGUtil.RotateShift(Start.Y.GetHashCode(), sizeof (int)/4) ^ PGUtil.RotateShift(End.X.GetHashCode(), sizeof (int)/2) ^ PGUtil.RotateShift(End.Y.GetHashCode(), sizeof (int)*3/4); } public bool Equals(NpgsqlLSeg other) { return Start == other.Start && End == other.End; } public override bool Equals(object obj) { return obj != null && obj is NpgsqlLSeg && Equals((NpgsqlLSeg) obj); } public static bool operator ==(NpgsqlLSeg x, NpgsqlLSeg y) { return x.Equals(y); } public static bool operator !=(NpgsqlLSeg x, NpgsqlLSeg y) { return !(x == y); } } /// /// Represents a PostgreSQL Path type. /// public struct NpgsqlPath : IList, IEquatable { private bool _open; private readonly List _points; public NpgsqlPath(IEnumerable points, bool open) { _points = new List(points); _open = open; } public NpgsqlPath(IEnumerable points) : this(points, false) { } public NpgsqlPath(NpgsqlPoint[] points) : this((IEnumerable)points, false) { } public NpgsqlPath(bool open) { _points = new List(); _open = open; } public NpgsqlPath(int capacity, bool open) { _points = new List(capacity); _open = open; } public NpgsqlPath(int capacity) : this(capacity, false) { } public bool Open { get { return _open; } set { _open = value; } } public NpgsqlPoint this[int index] { get { return _points[index]; } set { _points[index] = value; } } public int Count { get { return _points.Count; } } public bool IsReadOnly { get { return false; } } public int IndexOf(NpgsqlPoint item) { return _points.IndexOf(item); } public void Insert(int index, NpgsqlPoint item) { _points.Insert(index, item); } public void RemoveAt(int index) { _points.RemoveAt(index); } public void Add(NpgsqlPoint item) { _points.Add(item); } public void Clear() { _points.Clear(); } public bool Contains(NpgsqlPoint item) { return _points.Contains(item); } public void CopyTo(NpgsqlPoint[] array, int arrayIndex) { _points.CopyTo(array, arrayIndex); } public bool Remove(NpgsqlPoint item) { return _points.Remove(item); } public IEnumerator GetEnumerator() { return _points.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Equals(NpgsqlPath other) { if (Open != other.Open || Count != other.Count) return false; else if(ReferenceEquals(_points, other._points))//Short cut for shallow copies. return true; for (int i = 0; i != Count; ++i) { if (this[i] != other[i]) { return false; } } return true; } public override bool Equals(object obj) { return obj != null && obj is NpgsqlPath && Equals((NpgsqlPath) obj); } public static bool operator ==(NpgsqlPath x, NpgsqlPath y) { return x.Equals(y); } public static bool operator !=(NpgsqlPath x, NpgsqlPath y) { return !(x == y); } public override int GetHashCode() { int ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently. foreach (NpgsqlPoint point in this) { //The ideal amount to shift each value is one that would evenly spread it throughout //the resultant bytes. Using the current result % 32 is essentially using a random value //but one that will be the same on subsequent calls. ret ^= PGUtil.RotateShift(point.GetHashCode(), ret%sizeof (int)); } return Open ? ret : -ret; } } /// /// Represents a PostgreSQL Polygon type. /// public struct NpgsqlPolygon : IList, IEquatable { private readonly List _points; public NpgsqlPolygon(IEnumerable points) { _points = new List(points); } public NpgsqlPolygon(NpgsqlPoint[] points) : this ((IEnumerable) points) { } public NpgsqlPoint this[int index] { get { return _points[index]; } set { _points[index] = value; } } public int Count { get { return _points.Count; } } public bool IsReadOnly { get { return false; } } public int IndexOf(NpgsqlPoint item) { return _points.IndexOf(item); } public void Insert(int index, NpgsqlPoint item) { _points.Insert(index, item); } public void RemoveAt(int index) { _points.RemoveAt(index); } public void Add(NpgsqlPoint item) { _points.Add(item); } public void Clear() { _points.Clear(); } public bool Contains(NpgsqlPoint item) { return _points.Contains(item); } public void CopyTo(NpgsqlPoint[] array, int arrayIndex) { _points.CopyTo(array, arrayIndex); } public bool Remove(NpgsqlPoint item) { return _points.Remove(item); } public IEnumerator GetEnumerator() { return _points.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Equals(NpgsqlPolygon other) { if (Count != other.Count) return false; else if(ReferenceEquals(_points, _points))//Shortcut for copies of each other. return true; for (int i = 0; i != Count; ++i) { if (this[i] != other[i]) { return false; } } return true; } public override bool Equals(object obj) { return obj is NpgsqlPolygon && Equals((NpgsqlPolygon) obj); } public static bool operator ==(NpgsqlPolygon x, NpgsqlPolygon y) { return x.Equals(y); } public static bool operator !=(NpgsqlPolygon x, NpgsqlPolygon y) { return !(x == y); } public override int GetHashCode() { int ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently. foreach (NpgsqlPoint point in this) { //The ideal amount to shift each value is one that would evenly spread it throughout //the resultant bytes. Using the current result % 32 is essentially using a random value //but one that will be the same on subsequent calls. ret ^= PGUtil.RotateShift(point.GetHashCode(), ret%sizeof (int)); } return ret; } } /// /// Represents a PostgreSQL Circle type. /// public struct NpgsqlCircle : IEquatable { public NpgsqlPoint Center; public Double Radius; public NpgsqlCircle(NpgsqlPoint center, Double radius) { Center = center; Radius = radius; } public bool Equals(NpgsqlCircle other) { return Center == other.Center && Radius == other.Radius; } public override bool Equals(object obj) { return obj is NpgsqlCircle && Equals((NpgsqlCircle) obj); } public override String ToString() { return string.Format("({0}), {1}", Center, Radius); } public static bool operator ==(NpgsqlCircle x, NpgsqlCircle y) { return x.Equals(y); } public static bool operator !=(NpgsqlCircle x, NpgsqlCircle y) { return !(x == y); } public override int GetHashCode() { return Center.X.GetHashCode() ^ PGUtil.RotateShift(Center.Y.GetHashCode(), sizeof (int)/4) ^ PGUtil.RotateShift(Radius.GetHashCode(), sizeof (int)/2); } } /// /// Represents a PostgreSQL inet type. /// public struct NpgsqlInet : IEquatable { public IPAddress addr; public int mask; public NpgsqlInet(IPAddress addr, int mask) { this.addr = addr; this.mask = mask; } public NpgsqlInet(IPAddress addr) { this.addr = addr; this.mask = 32; } public NpgsqlInet(string addr) { if (addr.IndexOf('/') > 0) { string[] addrbits = addr.Split('/'); if (addrbits.GetUpperBound(0) != 1) { throw new FormatException("Invalid number of parts in CIDR specification"); } this.addr = IPAddress.Parse(addrbits[0]); this.mask = int.Parse(addrbits[1]); } else { this.addr = IPAddress.Parse(addr); this.mask = 32; } } public override String ToString() { if (mask != 32) { return string.Format("{0}/{1}", addr, mask); } return addr.ToString(); } public static explicit operator IPAddress(NpgsqlInet x) { if (x.mask != 32) { throw new InvalidCastException("Cannot cast CIDR network to address"); } return x.addr; } public static implicit operator NpgsqlInet(IPAddress ipaddress) { return new NpgsqlInet(ipaddress); } public bool Equals(NpgsqlInet other) { return addr.Equals(other.addr) && mask == other.mask; } public override bool Equals(object obj) { return obj != null && obj is NpgsqlInet && Equals((NpgsqlInet) obj); } public override int GetHashCode() { return PGUtil.RotateShift(addr.GetHashCode(), mask%32); } public static bool operator ==(NpgsqlInet x, NpgsqlInet y) { return x.Equals(y); } public static bool operator !=(NpgsqlInet x, NpgsqlInet y) { return !(x == y); } } /// /// Represents a PostgreSQL MacAddress type. /// public struct NpgsqlMacAddress : IEquatable { public PhysicalAddress macAddr; public NpgsqlMacAddress(PhysicalAddress macAddr) { this.macAddr = macAddr; } /// /// /// /// The macAddr parameter must contain a string that can only consist of numbers /// and upper-case letters as hexadecimal digits. (See PhysicalAddress.Parse method on MSDN) public NpgsqlMacAddress(string macAddr) { if (!string.IsNullOrEmpty(macAddr)) { string lowerMacAddr = macAddr.ToUpper(); System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (char c in lowerMacAddr) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { sb.Append(c); } } this.macAddr = PhysicalAddress.Parse(sb.ToString()); } else { this.macAddr = PhysicalAddress.None; } } public override String ToString() { return macAddr.ToString(); } public static explicit operator PhysicalAddress(NpgsqlMacAddress x) { return x.macAddr; } public static implicit operator NpgsqlMacAddress(PhysicalAddress macAddr) { return new NpgsqlMacAddress(macAddr); } public bool Equals(NpgsqlMacAddress other) { return macAddr.Equals(other.macAddr); } public override bool Equals(object obj) { return obj != null && obj is NpgsqlMacAddress && Equals((NpgsqlMacAddress)obj); } public override int GetHashCode() { int ret = 266370105; //seed with something other than zero to make paths of all zeros hash differently. return PGUtil.RotateShift(macAddr.GetHashCode(), ret); } public static bool operator ==(NpgsqlMacAddress x, NpgsqlMacAddress y) { return x.Equals(y); } public static bool operator !=(NpgsqlMacAddress x, NpgsqlMacAddress y) { return !(x == y); } } } #pragma warning restore 1591
X Tutup