<commit_before>/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_IMPL_SATOSHI_SERIALIZE_IPP
#define LIBBITCOIN_IMPL_SATOSHI_SERIALIZE_IPP

#include <boost/optional.hpp>

namespace libbitcoin {

// message headers
template <typename Iterator>
Iterator satoshi_save(const header_type& head, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_4_bytes(head.magic);
    serial.write_fixed_string(head.command, command_size);
    serial.write_4_bytes(head.payload_length);
    if (head.checksum != 0)
        serial.write_4_bytes(head.checksum);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    header_type& head)
{
    auto deserial = make_deserializer(first, last);
    head.magic = deserial.read_4_bytes();
    head.command = deserial.read_fixed_string(command_size);
    head.payload_length = deserial.read_4_bytes();
    head.checksum = 0;
}

// version messages
template <typename Iterator>
Iterator satoshi_save(const version_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_4_bytes(packet.version);
    serial.write_8_bytes(packet.services);
    serial.write_8_bytes(packet.timestamp);
    serial.write_network_address(packet.address_me);
    serial.write_network_address(packet.address_you);
    serial.write_8_bytes(packet.nonce);
    serial.write_string(packet.user_agent);
    serial.write_4_bytes(packet.start_height);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    version_type& packet)
{
    auto deserial = make_deserializer(first, last);
    packet.version = deserial.read_4_bytes();
    packet.services = deserial.read_8_bytes();
    packet.timestamp = deserial.read_8_bytes();
    packet.address_me = deserial.read_network_address();
    // Ignored field
    packet.address_me.timestamp = 0;
    if (packet.version < 106)
    {
        BITCOIN_ASSERT(std::distance(first, last) >= 46);
        return;
    }
    packet.address_you = deserial.read_network_address();
    // Ignored field
    packet.address_you.timestamp = 0;
    packet.nonce = deserial.read_8_bytes();
    packet.user_agent = deserial.read_string();
    if (packet.version < 209)
    {
        BITCOIN_ASSERT(std::distance(first, last) >= 46 + 26 + 8 + 1);
        return;
    }
    packet.start_height = deserial.read_4_bytes();
    BITCOIN_ASSERT(std::distance(first, last) >= 81 + 4);
}

// verack messages
template <typename Iterator>
Iterator satoshi_save(const verack_type& packet, Iterator result)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
    return result;
}
template <typename Iterator>
void satoshi_load(const Iterator, const Iterator, verack_type& packet)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
}

// addr messages
template <typename Iterator>
Iterator satoshi_save(const address_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_variable_uint(packet.addresses.size());
    for (const network_address_type& net_address: packet.addresses)
    {
        serial.write_4_bytes(net_address.timestamp);
        serial.write_network_address(net_address);
    }
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    address_type& packet)
{
    auto deserial = make_deserializer(first, last);
    uint64_t count = deserial.read_variable_uint();
    for (size_t i = 0; i < count; ++i)
    {
        uint32_t timestamp = deserial.read_4_bytes();
        network_address_type addr = deserial.read_network_address();
        addr.timestamp = timestamp;
        packet.addresses.push_back(addr);
    }
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// getaddr messages
template <typename Iterator>
Iterator satoshi_save(const get_address_type& packet, Iterator result)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
    return result;
}
template <typename Iterator>
void satoshi_load(const Iterator, const Iterator, get_address_type& packet)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
}

// inventory related stuff
uint32_t inventory_type_to_number(inventory_type_id inv_type);
inventory_type_id inventory_type_from_number(uint32_t raw_type);

