<commit_before>/*
 * Copyright (C) 2010 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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 "core/fileapi/FileReaderLoader.h"

#include "core/dom/ScriptExecutionContext.h"
#include "core/fetch/TextResourceDecoder.h"
#include "core/fileapi/Blob.h"
#include "core/fileapi/BlobRegistry.h"
#include "core/fileapi/BlobURL.h"
#include "core/fileapi/FileReaderLoaderClient.h"
#include "core/fileapi/Stream.h"
#include "core/loader/ThreadableLoader.h"
#include "core/platform/network/ResourceRequest.h"
#include "core/platform/network/ResourceResponse.h"
#include "wtf/ArrayBuffer.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
#include "wtf/text/Base64.h"
#include "wtf/text/StringBuilder.h"

using namespace std;

namespace WebCore {

const int defaultBufferLength = 32768;

FileReaderLoader::FileReaderLoader(ReadType readType, FileReaderLoaderClient* client)
    : m_readType(readType)
    , m_client(client)
    , m_urlForReadingIsStream(false)
    , m_isRawDataConverted(false)
    , m_stringResult("")
    , m_variableLength(false)
    , m_bytesLoaded(0)
    , m_totalBytes(0)
    , m_hasRange(false)
    , m_rangeStart(0)
    , m_rangeEnd(0)
    , m_errorCode(FileError::OK)
{
}

FileReaderLoader::~FileReaderLoader()
{
    terminate();
    if (!m_urlForReading.isEmpty()) {
        if (m_urlForReadingIsStream)
            BlobRegistry::unregisterStreamURL(m_urlForReading);
        else
            BlobRegistry::unregisterBlobURL(m_urlForReading);
    }
}

void FileReaderLoader::startForURL(ScriptExecutionContext* scriptExecutionContext, const KURL& url)
{
    // The blob is read by routing through the request handling layer given a temporary public url.
    m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin());
    if (m_urlForReading.isEmpty()) {
        failed(FileError::SECURITY_ERR);
        return;
    }

    if (m_urlForReadingIsStream)
        BlobRegistry::registerStreamURL(scriptExecutionContext->securityOrigin(), m_urlForReading, url);
    else
        BlobRegistry::registerBlobURL(scriptExecutionContext->securityOrigin(), m_urlForReading, url);

    // Construct and load the request.
    ResourceRequest request(m_urlForReading);
    request.setHTTPMethod("GET");
    if (m_hasRange)
        request.setHTTPHeaderField("Range", String::format("bytes=%d-%d", m_rangeStart, m_rangeEnd));

    ThreadableLoaderOptions options;
    options.sendLoadCallbacks = SendCallbacks;
    options.sniffContent = DoNotSniffContent;
    options.preflightPolicy = ConsiderPreflight;
    options.allowCredentials = AllowStoredCredentials;
    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
    // FIXME: Is there a directive to which this load should be subject?
    options.contentSecurityPolicyEnforcement = DoNotEnforceContentSecurityPolicy;

    if (m_client)
        m_loader = ThreadableLoader::create(scriptExecutionContext, this, request, options);
    else
        ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options);
}

void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, const Blob& blob)
{
    m_urlForReadingIsStream = false;
    startForURL(scriptExecutionContext, blob.url());
}

void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, const Stream& stream, unsigned readSize)
{
    if (readSize > 0) {
        m_hasRange = true;
        m_rangeStart = 0;
        m_rangeEnd = readSize - 1; // End is inclusive so (0,0) is a 1-byte read.
    }

    m_urlForReadingIsStream = true;
    startForURL(scriptExecutionContext, stream.url());
}

void FileReaderLoader::cancel()
{
    m_errorCode = FileError::ABORT_ERR;
    terminate();
}

void FileReaderLoader::terminate()
{
    if (m_loader) {
        m_loader->cancel();
        cleanup();
    }
}

void FileReaderLoader::cleanup()
{
    m_loader = 0;

    // If we get any error, we do not need to keep a buffer around.
    if (m_errorCode) {
        m_rawData = 0;
        m_stringResult = "";
        m_isRawDataConverted = true;
    }
}

void FileReaderLoader::didReceiveResponse(unsigned long, const ResourceResponse& response)
{
    if (response.httpStatusCode() != 200) {
        failed(httpStatusCodeToErrorCode(response.httpStatusCode()));
        return;
    }

    unsigned long long length = response.expectedContentLength();

    // A value larger than INT_MAX means that the content length wasn't
    // specified, so the buffer will need to be dynamically grown.
    if (length > INT_MAX) {
        m_variableLength = true;
        if (m_hasRange)
            length = 1 + m_rangeEnd - m_rangeStart;
        else
            length = defaultBufferLength;
    }

    // Check that we can cast to unsigned since we have to do
    // so to call ArrayBuffer's create function.
    // FIXME: Support reading more than the current size limit of ArrayBuffer.
    if (length > numeric_limits<unsigned>::max()) {
        failed(FileError::NOT_READABLE_ERR);
        return;
    }

    ASSERT(!m_rawData);
    m_rawData = ArrayBuffer::create(static_cast<unsigned>(length), 1);

    if (!m_rawData) {
        failed(FileError::NOT_READABLE_ERR);
        return;
    }

    m_totalBytes = static_cast<unsigned>(length);

    if (m_client)
        m_client->didStartLoading();
}

void FileReaderLoader::didReceiveData(const char* data, int dataLength)
{
    ASSERT(data);
    ASSERT(dataLength > 0);

    // Bail out if we already encountered an error.
    if (m_errorCode)
        return;

    if (m_readType == ReadByClient) {
        m_bytesLoaded += dataLength;

        if (m_client)
            m_client->didReceiveDataForClient(data, dataLength);
        return;
    }

    int length = dataLength;
    unsigned remainingBufferSpace = m_totalBytes - m_bytesLoaded;
    if (length > static_cast<long long>(remainingBufferSpace)) {
        // If the buffer has hit maximum size, it can't be grown any more.
        if (m_totalBytes >= numeric_limits<unsigned>::max()) {
            failed(FileError::NOT_READABLE_ERR);
            return;
        }
        if (m_variableLength) {
            unsigned long long newLength = m_totalBytes * 2;
            if (newLength > numeric_limits<unsigned>::max())
                newLength = numeric_limits<unsigned>::max();
            RefPtr<ArrayBuffer> newData =
                ArrayBuffer::create(static_cast<unsigned>(newLength), 1);
            memcpy(static_cast<char*>(newData->data()), static_cast<char*>(m_rawData->data()), m_bytesLoaded);

            m_rawData = newData;
            m_totalBytes = static_cast<unsigned>(newLength);
        } else
            length = remainingBufferSpace;
    }

    if (length <= 0)
        return;

    memcpy(static_cast<char*>(m_rawData->data()) + m_bytesLoaded, data, length);
    m_bytesLoaded += length;

    m_isRawDataConverted = false;

    if (m_client)
        m_client->didReceiveData();
}

void FileReaderLoader::didFinishLoading(unsigned long, double)
{
    if (m_readType != ReadByClient && m_variableLength && m_totalBytes > m_bytesLoaded) {
        RefPtr<ArrayBuffer> newData = m_rawData->slice(0, m_bytesLoaded);

        m_rawData = newData;
        m_isRawDataConverted = false;

        m_totalBytes = m_bytesLoaded;
    }
    cleanup();
    if (m_client)
        m_client->didFinishLoading();
}

void FileReaderLoader::didFail(const ResourceError&)
{
    // If we're aborting, do not proceed with normal error handling since it is covered in aborting code.
    if (m_errorCode == FileError::ABORT_ERR)
        return;

    failed(FileError::NOT_READABLE_ERR);
}

void FileReaderLoader::failed(FileError::ErrorCode errorCode)
{
    m_errorCode = errorCode;
    cleanup();
    if (m_client)
        m_client->didFail(m_errorCode);
}

FileError::ErrorCode FileReaderLoader::httpStatusCodeToErrorCode(int httpStatusCode)
{
    switch (httpStatusCode) {
    case 403:
        return FileError::SECURITY_ERR;
    case 404:
        return FileError::NOT_FOUND_ERR;
    default:
        return FileError::NOT_READABLE_ERR;
    }
}

PassRefPtr<ArrayBuffer> FileReaderLoader::arrayBufferResult() const
{
    ASSERT(m_readType == ReadAsArrayBuffer);

    // If the loading is not started or an error occurs, return an empty result.
    if (!m_rawData || m_errorCode)
        return 0;

    // If completed, we can simply return our buffer.
    if (isCompleted())
        return m_rawData;

    // Otherwise, return a copy.
    return m_rawData->slice(0, m_bytesLoaded);
}

String FileReaderLoader::stringResult()
{
    ASSERT(m_readType != ReadAsArrayBuffer && m_readType != ReadAsBlob && m_readType != ReadByClient);

    // If the loading is not started or an error occurs, return an empty result.
    if (!m_rawData || m_errorCode)
        return m_stringResult;

    // If already converted from the raw data, return the result now.
    if (m_isRawDataConverted)
        return m_stringResult;

    switch (m_readType) {
    case ReadAsArrayBuffer:
        // No conversion is needed.
        break;
    case ReadAsBinaryString:
        m_stringResult = String(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
        m_isRawDataConverted = true;
        break;
    case ReadAsText:
        convertToText();
        break;
    case ReadAsDataURL:
        // Partial data is not supported when reading as data URL.
        if (isCompleted())
            convertToDataURL();
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    return m_stringResult;
}

void FileReaderLoader::convertToText()
{
    m_isRawDataConverted = true;

    if (!m_bytesLoaded) {
        m_stringResult = "";
        return;
    }

    // Decode the data.
    // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this
    // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the
    // provided encoding.
    // FIXME: consider supporting incremental decoding to improve the perf.
    StringBuilder builder;
    if (!m_decoder)
        m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding());
    builder.append(m_decoder->decode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded));

    if (isCompleted())
        builder.append(m_decoder->flush());

    m_stringResult = builder.toString();
}

void FileReaderLoader::convertToDataURL()
{
    m_isRawDataConverted = true;

    StringBuilder builder;
    builder.append("data:");

    if (!m_bytesLoaded) {
        m_stringResult = builder.toString();
        return;
    }

    builder.append(m_dataType);
    builder.append(";base64,");

    Vector<char> out;
    base64Encode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded, out);
    out.append('\0');
    builder.append(out.data());

    m_stringResult = builder.toString();
}

bool FileReaderLoader::isCompleted() const
{
    return m_bytesLoaded == m_totalBytes;
}

void FileReaderLoader::setEncoding(const String& encoding)
{
    if (!encoding.isEmpty())
        m_encoding = WTF::TextEncoding(encoding);
}

} // namespace WebCore
<commit_msg>[FileReaderLoader] Don't allocate buffer in ReadByClient mode.<commit_after>/*
 * Copyright (C) 2010 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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 "core/fileapi/FileReaderLoader.h"

#include "core/dom/ScriptExecutionContext.h"
#include "core/fetch/TextResourceDecoder.h"
#include "core/fileapi/Blob.h"
#include "core/fileapi/BlobRegistry.h"
#include "core/fileapi/BlobURL.h"
#include "core/fileapi/FileReaderLoaderClient.h"
#include "core/fileapi/Stream.h"
#include "core/loader/ThreadableLoader.h"
#include "core/platform/network/ResourceRequest.h"
#include "core/platform/network/ResourceResponse.h"
#include "wtf/ArrayBuffer.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
#include "wtf/text/Base64.h"
#include "wtf/text/StringBuilder.h"

using namespace std;

namespace WebCore {

const int defaultBufferLength = 32768;

FileReaderLoader::FileReaderLoader(ReadType readType, FileReaderLoaderClient* client)
    : m_readType(readType)
    , m_client(client)
    , m_urlForReadingIsStream(false)
    , m_isRawDataConverted(false)
    , m_stringResult("")
    , m_variableLength(false)
    , m_bytesLoaded(0)
    , m_totalBytes(0)
    , m_hasRange(false)
    , m_rangeStart(0)
    , m_rangeEnd(0)
    , m_errorCode(FileError::OK)
{
}

FileReaderLoader::~FileReaderLoader()
{
    terminate();
    if (!m_urlForReading.isEmpty()) {
        if (m_urlForReadingIsStream)
            BlobRegistry::unregisterStreamURL(m_urlForReading);
        else
            BlobRegistry::unregisterBlobURL(m_urlForReading);
    }
}

void FileReaderLoader::startForURL(ScriptExecutionContext* scriptExecutionContext, const KURL& url)
{
    // The blob is read by routing through the request handling layer given a temporary public url.
    m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin());
    if (m_urlForReading.isEmpty()) {
        failed(FileError::SECURITY_ERR);
        return;
    }

    if (m_urlForReadingIsStream)
        BlobRegistry::registerStreamURL(scriptExecutionContext->securityOrigin(), m_urlForReading, url);
    else
        BlobRegistry::registerBlobURL(scriptExecutionContext->securityOrigin(), m_urlForReading, url);

    // Construct and load the request.
    ResourceRequest request(m_urlForReading);
    request.setHTTPMethod("GET");
    if (m_hasRange)
        request.setHTTPHeaderField("Range", String::format("bytes=%d-%d", m_rangeStart, m_rangeEnd));

    ThreadableLoaderOptions options;
    options.sendLoadCallbacks = SendCallbacks;
    options.sniffContent = DoNotSniffContent;
    options.preflightPolicy = ConsiderPreflight;
    options.allowCredentials = AllowStoredCredentials;
    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
    // FIXME: Is there a directive to which this load should be subject?
    options.contentSecurityPolicyEnforcement = DoNotEnforceContentSecurityPolicy;

    if (m_client)
        m_loader = ThreadableLoader::create(scriptExecutionContext, this, request, options);
    else
        ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options);
}

void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, const Blob& blob)
{
    m_urlForReadingIsStream = false;
    startForURL(scriptExecutionContext, blob.url());
}

void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, const Stream& stream, unsigned readSize)
{
    if (readSize > 0) {
        m_hasRange = true;
        m_rangeStart = 0;
        m_rangeEnd = readSize - 1; // End is inclusive so (0,0) is a 1-byte read.
    }

    m_urlForReadingIsStream = true;
    startForURL(scriptExecutionContext, stream.url());
}

void FileReaderLoader::cancel()
{
    m_errorCode = FileError::ABORT_ERR;
    terminate();
}

void FileReaderLoader::terminate()
{
    if (m_loader) {
        m_loader->cancel();
        cleanup();
    }
}

void FileReaderLoader::cleanup()
{
    m_loader = 0;

    // If we get any error, we do not need to keep a buffer around.
    if (m_errorCode) {
        m_rawData = 0;
        m_stringResult = "";
        m_isRawDataConverted = true;
    }
}

void FileReaderLoader::didReceiveResponse(unsigned long, const ResourceResponse& response)
{
    if (response.httpStatusCode() != 200) {
        failed(httpStatusCodeToErrorCode(response.httpStatusCode()));
        return;
    }

    unsigned long long length = response.expectedContentLength();

    // A value larger than INT_MAX means that the content length wasn't
    // specified, so the buffer will need to be dynamically grown.
    if (length > INT_MAX) {
        m_variableLength = true;
        if (m_hasRange)
            length = 1 + m_rangeEnd - m_rangeStart;
        else
            length = defaultBufferLength;
    }

    // Check that we can cast to unsigned since we have to do
    // so to call ArrayBuffer's create function.
    // FIXME: Support reading more than the current size limit of ArrayBuffer.
    if (length > numeric_limits<unsigned>::max()) {
        failed(FileError::NOT_READABLE_ERR);
        return;
    }

    ASSERT(!m_rawData);

    if (m_readType != ReadByClient) {
        m_rawData = ArrayBuffer::create(static_cast<unsigned>(length), 1);

        if (!m_rawData) {
            failed(FileError::NOT_READABLE_ERR);
            return;
        }
    }

    m_totalBytes = static_cast<unsigned>(length);

    if (m_client)
        m_client->didStartLoading();
}

void FileReaderLoader::didReceiveData(const char* data, int dataLength)
{
    ASSERT(data);
    ASSERT(dataLength > 0);

    // Bail out if we already encountered an error.
    if (m_errorCode)
        return;

    if (m_readType == ReadByClient) {
        m_bytesLoaded += dataLength;

        if (m_client)
            m_client->didReceiveDataForClient(data, dataLength);
        return;
    }

    int length = dataLength;
    unsigned remainingBufferSpace = m_totalBytes - m_bytesLoaded;
    if (length > static_cast<long long>(remainingBufferSpace)) {
        // If the buffer has hit maximum size, it can't be grown any more.
        if (m_totalBytes >= numeric_limits<unsigned>::max()) {
            failed(FileError::NOT_READABLE_ERR);
            return;
        }
        if (m_variableLength) {
            unsigned long long newLength = m_totalBytes * 2;
            if (newLength > numeric_limits<unsigned>::max())
                newLength = numeric_limits<unsigned>::max();
            RefPtr<ArrayBuffer> newData =
                ArrayBuffer::create(static_cast<unsigned>(newLength), 1);
            memcpy(static_cast<char*>(newData->data()), static_cast<char*>(m_rawData->data()), m_bytesLoaded);

            m_rawData = newData;
            m_totalBytes = static_cast<unsigned>(newLength);
        } else
            length = remainingBufferSpace;
    }

    if (length <= 0)
        return;

    memcpy(static_cast<char*>(m_rawData->data()) + m_bytesLoaded, data, length);
    m_bytesLoaded += length;

    m_isRawDataConverted = false;

    if (m_client)
        m_client->didReceiveData();
}

void FileReaderLoader::didFinishLoading(unsigned long, double)
{
    if (m_readType != ReadByClient && m_variableLength && m_totalBytes > m_bytesLoaded) {
        RefPtr<ArrayBuffer> newData = m_rawData->slice(0, m_bytesLoaded);

        m_rawData = newData;
        m_isRawDataConverted = false;

        m_totalBytes = m_bytesLoaded;
    }
    cleanup();
    if (m_client)
        m_client->didFinishLoading();
}

void FileReaderLoader::didFail(const ResourceError&)
{
    // If we're aborting, do not proceed with normal error handling since it is covered in aborting code.
    if (m_errorCode == FileError::ABORT_ERR)
        return;

    failed(FileError::NOT_READABLE_ERR);
}

void FileReaderLoader::failed(FileError::ErrorCode errorCode)
{
    m_errorCode = errorCode;
    cleanup();
    if (m_client)
        m_client->didFail(m_errorCode);
}

FileError::ErrorCode FileReaderLoader::httpStatusCodeToErrorCode(int httpStatusCode)
{
    switch (httpStatusCode) {
    case 403:
        return FileError::SECURITY_ERR;
    case 404:
        return FileError::NOT_FOUND_ERR;
    default:
        return FileError::NOT_READABLE_ERR;
    }
}

PassRefPtr<ArrayBuffer> FileReaderLoader::arrayBufferResult() const
{
    ASSERT(m_readType == ReadAsArrayBuffer);

    // If the loading is not started or an error occurs, return an empty result.
    if (!m_rawData || m_errorCode)
        return 0;

    // If completed, we can simply return our buffer.
    if (isCompleted())
        return m_rawData;

    // Otherwise, return a copy.
    return m_rawData->slice(0, m_bytesLoaded);
}

String FileReaderLoader::stringResult()
{
    ASSERT(m_readType != ReadAsArrayBuffer && m_readType != ReadAsBlob && m_readType != ReadByClient);

    // If the loading is not started or an error occurs, return an empty result.
    if (!m_rawData || m_errorCode)
        return m_stringResult;

    // If already converted from the raw data, return the result now.
    if (m_isRawDataConverted)
        return m_stringResult;

    switch (m_readType) {
    case ReadAsArrayBuffer:
        // No conversion is needed.
        break;
    case ReadAsBinaryString:
        m_stringResult = String(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
        m_isRawDataConverted = true;
        break;
    case ReadAsText:
        convertToText();
        break;
    case ReadAsDataURL:
        // Partial data is not supported when reading as data URL.
        if (isCompleted())
            convertToDataURL();
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    return m_stringResult;
}

void FileReaderLoader::convertToText()
{
    m_isRawDataConverted = true;

    if (!m_bytesLoaded) {
        m_stringResult = "";
        return;
    }

    // Decode the data.
    // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this
    // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the
    // provided encoding.
    // FIXME: consider supporting incremental decoding to improve the perf.
    StringBuilder builder;
    if (!m_decoder)
        m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding());
    builder.append(m_decoder->decode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded));

    if (isCompleted())
        builder.append(m_decoder->flush());

    m_stringResult = builder.toString();
}

void FileReaderLoader::convertToDataURL()
{
    m_isRawDataConverted = true;

    StringBuilder builder;
    builder.append("data:");

    if (!m_bytesLoaded) {
        m_stringResult = builder.toString();
        return;
    }

    builder.append(m_dataType);
    builder.append(";base64,");

    Vector<char> out;
    base64Encode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded, out);
    out.append('\0');
    builder.append(out.data());

    m_stringResult = builder.toString();
}

bool FileReaderLoader::isCompleted() const
{
    return m_bytesLoaded == m_totalBytes;
}

void FileReaderLoader::setEncoding(const String& encoding)
{
    if (!encoding.isEmpty())
        m_encoding = WTF::TextEncoding(encoding);
}

} // namespace WebCore
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkRendererCollection.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * 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.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 THE REGENTS 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 <stdlib.h>
#include "vtkRendererCollection.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkRendererCollection* vtkRendererCollection::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkRendererCollection");
  if(ret)
    {
    return (vtkRendererCollection*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkRendererCollection;
}

// Forward the Render() method to each renderer in the list.
void vtkRendererCollection::Render()
{
  vtkRenderer *ren;

  for (this->InitTraversal(); (ren = this->GetNextItem()); )
    {
    ren->Render();
    }
}

void vtkRendererCollection::RenderOverlay()
{
  vtkRenderer *ren;

  for (this->InitTraversal(); (ren = this->GetNextItem()); )
    {
    ren->RenderOverlay();
    }
}

<commit_msg>Have the Render and RenderOverlay methods iterate through the renderers from the back layer to the front layer to avoid issues with non-transparent renderers drawing over transparent renderers.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkRendererCollection.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * 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.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 THE REGENTS 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 <stdlib.h>
#include "vtkRendererCollection.h"
#include "vtkRenderWindow.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkRendererCollection* vtkRendererCollection::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkRendererCollection");
  if(ret)
    {
    return (vtkRendererCollection*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkRendererCollection;
}

// Forward the Render() method to each renderer in the list.
void vtkRendererCollection::Render()
{
  vtkRenderer      *ren, *firstRen;
  vtkRenderWindow  *renWin;
  int               numLayers, i;

  this->InitTraversal();
  firstRen = this->GetNextItem();
  if (firstRen == NULL)
    {
    // We cannot determine the number of layers because there are no
    // renderers.  No problem, just return.
    return;
    }
  renWin = firstRen->GetRenderWindow();
  numLayers = renWin->GetNumLayers();

  // Only have the renderers render from back to front.  This is
  // necessary because only the renderers on the back layer do Clears and
  // Clears blow away everything before it.
  for (i = numLayers-1 ; i >= 0 ; i--)
    {
    for (this->InitTraversal(); (ren = this->GetNextItem()); )
      {
      if (ren->GetLayer() == i)
        {
        ren->Render();
        }
      }
    }
}

void vtkRendererCollection::RenderOverlay()
{
  vtkRenderer      *ren, *firstRen;
  vtkRenderWindow  *renWin;
  int               numLayers, i;

  this->InitTraversal();
  firstRen = this->GetNextItem();
  if (firstRen == NULL)
    {
    // We cannot determine the number of layers because there are no
    // renderers.  No problem, just return.
    return;
    }
  renWin = firstRen->GetRenderWindow();
  numLayers = renWin->GetNumLayers();

  // Only have the renderers render from back to front.  This is
  // necessary because only the renderers on the back layer do Clears and
  // Clears blow away everything before it.
  for (i = numLayers-1 ; i >= 0 ; i--)
    {
    for (this->InitTraversal(); (ren = this->GetNextItem()); )
      {
      if (ren->GetLayer() == i)
        {
        ren->RenderOverlay();
        }
      }
    }
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "LocalTables.h"

using namespace std;

void LocalTables::init(std::function<int(const Motif&)> fn, double LB)
{
	fnGetNParents = fn;
	lowerBound = LB;
	candidateTables.reserve(16);
	nActLevel.reserve(16);
	nActLevelTotal.reserve(16);
}

void LocalTables::update(const Motif & m, const double newUB, const int num)
{
	int l = m.getnEdge();
	lock_guard<mutex> lg(mct);
	// add new level
	if(static_cast<int>(candidateTables.size()) < l ) {
		size_t len = max(candidateTables.size(), nActLevel.size());
		len = max<size_t>(len, l + 1);
		candidateTables.resize(len);
		lock_guard<mutex> lga(mat);
		nActLevel.resize(len);
		nActLevelTotal.resize(len);
	}
	// update the num. left for activation
	CT_t& ct = candidateTables[l];
	auto it = ct.find(m);
	if(it == ct.end()) {
		int np = fnGetNParents(m) - num;
		it = ct.insert(make_pair(move(m), make_pair(newUB, np))).first;
	} else {
		it->second.first = min(it->second.first, newUB);
		it->second.second -= num;
	}
	// move a motif from candiate to active
	if(it->second.second == 0) {
		if(it->second.first >= lowerBound) {
			lock_guard<mutex> lga(mat);
			activatedTable.push_back(make_pair(move(it->first), it->second.first));
			++nActLevel[l];
			++nActLevelTotal[l];
		}
		// Special Case: when using estimated num. parents algorithm:
		//   #-left may be negative. If remove it the first time, it may be activated again.
		//   Therefore, instead of remove it, I set its #-left to a very large number.
		// TODO: distinguish the method for calculating num. partents, exact type & estimated type
		//ct.erase(it);
		it->second.second = numeric_limits<int>::max();
	}

}

void LocalTables::addToActivated(const Motif & m, const double newUB)
{
	int l = m.getnEdge();
	lock_guard<mutex> lga(mat);
	// add new level
	if(static_cast<int>(nActLevel.size()) < l) {
		size_t len = max<size_t>(nActLevel.size(), l + 1);
		nActLevel.resize(len);
		nActLevelTotal.resize(len);
	}
	activatedTable.push_back(make_pair(m, newUB));
	++nActLevel[l];
	++nActLevelTotal[l];
}

void LocalTables::sortUp(const int l)
{
	lock_guard<mutex> lg(mct);
	size_t end = min(static_cast<size_t>(l + 1), candidateTables.size());
	for(size_t i = 1; i < end; ++i) {
		candidateTables[i].clear();
	}
}

int LocalTables::updateLowerBound(double newLB)
{
	if(lowerBound >= newLB)
		return 0;
	lowerBound = newLB;
	lock_guard<mutex> lg(mat);
	size_t s0 = activatedTable.size();
	auto it = activatedTable.begin();
	while(it != activatedTable.end()) {
		if(it->second < lowerBound) {
			--nActLevel[it->first.getnEdge()];
			it = activatedTable.erase(it);
		} else {
			++it;
		}
	}
	return s0 - activatedTable.size();
}

bool LocalTables::emptyCandidate() const
{
	for(size_t i = 0; i < candidateTables.size(); ++i) {
		if(emptyCandidate(i))
			return true;
	}
	return false;
}

bool LocalTables::emptyCandidate(const int level) const
{
	return static_cast<int>(candidateTables.size()) > level
		&& candidateTables[level].empty();
}

bool LocalTables::emptyActivated() const
{
	return activatedTable.empty();
}

bool LocalTables::emptyActivated(const int level) const
{
	return static_cast<int>(nActLevel.size()) > level
		&& nActLevel[level] == 0;
}

int LocalTables::getNumEverActive(const int level) const
{
	return static_cast<int>(nActLevelTotal.size()) > level ?
		nActLevelTotal[level] : 0;
}

bool LocalTables::empty() const
{
	unique_lock<mutex> ulc(mct, defer_lock);
	unique_lock<mutex> ula(mat, defer_lock);
	lock(ulc, ula);
	if(activatedTable.empty()) {
		for(auto& ct : candidateTables)
			if(!ct.empty())
				return false;
		return true;
	}
	return false;
}

bool LocalTables::empty(const int level) const
{
	unique_lock<mutex> ulc(mct, defer_lock);
	unique_lock<mutex> ula(mat, defer_lock);
	lock(ulc, ula);
	return candidateTables[level].empty() && nActLevel[level] == 0;
}

std::pair<bool, std::pair<Motif, double>> LocalTables::getOne()
{
	if(activatedTable.empty()) {
		return make_pair(false, make_pair(Motif(), 0.0));
	}
	lock_guard<mutex> lg(mat);
	if(activatedTable.empty()) {
		return make_pair(false, make_pair(Motif(), 0.0));
	}
	auto mu = move(activatedTable.front());
	--nActLevel[mu.first.getnEdge()];
	activatedTable.pop_front();
	return make_pair(true, move(mu));
}
<commit_msg>fix bugs.<commit_after>#include "stdafx.h"
#include "LocalTables.h"

using namespace std;

void LocalTables::init(std::function<int(const Motif&)> fn, double LB)
{
	fnGetNParents = fn;
	lowerBound = LB;
	candidateTables.reserve(16);
	nActLevel.reserve(16);
	nActLevelTotal.reserve(16);
}

void LocalTables::update(const Motif & m, const double newUB, const int num)
{
	int l = m.getnEdge();
	lock_guard<mutex> lg(mct);
	// add new level
	if(static_cast<int>(candidateTables.size()) <= l ) {
		size_t len = max(candidateTables.size(), nActLevel.size());
		len = max<size_t>(len, l + 1);
		candidateTables.resize(len);
		lock_guard<mutex> lga(mat);
		nActLevel.resize(len);
		nActLevelTotal.resize(len);
	}
	// update the num. left for activation
	CT_t& ct = candidateTables[l];
	auto it = ct.find(m);
	if(it == ct.end()) {
		int np = fnGetNParents(m) - num;
		it = ct.insert(make_pair(move(m), make_pair(newUB, np))).first;
	} else {
		it->second.first = min(it->second.first, newUB);
		it->second.second -= num;
	}
	// move a motif from candiate to active
	if(it->second.second == 0) {
		if(it->second.first >= lowerBound) {
			lock_guard<mutex> lga(mat);
			activatedTable.push_back(make_pair(move(it->first), it->second.first));
			++nActLevel[l];
			++nActLevelTotal[l];
		}
		// Special Case: when using estimated num. parents algorithm:
		//   #-left may be negative. If remove it the first time, it may be activated again.
		//   Therefore, instead of remove it, I set its #-left to a very large number.
		// TODO: distinguish the method for calculating num. partents, exact type & estimated type
		//ct.erase(it);
		it->second.second = numeric_limits<int>::max();
	}

}

void LocalTables::addToActivated(const Motif & m, const double newUB)
{
	int l = m.getnEdge();
	lock_guard<mutex> lga(mat);
	// add new level
	if(static_cast<int>(nActLevel.size()) <= l) {
		size_t len = max<size_t>(nActLevel.size(), l + 1);
		nActLevel.resize(len);
		nActLevelTotal.resize(len);
	}
	activatedTable.push_back(make_pair(m, newUB));
	++nActLevel[l];
	++nActLevelTotal[l];
}

void LocalTables::sortUp(const int l)
{
	lock_guard<mutex> lg(mct);
	size_t end = min(static_cast<size_t>(l + 1), candidateTables.size());
	for(size_t i = 1; i < end; ++i) {
		candidateTables[i].clear();
	}
}

int LocalTables::updateLowerBound(double newLB)
{
	if(lowerBound >= newLB)
		return 0;
	lowerBound = newLB;
	lock_guard<mutex> lg(mat);
	size_t s0 = activatedTable.size();
	auto it = activatedTable.begin();
	while(it != activatedTable.end()) {
		if(it->second < lowerBound) {
			--nActLevel[it->first.getnEdge()];
			it = activatedTable.erase(it);
		} else {
			++it;
		}
	}
	return s0 - activatedTable.size();
}

bool LocalTables::emptyCandidate() const
{
	for(size_t i = 0; i < candidateTables.size(); ++i) {
		if(emptyCandidate(i))
			return true;
	}
	return false;
}

bool LocalTables::emptyCandidate(const int level) const
{
	return static_cast<int>(candidateTables.size()) > level
		&& candidateTables[level].empty();
}

bool LocalTables::emptyActivated() const
{
	return activatedTable.empty();
}

bool LocalTables::emptyActivated(const int level) const
{
	return static_cast<int>(nActLevel.size()) > level
		&& nActLevel[level] == 0;
}

int LocalTables::getNumEverActive(const int level) const
{
	return static_cast<int>(nActLevelTotal.size()) > level ?
		nActLevelTotal[level] : 0;
}

bool LocalTables::empty() const
{
	unique_lock<mutex> ulc(mct, defer_lock);
	unique_lock<mutex> ula(mat, defer_lock);
	lock(ulc, ula);
	if(activatedTable.empty()) {
		for(auto& ct : candidateTables)
			if(!ct.empty())
				return false;
		return true;
	}
	return false;
}

bool LocalTables::empty(const int level) const
{
	unique_lock<mutex> ulc(mct, defer_lock);
	unique_lock<mutex> ula(mat, defer_lock);
	lock(ulc, ula);
	return candidateTables[level].empty() && nActLevel[level] == 0;
}

std::pair<bool, std::pair<Motif, double>> LocalTables::getOne()
{
	if(activatedTable.empty()) {
		return make_pair(false, make_pair(Motif(), 0.0));
	}
	lock_guard<mutex> lg(mat);
	if(activatedTable.empty()) {
		return make_pair(false, make_pair(Motif(), 0.0));
	}
	auto mu = move(activatedTable.front());
	--nActLevel[mu.first.getnEdge()];
	activatedTable.pop_front();
	return make_pair(true, move(mu));
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// Licensed 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.

#include "iceoryx_utils/log/logger.hpp"

#include "iceoryx_utils/log/logging.hpp"
#include "iceoryx_utils/log/logstream.hpp"

#include "iceoryx_utils/cxx/helplets.hpp"

#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>

namespace iox
{
namespace log
{
Logger::Logger(std::string ctxId [[gnu::unused]], std::string ctxDescription [[gnu::unused]], LogLevel appLogLevel)
    : m_logLevel(appLogLevel)
{
}

Logger::Logger(Logger&& other)
{
    m_logLevel.store(other.m_logLevel.load(std::memory_order_relaxed), std::memory_order_relaxed);
    m_logMode.store(other.m_logMode.load(std::memory_order_relaxed), std::memory_order_relaxed);
}

Logger& Logger::operator=(Logger&& rhs)
{
    m_logLevel.store(rhs.m_logLevel.load(std::memory_order_relaxed), std::memory_order_relaxed);
    m_logMode.store(rhs.m_logMode.load(std::memory_order_relaxed), std::memory_order_relaxed);
    return *this;
}

void Logger::SetLogLevel(const LogLevel logLevel) noexcept
{
    m_logLevel.store(logLevel, std::memory_order_relaxed);
}

void Logger::SetLogMode(const LogMode logMode) noexcept
{
    m_logMode.store(logMode, std::memory_order_relaxed);

    if ((logMode & LogMode::kRemote) == LogMode::kRemote)
    {
        LogError() << "Remote logging not yet supported!";
    }

    if ((logMode & LogMode::kFile) == LogMode::kFile)
    {
        LogError() << "Logging to file not yet supported!";
    }
}

LogStream Logger::LogFatal() noexcept
{
    return LogStream(*this, LogLevel::kFatal);
}

LogStream Logger::LogError() noexcept
{
    return LogStream(*this, LogLevel::kError);
}

LogStream Logger::LogWarn() noexcept
{
    return LogStream(*this, LogLevel::kWarn);
}

LogStream Logger::LogInfo() noexcept
{
    return LogStream(*this, LogLevel::kInfo);
}

LogStream Logger::LogDebug() noexcept
{
    return LogStream(*this, LogLevel::kDebug);
}

LogStream Logger::LogVerbose() noexcept
{
    return LogStream(*this, LogLevel::kVerbose);
}

void Logger::Print(const LogEntry entry) const
{
    // as long as there is only this synchronous logger, buffer the output before using clog to prevent interleaving
    // output because of threaded access
    std::stringstream buffer;

    auto sec = std::chrono::duration_cast<std::chrono::seconds>(entry.time);
    std::time_t time = sec.count();

    auto timeInfo = std::localtime(&time);

    buffer << "\033[0;90m" << std::put_time(timeInfo, "%Y-%m-%d %H:%M:%S");
    buffer << "." << std::right << std::setfill('0') << std::setw(3) << entry.time.count() % 1000 << " ";
    buffer << LogLevelColor[cxx::enumTypeAsUnderlyingType(entry.level)]
           << LogLevelText[cxx::enumTypeAsUnderlyingType(entry.level)];
    buffer << "\033[m: " << entry.message << std::endl;
    std::clog << buffer.str();
}

bool Logger::IsEnabled(const LogLevel logLevel) const noexcept
{
    if (logLevel <= m_logLevel.load(std::memory_order_relaxed))
    {
        return true;
    }
    return false;
}

void Logger::Log(const LogEntry& entry) const
{
    /// @todo do we want a ringbuffer where we store the last e.g. 100 logs
    /// event if they are below the current log level and print them if case of kFatal?
    if (IsEnabled(entry.level))
    {
        Print(entry);
    }
}

} // namespace log
} // namespace iox
<commit_msg>iox-#278 optimise IsEnabled()<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// Licensed 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.

#include "iceoryx_utils/log/logger.hpp"

#include "iceoryx_utils/log/logging.hpp"
#include "iceoryx_utils/log/logstream.hpp"

#include "iceoryx_utils/cxx/helplets.hpp"

#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>

namespace iox
{
namespace log
{
Logger::Logger(std::string ctxId [[gnu::unused]], std::string ctxDescription [[gnu::unused]], LogLevel appLogLevel)
    : m_logLevel(appLogLevel)
{
}

Logger::Logger(Logger&& other)
{
    m_logLevel.store(other.m_logLevel.load(std::memory_order_relaxed), std::memory_order_relaxed);
    m_logMode.store(other.m_logMode.load(std::memory_order_relaxed), std::memory_order_relaxed);
}

Logger& Logger::operator=(Logger&& rhs)
{
    m_logLevel.store(rhs.m_logLevel.load(std::memory_order_relaxed), std::memory_order_relaxed);
    m_logMode.store(rhs.m_logMode.load(std::memory_order_relaxed), std::memory_order_relaxed);
    return *this;
}

void Logger::SetLogLevel(const LogLevel logLevel) noexcept
{
    m_logLevel.store(logLevel, std::memory_order_relaxed);
}

void Logger::SetLogMode(const LogMode logMode) noexcept
{
    m_logMode.store(logMode, std::memory_order_relaxed);

    if ((logMode & LogMode::kRemote) == LogMode::kRemote)
    {
        LogError() << "Remote logging not yet supported!";
    }

    if ((logMode & LogMode::kFile) == LogMode::kFile)
    {
        LogError() << "Logging to file not yet supported!";
    }
}

LogStream Logger::LogFatal() noexcept
{
    return LogStream(*this, LogLevel::kFatal);
}

LogStream Logger::LogError() noexcept
{
    return LogStream(*this, LogLevel::kError);
}

LogStream Logger::LogWarn() noexcept
{
    return LogStream(*this, LogLevel::kWarn);
}

LogStream Logger::LogInfo() noexcept
{
    return LogStream(*this, LogLevel::kInfo);
}

LogStream Logger::LogDebug() noexcept
{
    return LogStream(*this, LogLevel::kDebug);
}

LogStream Logger::LogVerbose() noexcept
{
    return LogStream(*this, LogLevel::kVerbose);
}

void Logger::Print(const LogEntry entry) const
{
    // as long as there is only this synchronous logger, buffer the output before using clog to prevent interleaving
    // output because of threaded access
    std::stringstream buffer;

    auto sec = std::chrono::duration_cast<std::chrono::seconds>(entry.time);
    std::time_t time = sec.count();

    auto timeInfo = std::localtime(&time);

    buffer << "\033[0;90m" << std::put_time(timeInfo, "%Y-%m-%d %H:%M:%S");
    buffer << "." << std::right << std::setfill('0') << std::setw(3) << entry.time.count() % 1000 << " ";
    buffer << LogLevelColor[cxx::enumTypeAsUnderlyingType(entry.level)]
           << LogLevelText[cxx::enumTypeAsUnderlyingType(entry.level)];
    buffer << "\033[m: " << entry.message << std::endl;
    std::clog << buffer.str();
}

bool Logger::IsEnabled(const LogLevel logLevel) const noexcept
{
    return (logLevel <= m_logLevel.load(std::memory_order_relaxed));
}

void Logger::Log(const LogEntry& entry) const
{
    /// @todo do we want a ringbuffer where we store the last e.g. 100 logs
    /// event if they are below the current log level and print them if case of kFatal?
    if (IsEnabled(entry.level))
    {
        Print(entry);
    }
}

} // namespace log
} // namespace iox
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: WinImplHelper.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: tra $ $Date: 2001-06-15 15:26:07 $
 *
 *  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: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _AUTO_BUFFER_HXX_
#include "AutoBuffer.hxx"
#endif

#ifndef _WINIMPLHELPER_HXX_
#include "WinImplHelper.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <systools/win32/user9x.h>

//------------------------------------------------------------
// namespace directives
//------------------------------------------------------------

using rtl::OUString;
using ::com::sun::star::lang::IllegalArgumentException;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Sequence;

//------------------------------------------------------------
// determine if we are running under Win2000
//------------------------------------------------------------

sal_Bool SAL_CALL IsWin2000( )
{
    OSVERSIONINFOEX osvi;
    BOOL bOsVersionInfoEx;
    sal_Bool bRet = sal_False;

    osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
    bOsVersionInfoEx = GetVersionEx( ( OSVERSIONINFO* )&osvi );
    if( !bOsVersionInfoEx )
    {
        // if OSVERSIONINFOEX doesn't work
        osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
        if( !GetVersionEx( ( OSVERSIONINFO* )&osvi ) )
            return sal_False;
    }

    if( ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId ) && ( osvi.dwMajorVersion >= 5 ) )
        bRet = sal_True;

    return bRet;
}

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

void SAL_CALL ListboxAddString( HWND hwnd, const OUString& aString )
{
    LRESULT rc = SendMessageW(
        hwnd, CB_ADDSTRING, 0, reinterpret_cast< LPARAM >(aString.getStr( )) );

    OSL_ASSERT( (CB_ERR != rc) && (CB_ERRSPACE != rc) );
}

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

OUString SAL_CALL ListboxGetString( HWND hwnd, sal_Int32 aPosition )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    OUString aString;

    LRESULT lItem =
        SendMessageW( hwnd, CB_GETLBTEXTLEN, aPosition, 0 );

    if ( (CB_ERR != lItem) && (lItem > 0) )
    {
        // message returns the len of a combobox item
        // without trailing '\0' that's why += 1
        lItem++;

        CAutoUnicodeBuffer aBuff( lItem );

        LRESULT lRet =
            SendMessageW(
                hwnd, CB_GETLBTEXT, aPosition,
                reinterpret_cast<LPARAM>(&aBuff) );

        OSL_ASSERT( lRet != CB_ERR );

        if ( CB_ERR != lRet )
            aString = OUString( aBuff, lRet );
    }

    return aString;
}

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

void SAL_CALL ListboxAddItem( HWND hwnd, const Any& aItem, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aItem.hasValue( ) ||
         aItem.getValueType( ) != getCppuType((OUString*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    OUString cbItem;
    aItem >>= cbItem;

    ListboxAddString( hwnd, cbItem );
}

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

void SAL_CALL ListboxAddItems( HWND hwnd, const Any& aItemList, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aItemList.hasValue( ) ||
         aItemList.getValueType( ) != getCppuType((Sequence<OUString>*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    Sequence< OUString > aStringList;
    aItemList >>= aStringList;

    sal_Int32 nItemCount = aStringList.getLength( );
    for( sal_Int32 i = 0; i < nItemCount; i++ )
    {
        ListboxAddString( hwnd, aStringList[i] );
    }
}

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

void SAL_CALL ListboxDeleteItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aPosition.hasValue( ) ||
         aPosition.getValueType( ) != getCppuType((sal_Int32*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    sal_Int32 nPos;
    aPosition >>= nPos;

    LRESULT lRet = SendMessage( hwnd, CB_DELETESTRING, nPos, 0 );

    // if the return value is CB_ERR the given
    // index was not correct
    if ( CB_ERR == lRet )
        throw IllegalArgumentException(
            OUString::createFromAscii( "inavlid item position" ),
            rXInterface,
            aArgPos );
}

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

void SAL_CALL ListboxDeleteItems( HWND hwnd, const Any& /*unused*/, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT lRet = 0;

    do
    {
        // the return value on success is the number
        // of remaining elements in the listbox
        lRet = SendMessageW( hwnd, CB_DELETESTRING, 0, 0 );
    }
    while ( (lRet != CB_ERR) && (lRet > 0) );
}

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

void SAL_CALL ListboxSetSelectedItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

     if ( !aPosition.hasValue( ) ||
         aPosition.getValueType( ) != getCppuType((sal_Int32*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    sal_Int32 nPos;
    aPosition >>= nPos;

    if ( nPos < -1 )
        throw IllegalArgumentException(
            OUString::createFromAscii("invalid index"),
            rXInterface,
            aArgPos );

    LRESULT lRet = SendMessageW( hwnd, CB_SETCURSEL, nPos, 0 );

    if ( (CB_ERR == lRet) && (-1 != nPos) )
        throw IllegalArgumentException(
            OUString::createFromAscii("invalid index"),
            rXInterface,
            aArgPos );
}

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

Any SAL_CALL ListboxGetItems( HWND hwnd )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT nItemCount = SendMessageW( hwnd, CB_GETCOUNT, 0, 0 );

    Sequence< OUString > aItemList;

    if ( CB_ERR != nItemCount )
    {
        aItemList.realloc( nItemCount );

        for ( sal_Int32 i = 0; i < nItemCount; i++ )
        {
            aItemList[i] = ListboxGetString( hwnd, i );
        }
    }

    Any aAny;
    aAny <<= aItemList;

    return aAny;
}

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

Any SAL_CALL ListboxGetSelectedItem( HWND hwnd )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 );

    Any aAny;
    aAny <<= ListboxGetString( hwnd, idxItem );

    return aAny;
}

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

Any SAL_CALL CheckboxGetState( HWND hwnd )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT lChkState = SendMessageW( hwnd, BM_GETCHECK, 0, 0 );
    sal_Bool bChkState = (lChkState == BST_CHECKED) ? sal_True : sal_False;
    Any aAny;
    aAny.setValue( &bChkState, getCppuType((sal_Bool*)0) );
    return aAny;
}

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

void SAL_CALL CheckboxSetState(
    HWND hwnd, const ::com::sun::star::uno::Any& aState, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aState.hasValue( ) ||
         aState.getValueType( ) != getCppuType((sal_Bool*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    sal_Bool bCheckState = *reinterpret_cast< const sal_Bool* >( aState.getValue( ) );
    WPARAM wParam = bCheckState ? BST_CHECKED : BST_UNCHECKED;
    SendMessageW( hwnd, BM_SETCHECK, wParam, 0 );
}

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

sal_uInt32 SAL_CALL _wcslenex( const sal_Unicode* pStr )
{
    if ( !pStr )
        return 0;

    const sal_Unicode* pTemp = pStr;
    sal_uInt32 strLen = 0;
    while( *pTemp || *(pTemp + 1) )
    {
        pTemp++;
        strLen++;
    }

    return strLen;
}
<commit_msg>#87759#not so strictly check in methods that expect sal_Int32 now also accepting sal_Int16 and sal_Int8<commit_after>/*************************************************************************
 *
 *  $RCSfile: WinImplHelper.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: tra $ $Date: 2001-06-28 10:34:00 $
 *
 *  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: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _AUTO_BUFFER_HXX_
#include "AutoBuffer.hxx"
#endif

#ifndef _WINIMPLHELPER_HXX_
#include "WinImplHelper.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <systools/win32/user9x.h>

//------------------------------------------------------------
// namespace directives
//------------------------------------------------------------

using rtl::OUString;
using ::com::sun::star::lang::IllegalArgumentException;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Sequence;

//------------------------------------------------------------
// determine if we are running under Win2000
//------------------------------------------------------------

sal_Bool SAL_CALL IsWin2000( )
{
    OSVERSIONINFOEX osvi;
    BOOL bOsVersionInfoEx;
    sal_Bool bRet = sal_False;

    osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
    bOsVersionInfoEx = GetVersionEx( ( OSVERSIONINFO* )&osvi );
    if( !bOsVersionInfoEx )
    {
        // if OSVERSIONINFOEX doesn't work
        osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
        if( !GetVersionEx( ( OSVERSIONINFO* )&osvi ) )
            return sal_False;
    }

    if( ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId ) && ( osvi.dwMajorVersion >= 5 ) )
        bRet = sal_True;

    return bRet;
}

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

void SAL_CALL ListboxAddString( HWND hwnd, const OUString& aString )
{
    LRESULT rc = SendMessageW(
        hwnd, CB_ADDSTRING, 0, reinterpret_cast< LPARAM >(aString.getStr( )) );

    OSL_ASSERT( (CB_ERR != rc) && (CB_ERRSPACE != rc) );
}

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

OUString SAL_CALL ListboxGetString( HWND hwnd, sal_Int32 aPosition )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    OUString aString;

    LRESULT lItem =
        SendMessageW( hwnd, CB_GETLBTEXTLEN, aPosition, 0 );

    if ( (CB_ERR != lItem) && (lItem > 0) )
    {
        // message returns the len of a combobox item
        // without trailing '\0' that's why += 1
        lItem++;

        CAutoUnicodeBuffer aBuff( lItem );

        LRESULT lRet =
            SendMessageW(
                hwnd, CB_GETLBTEXT, aPosition,
                reinterpret_cast<LPARAM>(&aBuff) );

        OSL_ASSERT( lRet != CB_ERR );

        if ( CB_ERR != lRet )
            aString = OUString( aBuff, lRet );
    }

    return aString;
}

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

