From: | "Ilya A(dot) Kovalenko" <shadow(at)oganer(dot)net> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | inet increment w/ int8 |
Date: | 2005-04-17 20:25:34 |
Message-ID: | 17534258300.20050418042534@oganer.net |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Greetings,
I suggest function for "inet" increment w/ int8 (signed).
FUNCTION inet_inc(int, int8) RETURNS inet
Function, useful for making address pools (using also
existing "inet" compare functions to trap boundaries).
Notes:
This version lets address wrap around 0-*ff boundary.
Uses couple of non-POSIX functions - betoh64() and htobe64()
Tested on i386 with OpenBSD 3.7
PostgreSQL 8.0.2
-----------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "postgres.h" /* general Postgres declarations */
#include "fmgr.h" /* for argument/result macros */
#include "utils/inet.h"
Datum inet_inc(PG_FUNCTION_ARGS);
//------ stolen from backend/utils/adt/network.c --------
#define ip_family(inetptr) \
(((inet_struct *)VARDATA(inetptr))->family)
#define ip_bits(inetptr) \
(((inet_struct *)VARDATA(inetptr))->bits)
#define ip_type(inetptr) \
(((inet_struct *)VARDATA(inetptr))->type)
#define ip_addr(inetptr) \
(((inet_struct *)VARDATA(inetptr))->ipaddr)
#define ip_maxbits(inetptr) \
(ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
static int
ip_addrsize(inet *inetptr)
{
switch (ip_family(inetptr))
{
case PGSQL_AF_INET:
return 4;
case PGSQL_AF_INET6:
return 16;
default:
return 0;
}
}
//-------------------------------------------------------
PG_FUNCTION_INFO_V1(inet_inc);
Datum
inet_inc(PG_FUNCTION_ARGS)
{
inet *src = PG_GETARG_INET_P(0);
int64 arg = PG_GETARG_INT64(1);
inet *dst;
uint64 wsp;
// allocate destination structure
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
// copy to destination
*((inet_struct *)VARDATA(dst)) = *((inet_struct *)VARDATA(src));
if (ip_family(dst) == PGSQL_AF_INET)
{
// Increment v4 address w/ item truncated to 32 bits
*((uint32*)(ip_addr(dst))) =
htonl(ntohl(*((int32*)(ip_addr(dst)))) + (int32)arg);
}
else
{
// Increment v6 address low qword (store to workspace)
wsp = htobe64(betoh64(*((int64*)(ip_addr(dst) + 8))) + arg);
*((uint64*)(ip_addr(dst) + 8)) = wsp;
// Carry/borrow high qword
if ( arg > 0 && wsp < *((uint64*)(ip_addr(src) + 8)) )
{ *((int64*)(ip_addr(dst))) =
htobe64(betoh64(*((int64*)(ip_addr(dst)))) + 1);
}
else
if ( arg < 0 && wsp > *((uint64*)(ip_addr(src) + 8)) )
{ *((int64*)(ip_addr(dst))) =
htobe64(betoh64(*((int64*)(ip_addr(dst)))) - 1);
}
}
// Return result
VARATT_SIZEP(dst) = VARHDRSZ
+ ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
}
-----------------------------------------------------
Thank you
Ilya A. Kovalenko (mailto:shadow(at)oganer(dot)net)
SpecialEQ SW section
JSC Oganer-Service
P.S. Treat as Public Domain
From | Date | Subject | |
---|---|---|---|
Next Message | Chuck McDevitt | 2005-04-17 20:28:11 | Re: argtype_inherit() is dead code |
Previous Message | elein | 2005-04-17 18:27:52 | Re: argtype_inherit() is dead code |