Created
August 10, 2012 14:38
-
-
Save ahinz/3314704 to your computer and use it in GitHub Desktop.
Point Parsing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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