Homepage     Computer-Stoff [english]

Mini-C-libraries

Wer kennt das nicht: Man will mal schnell ein kleines Programm schreiben, und immer wieder tauchen dieselben Programmieraufgaben auf: Listen, Parsen von Konfigurationsdateien oder Kommandozeilenoptionen. Für all das gibt es natürlich Bibliotheken. Doch wer will schon für jedes kleine Projekt ein Dutzend Bibliotheken à 100KByte, deren volle Funktionalität er nicht braucht, einbinden? Wer will vorher noch x Präcompiler aufrufen müssen?

Weil mir das nicht paßte, gibt es hier einige äußerst leichtgewichtige C-libraries, die ich im Laufe der Zeit geschrieben habe. Der Funktionsumfang beschränkt sich dabei (außer im Falle der Listen-Bibliothek) auf das absolut Notwendige. Es handelt sich um Funktionen, die jeder selber schreiben könnte. Sie eignen sich nicht für größere Programmierprojekte, sondern sind eher für kleine und schnelle hacks gedacht.

Alle libraries bestehen aus ein oder zwei c- und h-Dateien und einer html- oder txt-Referenz. Die KByte-Angaben sind auf ganze Zahlen (auf oder ab) gerundet. Alle libraries stehen unter der GNU Lesser GPL oder unter der BSS-Lizenz. Sie laufen auf meinem Linux-System (SuSE6.4), sollten auf anderen Linux-Systemen aber ebenfalls ohne Probleme funktionieren. Bis auf die FTP- und die NNTP-libraries sollten sie sich mit vielleicht kleinen Anpassungen auch auf anderen Systemen übersetzen lassen.

Copyright: Die Bibliotheken stehen teils unter der GNU Lesser Public Licence (früher: Library Public Licence), größtenteils aber unter einer BSD-licence. Im Zweifelsfall muß man das in der mitgelieferten Dokumentation nachlesen. Auf der GNU-Homepage gibt es den genauen Wortlaut der Lesser Public Licence.

Betriebssystem: Geschrieben und getestet habe ich die Bibliotheken auf meinem Linux-System. Bis auf die FTP-, die NNTP- und die HTTP-Library sollten sie aber auch auf anderen Systemen laufen, zumindest wenn man die GNU-C-Library besitzt.


Doppelt verkettete Listen

lists.1.41.tgz (11K) [Die C-Datei ist 18K groß.]

(benötigt lediglich <stdio.h> und <malloc.h>)

Diese Bibliothek stellt doppelt verkettete Listen zur Verfügung. Abgesehen von den obligatorischen Funktionen zum Einfügen und Löschen von Listeneinträgen an beliebigen Stellen, Verketten, Kopieren oder Löschen von Listen usw. wird der sehr bequeme Umgang mit sortierten Listen unterstützt. Zum nachträglichen Sortieren von Listen sind der bubblesort- und mergesort-Algorithmus implementiert.

Zwei Beispiele, wie mit Listen umzugehen ist: Im ersten Beispiel soll der string s in eine sortierte Liste l an der richtigen Stelle eingefügt werden:

   insert_sorted_element (l, s, strcmp);

Im zweiten Beispiel sollen alle Werte, die in der Liste l stehen, bearbeitet werden:

  list_t *p=l;
  while ((p=p->next)) {
      /* mache irgendwas mit p->val */
    }

Status: Die Bibliothek wird von mir bis auf die Sortierroutinen massiv benutzt. Gröbere Fehler sind deshalb eher unwahrscheinlich.


Hashtables

hasht.1.1.tgz (6K) [Die C-Datei ist 4K groß.]

(benötigt die Listen-Bibliothek von oben)

In dieser Bibliothek wird der Umgang mit hashtables implementiert: Einfügen und Löschen von Einträgen, schnelles Finden von Werten. Außerdem die Umwandlung von Listen in hashtables und umgekehrt. Die Hashfunktion muß natürlich dem Problem angemessen sein und vom Anwender selber bereitgestellt werden.

Die html-Referenz enthält außerdem eine (ganz ganz) kurze Einführung in hashtables allgemein.

Status: Scheint zu funktionieren, wurde von mir aber bisher nur einmal ernsthaft eingesetzt. Beta.


Lesen von Konfigurationsdateien

rconfig.1.2.tgz (5K) [Die C-Datei ist 5K groß.]

