<commit_before>/*
 * Copyright (c) 2008 James Molloy, Jörg Pfähler, Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "Tcp.h"
#include <Module.h>
#include <Log.h>

#include "Ethernet.h"
#include "Ipv4.h"
#include "Ipv6.h"

#include "TcpManager.h"

#include "RoutingTable.h"

#include "Filter.h"

#include "Arp.h"
#include "IpCommon.h"

Tcp Tcp::tcpInstance;

Tcp::Tcp()
{
}

Tcp::~Tcp()
{
}

bool Tcp::send(IpAddress dest, uint16_t srcPort, uint16_t destPort, uint32_t seqNumber, uint32_t ackNumber, uint8_t flags, uint16_t window, size_t nBytes, uintptr_t payload)
{
  // IP base for all operations here.
  IpBase *pIp = &Ipv4::instance();
  if(dest.getType() == IpAddress::IPv6)
    pIp = &Ipv6::instance();

  // Grab the NIC to send on.
  /// \note The NIC is grabbed here *as well as* IP because we need to use the
  ///       NIC IP address for the checksum.
  IpAddress tmp = dest;
  Network* pCard = RoutingTable::instance().DetermineRoute(&tmp);
  if(!pCard)
  {
      WARNING("TCP: Couldn't find a route for destination '" << dest.toString() << "'.");
      return false;
  }

  // Grab information about ourselves
  StationInfo me = pCard->getStationInfo();

  // Lookup the MAC address of our target
  MacAddress destMac;
  bool macValid = true;
  if(dest == me.broadcast)
    destMac.setMac(0xff);
  else
    macValid = Arp::instance().getFromCache(tmp, true, &destMac, pCard);

  if(!macValid)
  {
    WARNING("TCP: Couldn't get a MAC address for the remote host (" << tmp.toString() << ")");
    return false;
  }

  // Allocate a packet to send
  uintptr_t packet = NetworkStack::instance().getMemPool().allocate();

  // Grab the ethernet header
  size_t ethSize = Ethernet::instance().injectHeader(packet, destMac, me.mac, dest.getType());
  if(!ethSize)
  {
    WARNING("TCP: Couldn't inject an ethernet header");
    NetworkStack::instance().getMemPool().free(packet);
    return false;
  }

  // Grab the IPv4 header
  size_t ipSize = pIp->injectHeader(packet + ethSize, dest, me.ipv4, IP_TCP);
  if(!ipSize)
  {
    WARNING("TCP: Couldn't inject an IPv4 header");
    NetworkStack::instance().getMemPool().free(packet);
    return false;
  }

  // Got everything we need - create TCP header
  uintptr_t tcpPacket = packet + ethSize + ipSize;
  tcpHeader* header = reinterpret_cast<tcpHeader*>(tcpPacket);
  header->src_port = HOST_TO_BIG16(srcPort);
  header->dest_port = HOST_TO_BIG16(destPort);
  header->seqnum = HOST_TO_BIG32(seqNumber);
  header->acknum = HOST_TO_BIG32(ackNumber);
  header->offset = sizeof(tcpHeader) / 4;

  header->rsvd = 0;
  header->flags = flags;
  header->winsize = HOST_TO_BIG16(window);
  header->urgptr = 0;

  if(payload && nBytes)
    memcpy(reinterpret_cast<void*>(tcpPacket + sizeof(tcpHeader)), reinterpret_cast<void*>(payload), nBytes);

  header->checksum = 0;
  header->checksum = pIp->ipChecksum(me.ipv4, dest, IP_TCP, tcpPacket, nBytes + sizeof(tcpHeader));

  // Perfom an IPv4 checksum over the packet
  pIp->injectChecksumAndDataFields(packet + ethSize, nBytes + sizeof(tcpHeader));

  // Transmit
  bool success = pCard->send(nBytes + sizeof(tcpHeader) + ipSize + ethSize, packet);
  if(!success)
    WARNING("TCP: Network card failed to transmit a packet");

  // Free the created packet
  NetworkStack::instance().getMemPool().free(packet);

  // All done.
  return success;
}

void Tcp::receive(IpAddress from, size_t nBytes, uintptr_t packet, Network* pCard, uint32_t offset)
{
  if(!packet || !nBytes)
      return;

  /// \todo Lower layer should give us more information!

  IpBase *pIp = 0;

  size_t tcpHeaderOffset = 0;
  size_t tcpPayloadSize = 0;
  IpAddress to;
  if(from.getType() == IpAddress::IPv6)
  {
    // Yay assumptions.
    /// \todo Fix this to not explode when extension headers are present
    tcpHeaderOffset = sizeof(Ipv6::ip6Header);
    to.setIp(reinterpret_cast<Ipv6::ip6Header*>(packet + offset)->destAddress);

    tcpPayloadSize = BIG_TO_HOST16(reinterpret_cast<Ipv6::ip6Header*>(packet + offset)->payloadLength) - tcpHeaderOffset;

    pIp = &Ipv4::instance();
  }
  else
  {
    // grab the IP header to find the size, so we can skip options and get to the UDP header
    Ipv4::ipHeader* ip = reinterpret_cast<Ipv4::ipHeader*>(packet + offset);
    tcpHeaderOffset = (ip->header_len) * 4; // len is the number of DWORDs
    to.setIp(ip->ipDest);

    tcpPayloadSize = BIG_TO_HOST16(ip->len) - tcpHeaderOffset;

    pIp = &Ipv6::instance();
  }

  // Check for filtering
  /// \todo Add statistics to NICs
  if(!NetworkFilter::instance().filter(3, packet + offset + tcpHeaderOffset, nBytes - offset - tcpHeaderOffset))
  {
    pCard->droppedPacket();
    return;
  }

  // check if this packet is for us, or if it's a broadcast
  /// \todo IPv6
  StationInfo cardInfo = pCard->getStationInfo();
  if(from.getType() == IpAddress::IPv4 &&
     cardInfo.ipv4 != to &&
     to.getIp() != 0xffffffff &&
     cardInfo.broadcast != to)
  {
    // not for us (depending on future requirements, we may need to implement a "catch-all"
    // flag in the same way as UDP)
    return;
  }

  // grab the header now
  tcpHeader* header = reinterpret_cast<tcpHeader*>(packet + offset + tcpHeaderOffset);

  // the size of the header (+ options)
  size_t headerSize = header->offset * 4;

  // find the payload and its size - tcpHeader::len is the size of the header + data
  // we use it rather than calculating the size from offsets in order to be able to handle
  // packets that may have been padded (for whatever reason)
  uintptr_t payload = reinterpret_cast<uintptr_t>(header) + (header->offset * 4); // offset is in DWORDs
  size_t payloadSize = tcpPayloadSize - headerSize; //  (packet + nBytes) - payload;

  // check the checksum, if it's not zero
  if(header->checksum != 0)
  {
    uint16_t checksum = pIp->ipChecksum(from, to, IP_TCP, reinterpret_cast<uintptr_t>(header), tcpPayloadSize);
    if(checksum)
    {
      WARNING("TCP Checksum failed on incoming packet [dp=" << Dec << BIG_TO_HOST16(header->dest_port) << Hex << "]. Header checksum is " << header->checksum << ", calculated should be zero but is " << checksum << "!");
      pCard->badPacket();
      return;
    }
  }
  else
  {
      WARNING("TCP Packet arrived on port " << Dec << BIG_TO_HOST16(header->dest_port) << Hex << " without a checksum.");
      pCard->badPacket();
      return; // must have a checksum
  }

  // NOTICE("TCP: Packet has arrived! Dest port is " << Dec << BIG_TO_HOST16(header->dest_port) << Hex << " and flags are " << header->flags << ".");

  // either no checksum, or calculation was successful, either way go on to handle it
  TcpManager::instance().receive(from, BIG_TO_HOST16(header->src_port), BIG_TO_HOST16(header->dest_port), header, payload, payloadSize, pCard);
}
<commit_msg>Network: TCP send fixed in the same way as UDP send. TCP is totally broken still, checksum issues (yay!).<commit_after>/*
 * Copyright (c) 2008 James Molloy, Jörg Pfähler, Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "Tcp.h"
#include <Module.h>
#include <Log.h>

#include "Ethernet.h"
#include "Ipv4.h"
#include "Ipv6.h"

#include "TcpManager.h"

#include "RoutingTable.h"

#include "Filter.h"

#include "Arp.h"
#include "IpCommon.h"

Tcp Tcp::tcpInstance;

Tcp::Tcp()
{
}

Tcp::~Tcp()
{
}

bool Tcp::send(IpAddress dest, uint16_t srcPort, uint16_t destPort, uint32_t seqNumber, uint32_t ackNumber, uint8_t flags, uint16_t window, size_t nBytes, uintptr_t payload)
{
  // IP base for all operations here.
  IpBase *pIp = &Ipv4::instance();
  if(dest.getType() == IpAddress::IPv6)
    pIp = &Ipv6::instance();

  // Grab the NIC to send on.
  /// \note The NIC is grabbed here *as well as* IP because we need to use the
  ///       NIC IP address for the checksum.
  IpAddress tmp = dest;
  Network* pCard = RoutingTable::instance().DetermineRoute(&tmp);
  if(!pCard)
  {
      WARNING("TCP: Couldn't find a route for destination '" << dest.toString() << "'.");
      return false;
  }

  // Grab information about ourselves
  StationInfo me = pCard->getStationInfo();

  // Lookup the MAC address of our target
  MacAddress destMac;
  bool macValid = true;
  if(dest == me.broadcast)
    destMac.setMac(0xff);
  else
    macValid = Arp::instance().getFromCache(tmp, true, &destMac, pCard);

  if(!macValid)
  {
    WARNING("TCP: Couldn't get a MAC address for the remote host (" << tmp.toString() << ")");
    return false;
  }

  // Allocate a packet to send
  uintptr_t packet = NetworkStack::instance().getMemPool().allocate();

  // Create TCP header
  uintptr_t tcpPacket = packet;
  tcpHeader* header = reinterpret_cast<tcpHeader*>(tcpPacket);
  header->src_port = HOST_TO_BIG16(srcPort);
  header->dest_port = HOST_TO_BIG16(destPort);
  header->seqnum = HOST_TO_BIG32(seqNumber);
  header->acknum = HOST_TO_BIG32(ackNumber);
  header->offset = sizeof(tcpHeader) / 4;

  header->rsvd = 0;
  header->flags = flags;
  header->winsize = HOST_TO_BIG16(window);
  header->urgptr = 0;

  // Inject the payload
  if(payload && nBytes)
    memcpy(reinterpret_cast<void*>(tcpPacket + sizeof(tcpHeader)), reinterpret_cast<void*>(payload), nBytes);

  header->checksum = 0;

  /// \todo IPv4-specific
  header->checksum = pIp->ipChecksum(me.ipv4, dest, IP_TCP, tcpPacket, nBytes + sizeof(tcpHeader));

  // Transmit
  bool success = pIp->send(me.ipv4, dest, IP_TCP, nBytes + sizeof(tcpHeader), packet, pCard);

  // Free the created packet
  NetworkStack::instance().getMemPool().free(packet);

  // All done.
  return success;
}

void Tcp::receive(IpAddress from, size_t nBytes, uintptr_t packet, Network* pCard, uint32_t offset)
{
  if(!packet || !nBytes)
      return;

  /// \todo Lower layer should give us more information!

  IpBase *pIp = 0;

  size_t tcpHeaderOffset = 0;
  size_t tcpPayloadSize = 0;
  IpAddress to;
  if(from.getType() == IpAddress::IPv6)
  {
    // Yay assumptions.
    /// \todo Fix this to not explode when extension headers are present
    tcpHeaderOffset = sizeof(Ipv6::ip6Header);
    to.setIp(reinterpret_cast<Ipv6::ip6Header*>(packet + offset)->destAddress);

    tcpPayloadSize = BIG_TO_HOST16(reinterpret_cast<Ipv6::ip6Header*>(packet + offset)->payloadLength) - tcpHeaderOffset;

    pIp = &Ipv4::instance();
  }
  else
  {
    // grab the IP header to find the size, so we can skip options and get to the UDP header
    Ipv4::ipHeader* ip = reinterpret_cast<Ipv4::ipHeader*>(packet + offset);
    tcpHeaderOffset = (ip->header_len) * 4; // len is the number of DWORDs
    to.setIp(ip->ipDest);

    tcpPayloadSize = BIG_TO_HOST16(ip->len) - tcpHeaderOffset;

    pIp = &Ipv6::instance();
  }

  // Check for filtering
  /// \todo Add statistics to NICs
  if(!NetworkFilter::instance().filter(3, packet + offset + tcpHeaderOffset, nBytes - offset - tcpHeaderOffset))
  {
    pCard->droppedPacket();
    return;
  }

  // check if this packet is for us, or if it's a broadcast
  /// \todo IPv6
  StationInfo cardInfo = pCard->getStationInfo();
  if(from.getType() == IpAddress::IPv4 &&
     cardInfo.ipv4 != to &&
     to.getIp() != 0xffffffff &&
     cardInfo.broadcast != to)
  {
    // not for us (depending on future requirements, we may need to implement a "catch-all"
    // flag in the same way as UDP)
    return;
  }

  // grab the header now
  tcpHeader* header = reinterpret_cast<tcpHeader*>(packet + offset + tcpHeaderOffset);

  // the size of the header (+ options)
  size_t headerSize = header->offset * 4;

  // find the payload and its size - tcpHeader::len is the size of the header + data
  // we use it rather than calculating the size from offsets in order to be able to handle
  // packets that may have been padded (for whatever reason)
  uintptr_t payload = reinterpret_cast<uintptr_t>(header) + (header->offset * 4); // offset is in DWORDs
  size_t payloadSize = tcpPayloadSize - headerSize; //  (packet + nBytes) - payload;

  // check the checksum, if it's not zero
  if(header->checksum != 0)
  {
    uint16_t checksum = pIp->ipChecksum(from, to, IP_TCP, reinterpret_cast<uintptr_t>(header), tcpPayloadSize);
    if(checksum)
    {
      WARNING("TCP Checksum failed on incoming packet [dp=" << Dec << BIG_TO_HOST16(header->dest_port) << Hex << "]. Header checksum is " << header->checksum << ", calculated should be zero but is " << checksum << "!");
      pCard->badPacket();
      return;
    }
  }
  else
  {
      WARNING("TCP Packet arrived on port " << Dec << BIG_TO_HOST16(header->dest_port) << Hex << " without a checksum.");
      pCard->badPacket();
      return; // must have a checksum
  }

  // NOTICE("TCP: Packet has arrived! Dest port is " << Dec << BIG_TO_HOST16(header->dest_port) << Hex << " and flags are " << header->flags << ".");

  // either no checksum, or calculation was successful, either way go on to handle it
  TcpManager::instance().receive(from, BIG_TO_HOST16(header->src_port), BIG_TO_HOST16(header->dest_port), header, payload, payloadSize, pCard);
}
<|endoftext|>


<commit_before>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2019 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_GRAPHICS_COLOR_GRADIENT_HPP
#define OPENMVG_GRAPHICS_COLOR_GRADIENT_HPP

#include <vector>

namespace openMVG
{
namespace graphics
{

// Port made from http://www.andrewnoske.com/wiki/Code_-_heatmaps_and_color_gradients
// - Use c++11 style
// - Add multiple possible color gradient initialization
//
// --------------------
// How to use the code:
// --------------------
// 1. Create the object and configure the color gradient
// --------------------
// Color_Gradient heatMapGradient(Color_Gradient::k2BlueRedHeatMap());
// // Re-Initialize to use a gradient based on 5 colors
// //heatMapGradient = Color_Gradient(Color_Gradient::k5ColorHeatMap());
// --------------------
// 2. Get the color corresponding to the % range you want
// --------------------
// float r,g,b;
// const float interpolated_ratio = .5f;
// heatMapGradient.getColor(interpolated_ratio, r, g, b);
// // [r,g,b] are in the range [0, 1]
//
class Color_Gradient
{
public:
  struct Color_Point  // Internal class used to store colors at different points in the gradient.
  {
    float r, g, b;   // Red, green and blue values of our color.
    float val;       // Position of our color along the gradient (between 0 and 1).
    Color_Point(float red, float green, float blue, float value)
      : r(red), g(green), b(blue), val(value) {}
  };

  using Color_Points = std::vector<Color_Point>;

  //-- Places a 5 color heatmap gradient into the "color" vector:
  static const Color_Points k5ColorHeatMap()
  {
    return
    {
      {0, 0, 1,   0.0f},      // Blue
      {0, 1, 1,   0.25f},     // Cyan
      {0, 1, 0,   0.5f},      // Green
      {1, 1, 0,   0.75f},     // Yellow
      {1, 0, 0,   1.0f}       // Red
    };
  }

  //-- Places a 2 color heatmap gradient (Blue to Red):
  static const Color_Points k2BlueRedHeatMap()
  {
    return
    {
      {0, 0, 1,   0.0f}, // Blue
      {1, 0, 0,   1.0f}  // Red
    };
  }

private:
  Color_Points color_map;      // An array of color points in ascending value

public:
  //-- Default constructor:
  Color_Gradient(const Color_Points & rhs_color = k5ColorHeatMap())
    : color_map(rhs_color)  {}

  //-- Inputs a (value) between 0 and 1 and outputs the (red), (green) and (blue)
  //-- values representing that position in the gradient.
  void getColor
  (
    const float value,
    float & red,
    float & green,
    float & blue
  ) const
  {
    if (color_map.empty())
      return;

    for (int i = 0; i < color_map.size(); ++i)
    {
      const Color_Point &currC = color_map[i];
      if (value < currC.val)
      {
        const Color_Point &prevC  = color_map[ std::max(0, i-1) ];
        const float valueDiff    = (prevC.val - currC.val);
        const float fractBetween = (valueDiff==0) ? 0 : (value - currC.val) / valueDiff;
        red   = (prevC.r - currC.r) * fractBetween + currC.r;
        green = (prevC.g - currC.g) * fractBetween + currC.g;
        blue  = (prevC.b - currC.b) * fractBetween + currC.b;
        return;
      }
    }
    red   = color_map.back().r;
    green = color_map.back().g;
    blue  = color_map.back().b;
    return;
  }
};

} // namespace graphics
} // namespace openMVG

#endif // OPENMVG_GRAPHICS_COLOR_GRADIENT_HPP
<commit_msg>[graphics] Add explicit to Color_Gradient constructor (C++). #1594<commit_after>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2019 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_GRAPHICS_COLOR_GRADIENT_HPP
#define OPENMVG_GRAPHICS_COLOR_GRADIENT_HPP

#include <vector>

namespace openMVG
{
namespace graphics
{

// Port made from http://www.andrewnoske.com/wiki/Code_-_heatmaps_and_color_gradients
// - Use c++11 style
// - Add multiple possible color gradient initialization
//
// --------------------
// How to use the code:
// --------------------
// 1. Create the object and configure the color gradient
// --------------------
// Color_Gradient heatMapGradient(Color_Gradient::k2BlueRedHeatMap());
// // Re-Initialize to use a gradient based on 5 colors
// //heatMapGradient = Color_Gradient(Color_Gradient::k5ColorHeatMap());
// --------------------
// 2. Get the color corresponding to the % range you want
// --------------------
// float r,g,b;
// const float interpolated_ratio = .5f;
// heatMapGradient.getColor(interpolated_ratio, r, g, b);
// // [r,g,b] are in the range [0, 1]
//
class Color_Gradient
{
public:
  struct Color_Point  // Internal class used to store colors at different points in the gradient.
  {
    float r, g, b;   // Red, green and blue values of our color.
    float val;       // Position of our color along the gradient (between 0 and 1).
    Color_Point(float red, float green, float blue, float value)
      : r(red), g(green), b(blue), val(value) {}
  };

  using Color_Points = std::vector<Color_Point>;

  //-- Places a 5 color heatmap gradient into the "color" vector:
  static const Color_Points k5ColorHeatMap()
  {
    return
    {
      {0, 0, 1,   0.0f},      // Blue
      {0, 1, 1,   0.25f},     // Cyan
      {0, 1, 0,   0.5f},      // Green
      {1, 1, 0,   0.75f},     // Yellow
      {1, 0, 0,   1.0f}       // Red
    };
  }

  //-- Places a 2 color heatmap gradient (Blue to Red):
  static const Color_Points k2BlueRedHeatMap()
  {
    return
    {
      {0, 0, 1,   0.0f}, // Blue
      {1, 0, 0,   1.0f}  // Red
    };
  }

private:
  Color_Points color_map;      // An array of color points in ascending value

public:
  //-- Default constructor:
  explicit Color_Gradient(const Color_Points & rhs_color = k5ColorHeatMap())
    : color_map(rhs_color)  {}

  //-- Inputs a (value) between 0 and 1 and outputs the (red), (green) and (blue)
  //-- values representing that position in the gradient.
  void getColor
  (
    const float value,
    float & red,
    float & green,
    float & blue
  ) const
  {
    if (color_map.empty())
      return;

    for (int i = 0; i < color_map.size(); ++i)
    {
      const Color_Point &currC = color_map[i];
      if (value < currC.val)
      {
        const Color_Point &prevC  = color_map[ std::max(0, i-1) ];
        const float valueDiff    = (prevC.val - currC.val);
        const float fractBetween = (valueDiff==0) ? 0 : (value - currC.val) / valueDiff;
        red   = (prevC.r - currC.r) * fractBetween + currC.r;
        green = (prevC.g - currC.g) * fractBetween + currC.g;
        blue  = (prevC.b - currC.b) * fractBetween + currC.b;
        return;
      }
    }
    red   = color_map.back().r;
    green = color_map.back().g;
    blue  = color_map.back().b;
    return;
  }
};

} // namespace graphics
} // namespace openMVG

#endif // OPENMVG_GRAPHICS_COLOR_GRADIENT_HPP
<|endoftext|>


<commit_before>/**
 * Autogenerated by Thrift
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */

