/*--------------------------------------------------------------------------* * * 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 #include /*+-------------------------------------------------------------------------* * ReadScalar * * Reads a scalar value from a stream. *--------------------------------------------------------------------------*/ template 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 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 static IStream& ReadString (IStream& stm, std::basic_string& str) { /* * read the length */ DWORD cch; stm >> cch; /* * allocate a buffer for the characters */ std::auto_ptr 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 static IStream& WriteString (IStream& stm, const std::basic_string& 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 static void ReadScalarVector (IStream* pstm, std::vector& 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 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 static void WriteScalarVector (IStream* pstm, const std::vector& 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) * Efficiently extracts an entire vector collection of scalar types * (written by insert_collection) from an IStream. * * insert_collection (specializations for std::vector) * Efficiently inserts an entire vector of scalar types into an IStream. *--------------------------------------------------------------------------*/ #define DefineScalarVectorStreamFunctions(scalar_type) \ void extract_vector (IStream* pstm, std::vector& v) \ { ReadScalarVector (pstm, v); } \ void insert_collection (IStream* pstm, const std::vector& 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);