/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * Change History
 Jan 2005			Created
 ************************************************************************/

#include "lwpobjstrm.hxx"
#include "lwptools.hxx"

/**
 * @descr  ctor() from LwpSvStream
 */
LwpObjectStream::LwpObjectStream(LwpSvStream *pStrm, BOOL isCompressed, sal_uInt16 size)
    :m_pContentBuf(NULL), m_nBufSize(size), m_nReadPos(0),
    m_pStrm(pStrm), m_bCompressed(isCompressed)
{
    assert(size<IO_BUFFERSIZE);
    ReadStream();
}
/**
 * @descr  read object data from stream
 */
void LwpObjectStream::ReadStream()
{
    if(m_nBufSize == 0)
    {
        m_pContentBuf = NULL;
    }
    else
    {
        Read2Buffer();
    }
}
/**
 * @descr  read object data from stream to buffer
 */
void LwpObjectStream::Read2Buffer()
{
    if( m_pContentBuf )
    {
        ReleaseBuffer();
    }

    m_nReadPos = 0;

    if( m_bCompressed )
    {
        sal_uInt8* pCompressBuffer = new sal_uInt8[m_nBufSize];
        m_pStrm->Read(pCompressBuffer, m_nBufSize);

        sal_uInt8 pTempDst[IO_BUFFERSIZE];
        m_nBufSize = DecompressBuffer(pTempDst, pCompressBuffer, m_nBufSize);
        assert( m_nBufSize < IO_BUFFERSIZE);
        delete [] pCompressBuffer;
        pCompressBuffer = NULL;

        m_pContentBuf = AllocBuffer(m_nBufSize);
        memcpy(m_pContentBuf, pTempDst, m_nBufSize);
        //delete [] pTempDst;

    }
    else
    {
        m_pContentBuf = AllocBuffer(m_nBufSize);
        m_pStrm->Read(m_pContentBuf, m_nBufSize);
    }
}
/**
 * @descr  alloc size of buffer
 */
sal_uInt8* LwpObjectStream::AllocBuffer(sal_uInt16 size)
{
    if(size<=100)
    {
        return(m_SmallBuffer);
    }
    else
    {
        return (new sal_uInt8[size]);
    }
}
/**
 * @descr  signal complete to release object buffer
 */
void LwpObjectStream::ReadComplete()
{
    ReleaseBuffer();
}

LwpObjectStream::~LwpObjectStream()
{
    ReleaseBuffer();
}
/**
 * @descr  release object buffer
 */
void LwpObjectStream::ReleaseBuffer()
{

    if(m_nBufSize>100)
    {
        if(m_pContentBuf)
        {
            delete [] m_pContentBuf;
            m_pContentBuf = NULL;
        }
    }
}
/**
 * @descr  read len bytes from object stream to buffer
 */
sal_uInt16 LwpObjectStream::QuickRead(void* buf, sal_uInt16 len)
{
    if( len > m_nBufSize - m_nReadPos )
    {
        assert(false);
        len = m_nBufSize - m_nReadPos;
    }
    if( m_pContentBuf && len)
    {
        memcpy(buf, m_pContentBuf+m_nReadPos, len);
        m_nReadPos += len;
    }
    return len;
}
/**
 * @descr  SeekRel pos in object stream/buffer
 */
void LwpObjectStream::SeekRel(sal_uInt16 pos)
{
    if( pos > m_nBufSize - m_nReadPos)
        pos = m_nBufSize - m_nReadPos;
    m_nReadPos +=pos;
}
/**
 * @descr  Seek to pos in object buffer/buffer
 */
BOOL LwpObjectStream::Seek( sal_uInt16 pos)
{
    if (pos < m_nBufSize)
    {
        m_nReadPos = pos;
        return TRUE;
    }
    return FALSE;
}

/**
 * @descr  Quick read sal_Bool
 */
sal_Bool LwpObjectStream::QuickReadBool()
{
    sal_uInt16 nValue;
    QuickRead(&nValue, 2);
    return (sal_Bool)(nValue != 0);
}
/**
 * @descr  Quick read sal_uInt32
 */
sal_uInt32 LwpObjectStream::QuickReaduInt32()
{
    sal_uInt32 nValue;
    QuickRead(&nValue, sizeof(nValue));
    return nValue;
}
/**
 * @descr  Quick read sal_uInt32
 */
