Versione di questo documento
4.0.0
- Specifiche 4.0.0
3.0.0
- Specifiche 3.0.0
- Definizione di report.
2.0.0
- Specifiche 2.0.0
1.0.0
- Specifiche 1.0.0
Versione delle specifiche descritte
4.0.0
- Aggiunto l'attributo "autore" al nodo <documento>.
- Aggiunto l'attributo "verso" al nodo <ripeti>.
- Aggiunto l'attributo variabile "RIPETI[nome].contatore" che dà accesso al contatore del nodo <ripeti>.
- Aggiunto il nodo <report>.
3.0.0
- Aggiunto l'attributo "mentre" al nodo <ripeti>.
- Sostituito l'attributo "id" con l'attributo "nome" nel nodo <campo>.
- Aggiunto l'attributo "buffer" al nodo <campo>.
- Aggiunto il nodo <buffer>.
- Aggiunto l'attributo "peso" al nodo <documento>.
- Gestione dei caratteri non visualizzabili nei campi di tipo testo.
- Dimensioni di un campo con marcatore.
- Tabelle con righe di tipo testo.
- Gestione dell'attributo variabile "CAMPO[nome].dimensione" che dà accesso all'attributo "dimensione" di un campo.
- Aggiunto il nodo <variabile> che definisce un valore utilizzabile come attributo variabile.
- Aggiunto l'attributo variabile "VARIABILE[nome].valore" che dà accesso al valore di un nodo <variabile>.
- Aggiunti i nodi <somma>, <sottrai>, <dividi> e <moltiplica> che eseguono le operazioni
aritmetiche e restituiscono il risultato in un attributo variabile "VARIABILE[nome].valore".
2.0.0
- Calcolo e verifica del checksum: aggiunti nuovi attributi al nodo <struttura> e il nuovo tipo "controllo" al nodo <campo>
1.0.0
- Prima stesura
Questo documento illustra le specifiche tecniche che definiscono un particolare documento XML che chiameremo "Descrittore del formato di un file" o semplicemente "Descrittore".
Il descrittore permette di attribuire uno specifico significato logico
ai byte letti da un qualsiasi file, sia esso binario, testuale o misto.
Un software può utilizzare un descrittore per generare un report.
1.1 Definizione di report
Un report è un file di testo contenente le descrizioni logiche e i valori dei campi indicati nel descrittore. Sia le descrizioni che i valori devono essere in chiaro cioè sotto forma di testo visualizzabile da un qualsiasi editor di testi (NotePad, JEdit...).
Segue l'elenco dei nodi e la loro sintassi riportata attraverso degli esempi.
2.1 Nodo <documento>
<documento ver="4.0.0" desc="File MioFormato Versione 5.0.0" peso="alto-basso" autore="Mario">
E' il primo nodo di ogni descrittore e tutti gli altri devono essere suoi figli.
ver="4.0.0"
Identifica le regole descritte in questo documento, la modifica di uno
o più nodi o di una regola si riflette in un valore di versione
diverso. Non può essere vuoto.
desc="File MioFormato Versione 5.0.0"
E' una descrizione del tipo di file individuato dal Descrittore. Non può essere vuoto.
peso="alto-basso"
E' un parametro facoltativo che indica come vanno valutati i byte dei campi numerici con dimensioni minori o uguali a 4.
Può assumere solo i valori seguenti:
"alto-basso": è
il valore di default. Il primo byte è considerato quello di peso maggiore,
l'ultimo byte è quello di peso minore;
"basso-alto": il
primo byte è considerato quello di peso minore, l'ultimo byte è
quello di peso maggiore;
autore="Mario"
Indica l'autore del Descrittore. Lo stesso attributo può essere usato nel report per indicare il software che lo ha generato. Facoltativo.
E' il nodo fondamentale di un descrittore perché effettua la
lettura dei byte attribuendo ad essi un significato logico e applica i
controlli indicati nei suoi attributi.
nome="baud"
Individua in modo univoco un <campo>. Può essere vuoto
a patto che in nessuna parte del documento sia presente una scrittura
del tipo "CAMPO[nome].valore" in cui "nome" fa riferimento proprio a questo
attributo (vedi "Attributi variabili" più avanti). Se presente deve essere univoco. Qualsiasi testo può essere un nome valido, lo sono "baud rate", "12", "3 anni", l'importante è che al momento del suo utilizzo, nella scrittura CAMPO[nome], esso sia riportato allo stesso modo, con gli stessi spazi, le stesse lettere maiuscole e minuscole.
desc="Baud Rate di trasmissione"
Una descrizione obbligatoria che dà un significato logico ai byte letti. Non è necessario che sia univoca ma è chiaro che se più nodi <campo> hanno la stessa descrizione si otterranno risultati poco chiari.
tipo="numero"
Tipo dei byte letti. E' obbligatorio e può assumere solo i valori seguenti
"numero": i
byte letti vengono interpretati come una sequenza di numeri da 0 a 255
(da 00 a FF in esadecimale). Se la "dimensione" del <campo>
è minore o uguale a 4 i byte letti vengono messi insieme in un
unico valore numerico utilizzabile in scritture del tipo
"CAMPO[nome].valore" (vedi "Attributi variabili" più avanti);
"testo": i
byte letti vengono interpretati come una sequenza di caratteri
alfanumerici utilizzabili in scritture del tipo "CAMPO[nome].valore"
(vedi "Attributi variabili" più avanti). Nel caso in cui un testo contenga anche byte numerici non visualizzabili vedi "Caratteri non visualizzabili" più avanti;
"scarto": i
byte letti vengono "scartati" cioè non interpretati in alcun
modo, non devono essere inseriti neanche nel report risultante.
"controllo": i
byte letti vengono interpretati come un numero e individuano un controllo di
integrità, un software può calcolare l'integrità di una struttura e
confrontare il risultato con il valore di questo campo. Un campo di questo
tipo deve avere un attributo "nome" assegnato (vedi "Algoritmi di controllo" più avanti).
dimensione="2"
Il numero di byte consecutivi da leggere. E' obbligatorio. Può assumere anche "attributi variabili" o "dimensioni raggruppate" o "dimensioni con marcatore" (descritti più avanti).
formato="decimale"
Permette di visualizzare i byte letti in uno dei formati di seguito indicati. E' facoltativo.
"esadecimale":
i byte letti vengono visualizzati come sequenza di byte in esadecimale.
E' il valore predefinito se l'attributo "formato" è omesso o
errato;
"decimale":
i byte letti vengono visualizzati come sequenza di byte in decimale. Se
la "dimensione" del <campo> è minore o uguale a 4 i byte
letti vengono visualizzati in un unico valore numerico;
"orario": 2
byte letti consecutivamente vengono interpretati come minuti successivi
alla mezzanotte e visualizzati nel formato hh:mm. Ha senso solo se la
"dimensione" del <campo> è 2 o del tipo
"2*CAMPO[nome].valore";
"ip": 4
byte letti consecutivamente vengono interpretati come indirizzo ip e
visualizzati nel formato aaa.bbb.ccc.ddd. Ha senso solo se la
"dimensione" del <campo> è 4 o del tipo
"4*CAMPO[nome].valore";
"data": 2
byte letti consecutivamente vengono interpretati come giorni successivi
a 01-01-2000 e visualizzati nel formato gg-mm-aaaa. Ha senso solo se la
"dimensione" del <campo> è 2 o del tipo
"2*CAMPO[nome].valore".
predefinito="0" minimo="1200" massimo="38400"
I parametri "predefinito", "minimo" e "massimo" sono facoltativi
e servono affinchè un software possa segnalare che eventuali
valori letti da un file sono in disaccordo con il formato previsto.
Hanno significato solo se il <campo> è di tipo "numero" e
la "dimensione" è minore o uguale a 4 o del tipo
"n*CAMPO[nome].valore" con n minore o uguale a 4.
segno="no"
E' un parametro facoltativo che si riferisce solo ai campi di tipo "numero" ed indica se il valore letto va considerato con segno o senza, tale scelta può influire il controllo eventualmente effettuato da un software sui parametri "predefinito", "minimo" e "massimo".
tabella="1"
Permette di sostituire il valore del <campo> con quello associato in un nodo <tabella> descritto più avanti. Facoltativo.
buffer="" Facoltativo. Se presente (il testo al suo interno è ininfluente) indica che il valore del campo non sarà letto direttamente dal file di input ma da un nodo <buffer> precedentemente definito che ha già letto i byte dal file.
Permette di raggruppare in modo logico i nodi <campo> e tutti gli altri nodi descritti in seguito.
desc="INTESTAZIONE"
Una descrizione facoltativa che un software può scrivere nel report. Non è necessario che sia univoca ma è chiaro che se più nodi <struttura> hanno la stessa descrizione si otterranno risultati poco chiari.
separatore="----------"
Un testo facoltativo
che un software può stampare per separare visivamente
più strutture, tipicamente una riga sopra la descrizione.
2.3.1 Algoritmi di controllo
Dalla versione 2.0.0 delle specifiche è possibile gestire gli algoritmi di integrità dei dati. Per attivare un controllo, un nodo <struttura> deve avere i seguenti attributi facoltativi (che indico con esempi):
controllo-classe="somma"
Indica l'algoritmo di controllo da eseguire sui byte di tutti i campi definiti all'interno della struttura. Per il momento l'unico valore ammesso è "somma" che seleziona il "checksum a 16 bit con scarto del riporto."
controllo-nome="17"
Deve corrispondere all'attributo "nome" di un campo all'interno della struttura il quale deve essere pure di tipo "controllo". Questo campo è quello che contiene il valore già calcolato, un software può applicare l'algoritmo ai byte della struttura e verificare la corretta corrispondenza con questo valore.
controllo-tipo="globale"
Indica che il valore calcolato deve essere mantenuto fino alla fine del file di input e, quindi, anche dopo l'uscita dalla struttura.
Questo nodo permette di eseguire i nodi che contiene solo se un'espressione è valutata vera, altrimenti li salta. Può far uso di attributi variabili.
Le espressioni gestite sono
"==" (uguaglianza): vera se il valore alla sua sinistra è uguale a quello (o uno tra quelli) alla sua destra;
"!=" (disuguaglianza):" vera se il valore alla sua sinistra è diverso da quello (o tutti quelli) alla sua destra;
Un esempio di uguaglianza è il seguente:
<se vero="CAMPO[0].valore==200">
vero="CAMPO[0].valore==200"
Condizione da verificare. I nodi contenuti vengono valutati solo se il
valore del <campo> con attributo "nome" impostato a "0" ha valore uguale a 200.
E' possibile indicare un'elenco di valori, ad esempio:
in tal caso i nodi contenuti vengono valutati solo se il valore del
<campo> con attributo "nome" impostato a "0" ha valore uguale a 200
oppure 202 oppure uno degli altri indicati.
Un esempio di disuguaglianza è il seguente
<se vero="CAMPO[15].valore!=05.00.00">
vero="CAMPO[15].valore!=05.00.00"
Condizione da verificare. I nodi contenuti vengono valutati solo se il
valore del <campo> con attributo "nome" impostato a "15" ha valore
diverso da "05.00.00".
E' possibile indicare un elenco di valori, ad esempio:
in tal caso i nodi contenuti vengono valutati solo se il valore del
<campo> con attributo "nome" impostato a "0" ha valore diverso da 200
e diverso da 202 e diverso da tutti gli altri indicati.
Se l'espressione non è verificata (uguaglianza o disuguaglianza
che sia) i nodi all'interno del nodo <se> vengono saltati.
Nel caso di costanti di tipo testo (nell'es. precedente "05.00.00") è possibile usare anche i caratteri non visualizzabili (vedi più avanti).
Questo nodo permette di ripetere la valutazione dei nodi che contiene per un numero di volte prefissato o in seguito alla valutazione di un attributo variabile. Una sua prima forma è la seguente:
per="33"
Numero di volte (obbligatorio)
di valutazione dei nodi. Nell'esempio i nodi contenuti saranno valutati
per 33 volte. La ripetizione può far uso anche di attributi
variabili come nell'esempio seguente:
nome="anni"
Individua in modo univoco un nodo <ripeti>. Può essere vuoto
a patto che in nessuna parte del documento sia presente una scrittura
del tipo "RIPETI[nome].contatore" in cui "nome" fa riferimento proprio a questo
attributo (vedi "Attributi variabili" più avanti). Se presente deve essere univoco. Qualsiasi testo può essere un nome valido, lo sono "baud rate", "12", "3 anni", l'importante è che al momento del suo utilizzo, nella scrittura RIPETI[nome], esso sia riportato allo stesso modo, con gli stessi spazi, le stesse lettere maiuscole e minuscole.
verso="incrementa"
Indica come il nodo <ripeti> deve gestire il conteggio delle ripetizioni. E' facoltativo ma se presente può assumere solo i valori seguenti
"decrementa": il
contatore ha come valore iniziale quello indicato dall'attributo "per" ed è decrementato fino al valore zero (0). Questo è il comportamento predefinito nel caso in cui l'attributo "verso" non sia indicato.
"incrementa": il
contatore ha come valore iniziale zero (0) ed è incrementato fino al valore indicato dall'attributo "per".
La seconda forma permette di ripetere secondo il valore di un'espressione:
mentre="CAMPO[num volte].valore!=0"
E' l'espressione (obbligatoria) da valutare, se vera, avviene la ripetizione. In questo caso è spontaneo l'uso di attributi variabili. Le possibili espressioni sono quelle già viste per il nodo <se>
Gli attributi "nome" e "verso" hanno il significato già descritto. E' possibile conoscere il valore assunto dal contatore utilizzando l'attributo variabile del tipo "RIPETI[nome].contatore" (vedi "Attributi variabili" più avanti).
Gli attributi "per" e "mentre" sono obbligatori nelle due distinte forme del nodo e non possono essere presenti entrambi.
Permette di dare un avviso all'utilizzatore. Non altera in nessun modo
il flusso di lettura del file di input. Tipicamente il software
visualizzerà il messaggio indicato facendo uso della propria
interfaccia utente.
Una tabella permette di associare delle descrizioni ai valori letti
mediante un <campo>. L'associazione può avvenire con
l'intero valore letto o con un singolo bit del valore. Esistono tre tipi di nodi
<tabella> come indicato negli esempi seguenti
<tabella id="0" tipo="numero"> ... </tabella>
<tabella id="0" tipo="testo"> ... </tabella>
<tabella id="0" tipo="bit"> ... </tabella>
id="0"
Individua in modo univoco una <tabella>. E' obbligatorio e deve
essere numerico e univoco. Mediante il suo valore è possibile
associare la tabella ad un <campo> riportandolo nella sua
proprietà "tabella". Una tabella può essere definita in
un qualsiasi punto del descrittore ma prima che un <campo> vi
faccia riferimento.
tipo="numero"
Tipo della tabella. E' obbligatorio e può assumere solo i valori
seguenti (vedere anche il nodo <riga>)
"numero":
quando il <campo> viene letto viene valutato il suo valore come
un numero intero. Ha senso se il campo ha "dimensione" minore o uguale
a 4;
"testo":
quando il <campo> viene letto viene valutato il suo valore come
un testo;
"bit":
quando il <campo> viene letto viene valutato un singolo bit del
suo valore come un numero intero. Ha senso se il campo ha "dimensione"
minore o uguale a 4.
Definisce le associazioni tra un numero, un testo o un bit ed una descrizione.
Deve essere definito all'interno di un nodo <tebella>.
<riga valore="33" desc="gli anni del signore"/>
se il nodo <riga> si trova all'interno di un nodo <tabella>
con attributo "tipo" uguale a "numero" e il valore del campo è
"33" esso deve essere sostituito nel report dalla descrizione "gli anni del
signore";
se invece si trova in una <tabella> con "tipo" uguale a "bit":
se il bit "0" del valore del campo è settato a 1 esso
deve essere sostituito dalla descrizione "assoluto". Se più bit
risultano settati le descrizioni dovranno essere presenti nel report in
modo da non ripetere la descrizione del campo, ad esempio:
Orario = assoluto | extraurbano
Se un bit non è previsto dalla tabella il suo valore non verrà
indicato, nel caso dell'esempio precedente non sarà possibile sapere il
valore dei bit "2" e "3" perché non hanno associata una <riga>.
Può essere utile inserire il nodo <riga> all'interno di un nodo <tabella> con attributo "tipo" uguale a "testo" nel caso in cui il valore del campo sia poco descrittivo:
<riga valore="[12" desc="font alto 12"/>
E' possibile usare anche caratteri non visualizzabili così da renderli leggibili nel report (vedi "Caratteri non visualizzabili" più avanti):
<riga valore="\0d\0a" desc="Ritorno a capo"/>
Se il valore assunto da un <campo> non è previsto dalla
tabella esso verrà visualizzato secondo gli attributi "tipo" e
"formato" del <campo>.
Mediante questo nodo è possibile utilizzare il risultato di alcune operazioni aritmetiche (vedi "Nodi aritmetici" più avanti) oppure definire delle costanti numeriche a cui far riferimento in altri punti del descrittore oppure permettere all'utilizzatore di un software di introdurre un valore numerico facendo uso dell'intefaccia del software.
<variabile nome="eta" desc="Gli anni del signore" valore="33"/>
nome="eta"
Individua in modo univoco una <variabile> quindi è obbligatorio. Permette di far riferimento a questo nodo in scritture del tipo "VARIABILE[nome].valore" (vedi "Attributi variabili" più avanti).
desc="Gli anni del signore"
Una descrizione obbligatoria. Non è necessario che sia univoca ma è chiaro che se più nodi <variabile> hanno la stessa descrizione si otterranno risultati poco chiari.
valore="33"
Il valore iniziale della <variabile>. Non è obbligatorio. Se presente deve essere numerico o un attributo variabile numerico, se assente assume il valore zero.
Se l'attributo "valore" è il testo "?" (punto interrogativo), un software può dare all'utente la possibilità di inserire un valore numerico facendo uso della propria interfaccia. In questo modo si può parametrizzare un descrittore come nell'esempio:
<variabile nome="cifre" desc="Numero di cifre" valore="?"/>
I nodi aritmetici permettono di eseguire le operazioni aritmetiche di base (somma, sottrazione, divisione e moltiplicazione) su operandi che possono essere costanti numeriche o attributi variabili (vedi "Attributi variabili" più avanti) e ripongono il risultato in un attributo variabile necessariamente del tipo VARIABILE[nome].valore precedentemente definito.
I nodi disponibili sono (descritti con degli esempi):
divide il valore della <variabile> con "nome" uguale a "1" con il valore della <variabile> con "nome" uguale a "2" e il risultato va a sostituire il valore della <variabile> con "nome" uguale a "1" (che è anche il primo operando).
moltiplica il valore della <variabile> con "nome" uguale a "1" con il valore letto dal file del <campo> con "nome" uguale a "2", il risultato va a sostituire il valore della <variabile> con "nome" uguale a "3".
In generale "op1" e "op2" individuano i 2 operandi mentre "ris" indica il nodo <variabile> che conterrà il risultato e che sarà utilizzabile in qualsiasi altro punto in cui si può far uso di attributi variabili.
Come il nodo <campo>, anche questo legge i byte dal file di input ma li salva in un'area di memoria condivisa da tutto il descrittore che chiamiamo buffer. Ha lo scopo di rendere diponibili i byte del buffer ai nodi <campo> che li leggeranno al posto di accedere al file di input. Più chiamate a questo nodo sovrascrivono sempre la stessa area di memoria. Un nodo <campo> accede ai byte del buffer invece che a quelli del file di input se presenta l'attributo "buffer".
<buffer dimensione="100"/>
dimensione="100"
Il numero di byte da leggere dal file di input. Può assumere anche attributi variabili. Questa operazione porta avanti il punto d'accesso al file quindi un successivo <campo> che legge dal file accede al byte 101. Se invece presenta l'attributo "buffer" legge proprio da questi 100 byte e porta avanti il punto d'accesso al buffer.
Questo nodo permette di stampare (scrivere) un qualsiasi testo nel file di report, indipendentemente dai dati letti dal file di input.
testo="commento"
E' il testo obbligatorio che si vuole scrivere nel report. Può contenere anche gli attributi variabili.
nuovalinea="si"
Indica se al termine del testo il software che genera il report deve inserire un "ritorno a capo" oppure no. E' facoltativo ma se presente può assumere solo i valori seguenti:
"si":
al testo si deve accodate un ritorno a capo, tipicamente "\0d\0a" ma dipende dal software che genera il report che terrà conto della piattaforma su cui il report sarà generato; E' il comportamento predefinito qualora l'attributo sia assente.
"no":
al testo non si deve accodate un ritorno a capo. Può essere utile se si vuole aggiungere un commento sulla stessa riga della "descrizione" del nodo <campo> che segue il nodo <stampa>.
Gli attributi variabili vengono usati per rendere flessibile la lettura di
un file. Il formato di un file, ad esempio, può avere campi con
dimensione variabile e cioè che dipendono dal valore letto da un altro
campo, intere strutture possono essere lette o meno secondo il valore
assunto dai campi già letti.
Un attributo variabile viene indicato con una delle seguenti scritture:
CAMPO[nome].valore: in cui "nome" deve essere l'attributo "nome" di un nodo <campo> già definito. Dà accesso al valore letto dal file per il campo il cui attributo "nome" corrisponde a quello indicato.
CAMPO[nome].dimensione: in cui "nome" deve essere l'attributo "nome" di un nodo <campo> già definito. Dà accesso all'attributo "dimensione" del campo il cui attributo "nome" corrisponde a quello indicato.
VARIABILE[nome].valore: in cui "nome" deve essere l'attributo "nome" di un nodo <variabile> già definito. Dà accesso all'attributo "valore" del nodo <variabile> il cui attributo "nome" corrisponde a quello indicato.
RIPETI[nome].contatore: in cui "nome" deve essere l'attributo "nome" di un nodo <ripeti> già definito. Dà accesso al valore del contatore gestito dal nodo <ripeti> il cui attributo "nome" corrisponde a quello indicato.
Nel caso di un nodo <campo>, se "nome" ne individua uno di tipo testo allora la scrittura "CAMPO[nome].valore" ha sempre senso mentre se individua un <campo> di tipo numerico ha senso solo se la sua "dimensione" è minore o uguale a 4.
Gli attributi variabili possono essere usati con i nodi <se> (per rendere variabile l'attributo "vero"), <ripeti> (per rendere variabile l'attributo "per" o "mentre"), <campo> (per rendere variabile l'attributo "dimensione"), uno dei nodi aritmetici quali <sottrai>, <somma>, <dividi> e <moltiplica> (per rendere variabili gli attributi "op1", "op2" e "ris").
Per definizione, un report deve contenere sono testi visualizzabili con un
qualsiasi editor di testi. Il fatto che un campo sia di tipo "testo" non
garantisce questa condizione perché potrebbe contenere dei caratteri non
visualizzabili rappresentanti formattazioni particolari o comunque controlli
specifici insieme al testo.
Un byte non è visualizzabile se ha un valore ascii
esadecimale minore di 0x20 oppure maggiore di 0x7D.
Si definisce che tali byte (letti mediante un <campo> di tipo testo) devono essere inseriti nel report con la sequenza "\xx" con "xx" pari al valore ascii esadecimale. Ad esempio il
byte 0x01, se letto da un campo di tipo testo, sarà inserito come
"\01" (testo di 3 byte che rappresenta un solo byte letto dal file di input).
Poichè il carattere "\" è utilizzato nella sequenza, se
il testo stesso contiene uno "\" esso deve essere inserito nel report come
"\\" (testo di 2 byte che rappresenta il singolo byte "\").
5 Dimensioni con marcatore
Le dimensioni con marcatore permettono di gestire quei campi che contengono dati
di lunghezza variabile cioè non prefissata a priori ma individuata da una
sequanza definita di byte che chiamiamo marcatore. Ad esempio un nodo
<campo> può avere la dimensione
dimensione="#\0d\0a"
in cui il carattere # indica che devono essere letti i byte fino alla lettura del testo indicato. Sottolineo il fatto che si tratta di un testo quindi, come nell'esempio precedente, può contenere caratteri non visualizzabili, anzi, è necessario farne uso se il marcatore previsto dal file invece è numerico (necessariamente non visualizzabile).
ATTENZIONE che il marcatore fa parte del valore del campo, altrimenti nel report non si avrebbe traccia della sua presenza.
La scrittura che segue il carattere "#" può essere anche un attributo variabile.
Le dimensioni raggruppate permettono di gestire quei campi che
contengono una lista di valori. Ad esempio un nodo <campo>
può avere la dimensione
dimensione="2*4"
in cui si indica che devono essere letti 8 byte ma questi sono
raggruppati logicamente come 4 gruppi da 2 byte. Una o entrambe le
parti separate dal carattere "*"
possono essere attributi variabili.