/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Class header file...
#include "XalanOutputStream.hpp"



#include <xercesc/util/TransService.hpp>



#include "xalanc/Include/STLHelper.hpp"



#include "XalanMessageLoader.hpp"
#include "XalanTranscodingServices.hpp"



namespace XALAN_CPP_NAMESPACE {



const XalanDOMChar  XalanOutputStream::s_nlString[] =
{
    XalanUnicode::charLF,
    0
};



const XalanDOMChar  XalanOutputStream::s_nlCRString[] =
{
    XalanUnicode::charCR,
    XalanUnicode::charLF,
    0
};



const XalanDOMString::size_type     XalanOutputStream::s_nlStringLength =
    sizeof(s_nlString) / sizeof(s_nlString[0]) - 1;

const XalanDOMString::size_type     XalanOutputStream::s_nlCRStringLength =
    sizeof(s_nlCRString) / sizeof(s_nlCRString[0]) - 1;



XalanOutputStream::XalanOutputStream(
            MemoryManager&      theManager,
            size_type               theBufferSize,
            size_type               theTranscoderBlockSize,
            bool                    fThrowTranscodeException) :
    m_transcoderBlockSize(theTranscoderBlockSize),
    m_transcoder(0),
    m_bufferSize(theBufferSize),
    m_buffer(theManager),
    m_encoding(theManager),
    m_writeAsUTF16(false),
    m_throwTranscodeException(fThrowTranscodeException),
    m_transcodingBuffer(theManager)
{
    if (m_bufferSize == 0)
    {
        m_bufferSize = 1;
    }

    m_buffer.reserve(theBufferSize + 1);
}



XalanOutputStream::~XalanOutputStream()
{
    XalanTranscodingServices::destroyTranscoder(m_transcoder);
}



void
XalanOutputStream::write(
            const XalanDOMChar*     theBuffer,
            size_type               theBufferLength)
{
    assert(theBuffer != 0);

    if (theBufferLength + m_buffer.size() > m_bufferSize)
    {
        flushBuffer();
    }

    if (theBufferLength > m_bufferSize)
    {
        assert(m_buffer.empty() == true);

        doWrite(theBuffer, theBufferLength);
    }
    else
    {
        m_buffer.insert(m_buffer.end(),
                        theBuffer,
                        theBuffer + theBufferLength);
    }
}



void
XalanOutputStream::transcode(
            const XalanDOMChar*     theBuffer,
            size_type               theBufferLength,
            TranscodeVectorType&    theDestination)
{
    if (m_transcoder == 0)
    {
        if (TranscodeToLocalCodePage(
                theBuffer,
                theBufferLength,
                theDestination) == false)
        {
            if (m_throwTranscodeException == true)
            {
                XalanDOMString  theExceptionBuffer(theDestination.getMemoryManager());

                throw TranscodingException(
                        theExceptionBuffer,
                        0);
            }
        }
    }
    else
    {
        bool    fDone = false;

        // Keep track of the total bytes we've added to the
        // destination vector, and the total bytes we've
        // eaten from theBuffer.
        size_type   theTotalBytesFilled = 0;
        size_type   theTotalBytesEaten = 0;

        // Keep track of the current position in the input buffer,
        // and amount remaining in the buffer, since we may not be
        // able to transcode it all at once.
        const XalanDOMChar*     theBufferPosition = theBuffer;
        size_type               theRemainingBufferLength = theBufferLength;

        // Keep track of the destination size, and the target size, which is
        // the size of the destination that has not yet been filled with
        // transcoded characters.  Double the buffer size, in case we're
        // transcoding to a 16-bit encoding.
        // $$$ ToDo: We need to know the size of an encoding, so we can
        // do the right thing with the destination size.
        size_type   theDestinationSize = theBufferLength * 2;
        size_type   theTargetSize = theDestinationSize;

        do
        {
            // Resize the buffer...
            theDestination.resize(theDestinationSize + 1);

            size_type   theSourceBytesEaten = 0;
            size_type   theTargetBytesEaten = 0;

            XalanTranscodingServices::eCode     theResult =
                m_transcoder->transcode(
                        theBufferPosition,
                        theRemainingBufferLength,
                        reinterpret_cast<XMLByte*>(&theDestination[0]) + theTotalBytesFilled,
                        theTargetSize,
                        theSourceBytesEaten,
                        theTargetBytesEaten);

            if(theResult != XalanTranscodingServices::OK)
            {
                if (m_throwTranscodeException == true)
                {
                    XalanDOMString  theExceptionBuffer(theDestination.getMemoryManager());

                    throw TranscodingException(
                            theExceptionBuffer,
                            0);
                }
            }

            theTotalBytesFilled += theTargetBytesEaten;
            theTotalBytesEaten += theSourceBytesEaten;

            if (theTotalBytesEaten == theBufferLength)
            {
                fDone = true;
            }
            else
            {
                assert(theTotalBytesEaten < theBufferLength);

                // Update everything...
                theBufferPosition += theSourceBytesEaten;
                theRemainingBufferLength -= theSourceBytesEaten;

                // The new target size will always be the
                // current destination size, since we
                // grow by a factor of 2.  This will
                // need to change if the factor is
                // every changed.
                theTargetSize = theDestinationSize;

                // Grow the destination by a factor of
                // two 2.  See the previous comment if
                // you want to change this.
                theDestinationSize = theDestinationSize * 2;
            }
        } while(fDone == false);

        // Resize things, if there are any extra bytes...
        if (theDestination.size() != theTotalBytesFilled)
        {
            theDestination.resize(theTotalBytesFilled);
        }
    }
}



void
XalanOutputStream::setOutputEncoding(const XalanDOMString&  theEncoding)
{
    // Flush, just in case.  This should probably be an error...
    flushBuffer();

    XalanTranscodingServices::destroyTranscoder(m_transcoder);

    m_transcoder = 0;

    XalanTranscodingServices::eCode     theCode = XalanTranscodingServices::OK;

    if (XalanTranscodingServices::encodingIsUTF16(theEncoding) == true)
    {
        m_writeAsUTF16 = true;
    }
    else
    {
        m_transcoder = XalanTranscodingServices::makeNewTranscoder(
                    getMemoryManager(),
                    theEncoding,
                    theCode,
                    m_transcoderBlockSize);

        if (theCode == XalanTranscodingServices::UnsupportedEncoding ||
            theCode == XalanTranscodingServices::SupportFilesNotFound)
        {
            XalanDOMString  theBuffer(getMemoryManager());

            throw UnsupportedEncodingException(theEncoding, theBuffer, 0);
        }
        else if (theCode != XalanTranscodingServices::OK)
        {
            XalanDOMString  theBuffer(getMemoryManager());

            throw TranscoderInternalFailureException(theEncoding, theBuffer, 0);
        }

        assert(m_transcoder != 0);
    }

    m_encoding = theEncoding;

    const XalanTranscodingServices::XalanXMLByte*   theProlog =
        XalanTranscodingServices::getStreamProlog(theEncoding);
    assert(theProlog != 0);

    const size_type     theLength = XalanTranscodingServices::length(theProlog);

    if (theLength > 0)
    {
        write(reinterpret_cast<const char*>(theProlog), theLength);
    }
}



bool
XalanOutputStream::canTranscodeTo(XalanUnicodeChar  theChar) const
{
    if (m_transcoder != 0)
    {
        return m_transcoder->canTranscodeTo(theChar);
    }
    else
    {
        // We'll always return true here, since an exception will be
        // thrown when we try to transcode.  We'ed like to enable the
        // commented out line, if we can ever figure out how to see
        // if a character can be encoded.
        return true;
    }
}



void
XalanOutputStream::flushBuffer()
{
    if (m_buffer.empty() == false)
    {
        CollectionClearGuard<BufferType>    theGuard(m_buffer);

        assert(size_type(m_buffer.size()) == m_buffer.size());

        doWrite(&*m_buffer.begin(), size_type(m_buffer.size()));
    }

    assert(m_buffer.empty() == true);
}



void
XalanOutputStream::doWrite(
            const XalanDOMChar*     theBuffer,
            size_type               theBufferLength)
{
    assert(theBuffer != 0);

    if (m_writeAsUTF16 == true)
    {
        // This is a hack to write UTF-16 through as if it
        // were just chars.  Saves lots of time "transcoding."
        writeData(reinterpret_cast<const char*>(theBuffer), theBufferLength * 2);
    }
    else
    {
        transcode(theBuffer, theBufferLength, m_transcodingBuffer);

        assert(&m_transcodingBuffer[0] != 0);

        assert(size_type(m_transcodingBuffer.size()) == m_transcodingBuffer.size());

        writeData(
            &m_transcodingBuffer[0],
            size_type(m_transcodingBuffer.size()));
    }
}



void
XalanOutputStream::setBufferSize(size_type  theBufferSize)
{
    flushBuffer();

    if (theBufferSize == 0)
    {
        m_bufferSize = 1;
    }
    else
    {
        m_bufferSize = theBufferSize;
    }

    if (m_buffer.size() < m_bufferSize)
    {
        // Enlarge the buffer...
        m_buffer.reserve(theBufferSize + 1);
    }
    else if (m_buffer.size() > m_bufferSize)
    {
        // Shrink the buffer.

        // Create a temp buffer and make it
        // the correct size.
        BufferType  temp(getMemoryManager());
        
        temp.reserve(theBufferSize + 1);
        
        // Swap temp with m_buffer so that
        // m_buffer is now the correct size.
        temp.swap(m_buffer);
    }
}



void
XalanOutputStream::newline()
{
    // We've had requests to make this a run-time switch, but for now,
    // it's compile time only...
#if defined(XALAN_NEWLINE_IS_CRLF)
    write(s_nlCRString, s_nlCRStringLength);
#else
    write(s_nlString, s_nlStringLength);
#endif
}



const XalanDOMChar*
XalanOutputStream::getNewlineString() const
{
    // We've had requests to make this a run-time switch, but for now,
    // it's compile time only...
#if defined(XALAN_NEWLINE_IS_CRLF)
    return s_nlCRString;
#else
    return s_nlString;
#endif
}



XalanOutputStream::XalanOutputStreamException::XalanOutputStreamException(
            const XalanDOMString&   theMessage,
            MemoryManager&          theManager,
            const Locator*          theLocator) :
    XSLException(
        theMessage,
        theManager,
        theLocator)
{
}



XalanOutputStream::XalanOutputStreamException::XalanOutputStreamException(
            const XalanDOMString&   theMessage,
            MemoryManager&          theManager) :
    XSLException(
        theMessage,
        theManager)
{
}