(benötigt <malloc.h>, <stdio.h>, <string.h> und <stdlib.h>.)

Dies ist eine Bibliothek, die simple, nach dem Muster

   OPTIONS_NAME = OPTIONS_WERT

aufgebaute Konfigurationsdateien einliest und die Werte (nur vom Typ char*) in die richtigen Variablen abspeichert. Eine ev. Umwandlung der char* in Zahlen bleibt dem Anwender überlassen.

Man übergibt der Funktion einfach eine Liste aller möglichen Options-Namen und den Namen der Konfigurationsdatei. Sie liest dann diese und versucht, den einzelnen Optionen Werte zuzuordnen. Die folgende Liste gibt einen Überblick darüber, was die Funktion macht, und was nicht.

Außerdem gibt es noch eine Funktion, die es einem erleichtern soll, den Namen der Konfigurationsdatei mit vollständigem Pfad richtig zusammenzusetzen. (Beispielsweise muß man sich um die Expansion von "~" zum home-Verzeichnis des Anwenders nicht mehr selber kümmern.)

Status: Ich habe diese Bibliothek bereits einigemale benutzt, ohne daß Probleme aufgetreten wären. Wegen des beschränkten Funktionsumfangs sind gröbere Fehler unwahrscheinlich.


Lesen von Kommandozeilen-Optionen

pclo1-0.1.tgz (2,5K) [Die C-Datei ist 6K groß.]

Versucht in den Parametern der Kommandozeile Optionen und ihre Parameter zu erkennen und ist ziemlich einfach zu benutzen.

Status: Einige exotische Sachen habe ich noch nicht häufig benutzt. Ansonsten scheint die Library ganz gut zu funktionineren.


Rekursives Absteigen von Verzeichnissen

libfind-0.3.tgz (2K) [Die C-Datei ist 4,5K groß.]

(benötigt stdio.h, sys/types.h, sys/stat.h, unistd.h, dirent.h, string.h)

Die libfind besteht aus nur einer einzigen kleinen Funktion. Dieser wird ein Verzeichnis und (eventuell) zwei Funktionzeiger übergeben. Sie steigt rekursiv in alle Unterverzeichnisse ab und ruft für jede gefundene Datei die übergebenen Funktionen auf. Mehr nicht.

Status: Wegen dem beschränkten Funktionsumfang sind Fehler unwahrscheinlich.


Parsen von mathematischen Ausdrücken

fpar-0.5.tgz (7K) [Die zwei C-Dateien sind zusammen 12KB groß]

(benötigt stdio.h, malloc.h, string.h und stdlib.h)

fpar ist eine kleiner Funktionsparser, also eine C-Library, die einen mathematischen Ausdruck in einer Zeichenkette parst und einen Baum daraus erstellt, der die logische Struktur des Ausdrucks wiedergibt, und den man auswerten kann.

Trotz der Kleinheit der Library ist sie sehr einfach erweiterbar, sogar, wenn man es darauf anlegt, zur Laufzeit. Im Augenblick beginnt die C-Datei mit folgender Definition:

   term_t op[] = {
     { "#+#", left , base_add },  /* Addition */
     { "#-#", left , base_sub },  /* Subtraktion */
     { "#*#", left , base_mult},  /* Multiplikation */
     { "#/#", left , base_div },  /* Division */
     { "sqrt#",left, base_sqrt},  /* Quadratwurzel */
     { "sin#",left , base_sin },  /* sinus */
     { "cos#",left , base_cos },  /* cosinus */
     { "tan#",left , base_tan },  /* tangens */
     { "exp#",left , base_exp },  /* Exponentialfunktion */
     { "ln#", left , base_ln  },  /* natuerlicher Logarithmus */
     { "-#",  left , base_neg },  /* das Negative */
     { "#^#", left , base_pow },  /* hoch */
     { "(#)", right, base_id  },  /* Identitaet, aber hohe Prioritaet */
     { "x",   left , base_x   },  /* frei verfuegbare Variable */
     { NULL,  right, NULL }
   };

Weitere Operationen, auch mit mehr als zwei Parametern und mit anderer Syntax können hier einfach entsprechend ihrer Priorität eingefügt werden. Außerdem muß man in diesem Fall, wenn man die Ausdrücke evaluieren will, eine Funktion angeben, die die neue Operation durchführt. (Dies sind hier die base_...-Funktionen.) Für die oben angegebenen Operationen werden im eigentlichen Code keinerlei Spezialfälle abgefragt. Leider hat diese Allgemeinheit und leichte Erweiterbarkeit des Codes nicht gerade zu dessen besserer Lesbarkeit beigetragen, sondern zu einer relativen Abstraktheit geführt.

Im Moment bearbeitet die Library reelle Zahlen (genauer: double-Zahlen. Es dürfte aber nicht schwierig sein, sie auf andere Typen,auch selbstdefinierte, umzustellen.

Kommentare und eine txt-Doku ebenso wie ein kleines Beispielprogramm liegen bei.

Status: Ich habe diese Bibliothek noch nicht ernsthaft benutzt, auch wenn sie beim Testen recht gut zu funktionieren schien: Beta.


Parsen von HTTP-Server-Log-Dateien

ploglib-0.3.tgz (16K) [Die C-Datei ist 15K groß.]

(benötigt eine ganze Reihe von Standard-Bibliotheken, außerdem regex.h und zum Umrechnen von IP-Adressen sys/socket.h, netinet/in.h und arpa/inet.h.)

Mit Hilfe der ploglib kann man aus Log-Dateien von HTTP-Servern relevante Informationen herausziehen. Kernstück der Library ist die Funktion

   access_t *parse_log_line (char *line, logformat_t *lf);

Im zurückgegebenen (neu allokierten) struct stehen dann alle möglichen Informationen, die in der Log-Zeile line enthalten waren, wie beispielsweise Zugriffszeit, IP der zugreifenden Clients, Antwortcode des Servers usw..

Es gibt allerdings auch einen Haken bei der Sache: Man muß der Library mitteilen, welches Format die Logzeilen haben. Dies geschieht mit Hilfe eines regulären Ausdrucks, welcher zusätzliche Zeichen enthalten darf. Für genauere Informationen kann man die im Paket enthaltene Dokumentation lesen. Man muß sich mit regulären Ausdrücken allerdings nicht besonders gut auskennen, um das zu kapieren.

Auch bei dieser Library handelt es sich um einen kleinen, aber bequemen hack. Sie ist weder besonders schnell, noch besonders mächtig, noch besonders benutzerfreundlich, erfüllt aber ihren Zweck. Sie parst auf meinem Pentium 1 mit 166MHz rund 250-300 Zeilen pro Sekunde.

Die Dokumentation enthält einen recht ausführlichen Teil auch darüber, wie man die Library selbst erweitern kann. Seit der Version 0.3 ist auch eine englische Dokumentation enthalten.

Status: Ich habe diese Bibliothek in einigen wenigen Programmen benutzt. In diesen scheint sie aber recht zuverlässig zu funktionieren.


FTP

ftpmlib.1.3.tgz (14K) [Die C-Datei ist 29K groß.]

(benötigt eine ganze Reihe von Standard-Bibliotheken, darunter natürlich auch die, die für Netzwerkbetrieb nötig sind: stdio.h, malloc.h, stdlib.h, string.h, errno.h, netdb.h, sys/types.h, netinet/in.h, arpa/inet.h, sys/socket.h, unistd.h, ctype.h)

Die ftp-mini-lib (ftpmlib) implementiert Teile des FTP-Protokolls, wie es im RFC959 festgelegt ist. Ich habe sie nicht geschrieben, um kompliziertere Dinge wie die Übertragung von Dateien zwischen verschiedenen FTP-Servern oder die Wiederaufnahme abgebrochener Übertragungen zustandezubringen, sondern um Dateien einfach hoch- bzw. runterladen zu können, Verzeichnisse anlegen oder Dateien löschen zu können. Auch FTP über einen Proxy wird z.Z. nicht unterstützt.

Hier ein Beispiel, wie einfach sie zu benutzen ist: Im folgenden wird eine Verbindung zu einem FTP-Server aufgebaut, ein neues Verzeichnis newdir angelegt, in dieses gewechselt und eine Datei localfile hochgeladen und auf der remote-Seite als remotefile abgespeichert. (Alles leichtsinnigerweise ohne Fehlerabfragen, deshalb die vielen NULLen.)

   ftp_server *fs = ftpserver_connect ("ftp.somedomain.de", 0, NULL, NULL);
   ftp_logon (fs, "username", "password", NULL, NULL, NULL);
   ftp_set_transfer_type (fs, TTYPE_1_IMAGE, NULL, NULL); /* auf binary-mode setzen */
   mk_working_dir (fs, 1, "newdir", NULL, NULL);
   ftp_change_dir (fs, 0, "newdir", NULL, NULL);
   ftp_put_file (fs, "localname", "remotename", NULL, NULL);
   ftpserver_close (fs, NULL, NULL);

Die beiden Zeilen ftp_change_dir und ftp_put_file sollte man in diesem Fall u.U. abwandeln zu

   ftp_put_file (fs, "localname", "newdir/remotename", NULL, NULL);

Status: Ich habe mir nicht die Mühe gemacht, einen FTP-Server zu manipulieren, um Fehler zu provozieren. Auch hatte ich nicht die Möglichkeit, die Zusammenarbeit mit vielen verschiedenen Servern zu testen. Die Bibliothek arbeitet mit meinem eigenen und dem meines Providers zusammen. Insbesondere die Fehlerbehandlung könnte noch einige kleine Fehler aufweisen.

Die Library ist thread-safe. Es können Timeouts gesetzt werden.

(Von der Version 1.0 auf 1.1 hat sich die API leicht geändert.)

Es gibt ein ähnliches Projekt von ungefähr derselben Größe und derselben Funktionalität: Die ftplib von Thomas Pfau.


NNTP

nntpmlib-0.2.1.tgz (24K) [Die C-Datei ist 23K groß.]

(benötigt eine ganze Reihe von Standard-Bibliotheken, darunter natürlich auch die, die für Netzwerkbetrieb nötig sind: stdio.h, malloc.h, stdlib.h, string.h, errno.h, netdb.h, sys/types.h, netinet/in.h, sys/socket.h, unistd.h.)

Die nntpmlib implementiert einen kleinen Teil des NNTP-Protokolls (RFC0977) und der common NNTP-extensions (RFC2980), und zwar von der Client-Seite aus gesehen. Aus dem letzten RFC wird bislang nur ein einziger Befehl (XOVER) unterstützt. Trotzdem reicht die Funktionalität dieser Bibliothek, um einen einfachen News-Reader zu schreiben, zumal die meisten Befehle der common NNTP-extensions sowieso nicht von allen Servern unterstützt werden.

Das folgende Beispiel stellt eine Verbindung zu einem news-server her und gibt eine Liste aller Gruppen auf die Standard-Ausgabe aus. Auf eine Fehlerbehandlung wurde in diesem Beispiel verzichtet - daher die vielen NULLen.

   nntp_server *ns;
   char *line;

   ns = nntp_connect ("news.irgendwo.de", 119, NULL, NULL, NULL);
   nntp_list_groups (ns, NULL, NULL);
   while ((line = get_line_from_server(ns, NULL))) {
      printf ("%s\n", line);
      free (line);
      }
   nntp_close (ns, NULL, NULL);

Für die Implementation weiterer Kommandos stellt die Bibliothek einige recht praktische Funktionen bereit. Da sie (meiner Meinung nach) recht übersichtlich programmiert ist, sollte sie sich leicht erweitern lassen.

Status: Ich habe diese Bibliothek mit drei verschiedenen News-Servern verwendet, allerdings nicht alle Befehle mit allen Servern getestet. Größere Probleme sind nicht aufgetreten.


HTTP

httpmlib-0.4.tgz (8K) [Die C-Datei ist 17K groß.]

(benötigt eine Reihe von Standard-Bibliotheken, darunter natürlich auch die, die für Netzwerkbetrieb nötig sind.)

Die httpmlib ist ein ziemlich rudimentäres API für HTTP-Abfragen. Es hilft einem dabei, HTTP-requests zusammenzubasteln und abzuschicken, und die Antwort des Servers zu lesen, wobei die Verantwortung dafür, was mit der Antwort des Servers gemacht wird, im wesentlichen beim Benutzer gelassen wird.

Als high-level-API sind lediglich HEAD und GET-Abfragen vorgesehen. Nach einem GET kann der Benutzer die angeforderte Datei aus einem FILE*-stream lesen. Sonstige Features:

Nachteile sind:


Homepage     Computer-Stoff by Michael Becker, 12/2000. Letzte Änderung: 10/2004.