buffers.h (4351B)
1 /* Copyright (c) 2001 Matej Pfajfar. 2 * Copyright (c) 2001-2004, Roger Dingledine. 3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 4 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 5 /* See LICENSE for licensing information */ 6 7 /** 8 * \file buffers.h 9 * 10 * \brief Header file for buffers.c. 11 **/ 12 13 #ifndef TOR_BUFFERS_H 14 #define TOR_BUFFERS_H 15 16 #include "lib/cc/compat_compiler.h" 17 #include "lib/cc/torint.h" 18 #include "lib/testsupport/testsupport.h" 19 20 #include <stdarg.h> 21 22 typedef struct buf_t buf_t; 23 24 buf_t *buf_new(void); 25 buf_t *buf_new_with_capacity(size_t size); 26 size_t buf_get_default_chunk_size(const buf_t *buf); 27 void buf_free_(buf_t *buf); 28 #define buf_free(b) FREE_AND_NULL(buf_t, buf_free_, (b)) 29 void buf_clear(buf_t *buf); 30 buf_t *buf_copy(const buf_t *buf); 31 32 /** Maximum bytes in a buffer, inclusive. */ 33 #define BUF_MAX_LEN (INT_MAX - 1) 34 35 MOCK_DECL(size_t, buf_datalen, (const buf_t *buf)); 36 size_t buf_allocation(const buf_t *buf); 37 size_t buf_slack(const buf_t *buf); 38 39 uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now); 40 size_t buf_get_total_allocation(void); 41 42 int buf_add(buf_t *buf, const char *string, size_t string_len); 43 void buf_add_string(buf_t *buf, const char *string); 44 void buf_add_printf(buf_t *buf, const char *format, ...) 45 CHECK_PRINTF(2, 3); 46 void buf_add_vprintf(buf_t *buf, const char *format, va_list args) 47 CHECK_PRINTF(2, 0); 48 int buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen); 49 size_t buf_move_all(buf_t *buf_out, buf_t *buf_in); 50 void buf_peek(const buf_t *buf, char *string, size_t string_len); 51 void buf_drain(buf_t *buf, size_t n); 52 int buf_get_bytes(buf_t *buf, char *string, size_t string_len); 53 int buf_get_line(buf_t *buf, char *data_out, size_t *data_len); 54 55 #define PEEK_BUF_STARTSWITH_MAX 16 56 int buf_peek_startswith(const buf_t *buf, const char *cmd); 57 58 int buf_set_to_copy(buf_t **output, 59 const buf_t *input); 60 61 void buf_assert_ok(buf_t *buf); 62 63 int buf_find_string_offset(const buf_t *buf, const char *s, size_t n); 64 void buf_pullup(buf_t *buf, size_t bytes, 65 const char **head_out, size_t *len_out); 66 char *buf_extract(buf_t *buf, size_t *sz_out); 67 68 #ifdef BUFFERS_PRIVATE 69 #ifdef TOR_UNIT_TESTS 70 buf_t *buf_new_with_data(const char *cp, size_t sz); 71 #endif 72 size_t buf_preferred_chunk_size(size_t target); 73 74 #define DEBUG_CHUNK_ALLOC 75 /** A single chunk on a buffer. */ 76 typedef struct chunk_t { 77 struct chunk_t *next; /**< The next chunk on the buffer. */ 78 size_t datalen; /**< The number of bytes stored in this chunk */ 79 size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */ 80 #ifdef DEBUG_CHUNK_ALLOC 81 size_t DBG_alloc; 82 #endif 83 char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */ 84 uint32_t inserted_time; /**< Timestamp when this chunk was inserted. */ 85 char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in 86 * this chunk. */ 87 } chunk_t; 88 89 /** Magic value for buf_t.magic, to catch pointer errors. */ 90 #define BUFFER_MAGIC 0xB0FFF312u 91 /** A resizeable buffer, optimized for reading and writing. */ 92 struct buf_t { 93 uint32_t magic; /**< Magic cookie for debugging: Must be set to 94 * BUFFER_MAGIC. */ 95 size_t datalen; /**< How many bytes is this buffer holding right now? */ 96 size_t default_chunk_size; /**< Don't allocate any chunks smaller than 97 * this for this buffer. */ 98 chunk_t *head; /**< First chunk in the list, or NULL for none. */ 99 chunk_t *tail; /**< Last chunk in the list, or NULL for none. */ 100 }; 101 102 chunk_t *buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped); 103 /** If a read onto the end of a chunk would be smaller than this number, then 104 * just start a new chunk. */ 105 #define MIN_READ_LEN 8 106 107 /** Return the number of bytes that can be written onto <b>chunk</b> without 108 * running out of space. */ 109 static inline size_t 110 CHUNK_REMAINING_CAPACITY(const chunk_t *chunk) 111 { 112 return (chunk->mem + chunk->memlen) - (chunk->data + chunk->datalen); 113 } 114 115 /** Return the next character in <b>chunk</b> onto which data can be appended. 116 * If the chunk is full, this might be off the end of chunk->mem. */ 117 static inline char * 118 CHUNK_WRITE_PTR(chunk_t *chunk) 119 { 120 return chunk->data + chunk->datalen; 121 } 122 123 #endif /* defined(BUFFERS_PRIVATE) */ 124 125 #endif /* !defined(TOR_BUFFERS_H) */