//------------------------------------------------------------------------------

// File: PStream.cpp

//

// Desc: DirectShow base classes.

//

// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.

//------------------------------------------------------------------------------





#include "streams.h"



#ifdef PERF

#include <measure.h>

#endif

// #include "pstream.h"  in streams.h



//

// Constructor

//

CPersistStream::CPersistStream(IUnknown *punk, HRESULT *phr)

    : mPS_fDirty(FALSE)

{

    mPS_dwFileVersion = GetSoftwareVersion();

}





//

// Destructor

//

CPersistStream::~CPersistStream() {

    // Nothing to do

}



#if 0

SAMPLE CODE TO COPY - not active at the moment



//

// NonDelegatingQueryInterface

//

// This object supports IPersist & IPersistStream

STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, void **ppv)

{

    if (riid == IID_IPersist) {

        return GetInterface((IPersist *) this, ppv);      // ???

    }

    else if (riid == IID_IPersistStream) {

        return GetInterface((IPersistStream *) this, ppv);

    }

    else {

        return CUnknown::NonDelegatingQueryInterface(riid, ppv);

    }

}

#endif





//

// WriteToStream

//

// Writes to the stream (default action is to write nothing)

HRESULT CPersistStream::WriteToStream(IStream *pStream)

{

    // You can override this to do things like

    // hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL);



    return NOERROR;

}







HRESULT CPersistStream::ReadFromStream(IStream * pStream)

{

    // You can override this to do things like

    // hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL);



    return NOERROR;

}





//

// Load

//

// Load all the data from the given stream

STDMETHODIMP CPersistStream::Load(LPSTREAM pStm)

{

    HRESULT hr;

    // Load the version number then the data

    mPS_dwFileVersion = ReadInt(pStm, hr);

    if (FAILED(hr)) {

        return hr;

    }



    return ReadFromStream(pStm);

}  // Load







//

// Save

//

// Save the contents of this Stream.

STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty)

{



    HRESULT hr = WriteInt(pStm, GetSoftwareVersion());

    if (FAILED(hr)) {

        return hr;

    }



    hr = WriteToStream(pStm);

    if (FAILED(hr)) {

        return hr;

    }



    mPS_fDirty = !fClearDirty;



    return hr;

} // Save





// WriteInt

//

// Writes an integer to an IStream as 11 UNICODE characters followed by one space.

// You could use this for shorts or unsigneds or anything (up to 32 bits)

// where the value isn't actually truncated by squeezing it into 32 bits.

// Values such as (unsigned) 0x80000000 would come out as -2147483648

// but would then load as 0x80000000 through ReadInt.  Cast as you please.



STDAPI WriteInt(IStream *pIStream, int n)

{

    WCHAR Buff[13];  // Allows for trailing null that we don't write

    wsprintfW(Buff, L"%011d ",n);

    return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL);

} // WriteInt





// ReadInt

//

// Reads an integer from an IStream.

// Read as 4 bytes.  You could use this for shorts or unsigneds or anything

// where the value isn't actually truncated by squeezing it into 32 bits

// Striped down subset of what sscanf can do (without dragging in the C runtime)



STDAPI_(int) ReadInt(IStream *pIStream, HRESULT &hr)

{



    int Sign = 1;

    unsigned int n = 0;    // result wil be n*Sign

    WCHAR wch;



    hr = pIStream->Read( &wch, sizeof(wch), NULL);

    if (FAILED(hr)) {

        return 0;

    }



    if (wch==L'-'){

        Sign = -1;

        hr = pIStream->Read( &wch, sizeof(wch), NULL);

        if (FAILED(hr)) {

            return 0;

        }

    }



    for( ; ; ) {

        if (wch>=L'0' && wch<=L'9') {

            n = 10*n+(int)(wch-L'0');

        } else if (  wch == L' '

                  || wch == L'\t'

                  || wch == L'\r'

                  || wch == L'\n'

                  || wch == L'\0'

                  ) {

            break;

        } else {

            hr = VFW_E_INVALID_FILE_FORMAT;

            return 0;

        }



        hr = pIStream->Read( &wch, sizeof(wch), NULL);

        if (FAILED(hr)) {

            return 0;

        }

    }



    if (n==0x80000000 && Sign==-1) {

        // This is the negative number that has no positive version!

        return (int)n;

    }

    else return (int)n * Sign;

} // ReadInt





// The microsoft C/C++ compile generates level 4 warnings to the effect that

// a particular inline function (from some base class) was not needed.

// This line gets rid of hundreds of such unwanted messages and makes

// -W4 compilation feasible:

#pragma warning(disable: 4514)