template <typename Message>
size_t raw_size_inventory_impl(const Message& packet)
{
    return variable_uint_size(packet.inventories.size()) +
        36 * packet.inventories.size();
}
template <typename Message, typename Iterator>
Iterator save_inventory_impl(const Message& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_variable_uint(packet.inventories.size());
    for (const inventory_vector_type inv: packet.inventories)
    {
        uint32_t raw_type = inventory_type_to_number(inv.type);
        serial.write_4_bytes(raw_type);
        serial.write_hash(inv.hash);
    }
    return serial.iterator();
}
template <typename Message, typename Iterator>
void load_inventory_impl(const Iterator first, const Iterator last,
    Message& packet)
{
    auto deserial = make_deserializer(first, last);
    uint64_t count = deserial.read_variable_uint();
    for (size_t i = 0; i < count; ++i)
    {
        inventory_vector_type inv;
        uint32_t raw_type = deserial.read_4_bytes();
        inv.type = inventory_type_from_number(raw_type);
        inv.hash = deserial.read_hash();
        packet.inventories.push_back(inv);
    }
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// inv messages
template <typename Iterator>
Iterator satoshi_save(const inventory_type& packet, Iterator result)
{
    return save_inventory_impl(packet, result);
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    inventory_type& packet)
{
    load_inventory_impl(first, last, packet);
}

// getdata messages
template <typename Iterator>
Iterator satoshi_save(const get_data_type& packet, Iterator result)
{
    return save_inventory_impl(packet, result);
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    get_data_type& packet)
{
    load_inventory_impl(first, last, packet);
}

// getblocks messages
const std::string satoshi_command(const get_blocks_type&);
size_t satoshi_raw_size(const get_blocks_type& packet);
template <typename Iterator>
Iterator satoshi_save(const get_blocks_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_4_bytes(protocol_version);
    serial.write_variable_uint(packet.start_hashes.size());
    for (hash_digest start_hash: packet.start_hashes)
        serial.write_hash(start_hash);
    serial.write_hash(packet.hash_stop);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    get_blocks_type& packet)
{
    auto deserial = make_deserializer(first, last);
    // Discard protocol version because it is stupid
    deserial.read_4_bytes();
    uint32_t count = deserial.read_variable_uint();
    for (size_t i = 0; i < count; ++i)
    {
        hash_digest start_hash = deserial.read_hash();
        packet.start_hashes.push_back(start_hash);
    }
    packet.hash_stop = deserial.read_hash();
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// ping messages
const std::string satoshi_command(const ping_type&);
size_t satoshi_raw_size(const ping_type& packet);
template <typename Iterator>
Iterator satoshi_save(const ping_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_8_bytes(packet.nonce);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    ping_type& packet)
{
    auto deserial = make_deserializer(first, last);
    packet.nonce = deserial.read_8_bytes();
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// pong messages
const std::string satoshi_command(const pong_type&);
size_t satoshi_raw_size(const pong_type& packet);
template <typename Iterator>
Iterator satoshi_save(const pong_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_8_bytes(packet.nonce);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    pong_type& packet)
{
    auto deserial = make_deserializer(first, last);
    packet.nonce = deserial.read_8_bytes();
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

} // libbitcoin

#endif

<commit_msg>Comment "deserial.iterator() == last" assertion<commit_after>/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_IMPL_SATOSHI_SERIALIZE_IPP
#define LIBBITCOIN_IMPL_SATOSHI_SERIALIZE_IPP

#include <boost/optional.hpp>

namespace libbitcoin {

// message headers
template <typename Iterator>
Iterator satoshi_save(const header_type& head, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_4_bytes(head.magic);
    serial.write_fixed_string(head.command, command_size);
    serial.write_4_bytes(head.payload_length);
    if (head.checksum != 0)
        serial.write_4_bytes(head.checksum);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    header_type& head)
{
    auto deserial = make_deserializer(first, last);
    head.magic = deserial.read_4_bytes();
    head.command = deserial.read_fixed_string(command_size);
    head.payload_length = deserial.read_4_bytes();
    head.checksum = 0;
}

// version messages
template <typename Iterator>
Iterator satoshi_save(const version_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_4_bytes(packet.version);
    serial.write_8_bytes(packet.services);
    serial.write_8_bytes(packet.timestamp);
    serial.write_network_address(packet.address_me);
    serial.write_network_address(packet.address_you);
    serial.write_8_bytes(packet.nonce);
    serial.write_string(packet.user_agent);
    serial.write_4_bytes(packet.start_height);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    version_type& packet)
{
    auto deserial = make_deserializer(first, last);
    packet.version = deserial.read_4_bytes();
    packet.services = deserial.read_8_bytes();
    packet.timestamp = deserial.read_8_bytes();
    packet.address_me = deserial.read_network_address();
    // Ignored field
    packet.address_me.timestamp = 0;
    if (packet.version < 106)
    {
        BITCOIN_ASSERT(std::distance(first, last) >= 46);
        return;
    }
    packet.address_you = deserial.read_network_address();
    // Ignored field
    packet.address_you.timestamp = 0;
    packet.nonce = deserial.read_8_bytes();
    packet.user_agent = deserial.read_string();
    if (packet.version < 209)
    {
        BITCOIN_ASSERT(std::distance(first, last) >= 46 + 26 + 8 + 1);
        return;
    }
    packet.start_height = deserial.read_4_bytes();
    BITCOIN_ASSERT(std::distance(first, last) >= 81 + 4);
}

// verack messages
template <typename Iterator>
Iterator satoshi_save(const verack_type& packet, Iterator result)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
    return result;
}
template <typename Iterator>
void satoshi_load(const Iterator, const Iterator, verack_type& packet)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
}

// addr messages
template <typename Iterator>
Iterator satoshi_save(const address_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_variable_uint(packet.addresses.size());
    for (const network_address_type& net_address: packet.addresses)
    {
        serial.write_4_bytes(net_address.timestamp);
        serial.write_network_address(net_address);
    }
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    address_type& packet)
{
    auto deserial = make_deserializer(first, last);
    uint64_t count = deserial.read_variable_uint();
    for (size_t i = 0; i < count; ++i)
    {
        uint32_t timestamp = deserial.read_4_bytes();
        network_address_type addr = deserial.read_network_address();
        addr.timestamp = timestamp;
        packet.addresses.push_back(addr);
    }
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    //BITCOIN_ASSERT(deserial.iterator() == last);
}

// getaddr messages
template <typename Iterator>
Iterator satoshi_save(const get_address_type& packet, Iterator result)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
    return result;
}
template <typename Iterator>
void satoshi_load(const Iterator, const Iterator, get_address_type& packet)
{
    BITCOIN_ASSERT(satoshi_raw_size(packet) == 0);
}

// inventory related stuff
uint32_t inventory_type_to_number(inventory_type_id inv_type);
inventory_type_id inventory_type_from_number(uint32_t raw_type);

template <typename Message>
size_t raw_size_inventory_impl(const Message& packet)
{
    return variable_uint_size(packet.inventories.size()) +
        36 * packet.inventories.size();
}
template <typename Message, typename Iterator>
Iterator save_inventory_impl(const Message& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_variable_uint(packet.inventories.size());
    for (const inventory_vector_type inv: packet.inventories)
    {
        uint32_t raw_type = inventory_type_to_number(inv.type);
        serial.write_4_bytes(raw_type);
        serial.write_hash(inv.hash);
    }
    return serial.iterator();
}
template <typename Message, typename Iterator>
void load_inventory_impl(const Iterator first, const Iterator last,
    Message& packet)
{
    auto deserial = make_deserializer(first, last);
    uint64_t count = deserial.read_variable_uint();
    for (size_t i = 0; i < count; ++i)
    {
        inventory_vector_type inv;
        uint32_t raw_type = deserial.read_4_bytes();
        inv.type = inventory_type_from_number(raw_type);
        inv.hash = deserial.read_hash();
        packet.inventories.push_back(inv);
    }
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// inv messages
template <typename Iterator>
Iterator satoshi_save(const inventory_type& packet, Iterator result)
{
    return save_inventory_impl(packet, result);
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    inventory_type& packet)
{
    load_inventory_impl(first, last, packet);
}

// getdata messages
template <typename Iterator>
Iterator satoshi_save(const get_data_type& packet, Iterator result)
{
    return save_inventory_impl(packet, result);
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    get_data_type& packet)
{
    load_inventory_impl(first, last, packet);
}

// getblocks messages
const std::string satoshi_command(const get_blocks_type&);
size_t satoshi_raw_size(const get_blocks_type& packet);
template <typename Iterator>
Iterator satoshi_save(const get_blocks_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_4_bytes(protocol_version);
    serial.write_variable_uint(packet.start_hashes.size());
    for (hash_digest start_hash: packet.start_hashes)
        serial.write_hash(start_hash);
    serial.write_hash(packet.hash_stop);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    get_blocks_type& packet)
{
    auto deserial = make_deserializer(first, last);
    // Discard protocol version because it is stupid
    deserial.read_4_bytes();
    uint32_t count = deserial.read_variable_uint();
    for (size_t i = 0; i < count; ++i)
    {
        hash_digest start_hash = deserial.read_hash();
        packet.start_hashes.push_back(start_hash);
    }
    packet.hash_stop = deserial.read_hash();
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// ping messages
const std::string satoshi_command(const ping_type&);
size_t satoshi_raw_size(const ping_type& packet);
template <typename Iterator>
Iterator satoshi_save(const ping_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_8_bytes(packet.nonce);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    ping_type& packet)
{
    auto deserial = make_deserializer(first, last);
    packet.nonce = deserial.read_8_bytes();
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

// pong messages
const std::string satoshi_command(const pong_type&);
size_t satoshi_raw_size(const pong_type& packet);
template <typename Iterator>
Iterator satoshi_save(const pong_type& packet, Iterator result)
{
    auto serial = make_serializer(result);
    serial.write_8_bytes(packet.nonce);
    return serial.iterator();
}
template <typename Iterator>
void satoshi_load(const Iterator first, const Iterator last,
    pong_type& packet)
{
    auto deserial = make_deserializer(first, last);
    packet.nonce = deserial.read_8_bytes();
    BITCOIN_ASSERT(deserial.iterator() == first + satoshi_raw_size(packet));
    BITCOIN_ASSERT(deserial.iterator() == last);
}

} // libbitcoin

#endif

<|endoftext|>


<commit_before>#include "StdAfx.h"

HINSTANCE  ghInstance = NULL;      // module handle.
PnPControl* control = NULL;

BOOL APIENTRY DllMain (HANDLE hModule, ULONG ul_reason_for_call, LPVOID lpReserved)
{
    UNREFERENCED_PARAMETER(ul_reason_for_call);
    UNREFERENCED_PARAMETER(lpReserved);

    ghInstance = (HINSTANCE) hModule;
    return TRUE;
}

DLL_API BOOL VIOSStartup(void)
{
    PnPControl::GetInstance();
    return TRUE;
}

DLL_API VOID VIOSCleanup ( void )
{
    PnPControl::CloseInstance();
}

DLL_API BOOL FindPort ( const wchar_t* name )
{
    PnPControl* control = PnPControl::GetInstance();
    BOOL ret = control->FindPort(name);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API PVOID OpenPortByName ( const wchar_t* name )
{
    PnPControl* control = PnPControl::GetInstance();
    PVOID ret = control->OpenPortByName(name);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API PVOID OpenPortById ( UINT id )
{
    PnPControl* control = PnPControl::GetInstance();
    PVOID ret = control->OpenPortById(id);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API BOOL ReadPort ( PVOID port, PVOID buf, PULONG size )
{
    PnPControl* control = PnPControl::GetInstance();
    BOOL ret = control->ReadPort(port, buf, size);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API BOOL WritePort ( PVOID port, PVOID buf, ULONG size )
{
    PnPControl* control = PnPControl::GetInstance();
    BOOL ret = control->WritePort(port, buf, size);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API VOID ClosePort ( PVOID port )
{
    PnPControl* control = PnPControl::GetInstance();
    control->ClosePort(port);
    PnPControl::CloseInstance();
}

DLL_API UINT NumPorts(void)
{
    PnPControl* control = PnPControl::GetInstance();
    UINT ret = control->NumPorts();
    PnPControl::CloseInstance();
    return ret;
}

DLL_API wchar_t* PortSymbolicName ( int index )
{
    PnPControl* control = PnPControl::GetInstance();
    wchar_t* ret = control->PortSymbolicName(index);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API VOID RegisterNotification(PVOID port, VIOSERIALNOTIFYCALLBACK pfn, PVOID ptr)
{
    PnPControl* control = PnPControl::GetInstance();
    control->RegisterNotification(port, pfn, ptr);
    PnPControl::CloseInstance();
}
<commit_msg>Fix x64 build<commit_after>#include "StdAfx.h"

HINSTANCE  ghInstance = NULL;      // module handle.
PnPControl* control = NULL;

BOOL APIENTRY DllMain (HANDLE hModule, ULONG ul_reason_for_call, LPVOID lpReserved)
{
    UNREFERENCED_PARAMETER(ul_reason_for_call);
    UNREFERENCED_PARAMETER(lpReserved);

    ghInstance = (HINSTANCE) hModule;
    return TRUE;
}

DLL_API BOOL VIOSStartup(void)
{
    PnPControl::GetInstance();
    return TRUE;
}

DLL_API VOID VIOSCleanup ( void )
{
    PnPControl::CloseInstance();
}

DLL_API BOOL FindPort ( const wchar_t* name )
{
    PnPControl* control = PnPControl::GetInstance();
    BOOL ret = control->FindPort(name);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API PVOID OpenPortByName ( const wchar_t* name )
{
    PnPControl* control = PnPControl::GetInstance();
    PVOID ret = control->OpenPortByName(name);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API PVOID OpenPortById ( UINT id )
{
    PnPControl* control = PnPControl::GetInstance();
    PVOID ret = control->OpenPortById(id);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API BOOL ReadPort ( PVOID port, PVOID buf, PULONG size )
{
    PnPControl* control = PnPControl::GetInstance();
    BOOL ret = control->ReadPort(port, buf, size);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API BOOL WritePort ( PVOID port, PVOID buf, ULONG size )
{
    PnPControl* control = PnPControl::GetInstance();
    BOOL ret = control->WritePort(port, buf, size);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API VOID ClosePort ( PVOID port )
{
    PnPControl* control = PnPControl::GetInstance();
    control->ClosePort(port);
    PnPControl::CloseInstance();
}

DLL_API UINT NumPorts(void)
{
    PnPControl* control = PnPControl::GetInstance();
    UINT ret = (UINT)control->NumPorts();
    PnPControl::CloseInstance();
    return ret;
}

DLL_API wchar_t* PortSymbolicName ( int index )
{
    PnPControl* control = PnPControl::GetInstance();
    wchar_t* ret = control->PortSymbolicName(index);
    PnPControl::CloseInstance();
    return ret;
}

DLL_API VOID RegisterNotification(PVOID port, VIOSERIALNOTIFYCALLBACK pfn, PVOID ptr)
{
    PnPControl* control = PnPControl::GetInstance();
    control->RegisterNotification(port, pfn, ptr);
    PnPControl::CloseInstance();
}
<|endoftext|>


<commit_before>//===- llvm-link.cpp - Low-level LLVM linker ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility may be invoked in the following manner:
//  llvm-link a.bc b.bc c.bc -o x.bc
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"

#include <memory>
using namespace llvm;

static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
               cl::desc("<input bitcode files>"));

static cl::list<std::string> OverridingInputs(
    "override", cl::ZeroOrMore, cl::value_desc("filename"),
    cl::desc(
        "input bitcode file which can override previously defined symbol(s)"));

// Option to simulate function importing for testing. This enables using
// llvm-link to simulate ThinLTO backend processes.
static cl::list<std::string> Imports(
    "import", cl::ZeroOrMore, cl::value_desc("function:filename"),
    cl::desc("Pair of function name and filename, where function should be "
             "imported from bitcode in filename"));

// Option to support testing of function importing. The module summary
// must be specified in the case were we request imports via the -import
// option, as well as when compiling any module with functions that may be
// exported (imported by a different llvm-link -import invocation), to ensure
// consistent promotion and renaming of locals.
static cl::opt<std::string>
    SummaryIndex("summary-index", cl::desc("Module summary index filename"),
                 cl::init(""), cl::value_desc("filename"));

static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
               cl::value_desc("filename"));

static cl::opt<bool>
Internalize("internalize", cl::desc("Internalize linked symbols"));

static cl::opt<bool>
OnlyNeeded("only-needed", cl::desc("Link only needed symbols"));

static cl::opt<bool>
Force("f", cl::desc("Enable binary output on terminals"));

static cl::opt<bool>
OutputAssembly("S",
         cl::desc("Write output as LLVM assembly"), cl::Hidden);

static cl::opt<bool>
Verbose("v", cl::desc("Print information about actions taken"));

static cl::opt<bool>
DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);

static cl::opt<bool>
SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"),
                 cl::init(false));

static cl::opt<bool> PreserveBitcodeUseListOrder(
    "preserve-bc-uselistorder",
    cl::desc("Preserve use-list order when writing LLVM bitcode."),
    cl::init(true), cl::Hidden);

static cl::opt<bool> PreserveAssemblyUseListOrder(
    "preserve-ll-uselistorder",
    cl::desc("Preserve use-list order when writing LLVM assembly."),
    cl::init(false), cl::Hidden);

// Read the specified bitcode file in and return it. This routine searches the
// link path for the specified file to try to find it...
//
static std::unique_ptr<Module> loadFile(const char *argv0,
                                        const std::string &FN,
                                        LLVMContext &Context,
                                        bool MaterializeMetadata = true) {
  SMDiagnostic Err;
  if (Verbose) errs() << "Loading '" << FN << "'\n";
  std::unique_ptr<Module> Result =
      getLazyIRFileModule(FN, Err, Context, !MaterializeMetadata);
  if (!Result)
    Err.print(argv0, errs());

  if (MaterializeMetadata) {
    Result->materializeMetadata();
    UpgradeDebugInfo(*Result);
  }

  return Result;
}

static void diagnosticHandler(const DiagnosticInfo &DI) {
  unsigned Severity = DI.getSeverity();
  switch (Severity) {
  case DS_Error:
    errs() << "ERROR: ";
    break;
  case DS_Warning:
    if (SuppressWarnings)
      return;
    errs() << "WARNING: ";
    break;
  case DS_Remark:
  case DS_Note:
    llvm_unreachable("Only expecting warnings and errors");
  }

  DiagnosticPrinterRawOStream DP(errs());
  DI.print(DP);
  errs() << '\n';
}

static void diagnosticHandlerWithContext(const DiagnosticInfo &DI, void *C) {
  diagnosticHandler(DI);
}

/// Import any functions requested via the -import option.
static bool importFunctions(const char *argv0, LLVMContext &Context,
                            Linker &L) {
  StringMap<std::unique_ptr<DenseMap<unsigned, MDNode *>>>
      ModuleToTempMDValsMap;
  for (const auto &Import : Imports) {
    // Identify the requested function and its bitcode source file.
    size_t Idx = Import.find(':');
    if (Idx == std::string::npos) {
      errs() << "Import parameter bad format: " << Import << "\n";
      return false;
    }
    std::string FunctionName = Import.substr(0, Idx);
    std::string FileName = Import.substr(Idx + 1, std::string::npos);

    // Load the specified source module.
    std::unique_ptr<Module> M = loadFile(argv0, FileName, Context, false);
    if (!M.get()) {
      errs() << argv0 << ": error loading file '" << FileName << "'\n";
      return false;
    }

    if (verifyModule(*M, &errs())) {
      errs() << argv0 << ": " << FileName
             << ": error: input module is broken!\n";
      return false;
    }

    Function *F = M->getFunction(FunctionName);
    if (!F) {
      errs() << "Ignoring import request for non-existent function "
             << FunctionName << " from " << FileName << "\n";
      continue;
    }
    // We cannot import weak_any functions without possibly affecting the
    // order they are seen and selected by the linker, changing program
    // semantics.
    if (F->hasWeakAnyLinkage()) {
      errs() << "Ignoring import request for weak-any function " << FunctionName
             << " from " << FileName << "\n";
      continue;
    }

    if (Verbose)
      errs() << "Importing " << FunctionName << " from " << FileName << "\n";

    // Link in the specified function.
    DenseSet<const GlobalValue *> GlobalsToImport;
    GlobalsToImport.insert(F);

    if (!SummaryIndex.empty()) {
      ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
          llvm::getModuleSummaryIndexForFile(SummaryIndex, diagnosticHandler);
      std::error_code EC = IndexOrErr.getError();
      if (EC) {
        errs() << EC.message() << '\n';
        return false;
      }
      auto Index = std::move(IndexOrErr.get());

      // Linkage Promotion and renaming
      if (renameModuleForThinLTO(*M, *Index, &GlobalsToImport))
        return true;
    }

    // Save the mapping of value ids to temporary metadata created when
    // importing this function. If we have already imported from this module,
    // add new temporary metadata to the existing mapping.
    auto &TempMDVals = ModuleToTempMDValsMap[FileName];
    if (!TempMDVals)
      TempMDVals = llvm::make_unique<DenseMap<unsigned, MDNode *>>();

    if (L.linkInModule(std::move(M), Linker::Flags::None, &GlobalsToImport,
                       TempMDVals.get()))
      return false;
  }

  // Now link in metadata for all modules from which we imported functions.
  for (StringMapEntry<std::unique_ptr<DenseMap<unsigned, MDNode *>>> &SME :
       ModuleToTempMDValsMap) {
    // Load the specified source module.
    std::unique_ptr<Module> M = loadFile(argv0, SME.getKey(), Context, true);
    if (!M.get()) {
      errs() << argv0 << ": error loading file '" << SME.getKey() << "'\n";
      return false;
    }

    if (verifyModule(*M, &errs())) {
      errs() << argv0 << ": " << SME.getKey()
             << ": error: input module is broken!\n";
      return false;
    }

    // Link in all necessary metadata from this module.
    if (L.linkInMetadata(std::move(M), SME.getValue().get()))
      return false;
  }
  return true;
}

static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
                      const cl::list<std::string> &Files,
                      unsigned Flags) {
  // Filter out flags that don't apply to the first file we load.
  unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
  for (const auto &File : Files) {
    std::unique_ptr<Module> M = loadFile(argv0, File, Context);
    if (!M.get()) {
      errs() << argv0 << ": error loading file '" << File << "'\n";
      return false;
    }

    if (verifyModule(*M, &errs())) {
      errs() << argv0 << ": " << File << ": error: input module is broken!\n";
      return false;
    }

    // If a module summary index is supplied, load it so linkInModule can treat
    // local functions/variables as exported and promote if necessary.
    if (!SummaryIndex.empty()) {
      ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
          llvm::getModuleSummaryIndexForFile(SummaryIndex, diagnosticHandler);
      std::error_code EC = IndexOrErr.getError();
      if (EC) {
        errs() << EC.message() << '\n';
        return false;
      }
      auto Index = std::move(IndexOrErr.get());

      // Promotion
      if (renameModuleForThinLTO(*M, *Index))
        return true;
    }

    if (Verbose)
      errs() << "Linking in '" << File << "'\n";

    if (L.linkInModule(std::move(M), ApplicableFlags))
      return false;
    // All linker flags apply to linking of subsequent files.
    ApplicableFlags = Flags;
  }

  return true;
}

int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);

  LLVMContext &Context = getGlobalContext();
  Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);

  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
  cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");

  auto Composite = make_unique<Module>("llvm-link", Context);
  Linker L(*Composite);

  unsigned Flags = Linker::Flags::None;
  if (Internalize)
    Flags |= Linker::Flags::InternalizeLinkedSymbols;
  if (OnlyNeeded)
    Flags |= Linker::Flags::LinkOnlyNeeded;

  // First add all the regular input files
  if (!linkFiles(argv[0], Context, L, InputFilenames, Flags))
    return 1;

  // Next the -override ones.
  if (!linkFiles(argv[0], Context, L, OverridingInputs,
                 Flags | Linker::Flags::OverrideFromSrc))
    return 1;

  // Import any functions requested via -import
  if (!importFunctions(argv[0], Context, L))
    return 1;

  if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;

  std::error_code EC;
  tool_output_file Out(OutputFilename, EC, sys::fs::F_None);
  if (EC) {
    errs() << EC.message() << '\n';
    return 1;
  }

  if (verifyModule(*Composite, &errs())) {
    errs() << argv[0] << ": error: linked module is broken!\n";
    return 1;
  }

  if (Verbose) errs() << "Writing bitcode...\n";
  if (OutputAssembly) {
    Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder);
  } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
    WriteBitcodeToFile(Composite.get(), Out.os(), PreserveBitcodeUseListOrder);

  // Declare success.
  Out.keep();

  return 0;
}
<commit_msg>[ThinLTO] Use bulk importing in llvm-link<commit_after>//===- llvm-link.cpp - Low-level LLVM linker ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility may be invoked in the following manner:
//  llvm-link a.bc b.bc c.bc -o x.bc
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"

#include <memory>
using namespace llvm;

static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
               cl::desc("<input bitcode files>"));

static cl::list<std::string> OverridingInputs(
    "override", cl::ZeroOrMore, cl::value_desc("filename"),
    cl::desc(
        "input bitcode file which can override previously defined symbol(s)"));

// Option to simulate function importing for testing. This enables using
// llvm-link to simulate ThinLTO backend processes.
static cl::list<std::string> Imports(
    "import", cl::ZeroOrMore, cl::value_desc("function:filename"),
    cl::desc("Pair of function name and filename, where function should be "
             "imported from bitcode in filename"));

// Option to support testing of function importing. The module summary
// must be specified in the case were we request imports via the -import
// option, as well as when compiling any module with functions that may be
// exported (imported by a different llvm-link -import invocation), to ensure
// consistent promotion and renaming of locals.
static cl::opt<std::string>
    SummaryIndex("summary-index", cl::desc("Module summary index filename"),
                 cl::init(""), cl::value_desc("filename"));

static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
               cl::value_desc("filename"));

static cl::opt<bool>
Internalize("internalize", cl::desc("Internalize linked symbols"));

static cl::opt<bool>
OnlyNeeded("only-needed", cl::desc("Link only needed symbols"));

static cl::opt<bool>
Force("f", cl::desc("Enable binary output on terminals"));

static cl::opt<bool>
OutputAssembly("S",
         cl::desc("Write output as LLVM assembly"), cl::Hidden);

static cl::opt<bool>
Verbose("v", cl::desc("Print information about actions taken"));

static cl::opt<bool>
DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);

static cl::opt<bool>
SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"),
                 cl::init(false));

static cl::opt<bool> PreserveBitcodeUseListOrder(
    "preserve-bc-uselistorder",
    cl::desc("Preserve use-list order when writing LLVM bitcode."),
    cl::init(true), cl::Hidden);

static cl::opt<bool> PreserveAssemblyUseListOrder(
    "preserve-ll-uselistorder",
    cl::desc("Preserve use-list order when writing LLVM assembly."),
    cl::init(false), cl::Hidden);

// Read the specified bitcode file in and return it. This routine searches the
// link path for the specified file to try to find it...
//
static std::unique_ptr<Module> loadFile(const char *argv0,
                                        const std::string &FN,
                                        LLVMContext &Context,
                                        bool MaterializeMetadata = true) {
  SMDiagnostic Err;
  if (Verbose) errs() << "Loading '" << FN << "'\n";
  std::unique_ptr<Module> Result =
      getLazyIRFileModule(FN, Err, Context, !MaterializeMetadata);
  if (!Result) {
    Err.print(argv0, errs());
    return nullptr;
  }

  if (MaterializeMetadata) {
    Result->materializeMetadata();
    UpgradeDebugInfo(*Result);
  }

  return Result;
}

namespace {

/// Helper to load on demand a Module from file and cache it for subsequent
/// queries during function importing.
class ModuleLazyLoaderCache {
  /// Cache of lazily loaded module for import.
  StringMap<std::unique_ptr<Module>> ModuleMap;

  /// Retrieve a Module from the cache or lazily load it on demand.
  std::function<std::unique_ptr<Module>(const char *argv0,
                                        const std::string &FileName)>
      createLazyModule;

public:
  /// Create the loader, Module will be initialized in \p Context.
  ModuleLazyLoaderCache(std::function<std::unique_ptr<Module>(
                            const char *argv0, const std::string &FileName)>
                            createLazyModule)
      : createLazyModule(createLazyModule) {}

  /// Retrieve a Module from the cache or lazily load it on demand.
  Module &operator()(const char *argv0, const std::string &FileName);

  std::unique_ptr<Module> takeModule(const std::string &FileName) {
    auto I = ModuleMap.find(FileName);
    assert(I != ModuleMap.end());
    std::unique_ptr<Module> Ret = std::move(I->second);
    ModuleMap.erase(I);
    return Ret;
  }
};

// Get a Module for \p FileName from the cache, or load it lazily.
Module &ModuleLazyLoaderCache::operator()(const char *argv0,
                                          const std::string &Identifier) {
  auto &Module = ModuleMap[Identifier];
  if (!Module)
    Module = createLazyModule(argv0, Identifier);
  return *Module;
}
} // anonymous namespace

static void diagnosticHandler(const DiagnosticInfo &DI) {
  unsigned Severity = DI.getSeverity();
  switch (Severity) {
  case DS_Error:
    errs() << "ERROR: ";
    break;
  case DS_Warning:
    if (SuppressWarnings)
      return;
    errs() << "WARNING: ";
    break;
  case DS_Remark:
  case DS_Note:
    llvm_unreachable("Only expecting warnings and errors");
  }

  DiagnosticPrinterRawOStream DP(errs());
  DI.print(DP);
  errs() << '\n';
}

static void diagnosticHandlerWithContext(const DiagnosticInfo &DI, void *C) {
  diagnosticHandler(DI);
}

/// Import any functions requested via the -import option.
static bool importFunctions(const char *argv0, LLVMContext &Context,
                            Linker &L) {
  if (SummaryIndex.empty())
    return true;
  ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
      llvm::getModuleSummaryIndexForFile(SummaryIndex, diagnosticHandler);
  std::error_code EC = IndexOrErr.getError();
  if (EC) {
    errs() << EC.message() << '\n';
    return false;
  }
  auto Index = std::move(IndexOrErr.get());

  // Map of Module -> List of globals to import from the Module
  std::map<StringRef, DenseSet<const GlobalValue *>> ModuleToGlobalsToImportMap;
  auto ModuleLoader = [&Context](const char *argv0,
                                 const std::string &Identifier) {
    return loadFile(argv0, Identifier, Context, false);
  };
  ModuleLazyLoaderCache ModuleLoaderCache(ModuleLoader);
  for (const auto &Import : Imports) {
    // Identify the requested function and its bitcode source file.
    size_t Idx = Import.find(':');
    if (Idx == std::string::npos) {
      errs() << "Import parameter bad format: " << Import << "\n";
      return false;
    }
    std::string FunctionName = Import.substr(0, Idx);
    std::string FileName = Import.substr(Idx + 1, std::string::npos);

    // Load the specified source module.
    auto &SrcModule = ModuleLoaderCache(argv0, FileName);

    if (verifyModule(SrcModule, &errs())) {
      errs() << argv0 << ": " << FileName
             << ": error: input module is broken!\n";
      return false;
    }

    Function *F = SrcModule.getFunction(FunctionName);
    if (!F) {
      errs() << "Ignoring import request for non-existent function "
             << FunctionName << " from " << FileName << "\n";
      continue;
    }
    // We cannot import weak_any functions without possibly affecting the
    // order they are seen and selected by the linker, changing program
    // semantics.
    if (F->hasWeakAnyLinkage()) {
      errs() << "Ignoring import request for weak-any function " << FunctionName
             << " from " << FileName << "\n";
      continue;
    }

    if (Verbose)
      errs() << "Importing " << FunctionName << " from " << FileName << "\n";

    auto &Entry = ModuleToGlobalsToImportMap[SrcModule.getModuleIdentifier()];
    Entry.insert(F);

    F->materialize();
  }

  // Do the actual import of globals now, one Module at a time
  for (auto &GlobalsToImportPerModule : ModuleToGlobalsToImportMap) {
    // Get the module for the import
    auto &GlobalsToImport = GlobalsToImportPerModule.second;
    std::unique_ptr<Module> SrcModule =
        ModuleLoaderCache.takeModule(GlobalsToImportPerModule.first);
    assert(&Context == &SrcModule->getContext() && "Context mismatch");

    // If modules were created with lazy metadata loading, materialize it
    // now, before linking it (otherwise this will be a noop).
    SrcModule->materializeMetadata();
    UpgradeDebugInfo(*SrcModule);

    // Linkage Promotion and renaming
    if (renameModuleForThinLTO(*SrcModule, *Index, &GlobalsToImport))
      return true;

    if (L.linkInModule(std::move(SrcModule), Linker::Flags::None,
                       &GlobalsToImport))
      return false;
  }

  return true;
}

static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
                      const cl::list<std::string> &Files,
                      unsigned Flags) {
  // Filter out flags that don't apply to the first file we load.
  unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
  for (const auto &File : Files) {
    std::unique_ptr<Module> M = loadFile(argv0, File, Context);
    if (!M.get()) {
      errs() << argv0 << ": error loading file '" << File << "'\n";
      return false;
    }

    if (verifyModule(*M, &errs())) {
      errs() << argv0 << ": " << File << ": error: input module is broken!\n";
      return false;
    }

    // If a module summary index is supplied, load it so linkInModule can treat
    // local functions/variables as exported and promote if necessary.
    if (!SummaryIndex.empty()) {
      ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
          llvm::getModuleSummaryIndexForFile(SummaryIndex, diagnosticHandler);
      std::error_code EC = IndexOrErr.getError();
      if (EC) {
        errs() << EC.message() << '\n';
        return false;
      }
      auto Index = std::move(IndexOrErr.get());

      // Promotion
      if (renameModuleForThinLTO(*M, *Index))
        return true;
    }

    if (Verbose)
      errs() << "Linking in '" << File << "'\n";

    if (L.linkInModule(std::move(M), ApplicableFlags))
      return false;
    // All linker flags apply to linking of subsequent files.
    ApplicableFlags = Flags;
  }

  return true;
}

