Skip to content

Instantly share code, notes, and snippets.

@ahinz
Created August 10, 2012 14:38
Show Gist options
  • Save ahinz/3314704 to your computer and use it in GitHub Desktop.
Save ahinz/3314704 to your computer and use it in GitHub Desktop.
Point Parsing
typedef struct {
uint8_t xoffset;
uint8_t yoffset;
uint8_t style;
} AZPoint;
typedef enum {
AZPointParserBadLength = 1,
AZPointParserBadMagicNumber = 2,
AZPointParserBufferOverflow = 3
} AZPointParserError;
uint32_t parseSection(const uint8_t *bytes, uint32_t byte_offset, uint32_t byte_len,
AZPoint **points, uint32_t *point_offset_ptr, uint32_t points_array_len,
AZPointParserError *error);
/**
* Parse the raw byte data
*
* @param bytes the data
* @return array of AZPoints
*/
AZPoint** parseData(const uint8_t *bytes, uint32_t length, AZPointParserError* error) {
if (length < 8) {
*error = AZPointParserBadLength;
return NULL;
}
if (bytes[3] != 0xA3 || // 0xA3A5EA <--> AZAVEA lolz
bytes[2] != 0xA5 ||
bytes[1] != 0xEA ||
bytes[0] != 0x00) {
*error = AZPointParserBadMagicNumber;
return NULL;
}
uint32_t nPoints = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | bytes[4];
uint32_t offset = 8; // Start at 8 (4 byte magic and 4 byte length)
AZPoint **points = malloc(sizeof(AZPoint*) * nPoints);
uint32_t point_offset = 0;
AZPointParserError err = 0;
while(offset < length && point_offset < nPoints) {
offset = parseSection(bytes, offset, length, points, &point_offset, nPoints, &err);
if (err != 0) {
*error = err;
return NULL;
}
}
return points;
}
/**
* Parse the raw byte data given for a section into points
*
* @param bytes the raw byte data
* @param byte_offset the current offset in the byte data
* @param byte_len length of byte array
* @param points array of points to write to
* @param point_offset_ptr pointer to where to write the next point
* @param point_array_len length of point array
* @param error_ptr error return value
*
* @return the new byte offset
* @return point_offset will be updated based on the number of poitns written
* @return error - a string describing a potential error state
*/
uint32_t parseSection(const uint8_t *bytes, uint32_t byte_offset, uint32_t byte_len,
AZPoint **points, uint32_t *point_offset_ptr, uint32_t points_array_len,
AZPointParserError *error) {
if (byte_offset + 3 >= byte_len) {
*error = AZPointParserBufferOverflow;
return 0;
}
uint32_t point_offset = *point_offset_ptr;
// Each section contains a simple header:
// [1 byte type][2 byte length ][1 byte pad]
uint16_t sectionLength = 0;
uint8_t sectionType = 0;
sectionType = bytes[byte_offset];
byte_offset += 1;
sectionLength = (bytes[byte_offset + 1] << 8) | bytes[byte_offset];
byte_offset += 2;
byte_offset += 1; // Skip padding
// We're going to read (sectionLength * 2) bytes
// and insert (sectionLength) bytes into the array
if ((byte_offset + sectionLength * 2) > byte_len) {
*error = AZPointParserBufferOverflow;
return 0;
}
if ((point_offset + sectionLength > points_array_len) || point_offset >= points_array_len) {
*error = AZPointParserBufferOverflow;
return 0;
}
uint8_t x=0, y=0;
for(int i=0;i<sectionLength;i++) {
x = bytes[byte_offset];
byte_offset += 1;
y = bytes[byte_offset];
byte_offset += 1;
AZPoint *p = malloc(sizeof(AZPoint));
p->xoffset = x;
p->yoffset = y;
p->style = sectionType;
points[point_offset] = p;
point_offset++;
}
*point_offset_ptr = point_offset;
return byte_offset;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment