Strumento per le strutture

Generale

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 Impostazioni. 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.

Installare definizioni di strutture

Installare con le Novità

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 Prendi nuove strutture. La finestra che apparirà permette di installare e disinstallare strutture.

Installare manualmente definizioni di 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 --paths GenericDataLocation). Potresti dover creare questa cartella se non ci sono ancora definizioni di strutture installate.

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 qtpaths --paths GenericDataLocation e una definizione di struttura chiamata Esempio, c'è la cartella okteta/structures/Esempio, contenente un file Esempio.desktop e un file Esempio.osd.

Usare le strutture appena installate

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 Applica, passa alla scheda Strutture e assicurati che l'elemento desiderato sia elencato sul lato destro.

Condividere definizioni di strutture

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.

Creare definizioni di strutture

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.

Formato dei file XML per le definizioni di strutture

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 e float. 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 bit

  • int8, int16, int32, int64 per un intero con segno di quella dimensione

  • uint8, uint16, uint32, uint64 per un intero senza segno di quella dimensione

  • bool8, bool16, bool32, bool64 per un booleano senza segno (0 = falso, qualsiasi altro valore = vero) di quella dimensione

  • float per un numero a virgola mobile IEEE754 a 32 bit

  • double 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 è che Double e Float 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 a 0x7f hanno senso. Se né questo valore, né maxCharCountmaxByteCount 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 con maxByteCount.

maxByteCount

La lunghezza massima in byte di questa stringa. Se è impostato anche terminatedBy, il primo criterio a verificarsi termina la stringa. Questo è mutuamente esclusivo con maxCharCount. Con codifiche come ASCII è la stessa cosa di maxCharCount.

type

La codifica di questa stringa. Può essere una delle seguenti:

  • ASCII

  • LATIN-1

  • UTF-8

  • UTF-16-LE o UTF-16-BE. Se non viene dato né il suffisso -LE-BE, si assume la codifica little endian.

  • UTF-32-LE o UTF-32-BE. Se non viene dato né il suffisso -LE-BE, si assume la codifica little endian.

Ogni elemento accetta anche un attributo name che è poi visibile nella vista delle strutture.

Una definizione di struttura d'esempio in XML e in JavaScript

Nota

Una guida più aggiornata, ma non completa, per la scrittura di definizioni di strutture può essere consultata sul wiki KDE UserBase.

Il passo in comune ad entrambi gli approcci

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 kdialog --geticon, o il percorso a un'icona.

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.

Una semplice definizione di struttura XML

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.

La struttura semplice in JavaScript

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() o int64()

  • uint8(), uint16(), uint32() o uint64()

  • bool8(), bool16(), bool32() o bool64()

  • 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.

Strutture più complesse

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.

Ulteriori informazioni

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 .