    XalanOutputStream::XalanOutputStreamException::XalanOutputStreamException(const XalanOutputStreamException& other):
    XSLException(other)
{
}



XalanOutputStream::XalanOutputStreamException::~XalanOutputStreamException()
{
}



const XalanDOMChar*
XalanOutputStream::XalanOutputStreamException::getType() const
{
    static const XalanDOMChar   s_type[] = 
    {   
        XalanUnicode::charLetter_X,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_l,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_F,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_l,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_O,
        XalanUnicode::charLetter_u,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_u,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_S,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_m,
        XalanUnicode::charLetter_E,
        XalanUnicode::charLetter_x,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_n,
        0
    };

    return s_type;
}



const XalanDOMChar*
XalanOutputStream::UnsupportedEncodingException::getType() const
{
    static const XalanDOMChar  s_type[] = 
    {
        XalanUnicode::charLetter_U,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_s,
        XalanUnicode::charLetter_u,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_d,
        XalanUnicode::charLetter_E,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_d,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_g,
        XalanUnicode::charLetter_E,
        XalanUnicode::charLetter_x,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_n,
        0
    };

    return s_type;
}



XalanOutputStream::UnsupportedEncodingException::UnsupportedEncodingException(
            const XalanDOMString&   theEncoding,
            XalanDOMString&         theBuffer,
            const Locator*          theLocator) :
    XalanOutputStreamException(
        XalanMessageLoader::getMessage(
            theBuffer,
            XalanMessages::UnsupportedEncoding_1Param,
            theEncoding),
        theBuffer.getMemoryManager(),
        theLocator),
   m_encoding(
       theEncoding, 
       theBuffer.getMemoryManager())
{
}



XalanOutputStream::UnsupportedEncodingException::UnsupportedEncodingException(
            const XalanDOMString&   theEncoding,
            XalanDOMString&         theBuffer) :
    XalanOutputStreamException(
        XalanMessageLoader::getMessage(
            theBuffer,
            XalanMessages::UnsupportedEncoding_1Param,
            theEncoding),
        theBuffer.getMemoryManager()),
   m_encoding(
       theEncoding, 
       theBuffer.getMemoryManager())
{
}



XalanOutputStream::UnsupportedEncodingException::~UnsupportedEncodingException()
{
}



XalanOutputStream::TranscoderInternalFailureException::TranscoderInternalFailureException(
            const XalanDOMString&   theEncoding,
            XalanDOMString&         theBuffer,
            const Locator*          theLocator) :
    XalanOutputStreamException(
        XalanMessageLoader::getMessage(
            theBuffer, 
            XalanMessages::UnknownErrorOccurredWhileTranscodingToEncoding_1Param,
            theEncoding),
        theBuffer.getMemoryManager(),
        theLocator),
    m_encoding(
        theEncoding,
        theBuffer.getMemoryManager())
{
}



XalanOutputStream::TranscoderInternalFailureException::TranscoderInternalFailureException(const TranscoderInternalFailureException& other) :
    XalanOutputStreamException(other),
    m_encoding(
        other.m_encoding,
        other.m_memoryManager)
{
}



XalanOutputStream::TranscoderInternalFailureException::~TranscoderInternalFailureException()
{
}



const XalanDOMChar*
XalanOutputStream::TranscoderInternalFailureException::getType() const
{
    static const XalanDOMChar  s_type[] = 
    {
        XalanUnicode::charLetter_T,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_s,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_d,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_I,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_l,
        XalanUnicode::charLetter_F,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_l,
        XalanUnicode::charLetter_u,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_E,
        XalanUnicode::charLetter_x,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_n,
        0
    };

    return s_type;
}



XalanOutputStream::TranscodingException::TranscodingException(
            XalanDOMString&     theBuffer,
            const Locator*      theLocator) :
    XalanOutputStreamException(
        XalanMessageLoader::getMessage(
            theBuffer,
            XalanMessages::AnErrorOccurredWhileTranscoding),
        theBuffer.getMemoryManager(),
        theLocator)
{
}



XalanOutputStream::TranscodingException::TranscodingException(const TranscodingException& other) :
    XalanOutputStreamException(other)
{
}



XalanOutputStream::TranscodingException::~TranscodingException()
{
}



const XalanDOMChar*
XalanOutputStream::TranscodingException::getType() const
{
    static const XalanDOMChar  s_type[] = 
    {
        XalanUnicode::charLetter_T,
        XalanUnicode::charLetter_r,
        XalanUnicode::charLetter_a,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_s,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_d,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_n,
        XalanUnicode::charLetter_g,
        XalanUnicode::charLetter_E,
        XalanUnicode::charLetter_x,
        XalanUnicode::charLetter_c,
        XalanUnicode::charLetter_e,
        XalanUnicode::charLetter_p,
        XalanUnicode::charLetter_t,
        XalanUnicode::charLetter_i,
        XalanUnicode::charLetter_o,
        XalanUnicode::charLetter_n,
        0
    };

    return s_type;
}



XalanDOMString&
XalanOutputStream::formatMessage(
            const XalanDOMString&   theMessage,
            int                     theErrorCode,
            XalanDOMString&         theBuffer)
{
    XalanDOMString  strErrorCode(theBuffer.getMemoryManager());

    XalanDOMString  strErrorMsg(theBuffer.getMemoryManager());

    NumberToDOMString(theErrorCode, strErrorCode);

    theBuffer.assign(theMessage);

    XalanMessageLoader::getMessage(
        strErrorMsg,
        XalanMessages::SystemErrorCode_1Param,
        strErrorCode);

    theBuffer.append(strErrorMsg);

    return theBuffer;
}




}