int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);

  LLVMContext &Context = getGlobalContext();
  Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);

  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
  cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");

  auto Composite = make_unique<Module>("llvm-link", Context);
  Linker L(*Composite);

  unsigned Flags = Linker::Flags::None;
  if (Internalize)
    Flags |= Linker::Flags::InternalizeLinkedSymbols;
  if (OnlyNeeded)
    Flags |= Linker::Flags::LinkOnlyNeeded;

  // First add all the regular input files
  if (!linkFiles(argv[0], Context, L, InputFilenames, Flags))
    return 1;

  // Next the -override ones.
  if (!linkFiles(argv[0], Context, L, OverridingInputs,
                 Flags | Linker::Flags::OverrideFromSrc))
    return 1;

  // Import any functions requested via -import
  if (!importFunctions(argv[0], Context, L))
    return 1;

  if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;

  std::error_code EC;
  tool_output_file Out(OutputFilename, EC, sys::fs::F_None);
  if (EC) {
    errs() << EC.message() << '\n';
    return 1;
  }

  if (verifyModule(*Composite, &errs())) {
    errs() << argv[0] << ": error: linked module is broken!\n";
    return 1;
  }

  if (Verbose) errs() << "Writing bitcode...\n";
  if (OutputAssembly) {
    Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder);
  } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
    WriteBitcodeToFile(Composite.get(), Out.os(), PreserveBitcodeUseListOrder);

  // Declare success.
  Out.keep();

  return 0;
}
<|endoftext|>


