<commit_before>/*******************************************************************************
 * Copyright (c) 2017 Nicola Del Gobbo
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the license at http://www.apache.org/licenses/LICENSE-2.0
 *
 * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
 * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
 * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
 * MERCHANTABLITY OR NON-INFRINGEMENT.
 *
 * See the Apache Version 2.0 License for specific language governing
 * permissions and limitations under the License.
 *
 * Contributors - initial API implementation:
 * Nicola Del Gobbo <nicoladelgobbo@gmail.com>
 * Mauro Doganieri <mauro.doganieri@gmail.com>
 ******************************************************************************/

#include "ghostscript4js.h"

/*class GhostscriptWorker : public AsyncWorker {
    public:
        GhostscriptWorker(Callback *callback, string RAWcmd)
            : AsyncWorker(callback), RAWcmd(RAWcmd), res(0) {}
        ~GhostscriptWorker() {}

        void Execute() {
            res = 0;
            vector<string> explodedCmd;
            istringstream iss(RAWcmd);
            for(string RAWcmd; iss >> RAWcmd;)
                explodedCmd.push_back(RAWcmd);
            void *minst;
            int code, exit_code;
            int gsargc = static_cast<int>(explodedCmd.size());
            char ** gsargv = new char*[gsargc];
            for(int i = 0; i < gsargc; i++) {
                gsargv[i] = (char*)explodedCmd[i].c_str();
            }
            code = gsapi_new_instance(&minst, NULL);
            if (code < 0) {
                msg << "Sorry error happened creating Ghostscript instance. Error code: " << code;
                res = 1;
            } else {
                gsapi_set_stdio(minst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
                code = gsapi_set_arg_encoding(minst, GS_ARG_ENCODING_UTF8);
                if (code == 0)
                    code = gsapi_init_with_args(minst, gsargc, gsargv);
                exit_code = gsapi_exit(minst);
                if ((code == 0) || (code == gs_error_Quit))
                    code = exit_code;
                gsapi_delete_instance(minst);
                if ((code == 0) || (code == gs_error_Quit)) {
                    res = 0;
                } else {
                    msg << "Sorry error happened executing Ghostscript command. Error code: " << code;
                    res = 1;
                }
            }
            delete[] gsargv;
        }

        void HandleOKCallback() {
            Nan::HandleScope();
            Local<Value> argv[1];
            if (res == 0) {
                argv[0] = Null();
            } else {
                argv[0] = Error(Nan::New<String>(msg.str()).ToLocalChecked());
            }
            callback->Call(1, argv);
        }

        private:
            string RAWcmd;
            int res;
            stringstream msg;
};*/

NAN_METHOD(Version)
{
    Nan::HandleScope();
    Local<Object> obj  = Nan::New<Object>();
    gsapi_revision_t r;
    int res = gsapi_revision(&r, sizeof(r));
    if ( res == 0) {
        obj->Set(Nan::New<String>("product").ToLocalChecked(), Nan::New<String>(r.product).ToLocalChecked());
        obj->Set(Nan::New<String>("copyright").ToLocalChecked(), Nan::New<String>(r.copyright).ToLocalChecked());
        obj->Set(Nan::New<String>("revision").ToLocalChecked(), Nan::New<Number>(r.revision));
        obj->Set(Nan::New<String>("revisiondate").ToLocalChecked(), Nan::New<Number>(r.revisiondate));
    } else {
        std::stringstream msg;
        msg << "Sorry error happened retrieving Ghostscript version info. Error code: " << res;
        return Nan::ThrowError(Nan::New<String>(msg.str()).ToLocalChecked());
    }
    info.GetReturnValue().Set(obj);
}

NAN_METHOD(Execute)
{
    Callback *callback = new Callback(info[1].As<Function>());
    Local<String> JScmd = Local<String>::Cast(info[0]);
    string RAWcmd = *String::Utf8Value(JScmd);
    //AsyncQueueWorker(new GhostscriptWorker(callback, RAWcmd));
}

NAN_METHOD(ExecuteSync)
{
    Nan::HandleScope();
    /*if (info.Length() < 1) {
        return Nan::ThrowError("Sorry executeSync() method requires 1 argument that represent the Ghostscript command.");
    }
    if (!info[0]->IsString()) {
        return Nan::ThrowError("Sorry executeSync() method's argument should be a string.");
    }
    Local<String> JScmd = Local<String>::Cast(info[0]);
    string RAWcmd = *String::Utf8Value(JScmd);
    vector<string> explodedCmd;
    istringstream iss(RAWcmd);
    for(string RAWcmd; iss >> RAWcmd;)
        explodedCmd.push_back(RAWcmd);
    void *minst;
    int code, exit_code;
    int gsargc = static_cast<int>(explodedCmd.size());
    char ** gsargv = new char*[gsargc];
    for(int i = 0; i < gsargc; i++) {
        gsargv[i] = (char*)explodedCmd[i].c_str();
    }
    code = gsapi_new_instance(&minst, NULL);
    if (code < 0) {
        delete[] gsargv;
        stringstream msg;
        msg << "Sorry error happened creating Ghostscript instance. Error code: " << code;
        return Nan::ThrowError(Nan::New<String>(msg.str()).ToLocalChecked());
    }
    gsapi_set_stdio(minst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
    code = gsapi_set_arg_encoding(minst, GS_ARG_ENCODING_UTF8);
    if (code == 0)
        code = gsapi_init_with_args(minst, gsargc, gsargv);
    exit_code = gsapi_exit(minst);
    if ((code == 0) || (code == gs_error_Quit))
	code = exit_code;
    gsapi_delete_instance(minst);
    if ((code == 0) || (code == gs_error_Quit)) {
        delete[] gsargv;
        return;
    } else {
        delete[] gsargv;
        stringstream msg;
        msg << "Sorry error happened executing Ghostscript command. Error code: " << code;
        return Nan::ThrowError(Nan::New<String>(msg.str()).ToLocalChecked());
    }*/
}

//////////////////////////// INIT & CONFIG MODULE //////////////////////////////

void Init(Local<Object> exports)
{
    exports->Set(Nan::New("version").ToLocalChecked(),
                 Nan::New<FunctionTemplate>(Version)->GetFunction());

    exports->Set(Nan::New("execute").ToLocalChecked(),
                 Nan::New<FunctionTemplate>(Execute)->GetFunction());

    exports->Set(Nan::New("executeSync").ToLocalChecked(),
                 Nan::New<FunctionTemplate>(ExecuteSync)->GetFunction());
}

NODE_MODULE(ghostscript4js, Init)

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Todo in refactor<commit_after>/*******************************************************************************
 * Copyright (c) 2017 Nicola Del Gobbo
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the license at http://www.apache.org/licenses/LICENSE-2.0
 *
 * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
 * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
 * IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
 * MERCHANTABLITY OR NON-INFRINGEMENT.
 *
 * See the Apache Version 2.0 License for specific language governing
 * permissions and limitations under the License.
 *
 * Contributors - initial API implementation:
 * Nicola Del Gobbo <nicoladelgobbo@gmail.com>
 * Mauro Doganieri <mauro.doganieri@gmail.com>
 ******************************************************************************/

#include "ghostscript4js.h"

//TODO create new Singleton class that handle the request
// count the works to do and if there are no work destroy the object

/*class GhostscriptWorker : public AsyncWorker {
    public:
        GhostscriptWorker(Callback *callback, string RAWcmd)
            : AsyncWorker(callback), RAWcmd(RAWcmd), res(0) {}
        ~GhostscriptWorker() {}

        void Execute() {
            res = 0;
            vector<string> explodedCmd;
            istringstream iss(RAWcmd);
            for(string RAWcmd; iss >> RAWcmd;)
                explodedCmd.push_back(RAWcmd);
            void *minst;
            int code, exit_code;
            int gsargc = static_cast<int>(explodedCmd.size());
            char ** gsargv = new char*[gsargc];
            for(int i = 0; i < gsargc; i++) {
                gsargv[i] = (char*)explodedCmd[i].c_str();
            }
            code = gsapi_new_instance(&minst, NULL);
            if (code < 0) {
                msg << "Sorry error happened creating Ghostscript instance. Error code: " << code;
                res = 1;
            } else {
                gsapi_set_stdio(minst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
                code = gsapi_set_arg_encoding(minst, GS_ARG_ENCODING_UTF8);
                if (code == 0)
                    code = gsapi_init_with_args(minst, gsargc, gsargv);
                exit_code = gsapi_exit(minst);
                if ((code == 0) || (code == gs_error_Quit))
                    code = exit_code;
                gsapi_delete_instance(minst);
                if ((code == 0) || (code == gs_error_Quit)) {
                    res = 0;
                } else {
                    msg << "Sorry error happened executing Ghostscript command. Error code: " << code;
                    res = 1;
                }
            }
            delete[] gsargv;
        }

        void HandleOKCallback() {
            Nan::HandleScope();
            Local<Value> argv[1];
            if (res == 0) {
                argv[0] = Null();
            } else {
                argv[0] = Error(Nan::New<String>(msg.str()).ToLocalChecked());
            }
            callback->Call(1, argv);
        }

        private:
            string RAWcmd;
            int res;
            stringstream msg;
};*/

NAN_METHOD(Version)
{
    Nan::HandleScope();
    Local<Object> obj  = Nan::New<Object>();
    gsapi_revision_t r;
    int res = gsapi_revision(&r, sizeof(r));
    if ( res == 0) {
        obj->Set(Nan::New<String>("product").ToLocalChecked(), Nan::New<String>(r.product).ToLocalChecked());
        obj->Set(Nan::New<String>("copyright").ToLocalChecked(), Nan::New<String>(r.copyright).ToLocalChecked());
        obj->Set(Nan::New<String>("revision").ToLocalChecked(), Nan::New<Number>(r.revision));
        obj->Set(Nan::New<String>("revisiondate").ToLocalChecked(), Nan::New<Number>(r.revisiondate));
    } else {
        std::stringstream msg;
        msg << "Sorry error happened retrieving Ghostscript version info. Error code: " << res;
        return Nan::ThrowError(Nan::New<String>(msg.str()).ToLocalChecked());
    }
    info.GetReturnValue().Set(obj);
}

NAN_METHOD(Execute)
{
    Callback *callback = new Callback(info[1].As<Function>());
    Local<String> JScmd = Local<String>::Cast(info[0]);
    string RAWcmd = *String::Utf8Value(JScmd);
    //AsyncQueueWorker(new GhostscriptWorker(callback, RAWcmd));
}

