1 1.1 christos /* 2 1.1 christos * buffer.h -- generic memory buffer. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * See LICENSE for the license. 7 1.1 christos * 8 1.1 christos * 9 1.1 christos * The buffer module implements a generic buffer. The API is based on 10 1.1 christos * the java.nio.Buffer interface. 11 1.1 christos */ 12 1.1 christos 13 1.1 christos #ifndef LDNS_SBUFFER_H 14 1.1 christos #define LDNS_SBUFFER_H 15 1.1 christos 16 1.1 christos #ifdef __cplusplus 17 1.1 christos extern "C" { 18 1.1 christos #endif 19 1.1 christos 20 1.1 christos #ifdef S_SPLINT_S 21 1.1 christos # define INLINE 22 1.1 christos #else 23 1.1 christos # ifdef SWIG 24 1.1 christos # define INLINE static 25 1.1 christos # else 26 1.1 christos # define INLINE static inline 27 1.1 christos # endif 28 1.1 christos #endif 29 1.1 christos 30 1.1 christos /* 31 1.1 christos * Copy data allowing for unaligned accesses in network byte order 32 1.1 christos * (big endian). 33 1.1 christos */ 34 1.1 christos INLINE uint16_t 35 1.1 christos sldns_read_uint16(const void *src) 36 1.1 christos { 37 1.1 christos #ifdef ALLOW_UNALIGNED_ACCESSES 38 1.1 christos return ntohs(*(const uint16_t *) src); 39 1.1 christos #else 40 1.1 christos const uint8_t *p = (const uint8_t *) src; 41 1.1 christos return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; 42 1.1 christos #endif 43 1.1 christos } 44 1.1 christos 45 1.1 christos INLINE uint32_t 46 1.1 christos sldns_read_uint32(const void *src) 47 1.1 christos { 48 1.1 christos #ifdef ALLOW_UNALIGNED_ACCESSES 49 1.1 christos return ntohl(*(const uint32_t *) src); 50 1.1 christos #else 51 1.1 christos const uint8_t *p = (const uint8_t *) src; 52 1.1 christos return ( ((uint32_t) p[0] << 24) 53 1.1 christos | ((uint32_t) p[1] << 16) 54 1.1 christos | ((uint32_t) p[2] << 8) 55 1.1 christos | (uint32_t) p[3]); 56 1.1 christos #endif 57 1.1 christos } 58 1.1 christos 59 1.1 christos /* 60 1.1 christos * Copy data allowing for unaligned accesses in network byte order 61 1.1 christos * (big endian). 62 1.1 christos */ 63 1.1 christos INLINE void 64 1.1 christos sldns_write_uint16(void *dst, uint16_t data) 65 1.1 christos { 66 1.1 christos #ifdef ALLOW_UNALIGNED_ACCESSES 67 1.1 christos * (uint16_t *) dst = htons(data); 68 1.1 christos #else 69 1.1 christos uint8_t *p = (uint8_t *) dst; 70 1.1 christos p[0] = (uint8_t) ((data >> 8) & 0xff); 71 1.1 christos p[1] = (uint8_t) (data & 0xff); 72 1.1 christos #endif 73 1.1 christos } 74 1.1 christos 75 1.1 christos INLINE void 76 1.1 christos sldns_write_uint32(void *dst, uint32_t data) 77 1.1 christos { 78 1.1 christos #ifdef ALLOW_UNALIGNED_ACCESSES 79 1.1 christos * (uint32_t *) dst = htonl(data); 80 1.1 christos #else 81 1.1 christos uint8_t *p = (uint8_t *) dst; 82 1.1 christos p[0] = (uint8_t) ((data >> 24) & 0xff); 83 1.1 christos p[1] = (uint8_t) ((data >> 16) & 0xff); 84 1.1 christos p[2] = (uint8_t) ((data >> 8) & 0xff); 85 1.1 christos p[3] = (uint8_t) (data & 0xff); 86 1.1 christos #endif 87 1.1 christos } 88 1.1 christos 89 1.1 christos 90 1.1.1.2 christos INLINE void 91 1.1.1.2 christos sldns_write_uint48(void *dst, uint64_t data) 92 1.1.1.2 christos { 93 1.1.1.2 christos uint8_t *p = (uint8_t *) dst; 94 1.1.1.2 christos p[0] = (uint8_t) ((data >> 40) & 0xff); 95 1.1.1.2 christos p[1] = (uint8_t) ((data >> 32) & 0xff); 96 1.1.1.2 christos p[2] = (uint8_t) ((data >> 24) & 0xff); 97 1.1.1.2 christos p[3] = (uint8_t) ((data >> 16) & 0xff); 98 1.1.1.2 christos p[4] = (uint8_t) ((data >> 8) & 0xff); 99 1.1.1.2 christos p[5] = (uint8_t) (data & 0xff); 100 1.1.1.2 christos } 101 1.1.1.2 christos 102 1.1.1.2 christos 103 1.1 christos /** 104 1.1 christos * \file sbuffer.h 105 1.1 christos * 106 1.1 christos * This file contains the definition of sldns_buffer, and functions to manipulate those. 107 1.1 christos */ 108 1.1 christos 109 1.1 christos /** 110 1.1 christos * implementation of buffers to ease operations 111 1.1 christos * 112 1.1 christos * sldns_buffers can contain arbitrary information, per octet. You can write 113 1.1 christos * to the current end of a buffer, read from the current position, and 114 1.1 christos * access any data within it. 115 1.1 christos */ 116 1.1 christos struct sldns_buffer 117 1.1 christos { 118 1.1 christos /** The current position used for reading/writing */ 119 1.1 christos size_t _position; 120 1.1 christos 121 1.1 christos /** The read/write limit */ 122 1.1 christos size_t _limit; 123 1.1 christos 124 1.1 christos /** The amount of data the buffer can contain */ 125 1.1 christos size_t _capacity; 126 1.1 christos 127 1.1 christos /** The data contained in the buffer */ 128 1.1 christos uint8_t *_data; 129 1.1 christos 130 1.1 christos /** If the buffer is fixed it cannot be resized */ 131 1.1 christos unsigned _fixed : 1; 132 1.1 christos 133 1.1 christos /** The current state of the buffer. If writing to the buffer fails 134 1.1 christos * for any reason, this value is changed. This way, you can perform 135 1.1 christos * multiple writes in sequence and check for success afterwards. */ 136 1.1 christos unsigned _status_err : 1; 137 1.1 christos }; 138 1.1 christos typedef struct sldns_buffer sldns_buffer; 139 1.1 christos 140 1.1 christos #ifdef NDEBUG 141 1.1 christos INLINE void 142 1.1 christos sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer)) 143 1.1 christos { 144 1.1 christos } 145 1.1 christos #else 146 1.1 christos INLINE void 147 1.1 christos sldns_buffer_invariant(sldns_buffer *buffer) 148 1.1 christos { 149 1.1 christos assert(buffer != NULL); 150 1.1.1.4 christos assert(buffer->_position <= buffer->_limit); 151 1.1 christos assert(buffer->_limit <= buffer->_capacity); 152 1.1.1.4 christos assert(buffer->_data != NULL); 153 1.1 christos } 154 1.1 christos #endif 155 1.1 christos 156 1.1 christos /** 157 1.1 christos * creates a new buffer with the specified capacity. 158 1.1 christos * 159 1.1 christos * \param[in] capacity the size (in bytes) to allocate for the buffer 160 1.1 christos * \return the created buffer 161 1.1 christos */ 162 1.1 christos sldns_buffer *sldns_buffer_new(size_t capacity); 163 1.1 christos 164 1.1 christos /** 165 1.1 christos * creates a buffer with the specified data. The data IS copied 166 1.1 christos * and MEMORY allocations are done. The buffer is not fixed and can 167 1.1 christos * be resized using buffer_reserve(). 168 1.1 christos * 169 1.1 christos * \param[in] buffer pointer to the buffer to put the data in 170 1.1 christos * \param[in] data the data to encapsulate in the buffer 171 1.1 christos * \param[in] size the size of the data 172 1.1 christos */ 173 1.1 christos void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size); 174 1.1 christos 175 1.1 christos /** 176 1.1 christos * Setup a buffer with the data pointed to. No data copied, no memory allocs. 177 1.1 christos * The buffer is fixed. 178 1.1 christos * \param[in] buffer pointer to the buffer to put the data in 179 1.1 christos * \param[in] data the data to encapsulate in the buffer 180 1.1 christos * \param[in] size the size of the data 181 1.1 christos */ 182 1.1 christos void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size); 183 1.1 christos 184 1.1 christos /** 185 1.1 christos * clears the buffer and make it ready for writing. The buffer's limit 186 1.1 christos * is set to the capacity and the position is set to 0. 187 1.1 christos * \param[in] buffer the buffer to clear 188 1.1 christos */ 189 1.1 christos INLINE void sldns_buffer_clear(sldns_buffer *buffer) 190 1.1 christos { 191 1.1 christos sldns_buffer_invariant(buffer); 192 1.1 christos 193 1.1 christos /* reset status here? */ 194 1.1 christos 195 1.1 christos buffer->_position = 0; 196 1.1 christos buffer->_limit = buffer->_capacity; 197 1.1 christos } 198 1.1 christos 199 1.1 christos /** 200 1.1 christos * makes the buffer ready for reading the data that has been written to 201 1.1 christos * the buffer. The buffer's limit is set to the current position and 202 1.1 christos * the position is set to 0. 203 1.1 christos * 204 1.1 christos * \param[in] buffer the buffer to flip 205 1.1 christos */ 206 1.1 christos INLINE void sldns_buffer_flip(sldns_buffer *buffer) 207 1.1 christos { 208 1.1 christos sldns_buffer_invariant(buffer); 209 1.1 christos 210 1.1 christos buffer->_limit = buffer->_position; 211 1.1 christos buffer->_position = 0; 212 1.1 christos } 213 1.1 christos 214 1.1 christos /** 215 1.1 christos * make the buffer ready for re-reading the data. The buffer's 216 1.1 christos * position is reset to 0. 217 1.1 christos * \param[in] buffer the buffer to rewind 218 1.1 christos */ 219 1.1 christos INLINE void sldns_buffer_rewind(sldns_buffer *buffer) 220 1.1 christos { 221 1.1 christos sldns_buffer_invariant(buffer); 222 1.1 christos 223 1.1 christos buffer->_position = 0; 224 1.1 christos } 225 1.1 christos 226 1.1 christos /** 227 1.1 christos * returns the current position in the buffer (as a number of bytes) 228 1.1 christos * \param[in] buffer the buffer 229 1.1 christos * \return the current position 230 1.1 christos */ 231 1.1 christos INLINE size_t 232 1.1 christos sldns_buffer_position(sldns_buffer *buffer) 233 1.1 christos { 234 1.1 christos return buffer->_position; 235 1.1 christos } 236 1.1 christos 237 1.1 christos /** 238 1.1 christos * sets the buffer's position to MARK. The position must be less than 239 1.1 christos * or equal to the buffer's limit. 240 1.1 christos * \param[in] buffer the buffer 241 1.1 christos * \param[in] mark the mark to use 242 1.1 christos */ 243 1.1 christos INLINE void 244 1.1 christos sldns_buffer_set_position(sldns_buffer *buffer, size_t mark) 245 1.1 christos { 246 1.1.1.4 christos assert(mark <= buffer->_limit); 247 1.1 christos buffer->_position = mark; 248 1.1 christos } 249 1.1 christos 250 1.1 christos /** 251 1.1 christos * changes the buffer's position by COUNT bytes. The position must not 252 1.1 christos * be moved behind the buffer's limit or before the beginning of the 253 1.1 christos * buffer. 254 1.1 christos * \param[in] buffer the buffer 255 1.1 christos * \param[in] count the count to use 256 1.1 christos */ 257 1.1 christos INLINE void 258 1.1 christos sldns_buffer_skip(sldns_buffer *buffer, ssize_t count) 259 1.1 christos { 260 1.1.1.4 christos assert(buffer->_position + count <= buffer->_limit); 261 1.1 christos buffer->_position += count; 262 1.1 christos } 263 1.1 christos 264 1.1 christos /** 265 1.1 christos * returns the maximum size of the buffer 266 1.1 christos * \param[in] buffer 267 1.1 christos * \return the size 268 1.1 christos */ 269 1.1 christos INLINE size_t 270 1.1 christos sldns_buffer_limit(sldns_buffer *buffer) 271 1.1 christos { 272 1.1 christos return buffer->_limit; 273 1.1 christos } 274 1.1 christos 275 1.1 christos /** 276 1.1 christos * changes the buffer's limit. If the buffer's position is greater 277 1.1 christos * than the new limit the position is set to the limit. 278 1.1 christos * \param[in] buffer the buffer 279 1.1 christos * \param[in] limit the new limit 280 1.1 christos */ 281 1.1 christos INLINE void 282 1.1 christos sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit) 283 1.1 christos { 284 1.1 christos assert(limit <= buffer->_capacity); 285 1.1 christos buffer->_limit = limit; 286 1.1 christos if (buffer->_position > buffer->_limit) 287 1.1 christos buffer->_position = buffer->_limit; 288 1.1 christos } 289 1.1 christos 290 1.1 christos /** 291 1.1 christos * returns the number of bytes the buffer can hold. 292 1.1 christos * \param[in] buffer the buffer 293 1.1 christos * \return the number of bytes 294 1.1 christos */ 295 1.1 christos INLINE size_t 296 1.1 christos sldns_buffer_capacity(sldns_buffer *buffer) 297 1.1 christos { 298 1.1 christos return buffer->_capacity; 299 1.1 christos } 300 1.1 christos 301 1.1 christos /** 302 1.1 christos * changes the buffer's capacity. The data is reallocated so any 303 1.1 christos * pointers to the data may become invalid. The buffer's limit is set 304 1.1 christos * to the buffer's new capacity. 305 1.1 christos * \param[in] buffer the buffer 306 1.1 christos * \param[in] capacity the capacity to use 307 1.1 christos * \return whether this failed or succeeded 308 1.1 christos */ 309 1.1 christos int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity); 310 1.1 christos 311 1.1 christos /** 312 1.1 christos * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's 313 1.1 christos * capacity is increased if necessary using buffer_set_capacity(). 314 1.1 christos * 315 1.1 christos * The buffer's limit is always set to the (possibly increased) 316 1.1 christos * capacity. 317 1.1 christos * \param[in] buffer the buffer 318 1.1 christos * \param[in] amount amount to use 319 1.1 christos * \return whether this failed or succeeded 320 1.1 christos */ 321 1.1 christos int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount); 322 1.1 christos 323 1.1 christos /** 324 1.1 christos * returns a pointer to the data at the indicated position. 325 1.1 christos * \param[in] buffer the buffer 326 1.1 christos * \param[in] at position 327 1.1 christos * \return the pointer to the data 328 1.1 christos */ 329 1.1 christos INLINE uint8_t * 330 1.1 christos sldns_buffer_at(const sldns_buffer *buffer, size_t at) 331 1.1 christos { 332 1.1.1.4 christos assert(at <= buffer->_limit); 333 1.1 christos return buffer->_data + at; 334 1.1 christos } 335 1.1 christos 336 1.1 christos /** 337 1.1 christos * returns a pointer to the beginning of the buffer (the data at 338 1.1 christos * position 0). 339 1.1 christos * \param[in] buffer the buffer 340 1.1 christos * \return the pointer 341 1.1 christos */ 342 1.1 christos INLINE uint8_t * 343 1.1 christos sldns_buffer_begin(const sldns_buffer *buffer) 344 1.1 christos { 345 1.1 christos return sldns_buffer_at(buffer, 0); 346 1.1 christos } 347 1.1 christos 348 1.1 christos /** 349 1.1 christos * returns a pointer to the end of the buffer (the data at the buffer's 350 1.1 christos * limit). 351 1.1 christos * \param[in] buffer the buffer 352 1.1 christos * \return the pointer 353 1.1 christos */ 354 1.1 christos INLINE uint8_t * 355 1.1 christos sldns_buffer_end(sldns_buffer *buffer) 356 1.1 christos { 357 1.1 christos return sldns_buffer_at(buffer, buffer->_limit); 358 1.1 christos } 359 1.1 christos 360 1.1 christos /** 361 1.1 christos * returns a pointer to the data at the buffer's current position. 362 1.1 christos * \param[in] buffer the buffer 363 1.1 christos * \return the pointer 364 1.1 christos */ 365 1.1 christos INLINE uint8_t * 366 1.1 christos sldns_buffer_current(sldns_buffer *buffer) 367 1.1 christos { 368 1.1 christos return sldns_buffer_at(buffer, buffer->_position); 369 1.1 christos } 370 1.1 christos 371 1.1 christos /** 372 1.1 christos * returns the number of bytes remaining between the indicated position and 373 1.1 christos * the limit. 374 1.1 christos * \param[in] buffer the buffer 375 1.1 christos * \param[in] at indicated position 376 1.1 christos * \return number of bytes 377 1.1 christos */ 378 1.1 christos INLINE size_t 379 1.1 christos sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at) 380 1.1 christos { 381 1.1 christos sldns_buffer_invariant(buffer); 382 1.1.1.4 christos assert(at <= buffer->_limit); 383 1.1.1.2 christos return at < buffer->_limit ? buffer->_limit - at : 0; 384 1.1 christos } 385 1.1 christos 386 1.1 christos /** 387 1.1 christos * returns the number of bytes remaining between the buffer's position and 388 1.1 christos * limit. 389 1.1 christos * \param[in] buffer the buffer 390 1.1 christos * \return the number of bytes 391 1.1 christos */ 392 1.1 christos INLINE size_t 393 1.1 christos sldns_buffer_remaining(sldns_buffer *buffer) 394 1.1 christos { 395 1.1 christos return sldns_buffer_remaining_at(buffer, buffer->_position); 396 1.1 christos } 397 1.1 christos 398 1.1 christos /** 399 1.1 christos * checks if the buffer has at least COUNT more bytes available. 400 1.1 christos * Before reading or writing the caller needs to ensure enough space 401 1.1 christos * is available! 402 1.1 christos * \param[in] buffer the buffer 403 1.1 christos * \param[in] at indicated position 404 1.1 christos * \param[in] count how much is available 405 1.1 christos * \return true or false (as int?) 406 1.1 christos */ 407 1.1 christos INLINE int 408 1.1 christos sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count) 409 1.1 christos { 410 1.1 christos return count <= sldns_buffer_remaining_at(buffer, at); 411 1.1 christos } 412 1.1 christos 413 1.1 christos /** 414 1.1 christos * checks if the buffer has count bytes available at the current position 415 1.1 christos * \param[in] buffer the buffer 416 1.1 christos * \param[in] count how much is available 417 1.1 christos * \return true or false (as int?) 418 1.1 christos */ 419 1.1 christos INLINE int 420 1.1 christos sldns_buffer_available(sldns_buffer *buffer, size_t count) 421 1.1 christos { 422 1.1 christos return sldns_buffer_available_at(buffer, buffer->_position, count); 423 1.1 christos } 424 1.1 christos 425 1.1 christos /** 426 1.1 christos * writes the given data to the buffer at the specified position 427 1.1 christos * \param[in] buffer the buffer 428 1.1 christos * \param[in] at the position (in number of bytes) to write the data at 429 1.1 christos * \param[in] data pointer to the data to write to the buffer 430 1.1 christos * \param[in] count the number of bytes of data to write 431 1.1 christos */ 432 1.1 christos INLINE void 433 1.1 christos sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count) 434 1.1 christos { 435 1.1.1.4 christos assert(sldns_buffer_available_at(buffer, at, count)); 436 1.1 christos memcpy(buffer->_data + at, data, count); 437 1.1 christos } 438 1.1 christos 439 1.1 christos /** 440 1.1.1.2 christos * set the given byte to the buffer at the specified position 441 1.1.1.2 christos * \param[in] buffer the buffer 442 1.1.1.2 christos * \param[in] at the position (in number of bytes) to write the data at 443 1.1.1.2 christos * \param[in] c the byte to set to the buffer 444 1.1.1.2 christos * \param[in] count the number of bytes of bytes to write 445 1.1.1.2 christos */ 446 1.1.1.2 christos 447 1.1.1.2 christos INLINE void 448 1.1.1.2 christos sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count) 449 1.1.1.2 christos { 450 1.1.1.4 christos assert(sldns_buffer_available_at(buffer, at, count)); 451 1.1.1.2 christos memset(buffer->_data + at, c, count); 452 1.1.1.2 christos } 453 1.1.1.2 christos 454 1.1.1.2 christos 455 1.1.1.2 christos /** 456 1.1 christos * writes count bytes of data to the current position of the buffer 457 1.1 christos * \param[in] buffer the buffer 458 1.1 christos * \param[in] data the data to write 459 1.1.1.2 christos * \param[in] count the length of the data to write 460 1.1 christos */ 461 1.1 christos INLINE void 462 1.1 christos sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count) 463 1.1 christos { 464 1.1 christos sldns_buffer_write_at(buffer, buffer->_position, data, count); 465 1.1 christos buffer->_position += count; 466 1.1 christos } 467 1.1 christos 468 1.1 christos /** 469 1.1 christos * copies the given (null-delimited) string to the specified position at the buffer 470 1.1 christos * \param[in] buffer the buffer 471 1.1 christos * \param[in] at the position in the buffer 472 1.1 christos * \param[in] str the string to write 473 1.1 christos */ 474 1.1 christos INLINE void 475 1.1 christos sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str) 476 1.1 christos { 477 1.1 christos sldns_buffer_write_at(buffer, at, str, strlen(str)); 478 1.1 christos } 479 1.1 christos 480 1.1 christos /** 481 1.1 christos * copies the given (null-delimited) string to the current position at the buffer 482 1.1 christos * \param[in] buffer the buffer 483 1.1 christos * \param[in] str the string to write 484 1.1 christos */ 485 1.1 christos INLINE void 486 1.1 christos sldns_buffer_write_string(sldns_buffer *buffer, const char *str) 487 1.1 christos { 488 1.1 christos sldns_buffer_write(buffer, str, strlen(str)); 489 1.1 christos } 490 1.1 christos 491 1.1 christos /** 492 1.1 christos * writes the given byte of data at the given position in the buffer 493 1.1 christos * \param[in] buffer the buffer 494 1.1 christos * \param[in] at the position in the buffer 495 1.1 christos * \param[in] data the 8 bits to write 496 1.1 christos */ 497 1.1 christos INLINE void 498 1.1 christos sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data) 499 1.1 christos { 500 1.1 christos assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 501 1.1 christos buffer->_data[at] = data; 502 1.1 christos } 503 1.1 christos 504 1.1 christos /** 505 1.1 christos * writes the given byte of data at the current position in the buffer 506 1.1 christos * \param[in] buffer the buffer 507 1.1 christos * \param[in] data the 8 bits to write 508 1.1 christos */ 509 1.1 christos INLINE void 510 1.1 christos sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data) 511 1.1 christos { 512 1.1 christos sldns_buffer_write_u8_at(buffer, buffer->_position, data); 513 1.1 christos buffer->_position += sizeof(data); 514 1.1 christos } 515 1.1 christos 516 1.1 christos /** 517 1.1 christos * writes the given 2 byte integer at the given position in the buffer 518 1.1 christos * \param[in] buffer the buffer 519 1.1 christos * \param[in] at the position in the buffer 520 1.1 christos * \param[in] data the 16 bits to write 521 1.1 christos */ 522 1.1 christos INLINE void 523 1.1 christos sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data) 524 1.1 christos { 525 1.1 christos assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 526 1.1 christos sldns_write_uint16(buffer->_data + at, data); 527 1.1 christos } 528 1.1 christos 529 1.1 christos /** 530 1.1 christos * writes the given 2 byte integer at the current position in the buffer 531 1.1 christos * \param[in] buffer the buffer 532 1.1 christos * \param[in] data the 16 bits to write 533 1.1 christos */ 534 1.1 christos INLINE void 535 1.1 christos sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data) 536 1.1 christos { 537 1.1 christos sldns_buffer_write_u16_at(buffer, buffer->_position, data); 538 1.1 christos buffer->_position += sizeof(data); 539 1.1 christos } 540 1.1 christos 541 1.1 christos /** 542 1.1 christos * writes the given 4 byte integer at the given position in the buffer 543 1.1 christos * \param[in] buffer the buffer 544 1.1 christos * \param[in] at the position in the buffer 545 1.1 christos * \param[in] data the 32 bits to write 546 1.1 christos */ 547 1.1 christos INLINE void 548 1.1 christos sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data) 549 1.1 christos { 550 1.1 christos assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 551 1.1 christos sldns_write_uint32(buffer->_data + at, data); 552 1.1 christos } 553 1.1 christos 554 1.1 christos /** 555 1.1.1.2 christos * writes the given 6 byte integer at the given position in the buffer 556 1.1.1.2 christos * \param[in] buffer the buffer 557 1.1.1.2 christos * \param[in] at the position in the buffer 558 1.1.1.2 christos * \param[in] data the (lower) 48 bits to write 559 1.1.1.2 christos */ 560 1.1.1.2 christos INLINE void 561 1.1.1.2 christos sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data) 562 1.1.1.2 christos { 563 1.1.1.2 christos assert(sldns_buffer_available_at(buffer, at, 6)); 564 1.1.1.2 christos sldns_write_uint48(buffer->_data + at, data); 565 1.1.1.2 christos } 566 1.1.1.2 christos 567 1.1.1.2 christos /** 568 1.1 christos * writes the given 4 byte integer at the current position in the buffer 569 1.1 christos * \param[in] buffer the buffer 570 1.1 christos * \param[in] data the 32 bits to write 571 1.1 christos */ 572 1.1 christos INLINE void 573 1.1 christos sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data) 574 1.1 christos { 575 1.1 christos sldns_buffer_write_u32_at(buffer, buffer->_position, data); 576 1.1 christos buffer->_position += sizeof(data); 577 1.1 christos } 578 1.1 christos 579 1.1 christos /** 580 1.1.1.2 christos * writes the given 6 byte integer at the current position in the buffer 581 1.1.1.2 christos * \param[in] buffer the buffer 582 1.1.1.2 christos * \param[in] data the 48 bits to write 583 1.1.1.2 christos */ 584 1.1.1.2 christos INLINE void 585 1.1.1.2 christos sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data) 586 1.1.1.2 christos { 587 1.1.1.2 christos sldns_buffer_write_u48_at(buffer, buffer->_position, data); 588 1.1.1.2 christos buffer->_position += 6; 589 1.1.1.2 christos } 590 1.1.1.2 christos 591 1.1.1.2 christos /** 592 1.1 christos * copies count bytes of data at the given position to the given data-array 593 1.1 christos * \param[in] buffer the buffer 594 1.1 christos * \param[in] at the position in the buffer to start 595 1.1 christos * \param[out] data buffer to copy to 596 1.1 christos * \param[in] count the length of the data to copy 597 1.1 christos */ 598 1.1 christos INLINE void 599 1.1 christos sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count) 600 1.1 christos { 601 1.1 christos assert(sldns_buffer_available_at(buffer, at, count)); 602 1.1 christos memcpy(data, buffer->_data + at, count); 603 1.1 christos } 604 1.1 christos 605 1.1 christos /** 606 1.1 christos * copies count bytes of data at the current position to the given data-array 607 1.1 christos * \param[in] buffer the buffer 608 1.1 christos * \param[out] data buffer to copy to 609 1.1 christos * \param[in] count the length of the data to copy 610 1.1 christos */ 611 1.1 christos INLINE void 612 1.1 christos sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count) 613 1.1 christos { 614 1.1 christos sldns_buffer_read_at(buffer, buffer->_position, data, count); 615 1.1 christos buffer->_position += count; 616 1.1 christos } 617 1.1 christos 618 1.1 christos /** 619 1.1 christos * returns the byte value at the given position in the buffer 620 1.1 christos * \param[in] buffer the buffer 621 1.1 christos * \param[in] at the position in the buffer 622 1.1 christos * \return 1 byte integer 623 1.1 christos */ 624 1.1 christos INLINE uint8_t 625 1.1 christos sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at) 626 1.1 christos { 627 1.1 christos assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t))); 628 1.1 christos return buffer->_data[at]; 629 1.1 christos } 630 1.1 christos 631 1.1 christos /** 632 1.1 christos * returns the byte value at the current position in the buffer 633 1.1 christos * \param[in] buffer the buffer 634 1.1 christos * \return 1 byte integer 635 1.1 christos */ 636 1.1 christos INLINE uint8_t 637 1.1 christos sldns_buffer_read_u8(sldns_buffer *buffer) 638 1.1 christos { 639 1.1 christos uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position); 640 1.1 christos buffer->_position += sizeof(uint8_t); 641 1.1 christos return result; 642 1.1 christos } 643 1.1 christos 644 1.1 christos /** 645 1.1 christos * returns the 2-byte integer value at the given position in the buffer 646 1.1 christos * \param[in] buffer the buffer 647 1.1 christos * \param[in] at position in the buffer 648 1.1 christos * \return 2 byte integer 649 1.1 christos */ 650 1.1 christos INLINE uint16_t 651 1.1 christos sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at) 652 1.1 christos { 653 1.1 christos assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t))); 654 1.1 christos return sldns_read_uint16(buffer->_data + at); 655 1.1 christos } 656 1.1 christos 657 1.1 christos /** 658 1.1 christos * returns the 2-byte integer value at the current position in the buffer 659 1.1 christos * \param[in] buffer the buffer 660 1.1 christos * \return 2 byte integer 661 1.1 christos */ 662 1.1 christos INLINE uint16_t 663 1.1 christos sldns_buffer_read_u16(sldns_buffer *buffer) 664 1.1 christos { 665 1.1 christos uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position); 666 1.1 christos buffer->_position += sizeof(uint16_t); 667 1.1 christos return result; 668 1.1 christos } 669 1.1 christos 670 1.1 christos /** 671 1.1 christos * returns the 4-byte integer value at the given position in the buffer 672 1.1 christos * \param[in] buffer the buffer 673 1.1 christos * \param[in] at position in the buffer 674 1.1 christos * \return 4 byte integer 675 1.1 christos */ 676 1.1 christos INLINE uint32_t 677 1.1 christos sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at) 678 1.1 christos { 679 1.1 christos assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t))); 680 1.1 christos return sldns_read_uint32(buffer->_data + at); 681 1.1 christos } 682 1.1 christos 683 1.1 christos /** 684 1.1 christos * returns the 4-byte integer value at the current position in the buffer 685 1.1 christos * \param[in] buffer the buffer 686 1.1 christos * \return 4 byte integer 687 1.1 christos */ 688 1.1 christos INLINE uint32_t 689 1.1 christos sldns_buffer_read_u32(sldns_buffer *buffer) 690 1.1 christos { 691 1.1 christos uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position); 692 1.1 christos buffer->_position += sizeof(uint32_t); 693 1.1 christos return result; 694 1.1 christos } 695 1.1 christos 696 1.1 christos /** 697 1.1 christos * returns the status of the buffer 698 1.1 christos * \param[in] buffer 699 1.1 christos * \return the status 700 1.1 christos */ 701 1.1 christos INLINE int 702 1.1 christos sldns_buffer_status(sldns_buffer *buffer) 703 1.1 christos { 704 1.1 christos return (int)buffer->_status_err; 705 1.1 christos } 706 1.1 christos 707 1.1 christos /** 708 1.1 christos * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise 709 1.1 christos * \param[in] buffer the buffer 710 1.1 christos * \return true or false 711 1.1 christos */ 712 1.1 christos INLINE int 713 1.1 christos sldns_buffer_status_ok(sldns_buffer *buffer) 714 1.1 christos { 715 1.1 christos if (buffer) { 716 1.1 christos return sldns_buffer_status(buffer) == 0; 717 1.1 christos } else { 718 1.1 christos return 0; 719 1.1 christos } 720 1.1 christos } 721 1.1 christos 722 1.1 christos /** 723 1.1 christos * prints to the buffer, increasing the capacity if required using 724 1.1 christos * buffer_reserve(). The buffer's position is set to the terminating '\\0' 725 1.1 christos * Returns the number of characters written (not including the 726 1.1 christos * terminating '\\0') or -1 on failure. 727 1.1 christos */ 728 1.1 christos int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) 729 1.1 christos ATTR_FORMAT(printf, 2, 3); 730 1.1 christos 731 1.1 christos /** 732 1.1 christos * frees the buffer. 733 1.1 christos * \param[in] *buffer the buffer to be freed 734 1.1 christos */ 735 1.1 christos void sldns_buffer_free(sldns_buffer *buffer); 736 1.1 christos 737 1.1 christos /** 738 1.1 christos * Copy contents of the from buffer to the result buffer and then flips 739 1.1 christos * the result buffer. Data will be silently truncated if the result buffer is 740 1.1 christos * too small. 741 1.1 christos * \param[out] *result resulting buffer which is copied to. 742 1.1 christos * \param[in] *from what to copy to result. 743 1.1 christos */ 744 1.1 christos void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from); 745 1.1 christos 746 1.1 christos #ifdef __cplusplus 747 1.1 christos } 748 1.1 christos #endif 749 1.1 christos 750 1.1 christos #endif /* LDNS_SBUFFER_H */ 751