xref: /netbsd-src/external/mpl/bind/dist/lib/isccc/include/isccc/util.h (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: util.h,v 1.9 2025/01/26 16:25:44 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0 AND ISC
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*
17  * Copyright (C) 2001 Nominum, Inc.
18  *
19  * Permission to use, copy, modify, and/or distribute this software for any
20  * purpose with or without fee is hereby granted, provided that the above
21  * copyright notice and this permission notice appear in all copies.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
24  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
26  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
29  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30  */
31 
32 #pragma once
33 
34 #include <inttypes.h>
35 
36 #include <isc/util.h>
37 
38 /*! \file isccc/util.h
39  * \brief
40  * Macros for dealing with unaligned numbers.
41  *
42  * \note no side effects are allowed when invoking these macros!
43  */
44 
45 #define GET8(v, w)      \
46 	do {            \
47 		v = *w; \
48 		w++;    \
49 	} while (0)
50 
51 #define GET16(v, w)                          \
52 	do {                                 \
53 		v = (unsigned int)w[0] << 8; \
54 		v |= (unsigned int)w[1];     \
55 		w += 2;                      \
56 	} while (0)
57 
58 #define GET24(v, w)                           \
59 	do {                                  \
60 		v = (unsigned int)w[0] << 16; \
61 		v |= (unsigned int)w[1] << 8; \
62 		v |= (unsigned int)w[2];      \
63 		w += 3;                       \
64 	} while (0)
65 
66 #define GET32(v, w)                            \
67 	do {                                   \
68 		v = (unsigned int)w[0] << 24;  \
69 		v |= (unsigned int)w[1] << 16; \
70 		v |= (unsigned int)w[2] << 8;  \
71 		v |= (unsigned int)w[3];       \
72 		w += 4;                        \
73 	} while (0)
74 
75 #define GET64(v, w)                        \
76 	do {                               \
77 		v = (uint64_t)w[0] << 56;  \
78 		v |= (uint64_t)w[1] << 48; \
79 		v |= (uint64_t)w[2] << 40; \
80 		v |= (uint64_t)w[3] << 32; \
81 		v |= (uint64_t)w[4] << 24; \
82 		v |= (uint64_t)w[5] << 16; \
83 		v |= (uint64_t)w[6] << 8;  \
84 		v |= (uint64_t)w[7];       \
85 		w += 8;                    \
86 	} while (0)
87 
88 #define GETC16(v, w, d)                      \
89 	do {                                 \
90 		GET8(v, w);                  \
91 		if (v == 0) {                \
92 			d = ISCCC_TRUE;      \
93 		} else {                     \
94 			d = ISCCC_FALSE;     \
95 			if (v == 255)        \
96 				GET16(v, w); \
97 		}                            \
98 	} while (0)
99 
100 #define GETC32(v, w)                  \
101 	do {                          \
102 		GET24(v, w);          \
103 		if (v == 0xffffffu) { \
104 			GET32(v, w);  \
105 		}                     \
106 	} while (0)
107 
108 #define GET_OFFSET(v, w) GET32(v, w)
109 
110 #define GET_MEM(v, c, w)          \
111 	do {                      \
112 		memmove(v, w, c); \
113 		w += c;           \
114 	} while (0)
115 
116 #define GET_TYPE(v, w)                                                        \
117 	do {                                                                  \
118 		GET8(v, w);                                                   \
119 		if (v > 127) {                                                \
120 			if (v < 255) {                                        \
121 				v = ((v & 0x7f) << 16) | ISCCC_RDATATYPE_SIG; \
122 			} else {                                              \
123 				GET32(v, w);                                  \
124 			}                                                     \
125 		}                                                             \
126 	} while (0)
127 
128 #define PUT8(v, w)                      \
129 	do {                            \
130 		*w = (v & 0x000000ffU); \
131 		w++;                    \
132 	} while (0)
133 
134 #define PUT16(v, w)                            \
135 	do {                                   \
136 		w[0] = (v & 0x0000ff00U) >> 8; \
137 		w[1] = (v & 0x000000ffU);      \
138 		w += 2;                        \
139 	} while (0)
140 
141 #define PUT24(v, w)                             \
142 	do {                                    \
143 		w[0] = (v & 0x00ff0000U) >> 16; \
144 		w[1] = (v & 0x0000ff00U) >> 8;  \
145 		w[2] = (v & 0x000000ffU);       \
146 		w += 3;                         \
147 	} while (0)
148 
149 #define PUT32(v, w)                             \
150 	do {                                    \
151 		w[0] = (v & 0xff000000U) >> 24; \
152 		w[1] = (v & 0x00ff0000U) >> 16; \
153 		w[2] = (v & 0x0000ff00U) >> 8;  \
154 		w[3] = (v & 0x000000ffU);       \
155 		w += 4;                         \
156 	} while (0)
157 
158 #define PUT64(v, w)                                       \
159 	do {                                              \
160 		w[0] = (v & 0xff00000000000000ULL) >> 56; \
161 		w[1] = (v & 0x00ff000000000000ULL) >> 48; \
162 		w[2] = (v & 0x0000ff0000000000ULL) >> 40; \
163 		w[3] = (v & 0x000000ff00000000ULL) >> 32; \
164 		w[4] = (v & 0x00000000ff000000ULL) >> 24; \
165 		w[5] = (v & 0x0000000000ff0000ULL) >> 16; \
166 		w[6] = (v & 0x000000000000ff00ULL) >> 8;  \
167 		w[7] = (v & 0x00000000000000ffULL);       \
168 		w += 8;                                   \
169 	} while (0)
170 
171 #define PUTC16(v, w)                    \
172 	do {                            \
173 		if (v > 0 && v < 255) { \
174 			PUT8(v, w);     \
175 		} else {                \
176 			PUT8(255, w);   \
177 			PUT16(v, w);    \
178 		}                       \
179 	} while (0)
180 
181 #define PUTC32(v, w)                         \
182 	do {                                 \
183 		if (v < 0xffffffU) {         \
184 			PUT24(v, w);         \
185 		} else {                     \
186 			PUT24(0xffffffU, w); \
187 			PUT32(v, w);         \
188 		}                            \
189 	} while (0)
190 
191 #define PUT_OFFSET(v, w) PUT32(v, w)
192 
193 #include <string.h>
194 
195 #define PUT_MEM(s, c, w)          \
196 	do {                      \
197 		memmove(w, s, c); \
198 		w += c;           \
199 	} while (0)
200 
201 /*
202  * Regions.
203  */
204 #define REGION_SIZE(r)	((unsigned int)((r).rend - (r).rstart))
205 #define REGION_EMPTY(r) ((r).rstart == (r).rend)
206 #define REGION_FROMSTRING(r, s)                    \
207 	do {                                       \
208 		(r).rstart = (unsigned char *)s;   \
209 		(r).rend = (r).rstart + strlen(s); \
210 	} while (0)
211