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.
305 lines
9.6 KiB
305 lines
9.6 KiB
/*--------------------------------------------------------------------------*
|
|
*
|
|
* Microsoft Windows
|
|
* Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
*
|
|
* File: stgio.h
|
|
*
|
|
* Contents: Interface file structured storage I/O utilities
|
|
*
|
|
* History: 25-Jun-98 jeffro Created
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
#include "stgio.h"
|
|
#include "stddbg.h"
|
|
#include "macros.h"
|
|
#include <comdef.h>
|
|
#include <tchar.h>
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* ReadScalar
|
|
*
|
|
* Reads a scalar value from a stream.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
template<class T>
|
|
static IStream& ReadScalar (IStream& stm, T& t)
|
|
{
|
|
ULONG cbActuallyRead;
|
|
HRESULT hr = stm.Read (&t, sizeof (t), &cbActuallyRead);
|
|
THROW_ON_FAIL (hr);
|
|
|
|
if (cbActuallyRead != sizeof (t))
|
|
_com_issue_error (E_FAIL);
|
|
|
|
return (stm);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* WriteScalar
|
|
*
|
|
* Writes a scalar value to a stream.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
template<class T>
|
|
static IStream& WriteScalar (IStream& stm, const T& t)
|
|
{
|
|
ULONG cbActuallyWritten;
|
|
HRESULT hr = stm.Write (&t, sizeof (t), &cbActuallyWritten);
|
|
THROW_ON_FAIL (hr);
|
|
|
|
if (cbActuallyWritten != sizeof (t))
|
|
_com_issue_error (E_FAIL);
|
|
|
|
return (stm);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* ReadString
|
|
*
|
|
* Reads a std::basic_string from a stream. The string should have been
|
|
* written with a DWORD character count preceding an array of characters
|
|
* that is not NULL-terminated.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
template<class E, class Tr, class A>
|
|
static IStream& ReadString (IStream& stm, std::basic_string<E,Tr,A>& str)
|
|
{
|
|
/*
|
|
* read the length
|
|
*/
|
|
DWORD cch;
|
|
stm >> cch;
|
|
|
|
/*
|
|
* allocate a buffer for the characters
|
|
*/
|
|
std::auto_ptr<E> spBuffer (new (std::nothrow) E[cch + 1]);
|
|
E* pBuffer = spBuffer.get();
|
|
|
|
if (pBuffer == NULL)
|
|
_com_issue_error (E_OUTOFMEMORY);
|
|
|
|
/*
|
|
* read the characters
|
|
*/
|
|
ULONG cbActuallyRead;
|
|
const ULONG cbToRead = cch * sizeof (E);
|
|
HRESULT hr = stm.Read (pBuffer, cbToRead, &cbActuallyRead);
|
|
THROW_ON_FAIL (hr);
|
|
|
|
if (cbToRead != cbActuallyRead)
|
|
_com_issue_error (E_FAIL);
|
|
|
|
/*
|
|
* terminate the character array and assign it to the string
|
|
*/
|
|
pBuffer[cch] = 0;
|
|
|
|
/*
|
|
* assign it to the string (clear the string first to work around
|
|
* the bug described in KB Q172398)
|
|
*/
|
|
str.erase();
|
|
str = pBuffer;
|
|
|
|
return (stm);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* WriteString
|
|
*
|
|
* Writes a std::basic_string to a stream. The string is written with a
|
|
* DWORD character count preceding an array of characters that is not
|
|
* NULL-terminated.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
template<class E, class Tr, class A>
|
|
static IStream& WriteString (IStream& stm, const std::basic_string<E,Tr,A>& str)
|
|
{
|
|
/*
|
|
* write the length
|
|
*/
|
|
DWORD cch = str.length();
|
|
stm << cch;
|
|
|
|
if (cch > 0)
|
|
{
|
|
/*
|
|
* write the characters
|
|
*/
|
|
ULONG cbActuallyWritten;
|
|
const ULONG cbToWrite = cch * sizeof (E);
|
|
HRESULT hr = stm.Write (str.data(), cbToWrite, &cbActuallyWritten);
|
|
THROW_ON_FAIL (hr);
|
|
|
|
if (cbToWrite != cbActuallyWritten)
|
|
_com_issue_error (E_FAIL);
|
|
}
|
|
|
|
return (stm);
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* operator<<, operator>>
|
|
*
|
|
* Stream insertion and extraction operators for various types
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
#define DefineScalarStreamOperators(scalar_type) \
|
|
IStream& operator>> (IStream& stm, scalar_type& t) \
|
|
{ return (ReadScalar (stm, t)); } \
|
|
IStream& operator<< (IStream& stm, scalar_type t) \
|
|
{ return (WriteScalar (stm, t)); }
|
|
|
|
#define DefineScalarStreamOperatorsByRef(scalar_type) \
|
|
IStream& operator>> (IStream& stm, scalar_type& t) \
|
|
{ return (ReadScalar (stm, t)); } \
|
|
IStream& operator<< (IStream& stm, const scalar_type& t) \
|
|
{ return (WriteScalar (stm, t)); }
|
|
|
|
DefineScalarStreamOperators (bool);
|
|
DefineScalarStreamOperators ( char);
|
|
DefineScalarStreamOperators (unsigned char);
|
|
DefineScalarStreamOperators ( short);
|
|
DefineScalarStreamOperators (unsigned short);
|
|
DefineScalarStreamOperators ( int);
|
|
DefineScalarStreamOperators (unsigned int);
|
|
DefineScalarStreamOperators ( long);
|
|
DefineScalarStreamOperators (unsigned long);
|
|
DefineScalarStreamOperators ( __int64);
|
|
DefineScalarStreamOperators (unsigned __int64);
|
|
DefineScalarStreamOperators (float);
|
|
DefineScalarStreamOperators (double);
|
|
DefineScalarStreamOperators (long double);
|
|
DefineScalarStreamOperatorsByRef (CLSID);
|
|
|
|
IStream& operator>> (IStream& stm, std::string& str)
|
|
{ return (ReadString (stm, str)); }
|
|
IStream& operator<< (IStream& stm, const std::string& str)
|
|
{ return (WriteString (stm, str)); }
|
|
|
|
IStream& operator>> (IStream& stm, std::wstring& str)
|
|
{ return (ReadString (stm, str)); }
|
|
IStream& operator<< (IStream& stm, const std::wstring& str)
|
|
{ return (WriteString (stm, str)); }
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* ReadScalarVector
|
|
*
|
|
* Reads an entire vector collection of scalar types (written by
|
|
* insert_collection) from an IStream.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
template<class T>
|
|
static void ReadScalarVector (IStream* pstm, std::vector<T>& v)
|
|
{
|
|
/*
|
|
* clear out the current container
|
|
*/
|
|
v.clear();
|
|
|
|
/*
|
|
* read the number of items
|
|
*/
|
|
DWORD cItems;
|
|
*pstm >> cItems;
|
|
|
|
if (cItems > 0)
|
|
{
|
|
/*
|
|
* allocate a buffer for the elements
|
|
*/
|
|
std::auto_ptr<T> spBuffer (new (std::nothrow) T[cItems]);
|
|
T* pBuffer = spBuffer.get();
|
|
|
|
if (pBuffer == NULL)
|
|
_com_issue_error (E_OUTOFMEMORY);
|
|
|
|
/*
|
|
* read the elements
|
|
*/
|
|
ULONG cbActuallyRead;
|
|
const ULONG cbToRead = cItems * sizeof (T);
|
|
HRESULT hr = pstm->Read (pBuffer, cbToRead, &cbActuallyRead);
|
|
THROW_ON_FAIL (hr);
|
|
|
|
if (cbToRead != cbActuallyRead)
|
|
_com_issue_error (E_FAIL);
|
|
|
|
/*
|
|
* assign the elements to the vector
|
|
*/
|
|
v.assign (pBuffer, pBuffer + cItems);
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* WriteScalarVector
|
|
*
|
|
* Writes an entire vector of scalar types to an IStream. Note that this
|
|
* code assumes that vectors store their elements sequentially.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
template<class T>
|
|
static void WriteScalarVector (IStream* pstm, const std::vector<T>& v)
|
|
{
|
|
/*
|
|
* write the size
|
|
*/
|
|
DWORD cItems = v.size();
|
|
*pstm << cItems;
|
|
|
|
if (cItems > 0)
|
|
{
|
|
/*
|
|
* write the elements
|
|
*/
|
|
ULONG cbActuallyWritten;
|
|
const ULONG cbToWrite = cItems * sizeof (T);
|
|
HRESULT hr = pstm->Write (v.begin(), cbToWrite, &cbActuallyWritten);
|
|
THROW_ON_FAIL (hr);
|
|
|
|
if (cbToWrite != cbActuallyWritten)
|
|
_com_issue_error (E_FAIL);
|
|
}
|
|
}
|
|
|
|
|
|
/*+-------------------------------------------------------------------------*
|
|
* extract_vector (specialization for std::vector<scalar>)
|
|
* Efficiently extracts an entire vector collection of scalar types
|
|
* (written by insert_collection) from an IStream.
|
|
*
|
|
* insert_collection (specializations for std::vector<scalar>)
|
|
* Efficiently inserts an entire vector of scalar types into an IStream.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
#define DefineScalarVectorStreamFunctions(scalar_type) \
|
|
void extract_vector (IStream* pstm, std::vector<scalar_type>& v) \
|
|
{ ReadScalarVector (pstm, v); } \
|
|
void insert_collection (IStream* pstm, const std::vector<scalar_type>& v)\
|
|
{ WriteScalarVector (pstm, v); }
|
|
|
|
DefineScalarVectorStreamFunctions (bool);
|
|
DefineScalarVectorStreamFunctions ( char);
|
|
DefineScalarVectorStreamFunctions (unsigned char);
|
|
DefineScalarVectorStreamFunctions ( short);
|
|
DefineScalarVectorStreamFunctions (unsigned short);
|
|
DefineScalarVectorStreamFunctions ( int);
|
|
DefineScalarVectorStreamFunctions (unsigned int);
|
|
DefineScalarVectorStreamFunctions ( long);
|
|
DefineScalarVectorStreamFunctions (unsigned long);
|
|
DefineScalarVectorStreamFunctions ( __int64);
|
|
DefineScalarVectorStreamFunctions (unsigned __int64);
|
|
DefineScalarVectorStreamFunctions (float);
|
|
DefineScalarVectorStreamFunctions (double);
|
|
DefineScalarVectorStreamFunctions (long double);
|