/*
 * Copyright (C) 2012 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <wtf/StringPrintStream.h>

#include <stdarg.h>
#include <stdio.h>
#include <wtf/FastMalloc.h>

namespace WTF {

StringPrintStream::StringPrintStream()
    : m_buffer(m_inlineBuffer)
    , m_next(0)
    , m_size(sizeof(m_inlineBuffer))
{
    m_buffer[0] = 0; // Make sure that we always have a null terminator.
}

StringPrintStream::~StringPrintStream()
{
    if (m_buffer == m_inlineBuffer)
        return;
    fastFree(m_buffer);
}

void StringPrintStream::vprintf(const char* format, va_list argList)
{
    ASSERT_WITH_SECURITY_IMPLICATION(m_next < m_size);
    ASSERT(!m_buffer[m_next]);

    va_list firstPassArgList;
    va_copy(firstPassArgList, argList);

    int numberOfBytesNotIncludingTerminatorThatWouldHaveBeenWritten =
        vsnprintf(m_buffer + m_next, m_size - m_next, format, firstPassArgList);

    va_end(firstPassArgList);

    int numberOfBytesThatWouldHaveBeenWritten =
        numberOfBytesNotIncludingTerminatorThatWouldHaveBeenWritten + 1;

    if (m_next + numberOfBytesThatWouldHaveBeenWritten <= m_size) {
        m_next += numberOfBytesNotIncludingTerminatorThatWouldHaveBeenWritten;
        return; // This means that vsnprintf() succeeded.
    }

    increaseSize(m_next + numberOfBytesThatWouldHaveBeenWritten);

    int numberOfBytesNotIncludingTerminatorThatWereWritten =
        vsnprintf(m_buffer + m_next, m_size - m_next, format, argList);

    int numberOfBytesThatWereWritten = numberOfBytesNotIncludingTerminatorThatWereWritten + 1;

    ASSERT_UNUSED(numberOfBytesThatWereWritten, m_next + numberOfBytesThatWereWritten <= m_size);

    m_next += numberOfBytesNotIncludingTerminatorThatWereWritten;

    ASSERT_WITH_SECURITY_IMPLICATION(m_next < m_size);
    ASSERT(!m_buffer[m_next]);
}

CString StringPrintStream::toCString()
{
    ASSERT(m_next == strlen(m_buffer));
    return CString(m_buffer, m_next);
}

void StringPrintStream::reset()
{
    m_next = 0;
    m_buffer[0] = 0;
}

String StringPrintStream::toString()
{
    ASSERT(m_next == strlen(m_buffer));
    return String::fromUTF8(m_buffer, m_next);
}

String StringPrintStream::toStringWithLatin1Fallback()
{
    ASSERT(m_next == strlen(m_buffer));
    return String::fromUTF8WithLatin1Fallback(m_buffer, m_next);
}

void StringPrintStream::increaseSize(size_t newSize)
{
    ASSERT_WITH_SECURITY_IMPLICATION(newSize > m_size);
    ASSERT(newSize > sizeof(m_inlineBuffer));

    // Use exponential resizing to reduce thrashing.
    m_size = newSize << 1;

    // Use fastMalloc instead of fastRealloc because we know that for the sizes we're using,
    // fastRealloc will just do malloc+free anyway. Also, this simplifies the code since
    // we can't realloc the inline buffer.
    char* newBuffer = static_cast<char*>(fastMalloc(m_size));
    memcpy(newBuffer, m_buffer, m_next + 1);
    if (m_buffer != m_inlineBuffer)
        fastFree(m_buffer);
    m_buffer = newBuffer;
}

} // namespace WTF

