Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | /* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (c) 2015 Google, Inc * Written by Simon Glass <sjg@chromium.org> * * Copyright (c) 1992 Simon Glass */ #ifndef _membuf_H #define _membuf_H #include <stdbool.h> /* Set this to 1 to support a 'full' flag */ #define MEMBUF_FULL 0 /** * @struct membuf: holds the state of a membuff - it is used for input and * output buffers. The buffer extends from @start to (@start + @size - 1). * Data in the buffer extends from @tail to @head: it is written in at * @head and read out from @tail. The membuff is empty when @head == @tail * and full when adding another character would make @head == @tail. We * therefore waste one character in the membuff to avoid having an extra flag * to determine whether (when @head == @tail) the membuff is empty or full. * * xxxxxx data * ...... empty * * .............xxxxxxxxxxxxxxxx......................... * ^ ^ * ^start tail head ^end * * xxxxxxxxxxxxx................xxxxxxxxxxxxxxxxxxxxxxxxx * ^ ^ * head tail */ struct membuf { char *start; /** the start of the buffer */ char *end; /** the end of the buffer (start + length) */ char *head; /** current buffer head */ char *tail; /** current buffer tail */ #if MEMBUF_FULL bool full; /** true if full (for when head == tail) */ #endif }; /** * membuf_purge() - reset a membuff to the empty state * * Initialise head and tail pointers so that the membuff becomes empty. * * @mb: membuff to purge */ void membuf_purge(struct membuf *mb); /** * membuf_putraw() - find out where bytes can be written * * Work out where in the membuff some data could be written. Return a pointer * to the address and the number of bytes which can be written there. If * @update is true, the caller must then write the data immediately, since * the membuff is updated as if the write has been done, * * Note that because the spare space in a membuff may not be contiguous, this * function may not return @maxlen even if there is enough space in the * membuff. However, by calling this function twice (with @update == true), * you will get access to all the spare space. * * @mb: membuff to adjust * @maxlen: the number of bytes we want to write * @update: true to update the membuff as if the write happened, false to not * @data: the address data can be written to * Return: number of bytes which can be written */ int membuf_putraw(struct membuf *mb, int maxlen, bool update, char **data); /** * membuf_getraw() - find and return a pointer to available bytes * * Returns a pointer to any valid input data in the given membuff and * optionally marks it as read. Note that not all input data may not be * returned, since data is not necessarily contiguous in the membuff. However, * if you call this function twice (with @update == true) you are guaranteed * to get all available data, in at most two installments. * * @mb: membuff to adjust * @maxlen: maximum number of bytes to get * @update: true to update the membuff as if the bytes have been read (use * false to check bytes without reading them) * @data: returns address of data in input membuff * Return: the number of bytes available at *@data */ int membuf_getraw(struct membuf *mb, int maxlen, bool update, char **data); /** * membuf_putbyte() - Writes a byte to a membuff * * @mb: membuff to adjust * @ch: byte to write * Return: true on success, false if membuff is full */ bool membuf_putbyte(struct membuf *mb, int ch); /** * @mb: membuff to adjust * membuf_getbyte() - Read a byte from the membuff * Return: the byte read, or -1 if the membuff is empty */ int membuf_getbyte(struct membuf *mb); /** * membuf_peekbyte() - check the next available byte * * Return the next byte which membuf_getbyte() would return, without * removing it from the membuff. * * @mb: membuff to adjust * Return: the byte peeked, or -1 if the membuff is empty */ int membuf_peekbyte(struct membuf *mb); /** * membuf_get() - get data from a membuff * * Copies any available data (up to @maxlen bytes) to @buff and removes it * from the membuff. * * @mb: membuff to adjust * @Buff: address of membuff to transfer bytes to * @maxlen: maximum number of bytes to read * Return: the number of bytes read */ int membuf_get(struct membuf *mb, char *buff, int maxlen); /** * membuf_put() - write data to a membuff * * Writes some data to a membuff. Returns the number of bytes added. If this * is less than @lnehgt, then the membuff got full * * @mb: membuff to adjust * @data: the data to write * @length: number of bytes to write from 'data' * Return: the number of bytes added */ int membuf_put(struct membuf *mb, const char *buff, int length); /** * membuf_isempty() - check if a membuff is empty * * @mb: membuff to check * Return: true if empty, else false */ bool membuf_isempty(struct membuf *mb); /** * membuf_avail() - check available data in a membuff * * @mb: membuff to check * Return: number of bytes of data available */ int membuf_avail(struct membuf *mb); /** * membuf_size() - get the size of a membuff * * Note that a membuff can only old data up to one byte less than its size. * * @mb: membuff to check * Return: total size */ int membuf_size(struct membuf *mb); /** * membuf_makecontig() - adjust all membuff data to be contiguous * * This places all data in a membuff into a single contiguous lump, if * possible * * @mb: membuff to adjust * Return: true on success */ bool membuf_makecontig(struct membuf *mb); /** * membuf_free() - find the number of bytes that can be written to a membuff * * @mb: membuff to check * Return: returns the number of bytes free in a membuff */ int membuf_free(struct membuf *mb); /** * membuf_readline() - read a line of text from a membuff * * Reads a line of text of up to 'maxlen' characters from a membuff and puts * it in @str. Any character less than @minch is assumed to be the end of * line character * * @mb: membuff to adjust * @str: Place to put the line * @maxlen: Maximum line length (excluding terminator) * @minch: Minimum ASCII character to permit as part of the line (e.g. ' ') * @must_fit: If true then str is empty if line doesn't fit * Return: number of bytes read (including terminator) if a line has been * read, 0 if nothing was there or line didn't fit when must_fit is set */ int membuf_readline(struct membuf *mb, char *str, int maxlen, int minch, bool must_fit); /** * membuf_extend_by() - expand a membuff * * Extends a membuff by the given number of bytes * * @mb: membuff to adjust * @by: Number of bytes to increase the size by * @max: Maximum size to allow * Return: 0 if the expand succeeded, -ENOMEM if not enough memory, -E2BIG * if the the size would exceed @max */ int membuf_extend_by(struct membuf *mb, int by, int max); /** * membuf_init() - set up a new membuff using an existing buffer * * The buffer is initially empty * * @mb: membuff to set up * @buff: Address of buffer * @size: Size of buffer */ void membuf_init(struct membuf *mb, char *buff, int size); /** * membuf_init_with_data() - set up a new membuff using existing data * * The buffer is set up to contain the provided data. with its size set to * @size + 1 (less MEMBUF_FULL), so that there is enough space for the head/tail * differece. * * @mb: membuff to set up * @buff: Address of buffer * @size: Number of bytes to put into the membuf */ void membuf_init_with_data(struct membuf *mb, char *buff, int size); /** * membuf_uninit() - clear a membuff so it can no longer be used * * @mb: membuff to uninit */ void membuf_uninit(struct membuf *mb); /** * membuf_new() - create a new membuff * * @mb: membuff to init * @size: size of membuff to create * Return: 0 if OK, -ENOMEM if out of memory */ int membuf_new(struct membuf *mb, int size); /** * membuf_dispose() - free memory allocated to a membuff and uninit it * * @mb: membuff to dispose */ void membuf_dispose(struct membuf *mb); /** * membuf_printf() - write a formatted string to a membuff * * Formats a string and writes it to the membuff. Returns the number of bytes * written (not including the terminating nul). * * @mb: membuff to write to * @fmt: format string * @...: arguments for format string * Return: number of bytes written, or negative error */ int membuf_printf(struct membuf *mb, const char *fmt, ...); #endif |