#include "src/gen-cpp2/module2_constants.h"

#include <folly/Indestructible.h>

namespace module2 {

 ::module2::Struct const& module2_constants::c2() {
  static folly::Indestructible< ::module2::Struct> const instance( ::module2::Struct(::apache::thrift::detail::wrap_argument<1>( ::module0::Struct(::apache::thrift::detail::wrap_argument<1>(101), ::apache::thrift::detail::wrap_argument<2>(apache::thrift::StringTraits< std::string>::fromStringLiteral("module0_str")))), ::apache::thrift::detail::wrap_argument<2>( ::module1::Struct(::apache::thrift::detail::wrap_argument<1>(201), ::apache::thrift::detail::wrap_argument<2>(apache::thrift::StringTraits< std::string>::fromStringLiteral("module1_str"))))));
  return *instance;
}

 ::module2::Struct const& module2_constants::c3() {
  static folly::Indestructible< ::module2::Struct> const instance( ::module2::Struct(::apache::thrift::detail::wrap_argument<1>( ::module0::Struct(::apache::thrift::detail::wrap_argument<1>(101), ::apache::thrift::detail::wrap_argument<2>(apache::thrift::StringTraits< std::string>::fromStringLiteral("module0_str")))), ::apache::thrift::detail::wrap_argument<2>( ::module1::Struct(::apache::thrift::detail::wrap_argument<1>(201), ::apache::thrift::detail::wrap_argument<2>(apache::thrift::StringTraits< std::string>::fromStringLiteral("module1_str"))))));
  return *instance;
}

