source410: literal 4.10 source reconstruction + BC++ 4.52 fleet toolchain archived

- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
  is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
  Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
  (extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
  BT game source (never mixed into CODE/). Round 1-3 state:
  * 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
    (BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
    since 1996.
  * BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
    its binary-recorded line 400 exactly.
  * BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
    (Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
    TeamScore=12 flagged [T4]).
  * MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
    (VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
    the period compiler is the drift detector).
  * Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
    (per-TU verification sweep under authentic OPT.MAK flags).
  * README: corrected roadmap - MECH.HPP is the capstone grown with the mech
    TU reconstructions; BTREG.CPP green = the header-family milestone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-19 07:33:26 -05:00
co-authored by Claude Fable 5
parent 599b2388a1
commit 63312e07f9
5913 changed files with 756089 additions and 0 deletions
+318
View File
@@ -0,0 +1,318 @@
/*------------------------------------------------------------------------*/
/* */
/* BINIMP.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( CLASSLIB_BINIMP_H )
#include <classlib/binimp.h>
#endif
TBinarySearchTreeBase::TBinarySearchTreeBase() :
Root(0),
ItemsInContainer(0)
{
}
int TBinarySearchTreeBase::InsertNode( BinNode *node )
{
BinNode *Current = Root;
BinNode *Parent = 0;
while( Current )
{
Parent = Current;
Current = LessThan( node, Current ) ? Current->Left : Current->Right;
}
if( Parent == 0 )
Root = node;
else
{
if( LessThan( node, Parent ) )
Parent->Left = node;
else
Parent->Right = node;
}
ItemsInContainer++;
return 1;
}
int TBinarySearchTreeBase::RemoveNode( BinNode *node, int del )
{
BinNode *Current = Root;
BinNode *Parent = 0;
while( Current )
{
if( EqualTo( node, Current ) )
return RemNode( Current, Parent, del );
else
{
Parent = Current;
Current = LessThan( node, Current ) ? Current->Left :
Current->Right;
}
}
return 0;
}
TBinarySearchTreeBase::BinNode *TBinarySearchTreeBase::FindNode( BinNode *node )
{
BinNode *Current = Root;
while( Current )
{
if( EqualTo( node, Current ) )
return Current;
else
Current = LessThan( node, Current ) ? Current->Left :
Current->Right;
}
return 0;
}
int TBinarySearchTreeBase::RemNode( BinNode *node, BinNode *parent, int del )
{
// See R. Sedgewick, "Algorithms, 2nd edition",
// Addison-Wesley 1988, p.210.
BinNode *Original = node;
if( Original->Right == 0 )
node = node->Left;
else if( Original->Right->Left )
{
BinNode *Current = Original->Right;
while( Current->Left->Left )
Current = Current->Left;
node = Current->Left;
Current->Left = node->Right;
node->Left = Original->Left;
node->Right = Original->Right;
}
else
{
node = node->Right;
node->Left = Original->Left;
}
if( parent == 0 )
Root = node;
else if( LessThan( Original, parent ) )
parent->Left = node;
else
parent->Right = node;
DeleteNode( Original, del );
ItemsInContainer--;
return 1;
}
class TBinaryTreeKiller : public TBinaryTreeInternalIteratorBase
{
public:
TBinaryTreeKiller( TBinarySearchTreeBase& tree, int del ) :
TBinaryTreeInternalIteratorBase( tree, TBinarySearchTreeBase::PostOrder ),
Del(del) {}
private:
virtual void Apply( TBinarySearchTreeBase::BinNode _FAR *node,
TBinarySearchTreeBase::BinNode _FAR *parent );
int Del;
TBinaryTreeKiller( const TBinaryTreeKiller& );
const TBinaryTreeKiller& operator = ( const TBinaryTreeKiller& );
};
void TBinaryTreeKiller::Apply( TBinarySearchTreeBase::BinNode _FAR *node,
TBinarySearchTreeBase::BinNode _FAR *parent )
{
Tree().RemNode( node, parent, Del );
}
void TBinarySearchTreeBase::Flush( int del )
{
if( Root != 0 )
TBinaryTreeKiller( *this, del ).Iterate();
}
void TBinaryTreeInternalIteratorBase::Iterate()
{
TBinarySearchTreeBase::BinNode _FAR *Current = Node;
TBinarySearchTreeBase::BinNode _FAR *Prev = 0;
TBinarySearchTreeBase::BinNode _FAR *Next = 0;
step2:
if( Order == TBinarySearchTreeBase::PreOrder )
Apply( Current, 0 );
Next = Current->Left;
if( Next != 0 )
{
Current->Left = Prev;
Prev = Current;
Current = Next;
goto step2;
}
step4:
if( Order == TBinarySearchTreeBase::InOrder )
Apply( Current, 0 );
Next = Current->Right;
if( Next != 0 )
{
Current->Right = Prev;
Prev = Current;
Current = Next;
goto step2;
}
step6:
if( Prev == 0 )
{
if( Order == TBinarySearchTreeBase::PostOrder )
Apply( Current, 0 );
return;
}
if( Tree().LessThan( Current, Prev ) )
{
TBinarySearchTreeBase::BinNode _FAR *Temp = Current;
Next = Prev->Left;
Prev->Left = Current;
Current = Prev;
Prev = Next;
if( Order == TBinarySearchTreeBase::PostOrder )
Apply( Temp, Current );
goto step4;
}
else
{
TBinarySearchTreeBase::BinNode _FAR *Temp = Current;
Next = Prev->Right;
Prev->Right = Current;
Current = Prev;
Prev = Next;
if( Order == TBinarySearchTreeBase::PostOrder )
Apply( Temp, Current );
goto step6;
}
}
TBinaryTreeExternalIteratorBase::TBinaryTreeExternalIteratorBase( TBinarySearchTreeBase& tree, TBinarySearchTreeBase::IteratorOrder order ) :
Stack( new TStackAsList<TBinarySearchTreeBase::BinNode _BIDSFAR *> ),
Tree(&tree),
Current( tree.Root ),
Order( order )
{
Restart();
}
TBinaryTreeExternalIteratorBase::~TBinaryTreeExternalIteratorBase()
{
delete Stack;
}
void TBinaryTreeExternalIteratorBase::Restart()
{
Stack->Flush();
Current = Tree->Root;
LeftVisited = RightVisited = 0;
Processed = 0;
}
TBinarySearchTreeBase::BinNode *TBinaryTreeExternalIteratorBase::Next()
{
if( Current == 0 )
return 0;
for(;;)
{
if( Order == TBinarySearchTreeBase::PreOrder && !Processed )
{
Processed = 1;
return Current;
}
if( Current->Left != 0 && !LeftVisited )
{
Stack->Push( Current );
Current = Current->Left;
LeftVisited = RightVisited = 0;
Processed = 0;
}
else if( Current->Right != 0 && !RightVisited )
{
TBinarySearchTreeBase::BinNode *Res = 0;
if( Order == TBinarySearchTreeBase::InOrder )
Res = Current;
Stack->Push( Current );
Current = Current->Right;
LeftVisited = RightVisited = 0;
Processed = 0;
if( Res != 0 )
return Res;
}
else
{
if( Stack->IsEmpty() )
{
if( Processed == 0 )
{
Processed = 1;
}
else
{
Current = 0;
}
return Current;
}
else
{
TBinarySearchTreeBase::BinNode *Res;
switch( Order )
{
case TBinarySearchTreeBase::PreOrder:
// This node has already been
// processed, so we have further to go.
Res = 0;
// This node's parent has
// already been processed
Processed = 1;
break;
case TBinarySearchTreeBase::InOrder:
if( IsInOrder() )
{
// This node needs to be processed.
Res = Current;
}
else
{
// Node has already been processed.
Res = 0;
}
// If we're the right-hand child, our parent
// has already been processed.
Processed = Stack->Top()->Right == Current;
break;
case TBinarySearchTreeBase::PostOrder:
// This node needs to be processed.
Res = Current;
// This node's parent has not been processed.
Processed = 0;
break;
}
LeftVisited = 1;
RightVisited = Stack->Top()->Right == Current;
Current = Stack->Pop();
if( Res != 0 )
return Res;
}
}
}
}
+26
View File
@@ -0,0 +1,26 @@
/*------------------------------------------------------------------------*/
/* */
/* CASTABLE.CPP */
/* */
/* Copyright (c) 1992, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( BI_NO_RTTI )
#define BI_NO_RTTI
#endif
#if !defined( CLASSLIB_OBJSTRM_H )
#include <classlib/objstrm.h>
#endif
TStreamableBase::~TStreamableBase()
{
}
void *TStreamableBase::FindBase( Type_id ) const
{
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
/*------------------------------------------------------------------------*/
/* */
/* CLASMAIN.CPP */
/* */
/* Copyright (c) 1991, 1994 Borland International */
/* All Rights Reserved */
/* */
/* Provides the LibMain() function for the DLL version */
/* of the class libraries */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __WINDOWS_H )
#include <windows.h>
#endif
#if defined(__WIN32__)
BOOL DllEntryPoint(HINSTANCE /*hInstance*/, DWORD /*flag*/, LPVOID)
{
return 1;
}
#else
extern "C" int FAR PASCAL LibMain( HANDLE, WORD, WORD, LPSTR )
{
return 1;
}
#endif
+339
View File
@@ -0,0 +1,339 @@
/*------------------------------------------------------------------------*/
/* */
/* DATE.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDIO_H )
#include <stdio.h>
#endif
#if !defined( __TIME_H )
#include <time.h>
#endif
#if !defined( __STRING_H )
#include <string.h>
#endif
#if !defined( __CTYPE_H )
#include <ctype.h>
#endif
#if !defined( __CSTRING_H )
#include <cstring.h>
#endif
#if !defined( __CHECKS_H )
#include <checks.h>
#endif
#if !defined( CLASSLIB_DATE_H )
#include <classlib/date.h>
#endif
/****************************************************************
* *
* static constants *
* *
****************************************************************/
static const unsigned char DaysInMonth[12] =
{ 31,28,31,30,31,30,31,31,30,31,30,31 };
static const DayTy FirstDayOfEachMonth[12] =
{ 1,32,60,91,121,152,182,213,244,274,305,335 };
static const char *MonthNames[12] =
{ "January","February","March","April","May","June",
"July","August","September","October","November","December" };
static const char *UCMonthNames[12] =
{ "JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE",
"JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER" };
static const char *WeekDayNames[7] =
{ "Monday","Tuesday","Wednesday",
"Thursday","Friday","Saturday","Sunday" };
static const char *UCWeekDayNames[7] =
{ "MONDAY","TUESDAY","WEDNESDAY",
"THURSDAY","FRIDAY","SATURDAY","SUNDAY" };
static int _BIDSNEARFUNC
FindMatch( const char *str, const char**candidates, int icand );
/***************************************************************************/
// constructors
/***************************************************************************/
// Construct a TDate for today's date.
TDate::TDate()
{
long clk = time(0);
struct tm _FAR *now = localtime(&clk);
Julnum = Jday(now->tm_mon+1, now->tm_mday, now->tm_year+1900);
}
/*
* Construct a TDate with a given day of the year and a given year. The
* base date for this computation is Dec. 31 of the previous year. If
* year == 0, Construct a TDate with Jan. 1, 1901 as the "day zero".
* i.e., TDate(-1) = Dec. 31, 1900 and TDate(1) = Jan. 2, 1901.
*/
TDate::TDate(DayTy day, YearTy year)
{
if( year )
Julnum = Jday( 12, 31, year-1 ) + (JulTy)day;
else
Julnum = jul1901 + (JulTy)day;
}
// Construct a TDate for the given day, monthName, and year.
TDate::TDate( DayTy day, const char _BIDSFAR *monthName, YearTy year )
{
Julnum = Jday( IndexOfMonth(monthName), day, year );
}
// Construct a TDate for the given day, month, and year.
TDate::TDate( DayTy day, MonthTy month, YearTy year )
{
Julnum = Jday( month, day, year );
}
/***************************************************************************/
// static member functions
/***************************************************************************/
// Returns a string name for the weekday number.
// Monday == 1, ... , Sunday == 7
// Return 0 for weekday number out of range
const char _BIDSFAR *TDate::DayName( DayTy weekDayNumber )
{
return AssertWeekDayNumber(weekDayNumber) ? WeekDayNames[weekDayNumber-1] : 0;
}
// Return the number, 1-7, of the day of the week named nameOfDay.
// Return 0 if name doesn't match.
DayTy TDate::DayOfWeek( const char _BIDSFAR *nameOfDay )
{
return (DayTy)(FindMatch( nameOfDay, UCWeekDayNames, 7 )+1);
}
// Is a day (1-31) within a given month?
int TDate::DayWithinMonth( MonthTy month, DayTy day, YearTy year )
{
if( day <= 0 || !AssertIndexOfMonth(month) )
return 0;
unsigned d = DaysInMonth[month-1];
if( LeapYear(year) && month == 2 )
d++;
return day <= d;
}
// How many days are in the given YearTy year?
DayTy TDate::DaysInYear( YearTy year )
{
return LeapYear(year) ? 366 : 365;
}
// Returns the number, 1-12, of the month named nameOfMonth.
// Return 0 for no match.
MonthTy TDate::IndexOfMonth( const char _BIDSFAR *nameOfMonth )
{
return (MonthTy)(FindMatch( nameOfMonth, UCMonthNames, 12 )+1);
}
/*
* Convert Gregorian calendar date to the corresponding Julian day
* number j. Algorithm 199 from Communications of the ACM, Volume 6, No.
* 8, (Aug. 1963), p. 444. Gregorian calendar started on Sep. 14, 1752.
* This function not valid before that.
* Returns 0 if the date is invalid.
*/
JulTy TDate::Jday( MonthTy m, DayTy d, YearTy y )
{
unsigned long c, ya;
if( y <= 99 )
y += 1900;
if( !DayWithinMonth(m, d, y) )
return (JulTy)0;
if( m > 2 )
m -= 3;
else
{
m += 9;
y--;
}
c = y / 100;
ya = y - 100*c;
return ((146097L*c)>>2) + ((1461*ya)>>2) + (153*m + 2)/5 + d + 1721119L;
}
// Algorithm from K & R, "The C Programming Language", 1st ed.
int TDate::LeapYear( YearTy year )
{
return (year&3) == 0 && year%100 != 0 || year % 400 == 0;
}
// Returns a string name for the month number.
// Return 0 if invalid month number.
const char _BIDSFAR *TDate::MonthName( MonthTy monthNumber )
{
return AssertIndexOfMonth(monthNumber) ? MonthNames[monthNumber-1] : 0;
}
// Return index of case-insensitive match; -1 if no match.
static int _BIDSNEARFUNC FindMatch( const char *str, const char**candidates, int icand )
{
unsigned len = strlen(str);
while(icand--)
{
if( strnicmp(str, candidates[icand], len) == 0)
break;
}
return icand;
}
/****************************************************************
* *
* Member functions *
* *
****************************************************************/
// Compare function:
int TDate::CompareTo( const TDate _BIDSFAR &d ) const
{
if( Julnum < d.Julnum )
return -1;
else if( Julnum > d.Julnum )
return 1;
else
return 0;
}
DayTy TDate::Day() const
{
return DayTy(Julnum - Jday( 12, 31, Year()-1 ));
}
// Returns the day of the month of this TDate.
DayTy TDate::DayOfMonth() const
{
MonthTy m; DayTy d; YearTy y;
Mdy( m, d, y );
return d;
}
// Return the number of the first day of a given month
// Return 0 if "month" is outside of the range 1 through 12, inclusive.
DayTy TDate::FirstDayOfMonth( MonthTy month ) const
{
if ( !AssertIndexOfMonth(month) )
return 0;
unsigned firstDay = FirstDayOfEachMonth[month-1];
if (month > 2 && Leap())
firstDay++;
return firstDay;
}
unsigned TDate::Hash() const
{
return (unsigned)Julnum;
}
/*
* Convert a Julian day number to its corresponding Gregorian calendar
* date. Algorithm 199 from Communications of the ACM, Volume 6, No. 8,
* (Aug. 1963), p. 444. Gregorian calendar started on Sep. 14, 1752.
* This function not valid before that.
*/
void _BIDSNEARFUNC TDate::Mdy( MonthTy _BIDSFAR & m, DayTy _BIDSFAR & D, YearTy _BIDSFAR & y ) const
{
unsigned long d;
JulTy j = Julnum - 1721119L;
y = (YearTy) (((j<<2) - 1) / 146097L);
j = (j<<2) - 1 - 146097L*y;
d = (j>>2);
j = ((d<<2) + 3) / 1461;
d = (d<<2) + 3 - 1461*j;
d = (d + 4)>>2;
m = (MonthTy)(5*d - 3)/153;
d = 5*d - 3 - 153*m;
D = (DayTy)((d + 5)/5);
y = (YearTy)(100*y + j);
if( m < 10 )
m += 3;
else
{
m -= 9;
y++;
}
}
TDate TDate::Max( const TDate _BIDSFAR & dt ) const
{
return dt.Julnum > Julnum ? dt : *this;
}
TDate TDate::Min( const TDate _BIDSFAR & dt ) const
{
return dt.Julnum < Julnum ? dt : *this;
}
// Returns the month of this TDate.
MonthTy TDate::Month() const
{
MonthTy m; DayTy d; YearTy y;
Mdy(m, d, y);
return m;
}
TDate TDate::Previous( const char _BIDSFAR *dayName) const
{
return Previous( DayOfWeek(dayName) );
}
TDate TDate::Previous( DayTy desiredDayOfWeek ) const
{
// Renumber the desired and current day of week to start at 0 (Monday)
// and end at 6 (Sunday).
desiredDayOfWeek--;
DayTy thisDayOfWeek = WeekDay() - 1;
JulTy j = Julnum;
// Have to determine how many days difference from current day back to
// desired, if any. Special calculation under the 'if' statement to
// effect the wraparound counting from Monday (0) back to Sunday (6).
if( desiredDayOfWeek > thisDayOfWeek )
thisDayOfWeek += 7 - desiredDayOfWeek;
else
thisDayOfWeek -= desiredDayOfWeek;
j -= thisDayOfWeek; // Adjust j to set it at the desired day of week.
return TDate(j);
}
DayTy TDate::WeekDay() const
{
return DayTy(((((Julnum+1)%7)+6)%7)+1);
}
// Returns the year of this TDate.
YearTy TDate::Year() const
{
MonthTy m; DayTy d; YearTy y;
Mdy(m, d, y);
return y;
}
+170
View File
@@ -0,0 +1,170 @@
/*------------------------------------------------------------------------*/
/* */
/* DATEIO.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDIO_H )
#include <stdio.h>
#endif
#if !defined( __CTYPE_H )
#include <ctype.h>
#endif
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif
#if !defined( __CSTRING_H )
#include <cstring.h>
#endif
#if !defined( CLASSLIB_DATE_H )
#include <classlib/date.h>
#endif
TDate::HowToPrint TDate::PrintOption = TDate::Normal;
string TDate::AsString() const
{
char buf[80];
ostrstream strtemp(buf, sizeof(buf));
strtemp << (*this) << ends;
string temp(buf);
return temp;
}
TDate::HowToPrint TDate::SetPrintOption( HowToPrint h )
{
HowToPrint oldoption = PrintOption;
PrintOption = h;
return oldoption;
}
// Skip any characters except alphanumeric characters
static void _BIDSNEARFUNC SkipDelim( istream _BIDSFAR & strm )
{
char c;
if( !strm.good() )
return;
do {
strm >> c;
} while (strm.good() && !isalnum(c)) ;
if (strm.good())
strm.putback(c);
}
// Parse the name of a month from input stream.
static const char* _BIDSNEARFUNC ParseMonth( istream _BIDSFAR & s )
{
static char month[12];
register char* p = month;
char c;
SkipDelim(s);
s.get(c);
while (s.good() && isalpha(c) && (p != &month[10]))
{
*p++ = c;
s.get(c);
}
if( s.good() )
s.putback(c);
*p = '\0';
return month;
}
// Parse a date from the specified input stream.
// The date must be in one of the following forms:
// dd-mmm-yy, mm/dd/yy, or mmm dd,yy
// e.g.: 10-MAR-86, 3/10/86, or March 10, 1986.
// Any non-alphanumeric character may be used as a delimiter.
void TDate::ParseFrom( istream _BIDSFAR & s )
{
unsigned d,m,y;
Julnum = 0; // Assume failure
if (s.good())
{
SkipDelim(s);
s >> m; // try to parse day or month number
SkipDelim(s);
if (s.eof())
return;
if( s.fail() ) // parse <monthName><day><year>
{
s.clear();
m = IndexOfMonth(ParseMonth(s)); // parse month name
SkipDelim(s);
s >> d; // parse day
}
else // try to parse day number
{
s >> d;
if (s.eof()) return;
if (s.fail()) // parse <day><monthName><year>
{
d = m;
s.clear();
m = IndexOfMonth(ParseMonth(s)); // parse month name
}
}
SkipDelim(s);
s >> y;
}
Julnum = s.good() ? Jday(m, d, y) : 0;
if(Julnum==0)
s.clear(ios::badbit);
}
ostream _BIDSFAR & _BIDSFUNC operator << ( ostream _BIDSFAR & s, const TDate _BIDSFAR & d )
{
char buf[80];
// we use an ostrstream to format into buf so that
// we don't affect the ostream's width setting.
ostrstream out( buf, sizeof(buf) );
switch ( TDate::PrintOption )
{
case TDate::Normal:
out << d.NameOfMonth() << " "
<< d.DayOfMonth() << ", "
<< d.Year() << ends;
break;
case TDate::Terse:
sprintf(buf,"%2u-%.3s-%.2u",
d.DayOfMonth(),
d.NameOfMonth(),
d.Year() % 100);
break;
case TDate::Numbers:
out << d.Month() << "/"
<< d.DayOfMonth() << "/"
<< (d.Year() % 100) << ends;
break;
case TDate::EuropeanNumbers:
out << d.DayOfMonth() << "/"
<< d.Month() <<"/"
<< (d.Year() % 100) << ends;
break;
case TDate::European:
out << d.DayOfMonth() << " "
<< d.NameOfMonth() << " "
<< d.Year() << ends;
break;
};
// now we write out the formatted buffer, and the ostream's
// width setting will control the actual width of the field.
s << buf;
return s;
}
+32
View File
@@ -0,0 +1,32 @@
/*------------------------------------------------------------------------*/
/* */
/* DATEP.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif
#if !defined( CLASSLIB_DATE_H )
#include <classlib/date.h>
#endif
#if !defined( CLASSLIB_OBJSTRM_H )
#include <classlib/objstrm.h>
#endif
opstream _BIDSFAR & _BIDSFUNC operator << ( opstream _BIDSFAR & os, const TDate _BIDSFAR & d )
{
return os << d.Julnum;
}
ipstream _BIDSFAR & _BIDSFUNC operator >> ( ipstream _BIDSFAR & is, TDate _BIDSFAR & d )
{
return is >> d.Julnum;
}
+44
View File
@@ -0,0 +1,44 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All rights
//
// TXBase class implementation.
//
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/defs.h>
#include <osl/except.h>
int TXBase::InstanceCount = 0;
TXBase::TXBase(const string& msg)
: xmsg(msg)
{
InstanceCount++;
}
TXBase::TXBase(const TXBase& src)
: xmsg(src)
{
InstanceCount++;
}
TXBase::~TXBase()
{
InstanceCount--;
}
TXBase*
TXBase::Clone()
{
return new TXBase(*this);
}
void
TXBase::Throw()
{
THROW( *this );
}
+265
View File
@@ -0,0 +1,265 @@
/*------------------------------------------------------------------------*/
/* */
/* FILE.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __LIMITS_H )
#include <limits.h>
#endif
#if !defined( __DIR_H )
#include <dir.h>
#endif
#if !defined( __DOS_H )
#include <dos.h>
#endif
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif
#if !defined( CLASSLIB_DEFS_H )
#include <classlib/defs.h>
#endif
#if defined( BI_PLAT_OS2 ) && !defined( __OS2_H )
#define INCL_BASE
#include <os2.h>
#endif
#if defined( BI_PLAT_WIN32 ) && !defined( __WINDOWS_H )
#include <windows.h>
#endif
#if !defined( CLASSLIB_FILE_H )
#include <classlib/file.h>
#endif
int TFile::Open( const char _BIDSFAR *name, uint16 access, uint16 permission )
{
const unsigned shareFlags =
Compat | DenyNone | DenyRead | DenyWrite | DenyRdWr | NoInherit;
if( IsOpen() )
return 0;
Handle = ::sopen( name,
access & ~shareFlags,
access & shareFlags,
permission );
return IsOpen();
}
int TFile::Close()
{
if( IsOpen() && ::close(Handle) == 0)
{
Handle = FileNull;
return 1;
}
else
return 0;
}
long TFile::Length() const
{
return ::filelength( Handle );
}
#if !defined( __OS2__ )
int TFile::GetStatus( TFileStatus _BIDSFAR & status ) const
{
struct ftime ftime;
if( ::getftime(Handle, &ftime) != 0 )
return 0;
TDate fileDate( ftime.ft_day, ftime.ft_month, ftime.ft_year+80 );
status.createTime = TTime( fileDate,
ftime.ft_hour,
ftime.ft_min,
ftime.ft_tsec*2 );
status.modifyTime = status.createTime;
status.accessTime = status.createTime;
status.size = Length();
status.attribute = 0;
status.fullName[0] = '\0';
return 1;
}
#else
TTime MakeTTime( FDATE fdate, FTIME ftime )
{
TDate fileDate( fdate.day, fdate.month, fdate.year );
return TTime( fileDate, ftime.hours, ftime.minutes, ftime.twosecs*2 );
}
int TFile::GetStatus( TFileStatus _BIDSFAR& status ) const
{
FILESTATUS stat;
if( ::DosQueryFileInfo( Handle, FIL_STANDARD, &stat, sizeof(stat) ) != 0 )
return 0;
status.createTime = MakeTTime( stat.fdateCreation, stat.ftimeCreation );
status.modifyTime = MakeTTime( stat.fdateLastWrite, stat.ftimeLastWrite );
status.accessTime = MakeTTime( stat.fdateLastAccess, stat.ftimeLastAccess );
status.size = stat.cbFile;
status.attribute = stat.attrFile;
status.fullName[0] = '\0';
return 1;
}
#endif
struct dos_ftime
{
unsigned tsec : 5;
unsigned min : 6;
unsigned hour : 5;
};
struct dos_fdate
{
unsigned day : 5;
unsigned mon : 4;
unsigned year : 7;
};
#if !defined( __OS2__ )
int TFile::GetStatus( const char _BIDSFAR *name,
TFileStatus _BIDSFAR & status )
{
if( ::_fullpath( status.fullName, name, sizeof(status.fullName) ) == 0 )
{
status.fullName[0] = '\0';
return 0;
}
ffblk blk;
const uint16 FA_ALL = FA_RDONLY | FA_HIDDEN | FA_SYSTEM |
FA_LABEL | FA_DIREC | FA_ARCH;
if( findfirst( status.fullName, &blk, FA_ALL ) != 0 )
return 0;
union
{
dos_ftime time;
dos_fdate date;
unsigned value;
};
value = blk.ff_fdate;
TDate fileDate( date.day, date.mon, date.year+80 );
value = blk.ff_ftime;
status.createTime = TTime( fileDate,
time.hour,
time.min,
time.tsec*2 );
status.modifyTime = status.createTime;
status.accessTime = status.createTime;
status.size = blk.ff_fsize;
status.attribute = blk.ff_attrib;
return 1;
}
#else
int TFile::GetStatus( const char _BIDSFAR *name,
TFileStatus _BIDSFAR & status )
{
if( ::_fullpath( status.fullName, name, sizeof(status.fullName) ) == 0 )
{
status.fullName[0] = '\0';
return 0;
}
const uint16 FA_ALL = FA_RDONLY | FA_HIDDEN | FA_SYSTEM |
FA_LABEL | FA_DIREC | FA_ARCH;
HDIR Handle;
FILEFINDBUF stat;
ULONG count;
if( ::DosFindFirst( status.fullName,
&Handle,
FA_ALL,
&stat,
sizeof(stat),
&count,
0 ) != 0 )
{
status.fullName[0] = '\0';
return 0;
}
status.createTime = MakeTTime( stat.fdateCreation, stat.ftimeCreation );
status.modifyTime = MakeTTime( stat.fdateLastWrite, stat.ftimeLastWrite );
status.accessTime = MakeTTime( stat.fdateLastAccess, stat.ftimeLastAccess );
status.size = stat.cbFile;
status.attribute = stat.attrFile;
return 1;
}
#endif
#if !defined( __OS2__ )
int TFile::SetStatus( const char _BIDSFAR *name,
const TFileStatus _BIDSFAR & status )
{
int attr = ::_rtl_chmod( name, 0 );
if( attr & TFile::RdOnly )
return 0;
ftime fileTime;
fileTime.ft_tsec = status.createTime.Second()/2;
fileTime.ft_min = status.createTime.Minute();
fileTime.ft_hour = status.createTime.Hour();
TDate date( status.createTime );
fileTime.ft_day = date.DayOfMonth();
fileTime.ft_month = date.Month();
fileTime.ft_year = date.Year()-80;
TFile file( name, ReadWrite | DenyWrite );
if( ::setftime( file.GetHandle(), &fileTime ) != 0 )
return 0;
if( ::chsize( file.GetHandle(), status.size ) != 0 )
return 0;
if( ::_rtl_chmod( name, 1, status.attribute ) == -1 )
return 0;
return 1;
}
#else
FDATE MakeFDATE( TTime time )
{
FDATE fdate;
fdate.day = TDate(time).Day();
fdate.month = TDate(time).Month();
fdate.year = TDate(time).Year();
return fdate;
}
FTIME MakeFTIME( TTime time )
{
FTIME ftime;
ftime.hours = time.Hour();
ftime.minutes = time.Minute();
ftime.twosecs = time.Second()/2;
return ftime;
}
int TFile::SetStatus( const char _BIDSFAR *name,
const TFileStatus _BIDSFAR & status )
{
FILESTATUS stat;
stat.fdateCreation = MakeFDATE( status.createTime );
stat.ftimeCreation = MakeFTIME( status.createTime );
stat.fdateLastAccess = MakeFDATE( status.accessTime );
stat.ftimeLastAccess = MakeFTIME( status.accessTime );
stat.fdateLastWrite = MakeFDATE( status.modifyTime );
stat.ftimeLastWrite = MakeFTIME( status.modifyTime );
stat.cbFile = status.size;
stat.cbFileAlloc = status.size;
stat.attrFile = status.attribute;
TFile file( name, ReadWrite | DenyWrite );
return ::DosSetFileInfo( file.GetHandle(),
FIL_STANDARD,
&stat,
sizeof(stat) );
}
#endif

+235
View File
@@ -0,0 +1,235 @@
//----------------------------------------------------------------------------
// (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
// Implementation of geometry (TPoint, TSize, TRect) classes.
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/defs.h>
#include <osl/geometry.h>
//
// Calculate the integer square root of a 32bit signed long. return a 16bit
// signed. Is fairly fast, esp. compared to FP versions
//
int _BIDSFUNC
Sqrt(long val)
{
if (val <= 0)
return 0; // Throw a math exception?
unsigned mask = 1; // Bit mask to shift left
int best = 0; // Best estimate so far
for (; !(mask&0x8000); mask <<= 1)
if (((long)best+mask)*(best+mask) <= val)
best |= mask;
return best;
}
//
// Make a duplicate of a C string using new char[]
//
char* _BIDSFUNC
strnewdup(const char* s, size_t allocSize)
{
if (!s)
s = "";
int alloc = max(strlen(s)+1, allocSize);
return strcpy(new char[alloc], s);
}
//
// Make a far duplicate of a C string using new char[] far
//
#if defined(BI_DATA_NEAR)
char far* _BIDSFUNC
strnewdup(const char far* s, size_t allocSize)
{
if (!s)
s = "";
int alloc = max(strlen(s)+1, allocSize);
return strcpy(new far char[alloc], s);
}
long
atol(const char far* s)
{
for (long val = 0; *s && isdigit(*s); s++)
val = val*10 + *s - '0';
return val;
}
#endif
#if !defined(BI_PLAT_WIN16)
//
// Make a duplicate of a wide C string using new wchar_t[]
//
wchar_t* _BIDSFUNC
strnewdup(const wchar_t* s, size_t allocSize)
{
if (!s)
s = L"";
int alloc = max((size_t)lstrlenW(s)+1, allocSize);
return lstrcpyW(new wchar_t[alloc], s);
}
//
// Wide string copy function.
//
wchar_t* _BIDSFUNC
strcpy(wchar_t* dst, const wchar_t* src)
{
wchar_t* p = dst;
while ((*p++ = *src++) != 0)
;
return dst;
}
//
// Wide string length function.
//
size_t _BIDSFUNC
strlen(const wchar_t* str)
{
const wchar_t* p = str;
for (; *p; p++)
;
return p - str;
}
#endif
//----------------------------------------------------------------------------
TRect&
TRect::Normalize()
{
if (left > right)
Swap(left, right);
if (top > bottom)
Swap(top, bottom);
return *this;
}
TRect&
TRect::Offset(int dx, int dy)
{
left += dx;
top += dy;
right += dx;
bottom += dy;
return *this;
}
TRect&
TRect::Inflate(int dx, int dy)
{
left -= dx;
top -= dy;
right += dx;
bottom += dy;
return *this;
}
TRect&
TRect::operator &=(const TRect& other)
{
if (!IsNull()) {
if (other.IsNull())
SetNull();
else {
left = Max(left, other.left);
top = Max(top, other.top);
right = Min(right, other.right);
bottom = Min(bottom, other.bottom);
}
}
return *this;
}
TRect&
TRect::operator |=(const TRect& other)
{
if (!other.IsNull()) {
if (IsNull())
*this = other;
else {
left = Min(left, other.left);
top = Min(top, other.top);
right = Max(right, other.right);
bottom = Max(bottom, other.bottom);
}
}
return *this;
}
//----------------------------------------------------------------------------
// class TCmdLine implementation
const char whitespace[] = " \t";
const char terminator[] = "=/ \t"; // remove /- to dissallow separating there
TCmdLine::TCmdLine(const char far* cmdLine)
{
Buffer = new char[strlen(cmdLine)+1];
strcpy(Buffer, cmdLine);
Reset();
}
void TCmdLine::Reset()
{
Token = TokenStart = Buffer;
TokenLen = 0;
Kind = Start;
}
TCmdLine::~TCmdLine()
{
delete [] Buffer;
}
TCmdLine::TKind TCmdLine::NextToken(bool removeCurrent)
{
// Done parsing, no more tokens
//
if (Kind == Done)
return Kind;
// Move Token ptr to next token, by copying over current token, or by ptr
// adjustment. TokenStart stays right past previous token
//
if (removeCurrent) {
strcpy(TokenStart, Token+TokenLen);
Token = TokenStart;
}
else {
Token += TokenLen;
TokenStart = Token;
}
// Adjust token ptr to begining of token & determine kind
//
Token += strspn(Token, whitespace); // skip leading whitespace
switch (*Token) {
case 0:
Kind = Done;
break;
case '=':
Kind = Value;
Token++;
break;
case '-':
case '/':
Kind = Option;
Token++;
break;
default:
Kind = Name;
}
Token += strspn(Token, whitespace); // skip any more whitespace
TokenLen = strcspn(Token, terminator);
return Kind;
}
+85
View File
@@ -0,0 +1,85 @@
//----------------------------------------------------------------------------
// (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
// Implementation of geometry streaming support
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/defs.h>
#include <osl/geometry.h>
ostream& _BIDSFUNC
operator <<(ostream& os, const TRect& r)
{
return os << '(' << r.left << ',' << r.top << '-'
<< r.right << ',' << r.bottom << ')';
}
//
// streaming operators for resource Ids
//
ostream& _BIDSFUNC
operator <<(ostream& os, const TResId& id)
{
bool isNumeric = static_cast<bool>(!id.IsString());
if (isNumeric)
os << (long)id.Id;
else
#if defined(BI_DATA_NEAR)
os << string(id.Id);
#else
os << id.Id;
#endif
return os;
}
//! Could break this file in half here...
ipstream& _BIDSFUNC
operator >>(ipstream& is, TRect& r)
{
return is >> r.left >> r.top >> r.right >> r.bottom;
}
opstream& _BIDSFUNC
operator <<(opstream& os, const TRect& r)
{
return os << r.left << r.top << r.right << r.bottom;
}
//
// streaming operators for resource Ids
//
ipstream& _BIDSFUNC
operator >>(ipstream& is, TResId& id)
{
bool isNumeric;
is >> isNumeric;
if (isNumeric) {
long nid;
is >> nid;
id = int(nid);
} else
id = (const char far *)is.freadString();
return is;
}
opstream& _BIDSFUNC
operator <<(opstream& os, const TResId& id)
{
bool isNumeric = static_cast<bool>(!id.IsString());
os << isNumeric;
if (isNumeric)
os << (long)id.Id;
else
os.fwriteString(id.Id);
return os;
}
+45
View File
@@ -0,0 +1,45 @@
/*------------------------------------------------------------------------*/
/* */
/* HEAPSEL.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
// THeapSelector doesn't have to do anything special under WIN32. It's
// only under Windows that we have to worry about multiple heaps.
#if !defined( __FLAT__ )
#if !defined( _Windows )
#define _Windows
#endif
#if !defined( __WINDOWS_H )
#include <windows.h>
#endif
#if !defined( __DOS_H )
#include <dos.h>
#endif
#if !defined( CLASSLIB_HEAPSEL_H )
#include <classlib/heapsel.h>
#endif
void _BIDSFARDATA *THeapSelector::Allocate( size_t sz ) const
{
HeapSetup frame(FP_SEG(this));
return MK_FP( _DS, LocalAlloc( sz, LMEM_MOVEABLE ) );
}
void THeapSelector::Free( void _BIDSFARDATA *block )
{
HeapSetup frame(FP_SEG(block));
HANDLE hMem = LocalHandle( FP_OFF(block) );
if( hMem )
LocalFree( hMem );
}
#endif
+418
View File
@@ -0,0 +1,418 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// TLocaleString implementation - localized name support
//
// NOTE: This code must reside in the same module that the strings are defined
// The cache, NativeLangId, HINSTANCE are managed on a per-module basis
// TLocaleString::NativeLangId may be user-implemented to symbol langid
// TLocaleString::Module may be reset from this to another resource DLL
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/locale.h>
#include <stdio.h>
//----------------------------------------------------------------------------
// Module global default values - except for TLocaleString::NativeLangId
//
TLangId TLocaleString::SystemDefaultLangId = TLocaleString::GetSystemLangId();
TLangId TLocaleString::UserDefaultLangId = TLocaleString::GetUserLangId();
HINSTANCE TLocaleString::Module = _hInstance;
TLocaleString TLocaleString::Null = {""};
//----------------------------------------------------------------------------
// TLocaleCache definitions, private for implementation
//
#define AUTOLANG_CACHEDNEUT 0x02 // prefix indicates cache entry with neutral
#define AUTOLANG_CACHEDLOAD 0x01 // prefix indicates Neutral is not a string
const TLangId InvalidLangId = 0xFFFF;
struct TLocaleCache;
struct TLocaleCacheBase;
//
// Static object to hold destructable pointer
//
struct TLocaleCacheList {
TLocaleCacheList() : Next(0) {}
~TLocaleCacheList(); // releases cache entries
TLocaleCache* Lookup(const char* name); // returns cache entry, 0 if failed
TLocaleCacheBase* Next; // linked list of cached translations
};
//
// This base struct is used to cache failure to find language resource
//
struct TLocaleCacheBase {
long Hash; // hashed original string, for duplicate elimination
const char* Neutral; // original string, +1 if resource found and loaded
TLocaleCacheBase* Next;// linked list of cached strings, for search, cleanup
TLocaleCacheBase(const char* name, long hash);
static TLocaleCacheList CacheList;
};
//
// Buffer follows this header, sized for maximum string + null term.
//
struct TLocaleCache : public TLocaleCacheBase {
void* operator new(unsigned size, unsigned buflen);
TLocaleCache(const char* name, long hash, HRSRC rscHdl, HGLOBAL resData);
~TLocaleCache() {}
const char* Translate(TLangId lang); // (re)translate string
TLangId ActLangId; // actual language ID of cached string
TLangId ReqLangId; // requested language ID of cached string
HRSRC ResHdl; // handle returned from ::FindResource()
char Buf[1]; // first character is string type
};
//----------------------------------------------------------------------------
// TLocaleCache implementation
//
TLocaleCacheBase::TLocaleCacheBase(const char* name, long hash)
:
Neutral(name),
Hash(hash)
{
Next = CacheList.Next;
CacheList.Next = this;
}
void* TLocaleCache::operator new(unsigned size, unsigned buflen)
{
return ::operator new(size+buflen);
}
TLocaleCache::TLocaleCache(const char* name, long hash,
HRSRC resHdl, HGLOBAL resData)
:
TLocaleCacheBase(name, hash),
ResHdl(resHdl)
{
ReqLangId = ActLangId = InvalidLangId; // indicate initializing state
*(HGLOBAL*)(Buf+1) = resData; // store resource pointer temp in buffer
}
TLocaleCache* TLocaleCacheList::Lookup(const char* name)
{
const char* neut = name + 1; // skip over prefix flag char
long hash = 0;
const char* pc = name;
while (*pc)
hash = hash*2 ^ *pc++;
for (TLocaleCacheBase* entry = Next; entry; entry = entry->Next) {
if (hash == entry->Hash) {
const char* pc = entry->Neutral;
if (*pc != *neut) // Neutral points to prefix if lookup failed
pc++;
if (TLocaleString::CompareLang(pc,neut,TLocaleString::NativeLangId) != 0)
return pc == entry->Neutral ? (TLocaleCache*)entry : 0;
}
}
pc = name;
if (*name != AUTOLANG_RCID)
pc++; // '#' part of Id
HRSRC resHdl = ::FindResource(TLocaleString::Module, pc, RT_LOCALIZATION);
if (!resHdl) {
new TLocaleCacheBase(name, hash); // add cache entry for failed lookup
return 0;
}
HGLOBAL resData = ::LoadResource(TLocaleString::Module, resHdl);
if (!resData) {
return 0; // should throw exception on failure?!!
}
unsigned char far* pr = (unsigned char far*)::LockResource(resData);
int maxLen = sizeof(HGLOBAL); // scan for longest string, including null
unsigned char c = *pr; // check first byte of langid or neutral text
if (c == 0) { // check for empty resource string
::FreeResource(resData);
new TLocaleCacheBase(name, hash); // add failed cache entry if null or err
return 0;
}
if (c >= ' ') // check for unprefixed neutral string first
pr--; // cancel ++ in for loop initialization
else
pr++; // start to skip over 2-byte language id
do { // loop to check for maximum string length
unsigned char far* p = ++pr; // skip over id to start of translation
while ((c=*pr++) >= ' ') ; // skip over translation string
if ((int)(pr-p) > maxLen) // update maximum, including terminator
maxLen = (int)(pr-p);
} while(c);
TLocaleCache* cache = new(maxLen) TLocaleCache(neut, hash, resHdl, resData);
cache->Buf[0] = (*name == AUTOLANG_XLAT ? AUTOLANG_CACHEDNEUT
: AUTOLANG_CACHEDLOAD);
return cache;
}
const char* TLocaleCache::Translate(TLangId reqLang)
{
HGLOBAL resData;
if (ReqLangId == InvalidLangId) { // if first time called after construction
resData = *(HGLOBAL*)(Buf+1);
ReqLangId = reqLang;
} else {
if (Buf[0]==AUTOLANG_CACHEDNEUT && TLocaleString::IsNativeLangId(reqLang))
return Neutral;
if (reqLang == ActLangId)
return Buf+1;
if (reqLang == ReqLangId) {
if (ActLangId != InvalidLangId)
return Buf+1;
else if (Buf[0] == AUTOLANG_CACHEDNEUT)
return Neutral;
else
return 0;
}
if ((resData = ::LoadResource(TLocaleString::Module, ResHdl)) == 0)
return Neutral; // should throw exception on failure?!!
}
unsigned char far* resBuf = (unsigned char far*)::LockResource(resData);
unsigned char far* translation = 0;
unsigned char far* pr = resBuf;
int actLang = InvalidLangId;
unsigned char c;
int resLang;
while ((c = *pr) != 0) {
if (c > ' ') { // check for initial neutral string, used with CACHEDLOAD
actLang = resLang = TLocaleString::NativeLangId;
translation = pr; // lowest preference match
} else {
resLang = ((c - 1)<<10) | *++pr,pr++;
}
if (resLang == reqLang) { // exact match
translation = pr;
actLang = resLang;
break;
}
if ((char)resLang == (char)reqLang) { // base language match
if ((char)actLang != (char)reqLang || resLang == (reqLang & 0x00FF)) {
translation = pr;
actLang = resLang;
}
}
for ( ; *pr >= ' '; ++pr) ; // skip over translation string till next Id
}
const char* retVal;
if (translation) {
while (*translation < ' ') // skip over multiple language IDs
translation += 2;
if (actLang != ActLangId) { // if same as in buffer, leave alone
char* pc;
for (pr = translation, pc = Buf + 1; *pr >= ' '; )
*pc++ = *pr++;
*pc = 0;
ActLangId = actLang;
if (reqLang != ActLangId)
ReqLangId = reqLang;
}
retVal = Buf+1;
} else if (Buf[0] == AUTOLANG_CACHEDNEUT) {
retVal = Neutral;
} else {
retVal = 0;
}
::FreeResource(resData);
return retVal;
}
TLocaleCacheList TLocaleCacheBase::CacheList; // declare module-global cache
TLocaleCacheList::~TLocaleCacheList()
{
while (Next) {
TLocaleCacheBase* p = Next;
Next = Next->Next;
delete p;
}
}
//----------------------------------------------------------------------------
// TLocaleString implementation, except for static int CompareLang(s1,s2,lang)
//
const char* TLocaleString::Translate(TLangId reqLang)
{
if (!Private) // check for null string pointer
return Private;
if (reqLang == LangNeutral)
reqLang = NativeLangId;
else if (reqLang == LangSysDefault)
reqLang = SystemDefaultLangId;
else if (reqLang == LangUserDefault)
reqLang = UserDefaultLangId;
TLocaleCache* cache;
switch (Private[0])
{
default: // untranslatable string, no prefix
return Private;
case AUTOLANG_XLAT: // not yet translated
if (IsNativeLangId(reqLang))
return Private+1; // resource name IS neutral or default name
if ((cache = TLocaleCacheBase::CacheList.Lookup(Private)) == 0)
return ++Private; // permanently bump pointer to make constant
Private = cache->Buf; // point to buffer in cache
return cache->Translate(reqLang);
case AUTOLANG_LOAD: // named resource not accessed yet
case AUTOLANG_RCID: // numeric resource not accessed yet
if ((cache = TLocaleCacheBase::CacheList.Lookup(Private)) == 0)
return (Private = 0); // permanently set pointer to null
Private = cache->Buf; // point to buffer in cache
return cache->Translate(reqLang);
case AUTOLANG_CACHEDNEUT: // string in cache with neutral pointer
case AUTOLANG_CACHEDLOAD: // string in cache with no neutral pointer
cache = (TLocaleCache*)(Private+1) - 1; // backup to point to header
return cache->Translate(reqLang);
}
}
TLocaleString::operator const char*()
{
if (Private == 0)
return 0;
switch (Private[0]) {
case AUTOLANG_XLAT: // not yet translated
case AUTOLANG_CACHEDNEUT: // translated string in cache
case AUTOLANG_CACHEDLOAD: // translated or neutral name in cache
return Private+1;
case AUTOLANG_RCID: // resource not accessed yet
case AUTOLANG_LOAD: // resource not accessed yet
return 0;
default: // untranslatable string, no prefix
return Private;
}
}
int TLocaleString::Compare(const char far* str, TLangId lang)
{
return CompareLang(this->Translate(lang), str, lang);
}
int TLocaleString::IsNativeLangId(TLangId lang)
{
return lang == NativeLangId || lang == (NativeLangId & 0x00FF);
}
//----------------------------------------------------------------------------
// Registration parameter structures and formatting functions
//
const char* TRegList::Lookup(const char* key, TLangId lang)
{
for (TRegItem* regItem = Items; regItem->Key != 0; regItem++) {
if (strcmp(regItem->Key, key) == 0)
if (regItem->Value.Private) // current can't test Value directly
return regItem->Value.Translate(lang);
else
return "";
}
return 0;
}
TLocaleString& TRegList::LookupRef(const char* key)
{
for (TRegItem* regItem = Items; regItem->Key != 0; regItem++) {
if (strcmp(regItem->Key, key) == 0)
return regItem->Value;
}
return TLocaleString::Null;
}
//----------------------------------------------------------------------------
//
// Maximum string length for REGFORMAT w/ string arg. String is clipped if too
// long.
//
const int MaxFormatLen = 40;
char* TRegItem::RegFormat(int f, int a, int t, int d, TRegFormatHeap& heap)
{
// sprintf into sized auto buffer
// ints have a max of 11 digits: -2000000000. Add pad of 8 just in case
//
char temp[11+1+11+1+11+1+11+1 +8];
int len = sprintf(temp, "%d,%d,%d,%d", f,a,t,d);
// Check for potential overflow
//
char* str = heap.Data + heap.Used;
heap.Used += len + 1;
if (heap.Used > heap.Size)
return "";
// Copy into real static buffer & return it
//
return strcpy(str, temp);
}
char* TRegItem::RegFormat(const char* f, int a, int t, int d, TRegFormatHeap& heap)
{
// sprintf into sized auto buffer
//
char temp[MaxFormatLen+1+11+1+11+1+11+1 +8];
int len = sprintf(temp, "%.*s,%d,%d,%d", MaxFormatLen,
(char far*)f,a,t,d);
// Check for potential overflow
//
char* str = heap.Data + heap.Used;
heap.Used += len + 1;
if (heap.Used > heap.Size)
return "";
// Copy into real static buffer & return it
//
return strcpy(str, temp);
}
char* TRegItem::RegFlags(long flags, TRegFormatHeap& heap)
{
// sprintf into sized auto buffer
//
char temp[11+1 +8];
int len = sprintf(temp, "%ld", flags);
// Check for potential overflow
//
char* str = heap.Data + heap.Used;
heap.Used += len + 1;
if (heap.Used > heap.Size)
return "";
// Copy into real static buffer & return it
//
return strcpy(str, temp);
}
char* TRegItem::RegVerbOpt(int mf, int sf, TRegFormatHeap& heap)
{
// sprintf into sized auto buffer
//
char temp[11+1+11+1 +8];
int len = sprintf(temp, "%d,%d", mf, sf);
// Check for potential overflow
//
char* str = heap.Data + heap.Used;
heap.Used += len + 1;
if (heap.Used > heap.Size)
return "";
// Copy into real static buffer & return it
//
return strcpy(str, temp);
}
+66
View File
@@ -0,0 +1,66 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// TLocaleString default NLS compare function - used only if non-OLE
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/locale.h>
#if defined(BI_PLAT_WIN32)
TLangId
TLocaleString::GetSystemLangId()
{
return ::GetSystemDefaultLangID();
}
TLangId
TLocaleString::GetUserLangId()
{
return ::GetUserDefaultLangID();
}
int
TLocaleString::CompareLang(const char far* s1, const char far* s2, TLangId lang)
{
typedef int WINAPI (*TCompareStringA)(LCID, DWORD, LPCSTR, int, LPCSTR, int);
static int WINAPI (*compareStringA)(LCID, DWORD, LPCSTR, int, LPCSTR, int) =
(TCompareStringA)::GetProcAddress(::GetModuleHandle("kernel32"), "CompareStringA");
// Use CompareStringA if it is available
//
if (compareStringA)
return compareStringA(lang, NORM_IGNORECASE | NORM_IGNORENONSPACE,
s1,-1, s2,-1) - 2;
// Otherwise just use RTL function
//
return _fstricmp(s1, s2); // only permissible if not an OLE application
}
#else
#include <string.h>
TLangId
TLocaleString::GetSystemLangId()
{
return 0x409; // US English if no OLE or Win32 support
}
TLangId
TLocaleString::GetUserLangId()
{
return 0x409; // US English if no OLE or Win32 support
}
int
TLocaleString::CompareLang(const char far* s1, const char far* s2, TLangId)
{
return _fstricmp(s1, s2); // only permissible if not an OLE application
}
#endif
+11
View File
@@ -0,0 +1,11 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// TLocaleString default native language for symbols, only if not user-defined
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/locale.h>
TLangId TLocaleString::NativeLangId = TLocaleString::GetSystemLangId();
+638
View File
@@ -0,0 +1,638 @@
#--------------------------------------------------------------------------#
# #
# MAKEFILE for Class Libraries #
# #
# Copyright (c) Borland International 1991, 1994 #
# All Rights Reserved #
# #
# Usage: #
# #
# maker options #
# #
# Options: #
# #
# -DDOS, -DWIN32, -DOS2 Specifies target system #
# #
# -DMT Build multi-thread version #
# #
# -DMODEL=x Specifies memory model for DOS library. #
# Required when building DOS library. #
# Must be s, c, m, l, or h. #
# #
# -DNAME=xxx Base name of the target library or DLL #
# Always required. #
# #
# -DSUFFIX=xxx Suffix to add to the base name when #
# building a DLL. For example, -DSUFFIX=d is #
# used when building the DBG DLLs. This puts #
# 'd' into the name of the dll and the name #
# of the import library. #
# #
# -DDLL Build a DLL. #
# #
# -DDBG Build the debugging version of the target. #
# #
# -DOBJECTS Also build the object-based containers #
# #
# -DBIDSFARVTABLE moves class vtables out of dgroup #
# #
# 16-bit non-diagnostic static libraries: #
# make -r -DDOS -DMODEL=s -DNAME=bidss #
# make -r -DDOS -DMODEL=c -DNAME=bidsc #
# make -r -DDOS -DMODEL=m -DNAME=bidsm #
# make -r -DDOS -DMODEL=l -DNAME=bidsl #
# make -r -DDOS -DMODEL=h -DNAME=bidsh #
# #
# 16-bit diagnostic static libraries: #
# make -r -DDOS -DMODEL=s -DDBG -DNAME=bidsdbs #
# make -r -DDOS -DMODEL=c -DDBG -DNAME=bidsdbc #
# make -r -DDOS -DMODEL=m -DDBG -DNAME=bidsdbm #
# make -r -DDOS -DMODEL=l -DDBG -DNAME=bidsdbl #
# make -r -DDOS -DMODEL=h -DDBG -DNAME=bidsdbh #
# #
# 16-bit DLLs: #
# make -r -DDOS -DDLL -DNAME=bids #
# make -r -DDOS -DDLL -DDBG -DNAME=bids -DSUFFIX=d #
# #
# WIN32 libraries: #
# make -r -DWIN32 -DNAME=bidsf #
# make -r -DWIN32 -DDBG -DNAME=bidsdf #
# #
# WIN32 DLLs: #
# make -r -DWIN32 -DDLL -DNAME=bids -DSUFFIX=f #
# make -r -DWIN32 -DDLL -DDBG -DNAME=bids -DSUFFIX=df #
# #
# OS/2 libraries: #
# make -r -DOS2 -DNAME=bids2 #
# make -r -DOS2 -DDBG -DNAME=bidsdb2 #
# #
# OS/2 DLLs: #
# make -r -DOS2 -DDLL -DNAME=bids -DSUFFIX=2 #
# make -r -DOS2 -DDLL -DDBG -DNAME=bids -DSUFFIX=d2 #
# #
#--------------------------------------------------------------------------#
.autodepend
.swap
!if !$d(DOS) && !$d(WIN32) && !$d(OS2)
!error Must specify target system DOS, WIN32, or OS2
!endif
!if $d(DOS) && !($d(MODEL) || $d(DLL))
!error When building DOS libraries, must specify MODEL or DLL
!endif
!if $d(MODEL) && ($d(OS2) || $d(WIN32))
!error When building OS2 or WIN32 libraries, cannot specify MODEL
!endif
!if $d(DLL) && !$d(NAME)
!error Must specify a NAME for a DLL.
!endif
!if $d(DOS) && $d(MT)
!error Cannot build multi-thread library for DOS.
!endif
!if $d(MODEL)
!if $(MODEL)!=s && $(MODEL)!=c && $(MODEL)!=m && $(MODEL)!=l && $(MODEL)!=h
!Error MODEL must be s, c, m, l, or h
!endif
!endif
#--------------------------------------------------------------------#
# #
# Set up the names of the tools to be used. If these macros have #
# already been defined in the environment, use those definitions. #
# #
# BCC is the compiler. #
# MAKE is make. #
# TLIB is the librarian. #
# TLINK is the linker. #
# #
#--------------------------------------------------------------------#
!if !$d(BCC)
!if $d(WIN32)
BCC = bcc32 +turboc.cfg -v- -x
!elif $d(OS2)
BCC = bcc
!else
BCC = bcc -2- -x
!endif
!endif
!if !$d(MAKE)
!if $d(WIN32)
MAKE = maker
!else
MAKE = make
!endif
!endif
!if !$d(TLIB)
!if $d(WIN32)
TLIB = tlib /C
!else
TLIB = tlib /C
!endif
!endif
!if !$d(TLINK)
!if $d(WIN32)
TLINK = tlink32
!else
TLINK = tlink
!endif
!endif
!if !$d(BRCC)
!if $d(WIN32)
BRCC = brcc32 -dWIN32
!else
BRCC = brcc
!endif
!endif
#--------------------------------------------------------------------#
# #
# Set up options for the various tools #
# #
# WFLAG does some magic to produce a library that works for both #
# DOS and Windows. #
# #
# WLFLAG is a variation of WFLAG for the implib objs #
# #
# DFLAG contains the debugging switches that will be passed to the #
# compiler through the .CFG file. #
# #
# LFLAG contains the switches that will be passed to TLIB on the #
# command line. #
# #
# XFLAG handles _RTLDLL, which is passed to the compiler in the #
# .CFG file and determines whether classes are to be exported. #
# It also handle far vtable options when they are enabled. #
# #
# LINKOPTS is the list of options for the linker. #
# #
#--------------------------------------------------------------------#
!if $d(DOS) && $d(DLL)
WFLAG = -WDE -xc
WLFLAG = -Y
!elif $d(DOS) && ($(MODEL) == s || $(MODEL) == c )
WFLAG = -WE
!elif $d(DOS) && ($(MODEL) == m || $(MODEL) == l)
WFLAG = -Y
!endif
!if $d(MT)
!if $d(OS2)
MTFLAG = -sm
!else
MTFLAG = -WM
!endif
!endif
!if $d(DBG)
DFLAG = -v- -D__DEBUG=2 -D__WARN -D__TRACE
LFLAG = /0
!else
DFLAG = -v- -D__DEBUG=0
LFLAG = /0
!endif
!if $d(DLL)
XFLAG = -D_RTLDLL -D_BUILDBIDSDLL
!endif
!if $d(BIDSFARVTABLE)
XFLAG = $(XFLAG) -D_BIDSFARVTABLE #;_RTLFARVTABLE if RTL is rebuilt too
!endif
!if $d(DOS)
!if $d(DLL)
MFLAG = -ml
!else
MFLAG = -m$(MODEL)
!endif
!endif
!if $d(DOS)
LINKOPTS = /C/c/s/Twd/Oc/Oi/Oa/Or
!elif $d(OS2)
LINKOPTS = /c/s/Tod
!elif $d(WIN32)
LINKOPTS = /c/s/Tpd
!endif
!if $d(DLL)
DEFFILE=deffile
!endif
#--------------------------------------------------------------------#
# #
# Build the macros to provide the startup code and library names #
# for building DLLs. #
# #
# STARTUP is the startup code. #
# #
# LINKLIBS is the list of libraries. #
# #
#--------------------------------------------------------------------#
!if !$d(DLL)
TARGETLIB = $(NAME)
!else
VER = 45
!if $d(DLL) && $d(WIN32) && $d(DBG)
TARGETFILE = bds$(VER)$(SUFFIX) # name is too long if we use 'bids'
!else
TARGETFILE = $(NAME)$(VER)$(SUFFIX)
!endif
TARGETLIB = $(NAME)$(SUFFIX)i.lib
!if $d(DOS)
STARTUP = $(LIB)\c0dl.obj
LINKLIBS = $(LIB)\import.lib $(LIB)\crtldll.lib
!elif $d(OS2)
STARTUP = $(LIB)\c02d.obj
!if $d(MT)
LINKLIBS = $(LIB)\c2mti.lib $(LIB)\os2.lib
!else
LINKLIBS = $(LIB)\c2i.lib $(LIB)\os2.lib
!endif
!else
STARTUP = $(LIB)\c0d32.obj
!if $d(MT)
LINKLIBS = $(LIB)\cw32mti.lib $(LIB)\import32.lib
!else
LINKLIBS = $(LIB)\cw32i.lib $(LIB)\import32.lib
!endif
!endif
!endif
#--------------------------------------------------------------------#
# #
# OBJDIRLIST is the list of subdirectories under the OBJ directory #
# #
# This is used by dirs to be sure all the subdirectories are #
# present and by clean to remove all OBJ files #
# #
#--------------------------------------------------------------------#
!if $d(DOS)
OBJDIRLIST = s ds c dc m dm l dl h dh i di
!endif
!if $d(WIN32)
OBJDIRLIST = 32 d32 i32 di32
!endif
!if $d(OS2)
OBJDIRLIST = 2 d2 i2 di2
!endif
#--------------------------------------------------------------------#
# #
# Set up the paths that will be needed later. #
# #
# INCLUDE is the full path to the compiler's include files and #
# to the classlib's include files. If it is not defined in the #
# environment, it is assumed to be under the directory where the #
# compiler was installed in the subdirectory INCLUDE. #
# #
# LIB is the full path to the compiler's libraries. If it is not #
# defined in the environment, it is assumed to be under the #
# directory where the compiler was installed in the subdirectory #
# LIB. #
# #
# SOURCEDIR is the full path to the source code. If it is not #
# defined in the environment, it is assumed to be under the #
# directory where the compiler was installed in the subdirectory #
# SOURCE\CLASSLIB. #
# #
# ROOTDIR is the full path to the directory in which the makefile #
# is located. If it is not defined in the environment, it is #
# assumed to be the same as SOURCEDIR. #
# #
# LIBDIR is the full path to the directory in which the libraries #
# should be placed when they are built. If it is not defined in #
# the environment, it is assumed to be the same as the directory #
# specified by LIB. #
# #
#--------------------------------------------------------------------#
!if !$d(BCROOT)
!if $d(OS2)
BCROOT=$(MAKEDIR)\..
!else
!include $(MAKEDIR)\bcroot.inc
!endif
!endif
!if !$d(INCLUDE)
INCLUDE = $(BCROOT)\include
!endif
!if !$d(RCINCLUDE)
RCINCLUDE = $(BCROOT)\include
!endif
!if !$d(LIB)
LIB = $(BCROOT)\lib
!endif
!if !$d(SOURCEDIR)
SOURCEDIR = $(BCROOT)\source\classlib
!endif
!if !$d(LIBDIR)
LIBDIR = $(LIB)
!endif
!if !$d(ROOTDIR)
ROOTDIR = $(SOURCEDIR)
!endif
#--------------------------------------------------------------------#
# #
# Set up the various paths that MAKE will use #
# #
# OBJDIR will only have been defined when we've decide on a target #
# platform and a set of options. Since .PATH.obj isn't used in any #
# context in which DBG and SUFFIX haven't been defined, it's ok #
# to use DBG and SUFFIX to define it. #
# #
#--------------------------------------------------------------------#
.PATH.cpp = $(SOURCEDIR)
.PATH.cpo = $(SOURCEDIR)\obsolete
.PATH.lib = $(LIBDIR)
.PATH.rc = $(SOURCEDIR)
!if $d(DOS)
OBJDIR=$(MODEL)
!elif $d(OS2)
OBJDIR=2
!else
OBJDIR=32
!endif
!if $d(DLL)
OBJDIR=i$(OBJDIR)
!endif
!if $d(DBG)
.PATH.obj = $(SOURCEDIR)\d$(OBJDIR)
!else
.PATH.obj = $(SOURCEDIR)\$(OBJDIR)
!endif
#--------------------------------------------------------------------#
# #
# Build the various file lists needed for dependency checking, #
# and LIBing. #
# #
# OBJS is the main list, conditionalized for the various targets #
# and options. #
# #
# OBJS_LIB are the objs that only go in libs & implib, not the dll #
# #
# OBJS_DLL are the objs that only go in the dll, not the libs #
# #
# DEPOBJS is the list of object files for dependency checking #
# #
# LIBOBJS is the list of object files for building the library #
# #
#--------------------------------------------------------------------#
!if $d(OBJECTS)
OBJS = \
PFXassoc.obj \
PFXbtree.obj \
PFXbtreeinn.obj \
PFXbtreelfn.obj \
PFXcollect.obj \
PFXcontain.obj \
PFXdbllist.obj \
PFXhashtbl.obj \
PFXldate.obj \
PFXlist.obj \
PFXltime.obj \
PFXobject.obj
!endif
OBJS = $(OBJS) \
PFXbinimp.obj \
PFXcastable.obj \
PFXdate.obj \
PFXdateio.obj \
PFXdatep.obj \
PFXfile.obj \
PFXheapsel.obj \
PFXobjstrm.obj \
PFXtime.obj \
PFXtimep.obj \
PFXtimeio.obj \
PFXversion.obj
!if !$d(OS2)
OBJS = $(OBJS) \
PFXexbase.obj \
PFXgeometry.obj \
PFXgeomstrm.obj \
PFXreglink.obj
!endif
OBJS_LIB = \
PFXlocale.obj \
PFXlocaleco.obj \
PFXlocaleid.obj \
PFXregheap.obj \
PFXustring.obj
OBJS_DLL =
!if $d(DOS) && !$d(DLL)
OBJS = $(OBJS) PFXtimer.obj
!endif
!if $d(WIN32) || $d(OS2)
OBJS = $(OBJS) PFXthread.obj
!endif
!if $d(OBJECTS)
!if $d(TEMPLATES)
OBJS = $(OBJS) \
PFXbabstary.obj \
PFXbdict.obj \
PFXbsortary.obj
!else
OBJS = $(OBJS) \
PFXabstarry.obj \
PFXarray.obj \
PFXdeque.obj \
PFXdict.obj \
PFXsortarry.obj \
PFXstack.obj
!endif
!endif
!if $d(DLL) && $(DOS)
OBJS = $(OBJS) PFXclasmain.obj
!endif
!if $d(DLL) && $d(OBJECTS)
!if $d(TEMPLATES)
OBJS = $(OBJS) PFXtmpl2.obj
!else
OBJS = $(OBJS) PFXtmpl1.obj
!endif
!endif
!if $d(DLL) && !$d(OBJECTS) && !$d(OS2)
RESFILE = version.res
!endif
#PFXOBJS = $(OBJS:SFX=)
#SFXOBJS = $(OBJS:PFX=)
DEPOBJS = $(OBJS:PFX=) $(OBJS_LIB:PFX=) $(OBJS_DLL:PFX=)
!if $d(DLL)
LIBOBJS = $(OBJS_LIB:PFX=+)
LINKOBJS = $(OBJS:PFX=) $(OBJS_DLL:PFX=)
!else
LIBOBJS = $(OBJS:PFX=-+) $(OBJS_LIB:PFX=-+)
!endif
#--------------------------------------------------------------------#
# #
# These are the targets that we can make. #
# #
# target: builds the target file #
# #
# dirs: makes sure all the necessary subdirectories are present #
# #
# clean: deletes the .OBJ files #
# #
# config: builds a .CFG file with the correct flags #
# #
#--------------------------------------------------------------------#
target: config $(DEFFILE) $(DEPOBJS) $(RESFILE)
!if !$d(DLL)
cd $(.PATH.obj)
$(TLIB) $(LFLAG) $(.PATH.lib)\$(TARGETLIB) @&&!
$(LIBOBJS)
!
cd $(ROOTDIR)
!else
cd $(.PATH.obj)
$(TLINK) @&&!
$(STARTUP)+
$(LINKOBJS)
$(TARGETFILE).dll
$(LINKOPTS) $(.PATH.lib)\$(TARGETFILE).map
$(LINKLIBS)
temp.def
$(RESFILE)
!
!if $(TARGET) == DOS
rc -30 $(TARGETFILE)
!endif
implib $(TARGETLIB) $(TARGETFILE).dll
tlib $(LFLAG) $(TARGETLIB) @&&|
$(LIBOBJS)
|
cd $(ROOTDIR)
copy $(.PATH.obj)\$(TARGETFILE).dll $(.PATH.lib)
del $(.PATH.obj)\$(TARGETFILE).dll
copy $(.PATH.obj)\$(TARGETLIB) $(.PATH.lib)
del $(.PATH.obj)\$(TARGETLIB)
!endif
dirs:
-for %d in ($(OBJDIRLIST)) do md $(SOURCEDIR)\%d
clean:
-for %d in ($(OBJDIRLIST)) do del $(SOURCEDIR)\%d\*.obj
config:
@-if not exist $(.PATH.obj)\..\NUL md $(.PATH.obj)\..
@-if not exist $(.PATH.obj)\NUL md $(.PATH.obj)
@type &&!
-c -n$(.PATH.obj) -I$(INCLUDE) $(DFLAG) $(XFLAG) $(MFLAG) $(TFLAG)
! >turboc.cfg
deffile:
!if $d(DOS)
@echo >$(.PATH.obj)\temp.def LIBRARY $(TARGETFILE)
!else
@echo >$(.PATH.obj)\temp.def LIBRARY $(TARGETFILE) INITINSTANCE
!endif
@echo >>$(.PATH.obj)\temp.def DESCRIPTION 'Parametrized Class Library for BC++'
!if $d(DOS)
@echo >>$(.PATH.obj)\temp.def EXETYPE WINDOWS
@echo >>$(.PATH.obj)\temp.def CODE PRELOAD MOVEABLE DISCARDABLE
@echo >>$(.PATH.obj)\temp.def DATA PRELOAD MOVEABLE SINGLE
!else
@echo >>$(.PATH.obj)\temp.def DATA MULTIPLE NONSHARED
!endif
@echo >>$(.PATH.obj)\temp.def HEAPSIZE 4096
#--------------------------------------------------------------------#
# #
# We need an implicit rule for building .OBJ files, and a few #
# explicit rules for special cases. #
# #
# TIMER.OBJ is never built for windows, so doesn't need the #
# windows flags. #
# #
#--------------------------------------------------------------------#
timer.obj: timer.cpp
$(BCC) $(SOURCEDIR)\timer
tmpl1.obj: tmplinst.cpp
$(BCC) -o$(.PATH.obj)\tmpl1.obj $(WFLAG) $(.PATH.cpp)\tmplinst
tmpl2.obj: tmplinst.cpp
$(BCC) -o$(.PATH.obj)\tmpl2.obj -DTEMPLATES $(WFLAG) $(.PATH.cpp)\tmplinst
.cpo.obj:
$(BCC) $(WFLAG) -P {$< }
.cpp.obj:
$(BCC) $(WFLAG) $(MTFLAG) {$* }
.rc.res:
$(BRCC) -i$(RCINCLUDE) $*.rc
copy $*.res $(.PATH.obj)
del $*.res
!if $d(DOS) && $d(DLL)
$(OBJS_LIB:PFX=):
$(BCC) $(WLFLAG) $(MTFLAG) -D_BIDSDLL -U_BUILDBIDSDLL $(.PATH.cpp)\$&.cpp
!endif
+1
View File
@@ -0,0 +1 @@
/* not needed for version 4.00 */
+786
View File
@@ -0,0 +1,786 @@
/*------------------------------------------------------------------------*/
/* */
/* OBJSTRM.CPP */
/* */
/* Copyright (c) 1992, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( _Windows )
#define _Windows
#endif
#if !defined( __ALLOC_H )
#include <alloc.h>
#endif
#if !defined( __CHECKS_H )
#include <checks.h>
#endif
#if !defined( __CSTRING_H )
#include <cstring.h>
#endif
#if !defined( CLASSLIB_STREAMBL_H )
#include <classlib/streambl.h>
#endif
#if !defined( CLASSLIB_OBJSTRM_H )
#include <classlib/objstrm.h>
#endif
#if defined( __FLAT__ )
#define _fstrncpy strncpy
#define _fstrcpy strcpy
#define _fstrlen strlen
#define _fmemcpy memcpy
#define farmalloc malloc
#endif
DIAG_DEFINE_GROUP(Objstrm,1,0);
const uint32 streamVersion = 0x0101;
const char versionIndicator = ':';
const char EOS = '\0';
const uint8 oldNullStringLen = UCHAR_MAX;
const uint32 nullStringLen = ULONG_MAX;
TStreamableTypes *pstream::types = 0;
const char *TStreamer::StreamableName() const
{
return 0;
}
TStreamableClass::TStreamableClass( const char *n,
BUILDER b,
int d,
ModuleId id ) :
ObjectBuilder( b, d ),
ModId(id)
{
ObjectId = new char[strlen(n)+1];
strcpy( CONST_CAST(char *,ObjectId), n );
pstream::initTypes();
if( id != 0 ) // id == 0 is used only during lookup.
// It flags an instance that shouldn't be registered
pstream::types->RegisterType( id, *this );
}
TStreamableClass::~TStreamableClass()
{
if( ModId != 0 )
pstream::types->UnRegisterType( ModId, *this );
delete [] CONST_CAST(char *,ObjectId);
}
void TStreamableTypes::RegisterType( ModuleId, TStreamableClass& ts )
{
Types.Add(&ts);
}
void TStreamableTypes::UnRegisterType( ModuleId, TStreamableClass& ts )
{
Types.Detach(&ts);
if( Types.Count() == 0 )
pstream::releaseTypes();
}
const ObjectBuilder *TStreamableTypes::Lookup( ModuleId,
const char *name ) const
{
unsigned loc = Types.Find(&TStreamableClass(name,0,0,0));
if( loc == UINT_MAX )
{
string msg;
msg.reserve(128);
msg = "Attempt to stream unregistered type '";
msg += name;
msg += "'";
throw xmsg(msg);
}
return Types[loc];
}
void TPReadObjects::RemoveAll()
{
Data.Flush();
}
void TPReadObjects::RegisterObject( TStreamableBase *adr )
{
Data.Add( adr );
}
TStreamableBase *TPReadObjects::Find( P_id_type id )
{
return Data[id];
}
TPReadObjects::TPReadObjects() : Data(5,5)
{
Data.Add(0); // prime it: 0 is not a legal index.
}
TPWrittenObjects::TPWrittenObjects() : CurId(0), Data(5,5)
{
}
void TPWrittenObjects::RemoveAll()
{
CurId = 0; Data.Flush();
}
void TPWrittenObjects::RegisterObject( TStreamableBase *adr )
{
Data.Add( TPWObj( ((char *)(void *)adr)+1, ++CurId ) );
}
void TPWrittenObjects::RegisterVB( const TStreamableBase *adr )
{
Data.Add( TPWObj( adr, ++CurId ) );
}
P_id_type TPWrittenObjects::FindObject( TStreamableBase *d )
{
unsigned res = Data.Find( TPWObj(((char *)(void *)d)+1,0) );
if( res == UINT_MAX )
return 0;
else
return Data[res].Ident;
}
P_id_type TPWrittenObjects::FindVB( TStreamableBase *d )
{
unsigned res = Data.Find( TPWObj(d,0) );
if( res == UINT_MAX )
return 0;
else
return Data[res].Ident;
}
pstream::~pstream()
{
}
void pstream::initTypes()
{
if( types == 0 )
types = new TStreamableTypes;
}
void pstream::releaseTypes()
{
delete types;
types = 0;
}
streampos ipstream::tellg()
{
streampos res;
if( !good() )
res = streampos(EOF);
else
{
res = bp->seekoff( 0, ios::cur, ios::in );
if( res == streampos(EOF) )
clear( ios::failbit );
}
return res;
}
ipstream& ipstream::seekg( streampos pos )
{
if( good() )
{
objs.RemoveAll();
if( bp->seekoff( pos, ios::beg, ios::in ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
ipstream& ipstream::seekg( streamoff off, ios::seek_dir dir )
{
if( good() )
{
objs.RemoveAll();
if( bp->seekoff( off, dir, ios::in ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
uint8 ipstream::readByte()
{
int res;
if( !good() )
res = uint8(0);
else
{
res = bp->sbumpc();
if( res == EOF )
clear( ios::failbit );
}
return uint8(res);
}
void ipstream::readBytes( void *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
if( bp->sgetn( (char *)data, sz ) != sz )
clear( ios::failbit );
}
}
void ipstream::freadBytes( void _BIDSFARDATA *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
char *buf = new char[sz];
if( bp->sgetn( buf, sz ) != sz )
clear( ios::failbit );
else
_fmemcpy( data, buf, sz);
delete [] buf;
}
}
uint32 ipstream::readWord()
{
if( getVersion() > 0 )
return readWord32();
else
return readWord16();
}
uint16 ipstream::readWord16()
{
if( !good() )
return 0;
else
{
uint16 temp;
if( bp->sgetn( (char *)&temp, sizeof( temp ) ) != sizeof( temp ) )
clear( ios::failbit );
return temp;
}
}
uint32 ipstream::readWord32()
{
if( !good() )
return 0;
else
{
uint32 temp;
if( bp->sgetn( (char *)&temp, sizeof( temp ) ) != sizeof( temp ) )
clear( ios::failbit );
return temp;
}
}
uint32 ipstream::readStringLength()
{
uint32 len;
if( getVersion() > 0x0100 )
{
len = readWord32();
}
else
{
len = readByte();
if( len == oldNullStringLen )
len = nullStringLen;
}
return len;
}
char *ipstream::readString()
{
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen )
return 0;
char *buf = new char[len+1];
if( buf == 0 )
return 0;
readBytes( buf, len );
buf[len] = EOS;
return buf;
}
}
char *ipstream::readString( char *buf, unsigned maxLen )
{
PRECONDITION( buf != 0 );
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen || len > maxLen-1 )
return 0;
readBytes( buf, len );
buf[len] = EOS;
return buf;
}
}
char _BIDSFARDATA *ipstream::freadString()
{
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen )
return 0;
char _BIDSFARDATA *buf = new _BIDSFARDATA char[len+1];
freadBytes(buf, len);
buf[len] = EOS;
return buf;
}
}
char _BIDSFARDATA *ipstream::freadString( char _BIDSFARDATA *buf, unsigned maxLen )
{
PRECONDITION(buf != 0 );
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen || len > maxLen-1 )
return 0;
freadBytes( buf, len);
buf[len] = EOS;
return buf;
}
}
void ipstream::readVersion()
{
if( !good() )
version = 0;
else
{
int res = bp->sgetc();
if( res == EOF )
{
clear( ios::eofbit );
version = 0;
return;
}
if( res != versionIndicator )
version = 0;
else
{
bp->sbumpc();
version = readWord32();
}
}
}
TStreamableBase _FAR *ipstream::readObject( TStreamableBase _FAR *&mem,
ModuleId mid )
{
if( good() )
{
const ObjectBuilder *pc = readPrefix( mid );
if( pc == 0 )
mem = 0;
else
{
readData( pc, mem );
readSuffix();
}
}
return mem;
}
const ObjectBuilder *ipstream::readPrefix( ModuleId mid )
{
char ch = readByte();
if( ch != '[' )
{
clear( ios::failbit );
return 0;
}
char name[128];
name[0] = EOS;
readString( name, sizeof name );
if( name[0] == EOS )
{
clear( ios::failbit );
return 0;
}
TRACEX(Objstrm,0,"Reading " << name);
const ObjectBuilder *res = types->Lookup( mid, name );
WARNX(Objstrm,res==0,0,"Unrecognized class identifier: " << name);
if( res == 0 )
{
clear( ios::failbit );
return 0;
}
return res;
}
void ipstream::readData( const ObjectBuilder *c, TStreamableBase _FAR *&mem )
{
TStreamer *strmr = c->Builder(mem);
mem = strmr->GetObject();
// register the address
registerObject( mem );
uint32 classVer = 0;
if( getVersion() > 0 )
classVer = readWord32();
strmr->Read( *this, classVer );
delete strmr;
}
void ipstream::readSuffix()
{
if( !good() )
return;
char ch = readByte();
if( ch != ']' )
clear( ios::failbit );
}
TStreamableBase _FAR *ipstream::readObjectPointer( TStreamableBase _FAR *&mem,
ModuleId mid )
{
if( !good() )
return 0;
char ch = readByte();
switch( ch )
{
case pstream::ptNull:
mem = 0;
break;
case pstream::ptIndexed:
{
P_id_type index = P_id_type(readWord());
mem = find( index );
CHECK( mem != 0 );
break;
}
case pstream::ptObject:
{
const ObjectBuilder *pc = readPrefix( mid );
readData( pc, mem );
readSuffix();
break;
}
default:
clear( ios::failbit );
break;
}
return mem;
}
opstream::opstream()
{
objs = new TPWrittenObjects;
if( bp != 0 )
writeVersion();
}
opstream::opstream( streambuf * sb )
{
objs = new TPWrittenObjects;
pstream::init( sb );
writeVersion();
}
streampos opstream::tellp()
{
streampos res;
if( !good() )
res = streampos(EOF);
else
{
res = bp->seekoff( 0, ios::cur, ios::out );
if( res == streampos(EOF) )
clear( ios::failbit );
}
return res;
}
opstream& opstream::seekp( streampos pos )
{
if( good() )
{
objs->RemoveAll();
if( bp->seekoff( pos, ios::beg, ios::out ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
opstream& opstream::seekp( streamoff pos, ios::seek_dir dir )
{
if( good() )
{
objs->RemoveAll();
if( bp->seekoff( pos, dir, ios::out ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
void opstream::writeVersion()
{
if( good() )
{
writeByte( versionIndicator );
writeWord32( streamVersion );
}
}
opstream& opstream::flush()
{
if( bp->sync() == EOF )
clear( ios::badbit );
return *this;
}
void opstream::writeByte( uint8 ch )
{
if( good() )
{
if( bp->sputc( ch ) == EOF )
clear( ios::failbit );
}
}
void opstream::writeBytes( const void *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
if( bp->sputn( (char *)data, sz ) != sz )
clear( ios::failbit );
}
}
void opstream::writeWord16( uint16 word16 )
{
if( good() )
{
if( bp->sputn( (char *)&word16, sizeof(word16) ) != sizeof(word16) )
clear( ios::failbit );
}
}
void opstream::writeWord32( uint32 word32 )
{
if( good() )
{
if( bp->sputn( (char *)&word32, sizeof(word32) ) != sizeof(word32) )
clear( ios::failbit );
}
}
void opstream::fwriteBytes( const void _BIDSFARDATA *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
char *buf = new char[sz];
_fmemcpy( buf, data, sz );
if( bp->sputn( (char *)buf, sz ) != sz )
clear( ios::failbit );
delete buf;
}
}
void opstream::writeString( const char *str )
{
if( !good() )
return;
if( str == 0 )
{
writeWord32( nullStringLen );
return;
}
size_t len = strlen( str );
writeWord32( len );
writeBytes( str, len );
}
void opstream::fwriteString( const char _BIDSFARDATA * str )
{
if( !good() )
return;
if( str == 0 )
{
writeWord32( nullStringLen );
return;
}
size_t len = _fstrlen( str );
writeWord32( len );
fwriteBytes(str, len);
}
#pragma warn -par
void opstream::writeObject( const TStreamableBase _FAR *mem, int isPtr, ModuleId mid )
{
WARNX(Objstrm,
!isPtr && findObject( CONST_CAST(TStreamableBase *,mem) ),
0,
"Pointer written before object: " \
<< _TYPENAME(mem) << '(' << (void _FAR *)mem << ')' );
if( good() )
{
writePrefix( mem );
writeData( mem, mid );
writeSuffix( mem );
}
}
#pragma warn +par
void opstream::writeObjectPointer( const TStreamableBase *t, ModuleId mid )
{
if( good() )
{
P_id_type index;
if( t == 0 )
writeByte( pstream::ptNull );
else if( (index = findObject( CONST_CAST(TStreamableBase *,t) )) != 0 )
{
writeByte( pstream::ptIndexed );
writeWord( index );
}
else
{
writeByte( pstream::ptObject );
writeObject( t, 1, mid );
}
}
}
void opstream::writePrefix( const TStreamableBase *t )
{
if( good() )
{
writeByte( '[' );
writeString( _TYPENAME(t) );
}
}
void opstream::writeData( const TStreamableBase *t, ModuleId mid )
{
if( good() )
{
registerObject( CONST_CAST(TStreamableBase *,t) );
const ObjectBuilder *res = types->Lookup( mid, _TYPENAME(t) );
CHECKX(res,_TYPENAME(t));
TStreamer *strmr = res->Builder(CONST_CAST(TStreamableBase *,t));
writeWord32( strmr->ClassVersion() );
strmr->Write( *this );
delete strmr;
}
}
void fpbase::open( const char *b, int m, int prot )
{
if( buf.is_open() )
clear(ios::failbit); // fail - already open
else if( buf.open(b, m, prot) )
clear(ios::goodbit); // successful open
else
clear(ios::badbit); // open failed
}
void fpbase::attach( int f )
{
if( buf.is_open() )
clear(ios::failbit);
else if( buf.attach(f) )
clear(ios::goodbit);
else
clear(ios::badbit);
}
void fpbase::close()
{
if( buf.close() )
clear(ios::goodbit);
else
clear(ios::failbit);
}
void fpbase::setbuf(char* b, int len)
{
if( buf.setbuf(b, len) )
clear(ios::goodbit);
else
clear(ios::failbit);
}
//
// These operators are not friends of string, so
// they must use only the public interface.
//
opstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator << ( opstream _BIDSFAR& os,
const string _BIDSFAR& str )
{
os.writeString( str.c_str() );
return os;
}
ipstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator >> ( ipstream _BIDSFAR& is,
string _BIDSFAR& str )
{
if( is.good() )
{
uint32 len = is.readStringLength();
if( len == nullStringLen )
str = "";
else
{
char *temp = new char[len+1];
is.readBytes( temp, len );
temp[len] = EOS;
str = temp;
delete [] temp;
}
}
return is;
}
@@ -0,0 +1,272 @@
/*------------------------------------------------------------------------*/
/* */
/* ABSTARRY.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __MEM_H )
#include <mem.h>
#endif // __MEM_H
#if !defined( __CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __ABSTARRY_H )
#include "classlib\obsolete\abstarry.h"
#endif // __ABSTARRY_H
AbstractArray::AbstractArray( int anUpper, int aLower, sizeType aDelta )
{
PRECONDITION( anUpper >= aLower );
lastElementIndex = aLower - 1;
lowerbound = aLower;
upperbound = anUpper;
delta = aDelta;
theArray = new Object *[ arraySize() ];
if( theArray == 0 )
ClassLib_error(__ENOMEM);
for( int i = 0; i < arraySize(); i++ )
{
theArray[ i ] = ZERO;
}
}
AbstractArray::~AbstractArray()
{
PRECONDITION( theArray != 0 );
if( ownsElements() )
for( int i = 0; i < arraySize(); i++ )
if( theArray[ i ] != ZERO )
delete theArray[ i ];
delete [] theArray;
}
void AbstractArray::detach( Object& toDetach, DeleteType dt )
{
detach( find( toDetach ), dt );
}
void AbstractArray::detach( int atIndex, DeleteType dt )
{
PRECONDITION( atIndex >= lowerbound &&
atIndex <= upperbound && theArray != 0
);
if( ptrAt(atIndex) != ZERO )
{
if( delObj(dt) )
delete ptrAt(atIndex);
itemsInContainer--;
}
removeEntry(atIndex);
if( atIndex <= lastElementIndex )
lastElementIndex--;
CHECK( itemsInContainer != UINT_MAX );
}
void AbstractArray::flush( DeleteType dt )
{
if( delObj(dt) )
for( unsigned i = 0; i <= zeroBase(upperbound); i++ )
if( theArray[i] != ZERO )
delete theArray[i];
for( unsigned i = 0; i <= zeroBase(upperbound); i++ )
theArray[i] = ZERO;
itemsInContainer = 0;
lastElementIndex = lowerbound-1;
}
inline unsigned nextDelta( unsigned sz, unsigned delta )
{
return (sz%delta) ? ((sz+delta)/delta)*delta : sz;
}
void AbstractArray::reallocate( sizeType newSize )
{
PRECONDITION( newSize > arraySize() );
if( delta == 0 )
ClassLib_error(__EEXPANDFS);
sizeType adjustedSize = arraySize() +
nextDelta( newSize - arraySize(), delta );
Object **newArray = new Object *[ adjustedSize ];
if( newArray == 0 )
ClassLib_error(__ENOMEM);
memcpy( newArray, theArray, arraySize() * sizeof( theArray[0] ) );
for( int i = arraySize(); i < adjustedSize; i++ )
newArray[i] = ZERO;
delete [] theArray;
theArray = newArray;
upperbound = adjustedSize + lowerbound - 1;
}
void AbstractArray::setData( int loc, Object *data )
{
PRECONDITION( loc >= lowerbound && loc <= upperbound );
theArray[ zeroBase(loc) ] = data;
}
void AbstractArray::insertEntry( int loc )
{
PRECONDITION( loc >= lowerbound && loc <= upperbound );
memmove( theArray + zeroBase(loc) + 1,
theArray + zeroBase(loc),
(upperbound - loc)*sizeof( theArray[0] )
);
}
void AbstractArray::removeEntry( int loc )
{
if( loc >= lastElementIndex )
theArray[zeroBase(loc)] = ZERO;
else
squeezeEntry( zeroBase(loc) );
}
void AbstractArray::squeezeEntry( int squeezePoint )
{
PRECONDITION( squeezePoint >= 0 &&
squeezePoint <= zeroBase(lastElementIndex)
);
memmove( theArray + squeezePoint,
theArray + squeezePoint + 1,
(zeroBase(lastElementIndex)-squeezePoint)*sizeof( theArray[0] )
);
theArray[zeroBase(lastElementIndex)] = ZERO;
}
int AbstractArray::find( const Object& o )
{
if( o == NOOBJECT )
return INT_MIN;
for( int index = 0; index < arraySize(); index++ )
if( *(theArray[index]) == o )
return boundBase(index);
return INT_MIN;
}
inline int isZero( const Object *o )
{
return o == &NOOBJECT;
}
int AbstractArray::isEqual( const Object& testObject ) const
{
PRECONDITION( isA() == testObject.isA() );
AbstractArray& test = (AbstractArray&)testObject;
if( lowerbound != test.lowerbound || upperbound != test.upperbound )
return 0;
for( int i = 0; i < arraySize(); i++ )
{
if( isZero(theArray[i]) != isZero(test.theArray[i]) )
return 0;
if( *(theArray[i]) != *(test.theArray[i]) )
return 0;
}
return 1;
}
ContainerIterator& AbstractArray::initIterator() const
{
return *( (ContainerIterator *)new ArrayIterator( *this ) );
}
void AbstractArray::printContentsOn( ostream& outputStream ) const
{
ContainerIterator& printIterator = initIterator();
printHeader( outputStream );
while( printIterator != 0 )
{
Object& arrayObject = printIterator++;
if( arrayObject != NOOBJECT )
{
arrayObject.printOn( outputStream );
if( printIterator != 0 )
printSeparator( outputStream );
else
break;
}
}
printTrailer( outputStream );
delete &printIterator;
}
ArrayIterator::ArrayIterator( const AbstractArray& toIterate ) :
beingIterated( toIterate ),
currentIndex( toIterate.lowerbound )
{
restart();
}
ArrayIterator::~ArrayIterator()
{
}
ArrayIterator::operator int()
{
return currentIndex <= beingIterated.upperbound;
}
Object& ArrayIterator::current()
{
if ( currentIndex <= beingIterated.upperbound )
return beingIterated.objectAt( currentIndex );
else
return NOOBJECT;
}
void ArrayIterator::scan()
{
if( currentIndex > beingIterated.upperbound )
return;
while( ++currentIndex <= beingIterated.upperbound &&
beingIterated.objectAt( currentIndex ) == NOOBJECT )
; // empty body
}
void ArrayIterator::restart()
{
currentIndex = beingIterated.lowerbound;
if( beingIterated.objectAt( currentIndex ) == NOOBJECT )
scan();
}
Object& ArrayIterator::operator ++ ( int )
{
Object& res = (currentIndex <= beingIterated.upperbound) ?
beingIterated.objectAt( currentIndex ) : NOOBJECT;
scan();
return res;
}
Object& ArrayIterator::operator ++ ()
{
scan();
return (currentIndex <= beingIterated.upperbound) ?
beingIterated.objectAt( currentIndex ) : NOOBJECT;
}
@@ -0,0 +1,50 @@
/*------------------------------------------------------------------------*/
/* */
/* ARRAY.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __ARRAY_H )
#include "classlib\obsolete\array.h"
#endif // __ARRAY_H
void Array::add( Object& toAdd )
{
lastElementIndex++;
while( lastElementIndex <= upperbound &&
ptrAt( lastElementIndex ) != ZERO
)
lastElementIndex++;
if( lastElementIndex > upperbound )
reallocate( lastElementIndex - lowerbound + 1 );
setData( lastElementIndex, &toAdd );
itemsInContainer++;
CHECK( itemsInContainer > 0 );
}
void Array::addAt( Object& toAdd, int atIndex )
{
PRECONDITION( atIndex >= lowerbound );
if( atIndex > upperbound )
reallocate( atIndex - lowerbound + 1 );
if( ptrAt( atIndex ) != ZERO )
{
if( ownsElements() )
delete ptrAt( atIndex );
itemsInContainer--;
}
setData( atIndex, &toAdd );
itemsInContainer++;
CHECK( itemsInContainer > 0 );
}
@@ -0,0 +1,45 @@
/*------------------------------------------------------------------------*/
/* */
/* ASSOC.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __ASSOC_H )
#include "classlib\obsolete\assoc.h"
#endif // __ASSOC_H
Association::~Association()
{
if( !ownsElements() )
return;
if( &aKey != ZERO )
delete &aKey;
if( &aValue != ZERO )
delete &aValue;
}
void Association::printOn( ostream& outputStream ) const
{
outputStream << " " << nameOf() << " { ";
aKey.printOn( outputStream );
outputStream << ", ";
aValue.printOn( outputStream );
outputStream << " }\n";
}
int Association::isEqual( const Object& toObject ) const
{
return aKey == ( (Association&)toObject ).key();
}
@@ -0,0 +1,87 @@
/*------------------------------------------------------------------------*/
/* */
/* BABSTARY.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( TEMPLATES )
#define TEMPLATES
#endif
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __MEM_H )
#include <mem.h>
#endif // __MEM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __ABSTARRY_H )
#include "classlib\obsolete\abstarry.h"
#endif // __ABSTARRY_H
inline int isZero( const Object& o )
{
return o == NOOBJECT;
}
int AbstractArray::isEqual( const Object& obj ) const
{
PRECONDITION( isA() == obj.isA() );
AbstractArray& test = (AbstractArray&)obj;
if( lowerBound() != test.lowerBound() ||
upperBound() != test.upperBound()
)
return 0;
ContainerIterator& iter1 = initIterator();
ContainerIterator& iter2 = test.initIterator();
while( iter1 && iter2 )
if( iter1.current() != iter2.current() )
{
delete &iter1;
delete &iter2;
return 0;
}
else
{
iter1++;
iter2++;
}
delete &iter1;
delete &iter2;
return 1;
}
void AbstractArray::printContentsOn( ostream& outputStream ) const
{
ContainerIterator& printIterator = initIterator();
printHeader( outputStream );
while( printIterator != 0 )
{
Object& arrayObject = printIterator++;
if( arrayObject != NOOBJECT )
{
arrayObject.printOn( outputStream );
if( printIterator != 0 )
printSeparator( outputStream );
else
break;
}
}
printTrailer( outputStream );
delete &printIterator;
}
@@ -0,0 +1,46 @@
/*------------------------------------------------------------------------*/
/* */
/* BDICT.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( TEMPLATES )
#define TEMPLATES
#endif
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __ASSOC_H )
#include "classlib\obsolete\assoc.h"
#endif // __ASSOC_H
#if !defined( __DICT_H )
#include "classlib\obsolete\dict.h"
#endif // __DICT_H
#if !defined( __CLSTYPES_H )
#include "classlib\obsolete\clstypes.h"
#endif // __CLSTYPES_H
void Dictionary::add( Object& objectToAdd )
{
if( !objectToAdd.isAssociation() )
ClassLib_error( __ENOTASSOC );
else
Set::add( objectToAdd );
}
Association& Dictionary::lookup( const Object& toLookUp ) const
{
Association toFind( (Object&)toLookUp, NOOBJECT );
toFind.ownsElements(0);
Association& found = (Association&)findMember( toFind );
return found;
}
@@ -0,0 +1,65 @@
/*------------------------------------------------------------------------*/
/* */
/* BSORTARY.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( TEMPLATES )
#define TEMPLATES
#endif
#if 0
#if !defined( __SORTABLE_H )
#include "classlib\obsolete\sortable.h"
#endif // __SORTABLE_H
#if !defined( __ARRAYS_H )
#include "classlib\arrays.h"
#endif // __ARRAYS_H
void BI_ISObjectVector::add( Object _FAR *o )
{
if( count_ >= lim )
resize( count_+1 );
unsigned loc = count_++;
while( loc > 0 && *(Sortable _FAR *)o < *(Sortable _FAR *)(void _FAR *)(data[loc-1]) )
{
data[loc] = data[loc-1];
loc--;
}
data[loc] = o;
}
unsigned BI_ISObjectVector::find( void _FAR * obj ) const
{
unsigned lower = 0;
unsigned upper = count_-1;
if( count_ != 0 )
{
while( lower < upper && upper != UINT_MAX )
{
unsigned middle = (lower+upper)/2;
if( *(const Sortable _FAR *)(void _FAR *)(data[middle]) ==
*(const Sortable _FAR *)obj
)
return middle;
if( *(const Sortable _FAR *)(const void _FAR *)(data[middle]) <
*(const Sortable _FAR *)obj
)
lower = middle+1;
else
upper = middle-1;
}
}
if( lower == upper &&
*(const Sortable _FAR *)(const void _FAR *)(data[lower]) == *(const Sortable _FAR *)obj
)
return lower;
else
return UINT_MAX;
}
#endif
@@ -0,0 +1,496 @@
/*------------------------------------------------------------------------*/
/* */
/* BTREE.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __BTREE_H )
#include "classlib\obsolete\btree.h"
#endif // __BTREE_H
/*
Implementation notes:
This implements B-trees with several refinements. Most of them can be found
in Knuth Vol 3, but some were developed to adapt to restrictions imposed
by C++. First, a restatement of Knuth's properties that a B-tree must
satisfy, assuming we make the enhancement he suggests in the paragraph
at the bottom of page 476. Instead of storing null pointers to non-existent
nodes (which Knuth calls the leaves) we utilize the space to store keys.
Therefore, what Knuth calls level (l-1) is the bottom of our tree, and
we call the nodes at this level LeafNodes. Other nodes are called InnerNodes.
The other enhancement we have adopted is in the paragraph at the bottom of
page 477: overflow control.
The following are modifications of Knuth's properties on page 478:
i) Every InnerNode has at most Order keys, and at most Order+1 sub-trees.
ii) Every LeafNode has at most 2*(Order+1) keys.
iii)An InnerNode with k keys has k+1 sub-trees.
iv) Every InnerNode that is not the root has at least InnerLowWaterMark keys.
v) Every LeafNode that is not the root has at least LeafLowWaterMark keys.
vi) If the root is a LeafNode, it has at least one key.
vii)If the root is an InnerNode, it has at least one key and two sub-trees.
viii)All LeafNodes are the same distance from the root as all the other
LeafNodes.
ix) For InnerNode n with key n[i].key, then sub-tree n[i-1].tree contains
all keys <= n[i].key, and sub-tree n[i].tree contains all keys >= n[i].key.
x) Order is at least 3.
The values of InnerLowWaterMark and LeafLowWaterMark may actually be set
by the user when the tree is initialized, but currently they are set
automatically to:
InnerLowWaterMark = ceiling(Order/2)
LeafLowWaterMark = Order - 1
If the tree is only filled, then all the nodes will be at least 2/3 full.
They will almost all be exactly 2/3 full if the elements are added to the
tree in order (either increasing or decreasing). [Knuth says McCreight's
experiments showed almost 100% memory utilization. I don't see how that
can be given the algorithms that Knuth gives. McCreight must have used
a different scheme for balancing. [ No, he used a different scheme for
splitting: he did a two-way split instead of the three way split as we do
here. Which means that McCreight does better on insertion of ordered data,
but we should do better on insertion of random data.]]
It must also be noted that B-trees were designed for DISK access algorithms,
not necessarily in-memory sorting, as we intend it to be used here. However,
if the order is kept small (< 6?) any inefficiency is negligible for
in-memory sorting. Knuth points out that balanced trees are actually
preferable for memory sorting. I'm not sure that I believe this, but
it's interesting. Also, deleting elements from balanced binary trees, being
beyond the scope of Knuth's book (p. 465), is beyond my scope. B-trees
are good enough.
A B-tree is declared to be of a certain ORDER (4 by default). This number
determines the number of keys contained in any interior node of the tree.
Each interior node will contain ORDER keys, and therefore ORDER+1 pointers
to sub-trees. The keys are numbered and indexed 1 to ORDER while the
pointers are numbered and indexed 0 to ORDER. The 0th ptr points to the
sub-tree of all elements that are less than key[1]. Ptr[1] points to the
sub-tree that contains all the elements greater than key[1] and less than
key[2]. etc. The array of pointers and keys is allocated as ORDER+1
pairs of keys and nodes, meaning that one key field (key[0]) is not used
and therefore wasted. Given that the number of interior nodes is
small, that this waste allows fewer cases of special code, and that it
is useful in certain of the methods, it was felt to be a worthwhile waste.
The size of the exterior nodes (leaf nodes) does not need to be related to
the size of the interior nodes at all. Since leaf nodes contain only
keys, they may be as large or small as we like independent of the size
of the interior nodes. For no particular reason other than it seems like
a good idea, we will allocate 2*(ORDER+1) keys in each leaf node, and they
will be numbered and indexed from 0 to 2*ORDER+1. It does have the advantage
of keeping the size of the leaf and interior arrays the same, so that if we
find allocation and de-allocation of these arrays expensive, we can modify
their allocation to use a garbage ring, or something.
Both of these numbers will be run-time constants associated with each tree
(each tree at run-time can be of a different order). The variable `order'
is the order of the tree, and the inclusive upper limit on the indices of
the keys in the interior nodes. The variable `order2' is the inclusive
upper limit on the indices of the leaf nodes, and is designed
(1) to keep the sizes of the two kinds of nodes the same;
(2) to keep the expressions involving the arrays of keys looking
somewhat the same: lower limit upper limit
for inner nodes: 1 order
for leaf nodes: 0 order2
Remember that index 0 of the inner nodes is special.
Currently, order2 = 2*(order+1).
picture: (also see Knuth Vol 3 pg 478)
+--+--+--+--+--+--...
| | | | | |
parent--->| | | |
| | | |
+*-+*-+*-+--+--+--...
| | |
+----+ | +-----+
| +-----+ |
V | V
+----------+ | +----------+
| | | | |
this->| | | | |<--sib
+----------+ | +----------+
V
data
It is conceptually VERY convenient to think of the data as being the
very first element of the sib node. Any primitive that tells sib to
perform some action on n nodes should include this `hidden' element.
For InnerNodes, the hidden element has (physical) index 0 in the array,
and in LeafNodes, the hidden element has (virtual) index -1 in the array.
Therefore, there are two `size' primitives for nodes:
Psize - the physical size: how many elements are contained in the
array in the node.
Vsize - the `virtual' size; if the node is pointed to by
element 0 of the parent node, then Vsize == Psize;
otherwise the element in the parent item that points to this
node `belongs' to this node, and Vsize == Psize+1;
Parent nodes are always InnerNodes.
These are the primitive operations on Nodes:
append(elt) - adds an element to the end of the array of elements in a
node. It must never be called where appending the element
would fill the node.
split() - divide a node in two, and create two new nodes.
splitWith(sib) - create a third node between this node and the sib node,
divvying up the elements of their arrays.
pushLeft(n) - move n elements into the left sibling
pushRight(n) - move n elements into the right sibling
balanceWithRight() - even up the number of elements in the two nodes.
balanceWithLeft() - ditto
To allow this implementation of btrees to also be an implementation of
sorted arrays/lists, the overhead is included to allow O(log n) access
of elements by their rank (`give me the 5th largest element').
Therefore, each Item keeps track of the number of keys in and below it
in the tree (remember, each item's tree is all keys to the RIGHT of the
item's own key).
[ [ < 0 1 2 3 > 4 < 5 6 7 > 8 < 9 10 11 12 > ] 13 [ < 14 15 16 > 17 < 18 19 20 > ] ]
4 1 1 1 1 4 1 1 1 5 1 1 1 1 7 3 1 1 1 4 1 1 1
*/
//====== Btree functions ========
void Btree::finishInit( int O )
{
if( O < 3 )
ClassLib_error( __EORDER3 );
ownsElements( 0 );
root = 0;
Order = O;
Order2 = 2 * (O+1);
Leaf_MaxIndex = Order2 - 1; // item[0..Order2-1]
Inner_MaxIndex = Order; // item[1..Order]
//
// the low water marks trigger an exploration for balancing
// or merging nodes.
// When the size of a node falls below X, then it must be possible to
// either balance this node with another node, or it must be possible
// to merge this node with another node.
// This can be guaranteed only if (this->size() < (maxSize()-1)/2).
//
//
Leaf_LowWaterMark = ((Leaf_MaxIndex+1 // == maxSize()
)-1) / 2 // satisfies the above
- 1; // because we compare
// lowwatermark with last
Inner_LowWaterMark = (Order-1) / 2;
}
Btree::Btree(int O) : itemsInContainer(0)
{
finishInit(O);
}
Btree::~Btree(void)
{
if( root != 0 )
delete root;
}
void Btree::flush( DeleteType dt )
{
int oldValue = ownsElements();
ownsElements( delObj(dt) );
if( root != 0 )
delete root;
itemsInContainer = 0;
root = 0;
ownsElements( oldValue );
}
int Btree::hasMember( Object& o ) const
{
if( !o.isSortable() )
ClassLib_error( __ENOTSORT );
if( root == 0 )
return 0;
else
{
Node* loc;
int idx;
return root->found(&(Sortable&)o, &loc, &idx) != NOOBJECT;
}
}
long Btree::rank( const Object& o ) const
{
if( !o.isSortable() )
ClassLib_error( __ENOTSORT );
if( root == 0 )
return -1;
else
return root->findRank(&(Sortable&)o);
}
Object& Btree::findMember( Object& o ) const
{
if( !o.isSortable() )
ClassLib_error(__ENOTSORT);
if( root == 0 )
return NOOBJECT;
else
{
Node* loc;
int idx;
return root->found(&(Sortable&)o, &loc, &idx);
}
}
void Btree::printOn( ostream& out ) const
{
if( root == 0 )
out << "<empty>" ;
else
root->printOn(out);
}
extern "C" void __ErrorMessage( const char * );
int Btree::isEqual( const Object& obj ) const
{
if( obj.isA() == btreeClass )
{
__ErrorMessage( "Btree isEqual not implemented\n" );
exit(1);
}
return 0;
// two btrees are equal only if they have the same number of
// elements, and they are all equal. The structure of the tree
// itself doesn't enter into it.
}
long Btree::i_add( const Object& o )
{
long r;
if( !o.isSortable() )
ClassLib_error( __ENOTSORT );
if( root == 0 )
{
root = new LeafNode( 0, &(Sortable&)o, this );
CHECK( root != 0 );
incrNofKeys();
r = 0;
}
else
{
Node* loc;
int idx;
if( root->found(&(Sortable&)o, &loc, &idx) != NOOBJECT )
{
// loc and idx are set to either where the object
// was found, or where it should go in the Btree.
// Nothing is here now, but later we might give the user
// the ability to declare a B-tree as `unique elements only',
// in which case we would handle an exception here.
// cerr << "Multiple entry warning\n";
}
else
{
CHECK( loc->isLeaf );
}
if( loc->isLeaf )
{
if( loc->parent == 0 )
r = idx;
else
r = idx + loc->parent->findRank_bu( loc );
}
else
{
InnerNode *iloc = (InnerNode*)loc;
r = iloc->findRank_bu( iloc->getTree( idx ) );
}
loc->add( &(Sortable&)o, idx );
}
CHECK( r == rank( (Sortable&)o ) || (Sortable&)o == (*this)[r] );
return r;
}
void Btree::add( Object& o )
{
if( !o.isSortable() )
ClassLib_error( __ENOTSORT );
if (root == 0)
{
root = new LeafNode( 0, &(Sortable&)o, this );
CHECK( root != 0 );
incrNofKeys();
}
else
{
Node* loc;
int idx;
if( root->found(&(Sortable&)o, &loc, &idx) != NOOBJECT )
{
// loc and idx are set to either where the object
// was found, or where it should go in the Btree.
// Nothing is here now, but later we might give the user
// the ability to declare a B-tree as `unique elements only',
// in which case we would handle an exception here.
}
loc->add( &(Sortable&)o, idx );
}
}
void Btree::detach( Object& o, DeleteType dt )
{
if( !o.isSortable() )
ClassLib_error(__ENOTSORT);
if( root == 0 )
return;
Node* loc;
int idx;
Object* obj = &(root->found( &(Sortable&)o, &loc, &idx ));
if( *obj == NOOBJECT )
return;
loc->remove( idx );
if( delObj(dt) )
delete obj;
}
void Btree::rootIsFull()
{
// the root of the tree is full; create an InnerNode that
// points to it, and then inform the InnerNode that it is full.
Node* oldroot = root;
root = new InnerNode( 0, this, oldroot );
CHECK( root != 0 );
oldroot->split();
}
void Btree::rootIsEmpty()
{
if( root->isLeaf )
{
LeafNode* lroot = (LeafNode*)root;
CHECK( lroot->Psize() == 0 );
delete lroot;
root = 0;
}
else {
InnerNode* iroot = (InnerNode*)root;
CHECK(iroot->Psize() == 0);
root = iroot->getTree(0);
root->parent = 0;
delete iroot;
}
}
Item::Item()
{
nofKeysInTree = 0;
tree = 0;
key = 0;
}
Item::Item(Node* n, Sortable* o)
{
nofKeysInTree = n->nofKeys()+1;
tree = n;
key = o;
}
Item::Item(Sortable* o, Node* n)
{
nofKeysInTree = n->nofKeys()+1;
tree = n;
key = o;
}
Item::~Item()
{
}
//
//====== Node functions ======
//
Node::Node(int isleaf, InnerNode* P, Btree* T)
{
// nofElts = 0;
last = -1;
isLeaf = isleaf;
parent = P;
if( P == 0 )
{
CHECK( T != 0 );
tree = T;
}
else
tree = P->tree;
}
Node::~Node()
{
}
//
//===== BtreeIterator methods =====
//
void BtreeIterator::restart()
{
index = 0;
}
Object& BtreeIterator::operator++()
{
return beingIterated[++index];
}
Object& BtreeIterator::operator++( int )
{
return beingIterated[index++];
}
Object& BtreeIterator::current()
{
return beingIterated[index];
}
ContainerIterator&
Btree::initIterator() const
{
return *( (ContainerIterator *)new BtreeIterator( *this ) );
}
BtreeIterator::~BtreeIterator()
{
}
BtreeIterator::operator int()
{
return index < beingIterated.getItemsInContainer();
}
@@ -0,0 +1,708 @@
/*------------------------------------------------------------------------*/
/* */
/* BTREEINN.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __BTREE_H )
#include "classlib\obsolete\btree.h"
#endif // __BTREE_H
//====== InnerNode functions ======
InnerNode::InnerNode(InnerNode* P, Btree* T) : Node(0,P,T)
{
item = new Item[maxIndex()+1];
if( item == 0 )
ClassLib_error( __ENOMEMIA );
}
InnerNode::InnerNode(InnerNode* Parent, Btree* Tree, Node* oldroot)
: Node(0, Parent, Tree)
{
// called only by Btree to initialize the InnerNode that is
// about to become the root.
item = new Item[maxIndex()+1];
if( item == 0 )
ClassLib_error( __ENOMEMIA );
append( 0, oldroot );
}
InnerNode::~InnerNode()
{
if( last > 0 )
delete item[0].tree;
for( int i = 1; i <= last; i++ )
{
delete item[i].tree;
if( tree->ownsElements() )
delete item[i].key;
}
delete [] item;
}
// for quick (human reader) lookup, functions are in alphabetical order
void InnerNode::add( Sortable *obj, int index )
{
// this is called only from Btree::add()
PRECONDITION( index >= 1 );
LeafNode* ln = getTree(index-1)->lastLeafNode();
ln->add( obj, ln->last+1 );
}
void InnerNode::addElt( Item& itm, int at )
{
PRECONDITION( 0 <= at && at <= last+1 );
PRECONDITION( last < maxIndex() );
for( int i = last+1; i > at ; i-- )
getItem(i) = getItem(i-1);
setItem( at, itm );
last++;
}
void InnerNode::addElt( int at, Sortable* k, Node* t)
{
Item newitem( k, t );
addElt( newitem, at );
}
void InnerNode::add( Item& itm, int at )
{
addElt( itm, at );
if( isFull() )
informParent();
}
void InnerNode::add( int at, Sortable* k, Node* t)
{
Item newitem( k, t );
add( newitem, at );
}
void InnerNode::appendFrom( InnerNode* src, int start, int stop )
{
// this should never create a full node
// that is, it is not used anywhere where THIS could possibly be
// near full.
if( start > stop )
return;
PRECONDITION( 0 <= start && start <= src->last );
PRECONDITION( 0 <= stop && stop <= src->last );
PRECONDITION( last + stop - start + 1 < maxIndex() ); // full-node check
for( int i = start; i <= stop; i++ )
setItem( ++last, src->getItem(i) );
}
void InnerNode::append( Sortable* D, Node* N )
{
// never called from anywhere where it might fill up THIS
PRECONDITION( last < maxIndex() );
setItem( ++last, D, N );
}
void InnerNode::append( Item& itm )
{
PRECONDITION( last < maxIndex() );
setItem( ++last, itm );
}
void InnerNode::balanceWithLeft( InnerNode* leftsib, int pidx )
{
// THIS has more than LEFTSIB; move some item from THIS to LEFTSIB.
// PIDX is the index of the parent item that will change when keys
// are moved.
PRECONDITION( Vsize() >= leftsib->Psize() );
PRECONDITION( parent->getTree(pidx) == this );
int newThisSize = (Vsize() + leftsib->Psize())/2;
int noFromThis = Psize() - newThisSize;
pushLeft( noFromThis, leftsib, pidx );
}
void InnerNode::balanceWithRight( InnerNode* rightsib, int pidx )
{
// THIS has more than RIGHTSIB; move some items from THIS to RIGHTSIB.
// PIDX is the index of the parent item that will change when keys
// are moved.
PRECONDITION( Psize() >= rightsib->Vsize() );
PRECONDITION( parent->getTree(pidx) == rightsib );
int newThisSize = (Psize() + rightsib->Vsize())/2;
int noFromThis = Psize() - newThisSize;
pushRight( noFromThis, rightsib, pidx );
}
void InnerNode::balanceWith( InnerNode* rightsib, int pindx )
{
// PINDX is the index of the parent item whose key will change when
// keys are shifted from one InnerNode to the other.
if( Psize() < rightsib->Vsize() )
rightsib->balanceWithLeft( this, pindx );
else
balanceWithRight( rightsib, pindx );
}
void InnerNode::decrNofKeys( Node *that )
{
// THAT is a child of THIS that has just shrunk by 1
int i = indexOf( that );
item[i].nofKeysInTree--;
if( parent != 0 )
parent->decrNofKeys( this );
else
tree->decrNofKeys();
}
long InnerNode::findRank( Sortable* what ) const
{
// recursively look for WHAT starting in the current node
if ( *what < *getKey(1) )
return getTree(0)->findRank(what);
long sum = getNofKeys(0);
for( int i = 1; i < last; i++ )
{
if( *what == *getKey(i) )
return sum;
sum++;
if( *what < *getKey(i+1) )
return sum + getTree(i)->findRank(what);
sum += getNofKeys(i);
}
if( *what == *getKey(last) )
return sum;
sum++;
// *what > getKey(last), so recurse on last item.tree
return sum + getTree(last)->findRank(what);
}
long InnerNode::findRank_bu( const Node *that ) const
{
// findRank_bu is findRank in reverse.
// whereas findRank looks for the object and computes the rank
// along the way while walking DOWN the tree, findRank_bu already
// knows where the object is and has to walk UP the tree from the
// object to compute the rank.
int L = indexOf( that );
long sum = 0;
for( int i = 0; i < L; i++ )
sum += getNofKeys(i);
return sum + L + (parent == 0 ? 0 : parent->findRank_bu( this ));
}
LeafNode*InnerNode::firstLeafNode()
{
return getTree(0)->firstLeafNode();
}
Object& InnerNode::found(Sortable* what, Node** which, int* where )
{
// recursively look for WHAT starting in the current node
for( int i = 1 ; i <= last; i++ )
{
if( *getKey(i) == *what )
{
// then could go in either item[i].tree or item[i-1].tree
// should go in one with the most room, but that's kinda
// hard to calculate, so we'll stick it in item[i].tree
*which = this;
*where = i;
return *getKey(i);
}
if( *getKey(i) > *what )
return getTree(i-1)->found(what, which, where);
}
// *what > *(*this)[last].key, so recurse on last item.tree
return getTree(last)->found( what, which, where );
}
void InnerNode::incrNofKeys( Node *that )
{
// THAT is a child of THIS that has just grown by 1
int i = indexOf( that );
item[i].nofKeysInTree++;
if( parent != 0 )
parent->incrNofKeys( this );
else
tree->incrNofKeys();
}
#pragma warn -rvl
int InnerNode::indexOf( const Node *that ) const
{
// returns a number in the range 0 to this->last
// 0 is returned if THAT == tree[0]
for( int i = 0; i <= last; i++ )
if( getTree(i) == that )
return i;
CHECK( 0 );
}
#pragma warn .rvl
void InnerNode::informParent()
{
if( parent == 0 )
{
// then this is the root of the tree and nees to be split
// inform the btree.
PRECONDITION( tree->root == this );
tree->rootIsFull();
}
else
parent->isFull( this );
}
void InnerNode::isFull(Node *that)
{
// the child node THAT is full. We will either redistribute elements
// or create a new node and then redistribute.
// In an attempt to minimize the number of splits, we adopt the following
// strategy:
// * redistribute if possible
// * if not possible, then split with a sibling
if( that->isLeaf )
{
LeafNode *leaf = (LeafNode *)that;
LeafNode *left, *right;
// split LEAF only if both sibling nodes are full.
int leafidx = indexOf(leaf);
int hasRightSib = (leafidx < last)
&& ((right=(LeafNode*)getTree(leafidx+1))
!= 0);
int hasLeftSib = (leafidx > 0)
&& ((left=(LeafNode*)getTree(leafidx-1))
!= 0);
int rightSibFull = (hasRightSib && right->isAlmostFull());
int leftSibFull = (hasLeftSib && left->isAlmostFull());
if( rightSibFull )
{
if( leftSibFull )
{
// both full, so pick one to split with
left->splitWith( leaf, leafidx );
}
else if( hasLeftSib )
{
// left sib not full, so balance with it
leaf->balanceWithLeft( left, leafidx );
}
else
{
// there is no left sibling, so split with right
leaf->splitWith( right, leafidx+1 );
}
}
else if( hasRightSib )
{
// right sib not full, so balance with it
leaf->balanceWithRight( right, leafidx+1 );
}
else if( leftSibFull )
{
// no right sib, and left sib is full, so split with it
left->splitWith( leaf, leafidx );
}
else if( hasLeftSib )
{
// left sib not full so balance with it
leaf->balanceWithLeft( left, leafidx );
}
else
{
// neither a left or right sib; should never happen
CHECK(0);
}
}
else {
InnerNode *inner = (InnerNode *)that;
// split INNER only if both sibling nodes are full.
int inneridx = indexOf(inner);
InnerNode *left, *right;
int hasRightSib = (inneridx < last)
&& ((right=(InnerNode*)getTree(inneridx+1))
!= 0);
int hasLeftSib = (inneridx > 0)
&& ((left=(InnerNode*)getTree(inneridx-1))
!= 0);
int rightSibFull = (hasRightSib && right->isAlmostFull());
int leftSibFull = (hasLeftSib && left->isAlmostFull());
if( rightSibFull )
{
if( leftSibFull )
{
left->splitWith( inner, inneridx );
}
else if( hasLeftSib )
{
inner->balanceWithLeft( left, inneridx );
}
else
{
// there is no left sibling
inner->splitWith(right, inneridx+1);
}
}
else if( hasRightSib )
{
inner->balanceWithRight( right, inneridx+1 );
}
else if( leftSibFull )
{
left->splitWith( inner, inneridx );
}
else if( hasLeftSib )
{
inner->balanceWithLeft( left, inneridx );
}
else {
CHECK(0);
}
}
}
void InnerNode::isLow( Node *that )
{
// the child node THAT is <= half full. We will either redistribute
// elements between children, or THAT will be merged with another child.
// In an attempt to minimize the number of mergers, we adopt the following
// strategy:
// * redistribute if possible
// * if not possible, then merge with a sibling
if( that->isLeaf )
{
LeafNode *leaf = (LeafNode *)that;
LeafNode *left, *right;
// split LEAF only if both sibling nodes are full.
int leafidx = indexOf(leaf);
int hasRightSib = (leafidx < last)
&& ((right=(LeafNode*)getTree(leafidx+1))
!= 0);
int hasLeftSib = (leafidx > 0)
&& ((left=(LeafNode*)getTree(leafidx-1))
!= 0);
if( hasRightSib
&& (leaf->Psize() + right->Vsize()) >= leaf->maxPsize())
{
// then cannot merge,
// and balancing this and rightsib will leave them both
// more than half full
leaf->balanceWith( right, leafidx+1 );
}
else if( hasLeftSib
&& (leaf->Vsize() + left->Psize()) >= leaf->maxPsize())
{
// ditto
left->balanceWith( leaf, leafidx );
}
else if( hasLeftSib )
{
// then they should be merged
left->mergeWithRight( leaf, leafidx );
}
else if( hasRightSib )
{
leaf->mergeWithRight( right, leafidx+1 );
}
else
{
CHECK(0); // should never happen
}
}
else
{
InnerNode *inner = (InnerNode *)that;
//
int inneridx = indexOf(inner);
InnerNode *left, *right;
int hasRightSib = (inneridx < last)
&& ((right=(InnerNode*)getTree(inneridx+1))
!= 0);
int hasLeftSib = (inneridx > 0)
&& ((left=(InnerNode*)getTree(inneridx-1))
!= 0);
if( hasRightSib
&& (inner->Psize() + right->Vsize()) >= inner->maxPsize())
{
// cannot merge
inner->balanceWith( right, inneridx+1 );
}
else if( hasLeftSib
&& (inner->Vsize() + left->Psize()) >= inner->maxPsize())
{
// cannot merge
left->balanceWith( inner, inneridx );
}
else if( hasLeftSib )
{
left->mergeWithRight( inner, inneridx );
}
else if( hasRightSib )
{
inner->mergeWithRight( right, inneridx+1 );
}
else
{
CHECK(0);
}
}
}
LeafNode*InnerNode::lastLeafNode()
{
return getTree(last)->lastLeafNode();
}
void InnerNode::mergeWithRight( InnerNode* rightsib, int pidx )
{
PRECONDITION( Psize() + rightsib->Vsize() < maxIndex() );
if( rightsib->Psize() > 0 )
rightsib->pushLeft( rightsib->Psize(), this, pidx );
rightsib->setKey( 0, parent->getKey( pidx ) );
appendFrom( rightsib, 0, 0 );
parent->incNofKeys( pidx-1, rightsib->getNofKeys(0)+1 );
parent->removeItem( pidx );
delete rightsib;
}
long InnerNode::nofKeys() const
{
long sum = 0;
for( int i = 0; i <= last; i++)
sum += getNofKeys(i);
return sum + Psize();
}
Object& InnerNode::operator[]( long idx ) const
{
for( int j=0; j <= last; j++ )
{
long R;
if( idx < (R = getNofKeys(j)) )
return (*getTree(j))[idx];
if( idx == R )
{
if( j == last )
return NOOBJECT;
else
return *getKey(j+1);
}
idx -= R+1; // +1 because of the key in the node
}
return NOOBJECT;
}
void InnerNode::printOn(ostream& out) const
{
out << " [ " << "/" << getNofKeys(0) << *getTree(0);
for( int i = 1; i <= last; i++ )
{
if( i > 1 )
CHECK( *getKey(i-1) <= *getKey(i) );
out << *getKey(i) << "/" << getNofKeys(i) << *getTree(i);
}
out << " ] ";
}
void InnerNode::pushLeft( int noFromThis, InnerNode* leftsib, int pidx )
{
// noFromThis==1 => moves the parent item into the leftsib,
// and the first item in this's array into the parent item
PRECONDITION( parent->getTree(pidx) == this );
PRECONDITION( noFromThis > 0 && noFromThis <= Psize() );
PRECONDITION( noFromThis + leftsib->Psize() < maxPsize() );
setKey( 0, parent->getKey(pidx) ); // makes appendFrom's job easier
leftsib->appendFrom( this, 0, noFromThis-1 );
shiftLeft( noFromThis );
parent->setKey( pidx, getKey(0) );
parent->setNofKeys( pidx-1, leftsib->nofKeys() );
parent->setNofKeys( pidx, nofKeys() );
}
void InnerNode::pushRight(int noFromThis, InnerNode* rightsib, int pidx)
{
PRECONDITION( noFromThis > 0 && noFromThis <= Psize() );
PRECONDITION( noFromThis + rightsib->Psize() < rightsib->maxPsize() );
PRECONDITION( parent->getTree(pidx) == rightsib );
//
// The operation is three steps:
// Step I. Make room for the incoming keys in RIGHTSIB.
// Step II. Move the items from THIS into RIGHTSIB.
// Step III.Update the length of THIS.
//
// Step I.: make space for noFromThis items
//
int start = last - noFromThis + 1;
int tgt, src;
tgt = rightsib->last + noFromThis;
src = rightsib->last;
rightsib->last = tgt;
rightsib->setKey( 0, parent->getKey( pidx ) ); incNofKeys(0);
while( src >= 0 )
{
// do this kind of assignment on InnerNode Items only when
// the parent fields
// of the moved items do not change, as they don't here.
// Otherwise, use setItem so the parents are updated appropriately.
rightsib->getItem(tgt--) = rightsib->getItem(src--);
}
// Step II.Move the items from THIS into RIGHTSIB
for( int i = last; i >= start; i-- )
{
// this is the kind of assignment to use when parents change
rightsib->setItem(tgt--, getItem(i));
}
parent->setKey( pidx, rightsib->getKey(0) );
decNofKeys(0);
CHECK( tgt == -1 );
// Step III.
last -= noFromThis;
// Step VI. update nofKeys
parent->setNofKeys( pidx-1, nofKeys() );
parent->setNofKeys( pidx, rightsib->nofKeys() );
}
void InnerNode::remove( int index )
{
PRECONDITION( index >= 1 && index <= last );
LeafNode* lf = getTree(index)->firstLeafNode();
setKey( index, lf->item[0] );
lf->removeItem(0);
}
void InnerNode::removeItem( int index )
{
PRECONDITION( index >= 1 && index <= last );
for( int to = index; to < last; to++ )
item[to] = item[to+1];
last--;
if( isLow() )
{
if( parent == 0 )
{
// then this is the root; when only one child, make the child
// the root
if( Psize() == 0 )
tree->rootIsEmpty();
}
else
parent->isLow( this );
}
}
void InnerNode::shiftLeft( int cnt )
{
if( cnt <= 0 )
return;
for( int i = cnt; i <= last; i++ )
getItem(i-cnt) = getItem(i);
last -= cnt;
}
void InnerNode::split()
{
// this function is called only when THIS is the only descendent
// of the root node, and THIS needs to be split.
// assumes that idx of THIS in Parent is 0.
InnerNode* newnode = new InnerNode( parent );
CHECK( newnode != 0 );
parent->append( getKey(last), newnode );
newnode->appendFrom( this, last, last );
last--;
parent->incNofKeys( 1, newnode->getNofKeys(0) );
parent->decNofKeys( 0, newnode->getNofKeys(0) );
balanceWithRight( newnode, 1 );
}
void
InnerNode::splitWith( InnerNode *rightsib, int keyidx )
{
// THIS and SIB are too full; create a NEWnODE, and balance
// the number of keys between the three of them.
//
// picture: (also see Knuth Vol 3 pg 478)
// keyidx keyidx+1
// +--+--+--+--+--+--...
// | | | | | |
// parent--->| | | |
// | | | |
// +*-+*-+*-+--+--+--...
// | | |
// +----+ | +-----+
// | +-----+ |
// V | V
// +----------+ | +----------+
// | | | | |
// this->| | | | |<--sib
// +----------+ | +----------+
// V
// data
//
// keyidx is the index of where the sibling is, and where the
// newly created node will be recorded (sibling will be moved to
// keyidx+1)
//
PRECONDITION( keyidx > 0 && keyidx <= parent->last );
// I would like to be able to prove that the following assertion
// is ALWAYS true, but it is beyond my time limits. If this assertion
// ever comes up False, then the code to make it so must be inserted
// here.
// assert(parent->getKey(keyidx) == rightsib->getKey(0));
// During debugging, this came up False, so
rightsib->setKey(0,parent->getKey(keyidx));
int nofKeys = Psize() + rightsib->Vsize();
int newSizeThis = nofKeys / 3;
int newSizeNew = (nofKeys - newSizeThis) / 2;
int newSizeSib = (nofKeys - newSizeThis - newSizeNew);
int noFromThis = Psize() - newSizeThis;
int noFromSib = rightsib->Vsize() - newSizeSib;
// because of their smaller size, this InnerNode may not have to
// give up any elements to the new node. I.e., noFromThis == 0.
// This will not happen for LeafNodes.
// We handle this by pulling an item from the rightsib.
CHECK( noFromThis >= 0 );
CHECK( noFromSib >= 1 );
InnerNode* newNode = new InnerNode(parent);
CHECK( newNode != 0 );
if( noFromThis > 0 )
{
newNode->append( getItem(last) );
parent->addElt( keyidx, getKey(last--), newNode );
if( noFromThis > 2 )
this->pushRight( noFromThis-1, newNode, keyidx );
rightsib->pushLeft( noFromSib, newNode, keyidx+1 );
}
else
{
// pull an element from the rightsib
newNode->append( rightsib->getItem(0) );
parent->addElt( keyidx+1, rightsib->getKey(1), rightsib);
rightsib->shiftLeft(1);
parent->setTree( keyidx, newNode );
rightsib->pushLeft( noFromSib-1, newNode, keyidx+1 );
}
parent->setNofKeys( keyidx-1, this->nofKeys() );
parent->setNofKeys( keyidx, newNode->nofKeys() );
parent->setNofKeys( keyidx+1, rightsib->nofKeys() );
if( parent->isFull() )
parent->informParent();
}
@@ -0,0 +1,359 @@
/*------------------------------------------------------------------------*/
/* */
/* BTREELFN.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __BTREE_H )
#include "classlib\obsolete\btree.h"
#endif // __BTREE_H
//====== LeafNode functions =======
LeafNode::LeafNode(InnerNode* P, Sortable* O, Btree* T): Node(1, P, T)
{
item = new Sortable *[maxIndex()+1];
if( item == 0 )
ClassLib_error( __ENOMEMLN );
if( O != 0 )
item[++last] = O;
}
LeafNode::~LeafNode()
{
if( tree->ownsElements() )
{
for( int i = 0; i <= last; i++ )
delete item[i];
}
delete [] item;
}
void LeafNode::add(Sortable *obj, int index)
{
// add the object OBJ to the leaf node, inserting it at location INDEX
// in the item array
PRECONDITION( 0 <= index && index <= last+1 );
PRECONDITION( last <= maxIndex() );
for( int i = last+1; i > index ; i-- )
item[i] = item[ i - 1 ];
item[ index ] = obj;
last++;
// check for overflow
if( parent == 0 )
tree->incrNofKeys( );
else
parent->incrNofKeys( this );
if( isFull() )
{
// it's full; tell parent node
if( parent == 0 )
{
// this occurs when this leaf is the only node in the
// btree, and this->tree->root == this
CHECK( tree->root == this );
// in which case we inform the btree, which can be
// considered the parent of this node
tree->rootIsFull();
}
else
{
// the parent is responsible for splitting/balancing subnodes
parent->isFull( this );
}
}
}
void LeafNode::appendFrom( LeafNode* src, int start, int stop )
{
// A convenience function, does not worry about the element in
// the parent, simply moves elements from SRC[start] to SRC[stop]
// into the current array.
// This should never create a full node.
// That is, it is not used anywhere where THIS could possibly be
// near full.
// Does NOT handle nofKeys.
if( start > stop )
return;
PRECONDITION( 0 <= start && start <= src->last );
PRECONDITION( 0 <= stop && stop <= src->last );
PRECONDITION( last + stop - start + 1 < maxIndex() ); // full-node check
for( int i = start; i <= stop; i++ )
item[++last] = src->item[i];
CHECK( last < maxIndex() );
}
void LeafNode::append( Sortable* D )
{
// never called from anywhere where it might fill up THIS
// does NOT handle nofKeys.
item[++last] = D;
CHECK( last < maxIndex() );
}
void LeafNode::balanceWithLeft( LeafNode* leftsib, int pidx )
{
// THIS has more than LEFTSIB; move some items from THIS to LEFTSIB.
PRECONDITION( Vsize() >= leftsib->Psize() );
int newThisSize = (Vsize() + leftsib->Psize())/2;
int noFromThis = Psize() - newThisSize;
pushLeft( noFromThis, leftsib, pidx );
}
void LeafNode::balanceWithRight( LeafNode* rightsib, int pidx )
{
// THIS has more than RIGHTSIB; move some items from THIS to RIGHTSIB.
PRECONDITION( Psize() >= rightsib->Vsize() );
int newThisSize = (Psize() + rightsib->Vsize())/2;
int noFromThis = Psize() - newThisSize;
pushRight( noFromThis, rightsib, pidx );
}
void LeafNode::balanceWith( LeafNode* rightsib, int pidx )
{
// PITEM is the parent item whose key will change when keys are shifted
// from one LeafNode to the other.
if( Psize() < rightsib->Vsize() )
rightsib->balanceWithLeft( this, pidx );
else
balanceWithRight( rightsib, pidx );
}
long LeafNode::findRank( Sortable* what ) const
{
// WHAT was not in any inner node; it is either here, or it's
// not in the tree
for( int i = 0; i <= last; i++ )
{
if( *item[i] == *what )
return i;
if( *item[i] >= *what )
return -1;
}
return -1;
}
LeafNode *LeafNode::firstLeafNode()
{
return this;
}
Object& LeafNode::found(Sortable* what, Node** which, int* where )
{
// WHAT was not in any inner node; it is either here, or it's
// not in the tree
for( int i = 0; i <= last; i++ )
{
if( *item[i] == *what )
{
*which = this;
*where = i;
return *item[i];
}
if( *item[i] >= *what )
{
*which = this;
*where = i;
return NOOBJECT;
}
}
*which = this;
*where = last+1;
return NOOBJECT;
}
#pragma warn -rvl
int LeafNode::indexOf( const Sortable *that ) const
{
// returns a number in the range 0 to maxIndex()
for( int i = 0; i <= last; i++ )
{
if( item[i] == that )
return i;
}
CHECK(0);
}
#pragma warn .rvl
LeafNode *LeafNode::lastLeafNode()
{
return this;
}
void LeafNode::mergeWithRight( LeafNode* rightsib, int pidx )
{
PRECONDITION( Psize() + rightsib->Vsize() < maxPsize() );
rightsib->pushLeft( rightsib->Psize(), this, pidx );
append( parent->getKey( pidx ) );
parent->setNofKeys( pidx-1, nofKeys() );
// cout << "in mergeWithRight:\n" << *parent << "\n";
parent->removeItem( pidx );
delete rightsib;
// cout << "in mergeWithRight:\n" << *parent << "\n";
}
long LeafNode::nofKeys( int ) const
{
return 1;
}
long LeafNode::nofKeys() const
{
return Psize();
}
void LeafNode::printOn(ostream& out) const
{
out << " < ";
for( int i = 0; i <= last; i++ )
out << *item[i] << " " ;
out << "> ";
}
void LeafNode::pushLeft( int noFromThis, LeafNode* leftsib, int pidx )
{
// noFromThis==1 => moves the parent item into the leftsib,
// and the first item in this's array into the parent item
PRECONDITION( noFromThis > 0 && noFromThis <= Psize() );
PRECONDITION( noFromThis + leftsib->Psize() < maxPsize() );
PRECONDITION( parent->getTree(pidx) == this );
leftsib->append( parent->getKey(pidx) );
if( noFromThis > 1 )
leftsib->appendFrom( this, 0, noFromThis-2 );
parent->setKey( pidx, item[noFromThis-1] );
shiftLeft( noFromThis );
parent->setNofKeys( pidx-1, leftsib->nofKeys() );
parent->setNofKeys( pidx, nofKeys() );
}
void LeafNode::pushRight( int noFromThis, LeafNode* rightsib, int pidx )
{
// noFromThis==1 => moves the parent item into the
// rightsib, and the last item in this's array into the parent
// item
PRECONDITION(noFromThis > 0 && noFromThis <= Psize());
PRECONDITION(noFromThis + rightsib->Psize() < maxPsize());
PRECONDITION(parent->getTree(pidx) == rightsib);
// The operation is five steps:
// Step I. Make room for the incoming keys in RIGHTSIB.
// Step II. Move the key in the parent into RIGHTSIB.
// Step III.Move the items from THIS into RIGHTSIB.
// Step IV. Move the item from THIS into the parent.
// Step V. Update the length of THIS.
//
// Step I.: make space for noFromThis items
//
int start = last - noFromThis + 1;
int tgt, src;
tgt = rightsib->last + noFromThis;
src = rightsib->last;
rightsib->last = tgt;
while (src >= 0)
rightsib->item[tgt--] = rightsib->item[src--];
// Step II. Move the key from the parent into place
rightsib->item[ tgt-- ] = parent->getKey( pidx );
// Step III.Move the items from THIS into RIGHTSIB
for( int i = last; i > start; i-- )
rightsib->item[tgt--] = item[i];
CHECK( tgt == -1 );
// Step IV.
parent->setKey( pidx, item[ start ] );
// Step V.
last -= noFromThis;
// Step VI. update nofKeys
parent->setNofKeys( pidx-1, nofKeys() );
parent->setNofKeys( pidx, rightsib->nofKeys() );
}
void LeafNode::remove( int index )
{
PRECONDITION( index >= 0 && index <= last );
for( int to = index; to < last; to++ )
item[to] = item[to+1];
last--;
if( parent == 0 )
tree->decrNofKeys();
else
parent->decrNofKeys( this );
if( isLow() )
{
if( parent == 0 )
{
// then this is the root; when no keys left, inform the tree
if( Psize() == 0 )
tree->rootIsEmpty();
}
else
parent->isLow( this );
}
}
void LeafNode::shiftLeft( int cnt )
{
if( cnt <= 0 )
return;
for( int i = cnt; i <= last; i++ )
item[i-cnt] = item[i];
last -= cnt;
}
void LeafNode::split()
{
// this function is called only when THIS is the only descendent
// of the root node, and THIS needs to be split.
// assumes that idx of THIS in Parent is 0.
LeafNode* newnode = new LeafNode( parent );
CHECK( newnode != 0 );
parent->append( item[last--], newnode );
parent->setNofKeys( 0, parent->getTree(0)->nofKeys() );
parent->setNofKeys( 1, parent->getTree(1)->nofKeys() );
balanceWithRight( newnode, 1 );
}
void LeafNode::splitWith( LeafNode *rightsib, int keyidx )
{
PRECONDITION(parent == rightsib->parent);
PRECONDITION(keyidx > 0 && keyidx <= parent->last);
int nofKeys = Psize() + rightsib->Vsize();
int newSizeThis = nofKeys / 3;
int newSizeNew = (nofKeys - newSizeThis) / 2;
int newSizeSib = (nofKeys - newSizeThis - newSizeNew);
int noFromThis = Psize() - newSizeThis;
int noFromSib = rightsib->Vsize() - newSizeSib;
CHECK(noFromThis >= 0);
CHECK(noFromSib >= 1);
LeafNode* newNode = new LeafNode(parent);
CHECK( newNode != 0 );
parent->addElt( keyidx, item[last--], newNode );
parent->setNofKeys( keyidx, 0 );
parent->decNofKeys( keyidx-1 );
this->pushRight( noFromThis-1, newNode, keyidx );
rightsib->pushLeft( noFromSib, newNode, keyidx+1 );
if( parent->isFull() )
parent->informParent();
}
@@ -0,0 +1,29 @@
/*------------------------------------------------------------------------*/
/* */
/* COLLECT.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __COLLECT_H )
#include "classlib\obsolete\collect.h"
#endif // __COLLECT_H
Object _FAR & Collection::findMember( Object _FAR & testObject ) const
{
ContainerIterator& containerIterator = initIterator();
while( containerIterator != 0 )
{
Object& listObject = containerIterator++;
if( listObject == testObject )
{
delete &containerIterator;
return listObject;
}
}
delete &containerIterator;
return NOOBJECT;
}
@@ -0,0 +1,142 @@
/*------------------------------------------------------------------------*/
/* */
/* CONTAIN.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __CONTAIN_H )
#include "classlib\obsolete\contain.h"
#endif // __CONTAIN_H
void Container::forEach( iterFuncType actionPtr, void *paramListPtr )
{
PRECONDITION( actionPtr != 0 );
ContainerIterator& containerIterator = initIterator();
while( containerIterator != 0 )
containerIterator++.forEach( actionPtr, paramListPtr );
delete &containerIterator;
}
Object& Container::firstThat( condFuncType testFuncPtr,
void *paramListPtr
) const
{
PRECONDITION( testFuncPtr != 0 );
ContainerIterator &containerIterator = initIterator();
while( containerIterator != 0 )
{
Object& testResult =
containerIterator++.firstThat( testFuncPtr, paramListPtr );
if ( testResult != NOOBJECT )
{
delete &containerIterator;
return testResult;
}
}
delete &containerIterator;
return NOOBJECT;
}
Object& Container::lastThat( condFuncType testFuncPtr,
void *paramListPtr
) const
{
PRECONDITION( testFuncPtr != 0 );
ContainerIterator& containerIterator = initIterator();
Object *lastMet = ZERO;
while( containerIterator != 0 )
{
Object& testResult =
containerIterator++.lastThat( testFuncPtr, paramListPtr );
if( testResult != NOOBJECT )
lastMet = &testResult;
}
delete &containerIterator;
return *lastMet;
}
int Container::isEqual( const Object& testContainer ) const
{
PRECONDITION( isA() == testContainer.isA() );
int res = 1;
ContainerIterator& thisIterator = initIterator();
ContainerIterator& testContainerIterator =
((Container &)(testContainer)).initIterator();
while( thisIterator != 0 && testContainerIterator != 0 )
{
if( thisIterator++ != testContainerIterator++ )
{
res = 0;
break;
}
}
if( thisIterator != 0 || testContainerIterator != 0 )
res = 0;
delete &testContainerIterator;
delete &thisIterator;
return res;
}
void Container::printOn( ostream& outputStream ) const
{
ContainerIterator& printIterator = initIterator();
printHeader( outputStream );
while( printIterator != 0 )
{
printIterator++.printOn( outputStream );
if ( printIterator != 0 )
printSeparator( outputStream );
else
break;
}
printTrailer( outputStream );
delete &printIterator;
}
static void getHashValue( Object& o, void *valPtr )
{
hashValueType *val = (hashValueType *)valPtr;
*val += o.hashValue();
}
#pragma warn -ncf
hashValueType Container::hashValue() const
{
hashValueType val = 0;
forEach( getHashValue, &val );
return val;
}
#pragma warn .ncf
void Container::printHeader( ostream& outputStream ) const
{
outputStream << nameOf() << " {\n ";
}
void Container::printSeparator( ostream& outputStream ) const
{
outputStream << ",\n ";
}
void Container::printTrailer( ostream& outputStream ) const
{
outputStream << " }\n";
}
@@ -0,0 +1,183 @@
/*------------------------------------------------------------------------*/
/* */
/* DBLLIST.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __RESOURCE_H )
#include "classlib\resource.h"
#endif // __RESOURCE_H
#if !defined( __DBLLIST_H )
#include "classlib\obsolete\dbllist.h"
#endif // __DBLLIST_H
unsigned DoubleListBlockInitializer::count = 0;
MemBlocks _FAR *DoubleList::ListElement::mgr = 0;
void DoubleList::flush( DeleteType dt )
{
ListElement *current = head->next;
while( current != tail )
{
ListElement *temp = current;
current = current->next;
if( delObj(dt) )
delete temp->data;
delete temp;
}
head->next = tail;
tail->prev = head;
itemsInContainer = 0;
}
void DoubleList::addAtHead( Object& toAdd )
{
ListElement *newElement =
new ListElement( &toAdd, head, head->next );
CHECK( newElement != 0 );
head->next->prev = newElement;
head->next = newElement;
itemsInContainer++;
}
void DoubleList::addAtTail( Object& toAdd )
{
ListElement *newElement =
new ListElement( &toAdd, tail->prev, tail );
CHECK( newElement != 0 );
tail->prev->next = newElement;
tail->prev = newElement;
itemsInContainer++;
}
void DoubleList::detach( Object& toDetach, DeleteType dt )
{
detachFromHead( toDetach, dt );
}
void DoubleList::detachFromHead( Object& toDetach, DeleteType dt )
{
tail->data = &toDetach;
ListElement *current = head->next;
while( *(current->data) != toDetach )
current = current->next;
tail->data = 0;
if( current->data == 0 ) // not found
return;
current->next->prev = current->prev;
current->prev->next = current->next;
if( delObj(dt) )
delete current->data;
delete current;
itemsInContainer--;
}
void DoubleList::detachFromTail( Object& toDetach, DeleteType dt )
{
head->data = &toDetach;
ListElement *current = tail->prev;
while( *(current->data) != toDetach )
current = current->prev;
head->data = 0;
if( current->data == 0 ) // not found
return;
current->next->prev = current->prev;
current->prev->next = current->next;
if( delObj(dt) )
delete current->data;
delete current;
itemsInContainer--;
}
ContainerIterator& DoubleList::initIterator() const
{
return *( (ContainerIterator *)new DoubleListIterator( *this ) );
}
ContainerIterator& DoubleList::initReverseIterator() const
{
return *( (ContainerIterator *)new DoubleListIterator( *this, 0 ) );
}
DoubleListIterator::operator int()
{
return currentElement != currentElement->next &&
currentElement != currentElement->prev;
}
Object& DoubleListIterator::current()
{
return *(currentElement->data);
}
Object& DoubleListIterator::operator ++ ( int )
{
if( currentElement != currentElement->next )
{
currentElement = currentElement->next;
return *(currentElement->prev->data);
}
else
return NOOBJECT;
}
Object& DoubleListIterator::operator ++ ()
{
currentElement = currentElement->next;
if( currentElement != currentElement->next )
return *(currentElement->data);
else
return NOOBJECT;
}
void DoubleListIterator::restart()
{
currentElement = startingElement;
}
Object& DoubleListIterator::operator -- ( int )
{
if( currentElement != currentElement->prev )
{
currentElement = currentElement->prev;
return *(currentElement->next->data);
}
else
return NOOBJECT;
}
Object& DoubleListIterator::operator -- ()
{
currentElement = currentElement->prev;
if( currentElement != currentElement->prev )
return *(currentElement->data);
else
return NOOBJECT;
}
DoubleListIterator::~DoubleListIterator()
{
}
@@ -0,0 +1,45 @@
/*------------------------------------------------------------------------*/
/* */
/* DEQUE.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __DEQUE_H )
#include "classlib\obsolete\deque.h"
#endif // __DEQUE_H
Object& Deque::getLeft()
{
Object& temp = list.peekAtHead();
if( temp != NOOBJECT )
{
list.detachFromHead( temp );
itemsInContainer--;
}
return temp;
}
Object& Deque::getRight()
{
Object& temp = list.peekAtTail();
if( temp != NOOBJECT )
{
list.detachFromTail( temp );
itemsInContainer--;
}
return temp;
}
ContainerIterator& Deque::initIterator() const
{
return *((ContainerIterator *)new DoubleListIterator(list));
}
@@ -0,0 +1,42 @@
/*------------------------------------------------------------------------*/
/* */
/* DICT.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __ASSOC_H )
#include "classlib\obsolete\assoc.h"
#endif // __ASSOC_H
#if !defined( __DICT_H )
#include "classlib\obsolete\dict.h"
#endif // __DICT_H
#if !defined( __CLSTYPES_H )
#include "classlib\obsolete\clstypes.h"
#endif // __CLSTYPES_H
void Dictionary::add( Object _FAR & objectToAdd )
{
if( !objectToAdd.isAssociation() )
ClassLib_error( __ENOTASSOC );
else
Set::add( objectToAdd );
}
Association _FAR & Dictionary::lookup( const Object _FAR & toLookUp ) const
{
Association toFind( (Object&)toLookUp, NOOBJECT );
toFind.ownsElements(0);
Association& found = (Association&)findMember( toFind );
return found;
}
@@ -0,0 +1,154 @@
/*------------------------------------------------------------------------*/
/* */
/* HASHTBL.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __HASHTBL_H )
#include "classlib\obsolete\hashtbl.h"
#endif // __HASHTBL_H
HashTable::HashTable( sizeType aPrime ) :
size( aPrime ),
table( aPrime ),
itemsInContainer(0)
{
}
void HashTable::add( Object& objectToAdd )
{
hashValueType index = getHashValue( objectToAdd );
if( table[ index ] == 0 )
table[index] = new List;
((List *)table[ index ])->add( objectToAdd );
itemsInContainer++;
}
void HashTable::detach( Object& objectToDetach, DeleteType dt )
{
hashValueType index = getHashValue( objectToDetach );
if( table[ index ] != 0 )
{
unsigned listSize = ((List *)table[ index ])->getItemsInContainer();
((List *)table[ index ])->detach( objectToDetach, delItem(dt) );
if( ((List *)table[ index ])->getItemsInContainer() != listSize )
itemsInContainer--;
}
}
static void setOwner( Object& list, void *owns )
{
((List&)list).ownsElements( *(TShouldDelete::DeleteType *)owns );
}
void HashTable::flush( DeleteType dt )
{
int shouldDel = delObj( dt );
table.forEach( setOwner, &shouldDel );
table.flush( 1 );
itemsInContainer = 0;
}
Object& HashTable::findMember( Object& testObject ) const
{
hashValueType index = getHashValue( testObject );
if( index >= table.limit() || table[ index ] == 0 )
{
return NOOBJECT;
}
return ((List *)table[ index ])->findMember( testObject );
}
ContainerIterator& HashTable::initIterator() const
{
return *( (ContainerIterator *)new HashTableIterator( *this ) );
}
HashTableIterator::HashTableIterator( const HashTable& toIterate ) :
beingIterated( toIterate ),
listIterator(0)
{
arrayIterator = new BI_IVectorIteratorImp<Object>( toIterate.table );
restart();
}
HashTableIterator::~HashTableIterator()
{
delete arrayIterator;
delete listIterator;
}
Object& HashTableIterator::operator ++ ( int )
{
Object& res = (listIterator == 0) ? NOOBJECT : listIterator->current();
scan();
return res;
}
Object& HashTableIterator::operator ++ ()
{
scan();
return (listIterator == 0) ? NOOBJECT : listIterator->current();
}
HashTableIterator::operator int()
{
return int(*arrayIterator);
}
Object& HashTableIterator::current()
{
return (listIterator == 0) ? NOOBJECT : listIterator->current();
}
void HashTableIterator::restart()
{
delete listIterator;
arrayIterator->restart();
while( *arrayIterator != 0 && arrayIterator->current() == 0 )
(*arrayIterator)++;
if( *arrayIterator != 0 )
{
const Object *curList = arrayIterator->current();
listIterator = &(((List *)curList)->initIterator());
if( listIterator->current() == NOOBJECT )
scan();
}
else
listIterator = 0;
}
void HashTableIterator::scan()
{
if( listIterator == 0 )
return;
(*listIterator)++;
while( listIterator != 0 && listIterator->current() == NOOBJECT )
{
delete listIterator;
(*arrayIterator)++;
while( *arrayIterator != 0 && arrayIterator->current() == 0 )
(*arrayIterator)++;
if( *arrayIterator == 0 || arrayIterator->current() == 0 )
{
listIterator = 0;
}
else
{
const Object *cur = arrayIterator->current();
listIterator = &(((Container *)cur)->initIterator());
}
}
}
@@ -0,0 +1,70 @@
/*------------------------------------------------------------------------*/
/* */
/* LDATE.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif // __STRSTREA_H
#if !defined( __STDIO_H )
#include <stdio.h>
#endif // __STDIO_H
#if !defined( __LDATE_H )
#include "classlib\obsolete\ldate.h"
#endif // __LDATE_H
const BufSize = 20;
static char *MonthNames[] =
{
"",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
int BaseDate::isEqual( const Object& testDate ) const
{
return MM == ((BaseDate&)testDate).MM &&
DD == ((BaseDate&)testDate).DD &&
YY == ((BaseDate&)testDate).YY;
}
int BaseDate::isLessThan( const Object& testDate ) const
{
if( YY != ((BaseDate&)testDate).YY )
return YY < ((BaseDate&)testDate).YY;
if( MM != ((BaseDate&)testDate).MM )
return MM < ((BaseDate&)testDate).MM;
return DD < ((BaseDate&)testDate).DD;
}
hashValueType BaseDate::hashValue() const
{
return hashValueType( YY + MM + DD );
}
void Date::printOn( ostream& outputStream ) const
{
char temp[BufSize];
ostrstream os( temp, BufSize );
os << MonthNames[ Month() ] << " "
<< Day() << ", " << Year() << ends;
outputStream << temp;
}
@@ -0,0 +1,106 @@
/*------------------------------------------------------------------------*/
/* */
/* LIST.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __RESOURCE_H )
#include "classlib\resource.h"
#endif // __RESOURCE_H
#if !defined( __LIST_H )
#include "classlib\obsolete\list.h"
#endif // __LIST_H
unsigned ListBlockInitializer::count = 0;
MemBlocks *List::ListElement::mgr = 0;
void List::add( Object& toAdd )
{
ListElement *newElement = new ListElement( &toAdd, head->next );
CHECK( newElement != 0 );
head->next = newElement;
itemsInContainer++;
}
List::ListElement *List::findPred( const Object& o )
{
tail->data = (Object *)&o;
ListElement *cursor = head;
while( o != *(cursor->next->data) )
cursor = cursor->next;
tail->data = 0;
return cursor;
}
void List::detach( Object& toDetach, DeleteType dt )
{
ListElement *pred = findPred( toDetach );
ListElement *item = pred->next;
if( delObj(dt) && pred->next != tail )
delete item->data;
pred->next = pred->next->next;
if( item != tail )
{
itemsInContainer--;
delete item;
}
}
void List::flush( DeleteType dt )
{
ListElement *current = head->next;
while( current != tail )
{
ListElement *temp = current;
current = current->next;
if( delObj(dt) )
delete temp->data;
delete temp;
}
head->next = tail;
itemsInContainer = 0;
}
ContainerIterator& List::initIterator() const
{
return *( (ContainerIterator *)new ListIterator( *this ) );
}
ListIterator::~ListIterator()
{
}
ListIterator::operator int()
{
return currentElement->next != currentElement;
}
Object& ListIterator::current()
{
return currentElement->data == 0 ? NOOBJECT : *(currentElement->data);
}
Object& ListIterator::operator ++ ( int )
{
Object *data = currentElement->data;
currentElement = currentElement->next;
return data == 0 ? NOOBJECT : *data;
}
Object& ListIterator::operator ++ ()
{
currentElement = currentElement->next;
return currentElement->data == 0 ? NOOBJECT : *(currentElement->data);
}
void ListIterator::restart()
{
currentElement = startingElement;
}
@@ -0,0 +1,66 @@
/*------------------------------------------------------------------------*/
/* */
/* LTIME.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __IOMANIP_H )
#include <iomanip.h>
#endif // __IOMANIP_H
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif // __STRSTREA_H
#if !defined( __STDIO_H )
#include <stdio.h>
#endif // __STDIO_H
#if !defined( __LTIME_H )
#include "classlib\obsolete\ltime.h"
#endif // __LTIME_H
const BufSize = 20;
int BaseTime::isEqual( const Object _FAR & testTime ) const
{
return HH == ((BaseTime&)testTime).HH &&
MM == ((BaseTime&)testTime).MM &&
SS == ((BaseTime&)testTime).SS &&
HD == ((BaseTime&)testTime).HD;
}
int BaseTime::isLessThan( const Object& testTime ) const
{
if( HH != ((BaseTime&)testTime).HH )
return HH < ((BaseTime&)testTime).HH;
if( MM != ((BaseTime&)testTime).MM )
return MM < ((BaseTime&)testTime).MM;
if( SS != ((BaseTime&)testTime).SS )
return SS < ((BaseTime&)testTime).SS;
if( HD != ((BaseTime&)testTime).HD )
return HD < ((BaseTime&)testTime).HD;
return 0;
}
hashValueType BaseTime::hashValue() const
{
return hashValueType( HH + MM + SS + HD );
}
void Time::printOn( ostream& outputStream ) const
{
char temp[BufSize];
ostrstream os( temp, BufSize );
os << ((hour()%12 == 0) ? 12 : hour()%12) << ":"
<< setfill( '0' )
<< setw( 2 ) << minute() << ":"
<< setw( 2 ) << second() << "."
<< setw( 2 ) << hundredths() << " "
<< ((hour() > 11) ? "p" : "a") << "m" << ends;
outputStream << temp;
}
@@ -0,0 +1,80 @@
/*------------------------------------------------------------------------*/
/* */
/* OBJECT.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif // __STRSTREA_H
#if !defined( __MALLOC_H )
#include <malloc.h>
#endif // __MALLOC_H
#if !defined( __CLSDEFS_H )
#include "classlib\obsolete\clsdefs.h"
#endif // __CLSDEFS_H
#if !defined( __OBJECT_H )
#include "classlib\obsolete\object.h"
#endif // __OBJECT_H
Error theErrorObject;
Object *Object::ZERO = &theErrorObject;
// Error reporting
static char *errstring[__ElastError] =
{
"firstError: [[ Error in error reporting???? ]]",
"EDELERROR: Attemping to delete the ERROR object",
"EXPANDFS: Attempting to expand a fixed size array.",
"EXPANDLB: Attempt to expand lower bound of array.",
"NOMEM: Out of Memory",
"NOTSORT: Object must be sortable.",
"NOTASSOC: Object must be association type.",
"ORDER3: B-trees must be at least of order 3.",
"NOMEMIA: No room for the item array for an InnerNode",
"NOMEMLN: No room for item array for a LeafNode.",
"PRBADCLASS: PersistRegister called with bad class id.",
"PRINCONS: PersistRegister called with inconsistent values.",
"BNZERODIV: Attempt to divide by zero.",
"BNILLLOG: Attempt to take log of zero or negative number.",
"BNNOMEM: No memory for a bignum.",
"RANDOM2SMALL: Bignum RNG must be bigger than 32 bits (> 2 words).",
"BNTEMPSTKOVFL: Too many markTempRing invocations,",
"BNTEMPSTKUNFL: Too many releaseTempRing invocations,",
"BN2MANYTEMPS: Ran out of temporaries on the Temp ring.",
"BN2BIG2PRINT: Bignum has too many digits in current output base.",
"BNNOMEM4PRINT: No memory for temporaries for printing.",
"BNRESULT2BIG: An operation would have resulted in too large of a number.",
"RNG2BIG: Sorry. RNGs are limited to 32767 `digits' in size.",
"BNSQRTILLEGAL: Trying to take sqrt of negative bignum.",
};
extern "C" void __ErrorMessage( const char _FAR * );
void _FARFUNC ClassLib_error( ClassLib_errors errnum, char _FAR *addstr )
{
ostrstream os;
os << endl << "Fatal error from class library:" << endl;
os << "__E" << errstring[errnum] << endl;
if( addstr != 0 )
os << addstr << endl;
os << ends;
char *buf = os.str();
__ErrorMessage( buf );
delete [] buf;
exit( errnum );
}
@@ -0,0 +1,63 @@
/*------------------------------------------------------------------------*/
/* */
/* SORTARRY.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( __SORTARRY_H )
#include "classlib\obsolete\sortarry.h"
#endif // __SORTARRY_H
void SortedArray::add( Object& toAdd )
{
if( toAdd.isSortable() )
{
if( lastElementIndex == upperbound )
{
reallocate( arraySize() + 1 );
}
int insertionPoint = lowerbound;
while( insertionPoint <= lastElementIndex &&
(Sortable&)objectAt( insertionPoint ) < (Sortable&)toAdd
)
insertionPoint++;
insertEntry( insertionPoint );
setData( insertionPoint, &toAdd );
itemsInContainer++;
lastElementIndex++;
}
else
ClassLib_error( __ENOTSORT );
}
void SortedArray::detach( int loc, DeleteType dt )
{
if( loc != INT_MIN )
{
if( delObj(dt) )
delete ptrAt( loc );
removeEntry( loc );
itemsInContainer--;
if( loc <= lastElementIndex )
lastElementIndex--;
}
}
void SortedArray::detach( Object& toDetach, DeleteType dt )
{
int detachPoint = find( toDetach );
detach( detachPoint, dt );
}
@@ -0,0 +1,33 @@
/*------------------------------------------------------------------------*/
/* */
/* STACK.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STACK_H )
#include "classlib\obsolete\stack.h"
#endif // __STACK_H
void Stack::push( Object& toPush )
{
list.add( toPush );
itemsInContainer++;
}
Object& Stack::pop()
{
Object& temp = list.peekHead();
list.detach( temp );
if( temp != NOOBJECT )
itemsInContainer--;
return temp;
}
ContainerIterator& Stack::initIterator() const
{
return *( (ContainerIterator *)new ListIterator( list ) );
}
@@ -0,0 +1 @@
// no longer used, beginning in classlib version 4.0
+18
View File
@@ -0,0 +1,18 @@
/*------------------------------------------------------------------------*/
/* */
/* OS2MAIN.CPP */
/* */
/* Copyright (c) 1991, 1994 Borland International */
/* All Rights Reserved */
/* */
/* Provides the initialization function for the DLL version */
/* of the class libraries */
/* */
/*------------------------------------------------------------------------*/
int main()
{
return 0;
}
+10
View File
@@ -0,0 +1,10 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/locale.h>
TRegFormatHeap TRegItem::Heap = {0, 0, 0};
+45
View File
@@ -0,0 +1,45 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#include <osl/locale.h>
#include <string.h>
//
// Construct a reglink pointing to a reglist, and add to end of list
//
TRegLink::TRegLink(TRegList& regList, TRegLink*& head)
:
RegList(&regList),
Next(0)
{
AddLink(head, *this);
}
//
// Add a new link to the end of the link list
//
void TRegLink::AddLink(TRegLink*& head, TRegLink& newLink)
{
TRegLink** link = &head;
while (*link) // put new link at end of list
link = &(*link)->Next;
*link = &newLink;
}
//
// Remove a link from the link list. Return true if link found & removed
//
bool TRegLink::RemoveLink(TRegLink*& head, TRegLink& remLink)
{
for (TRegLink** link = &head; *link; link = &(*link)->Next) {
if (*link == &remLink) {
*link = (*link)->Next; // remove from list
return true;
}
}
return false;
}
+499
View File
@@ -0,0 +1,499 @@
/*------------------------------------------------------------------------*/
/* */
/* THREAD.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __PROCESS_H )
#include <process.h>
#endif
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif
#if !defined( __CHECKS_H )
#include <checks.h>
#endif
#if !defined( CLASSLIB_DEFS_H )
#include <classlib/defs.h>
#endif
#if !defined( CLASSLIB_THREAD_H )
#include <classlib/thread.h>
#endif
DIAG_DEFINE_GROUP(Threads,1,0);
#if defined( BI_PLAT_WIN32 )
//------------------------------------------------
//
// WIN32
//
// Use OS call to close thread handle.
//
inline void InternalCloseHandle( TThread::THandle Handle )
{
::CloseHandle(Handle);
}
//------------------------------------------------
//
// WIN32
//
// Use OS call to suspend thread.
//
inline DWORD InternalSuspendThread( TThread::THandle Handle )
{
return ::SuspendThread(Handle);
}
//------------------------------------------------
//
// WIN32
//
// Use OS call to suspend thread.
//
inline DWORD InternalResumeThread( TThread::THandle Handle )
{
return ::ResumeThread(Handle);
}
//------------------------------------------------
//
// WIN32
//
// Use OS call to wait for thread termination.
//
inline unsigned long InternalWaitForThread( TThread::THandle Handle,
unsigned long timeout )
{
return ::WaitForSingleObject( Handle, timeout );
}
//------------------------------------------------
//
// WIN32
//
// Use OS call to get thread priority.
//
inline int InternalGetThreadPriority( TThread::THandle Handle )
{
return ::GetThreadPriority( Handle );
}
//------------------------------------------------
//
// WIN32
//
// Use OS call to set thread priority.
//
inline int InternalSetThreadPriority( TThread::THandle Handle, int pri )
{
return ::SetThreadPriority( Handle, pri );
}
#endif
#if defined( BI_PLAT_OS2 )
//------------------------------------------------
//
// OS/2
//
// Don't need to close the handle.
//
inline void InternalCloseHandle( TThread::THandle )
{
}
//------------------------------------------------
//
// OS/2
//
// Use OS call to suspend thread.
//
inline ULONG InternalSuspendThread( TThread::THandle Handle )
{
return ::DosSuspendThread(Handle);
}
//------------------------------------------------
//
// OS/2
//
// Use OS call to suspend thread.
//
inline ULONG InternalResumeThread( TThread::THandle Handle )
{
return ::DosResumeThread(Handle);
}
//------------------------------------------------
//
// OS/2
//
// Use OS call to wait for thread termination.
//
inline ULONG InternalWaitForThread( TThread::THandle &Handle,
unsigned long timeout )
{
return ::DosWaitThread( &Handle, timeout );
}
#endif
//------------------------------------------------
//
// TThread constructors
//
TThread::TThread() :
#if defined( BI_PLAT_WIN32 )
ThreadId(0),
#elif defined( BI_PLAT_OS2 )
Priority(0),
#endif
Handle(0),
Stat(Created),
TerminationRequested(0)
{
}
TThread::TThread( const TThread& ) :
#if defined( BI_PLAT_WIN32 )
ThreadId(0),
#elif defined( BI_PLAT_OS2 )
Priority(0),
#endif
Handle(0),
Stat(Created),
TerminationRequested(0)
{
}
//------------------------------------------------
//
// TThread assignment operator
//
// Used when assigning derived objects. Attempting to
// assign from a running object is an error, since the
// data fields in the running object can be changing
// asynchronously.
//
const TThread& TThread::operator = ( const TThread& thread )
{
switch( GetStatus() )
{
case Created:
case Suspended:
case Finished:
{
if( this != &thread )
{
Handle = 0;
#if defined( BI_PLAT_WIN32 )
ThreadId = 0;
#elif defined( BI_PLAT_OS2 )
Priority = 0;
#endif
Stat = Created;
TerminationRequested = 0;
}
return *this;
}
default:
throw ThreadError(ThreadError::AssignError);
}
}
//------------------------------------------------
//
// TThread destructor
//
// If the thread hasn't finished, destroying its control
// object is an error.
//
TThread::~TThread()
{
if( GetStatus() != Finished )
throw ThreadError(ThreadError::DestroyBeforeExit);
InternalCloseHandle(Handle);
}
//------------------------------------------------
//
// TThread::Start()
//
// Starts the thread executing. The actual call depends on the
// operating system. After the system call we check status.
//
TThread::THandle TThread::Start()
{
#if defined( BI_PLAT_WIN32 )
#if defined( __MT__ )
Handle = (HANDLE)::_beginthreadNT( &TThread::Execute, 4096, this, 0, 0, &ThreadId );
#else
Handle = ::CreateThread( 0, 0, &TThread::Execute, this, 0, &ThreadId );
#endif
#else
#if defined( __MT__ )
Handle = ::_beginthread( &TThread::Execute, 4096, this );
#else
APIRET res =
::DosCreateThread( &Handle,
(void (__syscall*)(unsigned long))&TThread::Execute,
REINTERPRET_CAST(unsigned long,this),
FALSE,
4000 );
#endif
#endif
if( Handle != 0 )
{
TRACEX( Threads, 1, "Thread started [id:" << Handle << ']' );
Stat = Running;
}
else
{
TRACEX(Threads, 2, "Thread failed to start" );
Stat = Invalid;
throw ThreadError(ThreadError::CreationFailure);
}
return Handle;
}
//------------------------------------------------
//
// TThread::Suspend()
//
// It's an error to try to suspend a thread that
// hasn't been started or that has already terminated.
//
unsigned long TThread::Suspend()
{
switch( GetStatus() )
{
case Created:
TRACEX( Threads, 2, "Illegal thread suspension [id:" << Handle << ']' );
throw ThreadError(ThreadError::SuspendBeforeRun);
case Finished:
TRACEX( Threads, 2, "Illegal thread suspension [id:" << Handle << ']' );
throw ThreadError(ThreadError::SuspendAfterExit);
default:
TRACEX( Threads, 0, "Thread suspended [id:" << Handle << ']' );
Stat = Suspended;
return InternalSuspendThread(Handle);
}
}
//------------------------------------------------
//
// TThread::Resume()
//
// It's an error to try to resume a thread that hasn't
// been suspended.
//
unsigned long TThread::Resume()
{
switch( GetStatus() )
{
case Created:
TRACEX( Threads, 2, "Illegal thread resumption [id:" << Handle << ']' );
throw ThreadError(ThreadError::ResumeBeforeRun);
case Running:
TRACEX( Threads, 2, "Illegal thread resumption [id:" << Handle << ']' );
throw ThreadError(ThreadError::ResumeDuringRun);
case Finished:
throw ThreadError(ThreadError::ResumeAfterExit);
default:
TRACEX( Threads, 0, "Thread resumed [id:" << Handle << ']' );
unsigned long res = InternalResumeThread(Handle);
if( res == 0 )
Stat = Running;
return res;
}
}
//------------------------------------------------
//
// TThread::Terminate()
//
// Mark the thread for termination.
//
void TThread::Terminate()
{
TRACEX( Threads, 1, "Thread termination requested [handle:" << Handle << ']' );
TerminationRequested = 1;
}
//------------------------------------------------
//
// TThread::WaitForExit()
//
// Block until the thread terminates.
//
// IMPORTANT: the meaning of the 'timeout' parameter is
// different for NT and OS/2. Under NT it specifies how long
// to wait for termination. Under OS/2 it specifies whether
// to wait or to return immediately if the thread hasn't
// terminated.
//
unsigned long TThread::WaitForExit( unsigned long timeout )
{
TRACEX( Threads, 1, "Waiting for thread exit [id:" << Handle << ']' );
if( Stat == Running )
return ::InternalWaitForThread( Handle, timeout );
else
return -1;
}
//------------------------------------------------
//
// TThread::TerminateAndWait()
//
// See note for WaitForExit().
//
unsigned long TThread::TerminateAndWait( unsigned long timeout )
{
Terminate();
return WaitForExit( timeout );
}
//------------------------------------------------
//
// TThread::SetPriority()
//
// Set the thread's priority.
//
int TThread::SetPriority( int pri )
{
TRACEX( Threads, 1, "Thread priority changed to " << pri << " [id:" << Handle << ']' );
#if defined( BI_PLAT_WIN32 )
return ::SetThreadPriority(Handle,pri);
#else
APIRET res = DosSetPriority( PRTYS_THREAD,
PRTYC_NOCHANGE,
pri-Priority,
Handle );
if( res != 0 )
Priority = pri;
return res;
#endif
}
//------------------------------------------------
//
// TThread::Execute()
//
// Run the thread.
//
#if defined( __MT__ )
void _USERENTRY TThread::Execute( void *thread )
{
STATIC_CAST(TThread*,thread)->Run();
}
#elif defined( BI_PLAT_WIN32 )
unsigned long _stdcall TThread::Execute( void *thread )
{
return STATIC_CAST(TThread*,thread)->Run();
}
#else
void __stdcall TThread::Execute( unsigned long thread )
{
REINTERPRET_CAST(TThread*,thread)->Run();
}
#endif
//------------------------------------------------
//
// TThread::CheckStatus()
//
// Call only when Stat claims that the thread is Running.
//
#if defined( BI_PLAT_WIN32 )
TThread::Status TThread::CheckStatus() const
{
DWORD ExitCode;
::GetExitCodeThread( Handle, &ExitCode );
if( ExitCode == STILL_ACTIVE )
return Running;
else
return Finished;
}
#elif defined( BI_PLAT_OS2 )
TThread::Status TThread::CheckStatus() const
{
if( ::DosWaitThread( CONST_CAST(THandle *,&Handle), DCWW_NOWAIT ) == ERROR_THREAD_NOT_TERMINATED )
return Running;
else
return Finished;
}
#endif
//------------------------------------------------
//
// TThread::ThreadError constructor
//
TThread::ThreadError::ThreadError(ErrorType type) :
xmsg(MakeString(type)),
Type(type)
{
}
//------------------------------------------------
//
// TThread::ThreadError::MakeString()
//
// Translates an error code into a string.
//
string TThread::ThreadError::MakeString(ErrorType type)
{
static char *Names[] =
{
"Suspend() before Run()",
"Resume() before Run()",
"Resume() during Run()",
"Suspend() after Exit()",
"Resume() after Exit()",
"creation failure",
"destroyed before Exit()",
"illegal assignment"
};
string Msg;
Msg.reserve(40);
Msg = "Error[thread]: ";
Msg += Names[type];
return Msg;
}

+275
View File
@@ -0,0 +1,275 @@
/*------------------------------------------------------------------------*/
/* */
/* TIME.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __TIME_H )
#include <time.h>
#endif
#if !defined( __STDIO_H )
#include <stdio.h>
#endif
#if !defined( __CHECKS_H )
#include <checks.h>
#endif
#if !defined( CLASSLIB_TIME_H )
#include <classlib/time.h>
#endif
enum TimeZone { CarolineIslands=-11, MarianaIslands, Japan,
China, minusSeven, minusSix,
Pakistan, CaspianSea, Turkey,
Finland, Europe, Greenwich,
Azores, two, Greenland,
Atlantic, USEastern, USCentral,
USMountain, USPacific, Alaska,
Hawaii, Bearing};
static const unsigned long SECONDS_IN_DAY = 86400L;
static const unsigned long SECONDS_IN_HOUR = 3600L;
static const unsigned SECONDS_IN_MIN = 60;
// Be sure that you have set your environment variable TZ.
// For example, for Pacific coast time, set TZ=PDT8PST.
// For other time zones, see your manuals.
struct TInitTime
{
TInitTime()
{ tzset(); }
};
static TInitTime cludgeTime; // To force the call to tzset()
const TDate TTime::RefDate( (DayTy)0, (YearTy)0 );
const TDate TTime::MaxDate( (DayTy)49709L, (YearTy)0 ); // ((2**32)-1)/SECONDS_IN_DAY -1
static const int SUNDAY = 7;
int TTime::AssertDate( const TDate _BIDSFAR & date )
{
return date.Between(RefDate,MaxDate);
}
/******************* private member functions ***********************/
// Adjust for local time zone and Daylight Savings Time.
ClockTy TTime::LocalSecs() const
{
TTime local_time( Sec - timezone );
if (local_time.IsDST())
local_time.Sec += SECONDS_IN_HOUR;
return local_time.Sec;
}
/*
* Builds the time from a local time, adjusting to GMT. Does *not* adjust for DST.
*/
TTime TTime::BuildLocal( const TDate _BIDSFAR & date, HourTy h )
{
return TTime( SECONDS_IN_DAY * (date-RefDate) +
SECONDS_IN_HOUR * h +
timezone);
}
/*************** public static member functions *******************/
/*
* Return the time at which DST starts for the given year.
* Note that the time returned is the time at which DST starts locally,
* but it is returned in GMT.
*/
TTime TTime::BeginDST( unsigned year )
{
if( year > 1986 )
{
TDate endMarch(31, 3, year);
return BuildLocal( endMarch.Previous(SUNDAY)+7, 2 );
}
// Ah, remember those energy conscious years...???
if( year==1974 )
return BuildLocal( TDate(6,1,1974), 2 );
if( year==1975 )
return BuildLocal( TDate(23,2,1975), 2 );
TDate endApril( 30, 4, year );
return BuildLocal( endApril.Previous(SUNDAY), 2 );
}
/*
* Return the time at which DST ends for the given year.
* Note that the time returned is the time at which DST ends locally,
* but it is returned in GMT.
*/
TTime TTime::EndDST( unsigned year )
{
TDate endOctober( 31, 10, year );
return BuildLocal( endOctober.Previous(SUNDAY), 1 );
}
/************************* constructor *********************************/
// Construct TTime with current time (seconds since Jan 1, 1901).
TTime::TTime()
{
time_t ltime;
time(&ltime);
struct tm _FAR *t = localtime(&ltime);
// Construct the date. The time struct returns int, so casts are used.
TDate today( (DayTy)t->tm_mday,
(MonthTy)(t->tm_mon + 1),
(YearTy)t->tm_year );
*this = TTime( today,
(HourTy)t->tm_hour,
(MinuteTy)t->tm_min,
(SecondTy)t->tm_sec );
}
// Specified time and today's date:
TTime::TTime( HourTy h, MinuteTy m, SecondTy s )
{
Sec = TTime( TDate(),h,m,s ).Sec;
}
/*
* Construct a Time for the specified (local) Date, hour, minute, and second.
* Note: this algorithm will fail if DST correction is something other
* than an hour.
* It is complicated by the DST boundary problem:
* 1) Times in the phantom zone between 2AM and 3AM when DST is invoked are invalid.
* 2) Times in the hour after 1AM when DST ends, are redundant.
* Checking for these situations necessitates a lot of jumping back
* and forth by an hour to check for the boundary.
*/
TTime::TTime( const TDate _BIDSFAR & date, HourTy h, MinuteTy m, SecondTy s )
{
if( date.IsValid() )
{
Sec = SECONDS_IN_DAY * (date-RefDate) +
SECONDS_IN_HOUR * (h-1L) + /* Note the adjustment by one hour */
SECONDS_IN_MIN * m + s;
if( Sec )
Sec += timezone; // Adjust to GMT.
if( IsDST() )
{
Sec += SECONDS_IN_HOUR;
if( IsDST() )
Sec -= SECONDS_IN_HOUR;
}
else
{
Sec += SECONDS_IN_HOUR;
if( IsDST() )
Sec = 0; // Invalid "phantom" time.
}
}
else
Sec = 0; // Invalid date
}
/*************** conversion from TTime to TDate *******************/
// Type conversion to date.
TDate::TDate( const TTime _BIDSFAR & t )
{
Julnum = t.IsValid() ? jul1901 + (JulTy)(t.LocalSecs()/SECONDS_IN_DAY) : 0;
}
/********************* public member functions **********************/
int TTime::CompareTo( const TTime _BIDSFAR &t ) const
{
ClockTy diff = Sec - t.Sec;
return diff==0 ? 0 : diff>0 ? 1 : -1;
}
// Hash function:
unsigned TTime::Hash() const
{
return (unsigned)Sec;
}
/*
* The hour in local time:
*/
HourTy TTime::Hour() const
{
return HourTy((LocalSecs() % SECONDS_IN_DAY) / SECONDS_IN_HOUR);
}
/*
* The hour in GMT:
*/
HourTy TTime::HourGMT() const
{
return HourTy((Sec % SECONDS_IN_DAY) / SECONDS_IN_HOUR);
}
/*
* Return TRUE if DST is active for this time:
*/
int TTime::IsDST() const
{
if( !daylight )
return 0;
DayTy daycount = (unsigned)(Sec/SECONDS_IN_DAY);
YearTy year = TDate( (DayTy)daycount, (YearTy)0 ).Year();
// Check to see if the time falls between the starting & stopping DST times.
return *this >= BeginDST( year ) && *this < EndDST( year );
}
TTime TTime::Max( const TTime _BIDSFAR & t ) const
{
if( *this > t )
return *this;
else
return t;
}
TTime TTime::Min( const TTime _BIDSFAR & t ) const
{
if( *this < t )
return *this;
else
return t;
}
/*
* minute, in local time
*/
MinuteTy TTime::Minute() const
{
return MinuteTy(((LocalSecs()%SECONDS_IN_DAY)%SECONDS_IN_HOUR)/SECONDS_IN_MIN);
}
/*
* minute: GMT
*/
MinuteTy TTime::MinuteGMT() const
{
return MinuteTy(((Sec%SECONDS_IN_DAY)%SECONDS_IN_HOUR)/SECONDS_IN_MIN);
}
// second;local time or GMT
SecondTy TTime::Second() const
{
return SecondTy(((Sec%SECONDS_IN_DAY)%SECONDS_IN_HOUR)%SECONDS_IN_MIN);
}
+88
View File
@@ -0,0 +1,88 @@
/*------------------------------------------------------------------------*/
/* */
/* TIMEIO.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDIO_H )
#include <stdio.h>
#endif
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif
#if !defined( __IOMANIP_H )
#include <iomanip.h>
#endif
#if !defined( __CSTRING_H )
#include <cstring.h>
#endif
#if !defined( CLASSLIB_TIME_H )
#include <classlib/time.h>
#endif
#if !defined( CLASSLIB_FILE_H )
#include <classlib/file.h>
#endif
// Static variable intialization:
int TTime::PrintDateFlag = 1;
string TTime::AsString() const
{
char buf[80];
ostrstream strtemp(buf, sizeof(buf));
strtemp << (*this) << ends;
string temp(buf);
return temp;
}
ostream _BIDSFAR & _BIDSFUNC operator << ( ostream _BIDSFAR & s, const TTime _BIDSFAR & t )
{
char buf[80];
// We use an ostrstream to format into buf so that
// we don't affect the ostream's width setting.
ostrstream out( buf, sizeof(buf) );
// First print the date if requested:
if(TTime::PrintDateFlag)
out << TDate(t) << " ";
unsigned hh = t.Hour();
out << (hh <= 12 ? hh : hh-12) << ':'
<< setfill('0') << setw(2) << t.Minute() << ':'
<< setw(2) << t.Second() << ' ' << setfill(' ');
out << ( hh<12 ? "am" : "pm") << ends;
// now we write out the formatted buffer, and the ostream's
// width setting will control the actual width of the field.
s << buf;
return s;
}
int TTime::PrintDate( int f )
{
int temp = PrintDateFlag;
PrintDateFlag = f;
return temp;
}
ostream _BIDSFAR & _BIDSFUNC operator << ( ostream _BIDSFAR & os, const TFileStatus _BIDSFAR & status )
{
os << "File Status: " << status.fullName << '\n';
os << " created: " << status.createTime << '\n';
os << " modified: " << status.modifyTime << '\n';
os << " accessed: " << status.accessTime << '\n';
os << " size: " << status.size << '\n';
os << " attributes: " << (int)status.attribute << '\n';
return os;
}
+35
View File
@@ -0,0 +1,35 @@
/*------------------------------------------------------------------------*/
/* */
/* TIMEP.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STRSTREA_H )
#include <strstrea.h>
#endif
#if !defined( CLASSLIB_TIME_H )
#include <classlib/time.h>
#endif
#if !defined( CLASSLIB_OBJSTRM_H )
#include <classlib/objstrm.h>
#endif
opstream _BIDSFAR & _BIDSFUNC operator << ( opstream _BIDSFAR & os,
const TTime _BIDSFAR & d )
{
return os << d.Sec;
}
ipstream _BIDSFAR & _BIDSFUNC operator >> ( ipstream _BIDSFAR & is,
TTime _BIDSFAR & d )
{
return is >> d.Sec;
}
+110
View File
@@ -0,0 +1,110 @@
/*------------------------------------------------------------------------*/
/* */
/* TIMER.CPP */
/* */
/* Copyright (c) 1991, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __DOS_H )
#include <dos.h>
#endif
#define BUILDBIDSTIMER
#if !defined( CLASSLIB_TIMER_H )
#include <classlib/timer.h>
#endif
const unsigned long far * const dosTime =
(const unsigned long far * const)MK_FP( 0x40, 0x6C );
unsigned TTimer::Adjust = Calibrate();
TTimer::TTimer() : Time_(0), Running(0)
{
}
void TTimer::Start()
{
if( !Running )
{
outportb( 0x43, 0x34 );
asm jmp __1;
__1:
outportb( 0x40, 0 );
asm jmp __2;
__2:
outportb( 0x40, 0 );
StartTime.DosCount = *dosTime;
StartTime.TimerCount = 0;
Running = 1;
}
}
void TTimer::Stop()
{
outportb( 0x43, 0 );
unsigned char temp = inportb( 0x40 );
TIME stopTime;
stopTime.TimerCount = (inportb( 0x40 ) << 8) + temp;
stopTime.DosCount = *dosTime;
TIME elapsedTime;
elapsedTime.DosCount = stopTime.DosCount - StartTime.DosCount;
elapsedTime.TimerCount = -( stopTime.TimerCount - Adjust );
const double fudge = 83810.0/100000.0;
Time_ += ((elapsedTime.DosCount << 16) + elapsedTime.TimerCount)*fudge;
Running = 0;
}
void TTimer::Reset()
{
Time_ = 0;
if( Running )
Start();
}
unsigned TTimer::Calibrate()
{
Adjust = 0;
unsigned long sum = 0;
TTimer w;
for( int i = 0; i < 100; i++ )
{
w.Start();
w.Stop();
sum += w.Time();
w.Reset();
}
return (unsigned)((sum+5)/100);
}
#if defined( TEST_TIMER )
#include <iostream.h>
#include <stdio.h>
int main( void )
{
delay( 0 );
cout << "Resolution: " << Timer::Resolution() << endl;
TTimer w;
for( unsigned del = 0; del < 10; del++ )
{
unsigned d1 = del*100;
w.Start();
delay( d1 );
w.Stop();
printf( "%4u ms., actual time = %6f seconds.\n", d1, w.Time() );
w.Reset();
}
return 0;
}
#endif
+91
View File
@@ -0,0 +1,91 @@
/*------------------------------------------------------------------------*/
/* */
/* TMPLINST.CPP */
/* */
/* Copyright (c) 1991, 1994 Borland International */
/* All Rights Reserved */
/* */
/* Provides instantiations of the various Object containers, */
/* for use in the class library DLLs. */
/* */
/*------------------------------------------------------------------------*/
#pragma option -Jgd
#if !defined( __HASHTBL_H )
#include <classlib\obsolete\hashtbl.h>
#endif
#if !defined( CLASSLIB_OBJSTRM_H )
#include <classlib/objstrm.h>
#endif
// needed for HashTable
typedef TIVectorImp<Object> dummy1;
// needed for Object Streaming
typedef TSVectorImp<TPWrittenObjects::TPWObj> dummy2;
typedef TCVectorImp<const void *> dummy3;
typedef TISVectorImp<TStreamableClass> dummy4;
#if !defined( CLASSLIB_VECTIMP_H )
#include <classlib/vectimp.h>
#endif
#if !defined( CLASSLIB_STACKS_H )
#include <classlib/stacks.h>
#endif
#if !defined( CLASSLIB_QUEUES_H )
#include <classlib/queues.h>
#endif
#if !defined( CLASSLIB_LISTIMP_H )
#include <classlib/listimp.h>
#endif
#if !defined( CLASSLIB_DLISTIMP_H )
#include <classlib/dlistimp.h>
#endif
#if !defined( CLASSLIB_DEQUES_H )
#include <classlib/deques.h>
#endif
#if !defined( CLASSLIB_SETS_H )
#include <classlib/sets.h>
#endif
typedef TSDoubleListImp<void _FAR *> dummy6;
typedef TDoubleListIteratorImp<void _FAR *> dummy7;
typedef TIDequeAsVector<Object> dummy8;
typedef TIDequeAsVectorIterator<Object> dummy9;
typedef TIDequeAsDoubleList<Object> dummy10;
typedef TIDequeAsDoubleListIterator<Object> dummy11;
typedef TSListImp<void _FAR *> dummy12;
typedef TListIteratorImp<void _FAR *> dummy13;
typedef TIQueueAsVector<Object> dummy14;
typedef TIQueueAsVectorIterator<Object> dummy15;
typedef TIQueueAsDoubleList<Object> dummy16;
typedef TIQueueAsDoubleListIterator<Object> dummy17;
typedef TIStackAsVector<Object> dummy18;
typedef TIStackAsVectorIterator<Object> dummy19;
typedef TIStackAsList<Object> dummy20;
typedef TIStackAsListIterator<Object> dummy21;
typedef TVectorImp<void _FAR *> dummy22;
typedef TCVectorImp<void _FAR *> dummy23;
typedef TSVectorImp<void _FAR *> dummy24;
typedef TMVectorIteratorImp<void _FAR *,TStandardAllocator> dummy25;
typedef TISetAsVector<Object> dummy26;
typedef TISetAsVectorIterator<Object> dummy27;
typedef TICVectorImp<Object> dummy28;
+468
View File
@@ -0,0 +1,468 @@
//----------------------------------------------------------------------------
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// TUString implementation (others functions are inline)
//
//----------------------------------------------------------------------------
#if !defined(_Windows)
# define _Windows // pretend we are in windows to get the headers we need
#endif
#if !defined(INC_OLE2)
# define INC_OLE2 // Make sure we get Ole2 headers
#endif
#include <osl/ustring.h>
#include <osl/inlines.h>
#include <string.h>
TUString TUString::Null; // null TAutoStrings reference this object
#if defined(BI_HAS_WCHAR)
//
// Take a wide char string & return an ANSI string in a new'd char[] buffer
//
char* TUString::ConvertWtoA(const wchar_t* src, size_t len)
{
size_t size = WideCharToMultiByte(CP_ACP, 0, src, len, 0, 0, 0, 0);
char* dst = new char[size + (len != -1)]; // room for null if fixed size
size = WideCharToMultiByte(CP_ACP, 0, src, len, dst, size, 0, 0);
if (len != -1)
dst[size] = 0;
return dst;
}
//
// Take an ANSI char string & return a wide string in a new'd wchar_t[] buffer
//
wchar_t* TUString::ConvertAtoW(const char* src, size_t len)
{
size_t size = MultiByteToWideChar(CP_ACP, 0, src, len, 0, 0);
wchar_t* dst = new wchar_t[size + (len != -1)];
size = MultiByteToWideChar(CP_ACP, 0, src, len, dst, size);
if (len != -1)
dst[size] = 0;
return dst;
}
#endif
//------------------------------------------------------------------------
//
// Change UString to isCopy regardless of current type
//
char* TUString::ChangeToCopy()
{
char* dst = 0;
const char far* src;
int len;
switch (Kind) {
case isNull:
return 0;
case isConst:
src = Const;
len = strlen(Const);
break;
case isCopy:
return Copy;
#if defined(BI_HAS_WCHAR)
case isWConst:
dst = ConvertWtoA(WConst);
break;
case isWCopy:
dst = ConvertWtoA(WCopy);
delete [] WCopy;
break;
#endif
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr:
dst = ConvertWtoA(Bstr, ::SysStringLen(Bstr));
break;
#else
case isBstr:
case isExtBstr:
src = Bstr;
len = ::SysStringLen(Bstr);
break;
#endif
case isString:
src = ((string*)&String)->c_str();
len = ((string*)&String)->length();
}
if (!dst) {
dst = new char[len+1];
memcpy(dst, src, len+1);
}
if (Kind == isBstr)
::SysFreeString(Bstr);
Kind = isCopy;
Copy = dst;
return Copy;
}
#if defined(BI_HAS_WCHAR)
//
// Change UString to isWCopy regardless of current type
//
wchar_t* TUString::ChangeToWCopy()
{
wchar_t* dst = 0;
const wchar_t* src;
int len;
switch (Kind) {
case isNull:
return 0;
case isConst:
dst = ConvertAtoW(Const);
break;
case isCopy:
dst = ConvertAtoW(Copy);
delete [] Copy;
break;
case isWConst:
src = WConst;
len = strlen(WConst);
break;
case isWCopy:
return WCopy;
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr:
src = Bstr;
len = ::SysStringLen(Bstr);
if (Kind == isBstr)
::SysFreeString(Bstr);
break;
#else // This case probably never happens
case isBstr:
case isExtBstr:
dst = ConvertAtoW(Bstr, ::SysStringLen(Bstr));
if (Kind == isBstr)
::SysFreeString(Bstr);
break;
#endif
case isString:
dst = ConvertAtoW(((string*)&String)->c_str(), ((string*)&String)->length());
}
if (!dst) {
dst = new wchar_t[len+1];
memcpy(dst, src, (len+1) * sizeof(wchar_t));
}
Kind = isWCopy;
WCopy = dst;
return WCopy;
}
#endif
//------------------------------------------------------------------------
// inline ctors used by Create functions
inline TUString::TUString(const char far& str)
:
Kind(isConst), Const(&str), RefCnt(1), Lang(0)
{
}
inline TUString::TUString(char& str)
:
Kind(isCopy), RefCnt(1), Lang(0)
{
Copy = new char[strlen(&str)+1];
strcpy(Copy, &str);
}
#if defined(BI_HAS_WCHAR)
inline TUString::TUString(const wchar_t& str)
:
Kind(isWConst), WConst(&str), RefCnt(1), Lang(0)
{
}
inline TUString::TUString(wchar_t& str)
:
Kind(isWCopy), RefCnt(1), Lang(0)
{
WCopy = new wchar_t[strlen(&str)+1];
strcpy(WCopy, &str);
}
#endif
inline TUString::TUString(BSTR str, bool loan, TLangId lang)
:
Kind(loan ? isExtBstr : isBstr), Bstr(str), RefCnt(loan ? 2 : 1), Lang(lang)
{
}
inline void* operator new(size_t, TStringRef** p) {return p;}
inline TUString::TUString(const string& str)
:
Kind(isString), RefCnt(1), Lang(0)
{
new(&String) string(str);
}
//------------------------------------------------------------------------
TUString* TUString::Create(const char far* str)
{
return str && *str ? new TUString(*str) : &++Null;
}
TUString* TUString::Create(char* str)
{
return str && *str ? new TUString(*str) : &++Null;
}
#if defined(BI_HAS_WCHAR)
TUString* TUString::Create(const wchar_t* str)
{
return str && *str ? new TUString(*str) : &++Null;
}
TUString* TUString::Create(wchar_t* str)
{
return str && *str ? new TUString(*str) : &++Null;
}
#endif
TUString* TUString::Create(BSTR str, bool loan, TLangId lang)
{
if (str && ::SysStringLen(str))
return new TUString(str, loan, lang);
if (!loan)
::SysFreeString(str);
return &++Null;
}
TUString* TUString::Create(const string& str)
{
return str.length() ? new TUString(str) : &++Null;
}
TUString* TUString::Assign(const TUString& s)
{
if (RefCnt == 1 && Kind != isNull && Kind != isExtBstr)
Free();
else
--*this;
CONST_CAST(TUString&,s).RefCnt++;
return &CONST_CAST(TUString&,s);
}
TUString* TUString::Assign(const string& s)
{
if (s.length() && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isString;
new(&String) string(s);
return this;
}
else {
--*this;
return Create(s);
}
}
TUString* TUString::Assign(const char far* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isConst;
Const = s;
return this;
}
else {
--*this;
return Create(s);
}
}
TUString* TUString::Assign(char* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isCopy;
Copy = new char[strlen(s)+1];
strcpy(Copy, s);
return this;
}
else {
--*this;
return Create(s);
}
}
#if defined(BI_HAS_WCHAR)
TUString* TUString::Assign(const wchar_t* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isWConst;
WConst = s;
return this;
}
else {
--*this;
return Create(s);
}
}
TUString* TUString::Assign(wchar_t* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isWCopy;
WCopy = new wchar_t[strlen(s)+1];
strcpy(WCopy, s);
return this;
}
else {
--*this;
return Create(s);
}
}
#endif
TUString* TUString::Assign(BSTR str, TLangId lang)
{
if (RefCnt==1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isBstr;
Bstr = str;
Lang = lang;
if (Bstr && ::SysStringLen(Bstr))
return this;
delete this;
return &++Null;
}
else {
--*this;
return Create(str, false, lang);
}
}
TUString::operator const char far*() const
{
switch (Kind) {
case isNull: return 0;
case isConst: return Const;
case isCopy: return Copy;
case isString: return ((string*)&String)->c_str();
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToCopy();
#else
case isBstr:
case isExtBstr: return Bstr;
#endif
case isWConst:
case isWCopy: return CONST_CAST(TUString*,this)->ChangeToCopy();
}
return 0; // suppress warning
}
TUString::operator char*()
{
return ChangeToCopy();
}
#if defined(BI_HAS_WCHAR)
TUString::operator const wchar_t*() const
{
switch (Kind) {
case isNull: return 0;
case isWConst: return WConst;
case isWCopy: return WCopy;
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr: return Bstr;
#else
case isBstr:
case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToWCopy();
#endif
case isConst:
case isCopy:
case isString: return CONST_CAST(TUString*,this)->ChangeToWCopy();
}
return 0; // suppress warning
}
TUString::operator wchar_t*()
{
return ChangeToWCopy();
}
#endif
//
//
//
int TUString::Length() const
{
switch (Kind) {
case isNull: return 0;
#if defined(BI_HAS_WCHAR)
case isWConst: return strlen(WConst);
case isWCopy: return strlen(WCopy);
#endif
case isBstr:
case isExtBstr: return ::SysStringLen(Bstr);
case isConst: return strlen(Const);
case isCopy: return strlen(Copy);
case isString: return ((string*)&String)->length();
}
return 0; // suppress warning
}
//
// Revokes BSTR ownership from this UString
//
void TUString::RevokeBstr(BSTR s)
{
if (Kind != isExtBstr || Bstr != s)
return;
if (RefCnt == 1) {
Kind = isNull;
delete this;
return;
}
Kind = isCopy;
#if defined(BI_OLECHAR_WIDE)
WCopy = new wchar_t[strlen(s)+1];
strcpy(WCopy, s);
#else
Copy = new char[strlen(s)+1];
strcpy(Copy, s);
#endif
}
//
// Passes BSTR ownership to this UString
//
void TUString::ReleaseBstr(BSTR s)
{
if (Kind == isExtBstr && Bstr == s) {
Kind = isBstr;
--*this;
}
else // has been overwritten with converted type
::SysFreeString(Bstr);
}
//
// Free any resources held by this UString. Union & Kind left in random state;
// must be reinitialized before use.
//
void TUString::Free()
{
switch (Kind) {
case isCopy: delete [] Copy; break;
#if defined(BI_HAS_WCHAR)
case isWCopy: delete [] WCopy; break;
#endif
case isBstr: ::SysFreeString(Bstr); break;
case isString: ((string*)&String)->string::~string();
}
Lang = 0;
//Kind = isNull; // for safety, not really needed
}
+27
View File
@@ -0,0 +1,27 @@
/*------------------------------------------------------------------------*/
/* */
/* VERSION.CPP */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( CLASSLIB_VERSION_H )
#include <classlib/version.h>
#endif
#define ID "CLASSLIB"
struct TVersionHeader
{
char Signature[6];
unsigned long InternalVersionNumber;
char ComponentIDstring[sizeof (ID)];
} VersionHeader =
{
{'$', '*', '$', '*', '$', '*'},
{InternalVersion},
ID
};
+47
View File
@@ -0,0 +1,47 @@
/*------------------------------------------------------------------------*/
/* */
/* VERSION.RC */
/* */
/* Copyright (c) 1993, 1994 Borland International */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#include <ver.h>
VS_VERSION_INFO VERSIONINFO
FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE
FILEFLAGS VS_FF_PRERELEASE | VS_FF_SPECIALBUILD
#ifndef WIN32
FILEOS VOS_DOS_WINDOWS16
#else
FILEOS VOS_NT_WINDOWS32
#endif
FILETYPE VFT_DLL
FILESUBTYPE VS_USER_DEFINED
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "Borland International\0"
VALUE "FileDescription", "BIDS Class Library\0"
VALUE "FileVersion", "1.00\0"
VALUE "InternalName", "BIDS Class Library\0"
VALUE "LegalCopyright", "Copyright Borland International 1993\0"
VALUE "ProductName", "Borland C++ 4.0\0"
VALUE "ProductVersion", "4.2"
VALUE "SpecialBuild", "05 Nov 1994 09:43:34 "
END
END
BLOCK "VarFileInfo"
BEGIN /* Language | Translation */
VALUE "Translation", 0x409, 1252 /* U.S. English, Windows Multilingual */
END
END