/************* TabSys C++ Program Source Code File (.CPP) **************/ /* PROGRAM NAME: TABSYS */ /* ------------- */ /* Version 2.4 */ /* */ /* Author Olivier BERTRAND 2004-2017 */ /* */ /* This program are the INI/CFG tables classes. */ /***********************************************************************/
/***********************************************************************/ /* Include relevant sections of the System header files. */ /***********************************************************************/ #include"my_global.h" #ifdefined(_WIN32) #ifdefined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif// __BORLANDC__ //#include <windows.h> #else// !_WIN32 #ifdefined(UNIX) #include <errno.h> #include <unistd.h> #else// !UNIX #include <io.h> #endif// !UNIX #include <fcntl.h> #endif// !_WIN32
/***********************************************************************/ /* Include application header files: */ /* global.h is header containing all global declarations. */ /* plgdbsem.h is header containing the DB application declarations. */ /* tabdos.h is header containing the TABDOS class declarations. */ /***********************************************************************/ #include"global.h" #include"plgdbsem.h" #include"reldef.h" #if !defined(_WIN32) #include"osutil.h" #endif// !_WIN32 #include"filamtxt.h" #include"tabdos.h" #include"tabsys.h" #include"tabmul.h" #include"inihandl.h"
Ln = GetSizeCatInfo("Secsize", "8K");
Desc = Fn; returnfalse;
} // end of DefineAM
/***********************************************************************/ /* GetTable: makes a new TDB of the proper type. */ /***********************************************************************/
PTDB INIDEF::GetTable(PGLOBAL g, MODE)
{
PTDBASE tdbp;
/***********************************************************************/ /* Implementation of the TDBINI class. */ /***********************************************************************/
TDBINI::TDBINI(PINIDEF tdp) : TDBASE(tdp)
{
Ifile = tdp->Fn;
Seclist = NULL;
Section = NULL;
Seclen = tdp->Ln;
N = 0;
} // end of TDBINI constructor
TDBINI::TDBINI(PTDBINI tdbp) : TDBASE(tdbp)
{
Ifile = tdbp->Ifile;
Seclist = tdbp->Seclist;
Section = tdbp->Section;
Seclen = tdbp->Seclen;
N = tdbp->N;
} // end of TDBINI copy constructor
// Is this really useful ???
PTDB TDBINI::Clone(PTABS t)
{
PTDB tp;
PINICOL cp1, cp2;
PGLOBAL g = t->G;
tp = new(g) TDBINI(this);
for (cp1 = (PINICOL)Columns; cp1; cp1 = (PINICOL)cp1->GetNext()) {
cp2 = new(g) INICOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of Clone
/***********************************************************************/ /* Get the section list from the INI file. */ /***********************************************************************/ char *TDBINI::GetSeclist(PGLOBAL g)
{ if (trace(1))
htrc("GetSeclist: Seclist=%p\n", Seclist);
if (!Seclist) { // Result will be retrieved from the INI file
Seclist = (char*)PlugSubAlloc(g, NULL, Seclen);
GetPrivateProfileSectionNames(Seclist, Seclen, Ifile);
} // endif Seclist
return Seclist;
} // end of GetSeclist
/***********************************************************************/ /* Allocate INI column description block. */ /***********************************************************************/
PCOL TDBINI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{ returnnew(g) INICOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/ /* INI Cardinality: returns the number of sections in the INI file. */ /***********************************************************************/ int TDBINI::Cardinality(PGLOBAL g)
{ if (!g) return1;
if (Cardinal < 0) { // Count the number of sections from the section list char *p = GetSeclist(g);
Cardinal = 0;
if (p) for (; *p; p += (strlen(p) + 1))
Cardinal++;
} // endif Cardinal
return Cardinal;
} // end of Cardinality
/***********************************************************************/ /* INI GetMaxSize: returns the table cardinality. */ /***********************************************************************/ int TDBINI::GetMaxSize(PGLOBAL g)
{ if (MaxSize < 0)
MaxSize = Cardinality(g);
if (Use == USE_OPEN) { #if0 if (To_Kindex) /*****************************************************************/ /* Table is to be accessed through a sorted index table. */ /*****************************************************************/
To_Kindex->Reset(); #endif// 0
Section = NULL;
N = 0; returnfalse;
} // endif use
/*********************************************************************/ /* OpenDB: initialize the INI file processing. */ /*********************************************************************/
GetSeclist(g);
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/ /* Allocate the buffers that will contain key values. */ /*********************************************************************/ for (colp = (PINICOL)Columns; colp; colp = (PINICOL)colp->GetNext()) if (!colp->IsSpecial()) // Not a pseudo column
colp->AllocBuf(g);
if (trace(1))
htrc("INI OpenDB: seclist=%s seclen=%d ifile=%s\n",
Seclist, Seclen, Ifile);
returnfalse;
} // end of OpenDB
/***********************************************************************/ /* Data Base read routine for INI access method. */ /***********************************************************************/ int TDBINI::ReadDB(PGLOBAL)
{ /*********************************************************************/ /* Now start the pseudo reading process. */ /*********************************************************************/ if (!Section)
Section = Seclist; else
Section += (strlen(Section) + 1);
if (trace(2))
htrc("INI ReadDB: section=%s N=%d\n", Section, N);
N++; return (*Section) ? RC_OK : RC_EF;
} // end of ReadDB
/***********************************************************************/ /* WriteDB: Data Base write routine for INI access methods. */ /***********************************************************************/ int TDBINI::WriteDB(PGLOBAL)
{ // This is to check that section name was given when inserting if (Mode == MODE_INSERT)
Section = NULL;
// Nothing else to do because all was done in WriteColumn return RC_OK;
} // end of WriteDB
/***********************************************************************/ /* Data Base delete line routine for INI access methods. */ /***********************************************************************/ int TDBINI::DeleteDB(PGLOBAL g, int irc)
{ switch (irc) { case RC_EF: break; case RC_FX: while (ReadDB(g) == RC_OK) if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) {
snprintf(g->Message, sizeof(g->Message), "Error %d accessing %s",
GetLastError(), Ifile); return RC_FX;
} // endif
/***********************************************************************/ /* Data Base close routine for INI access methods. */ /***********************************************************************/ void TDBINI::CloseDB(PGLOBAL)
{ #if !defined(_WIN32)
PROFILE_Close(Ifile); #endif// !_WIN32
} // end of CloseDB
/***********************************************************************/ /* INICOL public constructor. */ /***********************************************************************/
INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ)
: COLBLK(cdp, tdbp, i)
{ if (cprec) {
Next = cprec->GetNext();
cprec->SetNext(this);
} else {
Next = tdbp->GetColumns();
tdbp->SetColumns(this);
} // endif cprec
// Set additional INI access method information for column.
Valbuf = NULL;
Flag = cdp->GetOffset(); Long = cdp->GetLong();
To_Val = NULL;
} // end of INICOL constructor
/***********************************************************************/ /* INICOL constructor used for copying columns. */ /* tdbp is the pointer to the new table descriptor. */ /***********************************************************************/
INICOL::INICOL(INICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
Valbuf = col1->Valbuf;
Flag = col1->Flag; Long = col1->Long;
To_Val = col1->To_Val;
} // end of INICOL copy constructor
/***********************************************************************/ /* Allocate a buffer of the proper size. */ /***********************************************************************/ void INICOL::AllocBuf(PGLOBAL g)
{ if (!Valbuf)
Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
} // end of AllocBuf
/***********************************************************************/ /* SetBuffer: prepare a column block for write operation. */ /***********************************************************************/ bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{ if (!(To_Val = value)) {
snprintf(g->Message, sizeof(g->Message), MSG(VALUE_ERROR), Name); returntrue;
} elseif (Buf_Type == value->GetType()) { // Values are of the (good) column type if (Buf_Type == TYPE_DATE) { // If any of the date values is formatted // output format must be set for the receiving table if (GetDomain() || ((DTVAL *)value)->IsFormatted()) goto newval; // This will make a new value;
} elseif (Buf_Type == TYPE_DOUBLE || Buf_Type == TYPE_DECIM) // Float values must be written with the correct (column) precision // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else { // Values are not of the (good) column type if (check) {
snprintf(g->Message, sizeof(g->Message), MSG(TYPE_VALUE_ERR), Name,
GetTypeName(Buf_Type), GetTypeName(value->GetType())); returntrue;
} // endif check
newval: if (InitValue(g)) // Allocate the matching value block returntrue;
} // endif's Value, Buf_Type
// Allocate the internal value buffer
AllocBuf(g);
// Because Colblk's have been made from a copy of the original TDB in // case of Update, we must reset them to point to the original one. if (To_Tdb->GetOrig())
To_Tdb = (PTDB)To_Tdb->GetOrig();
// Set the Column
Status = (ok) ? BUF_EMPTY : BUF_NO; returnfalse;
} // end of SetBuffer
/***********************************************************************/ /* ReadColumn: what this routine does is to access the key buffer set */ /* from the corresponding section, extract from it the key value */ /* corresponding to this column name and convert it to buffer type. */ /***********************************************************************/ void INICOL::ReadColumn(PGLOBAL)
{
PTDBINI tdbp = (PTDBINI)To_Tdb;
if (trace(2))
htrc("INI ReadColumn: col %s R%d flag=%d\n",
Name, tdbp->GetTdb_No(), Flag);
/*********************************************************************/ /* Get the key value from the INI file. */ /*********************************************************************/ switch (Flag) { case1:
strncpy(Valbuf, tdbp->Section, Long); // Section name
Valbuf[Long] = '\0'; break; default:
GetPrivateProfileString(tdbp->Section, Name, "\b",
Valbuf, Long + 1, tdbp->Ifile); break;
} // endswitch Flag
// Missing keys are interpreted as null values if (!strcmp(Valbuf, "\b")) { if (Nullable)
Value->SetNull(true);
Value->Reset(); // Null value
} else
Value->SetValue_psz(Valbuf);
} // end of ReadColumn
/***********************************************************************/ /* WriteColumn: what this routine does is to access the last line */ /* read from the corresponding table, and rewrite the field */ /* corresponding to this column from the column buffer and type. */ /***********************************************************************/ void INICOL::WriteColumn(PGLOBAL g)
{ char *p; bool rc;
PTDBINI tdbp = (PTDBINI)To_Tdb;
if (trace(2))
htrc("INI WriteColumn: col %s R%d coluse=%.4X status=%.4X\n",
Name, tdbp->GetTdb_No(), ColUse, Status);
/*********************************************************************/ /* Get the string representation of Value according to column type. */ /*********************************************************************/ if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the updated value
// Null key are missing keys if (Value->IsNull()) return;
/*********************************************************************/ /* Updating must be done only when not in checking pass. */ /*********************************************************************/ if (Status) {
rc = WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile);
if (!rc) {
snprintf(g->Message, sizeof(g->Message), "Error %d writing to %s",
GetLastError(), tdbp->Ifile); throw31;
} // endif rc
// Is this really useful ???
PTDB TDBXIN::Clone(PTABS t)
{
PTDB tp;
PXINCOL cp1, cp2;
PGLOBAL g = t->G;
tp = new(g) TDBXIN(this);
for (cp1 = (PXINCOL)Columns; cp1; cp1 = (PXINCOL)cp1->GetNext()) {
cp2 = new(g) XINCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of Clone
/***********************************************************************/ /* Get the key list from the INI file. */ /***********************************************************************/ char *TDBXIN::GetKeylist(PGLOBAL g, char *sec)
{ if (!Keylist)
Keylist = (char*)PlugSubAlloc(g, NULL, Keylen);
GetPrivateProfileString(sec, NULL, "", Keylist, Keylen, Ifile); return Keylist;
} // end of GetKeylist
/***********************************************************************/ /* Allocate XIN column description block. */ /***********************************************************************/
PCOL TDBXIN::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{ returnnew(g) XINCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/ /* XIN Cardinality: returns the number of keys in the XIN file. */ /***********************************************************************/ int TDBXIN::Cardinality(PGLOBAL g)
{ if (!g) return1;
if (Cardinal < 0) { // Count the number of keys from the section list char *k, *p = GetSeclist(g);
Cardinal = 0;
if (p) for (; *p; p += (strlen(p) + 1)) for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1))
Cardinal++;
} // endif Cardinal
return Cardinal;
} // end of Cardinality
/***********************************************************************/ /* Record position is Section+Key. */ /***********************************************************************/ int TDBXIN::GetRecpos(void)
{ union { short X[2]; // Section and Key offsets int Xpos; // File position
} d; // end of union
d.X[0] = (short)(Section - Seclist);
d.X[1] = (short)(Keycur - Keylist); return d.Xpos;
} // end of GetRecpos
/***********************************************************************/ /* Record position is Section+Key. */ /***********************************************************************/ bool TDBXIN::SetRecpos(PGLOBAL g, int recpos)
{ union { short X[2]; // Section and Key offsets int Xpos; // File position
} d; // end of union
/***********************************************************************/ /* XIN Access Method opening routine. */ /***********************************************************************/ bool TDBXIN::OpenDB(PGLOBAL g)
{
Oldsec = -1; // To replace the table at its beginning return TDBINI::OpenDB(g);
} // end of OpenDB
/***********************************************************************/ /* Data Base read routine for XIN access method. */ /***********************************************************************/ int TDBXIN::ReadDB(PGLOBAL g)
{ /*********************************************************************/ /* Now start the pseudo reading process. */ /*********************************************************************/ #if0// XIN tables are not indexable if (To_Kindex) { /*******************************************************************/ /* Reading is by an index table. */ /*******************************************************************/ int recpos = To_Kindex->Fetch(g);
switch (recpos) { case -1: // End of file reached return RC_EF; case -2: // No match for join return RC_NF; case -3: // Same record as last non null one return RC_OK; default:
SetRecpos(g, recpos);
} // endswitch recpos
} else { #endif// 0 do { if (!Keycur || !*Keycur) { if (!Section)
Section = Seclist; else
Section += (strlen(Section) + 1);
if (*Section)
Keycur = GetKeylist(g, Section); else return RC_EF;
} else
Keycur += (strlen(Keycur) + 1);
} while (!*Keycur);
N++; //} // endif To_Kindex
return RC_OK;
} // end of ReadDB
/***********************************************************************/ /* WriteDB: Data Base write routine for XIN access methods. */ /***********************************************************************/ int TDBXIN::WriteDB(PGLOBAL)
{ // To check that section and key names were given when inserting if (Mode == MODE_INSERT) {
Section = NULL;
Keycur = NULL;
} // endif Mode
// Nothing else to do because all was done in WriteColumn return RC_OK;
} // end of WriteDB
/***********************************************************************/ /* Data Base delete line routine for XIN access methods. */ /***********************************************************************/ int TDBXIN::DeleteDB(PGLOBAL g, int irc)
{ if (irc == RC_EF) {
} elseif (irc == RC_FX) { for (Section = Seclist; *Section; Section += (strlen(Section) + 1)) if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) {
snprintf(g->Message, sizeof(g->Message), "Error %d accessing %s",
GetLastError(), Ifile); return RC_FX;
} // endif
/***********************************************************************/ /* XINCOL public constructor. */ /***********************************************************************/
XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: INICOL(cdp, tdbp, cprec, i, am)
{
} // end of XINCOL constructor
/***********************************************************************/ /* XINCOL constructor used for copying columns. */ /* tdbp is the pointer to the new table descriptor. */ /***********************************************************************/
XINCOL::XINCOL(XINCOL *col1, PTDB tdbp) : INICOL(col1, tdbp)
{
} // end of XINCOL copy constructor
/***********************************************************************/ /* ReadColumn: what this routine does is to access the key buffer set */ /* from the corresponding section, extract from it the key value */ /* corresponding to this column name and convert it to buffer type. */ /***********************************************************************/ void XINCOL::ReadColumn(PGLOBAL)
{
PTDBXIN tdbp = (PTDBXIN)To_Tdb;
/*********************************************************************/ /* Get the key value from the XIN file. */ /*********************************************************************/ switch (Flag) { case1:
strncpy(Valbuf, tdbp->Section, Long); // Section name
Valbuf[Long] = '\0'; break; case2:
strncpy(Valbuf, tdbp->Keycur, Long); // Key name
Valbuf[Long] = '\0'; break; default:
GetPrivateProfileString(tdbp->Section, tdbp->Keycur, "",
Valbuf, Long + 1, tdbp->Ifile); break;
} // endswitch Flag
Value->SetValue_psz(Valbuf);
} // end of ReadColumn
/***********************************************************************/ /* WriteColumn: what this routine does is to access the last line */ /* read from the corresponding table, and rewrite the field */ /* corresponding to this column from the column buffer and type. */ /***********************************************************************/ void XINCOL::WriteColumn(PGLOBAL g)
{ char *p; bool rc;
PTDBXIN tdbp = (PTDBXIN)To_Tdb;
if (trace(2))
htrc("XIN WriteColumn: col %s R%d coluse=%.4X status=%.4X\n",
Name, tdbp->GetTdb_No(), ColUse, Status);
/*********************************************************************/ /* Get the string representation of Value according to column type. */ /*********************************************************************/ if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the updated value
/*********************************************************************/ /* Updating must be done only when not in checking pass. */ /*********************************************************************/ if (Status) {
rc = WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile);
if (!rc) {
snprintf(g->Message, sizeof(g->Message), "Error %d writing to %s",
GetLastError(), tdbp->Ifile); throw31;
} // endif rc
} // endif Status
} // end of WriteColumn
/* ------------------------ End of System ---------------------------- */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.