<commit_before>/*
 * Copyright (c) 2017, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "SARA4_PPP.h"
#include "SARA4_PPP_CellularNetwork.h"

using namespace mbed;
using namespace events;

static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = {
    AT_CellularNetwork::RegistrationModeLAC, // C_EREG
    AT_CellularNetwork::RegistrationModeLAC, // C_GREG
    AT_CellularNetwork::RegistrationModeDisable, // C_REG
    0,  // AT_CGSN_WITH_TYPE
    0,  // AT_CGDATA
    1,  // AT_CGAUTH
    1,  // AT_CNMI
    1,  // AT_CSMP
    1,  // AT_CMGF
    1,  // AT_CSDH
    1,  // PROPERTY_IPV4_STACK
    0,  // PROPERTY_IPV6_STACK
    0,  // PROPERTY_IPV4V6_STACK
    0,  // PROPERTY_NON_IP_PDP_TYPE
    1,  // PROPERTY_AT_CGEREP
    1,  // PROPERTY_AT_COPS_FALLBACK_AUTO
    0,  // PROPERTY_SOCKET_COUNT
    0,  // PROPERTY_IP_TCP
    0,  // PROPERTY_IP_UDP
    0,  // PROPERTY_AT_SEND_DELAY
};

SARA4_PPP::SARA4_PPP(FileHandle *fh) : AT_CellularDevice(fh)
{
    set_cellular_properties(cellular_properties);
}

AT_CellularNetwork *SARA4_PPP::open_network_impl(ATHandler &at)
{
    return new SARA4_PPP_CellularNetwork(at, *this);
}

#if MBED_CONF_SARA4_PPP_PROVIDE_DEFAULT
#include "drivers/BufferedSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
    static BufferedSerial serial(MBED_CONF_SARA4_PPP_TX, MBED_CONF_SARA4_PPP_RX, MBED_CONF_SARA4_PPP_BAUDRATE);
#if defined (MBED_CONF_SARA4_PPP_RTS) && defined (MBED_CONF_SARA4_PPP_CTS)
    tr_debug("SARA4_PPP flow control: RTS %d CTS %d", MBED_CONF_SARA4_PPP_RTS, MBED_CONF_SARA4_PPP_CTS);
    serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_SARA4_PPP_RTS, MBED_CONF_SARA4_PPP_CTS);
#endif
    static SARA4_PPP device(&serial);
    return &device;
}
#endif
<commit_msg>PDP Type needs to be IPV4V6<commit_after>/*
 * Copyright (c) 2017, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "SARA4_PPP.h"
#include "SARA4_PPP_CellularNetwork.h"

using namespace mbed;
using namespace events;

static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = {
    AT_CellularNetwork::RegistrationModeLAC, // C_EREG
    AT_CellularNetwork::RegistrationModeLAC, // C_GREG
    AT_CellularNetwork::RegistrationModeDisable, // C_REG
    0,  // AT_CGSN_WITH_TYPE
    0,  // AT_CGDATA
    1,  // AT_CGAUTH
    1,  // AT_CNMI
    1,  // AT_CSMP
    1,  // AT_CMGF
    1,  // AT_CSDH
    0,  // PROPERTY_IPV4_STACK
    0,  // PROPERTY_IPV6_STACK
    1,  // PROPERTY_IPV4V6_STACK
    0,  // PROPERTY_NON_IP_PDP_TYPE
    1,  // PROPERTY_AT_CGEREP
    1,  // PROPERTY_AT_COPS_FALLBACK_AUTO
    0,  // PROPERTY_SOCKET_COUNT
    0,  // PROPERTY_IP_TCP
    0,  // PROPERTY_IP_UDP
    0,  // PROPERTY_AT_SEND_DELAY
};

SARA4_PPP::SARA4_PPP(FileHandle *fh) : AT_CellularDevice(fh)
{
    set_cellular_properties(cellular_properties);
}

AT_CellularNetwork *SARA4_PPP::open_network_impl(ATHandler &at)
{
    return new SARA4_PPP_CellularNetwork(at, *this);
}

#if MBED_CONF_SARA4_PPP_PROVIDE_DEFAULT
#include "drivers/BufferedSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
    static BufferedSerial serial(MBED_CONF_SARA4_PPP_TX, MBED_CONF_SARA4_PPP_RX, MBED_CONF_SARA4_PPP_BAUDRATE);
#if defined (MBED_CONF_SARA4_PPP_RTS) && defined (MBED_CONF_SARA4_PPP_CTS)
    tr_debug("SARA4_PPP flow control: RTS %d CTS %d", MBED_CONF_SARA4_PPP_RTS, MBED_CONF_SARA4_PPP_CTS);
    serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_SARA4_PPP_RTS, MBED_CONF_SARA4_PPP_CTS);
#endif
    static SARA4_PPP device(&serial);
    return &device;
}
#endif
<|endoftext|>


<commit_before>#include "ctrcommon/sound.hpp"

#include "service.hpp"

#include <3ds.h>

void* soundAlloc(u32 size) {
    return linearAlloc(size);
}

void soundFree(void* mem) {
    linearFree(mem);
}

bool soundPlay(u32 channel, SoundFormat format, u32 sampleRate, void* samples, u32 numSamples) {
    if(!serviceRequire("csnd")) {
        return false;
    }

    if(channel > 7) {
        channel = 7;
    }

    GSPGPU_FlushDataCache(NULL, (u8*) samples, numSamples * (format == FORMAT_PCM16 ? 2 : 1));
    Result res = csndPlaySound((int) (8 + channel), format | SOUND_ONE_SHOT, sampleRate, samples, samples, numSamples * (format == FORMAT_PCM16 ? 2 : 1));
    if(res != 0) {
        platformSetError(serviceParseError((u32) res));
    }

    return res == 0;
}<commit_msg>Update to latest ctrulib.<commit_after>#include "ctrcommon/sound.hpp"

#include "service.hpp"

#include <3ds.h>

void* soundAlloc(u32 size) {
    return linearAlloc(size);
}

void soundFree(void* mem) {
    linearFree(mem);
}

bool soundPlay(u32 channel, SoundFormat format, u32 sampleRate, void* samples, u32 numSamples) {
    if(!serviceRequire("csnd")) {
        return false;
    }

    if(channel > 7) {
        channel = 7;
    }

    GSPGPU_FlushDataCache(NULL, (u8*) samples, numSamples * (format == FORMAT_PCM16 ? 2 : 1));
    Result res = csndPlaySound((int) (8 + channel), format | SOUND_ONE_SHOT, sampleRate, 1, 0, samples, samples, numSamples * (format == FORMAT_PCM16 ? 2 : 1));
    if(res != 0) {
        platformSetError(serviceParseError((u32) res));
    }

    return res == 0;
}<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            ipc/pipe_channel.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "ipc/pipe_channel.h"
#include "ipc/pipe_channel_proxy.h"
#include "base/version_helpers.h"
#include "base/security_helpers.h"
#include "base/strings/string_util.h"
#include "base/logging.h"

#include <random>

namespace aspia {

static const WCHAR kPipeNamePrefix[] = L"\\\\.\\pipe\\aspia.";
static const DWORD kPipeBufferSize = 512 * 1024; // 512 KB

static std::atomic_uint32_t _last_channel_id = 0;

static bool IsFailureCode(const std::error_code& code)
{
    return code.value() != 0;
}

static std::wstring GenerateUniqueRandomChannelID()
{
    uint32_t process_id = GetCurrentProcessId();
    uint32_t last_channel_id = _last_channel_id;

    std::random_device device;
    std::uniform_int_distribution<uint32_t> uniform(
        0, std::numeric_limits<uint32_t>::max());

    uint32_t random = uniform(device);

    ++_last_channel_id;

    return StringPrintfW(L"%u.%u.%u", process_id, last_channel_id, random);
}

static std::wstring CreatePipeName(const std::wstring& channel_id)
{
    std::wstring pipe_name(kPipeNamePrefix);
    pipe_name.append(channel_id);

    return pipe_name;
}

// static
std::unique_ptr<PipeChannel> PipeChannel::CreateServer(
    std::wstring& channel_id)
{
    std::wstring user_sid;

    if (!GetUserSidString(user_sid))
    {
        LOG(ERROR) << "Failed to query the current user SID";
        return nullptr;
    }

    // Create a security descriptor that gives full access to the caller and
    // BUILTIN_ADMINISTRATORS and denies access by anyone else.
    // Local admins need access because the privileged host process will run
    // as a local admin which may not be the same user as the current user.
    std::wstring security_descriptor =
        StringPrintfW(L"O:%sG:%sD:(A;;GA;;;%s)(A;;GA;;;BA)",
                      user_sid.c_str(),
                      user_sid.c_str(),
                      user_sid.c_str());

    ScopedSd sd = ConvertSddlToSd(security_descriptor);
    if (!sd.get())
    {
        LOG(ERROR) << "Failed to create a security descriptor";
        return nullptr;
    }

    SECURITY_ATTRIBUTES security_attributes = { 0 };
    security_attributes.nLength = sizeof(security_attributes);
    security_attributes.lpSecurityDescriptor = sd.get();
    security_attributes.bInheritHandle = FALSE;

    channel_id = GenerateUniqueRandomChannelID();

    DWORD open_mode = FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
    DWORD pipe_mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;

    // Windows XP/2003 does't support this flag.
    if (IsWindowsVistaOrGreater())
        pipe_mode |= PIPE_REJECT_REMOTE_CLIENTS;

    ScopedHandle pipe(CreateNamedPipeW(CreatePipeName(channel_id).c_str(),
                                       open_mode | PIPE_ACCESS_DUPLEX,
                                       pipe_mode,
                                       1,
                                       kPipeBufferSize,
                                       kPipeBufferSize,
                                       5000,
                                       &security_attributes));

    if (!pipe.IsValid())
    {
        LOG(ERROR) << "CreateNamedPipeW() failed: "
                   << GetLastSystemErrorString();
        return nullptr;
    }

    return std::unique_ptr<PipeChannel>(
        new PipeChannel(pipe.Release(), Mode::SERVER));
}

// static
std::unique_ptr<PipeChannel> PipeChannel::CreateClient(
    const std::wstring& channel_id)
{
    DWORD flags = SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
                  FILE_FLAG_OVERLAPPED;

    ScopedHandle pipe(CreateFileW(CreatePipeName(channel_id).c_str(),
                                  GENERIC_WRITE | GENERIC_READ,
                                  0,
                                  nullptr,
                                  OPEN_EXISTING,
                                  flags,
                                  nullptr));
    if (!pipe.IsValid())
    {
        LOG(ERROR) << "CreateFileW() failed: " << GetLastSystemErrorString();
        return nullptr;
    }

    return std::unique_ptr<PipeChannel>(
        new PipeChannel(pipe.Release(), Mode::CLIENT));
}

PipeChannel::PipeChannel(HANDLE pipe, Mode mode)
    : mode_(mode)
{
    proxy_.reset(new PipeChannelProxy(this));

    std::error_code ignored_code;
    stream_.assign(pipe, ignored_code);

    Start();
}

PipeChannel::~PipeChannel()
{
    proxy_->WillDestroyCurrentChannel();
    proxy_ = nullptr;

    io_service_.dispatch(std::bind(&PipeChannel::DoDisconnect, this));
    Stop();
}

void PipeChannel::ScheduleWrite()
{
    DCHECK(!write_queue_.empty());

    write_buffer_ = std::move(write_queue_.front().first);

    if (!write_buffer_)
    {
        DoDisconnect();
        return;
    }

    write_size_ = write_buffer_->size();

    asio::async_write(stream_,
                      asio::buffer(&write_size_, sizeof(uint32_t)),
                      std::bind(&PipeChannel::OnWriteSizeComplete,
                                this,
                                std::placeholders::_1,
                                std::placeholders::_2));
}

void PipeChannel::OnWriteSizeComplete(const std::error_code& code,
                                      size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != sizeof(uint32_t))
    {
        DoDisconnect();
        return;
    }

    asio::async_write(stream_,
                      asio::buffer(write_buffer_->data(),
                                   write_buffer_->size()),
                      std::bind(&PipeChannel::OnWriteComplete,
                                this,
                                std::placeholders::_1,
                                std::placeholders::_2));
}

void PipeChannel::OnWriteComplete(const std::error_code& code,
                                  size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != write_buffer_->size())
    {
        DoDisconnect();
        return;
    }

    SendCompleteHandler complete_handler;

    {
        std::lock_guard<std::mutex> lock(write_queue_lock_);

        // The queue must contain the current write task.
        DCHECK(!write_queue_.empty());

        complete_handler = std::move(write_queue_.front().second);
        write_queue_.pop();

        if (!write_queue_.empty())
            ScheduleWrite();
    }

    if (complete_handler != nullptr)
        complete_handler();
}

void PipeChannel::Send(std::unique_ptr<IOBuffer> buffer,
                       SendCompleteHandler handler)
{
    std::lock_guard<std::mutex> lock(write_queue_lock_);

    bool schedule_write = write_queue_.empty();

    write_queue_.push(
        std::make_pair<std::unique_ptr<IOBuffer>, SendCompleteHandler>(
            std::move(buffer), std::move(handler)));

    if (schedule_write)
        ScheduleWrite();
}

void PipeChannel::Send(std::unique_ptr<IOBuffer> buffer)
{
    Send(std::move(buffer), nullptr);
}

bool PipeChannel::Connect(uint32_t& user_data,
                          DisconnectHandler disconnect_handler)
{
    disconnect_handler_ = std::move(disconnect_handler);

    std::error_code ignored_code;
    uint32_t remote_user_data;

    if (mode_ == Mode::SERVER)
    {
        if (!ConnectNamedPipe(stream_.native_handle(), nullptr))
        {
            LOG(ERROR) << "ConnectNamedPipe() failed: "
                       << GetLastSystemErrorString();
            return false;
        }

        if (asio::read(stream_,
                       asio::buffer(&remote_user_data,
                                    sizeof(remote_user_data)),
                       ignored_code) != sizeof(remote_user_data))
            return false;

        if (asio::write(stream_,
                        asio::buffer(&user_data, sizeof(user_data)),
                        ignored_code) != sizeof(user_data))
            return false;
    }
    else
    {
        DCHECK(mode_ == Mode::CLIENT);

        if (asio::write(stream_,
                        asio::buffer(&user_data, sizeof(user_data)),
                        ignored_code) != sizeof(user_data))
            return false;

        if (asio::read(stream_,
                       asio::buffer(&remote_user_data,
                                    sizeof(remote_user_data)),
                       ignored_code) != sizeof(remote_user_data))
            return false;
    }

    user_data = remote_user_data;
    return true;
}

void PipeChannel::ScheduleRead()
{
    asio::async_read(stream_,
                     asio::buffer(&read_size_, sizeof(uint32_t)),
                     std::bind(&PipeChannel::OnReadSizeComplete,
                               this,
                               std::placeholders::_1,
                               std::placeholders::_2));
}

void PipeChannel::OnReadSizeComplete(const std::error_code& code,
                                     size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != sizeof(uint32_t))
    {
        DoDisconnect();
        return;
    }

    if (!read_size_)
    {
        DoDisconnect();
        return;
    }

    read_buffer_ = std::make_unique<IOBuffer>(read_size_);

    asio::async_read(stream_,
                     asio::buffer(read_buffer_->data(), read_buffer_->size()),
                     std::bind(&PipeChannel::OnReadComplete,
                               this,
                               std::placeholders::_1,
                               std::placeholders::_2));
}

void PipeChannel::OnReadComplete(const std::error_code& code,
                                 size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != read_buffer_->size())
    {
        DoDisconnect();
        return;
    }

    receive_complete_handler_(std::move(read_buffer_));
}

void PipeChannel::Receive(ReceiveCompleteHandler handler)
{
    DCHECK(handler != nullptr);
    receive_complete_handler_ = std::move(handler);
    io_service_.post(std::bind(&PipeChannel::ScheduleRead, this));
}

void PipeChannel::DoDisconnect()
{
    StopSoon();

    std::error_code ignored_code;
    stream_.close(ignored_code);

    work_.reset();

    if (!io_service_.stopped())
        io_service_.stop();
}

void PipeChannel::Run()
{
    work_ = std::make_unique<asio::io_service::work>(io_service_);

    std::error_code ignored_code;
    io_service_.run(ignored_code);

    if (disconnect_handler_ != nullptr)
        disconnect_handler_();
}

} // namespace aspia
<commit_msg>- Allow access for all authenticated users.<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            ipc/pipe_channel.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "ipc/pipe_channel.h"
#include "ipc/pipe_channel_proxy.h"
#include "base/version_helpers.h"
#include "base/security_helpers.h"
#include "base/strings/string_util.h"
#include "base/logging.h"

#include <random>

namespace aspia {

static const WCHAR kPipeNamePrefix[] = L"\\\\.\\pipe\\aspia.";
static const DWORD kPipeBufferSize = 512 * 1024; // 512 KB

static std::atomic_uint32_t _last_channel_id = 0;

static bool IsFailureCode(const std::error_code& code)
{
    return code.value() != 0;
}

static std::wstring GenerateUniqueRandomChannelID()
{
    uint32_t process_id = GetCurrentProcessId();
    uint32_t last_channel_id = _last_channel_id;

    std::random_device device;
    std::uniform_int_distribution<uint32_t> uniform(
        0, std::numeric_limits<uint32_t>::max());

    uint32_t random = uniform(device);

    ++_last_channel_id;

    return StringPrintfW(L"%u.%u.%u", process_id, last_channel_id, random);
}

static std::wstring CreatePipeName(const std::wstring& channel_id)
{
    std::wstring pipe_name(kPipeNamePrefix);
    pipe_name.append(channel_id);

    return pipe_name;
}

// static
std::unique_ptr<PipeChannel> PipeChannel::CreateServer(
    std::wstring& channel_id)
{
    std::wstring user_sid;

    if (!GetUserSidString(user_sid))
    {
        LOG(ERROR) << "Failed to query the current user SID";
        return nullptr;
    }

    // Create a security descriptor that gives full access to the caller and
    // authenticated users and denies access by anyone else.
    // Local admins need access because the privileged host process will run
    // as a local admin which may not be the same user as the current user.
    std::wstring security_descriptor =
        StringPrintfW(L"O:%sG:%sD:(A;;GA;;;%s)(A;;GA;;;AU)",
                      user_sid.c_str(),
                      user_sid.c_str(),
                      user_sid.c_str());

    ScopedSd sd = ConvertSddlToSd(security_descriptor);
    if (!sd.get())
    {
        LOG(ERROR) << "Failed to create a security descriptor";
        return nullptr;
    }

    SECURITY_ATTRIBUTES security_attributes = { 0 };
    security_attributes.nLength = sizeof(security_attributes);
    security_attributes.lpSecurityDescriptor = sd.get();
    security_attributes.bInheritHandle = FALSE;

    channel_id = GenerateUniqueRandomChannelID();

    DWORD open_mode = FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
    DWORD pipe_mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;

    // Windows XP/2003 does't support this flag.
    if (IsWindowsVistaOrGreater())
        pipe_mode |= PIPE_REJECT_REMOTE_CLIENTS;

    ScopedHandle pipe(CreateNamedPipeW(CreatePipeName(channel_id).c_str(),
                                       open_mode | PIPE_ACCESS_DUPLEX,
                                       pipe_mode,
                                       1,
                                       kPipeBufferSize,
                                       kPipeBufferSize,
                                       5000,
                                       &security_attributes));

    if (!pipe.IsValid())
    {
        LOG(ERROR) << "CreateNamedPipeW() failed: "
                   << GetLastSystemErrorString();
        return nullptr;
    }

    return std::unique_ptr<PipeChannel>(
        new PipeChannel(pipe.Release(), Mode::SERVER));
}

// static
std::unique_ptr<PipeChannel> PipeChannel::CreateClient(
    const std::wstring& channel_id)
{
    DWORD flags = SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
                  FILE_FLAG_OVERLAPPED;

    ScopedHandle pipe(CreateFileW(CreatePipeName(channel_id).c_str(),
                                  GENERIC_WRITE | GENERIC_READ,
                                  0,
                                  nullptr,
                                  OPEN_EXISTING,
                                  flags,
                                  nullptr));
    if (!pipe.IsValid())
    {
        LOG(ERROR) << "CreateFileW() failed: " << GetLastSystemErrorString();
        return nullptr;
    }

    return std::unique_ptr<PipeChannel>(
        new PipeChannel(pipe.Release(), Mode::CLIENT));
}

PipeChannel::PipeChannel(HANDLE pipe, Mode mode)
    : mode_(mode)
{
    proxy_.reset(new PipeChannelProxy(this));

    std::error_code ignored_code;
    stream_.assign(pipe, ignored_code);

    Start();
}

PipeChannel::~PipeChannel()
{
    proxy_->WillDestroyCurrentChannel();
    proxy_ = nullptr;

    io_service_.dispatch(std::bind(&PipeChannel::DoDisconnect, this));
    Stop();
}

void PipeChannel::ScheduleWrite()
{
    DCHECK(!write_queue_.empty());

    write_buffer_ = std::move(write_queue_.front().first);

    if (!write_buffer_)
    {
        DoDisconnect();
        return;
    }

    write_size_ = write_buffer_->size();

    asio::async_write(stream_,
                      asio::buffer(&write_size_, sizeof(uint32_t)),
                      std::bind(&PipeChannel::OnWriteSizeComplete,
                                this,
                                std::placeholders::_1,
                                std::placeholders::_2));
}

void PipeChannel::OnWriteSizeComplete(const std::error_code& code,
                                      size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != sizeof(uint32_t))
    {
        DoDisconnect();
        return;
    }

    asio::async_write(stream_,
                      asio::buffer(write_buffer_->data(),
                                   write_buffer_->size()),
                      std::bind(&PipeChannel::OnWriteComplete,
                                this,
                                std::placeholders::_1,
                                std::placeholders::_2));
}

void PipeChannel::OnWriteComplete(const std::error_code& code,
                                  size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != write_buffer_->size())
    {
        DoDisconnect();
        return;
    }

    SendCompleteHandler complete_handler;

    {
        std::lock_guard<std::mutex> lock(write_queue_lock_);

        // The queue must contain the current write task.
        DCHECK(!write_queue_.empty());

        complete_handler = std::move(write_queue_.front().second);
        write_queue_.pop();

        if (!write_queue_.empty())
            ScheduleWrite();
    }

    if (complete_handler != nullptr)
        complete_handler();
}

void PipeChannel::Send(std::unique_ptr<IOBuffer> buffer,
                       SendCompleteHandler handler)
{
    std::lock_guard<std::mutex> lock(write_queue_lock_);

    bool schedule_write = write_queue_.empty();

    write_queue_.push(
        std::make_pair<std::unique_ptr<IOBuffer>, SendCompleteHandler>(
            std::move(buffer), std::move(handler)));

    if (schedule_write)
        ScheduleWrite();
}

void PipeChannel::Send(std::unique_ptr<IOBuffer> buffer)
{
    Send(std::move(buffer), nullptr);
}

bool PipeChannel::Connect(uint32_t& user_data,
                          DisconnectHandler disconnect_handler)
{
    disconnect_handler_ = std::move(disconnect_handler);

    std::error_code ignored_code;
    uint32_t remote_user_data;

    if (mode_ == Mode::SERVER)
    {
        if (!ConnectNamedPipe(stream_.native_handle(), nullptr))
        {
            LOG(ERROR) << "ConnectNamedPipe() failed: "
                       << GetLastSystemErrorString();
            return false;
        }

        if (asio::read(stream_,
                       asio::buffer(&remote_user_data,
                                    sizeof(remote_user_data)),
                       ignored_code) != sizeof(remote_user_data))
            return false;

        if (asio::write(stream_,
                        asio::buffer(&user_data, sizeof(user_data)),
                        ignored_code) != sizeof(user_data))
            return false;
    }
    else
    {
        DCHECK(mode_ == Mode::CLIENT);

        if (asio::write(stream_,
                        asio::buffer(&user_data, sizeof(user_data)),
                        ignored_code) != sizeof(user_data))
            return false;

        if (asio::read(stream_,
                       asio::buffer(&remote_user_data,
                                    sizeof(remote_user_data)),
                       ignored_code) != sizeof(remote_user_data))
            return false;
    }

    user_data = remote_user_data;
    return true;
}

void PipeChannel::ScheduleRead()
{
    asio::async_read(stream_,
                     asio::buffer(&read_size_, sizeof(uint32_t)),
                     std::bind(&PipeChannel::OnReadSizeComplete,
                               this,
                               std::placeholders::_1,
                               std::placeholders::_2));
}

void PipeChannel::OnReadSizeComplete(const std::error_code& code,
                                     size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != sizeof(uint32_t))
    {
        DoDisconnect();
        return;
    }

    if (!read_size_)
    {
        DoDisconnect();
        return;
    }

    read_buffer_ = std::make_unique<IOBuffer>(read_size_);

    asio::async_read(stream_,
                     asio::buffer(read_buffer_->data(), read_buffer_->size()),
                     std::bind(&PipeChannel::OnReadComplete,
                               this,
                               std::placeholders::_1,
                               std::placeholders::_2));
}

void PipeChannel::OnReadComplete(const std::error_code& code,
                                 size_t bytes_transferred)
{
    if (IsFailureCode(code) || bytes_transferred != read_buffer_->size())
    {
        DoDisconnect();
        return;
    }

    receive_complete_handler_(std::move(read_buffer_));
}

void PipeChannel::Receive(ReceiveCompleteHandler handler)
{
    DCHECK(handler != nullptr);
    receive_complete_handler_ = std::move(handler);
    io_service_.post(std::bind(&PipeChannel::ScheduleRead, this));
}

void PipeChannel::DoDisconnect()
{
    StopSoon();

    std::error_code ignored_code;
    stream_.close(ignored_code);

    work_.reset();

    if (!io_service_.stopped())
        io_service_.stop();
}

void PipeChannel::Run()
{
    work_ = std::make_unique<asio::io_service::work>(io_service_);

    std::error_code ignored_code;
    io_service_.run(ignored_code);

    if (disconnect_handler_ != nullptr)
        disconnect_handler_();
}

} // namespace aspia
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_check_for_ready.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file exp_check_for_ready.C
/// @brief FW polls I2C slave interface to determine when it is ready
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <exp_check_for_ready.H>
#include <lib/i2c/exp_i2c.H>
#include <generic/memory/lib/utils/poll.H>

extern "C"
{
///
/// @brief Checks if the explorer I2C is ready to receive commands
/// @param[in] i_target the controller
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode exp_check_for_ready(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
    {
        // Using default parameters
        mss::poll_parameters l_poll_params;

        // From MSCC explorer firmware arch spec
        // 4.1.5: After power-up, the Explorer Chip will respond with NACK to all incoming I2C requests
        // from the HOST until the I2C slave interface is ready to receive commands.
        FAPI_ASSERT( mss::poll(i_target, l_poll_params, [i_target]()->bool
        {
            return mss::exp::i2c::is_ready(i_target) == fapi2::FAPI2_RC_SUCCESS;
        }),
        fapi2::MSS_EXP_I2C_POLLING_TIMEOUT().
        set_TARGET(i_target),
        "Failed to see an ACK from I2C -- polling timeout on %s",
        mss::c_str(i_target) );

        // We send the EXP_FW_STATUS command as a sanity check to see if it returns SUCCESS
        FAPI_ASSERT( mss::poll(i_target, l_poll_params, [i_target]()->bool
        {
            return mss::exp::i2c::fw_status(i_target) == fapi2::FAPI2_RC_SUCCESS;
        }),
        fapi2::MSS_EXP_STATUS_POLLING_TIMEOUT().
        set_TARGET(i_target),
        "Failled to see a successful return code -- polling timeout on %s",
        mss::c_str(i_target) );

        return fapi2::FAPI2_RC_SUCCESS;

    fapi_try_exit:
        return fapi2::current_err;
    }

}// extern C
<commit_msg>Add snapshot of ocmb/explorer for master-p10 branch<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_check_for_ready.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file exp_check_for_ready.C
/// @brief FW polls I2C slave interface to determine when it is ready
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/shared/exp_defaults.H>
#include <exp_check_for_ready.H>
#include <lib/i2c/exp_i2c.H>
#include <generic/memory/mss_git_data_helper.H>

extern "C"
{
///
/// @brief Checks if the explorer I2C is ready to receive commands
/// @param[in] i_target the controller
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode exp_check_for_ready(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
    {
        mss::display_git_commit_info("exp_check_for_ready");

        FAPI_TRY(mss::exp::i2c::exp_check_for_ready_helper(i_target));

    fapi_try_exit:
        return fapi2::current_err;
    }

}// extern C
<|endoftext|>


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

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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 "vtkChartGradientOpacityEditor.h"

#include <vtkAxis.h>
#include <vtkChart.h>
#include <vtkColorTransferControlPointsItem.h>
#include <vtkColorTransferFunction.h>
#include <vtkColorTransferFunctionItem.h>
#include <vtkContextItem.h>
#include <vtkContextScene.h>
#include <vtkObjectFactory.h>
#include <vtkPiecewiseFunction.h>
#include <vtkScalarsToColors.h>
#include <vtkSmartPointer.h>
#include <vtkTable.h>
#include <vtkVector.h>

#include "vtkChartHistogram.h"

class vtkChartGradientOpacityEditor::PIMPL
{
public:
  PIMPL() : Geometry(0, 0), NeedsUpdate(true) {}
  ~PIMPL() {}

  void ForwardEvent(vtkObject* vtkNotUsed(object), unsigned long eventId,
                    void* vtkNotUsed(data))
  {
    this->Self->InvokeEvent(eventId);
  }

  // Cached geometry of the chart
  vtkVector2i Geometry;

  // Dirty bit
  bool NeedsUpdate;

  // Reference to owner of the PIMPL
  vtkChartGradientOpacityEditor* Self;
};

vtkStandardNewMacro(vtkChartGradientOpacityEditor)

  vtkChartGradientOpacityEditor::vtkChartGradientOpacityEditor()
{
  this->Private = new PIMPL();
  this->Private->Self = this;

  this->Borders[vtkAxis::LEFT] = 8;
  this->Borders[vtkAxis::BOTTOM] = 8;
  this->Borders[vtkAxis::RIGHT] = 8;
  this->Borders[vtkAxis::TOP] = 20;

  this->HistogramChart->SetHiddenAxisBorder(10);
  this->HistogramChart->SetLayoutStrategy(vtkChart::AXES_TO_RECT);
  this->AddItem(this->HistogramChart.Get());

  vtkAxis* bottomAxis = this->HistogramChart->GetAxis(vtkAxis::BOTTOM);
  bottomAxis->SetTitle("Gradient Magnitude");

  // Forward events from internal charts to observers of this object
  this->HistogramChart->AddObserver(vtkCommand::CursorChangedEvent,
                                    this->Private, &PIMPL::ForwardEvent);
}

vtkChartGradientOpacityEditor::~vtkChartGradientOpacityEditor()
{
  delete this->Private;
}

void vtkChartGradientOpacityEditor::SetHistogramInputData(
  vtkTable* table, const char* xAxisColumn, const char* yAxisColumn)
{
  this->HistogramChart->SetHistogramInputData(table, xAxisColumn, yAxisColumn);
  this->HistogramChart->SetHistogramVisible(false);
  this->HistogramChart->SetMarkerVisible(false);
  this->HistogramChart->GetAxis(vtkAxis::LEFT)->SetRange(0.0, 1.0);
  this->HistogramChart->GetAxis(vtkAxis::LEFT)->SetLogScale(false);

  // The data range may change and cause the labels to change. Hence, update
  // the geometry.
  this->Private->NeedsUpdate = true;
}

void vtkChartGradientOpacityEditor::SetScalarVisibility(bool visible)
{
  this->HistogramChart->SetScalarVisibility(visible);
}

void vtkChartGradientOpacityEditor::SelectColorArray(const char* arrayName)
{
  this->HistogramChart->SelectColorArray(arrayName);
}

void vtkChartGradientOpacityEditor::SetOpacityFunction(
  vtkPiecewiseFunction* opacityFunction)
{
  this->HistogramChart->SetOpacityFunction(opacityFunction);
}

vtkAxis* vtkChartGradientOpacityEditor::GetHistogramAxis(int axis)
{
  return this->HistogramChart->GetAxis(axis);
}

bool vtkChartGradientOpacityEditor::Paint(vtkContext2D* painter)
{
  vtkContextScene* scene = this->GetScene();
  int sceneWidth = scene->GetSceneWidth();
  int sceneHeight = scene->GetSceneHeight();
  if (this->Private->NeedsUpdate ||
      sceneWidth != this->Private->Geometry.GetX() ||
      sceneHeight != this->Private->Geometry.GetY()) {
    this->Private->NeedsUpdate = false;

    // Update the geometry size cache
    this->Private->Geometry.Set(sceneWidth, sceneHeight);

    // Upper chart (histogram) expands, lower chart (color bar) is fixed height.
    float x = this->Borders[vtkAxis::LEFT];
    float y = this->Borders[vtkAxis::BOTTOM];

    // Add the width of the left axis to x to make room for y labels
    this->GetHistogramAxis(vtkAxis::LEFT)->Update();
    float leftAxisWidth = this->GetHistogramAxis(vtkAxis::LEFT)
                            ->GetBoundingRect(painter)
                            .GetWidth();
    x += leftAxisWidth;
    float plotWidth = sceneWidth - x - this->Borders[vtkAxis::RIGHT];

    this->GetHistogramAxis(vtkAxis::BOTTOM)->Update();
    float bottomAxisHeight = this->GetHistogramAxis(vtkAxis::BOTTOM)
                               ->GetBoundingRect(painter)
                               .GetHeight();
    float verticalMargin = bottomAxisHeight;
    y += verticalMargin - 5;
    vtkRectf histogramChart(x, y, plotWidth,
                            sceneHeight - y - this->Borders[vtkAxis::TOP]);
    this->HistogramChart->SetSize(histogramChart);
  }

  return this->Superclass::Paint(painter);
}
<commit_msg>Ensure the plot transform is recalculated<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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 "vtkChartGradientOpacityEditor.h"

#include <vtkAxis.h>
#include <vtkChart.h>
#include <vtkColorTransferControlPointsItem.h>
#include <vtkColorTransferFunction.h>
#include <vtkColorTransferFunctionItem.h>
#include <vtkContextItem.h>
#include <vtkContextScene.h>
#include <vtkObjectFactory.h>
#include <vtkPiecewiseFunction.h>
#include <vtkScalarsToColors.h>
#include <vtkSmartPointer.h>
#include <vtkTable.h>
#include <vtkVector.h>

#include "vtkChartHistogram.h"

class vtkChartGradientOpacityEditor::PIMPL
{
public:
  PIMPL() : Geometry(0, 0), NeedsUpdate(true) {}
  ~PIMPL() {}

  void ForwardEvent(vtkObject* vtkNotUsed(object), unsigned long eventId,
                    void* vtkNotUsed(data))
  {
    this->Self->InvokeEvent(eventId);
  }

  // Cached geometry of the chart
  vtkVector2i Geometry;

  // Dirty bit
  bool NeedsUpdate;

  // Reference to owner of the PIMPL
  vtkChartGradientOpacityEditor* Self;
};

vtkStandardNewMacro(vtkChartGradientOpacityEditor)

  vtkChartGradientOpacityEditor::vtkChartGradientOpacityEditor()
{
  this->Private = new PIMPL();
  this->Private->Self = this;

  this->Borders[vtkAxis::LEFT] = 8;
  this->Borders[vtkAxis::BOTTOM] = 8;
  this->Borders[vtkAxis::RIGHT] = 8;
  this->Borders[vtkAxis::TOP] = 20;

  this->HistogramChart->SetHiddenAxisBorder(10);
  this->HistogramChart->SetLayoutStrategy(vtkChart::AXES_TO_RECT);
  this->AddItem(this->HistogramChart.Get());

  vtkAxis* bottomAxis = this->HistogramChart->GetAxis(vtkAxis::BOTTOM);
  bottomAxis->SetTitle("Gradient Magnitude");

  // Forward events from internal charts to observers of this object
  this->HistogramChart->AddObserver(vtkCommand::CursorChangedEvent,
                                    this->Private, &PIMPL::ForwardEvent);
}

vtkChartGradientOpacityEditor::~vtkChartGradientOpacityEditor()
{
  delete this->Private;
}

void vtkChartGradientOpacityEditor::SetHistogramInputData(
  vtkTable* table, const char* xAxisColumn, const char* yAxisColumn)
{
  this->HistogramChart->SetHistogramInputData(table, xAxisColumn, yAxisColumn);
  this->HistogramChart->SetHistogramVisible(false);
  this->HistogramChart->SetMarkerVisible(false);
  this->HistogramChart->GetAxis(vtkAxis::LEFT)->SetRange(0.0, 1.0);
  this->HistogramChart->GetAxis(vtkAxis::LEFT)->SetLogScale(false);

  // The data range may change and cause the labels to change. Hence, update
  // the geometry.
  this->Private->NeedsUpdate = true;
}

void vtkChartGradientOpacityEditor::SetScalarVisibility(bool visible)
{
  this->HistogramChart->SetScalarVisibility(visible);
}

void vtkChartGradientOpacityEditor::SelectColorArray(const char* arrayName)
{
  this->HistogramChart->SelectColorArray(arrayName);
}

void vtkChartGradientOpacityEditor::SetOpacityFunction(
  vtkPiecewiseFunction* opacityFunction)
{
  this->HistogramChart->SetOpacityFunction(opacityFunction);
}

vtkAxis* vtkChartGradientOpacityEditor::GetHistogramAxis(int axis)
{
  return this->HistogramChart->GetAxis(axis);
}

bool vtkChartGradientOpacityEditor::Paint(vtkContext2D* painter)
{
  vtkContextScene* scene = this->GetScene();
  int sceneWidth = scene->GetSceneWidth();
  int sceneHeight = scene->GetSceneHeight();
  if (this->Private->NeedsUpdate ||
      sceneWidth != this->Private->Geometry.GetX() ||
      sceneHeight != this->Private->Geometry.GetY()) {
    this->Private->NeedsUpdate = false;

    // Update the geometry size cache
    this->Private->Geometry.Set(sceneWidth, sceneHeight);

    // Upper chart (histogram) expands, lower chart (color bar) is fixed height.
    float x = this->Borders[vtkAxis::LEFT];
    float y = this->Borders[vtkAxis::BOTTOM];

    // Add the width of the left axis to x to make room for y labels
    this->GetHistogramAxis(vtkAxis::LEFT)->Update();
    float leftAxisWidth = this->GetHistogramAxis(vtkAxis::LEFT)
                            ->GetBoundingRect(painter)
                            .GetWidth();
    x += leftAxisWidth;
    float plotWidth = sceneWidth - x - this->Borders[vtkAxis::RIGHT];

    this->GetHistogramAxis(vtkAxis::BOTTOM)->Update();
    float bottomAxisHeight = this->GetHistogramAxis(vtkAxis::BOTTOM)
                               ->GetBoundingRect(painter)
                               .GetHeight();
    float verticalMargin = bottomAxisHeight;
    y += verticalMargin - 5;
    vtkRectf histogramChart(x, y, plotWidth,
                            sceneHeight - y - this->Borders[vtkAxis::TOP]);
    this->HistogramChart->SetSize(histogramChart);
    this->HistogramChart->GetAxis(vtkAxis::LEFT)->Modified();
  }

  return this->Superclass::Paint(painter);
}
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2013 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
#include <gtest/gtest.h>
#include "joynr/JoynrMessageFactory.h"
#include "joynr/Request.h"
#include "joynr/Reply.h"
#include "joynr/MessagingQos.h"
#include "joynr/SubscriptionPublication.h"
#include "joynr/SubscriptionRequest.h"
#include "joynr/SubscriptionStop.h"
#include "joynr/DispatcherUtils.h"
#include "joynr/OnChangeSubscriptionQos.h"
#include <chrono>
#include <cstdint>
#include <string>

using namespace joynr;

class JoynrMessageFactoryTest : public ::testing::Test
{
public:
    JoynrMessageFactoryTest()
            : messageFactory(),
              senderID(),
              receiverID(),
              requestReplyID(),
              qos(),
              request(),
              oneWayRequest(),
              reply(),
              subscriptionPublication()
    {
    }

    void SetUp()
    {
        senderID = std::string("senderId");
        receiverID = std::string("receiverID");
        requestReplyID = "requestReplyID";
        qos = MessagingQos(456000);
        qos.putCustomMessageHeader("test-header", "test-header-value");
        request.setMethodName("methodName");
        request.setRequestReplyId(requestReplyID);
        request.setParams(42, "value");
        request.setParamDatatypes({"java.lang.Integer","java.lang.String"});
        oneWayRequest.setMethodName("methodName");
        oneWayRequest.setParams(42, "value");
        oneWayRequest.setParamDatatypes({"java.lang.Integer","java.lang.String"});
        reply.setRequestReplyId(requestReplyID);
        reply.setResponse("response");

        std::string subscriptionId("subscriptionTestId");
        subscriptionPublication.setSubscriptionId(subscriptionId);
        std::vector<Variant> response;
        response.push_back(Variant::make<std::string>("publication"));
        subscriptionPublication.setResponseVariant(response);
    }
    void TearDown()
    {
    }
    void checkHeaderCreatorFromTo(const JoynrMessage& joynrMessage)
    {
        EXPECT_TRUE(joynrMessage.containsHeaderCreatorUserId());
        EXPECT_STREQ(senderID.c_str(), joynrMessage.getHeaderFrom().c_str());
        EXPECT_STREQ(receiverID.c_str(), joynrMessage.getHeaderTo().c_str());
        EXPECT_TRUE(joynrMessage.containsCustomHeader("test-header"));
        EXPECT_STREQ("test-header-value", joynrMessage.getCustomHeader("test-header").c_str());
    }

    void checkRequest(const JoynrMessage& joynrMessage)
    {
        // TODO create expected string from params and methodName
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.Request",)";
        expectedPayloadStream << R"("methodName":"methodName",)";
        expectedPayloadStream << R"("paramDatatypes":["java.lang.Integer","java.lang.String"],)";
        expectedPayloadStream << R"("params":[42,"value"],)";
        expectedPayloadStream << R"("requestReplyId":")" << request.getRequestReplyId() << R"("})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

    void checkOneWayRequest(const JoynrMessage& joynrMessage)
    {
        // TODO create expected string from params and methodName
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.OneWayRequest",)";
        expectedPayloadStream << R"("methodName":"methodName",)";
        expectedPayloadStream << R"("paramDatatypes":["java.lang.Integer","java.lang.String"],)";
        expectedPayloadStream << R"("params":[42,"value"])";
        expectedPayloadStream << R"(})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

    void checkReply(const JoynrMessage& joynrMessage)
    {
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.Reply",)";
        expectedPayloadStream << R"("requestReplyId":")" << reply.getRequestReplyId() << R"(",)";
        expectedPayloadStream << R"("response":["response"]})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

    void checkSubscriptionPublication(const JoynrMessage& joynrMessage)
    {
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.SubscriptionPublication",)";
        expectedPayloadStream << R"("subscriptionId": ")"
                              << subscriptionPublication.getSubscriptionId() << R"(",)";
        expectedPayloadStream << R"("response": ["publication"]})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

protected:
    ADD_LOGGER(JoynrMessageFactoryTest);
    JoynrMessageFactory messageFactory;
    std::string senderID;
    std::string receiverID;
    std::string requestReplyID;
    MessagingQos qos;
    Request request;
    OneWayRequest oneWayRequest;
    Reply reply;
    SubscriptionPublication subscriptionPublication;
};

INIT_LOGGER(JoynrMessageFactoryTest);

TEST_F(JoynrMessageFactoryTest, createRequest_withContentType)
{
    JoynrMessage joynrMessage = messageFactory.createRequest(senderID, receiverID, qos, request);
    checkHeaderCreatorFromTo(joynrMessage);
}

TEST_F(JoynrMessageFactoryTest, createRequest)
{
    JoynrMessage joynrMessage = messageFactory.createRequest(senderID, receiverID, qos, request);
    // warning if prepareRequest needs to long this assert will fail as it compares absolute
    // timestamps
    JoynrTimePoint now = std::chrono::time_point_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now());
    JoynrTimePoint expectedExpiryDate = now + std::chrono::milliseconds(qos.getTtl());
    JoynrTimePoint expiryDate = joynrMessage.getHeaderExpiryDate();
    EXPECT_NEAR(expectedExpiryDate.time_since_epoch().count(),
                expiryDate.time_since_epoch().count(),
                100.);
    JOYNR_LOG_DEBUG(logger,
                    "expiryDate: {} [{}]",
                    DispatcherUtils::convertAbsoluteTimeToTtlString(expiryDate),
                    std::chrono::duration_cast<std::chrono::milliseconds>(
                            expiryDate.time_since_epoch()).count());
    JOYNR_LOG_DEBUG(logger,
                    "expectedExpiryDate: {}  [{}]",
                    DispatcherUtils::convertAbsoluteTimeToTtlString(expectedExpiryDate),
                    std::chrono::duration_cast<std::chrono::milliseconds>(
                            expectedExpiryDate.time_since_epoch()).count());

    checkHeaderCreatorFromTo(joynrMessage);
    checkRequest(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_REQUEST, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createReply)
{
    JoynrMessage joynrMessage = messageFactory.createReply(senderID, receiverID, qos, reply);
    checkHeaderCreatorFromTo(joynrMessage);
    checkReply(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_REPLY, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createOneWayRequest)
{
    JoynrMessage joynrMessage =
            messageFactory.createOneWayRequest(senderID, receiverID, qos, oneWayRequest);
    checkHeaderCreatorFromTo(joynrMessage);
    checkOneWayRequest(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_ONE_WAY, joynrMessage.getType());
}

// TEST_F(JoynrMessageFactoryTest, createSubscriptionReply){
//    std::string subscriptionId("subscriptionTestId");
//    JoynrMessage joynrMessage = JoynrMessageFactory::prepareSubscriptionReply(senderID,
//    receiverID, payload, subscriptionId);
//    checkHeaderCreatorFromTo(joynrMessage);
//    checkPayload(joynrMessage);
//    EXPECT_QSTREQ(subscriptionId,
//    joynrMessage.getHeader<std::string>(JoynrMessage::HEADER_NAME_SUBSCRIPTION_ID));
//    EXPECT_QSTREQ(JoynrMessage::MESSAGE_TYPE_SUBSCRIPTION_REPLY, joynrMessage.getType());
//}

TEST_F(JoynrMessageFactoryTest, createPublication)
{
    JoynrMessage joynrMessage = messageFactory.createSubscriptionPublication(
            senderID, receiverID, qos, subscriptionPublication);
    checkHeaderCreatorFromTo(joynrMessage);
    checkSubscriptionPublication(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_PUBLICATION, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createSubscriptionRequest)
{
    Variant subscriptionQos = Variant::make<OnChangeSubscriptionQos>(OnChangeSubscriptionQos());
    SubscriptionRequest subscriptionRequest;
    subscriptionRequest.setSubscriptionId("subscriptionId");
    subscriptionRequest.setSubscribeToName("attributeName");
    subscriptionRequest.setQosVariant(subscriptionQos);
    JoynrMessage joynrMessage = messageFactory.createSubscriptionRequest(
            senderID, receiverID, qos, subscriptionRequest);
    checkHeaderCreatorFromTo(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REQUEST, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createSubscriptionStop)
{
    std::string subscriptionId("TEST-SubscriptionId");
    SubscriptionStop subscriptionStop;
    subscriptionStop.setSubscriptionId(subscriptionId);
    JoynrMessage joynrMessage =
            messageFactory.createSubscriptionStop(senderID, receiverID, qos, subscriptionStop);
    checkHeaderCreatorFromTo(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_SUBSCRIPTION_STOP, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, testRequestContentType)
{
    Request request;
    std::vector<Variant> params;
    params.push_back(Variant::make<std::string>("test"));
    request.setMethodName("methodName");
    request.setParamsVariant(params);

    JoynrMessage message = messageFactory.createRequest(senderID, receiverID, qos, request);
    EXPECT_EQ(JoynrMessage::VALUE_CONTENT_TYPE_APPLICATION_JSON, message.getHeaderContentType());
}
<commit_msg>[C++] Fix JoynrMessageFactoryTest<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2013 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
#include <gtest/gtest.h>
#include "joynr/JoynrMessageFactory.h"
#include "joynr/Request.h"
#include "joynr/Reply.h"
#include "joynr/MessagingQos.h"
#include "joynr/SubscriptionPublication.h"
#include "joynr/SubscriptionRequest.h"
#include "joynr/SubscriptionStop.h"
#include "joynr/DispatcherUtils.h"
#include "joynr/OnChangeSubscriptionQos.h"
#include <chrono>
#include <cstdint>
#include <string>

using namespace joynr;

class JoynrMessageFactoryTest : public ::testing::Test
{
public:
    JoynrMessageFactoryTest()
            : messageFactory(),
              senderID(),
              receiverID(),
              requestReplyID(),
              qos(),
              request(),
              oneWayRequest(),
              reply(),
              subscriptionPublication()
    {
    }

    void SetUp()
    {
        senderID = std::string("senderId");
        receiverID = std::string("receiverID");
        requestReplyID = "requestReplyID";
        qos = MessagingQos(456000);
        qos.putCustomMessageHeader("test-header", "test-header-value");
        request.setMethodName("methodName");
        request.setRequestReplyId(requestReplyID);
        request.setParams(42, "value");
        request.setParamDatatypes({"java.lang.Integer","java.lang.String"});
        oneWayRequest.setMethodName("methodName");
        oneWayRequest.setParams(42, "value");
        oneWayRequest.setParamDatatypes({"java.lang.Integer","java.lang.String"});
        reply.setRequestReplyId(requestReplyID);
        reply.setResponse("response");

        std::string subscriptionId("subscriptionTestId");
        subscriptionPublication.setSubscriptionId(subscriptionId);
        subscriptionPublication.setResponse("publication");
    }
    void TearDown()
    {
    }
    void checkHeaderCreatorFromTo(const JoynrMessage& joynrMessage)
    {
        EXPECT_TRUE(joynrMessage.containsHeaderCreatorUserId());
        EXPECT_STREQ(senderID.c_str(), joynrMessage.getHeaderFrom().c_str());
        EXPECT_STREQ(receiverID.c_str(), joynrMessage.getHeaderTo().c_str());
        EXPECT_TRUE(joynrMessage.containsCustomHeader("test-header"));
        EXPECT_STREQ("test-header-value", joynrMessage.getCustomHeader("test-header").c_str());
    }

    void checkRequest(const JoynrMessage& joynrMessage)
    {
        // TODO create expected string from params and methodName
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.Request",)";
        expectedPayloadStream << R"("methodName":"methodName",)";
        expectedPayloadStream << R"("paramDatatypes":["java.lang.Integer","java.lang.String"],)";
        expectedPayloadStream << R"("params":[42,"value"],)";
        expectedPayloadStream << R"("requestReplyId":")" << request.getRequestReplyId() << R"("})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

    void checkOneWayRequest(const JoynrMessage& joynrMessage)
    {
        // TODO create expected string from params and methodName
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.OneWayRequest",)";
        expectedPayloadStream << R"("methodName":"methodName",)";
        expectedPayloadStream << R"("paramDatatypes":["java.lang.Integer","java.lang.String"],)";
        expectedPayloadStream << R"("params":[42,"value"])";
        expectedPayloadStream << R"(})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

    void checkReply(const JoynrMessage& joynrMessage)
    {
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.Reply",)";
        expectedPayloadStream << R"("response":["response"],)";
        expectedPayloadStream << R"("requestReplyId":")" << reply.getRequestReplyId() << R"("})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

    void checkSubscriptionPublication(const JoynrMessage& joynrMessage)
    {
        std::stringstream expectedPayloadStream;
        expectedPayloadStream << R"({"_typeName":"joynr.SubscriptionPublication",)";
        expectedPayloadStream << R"("response":["publication"],)";
        expectedPayloadStream << R"("subscriptionId":")"
                              << subscriptionPublication.getSubscriptionId() << R"("})";
        std::string expectedPayload = expectedPayloadStream.str();
        EXPECT_EQ(expectedPayload, joynrMessage.getPayload());
    }

protected:
    ADD_LOGGER(JoynrMessageFactoryTest);
    JoynrMessageFactory messageFactory;
    std::string senderID;
    std::string receiverID;
    std::string requestReplyID;
    MessagingQos qos;
    Request request;
    OneWayRequest oneWayRequest;
    Reply reply;
    SubscriptionPublication subscriptionPublication;
};

INIT_LOGGER(JoynrMessageFactoryTest);

TEST_F(JoynrMessageFactoryTest, createRequest_withContentType)
{
    JoynrMessage joynrMessage = messageFactory.createRequest(senderID, receiverID, qos, request);
    checkHeaderCreatorFromTo(joynrMessage);
}

TEST_F(JoynrMessageFactoryTest, createRequest)
{
    JoynrMessage joynrMessage = messageFactory.createRequest(senderID, receiverID, qos, request);
    // warning if prepareRequest needs to long this assert will fail as it compares absolute
    // timestamps
    JoynrTimePoint now = std::chrono::time_point_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now());
    JoynrTimePoint expectedExpiryDate = now + std::chrono::milliseconds(qos.getTtl());
    JoynrTimePoint expiryDate = joynrMessage.getHeaderExpiryDate();
    EXPECT_NEAR(expectedExpiryDate.time_since_epoch().count(),
                expiryDate.time_since_epoch().count(),
                100.);
    JOYNR_LOG_DEBUG(logger,
                    "expiryDate: {} [{}]",
                    DispatcherUtils::convertAbsoluteTimeToTtlString(expiryDate),
                    std::chrono::duration_cast<std::chrono::milliseconds>(
                            expiryDate.time_since_epoch()).count());
    JOYNR_LOG_DEBUG(logger,
                    "expectedExpiryDate: {}  [{}]",
                    DispatcherUtils::convertAbsoluteTimeToTtlString(expectedExpiryDate),
                    std::chrono::duration_cast<std::chrono::milliseconds>(
                            expectedExpiryDate.time_since_epoch()).count());

    checkHeaderCreatorFromTo(joynrMessage);
    checkRequest(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_REQUEST, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createReply)
{
    JoynrMessage joynrMessage = messageFactory.createReply(senderID, receiverID, qos, reply);
    checkHeaderCreatorFromTo(joynrMessage);
    checkReply(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_REPLY, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createOneWayRequest)
{
    JoynrMessage joynrMessage =
            messageFactory.createOneWayRequest(senderID, receiverID, qos, oneWayRequest);
    checkHeaderCreatorFromTo(joynrMessage);
    checkOneWayRequest(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_ONE_WAY, joynrMessage.getType());
}

// TEST_F(JoynrMessageFactoryTest, createSubscriptionReply){
//    std::string subscriptionId("subscriptionTestId");
//    JoynrMessage joynrMessage = JoynrMessageFactory::prepareSubscriptionReply(senderID,
//    receiverID, payload, subscriptionId);
//    checkHeaderCreatorFromTo(joynrMessage);
//    checkPayload(joynrMessage);
//    EXPECT_QSTREQ(subscriptionId,
//    joynrMessage.getHeader<std::string>(JoynrMessage::HEADER_NAME_SUBSCRIPTION_ID));
//    EXPECT_QSTREQ(JoynrMessage::MESSAGE_TYPE_SUBSCRIPTION_REPLY, joynrMessage.getType());
//}

TEST_F(JoynrMessageFactoryTest, createPublication)
{
    JoynrMessage joynrMessage = messageFactory.createSubscriptionPublication(
            senderID, receiverID, qos, subscriptionPublication);
    checkHeaderCreatorFromTo(joynrMessage);
    checkSubscriptionPublication(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_PUBLICATION, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createSubscriptionRequest)
{
    Variant subscriptionQos = Variant::make<OnChangeSubscriptionQos>(OnChangeSubscriptionQos());
    SubscriptionRequest subscriptionRequest;
    subscriptionRequest.setSubscriptionId("subscriptionId");
    subscriptionRequest.setSubscribeToName("attributeName");
    subscriptionRequest.setQosVariant(subscriptionQos);
    JoynrMessage joynrMessage = messageFactory.createSubscriptionRequest(
            senderID, receiverID, qos, subscriptionRequest);
    checkHeaderCreatorFromTo(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REQUEST, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, createSubscriptionStop)
{
    std::string subscriptionId("TEST-SubscriptionId");
    SubscriptionStop subscriptionStop;
    subscriptionStop.setSubscriptionId(subscriptionId);
    JoynrMessage joynrMessage =
            messageFactory.createSubscriptionStop(senderID, receiverID, qos, subscriptionStop);
    checkHeaderCreatorFromTo(joynrMessage);
    EXPECT_EQ(JoynrMessage::VALUE_MESSAGE_TYPE_SUBSCRIPTION_STOP, joynrMessage.getType());
}

TEST_F(JoynrMessageFactoryTest, testRequestContentType)
{
    Request request;
    std::vector<Variant> params;
    params.push_back(Variant::make<std::string>("test"));
    request.setMethodName("methodName");
    request.setParamsVariant(params);

    JoynrMessage message = messageFactory.createRequest(senderID, receiverID, qos, request);
    EXPECT_EQ(JoynrMessage::VALUE_CONTENT_TYPE_APPLICATION_JSON, message.getHeaderContentType());
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "IpUpdatesLog.h"
#include "MiscUtil.h"
#include "StrUtil.h"

/*
TODO:
* finish writing out the truncated log
*/

// When we reach that many updates, we'll trim the ip updates log
#define IP_UPDATES_PURGE_LIMIT 1000

// After we reach IP_UPDATES_PURGE_LIMIT, we'll only write out
// IP_UPDATES_AFTER_PURGE_SIZE items, so that we don't have to purge every
// time once we reach purge limit
#define IP_UPDATES_SIZE_AFTER_PURGE 500

// Linked list of ip updates. Newest are at the front.
IpUpdate *				g_ipUpdates = NULL;

// name of the file where we persist ip updates history
static const TCHAR *	gIpUpdatesLogFileName;
static FILE *			gIpUpdatesLogFile;

static void FreeIpUpdate(IpUpdate *ipUpdate)
{
	assert(ipUpdate);
	if (!ipUpdate)
		return;
	free(ipUpdate->ipAddress);
	free(ipUpdate->time);
	free(ipUpdate);
}

static void FreeIpUpdatesFromElement(IpUpdate *curr)
{
	while (curr) {
		IpUpdate *next = curr->next;
		FreeIpUpdate(curr);
		curr = next;
	}
}

static void InsertIpUpdate(const char *ipAddress, const char *time)
{
	assert(ipAddress);
	assert(time);
	if (!ipAddress || !time)
		return;
	IpUpdate *ipUpdate = SA(IpUpdate);
	if (!ipUpdate)
		return;

	ipUpdate->ipAddress = strdup(ipAddress);
	ipUpdate->time = strdup(time);
	if (!ipUpdate->ipAddress || !ipUpdate->time) {
		FreeIpUpdate(ipUpdate);
		return;
	}

	ipUpdate->next = g_ipUpdates;
	g_ipUpdates = ipUpdate;
}