NAN_METHOD(ExecuteSync)
{
    Nan::HandleScope();
    /*if (info.Length() < 1) {
        return Nan::ThrowError("Sorry executeSync() method requires 1 argument that represent the Ghostscript command.");
    }
    if (!info[0]->IsString()) {
        return Nan::ThrowError("Sorry executeSync() method's argument should be a string.");
    }
    Local<String> JScmd = Local<String>::Cast(info[0]);
    string RAWcmd = *String::Utf8Value(JScmd);
    vector<string> explodedCmd;
    istringstream iss(RAWcmd);
    for(string RAWcmd; iss >> RAWcmd;)
        explodedCmd.push_back(RAWcmd);
    void *minst;
    int code, exit_code;
    int gsargc = static_cast<int>(explodedCmd.size());
    char ** gsargv = new char*[gsargc];
    for(int i = 0; i < gsargc; i++) {
        gsargv[i] = (char*)explodedCmd[i].c_str();
    }
    code = gsapi_new_instance(&minst, NULL);
    if (code < 0) {
        delete[] gsargv;
        stringstream msg;
        msg << "Sorry error happened creating Ghostscript instance. Error code: " << code;
        return Nan::ThrowError(Nan::New<String>(msg.str()).ToLocalChecked());
    }
    gsapi_set_stdio(minst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
    code = gsapi_set_arg_encoding(minst, GS_ARG_ENCODING_UTF8);
    if (code == 0)
        code = gsapi_init_with_args(minst, gsargc, gsargv);
    exit_code = gsapi_exit(minst);
    if ((code == 0) || (code == gs_error_Quit))
	code = exit_code;
    gsapi_delete_instance(minst);
    if ((code == 0) || (code == gs_error_Quit)) {
        delete[] gsargv;
        return;
    } else {
        delete[] gsargv;
        stringstream msg;
        msg << "Sorry error happened executing Ghostscript command. Error code: " << code;
        return Nan::ThrowError(Nan::New<String>(msg.str()).ToLocalChecked());
    }*/
}

//////////////////////////// INIT & CONFIG MODULE //////////////////////////////

void Init(Local<Object> exports)
{
    exports->Set(Nan::New("version").ToLocalChecked(),
                 Nan::New<FunctionTemplate>(Version)->GetFunction());

    exports->Set(Nan::New("execute").ToLocalChecked(),
                 Nan::New<FunctionTemplate>(Execute)->GetFunction());

    exports->Set(Nan::New("executeSync").ToLocalChecked(),
                 Nan::New<FunctionTemplate>(ExecuteSync)->GetFunction());
}

NODE_MODULE(ghostscript4js, Init)

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 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_ASYNC_PARALLEL_HPP
#define LIBBITCOIN_ASYNC_PARALLEL_HPP

#include <atomic>
#include <cstddef>
#include <memory>
#include <system_error>
#include <bitcoin/bitcoin/utility/assert.hpp>

namespace libbitcoin {

/**
 * async_parallel(completion_handler, clearance_count)
 *
 * Returns a callback that will stop when:
 *
 * 1. An error is passed as the first argument.
 * 2. It has been called clearance_count number of times.
 *
 * This is useful when we have a piece of code that forks into several
 * asynchronous code paths. This utility ensures that all code paths
 * are completed before calling the completion_handler.
 *
 *   auto complete = [](std::error_code ec, std::string s) { ... };
 *   auto cb = async_parallel(complete, 3);
 *   cb(std::error_code, "hello");
 *   // Calling cb(error::service_stopped, "") here will
 *   // call complete(error::service_stopped, "")
 *   cb(std::error_code, "world");
 *   // Calls complete(std::error_code, "final")
 *   cb(std::error_code, "final");
 */

typedef std::atomic<size_t> atomic_counter;
typedef std::shared_ptr<atomic_counter> atomic_counter_ptr;

template <typename Handler>
struct async_parallel_dispatch
{
    Handler handler;
    size_t clearance_count;
    atomic_counter_ptr counter;

    template <typename... Args>
    void operator()(const std::error_code& code, Args&&... args)
    {
        BITCOIN_ASSERT(*counter <= clearance_count);
        if (*counter == clearance_count)
            return;

        if (code)
        {
            // Stop because of failure.
            *counter = clearance_count;
            handler(code, std::forward<Args>(args)...);
        }
        else if (++(*counter) == clearance_count)
        {
            // Finished executing multiple async paths.
            handler(code, std::forward<Args>(args)...);
        }
    }
};

template <typename Handler>
async_parallel_dispatch<typename std::decay<Handler>::type>
async_parallel(Handler&& handler, size_t clearance_count)
{
    return
    {
        handler,
        clearance_count,
        std::make_shared<atomic_counter>(0)
    };
}

} // libbitcoin

#endif

<commit_msg>Comments.<commit_after>/**
 * Copyright (c) 2011-2015 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_ASYNC_PARALLEL_HPP
#define LIBBITCOIN_ASYNC_PARALLEL_HPP

#include <atomic>
#include <cstddef>
#include <memory>
#include <system_error>
#include <bitcoin/bitcoin/utility/assert.hpp>

namespace libbitcoin {

/**
 * async_parallel(completion_handler, clearance_count)
 *
 * Returns a callback that will stop when:
 *
 * 1. An error is passed as the first argument.
 * 2. It has been called clearance_count number of times.
 *
 * This is useful when we have a piece of code that forks into several
 * asynchronous code paths. This utility ensures that all code paths
 * are completed before calling the completion_handler.
 *
 *   auto complete = [](std::error_code ec, std::string s) { ... };
 *   auto cb = async_parallel(complete, 3);
 *   cb(std::error_code, "hello");
 *   // Calling cb(error::operation_failed, "") here will
 *   // call complete(error::operation_failed, "")
 *   cb(std::error_code, "world");
 *   // Calls complete(std::error_code, "final")
 *   cb(std::error_code, "final");
 */

typedef std::atomic<size_t> atomic_counter;
typedef std::shared_ptr<atomic_counter> atomic_counter_ptr;

template <typename Handler>
struct async_parallel_dispatch
{
    Handler handler;
    size_t clearance_count;
    atomic_counter_ptr counter;

    template <typename... Args>
    void operator()(const std::error_code& code, Args&&... args)
    {
        BITCOIN_ASSERT(*counter <= clearance_count);
        if (*counter == clearance_count)
            return;

        if (code)
        {
            // Stop because of failure.
            *counter = clearance_count;
            handler(code, std::forward<Args>(args)...);
        }
        else if (++(*counter) == clearance_count)
        {
            // Finished executing multiple async paths.
            handler(code, std::forward<Args>(args)...);
        }
    }
};

template <typename Handler>
async_parallel_dispatch<typename std::decay<Handler>::type>
async_parallel(Handler&& handler, size_t clearance_count)
{
    return
    {
        handler,
        clearance_count,
        std::make_shared<atomic_counter>(0)
    };
}

} // libbitcoin

#endif

<|endoftext|>


<commit_before>#include "physical.h"

#if defined(linux) || defined(LINUX)
#include <sys/ioctl.h>
#elif defined(__APPLE__)
#include <ifaddrs.h>
#include <net/if_dl.h>
#else
#error no definition for GetMacAddress() on this platform!
#endif

namespace nc {
namespace htsim {

#if defined(linux) || defined(LINUX)
static bool GetMacAddress(char* mac_addr, const char* if_name) {
  struct ifreq ifinfo;
  strcpy(ifinfo.ifr_name, if_name);
  int sd = socket(AF_INET, SOCK_DGRAM, 0);
  int result = ioctl(sd, SIOCGIFHWADDR, &ifinfo);
  close(sd);

  if ((result == 0) && (ifinfo.ifr_hwaddr.sa_family == 1)) {
    memcpy(mac_addr, ifinfo.ifr_hwaddr.sa_data, IFHWADDRLEN);
    return true;
  } else {
    return false;
  }
}
#elif defined(__APPLE__)
static bool GetMacAddress(u_char* mac_addr, const char* if_name) {
  ifaddrs* iflist;
  bool found = false;
  if (getifaddrs(&iflist) == 0) {
    for (ifaddrs* cur = iflist; cur; cur = cur->ifa_next) {
      if ((cur->ifa_addr->sa_family == AF_LINK) &&
          (strcmp(cur->ifa_name, if_name) == 0) && cur->ifa_addr) {
        sockaddr_dl* sdl = (sockaddr_dl*)cur->ifa_addr;
        memcpy(mac_addr, LLADDR(sdl), sdl->sdl_alen);
        found = true;
        break;
      }
    }

    freeifaddrs(iflist);
  }
  return found;
}
#else
#error no definition for GetMacAddress() on this platform!
#endif

static unsigned short csum(unsigned short* buf, int nwords) {
  unsigned long sum;
  for (sum = 0; nwords > 0; nwords--) sum += *buf++;
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  return (unsigned short)(~sum);
}

PhysicalInterfacePacketHandler::PhysicalInterfacePacketHandler(
    const std::string& iface_name) {
  char pcap_errbuf[PCAP_ERRBUF_SIZE];
  pcap_errbuf[0] = '\0';
  pcap_ = pcap_open_live(iface_name.c_str(), 96, 0, 0, pcap_errbuf);
  CHECK(pcap_errbuf[0] == '\0');
  CHECK(pcap_ != nullptr);

  int link_type = pcap_datalink(pcap_);
  if (link_type == DLT_EN10MB) {
    // Ethernet interface. Regular ethernet header.
    pcap::EtherHeader* eh = reinterpret_cast<pcap::EtherHeader*>(sendbuf_);
    memset(eh, 0, sizeof(pcap::EtherHeader));
    CHECK(GetMacAddress(eh->ether_shost, iface_name.c_str()));
    eh->ether_type = htons(0x0800);
    ll_header_size_ = sizeof(pcap::EtherHeader);
  } else if (link_type == DLT_NULL) {
    // Loopback interface, no ethernet header, just a null pseudoheader
    uint32_t* header = reinterpret_cast<uint32_t*>(sendbuf_);
    *header = 2;  // IPv4.
    ll_header_size_ = 4;
  } else {
    LOG(FATAL) << "Bad link on interface " << iface_name;
  }

  iph_ = reinterpret_cast<pcap::IPHeader*>(sendbuf_ + ll_header_size_);
  iph_->ip_hl = 5;
  iph_->ip_v = 4;
  iph_->ip_tos = 0;
}

void PhysicalInterfacePacketHandler::SendUDP(const UDPPacket& udp_packet) {
  iph_->ip_id = htons(udp_packet.ip_id());
  iph_->ip_ttl = udp_packet.ttl();
  iph_->ip_p = 0x11;

  uint32_t ip_src_raw = udp_packet.five_tuple().ip_src().Raw();
  uint32_t ip_dst_raw = udp_packet.five_tuple().ip_dst().Raw();
  iph_->ip_src.s_addr = htonl(ip_src_raw);
  iph_->ip_dst.s_addr = htonl(ip_dst_raw);

  pcap::UDPHeader* udph = reinterpret_cast<pcap::UDPHeader*>(
      sendbuf_ + sizeof(pcap::IPHeader) + ll_header_size_);

  uint16_t src_port_raw = udp_packet.five_tuple().src_port().Raw();
  uint16_t dst_port_raw = udp_packet.five_tuple().dst_port().Raw();

  udph->uh_sport = htons(src_port_raw);
  udph->uh_dport = htons(dst_port_raw);
  udph->uh_sum = 0;

  uint32_t total_len = udp_packet.payload_bytes() + sizeof(pcap::UDPHeader);
  udph->uh_ulen = htons(total_len);

  uint32_t total_len_ip = total_len + sizeof(pcap::IPHeader);
  CHECK(total_len_ip <= std::numeric_limits<uint16_t>::max());
  iph_->ip_len = htons(total_len_ip);
  iph_->ip_sum =
      csum(reinterpret_cast<unsigned short*>(sendbuf_ + ll_header_size_),
           (sizeof(pcap::IPHeader) / 2));

  CHECK(pcap_inject(pcap_, sendbuf_, total_len + sizeof(pcap::IPHeader) +
                                         ll_header_size_) != -1);
}

void PhysicalInterfacePacketHandler::HandlePacket(PacketPtr pkt) {
  if (pkt->five_tuple().ip_proto() == net::kProtoUDP) {
    const UDPPacket* udp_packet = static_cast<const UDPPacket*>(pkt.get());
    SendUDP(*udp_packet);
    return;
  }

  LOG(FATAL) << "Don't know how to handle IP type " << pkt->ip_id();
}

}  // namespace htsim
}  // namespace nc
<commit_msg>updates to real-time event queue<commit_after>#include "physical.h"

