AMIGA-Magazin · Ausgabe 3/05 OS-4-Programmierung: Utility-Library

Aktuelles Heft 03/05

Kleine Helferin

Die unscheinbare utility.library wurde um viele nützliche Funktionen in Amiga-OS 4 erweitert.
Ein Grund mehr, sie hier genauer unter die Lupe zu nehmen und einige Praxisanwendungen zu zeigen.

von Michael Christoph

 

Die Taglisten gewinnen bei der utility.library unter AmigaOS 4 mehr an Bedeutung. Sie lassen sehr flexible Erweiterungen an den Bibliotheksfunktionen zu. Es muss nicht die Anzahl der übergebenen Argumente erweitert werden, sondern es wird einfach ein neuer Eintrag in den Taglisten aufgenommen. Unbekannte Tags ignoriert man.

Viele neue Funktionen der Utility-Bibliothek helfen beim Erzeugen, Durchsuchen und Filtern der angelegten Taglisten.

Prüfziffern
Es gibt die verschiedensten Arten von Prüfziffern und Möglichkeiten von Checksummen (z.B. CRC32, MD5). Die utility.library bietet jetzt auch die Möglichkeit zur Berechnung einer 160 Bit (20 Byte langen) Prüfziffer.

Dabei wird der SHA-1-Algorithmus verwendet. Im Vergleich zu den CRC16- bzw. CRC32-Prüfsummen (mit 2 bzw. 4 Byte) können so wesentlich größere Datenbereiche auf Eindeutigkeit geprüft werden. Damit wird verhindert, dass es zur Wiederholung einzelner Summen kommt und die Checksumme nicht mehr eindeutig ist.

Zuvor muss jedoch die Datenstruktur initialisiert werden, was von MessageDigest_SHA_Init() übernommen wird. Danach ist der Funktion MessageDigest_SHA_Update() der Speicherbereich und dessen Größe zu übergeben, für die die Summe berechnet werden soll. Die Funktion kann auch mehrfach hintereinander auf unterschiedliche Speicherbereiche angewendet werden.

So muss, z.B. für die Checksumme auf eine Datei, diese nicht vollständig im Speicher vorliegen, sondern kann auch blockweise berechnet werden. Nach abschließendem Aufruf von MessageDigest_SHA_Final() ist die generierte Checksumme unter mdsha->mdsha_Code zu finden. Beachtet werden muss, dass der String nicht mit einem Null-Byte abgeschlossen ist und daher mit strncpy() umkopiert/weiterverarbeitet werden muss. In kompakter Schreibweise würde er wie in Listing 2 aussehen.

Da es sich um einen bitweisen Prüfwert handelt, ist die Ausgabe/Anzeige mit Hilfe von Printf nicht unbedingt sinnvoll, da auch Steuerzeichen etc. dabei herauskommen können. Der Wert ist anhand von strncmp bzw. StriCmp mit dem Referenzwert zu vergleichen. Als externe Prüfziffer, die z.B. in Textdateien weitergegeben wird, ist diese Funktion also nicht geeignet.

Standard-C-Funktionen
Um unabhängiger von den C-Bibliotheken zu sein, gibt es jetzt auch die beiden Funktionen zum Kopieren und Anhängen von Strings in der utility.library. Allerdings sind die Namen etwas gewöhnungsbedürftig: Strlcpy und Strlcat. Die Reihenfolge ist aber identisch zu den strncpy- und strncat-Funktionen der C-Bibliothek.

Auch zum Setzen von Speicherbereichen gibt es jetzt in Anlehnung an memset eine SetMem-Funktion. Als Argumente sind neben der Startadresse im Speicher der zu setzende Wert anzugeben. Normalerweise ist es eine 0 zum Löschen des Speicherbereichs - zusätzlich übergeben Sie die Anzahl der zu ändernden Bytes. Die Reihenfolge entspricht der wie bei memset. Kürzer ist die Schreibweise mit ClearMem. Diese verlangt nur die Startadresse und die Anzahl der zu löschenden Bytes. Eine weitere Funktion, die mit Speicherbereichen arbeitet, ist MoveMem. Wie der Name schon vermuten lässt, dient sie zum Verschieben von Speicherbereichen.

Der Quellbereich wird allerdings nicht verändert, wodurch man richtigerweise von «Bereich kopieren» sprechen muss. Die Funktion ist vergleichbar mit CopyMem aus der exec.library, erlaubt darüber hinaus aber auch überlappende Speicherbereiche.