static inline bool is_newline_char(char c)
{
	return (c == '\r') || (c == '\n');
}

// at this point <*dataStartInOut> points at the beginning of the log file,
// which consists of lines in format:
// $ipaddr $time\r\n
static bool ExtractIpAddrAndTime(char **dataStartInOut, uint64_t *dataSizeLeftInOut, char **ipAddrOut, char **timeOut)
{
	char *curr = *dataStartInOut;
	uint64_t dataSizeLeft = *dataSizeLeftInOut;
	char *time = NULL;
	char *ipAddr = curr;

	// first space separates $ipaddr from $time
	while ((dataSizeLeft > 0) && (*curr != ' ')) {
		--dataSizeLeft;
		++curr;
	}

	// didn't find the space => something's wrong
	if (0 == dataSizeLeft)
		return false;

	assert(*curr == ' ');
	// replace space with 0 to make ipAddr a null-terminated string
	*curr = 0;
	--dataSizeLeft;
	++curr;

	time = curr;

	// find "\r\n' at the end
	while ((dataSizeLeft > 0) && !is_newline_char(*curr)) {
		--dataSizeLeft;
		++curr;
	}

	// replace '\r\n' with 0, to make time a null-terminated string
	while ((dataSizeLeft > 0) && is_newline_char(*curr)) {
		*curr++ = 0;
		--dataSizeLeft;
	}

	*ipAddrOut = ipAddr;
	*timeOut = time;
	*dataSizeLeftInOut = dataSizeLeft;
	*dataStartInOut = curr;
	return true;
}

