Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / backend / utils / adt / mac.c
blobfe3a482f3326c881a585db768610555d7b6265cf
1 /*
2 * PostgreSQL type definitions for MAC addresses.
4 * $PostgreSQL$
5 */
7 #include "postgres.h"
9 #include "access/hash.h"
10 #include "libpq/pqformat.h"
11 #include "utils/builtins.h"
12 #include "utils/inet.h"
16 * Utility macros used for sorting and comparing:
19 #define hibits(addr) \
20 ((unsigned long)(((addr)->a<<16)|((addr)->b<<8)|((addr)->c)))
22 #define lobits(addr) \
23 ((unsigned long)(((addr)->d<<16)|((addr)->e<<8)|((addr)->f)))
26 * MAC address reader. Accepts several common notations.
29 Datum
30 macaddr_in(PG_FUNCTION_ARGS)
32 char *str = PG_GETARG_CSTRING(0);
33 macaddr *result;
34 int a,
40 char junk[2];
41 int count;
43 /* %1s matches iff there is trailing non-whitespace garbage */
45 count = sscanf(str, "%x:%x:%x:%x:%x:%x%1s",
46 &a, &b, &c, &d, &e, &f, junk);
47 if (count != 6)
48 count = sscanf(str, "%x-%x-%x-%x-%x-%x%1s",
49 &a, &b, &c, &d, &e, &f, junk);
50 if (count != 6)
51 count = sscanf(str, "%2x%2x%2x:%2x%2x%2x%1s",
52 &a, &b, &c, &d, &e, &f, junk);
53 if (count != 6)
54 count = sscanf(str, "%2x%2x%2x-%2x%2x%2x%1s",
55 &a, &b, &c, &d, &e, &f, junk);
56 if (count != 6)
57 count = sscanf(str, "%2x%2x.%2x%2x.%2x%2x%1s",
58 &a, &b, &c, &d, &e, &f, junk);
59 if (count != 6)
60 count = sscanf(str, "%2x%2x%2x%2x%2x%2x%1s",
61 &a, &b, &c, &d, &e, &f, junk);
62 if (count != 6)
63 ereport(ERROR,
64 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
65 errmsg("invalid input syntax for type macaddr: \"%s\"", str)));
67 if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
68 (c < 0) || (c > 255) || (d < 0) || (d > 255) ||
69 (e < 0) || (e > 255) || (f < 0) || (f > 255))
70 ereport(ERROR,
71 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
72 errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
74 result = (macaddr *) palloc(sizeof(macaddr));
76 result->a = a;
77 result->b = b;
78 result->c = c;
79 result->d = d;
80 result->e = e;
81 result->f = f;
83 PG_RETURN_MACADDR_P(result);
87 * MAC address output function. Fixed format.
90 Datum
91 macaddr_out(PG_FUNCTION_ARGS)
93 macaddr *addr = PG_GETARG_MACADDR_P(0);
94 char *result;
96 result = (char *) palloc(32);
98 snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
99 addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
101 PG_RETURN_CSTRING(result);
105 * macaddr_recv - converts external binary format to macaddr
107 * The external representation is just the six bytes, MSB first.
109 Datum
110 macaddr_recv(PG_FUNCTION_ARGS)
112 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
113 macaddr *addr;
115 addr = (macaddr *) palloc(sizeof(macaddr));
117 addr->a = pq_getmsgbyte(buf);
118 addr->b = pq_getmsgbyte(buf);
119 addr->c = pq_getmsgbyte(buf);
120 addr->d = pq_getmsgbyte(buf);
121 addr->e = pq_getmsgbyte(buf);
122 addr->f = pq_getmsgbyte(buf);
124 PG_RETURN_MACADDR_P(addr);
128 * macaddr_send - converts macaddr to binary format
130 Datum
131 macaddr_send(PG_FUNCTION_ARGS)
133 macaddr *addr = PG_GETARG_MACADDR_P(0);
134 StringInfoData buf;
136 pq_begintypsend(&buf);
137 pq_sendbyte(&buf, addr->a);
138 pq_sendbyte(&buf, addr->b);
139 pq_sendbyte(&buf, addr->c);
140 pq_sendbyte(&buf, addr->d);
141 pq_sendbyte(&buf, addr->e);
142 pq_sendbyte(&buf, addr->f);
143 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
148 * Comparison function for sorting:
151 static int32
152 macaddr_cmp_internal(macaddr *a1, macaddr *a2)
154 if (hibits(a1) < hibits(a2))
155 return -1;
156 else if (hibits(a1) > hibits(a2))
157 return 1;
158 else if (lobits(a1) < lobits(a2))
159 return -1;
160 else if (lobits(a1) > lobits(a2))
161 return 1;
162 else
163 return 0;
166 Datum
167 macaddr_cmp(PG_FUNCTION_ARGS)
169 macaddr *a1 = PG_GETARG_MACADDR_P(0);
170 macaddr *a2 = PG_GETARG_MACADDR_P(1);
172 PG_RETURN_INT32(macaddr_cmp_internal(a1, a2));
176 * Boolean comparisons.
179 Datum
180 macaddr_lt(PG_FUNCTION_ARGS)
182 macaddr *a1 = PG_GETARG_MACADDR_P(0);
183 macaddr *a2 = PG_GETARG_MACADDR_P(1);
185 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) < 0);
188 Datum
189 macaddr_le(PG_FUNCTION_ARGS)
191 macaddr *a1 = PG_GETARG_MACADDR_P(0);
192 macaddr *a2 = PG_GETARG_MACADDR_P(1);
194 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) <= 0);
197 Datum
198 macaddr_eq(PG_FUNCTION_ARGS)
200 macaddr *a1 = PG_GETARG_MACADDR_P(0);
201 macaddr *a2 = PG_GETARG_MACADDR_P(1);
203 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) == 0);
206 Datum
207 macaddr_ge(PG_FUNCTION_ARGS)
209 macaddr *a1 = PG_GETARG_MACADDR_P(0);
210 macaddr *a2 = PG_GETARG_MACADDR_P(1);
212 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) >= 0);
215 Datum
216 macaddr_gt(PG_FUNCTION_ARGS)
218 macaddr *a1 = PG_GETARG_MACADDR_P(0);
219 macaddr *a2 = PG_GETARG_MACADDR_P(1);
221 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) > 0);
224 Datum
225 macaddr_ne(PG_FUNCTION_ARGS)
227 macaddr *a1 = PG_GETARG_MACADDR_P(0);
228 macaddr *a2 = PG_GETARG_MACADDR_P(1);
230 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) != 0);
234 * Support function for hash indexes on macaddr.
236 Datum
237 hashmacaddr(PG_FUNCTION_ARGS)
239 macaddr *key = PG_GETARG_MACADDR_P(0);
241 return hash_any((unsigned char *) key, sizeof(macaddr));
245 * Truncation function to allow comparing mac manufacturers.
246 * From suggestion by Alex Pilosov <alex@pilosoft.com>
248 Datum
249 macaddr_trunc(PG_FUNCTION_ARGS)
251 macaddr *addr = PG_GETARG_MACADDR_P(0);
252 macaddr *result;
254 result = (macaddr *) palloc(sizeof(macaddr));
256 result->a = addr->a;
257 result->b = addr->b;
258 result->c = addr->c;
259 result->d = 0;
260 result->e = 0;
261 result->f = 0;
263 PG_RETURN_MACADDR_P(result);