Het hulpmiddel Structuren schakelt analyseren en bewerking van byte-arrays in gebaseerd op door de gebruiker gemaakte structuurdefinities, die kunnen worden gebouwd uit arrays, unions, primitieve typen en een lijst met waarden.
Het heeft een eigen instellingendialoog, die bereikt wordt de knop . Er zijn verschillende opties die ingesteld kunnen worden, zoals de stijl waarin (decimaal, hexadecimaal of binair) de waarden getoond worden. Verder is het mogelijk te kiezen welke structuurdefinities geladen moeten worden en welke structuren getoond worden in het voorbeeld.
Structuren worden gedefinieerd in Okteta-structuurdefinitiebestanden (gebaseerd op XML, met de bestandsextensie .osd
). Verder kan een .desktop
bestand metagegevens bevatten over dat structuurbeschrijvingsbestand, zoals auteur, homepagina en licentie.
Op dit moment is er geen ingebouwde ondersteuning voor maken of bewerken van structuurdefinities, dit moet daarom handmatig gedaan worden zoals beschreven in de volgende secties.
De gemakkelijkste manier om nieuwe structuurdefinities te installeren is door de ingebouwde KNewStuff-ondersteuning in Okteta te gebruiken. Om een bestaande structuur te installeren opent u de instellingendialoog van het hulpmiddel Structures. U selecteert daar het tabblad Beheer van structuren en drukt op de knop . De dialoog die verschijnt stelt u nu in staat om structuren te installeren en te deïnstalleren.
Het hulpmiddel voor structuren zoekt naar structuurdefinities in de map okteta/structures/
van de map voor programmagegevens van de gebruiker (u kunt deze vinden via de opdracht qtpaths
). U moet deze map misschien nog aanmaken als er nog geen structuurdefinities zijn geïnstalleerd.--paths GenericDataLocation
Er bestaan twee bestanden voor elke structuurdefinitie: een bestand voor de actuele definitie en een .desktop
-bestand voor de metagegevens (auteur, versie, etc.).
In deze map is een submap voor elke structuurdefinitie, waarin zowel het .desktop
-bestand en het .osd
of main.js
bestand van deze definitie aanwezig zijn.
Bijvoorbeeld met de programmagegevensmap
en een structuurdefinitie genaamd VoorbeeldStructuur is de map qtpaths
--paths GenericDataLocation
okteta/structures/VoorbeeldStructuur
, die bestanden VoorbeelStructuur.desktop
en VoorbeeldStructuur.osd
bevat.
Nadat u nieuwe structuurdefinities heeft geïnstalleerd, moet u Okteta opnieuw starten voordat u deze kunt gebruiken. Nadat Okteta opnieuw is gestart, opent u de instellingendialoog van het hulpmiddel voor structuren en selecteert u vervolgens het tabblad Beheer van structuren en controleert of de relevante structuurdefinitie is ingeschakeld. Ga vervolgens naar het tabblad Structuren en controleer dat het verlangde element aan de rechterkant is te zien.
Het is waarschijnlijk niet nodig voor standaard structuren dat u de definitie zelf aanmaakt, in plaats daarvan kunt u een al bestaande definitie gebruiken van een plaats zoals store.kde.org.
U kunt ook een eigengemaakte definitie met anderen delen. Om dit te doen maakt u een archiefbestand aan (bijv. een gezipt tar-archief, .tar.gz
) met daarin de map met het .desktop
-bestand en het structuurdefinitiebestand. In het voorbeeld in het laatste sectie van dit hoofdstuk zal dit zijn de map ExampleStructure
met al zijn inhoud. Door gebruik van dit formaat voor het delen van de structuurdefinities is het mogelijk ze automatisch in Okteta te installeren en is handmatige installatie niet nodig.
Opmerking
een meer bijgewerkte, maar niet geheel gerede handleiding om structuurdefinities te schrijven is te vinden in op de KDE UserBase Wiki.
Er zijn twee verschillende manieren om structuurdefinities aan te maken. De eerste is het schrijven van de definitie in XML de andere is het gebruik van JavaScript. Het gebruik van JavaScript geeft u de vrijheid om meer complexere structuren met mogelijkheden zoals structuurcontrole te creëren. Het gebruik van XML geeft u minder mogelijkheden maar als statistische structuren alles is wat u nodig heeft dan kan dit de makkelijkste manier zijn. Als u een dynamische structuur nodig heeft bijv. waar array lengtes van andere waarden in de structuur afhangen of de structuurindeling verandert wanneer sommige waarden wijzigingen, dan zult u de structuurdefinitie in JavaScript moeten schrijven. Er is een uitzondering op die regel: als u een array heeft waarvan de lengte exact gelijk is aan een andere waarde in de structuur, dan kan u ook XML gebruiken. Maar als het iets is zoals lengte - 1 dan moet het JavaScript zijn.
Opmerking
een meer bijgewerkte, maar niet geheel gerede handleiding om structuurdefinities te schrijven is te vinden in op de KDE UserBase Wiki.
Het .osd
XML-bestand heeft één basiselement: <data> zonder attributen. Binnen dit element moet er één van de volgende elementen zijn:
- <primitive>
Om een 'primitive' gegevenstype zoals bijv. int en float aan te maken. Dit element accepteert geen subelementen en kan de volgende attributen hebben:
- type
Het type van deze primitieve type. Het moet een van de volgende zijn:
char voor een 8-bits ASCII-teken
int8, int16, int32, int64 voor een geheel getal met teken met die grootte
uint8, uint16, uint32, uint64 voor een geheel getal zonder teken van die grootte
bool8, bool16, bool32, bool64 voor een logische waarde (boolean) (0 = false, elke andere waarde = true) van die grootte
float voor een 32-bits IEEE754 drijvende-komma getal
double voor een 64-bits IEEE754 drijvende-komma getal
- <bitfield>
Om een 'bitfield' aan te maken Dit element accepteert geen subelementen en kan de volgende attributen hebben:
- breedte
Het aantal bits gebruikt door dit 'bitfield'. Moet liggen tussen 1 en 64.
- type
Het type van dit 'bitfield'. Het moet één van de volgende zijn:
unsigned voor een bitfield waar de waarde geïnterpreteerd zal worden als een waarde zonder teken (waardereeks van 0 tot 2breedte - 1)
signed voor een bitfield waar de waarde geïnterpreteerd zal worden als een waarde met teken (waardereeks van -2breedte - 1 tot 2breedte - 1 - 1)
bool voor een 'bitfield' waar de waarde als een booleaanse waarde zal worden geïnterpreteerd
Opmerking
Denk er aan om padding toe te voegen na een <bitfield>, omdat het volgende element anders in het midden van een byte zou beginnen (behalve voor tekenreeksen en arrays, omdat zij automatisch padding toevoegen). Als u dit gedrag wenst dan is padding natuurlijk niet nodig.
- <enum>
Om een type primitive te maken, maar waar de waarden getoond worden, indien mogelijk, als leden van een enumeratie. Dit element accepteert geen subelementen (maar u hebt mogelijk een tag <enumDef> in het bestand nodig om er naar te refereren). Het heeft de volgende attributen:
- enum
De onderliggende 'enum' voor deze waarde. Moet overeenkomen met het attribuut name van één van de tags <enumDef> in dit bestand.
- type
Het type hiervan is enum. Zie type attribuut van <primitive>. Het enige verschil is dat Double en Float geen betekenis hebben.
- <flags>
Dit is hetzelfde als <enum> met het enige verschil dat waarden gerepresenteerd worden als een bitwise-or van alle waarden van de enumeratie (opsomming).
- <struct>
Hiermee creëert u een structuur. Alle andere elementen (inclusief een <struct>) kunnen hiervan onderdeel uitmaken (child)
- <union>
Hiermee creëert u een union. In wezen hetzelfde als een <struct>, behalve het feit dat alle child-elementen vanaf dezelfde offset starten. Dit is handig voor het op verschillende manieren onderzoeken van dezelfde volgorde van bytes.
- <array>
Hiermee creëert u een array. Dit element accepteert precies een child (het onderliggende type array), waarin u elk soort element kan plaatsten, zelfs een <array>. Het heeft de volgende attributen:
- lengte
Het aantal elementen in dit array als decimaal getal. Als alternatief kan het ook een tekenreeks zijn waarvan de naam overeenkomt met een eerder gedefinieerde <primitive>, <enum> of <flags> element. De lengte zal dan overeenkomen met de waarde van dat element. De lengte is op dit moment beperkt tot 10000, omdat grotere arrays teveel geheugen gebruiken en teveel vertragen.
- <string>
Hiermee kun u een tekenreeks in een codering naar keuze creëren. Standaard is dit een tekenreeks in de C-style beëindigt door een NULL. Maar met de volgende attributen kunt u andere soorten tekenreeksen creëren:
- terminatedBy
Dit attribute bepaalt door welk unicode karakter de tekenreeks wordt beëindigd. Dit moet een hexadecimaal nummer zijn (optioneel met een leidende 0x). Wanneer de codering in ASCII is dan hebben alleen waarden tot 0x7f een betekenis. Als u zowel dit of maxCharCount of maxByteCount niet heeft ingesteld dan is dit standaard ingesteld op 0 (C-style string)
- maxCharCount
Het maximum aantal tekens dat deze tekenreeks kan hebben. Als terminatedBy ook is ingesteld dan eindigt de tekenreeks door datgene wat als eerste is bereikt. Dit gaat niet samen met maxByteCount
- maxByteCount
Het maximum aantal bytes dat in deze tekenreeks past. Als terminatedBy ook is ingesteld, dan wordt de tekenreeks afgesloten door datgene wat het eerst bereikt wordt. Dit gaat niet samen met maxCharCount. Alleen bij decoderingen zoals ASCII komt dit overeen met maxCharCount.
- type
De codering van deze tekenreeks. Kan een van de volgende zijn:
ASCII
LATIN-1
UTF-8
UTF-16-LE of UTF-16-BE. Als geen -LE of -BE achtervoegsel is gegeven, wordt 'little endian' aangenomen.
UTF-32-LE of UTF-32-BE. Als geen -LE of -BE achtervoegsel is gegeven, wordt 'little endian' aangenomen.
Elk element accepteert ook een attribuut name dat dan zichtbaar is in de structurenweergave.
Opmerking
een meer bijgewerkte, maar niet geheel gerede handleiding om structuurdefinities te schrijven is te vinden in op de KDE UserBase Wiki.
Ons bestand met metagegevens ziet er zo uit:
[Desktop Entry] Icon=arrow-up❶ Type=Service ServiceTypes=KPluginInfo Name=Simpele teststructuur Comment=Een erg simpele teststructuur met slechts twee items X-KDE-PluginInfo-Author=Alex Richardson X-KDE-PluginInfo-Email=foo.bar@email.org X-KDE-PluginInfo-Name=simplestruct X-KDE-PluginInfo-Version=1.0 X-KDE-PluginInfo-Website=https://www.plugin.org/ X-KDE-PluginInfo-Category=structure X-KDE-PluginInfo-License=LGPL X-KDE-PluginInfo-EnabledByDefault=false
Het pictogram getoond in Okteta voor deze structuur kan alles zijn wat gevonden wordt door |
Deze velden zouden allemaal zichzelf moeten verklaren, behalve voor X-KDE-PluginInfo-Name
. De waarde van dit veld moet overeenkomen met de naam van de map met het bestand evenals de naam van het .desktop
-bestand. Bij het maken van XML-structuurdefinities zal de naam van het .osd
bestand ook met de naam overeen moeten komen.
In dit voorbeeld willen we een map met de naam simplestruct
met daarin het bestand simplestruct.desktop
hebben. Als we de structuren definiëren in XML dan is in de map ook een bestand genaamd simplestruct.osd
aanwezig. Bij gebruik van JavaScript hebben we in plaats daarvan een bestand met de naam main.js
.
Om te beginnen creëren we een definitie voor een eenvoudige teststructuur met alleen integrale gegevenstypes (een char, een 32-bit signed integer en een bitfield). Dit is in C/C++ uitgeschreven als:
struct simple { char aChar; int anInt; bool bitFlag :1; unsigned padding :7; };
De eerste stap is het schrijven van het .osd
-bestand overeenkomstig het bestandsformaat zoals in de vorige sectie beschreven. We geven het de naam simplestruct.osd
:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<struct name="simple">
<primitive name="aChar" type="Char"/>
<primitive name="anInt" type="Int32"/>
<bitfield name="bitFlag" type="bool" width="1"/>
<bitfield name="padding" type="unsigned" width="7"/>
</struct>
</data>
wat overeenkomt met de C/C++ definitie.
Maak nu een map aan met de naam simplestruct
in de structuur installatiemap (lees handmatig structuurdefinities installeren) en kopieer de twee bestanden naar deze map. Na het opnieuw opstarten van Okteta kunt u de nieuwe structuur gebruiken.
Om bovengenoemde structuren in JavaScript te implementeren, creëert u een bestand met de naam main.js
in plaats van simplestruct.osd
en wijzigt u X-KDE-PluginInfo-Category=structure in X-KDE-PluginInfo-Category=structure/js. De inhoud van dat bestand zou het volgende moeten zijn:
function init() { var structure = struct({ aChar : char(), anInt : int32(), bitFlag : bitfield("bool", 1), padding : bitfield("unsigned", 7), }) return structure; }
De structuur die Okteta toont is altijd de "return value" van de init
-functie.
U kunt de volgende functies aanroepen om een primitief type te creeëren:
char()
int8(), int16(), int32() or int64()
uint8(), uint16(), uint32() or uint64()
bool8(), bool16(), bool32() or bool64()
float()
double()
De bitfield-functie heeft twee parameters nodig, de eerste is een tekenreeks bestaande uit bool
, signed
of unsigned
. De tweede parameter is een integer die de breedte in bits instelt.
Vervolgens creëren we een definitie voor een complexere structuur waaraan we de naam "complex" geven en we slaan dit op in een bestand genaamd complex.osd
. Deze structuur bestaat uit twee arrays (een met een vaste lengte en een waarvan de lengte tijdens de uitvoering wordt bepaald), een geneste structuur en een verzameling.
<?xml version="1.0" encoding="UTF-8"?>
<data>
<struct name="complex">
<primitive name="size" type="UInt8" />
<union name="aUnion">
<array name="fourBytes" length="4">
<primitive type="Int8" />
</array>
</union>
<struct name="nested">
<array name="string" length="size"> <!-- verwijzing naar de field-size boven -->
<primitive type="Char" />
</array>
</struct>
</struct>
</data>
Dit zou overeen moeten komen met het volgende in pseudo-C/C++
struct complex { uint8_t size; union aUnion { int8_t fourBytes[4]; }; struct nested { char string[size] //geen geldige C++, refereert waarde van de grootte uint8 }; };
Opmerking
U kunt uiteraard de referentie-velden voor arrays met dynamische lengte alleen vóór het array hebben,
Vervolgens maken we het bestand complex.desktop
net als in het vorige voorbeeld (ga na dat u X-KDE-PluginInfo-Name
juist instelt) en ook hetzelfde doet om beide bestanden te installeren.
Enkele voorbeelden voor structuurdefinities kunt u vinden in deze Git repository. Inclusief voorbeelden voor de bestand-header van PNG-bestanden en de ELF bestand-header. Een XML schema voor de structuur van een .osd
-bestand kunt u hier vinden. Als u meer informatie wilt dan kunt u met mij contact opnemen via (arichardson.kde gmail.com)