 ::module2::Struct const& module2_constants::c4() {
  static folly::Indestructible< ::module2::Struct> const instance( ::module2::Struct(::apache::thrift::detail::wrap_argument<1>( ::module0::Struct(::apache::thrift::detail::wrap_argument<1>(101), ::apache::thrift::detail::wrap_argument<2>(apache::thrift::StringTraits< std::string>::fromStringLiteral("module0_str")))), ::apache::thrift::detail::wrap_argument<2>( ::module1::Struct(::apache::thrift::detail::wrap_argument<1>(201), ::apache::thrift::detail::wrap_argument<2>(apache::thrift::StringTraits< std::string>::fromStringLiteral("module1_str"))))));
  return *instance;
}

} // module2
<commit_msg>Rebuild compiler test fixtures<commit_after>/**
 * Autogenerated by Thrift
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */

#include "src/gen-cpp2/module2_constants.h"

#include "thrift/compiler/test/fixtures/qualified/gen-cpp2/module0_constants.h"
#include "thrift/compiler/test/fixtures/qualified/gen-cpp2/module1_constants.h"
#include <folly/Indestructible.h>

namespace module2 {

 ::module2::Struct const& module2_constants::c2() {
  static folly::Indestructible< ::module2::Struct> const instance( ::module2::Struct(::apache::thrift::detail::wrap_argument<1>( ::module0::Struct(::module0::module0_constants::c0())), ::apache::thrift::detail::wrap_argument<2>( ::module1::Struct(::module1::module1_constants::c1()))));
  return *instance;
}

 ::module2::Struct const& module2_constants::c3() {
  static folly::Indestructible< ::module2::Struct> const instance( ::module2::Struct(::module2::module2_constants::c2()));
  return *instance;
}

 ::module2::Struct const& module2_constants::c4() {
  static folly::Indestructible< ::module2::Struct> const instance( ::module2::Struct(::module2::module2_constants::c2()));
  return *instance;
}

} // module2
<|endoftext|>


<commit_before>#include "forumthreadpool.h"

#include <website_backend/gumboparserimpl.h>

ForumThreadPool::ForumThreadPool(QObject *parent) : QObject(parent)
{
}

ForumThreadPool::~ForumThreadPool()
{
}

size_t ForumThreadPool::pageCountCacheSize() const
{
    return m_threadPageCountCollection.size() * (sizeof(ForumThreadUrlData) + sizeof(int));
}

namespace {
size_t postListSize(const bfr::PostList &posts)
{
    return posts.size() * (sizeof(bfr::PostPtr));
}
}

size_t ForumThreadPool::pagePostsCacheSize() const
{
    size_t result;
    for (const auto &urlKey : m_threadPagePostCollection.keys())
    {
        result += sizeof(ForumThreadUrlData);

        for (const auto &pageNoKey : m_threadPagePostCollection.value(urlKey).keys())
        {
            result += sizeof(int);
            result += postListSize(m_threadPagePostCollection.value(urlKey).value(pageNoKey));
        }
    }
    return result;
}

void ForumThreadPool::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    emit downloadProgress(bytesReceived, bytesTotal);
}

ForumThreadPool &ForumThreadPool::globalInstance()
{
    // Since it's a static variable, if the class has already been created, it won't be created again.
    // And it **is** thread-safe in C++11.
    static ForumThreadPool instance;
    return instance;
}

result_code::Type ForumThreadPool::getForumThreadPageCount(ForumThreadUrlData urlData, int &pageCount)
{
    QScopedPointer<ForumThreadUrl> url(new ForumThreadUrl(urlData.m_sectionId, urlData.m_threadId));

    if (m_threadPageCountCollection.contains(urlData))
    {
        pageCount = m_threadPageCountCollection.value(urlData);

        ConsoleLogger->debug("Got forum thread '{}' page count ({}) from pagecount-cache", url->firstPageUrl(), pageCount);
        return result_code::Type::Ok;
    }

    // 1) Download the first forum web page
    ConsoleLogger->debug("Forum thread '{}' was not parsed yet, no page count in the pagecount-cache", url->firstPageUrl());
    ConsoleLogger->debug("Downloading first page of forum thread '{}'...", url->firstPageUrl());
    QByteArray htmlRawData;
    BFR_RETURN_VALUE_IF(!FileDownloader::downloadUrl(url->firstPageUrl(), htmlRawData,
                                                     std::bind(&ForumThreadPool::onDownloadProgress, this, std::placeholders::_1, std::placeholders::_2)),
                        result_code::Type::NetworkError,
                        "Unable to download first forum thread page");
    ConsoleLogger->debug("Forum thread '{}' first page has been downloaded", url->firstPageUrl());

    // 2) Parse the page HTML to get the page count
    bfr::ForumPageParser fpp;
    int pageCountTemp = -1;
    ConsoleLogger->debug("Parsing first page of forum thread '{}'...", url->firstPageUrl());
    result_code::Type result = fpp.getPageCount(htmlRawData, pageCountTemp);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to parse first forum thread page");
    ConsoleLogger->debug("Forum thread '{}' first page has been parsed", url->firstPageUrl());

    // 4) Update cache
    pageCount = pageCountTemp;
    m_threadPageCountCollection.insert(urlData, pageCount);
    ConsoleLogger->debug("Forum thread '{}' page count ({}) was added to pagecount-cache", url->firstPageUrl(), pageCount);
    ConsoleLogger->debug("New size of pagecount-cache: {} bytes", pageCountCacheSize());
    return result_code::Type::Ok;
}

result_code::Type ForumThreadPool::getForumPagePosts(ForumThreadUrlData urlData, int pageNo, bfr::PostList &posts)
{
    QScopedPointer<ForumThreadUrl> url(new ForumThreadUrl(urlData.m_sectionId, urlData.m_threadId));

    if (m_threadPagePostCollection.contains(urlData))
    {
        if (m_threadPagePostCollection.value(urlData).contains(pageNo))
        {
            posts = m_threadPagePostCollection.value(urlData).value(pageNo);

            ConsoleLogger->debug("Got forum thread '{}' page posts (size = {}) from pageposts-cache", url->pageUrl(pageNo), posts.size());
            return result_code::Type::Ok;
        }
    }

    // 1) Download the first forum web page
    ConsoleLogger->debug("Forum thread '{}' was not parsed yet, no page posts in the pageposts-cache", url->pageUrl(pageNo));
    ConsoleLogger->debug("Downloading first page of forum thread '{}'...", url->pageUrl(pageNo));
    QByteArray htmlRawData;
    BFR_RETURN_VALUE_IF(!FileDownloader::downloadUrl(
                            url->pageUrl(pageNo), htmlRawData,
                            std::bind(&ForumThreadPool::onDownloadProgress, this, std::placeholders::_1, std::placeholders::_2)),
                            result_code::Type::NetworkError,
                            "Unable to download specified forum thread page");
    ConsoleLogger->debug("Forum thread '{}' specified page has been downloaded", url->pageUrl(pageNo));

    // 2) Parse the page HTML to get the page count
    bfr::ForumPageParser fpp;
    int pageCount = -1;
    ConsoleLogger->debug("Parsing specified page of forum thread '{}': page count...", url->pageUrl(pageNo));
    result_code::Type result = fpp.getPageCount(htmlRawData, pageCount);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to parse specified forum thread page");
    ConsoleLogger->debug("Forum thread '{}' specified page has been parsed: page count", url->pageUrl(pageNo));

    // 3) Parse the page HTML to get the page user posts
    bfr::PostList postsTemp;
    ConsoleLogger->debug("Parsing specified page of forum thread '{}': page posts...", url->pageUrl(pageNo));
    result = fpp.getPagePosts(htmlRawData, postsTemp);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to parse specified forum thread page");
    ConsoleLogger->debug("Forum thread '{}' specified page has been parsed: page posts", url->pageUrl(pageNo));

    // 4) Update cache
    m_threadPagePostCollection[urlData][pageNo] = postsTemp;
    posts.swap(postsTemp);
    ConsoleLogger->debug("Forum thread '{}' page posts (count: {}) was added to pageposts-cache", url->pageUrl(pageNo), posts.size());
    ConsoleLogger->debug("New size of pageposts-cache: {} bytes", pagePostsCacheSize());
    return result_code::Type::Ok;
}

