Sobre implementación de archivo base de datos Arduino

Lucario448:
Bueno, ahora que lo tengo, más adelante empezaré con las "críticas" :smiley: :smiling_imp:

Lo prometido es deuda, así que a eso vengo ahora.

Más que una crítica, en realidad son sugerencias de modificaciones que (considero que) se deberían realizar.
Los cambios están en los siguientes fragmentos del archivo "FDB_DEF.h":

template <class ESTRUCTURA>
Status FDB<ESTRUCTURA>::Open(char *nombreArchivo)
{
  if (_dbFile) _dbFile.close(); // Pudo haber ocurrido una "fuga de recursos" (y hasta posiblemente de memoria) al omitir esta verficación
  _dbFile = SD.open ( nombreArchivo, FILE_WRITE ); // | O_TRUNC
  if (!_dbFile)
    return (FDB_ERR);
  if (_dbFile.size() >= sizeof(FDB_Header)) {
    _ReadHead();
   //comprobar que tamaño estructura coincida con tamaño registro
    if ( _head.rec_size != (sizeof(ESTRUCTURA)) ) {
  _dbFile.close(); // Si el archivo se considera inválido, ¿entonces para qué mantenerlo abierto?
      return (FDB_ERR);
 }
  } else {
    _head.rec_size = sizeof(ESTRUCTURA); // Tamaño de registro
    _head.filledRecords = _head.deletedRecords = 0;
    _head.dataStart = HEAD_SIZE + DEFAULT_INDEX_SPACE; // Inicio de datos tras espacio indices
    _WriteHead();
    for (int i = 0; i < DEFAULT_INDEX_SPACE; i++)    // Escritura del espacio para índices
      _dbFile.write((byte) 0);
 }
  _registroActual = 0;
  return (FDB_OK);
}
template <class ESTRUCTURA>
Status FDB<ESTRUCTURA>::NuevoRegistro(const ESTRUCTURA &newReg)
{
  FilePointer posDataInsertar; // Puntero a la posición de los datos (la del registro reutilizado o final de archivo)
  IdReg posIndexInsertar; // posición de inserción del índice
  
  // Buscamos posición de inserción, y si el índice existe, devolvemos error;
  if (EncuentraIndex(newReg, posIndexInsertar) == FDB_OK)
    return (FDB_ERR);

  // Comprobamos si existe espacio suficiente para el nuevo índice. Si no lo hay, aumentamos el espacio.
  // Si había espacio, si hubiera registros borrados, nos estaremos cargando uno. Para uso futuro (tal vez podamos "desborrar")
  while ( (_head.dataStart - HEAD_SIZE - (FPOINTER_SIZE * _head.filledRecords)) < FPOINTER_SIZE ) { // Se usa while para coregir el bug de cuando sizeof(ESTRUCTURA) < FPOINTER_SIZE
    _AumentaEspacioIndex();
  }

  // Movemos el registro actual a la posición "nuevo registro" (tras el último índice relleno)
  _registroActual = _head.filledRecords;

  // Si existen registros borrados, aprovecharemos la posición de datos que apuntaba el índice anterior.
  if ( _head.deletedRecords > 0 ) {
    _LeerIndex(_registroActual, posDataInsertar);
    _head.deletedRecords--;
  } else {
    // Si no aprovechamos un borrado, los datos irán al final del archivo
    posDataInsertar = _dbFile.size();
    _EscribirIndex(_registroActual, posDataInsertar);
  }

  // Escribimos los datos
  _EscribirDatos(posDataInsertar, newReg);
  // y desplazamos el registro actual desde la posición "nuevo registro" a la posición de inserción.
  _MueveIndex(posIndexInsertar);
  _head.filledRecords++;
  _WriteHead();
  _dbFile.flush();
  return (FDB_OK);
}
template <class ESTRUCTURA>
Status FDB<ESTRUCTURA>::LeeRegistro(ESTRUCTURA &datos)
{
  if (_registroActual >= _head.filledRecords) return (FDB_ERR);
  FilePointer posDataLeer;
  _LeerIndex(_registroActual,posDataLeer);
  _LeerDatos(posDataLeer, datos);
  return (FDB_OK); // Faltaba
}
template <class ESTRUCTURA>
void FDB<ESTRUCTURA>::_ReadHead()
{
  _dbFile.seek(0L);
  _dbFile.read ( (byte *)&_head, sizeof(FDB_Header) ); // ¿Olvidaste castear el puntero?
}

Antes según yo iba a sugerir más cambios aparte de estos, pero luego me di cuenta que se debía a mi falta de entendimiento del código. Un ejemplo fue al crearse un archivo nuevo, que no me había dado cuenta cómo manejabas los punteros "en cero"; la clave estaba en que:

  • No existen registros "eliminados"; o mejor dicho, espacios preexistentes pero en desuso.
  • La brecha entre el último puntero válido y _head.dataStart todavía es mayor o igual que FPOINTER_SIZE.

Si la primera se cumple pero la segunda no, ahí es donde _AumentaEspacioIndex() entra en juego (cíclicamente según sugerencia).
Si la primera NO se cumple (una doble negación es una afirmación), la segunda no debería importar en lo absoluto.
Si ambas se cumplen, hay que crear un espacio para un registro (siempre al final del archivo), solamente hacer incremento a _head.filledRecords, y asignar dicha posición al nuevo puntero; haciendo innecesario pre-inicializar los valores (que era lo que tenía en mente).
Si ambas NO se cumplen, es una contradicción; y por ende, un error de consistencia (¿posiblemente archivo corrupto?).

Por lo demás creo que está correcto, excepto por la siguiente duda: si el parámetro de una función declaras una variable de tipo no-puntero, pero con la referencia del nombre (precedido por &); ¿seguro que no hay que desreferenciar (*) antes de modificar su valor?

Este ha sido todo mi veredicto. ¡Gracais por leer! :smiley: