Diese Bibliothek stellt C-Routinen zur Manipulation von EAS2/3 Dateien zur Verfügung. Zur Zeit funktioniert die Bibliothek auf SGI (auch 64bit), HP-VClass, Linux und NEC SX4, jedoch noch nicht auf der Cray. Dateien größer 2GB werden unterstützt, sofern das Betriebssystem dies erlaubt.
Das grundsätzliche Vorgehen entspricht dem im Fortran-Modul: Eine Datei wird durch ihren Namen und eine zugeordnete Dateinummer gekennzeichnet. Der Dateiname wird nur einmal beim ersten Schreiben/Lesen des Kennsatzes benötigt, danach wird die Datei über die Dateinummer angesprochen. Es werden maximal EAS3_MAXFILES+1 Dateien gleichzeitig unterstützt, sofern das Betriebssystem dies zuläßt.
Diese Dokumentation ist nicht so ausführlich wie die entsprechende Fortran Doku, deswegen ist ein Studium des entsprechenden Quelltextes unumgänglich (insbesondere die Headerdatei eas3llc.h sollte man sich anschauen). Es wird nur das User Interface dokumentiert, nicht jedoch interne Routinen oder das erweiterte User Interface.
Die Bibliotheksroutinen arbeiten im wesentlichen mit zwei Datenstrukturen, dies sind "Kennsätze" (eas3Hdr) und "Parameter" (eas3Par).
Der Kennsatz entspricht weitgehend dem aus dem Fortran-Modul (eas3ks_t);
geändert werden musste der Name für das benutzerdefinierte
Integerfeld (Fortran90: ks%if), weil sich der Compiler nicht mit dem
Namen if anfreunden wollte. Daher heißen die
benutzerdefinierten Felder ucf, uif und urf.
Zusätzlich zu den gleichen Daten wie eas3ks_t besitzt
der C-Kennsatz eas3Hdr jedoch noch zwei Felder, die die
Namen und Grössen der fünf Dateidimensionen (Zeitindex,
Parameter, Dimensionen 1..3) enthalten. Dies ist sehr nützlich bei
Schleifen über mehrere dieser Dimensionen.
Der eas3Par-Datentyp dient dazu, alle Operationen auf die Daten selbst von deren Typ (single/double/quadruple precision) unabhängig zu machen.
Die wichstigsten Datenstrukturen sind im Folgenden aus der Headerdatei eas3llc.h entnommen:
/*-------------------- eas3Hdr -----------------------------*/
typedef struct
{
char eas3id[EAS3KENNLEN+1];
eas3Dform dform;
eas3Bform bform;
Int64 nzs;
Int64 npar;
Int64 ndim1, ndim2, ndim3;
Int64 *zsf;
eas3AttrMode amode;
char **zsattr;
char **parattr;
char dim1attr[ATTRLEN+1];
char dim2attr[ATTRLEN+1];
char dim3attr[ATTRLEN+1];
eas3GeomMode gmode[5];
Int64 ng[5];
Float64 **gf;
eas3UdefMode umode;
Int64 nu[3];
char **ucf;
Int64 *uif;
Float64 *urf;
/* Zusaetzliche Informationen, werden nicht in der Datei gespeichert */
char **dimname;
Int64 dimsize[5];
Int64 len;
} eas3Hdr;
/*-------------------- eas3Par -----------------------------*/
typedef struct
{
/* Typ und Groesse */
eas3Bform type;
Int32 dim1, dim2, dim3;
Int32 bytes, count, itemsize;
/* Arrays */
Float32 *f;
Float64 *d;
Float128 *q;
/* void-pointer auf Datenblock fuer fread/fwrite */
void *vp;
} eas3Par;
/* --------------- Konstanten fuer EAS3 --------------------*/
/* eas3Dform */
typedef enum {EAS2=1, EAS3} eas3Dform;
/* eas3Bform */
typedef enum {IEEES=1, IEEED, IEEEQ} eas3Bform;
/* eas3AttrMode */
typedef enum {EAS3_NO_ATTR=1, EAS3_ALL_ATTR} eas3AttrMode;
/* eas3GeomMode */
typedef enum {EAS3_NO_G=1, EAS3_X0DX_G, EAS3_UDEF_G, EAS3_ALL_G} eas3GeomMode;
/* eas3UdefMode */
typedef enum {EAS3_NO_UDEF=1, EAS3_ALL_UDEF, EAS3_INT_UDEF} eas3UdefMode;
/* eas3OpenMode */
typedef enum {EAS3_CLOSED=0, EAS3_RO, EAS3_WO, EAS3_RW, EAS3_WRA} eas3OpenMode;
/* eas3ReordMode */
typedef enum {EAS3_NOREORD=0, EAS3_CORD_XY, EAS3_CORD_YX} eas3ReordMode;
Weil die C-Zahlenformate je nach Rechner verschieden viel Platz
belegen, werden in eas3llc.h neue Typen definiert, die
unabhängig von der Rechnerarchitektur feste Längen haben.
Soll die Bibliothek auf eine weitere Maschine portiert werden,
müssen hier entsprechende zusätzliche Einträge
vorgenommen werden. Der ganze restliche Code ist damit frei von
Hardware-Abängigkeiten (hoffe ich).
Beispiel:
#define Int32 int
#define Int64 long long int
#define Float32 float
#define Float64 double
#define Float128 long double
#define QUAD_SUPPORT 1
Die Konstante QUAD_SUPPORT gibt an, ob der grösste Typ wirklich 128bit lang ist oder (wie z.B. auf Cray) nicht. Diese Konstante entscheided, ob 128bit Zahlen überhaupt gelesen werden können oder nicht. Betriebssystemabhängig sind leider auch die Aufrufe von ftell/fseek für große Dateien sowie der Typ für Dateioffsets. Bei Bedarf werden diese Namen also an gleicher Stelle umdefiniert.
Fast alle Routinen manipulieren Pointer, damit nicht (potenziell große) Parameterfelder in den Stack und wieder heraus kopiert werden müssen. Bei Zuweisungen wie
eas3Par *prm1;
eas3Par *prm2;
....
prm1 = prm2; /* Pointerkopie */
ist daher Vorsicht geboten; es handelt sich um das Kopieren von Pointern, wobei vermutlich eher
eas3_copyPar(prm1, prm2); /* Inhalt kopieren */
erreicht werden sollte.
Da alle internen Strings dynamisch verwaltet werden, müssen
sie mit den str...() Funktionen aus <string.h>
bearbeitet werden (strcat, strcpy,...). Eine Zuweisung wie dfile->hdr.parattr[3]
= "w_xx" ändert dummerweise nicht nur den Inhalt
des allokierten Strings, sondern biegt auch dessen Pointer um, sodass
der dann ziemlich sicher nicht mehr auf einen Speicherbereich der
richtigen Länge (hier: ATTRLEN+1) zeigt. Empfehlenswerte
Alternative für Zuweisungen wäre sprintf(dfile->hdr.parattr[3],
"w_xx");
Vor dem Build bitte die der Architektur entsprechende Zeile im Kopf des
Makefile auskommentieren. Wenn als default-Fliesskommazahlformat nicht
"double" verwendet werden soll, kann die entsprechende #define
DefaultFloat double Direktive auch nocht geändert werden.
In eigenen Programmen muss dann mit #include <eas3llc.h> der
Header eigebunden werden und beim Linken die Bibliothek mit angegeben
werden: cc -O2 prog.c -o prog -leas3llc . Den eas3llc.h -
Header bitte nach etwaigen Systemheadern (stdio.h & Co.)
einbinden, da er bei manchen Systemen deren #defines überschreiben
muss.
Funktionen mit Rückgabetyp 'Int32' geben EAS3_SUCCESS bzw. EAS3_FAILURE zurück, sofern nicht anders angegeben.
Es werden maximal EAS3_MAXFILES+1 Dateien verwaltet. Die zulässigen Dateinummern liegen im Bereich 0..EAS3_MAXFILES.
Beispiele zur Verwendung der Routinen sind in den Demoprogrammen create.c und avg.c zu finden, die mit der Bibliothek eas3llc zusammen compiliert werden.
Int32 eas3_writeHdr(const Int32 filenr, const char *fn, eas3Hdr *hdr, eas3OpenMode mode)
Öffnet die Datei und schreibt den Kennsatz hdr auf die Datei mit dem Namen fn und der Nummer filenr. Die Datei wird im Modus mode geöffnet.
Verfügbare Modi sind:
| EAS3_WO | write-only |
| EAS3_RW | read-write |
| EAS3_WRA | read-write / random-access |
Der letzte Modus beschreibt die Datei beim Öffnen vollständig mit Nullen, was bei sehr großen Dateien entsprechend lange dauert. Dadurch wird erreicht, dass jede Dateiposition direkt ansprechbar ist (random access). Wird eine neue Datei nicht mit EAS3_WRA geöffnet, ist nur sequentielles Schreiben möglich, da nicht ohne weiteres hinter das aktuelle EOF geschrieben werden kann.
eas3Hdr *eas3_readHdr(const Int32 filenr, const char *fn, eas3OpenMode mode)
Öffnet die Datei und liest den Kennsatz hdr von der Datei mit dem Namen fn und der Nummer filenr. Die Datei wird im Modus mode geöffnet.
Verfügbare Modi sind:
| EAS3_RO | write-only |
| EAS3_RW | read-write |
void eas3_newHdr(eas3Hdr *hdr)
Diese Routine allokiert den Speicher für die Felder innerhalb des Kennsatzes. Die Elemente, welche die Felddimensionen beschreiben, müssen bereits mit sinnvollen Werten belegt sein. Alle Feldeinträge werden mit den entsprechenden Defaultwerten (wie im Fortran-Modul beim Aufruf von eas3getks) belegt.
Beispiel:
eas3Hdr *ks;
/* Dimensionierung festlegen */
ks->dform = EAS3;
ks->bform = IEEED;
ks->nzs = 12;
ks->npar = 60;
ks->ndim1 = 100;
ks->ndim2 = 10;
ks->ndim3 = 10;
ks->amode = EAS3_ALL_ATTR;
ks->umode = EAS3_ALL_UDEF;
ks->nu[0] = 3;
ks->nu[1] = 5;
ks->nu[2] = 9;
for (i=0; i<5; i++)
{
ks->gmode[i] = EAS3_UDEF_G;
ks->ng[i] = 4;
}
/* Speicher fuer Feldeintraege allokieren und Defaultwerte setzen */
eas3_newHdr(ks);
/* Ab hier koennen die dynamischen Felder belegt werden, z.B.: */
for (i=0; i<fs->hdr.npar; i++)
sprintf(fs->hdr.parattr[i], "par %d", i+1);
void eas3_freeHdr(eas3Hdr **hdr)
Gibt den mit eas3_newHdr reservierten Speicher für die Feldelemente des Kennsatzes wieder frei und setzt anschließend den Pointer auf NULL.
eas3Hdr *eas3_getHdr(const Int32 filenr)
Liefert den Header zur Datei mit der Nummer filenr. Die Datei muß vorher durch eas3_readHdr oder eas3_writeHdr geöffnet worden sein.
eas3Hdr *eas3_copyHdr(eas3Hdr *src)
Liefert eine Kopie des Kennsatzes src auf den neuen Kennsatz zurück. Der neue Kennsatz wird vollständig allokiert und der Inhalt des Quellkennsatzes kopiert.
void eas3_printHdr(eas3Hdr *hdr, FILE* fp)
Druckt den übergebenen Kennsatz hdr auf die Datei fp (auch stdout möglich).
void eas3_writePar(const Int32 filenr, eas3Par *prm, Int32 zs, Int32 par)
Schreibt den Parameter prm auf die Datei mit der Nummer filenr, an die Position Zeitindex zs, Parameter par. Sollte der Parameter ein anderes Binärformat aufweisen als die Datei, wird automatisch konvertiert.
void eas3_writeParSeq(const Int32 filenr, eas3Par *prm)
Schreibt den Parameter prm auf die Datei mit der Nummer filenr. Der Parameter wird entsprechend sequentieller Reihenfolge geschrieben. Sollte der Parameter ein anderes Binärformat aufweisen als die Datei, wird automatisch konvertiert.
eas3Par *eas3_readPar(const Int32 filenr, const Int32 zs, const Int32 par)
Liest einen Parameter von der angegebenen Position (zs, par) der Datei mit der Dateinummer filenr. Der gelesene Parameter wird als interner Parameter in die interne Dateiliste geschrieben. Zur Bequemlichkeit wird auch der Pointer auf den Parameter mit zurückgegeben.
eas3Par *eas3_readParSeq(const Int32 filenr)
Liest den nächsten Parameter von der Datei mit der Nummer filenr. Der gelesene Parameter wird als interner Parameter in die interne Dateiliste geschrieben. Zur Bequemlichkeit wird auch der Pointer auf den Parameter mit zurückgegeben.
eas3Par *eas3_newPar(const eas3Bform type, Int32 i, Int32 j, Int32 k)
Allokiert einen neuen Parameter im Binärformat type mit den Dimensionen i, j, k (dim1, dim2, dim3).
void eas3_freePar(eas3Par **p)
Deallokiert den Speicher des Parameters und setzt den Zeiger auf NULL.
eas3Par *eas3_getPar(const Int32 filenr)
Liefert den aktuellen internen Parameter zur Datei mit der Nummer filenr zurück.
void eas3_copyPar(eas3Par *src, eas3Par *dst, const eas3reordMode reord)
Kopiert den Inhalt von src nach dst.
Beide Parameter müssen dazu allokiert sein. Es können auch
(evtl. Verlust an Genauigkeit und Wertebereich) Parameter verschiedenen
Binärformats aufeinander kopiert werden. Mit dem Modusschalter reord
kann die Anordnung der Daten auf dem Ausgabeparameter geändert
werden.
Verwendbare Anordnungsmodi:
| Modus | Bedeutung |
| EAS3_NOREORD | Daten in Fortran-Anordung auf dem Feld (erster Index ändert sich am schnellsten) |
| EAS3_CORD_XY | Daten in C-Anordnung auf dem Feld (letzter Index ändert sich am schnellsten) |
| EAS3_CORD_YX | Spezialmodus für Benutzung in x3dp (bzgl. der Fortran-Anordnung 1. und 2. Dimension vertauscht; 3. Dimension nach vorne geholt) |
void eas3_printPar(eas3Par *prm, const char *fn)
Druckt den übergebenen Parameter prm auf die Datei fp (auch stdout möglich).
void eas3_closeFile(const Int32 filenr)
Schließt die Datei mit der Nummer filenr.
void eas3_removeFile(const Int32 filenr)
Schließt gegebenenfalls die Datei mit der Nummer filenr und entfernt die Datei vom Dateissytem.
char *eas3_getFileName(const Int32 filenr)
Liefert den Dateinamen zur Datei mit der Nummer filenr.
Int64 eas3_getFileLen(const Int32 filenr)
Liefert die Dateilänge in Byte zur Datei mit der Nummer filenr.
Hier steht eine aktuelle Version zum Download bereit.
| Version | Datum | Kommentar |
| 1.0.0 | 17.01.2000 | erste freigegebene Version |
| 1.1.0 | 29.02.2000 | Userinterfaces des Moduls komplett überarbeitet und auf Form analog zum Fortran-Interface mit Dateinummern umgestellt. |
| 1.2.0 | 15.05.2000 | Möglichkeit zum Umsortieren der Daten auf den Parametern in C-Anordnung implementiert. |
| 1.3.0 | 07.06.2000 | Umstellung auf EAS3_I8R8-Kennsatz (8-Byte-Typen im Kennsatz). |
| 1.3.1 | 02.07.2000 | Fehler bei Speicherallokierung für Geometriefelder behoben. |