// load up to IP_UPDATES_HISTORY_MAX latest entries from ip updates log
// When we finish g_ipUpdates is a list of ip updates with the most recent
// at the beginning of the list
static void ParseIpLogHistory(char *data, uint64_t dataSize)
{
	char *ipAddr = NULL;
	char *time = NULL;
	while (dataSize != 0) {
		bool ok = ExtractIpAddrAndTime(&data, &dataSize, &ipAddr, &time);
		if (!ok) {
			assert(0);
			break;
		}
		InsertIpUpdate(ipAddr, time);
	}
}

static void LogIpUpdateEntry(FILE *log, const char *ipAddress, const char *time)
{
	assert(log && ipAddress && time);
	if (!log || !ipAddress || !time)
		return;

	size_t slen = strlen(ipAddress);
	fwrite(ipAddress, slen, 1, log);
	fwrite(" ", 1, 1, log);

	slen = strlen(time);
	fwrite(time, slen, 1, log);
	fwrite("\r\n", 2, 1, log);
	fflush(log);
}

#if 0
// overwrite the history log file with the current history in g_ipUpdates
// The assumption is that we've limited
static void WriteIpLogHistory(const TCHAR *logFileName)
{
	FILE *log = _tfopen(logFileName, _T("wb"));

	fclose(log);
}

static void RemoveLogEntries(int max)
{
	IpUpdate *curr = g_ipUpdates;
	IpUpdate **currPtr = NULL;
	while (curr && max > 0) {
		currPtr = &curr->next;
		curr = curr->next;
		--max;
	}
	if (!curr || !currPtr)
		return;
	FreeIpUpdatesFromElement(*currPtr);
	*currPtr = NULL;
}
#endif

static void LoadAndParseHistory(const TCHAR *logFileName)
{
	uint64_t dataSize;
	char *data = FileReadAll(logFileName, &dataSize);
	if (!data)
		return;
	ParseIpLogHistory(data, dataSize);
	free(data);
}

void LoadIpUpdatesHistory(const TCHAR *logFileName)
{
	assert(!gIpUpdatesLogFileName);
	assert(!gIpUpdatesLogFile);

	LoadAndParseHistory(logFileName);

	gIpUpdatesLogFileName = tstrdup(logFileName);
	gIpUpdatesLogFile = _tfopen(logFileName, _T("ab"));
}

void LogIpUpdate(const char *ipAddress)
{
	char timeBuf[256];
	__time64_t ltime;
	struct tm *today;
	today = _localtime64(&ltime);
	strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M", today);
	assert(gIpUpdatesLogFile);
	LogIpUpdateEntry(gIpUpdatesLogFile, ipAddress, timeBuf);
}

