Newsgroup: it.hobby.elettronica.digitale
Titolo: Leggere file INI con un uC

Ciao,
devo leggere un file INI classico:
[SEZIONE1]
campo1=valore1
campo2=valore2
[SEZIONE2]
campo1=valore1
lo devo fare con un micro (LM3S1918) in C.
Ho trovato una strada che funziona ma mi sembra macchinosa e abbastanza 
brutta.
1) leggo il file riga per riga tramite fgets
2) comparo a manina (if, elseif, elseif) con strcmp l'intera riga e se 
corrisponde al nome di una sezione allora imposto la variabile section.
3) se non trovo corrispondenze, spezzo la riga con strtok usando '=' 
come delimitatore e mi prendo campo e valore.
4) come prima comparo a manina il campo con tutti i possibili nomi. 
Quando (e se) lo trovo imposto la variabile item.
5) converto la stringa valore in intero (sono tutti interi per fortuna).
6) passo a una funzione gli interi section, item e value.
7) questa funzione ha due switch annidati che in base alla sezione e al 
campo indicati (faccio riferimento a degli enum per comodità di lettura) 
assegna il valore alla variabile corretta, ovviamente contenuta in una 
struttura, così da avere tutti i parametri assieme.
8) proseguo con la riga successiva...
Il vantaggio di un simile "algoritmo" è che non mi devo preoccupare 
dell'ordine delle sezioni e dei campi e quindi è facilmente espandibile 
(aggiungendo la nuova voce nell'enum, negli else if e negli switch).
Chiaramente gestisco e segnalo eventuali errori di coerenza.
Come si può fare meglio?
Grazie!
Marco

 Come si può fare meglio?
Mi sembra che questa implementazione sia di difficile manutenzione.
Secondo me dovresti separare la logica di parsing dai dati (nomi sezioni 
e campi).
In questo modo la funzione rimane generica e la puoi chiamare quante 
volte vuoi, semplificando anche la manutenzione.
Di solito, la API più diffusa che si usa per leggere un file ini è la 
seguente:
get_string(file, sezione, chiave, default, buffer);
Tutto il file viene letto alla ricerca della "sezione" contenente la 
"chiave". Il risultato viene messo in "buffer" se il campo è trovato, 
altrimenti viene usato il "default".
Con solo questa funzione puoi farci tutte le varianti che vuoi, perché 
basta che poi chiami la atoi() per ottenere un intero, atof() per i 
float e via dicendo.
Per usi normali, il fatto che il file venga riletto tutte le volte non è 
un problema. Per normali intendo fino a diverse decine/un centinaio di 
valori da leggere.
Un'implementazione come quella che ho indicato sopra è disponibile in 
BeRTOS, fatta da un mio collega.
Qui trovi la documentazione:
http://doc.bertos.org/2.5/ini__reader_8h.html
Qui il sorgente:
http://dev.bertos.org/browser/trunk/bertos/mware/ini_reader.c
BTW, BeRTOS supporta anche i Luminary ;-P
-- 
  _|/ Francesco Sacchi - Develer S.r.l., R&D dept.
   |\ 
http://www.develer.com/
 - 
http://www.bertos.org/

 BTW, BeRTOS supporta anche i Luminary ;-P
Sono mesi che ho installato BeRTOS dicendo che al prossimo progetto 
l'avrei provato... ma ogni volta risolvo sempre senza RTOS :)
Uff... abbi fede che prima o poi ci riesco!
Ciao!
Marco

 inventato l'obbrobrio di fare il parsing in real-time... te pareva :)
Non è male come idea, è solo che è più semplice rileggere tutto, 
quantomeno finché non hai problemi di performance.
Se proprioproprio dovessi averli, il tuo sistema va bene ma i campi da 
matchare non li hardcoderei nel codice con degli if/switch, piuttosto 
farei un paio di tabelle da passare alla funzione di parsing.
In questo modo l'implementazione la scrivi e la testi una volta sola, 
e quando vuoi aggiungere/togliere un campo modifichi solo le tabelle.


 quando vuoi aggiungere/togliere un campo modifichi solo le tabelle.
Anche questa è un'idea migliore.
Comunque ho preso spunto dal codice che hai segnalato e l'ho modificato 
in base alle funzioni che avevo disponibili.
Lo sto provando in questo momento.
Ciao!
Marco