changed the semantics of eeprom__copy()
the direction in which the data is copied is now well defined. this allows us to copy a large block a small distance (where the block's new address range overlaps with its old one), in either direction (to a higher block of addresses or a lower one), in a well defined and documented manner.partial-rewrite
parent
a32a9b59d6
commit
0bf0181ffa
|
@ -125,26 +125,17 @@ uint8_t eeprom__copy (uint8_t * to, uint8_t * from, uint8_t length);
|
|||
* - success: `0`
|
||||
* - failure: [other]
|
||||
*
|
||||
*
|
||||
* Implementation notes:
|
||||
* - Undefined behavior will result if
|
||||
* - `to` is not a valid address.
|
||||
* - `from` is not a valid address.
|
||||
* - Any address in either the block you're copying from
|
||||
* (`from`..`from+length-1`) or the block you're copying to
|
||||
* (`to`..`to+length-1`) is invalid.
|
||||
* - The block you're copying from overlaps with the block you're copying
|
||||
* to.
|
||||
* - The direction in which the block is copied (beginning with `to` and
|
||||
* incrementing, or beginning with `to + length - 1` and decrementing) is
|
||||
* undefined.
|
||||
* - Ideally, one would probably want to start with `to` and increment if
|
||||
* one was copying from a higher address to a lower one, and with `to +
|
||||
* length - 1` and decrement if one was copying from a lower address to a
|
||||
* higher one. This way, copying overlapping blocks would work as one
|
||||
* would expect (i.e. data would be moved up or down by `length` bytes).
|
||||
* But it seems like this might become more complicated than I'd like it
|
||||
* to be, and it also (if it turns out to matter) would be inordinately
|
||||
* difficult to make safe against data corruption in the event of power
|
||||
* loss.
|
||||
*
|
||||
* - If `to == from`, nothing should be done
|
||||
* - If `to < from`, copying should start with the given addresses, and
|
||||
* increment for `length - 1` bytes
|
||||
* - If `to > from`, copying should start with the given addresses, and
|
||||
* decrement for `length - 1` bytes
|
||||
*
|
||||
* - Undefined behavior will result if any address in either the block you're
|
||||
* copying from (`from`..`from+length-1`) or the block you're copying to
|
||||
* (`to`..`to+length-1`) is invalid.
|
||||
*/
|
||||
|
||||
|
|
|
@ -380,8 +380,13 @@ static void write_queued(void) {
|
|||
// copy 1 byte
|
||||
write( next_write.to, eeprom__read( (uint8_t *) next_copy.from ) );
|
||||
// prepare for the next
|
||||
++(next_write.to);
|
||||
++(next_copy.from);
|
||||
if (next_write.to < next_write.from) {
|
||||
++(next_write.to);
|
||||
++(next_copy.from);
|
||||
} else {
|
||||
--(next_write.to);
|
||||
--(next_copy.from);
|
||||
}
|
||||
--(next_write.value);
|
||||
|
||||
} else {
|
||||
|
@ -449,6 +454,9 @@ uint8_t eeprom__write(uint8_t * address, uint8_t data) {
|
|||
|
||||
// note: this should be the only function adding elements to `to_copy`
|
||||
uint8_t eeprom__copy(uint8_t * to, uint8_t * from, uint8_t length) {
|
||||
if (to == from)
|
||||
return 0; // nothing to do
|
||||
|
||||
to_write.unused_back--;
|
||||
to_copy.unused_back--;
|
||||
if (resize_to_write() || resize_to_copy()) {
|
||||
|
|
Loading…
Reference in New Issue