Sichergestellt werden muss, dass der Zielbereich auch groß genug ist, die Daten aufzunehmen. Und natürlich muss dieser auch für das eigene Programm reserviert worden sein. Mit »verschärftem« Speicherschutz ist ansonsten das Programm recht schnell vom Betriebssystem stillgelegt.

Zufallszahlen und Hilfsfunktionen
Auch eine neue Funktion zum Ermitteln von Zufallszahlen hat es in die utility.library geschafft: Random(). Zu übergeben ist der letzte Ergebniswert, falls eine Liste von zufälligen Zahlen erfragt werden soll. Möglich als Initialisierungswert ist z.B. auch die aktuelle Systemzeit oder gar nichts, wenn die Struktur auf dem Stack angelegt wird. Dann enthält sie auch einen sehr zufälligen Wert (den bisherigen Speicherinhalt). Wieder ein kleines Beispiel zur Ziehung der Lottozahlen (Listing 4). Nicht berücksichtigt wurde, dass jede Zahl nur einmal vorkommen darf.

Mit der Funktion GetUniqueID() lässt sich eine eindeutige Zahl ermitteln. Allerdings gilt das nur solange der Rechner nicht ausgeschaltet wird. Sie eignet sich also nicht für den langfristigen Einsatz oder auf Festplatte gespeicherte Dateinamen. Wenn z.B. mehrere Hintergrund-Tasks arbeiten und jede temporäre Daten auslagern will, kann hiermit ein eindeutiger Dateiname zusammengestellt werden. Auch der lha-Packer oder pgp-Tools arbeiten mit temporären Dateien, damit sie mehrfach gleichzeitig laufen können. Hierzu finden Sie in Listing 5 ein simples Beispiel, wie sich ein eindeutiger Name erzeugen lässt