static void CloseIpUpdatesLog()
{
	TStrFree(&gIpUpdatesLogFileName);
	if (gIpUpdatesLogFile) {
		fclose(gIpUpdatesLogFile);
		gIpUpdatesLogFile = NULL;
	}
}

void FreeIpUpdatesHistory()
{
	CloseIpUpdatesLog();
	// TODO: if we have more than IP_UPDATES_HISTORY_MAX entries, over-write
	// the log with only the recent entries
	FreeIpUpdatesFromElement(g_ipUpdates);
	g_ipUpdates = NULL;
}

<commit_msg>if the we reached the limit of ip update log entries, overwrite the log at exit with limited number of entries<commit_after>#include "stdafx.h"

#include "IpUpdatesLog.h"
#include "MiscUtil.h"
#include "StrUtil.h"

// When we reach that many updates, we'll trim the ip updates log
#define IP_UPDATES_PURGE_LIMIT 1000

// After we reach IP_UPDATES_PURGE_LIMIT, we'll only write out
// IP_UPDATES_AFTER_PURGE_SIZE items, so that we don't have to purge every
// time once we reach purge limit
#define IP_UPDATES_SIZE_AFTER_PURGE 500

// Linked list of ip updates. Newest are at the front.
IpUpdate *				g_ipUpdates = NULL;

// name of the file where we persist ip updates history
static const TCHAR *	gIpUpdatesLogFileName;
static FILE *			gIpUpdatesLogFile;

static void FreeIpUpdate(IpUpdate *ipUpdate)
{
	assert(ipUpdate);
	if (!ipUpdate)
		return;
	free(ipUpdate->ipAddress);
	free(ipUpdate->time);
	free(ipUpdate);
}

static void FreeIpUpdatesFromElement(IpUpdate *curr)
{
	while (curr) {
		IpUpdate *next = curr->next;
		FreeIpUpdate(curr);
		curr = next;
	}
}

static void InsertIpUpdate(const char *ipAddress, const char *time)
{
	assert(ipAddress);
	assert(time);
	if (!ipAddress || !time)
		return;
	IpUpdate *ipUpdate = SA(IpUpdate);
	if (!ipUpdate)
		return;

	ipUpdate->ipAddress = strdup(ipAddress);
	ipUpdate->time = strdup(time);
	if (!ipUpdate->ipAddress || !ipUpdate->time) {
		FreeIpUpdate(ipUpdate);
		return;
	}

	ipUpdate->next = g_ipUpdates;
	g_ipUpdates = ipUpdate;
}

static inline bool is_newline_char(char c)
{
	return (c == '\r') || (c == '\n');
}

// at this point <*dataStartInOut> points at the beginning of the log file,
// which consists of lines in format:
// $ipaddr $time\r\n
static bool ExtractIpAddrAndTime(char **dataStartInOut, uint64_t *dataSizeLeftInOut, char **ipAddrOut, char **timeOut)
{
	char *curr = *dataStartInOut;
	uint64_t dataSizeLeft = *dataSizeLeftInOut;
	char *time = NULL;
	char *ipAddr = curr;

	// first space separates $ipaddr from $time
	while ((dataSizeLeft > 0) && (*curr != ' ')) {
		--dataSizeLeft;
		++curr;
	}

	// didn't find the space => something's wrong
	if (0 == dataSizeLeft)
		return false;

	assert(*curr == ' ');
	// replace space with 0 to make ipAddr a null-terminated string
	*curr = 0;
	--dataSizeLeft;
	++curr;

	time = curr;

	// find "\r\n' at the end
	while ((dataSizeLeft > 0) && !is_newline_char(*curr)) {
		--dataSizeLeft;
		++curr;
	}

	// replace '\r\n' with 0, to make time a null-terminated string
	while ((dataSizeLeft > 0) && is_newline_char(*curr)) {
		*curr++ = 0;
		--dataSizeLeft;
	}

	*ipAddrOut = ipAddr;
	*timeOut = time;
	*dataSizeLeftInOut = dataSizeLeft;
	*dataStartInOut = curr;
	return true;
}

// load up to IP_UPDATES_HISTORY_MAX latest entries from ip updates log
// When we finish g_ipUpdates is a list of ip updates with the most recent
// at the beginning of the list
static void ParseIpLogHistory(char *data, uint64_t dataSize)
{
	char *ipAddr = NULL;
	char *time = NULL;
	while (dataSize != 0) {
		bool ok = ExtractIpAddrAndTime(&data, &dataSize, &ipAddr, &time);
		if (!ok) {
			assert(0);
			break;
		}
		InsertIpUpdate(ipAddr, time);
	}
}

static void LogIpUpdateEntry(FILE *log, const char *ipAddress, const char *time)
{
	assert(log && ipAddress && time);
	if (!log || !ipAddress || !time)
		return;

	size_t slen = strlen(ipAddress);
	fwrite(ipAddress, slen, 1, log);
	fwrite(" ", 1, 1, log);

	slen = strlen(time);
	fwrite(time, slen, 1, log);
	fwrite("\r\n", 2, 1, log);
	fflush(log);
}

#if 0
// overwrite the history log file with the current history in g_ipUpdates
// The assumption is that we've limited

static void RemoveLogEntries(int max)
{
	IpUpdate *curr = g_ipUpdates;
	IpUpdate **currPtr = NULL;
	while (curr && max > 0) {
		currPtr = &curr->next;
		curr = curr->next;
		--max;
	}
	if (!curr || !currPtr)
		return;
	FreeIpUpdatesFromElement(*currPtr);
	*currPtr = NULL;
}
#endif