result_code::Type ForumThreadPool::getForumThreadPosts(ForumThreadUrlData urlData, bfr::PostList &posts)
{
    QScopedPointer<ForumThreadUrl> url(new ForumThreadUrl(urlData.m_sectionId, urlData.m_threadId));

    // 1) Get thread page count
    int pageCount = -1;
    result_code::Type result = getForumThreadPageCount(urlData, pageCount);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to get forum thread page count");

    // 2) Load and parse absent pages
    bfr::PostList postsTemp;
    for (int i = 1; i <= pageCount; i++)
    {
        result = getForumPagePosts(urlData, i, postsTemp);
        BFR_RETURN_VALUE_IF(result_code::failed(result),
                            result,
                            "Unable to get specified forum thread page posts");

        posts << postsTemp;
        postsTemp.clear();

        emit threadParseProgress(i, pageCount);
    }

    ConsoleLogger->debug("Forum thread '{}' posts has been parsed", url->firstPageUrl());
    return result_code::Type::Ok;
}
<commit_msg>Parser frontend: several issues fixed<commit_after>#include "forumthreadpool.h"

#include <website_backend/gumboparserimpl.h>

ForumThreadPool::ForumThreadPool(QObject *parent) : QObject(parent)
{
}

ForumThreadPool::~ForumThreadPool()
{
}

size_t ForumThreadPool::pageCountCacheSize() const
{
    return static_cast<size_t>(m_threadPageCountCollection.size()) * (sizeof(ForumThreadUrlData) + sizeof(int));
}

namespace {
size_t postListSize(const bfr::PostList &posts)
{
    return static_cast<size_t>(posts.size()) * (sizeof(bfr::PostPtr));
}
}

size_t ForumThreadPool::pagePostsCacheSize() const
{
    size_t result = 0;
    for (const auto &urlKey : m_threadPagePostCollection.keys())
    {
        result += sizeof(ForumThreadUrlData);

        for (const auto &pageNoKey : m_threadPagePostCollection.value(urlKey).keys())
        {
            result += sizeof(int);
            result += postListSize(m_threadPagePostCollection.value(urlKey).value(pageNoKey));
        }
    }
    return result;
}

void ForumThreadPool::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    emit downloadProgress(bytesReceived, bytesTotal);
}

ForumThreadPool &ForumThreadPool::globalInstance()
{
    // Since it's a static variable, if the class has already been created, it won't be created again.
    // And it **is** thread-safe in C++11.
    static ForumThreadPool instance;
    return instance;
}

result_code::Type ForumThreadPool::getForumThreadPageCount(ForumThreadUrlData urlData, int &pageCount)
{
    QScopedPointer<ForumThreadUrl> url(new ForumThreadUrl(urlData.m_sectionId, urlData.m_threadId));

    if (m_threadPageCountCollection.contains(urlData))
    {
        pageCount = m_threadPageCountCollection.value(urlData);

        ConsoleLogger->debug("Got forum thread '{}' page count ({}) from pagecount-cache", url->firstPageUrl(), pageCount);
        return result_code::Type::Ok;
    }

    // 1) Download the first forum web page
    ConsoleLogger->debug("Forum thread '{}' was not parsed yet, no page count in the pagecount-cache", url->firstPageUrl());
    ConsoleLogger->debug("Downloading first page of forum thread '{}'...", url->firstPageUrl());
    QByteArray htmlRawData;
    BFR_RETURN_VALUE_IF(!FileDownloader::downloadUrl(url->firstPageUrl(), htmlRawData,
                                                     std::bind(&ForumThreadPool::onDownloadProgress, this, std::placeholders::_1, std::placeholders::_2)),
                        result_code::Type::NetworkError,
                        "Unable to download first forum thread page");
    ConsoleLogger->debug("Forum thread '{}' first page has been downloaded", url->firstPageUrl());

    // 2) Parse the page HTML to get the page count
    bfr::ForumPageParser fpp;
    int pageCountTemp = -1;
    ConsoleLogger->debug("Parsing first page of forum thread '{}'...", url->firstPageUrl());
    result_code::Type result = fpp.getPageCount(htmlRawData, pageCountTemp);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to parse first forum thread page");
    ConsoleLogger->debug("Forum thread '{}' first page has been parsed", url->firstPageUrl());

    // 4) Update cache
    pageCount = pageCountTemp;
    m_threadPageCountCollection.insert(urlData, pageCount);
    ConsoleLogger->debug("Forum thread '{}' page count ({}) was added to pagecount-cache", url->firstPageUrl(), pageCount);
    ConsoleLogger->debug("New size of pagecount-cache: {} bytes", pageCountCacheSize());
    return result_code::Type::Ok;
}

result_code::Type ForumThreadPool::getForumPagePosts(ForumThreadUrlData urlData, int pageNo, bfr::PostList &posts)
{
    QScopedPointer<ForumThreadUrl> url(new ForumThreadUrl(urlData.m_sectionId, urlData.m_threadId));

    if (m_threadPagePostCollection.contains(urlData))
    {
        if (m_threadPagePostCollection.value(urlData).contains(pageNo))
        {
            posts = m_threadPagePostCollection.value(urlData).value(pageNo);

            ConsoleLogger->debug("Got forum thread '{}' page posts (size = {}) from pageposts-cache", url->pageUrl(pageNo), posts.size());
            return result_code::Type::Ok;
        }
    }

    // 1) Download the first forum web page
    ConsoleLogger->debug("Forum thread '{}' was not parsed yet, no page posts in the pageposts-cache", url->pageUrl(pageNo));
    ConsoleLogger->debug("Downloading first page of forum thread '{}'...", url->pageUrl(pageNo));
    QByteArray htmlRawData;
    BFR_RETURN_VALUE_IF(!FileDownloader::downloadUrl(
                            url->pageUrl(pageNo), htmlRawData,
                            std::bind(&ForumThreadPool::onDownloadProgress, this, std::placeholders::_1, std::placeholders::_2)),
                            result_code::Type::NetworkError,
                            "Unable to download specified forum thread page");
    ConsoleLogger->debug("Forum thread '{}' specified page has been downloaded", url->pageUrl(pageNo));

    // 2) Parse the page HTML to get the page count
    bfr::ForumPageParser fpp;
    int pageCount = -1;
    ConsoleLogger->debug("Parsing specified page of forum thread '{}': page count...", url->pageUrl(pageNo));
    result_code::Type result = fpp.getPageCount(htmlRawData, pageCount);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to parse specified forum thread page");
    ConsoleLogger->debug("Forum thread '{}' specified page has been parsed: page count", url->pageUrl(pageNo));

    // 3) Parse the page HTML to get the page user posts
    bfr::PostList postsTemp;
    ConsoleLogger->debug("Parsing specified page of forum thread '{}': page posts...", url->pageUrl(pageNo));
    result = fpp.getPagePosts(htmlRawData, postsTemp);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to parse specified forum thread page");
    ConsoleLogger->debug("Forum thread '{}' specified page has been parsed: page posts", url->pageUrl(pageNo));

    // 4) Update cache
    m_threadPagePostCollection[urlData][pageNo] = postsTemp;
    posts.swap(postsTemp);
    ConsoleLogger->debug("Forum thread '{}' page posts (count: {}) was added to pageposts-cache", url->pageUrl(pageNo), posts.size());
    ConsoleLogger->debug("New size of pageposts-cache: {} bytes", pagePostsCacheSize());
    return result_code::Type::Ok;
}

result_code::Type ForumThreadPool::getForumThreadPosts(ForumThreadUrlData urlData, bfr::PostList &posts)
{
    QScopedPointer<ForumThreadUrl> url(new ForumThreadUrl(urlData.m_sectionId, urlData.m_threadId));

    // 1) Get thread page count
    int pageCount = -1;
    result_code::Type result = getForumThreadPageCount(urlData, pageCount);
    BFR_RETURN_VALUE_IF(result_code::failed(result),
                        result,
                        "Unable to get forum thread page count");

    // 2) Load and parse absent pages
    bfr::PostList postsTemp;
    for (int i = 1; i <= pageCount; i++)
    {
        result = getForumPagePosts(urlData, i, postsTemp);
        BFR_RETURN_VALUE_IF(result_code::failed(result),
                            result,
                            "Unable to get specified forum thread page posts");

        posts << postsTemp;
        postsTemp.clear();

        emit threadParseProgress(i, pageCount);
    }

    ConsoleLogger->debug("Forum thread '{}' posts has been parsed", url->firstPageUrl());
    return result_code::Type::Ok;
}
<|endoftext|>


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

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

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

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

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

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

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

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

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkImplicitFunction.h"

vtkImplicitFunction::vtkImplicitFunction()
{
  this->Transform = NULL;
}

vtkImplicitFunction::~vtkImplicitFunction()
{
  this->SetTransform(NULL);
}

// Evaluate function at position x-y-z and return value. Point x[3] is
// transformed through transform (if provided).
float vtkImplicitFunction::FunctionValue(const float x[3])
{
  if ( ! this->Transform )
    {
    return this->EvaluateFunction((float *)x);
    }

  else //pass point through transform
    {
    float pt[3];
    this->Transform->TransformPoint(x,pt);
    return this->EvaluateFunction((float *)pt);
    }
}

