mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
7.9 KiB
342 lines
7.9 KiB
//-----------------------------------------------------------------------------
|
|
// SSBuf.h
|
|
//
|
|
// Copyright (C) 1995, Microsoft Corporation
|
|
//
|
|
// Purpose:
|
|
// Subclass Map, Set, and Array templates to handle versioning and
|
|
// reloading directly from a stream.
|
|
//
|
|
// Revision History:
|
|
//
|
|
// [] 13-Jan-1995 Dans Created
|
|
// [] 16-Apr-1995 Dans Added ArrayVer<> template
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if !defined(_ssbuf_h)
|
|
#define _ssbuf_h 1
|
|
|
|
// Depends on buffer.h
|
|
#include <stdlib.h>
|
|
#include <search.h>
|
|
|
|
#include <array.h>
|
|
#include <map.h>
|
|
#include <set.h>
|
|
#include <misc.h>
|
|
|
|
//
|
|
// All streams and sub-streams hav this header followed by the
|
|
// stream specific data
|
|
//
|
|
struct STRMHDR {
|
|
DWORD dwSig;
|
|
union {
|
|
DWORD cEntries;
|
|
DWORD cb;
|
|
};
|
|
long lVer;
|
|
DWORD dwReserved;
|
|
};
|
|
|
|
template <unsigned _cbExtra>
|
|
struct UserHdr {
|
|
unsigned __int32 cb;
|
|
BYTE rgb[ _cbExtra ];
|
|
};
|
|
|
|
//
|
|
// Versioned Maps
|
|
//
|
|
template <class D, class R, class H, unsigned _cbExtra>
|
|
class MapVer : public Map<D, R, H> {
|
|
|
|
private:
|
|
enum { sig = sigMagic };
|
|
typedef Map<D,R,H> BaseClass;
|
|
typedef UserHdr<_cbExtra> UsrHdr;
|
|
|
|
long m_lVer;
|
|
UsrHdr m_usrhdr;
|
|
|
|
public:
|
|
MapVer ( long lVer ) {
|
|
m_lVer = lVer;
|
|
m_usrhdr.cb = _cbExtra;
|
|
memset ( m_usrhdr.rgb, 0, _cbExtra );
|
|
}
|
|
// overload the relevant functions to handle the versioning
|
|
CB cbSave() const;
|
|
BOOL save ( Buffer * );
|
|
BOOL reload ( PB * );
|
|
// couple of supporting functions for user headers and direct
|
|
// to stream ops.
|
|
BOOL reloadStream ( Stream * );
|
|
BYTE * PbUserData();
|
|
};
|
|
|
|
template <class D, class R, class H, unsigned _cbExtra> inline
|
|
CB MapVer<D,R,H,_cbExtra>::cbSave() const {
|
|
return sizeof STRMHDR + sizeof UsrHdr + BaseClass::cbSave();
|
|
}
|
|
|
|
template <class D, class R, class H, unsigned _cbExtra>
|
|
BOOL MapVer<D,R,H,_cbExtra>::save ( Buffer * pbuf ) {
|
|
STRMHDR hdr = { sig, cbSave(), m_lVer, 0 };
|
|
assert ( m_usrhdr.cb == _cbExtra );
|
|
return
|
|
pbuf->Append ( PB(&hdr), sizeof(hdr) ) &&
|
|
pbuf->Append ( PB(&m_usrhdr), sizeof(m_usrhdr) ) &&
|
|
BaseClass::save ( pbuf );
|
|
}
|
|
|
|
template <class D, class R, class H, unsigned _cbExtra>
|
|
BOOL MapVer<D,R,H,_cbExtra>::reload ( PB * ppb ) {
|
|
STRMHDR hdr;
|
|
BOOL fRet = fFalse;
|
|
|
|
debug(PB pbT = *ppb;)
|
|
|
|
hdr = *(STRMHDR UNALIGNED *) *ppb;
|
|
if ( hdr.dwSig == sig && hdr.cb > sizeof(hdr) && hdr.lVer == m_lVer ) {
|
|
*ppb += sizeof(hdr);
|
|
// reload the user data
|
|
unsigned __int32 cbUser;
|
|
cbUser = __min ( *(unsigned __int32 UNALIGNED *)*ppb, _cbExtra );
|
|
*ppb += sizeof(unsigned __int32);
|
|
memcpy ( &m_usrhdr.rgb[0], *ppb, cbUser );
|
|
*ppb += _cbExtra;
|
|
|
|
// now do the actual map class
|
|
fRet = BaseClass::reload ( ppb );
|
|
assert ( pbT + hdr.cb == *ppb );
|
|
}
|
|
else {
|
|
// something bogus is going on, skip the header...
|
|
*ppb += max ( hdr.cb, sizeof(hdr) );
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
template <class D, class R, class H, unsigned _cbExtra>
|
|
BOOL MapVer<D,R,H,_cbExtra>::reloadStream ( Stream * pstream ) {
|
|
PB pb;
|
|
CB cb = pstream->QueryCb();
|
|
BOOL fRet = fFalse;
|
|
|
|
if ( cb > 0 ) {
|
|
Buffer buf;
|
|
if ( buf.Reserve ( cb, &pb ) ) {
|
|
if ( pstream->Read2 ( 0, pb, cb ) ) {
|
|
fRet = reload ( &pb );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
fRet = fTrue;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
template <class D, class R, class H, unsigned _cbExtra> inline
|
|
BYTE * MapVer<D,R,H,_cbExtra>::PbUserData() {
|
|
//precondition ( _cbExtra );
|
|
return _cbExtra ? &m_usrhdr.rgb[0] : NULL;
|
|
}
|
|
|
|
//
|
|
// Versioned Sets
|
|
//
|
|
template <class D, class H, unsigned _cbExtra>
|
|
class SetVer : public Set<D,H> {
|
|
private:
|
|
enum { sig = sigMagic };
|
|
typedef Set<D,H> BaseClass;
|
|
typedef UserHdr<_cbExtra> UsrHdr;
|
|
|
|
long m_lVer;
|
|
UsrHdr m_usrhdr;
|
|
|
|
public:
|
|
SetVer ( long lVer ) {
|
|
m_lVer = lVer;
|
|
m_usrhdr.cb = _cbExtra;
|
|
}
|
|
// overload the relevant functions to handle the versioning
|
|
CB cbSave() const;
|
|
BOOL save ( Buffer * );
|
|
BOOL reload ( PB * );
|
|
// couple of supporting functions for user headers and direct
|
|
// to stream ops.
|
|
BOOL reloadStream ( Stream * );
|
|
BYTE * PbUserData();
|
|
};
|
|
|
|
template <class D, class H, unsigned _cbExtra> inline
|
|
CB SetVer<D,H,_cbExtra>::cbSave() const {
|
|
return sizeof STRMHDR + sizeof UsrHdr + BaseClass::cbSave();
|
|
}
|
|
|
|
template <class D, class H, unsigned _cbExtra> inline
|
|
BOOL SetVer<D,H,_cbExtra>::save ( Buffer * pbuf ) {
|
|
STRMHDR hdr = { sig, cbSave(), m_lVer, 0 };
|
|
assert ( m_usrhdr.cb == _cbExtra );
|
|
|
|
return
|
|
pbuf->Append ( PB(&hdr), sizeof(hdr) ) &&
|
|
pbuf->Append ( PB(&m_usrhdr), sizeof(m_usrhdr) ) &&
|
|
BaseClass::save ( pbuf );
|
|
}
|
|
|
|
template <class D, class H, unsigned _cbExtra>
|
|
BOOL SetVer<D,H,_cbExtra>::reload ( PB * ppb ) {
|
|
STRMHDR hdr;
|
|
BOOL fRet = fFalse;
|
|
debug(PB pbT = *ppb;)
|
|
|
|
hdr = *(STRMHDR UNALIGNED *) *ppb;
|
|
if ( hdr.dwSig == sig && hdr.cb > sizeof(hdr) && hdr.lVer == m_lVer ) {
|
|
*ppb += sizeof(hdr);
|
|
// reload the user data
|
|
unsigned __int32 cbUser;
|
|
cbUser = __min ( *(unsigned __int32 UNALIGNED *)*ppb, _cbExtra );
|
|
*ppb += sizeof(unsigned __int32);
|
|
memcpy ( &m_usrhdr.rgb[0], *ppb, cbUser );
|
|
*ppb += _cbExtra;
|
|
|
|
// now do the actual set class
|
|
fRet = BaseClass::reload ( ppb );
|
|
assert ( pbT + hdr.cb == *ppb );
|
|
}
|
|
else {
|
|
// something bogus is going on, skip the header...
|
|
*ppb += max(hdr.cb, sizeof(hdr));
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
template <class D, class H, unsigned _cbExtra>
|
|
BOOL SetVer<D,H,_cbExtra>::reloadStream ( Stream * pstream ) {
|
|
PB pb;
|
|
CB cb = pstream->QueryCb();
|
|
BOOL fRet = fFalse;
|
|
|
|
if ( cb > 0 ) {
|
|
Buffer buf;
|
|
if ( buf.Reserve ( cb, &pb ) ) {
|
|
if ( pstream->Read2 ( 0, pb, cb ) ) {
|
|
fRet = reload ( &pb );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
fRet = fTrue;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
template <class D, class H, unsigned _cbExtra> inline
|
|
BYTE * SetVer<D,H,_cbExtra>::PbUserData() {
|
|
precondition ( _cbExtra );
|
|
return _cbExtra ? &m_usrhdr.rgb[0] : NULL;
|
|
}
|
|
|
|
//
|
|
// Versioned arrays
|
|
//
|
|
template <class T, unsigned _cbExtra>
|
|
class ArrayVer : public Array<T> {
|
|
private:
|
|
enum { sig = sigMagic };
|
|
typedef Array<T> BaseClass;
|
|
typedef UserHdr<_cbExtra> UsrHdr;
|
|
|
|
long m_lVer;
|
|
UsrHdr m_usrhdr;
|
|
|
|
public:
|
|
ArrayVer ( long lVer ) {
|
|
m_lVer = lVer;
|
|
m_usrhdr.cb = _cbExtra;
|
|
memset ( m_usrhdr.rgb, 0, _cbExtra );
|
|
}
|
|
// overload the relevant functions to handle the versioning
|
|
CB cbSave() const;
|
|
BOOL save ( Buffer * );
|
|
BOOL reload ( PB * );
|
|
// couple of supporting functions for user headers and direct
|
|
// to stream ops.
|
|
BOOL reloadStream ( Stream * );
|
|
BYTE * PbUserData();
|
|
};
|
|
|
|
template <class T, unsigned _cbExtra> inline
|
|
CB ArrayVer<T,_cbExtra>::cbSave() const {
|
|
return sizeof STRMHDR + sizeof UsrHdr + BaseClass::cbSave();
|
|
}
|
|
|
|
template <class T, unsigned _cbExtra>
|
|
BOOL ArrayVer<T,_cbExtra>::save ( Buffer * pbuf ) {
|
|
STRMHDR hdr = { sig, cbSave(), m_lVer, 0 };
|
|
assert ( m_usrhdr.cb == _cbExtra );
|
|
return
|
|
pbuf->Append ( PB(&hdr), sizeof(hdr) ) &&
|
|
pbuf->Append ( PB(&m_usrhdr), sizeof(m_usrhdr) ) &&
|
|
BaseClass::save ( pbuf );
|
|
}
|
|
|
|
template <class T, unsigned _cbExtra>
|
|
BOOL ArrayVer<T,_cbExtra>::reload ( PB * ppb ) {
|
|
STRMHDR hdr;
|
|
BOOL fRet = fFalse;
|
|
|
|
debug(PB pbT = *ppb;)
|
|
|
|
hdr = *(STRMHDR UNALIGNED *) *ppb;
|
|
if ( hdr.dwSig == sig && hdr.cb > sizeof(hdr) && hdr.lVer == m_lVer ) {
|
|
*ppb += sizeof(hdr);
|
|
// reload the user data
|
|
unsigned __int32 cbUser;
|
|
cbUser = __min ( *(unsigned __int32 UNALIGNED *)*ppb, _cbExtra );
|
|
*ppb += sizeof(unsigned __int32);
|
|
memcpy ( &m_usrhdr.rgb[0], *ppb, cbUser );
|
|
*ppb += _cbExtra;
|
|
|
|
// now do the actual array
|
|
fRet = BaseClass::reload ( ppb );
|
|
assert ( pbT + hdr.cb == *ppb );
|
|
}
|
|
else {
|
|
// something bogus is going on, skip the header...
|
|
*ppb += max ( hdr.cb, sizeof(hdr) );
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
template <class T, unsigned _cbExtra>
|
|
BOOL ArrayVer<T,_cbExtra>::reloadStream ( Stream * pstream ) {
|
|
PB pb;
|
|
CB cb = pstream->QueryCb();
|
|
BOOL fRet = fFalse;
|
|
|
|
if ( cb > 0 ) {
|
|
Buffer buf;
|
|
if ( buf.Reserve ( cb, &pb ) ) {
|
|
if ( pstream->Read2 ( 0, pb, cb ) ) {
|
|
fRet = reload ( &pb );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
fRet = fTrue;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
template <class T, unsigned _cbExtra>
|
|
BYTE * ArrayVer<T,_cbExtra>::PbUserData() {
|
|
//precondition ( _cbExtra );
|
|
return _cbExtra ? &m_usrhdr.rgb[0] : NULL;
|
|
}
|
|
|
|
#endif
|