aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/network.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-02-21 18:47:12 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-02-21 18:47:12 +0000
commit393f313227fba2b7905cfbd69b3e4c18d762bf4f (patch)
tree0eab81bd6705a19b625880d9b5cefb1d50c78d78 /src/backend/utils/adt/network.c
parentee97d103ccf68ae45343caea4188ca3dd5ce7365 (diff)
downloadpostgresql-393f313227fba2b7905cfbd69b3e4c18d762bf4f.tar.gz
postgresql-393f313227fba2b7905cfbd69b3e4c18d762bf4f.zip
Change parse-time representation of float literals (which include oversize
integers) to be strings instead of 'double'. We convert from string form to internal representation only after type resolution has determined the correct type for the constant. This eliminates loss-of-precision worries and gets rid of the change in behavior seen at 17 digits with the previous kluge.
Diffstat (limited to 'src/backend/utils/adt/network.c')
-rw-r--r--src/backend/utils/adt/network.c115
1 files changed, 45 insertions, 70 deletions
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index cb1b9b90bfe..44045c184b5 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -3,22 +3,23 @@
* is for IP V4 CIDR notation, but prepared for V6: just
* add the necessary bits where the comments indicate.
*
- * $Id: network.c,v 1.16 1999/09/23 17:42:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.17 2000/02/21 18:47:07 tgl Exp $
+ *
* Jon Postel RIP 16 Oct 1998
*/
+#include "postgres.h"
+
#include <sys/types.h>
#include <sys/socket.h>
-
#include <errno.h>
-
#include <netinet/in.h>
#include <arpa/inet.h>
-#include "postgres.h"
#include "utils/builtins.h"
-static int v4bitncmp(unsigned int a1, unsigned int a2, int bits);
+
+static int v4bitncmp(unsigned long a1, unsigned long a2, int bits);
/*
* Access macros. Add IPV6 support.
@@ -39,6 +40,7 @@ static int v4bitncmp(unsigned int a1, unsigned int a2, int bits);
#define ip_v4addr(inetptr) \
(((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr)
+
/* Common input routine */
static inet *
network_in(char *src, int type)
@@ -127,7 +129,8 @@ cidr_out(inet *src)
}
/*
- * Boolean tests for magnitude. Add V4/V6 testing!
+ * Boolean tests for ordering operators --- must agree with sorting
+ * operator network_cmp().
*/
bool
@@ -135,19 +138,7 @@ network_lt(inet *a1, inet *a2)
{
if (!PointerIsValid(a1) || !PointerIsValid(a2))
return FALSE;
- if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
- {
- int order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
-
- return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));
- }
- else
- {
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "cannot compare address families %d and %d",
- ip_family(a1), ip_family(a2));
- return FALSE;
- }
+ return (bool) (network_cmp(a1, a2) < 0);
}
bool
@@ -155,7 +146,7 @@ network_le(inet *a1, inet *a2)
{
if (!PointerIsValid(a1) || !PointerIsValid(a2))
return FALSE;
- return (network_lt(a1, a2) || network_eq(a1, a2));
+ return (bool) (network_cmp(a1, a2) <= 0);
}
bool
@@ -163,18 +154,7 @@ network_eq(inet *a1, inet *a2)
{
if (!PointerIsValid(a1) || !PointerIsValid(a2))
return FALSE;
- if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
- {
- return ((ip_bits(a1) == ip_bits(a2))
- && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
- }
- else
- {
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "cannot compare address families %d and %d",
- ip_family(a1), ip_family(a2));
- return FALSE;
- }
+ return (bool) (network_cmp(a1, a2) == 0);
}
bool
@@ -182,7 +162,7 @@ network_ge(inet *a1, inet *a2)
{
if (!PointerIsValid(a1) || !PointerIsValid(a2))
return FALSE;
- return (network_gt(a1, a2) || network_eq(a1, a2));
+ return (bool) (network_cmp(a1, a2) >= 0);
}
bool
@@ -190,30 +170,45 @@ network_gt(inet *a1, inet *a2)
{
if (!PointerIsValid(a1) || !PointerIsValid(a2))
return FALSE;
+ return (bool) (network_cmp(a1, a2) > 0);
+}
+
+bool
+network_ne(inet *a1, inet *a2)
+{
+ if (!PointerIsValid(a1) || !PointerIsValid(a2))
+ return FALSE;
+ return (bool) (network_cmp(a1, a2) != 0);
+}
+
+/*
+ * Comparison function for sorting. Add V4/V6 testing!
+ */
+
+int4
+network_cmp(inet *a1, inet *a2)
+{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
- int order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
-
- return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));
+ int order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2),
+ (ip_bits(a1) < ip_bits(a2)) ?
+ ip_bits(a1) : ip_bits(a2));
+
+ if (order)
+ return order;
+ /* They agree in the first N bits, so shorter one comes first */
+ return (int) ip_bits(a1) - (int) ip_bits(a2);
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
- return FALSE;
+ return 0;
}
}
bool
-network_ne(inet *a1, inet *a2)
-{
- if (!PointerIsValid(a1) || !PointerIsValid(a2))
- return FALSE;
- return (!network_eq(a1, a2));
-}
-
-bool
network_sub(inet *a1, inet *a2)
{
if (!PointerIsValid(a1) || !PointerIsValid(a2))
@@ -293,28 +288,6 @@ network_supeq(inet *a1, inet *a2)
}
}
-/*
- * Comparison function for sorting. Add V4/V6 testing!
- */
-
-int4
-network_cmp(inet *a1, inet *a2)
-{
- if (ntohl(ip_v4addr(a1)) < ntohl(ip_v4addr(a2)))
- return (-1);
-
- if (ntohl(ip_v4addr(a1)) > ntohl(ip_v4addr(a2)))
- return (1);
-
- if (ip_bits(a1) < ip_bits(a2))
- return (-1);
-
- if (ip_bits(a1) > ip_bits(a2))
- return (1);
-
- return 0;
-}
-
text *
network_host(inet *ip)
{
@@ -476,7 +449,7 @@ network_netmask(inet *ip)
*/
static int
-v4bitncmp(unsigned int a1, unsigned int a2, int bits)
+v4bitncmp(unsigned long a1, unsigned long a2, int bits)
{
unsigned long mask = 0;
int i;
@@ -485,9 +458,11 @@ v4bitncmp(unsigned int a1, unsigned int a2, int bits)
mask = (mask >> 1) | 0x80000000;
a1 = ntohl(a1);
a2 = ntohl(a2);
- if ((a1 & mask) < (a2 & mask))
+ a1 &= mask;
+ a2 &= mask;
+ if (a1 < a2)
return (-1);
- else if ((a1 & mask) > (a2 & mask))
+ else if (a1 > a2)
return (1);
return (0);
}