<commit_before>/***************************************************************************
  file : $URL: file:///C:/develop/SVNrepository/frepple/trunk/contrib/scripting/frepple.i $
  version : $LastChangedRevision$  $LastChangedBy$
  date : $LastChangedDate$
  email : jdetaeye@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 * Copyright (C) 2006 by Johan De Taeye                                    *
 *                                                                         *
 * This library is free software; you can redistribute it and/or modify it *
 * under the terms of the GNU Lesser General Public License as published   *
 * by the Free Software Foundation; either version 2.1 of the License, or  *
 * (at your option) any later version.                                     *
 *                                                                         *
 * 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 "mod_frepple.h"

int getInventoryFilter(request_rec *r)
{
  try
  {

  // Set the response headers: xml data that can be cached by your browser
  ap_set_content_type(r, "application/xml");
  //xxxapr_table_setn(r->headers_out, "Cache-Control", "max-age=10800");
  apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
  if (r->header_only) return OK;

  // Generating the list of locations
  ap_rputs(
   "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
   "<PLAN xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
   "<LOCATIONS>\n", r);
  for (Location::iterator gloc = Location::begin();
    gloc != Location::end(); ++gloc)
    if (!(*gloc)->getHidden())
      ap_rprintf(r, "<LOCATION NAME=\"%s\"/>\n", (*gloc)->getName().c_str());

  // Generating the list of items
  ap_rputs(
   "</LOCATIONS><ITEMS>\n", r);
  for (Item::iterator gitem = Item::begin();
    gitem != Item::end(); ++gitem)
    if (!(*gitem)->getHidden())
     ap_rprintf(r, "<ITEM NAME=\"%s\"/>\n", (*gitem)->getName().c_str());

  // Generating the list of buffers
  ap_rputs(
   "  </ITEMS><BUFFERS>\n", r);
  for (Buffer::iterator gbuf = Buffer::begin();
      gbuf != Buffer::end(); ++gbuf)
    if (!(*gbuf)->getHidden())
    ap_rprintf(r,
      "<BUFFER NAME=\"%s\" LOCATION=\"%s\" ITEM=\"%s\"/>\n",
      (*gbuf)->getName().c_str(),
      (*gbuf)->getLocation() ? (*gbuf)->getLocation()->getName().c_str() : "",
      (*gbuf)->getItem() ? (*gbuf)->getItem()->getName().c_str() : "");
  ap_rputs("</BUFFERS></PLAN>\n", r);

  return OK;
  }
  catch (...) {return HTTP_NOT_FOUND;}
};
<commit_msg>- Apache filter wasn't up to date yet with the new iterators<commit_after>/***************************************************************************
  file : $URL: file:///C:/develop/SVNrepository/frepple/trunk/contrib/scripting/frepple.i $
  version : $LastChangedRevision$  $LastChangedBy$
  date : $LastChangedDate$
  email : jdetaeye@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 * Copyright (C) 2006 by Johan De Taeye                                    *
 *                                                                         *
 * This library is free software; you can redistribute it and/or modify it *
 * under the terms of the GNU Lesser General Public License as published   *
 * by the Free Software Foundation; either version 2.1 of the License, or  *
 * (at your option) any later version.                                     *
 *                                                                         *
 * 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 "mod_frepple.h"

int getInventoryFilter(request_rec *r)
{
  try
  {

  // Set the response headers: xml data that can be cached by your browser
  ap_set_content_type(r, "application/xml");
  //xxxapr_table_setn(r->headers_out, "Cache-Control", "max-age=10800");
  apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
  if (r->header_only) return OK;

  // Generating the list of locations
  ap_rputs(
   "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
   "<PLAN xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
   "<LOCATIONS>\n", r);
  for (Location::iterator gloc = Location::begin();
    gloc != Location::end(); ++gloc)
    if (!gloc->getHidden())
      ap_rprintf(r, "<LOCATION NAME=\"%s\"/>\n", gloc->getName().c_str());

  // Generating the list of items
  ap_rputs(
   "</LOCATIONS><ITEMS>\n", r);
  for (Item::iterator gitem = Item::begin();
    gitem != Item::end(); ++gitem)
    if (!gitem->getHidden())
     ap_rprintf(r, "<ITEM NAME=\"%s\"/>\n", gitem->getName().c_str());

  // Generating the list of buffers
  ap_rputs(
   "  </ITEMS><BUFFERS>\n", r);
  for (Buffer::iterator gbuf = Buffer::begin();
      gbuf != Buffer::end(); ++gbuf)
    if (!gbuf->getHidden())
    ap_rprintf(r,
      "<BUFFER NAME=\"%s\" LOCATION=\"%s\" ITEM=\"%s\"/>\n",
      gbuf->getName().c_str(),
      gbuf->getLocation() ? gbuf->getLocation()->getName().c_str() : "",
      gbuf->getItem() ? gbuf->getItem()->getName().c_str() : "");
  ap_rputs("</BUFFERS></PLAN>\n", r);

  return OK;
  }
  catch (...) {return HTTP_NOT_FOUND;}
};
<|endoftext|>


<commit_before>#include "musicuserlineedit.h"
#include "musicuiobject.h"

#if defined(Q_CC_MSVC)
#   pragma warning(disable:4129)
#elif defined(Q_CC_GNU)
#   pragma GCC diagnostic ignored "-Wswitch"
#endif

MusicUserLineEdit::MusicUserLineEdit(QWidget *parent)
    : QLineEdit(parent)
{
    m_mailContains = false;
    m_strContains = false;
    m_tipsLabel = nullptr;
    m_statusLabel = nullptr;
}

void MusicUserLineEdit::focusInEvent(QFocusEvent *event)
{
    QLineEdit::focusInEvent(event);
    if(m_tipsLabel)
    {
        m_tipsLabel->show();
        m_tipsLabel->setStyleSheet(MusicUIObject::MCustomStyle13);
    }
}

void MusicUserLineEdit::focusOutEvent(QFocusEvent *event)
{
    QLineEdit::focusOutEvent(event);
    checkTheInput();
}

void MusicUserLineEdit::setLabel(LabelType ty, QLabel *t, QLabel *s)
{
    m_tipsLabel = t;
    m_statusLabel = s;
    m_type = ty;
    if(ty == PasswdNew)
    {
        connect(this, SIGNAL(textChanged(QString)), SLOT(checkPwdStrength()));
    }
}

void MusicUserLineEdit::labelCheck(bool check)
{
    if(check)
    {
        if(m_tipsLabel) m_tipsLabel->hide();
        if(m_statusLabel) m_statusLabel->show();
    }
    else
    {
        if(m_statusLabel) m_statusLabel->hide();
        if(m_tipsLabel)
        {
            m_tipsLabel->show();
            m_tipsLabel->setStyleSheet(MusicUIObject::MCustomStyle14);
        }
    }
}

void MusicUserLineEdit::showLabel(int s, int e)
{
    int textLength = text().length();
    labelCheck(m_strContains = (s <= textLength && textLength <= e));
}

void MusicUserLineEdit::showLabel()
{
    QRegExp mailRx("^[0-9a-z][a-z0-9\\._-]{1,}@[a-z0-9-]{1,}[a-z0-9]\\.[a-z\\.]{1,}[a-z]+$");
    labelCheck(m_mailContains = (text().contains(mailRx)));
}

void MusicUserLineEdit::checkTheInput()
{
    switch(m_type)
    {
        case User:
             showLabel(4, 20);
             break;
        case Passwd:
        case PwdConfirm:
             showLabel(6, 16);
             break;
        case Mail:
             showLabel();
             break;
    }
}

void MusicUserLineEdit::checkPwdStrength()
{
    if(text().isEmpty())
    {
        emit checkPwdStrength(-1);
        return;
    }

    bool onlyNum, onlyChar, onlySp;
    onlyNum = text().contains(QRegExp("[0-9]"));
    onlyChar = text().contains(QRegExp("[a-zA-z]"));;
    onlySp = text().contains(QRegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~@#]"));

    if( ( onlyNum && !onlyChar && !onlySp) ||
        (!onlyNum &&  onlyChar && !onlySp) ||
        (!onlyNum && !onlyChar &&  onlySp) ||
        (!onlyNum && !onlyChar && !onlySp) )
    {
        emit checkPwdStrength(0);
    }
    else if( ( onlyNum &&  onlyChar && !onlySp) ||
             ( onlyNum && !onlyChar &&  onlySp) ||
             (!onlyNum &&  onlyChar &&  onlySp) )
    {
        emit checkPwdStrength(1);
    }
    else
    {
        emit checkPwdStrength(2);
    }

}
<commit_msg>update mail regular expression[002316]<commit_after>#include "musicuserlineedit.h"
#include "musicuiobject.h"

#if defined(Q_CC_MSVC)
#   pragma warning(disable:4129)
#elif defined(Q_CC_GNU)
#   pragma GCC diagnostic ignored "-Wswitch"
#endif

MusicUserLineEdit::MusicUserLineEdit(QWidget *parent)
    : QLineEdit(parent)
{
    m_mailContains = false;
    m_strContains = false;
    m_tipsLabel = nullptr;
    m_statusLabel = nullptr;
}

void MusicUserLineEdit::focusInEvent(QFocusEvent *event)
{
    QLineEdit::focusInEvent(event);
    if(m_tipsLabel)
    {
        m_tipsLabel->show();
        m_tipsLabel->setStyleSheet(MusicUIObject::MCustomStyle13);
    }
}

void MusicUserLineEdit::focusOutEvent(QFocusEvent *event)
{
    QLineEdit::focusOutEvent(event);
    checkTheInput();
}

void MusicUserLineEdit::setLabel(LabelType ty, QLabel *t, QLabel *s)
{
    m_tipsLabel = t;
    m_statusLabel = s;
    m_type = ty;
    if(ty == PasswdNew)
    {
        connect(this, SIGNAL(textChanged(QString)), SLOT(checkPwdStrength()));
    }
}

void MusicUserLineEdit::labelCheck(bool check)
{
    if(check)
    {
        if(m_tipsLabel) m_tipsLabel->hide();
        if(m_statusLabel) m_statusLabel->show();
    }
    else
    {
        if(m_statusLabel) m_statusLabel->hide();
        if(m_tipsLabel)
        {
            m_tipsLabel->show();
            m_tipsLabel->setStyleSheet(MusicUIObject::MCustomStyle14);
        }
    }
}

void MusicUserLineEdit::showLabel(int s, int e)
{
    int textLength = text().length();
    labelCheck(m_strContains = (s <= textLength && textLength <= e));
}

void MusicUserLineEdit::showLabel()
{
    QRegExp mailRx("([a-zA-Z0-9][\\w-\\.]*)*[a-z0-9A-Z]@[a-z0-9A-Z][a-z0-9A-Z-]*[a-z0-9A-Z]\\.[a-zA-Z]{2,})");
    labelCheck(m_mailContains = (text().contains(mailRx)));
}

void MusicUserLineEdit::checkTheInput()
{
    switch(m_type)
    {
        case User:
             showLabel(4, 20);
             break;
        case Passwd:
        case PwdConfirm:
             showLabel(6, 16);
             break;
        case Mail:
             showLabel();
             break;
    }
}

void MusicUserLineEdit::checkPwdStrength()
{
    if(text().isEmpty())
    {
        emit checkPwdStrength(-1);
        return;
    }

    bool onlyNum, onlyChar, onlySp;
    onlyNum = text().contains(QRegExp("[0-9]"));
    onlyChar = text().contains(QRegExp("[a-zA-z]"));;
    onlySp = text().contains(QRegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~@#]"));

    if( ( onlyNum && !onlyChar && !onlySp) ||
        (!onlyNum &&  onlyChar && !onlySp) ||
        (!onlyNum && !onlyChar &&  onlySp) ||
        (!onlyNum && !onlyChar && !onlySp) )
    {
        emit checkPwdStrength(0);
    }
    else if( ( onlyNum &&  onlyChar && !onlySp) ||
             ( onlyNum && !onlyChar &&  onlySp) ||
             (!onlyNum &&  onlyChar &&  onlySp) )
    {
        emit checkPwdStrength(1);
    }
    else
    {
        emit checkPwdStrength(2);
    }

}
<|endoftext|>


<commit_before>/*
 * ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013, Numenta, Inc.  Unless you have purchased from
 * Numenta, Inc. a separate commercial license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include <nta/types/BasicType.hpp>
#include <nta/engine/YAMLUtils.hpp>
#include <nta/ntypes/Value.hpp>
#include <nta/ntypes/Collection.hpp>
#include <nta/ntypes/MemStream.hpp>
#include <nta/engine/Spec.hpp>
#include <string.h> // strlen
#include <yaml-cpp/yaml.h>

#include <sstream>

namespace nta
{
namespace YAMLUtils
{

/*
 * These functions are used internally by toValue and toValueMap
 */
