ref: 056cdff7cef7dd545fe045532188c77533c6b5f9
parent: b5302fee81f0b1c46520c96ec7fa7b2d7e2289f2
author: Alex Mayfield <alexmax2742@gmail.com>
date: Wed Feb 15 16:11:19 EST 2017
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.
--- a/midiproc/buffer.c
+++ b/midiproc/buffer.c
@@ -121,22 +121,125 @@
}
//
-// 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;
}
--- a/midiproc/buffer.h
+++ b/midiproc/buffer.h
@@ -24,15 +24,15 @@
typedef struct {
byte buffer[BUFFER_SIZE]; // Buffer.
- byte* buffer_end; // End of Buffer.
- byte* data; // Start of actual data.
- byte* data_end; // End of actual data.
+ byte *buffer_end; // End of Buffer.
+ byte *data; // Start of actual data.
+ byte *data_end; // End of actual data.
int data_len; // Length of actual data.
} buffer_t;
typedef struct {
buffer_t *buffer;
- int pos;
+ byte *pos;
} buffer_reader_t;
buffer_t *NewBuffer();
@@ -41,6 +41,14 @@
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