
Lo strumento per le strutture permette di analizzare e modificare i vettori di byte in base a definizioni di strutture dell'utente, che possono essere costituite da array, unioni, tipi primitivi ed enumerazioni.
Ha una propria finestra di configurazione, che si può raggiungere con il pulsante . Ci sono diverse opzioni configurabili, come lo stile con cui i valori sono visualizzati (decimale, esadecimale, o binario). Inoltre è possibile scegliere quali definizioni di strutture caricare e quali mostrare nella vista.
Le strutture sono definite in file di definizione di strutture di Okteta (basati su XML, con estensione .osd
). Inoltre, un file .desktop
contiene metadati sul file di descrizione delle strutture, come autore, pagina Web e licenza.
Attualmente non c'è un supporto integrato per creare o modificare definizioni di strutture, quindi ciò va fatto manualmente, come descritto nelle sezioni seguenti.
Il modo più facile di installare nuove definizioni di strutture è usare il supporto per le Novità incorporato in Okteta. Per installare una struttura esistente apri la finestra delle impostazioni dello strumento per le strutture. Lì, seleziona la scheda Gestione strutture e premi il pulsante . La finestra che apparirà permette di installare e disinstallare strutture.
Lo strumento per le strutture cerca descrizioni di strutture nella sotto-cartella okteta/structures/
della cartella dei dati dei programmi dell'utente (si trova con qtpaths
). Potresti dover creare questa cartella se non ci sono ancora definizioni di strutture installate.--paths GenericDataLocation
Ci sono due file per ogni definizione di struttura: un file per la definizione vera e propria, e un file .desktop
per i metadati (autore, versione, eccetera).
In quella cartella c'è una sottocartella per ogni definizione di struttura, contenente sia il file .desktop
che il file .osd
o main.js
della definizione.
Per esempio, con la cartella di dati dei programmi
e una definizione di struttura chiamata Esempio, c'è la cartella qtpaths
--paths GenericDataLocation
okteta/structures/Esempio
, contenente un file Esempio.desktop
e un file Esempio.osd
.
Se hai installato una nuova definizione di struttura creando una tale sottocartella con i due file o li hai modificati, devi riavviare Okteta e aprire la finestra di configurazione dello strumento per le strutture. Lì, seleziona la scheda Gestione strutture e assicurati che la definizione di struttura desiderata sia segnata. Usa quindi il pulsante , passa alla scheda Strutture e assicurati che l'elemento desiderato sia elencato sul lato destro.
Per le strutture comuni potresti non dover creare una definizione personalizzata, ma riutilizzarne invece una già disponibile per esempio da store.kde.org.
Potresti anche voler condividere una tua definizione. Per farlo, crea un file d'archivio (per esempio un archivio tar compresso, .tar.gz
) contenente solo la sottocartella con il file .desktop
e il file di definizione della struttura. Nell'esempio nella sezione precedente sarebbe nella cartella Esempio
con tutti i suoi contenuti. Usare questo formato per condividere le definizioni delle strutture permette di installarle da dentro Okteta e non richiede l'installazione manuale.
Nota
Una guida più aggiornata, ma non completa, per la scrittura di definizioni di strutture può essere consultata sul wiki KDE UserBase.
Ci sono due modi diversi di creare definizioni di strutture. La prima è scrivere la definizione in XML, l'altra è usare JavaScript. L'approccio con JavaScript permette di creare strutture più complesse con funzionalità come per esempio la validazione della struttura. Usare XML dà meno opportunità, ma se ti serve solo una struttura statica potrebbe essere la cosa più facile. Se ti serve una struttura dinamica, per esempio in cui le lunghezze dei vettori dipendono da altri valori nella struttura, o la disposizione della struttura è diversa quando qualche valore membro cambia, dovrai scrivere la definizione della struttura in JavaScript. C'è un'eccezione a questa regola: se hai un array in cui la lunghezza deve essere esattamente la stessa di un altro valore nella struttura, puoi usare XML. Se invece è qualcosa come lunghezza - 1
devi ancora usare JavaScript.
Nota
Una guida più aggiornata, ma non completa, per la scrittura di definizioni di strutture può essere consultata sul wiki KDE UserBase.
Il file XML .osd
ha un elemento radice: <data>
, senza attributi. Dentro a questo elemento ci dev'essere uno dei seguenti elementi:
- <primitive>
Per creare un tipo di dati primitivo, come per esempio
int
efloat
. Questo elemento non accetta sottoelementi e può avere i seguenti attributi:- type
Il tipo di questo tipo primitivo. Deve essere uno dei seguenti:
char
per un carattere ASCII a 8 bitint8, int16, int32, int64
per un intero con segno di quella dimensioneuint8, uint16, uint32, uint64
per un intero senza segno di quella dimensionebool8, bool16, bool32, bool64
per un booleano senza segno (0 = falso, qualsiasi altro valore = vero) di quella dimensionefloat
per un numero a virgola mobile IEEE754 a 32 bitdouble
per un numero a virgola mobile IEEE754 a 64 bit
- <bitfield>
Per creare un campo di bit. Questo elemento non accetta sottoelementi e può avere i seguenti attributi:
- width
Il numero di bit usati da questo campo. Deve essere tra 1 e 64.
- type
Il tipo di questo campo di bit. Deve essere uno dei seguenti:
unsigned
per un campo di bit dove il valore verrà interpretato come senza segno (valore tra 0 e 2larghezza - 1)signed
per un campo di bit dove il valore verrà interpretato come con segno (valore tra - 2larghezza - 1 e 2larghezza - 1 - 1)bool
per un campo di bit dove il valore verrà interpretato come un booleano
Nota
Ricordati sempre di aggiungere dello spazio dopo un
<bitfield>
, perché altrimenti il prossimo elemento (tranne che per stringhe ed array, visto che questi aggiungono spazio automaticamente) comincerà nel mezzo di un byte. Ovviamente lo spazio non è necessario se desideri questo comportamento.
- <enum>
Per creare un tipo primitivo, ma in cui i valori siano visualizzati come membri di un'enumerazione, se possibile. Questo elemento non accetta nessun sottoelemento (servirà però un'etichetta
<enumDef>
nel file per farvi riferimento). Ha i seguenti attributi:- enum
L'enumerazione su cui si basa questo valore. Deve corrispondere all'attributo
name
delle etichette<enumDef>
in questo file.- type
Il tipo dell'enumerazione. Vedi l'attributo omonimo di
<primitive>
. L'unica differenza è cheDouble
eFloat
non hanno senso.
- <flags>
È la stessa cosa che
<enum>
con la sola differenza che i valori sono rappresentati come un O logico sui bit di tutti i valori dell'enumerazione.- <struct>
Per creare una struttura. Tutti gli altri elementi (incluso
<struct>
) possono esserne figli, e saranno parte della struttura risultante.- <union>
Per creare un'unione. Sostanzialmente la stessa cosa di
<struct>
, tranne che tutti gli elementi figli partiranno dallo stesso scostamento. È utile per interpretare la stessa sequenza di byte in modi diversi.- <array>
Per creare un array. Questo elemento accetta esattamente un figlio (il tipo di array su cui si basa), che può essere qualsiasi elemento, anche
<array>
stesso. Ha anche i seguenti attributi:- length
Il numero di elementi in questo array come numero decimale. In alternativa può anche essere una stringa corrispondente al nome di un
<primitive>
,<enum>
o<flags>
definito in precedenza. La lunghezza sarà in tal caso sempre uguale al valore di quell'elemento. Attualmente è limitata a 10000, perché array di maggiori dimensioni userebbero troppa memoria e rallenterebbero troppo lo strumento.
- <string>
Per creare una stringa in varie codifiche. Come impostazione predefinita ottieni una stringa terminata da NULL in stile C. È però possibile creare diversi tipi di stringa con i seguenti attributi:
- terminatedBy
Questo attributo determina quale punto di codice Unicode conclude la stringa. Deve essere un numero esadecimale (facoltativamente con un
0x
iniziale). Quando la codifica è ASCII, solo i valori fino a0x7f
hanno senso. Se né questo valore, némaxCharCount
némaxByteCount
sono impostati, si assume che sia 0 (stringa in stile C).- maxCharCount
Il numero massimo di caratteri di questa stringa. Se è impostato anche
terminatedBy
, il primo criterio a verificarsi termina la stringa. Questo è mutuamente esclusivo conmaxByteCount
.- maxByteCount
La lunghezza massima in byte di questa stringa. Se è impostato anche
terminatedBy
, il primo criterio a verificarsi termina la stringa. Questo è mutuamente esclusivo conmaxCharCount
. Con codifiche comeASCII
è la stessa cosa dimaxCharCount
.- type
La codifica di questa stringa. Può essere una delle seguenti:
ASCII
LATIN-1
UTF-8
UTF-16-LE
oUTF-16-BE
. Se non viene dato né il suffisso-LE
né-BE
, si assume la codifica little endian.UTF-32-LE
oUTF-32-BE
. Se non viene dato né il suffisso-LE
né-BE
, si assume la codifica little endian.
Ogni elemento accetta anche un attributo name
che è poi visibile nella vista delle strutture.
Nota
Una guida più aggiornata, ma non completa, per la scrittura di definizioni di strutture può essere consultata sul wiki KDE UserBase.
Il nostro file di metadati ha questo aspetto:
[Desktop Entry] Icon=arrow-up❶ Type=Service ServiceTypes=KPluginInfo Name=Semplice struttura di prova Comment=Struttura di prova molto semplice con due soli elementi X-KDE-PluginInfo-Author=Pinco Pallino X-KDE-PluginInfo-Email=pinco@pallino.it X-KDE-PluginInfo-Name=semplice X-KDE-PluginInfo-Version=1.0 X-KDE-PluginInfo-Website=https://it.wiktionary.org/wiki/semplice X-KDE-PluginInfo-Category=structure X-KDE-PluginInfo-License=LGPL X-KDE-PluginInfo-EnabledByDefault=false
L'icona visualizzata in Okteta per questa struttura. Può essere qualsiasi cosa che si può trovare eseguendo |
Questi campi dovrebbero essere tutti abbastanza facili da capire, tranne X-KDE-PluginInfo-Name
: questo deve avere il nome della cartella contenente il file così come il nome del file .desktop
. Quando si creano definizioni di strutture con XML, anche il nome del file .osd
deve corrispondere.
In questo esempio avremmo una cartella di nome semplice
contenente il file semplice.desktop
. Quando si definiscono strutture in XML, la cartella conterrebbe anche un file di nome semplice.osd
. Usando JavaScript, avremmo invece un file di nome main.js
.
Per cominciare creiamo una definizione per una struttura di prova molto semplice, contenente solo tipo di dati integrali (un carattere, un intero a 32 bit, e un campo di bit). In C e C++ verrebbero espressi come:
struct simple { char aChar; int anInt; bool bitFlag :1; unsigned padding :7; };
Il primo passo è scrivere il file .osd
secondo il formato di file definito nella sezione precedente. Lo chiameremo semplice.osd
:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<struct name="semplice">
<primitive name="carattere" type="Char"/>
<primitive name="intero" type="Int32"/>
<bitfield name="bitFlag" type="bool" width="1"/>
<bitfield name="padding" type="unsigned" width="7"/>
</struct>
</data>
il che è abbastanza simile alla definizione in C o C++.
Adesso crea una cartella semplice
sotto la cartella di installazione delle strutture (rivedi come si installano manualmente le strutture), e copiaci i due file. Adesso puoi riavviare Okteta e usare la nuova struttura.
Per implementare la struttura sopra in JavaScript, crea un file di nome main.js
invece che semplicestruttura.osd
e cambia X-KDE-PluginInfo-Category=structure in X-KDE-PluginInfo-Category=structure/js. I contenuti di questo file dovrebbero essere:
function init() { var structure = struct({ aChar : char(), anInt : int32(), bitFlag : bitfield("bool", 1), padding : bitfield("unsigned", 7), }) return structure; }
La struttura visualizzata da Okteta è sempre il valore restituito dalla funzione init
.
Le funzioni seguenti possono essere chiamate per creare un tipo primitivo:
char()
int8()
,int16()
,int32()
oint64()
uint8()
,uint16()
,uint32()
ouint64()
bool8()
,bool16()
,bool32()
obool64()
float()
double()
La funzione bitfield
prende due argomenti, di cui il primo è una stringa che può essere bool
, signed
o unsigned
. Il secondo è un intero che imposta l'ampiezza in bit.
Adesso creiamo la definizione di una struttura più complessa, che chiameremo «complessa» e salveremo in un file di nome complessa.osd
. Questa struttura conterrà due array (uno di lunghezza fissa e uno di lunghezza determinata durante l'esecuzione), oltre a una struttura annidata e un'unione.
<?xml version="1.0" encoding="UTF-8"?>
<data>
<struct name="complessa">
<primitive name="dimensione" type="UInt8" />
<union name="unione">
<array name="quattroByte" length="4">
<primitive type="Int8" />
</array>
</union>
<struct name="annidata">
<array name="stringa" length="dimensione"> <!-- fa riferimento alla dimensione di cui sopra -->
<primitive type="Char" />
</array>
</struct>
</struct>
</data>
Ciò corrisponderebbe a quanto segue in pseudo C o C++:
struct complessa { uint8_t dimensione; union unione { int8_t quattroByte[4]; }; struct annidata { char stringa[dimensione] // non è C++ valido, fa riferimento al valore della dimensione uint8 }; };
Nota
Ovviamente puoi far riferire array a lunghezza dinamica solo a campi che vengono prima di questi.
Adesso creiamo il file complessa.desktop
come nell'esempio precedente (assicurati di impostare X-KDE-PluginInfo-Name
correttamente) e facciamo lo stesso per installare i file.
Alcune definizioni di strutture esemplificative sono reperibili nel deposito Git, incluse per esempio le intestazioni dei file PNG e per i file ELF. Uno schema XML che descrive la struttura del file .osd
è disponibile qui. Se servono maggiori informazioni, non esitare a contattare (arichardson.kde gmail.com)
.