// Evaluate function gradient at position x-y-z and pass back vector. Point
// x[3] is transformed through transform (if provided).
void vtkImplicitFunction::FunctionGradient(const float x[3], float g[3])
{
  if ( ! this->Transform )
    {
    this->EvaluateGradient((float *)x,g);
    }

  else //pass point through transform
    {
    float pt[3];
    float A[3][3];
    this->Transform->Update();
    this->Transform->InternalTransformDerivative(x,pt,A);
    this->EvaluateGradient((float *)pt,g);

    // the gradient must be multiplied by the inverse of the
    // transposed inverse of the derivative of the transform,
    // which is (of course) just the transpose of the derivative.
    float x = g[0], y = g[1], z = g[2];
    g[0] = x*A[0][0] + y*A[1][0] + z*A[2][0];
    g[1] = x*A[0][1] + y*A[1][1] + z*A[2][1];
    g[2] = x*A[0][2] + y*A[1][2] + z*A[2][2];
    }
}

// Overload standard modified time function. If Transform is modified,
// then this object is modified as well.
unsigned long vtkImplicitFunction::GetMTime()
{
  unsigned long mTime=this->vtkObject::GetMTime();
  unsigned long TransformMTime;

  if ( this->Transform != NULL )
    {
    TransformMTime = this->Transform->GetMTime();
    mTime = ( TransformMTime > mTime ? TransformMTime : mTime );
    }

  return mTime;
}

void vtkImplicitFunction::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  if ( this->Transform )
    {
    os << indent << "Transform:\n";
    this->Transform->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Transform: (None)\n";
    }
}

<commit_msg>removed warning<commit_after>/*=========================================================================

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

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

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

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

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

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

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

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkImplicitFunction.h"

vtkImplicitFunction::vtkImplicitFunction()
{
  this->Transform = NULL;
}

vtkImplicitFunction::~vtkImplicitFunction()
{
  this->SetTransform(NULL);
}

// Evaluate function at position x-y-z and return value. Point x[3] is
// transformed through transform (if provided).
float vtkImplicitFunction::FunctionValue(const float x[3])
{
  if ( ! this->Transform )
    {
    return this->EvaluateFunction((float *)x);
    }

  else //pass point through transform
    {
    float pt[3];
    this->Transform->TransformPoint(x,pt);
    return this->EvaluateFunction((float *)pt);
    }
}

// Evaluate function gradient at position x-y-z and pass back vector. Point
// x[3] is transformed through transform (if provided).
void vtkImplicitFunction::FunctionGradient(const float x[3], float g[3])
{
  if ( ! this->Transform )
    {
    this->EvaluateGradient((float *)x,g);
    }

  else //pass point through transform
    {
    float pt[3];
    float A[3][3];
    this->Transform->Update();
    this->Transform->InternalTransformDerivative(x,pt,A);
    this->EvaluateGradient((float *)pt,g);

    // the gradient must be multiplied by the inverse of the
    // transposed inverse of the derivative of the transform,
    // which is (of course) just the transpose of the derivative.
    float dx = g[0], dy = g[1], dz = g[2];
    g[0] = dx*A[0][0] + dy*A[1][0] + dz*A[2][0];
    g[1] = dx*A[0][1] + dy*A[1][1] + dz*A[2][1];
    g[2] = dx*A[0][2] + dy*A[1][2] + dz*A[2][2];
    }
}

// Overload standard modified time function. If Transform is modified,
// then this object is modified as well.
unsigned long vtkImplicitFunction::GetMTime()
{
  unsigned long mTime=this->vtkObject::GetMTime();
  unsigned long TransformMTime;

  if ( this->Transform != NULL )
    {
    TransformMTime = this->Transform->GetMTime();
    mTime = ( TransformMTime > mTime ? TransformMTime : mTime );
    }

  return mTime;
}

void vtkImplicitFunction::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  if ( this->Transform )
    {
    os << indent << "Transform:\n";
    this->Transform->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Transform: (None)\n";
    }
}

<|endoftext|>


<commit_before>#include "Signal.h"

#include <sndfile.hh>

using namespace psl;

Signal::Signal(std::string filename) :
    Signal(fillFromFile(filename))
{ }

Signal::Signal(fill_t fill) :
    fill_(fill)
{ }

void Signal::fillBuffer()
{
    fill_(buffer_);
}

fill_t Signal::fillFromFile(std::string filename)
{
    SndfileHandle file(filename);

    std::vector<short> fileData(file.channels() * file.frames());
    file.read(fileData.data(), fileData.size());

    int pos = 0;
    return [fileData, pos](buffer_t& buffer) {
        // fill fileData from buffer
    };
}
<commit_msg>Finished file reading signal<commit_after>#include "Signal.h"

#include <sndfile.hh>
#include <memory>

using namespace psl;

Signal::Signal(std::string filename) :
    Signal(fillFromFile(filename))
{ }

Signal::Signal(fill_t fill) :
    fill_(fill)
{ }

void Signal::fillBuffer()
{
    fill_(buffer_);
}

fill_t Signal::fillFromFile(std::string filename)
{
    SndfileHandle file(filename);

    auto fileDataP = std::shared_ptr<std::vector<short>>(
            new std::vector<short>(file.channels() * file.frames()));
    file.read(fileDataP->data(), fileDataP->size());

    auto posP = std::shared_ptr<int>(0);
    int channels = file.channels();
    return [channels, fileDataP, posP](buffer_t& buffer) {

        // fill buffer from fileDataP
        int stopPos = std::min(buffer.size(), fileDataP->size() - *posP);
        for(int i = 0; i < stopPos; i++)
            buffer[i] = std::vector<std::complex<double>>(channels,
                    fileDataP->at(i + *posP));
        *posP += stopPos;
        for(int i = stopPos; i < buffer.size(); i++)
            buffer[i] = std::vector<std::complex<double>>(channels, 0);
    };
}
<|endoftext|>


<commit_before>/***************************************************************************
 * Copyright 1998-2013 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxRender.                                       *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include "slg/engines/bidirvmcpu/bidirvmcpu.h"

using namespace std;
using namespace luxrays;
using namespace slg;

void HashGrid::Build(vector<vector<PathVertexVM> > &pathsVertices, const float radius) {
	radius2 = radius * radius;

	// Build the vertices bounding box
	vertexCount = 0;
	vertexBBox = BBox();
	for (u_int i = 0; i < pathsVertices.size(); ++i) {
		vertexCount += pathsVertices[i].size();

		for (u_int j = 0; j < pathsVertices[i].size(); ++j)
			vertexBBox = Union(vertexBBox, pathsVertices[i][j].bsdf.hitPoint.p);
	}

	if (vertexCount <= 0)
		return;

	vertexBBox.Expand(radius + DEFAULT_EPSILON_STATIC);

	// Calculate the size of the grid cell
	const float cellSize = radius * 2.f;
	invCellSize = 1.f / cellSize;

	gridSize = vertexCount;
	cellEnds.resize(gridSize);
	fill(cellEnds.begin(), cellEnds.end(), 0);
	lightVertices.resize(gridSize, NULL);

	for (u_int i = 0, k = 0; i < pathsVertices.size(); ++i) {
		for (u_int j = 0; j < pathsVertices[i].size(); ++j, ++k) {
			const PathVertexVM *vertex = &pathsVertices[i][j];

			cellEnds[Hash(vertex->bsdf.hitPoint.p)]++;
		}
	}

	int sum = 0;
	for (u_int i = 0; i < cellEnds.size(); ++i) {
		int temp = cellEnds[i];
		cellEnds[i] = sum;
		sum += temp;
	}

	for (u_int i = 0; i < pathsVertices.size(); ++i) {
		for (u_int j = 0; j < pathsVertices[i].size(); ++j) {
			const PathVertexVM *vertex = &pathsVertices[i][j];

			const int targetIdx = cellEnds[Hash(vertex->bsdf.hitPoint.p)]++;
            lightVertices[targetIdx] = vertex;
		}
	}
}

void HashGrid::Process(const BiDirVMCPURenderThread *thread,
		const PathVertexVM &eyeVertex, Spectrum *radiance) const {
	if ((vertexCount <= 0) ||
			!vertexBBox.Inside(eyeVertex.bsdf.hitPoint.p))
		return;

	const Vector distMin = eyeVertex.bsdf.hitPoint.p - vertexBBox.pMin;
	const Vector cellPoint = invCellSize * distMin;
	const Vector coordFloor(floorf(cellPoint.x), floorf(cellPoint.y), floorf(cellPoint.z));

	const int px = int(coordFloor.x);
	const int py = int(coordFloor.y);
	const int pz = int(coordFloor.z);

	const Vector fractCoord = cellPoint - coordFloor;

	const int pxo = px + ((fractCoord.x < .5f) ? -1 : +1);
	const int pyo = py + ((fractCoord.y < .5f) ? -1 : +1);
	const int pzo = pz + ((fractCoord.z < .5f) ? -1 : +1);

	int i0, i1;
	HashRange(Hash(px, py, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(px, py, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(px, pyo, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(px, pyo, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, py, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, py, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, pyo, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, pyo, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
}

void HashGrid::Process(const BiDirVMCPURenderThread *thread,
		const PathVertexVM &eyeVertex, const int i0, const int i1,
		Spectrum *radiance) const {
	for (int i = i0; i < i1; ++i) {
		const PathVertexVM *lightVertex = lightVertices[i];
		Process(thread, eyeVertex, lightVertex, radiance);
	}
}

void HashGrid::Process(const BiDirVMCPURenderThread *thread,
		const PathVertexVM &eyeVertex, const PathVertexVM *lightVertex,
		Spectrum *radiance) const {
	const float distance2 = (lightVertex->bsdf.hitPoint.p - eyeVertex.bsdf.hitPoint.p).LengthSquared();

	if (distance2 <= radius2) {
		float eyeBsdfPdfW, eyeBsdfRevPdfW;
		BSDFEvent eyeEvent;
		/* Trick to have proper shading normal adaption */
		/* lightVertex can't be used directly because of texture variations */
		const_cast<PathVertexVM &>(eyeVertex).bsdf.hitPoint.fromLight = true;
		const Spectrum eyeBsdfEval = eyeVertex.bsdf.Evaluate(lightVertex->bsdf.hitPoint.fixedDir,
				&eyeEvent, &eyeBsdfPdfW, &eyeBsdfRevPdfW) / AbsDot(eyeVertex.bsdf.hitPoint.fixedDir, eyeVertex.bsdf.hitPoint.shadeN);
		const_cast<PathVertexVM &>(eyeVertex).bsdf.hitPoint.fromLight = false;
		if(eyeBsdfEval.Black())
			return;

		BiDirVMCPURenderEngine *engine = (BiDirVMCPURenderEngine *)thread->renderEngine;
		if (eyeVertex.depth >= engine->rrDepth) {
			// Russian Roulette
			const float prob = RenderEngine::RussianRouletteProb(eyeBsdfEval, engine->rrImportanceCap);
			eyeBsdfPdfW *= prob;
			eyeBsdfRevPdfW *= prob; // Note: SmallVCM uses light prob here
		}

		// MIS weights
		const float weightLight = lightVertex->dVCM * thread->misVcWeightFactor +
			lightVertex->dVM * BiDirVMCPURenderThread::MIS(eyeBsdfPdfW);
		const float weightCamera = eyeVertex.dVCM * thread->misVcWeightFactor +
			eyeVertex.dVM * BiDirVMCPURenderThread::MIS(eyeBsdfRevPdfW);
		const float misWeight = 1.f / (weightLight + 1.f + weightCamera);

		*radiance += (thread->vmNormalization * misWeight) *
				eyeVertex.throughput * eyeBsdfEval * lightVertex->throughput;
	}
}
<commit_msg>Fix for vertex merging after last commit.<commit_after>/***************************************************************************
 * Copyright 1998-2013 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxRender.                                       *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include "slg/engines/bidirvmcpu/bidirvmcpu.h"

using namespace std;
using namespace luxrays;
using namespace slg;

void HashGrid::Build(vector<vector<PathVertexVM> > &pathsVertices, const float radius) {
	radius2 = radius * radius;

	// Build the vertices bounding box
	vertexCount = 0;
	vertexBBox = BBox();
	for (u_int i = 0; i < pathsVertices.size(); ++i) {
		vertexCount += pathsVertices[i].size();

		for (u_int j = 0; j < pathsVertices[i].size(); ++j)
			vertexBBox = Union(vertexBBox, pathsVertices[i][j].bsdf.hitPoint.p);
	}

	if (vertexCount <= 0)
		return;

	vertexBBox.Expand(radius + DEFAULT_EPSILON_STATIC);

	// Calculate the size of the grid cell
	const float cellSize = radius * 2.f;
	invCellSize = 1.f / cellSize;

	gridSize = vertexCount;
	cellEnds.resize(gridSize);
	fill(cellEnds.begin(), cellEnds.end(), 0);
	lightVertices.resize(gridSize, NULL);

	for (u_int i = 0, k = 0; i < pathsVertices.size(); ++i) {
		for (u_int j = 0; j < pathsVertices[i].size(); ++j, ++k) {
			const PathVertexVM *vertex = &pathsVertices[i][j];

			cellEnds[Hash(vertex->bsdf.hitPoint.p)]++;
		}
	}

	int sum = 0;
	for (u_int i = 0; i < cellEnds.size(); ++i) {
		int temp = cellEnds[i];
		cellEnds[i] = sum;
		sum += temp;
	}

	for (u_int i = 0; i < pathsVertices.size(); ++i) {
		for (u_int j = 0; j < pathsVertices[i].size(); ++j) {
			const PathVertexVM *vertex = &pathsVertices[i][j];

			const int targetIdx = cellEnds[Hash(vertex->bsdf.hitPoint.p)]++;
            lightVertices[targetIdx] = vertex;
		}
	}
}

void HashGrid::Process(const BiDirVMCPURenderThread *thread,
		const PathVertexVM &eyeVertex, Spectrum *radiance) const {
	if ((vertexCount <= 0) ||
			!vertexBBox.Inside(eyeVertex.bsdf.hitPoint.p))
		return;

	const Vector distMin = eyeVertex.bsdf.hitPoint.p - vertexBBox.pMin;
	const Vector cellPoint = invCellSize * distMin;
	const Vector coordFloor(floorf(cellPoint.x), floorf(cellPoint.y), floorf(cellPoint.z));

	const int px = int(coordFloor.x);
	const int py = int(coordFloor.y);
	const int pz = int(coordFloor.z);

	const Vector fractCoord = cellPoint - coordFloor;

	const int pxo = px + ((fractCoord.x < .5f) ? -1 : +1);
	const int pyo = py + ((fractCoord.y < .5f) ? -1 : +1);
	const int pzo = pz + ((fractCoord.z < .5f) ? -1 : +1);

	int i0, i1;
	HashRange(Hash(px, py, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(px, py, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(px, pyo, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(px, pyo, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, py, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, py, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, pyo, pz), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
	HashRange(Hash(pxo, pyo, pzo), &i0, &i1);
	Process(thread, eyeVertex, i0, i1, radiance);
}

void HashGrid::Process(const BiDirVMCPURenderThread *thread,
		const PathVertexVM &eyeVertex, const int i0, const int i1,
		Spectrum *radiance) const {
	for (int i = i0; i < i1; ++i) {
		const PathVertexVM *lightVertex = lightVertices[i];
		Process(thread, eyeVertex, lightVertex, radiance);
	}
}

void HashGrid::Process(const BiDirVMCPURenderThread *thread,
		const PathVertexVM &eyeVertex, const PathVertexVM *lightVertex,
		Spectrum *radiance) const {
	const float distance2 = (lightVertex->bsdf.hitPoint.p - eyeVertex.bsdf.hitPoint.p).LengthSquared();

	if (distance2 <= radius2) {
		float eyeBsdfPdfW, eyeBsdfRevPdfW;
		BSDFEvent eyeEvent;
		/* Trick to have proper shading normal adaption */
		/* lightVertex can't be used directly because of texture variations */
		const Spectrum eyeBsdfEval = eyeVertex.bsdf.Evaluate(lightVertex->bsdf.hitPoint.fixedDir,
				&eyeEvent, &eyeBsdfPdfW, &eyeBsdfRevPdfW) / AbsDot(lightVertex->bsdf.hitPoint.fixedDir, eyeVertex.bsdf.hitPoint.geometryN);
		if(eyeBsdfEval.Black())
			return;

		BiDirVMCPURenderEngine *engine = (BiDirVMCPURenderEngine *)thread->renderEngine;
		if (eyeVertex.depth >= engine->rrDepth) {
			// Russian Roulette
			const float prob = RenderEngine::RussianRouletteProb(eyeBsdfEval, engine->rrImportanceCap);
			eyeBsdfPdfW *= prob;
			eyeBsdfRevPdfW *= prob; // Note: SmallVCM uses light prob here
		}

		// MIS weights
		const float weightLight = lightVertex->dVCM * thread->misVcWeightFactor +
			lightVertex->dVM * BiDirVMCPURenderThread::MIS(eyeBsdfPdfW);
		const float weightCamera = eyeVertex.dVCM * thread->misVcWeightFactor +
			eyeVertex.dVM * BiDirVMCPURenderThread::MIS(eyeBsdfRevPdfW);
		const float misWeight = 1.f / (weightLight + 1.f + weightCamera);

		*radiance += (thread->vmNormalization * misWeight) *
				eyeVertex.throughput * eyeBsdfEval * lightVertex->throughput;
	}
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSparql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsparqlconnection.h"
#include "qsparqlconnection_p.h"
#include "qsparqlquery.h"

#ifdef QT_SPARQL_VIRTUOSO
#include "../drivers/virtuoso/qsparql_virtuoso.h"
#endif
#ifdef QT_SPARQL_TRACKER
#include "../drivers/tracker/qsparql_tracker.h"
#endif
#ifdef QT_SPARQL_ENDPOINT
#include "../drivers/endpoint/qsparql_endpoint.h"
#endif

#include "qdebug.h"
#include "qcoreapplication.h"
#include "qsparqlresult.h"
#include "qsparqlconnectionoptions.h"
#include "qsparqldriver_p.h"
#include "qsparqldriverplugin_p.h"
#if WE_ARE_QT
// QFactoryLoader is an internal part of Qt; we'll use it when where part of Qt
// (or when Qt publishes it.)
# include "qfactoryloader_p.h"
#else
# include "qdir.h"
# include "qpluginloader.h"
#endif
#include "qsparqlnulldriver_p.h"
#include "qhash.h"

QT_BEGIN_NAMESPACE

#if WE_ARE_QT

#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
                          (QSparqlDriverFactoryInterface_iid,
                           QLatin1String("/sparqldrivers")))
#endif
#endif

typedef QHash<QString, QSparqlDriverCreatorBase*> DriverDict;

class QSparqlConnectionPrivate
{
public:
    QSparqlConnectionPrivate(QSparqlDriver *dr,
                             const QString& name,
                             const QSparqlConnectionOptions& opts):
        driver(dr),
        drvName(name),
        options(opts)
    {
    }
    ~QSparqlConnectionPrivate();

    static DriverDict &driverDict();
    static QSparqlDriver* findDriver(const QString& type);
    static QSparqlDriver* findDriverWithFactoryLoader(const QString& type);
    static QSparqlDriver* findDriverWithPluginLoader(const QString& type);
    static void registerConnectionCreator(const QString &type,
                                          QSparqlDriverCreatorBase* creator);

    static QSparqlConnectionPrivate* shared_null();

    QSparqlDriver* driver;
    QString drvName;
    QSparqlConnectionOptions options;
};

QSparqlConnectionPrivate *QSparqlConnectionPrivate::shared_null()
{
    static QSparqlNullDriver dr;
    static QSparqlConnectionPrivate n(&dr, QString(),
                                      QSparqlConnectionOptions());
    return &n;
}

QSparqlConnectionPrivate::~QSparqlConnectionPrivate()
{
    if (driver != shared_null()->driver) {
        delete driver;
        driver = shared_null()->driver;
    }
}

static bool qDriverDictInit = false;
static void cleanDriverDict()
{
    qDeleteAll(QSparqlConnectionPrivate::driverDict());
    QSparqlConnectionPrivate::driverDict().clear();
    qDriverDictInit = false;
}

DriverDict &QSparqlConnectionPrivate::driverDict()
{
    static DriverDict dict;
    if (!qDriverDictInit) {
        qDriverDictInit = true;
        qAddPostRoutine(cleanDriverDict);
    }
    return dict;
}
/*!
    \internal

    Create the actual driver instance \a type.
*/

