home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Borland
/
Cplus45
/
BC45
/
OWL1.PAK
/
OBJSTRM.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-29
|
19KB
|
811 lines
// Borland C++ - (C) Copyright 1992 by Borland International
/*------------------------------------------------------------*/
/* filename - objstrm.cpp */
/* */
/* function(s) */
/* Member function(s) of following classes: */
/* TStreamable */
/* TStreamableClass */
/* TStreamableTypes */
/* TPWrittenObjects */
/* TPReadObjects */
/* pstream */
/* ipstream */
/* opstream */
/* iopstream */
/* fpbase */
/* ifpstream */
/* ofpstream */
/* fpstream */
/*------------------------------------------------------------*/
#if !defined( __OBJSTRM_H )
#include <objstrm.h>
#endif // __OBJSTRM_H
#if !defined( __STRING_H )
#include <string.h>
#endif // __STRING_H
#if !defined( __FSTREAM_H )
#include <fstream.h>
#endif // __FSTREAM_H
#if !defined( __IO_H )
#include <io.h>
#endif // __IO_H
#if !defined( __STAT_H )
#include <sys\Stat.h>
#endif // __STAT_H
#if !defined( __FCNTL_H )
#include <fcntl.h>
#endif // __FCNTL_H
#if !defined( __ASSERT_H )
#include <assert.h>
#endif // __ASSERT_H
#if !defined(__ALLOC_H)
#include <alloc.h>
#endif // __ALLOC_H
#if !defined(__APPLICAT_H)
#include <applicat.h>
#endif
#if !defined(__WINDOBJ_H)
#include <windobj.h>
#endif
#if defined(__DLL__)
extern "C"
unsigned _WinAllocFlag;
#endif
TStreamableTypes *pstream::types;
#if defined(__DLL__)
static unsigned short GetSegmentLimit(Pvoid pMem)
{
unsigned short Temp = FP_SEG(pMem); // Temp = selector
asm lsl ax, Temp; // ax = segment limit
asm mov Temp, ax; // Temp = segment limit
return Temp;
}
static unsigned short GetChecksum(Pvoid pMem, unsigned short SegmentLimit)
{
unsigned long TempChecksum = 0; // intialize checksum
SegmentLimit -= FP_OFF(pMem); // adjust for starting offset
// Use either 64 bytes (32 words) or the segment limit, whichever
// is smaller
int ChecksumLimit = (SegmentLimit < 64) ? (SegmentLimit>>1) : 32;
unsigned short _FAR *p = (unsigned short _FAR *)pMem;
for (int i = 0; i < ChecksumLimit; i++)
TempChecksum += *p++;
return (unsigned short)TempChecksum;
}
TObjStrmRegRecord::TObjStrmRegRecord(PTStreamableClass pTStreamableClass)
{
this->pTStreamableClass = pTStreamableClass;
SegmentLimit = GetSegmentLimit(pTStreamableClass->build);
Checksum = GetChecksum(pTStreamableClass->build, SegmentLimit);
}
Pvoid TObjStrmRegRecord::operator new (size_t s)
{
return (Pvoid)LocalLock(LocalAlloc(LPTR, s));
}
void TObjStrmRegRecord::operator delete(Pvoid ptr)
{
HANDLE hMem =
#ifdef STRICT
LocalHandle( (void NEAR *)FP_OFF( ptr ) );
#else
LocalHandle( FP_OFF( ptr ) );
#endif
if (LocalUnlock(hMem))
LocalFree(hMem);
}
int TObjStrmRegRecord::Validate()
{
WORD Temp = FP_SEG(pTStreamableClass);
asm lar ax, Temp; // get access rights
asm jnz invalid; // invalid segment
asm and ax, 0x0800; // code or data?
asm jnz invalid; // code, invalid
// We can access the pTStreamableClass pointer. See if segment is
// big enough to contain a TStreamableClass object.
long TempSegmentLimit = GetSegmentLimit(pTStreamableClass);
if (TempSegmentLimit-FP_OFF(pTStreamableClass) <=
sizeof(TStreamableClass)-1)
return 0;
// We can access the TStreamableClass object and the segment in
// which it resides is big enough to hold a TStreamableClass
Temp = FP_SEG(pTStreamableClass->build);
asm lar ax, Temp; // get access rights
asm jnz invalid; // invalid selector
asm and ax, 0x0800; // code or data
asm jz invalid; // data, invalid
unsigned short ActualSegmentLimit =
GetSegmentLimit(pTStreamableClass->build);
if (ActualSegmentLimit != SegmentLimit)
{
invalid:
return 0;
}
else
return (GetChecksum(pTStreamableClass->build,
ActualSegmentLimit) == Checksum);
}
#endif // __DLL__
TStreamableClass::TStreamableClass( const char *n, BUILDER b, int d ) :
name( n ),
build( b ),
delta( d )
{
pstream::initTypes();
#if defined(__DLL__)
TObjStrmRegRecord * pTObjStrmRegRecord =
new TObjStrmRegRecord(this);
pstream::types->registerType(pTObjStrmRegRecord);
#else
pstream::types->registerType(this);
#endif
}
#if defined(__DLL__)
void TStreamableTypes::registerType(TObjStrmRegRecord *pTObjStrmRegRecord)
{
unsigned SavedWinAllocFlag = _WinAllocFlag;
_WinAllocFlag |= GMEM_DDESHARE;
insert((void *)pTObjStrmRegRecord);
_WinAllocFlag = SavedWinAllocFlag;
}
#endif
Boolean TStreamableTypes::search( void *key, ccIndex& index )
{
ccIndex l = 0;
ccIndex h = count - 1;
while( l <= h )
{
ccIndex i = (l + h) >> 1;
// i is our midpoint
#if defined(__DLL__)
TObjStrmRegRecord * pTObjStrmRegRecord =
(TObjStrmRegRecord *)items[i];
if (!(pTObjStrmRegRecord->Validate()))
{
// remove this entry
count--;
memmove(&items[i], &items[i+1], (count-i)*sizeof(void *));
h--;
continue; // do the while again
}
#endif
ccIndex c = compare( keyOf( items[i] ), key );
if (c < 0)
l = i + 1;
else if (c > 0)
h = i - 1;
else
{
index = i;
return True;
}
}
index = l;
return False;
}
const TStreamableClass *TStreamableTypes::lookup( const char *name )
{
ccIndex loc;
if (!search((void *)name, loc))
return NULL;
#if defined(__DLL__)
return ((TObjStrmRegRecord *)at(loc))->pTStreamableClass;
#else
return (PTStreamableClass)at(loc);
#endif
}
Pvoid TStreamableTypes::keyOf(Pvoid d)
{
#if defined(__DLL__)
TObjStrmRegRecord * pTObjStrmRegRecord = (TObjStrmRegRecord *)d;
return (void *)((pTObjStrmRegRecord->pTStreamableClass)->name);
#else
return (void *)((PTStreamableClass)d)->name;
#endif
}
int TStreamableTypes::compare( void *d1, void *d2 )
{
return strcmp( (char *)d1, (char *)d2 );
}
void TPWrittenObjects::registerObject( const void *adr )
{
TPWObj *o = new TPWObj( adr, curId++ );
insert( o );
}
P_id_type TPWrittenObjects::find( const void *d )
{
ccIndex loc;
if( search( Pvoid( d ), loc ) )
return ((TPWObj *)at( loc ))->ident;
else
return 0;
}
int TPWrittenObjects::compare( void *o1, void *o2 )
{
if( o1 == o2 )
return 0;
else if( (void huge *)o1 < (void huge *)o2 )
return -1;
else
return 1;
}
void TPReadObjects::registerObject( const void *adr )
{
ccIndex loc = insert( Pvoid( adr ));
assert( loc == curId++ ); // to be sure that TNSCollection
// continues to work the way
// it does now...
}
void _Cdecl pstream::error( StreamableError errorcondition )
{
setstate( errorcondition );
if(errorcondition == peNotRegistered)
MessageBox(
GetApplicationObject()->MainWindow->HWindow,
"Type Not Registered", "PStream Error Condition",
MB_OK | MB_ICONEXCLAMATION);
else
{
assert(errorcondition == peInvalidType);
MessageBox(
GetApplicationObject()->MainWindow->HWindow,
"Invalid Type Encountered", "PStream Error Condition",
MB_OK | MB_ICONEXCLAMATION);
}
clear(ios::badbit);
}
void _Cdecl pstream::error( StreamableError errorcondition, RCTStreamable )
{
error( errorcondition );
}
void pstream::initTypes()
{
if( types == NULL )
{
#if defined(__DLL__)
unsigned SavedWinAllocFlag = _WinAllocFlag;
_WinAllocFlag |= GMEM_DDESHARE;
#endif
types = new TStreamableTypes;
#if defined(__DLL__)
_WinAllocFlag = SavedWinAllocFlag;
#endif
}
}
ipstream& ipstream::seekg( streampos pos )
{
objs.removeAll();
objs.insert( new TPWObj( 0, 0 ));
bp->seekoff( pos, ios::beg );
return *this;
}
ipstream& ipstream::seekg( streamoff off, ios::seek_dir dir )
{
objs.removeAll();
objs.insert( new TPWObj( 0, 0 ));
bp->seekoff( off, dir );
return *this;
}
ushort ipstream::readWord()
{
ushort temp;
bp->sgetn( (char *)&temp, sizeof( ushort ) );
return temp;
}
void ipstream::freadBytes( void far *data, size_t sz )
{
if (sz > 0)
{
char *buf = new char[sz+1];
bp->sgetn( (char *)buf, sz );
_fstrncpy((char far *)data, buf, sz);
delete buf;
}
}
char *ipstream::readString()
{
uchar len = readByte();
char *buf = new char[len+1];
if( buf != 0 )
{
readBytes( buf, len );
buf[len] = EOS;
}
return buf;
}
char *ipstream::readString( char *buf, unsigned maxLen )
{
assert( buf != 0 );
uchar len = readByte();
if( len > maxLen-1 )
len = maxLen; // but see buf[len] = EOS;
readBytes( buf, len );
buf[len] = EOS;
return buf;
}
char far *ipstream::freadString( char far *buf, unsigned maxLen )
{
assert (buf != 0 );
uchar len = readByte();
if( len > maxLen-1 )
len = maxLen; // but see buf[len] = EOS;
freadBytes( buf, len);
buf[len] = EOS;
return buf;
}
char far *ipstream::freadString()
{
uchar len = readByte();
char far *buf = (char far *)farmalloc(len+1);
freadBytes(buf, len);
buf[len] = EOS;
return buf;
}
ipstream& operator >> ( ipstream& ps, signed char &ch )
{
ch = ps.readByte();
return ps;
}
ipstream& operator >> ( ipstream& ps, unsigned char &ch )
{
ch = ps.readByte();
return ps;
}
ipstream& operator >> ( ipstream& ps, signed short &sh )
{
sh = ps.readWord();
return ps;
}
ipstream& operator >> ( ipstream& ps, unsigned short &sh )
{
sh = ps.readWord();
return ps;
}
ipstream& operator >> ( ipstream& ps, signed int &i )
{
i = ps.readWord();
return ps;
}
ipstream& operator >> ( ipstream& ps, unsigned int &i )
{
i = ps.readWord();
return ps;
}
ipstream& operator >> ( ipstream& ps, signed long &l )
{
ps.readBytes( &l, sizeof(l) );
return ps;
}
ipstream& operator >> ( ipstream& ps, unsigned long &l )
{
ps.readBytes( &l, sizeof(l) );
return ps;
}
ipstream& operator >> ( ipstream& ps, float &l )
{
ps.readBytes( &l, sizeof(l) );
return ps;
}
ipstream& operator >> ( ipstream& ps, double &l )
{
ps.readBytes( &l, sizeof(l) );
return ps;
}
ipstream& operator >> ( ipstream& ps, long double &l )
{
ps.readBytes( &l, sizeof(l) );
return ps;
}
ipstream& operator >> ( ipstream& ps, TStreamable& t )
{
const TStreamableClass *pc;
if((pc = ps.readPrefix()) == NULL)
ps.error(pstream::peInvalidType );
ps.readData( pc, &t );
ps.readSuffix();
return ps;
}
ipstream& operator >> ( ipstream& ps, void *&t )
{
char ch = ps.readByte();
switch( ch )
{
case pstream::ptNull:
t = 0;
break;
case pstream::ptIndexed:
{
P_id_type index = ps.readWord();
t = Pvoid( ps.find( index ) );
assert( t != 0 );
break;
}
case pstream::ptObject:
{
const TStreamableClass *pc;
if((pc = ps.readPrefix()) == NULL)
ps.error( pstream::peInvalidType );
t = ps.readData( pc, 0 );
ps.readSuffix();
break;
}
default:
ps.error( pstream::peInvalidType );
break;
}
return ps;
}
const TStreamableClass *ipstream::readPrefix()
{
char ch = readByte();
assert( ch == '[' ); // don't combine this with the previous line!
// We must always do the read, even if we're
// not checking assertions
char name[125];
readString( name, sizeof name );
return types->lookup( name );
}
void *ipstream::readData( const TStreamableClass *c, TStreamable *mem )
{
if( mem == 0 )
mem = c->build();
registerObject( (char *)mem - c->delta ); // register the actual address
// of the object, not the address
// of the TStreamable sub-object
return mem->read( *this );
}
void ipstream::readSuffix()
{
char ch = readByte();
assert( ch == ']' ); // don't combine this with the previous line!
// We must always do the write, even if we're
// not checking assertions
}
opstream& opstream::seekp( streampos pos )
{
objs.removeAll();
objs.insert( new TPWObj( 0, 0 ));
bp->seekoff( pos, ios::beg );
return *this;
}
opstream& opstream::seekp( streamoff pos, ios::seek_dir dir )
{
objs.removeAll();
objs.insert( new TPWObj( 0, 0 ));
bp->seekoff( pos, dir );
return *this;
}
opstream& opstream::flush()
{
bp->sync();
return *this;
}
void opstream::fwriteBytes( const void far *data, size_t sz )
{
if (sz > 0)
{
char *buf = new char[sz+1];
_fstrcpy(buf, (char far *)data);
bp->sputn( (char *)buf, sz );
delete buf;
}
}
void opstream::writeString( const char *str )
{
int len = strlen( str );
writeByte( (uchar)len );
writeBytes( str, len );
}
void opstream::fwriteString( const char far * str )
{
int len = _fstrlen( str );
writeByte( (uchar)len );
fwriteBytes(str, len);
}
opstream& operator << ( opstream& ps, signed char ch )
{
ps.writeByte( ch );
return ps;
}
opstream& operator << ( opstream& ps, unsigned char ch )
{
ps.writeByte( ch );
return ps;
}
opstream& operator << ( opstream& ps, signed short sh )
{
ps.writeWord( sh );
return ps;
}
opstream& operator << ( opstream& ps, unsigned short sh )
{
ps.writeWord( sh );
return ps;
}
opstream& operator << ( opstream& ps, signed int i )
{
ps.writeWord( i );
return ps;
}
opstream& operator << ( opstream& ps, unsigned int i )
{
ps.writeWord( i );
return ps;
}
opstream& operator << ( opstream& ps, signed long l )
{
ps.writeBytes( &l, sizeof(l) );
return ps;
}
opstream& operator << ( opstream& ps, unsigned long l )
{
ps.writeBytes( &l, sizeof(l) );
return ps;
}
opstream& operator << ( opstream& ps, float l )
{
ps.writeBytes( &l, sizeof(l) );
return ps;
}
opstream& operator << ( opstream& ps, double l )
{
ps.writeBytes( &l, sizeof(l) );
return ps;
}
opstream& operator << ( opstream& ps, long double l )
{
ps.writeBytes( &l, sizeof(l) );
return ps;
}
opstream& operator << ( opstream& ps, TStreamable& t )
{
ps.writePrefix( t );
ps.writeData( t );
ps.writeSuffix( t );
return ps;
}
opstream& operator << ( opstream& ps, TStreamable *t )
{
P_id_type index;
if( t == 0 )
ps.writeByte( pstream::ptNull );
else if( (index = ps.find( t )) != 0 )
{
ps.writeByte( pstream::ptIndexed );
ps.writeWord( index );
}
else
{
ps.writeByte( pstream::ptObject );
ps << *t;
}
return ps;
}
void opstream::writePrefix( const TStreamable& t )
{
writeByte( '[' );
writeString( t.streamableName() );
}
void opstream::writeData( TStreamable& t )
{
if ( types->lookup( t.streamableName() ) == NULL )
error( peNotRegistered, t );
else
{
registerObject( &t );
t.write( *this );
}
}
fpbase::fpbase( const char *name, int omode, int prot )
{
pstream::init( &buf );
open( name, omode, prot );
}
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);
}
else
clear(ios::badbit); // open failed
}
void fpbase::attach( int f )
{
if( buf.is_open() )
setstate(ios::failbit);
else if( buf.attach(f) )
clear(ios::goodbit);
else
clear(ios::badbit);
}
void fpbase::close()
{
if( buf.close() )
clear(ios::goodbit);
else
setstate(ios::failbit);
}
void fpbase::setbuf(char* b, int len)
{
if( buf.setbuf(b, len) )
clear(ios::goodbit);
else
setstate(ios::failbit);
}
ifpstream::ifpstream( const char* name, int omode, int prot ) :
fpbase( name, omode | ios::in | ios::binary, prot )
{
}
void ifpstream::open( const char _FAR *name, int omode, int prot )
{
fpbase::open( name, omode | ios::in | ios::binary, prot );
}
ofpstream::ofpstream( const char* name, int omode, int prot ) :
fpbase( name, omode | ios::out | ios::binary, prot )
{
}
void ofpstream::open( const char _FAR *name, int omode, int prot )
{
fpbase::open( name, omode | ios::out | ios::binary, prot );
}
fpstream::fpstream( const char* name, int omode, int prot ) :
fpbase( name, omode | ios::out | ios::binary, prot )
{
}
void fpstream::open( const char _FAR *name, int omode, int prot )
{
fpbase::open( name, omode | ios::in | ios::out | ios::binary, prot );
}