static void toScalar(const YAML::Node& node, boost::shared_ptr<Scalar>& s);
static void toArray(const YAML::Node& node, boost::shared_ptr<Array>& a);
static Value toValue(const YAML::Node& node, NTA_BasicType dataType);

static void toScalar(const YAML::Node& node, boost::shared_ptr<Scalar>& s)
{
  NTA_CHECK(node.Type() == YAML::NodeType::Scalar);
  switch(s->getType())
  {
  case NTA_BasicType_Byte:
    // We should have already detected this and gone down the string path
    NTA_THROW << "Internal error: attempting to convert YAML string to scalar of type Byte";
    break;
  case NTA_BasicType_UInt16:
    node >> s->value.uint16;
    break;
  case NTA_BasicType_Int16:
    node >> s->value.int16;
    break;
  case NTA_BasicType_UInt32:
    node >> s->value.uint32;
    break;
  case NTA_BasicType_Int32:
    node >> s->value.int32;
    break;
  case NTA_BasicType_UInt64:
    node >> s->value.uint64;
    break;
  case NTA_BasicType_Int64:
    node >> s->value.int64;
    break;
  case NTA_BasicType_Real32:
    node >> s->value.real32;
    break;
  case NTA_BasicType_Real64:
    node >> s->value.real64;
    break;
  case NTA_BasicType_Handle:
    NTA_THROW << "Attempt to specify a YAML value for a scalar of type Handle";
    break;
  default:
    // should not happen
    std::string val;
    node >> val;
    NTA_THROW << "Unknown data type " << s->getType() << " for yaml node '" << val << "'";
  }
}

