Cannot Save and Delete Data from Preferences in the Same Function

Here it is.

If BREAK_THE_CODE = true, the deletes are done BEFORE the saves, and the code fails in that the db is corrupted as before. If BREAK_THE_CODE = false, the deletes are done AFTER the saves, and the code functions as expected.

BREAK_THE_CODE = false leaves the Preferences db in this state after all the tests:

	{1: 01:02:03:04:05:06}, {010203040506: 1}
	{3: 03:05:04:03:02:01}, {030504030201: 3}
	{8: 08:05:04:03:02:01}, {080504030201: 8}
	{9: 02:05:04:03:02:01}, {020504030201: 9}

BREAK_THE_CODE = true leaves the Preferences db in this state after all the tests:

    {1: 01:02:03:04:05:06}, {010203040506: 1}
	{3: 03:05:04:03:02:01}, {030504030201: 3}
	{8: 08:05:04:03:02:01}, {080504030201: 8}
	{9: }, {080504030201: 8}
#include <Preferences.h>
#include <string.h>
#include <cstring> // For strcpy
#include <stdbool.h>

/* Preference Data 
* launcher_id_str: macAddrStr -  note launcher_id is an int, so have to convert to a String to use as a key
* "keys": [launcher-1_id, launcher-2_id, launcher-3_id,] - an int array of the launcher_ids using the key "keys"
*/

Preferences preferences;
const char PREFERENCES_NAME_SPACE[] = "multiLauncher";
const bool CLEAR_PREFERENCES = true;
const bool TEST_PREFERENCES = true;

const bool BREAK_THE_CODE = false;

/*
  Testing different scenarios.
  * Add a launcher_id MAC address pair
  * Add a duplicate launcher_id and MAC address
  * Add a duplicate launcher_id with a different MAC address
  In each case print out the contents of the preferences and the keys
  Start the process each time with the preferences db empty
*/
void setup() {
  Serial.begin(115200); 
  delay(1000);     

  Serial.printf("Storage Setup*****");
  if (CLEAR_PREFERENCES) {
    preferences.begin(PREFERENCES_NAME_SPACE, false);
    preferences.clear();
    preferences.end();
    
  }
  if (TEST_PREFERENCES) {
    Serial.println("Testing Preferences - START");
    printKeys();
    printPreferences();

    // Add the first set of data
    char mac_str[] = "01:02:03:04:05:06";
    saveToPreferences(1, mac_str);
    printKeys();
    printPreferences();
    // Add a second set
    saveToPreferences(3, "03:05:04:03:02:01");
    printKeys();
    printPreferences();
    // Add a third set
    saveToPreferences(2, "02:05:04:03:02:01");
    printKeys();
    printPreferences();
    // Add a fourth set
    saveToPreferences(8, "08:05:04:03:02:01");
    printKeys();
    printPreferences();
    // Add a duplicate launcher_id MAC address pair
    saveToPreferences(3, "03:05:04:03:02:01");
    printKeys();
    printPreferences();
    // Update the launcher_id=2 a new MAC address
    // This should replace the launcher_id=2 with launcher_id=9
    // for MAC address 02:05:04:03:02:01
    saveToPreferences(9, "02:05:04:03:02:01");
    printKeys();
    printPreferences();

    Serial.println("Testing Preferences - DONE");
  }
  Serial.println("Storage setup done");
}

