shithub: choc

Download patch

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