static void LoadAndParseHistory(const TCHAR *logFileName)
{
	uint64_t dataSize;
	char *data = FileReadAll(logFileName, &dataSize);
	if (!data)
		return;
	ParseIpLogHistory(data, dataSize);
	free(data);
}

void LoadIpUpdatesHistory(const TCHAR *logFileName)
{
	assert(!gIpUpdatesLogFileName);
	assert(!gIpUpdatesLogFile);

	LoadAndParseHistory(logFileName);

	gIpUpdatesLogFileName = tstrdup(logFileName);
	gIpUpdatesLogFile = _tfopen(logFileName, _T("ab"));
}

void LogIpUpdate(const char *ipAddress)
{
	char timeBuf[256];
	__time64_t ltime;
	struct tm *today;
	today = _localtime64(&ltime);
	strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M", today);
	assert(gIpUpdatesLogFile);
	LogIpUpdateEntry(gIpUpdatesLogFile, ipAddress, timeBuf);
}

static void CloseIpUpdatesLog()
{
	if (gIpUpdatesLogFile) {
		fclose(gIpUpdatesLogFile);
		gIpUpdatesLogFile = NULL;
	}
}

static inline void FreeIpUpdatesLogName()
{
	TStrFree(&gIpUpdatesLogFileName);
}

// reverse g_ipUpdates and return size of the list
size_t ReverseIpUpdateList()
{
	size_t size = 0;
	IpUpdate *newHead = NULL;
	IpUpdate *curr = g_ipUpdates;
	while (curr) {
		IpUpdate *next = curr->next;
		curr->next = newHead;
		newHead = curr;
		curr = next;
		size++;
	}
	g_ipUpdates = newHead;
	return size;
}

static void WriteIpLogHistory(const TCHAR *logFileName, IpUpdate *head)
{
	FILE *log = _tfopen(logFileName, _T("wb"));
	IpUpdate *curr = head;
	while (curr) {
		LogIpUpdateEntry(log, curr->ipAddress, curr->time);
		curr = curr->next;
	}
	fclose(log);
}

// if we have more than IP_UPDATES_HISTORY_MAX entries, over-write
// the log with only the recent entries
static void OverwriteLogIfReachedLimit()
{
	// in order to (possibly) write out log entries, we have to write from
	// the end, so we need to reverse the list. We combine this with
	// calculating the size because we need to know the size to decide
	// if we need to overwrite the log
	size_t size = ReverseIpUpdateList();
	if (size < IP_UPDATES_PURGE_LIMIT)
		return;

	// skip the entries we don't want to write out
	assert(size > IP_UPDATES_SIZE_AFTER_PURGE);
	size_t toSkip = size - IP_UPDATES_SIZE_AFTER_PURGE;
	IpUpdate *curr = g_ipUpdates;
	while (curr && (toSkip != 0)) {
		curr = curr->next;
		toSkip--;
	}

	// write the rest to the new log
	WriteIpLogHistory(gIpUpdatesLogFileName, curr);
}

void FreeIpUpdatesHistory()
{
	CloseIpUpdatesLog();
	OverwriteLogIfReachedLimit();
	FreeIpUpdatesLogName();
	FreeIpUpdatesFromElement(g_ipUpdates);
	g_ipUpdates = NULL;
}

<|endoftext|>


<commit_before>// RUN: %clangxx -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s

// REQUIRES: stable-runtime

// XFAIL: ubsan
// FIXME(dliew): Make this test work on Darwin with LSan
// XFAIL: darwin && lsan

#include <sanitizer/common_interface_defs.h>
#include <stdio.h>

volatile char *zero = 0;

void Death() {
  fprintf(stderr, "DEATH CALLBACK EXECUTED\n");
}
// CHECK: DEATH CALLBACK EXECUTED

char global;
volatile char *sink;

__attribute__((noinline))
void MaybeInit(int *uninitialized) {
  if (zero)
    *uninitialized = 1;
}

__attribute__((noinline))
void Leak() {
  // Trigger lsan report. Two attempts in case the address of the first
  // allocation remained on the stack.
  sink = new char[100];
  sink = new char[100];
}

int main(int argc, char **argv) {
  int uninitialized;
  __sanitizer_set_death_callback(Death);
  MaybeInit(&uninitialized);
  if (uninitialized)  // trigger msan report.
    global = 77;
  sink = new char[100];
  delete[] sink;
  global = sink[0];  // use-after-free: trigger asan/tsan report.
  Leak();
  sink = 0;
}
<commit_msg>[LSan][Darwin][NFC] Add comment explaining test failure<commit_after>// RUN: %clangxx -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s

// REQUIRES: stable-runtime

// XFAIL: ubsan
// FIXME: On Darwin, LSAn detects the leak, but does not invoke the death_callback.
// XFAIL: darwin && lsan

#include <sanitizer/common_interface_defs.h>
#include <stdio.h>

volatile char *zero = 0;

void Death() {
  fprintf(stderr, "DEATH CALLBACK EXECUTED\n");
}
// CHECK: DEATH CALLBACK EXECUTED

char global;
volatile char *sink;

__attribute__((noinline))
void MaybeInit(int *uninitialized) {
  if (zero)
    *uninitialized = 1;
}

__attribute__((noinline))
void Leak() {
  // Trigger lsan report. Two attempts in case the address of the first
  // allocation remained on the stack.
  sink = new char[100];
  sink = new char[100];
}

int main(int argc, char **argv) {
  int uninitialized;
  __sanitizer_set_death_callback(Death);
  MaybeInit(&uninitialized);
  if (uninitialized)  // trigger msan report.
    global = 77;
  sink = new char[100];
  delete[] sink;
  global = sink[0];  // use-after-free: trigger asan/tsan report.
  Leak();
  sink = 0;
}
<|endoftext|>


<commit_before>#include "mbed.h"

float readTemperature(AnalogIn pin) {
    float value = pin.read();
    float celcius = (value * 3.3f - 0.6f) * 100.0f;
    float fahrenheit = celcius * 1.8f / 32;

    //return celcius;

    return fahrenheit;
}
<commit_msg>Fixed formula<commit_after>#include "mbed.h"

