1 // NpgsqlTypes.NpgsqlTypesHelper.cs
4 // Glen Parker <glenebob@nwlink.com>
6 // Copyright (C) 2004 The Npgsql Development Team
7 // npgsql-general@gborg.postgresql.org
8 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
10 // Permission to use, copy, modify, and distribute this software and its
11 // documentation for any purpose, without fee, and without a written
12 // agreement is hereby granted, provided that the above copyright notice
13 // and this paragraph and the following two paragraphs appear in all copies.
15 // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
16 // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
17 // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
18 // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
19 // THE POSSIBILITY OF SUCH DAMAGE.
21 // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
22 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
24 // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
25 // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27 // This file provides implementations of PostgreSQL specific data types that cannot
28 // be mapped to standard .NET classes.
31 using System
.Collections
;
32 using System
.Collections
.Generic
;
39 /// Represents a PostgreSQL Point type
41 public struct NpgsqlPoint
: IEquatable
<NpgsqlPoint
>
46 public NpgsqlPoint(Single x
, Single y
)
79 public bool Equals(NpgsqlPoint other
)
81 return X
== other
.X
&& Y
== other
.Y
;
84 public override bool Equals(object obj
)
86 return obj
!= null && obj
is NpgsqlPoint
&& Equals((NpgsqlPoint
) obj
);
89 public static bool operator ==(NpgsqlPoint x
, NpgsqlPoint y
)
94 public static bool operator !=(NpgsqlPoint x
, NpgsqlPoint y
)
99 public override int GetHashCode()
101 return X
.GetHashCode() ^ PGUtil
.RotateShift(Y
.GetHashCode(), sizeof (int)/2);
105 public struct NpgsqlBox
: IEquatable
<NpgsqlBox
>
108 private NpgsqlPoint _upperRight
;
109 private NpgsqlPoint _lowerLeft
;
111 public NpgsqlBox(NpgsqlPoint upperRight
, NpgsqlPoint lowerLeft
)
113 _upperRight
= upperRight
;
114 _lowerLeft
= lowerLeft
;
117 public NpgsqlBox(float Top
, float Right
, float Bottom
, float Left
)
118 : this(new NpgsqlPoint(Right
, Top
), new NpgsqlPoint(Left
, Bottom
))
122 public NpgsqlPoint UpperRight
136 public NpgsqlPoint LowerLeft
152 get { return LowerLeft.X; }
157 get { return UpperRight.X; }
162 get { return LowerLeft.Y; }
167 get { return UpperRight.Y; }
172 get { return Right - Left; }
177 get { return Top - Bottom; }
182 get { return Width == 0 || Height == 0; }
185 public bool Equals(NpgsqlBox other
)
187 return UpperRight
== other
.UpperRight
&& LowerLeft
== other
.LowerLeft
;
190 public override bool Equals(object obj
)
192 return obj
!= null && obj
is NpgsqlBox
&& Equals((NpgsqlBox
) obj
);
195 public static bool operator ==(NpgsqlBox x
, NpgsqlBox y
)
200 public static bool operator !=(NpgsqlBox x
, NpgsqlBox y
)
205 public override int GetHashCode()
208 Top
.GetHashCode() ^ PGUtil
.RotateShift(Right
.GetHashCode(), sizeof (int)/4) ^
209 PGUtil
.RotateShift(Bottom
.GetHashCode(), sizeof (int)/2) ^
210 PGUtil
.RotateShift(LowerLeft
.GetHashCode(), sizeof (int)*3/4);
216 /// Represents a PostgreSQL Line Segment type.
218 public struct NpgsqlLSeg
: IEquatable
<NpgsqlLSeg
>
220 public NpgsqlPoint Start
;
221 public NpgsqlPoint End
;
223 public NpgsqlLSeg(NpgsqlPoint start
, NpgsqlPoint end
)
229 public override String
ToString()
231 return String
.Format("({0}, {1})", Start
, End
);
234 public override int GetHashCode()
237 Start
.X
.GetHashCode() ^ PGUtil
.RotateShift(Start
.Y
.GetHashCode(), sizeof (int)/4) ^
238 PGUtil
.RotateShift(End
.X
.GetHashCode(), sizeof (int)/2) ^ PGUtil
.RotateShift(End
.Y
.GetHashCode(), sizeof (int)*3/4);
241 public bool Equals(NpgsqlLSeg other
)
243 return Start
== other
.Start
&& End
== other
.End
;
246 public override bool Equals(object obj
)
248 return obj
!= null && obj
is NpgsqlLSeg
&& Equals((NpgsqlLSeg
) obj
);
251 public static bool operator ==(NpgsqlLSeg x
, NpgsqlLSeg y
)
256 public static bool operator !=(NpgsqlLSeg x
, NpgsqlLSeg y
)
263 /// Represents a PostgreSQL Path type.
265 public struct NpgsqlPath
: IList
<NpgsqlPoint
>, IEquatable
<NpgsqlPath
>
268 private readonly List
<NpgsqlPoint
> _points
;
270 public NpgsqlPath(IEnumerable
<NpgsqlPoint
> points
, bool open
)
272 _points
= new List
<NpgsqlPoint
>(points
);
276 public NpgsqlPath(IEnumerable
<NpgsqlPoint
> points
)
277 : this(points
, false)
281 public NpgsqlPath(NpgsqlPoint
[] points
) : this((IEnumerable
<NpgsqlPoint
>)points
, false)
285 public NpgsqlPath(bool open
)
287 _points
= new List
<NpgsqlPoint
>();
291 public NpgsqlPath(int capacity
, bool open
)
293 _points
= new List
<NpgsqlPoint
>(capacity
);
297 public NpgsqlPath(int capacity
)
298 : this(capacity
, false)
315 public NpgsqlPoint
this[int index
]
317 get { return _points[index]; }
318 set { _points[index] = value; }
323 get { return _points.Count; }
326 public bool IsReadOnly
328 get { return false; }
331 public int IndexOf(NpgsqlPoint item
)
333 return _points
.IndexOf(item
);
336 public void Insert(int index
, NpgsqlPoint item
)
338 _points
.Insert(index
, item
);
341 public void RemoveAt(int index
)
343 _points
.RemoveAt(index
);
346 public void Add(NpgsqlPoint item
)
356 public bool Contains(NpgsqlPoint item
)
358 return _points
.Contains(item
);
361 public void CopyTo(NpgsqlPoint
[] array
, int arrayIndex
)
363 _points
.CopyTo(array
, arrayIndex
);
366 public bool Remove(NpgsqlPoint item
)
368 return _points
.Remove(item
);
371 public IEnumerator
<NpgsqlPoint
> GetEnumerator()
373 return _points
.GetEnumerator();
376 IEnumerator IEnumerable
.GetEnumerator()
378 return GetEnumerator();
381 public bool Equals(NpgsqlPath other
)
383 if (Open
!= other
.Open
|| Count
!= other
.Count
)
387 for (int i
= 0; i
!= Count
; ++i
)
389 if (this[i
] != other
[i
])
397 public override bool Equals(object obj
)
399 return obj
!= null && obj
is NpgsqlPath
&& Equals((NpgsqlPath
) obj
);
402 public static bool operator ==(NpgsqlPath x
, NpgsqlPath y
)
407 public static bool operator !=(NpgsqlPath x
, NpgsqlPath y
)
412 public override int GetHashCode()
415 foreach (NpgsqlPoint point
in this)
417 //The ideal amount to shift each value is one that would evenly spread it throughout
418 //the resultant bytes. Using the current result % 32 is essentially using a random value
419 //but one that will be the same on subsequent calls.
420 ret ^
= PGUtil
.RotateShift(point
.GetHashCode(), ret
%sizeof (int));
422 return Open
? ret
: -ret
;
427 /// Represents a PostgreSQL Polygon type.
429 public struct NpgsqlPolygon
: IList
<NpgsqlPoint
>, IEquatable
<NpgsqlPolygon
>
431 private readonly List
<NpgsqlPoint
> _points
;
433 public NpgsqlPolygon(IEnumerable
<NpgsqlPoint
> points
)
435 _points
= new List
<NpgsqlPoint
>(points
);
438 public NpgsqlPolygon(NpgsqlPoint
[] points
) : this ((IEnumerable
<NpgsqlPoint
>) points
)
442 public NpgsqlPoint
this[int index
]
444 get { return _points[index]; }
445 set { _points[index] = value; }
450 get { return _points.Count; }
453 public bool IsReadOnly
455 get { return false; }
458 public int IndexOf(NpgsqlPoint item
)
460 return _points
.IndexOf(item
);
463 public void Insert(int index
, NpgsqlPoint item
)
465 _points
.Insert(index
, item
);
468 public void RemoveAt(int index
)
470 _points
.RemoveAt(index
);
473 public void Add(NpgsqlPoint item
)
483 public bool Contains(NpgsqlPoint item
)
485 return _points
.Contains(item
);
488 public void CopyTo(NpgsqlPoint
[] array
, int arrayIndex
)
490 _points
.CopyTo(array
, arrayIndex
);
493 public bool Remove(NpgsqlPoint item
)
495 return _points
.Remove(item
);
498 public IEnumerator
<NpgsqlPoint
> GetEnumerator()
500 return _points
.GetEnumerator();
503 IEnumerator IEnumerable
.GetEnumerator()
505 return GetEnumerator();
508 public bool Equals(NpgsqlPolygon other
)
510 if (Count
!= other
.Count
)
514 for (int i
= 0; i
!= Count
; ++i
)
516 if (this[i
] != other
[i
])
524 public override bool Equals(object obj
)
526 return obj
!= null && obj
is NpgsqlPolygon
&& Equals((NpgsqlPolygon
) obj
);
529 public static bool operator ==(NpgsqlPolygon x
, NpgsqlPolygon y
)
534 public static bool operator !=(NpgsqlPolygon x
, NpgsqlPolygon y
)
539 public override int GetHashCode()
542 foreach (NpgsqlPoint point
in this)
544 //The ideal amount to shift each value is one that would evenly spread it throughout
545 //the resultant bytes. Using the current result % 32 is essentially using a random value
546 //but one that will be the same on subsequent calls.
547 ret ^
= PGUtil
.RotateShift(point
.GetHashCode(), ret
%sizeof (int));
554 /// Represents a PostgreSQL Circle type.
556 public struct NpgsqlCircle
: IEquatable
<NpgsqlCircle
>
558 public NpgsqlPoint Center
;
559 public Double Radius
;
561 public NpgsqlCircle(NpgsqlPoint center
, Double radius
)
567 public bool Equals(NpgsqlCircle other
)
569 return Center
== other
.Center
&& Radius
== other
.Radius
;
572 public override bool Equals(object obj
)
574 return obj
!= null && obj
is NpgsqlCircle
&& Equals((NpgsqlCircle
) obj
);
577 public override String
ToString()
579 return string.Format("({0}), {1}", Center
, Radius
);
582 public static bool operator ==(NpgsqlCircle x
, NpgsqlCircle y
)
587 public static bool operator !=(NpgsqlCircle x
, NpgsqlCircle y
)
592 public override int GetHashCode()
595 Center
.X
.GetHashCode() ^ PGUtil
.RotateShift(Center
.Y
.GetHashCode(), sizeof (int)/4) ^
596 PGUtil
.RotateShift(Radius
.GetHashCode(), sizeof (int)/2);
602 /// Represents a PostgreSQL inet type.
604 public struct NpgsqlInet
: IEquatable
<NpgsqlInet
>
606 public IPAddress addr
;
609 public NpgsqlInet(IPAddress addr
, int mask
)
615 public NpgsqlInet(IPAddress addr
)
621 public NpgsqlInet(string addr
)
623 if (addr
.IndexOf('/') > 0)
625 string[] addrbits
= addr
.Split('/');
626 if (addrbits
.GetUpperBound(0) != 1)
628 throw new FormatException("Invalid number of parts in CIDR specification");
630 this.addr
= IPAddress
.Parse(addrbits
[0]);
631 this.mask
= int.Parse(addrbits
[1]);
635 this.addr
= IPAddress
.Parse(addr
);
640 public override String
ToString()
644 return string.Format("{0}/{1}", addr
, mask
);
646 return addr
.ToString();
650 public static implicit operator IPAddress(NpgsqlInet x
)
654 throw new InvalidCastException("Cannot cast CIDR network to address");
660 public bool Equals(NpgsqlInet other
)
662 return addr
.Equals(other
.addr
) && mask
== other
.mask
;
665 public override bool Equals(object obj
)
667 return obj
!= null && obj
is NpgsqlInet
&& Equals((NpgsqlInet
) obj
);
670 public override int GetHashCode()
672 return PGUtil
.RotateShift(addr
.GetHashCode(), mask
%32);
675 public static bool operator ==(NpgsqlInet x
, NpgsqlInet y
)
680 public static bool operator !=(NpgsqlInet x
, NpgsqlInet y
)