// record.hpp : Datensatz im Arbeitsspeicher // 1995-08-19 Datensatz, Struktur und Manipulation im Arbeitsspeicher // (Lesen und Speichern siehe ABASEW.CPP) // Klasse RECORD (c) UB Braunschweig 1995/2003 // Setzt die Klasse KONFIG voraus // Ein Objekt RECORD wird gebraucht, um einen Datensatz darzustellen // und zu manipulieren // Einlesen aus und Speichern in einer Datenbank leistet Klasse ABASE // Ein RECORD kann an ein Objekt EXET uebergeben werden zwecks Export // RECORD wird benoetigt von den Klassen: // EXET, ABASE // Methoden: Kurzübersicht (Unten genauere Beschreibung, Funktionen selbst in record.cpp) // RECORD(KONFIG *cfg, unsigned int gsp=0, int gd=0, int wsp=0) // Konstruktor // ~RECORD() Destruktor, enthaelt Release() zur Freigabe // CHAR *Adr(CHAR *kat,int) Adresse von Feld kat (z.B. Adr("#20") // int Pos(CHAR *kat,int) interne Nummer von a // int Ins(CHAR *kat) Feld einfuegen (oder ersetzen) // int Del(CHAR *kat) loeschen // int PartDel(int i, int j) mehrere Felder loeschen // CHAR *SrRp(CHAR *a,CHAR *b,int mde,int d,int r) // Zeichenkette im Satz suchen und ersetzen // CHAR *FSrRp(CHAR *a) Feldspezifisches Suchen und ersetzen // int Reserve() Satz zum Bearbeiten reservieren (sperren) // int Release() Satz wieder freigeben (wenn nicht gespeichert wurde) // void Copy(RECORD *Rec) Inhalt aus anderem Satz kopieren // SubPos(CHAR *kat) hierarchischen Untersatz suchen // SubDel(CHAR *kat) hierarchischen Untersatz loeschen ab kat // SubDel(int pos) hierarchischen Untersatz loeschen ab pos // SubCopy US kopieren // SubMove US bewegen // SubNxt(int) Position des naechsten Untersatzes finden, nicht-zyklisch // SubPre(int) Position des vorigen US finden, zyklisch // private: // int ginst(int f) String Wspace als Feld mit interner Nummer f einfuegen // die interne Nr. ist die Ordnungsnummer der Kat. in der CFG #ifndef __ALLEGRO #include "allegro.hpp" // globale Konstanten und Variablen #endif #ifndef __RECORD #define __RECORD #define WSPACE 48000 // max. Feldlaenge (vorher 32000) // Ein Objekt der Klasse KONFIG wird gebraucht: #include "konfig.hpp" // eigentliche Klassenbeschreibung class RECORD { //===========// public: // Variablen // %% Namen der aelteren DOS-Variablen //===========// CHAR *g ; // Basisadresse der Datenfelder CHAR **ga ; // Adressenarray f.d. Datenfelder int *gi ; // Array der internen Nummern der Felder gemaess Konfiguration int cri ; // Position der 1. Kat. d. aktuellen Satzes in ga[] // normal: 0, nur bei Untersaetzen waehrend Export >0 int gri ; // Anzahl Felder des Satzes CHAR *gend ; // Endadresse der Daten (hinter letztem Byte) int mri ; // markierte Kategorie; Adresse: rec->ga[mri] // Fuer Editor-Zwecke. Bleibt auf der gewaehlten // Kategorie auch bei Verschiebungen per Ins/Del int Adn ; // logische Nr. der Datenbank (0,1,2,3) %% Adb // -1 wenn rec nicht zu einer Datenbank gehoert // globale Variable ABASE Abase[Adn] enthaelt Adresse! int rFi ; // Nr. der .ALD-Datei d. Satzes %% filenmb long rOf ; // Position innerhalb .ALD-Datei %% rad long rNr ; // Satznummer, 0L = neu %% recn int rLg ; // Satzlaenge in der Datei %% rlg int rSt ; // Status %% rstat // (0=neu,1=normal,2=reserviert,8=gesperrt,9=geloescht) KONFIG *kfg ; // pointer auf das zustaendige KONFIG-Objekt char schema; // Konfig.Buchstabe // Nur wenn indexiert wird: int rKx ; // Anzahl Schluessel %% okn CHAR *rKy[1000]; // Liste der Schluessel %% oldkeys[] CHAR *rKbase; // Basisadresse fuer Schluessel // Platzzuteilung in index.cpp char rKf[1000]; // flag: key valid / not valid %% okf long rNa ; // additional, for #nra (nachgeladener Satz) $$981109 //============// public: // Methoden // //============// // Konstruktor: RECORD(KONFIG *cfg, unsigned int gsp=0, int gd=0, int wsp=0); // cfg = ein Objekt KONFIG, muss vorher angelegt werden // Defaults fuer folgende Werte werden aus CFG uebernommen, // wenn nicht angegeben oder 0 angegeben: // gsp = max. Groesse des Speichers fuer Felder, // gd = max. Zahl der Felder eines Satzes // wsp = max. Groesse eines Feldes (default WSPACE) // Fehler: Aerror enthaelt eine Meldung, sonst *Aerror == 0 (Konstruktor kann kein "return xyz" machen) // Beispiel: KONFIG *kfg = new KONFIG("A","C:\\ALLEGRO\\DEMO"); // RECORD *satz = new RECORD(kfg); // Standard! // RECORD *rec = new RECORD(kfg,10000,0,2000); // RECORD *dummy = new RECORD(kfg,100,10,300); // Destruktor ~RECORD(); // ***************** // Sonstige Methoden // ------------------------------------------------------------ // Positionsnr. eines Feldes innerhalb des Array ga[] im RECORD bestimmen: int Pos(FLD *, int md=0); // %% kat_pos(CHAR *); // return: interne Position der Kategorie im ga[]-Array // -1 wenn nicht vorhanden // Beispiel: i=rec->Pos("#123"); // Ergebnis: rec->ga[i] ist die Adresse des Feldes // und zwar des Zeichens '#' // md == 1 : ganzen hierarchischen Satz durchsuchen, incl. Untersaetze // 0 : nur aktuellen Satz ab Position cri, Untersaetze nicht // ------------------------------------------------------------ // absolute String-Adresse des Feldtextes bestimmen: CHAR *Adr(FLD *,int md=0); // %% kat_adr(CHAR *); // return: Adresse des Feldtextes (erstes Textzeichen des Inhalts!) // NULL wenn Feld nicht vorhanden // Beispiel: adr=rec->Adr("#123"); // Ergebnis: adr ist die Adresse des Feldtextes (!) // also des Zeichens hinter #123 // adr-kfg->skt ist die Adresse von '#' // md wie bei Pos() // ------------------------------------------------------------ // Ein Feld in den Datensatz einsortieren int Ins(FLD *); // %% kat_ins(CHAR *); // return: Position, an der das Feld eingeordnet wurde // -1 wenn Feld fehlerhaft, Fehlermeldung in Aerror // z.B. unerlaubte Wiederholung, Feld nicht aenderbar // d.h. der Felddeskriptor in der CFG wird verwendet // Beispiel: rec->Ins("#123 Text"); // ------------------------------------------------------------ // Ein Feld aus dem Satz loeschen int Del(FLD *); // %% rdelete(i,i+1); // return: Position, wo sich das Feld befand // komplettes Feld steht dann in Aerror, falls man es braucht // -1 wenn nicht gefunden (Aerror leer) // Beispiel: rec->Del("#123"); // ------------------------------------------------------------ // PartDelete : Mehrere Felder aus dem Satz loeschen int PartDel(int i ,int j); // %% rdelete(i,j); // loesche die Felder i bis j-1 // Bedingungen: i,j > 0, j>i, i,j<=rec->gri // Special case : j==-1 : from i to end of rec (= gri) // return: 0 if not possible, 1:done // Example : i=rec->Pos("#81"); // j=rec->Pos("#90"); // PartDel(i,j); // ------------------------------------------------------------ // Search+Replace innerhalb eines Satzes: CHAR *SrRp(CHAR *,CHAR *,int ,int ,int ); /* srch (+repl) */ CHAR *FSrRp(CHAR *,int); // md=1: repl 0:not // field specific srch&repl in current rec // NEU: int SubPos(CHAR *); // Position eines Untersatzes bestimmen // und diesen zum aktuellen Satz machen int SubDel(CHAR *); // Untersatz loeschen ab angegebener Kategorie int SubDel(int ); // Untersatz loeschen ab einer Position int SubCopy(int, RECORD *, int, int md=0); // Untersatz kopieren int SubMove(int, RECORD *, int); // Untersatz verschieben int SubNxt(int); // naechsten Untersatz finden, ab Position int // return -1 wenn keiner mehr kommt, nicht-zyklisch int SubPre(int); // vorigen Untersatz finden, ab Position int // return -1 wenn es keinen Untersatz gibt, // zyklisch: wenn (0), dann Pos. des letzten // ======================================================================== int Reserve(); // Satz zum Bearbeiten reservieren // blockieren, aktuelle Schluessel bestimmen int Release(); // wieder freigeben void Copy(RECORD *); // Inhalt aus anderem Satz kopieren void Empty(); // reset rec as if new // ======================================================================== private: CHAR *Wspace; // internal workspace // Hilfsfunktion zum Einordnen eines Datenfelds in den Satz int ginst(int); // %% ginst(int); // das ist die alte Funktion aus acore.c, fuer die String-Array-Operation // ======================================================================== }; // end RECORD class #endif