#if defined(__linux__)
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#elif defined(__APPLE__)
#include <ifaddrs.h>
#include <net/if_dl.h>
#else
#error no definition for GetMacAddress() on this platform!
#endif

namespace nc {
namespace htsim {

#if defined(__linux__)
static bool GetMacAddress(u_char* mac_addr, const char* if_name) {
  ifreq ifinfo;
  strcpy(ifinfo.ifr_name, if_name);
  int sd = socket(AF_INET, SOCK_DGRAM, 0);
  int result = ioctl(sd, SIOCGIFHWADDR, &ifinfo);
  close(sd);

  if (result == 0) {
    memcpy(mac_addr, ifinfo.ifr_hwaddr.sa_data, IFHWADDRLEN);
    return true;
  } else {
    return false;
  }
}
#elif defined(__APPLE__)
static bool GetMacAddress(u_char* mac_addr, const char* if_name) {
  ifaddrs* iflist;
  bool found = false;
  if (getifaddrs(&iflist) == 0) {
    for (ifaddrs* cur = iflist; cur; cur = cur->ifa_next) {
      if ((cur->ifa_addr->sa_family == AF_LINK) &&
          (strcmp(cur->ifa_name, if_name) == 0) && cur->ifa_addr) {
        sockaddr_dl* sdl = (sockaddr_dl*)cur->ifa_addr;
        memcpy(mac_addr, LLADDR(sdl), sdl->sdl_alen);
        found = true;
        break;
      }
    }

    freeifaddrs(iflist);
  }
  return found;
}
#else
#error no definition for GetMacAddress() on this platform!
#endif

static unsigned short csum(unsigned short* buf, int nwords) {
  unsigned long sum;
  for (sum = 0; nwords > 0; nwords--) sum += *buf++;
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  return (unsigned short)(~sum);
}

PhysicalInterfacePacketHandler::PhysicalInterfacePacketHandler(
    const std::string& iface_name) {
  char pcap_errbuf[PCAP_ERRBUF_SIZE];
  pcap_errbuf[0] = '\0';
  pcap_ = pcap_open_live(iface_name.c_str(), 96, 0, 0, pcap_errbuf);
  CHECK(pcap_errbuf[0] == '\0');
  CHECK(pcap_ != nullptr);

  int link_type = pcap_datalink(pcap_);
  if (link_type == DLT_EN10MB) {
    // Ethernet interface. Regular ethernet header.
    pcap::EtherHeader* eh = reinterpret_cast<pcap::EtherHeader*>(sendbuf_);
    memset(eh, 0, sizeof(pcap::EtherHeader));
    CHECK(GetMacAddress(eh->ether_shost, iface_name.c_str()));
    eh->ether_type = htons(0x0800);
    ll_header_size_ = sizeof(pcap::EtherHeader);
  } else if (link_type == DLT_NULL) {
    // Loopback interface, no ethernet header, just a null pseudoheader
    uint32_t* header = reinterpret_cast<uint32_t*>(sendbuf_);
    *header = 2;  // IPv4.
    ll_header_size_ = 4;
  } else {
    LOG(FATAL) << "Bad link on interface " << iface_name;
  }

  iph_ = reinterpret_cast<pcap::IPHeader*>(sendbuf_ + ll_header_size_);
  iph_->ip_hl = 5;
  iph_->ip_v = 4;
  iph_->ip_tos = 0;
}

void PhysicalInterfacePacketHandler::SendUDP(const UDPPacket& udp_packet) {
  iph_->ip_id = htons(udp_packet.ip_id());
  iph_->ip_ttl = udp_packet.ttl();
  iph_->ip_p = 0x11;

  uint32_t ip_src_raw = udp_packet.five_tuple().ip_src().Raw();
  uint32_t ip_dst_raw = udp_packet.five_tuple().ip_dst().Raw();
  iph_->ip_src.s_addr = htonl(ip_src_raw);
  iph_->ip_dst.s_addr = htonl(ip_dst_raw);

  pcap::UDPHeader* udph = reinterpret_cast<pcap::UDPHeader*>(
      sendbuf_ + sizeof(pcap::IPHeader) + ll_header_size_);

  uint16_t src_port_raw = udp_packet.five_tuple().src_port().Raw();
  uint16_t dst_port_raw = udp_packet.five_tuple().dst_port().Raw();

  udph->uh_sport = htons(src_port_raw);
  udph->uh_dport = htons(dst_port_raw);
  udph->uh_sum = 0;

  uint32_t total_len = udp_packet.payload_bytes() + sizeof(pcap::UDPHeader);
  udph->uh_ulen = htons(total_len);

  uint32_t total_len_ip = total_len + sizeof(pcap::IPHeader);
  CHECK(total_len_ip <= std::numeric_limits<uint16_t>::max());
  iph_->ip_len = htons(total_len_ip);
  iph_->ip_sum =
      csum(reinterpret_cast<unsigned short*>(sendbuf_ + ll_header_size_),
           (sizeof(pcap::IPHeader) / 2));

  CHECK(pcap_inject(pcap_, sendbuf_, total_len + sizeof(pcap::IPHeader) +
                                         ll_header_size_) != -1);
}

void PhysicalInterfacePacketHandler::HandlePacket(PacketPtr pkt) {
  if (pkt->five_tuple().ip_proto() == net::kProtoUDP) {
    const UDPPacket* udp_packet = static_cast<const UDPPacket*>(pkt.get());
    SendUDP(*udp_packet);
    return;
  }

  LOG(FATAL) << "Don't know how to handle IP type " << pkt->ip_id();
}

}  // namespace htsim
}  // namespace nc
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_GEOMETRY_GENERATOR_GRAMMAR_HPP
#define MAPNIK_JSON_GEOMETRY_GENERATOR_GRAMMAR_HPP

// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp>
#include <mapnik/vertex.hpp>    // for CommandType::SEG_MOVETO

// boost
#include <boost/tuple/tuple.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/math/special_functions/trunc.hpp> // for vc++ and android whose c++11 libs lack std::trunct

namespace boost { namespace spirit { namespace traits {

// make gcc and darwin toolsets happy.
template <>
struct is_container<mapnik::geometry_container>
    : mpl::false_
{};

}}}

namespace mapnik { namespace json {

namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;

namespace {

#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct get_type
{
    typedef int result_type;
    result_type operator() (geometry_type const& geom) const
    {
        return static_cast<int>(geom.type());
    }
};

struct get_first
{
    typedef geometry_type::value_type const result_type;
    result_type operator() (geometry_type const& geom) const
    {
        geometry_type::value_type coord;
        std::get<0>(coord) = geom.vertex(0,&std::get<1>(coord),&std::get<2>(coord));
        return coord;
    }
};

struct get_size
{
    typedef unsigned result_type;
    result_type operator() (geometry_type const& geom) const
    {
        return geom.size();
    }
};

struct multi_geometry_type
{
    typedef std::tuple<unsigned,bool>  result_type;
    result_type operator() (geometry_container const& geom) const
    {
        unsigned type = 0u;
        bool collection = false;

        geometry_container::const_iterator itr = geom.begin();
        geometry_container::const_iterator end = geom.end();

        for ( ; itr != end; ++itr)
        {
            if (type != 0u && itr->type() != type)
            {
                collection = true;
                break;
            }
            type = itr->type();
        }
        if (geom.size() > 1) type +=3;
        return std::tuple<unsigned,bool>(type, collection);
    }
};

struct not_empty
{
    typedef bool result_type;
    result_type operator() (geometry_container const& cont) const
    {
        for (auto const& geom : cont)
        {
            if (geom.size() > 0) return true;
        }
        return false;
    }
};

#else
struct get_type
{
    template <typename T>
    struct result { typedef int type; };

    int operator() (geometry_type const& geom) const
    {
        return static_cast<int>(geom.type());
    }
};

struct get_first
{
    template <typename T>
    struct result { typedef geometry_type::value_type const type; };

    geometry_type::value_type const operator() (geometry_type const& geom) const
    {
        geometry_type::value_type coord;
        std::get<0>(coord) = geom.vertex(0,&std::get<1>(coord),&std::get<2>(coord));
        return coord;
    }
};

struct multi_geometry_type
{
    template <typename T>
    struct result { typedef std::tuple<unsigned,bool> type; };

    std::tuple<unsigned,bool> operator() (geometry_container const& geom) const
    {
        unsigned type = 0u;
        bool collection = false;

        geometry_container::const_iterator itr = geom.begin();
        geometry_container::const_iterator end = geom.end();

        for ( ; itr != end; ++itr)
        {
            if (type != 0u && static_cast<unsigned>(itr->type()) != type)
            {
                collection = true;
                break;
            }
            type = itr->type();
        }
        if (geom.size() > 1) type +=3;
        return std::tuple<unsigned,bool>(type, collection);
    }
};

struct not_empty
{
    template <typename T>
    struct result { typedef bool type; };

    bool operator() (geometry_container const& cont) const
    {
        geometry_container::const_iterator itr = cont.begin();
        geometry_container::const_iterator end = cont.end();

        for (; itr!=end; ++itr)
        {
            if (itr->size() > 0) return true;
        }
        return false;
    }
};

#endif

template <typename T>
struct json_coordinate_policy : karma::real_policies<T>
{
    typedef boost::spirit::karma::real_policies<T> base_type;
    static int floatfield(T n) { return base_type::fmtflags::fixed; }

    static unsigned precision(T n)
    {
        if (n == 0.0) return 0;
        using namespace boost::spirit;
        return static_cast<unsigned>(14 - boost::math::trunc(log10(traits::get_absolute_value(n))));
    }

    template <typename OutputIterator>
    static bool dot(OutputIterator& sink, T n, unsigned precision)
    {
        if (n == 0) return true;
        return base_type::dot(sink, n, precision);
    }

    template <typename OutputIterator>
    static bool fraction_part(OutputIterator& sink, T n
                              , unsigned adjprec, unsigned precision)
    {
        if (n == 0) return true;
        return base_type::fraction_part(sink, n, adjprec, precision);
    }
};

}

template <typename OutputIterator>
struct geometry_generator_grammar :
        karma::grammar<OutputIterator, geometry_type const& ()>
{

    geometry_generator_grammar()
        : geometry_generator_grammar::base_type(coordinates)
    {
        using boost::spirit::karma::uint_;
        using boost::spirit::bool_;
        using boost::spirit::karma::_val;
        using boost::spirit::karma::_1;
        using boost::spirit::karma::lit;
        using boost::spirit::karma::_a;
        using boost::spirit::karma::_r1;
        using boost::spirit::karma::eps;

        coordinates =  point | linestring | polygon
            ;

        point = &uint_(mapnik::geometry_type::types::Point)[_1 = _type(_val)]
            << point_coord [_1 = _first(_val)]
            ;

        linestring = &uint_(mapnik::geometry_type::types::LineString)[_1 = _type(_val)]
            << lit('[')
            << coords
            << lit(']')
            ;

        polygon = &uint_(mapnik::geometry_type::types::Polygon)[_1 = _type(_val)]
            << lit('[')
            << coords2
            << lit("]]")
            ;

        point_coord = &uint_
            << lit('[')
            << coord_type << lit(',') << coord_type
            << lit(']')
            ;

        polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1]
                           << karma::string[ if_ (_r1 > 1) [_1 = "],["]
                                             .else_[_1 = '[' ]]
                           |
                           &uint_(mapnik::SEG_LINETO)
                           << lit(',')) << lit('[') << coord_type << lit(',') << coord_type << lit(']')
            ;

        coords2 %= *polygon_coord(_a)
            ;

        coords = point_coord % lit(',')
            ;

    }
    // rules
    karma::rule<OutputIterator, geometry_type const& ()> coordinates;
    karma::rule<OutputIterator, geometry_type const& ()> point;
    karma::rule<OutputIterator, geometry_type const& ()> linestring;
    karma::rule<OutputIterator, geometry_type const& ()> polygon;
    karma::rule<OutputIterator, geometry_type const& ()> coords;
    karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2;
    karma::rule<OutputIterator, geometry_type::value_type ()> point_coord;
    karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord;

    // phoenix functions
    phoenix::function<get_type > _type;
    phoenix::function<get_first> _first;
    //
    karma::real_generator<double, json_coordinate_policy<double> > coord_type;

};

template <typename OutputIterator>
struct multi_geometry_generator_grammar :
        karma::grammar<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                       geometry_container const& ()>
{

    multi_geometry_generator_grammar()
        : multi_geometry_generator_grammar::base_type(start)
    {
        using boost::spirit::karma::lit;
        using boost::spirit::karma::eps;
        using boost::spirit::karma::_val;
        using boost::spirit::karma::_1;
        using boost::spirit::karma::_a;
        using boost::spirit::karma::_r1;
        using boost::spirit::bool_;

        geometry_types.add
            (mapnik::geometry_type::types::Point,"\"Point\"")
            (mapnik::geometry_type::types::LineString,"\"LineString\"")
            (mapnik::geometry_type::types::Polygon,"\"Polygon\"")
            (mapnik::geometry_type::types::Point + 3,"\"MultiPoint\"")
            (mapnik::geometry_type::types::LineString + 3,"\"MultiLineString\"")
            (mapnik::geometry_type::types::Polygon + 3,"\"MultiPolygon\"")
            ;

        start %= ( eps(phoenix::at_c<1>(_a))[_a = multi_type_(_val)]
                   << lit("{\"type\":\"GeometryCollection\",\"geometries\":[")
                   << geometry_collection << lit("]}")
                   |
                   geometry)
            ;

        geometry_collection = -(geometry2 % lit(','))
            ;

        geometry = ( &bool_(true)[_1 = not_empty_(_val)] << lit("{\"type\":")
                     << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = multi_type_(_val)]
                     << lit(",\"coordinates\":")
                     << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3) [_1 = '['].else_[_1 = ""]]
                     << coordinates
                     << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']'].else_[_1 = ""]]
                     << lit('}')) | lit("null")
            ;

        geometry2 = lit("{\"type\":")
            << geometry_types[_1 = _a][_a = type_(_val)]
            << lit(",\"coordinates\":")
            << path
            << lit('}')
            ;

        coordinates %= path % lit(',')
            ;

    }
    // rules
    karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                geometry_container const&()> start;
    karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                geometry_container const&()> geometry_collection;
    karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                geometry_container const&()> geometry;
    karma::rule<OutputIterator, karma::locals<unsigned>,
                geometry_type const&()> geometry2;
    karma::rule<OutputIterator, geometry_container const&()> coordinates;
    geometry_generator_grammar<OutputIterator>  path;
    // phoenix
    phoenix::function<multi_geometry_type> multi_type_;
    phoenix::function<get_type > type_;
    phoenix::function<not_empty> not_empty_;
    // symbols table
    karma::symbols<unsigned, char const*> geometry_types;
};

}}

#endif // MAPNIK_JSON_GEOMETRY_GENERATOR_GRAMMAR_HPP
<commit_msg>remove unused code<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_GEOMETRY_GENERATOR_GRAMMAR_HPP
#define MAPNIK_JSON_GEOMETRY_GENERATOR_GRAMMAR_HPP

// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp>
#include <mapnik/vertex.hpp>    // for CommandType::SEG_MOVETO

// boost
#include <boost/tuple/tuple.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/math/special_functions/trunc.hpp> // for vc++ and android whose c++11 libs lack std::trunct

namespace boost { namespace spirit { namespace traits {

// make gcc and darwin toolsets happy.
template <>
struct is_container<mapnik::geometry_container>
    : mpl::false_
{};

}}}

namespace mapnik { namespace json {

namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;

namespace {

#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct get_type
{
    typedef int result_type;
    result_type operator() (geometry_type const& geom) const
    {
        return static_cast<int>(geom.type());
    }
};

struct get_first
{
    typedef geometry_type::value_type const result_type;
    result_type operator() (geometry_type const& geom) const
    {
        geometry_type::value_type coord;
        std::get<0>(coord) = geom.vertex(0,&std::get<1>(coord),&std::get<2>(coord));
        return coord;
    }
};

struct multi_geometry_type
{
    typedef std::tuple<unsigned,bool>  result_type;
    result_type operator() (geometry_container const& geom) const
    {
        unsigned type = 0u;
        bool collection = false;

        geometry_container::const_iterator itr = geom.begin();
        geometry_container::const_iterator end = geom.end();

        for ( ; itr != end; ++itr)
        {
            if (type != 0u && itr->type() != type)
            {
                collection = true;
                break;
            }
            type = itr->type();
        }
        if (geom.size() > 1) type +=3;
        return std::tuple<unsigned,bool>(type, collection);
    }
};

struct not_empty
{
    typedef bool result_type;
    result_type operator() (geometry_container const& cont) const
    {
        for (auto const& geom : cont)
        {
            if (geom.size() > 0) return true;
        }
        return false;
    }
};

#else
struct get_type
{
    template <typename T>
    struct result { typedef int type; };

    int operator() (geometry_type const& geom) const
    {
        return static_cast<int>(geom.type());
    }
};

struct get_first
{
    template <typename T>
    struct result { typedef geometry_type::value_type const type; };

    geometry_type::value_type const operator() (geometry_type const& geom) const
    {
        geometry_type::value_type coord;
        std::get<0>(coord) = geom.vertex(0,&std::get<1>(coord),&std::get<2>(coord));
        return coord;
    }
};

struct multi_geometry_type
{
    template <typename T>
    struct result { typedef std::tuple<unsigned,bool> type; };

    std::tuple<unsigned,bool> operator() (geometry_container const& geom) const
    {
        unsigned type = 0u;
        bool collection = false;

        geometry_container::const_iterator itr = geom.begin();
        geometry_container::const_iterator end = geom.end();

        for ( ; itr != end; ++itr)
        {
            if (type != 0u && static_cast<unsigned>(itr->type()) != type)
            {
                collection = true;
                break;
            }
            type = itr->type();
        }
        if (geom.size() > 1) type +=3;
        return std::tuple<unsigned,bool>(type, collection);
    }
};

struct not_empty
{
    template <typename T>
    struct result { typedef bool type; };

    bool operator() (geometry_container const& cont) const
    {
        geometry_container::const_iterator itr = cont.begin();
        geometry_container::const_iterator end = cont.end();

        for (; itr!=end; ++itr)
        {
            if (itr->size() > 0) return true;
        }
        return false;
    }
};

#endif

template <typename T>
struct json_coordinate_policy : karma::real_policies<T>
{
    typedef boost::spirit::karma::real_policies<T> base_type;
    static int floatfield(T n) { return base_type::fmtflags::fixed; }

    static unsigned precision(T n)
    {
        if (n == 0.0) return 0;
        using namespace boost::spirit;
        return static_cast<unsigned>(14 - boost::math::trunc(log10(traits::get_absolute_value(n))));
    }

    template <typename OutputIterator>
    static bool dot(OutputIterator& sink, T n, unsigned precision)
    {
        if (n == 0) return true;
        return base_type::dot(sink, n, precision);
    }

    template <typename OutputIterator>
    static bool fraction_part(OutputIterator& sink, T n
                              , unsigned adjprec, unsigned precision)
    {
        if (n == 0) return true;
        return base_type::fraction_part(sink, n, adjprec, precision);
    }
};

}

template <typename OutputIterator>
struct geometry_generator_grammar :
        karma::grammar<OutputIterator, geometry_type const& ()>
{

    geometry_generator_grammar()
        : geometry_generator_grammar::base_type(coordinates)
    {
        using boost::spirit::karma::uint_;
        using boost::spirit::bool_;
        using boost::spirit::karma::_val;
        using boost::spirit::karma::_1;
        using boost::spirit::karma::lit;
        using boost::spirit::karma::_a;
        using boost::spirit::karma::_r1;
        using boost::spirit::karma::eps;

        coordinates =  point | linestring | polygon
            ;

        point = &uint_(mapnik::geometry_type::types::Point)[_1 = _type(_val)]
            << point_coord [_1 = _first(_val)]
            ;

        linestring = &uint_(mapnik::geometry_type::types::LineString)[_1 = _type(_val)]
            << lit('[')
            << coords
            << lit(']')
            ;

        polygon = &uint_(mapnik::geometry_type::types::Polygon)[_1 = _type(_val)]
            << lit('[')
            << coords2
            << lit("]]")
            ;

        point_coord = &uint_
            << lit('[')
            << coord_type << lit(',') << coord_type
            << lit(']')
            ;

        polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1]
                           << karma::string[ if_ (_r1 > 1) [_1 = "],["]
                                             .else_[_1 = '[' ]]
                           |
                           &uint_(mapnik::SEG_LINETO)
                           << lit(',')) << lit('[') << coord_type << lit(',') << coord_type << lit(']')
            ;

        coords2 %= *polygon_coord(_a)
            ;

        coords = point_coord % lit(',')
            ;

    }
    // rules
    karma::rule<OutputIterator, geometry_type const& ()> coordinates;
    karma::rule<OutputIterator, geometry_type const& ()> point;
    karma::rule<OutputIterator, geometry_type const& ()> linestring;
    karma::rule<OutputIterator, geometry_type const& ()> polygon;
    karma::rule<OutputIterator, geometry_type const& ()> coords;
    karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2;
    karma::rule<OutputIterator, geometry_type::value_type ()> point_coord;
    karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord;

    // phoenix functions
    phoenix::function<get_type > _type;
    phoenix::function<get_first> _first;
    //
    karma::real_generator<double, json_coordinate_policy<double> > coord_type;

};

template <typename OutputIterator>
struct multi_geometry_generator_grammar :
        karma::grammar<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                       geometry_container const& ()>
{

    multi_geometry_generator_grammar()
        : multi_geometry_generator_grammar::base_type(start)
    {
        using boost::spirit::karma::lit;
        using boost::spirit::karma::eps;
        using boost::spirit::karma::_val;
        using boost::spirit::karma::_1;
        using boost::spirit::karma::_a;
        using boost::spirit::karma::_r1;
        using boost::spirit::bool_;

        geometry_types.add
            (mapnik::geometry_type::types::Point,"\"Point\"")
            (mapnik::geometry_type::types::LineString,"\"LineString\"")
            (mapnik::geometry_type::types::Polygon,"\"Polygon\"")
            (mapnik::geometry_type::types::Point + 3,"\"MultiPoint\"")
            (mapnik::geometry_type::types::LineString + 3,"\"MultiLineString\"")
            (mapnik::geometry_type::types::Polygon + 3,"\"MultiPolygon\"")
            ;

        start %= ( eps(phoenix::at_c<1>(_a))[_a = multi_type_(_val)]
                   << lit("{\"type\":\"GeometryCollection\",\"geometries\":[")
                   << geometry_collection << lit("]}")
                   |
                   geometry)
            ;

        geometry_collection = -(geometry2 % lit(','))
            ;

        geometry = ( &bool_(true)[_1 = not_empty_(_val)] << lit("{\"type\":")
                     << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = multi_type_(_val)]
                     << lit(",\"coordinates\":")
                     << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3) [_1 = '['].else_[_1 = ""]]
                     << coordinates
                     << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']'].else_[_1 = ""]]
                     << lit('}')) | lit("null")
            ;

        geometry2 = lit("{\"type\":")
            << geometry_types[_1 = _a][_a = type_(_val)]
            << lit(",\"coordinates\":")
            << path
            << lit('}')
            ;

        coordinates %= path % lit(',')
            ;

    }
    // rules
    karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                geometry_container const&()> start;
    karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                geometry_container const&()> geometry_collection;
    karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >,
                geometry_container const&()> geometry;
    karma::rule<OutputIterator, karma::locals<unsigned>,
                geometry_type const&()> geometry2;
    karma::rule<OutputIterator, geometry_container const&()> coordinates;
    geometry_generator_grammar<OutputIterator>  path;
    // phoenix
    phoenix::function<multi_geometry_type> multi_type_;
    phoenix::function<get_type > type_;
    phoenix::function<not_empty> not_empty_;
    // symbols table
    karma::symbols<unsigned, char const*> geometry_types;
};

}}

#endif // MAPNIK_JSON_GEOMETRY_GENERATOR_GRAMMAR_HPP
<|endoftext|>


<commit_before>#ifndef BEAM_INTERNET_IP4_HPP
#define BEAM_INTERNET_IP4_HPP

#include <cstdint>
#include <array>
#include <iosfwd>
#include <string>
#include <vector>

namespace beam {
namespace internet {
namespace ipv4 {

typedef std::uint32_t address;
typedef std::uint16_t port;

class endpoint_id
{
public:
    endpoint_id();
    endpoint_id(address addr, port pt);
    inline bool operator==(const endpoint_id& other) const
    {
	return this->value_ == other.value_;
    }
    inline bool operator!=(const endpoint_id& other) const
    {
	return !(*this == other);
    }
    inline bool operator<(const endpoint_id& other) const
    {
	return this->value_ < other.value_;
    }
    address get_address() const;
    port get_port() const;
    inline std::uint64_t get_value() const { return value_; }
private:
    std::uint64_t value_;
};

std::vector<address> resolve(const std::string& hostname);

} // namespace ipv4
} // namespace internet
} // namespace beam

namespace std {

ostream& operator<<(ostream& stream, const beam::internet::ipv4::endpoint_id& id);

template<>
struct hash<beam::internet::ipv4::endpoint_id>
{
    std::size_t operator()(beam::internet::ipv4::endpoint_id id) const
    {
	std::hash<std::uint64_t> hasher;
	return hasher(id.get_value());
    }
};

} // namespace std

#endif
<commit_msg>adding more comparison operators to endpoint_id<commit_after>#ifndef BEAM_INTERNET_IP4_HPP
#define BEAM_INTERNET_IP4_HPP

#include <cstdint>
#include <array>
#include <iosfwd>
#include <string>
#include <vector>

namespace beam {
namespace internet {
namespace ipv4 {

typedef std::uint32_t address;
typedef std::uint16_t port;

class endpoint_id
{
public:
    endpoint_id();
    endpoint_id(address addr, port pt);
    inline bool operator==(const endpoint_id& other) const
    {
	return this->value_ == other.value_;
    }
    inline bool operator!=(const endpoint_id& other) const
    {
	return !(*this == other);
    }
    inline bool operator<(const endpoint_id& other) const
    {
	return this->value_ < other.value_;
    }
    inline bool operator<=(const endpoint_id& other) const
    {
	return this->value_ <= other.value_;
    }
    inline bool operator>(const endpoint_id& other) const
    {
	return this->value_ > other.value_;
    }
    inline bool operator>=(const endpoint_id& other) const
    {
	return this->value_ >= other.value_;
    }
    address get_address() const;
    port get_port() const;
    inline std::uint64_t get_value() const { return value_; }
private:
    std::uint64_t value_;
};

std::vector<address> resolve(const std::string& hostname);

} // namespace ipv4
} // namespace internet
} // namespace beam

namespace std {

ostream& operator<<(ostream& stream, const beam::internet::ipv4::endpoint_id& id);

template<>
struct hash<beam::internet::ipv4::endpoint_id>
{
    std::size_t operator()(beam::internet::ipv4::endpoint_id id) const
    {
	std::hash<std::uint64_t> hasher;
	return hasher(id.get_value());
    }
};

} // namespace std

#endif
<|endoftext|>


<commit_before>// Copyright 2008 Paul Hodge

#include "common_headers.h"

#include "branch.h"
#include "function.h"
#include "introspection.h"
#include "runtime.h"
#include "term.h"
#include "type.h"

namespace circa {

std::string get_short_local_name(Term* term)
{
    if (term == NULL)
        return "NULL";
    if (term->name != "")
        return term->name;

    std::stringstream stream;
    stream << "#" << term->globalID;
    return stream.str();
}

void print_term_extended(Term* term, std::ostream &output)
{
    if (term == NULL) {
        output << "<NULL>";
        return;
    }

    std::string name = term->name;
    std::string funcName = get_short_local_name(term->function);
    std::string typeName = term->type->name;

    output << "#" << term->globalID;

    if (name != "")
        output << " " << name << "";

    output << ": ";

    output << funcName << "(";

    bool first_input = true;
    for (unsigned int input_index=0; input_index < term->inputs.count(); input_index++) {
        Term* input = term->inputs[input_index];
        if (!first_input) output << ", ";
        output << get_short_local_name(input);
        first_input = false;
    }

    output << ")";

    if (term->type != VOID_TYPE)
        output << " -> " << typeName;

    if (term->hasError())
        output << " *" << term->getErrorMessage() << "*";

    output << std::endl;
}

void print_branch_extended(Branch& branch, std::ostream &output)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];

        print_term_extended(term, output);
    }
}

void print_terms(ReferenceList const& list, std::ostream &output)
{
    for (unsigned int i=0; i < list.count(); i++) {
        print_term_extended(list[i], output);
    }
}

ReferenceList list_all_pointers(Term* term)
{
    ReferenceList result;

    struct AppendPointersToList : PointerVisitor
    {
        ReferenceList& list;
        AppendPointersToList(ReferenceList &_list) : list(_list) {}

        virtual void visitPointer(Term* term) {
            if (term != NULL)
                list.appendUnique(term);
        }
    };

    AppendPointersToList visitor(result);
    visit_pointers(term, visitor);

    return result;
}

bool is_using(Term* user, Term* usee)
{
    assert_good_pointer(user);
    assert_good_pointer(usee);
    if (user->inputs.contains(usee))
        return true;
    if (user->function == usee)
        return true;

    return false;
}

bool function_allows_term_reuse(Function &function)
{
    if ((function.stateType != VOID_TYPE) && (function.stateType != NULL))
        return false;

    if (!function.pureFunction)
        return false;

    return true;
}

bool is_equivalent(Term* target, Term* function, ReferenceList const& inputs)
{
    if (target->function != function)
        return false;

    if (!function_allows_term_reuse(as_function(function)))
        return false;

    // Check inputs
    unsigned int numInputs = target->inputs.count();

    if (numInputs != inputs.count())
        return false;

    for (unsigned int i=0; i < numInputs; i++) {
        if (target->inputs[i] != inputs[i]) {
            return false;
        }
    }

    return true;
}

Term* find_equivalent(Branch &branch, Term* function, ReferenceList const& inputs)
{
    // This step is inefficient because we check every term in the branch.
    // Will improve in the future.
    for (int i=0; i < branch.numTerms(); i++) {
        Term *term = branch[i];
        if (is_equivalent(term, function, inputs))
            return term;
    }
    return NULL;
}

Term* find_equivalent(Term* function, ReferenceList const& inputs)
{
    if (!function_allows_term_reuse(as_function(function))) {
        return false;
    }

    Term* term = NULL;

    if (function->owningBranch != NULL)
        term = find_equivalent(*function->owningBranch, function, inputs);
    if (term != NULL)
        return term;

    // This step is inefficient because we check the owning branch of
    // every input, which may check some branches multiple times.
    for (unsigned int i=0; i < inputs.count(); i++) {
        if (inputs[i] == NULL)
            continue;

        Branch* branch = inputs[i]->owningBranch;
        if (branch != NULL)
            term = find_equivalent(*branch, function, inputs);
        if (term != NULL)
            return term;
    }

    return NULL;
}

void print_runtime_errors(Branch& branch, std::ostream& output)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term *term = branch[i];

        if (term == NULL)
            continue;

        if (term->hasError()) {
            output << "error on " << term->name << ": " << term->getErrorMessage() << std::endl;
        }
    }
}

void check_for_compile_error(Term* term, std::string& errorMessage)
{
    if (term->function == UNKNOWN_FUNCTION) {
        errorMessage = std::string("Unknown function: " + as_string(term->state));
    }
}

bool has_compile_errors(Branch& branch)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];
        std::string message;
        check_for_compile_error(term, message);
        if (message != "")
            return true;
    }
    return false;
}

std::vector<std::string> get_compile_errors(Branch& branch)
{
    std::vector<std::string> results;

    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];
        std::string message;

        check_for_compile_error(term, message);

        if (message != "")
            results.push_back(message);
    }

    return results;
}

void print_compile_errors(Branch& branch, std::ostream& output)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];
        std::string message;

        check_for_compile_error(term, message);

        if (message != "")
            output << message << std::endl;
    }
}

std::string get_source_of_input(Term* term, int inputIndex)
{
    switch (term->syntaxHints.getInputSyntax(inputIndex).style) {
        case TermSyntaxHints::InputSyntax::BY_SOURCE:
        {
            return get_term_source(term->input(inputIndex));
        }
        break;

        case TermSyntaxHints::InputSyntax::BY_NAME:
        {
            return term->input(inputIndex)->name;
        }
        break;

        case TermSyntaxHints::InputSyntax::UNKNOWN_STYLE:
        default:
        {
            return "(!unknown)";
        }
        break;
    }
}

bool should_print_term_source_line(Term* term)
{
    if (term->syntaxHints.occursInsideAnExpression)
        return false;

    return true;
}

std::string get_term_source(Term* term)
{
    std::stringstream result;

    // handle special cases
    if (term->function == COMMENT_FUNC) {
        std::string comment = as_string(term->state->field(0));

        if (comment == "")
            return "";
        else {
            result << "--" << comment;
            return result.str();
        }
    }

    // add possible name binding
    if (term->name != "") {
        result << term->name << " = ";
    }

    // add the declaration syntax
    switch (term->syntaxHints.declarationStyle) {
        case TermSyntaxHints::FUNCTION_CALL:
        {

            result << term->function->name << "(";

            for (int i=0; i < term->numInputs(); i++) {
                if (i > 0) result << ", ";

                result << get_source_of_input(term, i);
            }

            result << ")";
        }
        break;

        case TermSyntaxHints::LITERAL_VALUE:
        {
            result << to_source_string(term);
        }
        break;

        case TermSyntaxHints::UNKNOWN_DECLARATION_STYLE:
        {
            result << "(!error, unknown declaration style)";
        }
        break;

        case TermSyntaxHints::DOT_CONCATENATION:
        {
            result << get_source_of_input(term, 0);
            result << ".";
            result << term->function->name; /*<< "(";
            for (int i=1; i < term->numInputs(); i++) {
                if (i > 1) result << ", ";

                result << get_source_of_input(term, i);
            }
            result << ")";*/
        }
    }

    return result.str();
}

} // namespace circa
<commit_msg>find_equivalent now checks 'users' instead of checking the whole branch<commit_after>// Copyright 2008 Paul Hodge

#include "common_headers.h"

#include "branch.h"
#include "function.h"
#include "introspection.h"
#include "runtime.h"
#include "term.h"
#include "type.h"

namespace circa {

std::string get_short_local_name(Term* term)
{
    if (term == NULL)
        return "NULL";
    if (term->name != "")
        return term->name;

    std::stringstream stream;
    stream << "#" << term->globalID;
    return stream.str();
}

void print_term_extended(Term* term, std::ostream &output)
{
    if (term == NULL) {
        output << "<NULL>";
        return;
    }

    std::string name = term->name;
    std::string funcName = get_short_local_name(term->function);
    std::string typeName = term->type->name;

    output << "#" << term->globalID;

    if (name != "")
        output << " " << name << "";

    output << ": ";

    output << funcName << "(";

    bool first_input = true;
    for (unsigned int input_index=0; input_index < term->inputs.count(); input_index++) {
        Term* input = term->inputs[input_index];
        if (!first_input) output << ", ";
        output << get_short_local_name(input);
        first_input = false;
    }

    output << ")";

    if (term->type != VOID_TYPE)
        output << " -> " << typeName;

    if (term->hasError())
        output << " *" << term->getErrorMessage() << "*";

    output << std::endl;
}

void print_branch_extended(Branch& branch, std::ostream &output)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];

        print_term_extended(term, output);
    }
}

void print_terms(ReferenceList const& list, std::ostream &output)
{
    for (unsigned int i=0; i < list.count(); i++) {
        print_term_extended(list[i], output);
    }
}

ReferenceList list_all_pointers(Term* term)
{
    ReferenceList result;

    struct AppendPointersToList : PointerVisitor
    {
        ReferenceList& list;
        AppendPointersToList(ReferenceList &_list) : list(_list) {}

        virtual void visitPointer(Term* term) {
            if (term != NULL)
                list.appendUnique(term);
        }
    };

    AppendPointersToList visitor(result);
    visit_pointers(term, visitor);

    return result;
}

bool function_allows_term_reuse(Function &function)
{
    if ((function.stateType != VOID_TYPE) && (function.stateType != NULL))
        return false;

    if (!function.pureFunction)
        return false;

    return true;
}

bool is_equivalent(Term* target, Term* function, ReferenceList const& inputs)
{
    if (target->function != function)
        return false;

    if (!function_allows_term_reuse(as_function(function)))
        return false;

    // Check inputs
    unsigned int numInputs = target->inputs.count();

    if (numInputs != inputs.count())
        return false;

    for (unsigned int i=0; i < numInputs; i++) {
        if (target->inputs[i] != inputs[i]) {
            return false;
        }
    }

    return true;
}

Term* find_equivalent(Term* function, ReferenceList const& inputs)
{
    if (!function_allows_term_reuse(as_function(function))) {
        return NULL;
    }

    // Check users of each input
    for (unsigned int input_i=0; input_i < inputs.count(); input_i++) {
        Term* input = inputs[input_i];
        if (input == NULL)
            continue;

        for (unsigned int user_i=0; user_i < input->users.count(); user_i++) {
            Term* user = input->users[user_i];

            if (is_equivalent(user, function, inputs))
                return user;
        }
    }

    // Check users of function
    for (unsigned int i=0; i < function->users.count(); i++) {
        Term* user = function->users[i];
        if (is_equivalent(user, function, inputs))
            return user;
    }

    return NULL;
}

void print_runtime_errors(Branch& branch, std::ostream& output)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term *term = branch[i];

        if (term == NULL)
            continue;

        if (term->hasError()) {
            output << "error on " << term->name << ": " << term->getErrorMessage() << std::endl;
        }
    }
}

void check_for_compile_error(Term* term, std::string& errorMessage)
{
    if (term->function == UNKNOWN_FUNCTION) {
        errorMessage = std::string("Unknown function: " + as_string(term->state));
    }
}

bool has_compile_errors(Branch& branch)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];
        std::string message;
        check_for_compile_error(term, message);
        if (message != "")
            return true;
    }
    return false;
}

std::vector<std::string> get_compile_errors(Branch& branch)
{
    std::vector<std::string> results;

    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];
        std::string message;

        check_for_compile_error(term, message);

        if (message != "")
            results.push_back(message);
    }

    return results;
}

void print_compile_errors(Branch& branch, std::ostream& output)
{
    for (int i=0; i < branch.numTerms(); i++) {
        Term* term = branch[i];
        std::string message;

        check_for_compile_error(term, message);

        if (message != "")
            output << message << std::endl;
    }
}

std::string get_source_of_input(Term* term, int inputIndex)
{
    switch (term->syntaxHints.getInputSyntax(inputIndex).style) {
        case TermSyntaxHints::InputSyntax::BY_SOURCE:
        {
            return get_term_source(term->input(inputIndex));
        }
        break;

        case TermSyntaxHints::InputSyntax::BY_NAME:
        {
            return term->input(inputIndex)->name;
        }
        break;

        case TermSyntaxHints::InputSyntax::UNKNOWN_STYLE:
        default:
        {
            return "(!unknown)";
        }
        break;
    }
}

bool should_print_term_source_line(Term* term)
{
    if (term->syntaxHints.occursInsideAnExpression)
        return false;

    return true;
}

std::string get_term_source(Term* term)
{
    std::stringstream result;

    // handle special cases
    if (term->function == COMMENT_FUNC) {
        std::string comment = as_string(term->state->field(0));

        if (comment == "")
            return "";
        else {
            result << "--" << comment;
            return result.str();
        }
    }

    // add possible name binding
    if (term->name != "") {
        result << term->name << " = ";
    }

    // add the declaration syntax
    switch (term->syntaxHints.declarationStyle) {
        case TermSyntaxHints::FUNCTION_CALL:
        {

            result << term->function->name << "(";

            for (int i=0; i < term->numInputs(); i++) {
                if (i > 0) result << ", ";

                result << get_source_of_input(term, i);
            }

            result << ")";
        }
        break;

        case TermSyntaxHints::LITERAL_VALUE:
        {
            result << to_source_string(term);
        }
        break;

        case TermSyntaxHints::UNKNOWN_DECLARATION_STYLE:
        {
            result << "(!error, unknown declaration style)";
        }
        break;

        case TermSyntaxHints::DOT_CONCATENATION:
        {
            result << get_source_of_input(term, 0);
            result << ".";
            result << term->function->name; /*<< "(";
            for (int i=1; i < term->numInputs(); i++) {
                if (i > 1) result << ", ";

                result << get_source_of_input(term, i);
            }
            result << ")";*/
        }
    }

    return result.str();
}

} // namespace circa
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Interpreter/Value.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/GenericValue.h"

#include <string>
#include <sstream>
#include <cstdio>

// Fragment copied from LLVM's raw_ostream.cpp
#if defined(_MSC_VER)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#else
//#if defined(HAVE_UNISTD_H)
# include <unistd.h>
//#endif
#endif

using namespace cling;

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*cling::Value**/ V) {
  //Value* value = (Value*)V;

  // We need stream that doesn't close its file descriptor, thus we are not
  // using llvm::outs. Keeping file descriptor open we will be able to use
  // the results in pipes (Savannah #99234).
  //llvm::raw_fd_ostream outs (STDOUT_FILENO, /*ShouldClose*/false);

  //std::string typeStr = printType(value->getPtr(), value->getPtr(), *value);
  //std::string valueStr = printValue(value->getPtr(), value->getPtr(), *value);
}

static void StreamValue(llvm::raw_ostream& o, const void* V, clang::QualType QT,
                        clang::ASTContext& C);

static void StreamChar(llvm::raw_ostream& o, const char v) {
  if (isprint(v))
    o << '"' << v << "\"";
  else {
    o << "\\0x";
    o.write_hex(v);
  }
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v) {
  if (!v) {
    o << "<<<NULL>>>";
    return;
  }
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"...";
  else o << "\"";
}

static void StreamRef(llvm::raw_ostream& o, const void** V, clang::QualType Ty,
                       clang::ASTContext& C){
  const clang::ReferenceType* RTy = llvm::dyn_cast<clang::ReferenceType>(Ty);
  StreamValue(o, *V, RTy->getPointeeTypeAsWritten(), C);
}

static void StreamPtr(llvm::raw_ostream& o, const void* v) {
  o << v;
}

static void StreamArr(llvm::raw_ostream& o, const void* V, clang::QualType Ty,
                      clang::ASTContext& C) {
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)V);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, (const char*) V + i * ElBytes, ElementTy, C);
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }";
  } else
    StreamPtr(o, V);
}

static void StreamFunction(llvm::raw_ostream& o, Value* V) {
  o << "Function @" << V->getPtr() << '\n';

  Interpreter* interp = V->getInterpreter();
  const Transaction* T = interp->getLastTransaction();
  assert(T->getWrapperFD() && "Must have a wrapper.");
  clang::FunctionDecl* WrapperFD = T->getWrapperFD();
  clang::Expr* ExprAttachedTo
    = utils::Analyze::GetOrCreateLastExpr(WrapperFD, /*foundAtPos*/0,
                                          /*omitDS*/false, &interp->getSema());
  const clang::DeclRefExpr* DeclRefExp
    = llvm::dyn_cast_or_null<clang::DeclRefExpr>(ExprAttachedTo);
  const clang::FunctionDecl* FD = 0;
  if (DeclRefExp)
    FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl());
  if (FD) {
    clang::SourceRange SRange = FD->getSourceRange();
    const char* cBegin = 0;
    const char* cEnd = 0;
    bool Invalid;
    if (SRange.isValid()) {
      clang::SourceManager& SM = V->getASTContext().getSourceManager();
      clang::SourceLocation LocBegin = SRange.getBegin();
      LocBegin = SM.getExpansionRange(LocBegin).first;
      o << "  at " << SM.getFilename(LocBegin);
      unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid);
      if (!Invalid)
        o << ':' << LineNo;
      o << ":\n";
      bool Invalid = false;
      cBegin = SM.getCharacterData(LocBegin, &Invalid);
      if (!Invalid) {
        clang::SourceLocation LocEnd = SRange.getEnd();
        LocEnd = SM.getExpansionRange(LocEnd).second;
        cEnd = SM.getCharacterData(LocEnd, &Invalid);
        if (Invalid)
          cBegin = 0;
      } else {
        cBegin = 0;
      }
    }
    if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) {
      o << llvm::StringRef(cBegin, cEnd - cBegin + 1);
    } else {
      const clang::FunctionDecl* FDef;
      if (FD->hasBody(FDef))
        FD = FDef;
      FD->print(o);
      //const clang::FunctionDecl* FD
      //  = llvm::cast<const clang::FunctionType>(Ty)->getDecl();
    }
  } else {
    o << ":\n";
    // type-based printing:
    V->getType().print(o, V->getASTContext().getPrintingPolicy());
  }
  // type-based print() never and decl-based print() sometimes does not include
  // a final newline:
  o << '\n';
}

static void StreamLongDouble(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C) {
  std::stringstream sstr;
  sstr << value->simplisticCastAs<long double>();
  o << sstr.str() << 'L';
}

static void StreamClingValue(llvm::raw_ostream& o, const Value* value) {
  if (!value || !value->isValid()) {
    o << "<<<invalid>>> @" << value;
  } else {
    clang::ASTContext& C = value->getASTContext();
    clang::QualType QT = value->getType();
    o << "boxes [";
    o << "("
      << QT.getAsString(C.getPrintingPolicy())
      << ") ";
    clang::QualType valType = QT.getDesugaredType(C).getNonReferenceType();
    if (C.hasSameType(valType, C.LongDoubleTy))
      StreamLongDouble(o, value, C);
    else if (valType->isFloatingType())
      o << value->simplisticCastAs<double>();
    else if (valType->isIntegerType()) {
      if (valType->hasSignedIntegerRepresentation())
        o << value->simplisticCastAs<long long>();
      else
        o << value->simplisticCastAs<unsigned long long>();
    } else if (valType->isBooleanType())
      o << (value->simplisticCastAs<bool>() ? "true" : "false");
    else {
      StreamValue(o, value->getPtr(), valType, value->getASTContext());
    }
    o << "]";
  }
}

static void StreamObj(llvm::raw_ostream& o, const void* V, clang::QualType Ty) {
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    std::string QualName = CXXRD->getQualifiedNameAsString();
    if (QualName == "cling::Value"){
      StreamClingValue(o, (const cling::Value*)V);
      return;
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << V;
}

static void StreamValue(llvm::raw_ostream& o, const void* V,
                        clang::QualType Ty, clang::ASTContext& C) {
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)V)
        o << "true";
      else
        o << "false";
      break;
    case clang::BuiltinType::Char_U: // intentional fall through
    case clang::BuiltinType::UChar: // intentional fall through
    case clang::BuiltinType::Char_S: // intentional fall through
    case clang::BuiltinType::SChar:
      StreamChar(o, *(const char*)V); break;
    case clang::BuiltinType::Short:
      o << *(const short*)V; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)V; break;
    case clang::BuiltinType::Int:
      o << *(const int*)V; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)V; break;
    case clang::BuiltinType::Long:
      o << *(const long*)V; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)V; break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)V; break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)V; break;
    case clang::BuiltinType::Float:
      o << *(const float*)V; break;
    case clang::BuiltinType::Double:
      o << *(const double*)V; break;
    case clang::BuiltinType::LongDouble: {
      std::stringstream ssLD;
      ssLD << *(const long double*)V;
      o << ssLD.str() << 'L'; break;
    }
    default:
      StreamObj(o, V, Ty);
    }
  }
  else if (Ty.getAsString().compare("std::string") == 0) {
    StreamObj(o, V, Ty);
    o << " "; // force a space
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)V).c_str()));
  }
  else if (Ty->isEnumeralType()) {
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)V;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10);
  }
  else if (Ty->isReferenceType())
    StreamRef(o, (const void**)&V, Ty, C);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)V);
    else
      StreamPtr(o, V);
  }
  else if (Ty->isArrayType())
    StreamArr(o, V, Ty, C);
  else if (Ty->isFunctionType())
    StreamFunction(o, const_cast<cling::Value*>((const cling::Value*)V));
  else
    StreamObj(o, V, Ty);
}

namespace cling {
namespace valuePrinterInternal {
  void printValue_Default(llvm::raw_ostream& o, const Value& V) {
    clang::ASTContext& C = V.getASTContext();
    clang::QualType Ty = V.getType().getDesugaredType(C);
    if (const clang::BuiltinType *BT
        = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
      switch (BT->getKind()) {
      case clang::BuiltinType::Bool: // intentional fall through
      case clang::BuiltinType::Char_U: // intentional fall through
      case clang::BuiltinType::Char_S: // intentional fall through
      case clang::BuiltinType::SChar: // intentional fall through
      case clang::BuiltinType::Short: // intentional fall through
      case clang::BuiltinType::Int: // intentional fall through
      case clang::BuiltinType::Long: // intentional fall through
      case clang::BuiltinType::LongLong: {
        long long res = V.getLL();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::UChar: // intentional fall through
      case clang::BuiltinType::UShort: // intentional fall through
      case clang::BuiltinType::UInt: // intentional fall through
      case clang::BuiltinType::ULong: // intentional fall through
      case clang::BuiltinType::ULongLong: {
        unsigned long long res = V.getULL();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::Float: {
        float res = V.getFloat();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::Double: {
        double res = V.getDouble();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::LongDouble: {
        long double res = V.getLongDouble();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      default:
        StreamValue(o, V.getPtr(), Ty, C);
        break;
      }
    }
    else if (Ty->isIntegralOrEnumerationType()) {
      long long res = V.getLL();
      StreamValue(o, &res, Ty, C);
    }
    else if (Ty->isFunctionType())
      StreamValue(o, &V, Ty, C);
    else
      StreamValue(o, V.getPtr(), Ty, C);
  }

  void printType_Default(llvm::raw_ostream& o, const Value& V) {
    o << "(";
    o << V.getType().getAsString();
    o << ") ";
  }

  void flushToStream(llvm::raw_ostream& o, const std::string& s) {
    // We want to keep stdout and o in sync if o is different from stdout.
    fflush(stdout);
    o << s;
    o.flush();
  }
} // end namespace valuePrinterInternal
} // end namespace cling
<commit_msg>Use ticks instead of quotes when printing a single char.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Interpreter/Value.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/GenericValue.h"

#include <string>
#include <sstream>
#include <cstdio>

// Fragment copied from LLVM's raw_ostream.cpp
#if defined(_MSC_VER)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#else
//#if defined(HAVE_UNISTD_H)
# include <unistd.h>
//#endif
#endif

using namespace cling;

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*cling::Value**/ V) {
  //Value* value = (Value*)V;

  // We need stream that doesn't close its file descriptor, thus we are not
  // using llvm::outs. Keeping file descriptor open we will be able to use
  // the results in pipes (Savannah #99234).
  //llvm::raw_fd_ostream outs (STDOUT_FILENO, /*ShouldClose*/false);

  //std::string typeStr = printType(value->getPtr(), value->getPtr(), *value);
  //std::string valueStr = printValue(value->getPtr(), value->getPtr(), *value);
}

static void StreamValue(llvm::raw_ostream& o, const void* V, clang::QualType QT,
                        clang::ASTContext& C);

static void StreamChar(llvm::raw_ostream& o, const char v) {
  if (isprint(v))
    o << '\'' << v << '\'';
  else {
    o << "\\0x";
    o.write_hex(v);
  }
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v) {
  if (!v) {
    o << "<<<NULL>>>";
    return;
  }
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"...";
  else o << "\"";
}

static void StreamRef(llvm::raw_ostream& o, const void** V, clang::QualType Ty,
                       clang::ASTContext& C){
  const clang::ReferenceType* RTy = llvm::dyn_cast<clang::ReferenceType>(Ty);
  StreamValue(o, *V, RTy->getPointeeTypeAsWritten(), C);
}

static void StreamPtr(llvm::raw_ostream& o, const void* v) {
  o << v;
}

static void StreamArr(llvm::raw_ostream& o, const void* V, clang::QualType Ty,
                      clang::ASTContext& C) {
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)V);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, (const char*) V + i * ElBytes, ElementTy, C);
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }";
  } else
    StreamPtr(o, V);
}

static void StreamFunction(llvm::raw_ostream& o, Value* V) {
  o << "Function @" << V->getPtr() << '\n';

  Interpreter* interp = V->getInterpreter();
  const Transaction* T = interp->getLastTransaction();
  assert(T->getWrapperFD() && "Must have a wrapper.");
  clang::FunctionDecl* WrapperFD = T->getWrapperFD();
  clang::Expr* ExprAttachedTo
    = utils::Analyze::GetOrCreateLastExpr(WrapperFD, /*foundAtPos*/0,
                                          /*omitDS*/false, &interp->getSema());
  const clang::DeclRefExpr* DeclRefExp
    = llvm::dyn_cast_or_null<clang::DeclRefExpr>(ExprAttachedTo);
  const clang::FunctionDecl* FD = 0;
  if (DeclRefExp)
    FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl());
  if (FD) {
    clang::SourceRange SRange = FD->getSourceRange();
    const char* cBegin = 0;
    const char* cEnd = 0;
    bool Invalid;
    if (SRange.isValid()) {
      clang::SourceManager& SM = V->getASTContext().getSourceManager();
      clang::SourceLocation LocBegin = SRange.getBegin();
      LocBegin = SM.getExpansionRange(LocBegin).first;
      o << "  at " << SM.getFilename(LocBegin);
      unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid);
      if (!Invalid)
        o << ':' << LineNo;
      o << ":\n";
      bool Invalid = false;
      cBegin = SM.getCharacterData(LocBegin, &Invalid);
      if (!Invalid) {
        clang::SourceLocation LocEnd = SRange.getEnd();
        LocEnd = SM.getExpansionRange(LocEnd).second;
        cEnd = SM.getCharacterData(LocEnd, &Invalid);
        if (Invalid)
          cBegin = 0;
      } else {
        cBegin = 0;
      }
    }
    if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) {
      o << llvm::StringRef(cBegin, cEnd - cBegin + 1);
    } else {
      const clang::FunctionDecl* FDef;
      if (FD->hasBody(FDef))
        FD = FDef;
      FD->print(o);
      //const clang::FunctionDecl* FD
      //  = llvm::cast<const clang::FunctionType>(Ty)->getDecl();
    }
  } else {
    o << ":\n";
    // type-based printing:
    V->getType().print(o, V->getASTContext().getPrintingPolicy());
  }
  // type-based print() never and decl-based print() sometimes does not include
  // a final newline:
  o << '\n';
}

static void StreamLongDouble(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C) {
  std::stringstream sstr;
  sstr << value->simplisticCastAs<long double>();
  o << sstr.str() << 'L';
}

static void StreamClingValue(llvm::raw_ostream& o, const Value* value) {
  if (!value || !value->isValid()) {
    o << "<<<invalid>>> @" << value;
  } else {
    clang::ASTContext& C = value->getASTContext();
    clang::QualType QT = value->getType();
    o << "boxes [";
    o << "("
      << QT.getAsString(C.getPrintingPolicy())
      << ") ";
    clang::QualType valType = QT.getDesugaredType(C).getNonReferenceType();
    if (C.hasSameType(valType, C.LongDoubleTy))
      StreamLongDouble(o, value, C);
    else if (valType->isFloatingType())
      o << value->simplisticCastAs<double>();
    else if (valType->isIntegerType()) {
      if (valType->hasSignedIntegerRepresentation())
        o << value->simplisticCastAs<long long>();
      else
        o << value->simplisticCastAs<unsigned long long>();
    } else if (valType->isBooleanType())
      o << (value->simplisticCastAs<bool>() ? "true" : "false");
    else {
      StreamValue(o, value->getPtr(), valType, value->getASTContext());
    }
    o << "]";
  }
}

static void StreamObj(llvm::raw_ostream& o, const void* V, clang::QualType Ty) {
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    std::string QualName = CXXRD->getQualifiedNameAsString();
    if (QualName == "cling::Value"){
      StreamClingValue(o, (const cling::Value*)V);
      return;
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << V;
}

static void StreamValue(llvm::raw_ostream& o, const void* V,
                        clang::QualType Ty, clang::ASTContext& C) {
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)V)
        o << "true";
      else
        o << "false";
      break;
    case clang::BuiltinType::Char_U: // intentional fall through
    case clang::BuiltinType::UChar: // intentional fall through
    case clang::BuiltinType::Char_S: // intentional fall through
    case clang::BuiltinType::SChar:
      StreamChar(o, *(const char*)V); break;
    case clang::BuiltinType::Short:
      o << *(const short*)V; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)V; break;
    case clang::BuiltinType::Int:
      o << *(const int*)V; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)V; break;
    case clang::BuiltinType::Long:
      o << *(const long*)V; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)V; break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)V; break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)V; break;
    case clang::BuiltinType::Float:
      o << *(const float*)V; break;
    case clang::BuiltinType::Double:
      o << *(const double*)V; break;
    case clang::BuiltinType::LongDouble: {
      std::stringstream ssLD;
      ssLD << *(const long double*)V;
      o << ssLD.str() << 'L'; break;
    }
    default:
      StreamObj(o, V, Ty);
    }
  }
  else if (Ty.getAsString().compare("std::string") == 0) {
    StreamObj(o, V, Ty);
    o << " "; // force a space
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)V).c_str()));
  }
  else if (Ty->isEnumeralType()) {
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)V;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10);
  }
  else if (Ty->isReferenceType())
    StreamRef(o, (const void**)&V, Ty, C);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)V);
    else
      StreamPtr(o, V);
  }
  else if (Ty->isArrayType())
    StreamArr(o, V, Ty, C);
  else if (Ty->isFunctionType())
    StreamFunction(o, const_cast<cling::Value*>((const cling::Value*)V));
  else
    StreamObj(o, V, Ty);
}

namespace cling {
namespace valuePrinterInternal {
  void printValue_Default(llvm::raw_ostream& o, const Value& V) {
    clang::ASTContext& C = V.getASTContext();
    clang::QualType Ty = V.getType().getDesugaredType(C);
    if (const clang::BuiltinType *BT
        = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
      switch (BT->getKind()) {
      case clang::BuiltinType::Bool: // intentional fall through
      case clang::BuiltinType::Char_U: // intentional fall through
      case clang::BuiltinType::Char_S: // intentional fall through
      case clang::BuiltinType::SChar: // intentional fall through
      case clang::BuiltinType::Short: // intentional fall through
      case clang::BuiltinType::Int: // intentional fall through
      case clang::BuiltinType::Long: // intentional fall through
      case clang::BuiltinType::LongLong: {
        long long res = V.getLL();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::UChar: // intentional fall through
      case clang::BuiltinType::UShort: // intentional fall through
      case clang::BuiltinType::UInt: // intentional fall through
      case clang::BuiltinType::ULong: // intentional fall through
      case clang::BuiltinType::ULongLong: {
        unsigned long long res = V.getULL();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::Float: {
        float res = V.getFloat();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::Double: {
        double res = V.getDouble();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      case clang::BuiltinType::LongDouble: {
        long double res = V.getLongDouble();
        StreamValue(o, (const void*)&res, Ty, C);
      }
        break;
      default:
        StreamValue(o, V.getPtr(), Ty, C);
        break;
      }
    }
    else if (Ty->isIntegralOrEnumerationType()) {
      long long res = V.getLL();
      StreamValue(o, &res, Ty, C);
    }
    else if (Ty->isFunctionType())
      StreamValue(o, &V, Ty, C);
    else
      StreamValue(o, V.getPtr(), Ty, C);
  }

  void printType_Default(llvm::raw_ostream& o, const Value& V) {
    o << "(";
    o << V.getType().getAsString();
    o << ") ";
  }

  void flushToStream(llvm::raw_ostream& o, const std::string& s) {
    // We want to keep stdout and o in sync if o is different from stdout.
    fflush(stdout);
    o << s;
    o.flush();
  }
} // end namespace valuePrinterInternal
} // end namespace cling
<|endoftext|>