void SAL_CALL ListboxAddItem( HWND hwnd, const Any& aItem, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aItem.hasValue( ) ||
         aItem.getValueType( ) != getCppuType((OUString*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    OUString cbItem;
    aItem >>= cbItem;

    ListboxAddString( hwnd, cbItem );
}

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

void SAL_CALL ListboxAddItems( HWND hwnd, const Any& aItemList, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aItemList.hasValue( ) ||
         aItemList.getValueType( ) != getCppuType((Sequence<OUString>*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    Sequence< OUString > aStringList;
    aItemList >>= aStringList;

    sal_Int32 nItemCount = aStringList.getLength( );
    for( sal_Int32 i = 0; i < nItemCount; i++ )
    {
        ListboxAddString( hwnd, aStringList[i] );
    }
}

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

void SAL_CALL ListboxDeleteItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aPosition.hasValue( ) ||
         ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) &&
           (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) &&
           (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    sal_Int32 nPos;
    aPosition >>= nPos;

    LRESULT lRet = SendMessage( hwnd, CB_DELETESTRING, nPos, 0 );

    // if the return value is CB_ERR the given
    // index was not correct
    if ( CB_ERR == lRet )
        throw IllegalArgumentException(
            OUString::createFromAscii( "inavlid item position" ),
            rXInterface,
            aArgPos );
}

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

void SAL_CALL ListboxDeleteItems( HWND hwnd, const Any& /*unused*/, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT lRet = 0;

    do
    {
        // the return value on success is the number
        // of remaining elements in the listbox
        lRet = SendMessageW( hwnd, CB_DELETESTRING, 0, 0 );
    }
    while ( (lRet != CB_ERR) && (lRet > 0) );
}

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

void SAL_CALL ListboxSetSelectedItem( HWND hwnd, const Any& aPosition, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

     if ( !aPosition.hasValue( ) ||
         ( (aPosition.getValueType( ) != getCppuType((sal_Int32*)0)) &&
           (aPosition.getValueType( ) != getCppuType((sal_Int16*)0)) &&
           (aPosition.getValueType( ) != getCppuType((sal_Int8*)0)) ) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    sal_Int32 nPos;
    aPosition >>= nPos;

    if ( nPos < -1 )
        throw IllegalArgumentException(
            OUString::createFromAscii("invalid index"),
            rXInterface,
            aArgPos );

    LRESULT lRet = SendMessageW( hwnd, CB_SETCURSEL, nPos, 0 );

    if ( (CB_ERR == lRet) && (-1 != nPos) )
        throw IllegalArgumentException(
            OUString::createFromAscii("invalid index"),
            rXInterface,
            aArgPos );
}

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

Any SAL_CALL ListboxGetItems( HWND hwnd )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT nItemCount = SendMessageW( hwnd, CB_GETCOUNT, 0, 0 );

    Sequence< OUString > aItemList;

    if ( CB_ERR != nItemCount )
    {
        aItemList.realloc( nItemCount );

        for ( sal_Int32 i = 0; i < nItemCount; i++ )
        {
            aItemList[i] = ListboxGetString( hwnd, i );
        }
    }

    Any aAny;
    aAny <<= aItemList;

    return aAny;
}

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

Any SAL_CALL ListboxGetSelectedItem( HWND hwnd )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT idxItem = SendMessageW( hwnd, CB_GETCURSEL, 0, 0 );

    Any aAny;
    aAny <<= ListboxGetString( hwnd, idxItem );

    return aAny;
}

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

Any SAL_CALL CheckboxGetState( HWND hwnd )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    LRESULT lChkState = SendMessageW( hwnd, BM_GETCHECK, 0, 0 );
    sal_Bool bChkState = (lChkState == BST_CHECKED) ? sal_True : sal_False;
    Any aAny;
    aAny.setValue( &bChkState, getCppuType((sal_Bool*)0) );
    return aAny;
}

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

void SAL_CALL CheckboxSetState(
    HWND hwnd, const ::com::sun::star::uno::Any& aState, const Reference< XInterface >& rXInterface, sal_Int16 aArgPos )
    throw( IllegalArgumentException )
{
    OSL_ASSERT( IsWindow( hwnd ) );

    if ( !aState.hasValue( ) ||
         aState.getValueType( ) != getCppuType((sal_Bool*)0) )
         throw IllegalArgumentException(
            OUString::createFromAscii( "invalid value type or any has no value" ),
            rXInterface,
            aArgPos );

    sal_Bool bCheckState = *reinterpret_cast< const sal_Bool* >( aState.getValue( ) );
    WPARAM wParam = bCheckState ? BST_CHECKED : BST_UNCHECKED;
    SendMessageW( hwnd, BM_SETCHECK, wParam, 0 );
}

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

sal_uInt32 SAL_CALL _wcslenex( const sal_Unicode* pStr )
{
    if ( !pStr )
        return 0;

    const sal_Unicode* pTemp = pStr;
    sal_uInt32 strLen = 0;
    while( *pTemp || *(pTemp + 1) )
    {
        pTemp++;
        strLen++;
    }

    return strLen;
}
<|endoftext|>


<commit_before>/**

    Logging for the server.

*/

#ifndef LOG_HPP
#define LOG_HPP

#include <iostream>
#include <fstream>
#include <string>

namespace prattle
{
    class Log
    {
        public:
            Log();
            ~Log();

            void addNewLogOutput(const std::string& log_message);
                                        // Adds a new line to server_log.txt about any important
                                        // events that occurs, e.g. modification of an object etc.

        private:
            std::ofstream m_logFile;
    };
}

#endif // LOG_HPP
<commit_msg>Deleted files that were accidentally pushed<commit_after><|endoftext|>


<commit_before>/* Here is how the code is produced
  1) Get on an airplane with Android phone
  2) Install 'C++ Compiler IDE' from the Play Store
  3) Sometimes it is possible to Google for some code snippets but sometimes not. But it is not documented what version of C++ is being written.
  4) It is very difficult to enter code because extra keystroke attempts are needed to switch between alphabetic, numeric, and symbol
Therefore the effort was quite heroic. */

#include <iostream>
#include <string>
#include <cstdlib>
#include <time.h>  // for random seed
#include <vector>
#include <algorithm>

using namespace std;

char grid[15][15]; // the board to square up
int gridx[100];
int gridy[100];  // row, col coords for each tile on board

class Square
{
    public:
       int row; // 0..10
       int col;  // 0..10
       int cost; // equals tile count in v 0.1
};

bool square_lessthan(Square left, Square right)
       {
        return left.cost < right.cost;
        }

// blah bbbb bbbb bbbbb llll aasas hhhhh

Square all_squares[121]; // each 5x5 square

std::vector<Square> v_squares (all_squares, all_squares+121);

std::string letters  ("AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOO??PPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ");

// Function to randomize the initial position
int initGrid() {

   time_t seconds;
   time(&seconds);
   srand((unsigned int) seconds);

    for (int i=0; i<15; i++) {
        for (int j=0; j<15; j++) {
            grid[i][j] = '_';
    }}

  for (int i =0; i<100;i++)
    {
        for (char g='.';g == '.';)
        {
            int b = rand() % 15;
            int c = rand() % 15;
            if (grid[b][c] == '_')
            {
                g = letters[i];
                grid[b][c] = g;
               gridx[i]=b;
                gridy[i]=c;
             }
        }
    }

   return 0;
}

// version 0.1 movecost is number of moved tiles
// find set of four 5x5 blocks containing maximum number of tiles
int movecost(int a, int b, int u, int v)
{
   if (a==u && b==v)
   {
      return 0;
   } else {
      //return 2 + max(abs(a-u), abs(b-v));
      return 1;
   }
}

// Function to inefficiently determine the cost, given it's the indicator cost function, of moving tiles into any given square
int doCount()
{
   int square_index = 0;
   for (int i=0; i<11; i++)
   {
      for (int j=0; j<11; j++)
      {
         int totalcost = 0;
         for (int k=0; k<5;k++)
         {
            for (int m=0; m<5; m++)
            {
                if (grid[i+k][j+m] !='_')
                {
                      totalcost ++; // todo: 5x speedup
                }
           }
        }
// make a square here
// It's accumulating an array of all the possible squares, with coordinates i,j of upper left corner, and remembering the tile count it contains
        Square* sq = all_squares + square_index++;

        sq->row = i;
       sq->col = j;
        sq->cost = totalcost;

// . . . . . . . . . . . . . . . m

   // cout <<  totalcost << ' ';
   }
  // cout << endl;
}
   return 0;
}

// This uses bubble sort so the list of 5x5 squares is ordered from lowest cost
//  (most tiles in it initially) to highest cost (fewest tiles in it initially).
// The quantity "cost" in the program may be reversed
int doSort() {
    for (int count=0; count < 121; count++) {
      for (int p= 0; p< 120; p++) {
        Square squareone = all_squares[p+1];
        if (all_squares[p].cost < squareone.cost) {
           all_squares[p+1] = all_squares[p];
           all_squares[p] = squareone;
           //cout <<  squareone.cost << '!';
   }}}
}

int showGrid() {
    for (int i=0; i<15; i++)
    {
        for (int j= 0; j<15; j++)
        {
             cout << grid[i][ j ];
        }
        cout << endl;
    }
    return 0;
}

int showSorted() {

    for (int k=0; k<50; k++) {
        //Square sq = v_squares.component(k);
        Square sq = all_squares[k];
        cout << '(' <<  sq.row << ',' << sq.col << ','  << sq.cost  << ") ";
    }
   return 0;
}

// Does square p overlap square q? (referring to the global all_squares array)
bool overlap2(int p, int q) {
    return (abs(all_squares[p].row - all_squares[q].row)<5 && abs(all_squares[p].col - all_squares[q].col)<5);
}

// Do any of the four squares a, b, c, d overlap?  (Variables changed more often in the iteration are checked before others)
bool overlap(int a, int b, int c, int d) {
    return overlap2(d,c) || overlap2(d,b) ||overlap2(d,a) ||overlap2(c,b) ||overlap2(c,a) ||overlap2(b,a) ;
}

int main(){

    cout<<("Squaring Tiles - 0.1 by Kevin Leeds\n"); // Egotizing

    initGrid();  // randomize

   showGrid();

// plan
// v0.1 cost of squaring is number of tiles not in the four squares
// so maximize the tile count inside them
// i guess it can start with the four best and gradually relax and iterate exhaustively

    doCount();

   // std::sort (v_squares.begin(), v_squares.end(), square_lessthan);

   doSort();

 //  showSorted();

   // do complicated loop to search for best combination of four squares
    // simplified by the fact they don't interact to change each other's cost in v 0.1
    // tiles_limit is the max "cost" to consider (cost is perverse - todo: rename it)

    // todo: improve the iteration so it does not re-do all the work each time the target is relaxed
    // and also make it more readable I hope, maybe by abstracting the iterator or pre-computing somehow.

    int a=0;
    int b=a+1;
    int c=b+1;
    int d=c+1;   // start optimistically with the four best squares, but likely they will overlap
    int tiles_restart=all_squares[a].cost +all_squares[b].cost + all_squares[c].cost + all_squares[d].cost;
     //cout << "hope for "+tiles_restart;

    // it starts out optimistic but it gets overlaps
    // it knows it can get tiles_restart but then they overlap
    // so it tries to find another combination without giving up its hope (or a target)
    // if that doesn't work it relaxes its hope

    while (overlap(a,b,c,d)) {
        // conditions are
        // 121>d>c>b>a
        //
        // if tiles_inside unavoidably decreases to less than restart value, start back at 0,1,2,3
        // note 'cost' is actually the tile count, not the cost of moving, so try to maximize it without overlapping here
        int ta = all_squares[a].cost;
        int tb = ta + all_squares[b].cost;
        int tc = tb + all_squares[c].cost;

        // increase d if not exceed
        // this is a 4-nested loop, for upper triangle, a<b<c<d, d ranges from c+1 to end of array, but
        //   if we notice we are outside the target then iterate an earlier variable instead.  this is
        //   inefficient but it does work fast enough to enjoy the output

        if (d<120 && tc+all_squares[d+1].cost>= tiles_restart) {
            d++;
            //cout << 'd';
         } else if (c < 119 && tb+all_squares[c+1].cost+all_squares[c+2].cost>= tiles_restart){
            c++;
            d= c+1;
           // cout << 'c';
         } else if (b<118 && ta + all_squares[b+1].cost + all_squares[b+2].cost+all_squares[b+3].cost >= tiles_restart) {
            b++;
            c=b+1;
            d=c+1;
            //cout << 'b';
         } else if (a<117 && all_squares[a+1].cost+all_squares[a+2].cost+all_squares[a+3].cost+all_squares[a+4].cost >= tiles_restart ) {
            a++;
            b=a+1;
            c=b+1;
            d=c+1;
            //cout << 'a';
         } else {
            a=1;
            b=a+1;
            c=b+1;
            d=c+1;
            tiles_restart--;
            //cout << "Hoping for " << tiles_restart << "\n";
         }

       // cout << a << ' ' << b << ' ' << c << ' ' << d << '\n';

    }

   // cout << "Answer:\n";
 //  cout << "a,b,c,d=" << a << "," << b << "," << c << "," << d << "\n";
    cout << '(' << all_squares[a].row << ',' << all_squares[a].col << ") =" << all_squares[a].cost << " ";

Square* all_tiles = all_squares; // compensate for typo/goof

cout << '(' << all_tiles[b].row << ',' << all_tiles[b].col << ") =" << all_tiles[b].cost << " ";
cout << '(' << all_tiles[c].row << ',' << all_tiles[c].col << ") =" << all_tiles[d].cost << " ";
cout << '(' << all_tiles[d].row << ',' << all_tiles[d].col << ") =" << all_tiles[d].cost << " ";

cout << "total tiles to not move is " << all_tiles[a].cost + all_tiles[b].cost + all_tiles[c].cost + all_tiles[d].cost << ".\n";

    return 0;
}

<commit_msg>square.cost vs. square.tilecount, clean up<commit_after>/* Here is how the code is produced
  1) Get on an airplane with Android phone
  2) Install 'C++ Compiler IDE' from the Play Store
  3) Sometimes it is possible to Google for some code snippets but sometimes not.
     But it is not documented what version of C++ is being written.
  4) It is very difficult to enter code because extra keystroke attempts are needed to switch
     between alphabetic, numeric, and symbol
Therefore the effort was quite heroic. */

#include <iostream>
#include <string>
#include <cstdlib>
#include <time.h>  // for random seed
#include <vector>
#include <algorithm> // to sort using vector and algorithm got accomplished only partly

using namespace std;

char grid[15][15]; // the board to square up
int gridx[100];
int gridy[100];  // row, col coords for each tile on board

class Square
{
    // represents a 5x5 square, a sub-region of the 15x15 grid.
    public:
       int row; // 0..10
       int col;  // 0..10
       int tilecount;
       int cost;  // would be 25 - tilecount.
};

// blah bbbb bbbb bbbbb llll aasas hhhhh

Square all_squares[121]; // each 5x5 square

std::vector<Square> v_squares (all_squares, all_squares+121);

std::string letters  ("AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOO??PPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ");

// Function to randomize the initial position
int initGrid() {

   time_t seconds;
   time(&seconds);
   srand((unsigned int) seconds);

    for (int i=0; i<15; i++) {
        for (int j=0; j<15; j++) {
            grid[i][j] = '_';
    }}

  for (int i =0; i<100;i++)
    {
        for (char g='.';g == '.';)
        {
            int b = rand() % 15;
            int c = rand() % 15;
            if (grid[b][c] == '_')
            {
                g = letters[i];
                grid[b][c] = g;
               gridx[i]=b;
                gridy[i]=c;
             }
        }
    }

   return 0;
}

// version 0.1 movecost is number of moved tiles
// find set of four 5x5 blocks containing maximum number of tiles
int movecost(int a, int b, int u, int v)
{
   if (a==u && b==v)
   {
      return 0;
   } else {
      //return 2 + max(abs(a-u), abs(b-v));
      return 1;
   }
}

// Function to inefficiently determine the cost, given it's the indicator cost function, of moving tiles into any given square
int doCount()
{
   int square_index = 0;
   for (int i=0; i<11; i++)
   {
      for (int j=0; j<11; j++)
      {
         int tcount = 0;
         for (int k=0; k<5;k++)
         {
            for (int m=0; m<5; m++)
            {
                if (grid[i+k][j+m] !='_')
                {
                      tcount ++; // todo: 5x speedup
                }
           }
        }
// make a 5x5 square here, and add it to the array
       Square* sq = all_squares + square_index++;

        sq->row = i;
        sq->col = j;
        sq->tilecount = tcount;
        sq->cost = 25 - tcount;

   // cout <<  totalcost << ' ';
   }
  // cout << endl;
}
   return 0;
}

// This uses bubble sort so the list of 5x5 squares is ordered from lowest cost to highest cost.
// todo: i think a better bubble sort might move the bubble more than 1 spot at a time.
int doSort() {
  for (int count=0; count < 121; count++) {
    for (int p= 0; p< 120; p++) {
      Square low_cost_square = all_squares[p+1];
      if (all_squares[p].cost < low_cost_square.cost) {
         all_squares[p+1] = all_squares[p];
         all_squares[p] = low_cost_square;
         //cout <<  squareone.cost << '!';
      }
    }
  }
}

int showGrid() {
    for (int i=0; i<15; i++)
    {
        for (int j= 0; j<15; j++)
        {
             cout << grid[i][ j ];
        }
        cout << endl;
    }
    return 0;
}

int showSorted() {

    for (int k=0; k<50; k++) {
        //Square sq = v_squares.component(k);
        Square sq = all_squares[k];
        cout << '(' <<  sq.row << ',' << sq.col << ','  << sq.cost  << ") ";
    }
   return 0;
}

// Does square p overlap square q? (referring to the global all_squares array)
bool overlap2(int p, int q) {
    return (abs(all_squares[p].row - all_squares[q].row)<5 && abs(all_squares[p].col - all_squares[q].col)<5);
}

// Do any of the four squares a, b, c, d overlap?  (Variables changed more often in the iteration are checked before others)
bool overlap(int a, int b, int c, int d) {
    return overlap2(d,c) || overlap2(d,b) ||overlap2(d,a) ||overlap2(c,b) ||overlap2(c,a) ||overlap2(b,a) ;
}

int main(){

    cout<<("Squaring Tiles - 0.1 by Kevin Leeds\n"); // Egotizing

    initGrid();  // randomize

   showGrid();

//
// v0.1 cost of squaring is number of tiles not in the four squares, so maximize the tile count inside them
// Work with a list all the possible 5x5 squares, sorted from lowest cost to highest
// Inspect all combinations of four of those.  Iterate to gradually increase the sum of the four costs ...
//    Don't look at higher cost solutions til various combinations have been inspected
//    That cutoff quantity is called "tiles_restart" in the program.
//    Then all that has to be done is locate a set that does not have overlaps - the first one encountered will be the best answer.

// If the cost function is more complicated then the search will not be so simple,
//   because the location of each region will affect the cost amount of itself and the other ones too.

    doCount();

   // std::sort (v_squares.begin(), v_squares.end(), square_lessthan);

   doSort();

 //  showSorted();

   // do complicated loop to search for best combination of four squares
    // simplified by the fact they don't interact to change each other's cost in v 0.1
    // tiles_limit is the max "cost" to consider (cost is perverse - todo: rename it)

    // todo: improve the iteration so it does not re-do all the work each time the target is relaxed
    // and also make it more readable I hope, maybe by abstracting the iterator or pre-computing somehow.

    int a=0;
    int b=a+1;
    int c=b+1;
    int d=c+1;   // start optimistically with the four best squares, but likely they will overlap
    int tiles_restart = all_squares[a].cost +all_squares[b].cost + all_squares[c].cost + all_squares[d].cost;
     //cout << "hope for "+tiles_restart;

    // it starts out optimistic but it gets overlaps
    // it knows it can get tiles_restart but then they overlap
    // so it tries to find another combination without giving up its hope (or a target)
    // if that doesn't work it relaxes its hope

    while (overlap(a,b,c,d)) {
        // conditions are
        // 121>d>c>b>a
        //
        // if tiles_inside unavoidably decreases to less than restart value, start back at 0,1,2,3
        // note 'cost' is actually the tile count, not the cost of moving, so try to maximize it without overlapping here
        int ta = all_squares[a].cost;
        int tb = ta + all_squares[b].cost;
        int tc = tb + all_squares[c].cost;

        // increase d if not exceed
        // this is a 4-nested loop, for upper triangle, a<b<c<d, d ranges from c+1 to end of array, but
        //   if we notice we are outside the target then iterate an earlier variable instead.  this is
        //   inefficient but it does work fast enough to enjoy the output

        if (d<120 && tc+all_squares[d+1].cost <= tiles_restart) {
            d++;
            //cout << 'd';
         } else if (c < 119 && tb+all_squares[c+1].cost+all_squares[c+2].cost <= tiles_restart){
            c++;
            d= c+1;
           // cout << 'c';
         } else if (b<118 && ta + all_squares[b+1].cost + all_squares[b+2].cost+all_squares[b+3].cost <= tiles_restart) {
            b++;
            c=b+1;
            d=c+1;
            //cout << 'b';
         } else if (a<117 && all_squares[a+1].cost+all_squares[a+2].cost+all_squares[a+3].cost+all_squares[a+4].cost <= tiles_restart ) {
            a++;
            b=a+1;
            c=b+1;
            d=c+1;
            //cout << 'a';
         } else {
            a=1;
            b=a+1;
            c=b+1;
            d=c+1;
            tiles_restart++;
            //cout << "Hoping for " << tiles_restart << "\n";
         }

       // cout << a << ' ' << b << ' ' << c << ' ' << d << '\n';

    }

   // cout << "Answer:\n";
 //  cout << "a,b,c,d=" << a << "," << b << "," << c << "," << d << "\n";
    cout << '(' << all_squares[a].row << ',' << all_squares[a].col << ") =" << all_squares[a].cost << " ";

cout << '(' << all_squares[b].row << ',' << all_squares[b].col << ") =" << all_squares[b].cost << " ";
cout << '(' << all_squares[c].row << ',' << all_squares[c].col << ") =" << all_squares[d].cost << " ";
cout << '(' << all_squares[d].row << ',' << all_squares[d].col << ") =" << all_squares[d].cost << " ";

cout << "total tiles to move is " << all_squares[a].cost + all_squares[b].cost + all_squares[c].cost + all_squares[d].cost << ".\n";

    return 0;
}

<|endoftext|>


<commit_before><commit_msg>Adicionada questão de adivinhar estruturas<commit_after><|endoftext|>