sal_uInt16 LwpObjectStream::QuickReaduInt16()
{
    sal_uInt16 nValue;
    QuickRead(&nValue, sizeof(nValue));
    return nValue;
}
/**
 * @descr  Quick read sal_Int32
 */
sal_Int32 LwpObjectStream::QuickReadInt32()
{
    sal_Int32 nValue;
    QuickRead(&nValue, sizeof(nValue));
    return nValue;
}
/**
 * @descr  Quick read sal_Int16
 */
sal_Int16 LwpObjectStream::QuickReadInt16()
{
    sal_Int16 nValue;
    QuickRead(&nValue, sizeof(nValue));
    return nValue;
}
/**
 * @descr  Quick read sal_Int8
 */
sal_Int8 LwpObjectStream::QuickReadInt8()
{
    sal_Int8 nValue;
    QuickRead(&nValue, sizeof(nValue));
    return nValue;
}
/**
 * @descr  Quick read sal_uInt8
 */
sal_uInt8 LwpObjectStream::QuickReaduInt8()
{
    sal_uInt8 nValue;
    QuickRead(&nValue, sizeof(nValue));
    return nValue;
}
/**
 * @descr  skip extra bytes
 */
void LwpObjectStream::SkipExtra()
{
    sal_uInt16 extra;

    QuickRead(&extra, sizeof(extra));
    while (extra != 0)
    {
        assert(false);
        QuickRead(&extra, sizeof(extra));
    }
}
/**
 * @descr  check if extra bytes
 */
sal_uInt16 LwpObjectStream::CheckExtra()
{
    sal_uInt16 extra;
    QuickRead(&extra, sizeof(extra));
    return extra;
}
/**
 * @descr  decompress data buffer from pSrc to pDst
 * 		  Refer to the CAmiPro40File::DecompressObject(~) in LWP
 */
sal_uInt16 LwpObjectStream::DecompressBuffer(sal_uInt8* pDst, sal_uInt8* pSrc, sal_uInt16 Size)
{
    sal_uInt16 Cnt;
    sal_uInt32 DstSize = 0;

    while (Size)
    {
        switch (*pSrc & 0xC0)
        {
            case 0x00:
                // 1 - 64 bytes of 0
                // Code 00zzzzzz
                // where zzzzzz is the count - 1 of compressed 0 bytes

                Cnt = (*pSrc++ & 0x3F) + 1;
                memset(pDst, 0, Cnt);
                pDst += Cnt;
                DstSize += Cnt;
                Size--;
                break;

            case 0x40:
                // 1 - 8 zeros followed by 1 - 8 non-zero
                // Code 01zzznnn binary
                // where zzz is the count - 1 of compressed zero bytes
                // and nnn is the count - 1 of following non-zero bytes

                Cnt = ((*pSrc & 0x38) >> 3) + 1;
                memset(pDst, 0, Cnt);
                pDst += Cnt;
                DstSize += Cnt;
                Cnt = (*pSrc++ & 0x07) + 1;
                memcpy(pDst, pSrc, Cnt);
                pDst += Cnt;
                DstSize += Cnt;
                pSrc += Cnt;
                Size -= Cnt + 1;
                break;

            case 0x80:
                // 1 0 followed by 1 - 64 bytes of non-zero
                // Code 0x80 (or 0x40 if 8 or less non-zero)
                // Code 10nnnnnn binary
                // where nnnnnn is the count - 1 of following non-zero bytes

                *pDst++ = 0;
                DstSize++;
                // fall thru into next case!

            case 0xC0:
                // 1 - 64 bytes of non-zero
                // Code = 11nnnnnn binary
                // nnnnnn is the count less 1 of following non-zero bytes

                Cnt = (*pSrc++ & 0x3F) + 1;
                memcpy(pDst, pSrc, Cnt);
                pDst += Cnt;
                DstSize += Cnt;
                pSrc += Cnt;
                Size -= Cnt + 1;
                break;
        }
        assert(DstSize < IO_BUFFERSIZE);
    }
    return(static_cast<sal_uInt16>(DstSize));
}
/**
 * @descr  quick read string with 1252
 */
OUString LwpObjectStream::QuickReadStringPtr(void)
{
    sal_uInt16 len, diskSize;

    diskSize = QuickReaduInt16();
    len = QuickReaduInt16();

    OUString str;
    rtl_TextEncoding rEncode =  RTL_TEXTENCODING_MS_1252;
    LwpTools::QuickReadUnicode(this, str, diskSize-sizeof(diskSize), rEncode);
    return str;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