Teilweise sind die hier besprochenen Funktionen erst in der utility.library Version 51 zu finden. Zum Ausprobieren der Beispiele müssen Sie sich die letzte Version des SDK`s bei Hyperion besorgen. Eine PDF-Datei mit weiteren Informationen zu den Funktionen der utility.library finden Sie auf der CD zur nächsten Ausgabe.

In der nächsten Ausgabe geht es dann um die gadtools.library und Reaction. Während erstere praktisch keine Bedeutung mehr hat, findet man bei Reaction wieder neue Funktionen.

lb

 

Glücksspiel-Hilfe:
Das Beispiel zur Erzeugung der Lottozahlen in der Praxis.

 

Listingübersicht

Listing 1: Die Bearbeitung der Tag-Listen.

Listing 2: Prüfsummen-Bearbeitung kompakt
Listing 3: Speicher- manipluationen mit der utility.library
Listing 4: Erzeugung von Lottozahlen
Listing 5: Erzeugung eines eindeutigen Namen für eine Temp-Datei

 

 

 

 

 

 

 

 

 

 

 

 

 

Hilfsfunktionen in der utility.library
VOID MessageDigest_SHA_Init(struct MessageDigest_SHA *mdsha);
VOID MessageDigest_SHA_Update(struct MessageDigest_SHA *mdsha, APTR data, LONG num_bytes);
VOID MessageDigest_SHA_Final(struct MessageDigest_SHA *mdsha);
Berechnen einer 160 bit Checksumme.
ULONG CallHookPkt(struct Hook *hook, APTR object, APTR message); Eine Hook-Funktion von object aufrufen und dabei message übermitteln.
ULONG GetUniqueID(void); Liefert eine eindeutige Zahl (solange der Rechner läuft).
LONG Random(struct RandomState *state); Liefert eine Zufallszahl im Bereich von 1 ... 2147483647 zurück
APTR SetMem(APTR destination, UBYTE value, LONG length); Füllt einen Speicherbereich mit einem Wert.
VOID ClearMem(APTR destination, uint32 size); Löscht einen Speicherbereich (füllt ihn mit 0-Bytes).
VOID MoveMem(APTR source, APTR destination, uint32 size); Verschieben von Speicherbereichen (auch überlap-
pend möglich).
LONG Strlcat(STRPTR destination, CONST_STRPTR source, LONG destination_size); Hängt an destination den String aus source an, wobei die maximale Länge beachtet wird
LONG Strlcpy(STRPTR destination, CONST_STRPTR source,
LONG destination_size);
Kopiert den String aus source nach destination, wobei die maximale Länge beachtet wird
struct Node *node = FindNameNC(struct Node *start, STRPTR name); Sucht einen Node anhand des Namens ohne Beachtung von Groß- und Kleinschreibung.
STRPTR VASPrintf(CONST_STRPTR format, APTR args);
STRPTR ASPrintf(CONST_STRPTR format, ...);
Erstellt einen String aus format und den gegebenen
args (der zurückgelieferte String ist per FreeVec freizugeben).
LONG VSNPrintf(STRPTR buffer, LONG buffer_size, CONST_STRPTR format, APTR args);
LONG SNPrintf(STRPTR buffer, LONG buffer_size, CONST_STRPTR format, ...);

Format-String erzeugen, wobei das Ergebnis im übergebenen buffer abgelegt wird.

 

Neue Funktionen in der utility.library
Tag-Listen-Funktionen
struct TagItem *AllocateTagItems(ULONG numtags); Speicher allokieren für die angegebene Anzahl von Tags.
VOID ApplyTagChanges(struct TagItem *list,.struct TagItem *changelist); Ändert die tag-data-Werte in changelist auf die aus list, nicht in list vorhandene Tags werden ignoriert.
struct TagItem *CloneTagItems(struct TagItem *orglist); Anlegen einer Kopie einer Tagliste; muß mittels FreeTagItems() freigegeben werden.
VOID FreeTagItems(struct TagItem *taglist); Speicher der Tagliste freigeben
struct SkipList * CreateSkipList(struct Hook *hook,.LONG max_levels);
.VOID DeleteSkipList(struct SkipList *list);
Erzeugen einer Skip-Tag-Liste; muß mittels DeleteSkipList() freigegeben werden
VOID FilterTagChanges(struct TagItem *changelist,.struct TagItem *orglist, ULONG apply); Durchsucht changelist und entfernt Einträge, die identisch in orglist vorhanden sind bei unterschiedlichen Werten bestimmt apply ob der Wert aus orglist übernommen werden soll.
ULONG FilterTagItems(struct TagItem *changelist,.Tag *filterarray ,ULONG logic); Entfernt Tags aus changelist, wenn diese in filterarray vorkommen (logic=TAGFILTER_AND) bzw. nicht vorkommen(logic=TAGFILTER_NOT).
.struct TagItem *FindTagItem(Tag tag,struct TagItem.*taglist); Durchsucht die taglist nach dem tag-Eintrag und liefert das gefundene Item zurück.
ULONG GetTagData(Tag tag, ULONG default, structTagItem *taglist); Ermittelt den Datenwert zum angegebenen Tag aus der Liste.
VOID MapTags(struct TagItem *taglist, struct TagItem.*maplist, ULONG type); Übertrag die Werte aus maplist in die gleichnamigen Felder in taglist. type legt fest was mit den Einträgen passieren soll, die nur in taglist vorkommen.
Splay-Tree-Funktionen  
struct SplayTree * CreateSplayTree(struct Hook *hook); Anlegen einer Splay-Tree-Datenstruktur; muß mittels Delete-SplayTree() freigegeben werden
VOID DeleteSplayTree(struct SplayTree *tree);  
struct SplayNode * FindSplayNode(struct SplayTree
.*tree, APTR key);
Erzeugt einen neuen SplayNode und fügt ihn im tree ein
BOOL emoveSplayNode(struct SplayTree *tree,.APTR key); Entfernt den SplayNode aus dem tree, wenn ein zu key passender Eintrag gefunden wird
Skip-List-Funktionen  
struct SkipNode * FindSkipNode(struct SkipList *list,
.APTR key);
Durchsucht list nach dem key und liefert den gefundenen
Node zurück.
struct SkipNode * GetFirstSkipNode(struct SkipList *list);
Ermittelt den ersten Node in list.
SkipList *list, struct SkipNode *previousnode);
Ermittelt den nächsten Node nach previousnode in list
struct SkipNode * InsertSkipNode(struct SkipList *list,
.APTR key, ULONG total_size);
Erzeugt einen neuen SkipNode und hängt in list ein.
BOOL RemoveSkipNode(struct SkipList *list, APTR key); Entfernt den SkipNode von list, wenn ein zu key passender Eintrag gefunden wird

 


Download:enthält:
Download OeffneInterface.c : Interface öffnen
BerechnePruefziffer.c : CRC-Prüffziffer erzeugen
LottoGenerator.c : generieren von Zufallszahlen
SpeicerFunks.c : Speicherbereiche manipulieren
os4prog-8-utility-src.lha,
104.311 bytes


Hauptseite © 2005 All Rights Reserved. Alle Rechte vorbehalten Franzis' Verlag GmbH
Veröffentlichung und Vervielfältigung nur mit schriftlicher Genehmigung des Verlags

Kommentare, Fragen, Korrekturen und Kritik bitte an Webmaster AMIGA schicken.
Zuletzt aktualisiert am 23. Juli 2005, Michael Christoph.