287 lines
7.5 KiB
C
287 lines
7.5 KiB
C
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
||
|
//
|
||
|
// File: stlstream.h
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
//
|
||
|
// stlstream.h: Stream STL template classes.
|
||
|
//
|
||
|
// Templates in this file typically generate functions which take a
|
||
|
// stream reference as an argument, along with a const reference to
|
||
|
// the thing to be streamed; it returns a reference to the stream.
|
||
|
//
|
||
|
// The reason that the stream parameter must be included in the
|
||
|
// template is generate a function which returns the correct stream type.
|
||
|
// If the stream type were not a templated argument, then the
|
||
|
// template would be forced to return a single immutable type, such
|
||
|
// as "ostream". This would cause cascaded stream insertion operators
|
||
|
// to fail to compile, since type errors would occur in the middle of the
|
||
|
// sequence. In the following example, assume that there is a special
|
||
|
// insertion operator defined between class MYSTREAM and class Y:
|
||
|
//
|
||
|
// MYSTREAM myst;
|
||
|
// extern MYSTREAM & operator << ( MYSTREAM & m, const Y & y );
|
||
|
// X x;
|
||
|
// Y y;
|
||
|
//
|
||
|
// myst << x // Template function generated and called
|
||
|
// << y; // ERROR: return value of template function
|
||
|
// // incorrect for special operator above.
|
||
|
//
|
||
|
#ifndef _STLSTREAM_H_
|
||
|
#define _STLSTREAM_H_
|
||
|
|
||
|
#include <iostream> // C++ RTL/STL Streams inclusion
|
||
|
#include <fstream>
|
||
|
|
||
|
#include "mscver.h" // Version-dependent stuff
|
||
|
#include "zstr.h" // ZSTR handling
|
||
|
#include "mdvect.h" // Multi-dimensional vector handling
|
||
|
|
||
|
// Delimiters used in parameter files
|
||
|
#define CH_EOS ((char)0) // End of string
|
||
|
#define CH_DELM_OPEN ((char)'(') // Start of value group
|
||
|
#define CH_DELM_CLOSE ((char)')') // End of value group
|
||
|
#define CH_BLOCK_OPEN ((char)'{') // Start of value block
|
||
|
#define CH_BLOCK_CLOSE ((char)'}') // End of value block
|
||
|
#define CH_INDEX_OPEN ((char)'[') // Name index start
|
||
|
#define CH_INDEX_CLOSE ((char)']') // Name index end
|
||
|
#define CH_PREAMBLE ((char)':') // Delmiter for array size
|
||
|
#define CH_FILL ((char)' ') // Fill character
|
||
|
#define CH_SEP ((char)',') // Value group separator
|
||
|
#define CH_DELM_STR ((char)'\"')
|
||
|
#define CH_META ((char)'\\')
|
||
|
#define CH_DELM_ENTRY ((char)';')
|
||
|
#define CH_EQ ((char)'=')
|
||
|
#define CH_NAME_SEP ((char)'.')
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// Read and write STL pairs from or to a stream
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
template<class _OS, class _First, class _Second> inline
|
||
|
_OS & operator << (_OS & os, const pair<_First,_Second> & pr)
|
||
|
{
|
||
|
os << CH_DELM_OPEN;
|
||
|
os << pr.first;
|
||
|
os << pr.second;
|
||
|
os << CH_DELM_CLOSE;
|
||
|
return os;
|
||
|
}
|
||
|
|
||
|
template<class _IS, class _First, class _Second> inline
|
||
|
_IS & operator >> (_IS & is, pair<_First,_Second> & pr)
|
||
|
{
|
||
|
char ch;
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_OPEN)
|
||
|
_THROW1(runtime_error("invalid block: pair >> (1)"));
|
||
|
|
||
|
is >> pr.first;
|
||
|
is >> pr.second;
|
||
|
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_CLOSE)
|
||
|
_THROW1(runtime_error("invalid block: pair >> (2)"));
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// Read and write STL vectors from or to a stream
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
template<class _OS, class _T> inline
|
||
|
_OS & operator << (_OS & os, const vector<_T>& vt )
|
||
|
{
|
||
|
os << CH_DELM_OPEN;
|
||
|
os << (UINT) vt.size();
|
||
|
os << CH_PREAMBLE;
|
||
|
for ( size_t i = 0; i < vt.size(); )
|
||
|
{
|
||
|
os << vt[i];
|
||
|
if ( ++i != vt.size() )
|
||
|
os << ',' ;
|
||
|
}
|
||
|
os << CH_DELM_CLOSE;
|
||
|
return os;
|
||
|
}
|
||
|
|
||
|
template<class _IS, class _T> inline
|
||
|
_IS & operator >> (_IS & is, vector<_T>& vt )
|
||
|
{
|
||
|
char ch;
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_OPEN)
|
||
|
_THROW1(runtime_error("invalid block: vector>> (1)"));
|
||
|
size_t l;
|
||
|
is >> l;
|
||
|
is >> ch;
|
||
|
if (ch != CH_PREAMBLE)
|
||
|
_THROW1(runtime_error("invalid block: vector>> (2)"));
|
||
|
|
||
|
vt.resize(l);
|
||
|
for ( size_t i = 0 ; i < l; )
|
||
|
{
|
||
|
_T it;
|
||
|
is >> it;
|
||
|
vt[i] = it;
|
||
|
if ( ++i < l )
|
||
|
{
|
||
|
is >> ch;
|
||
|
if (ch != CH_SEP)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( i != l )
|
||
|
_THROW1(runtime_error("invalid block: vector>> (3)"));
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_CLOSE)
|
||
|
_THROW1(runtime_error("invalid block: vector>> (4)"));
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// Read and write STL valarrays from or to a stream
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
template<class _OS, class _T> inline
|
||
|
_OS & operator << ( _OS & os, const valarray<_T>& vt )
|
||
|
{
|
||
|
os << CH_DELM_OPEN;
|
||
|
os << (UINT) vt.size();
|
||
|
os << CH_PREAMBLE;
|
||
|
for ( int i = 0;
|
||
|
i < vt.size() ; )
|
||
|
{
|
||
|
os << vt[i];
|
||
|
if ( ++i != vt.size() )
|
||
|
os << ',' ;
|
||
|
}
|
||
|
os << CH_DELM_CLOSE;
|
||
|
return os;
|
||
|
}
|
||
|
|
||
|
template<class _IS, class _T> inline
|
||
|
_IS & operator >> (_IS & is, valarray<_T>& vt )
|
||
|
{
|
||
|
char ch;
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_OPEN)
|
||
|
_THROW1(runtime_error("invalid block: valarray >> (1)"));
|
||
|
size_t l;
|
||
|
is >> l;
|
||
|
is >> ch;
|
||
|
if (ch != CH_PREAMBLE)
|
||
|
_THROW1(runtime_error("invalid block: valarray >> (2)"));
|
||
|
|
||
|
vt.resize(l);
|
||
|
for ( size_t i = 0 ; i < l; )
|
||
|
{
|
||
|
_T it;
|
||
|
is >> it;
|
||
|
vt[i] = it;
|
||
|
if ( ++i < l )
|
||
|
{
|
||
|
is >> ch;
|
||
|
if (ch != CH_SEP)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( i != l )
|
||
|
_THROW1(runtime_error("invalid block: valarray >> (3)"));
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_CLOSE)
|
||
|
_THROW1(runtime_error("invalid block: valarray >> (4)"));
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// Read and write MDVSLICEs from or to a stream
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
template<class _OS> inline
|
||
|
_OS & operator << (_OS & os, const MDVSLICE & mslice )
|
||
|
{
|
||
|
os << CH_DELM_OPEN;
|
||
|
os << (UINT) mslice.start();
|
||
|
os << mslice.size();
|
||
|
os << mslice.stride();
|
||
|
os << CH_DELM_CLOSE;
|
||
|
return os;
|
||
|
}
|
||
|
|
||
|
template<class _IS> inline
|
||
|
_IS & operator >> ( _IS & is, MDVSLICE & mslice )
|
||
|
{
|
||
|
char ch;
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_OPEN)
|
||
|
_THROW1(runtime_error("invalid block: slice >> (1)"));
|
||
|
VIMD vimdLen;
|
||
|
VIMD vimdStride;
|
||
|
size_t lStart;
|
||
|
is >> lStart;
|
||
|
is >> vimdLen;
|
||
|
is >> vimdStride;
|
||
|
mslice = MDVSLICE( lStart, vimdLen, vimdStride );
|
||
|
|
||
|
is >> ch;
|
||
|
if (ch != CH_DELM_CLOSE)
|
||
|
_THROW1(runtime_error("invalid block: slice >> (2)"));
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// Format (pretty-print) MDVDENSEs using an Iterator.
|
||
|
//
|
||
|
// This is NOT the same as streaming out an MDVDENSE; it formats the array for
|
||
|
// easy reading. Note that it requires an Iterator.
|
||
|
//
|
||
|
// MSRDEVBUG: This, too, should be templatized, but there's a bug in template
|
||
|
// expansion using nested class names.
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
inline
|
||
|
ostream & operator << ( ostream & os, TMDVDENSE<double>::Iterator & itmdv )
|
||
|
{
|
||
|
os << "\ndump of mdvect,\n\t\tslice = "
|
||
|
<< itmdv.Slice();
|
||
|
|
||
|
if ( itmdv.Slice() != itmdv.Mdv().Slice() )
|
||
|
{
|
||
|
os << ",\n\t\toriginal slice = "
|
||
|
<< itmdv.Mdv().Slice();
|
||
|
}
|
||
|
if ( itmdv.BReorder() )
|
||
|
{
|
||
|
os << ",\n\t\treordered ";
|
||
|
os << itmdv.VimdReorder();
|
||
|
}
|
||
|
os << '.';
|
||
|
itmdv.Reset();
|
||
|
for ( int ii = 0 ; itmdv.BNext() ; ii++ )
|
||
|
{
|
||
|
const VIMD & vimd = itmdv.Vitmd();
|
||
|
cout << "\n\t[";
|
||
|
for ( int i = 0 ; i < vimd.size(); i++ )
|
||
|
{
|
||
|
cout << vimd[i];
|
||
|
if ( i + 1 < vimd.size() )
|
||
|
cout << ",";
|
||
|
}
|
||
|
size_t indx = itmdv.Indx();
|
||
|
const double & t = itmdv.Next();
|
||
|
cout << "] ("
|
||
|
<< ii
|
||
|
<< '='
|
||
|
<< (UINT) indx
|
||
|
<< ") = "
|
||
|
<< t;
|
||
|
}
|
||
|
return os;
|
||
|
}
|
||
|
|
||
|
#endif // _STLSTREAM_H_
|