/*
  Save a launcher_id/MAC address pair to the preferences DB. 
  * Ignore duplicates
  * If the MAC address for a particular launcher_id changes, 
      then update the MAC address and remove the old entries
*/
void saveToPreferences(int launcher_number, char* macStr) {
  Serial.printf("Saving to preferences: launcher_number=%d, macStr=%s\n", launcher_number, macStr);
  preferences.begin(PREFERENCES_NAME_SPACE, false);
  char macStr_short[13];
  macToShort(macStr_short, macStr);
  int key = preferences.getInt(macStr_short);

/*******************************************************************************************/
  if (BREAK_THE_CODE) {
    // deleting the data before saving always breaks the code
    // so I moved the deleting part to after the saving part
    if (key != launcher_number && key != 0) {
      Serial.printf("\tremoving mac=%s, mac_short=%s, launcher_id=%d\n", macStr, macStr_short, key);
      char key_str[6];
      keyToString(key, key_str);
      preferences.remove(key_str);
      removeKey(key);
    }
  }
/*************************************************************************************************/
  char new_key_str[6];
  keyToString(launcher_number, new_key_str);
  preferences.putString(new_key_str, macStr);
  Serial.printf("\tSaving %s: %s\n", new_key_str, macStr);
  preferences.putInt(macStr_short, launcher_number);
  Serial.printf("\tSaving %s: %d\n", macStr_short, launcher_number);
  
  /********************************************************************************/
  if (!BREAK_THE_CODE) {
    if (key != launcher_number && key != 0) {
      Serial.printf("\tremoving mac=%s, mac_short=%s, launcher_id=%d\n", macStr, macStr_short, key);
      char key_str[6];
      keyToString(key, key_str);
      preferences.remove(key_str);
      removeKey(key);
    }
  }
  /************************************************************************************/

  preferences.end();
  saveKey(launcher_number);
}

/*
  Save a key to Preferneces. Check for duplicates and ignore them.
  Create the "keys" array if needed.
*/
void saveKey(int launcher_number) {
  Serial.printf("Save Key: launcher_number=%d\n", launcher_number);
  preferences.begin(PREFERENCES_NAME_SPACE, false);
  size_t storedSize = preferences.getBytesLength("keys");
  int arraySize = storedSize / sizeof(int);
  //Serial.printf("\t#1 storedSize=%d\n", storedSize);
  if (storedSize > 0) {
    int retrievedArray[arraySize + 1];
    preferences.getBytes("keys", retrievedArray, storedSize + sizeof(int));
    bool duplicate = false;
    for (int i = 0; i < arraySize; i++) {
      if (launcher_number == retrievedArray[i]) {
        duplicate = true;
        //Serial.printf("Found a duplicate: launcher_number=%d\n", launcher_number);
        // ignore the duplicate, just don't add another.
      }
    }
    if (!duplicate) {
      retrievedArray[arraySize] = launcher_number;
      preferences.putBytes("keys", retrievedArray, sizeof(retrievedArray));
    }
  }
  else {
    // storing first key, so create a new array and save it
    int keys[] = {launcher_number};
    preferences.putBytes("keys", keys, sizeof(keys));
  }
  // storedSize = preferences.getBytesLength("keys");
  // Serial.printf("\t#2 stored_size=%d\n", storedSize);
  preferences.end();
}

/* Copy the keys into a new array, one element shorter than the 
   original array and leave out the one we want to remove. 
*/
void removeKey(int key) {
  Serial.printf("Remove Key: key=%d\n", key);
  preferences.begin(PREFERENCES_NAME_SPACE, false);
  size_t storedSize = preferences.getBytesLength("keys");
  int arraySize = storedSize / sizeof(int);
  //Serial.printf("#1 stored_size=%zu, arraySize=%d\n", storedSize, arraySize);
  if (arraySize > 1) {
    //Serial.println("here");
    int retrievedArray[arraySize];
    int newArray[arraySize - 1];
    preferences.getBytes("keys", retrievedArray, storedSize);
    for (int i = 0; i < arraySize-1; i++) {
      //Serial.printf("key=%d, i=%d, array_value=%d\n", key, i, retrievedArray[i]);
      if (key != retrievedArray[i]) {
        newArray[i] = retrievedArray[i];
      }
      else {
        newArray[i] = retrievedArray[i+1];
      }
      //Serial.printf("newArray[i]=%d\n", newArray[i]);
    }
    preferences.putBytes("keys", newArray, sizeof(newArray));
  }
  else {
    preferences.remove("keys");
  }
  storedSize = preferences.getBytesLength("keys");
  //Serial.printf("#2 new stored_size=%zu\n", storedSize);
  preferences.end();
}