static void toArray(const YAML::Node& node, boost::shared_ptr<Array>& a)
{
  NTA_CHECK(node.Type() == YAML::NodeType::Sequence);

  a->allocateBuffer(node.size());
  void* buffer = a->getBuffer();

  for (size_t i = 0; i < node.size(); i++)
  {
    const YAML::Node& item = node[i];
    NTA_CHECK(item.Type() == YAML::NodeType::Scalar);
    switch(a->getType())
    {
    case NTA_BasicType_Byte:
      // We should have already detected this and gone down the string path
      NTA_THROW << "Internal error: attempting to convert YAML string to array of type Byte";
      break;
    case NTA_BasicType_UInt16:
      item.to<UInt16>();
      break;
    case NTA_BasicType_Int16:
      item.to<Int16>();
      break;
    case NTA_BasicType_UInt32:
      item.to<UInt32>();
      break;
    case NTA_BasicType_Int32:
      item.to<Int32>();
      break;
    case NTA_BasicType_UInt64:
      item.to<UInt64>();
      break;
    case NTA_BasicType_Int64:
      item.to<Int64>();
      break;
    case NTA_BasicType_Real32:
      item.to<Real32>();
      break;
    case NTA_BasicType_Real64:
      item.to<Real64>();
      break;
    default:
      // should not happen
      NTA_THROW << "Unknown data type " << a->getType();
    }
  }
}

static Value toValue(const YAML::Node& node, NTA_BasicType dataType)
{
  if (node.Type() == YAML::NodeType::Map || node.Type() == YAML::NodeType::Null)
  {
    NTA_THROW << "YAML string does not not represent a value.";
  }
  if (node.Type() == YAML::NodeType::Scalar)
  {
    if (dataType == NTA_BasicType_Byte)
    {
      // node >> *str;
      std::string val;
      node.Read(val);
      boost::shared_ptr<std::string> str(new std::string(val));
      Value v(str);
      return v;
    } else {
      boost::shared_ptr<Scalar> s(new Scalar(dataType));
      toScalar(node, s);
      Value v(s);
      return v;
    }
  } else {
    // array
    boost::shared_ptr<Array> a(new Array(dataType));
    toArray(node, a);
    Value v(a);
    return v;
  }
}

/*
 * For converting default values specified in nodespec
 */
Value toValue(const std::string& yamlstring, NTA_BasicType dataType)
{
  // IMemStream s(yamlstring, ::strlen(yamlstring));

  // yaml-cpp bug: append a space if it is only one character
  // This is very inefficient, but should be ok since it is
  // just used at construction time for short strings
  std::string paddedstring(yamlstring);
  if (paddedstring.size() < 2)
    paddedstring = paddedstring + " ";
  std::stringstream s(paddedstring);

  // TODO -- return value? exceptions?
  bool success = false;
  YAML::Node doc;
  try
  {
    YAML::Parser parser(s);
    success = parser.GetNextDocument(doc);
    // } catch(YAML::ParserException& e) {
  } catch(...) {
    success = false;
  }
  if (!success)
  {
    std::string ys(paddedstring);
    if (ys.size() > 30)
    {
      ys = ys.substr(0, 30) + "...";
    }
    NTA_THROW << "Unable to parse YAML string '" << ys << "' for a scalar value";
  }
  Value v = toValue(doc, dataType);
  return v;
}

/*
 * For converting param specs for Regions and LinkPolicies
 */
ValueMap toValueMap(const char* yamlstring,
                               Collection<ParameterSpec>& parameters,
                               const std::string & nodeType,
                               const std::string & regionName)
{

  ValueMap vm;

  // yaml-cpp bug: append a space if it is only one character
  // This is very inefficient, but should be ok since it is
  // just used at construction time for short strings
  std::string paddedstring(yamlstring);
  // TODO: strip white space to determine if empty
  bool empty = (paddedstring.size() == 0);

  if (paddedstring.size() < 2)
    paddedstring = paddedstring + " ";
  std::stringstream s(paddedstring);
  // IMemStream s(yamlstring, ::strlen(yamlstring));

  // TODO: utf-8 compatible?
  YAML::Node doc;
  if (!empty)
  {
    YAML::Parser parser(s);
    bool success = parser.GetNextDocument(doc);

    if (!success)
      NTA_THROW << "Unable to find document in YAML string";

    // A ValueMap is specified as a dictionary
    if (doc.Type() != YAML::NodeType::Map)
    {
      std::string ys(yamlstring);
      if (ys.size() > 30)
      {
        ys = ys.substr(0, 30) + "...";
      }
      NTA_THROW << "YAML string '" << ys
                << "' does not not specify a dictionary of key-value pairs. "
                << "Region and Link parameters must be specified at a dictionary";
    }
  }

  // Grab each value out of the YAML dictionary and put into the ValueMap
  // if it is allowed by the nodespec.
  YAML::Iterator i;
  for (i = doc.begin(); i != doc.end(); i++)
  {
    const std::string key = i.first().to<std::string>();
    if (!parameters.contains(key))
    {
      std::stringstream ss;
      for (UInt j = 0; j < parameters.getCount(); j++)
      {
        ss << "   " << parameters.getByIndex(j).first << "\n";
      }

      if (nodeType == std::string(""))
      {
        NTA_THROW << "Unknown parameter '" << key << "'\n"
                  << "Valid parameters are:\n" << ss.str();
      }
      else
      {
        NTA_CHECK(regionName != std::string(""));
        NTA_THROW << "Unknown parameter '" << key << "' for region '"
                  << regionName << "' of type '" << nodeType << "'\n"
                  << "Valid parameters are:\n" << ss.str();
      }
    }
    if (vm.contains(key))
      NTA_THROW << "Parameter '" << key << "' specified more than once in YAML document";
    ParameterSpec spec = parameters.getByName(key);
    try
    {
      Value v = toValue(i.second(), spec.dataType);
      if (v.isScalar() && spec.count != 1)
      {
        throw std::runtime_error("Expected array value but got scalar value");
      }
      if (!v.isScalar() && spec.count == 1)
      {
        throw std::runtime_error("Expected scalar value but got array value");
      }
      vm.add(key, v);
    } catch (std::runtime_error& e) {
      NTA_THROW << "Unable to set parameter '" << key << "'. " << e.what();
    }
  }

  // Populate ValueMap with default values if they were not specified in the YAML dictionary.
  for (size_t i = 0; i < parameters.getCount(); i++)
  {
    std::pair<std::string, ParameterSpec>& item = parameters.getByIndex(i);
    if (!vm.contains(item.first))
    {
      ParameterSpec & ps = item.second;
      if (ps.defaultValue != "")
      {
        // TODO: This check should be uncommented after dropping NuPIC 1.x nodes (which don't comply)
        // if (ps.accessMode != ParameterSpec::CreateAccess)
        // {
        //   NTA_THROW << "Default value for non-create parameter: " << item.first;
        // }

        try {
#ifdef YAMLDEBUG
          NTA_DEBUG << "Adding default value '" << ps.defaultValue
                    << "' to parameter " << item.first
                    << " of type " << BasicType::getName(ps.dataType)
                    << " count " << ps.count;
#endif
          Value v = toValue(ps.defaultValue, ps.dataType);
          vm.add(item.first, v);
        } catch (...) {
          NTA_THROW << "Unable to set default value for item '"
                    << item.first << "' of datatype "
                    << BasicType::getName(ps.dataType)
                    <<" with value '" << ps.defaultValue << "'";
        }
      }
    }
  }

  return vm;
}

} // end of YAMLUtils namespace

} // end of nta namespace

<commit_msg>enable check (was blocked by nupic 1.x Nodes)<commit_after>/*
 * ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013, Numenta, Inc.  Unless you have purchased from
 * Numenta, Inc. a separate commercial license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include <nta/types/BasicType.hpp>
#include <nta/engine/YAMLUtils.hpp>
#include <nta/ntypes/Value.hpp>
#include <nta/ntypes/Collection.hpp>
#include <nta/ntypes/MemStream.hpp>
#include <nta/engine/Spec.hpp>
#include <string.h> // strlen
#include <yaml-cpp/yaml.h>

#include <sstream>

namespace nta
{
namespace YAMLUtils
{

/*
 * These functions are used internally by toValue and toValueMap
 */
static void toScalar(const YAML::Node& node, boost::shared_ptr<Scalar>& s);
static void toArray(const YAML::Node& node, boost::shared_ptr<Array>& a);
static Value toValue(const YAML::Node& node, NTA_BasicType dataType);

static void toScalar(const YAML::Node& node, boost::shared_ptr<Scalar>& s)
{
  NTA_CHECK(node.Type() == YAML::NodeType::Scalar);
  switch(s->getType())
  {
  case NTA_BasicType_Byte:
    // We should have already detected this and gone down the string path
    NTA_THROW << "Internal error: attempting to convert YAML string to scalar of type Byte";
    break;
  case NTA_BasicType_UInt16:
    node >> s->value.uint16;
    break;
  case NTA_BasicType_Int16:
    node >> s->value.int16;
    break;
  case NTA_BasicType_UInt32:
    node >> s->value.uint32;
    break;
  case NTA_BasicType_Int32:
    node >> s->value.int32;
    break;
  case NTA_BasicType_UInt64:
    node >> s->value.uint64;
    break;
  case NTA_BasicType_Int64:
    node >> s->value.int64;
    break;
  case NTA_BasicType_Real32:
    node >> s->value.real32;
    break;
  case NTA_BasicType_Real64:
    node >> s->value.real64;
    break;
  case NTA_BasicType_Handle:
    NTA_THROW << "Attempt to specify a YAML value for a scalar of type Handle";
    break;
  default:
    // should not happen
    std::string val;
    node >> val;
    NTA_THROW << "Unknown data type " << s->getType() << " for yaml node '" << val << "'";
  }
}

static void toArray(const YAML::Node& node, boost::shared_ptr<Array>& a)
{
  NTA_CHECK(node.Type() == YAML::NodeType::Sequence);

  a->allocateBuffer(node.size());
  void* buffer = a->getBuffer();

  for (size_t i = 0; i < node.size(); i++)
  {
    const YAML::Node& item = node[i];
    NTA_CHECK(item.Type() == YAML::NodeType::Scalar);
    switch(a->getType())
    {
    case NTA_BasicType_Byte:
      // We should have already detected this and gone down the string path
      NTA_THROW << "Internal error: attempting to convert YAML string to array of type Byte";
      break;
    case NTA_BasicType_UInt16:
      item.to<UInt16>();
      break;
    case NTA_BasicType_Int16:
      item.to<Int16>();
      break;
    case NTA_BasicType_UInt32:
      item.to<UInt32>();
      break;
    case NTA_BasicType_Int32:
      item.to<Int32>();
      break;
    case NTA_BasicType_UInt64:
      item.to<UInt64>();
      break;
    case NTA_BasicType_Int64:
      item.to<Int64>();
      break;
    case NTA_BasicType_Real32:
      item.to<Real32>();
      break;
    case NTA_BasicType_Real64:
      item.to<Real64>();
      break;
    default:
      // should not happen
      NTA_THROW << "Unknown data type " << a->getType();
    }
  }
}

static Value toValue(const YAML::Node& node, NTA_BasicType dataType)
{
  if (node.Type() == YAML::NodeType::Map || node.Type() == YAML::NodeType::Null)
  {
    NTA_THROW << "YAML string does not not represent a value.";
  }
  if (node.Type() == YAML::NodeType::Scalar)
  {
    if (dataType == NTA_BasicType_Byte)
    {
      // node >> *str;
      std::string val;
      node.Read(val);
      boost::shared_ptr<std::string> str(new std::string(val));
      Value v(str);
      return v;
    } else {
      boost::shared_ptr<Scalar> s(new Scalar(dataType));
      toScalar(node, s);
      Value v(s);
      return v;
    }
  } else {
    // array
    boost::shared_ptr<Array> a(new Array(dataType));
    toArray(node, a);
    Value v(a);
    return v;
  }
}

/*
 * For converting default values specified in nodespec
 */
Value toValue(const std::string& yamlstring, NTA_BasicType dataType)
{
  // IMemStream s(yamlstring, ::strlen(yamlstring));

  // yaml-cpp bug: append a space if it is only one character
  // This is very inefficient, but should be ok since it is
  // just used at construction time for short strings
  std::string paddedstring(yamlstring);
  if (paddedstring.size() < 2)
    paddedstring = paddedstring + " ";
  std::stringstream s(paddedstring);

  // TODO -- return value? exceptions?
  bool success = false;
  YAML::Node doc;
  try
  {
    YAML::Parser parser(s);
    success = parser.GetNextDocument(doc);
    // } catch(YAML::ParserException& e) {
  } catch(...) {
    success = false;
  }
  if (!success)
  {
    std::string ys(paddedstring);
    if (ys.size() > 30)
    {
      ys = ys.substr(0, 30) + "...";
    }
    NTA_THROW << "Unable to parse YAML string '" << ys << "' for a scalar value";
  }
  Value v = toValue(doc, dataType);
  return v;
}

/*
 * For converting param specs for Regions and LinkPolicies
 */
ValueMap toValueMap(const char* yamlstring,
                               Collection<ParameterSpec>& parameters,
                               const std::string & nodeType,
                               const std::string & regionName)
{

  ValueMap vm;

  // yaml-cpp bug: append a space if it is only one character
  // This is very inefficient, but should be ok since it is
  // just used at construction time for short strings
  std::string paddedstring(yamlstring);
  // TODO: strip white space to determine if empty
  bool empty = (paddedstring.size() == 0);

  if (paddedstring.size() < 2)
    paddedstring = paddedstring + " ";
  std::stringstream s(paddedstring);
  // IMemStream s(yamlstring, ::strlen(yamlstring));

  // TODO: utf-8 compatible?
  YAML::Node doc;
  if (!empty)
  {
    YAML::Parser parser(s);
    bool success = parser.GetNextDocument(doc);

    if (!success)
      NTA_THROW << "Unable to find document in YAML string";

    // A ValueMap is specified as a dictionary
    if (doc.Type() != YAML::NodeType::Map)
    {
      std::string ys(yamlstring);
      if (ys.size() > 30)
      {
        ys = ys.substr(0, 30) + "...";
      }
      NTA_THROW << "YAML string '" << ys
                << "' does not not specify a dictionary of key-value pairs. "
                << "Region and Link parameters must be specified at a dictionary";
    }
  }

  // Grab each value out of the YAML dictionary and put into the ValueMap
  // if it is allowed by the nodespec.
  YAML::Iterator i;
  for (i = doc.begin(); i != doc.end(); i++)
  {
    const std::string key = i.first().to<std::string>();
    if (!parameters.contains(key))
    {
      std::stringstream ss;
      for (UInt j = 0; j < parameters.getCount(); j++)
      {
        ss << "   " << parameters.getByIndex(j).first << "\n";
      }

      if (nodeType == std::string(""))
      {
        NTA_THROW << "Unknown parameter '" << key << "'\n"
                  << "Valid parameters are:\n" << ss.str();
      }
      else
      {
        NTA_CHECK(regionName != std::string(""));
        NTA_THROW << "Unknown parameter '" << key << "' for region '"
                  << regionName << "' of type '" << nodeType << "'\n"
                  << "Valid parameters are:\n" << ss.str();
      }
    }
    if (vm.contains(key))
      NTA_THROW << "Parameter '" << key << "' specified more than once in YAML document";
    ParameterSpec spec = parameters.getByName(key);
    try
    {
      Value v = toValue(i.second(), spec.dataType);
      if (v.isScalar() && spec.count != 1)
      {
        throw std::runtime_error("Expected array value but got scalar value");
      }
      if (!v.isScalar() && spec.count == 1)
      {
        throw std::runtime_error("Expected scalar value but got array value");
      }
      vm.add(key, v);
    } catch (std::runtime_error& e) {
      NTA_THROW << "Unable to set parameter '" << key << "'. " << e.what();
    }
  }

  // Populate ValueMap with default values if they were not specified in the YAML dictionary.
  for (size_t i = 0; i < parameters.getCount(); i++)
  {
    std::pair<std::string, ParameterSpec>& item = parameters.getByIndex(i);
    if (!vm.contains(item.first))
    {
      ParameterSpec & ps = item.second;
      if (ps.defaultValue != "")
      {
        if (ps.accessMode != ParameterSpec::CreateAccess)
        {
          NTA_THROW << "Default value for non-create parameter: " << item.first;
        }

        try {
#ifdef YAMLDEBUG
          NTA_DEBUG << "Adding default value '" << ps.defaultValue
                    << "' to parameter " << item.first
                    << " of type " << BasicType::getName(ps.dataType)
                    << " count " << ps.count;
#endif
          Value v = toValue(ps.defaultValue, ps.dataType);
          vm.add(item.first, v);
        } catch (...) {
          NTA_THROW << "Unable to set default value for item '"
                    << item.first << "' of datatype "
                    << BasicType::getName(ps.dataType)
                    <<" with value '" << ps.defaultValue << "'";
        }
      }
    }
  }

  return vm;
}

} // end of YAMLUtils namespace

} // end of nta namespace

<|endoftext|>


<commit_before>// Copyright (C) 2014 - 2015 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * CQUndoHistoryDialog.cpp
 *
 *  Created on: 10 Dec 2014
 *      Author: dada
 */

#include <QTableView>
#include <QItemDelegate>
#include <QStandardItemModel>
#include <QUndoStack>

#include "qtUtilities.h"

#include "copasi/undoFramework/CCopasiUndoCommand.h"
#include "copasi/undoFramework/CreateNewCompartmentCommand.h"
#include "copasi/undoFramework/CreateNewEventCommand.h"
#include "copasi/undoFramework/UndoData.h"
#include "copasi/undoFramework/UndoCompartmentData.h"
#include "copasi/undoFramework/UndoEventData.h"
#include "CQUndoHistoryDialog.h"

/*
 *  Constructs a CQUndoHistoryDialog as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  true to construct a modal dialog.
 */
CQUndoHistoryDialog::CQUndoHistoryDialog(QWidget* parent, QUndoStack *undoStack, const char* name, bool modal, Qt::WindowFlags fl)
  : QDialog(parent, fl)
{
  setObjectName(QString::fromUtf8(name));
  setModal(modal);
  setupUi(this);
  connect(closeButton, SIGNAL(clicked()), this, SLOT(closeButtonClicked()));
  connect(undoButton, SIGNAL(clicked()), this, SLOT(undoButtonClicked()));

  mpUndoStack = undoStack;
  mNCol = 6; //total number of UNDO History column
// int count = mpUndoStack->count(); //number of command in unod stack

  // Create a new model
  // QStandardItemModel(int rows, int columns, QObject * parent = parent)
  mpModel = new QStandardItemModel(mpUndoStack->count(), mNCol, parent);

  // attach the model to the view
  mpUndoHistoryView->setModel(mpModel);

  //generate UNDO History data from undostack
  generateUndoData(mpUndoStack, mpUndoStack->count(), mNCol);
}

CQUndoHistoryDialog::~CQUndoHistoryDialog()
{
  pdelete(mpModel);
  // no need to delete child widgets, Qt does it all
}

void CQUndoHistoryDialog::closeButtonClicked()
{
  close();
}

void CQUndoHistoryDialog::undoButtonClicked()
{
  mSelectedIndex = 2; //TODO just a test
  mpUndoStack->setIndex(mSelectedIndex);
  //generate new UNDO History data from undostack
  generateUndoData(mpUndoStack, mpUndoStack->count(), mNCol);
}

void CQUndoHistoryDialog::generateUndoData(QUndoStack *undoStack, int commandCount, int nCol)
{
  // set the table header data
  for (int col = 0; col < nCol; col++)
    {
      switch (col)
        {
          case 0:
            mpModel->setHeaderData(0, Qt::Horizontal, QString("Entity Type"));
            break;

          case 1:
            mpModel->setHeaderData(1, Qt::Horizontal, QString("Name"));
            break;

          case 2:
            mpModel->setHeaderData(2, Qt::Horizontal, QString("Action"));
            break;

          case 3:
            mpModel->setHeaderData(3, Qt::Horizontal, QString("Property"));
            break;

          case 4:
            mpModel->setHeaderData(4, Qt::Horizontal, QString("New Value"));
            break;

          case 5:
            mpModel->setHeaderData(5, Qt::Horizontal, QString("Old Value"));
            break;
        }
    }

  for (int row = 0; row < commandCount; row++)
    {
      const QUndoCommand *cmd = undoStack->command(row);
      const CCopasiUndoCommand *cCommand = dynamic_cast<const CCopasiUndoCommand*>(cmd);
      // const UndoData *undoData =  cCommand->getUndoData();

      for (int col = 0; col < 6; col++)
        {
          QModelIndex index = mpModel->index(row, col, QModelIndex());

          switch (col)
            {
              case 0:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getEntityType()))));
                break;

              case 1:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getName()))));
                break;

              case 2:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getAction()))));
                break;

              case 3:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getProperty()))));
                break;

              case 4:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getNewValue()))));
                break;

              case 5:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getOldValue()))));
                break;
            }
        }
    }
}
<commit_msg>Add row selection capability to Undo History table view.<commit_after>// Copyright (C) 2014 - 2015 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * CQUndoHistoryDialog.cpp
 *
 *  Created on: 10 Dec 2014
 *      Author: dada
 */

#include <QTableView>
#include <QItemDelegate>
#include <QStandardItemModel>
#include <QUndoStack>

#include "CQMessageBox.h"
#include "qtUtilities.h"

#include "copasi/undoFramework/CCopasiUndoCommand.h"
#include "copasi/undoFramework/CreateNewCompartmentCommand.h"
#include "copasi/undoFramework/CreateNewEventCommand.h"
#include "copasi/undoFramework/UndoData.h"
#include "copasi/undoFramework/UndoCompartmentData.h"
#include "copasi/undoFramework/UndoEventData.h"
#include "CQUndoHistoryDialog.h"

/*
 *  Constructs a CQUndoHistoryDialog as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  true to construct a modal dialog.
 */
CQUndoHistoryDialog::CQUndoHistoryDialog(QWidget* parent, QUndoStack *undoStack, const char* name, bool modal, Qt::WindowFlags fl)
  : QDialog(parent, fl)
{
  setObjectName(QString::fromUtf8(name));
  setModal(modal);
  setupUi(this);
  connect(closeButton, SIGNAL(clicked()), this, SLOT(closeButtonClicked()));
  connect(undoButton, SIGNAL(clicked()), this, SLOT(undoButtonClicked()));

  mpUndoStack = undoStack;
  mNCol = 6; //total number of UNDO History column
  mSelectedIndex = 0;
// int count = mpUndoStack->count(); //number of command in unod stack

  // Create a new model
  // QStandardItemModel(int rows, int columns, QObject * parent = parent)
  mpModel = new QStandardItemModel(mpUndoStack->count(), mNCol, parent);

  // attach the model to the view
  mpUndoHistoryView->setModel(mpModel);

  //generate UNDO History data from undostack
  generateUndoData(mpUndoStack, mpUndoStack->count(), mNCol);
}

CQUndoHistoryDialog::~CQUndoHistoryDialog()
{
  pdelete(mpModel);
  // no need to delete child widgets, Qt does it all
}

void CQUndoHistoryDialog::closeButtonClicked()
{
  close();
}

void CQUndoHistoryDialog::undoButtonClicked()
{
  //find the selected row
  const QItemSelectionModel * pSelectionModel = mpUndoHistoryView->selectionModel();
  size_t i, imax = mpModel->rowCount();
  bool isRowSelected = false;

  for (i = 0; i < imax; i++)
    {
      if (pSelectionModel->isRowSelected((int) i, QModelIndex()))
        {
          mSelectedIndex = i;
          isRowSelected = true;
        }
    }

  if (isRowSelected)
    {
      QString msg;
      msg = "All actions up to the selected row will be undone!";

      QMessageBox::StandardButton choice = CQMessageBox::question(NULL, QString("Undo Actions"), msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);

      if (choice == QMessageBox::Ok)
        {
          mpUndoStack->setIndex(mSelectedIndex);
          close();
          //generate new UNDO History data from undostack
          //  generateUndoData(mpUndoStack, mpUndoStack->count(), mNCol);
        }
    }
}

void CQUndoHistoryDialog::generateUndoData(QUndoStack *undoStack, int commandCount, int nCol)
{
  // set the table header data
  for (int col = 0; col < nCol; col++)
    {
      switch (col)
        {
          case 0:
            mpModel->setHeaderData(0, Qt::Horizontal, QString("Entity Type"));
            break;

          case 1:
            mpModel->setHeaderData(1, Qt::Horizontal, QString("Name"));
            break;

          case 2:
            mpModel->setHeaderData(2, Qt::Horizontal, QString("Action"));
            break;

          case 3:
            mpModel->setHeaderData(3, Qt::Horizontal, QString("Property"));
            break;

          case 4:
            mpModel->setHeaderData(4, Qt::Horizontal, QString("New Value"));
            break;

          case 5:
            mpModel->setHeaderData(5, Qt::Horizontal, QString("Old Value"));
            break;
        }
    }

  for (int row = 0; row < commandCount; row++)
    {
      const QUndoCommand *cmd = undoStack->command(row);
      const CCopasiUndoCommand *cCommand = dynamic_cast<const CCopasiUndoCommand*>(cmd);
      // const UndoData *undoData =  cCommand->getUndoData();

      for (int col = 0; col < 6; col++)
        {
          QModelIndex index = mpModel->index(row, col, QModelIndex());

          switch (col)
            {
              case 0:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getEntityType()))));
                break;

              case 1:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getName()))));
                break;

              case 2:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getAction()))));
                break;

              case 3:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getProperty()))));
                break;

              case 4:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getNewValue()))));
                break;

              case 5:
                mpModel->setData(index, QVariant(QString(FROM_UTF8(cCommand->getOldValue()))));
                break;
            }
        }
    }
}
<|endoftext|>