float readTemperature(AnalogIn pin) {
    float value = pin.read();
    float celcius = (value * 3.3f - 0.6f) * 100.0f;
    float fahrenheit = celcius * 1.8f + 32;

    //return celcius;

    return fahrenheit;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: syshelp.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 11:58:31 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#include <syshelp.hxx>

// NOT FULLY DEFINED SERVICES
#include <string.h>
#include "sistr.hxx"
#include "list.hxx"

#ifdef WNT
#include <io.h>
#elif defined(UNX)
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define stricmp strcasecmp
#else
#error Must run under unix or windows, please define UNX or WNT.
#endif

char C_sSpaceInName[] = "   ";

void
WriteName( std::ostream &       o_rFile,
           const Simstr &   i_rIdlDocuBaseDir,
           const Simstr &   i_rName,
           E_LinkType       i_eLinkType )
{
    if (i_rName.l() == 0)
        return;

    const char * pNameEnd = strstr( i_rName.str(), " in " );

    // No link:
    if ( i_eLinkType == lt_nolink )
    {
        if ( pNameEnd != 0 )
        {
            const char * pStart = i_rName.str();
            o_rFile.write( pStart, pNameEnd - pStart );
            WriteStr( o_rFile, C_sSpaceInName );
            WriteStr( o_rFile, pNameEnd );
        }
        else
        {
            WriteStr( o_rFile, i_rName );
        }
        return;
    }

    if ( i_eLinkType == lt_idl )
    {
        Simstr sPath(i_rName);
        sPath.replace_all('.','/');
        int nNameEnd = sPath.pos_first(' ');
        int nPathStart = sPath.pos_last(' ');
        WriteStr( o_rFile, " -1 )
        {
            WriteStr( o_rFile, "file:///" );
            WriteStr( o_rFile, i_rIdlDocuBaseDir );
            WriteStr( o_rFile, "/" );
            WriteStr( o_rFile, sPath.str() + 1 + nPathStart );
            WriteStr( o_rFile, "/" );
            o_rFile.write( sPath.str(), nNameEnd );
            WriteStr( o_rFile, ".html\">" );
        }
        else
        {   // Should not be reached:
            WriteStr(o_rFile, i_rName);
            return;
        }
    }
    else if ( i_eLinkType == lt_html )
    {
        int nKomma = i_rName.pos_first(',');
        int nEnd = i_rName.pos_first(' ');
        if ( nKomma > -1 )
        {
            o_rFile.write( i_rName.str(), nKomma );
            WriteStr( o_rFile, ": " );

            WriteStr( o_rFile, " -1 )
                o_rFile.write( i_rName.str() + nKomma + 1, nEnd - nKomma );
            else
                WriteStr( o_rFile, i_rName.str() + nKomma + 1 );
            WriteStr( o_rFile, "\">" );

            o_rFile.write( i_rName.str() + nKomma + 1, nEnd - nKomma );
        }
        else
        {
            WriteStr( o_rFile, "" );

            WriteStr( o_rFile, i_rName );
        }
        WriteStr( o_rFile, "" );
        return;
    }

    if ( pNameEnd != 0 )
    {
        const char * pStart = i_rName.str();
        if ( pNameEnd > pStart )
            o_rFile.write( pStart, pNameEnd - pStart );
        WriteStr( o_rFile, "" );

        WriteStr( o_rFile, C_sSpaceInName );
        WriteStr( o_rFile, pNameEnd );
    }
    else
    {
        WriteStr( o_rFile, i_rName );
        WriteStr( o_rFile, "" );
    }
}

void
WriteStr( std::ostream &    o_rFile,
          const char *      i_sStr )
{
    o_rFile.write( i_sStr, strlen(i_sStr) );
}

void
WriteStr( std::ostream &      o_rFile,
          const Simstr &      i_sStr )
{
    o_rFile.write( i_sStr.str(), i_sStr.l() );
}

const char C_sXML_END[] = "\\*.xml";

void
GatherFileNames( List<Simstr> &     o_sFiles,
                 const char *       i_sSrcDirectory )
{
    static int   nAliveCounter = 0;

    char *       sNextDir = 0;
    Simstr       sNew = 0;

#ifdef WNT
    struct _finddata_t aEntry;
    long hFile = 0;
    int bFindMore = 0;
    char * sFilter = new char[ strlen(i_sSrcDirectory) + sizeof C_sXML_END ];

    // Stayingalive sign
    if (++nAliveCounter % 100 == 1)
        std::cout << "." << std::flush;

    strcpy(sFilter, i_sSrcDirectory);       // STRCPY SAFE HERE
    strcat(sFilter,C_sXML_END);             // STRCAT SAFE HERE

    hFile = _findfirst( sFilter, &aEntry );
    for ( bFindMore = hFile == -1;
          bFindMore == 0;
          bFindMore = _findnext( hFile, &aEntry ) )
    {
        sNew = i_sSrcDirectory;
        sNew += "\\";
        sNew += aEntry.name;
        o_sFiles.push_back(sNew);
    }   // end for

    _findclose(hFile);
    delete [] sFilter;
#elif defined(UNX)
    DIR * pDir = opendir( i_sSrcDirectory );
    dirent * pEntry = 0;
    char * sEnding;

    // Stayingalive sign
    if (++nAliveCounter % 100 == 1)
        std::cout << "." << std::flush;

    while ( (pEntry = readdir(pDir)) != 0 )
    {
        sEnding = strrchr(pEntry->d_name,'.');
        if (sEnding != 0 ? stricmp(sEnding,".xml") == 0 : 0 )
        {
            sNew = i_sSrcDirectory;
            sNew += "/";
            sNew += pEntry->d_name;
            o_sFiles.push_back(sNew);
        }
    }   // end while

    closedir( pDir );
#else
#error Must run on unix or windows, please define UNX or WNT.
#endif

    //  gathering from subdirectories:
    List<Simstr> aSubDirectories;
    GatherSubDirectories( aSubDirectories, i_sSrcDirectory );

    unsigned d_max = aSubDirectories.size();
    for ( unsigned d = 0; d < d_max; ++d )
    {
        sNextDir = new char[ strlen(i_sSrcDirectory) + 2 + aSubDirectories[d].l() ];

        strcpy(sNextDir, i_sSrcDirectory);
        strcat(sNextDir, C_sSLASH);
        strcat(sNextDir, aSubDirectories[d].str());
        GatherFileNames(o_sFiles, sNextDir);

        delete [] sNextDir;
    }
}

const char * C_sANYDIR = "\\*.*";

void
GatherSubDirectories( List<Simstr> &    o_sSubDirectories,
                      const char *      i_sParentdDirectory )
{
    Simstr sNew;

#ifdef WNT
    struct _finddata_t aEntry;
    long hFile = 0;
    int bFindMore = 0;
    char * sFilter = new char[strlen(i_sParentdDirectory) + sizeof C_sANYDIR];

    strcpy(sFilter, i_sParentdDirectory);
    strcat(sFilter,C_sANYDIR);

    hFile = _findfirst( sFilter, &aEntry );
    for ( bFindMore = hFile == -1;
          bFindMore == 0;
          bFindMore = _findnext( hFile, &aEntry ) )
    {
        if (aEntry.attrib == _A_SUBDIR)
        {
            // Do not gather . .. and outputtree directories
            if ( strchr(aEntry.name,'.') == 0
                 && strncmp(aEntry.name, "wnt", 3) != 0
                 && strncmp(aEntry.name, "unx", 3) != 0 )
            {
                sNew = aEntry.name;
                o_sSubDirectories.push_back(sNew);
            }
        }   // endif (aEntry.attrib == _A_SUBDIR)
    }   // end for
    _findclose(hFile);
    delete [] sFilter;

#elif defined(UNX)
    DIR * pDir = opendir( i_sParentdDirectory );
    dirent * pEntry = 0;
    struct stat     aEntryStatus;

    while ( ( pEntry = readdir(pDir) ) != 0 )
    {
        stat(pEntry->d_name, &aEntryStatus);
        if ( ( aEntryStatus.st_mode & S_IFDIR ) == S_IFDIR )
        {
            // Do not gather . .. and outputtree directories
            if ( strchr(pEntry->d_name,'.') == 0
                 && strncmp(pEntry->d_name, "wnt", 3) != 0
                 && strncmp(pEntry->d_name, "unx", 3) != 0 )
            {
                sNew = pEntry->d_name;
                o_sSubDirectories.push_back(sNew);
            }
        }   // endif (aEntry.attrib == _A_SUBDIR)
    }   // end while
    closedir( pDir );
#else
#error Must run on unix or windows, please define UNX or WNT.
#endif
}

<commit_msg>INTEGRATION: CWS obo05 (1.10.16); FILE MERGED 2006/06/27 13:15:58 obo 1.10.16.1: #i53611# port for .net 2005<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: syshelp.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: vg $ $Date: 2006-09-25 13:25:54 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#include <syshelp.hxx>

// NOT FULLY DEFINED SERVICES
#include <string.h>
#include "sistr.hxx"
#include "list.hxx"

#ifdef WNT
#include <io.h>
#elif defined(UNX)
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define stricmp strcasecmp
#else
#error Must run under unix or windows, please define UNX or WNT.
#endif

char C_sSpaceInName[] = "   ";

void
WriteName( std::ostream &       o_rFile,
           const Simstr &   i_rIdlDocuBaseDir,
           const Simstr &   i_rName,
           E_LinkType       i_eLinkType )
{
    if (i_rName.l() == 0)
        return;

    const char * pNameEnd = strstr( i_rName.str(), " in " );

    // No link:
    if ( i_eLinkType == lt_nolink )
    {
        if ( pNameEnd != 0 )
        {
            const char * pStart = i_rName.str();
            o_rFile.write( pStart, pNameEnd - pStart );
            WriteStr( o_rFile, C_sSpaceInName );
            WriteStr( o_rFile, pNameEnd );
        }
        else
        {
            WriteStr( o_rFile, i_rName );
        }
        return;
    }

    if ( i_eLinkType == lt_idl )
    {
        Simstr sPath(i_rName);
        sPath.replace_all('.','/');
        int nNameEnd = sPath.pos_first(' ');
        int nPathStart = sPath.pos_last(' ');
        WriteStr( o_rFile, " -1 )
        {
            WriteStr( o_rFile, "file:///" );
            WriteStr( o_rFile, i_rIdlDocuBaseDir );
            WriteStr( o_rFile, "/" );
            WriteStr( o_rFile, sPath.str() + 1 + nPathStart );
            WriteStr( o_rFile, "/" );
            o_rFile.write( sPath.str(), nNameEnd );
            WriteStr( o_rFile, ".html\">" );
        }
        else
        {   // Should not be reached:
            WriteStr(o_rFile, i_rName);
            return;
        }
    }
    else if ( i_eLinkType == lt_html )
    {
        int nKomma = i_rName.pos_first(',');
        int nEnd = i_rName.pos_first(' ');
        if ( nKomma > -1 )
        {
            o_rFile.write( i_rName.str(), nKomma );
            WriteStr( o_rFile, ": " );

            WriteStr( o_rFile, " -1 )
                o_rFile.write( i_rName.str() + nKomma + 1, nEnd - nKomma );
            else
                WriteStr( o_rFile, i_rName.str() + nKomma + 1 );
            WriteStr( o_rFile, "\">" );

            o_rFile.write( i_rName.str() + nKomma + 1, nEnd - nKomma );
        }
        else
        {
            WriteStr( o_rFile, "" );

            WriteStr( o_rFile, i_rName );
        }
        WriteStr( o_rFile, "" );
        return;
    }

    if ( pNameEnd != 0 )
    {
        const char * pStart = i_rName.str();
        if ( pNameEnd > pStart )
            o_rFile.write( pStart, pNameEnd - pStart );
        WriteStr( o_rFile, "" );

        WriteStr( o_rFile, C_sSpaceInName );
        WriteStr( o_rFile, pNameEnd );
    }
    else
    {
        WriteStr( o_rFile, i_rName );
        WriteStr( o_rFile, "" );
    }
}

void
WriteStr( std::ostream &    o_rFile,
          const char *      i_sStr )
{
    o_rFile.write( i_sStr, (int) strlen(i_sStr) );
}

void
WriteStr( std::ostream &      o_rFile,
          const Simstr &      i_sStr )
{
    o_rFile.write( i_sStr.str(), i_sStr.l() );
}

const char C_sXML_END[] = "\\*.xml";

void
GatherFileNames( List<Simstr> &     o_sFiles,
                 const char *       i_sSrcDirectory )
{
    static int   nAliveCounter = 0;

    char *       sNextDir = 0;
    Simstr       sNew = 0;

#ifdef WNT
    struct _finddata_t aEntry;
    long hFile = 0;
    int bFindMore = 0;
    char * sFilter = new char[ strlen(i_sSrcDirectory) + sizeof C_sXML_END ];

    // Stayingalive sign
    if (++nAliveCounter % 100 == 1)
        std::cout << "." << std::flush;

    strcpy(sFilter, i_sSrcDirectory);       // STRCPY SAFE HERE
    strcat(sFilter,C_sXML_END);             // STRCAT SAFE HERE

    hFile = _findfirst( sFilter, &aEntry );
    for ( bFindMore = hFile == -1;
          bFindMore == 0;
          bFindMore = _findnext( hFile, &aEntry ) )
    {
        sNew = i_sSrcDirectory;
        sNew += "\\";
        sNew += aEntry.name;
        o_sFiles.push_back(sNew);
    }   // end for

    _findclose(hFile);
    delete [] sFilter;
#elif defined(UNX)
    DIR * pDir = opendir( i_sSrcDirectory );
    dirent * pEntry = 0;
    char * sEnding;

    // Stayingalive sign
    if (++nAliveCounter % 100 == 1)
        std::cout << "." << std::flush;

    while ( (pEntry = readdir(pDir)) != 0 )
    {
        sEnding = strrchr(pEntry->d_name,'.');
        if (sEnding != 0 ? stricmp(sEnding,".xml") == 0 : 0 )
        {
            sNew = i_sSrcDirectory;
            sNew += "/";
            sNew += pEntry->d_name;
            o_sFiles.push_back(sNew);
        }
    }   // end while

    closedir( pDir );
#else
#error Must run on unix or windows, please define UNX or WNT.
#endif

    //  gathering from subdirectories:
    List<Simstr> aSubDirectories;
    GatherSubDirectories( aSubDirectories, i_sSrcDirectory );

    unsigned d_max = aSubDirectories.size();
    for ( unsigned d = 0; d < d_max; ++d )
    {
        sNextDir = new char[ strlen(i_sSrcDirectory) + 2 + aSubDirectories[d].l() ];

        strcpy(sNextDir, i_sSrcDirectory);
        strcat(sNextDir, C_sSLASH);
        strcat(sNextDir, aSubDirectories[d].str());
        GatherFileNames(o_sFiles, sNextDir);

        delete [] sNextDir;
    }
}

const char * C_sANYDIR = "\\*.*";

void
GatherSubDirectories( List<Simstr> &    o_sSubDirectories,
                      const char *      i_sParentdDirectory )
{
    Simstr sNew;

#ifdef WNT
    struct _finddata_t aEntry;
    long hFile = 0;
    int bFindMore = 0;
    char * sFilter = new char[strlen(i_sParentdDirectory) + sizeof C_sANYDIR];

    strcpy(sFilter, i_sParentdDirectory);
    strcat(sFilter,C_sANYDIR);

    hFile = _findfirst( sFilter, &aEntry );
    for ( bFindMore = hFile == -1;
          bFindMore == 0;
          bFindMore = _findnext( hFile, &aEntry ) )
    {
        if (aEntry.attrib == _A_SUBDIR)
        {
            // Do not gather . .. and outputtree directories
            if ( strchr(aEntry.name,'.') == 0
                 && strncmp(aEntry.name, "wnt", 3) != 0
                 && strncmp(aEntry.name, "unx", 3) != 0 )
            {
                sNew = aEntry.name;
                o_sSubDirectories.push_back(sNew);
            }
        }   // endif (aEntry.attrib == _A_SUBDIR)
    }   // end for
    _findclose(hFile);
    delete [] sFilter;

#elif defined(UNX)
    DIR * pDir = opendir( i_sParentdDirectory );
    dirent * pEntry = 0;
    struct stat     aEntryStatus;

    while ( ( pEntry = readdir(pDir) ) != 0 )
    {
        stat(pEntry->d_name, &aEntryStatus);
        if ( ( aEntryStatus.st_mode & S_IFDIR ) == S_IFDIR )
        {
            // Do not gather . .. and outputtree directories
            if ( strchr(pEntry->d_name,'.') == 0
                 && strncmp(pEntry->d_name, "wnt", 3) != 0
                 && strncmp(pEntry->d_name, "unx", 3) != 0 )
            {
                sNew = pEntry->d_name;
                o_sSubDirectories.push_back(sNew);
            }
        }   // endif (aEntry.attrib == _A_SUBDIR)
    }   // end while
    closedir( pDir );
#else
#error Must run on unix or windows, please define UNX or WNT.
#endif
}

<|endoftext|>