/*
  Print out each key on one line from preferences.
*/
void printKeys() {
  Serial.println("print keys: ");
  preferences.begin(PREFERENCES_NAME_SPACE, false);
  size_t storedSize = preferences.getBytesLength("keys");
  //Serial.printf("#1 stored_size=%d\n", storedSize);
  if (storedSize > 0) {
    int arraySize = storedSize / sizeof(int);
    Serial.printf("\tnumber of keys = %d\n", arraySize);
    int retrievedArray[arraySize];
    preferences.getBytes("keys", retrievedArray, storedSize);
    for (int i = 0; i < arraySize; i++) {
      Serial.printf("\tkey=%d\n", retrievedArray[i]);
    }
  }
  else {
    Serial.printf("\tNo keys in the store\n");
  }
  preferences.end();
}

/*
  Print out the preferences. Preferences consist of three types:
  launcher_id_str : macString
  macString: launcher)id_int
  "keys": [launcher_id_int_1, launcher_id_int_2, ...]
  Use print keys to print the keys preferences
*/
void printPreferences() {
  Serial.println("print preferences: ");
  preferences.begin(PREFERENCES_NAME_SPACE, false);
  size_t storedSize = preferences.getBytesLength("keys");
  if (storedSize > 0) {
    int arraySize = storedSize / sizeof(int);
    //Serial.printf("\tnumber of keys = %d\n", arraySize);
    int retrievedArray[arraySize];
    preferences.getBytes("keys", retrievedArray, storedSize);
    for (int i=0; i < arraySize; i++) {
      int key = retrievedArray[i];
      //Serial.printf("\tkey=%d\n", key);
      char key_str[6];
      keyToString(key, key_str);
      String cma = preferences.getString(key_str);
      //Serial.printf("\tcma=%s\n", cma.c_str());
      uint8_t mac_array[6];
      macToArray((char*)cma.c_str(), mac_array);
      char macStr_short[13];
      macToString(mac_array, macStr_short, 13, true);
      //Serial.printf("\tmacStr_short=%s\n", macStr_short);
      int same_key = preferences.getInt(macStr_short);
      Serial.printf("\t{%s: %s}, {%s: %d}\n", key_str, cma.c_str(), macStr_short, same_key);
    }
  }
  else {
    Serial.printf("\tNo data stored in Preferences\n");
  }
  preferences.end();
}

/*
  Use to convert a launcher_id_int to a launcher_id_string, so it can 
  be used as a key in preferences.
*/
void keyToString(int launcher_number, char* launcher_number_str) {
  char buffer[6];
  sprintf(launcher_number_str, "%d", launcher_number); 
  //Serial.printf("launcher_number=%d, launcher_number_str=%s\n", launcher_number, launcher_number_str);
}

/*
  MAC addresses for ESP_NOW need to be an array, whereas it is easier to store the MAC address as
  a string in preferences. However, keys used in preferences cannot exceed 15 characters, so a formatted
  MAC address as a string (18 characters) is too long for a preference key. Therefore, we nned a third MAC address
  form as a stirng without the ':' to keep it at 12 characters.
*/
// Formats MAC Address from uint8_t array to a string for printing and saving to Preferences, short format removes ':'
void macToString(const uint8_t *macArray, char *macString, int maxLength, bool short_format) {
  if (short_format) {
    snprintf(macString, maxLength, "%02x%02x%02x%02x%02x%02x", macArray[0], macArray[1], macArray[2], macArray[3], macArray[4], macArray[5]);
  }
  else {
    snprintf(macString, maxLength, "%02x:%02x:%02x:%02x:%02x:%02x", macArray[0], macArray[1], macArray[2], macArray[3], macArray[4], macArray[5]);
  }
}

/*
  The long string version (with ':') of the MAC address is passed as function arguments, so when saving
  the MAC address to preferences it has to be trimmed down to the short version.
*/
void macToShort(char* macShort, char* macLong) {
  int i, j;
  Serial.printf("size macShort=%d, size macLong=%d\n", strlen(macShort), strlen(macLong));
  for (i = 0, j = 0; i < strlen(macLong); i++) {
    if (macLong[i] != ':') {
      macShort[j++] = macLong[i];
    }
  }
  macShort[j] = '\0';
}

/* 
  Converts a string version of the mac address back into a uint8_t array used by esp-now
*/
void macToArray(char *macString, uint8_t *macArray) {
    sscanf(macString, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macArray[0], &macArray[1], &macArray[2], &macArray[3], &macArray[4], &macArray[5]);
}

/*
  Not needed for this excercise.
*/
void loop() {

}