OSDN Git Service

pgindent run.
[pg-rex/syncrep.git] / src / backend / utils / adt / mac.c
1 /*
2  *      PostgreSQL type definitions for MAC addresses.
3  *
4  *      $Header: /cvsroot/pgsql/src/backend/utils/adt/mac.c,v 1.26 2002/09/04 20:31:28 momjian Exp $
5  */
6
7 #include "postgres.h"
8
9 #include "access/hash.h"
10 #include "utils/builtins.h"
11 #include "utils/inet.h"
12
13 /*
14  *      Utility macros used for sorting and comparing:
15  */
16
17 #define hibits(addr) \
18   ((unsigned long)(((addr)->a<<16)|((addr)->b<<8)|((addr)->c)))
19
20 #define lobits(addr) \
21   ((unsigned long)(((addr)->d<<16)|((addr)->e<<8)|((addr)->f)))
22
23 /*
24  *      MAC address reader.  Accepts several common notations.
25  */
26
27 Datum
28 macaddr_in(PG_FUNCTION_ARGS)
29 {
30         char       *str = PG_GETARG_CSTRING(0);
31         macaddr    *result;
32         int                     a,
33                                 b,
34                                 c,
35                                 d,
36                                 e,
37                                 f;
38         int                     count;
39
40         count = sscanf(str, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f);
41         if (count != 6)
42                 count = sscanf(str, "%x-%x-%x-%x-%x-%x", &a, &b, &c, &d, &e, &f);
43         if (count != 6)
44                 count = sscanf(str, "%2x%2x%2x:%2x%2x%2x", &a, &b, &c, &d, &e, &f);
45         if (count != 6)
46                 count = sscanf(str, "%2x%2x%2x-%2x%2x%2x", &a, &b, &c, &d, &e, &f);
47         if (count != 6)
48                 count = sscanf(str, "%2x%2x.%2x%2x.%2x%2x", &a, &b, &c, &d, &e, &f);
49         if (count != 6)
50                 count = sscanf(str, "%2x%2x%2x%2x%2x%2x", &a, &b, &c, &d, &e, &f);
51         if (count != 6)
52                 elog(ERROR, "macaddr_in: error in parsing \"%s\"", str);
53
54         if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
55                 (c < 0) || (c > 255) || (d < 0) || (d > 255) ||
56                 (e < 0) || (e > 255) || (f < 0) || (f > 255))
57                 elog(ERROR, "macaddr_in: illegal address \"%s\"", str);
58
59         result = (macaddr *) palloc(sizeof(macaddr));
60
61         result->a = a;
62         result->b = b;
63         result->c = c;
64         result->d = d;
65         result->e = e;
66         result->f = f;
67
68         PG_RETURN_MACADDR_P(result);
69 }
70
71 /*
72  *      MAC address output function.  Fixed format.
73  */
74
75 Datum
76 macaddr_out(PG_FUNCTION_ARGS)
77 {
78         macaddr    *addr = PG_GETARG_MACADDR_P(0);
79         char       *result;
80
81         result = (char *) palloc(32);
82
83         snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
84                          addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
85
86         PG_RETURN_CSTRING(result);
87 }
88
89 /*
90  * Convert macaddr to text data type.
91  */
92
93 Datum
94 macaddr_text(PG_FUNCTION_ARGS)
95 {
96         /* Input is a macaddr, but may as well leave it in Datum form */
97         Datum           addr = PG_GETARG_DATUM(0);
98         text       *result;
99         char       *str;
100         int                     len;
101
102         str = DatumGetCString(DirectFunctionCall1(macaddr_out, addr));
103
104         len = (strlen(str) + VARHDRSZ);
105
106         result = palloc(len);
107
108         VARATT_SIZEP(result) = len;
109         memmove(VARDATA(result), str, (len - VARHDRSZ));
110
111         pfree(str);
112
113         PG_RETURN_TEXT_P(result);
114 }
115
116 /*
117  * Convert text to macaddr data type.
118  */
119
120 Datum
121 text_macaddr(PG_FUNCTION_ARGS)
122 {
123         text       *addr = PG_GETARG_TEXT_P(0);
124         Datum           result;
125         char            str[18];
126         int                     len;
127
128         len = (VARSIZE(addr) - VARHDRSZ);
129         if (len >= 18)
130                 elog(ERROR, "Text is too long to convert to MAC address");
131
132         memcpy(str, VARDATA(addr), len);
133         *(str + len) = '\0';
134
135         result = DirectFunctionCall1(macaddr_in, CStringGetDatum(str));
136
137         return (result);
138 }
139
140 /*
141  *      Comparison function for sorting:
142  */
143
144 static int32
145 macaddr_cmp_internal(macaddr *a1, macaddr *a2)
146 {
147         if (hibits(a1) < hibits(a2))
148                 return -1;
149         else if (hibits(a1) > hibits(a2))
150                 return 1;
151         else if (lobits(a1) < lobits(a2))
152                 return -1;
153         else if (lobits(a1) > lobits(a2))
154                 return 1;
155         else
156                 return 0;
157 }
158
159 Datum
160 macaddr_cmp(PG_FUNCTION_ARGS)
161 {
162         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
163         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
164
165         PG_RETURN_INT32(macaddr_cmp_internal(a1, a2));
166 }
167
168 /*
169  *      Boolean comparisons.
170  */
171
172 Datum
173 macaddr_lt(PG_FUNCTION_ARGS)
174 {
175         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
176         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
177
178         PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) < 0);
179 }
180
181 Datum
182 macaddr_le(PG_FUNCTION_ARGS)
183 {
184         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
185         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
186
187         PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) <= 0);
188 }
189
190 Datum
191 macaddr_eq(PG_FUNCTION_ARGS)
192 {
193         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
194         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
195
196         PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) == 0);
197 }
198
199 Datum
200 macaddr_ge(PG_FUNCTION_ARGS)
201 {
202         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
203         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
204
205         PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) >= 0);
206 }
207
208 Datum
209 macaddr_gt(PG_FUNCTION_ARGS)
210 {
211         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
212         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
213
214         PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) > 0);
215 }
216
217 Datum
218 macaddr_ne(PG_FUNCTION_ARGS)
219 {
220         macaddr    *a1 = PG_GETARG_MACADDR_P(0);
221         macaddr    *a2 = PG_GETARG_MACADDR_P(1);
222
223         PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) != 0);
224 }
225
226 /*
227  * Support function for hash indexes on macaddr.
228  */
229 Datum
230 hashmacaddr(PG_FUNCTION_ARGS)
231 {
232         macaddr    *key = PG_GETARG_MACADDR_P(0);
233
234         return hash_any((unsigned char *) key, sizeof(macaddr));
235 }
236
237 /*
238  *      Truncation function to allow comparing mac manufacturers.
239  *      From suggestion by Alex Pilosov <alex@pilosoft.com>
240  */
241 Datum
242 macaddr_trunc(PG_FUNCTION_ARGS)
243 {
244         macaddr    *addr = PG_GETARG_MACADDR_P(0);
245         macaddr    *result;
246
247         result = (macaddr *) palloc(sizeof(macaddr));
248
249         result->a = addr->a;
250         result->b = addr->b;
251         result->c = addr->c;
252         result->d = 0;
253         result->e = 0;
254         result->f = 0;
255
256         PG_RETURN_MACADDR_P(result);
257 }