зеркало из https://github.com/microsoft/git.git
pkt-line: allow peeking a packet line without consuming it
Sometimes it is advantageous to be able to peek the next packet line without consuming it (e.g. to be able to determine the protocol version a server is speaking). In order to do that introduce 'struct packet_reader' which is an abstraction around the normal packet reading logic. This enables a caller to be able to peek a single line at a time using 'packet_reader_peek()' and having a caller consume a line by calling 'packet_reader_read()'. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
2153d478b7
Коммит
77dabc14c4
50
pkt-line.c
50
pkt-line.c
|
@ -400,3 +400,53 @@ ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
|
|||
}
|
||||
return sb_out->len - orig_len;
|
||||
}
|
||||
|
||||
/* Packet Reader Functions */
|
||||
void packet_reader_init(struct packet_reader *reader, int fd,
|
||||
char *src_buffer, size_t src_len,
|
||||
int options)
|
||||
{
|
||||
memset(reader, 0, sizeof(*reader));
|
||||
|
||||
reader->fd = fd;
|
||||
reader->src_buffer = src_buffer;
|
||||
reader->src_len = src_len;
|
||||
reader->buffer = packet_buffer;
|
||||
reader->buffer_size = sizeof(packet_buffer);
|
||||
reader->options = options;
|
||||
}
|
||||
|
||||
enum packet_read_status packet_reader_read(struct packet_reader *reader)
|
||||
{
|
||||
if (reader->line_peeked) {
|
||||
reader->line_peeked = 0;
|
||||
return reader->status;
|
||||
}
|
||||
|
||||
reader->status = packet_read_with_status(reader->fd,
|
||||
&reader->src_buffer,
|
||||
&reader->src_len,
|
||||
reader->buffer,
|
||||
reader->buffer_size,
|
||||
&reader->pktlen,
|
||||
reader->options);
|
||||
|
||||
if (reader->status == PACKET_READ_NORMAL)
|
||||
reader->line = reader->buffer;
|
||||
else
|
||||
reader->line = NULL;
|
||||
|
||||
return reader->status;
|
||||
}
|
||||
|
||||
enum packet_read_status packet_reader_peek(struct packet_reader *reader)
|
||||
{
|
||||
/* Only allow peeking a single line */
|
||||
if (reader->line_peeked)
|
||||
return reader->status;
|
||||
|
||||
/* Peek a line by reading it and setting peeked flag */
|
||||
packet_reader_read(reader);
|
||||
reader->line_peeked = 1;
|
||||
return reader->status;
|
||||
}
|
||||
|
|
58
pkt-line.h
58
pkt-line.h
|
@ -112,6 +112,64 @@ char *packet_read_line_buf(char **src_buf, size_t *src_len, int *size);
|
|||
*/
|
||||
ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out);
|
||||
|
||||
struct packet_reader {
|
||||
/* source file descriptor */
|
||||
int fd;
|
||||
|
||||
/* source buffer and its size */
|
||||
char *src_buffer;
|
||||
size_t src_len;
|
||||
|
||||
/* buffer that pkt-lines are read into and its size */
|
||||
char *buffer;
|
||||
unsigned buffer_size;
|
||||
|
||||
/* options to be used during reads */
|
||||
int options;
|
||||
|
||||
/* status of the last read */
|
||||
enum packet_read_status status;
|
||||
|
||||
/* length of data read during the last read */
|
||||
int pktlen;
|
||||
|
||||
/* the last line read */
|
||||
const char *line;
|
||||
|
||||
/* indicates if a line has been peeked */
|
||||
int line_peeked;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a 'struct packet_reader' object which is an
|
||||
* abstraction around the 'packet_read_with_status()' function.
|
||||
*/
|
||||
extern void packet_reader_init(struct packet_reader *reader, int fd,
|
||||
char *src_buffer, size_t src_len,
|
||||
int options);
|
||||
|
||||
/*
|
||||
* Perform a packet read and return the status of the read.
|
||||
* The values of 'pktlen' and 'line' are updated based on the status of the
|
||||
* read as follows:
|
||||
*
|
||||
* PACKET_READ_ERROR: 'pktlen' is set to '-1' and 'line' is set to NULL
|
||||
* PACKET_READ_NORMAL: 'pktlen' is set to the number of bytes read
|
||||
* 'line' is set to point at the read line
|
||||
* PACKET_READ_FLUSH: 'pktlen' is set to '0' and 'line' is set to NULL
|
||||
*/
|
||||
extern enum packet_read_status packet_reader_read(struct packet_reader *reader);
|
||||
|
||||
/*
|
||||
* Peek the next packet line without consuming it and return the status.
|
||||
* The next call to 'packet_reader_read()' will perform a read of the same line
|
||||
* that was peeked, consuming the line.
|
||||
*
|
||||
* Peeking multiple times without calling 'packet_reader_read()' will return
|
||||
* the same result.
|
||||
*/
|
||||
extern enum packet_read_status packet_reader_peek(struct packet_reader *reader);
|
||||
|
||||
#define DEFAULT_PACKET_MAX 1000
|
||||
#define LARGE_PACKET_MAX 65520
|
||||
#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - 4)
|
||||
|
|
Загрузка…
Ссылка в новой задаче