Implement buffer reader functions
This functionality allows us to read data out of a buffer without irrevocably consuming it. We read what we can, and when we're done we throw the reader away. The plan is to read as much of a stream of data as is available, and if we can't read a complete message, we simply toss the reader away and try again when we get more data. I think that perhaps this strategy might be easier than coming up with a state machine to parse the stream. Please do not advance the underlying buffer while trying to use a reader.
This commit is contained in:
parent
b5302fee81
commit
056cdff7ce
2 changed files with 118 additions and 7 deletions
|
|
@ -121,22 +121,125 @@ void Buffer_Clear(buffer_t *buf)
|
|||
}
|
||||
|
||||
//
|
||||
// Create a new buffer reader
|
||||
// Create a new buffer reader.
|
||||
//
|
||||
// WARNING: This reader will invalidate if the underlying buffer changes.
|
||||
// Use it, then delete it before you touch the underlying buffer again.
|
||||
//
|
||||
buffer_reader_t *NewReader(buffer_t* buffer)
|
||||
{
|
||||
buffer_reader_t *reader = malloc(sizeof(buffer_reader_t));
|
||||
|
||||
reader->buffer = buffer;
|
||||
reader->pos = 0;
|
||||
reader->pos = buffer->data;
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
//
|
||||
// Delete a buffer reader
|
||||
// Delete a buffer reader.
|
||||
//
|
||||
void DeleteReader(buffer_reader_t *reader)
|
||||
{
|
||||
free(reader);
|
||||
}
|
||||
|
||||
//
|
||||
// Count the number of bytes read thus far.
|
||||
//
|
||||
int Reader_BytesRead(buffer_reader_t *reader)
|
||||
{
|
||||
return reader->pos - reader->buffer->data;
|
||||
}
|
||||
|
||||
//
|
||||
// Read an unsigned byte from a buffer.
|
||||
//
|
||||
boolean Reader_ReadInt8(buffer_reader_t *reader, uint8_t *out)
|
||||
{
|
||||
byte *data, *data_end;
|
||||
int len = Buffer_Data(reader->buffer, &data);
|
||||
|
||||
data_end = data + len;
|
||||
|
||||
if (data_end - reader->pos < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = (uint8_t)*reader->pos;
|
||||
reader->pos += 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Read an unsigned short from a buffer.
|
||||
//
|
||||
boolean Reader_ReadInt16(buffer_reader_t *reader, uint16_t *out)
|
||||
{
|
||||
byte *data, *data_end, *dp;
|
||||
int len = Buffer_Data(reader->buffer, &data);
|
||||
|
||||
data_end = data + len;
|
||||
dp = reader->pos;
|
||||
|
||||
if (data_end - reader->pos < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = (uint16_t)((dp[0] << 8) | dp[1]);
|
||||
reader->pos += 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Read an unsigned int from a buffer.
|
||||
//
|
||||
boolean Reader_ReadInt32(buffer_reader_t *reader, uint32_t *out)
|
||||
{
|
||||
byte *data, *data_end, *dp;
|
||||
int len = Buffer_Data(reader->buffer, &data);
|
||||
|
||||
data_end = data + len;
|
||||
dp = reader->pos;
|
||||
|
||||
if (data_end - reader->pos < 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = (uint32_t)((dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3]);
|
||||
reader->pos += 4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Read a string from a buffer.
|
||||
//
|
||||
char *Reader_ReadString(buffer_reader_t *reader)
|
||||
{
|
||||
byte *data, *data_start, *data_end, *dp;
|
||||
int len = Buffer_Data(reader->buffer, &data);
|
||||
|
||||
data_start = reader->pos;
|
||||
data_end = data + len;
|
||||
dp = reader->pos;
|
||||
|
||||
while (dp < data_end && *dp != '\0')
|
||||
{
|
||||
dp++;
|
||||
}
|
||||
|
||||
if (dp >= data_end)
|
||||
{
|
||||
// Didn't see a null terminator, not a complete string.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reader->pos = dp + 1;
|
||||
return (char*)data_start;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
buffer_t *buffer;
|
||||
int pos;
|
||||
byte *pos;
|
||||
} buffer_reader_t;
|
||||
|
||||
buffer_t *NewBuffer();
|
||||
|
|
@ -42,5 +42,13 @@ boolean Buffer_Push(buffer_t *buf, const void *data, int len);
|
|||
void Buffer_Shift(buffer_t *buf, int len);
|
||||
void Buffer_Clear(buffer_t *buf);
|
||||
|
||||
buffer_reader_t *NewReader(buffer_t* buffer);
|
||||
void DeleteReader(buffer_reader_t *reader);
|
||||
int Reader_BytesRead(buffer_reader_t *reader);
|
||||
boolean Reader_ReadInt8(buffer_reader_t *reader, uint8_t *out);
|
||||
boolean Reader_ReadInt16(buffer_reader_t *reader, uint16_t *out);
|
||||
boolean Reader_ReadInt32(buffer_reader_t *reader, uint32_t *out);
|
||||
char *Reader_ReadString(buffer_reader_t *reader);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue