mirror of
https://github.com/VARCem/ihex.git
synced 2026-09-25 00:14:51 +00:00
Size optimisation
This commit is contained in:
20
kk_ihex.h
20
kk_ihex.h
@@ -135,11 +135,12 @@ enum ihex_record_type {
|
||||
IHEX_START_LINEAR_ADDRESS_RECORD
|
||||
};
|
||||
|
||||
#ifndef IHEX_DISABLE_SEGMENTS
|
||||
|
||||
// Resolve segmented address (if any). It is the author's recommendation that
|
||||
// segmented addressing not be used (and indeed the write function of this
|
||||
// library uses linear 32-bit addressing unless manually overridden).
|
||||
//
|
||||
#ifndef IHEX_DISABLE_SEGMENTS
|
||||
#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address + (((ihex_address_t)((ihex)->segment)) << 4))
|
||||
//
|
||||
// Note that segmented addressing with this macro is not strictly adherent to
|
||||
@@ -160,6 +161,23 @@ enum ihex_record_type {
|
||||
|
||||
#endif
|
||||
|
||||
// The newline string (appended to every output line, e.g., "\r\n")
|
||||
#ifndef IHEX_NEWLINE_STRING
|
||||
#define IHEX_NEWLINE_STRING "\n"
|
||||
#endif
|
||||
|
||||
// Define this as 1 to catch truncated lines when reading (they will report
|
||||
// a checksum error or at the very least insufficient length). The default
|
||||
// is to ignore truncated lines - this allows for somewhat smaller and faster
|
||||
// code, and the only potential risk is when there is an error in the
|
||||
// transmission that only cuts some lines short while not causing any
|
||||
// checksum errors in non-truncated lines. That scenario seems unlikely,
|
||||
// and in any case one should use a better checksum (e.g., SHA1/MD5) over
|
||||
// the whole data if integrity is critical.
|
||||
#ifndef IHEX_CATCH_TRUNCATED_LINES
|
||||
#define IHEX_CATCH_TRUNCATED_LINES 0
|
||||
#endif
|
||||
|
||||
// See kk_ihex_read.h and kk_ihex_write.h for function declarations!
|
||||
|
||||
#endif // !KK_IHEX_H
|
||||
|
||||
110
kk_ihex_read.c
110
kk_ihex_read.c
@@ -15,8 +15,8 @@
|
||||
#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U)
|
||||
|
||||
enum ihex_read_state {
|
||||
READ_WAIT_FOR_START,
|
||||
READ_COUNT_HIGH,
|
||||
READ_WAIT_FOR_START = 0,
|
||||
READ_COUNT_HIGH = 1,
|
||||
READ_COUNT_LOW,
|
||||
READ_ADDRESS_MSB_HIGH,
|
||||
READ_ADDRESS_MSB_LOW,
|
||||
@@ -95,71 +95,71 @@ ihex_read_byte (struct ihex_state *ihex, int b) {
|
||||
enum ihex_read_state state = (ihex->flags & IHEX_READ_STATE_MASK);
|
||||
ihex->flags ^= state; // turn off the old state
|
||||
state >>= IHEX_READ_STATE_OFFSET;
|
||||
if (state != READ_WAIT_FOR_START) {
|
||||
if (b != IHEX_START) {
|
||||
if (b >= '0' && b <= '9') {
|
||||
b -= '0';
|
||||
} else if (b >= 'A' && b <= 'F') {
|
||||
b -= 'A' - 10;
|
||||
} else if (b >= 'a' && b <= 'f') {
|
||||
b -= 'a' - 10;
|
||||
} else if (b == '\n' || b == '\r' || b == '\0') {
|
||||
ihex_end_read(ihex);
|
||||
return;
|
||||
} else {
|
||||
// ignore extra characters
|
||||
goto save_read_state;
|
||||
}
|
||||
if ((state & 1) == (READ_COUNT_HIGH & 1)) {
|
||||
// states are arranged alternating high/low nybble
|
||||
b <<= 4;
|
||||
}
|
||||
switch (state) {
|
||||
case READ_COUNT_HIGH:
|
||||
ihex->line_length = b;
|
||||
break;
|
||||
case READ_COUNT_LOW:
|
||||
b = ihex->line_length | b;
|
||||
ihex->line_length = b;
|
||||
if (b > IHEX_LINE_MAX_LENGTH) {
|
||||
ihex_end_read(ihex);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case READ_ADDRESS_MSB_HIGH:
|
||||
// clear the low 16 bits of address
|
||||
ihex->address = (ihex->address & ADDRESS_HIGH_MASK);
|
||||
case READ_ADDRESS_MSB_LOW:
|
||||
b <<= 8;
|
||||
case READ_ADDRESS_LSB_HIGH:
|
||||
case READ_ADDRESS_LSB_LOW:
|
||||
ihex->address |= b;
|
||||
break;
|
||||
case READ_RECORD_TYPE_HIGH:
|
||||
ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK);
|
||||
case READ_RECORD_TYPE_LOW:
|
||||
if (b > IHEX_READ_RECORD_TYPE_MASK) {
|
||||
// ignore unknown record type
|
||||
return; // state has been zeroed
|
||||
}
|
||||
ihex->flags |= (b & IHEX_READ_RECORD_TYPE_MASK);
|
||||
break;
|
||||
case READ_DATA_HIGH:
|
||||
ihex->data[ihex->length] = b;
|
||||
break;
|
||||
case READ_DATA_LOW: {
|
||||
{
|
||||
unsigned int len = ihex->length;
|
||||
ihex->data[len] |= b;
|
||||
if (len < ihex->line_length) {
|
||||
ihex->length = len + 1;
|
||||
state = READ_DATA_HIGH;
|
||||
goto save_read_state;
|
||||
if (state & 1) {
|
||||
// high nybble, store temporarily at end of data:
|
||||
ihex->data[len] = b << 4;
|
||||
} else {
|
||||
// low nybble, combine with stored high nybble:
|
||||
b = (ihex->data[len] |= b);
|
||||
switch (state >> 1) {
|
||||
case (READ_COUNT_LOW >> 1):
|
||||
// data length
|
||||
ihex->line_length = b;
|
||||
if (b > IHEX_LINE_MAX_LENGTH) {
|
||||
ihex_end_read(ihex);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case (READ_ADDRESS_MSB_LOW >> 1):
|
||||
// high byte of 16-bit address
|
||||
ihex->address = (ihex->address & ADDRESS_HIGH_MASK);
|
||||
b <<= 8;
|
||||
case (READ_ADDRESS_LSB_LOW >> 1):
|
||||
// low byte of 16-bit address
|
||||
ihex->address |= b;
|
||||
break;
|
||||
case (READ_RECORD_TYPE_LOW >> 1):
|
||||
// record type
|
||||
if (b > IHEX_READ_RECORD_TYPE_MASK) {
|
||||
// skip non-standard record types silently
|
||||
return;
|
||||
}
|
||||
ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK) | b;
|
||||
break;
|
||||
case (READ_DATA_LOW >> 1): {
|
||||
if (len < ihex->line_length) {
|
||||
// data byte
|
||||
ihex->length = len + 1;
|
||||
--state; // back to READ_DATA_HIGH
|
||||
goto save_read_state;
|
||||
}
|
||||
// end of line (last "data" byte is checksum)
|
||||
ihex_end_read(ihex);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ihex_end_read(ihex);
|
||||
++state;
|
||||
}
|
||||
default:
|
||||
return; // state has been zeroed
|
||||
}
|
||||
++state;
|
||||
} else if (b == IHEX_START) {
|
||||
} else {
|
||||
// start of record
|
||||
#if IHEX_CATCH_TRUNCATED_LINES != 0
|
||||
ihex_end_read(ihex);
|
||||
#endif
|
||||
state = READ_COUNT_HIGH;
|
||||
}
|
||||
save_read_state:
|
||||
|
||||
@@ -76,11 +76,6 @@
|
||||
#define IHEX_MAX_OUTPUT_LINE_LENGTH IHEX_LINE_MAX_LENGTH
|
||||
#endif
|
||||
|
||||
// The newline string (appended to every output line)
|
||||
#ifndef IHEX_NEWLINE_STRING
|
||||
#define IHEX_NEWLINE_STRING "\n"
|
||||
#endif
|
||||
|
||||
// Initialise the structure `ihex` for writing
|
||||
void ihex_init(struct ihex_state * const ihex);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user