iPXE
linebuf.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/**
28 * @file
29 *
30 * Line buffering
31 *
32 */
33
34#include <stdint.h>
35#include <string.h>
36#include <stdlib.h>
37#include <errno.h>
38#include <ipxe/linebuf.h>
39
40/**
41 * Retrieve buffered-up line
42 *
43 * @v linebuf Line buffer
44 * @ret line Buffered line, or NULL if no line ready to read
45 */
46char * buffered_line ( struct line_buffer *linebuf ) {
47 char *line = &linebuf->data[ linebuf->len ];
48
49 /* Fail unless we have a newly completed line to retrieve */
50 if ( ( linebuf->len == 0 ) || ( linebuf->consumed == 0 ) ||
51 ( *(--line) != '\0' ) )
52 return NULL;
53
54 /* Identify start of line */
55 while ( ( line > linebuf->data ) && ( line[-1] != '\0' ) )
56 line--;
57
58 return line;
59}
60
61/**
62 * Discard line buffer contents
63 *
64 * @v linebuf Line buffer
65 */
66void empty_line_buffer ( struct line_buffer *linebuf ) {
67
68 free ( linebuf->data );
69 linebuf->data = NULL;
70 linebuf->len = 0;
71 linebuf->consumed = 0;
72}
73
74/**
75 * Buffer up received data by lines
76 *
77 * @v linebuf Line buffer
78 * @v data New data to add
79 * @v len Length of new data to add
80 * @ret len Consumed length, or negative error number
81 *
82 * After calling line_buffer(), use buffered_line() to determine
83 * whether or not a complete line is available. Carriage returns and
84 * newlines will have been stripped, and the line will be
85 * NUL-terminated. This buffered line is valid only until the next
86 * call to line_buffer() (or to empty_line_buffer()).
87 *
88 * Note that line buffers use dynamically allocated storage; you
89 * should call empty_line_buffer() before freeing a @c struct @c
90 * line_buffer.
91 */
92int line_buffer ( struct line_buffer *linebuf, const char *data, size_t len ) {
93 const char *eol;
94 size_t consume;
95 size_t new_len;
96 char *new_data;
97 char *lf;
98 char *cr;
99
100 /* Search for line terminator */
101 if ( ( eol = memchr ( data, '\n', len ) ) ) {
102 consume = ( eol - data + 1 );
103 } else {
104 consume = len;
105 }
106
107 /* Reject any embedded NULs within the data to be consumed */
108 if ( memchr ( data, '\0', consume ) )
109 return -EINVAL;
110
111 /* Reallocate data buffer and copy in new data */
112 new_len = ( linebuf->len + consume );
113 new_data = realloc ( linebuf->data, ( new_len + 1 ) );
114 if ( ! new_data )
115 return -ENOMEM;
116 memcpy ( ( new_data + linebuf->len ), data, consume );
117 new_data[new_len] = '\0';
118 linebuf->data = new_data;
119 linebuf->len = new_len;
120
121 /* If we have reached end of line, terminate the line */
122 if ( eol ) {
123
124 /* Overwrite trailing LF (which must exist at this point) */
125 assert ( linebuf->len > 0 );
126 lf = &linebuf->data[ linebuf->len - 1 ];
127 assert ( *lf == '\n' );
128 *lf = '\0';
129
130 /* Trim (and overwrite) trailing CR, if present */
131 if ( linebuf->len > 1 ) {
132 cr = ( lf - 1 );
133 if ( *cr == '\r' ) {
134 linebuf->len--;
135 *cr = '\0';
136 }
137 }
138 }
139
140 /* Record consumed length */
141 linebuf->consumed = consume;
142
143 return consume;
144}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
int line_buffer(struct line_buffer *linebuf, const char *data, size_t len)
Buffer up received data by lines.
Definition linebuf.c:92
char * buffered_line(struct line_buffer *linebuf)
Retrieve buffered-up line.
Definition linebuf.c:46
void empty_line_buffer(struct line_buffer *linebuf)
Discard line buffer contents.
Definition linebuf.c:66
Line buffering.
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:607
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
@ cr
Definition sis900.h:22
void * memchr(const void *src, int character, size_t len)
Find character within a memory region.
Definition string.c:136
A line buffer.
Definition linebuf.h:17
size_t len
Length of buffered data.
Definition linebuf.h:21
char * data
Data buffer.
Definition linebuf.h:19
size_t consumed
Most recently consumed length.
Definition linebuf.h:23