QSparqlDriver* QSparqlConnectionPrivate::findDriver(const QString &type)
{
    QSparqlDriver * driver = 0;
    DriverDict dict = QSparqlConnectionPrivate::driverDict();
    for (DriverDict::const_iterator it = dict.constBegin();
         it != dict.constEnd() && !driver; ++it) {
        if (type == it.key()) {
            driver = ((QSparqlDriverCreatorBase*)(*it))->createObject();
        }
    }
    if (driver)
        return driver;
#if WE_ARE_QT
    return findDriverWithFactoryLoader(type);
#else
    return findDriverWithPluginLoader(type);
#endif
}

QSparqlDriver* QSparqlConnectionPrivate::findDriverWithFactoryLoader(const QString &type)
{
#if WE_ARE_QT
#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
    if (!driver && loader()) {
        if (QSparqlDriverFactoryInterface *factory = qobject_cast<QSparqlDriverFactoryInterface*>(loader()->instance(type)))
            driver = factory->create(type);
    }
#endif // QT_NO_LIBRARY

    if (!driver) {
        qWarning("QSparqlConnection: %s driver not loaded", type.toLatin1().data());
        qWarning("QSparqlConnection: available drivers: %s",
                        QSparqlConnection::drivers().join(QLatin1String(" ")).toLatin1().data());
        if (QCoreApplication::instance() == 0)
            qWarning("QSparqlConnectionPrivate: an instance of QCoreApplication is required for loading driver plugins");
        driver = QSparqlConnectionPrivate::shared_null()->driver;
    }
    return driver;
#else
    return 0;
#endif
}

QSparqlDriver* QSparqlConnectionPrivate::findDriverWithPluginLoader(const QString &type)
{
#if WE_ARE_QT
    return 0;
#else
    static bool keysRead = false;
    static QHash<QString, QSparqlDriverPlugin*> plugins;

    if (!keysRead) {
        keysRead = true;
        QStringList paths = QCoreApplication::libraryPaths();
        foreach(const QString& path, paths) {
            QString realPath = path + QLatin1String("/sparqldrivers");
            QStringList pluginNames = QDir(realPath).entryList(QDir::Files);
            for (int j = 0; j < pluginNames.count(); ++j) {
                QString fileName = QDir::cleanPath(realPath +
                                                   QLatin1Char('/') +
                                                   pluginNames.at(j));
                QPluginLoader loader(fileName);
                QObject* instance = loader.instance();
                QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
                QSparqlDriverPlugin* driPlu = dynamic_cast<QSparqlDriverPlugin*>(factory);
                if (instance && factory && driPlu) {
                    QStringList keys = factory->keys();
                    for (int k = 0; k < keys.size(); ++k) {
                        plugins[keys[k]] = driPlu;
                    }
                }
            }
        }
    }
    if (plugins.contains(type))
        return plugins[type]->create(type);
    return QSparqlConnectionPrivate::shared_null()->driver;
#endif
}

void qSparqlRegisterConnectionCreator(const QString& type,
                               QSparqlDriverCreatorBase* creator)
{
    QSparqlConnectionPrivate::registerConnectionCreator(type, creator);
}

void QSparqlConnectionPrivate::registerConnectionCreator(const QString& name,
                                                         QSparqlDriverCreatorBase* creator)
{
    delete QSparqlConnectionPrivate::driverDict().take(name);
    if (creator)
        QSparqlConnectionPrivate::driverDict().insert(name, creator);
}

/*!
    Destroys the object and frees any allocated resources.

    If this is the last QSparqlConnection object that uses a certain
    database connection, the is automatically closed.

    \sa close()
*/

QSparqlConnection::QSparqlConnection(QObject* parent)
    : QObject(parent)
{
    QSparqlDriver* driver = QSparqlConnectionPrivate::shared_null()->driver;
    d = new QSparqlConnectionPrivate(driver, QString(),
                                     QSparqlConnectionOptions());
}

QSparqlConnection::QSparqlConnection(const QString& type,
                                     const QSparqlConnectionOptions& options,
                                     QObject* parent)
    : QObject(parent)
{
    QSparqlDriver* driver = QSparqlConnectionPrivate::findDriver(type);
    d = new QSparqlConnectionPrivate(driver, type, options);
    d->driver->open(d->options);
}

QSparqlConnection::~QSparqlConnection()
{
    d->driver->close();
    delete d;
}

/*!
    Executes a SPARQL query on the database and returns a pointer to a
    QSparqlResult object. The user is responsible for freeing it.

    If \a query is empty or if the this QSparqlConnection is not
    valid, exec() returns a QSparqlResult which is in the error
    state. It won't emit the finished() signal.

    // TODO: isn't it quite bad that the user must check the error
    // state of the result? Or should the "error result" emit the
    // finished() signal when the main loop is entered the next time,
    // so that the user has a change to connect to it?

    \sa QSparqlQuery, QSparqlResult
*/

QSparqlResult* QSparqlConnection::exec(const QSparqlQuery& query) const
{
    if (!d->driver->isOpen() || d->driver->isOpenError()) {
        qWarning("QSparqlConnection::exec: database not open");

        QSparqlResult* result = new QSparqlNullResult();
        result->setLastError(QSparqlError(QLatin1String("Connection not open"),
                                          QSparqlError::ConnectionError));
        return result;
    }
    QString queryText = query.preparedQueryText();
    if (queryText.isEmpty()) {
        qWarning("QSparqlConnection::exec: empty query");
        QSparqlResult* result = new QSparqlNullResult();
        result->setLastError(QSparqlError(QLatin1String("Query is empty"),
                                          QSparqlError::ConnectionError));
        return result;
    }
    return d->driver->exec(queryText, query.type());
}

/*!
    Returns the connection's driver name.
*/
QString QSparqlConnection::driverName() const
{
    return d->drvName;
}

/*!
    Returns true if the QSparqlConnection supports feature \a feature;
    otherwise returns false.
*/
bool QSparqlConnection::hasFeature(Feature feature) const
{
    return d->driver->hasFeature(feature);
}

/*!
    Returns true if the QSparqlConnection has a valid driver, i.e.,
    the name of the driver given in the constructor was valid.

    Example:
    \snippet doc/src/snippets/code/src_sql_kernel_qsparqlconnection.cpp 8
*/
bool QSparqlConnection::isValid() const
{
    return d->driver && d->driver != d->shared_null()->driver;
}

QStringList QSparqlConnection::drivers()
{
    QStringList list;
    return list; // a hack

#if WE_ARE_QT
#ifdef QT_SPARQL_ODBC
    list << QLatin1String("QODBC3");
    list << QLatin1String("QODBC");
#endif
#ifdef QT_SPARQL_TRACKER
    list << QLatin1String("QTRACKER");
#endif
#ifdef QT_SPARQL_ENDPOINT
    list << QLatin1String("QENDPOINT");
#endif

#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
    if (QFactoryLoader *fl = loader()) {
        QStringList keys = fl->keys();
        for (QStringList::const_iterator i = keys.constBegin(); i != keys.constEnd(); ++i) {
            if (!list.contains(*i))
                list << *i;
        }
    }
#endif

    DriverDict dict = QSparqlConnectionPrivate::driverDict();
    for (DriverDict::const_iterator i = dict.constBegin(); i != dict.constEnd(); ++i) {
        if (!list.contains(i.key()))
            list << i.key();
    }

    return list;
#endif
}

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSparqlConnection &d)
{
    if (!d.isValid()) {
        dbg.nospace() << "QSparqlConnection(invalid)";
        return dbg.space();
    }

    dbg.nospace() << "QSparqlConnection(driver=\"" << d.driverName() << ")";
    return dbg.space();
}
#endif

QT_END_NAMESPACE

/*!
    \mainpage The QtSparql library

    \brief QtSparql is a client-side library for accessing RDF stores.

    FIXME: insert intro text here

    \include simple/main.cpp
*/
<commit_msg>Intro doc with code snippets.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSparql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsparqlconnection.h"
#include "qsparqlconnection_p.h"
#include "qsparqlquery.h"

#ifdef QT_SPARQL_VIRTUOSO
#include "../drivers/virtuoso/qsparql_virtuoso.h"
#endif
#ifdef QT_SPARQL_TRACKER
#include "../drivers/tracker/qsparql_tracker.h"
#endif
#ifdef QT_SPARQL_ENDPOINT
#include "../drivers/endpoint/qsparql_endpoint.h"
#endif

#include "qdebug.h"
#include "qcoreapplication.h"
#include "qsparqlresult.h"
#include "qsparqlconnectionoptions.h"
#include "qsparqldriver_p.h"
#include "qsparqldriverplugin_p.h"
#if WE_ARE_QT
// QFactoryLoader is an internal part of Qt; we'll use it when where part of Qt
// (or when Qt publishes it.)
# include "qfactoryloader_p.h"
#else
# include "qdir.h"
# include "qpluginloader.h"
#endif
#include "qsparqlnulldriver_p.h"
#include "qhash.h"

QT_BEGIN_NAMESPACE

#if WE_ARE_QT

#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
                          (QSparqlDriverFactoryInterface_iid,
                           QLatin1String("/sparqldrivers")))
#endif
#endif

typedef QHash<QString, QSparqlDriverCreatorBase*> DriverDict;

class QSparqlConnectionPrivate
{
public:
    QSparqlConnectionPrivate(QSparqlDriver *dr,
                             const QString& name,
                             const QSparqlConnectionOptions& opts):
        driver(dr),
        drvName(name),
        options(opts)
    {
    }
    ~QSparqlConnectionPrivate();

    static DriverDict &driverDict();
    static QSparqlDriver* findDriver(const QString& type);
    static QSparqlDriver* findDriverWithFactoryLoader(const QString& type);
    static QSparqlDriver* findDriverWithPluginLoader(const QString& type);
    static void registerConnectionCreator(const QString &type,
                                          QSparqlDriverCreatorBase* creator);

    static QSparqlConnectionPrivate* shared_null();

    QSparqlDriver* driver;
    QString drvName;
    QSparqlConnectionOptions options;
};

QSparqlConnectionPrivate *QSparqlConnectionPrivate::shared_null()
{
    static QSparqlNullDriver dr;
    static QSparqlConnectionPrivate n(&dr, QString(),
                                      QSparqlConnectionOptions());
    return &n;
}

QSparqlConnectionPrivate::~QSparqlConnectionPrivate()
{
    if (driver != shared_null()->driver) {
        delete driver;
        driver = shared_null()->driver;
    }
}

static bool qDriverDictInit = false;
static void cleanDriverDict()
{
    qDeleteAll(QSparqlConnectionPrivate::driverDict());
    QSparqlConnectionPrivate::driverDict().clear();
    qDriverDictInit = false;
}

