Revert the revert
[mcs.git] / class / Npgsql / NpgsqlTypes / NpgsqlTypes.cs
blob81991b487a57360d352458cc26999bdef7b8d856
1 // NpgsqlTypes.NpgsqlTypesHelper.cs
2 //
3 // Author:
4 // Glen Parker <glenebob@nwlink.com>
5 //
6 // Copyright (C) 2004 The Npgsql Development Team
7 // npgsql-general@gborg.postgresql.org
8 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
9 //
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.
14 //
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.
20 //
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.
30 using System;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Net;
34 using Npgsql;
36 namespace NpgsqlTypes
38 /// <summary>
39 /// Represents a PostgreSQL Point type
40 /// </summary>
41 public struct NpgsqlPoint : IEquatable<NpgsqlPoint>
43 private Single _x;
44 private Single _y;
46 public NpgsqlPoint(Single x, Single y)
48 _x = x;
49 _y = y;
52 public Single X
54 get
56 return _x;
59 set
61 _x = value;
65 public Single Y
67 get
69 return _y;
72 set
74 _y = value;
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)
91 return x.Equals(y);
94 public static bool operator !=(NpgsqlPoint x, NpgsqlPoint y)
96 return !(x == 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
126 return _upperRight;
131 _upperRight = value;
136 public NpgsqlPoint LowerLeft
140 return _lowerLeft;
145 _lowerLeft = value;
150 public float Left
152 get { return LowerLeft.X; }
155 public float Right
157 get { return UpperRight.X; }
160 public float Bottom
162 get { return LowerLeft.Y; }
165 public float Top
167 get { return UpperRight.Y; }
170 public float Width
172 get { return Right - Left; }
175 public float Height
177 get { return Top - Bottom; }
180 public bool IsEmpty
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)
197 return x.Equals(y);
200 public static bool operator !=(NpgsqlBox x, NpgsqlBox y)
202 return !(x == y);
205 public override int GetHashCode()
207 return
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);
215 /// <summary>
216 /// Represents a PostgreSQL Line Segment type.
217 /// </summary>
218 public struct NpgsqlLSeg : IEquatable<NpgsqlLSeg>
220 public NpgsqlPoint Start;
221 public NpgsqlPoint End;
223 public NpgsqlLSeg(NpgsqlPoint start, NpgsqlPoint end)
225 Start = start;
226 End = end;
229 public override String ToString()
231 return String.Format("({0}, {1})", Start, End);
234 public override int GetHashCode()
236 return
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)
253 return x.Equals(y);
256 public static bool operator !=(NpgsqlLSeg x, NpgsqlLSeg y)
258 return !(x == y);
262 /// <summary>
263 /// Represents a PostgreSQL Path type.
264 /// </summary>
265 public struct NpgsqlPath : IList<NpgsqlPoint>, IEquatable<NpgsqlPath>
267 private bool _open;
268 private readonly List<NpgsqlPoint> _points;
270 public NpgsqlPath(IEnumerable<NpgsqlPoint> points, bool open)
272 _points = new List<NpgsqlPoint>(points);
273 _open = open;
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>();
288 _open = open;
291 public NpgsqlPath(int capacity, bool open)
293 _points = new List<NpgsqlPoint>(capacity);
294 _open = open;
297 public NpgsqlPath(int capacity)
298 : this(capacity, false)
302 public bool Open
306 return _open;
311 _open = value;
315 public NpgsqlPoint this[int index]
317 get { return _points[index]; }
318 set { _points[index] = value; }
321 public int Count
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)
348 _points.Add(item);
351 public void Clear()
353 _points.Clear();
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)
385 return false;
387 for (int i = 0; i != Count; ++i)
389 if (this[i] != other[i])
391 return false;
394 return true;
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)
404 return x.Equals(y);
407 public static bool operator !=(NpgsqlPath x, NpgsqlPath y)
409 return !(x == y);
412 public override int GetHashCode()
414 int ret = 0;
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;
426 /// <summary>
427 /// Represents a PostgreSQL Polygon type.
428 /// </summary>
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; }
448 public int Count
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)
475 _points.Add(item);
478 public void Clear()
480 _points.Clear();
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)
512 return false;
514 for (int i = 0; i != Count; ++i)
516 if (this[i] != other[i])
518 return false;
521 return true;
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)
531 return x.Equals(y);
534 public static bool operator !=(NpgsqlPolygon x, NpgsqlPolygon y)
536 return !(x == y);
539 public override int GetHashCode()
541 int ret = 0;
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));
549 return ret;
553 /// <summary>
554 /// Represents a PostgreSQL Circle type.
555 /// </summary>
556 public struct NpgsqlCircle : IEquatable<NpgsqlCircle>
558 public NpgsqlPoint Center;
559 public Double Radius;
561 public NpgsqlCircle(NpgsqlPoint center, Double radius)
563 Center = center;
564 Radius = 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)
584 return x.Equals(y);
587 public static bool operator !=(NpgsqlCircle x, NpgsqlCircle y)
589 return !(x == y);
592 public override int GetHashCode()
594 return
595 Center.X.GetHashCode() ^ PGUtil.RotateShift(Center.Y.GetHashCode(), sizeof (int)/4) ^
596 PGUtil.RotateShift(Radius.GetHashCode(), sizeof (int)/2);
601 /// <summary>
602 /// Represents a PostgreSQL inet type.
603 /// </summary>
604 public struct NpgsqlInet : IEquatable<NpgsqlInet>
606 public IPAddress addr;
607 public int mask;
609 public NpgsqlInet(IPAddress addr, int mask)
611 this.addr = addr;
612 this.mask = mask;
615 public NpgsqlInet(IPAddress addr)
617 this.addr = addr;
618 this.mask = 32;
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]);
633 else
635 this.addr = IPAddress.Parse(addr);
636 this.mask = 32;
640 public override String ToString()
642 if (mask != 32)
644 return string.Format("{0}/{1}", addr, mask);
646 return addr.ToString();
650 public static implicit operator IPAddress(NpgsqlInet x)
652 if (x.mask != 32)
654 throw new InvalidCastException("Cannot cast CIDR network to address");
656 return x.addr;
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)
677 return x.Equals(y);
680 public static bool operator !=(NpgsqlInet x, NpgsqlInet y)
682 return !(x == y);