static int ihex_parse_single_record(ihex_rdata_t data, unsigned int length, ihex_record_t* record) { uint_t i; // Records needs to begin with record mark (usually ":") if (*(data) != IHEX_CHR_RECORDMARK) { IHEX_SET_ERROR_RETURN(IHEX_ERR_PARSE_ERROR, "Missing record mark"); } // Record layout: // 1 2 3 4 // 0 12 3456 78 90123456789012345678901234567890 12 // : 10 0100 00 214601360121470136007EFE09D21901 40 record->ihr_length = (ihex_rlen_t) length; record->ihr_address = (ihex_addr_t) ihex_fromhex16(data + 3); record->ihr_type = (ihex_rtype_t) ihex_fromhex8 (data + 7); record->ihr_checksum = (ihex_rchks_t) ihex_fromhex8 (data + 9 + record->ihr_length * 2); if ((record->ihr_data = (ihex_rdata_t) malloc(record->ihr_length)) == NULL) { IHEX_SET_ERROR_RETURN(IHEX_ERR_MALLOC_FAILED, "Could not allocate memory"); } // Records needs to end with CRLF or LF. if ( ( data[11 + record->ihr_length * 2] != 0x0D || data[12 + record->ihr_length * 2] != 0x0A) && (data[11 + record->ihr_length * 2] != 0x0A)) { free(record->ihr_data); IHEX_SET_ERROR_RETURN(IHEX_ERR_WRONG_RECORD_LENGTH, "Incorrect record length"); } for (i = 0; i < record->ihr_length; i ++) { if (data[9 + i*2] == 0x0A || data[9 + i*2] == 0x0D) { free(record->ihr_data); IHEX_SET_ERROR_RETURN(IHEX_ERR_WRONG_RECORD_LENGTH, "Unexpected end of line"); } record->ihr_data[i] = ihex_fromhex8(data + 9 + i*2); } if (ihex_check_record(record) != 0) { free(record->ihr_data); IHEX_SET_ERROR_RETURN(IHEX_ERR_INCORRECT_CHECKSUM, "Checksum validation failed"); } return 0; }
ihex_recordset_t* ihex_rs_from_mem(const char* data, size_t size) { uint_t i = 0; int r = 0, c = 0; const char *end = data + size; ihex_last_errno = 0; ihex_last_error = NULL; ihex_record_t *rec; ihex_recordset_t *recls; const char *p; // Count number of record marks in input string. for (p = data; p < end && *p != 0x00; p ++) { if (*p == IHEX_CHR_RECORDMARK) { c ++; } } // Allocate memory for the record container structure and for each // individual record. if ((rec = (ihex_record_t*) calloc(c, sizeof(ihex_record_t))) == NULL) { IHEX_SET_ERROR(IHEX_ERR_MALLOC_FAILED, "Could not allocate memory"); goto malloc_rec_failed; } if ((recls = (ihex_recordset_t*) malloc(sizeof(ihex_recordset_t))) == NULL) { IHEX_SET_ERROR(IHEX_ERR_MALLOC_FAILED, "Could not allocate memory"); goto malloc_recls_failed; } recls->ihrs_count = c; recls->ihrs_records = rec; while (data < end && *(data) != 0x00) { i ++; if (data + 3 >= end) break; ihex_rlen_t l = ihex_fromhex8(((ihex_rdata_t) data) + 1); if (data + 9 + l * 2 >= end || (r = ihex_parse_single_record((ihex_rdata_t) data, l, rec + i - 1)) != 0) { IHEX_SET_ERROR(r, "Line %i: %s", i, ihex_last_error); goto parse_single_failed; } data += (rec[i - 1].ihr_length * 2) + 10; while (data < end && *(data) != IHEX_CHR_RECORDMARK && *(data) != 0x00) { data ++; } } if (recls->ihrs_records[recls->ihrs_count - 1].ihr_type != IHEX_EOF) { IHEX_SET_ERROR(IHEX_ERR_NO_EOF, "Missing EOF record"); goto missing_eof_record; } return recls; missing_eof_record: for (i = 0; i < recls->ihrs_count; i ++) { free(recls->ihrs_records[i].ihr_data); } parse_single_failed: free(recls); malloc_recls_failed: free(rec); malloc_rec_failed: return NULL; }
void test_can_parse_8bit_hex_2(void) { CU_ASSERT_EQUAL(ihex_fromhex8((uint8_t*) "00"), 0x00); }