DriverDict &QSparqlConnectionPrivate::driverDict()
{
    static DriverDict dict;
    if (!qDriverDictInit) {
        qDriverDictInit = true;
        qAddPostRoutine(cleanDriverDict);
    }
    return dict;
}
/*!
    \internal

    Create the actual driver instance \a type.
*/

QSparqlDriver* QSparqlConnectionPrivate::findDriver(const QString &type)
{
    QSparqlDriver * driver = 0;
    DriverDict dict = QSparqlConnectionPrivate::driverDict();
    for (DriverDict::const_iterator it = dict.constBegin();
         it != dict.constEnd() && !driver; ++it) {
        if (type == it.key()) {
            driver = ((QSparqlDriverCreatorBase*)(*it))->createObject();
        }
    }
    if (driver)
        return driver;
#if WE_ARE_QT
    return findDriverWithFactoryLoader(type);
#else
    return findDriverWithPluginLoader(type);
#endif
}

QSparqlDriver* QSparqlConnectionPrivate::findDriverWithFactoryLoader(const QString &type)
{
#if WE_ARE_QT
#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
    if (!driver && loader()) {
        if (QSparqlDriverFactoryInterface *factory = qobject_cast<QSparqlDriverFactoryInterface*>(loader()->instance(type)))
            driver = factory->create(type);
    }
#endif // QT_NO_LIBRARY

    if (!driver) {
        qWarning("QSparqlConnection: %s driver not loaded", type.toLatin1().data());
        qWarning("QSparqlConnection: available drivers: %s",
                        QSparqlConnection::drivers().join(QLatin1String(" ")).toLatin1().data());
        if (QCoreApplication::instance() == 0)
            qWarning("QSparqlConnectionPrivate: an instance of QCoreApplication is required for loading driver plugins");
        driver = QSparqlConnectionPrivate::shared_null()->driver;
    }
    return driver;
#else
    return 0;
#endif
}

QSparqlDriver* QSparqlConnectionPrivate::findDriverWithPluginLoader(const QString &type)
{
#if WE_ARE_QT
    return 0;
#else
    static bool keysRead = false;
    static QHash<QString, QSparqlDriverPlugin*> plugins;

    if (!keysRead) {
        keysRead = true;
        QStringList paths = QCoreApplication::libraryPaths();
        foreach(const QString& path, paths) {
            QString realPath = path + QLatin1String("/sparqldrivers");
            QStringList pluginNames = QDir(realPath).entryList(QDir::Files);
            for (int j = 0; j < pluginNames.count(); ++j) {
                QString fileName = QDir::cleanPath(realPath +
                                                   QLatin1Char('/') +
                                                   pluginNames.at(j));
                QPluginLoader loader(fileName);
                QObject* instance = loader.instance();
                QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
                QSparqlDriverPlugin* driPlu = dynamic_cast<QSparqlDriverPlugin*>(factory);
                if (instance && factory && driPlu) {
                    QStringList keys = factory->keys();
                    for (int k = 0; k < keys.size(); ++k) {
                        plugins[keys[k]] = driPlu;
                    }
                }
            }
        }
    }
    if (plugins.contains(type))
        return plugins[type]->create(type);
    return QSparqlConnectionPrivate::shared_null()->driver;
#endif
}

void qSparqlRegisterConnectionCreator(const QString& type,
                               QSparqlDriverCreatorBase* creator)
{
    QSparqlConnectionPrivate::registerConnectionCreator(type, creator);
}

void QSparqlConnectionPrivate::registerConnectionCreator(const QString& name,
                                                         QSparqlDriverCreatorBase* creator)
{
    delete QSparqlConnectionPrivate::driverDict().take(name);
    if (creator)
        QSparqlConnectionPrivate::driverDict().insert(name, creator);
}

/*!
    Destroys the object and frees any allocated resources.

    If this is the last QSparqlConnection object that uses a certain
    database connection, the is automatically closed.

    \sa close()
*/

QSparqlConnection::QSparqlConnection(QObject* parent)
    : QObject(parent)
{
    QSparqlDriver* driver = QSparqlConnectionPrivate::shared_null()->driver;
    d = new QSparqlConnectionPrivate(driver, QString(),
                                     QSparqlConnectionOptions());
}

QSparqlConnection::QSparqlConnection(const QString& type,
                                     const QSparqlConnectionOptions& options,
                                     QObject* parent)
    : QObject(parent)
{
    QSparqlDriver* driver = QSparqlConnectionPrivate::findDriver(type);
    d = new QSparqlConnectionPrivate(driver, type, options);
    d->driver->open(d->options);
}

QSparqlConnection::~QSparqlConnection()
{
    d->driver->close();
    delete d;
}

/*!
    Executes a SPARQL query on the database and returns a pointer to a
    QSparqlResult object. The user is responsible for freeing it.

    If \a query is empty or if the this QSparqlConnection is not
    valid, exec() returns a QSparqlResult which is in the error
    state. It won't emit the finished() signal.

    // TODO: isn't it quite bad that the user must check the error
    // state of the result? Or should the "error result" emit the
    // finished() signal when the main loop is entered the next time,
    // so that the user has a change to connect to it?

    \sa QSparqlQuery, QSparqlResult
*/

QSparqlResult* QSparqlConnection::exec(const QSparqlQuery& query) const
{
    if (!d->driver->isOpen() || d->driver->isOpenError()) {
        qWarning("QSparqlConnection::exec: database not open");

        QSparqlResult* result = new QSparqlNullResult();
        result->setLastError(QSparqlError(QLatin1String("Connection not open"),
                                          QSparqlError::ConnectionError));
        return result;
    }
    QString queryText = query.preparedQueryText();
    if (queryText.isEmpty()) {
        qWarning("QSparqlConnection::exec: empty query");
        QSparqlResult* result = new QSparqlNullResult();
        result->setLastError(QSparqlError(QLatin1String("Query is empty"),
                                          QSparqlError::ConnectionError));
        return result;
    }
    return d->driver->exec(queryText, query.type());
}

/*!
    Returns the connection's driver name.
*/
QString QSparqlConnection::driverName() const
{
    return d->drvName;
}

/*!
    Returns true if the QSparqlConnection supports feature \a feature;
    otherwise returns false.
*/
bool QSparqlConnection::hasFeature(Feature feature) const
{
    return d->driver->hasFeature(feature);
}

/*!
    Returns true if the QSparqlConnection has a valid driver, i.e.,
    the name of the driver given in the constructor was valid.

    Example:
    \snippet doc/src/snippets/code/src_sql_kernel_qsparqlconnection.cpp 8
*/
bool QSparqlConnection::isValid() const
{
    return d->driver && d->driver != d->shared_null()->driver;
}

QStringList QSparqlConnection::drivers()
{
    QStringList list;
    return list; // a hack

#if WE_ARE_QT
#ifdef QT_SPARQL_ODBC
    list << QLatin1String("QODBC3");
    list << QLatin1String("QODBC");
#endif
#ifdef QT_SPARQL_TRACKER
    list << QLatin1String("QTRACKER");
#endif
#ifdef QT_SPARQL_ENDPOINT
    list << QLatin1String("QENDPOINT");
#endif

#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
    if (QFactoryLoader *fl = loader()) {
        QStringList keys = fl->keys();
        for (QStringList::const_iterator i = keys.constBegin(); i != keys.constEnd(); ++i) {
            if (!list.contains(*i))
                list << *i;
        }
    }
#endif

    DriverDict dict = QSparqlConnectionPrivate::driverDict();
    for (DriverDict::const_iterator i = dict.constBegin(); i != dict.constEnd(); ++i) {
        if (!list.contains(i.key()))
            list << i.key();
    }

    return list;
#endif
}

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSparqlConnection &d)
{
    if (!d.isValid()) {
        dbg.nospace() << "QSparqlConnection(invalid)";
        return dbg.space();
    }

    dbg.nospace() << "QSparqlConnection(driver=\"" << d.driverName() << ")";
    return dbg.space();
}
#endif

QT_END_NAMESPACE

/*!
    \mainpage The QtSparql library

    \brief QtSparql is a client-side library for accessing RDF stores.

    The query language for RDF stores is <a
    href="http://www.w3.org/TR/rdf-sparql-query/">SPARQL</a>.

    QtSparql takes in SPARQL queries, forwards them to the selected backend, and
    gives back the results of the query.  It can return the results
    asynchronously if the backend supports asynchronous operations.

    QtSparql can connect to different backends.  Currently the following backends
    exist:

    - tracker backend for accessing <a href="http://projects.gnome.org/tracker/">Tracker</a>
    - endpoint backend of accessing online RDF stores, e.g., <a href="http://dbpedia.org">DBpedia</a>
    - virtuoso backend for accessing Virtuoso

    \section basicusage Basic usage

    - Create a QSparqlConnection object specifiying the backend you want to use.
      If necessary, specify the parameters by using QSparqlConnectionOptions and
      passing it to QSparqlConnection.

    E.g., to use tracker:
    \dontinclude simple/main.cpp
    \skipline QSparqlConnection

    E.g., to use DBpedia:
    \dontinclude dbpedia/main.cpp
    \skip QSparqlConnectionOptions
    \until QENDPOINT

    - Construct a QSparqlQuery with the SPARQL query string.  Specify the query
      type, if needed.

    E.g.,
    \dontinclude simple/main.cpp
    \skipline QSparqlQuery

    or

    \dontinclude bindingset/main.cpp
    \skip QSparqlQuery insert
    \until InsertStatement

    - Use QSparqlConnection::exec() to execute the query. It gives back a
      pointer to QSparqlResult.

    E.g.,
    \dontinclude simple/main.cpp
    \skipline QSparqlResult

    - You can use QSparqlResult::waitForFinished() to wait until the query has
      finished, or connect to the QSparqlResult::finished() signal.

    - The QSparqlResult can be iterated by using the following functions:
      QSparqlResult::first(), QSparqlResult::last(), QSparlqResult::next(),
      QSparqlResult::previous(), QSparqlResult::seek().

    E.g.,
    \dontinclude simple/main.cpp
    \skip result->next
    \until toString

    - Data can be retrieved by using QSparqlResult::data().

    \section querymodels Query models

    TODO

    \section backendspecific Accessing backend-specific functionalities

    TODO

*/
<|endoftext|>