<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: normal_estimation.cpp 1032 2011-05-18 22:43:27Z marton $
 *
 */

#include <sensor_msgs/PointCloud2.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

int    default_k = 0;
double default_radius = 0.0;

void
printHelp (int argc, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -radius X = use a radius of Xm around each point to determine the neighborhood (default: ");
  print_value ("%f", default_radius); print_info (")\n");
  print_info ("                     -k X      = use a fixed number of X-nearest neighbors around each point (default: ");
  print_value ("%f", default_k); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         int k, double radius)
{
  // Convert data to PointCloud<T>
  PointCloud<PointXYZ>::Ptr xyz (new PointCloud<PointXYZ>);
  fromROSMsg (*input, *xyz);

  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (xyz);
  ne.setSearchMethod (pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr (new pcl::KdTreeFLANN<pcl::PointXYZ>));
  ne.setKSearch (k);
  ne.setRadiusSearch (radius);

  PointCloud<Normal> normals;
  ne.compute (normals);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", normals.width * normals.height); print_info (" points]\n");

  // Convert data back
  sensor_msgs::PointCloud2 output_normals;
  toROSMsg (normals, output_normals);
  concatenateFields (*input, output_normals, output);
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  pcl::io::savePCDFile (filename, output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Estimate surface normals using pcl::NormalEstimation. For more information, use: %s -h\n", argv[0]);

  if (argc < 3)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  int k = default_k;
  double radius = default_radius;
  parse_argument (argc, argv, "-k", k);
  parse_argument (argc, argv, "-radius", radius);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;
  compute (cloud, output, k, radius);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}

<commit_msg>saving files as binary in the normal estimation PCL_TOOL<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: normal_estimation.cpp 1032 2011-05-18 22:43:27Z marton $
 *
 */

#include <sensor_msgs/PointCloud2.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

int    default_k = 0;
double default_radius = 0.0;

Eigen::Vector4f    translation;
Eigen::Quaternionf orientation;

void
printHelp (int argc, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -radius X = use a radius of Xm around each point to determine the neighborhood (default: ");
  print_value ("%f", default_radius); print_info (")\n");
  print_info ("                     -k X      = use a fixed number of X-nearest neighbors around each point (default: ");
  print_value ("%f", default_k); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud, translation, orientation) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         int k, double radius)
{
  // Convert data to PointCloud<T>
  PointCloud<PointXYZ>::Ptr xyz (new PointCloud<PointXYZ>);
  fromROSMsg (*input, *xyz);

  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (xyz);
  ne.setSearchMethod (pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr (new pcl::KdTreeFLANN<pcl::PointXYZ>));
  ne.setKSearch (k);
  ne.setRadiusSearch (radius);

  PointCloud<Normal> normals;
  ne.compute (normals);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", normals.width * normals.height); print_info (" points]\n");

  // Convert data back
  sensor_msgs::PointCloud2 output_normals;
  toROSMsg (normals, output_normals);
  concatenateFields (*input, output_normals, output);
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  pcl::io::savePCDFile (filename, output, translation, orientation, true);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" seconds : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Estimate surface normals using pcl::NormalEstimation. For more information, use: %s -h\n", argv[0]);

  if (argc < 3)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  int k = default_k;
  double radius = default_radius;
  parse_argument (argc, argv, "-k", k);
  parse_argument (argc, argv, "-radius", radius);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;
  compute (cloud, output, k, radius);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}

<|endoftext|>


<commit_before>//===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief The ELF component of yaml2obj.
///
//===----------------------------------------------------------------------===//

#include "yaml2obj.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFYAML.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

// There is similar code in yaml2coff, but with some slight COFF-specific
// variations like different initial state. Might be able to deduplicate
// some day, but also want to make sure that the Mach-O use case is served.
//
// This class has a deliberately small interface, since a lot of
// implementation variation is possible.
//
// TODO: Use an ordered container with a suffix-based comparison in order
// to deduplicate suffixes. std::map<> with a custom comparator is likely
// to be the simplest implementation, but a suffix trie could be more
// suitable for the job.
class StringTableBuilder {
  /// \brief Indices of strings currently present in `Buf`.
  StringMap<unsigned> StringIndices;
  /// \brief The contents of the string table as we build it.
  std::string Buf;
public:
  StringTableBuilder() {
    Buf.push_back('\0');
  }
  /// \returns Index of string in string table.
  unsigned addString(StringRef S) {
    StringMapEntry<unsigned> &Entry = StringIndices.GetOrCreateValue(S);
    unsigned &I = Entry.getValue();
    if (I != 0)
      return I;
    I = Buf.size();
    Buf.append(S.begin(), S.end());
    Buf.push_back('\0');
    return I;
  }
  size_t size() const {
    return Buf.size();
  }
  void writeToStream(raw_ostream &OS) {
    OS.write(Buf.data(), Buf.size());
  }
};

// This class is used to build up a contiguous binary blob while keeping
// track of an offset in the output (which notionally begins at
// `InitialOffset`).
class ContiguousBlobAccumulator {
  const uint64_t InitialOffset;
  raw_svector_ostream OS;

public:
  ContiguousBlobAccumulator(uint64_t InitialOffset_, SmallVectorImpl<char> &Buf)
      : InitialOffset(InitialOffset_), OS(Buf) {}
  raw_ostream &getOS() { return OS; }
  uint64_t currentOffset() const { return InitialOffset + OS.tell(); }
  void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
};

// Used to keep track of section names, so that in the YAML file sections
// can be referenced by name instead of by index.
class SectionNameToIdxMap {
  StringMap<int> Map;
public:
  /// \returns true if name is already present in the map.
  bool addName(StringRef SecName, unsigned i) {
    StringMapEntry<int> &Entry = Map.GetOrCreateValue(SecName, -1);
    if (Entry.getValue() != -1)
      return true;
    Entry.setValue((int)i);
    return false;
  }
  /// \returns true if name is not present in the map
  bool lookupSection(StringRef SecName, unsigned &Idx) const {
    StringMap<int>::const_iterator I = Map.find(SecName);
    if (I == Map.end())
      return true;
    Idx = I->getValue();
    return false;
  }
};

template <class T>
static size_t vectorDataSize(const std::vector<T> &Vec) {
  return Vec.size() * sizeof(T);
}

template <class T>
static void writeVectorData(raw_ostream &OS, const std::vector<T> &Vec) {
  OS.write((const char *)Vec.data(), vectorDataSize(Vec));
}

template <class T>
static void zero(T &Obj) {
  memset(&Obj, 0, sizeof(Obj));
}

template <class ELFT>
static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
  using namespace llvm::ELF;
  using namespace llvm::object;
  typedef typename ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
  typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;

  const ELFYAML::FileHeader &Hdr = Doc.Header;

  Elf_Ehdr Header;
  zero(Header);
  Header.e_ident[EI_MAG0] = 0x7f;
  Header.e_ident[EI_MAG1] = 'E';
  Header.e_ident[EI_MAG2] = 'L';
  Header.e_ident[EI_MAG3] = 'F';
  Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
  bool IsLittleEndian = ELFT::TargetEndianness == support::little;
  Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
  Header.e_ident[EI_VERSION] = EV_CURRENT;
  // TODO: Implement ELF_ELFOSABI enum.
  Header.e_ident[EI_OSABI] = ELFOSABI_NONE;
  // TODO: Implement ELF_ABIVERSION enum.
  Header.e_ident[EI_ABIVERSION] = 0;
  Header.e_type = Hdr.Type;
  Header.e_machine = Hdr.Machine;
  Header.e_version = EV_CURRENT;
  Header.e_entry = Hdr.Entry;
  Header.e_ehsize = sizeof(Elf_Ehdr);

  // TODO: Flesh out section header support.
  // TODO: Program headers.

  Header.e_shentsize = sizeof(Elf_Shdr);
  // Immediately following the ELF header.
  Header.e_shoff = sizeof(Header);
  std::vector<ELFYAML::Section> Sections = Doc.Sections;
  if (Sections.empty() || Sections.front().Type != SHT_NULL) {
    ELFYAML::Section S;
    S.Type = SHT_NULL;
    zero(S.Flags);
    Sections.insert(Sections.begin(), S);
  }
  // "+ 1" for string table.
  Header.e_shnum = Sections.size() + 1;
  // Place section header string table last.
  Header.e_shstrndx = Sections.size();

  SectionNameToIdxMap SN2I;
  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
    StringRef Name = Sections[i].Name;
    if (Name.empty())
      continue;
    if (SN2I.addName(Name, i)) {
      errs() << "error: Repeated section name: '" << Name
             << "' at YAML section number " << i << ".\n";
      return;
    }
  }

  StringTableBuilder StrTab;
  SmallVector<char, 128> Buf;
  // XXX: This offset is tightly coupled with the order that we write
  // things to `OS`.
  const size_t SectionContentBeginOffset =
      Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
  ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf);
  std::vector<Elf_Shdr> SHeaders;
  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
    const ELFYAML::Section &Sec = Sections[i];
    Elf_Shdr SHeader;
    zero(SHeader);
    SHeader.sh_name = StrTab.addString(Sec.Name);
    SHeader.sh_type = Sec.Type;
    SHeader.sh_flags = Sec.Flags;
    SHeader.sh_addr = Sec.Address;

    SHeader.sh_offset = CBA.currentOffset();
    SHeader.sh_size = Sec.Content.binary_size();
    Sec.Content.writeAsBinary(CBA.getOS());

    if (!Sec.Link.empty()) {
      unsigned Index;
      if (SN2I.lookupSection(Sec.Link, Index)) {
        errs() << "error: Unknown section referenced: '" << Sec.Link
               << "' at YAML section number " << i << ".\n";
        return;
      }
      SHeader.sh_link = Index;
    }
    SHeader.sh_info = 0;
    SHeader.sh_addralign = Sec.AddressAlign;
    SHeader.sh_entsize = 0;
    SHeaders.push_back(SHeader);
  }

  // String table header.
  Elf_Shdr StrTabSHeader;
  zero(StrTabSHeader);
  StrTabSHeader.sh_name = 0;
  StrTabSHeader.sh_type = SHT_STRTAB;
  StrTabSHeader.sh_flags = 0;
  StrTabSHeader.sh_addr = 0;
  StrTabSHeader.sh_offset = CBA.currentOffset();
  StrTabSHeader.sh_size = StrTab.size();
  StrTab.writeToStream(CBA.getOS());
  StrTabSHeader.sh_link = 0;
  StrTabSHeader.sh_info = 0;
  StrTabSHeader.sh_addralign = 1;
  StrTabSHeader.sh_entsize = 0;

  OS.write((const char *)&Header, sizeof(Header));
  writeVectorData(OS, SHeaders);
  OS.write((const char *)&StrTabSHeader, sizeof(StrTabSHeader));
  CBA.writeBlobToStream(OS);
}

int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
  yaml::Input YIn(Buf->getBuffer());
  ELFYAML::Object Doc;
  YIn >> Doc;
  if (YIn.error()) {
    errs() << "yaml2obj: Failed to parse YAML file!\n";
    return 1;
  }
  if (Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) {
    if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
      writeELF<object::ELFType<support::little, 8, true> >(outs(), Doc);
    else
      writeELF<object::ELFType<support::big, 8, true> >(outs(), Doc);
  } else {
    if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
      writeELF<object::ELFType<support::little, 4, false> >(outs(), Doc);
    else
      writeELF<object::ELFType<support::big, 4, false> >(outs(), Doc);
  }

  return 0;
}
<commit_msg>[yaml2obj] Move some classes into anonymous namespaces.<commit_after>//===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief The ELF component of yaml2obj.
///
//===----------------------------------------------------------------------===//

#include "yaml2obj.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFYAML.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

// There is similar code in yaml2coff, but with some slight COFF-specific
// variations like different initial state. Might be able to deduplicate
// some day, but also want to make sure that the Mach-O use case is served.
//
// This class has a deliberately small interface, since a lot of
// implementation variation is possible.
//
// TODO: Use an ordered container with a suffix-based comparison in order
// to deduplicate suffixes. std::map<> with a custom comparator is likely
// to be the simplest implementation, but a suffix trie could be more
// suitable for the job.
namespace {
class StringTableBuilder {
  /// \brief Indices of strings currently present in `Buf`.
  StringMap<unsigned> StringIndices;
  /// \brief The contents of the string table as we build it.
  std::string Buf;
public:
  StringTableBuilder() {
    Buf.push_back('\0');
  }
  /// \returns Index of string in string table.
  unsigned addString(StringRef S) {
    StringMapEntry<unsigned> &Entry = StringIndices.GetOrCreateValue(S);
    unsigned &I = Entry.getValue();
    if (I != 0)
      return I;
    I = Buf.size();
    Buf.append(S.begin(), S.end());
    Buf.push_back('\0');
    return I;
  }
  size_t size() const {
    return Buf.size();
  }
  void writeToStream(raw_ostream &OS) {
    OS.write(Buf.data(), Buf.size());
  }
};
} // end anonymous namespace

// This class is used to build up a contiguous binary blob while keeping
// track of an offset in the output (which notionally begins at
// `InitialOffset`).
namespace {
class ContiguousBlobAccumulator {
  const uint64_t InitialOffset;
  raw_svector_ostream OS;

public:
  ContiguousBlobAccumulator(uint64_t InitialOffset_, SmallVectorImpl<char> &Buf)
      : InitialOffset(InitialOffset_), OS(Buf) {}
  raw_ostream &getOS() { return OS; }
  uint64_t currentOffset() const { return InitialOffset + OS.tell(); }
  void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
};
} // end anonymous namespace

// Used to keep track of section names, so that in the YAML file sections
// can be referenced by name instead of by index.
namespace {
class SectionNameToIdxMap {
  StringMap<int> Map;
public:
  /// \returns true if name is already present in the map.
  bool addName(StringRef SecName, unsigned i) {
    StringMapEntry<int> &Entry = Map.GetOrCreateValue(SecName, -1);
    if (Entry.getValue() != -1)
      return true;
    Entry.setValue((int)i);
    return false;
  }
  /// \returns true if name is not present in the map
  bool lookupSection(StringRef SecName, unsigned &Idx) const {
    StringMap<int>::const_iterator I = Map.find(SecName);
    if (I == Map.end())
      return true;
    Idx = I->getValue();
    return false;
  }
};
} // end anonymous namespace

template <class T>
static size_t vectorDataSize(const std::vector<T> &Vec) {
  return Vec.size() * sizeof(T);
}

template <class T>
static void writeVectorData(raw_ostream &OS, const std::vector<T> &Vec) {
  OS.write((const char *)Vec.data(), vectorDataSize(Vec));
}

template <class T>
static void zero(T &Obj) {
  memset(&Obj, 0, sizeof(Obj));
}

template <class ELFT>
static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
  using namespace llvm::ELF;
  using namespace llvm::object;
  typedef typename ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
  typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;

  const ELFYAML::FileHeader &Hdr = Doc.Header;

  Elf_Ehdr Header;
  zero(Header);
  Header.e_ident[EI_MAG0] = 0x7f;
  Header.e_ident[EI_MAG1] = 'E';
  Header.e_ident[EI_MAG2] = 'L';
  Header.e_ident[EI_MAG3] = 'F';
  Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
  bool IsLittleEndian = ELFT::TargetEndianness == support::little;
  Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
  Header.e_ident[EI_VERSION] = EV_CURRENT;
  // TODO: Implement ELF_ELFOSABI enum.
  Header.e_ident[EI_OSABI] = ELFOSABI_NONE;
  // TODO: Implement ELF_ABIVERSION enum.
  Header.e_ident[EI_ABIVERSION] = 0;
  Header.e_type = Hdr.Type;
  Header.e_machine = Hdr.Machine;
  Header.e_version = EV_CURRENT;
  Header.e_entry = Hdr.Entry;
  Header.e_ehsize = sizeof(Elf_Ehdr);

  // TODO: Flesh out section header support.
  // TODO: Program headers.

  Header.e_shentsize = sizeof(Elf_Shdr);
  // Immediately following the ELF header.
  Header.e_shoff = sizeof(Header);
  std::vector<ELFYAML::Section> Sections = Doc.Sections;
  if (Sections.empty() || Sections.front().Type != SHT_NULL) {
    ELFYAML::Section S;
    S.Type = SHT_NULL;
    zero(S.Flags);
    Sections.insert(Sections.begin(), S);
  }
  // "+ 1" for string table.
  Header.e_shnum = Sections.size() + 1;
  // Place section header string table last.
  Header.e_shstrndx = Sections.size();

  SectionNameToIdxMap SN2I;
  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
    StringRef Name = Sections[i].Name;
    if (Name.empty())
      continue;
    if (SN2I.addName(Name, i)) {
      errs() << "error: Repeated section name: '" << Name
             << "' at YAML section number " << i << ".\n";
      return;
    }
  }

  StringTableBuilder StrTab;
  SmallVector<char, 128> Buf;
  // XXX: This offset is tightly coupled with the order that we write
  // things to `OS`.
  const size_t SectionContentBeginOffset =
      Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
  ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf);
  std::vector<Elf_Shdr> SHeaders;
  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
    const ELFYAML::Section &Sec = Sections[i];
    Elf_Shdr SHeader;
    zero(SHeader);
    SHeader.sh_name = StrTab.addString(Sec.Name);
    SHeader.sh_type = Sec.Type;
    SHeader.sh_flags = Sec.Flags;
    SHeader.sh_addr = Sec.Address;

    SHeader.sh_offset = CBA.currentOffset();
    SHeader.sh_size = Sec.Content.binary_size();
    Sec.Content.writeAsBinary(CBA.getOS());

    if (!Sec.Link.empty()) {
      unsigned Index;
      if (SN2I.lookupSection(Sec.Link, Index)) {
        errs() << "error: Unknown section referenced: '" << Sec.Link
               << "' at YAML section number " << i << ".\n";
        return;
      }
      SHeader.sh_link = Index;
    }
    SHeader.sh_info = 0;
    SHeader.sh_addralign = Sec.AddressAlign;
    SHeader.sh_entsize = 0;
    SHeaders.push_back(SHeader);
  }

  // String table header.
  Elf_Shdr StrTabSHeader;
  zero(StrTabSHeader);
  StrTabSHeader.sh_name = 0;
  StrTabSHeader.sh_type = SHT_STRTAB;
  StrTabSHeader.sh_flags = 0;
  StrTabSHeader.sh_addr = 0;
  StrTabSHeader.sh_offset = CBA.currentOffset();
  StrTabSHeader.sh_size = StrTab.size();
  StrTab.writeToStream(CBA.getOS());
  StrTabSHeader.sh_link = 0;
  StrTabSHeader.sh_info = 0;
  StrTabSHeader.sh_addralign = 1;
  StrTabSHeader.sh_entsize = 0;

  OS.write((const char *)&Header, sizeof(Header));
  writeVectorData(OS, SHeaders);
  OS.write((const char *)&StrTabSHeader, sizeof(StrTabSHeader));
  CBA.writeBlobToStream(OS);
}

int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
  yaml::Input YIn(Buf->getBuffer());
  ELFYAML::Object Doc;
  YIn >> Doc;
  if (YIn.error()) {
    errs() << "yaml2obj: Failed to parse YAML file!\n";
    return 1;
  }
  if (Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) {
    if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
      writeELF<object::ELFType<support::little, 8, true> >(outs(), Doc);
    else
      writeELF<object::ELFType<support::big, 8, true> >(outs(), Doc);
  } else {
    if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
      writeELF<object::ELFType<support::little, 4, false> >(outs(), Doc);
    else
      writeELF<object::ELFType<support::big, 4, false> >(outs(), Doc);
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "FancyMeshComponent.hpp"

#include <Core/String/StringUtils.hpp>
#include <Core/Mesh/MeshUtils.hpp>

#include <Core/Geometry/Normal/Normal.hpp>

#include <Engine/Renderer/RenderObject/RenderObjectManager.hpp>
#include <Engine/Renderer/Mesh/Mesh.hpp>
#include <Engine/Renderer/RenderObject/RenderObject.hpp>
#include <Engine/Renderer/RenderObject/RenderObjectTypes.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderConfiguration.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderProgramManager.hpp>
#include <Engine/Renderer/RenderObject/Primitives/DrawPrimitives.hpp>

#include <Engine/Assets/FileData.hpp>
#include <Engine/Assets/GeometryData.hpp>

namespace FancyMeshPlugin
{
    FancyMeshComponent::FancyMeshComponent( const std::string& name )
        : Ra::Engine::Component( name )
    {
    }

    FancyMeshComponent::~FancyMeshComponent()
    {
        // TODO(Charly): Should we ask the RO manager to delete our render object ?
    }

    void FancyMeshComponent::initialize()
    {
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh, const std::string& name )
    {
        Ra::Engine::RenderTechnique* technique = new Ra::Engine::RenderTechnique;
        technique->material = new Ra::Engine::Material( "Default" );
        technique->shaderConfig = Ra::Engine::ShaderConfiguration( "Default", "../Shaders" );

        addMeshRenderObject(mesh, name, technique);
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh,
                                                  const std::string& name,
                                                  Ra::Engine::RenderTechnique* technique )
    {
        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( name, this, Ra::Engine::RenderObjectType::FANCY );
        renderObject->setVisible( true );

        renderObject->setRenderTechnique( technique );

        std::shared_ptr<Ra::Engine::Mesh> displayMesh( new Ra::Engine::Mesh( name ) );
        std::vector<uint> indices;
        indices.reserve( mesh.m_triangles.size() * 3 );
        for ( const auto& i : mesh.m_triangles )
        {
            indices.push_back( i.x() );
            indices.push_back( i.y() );
            indices.push_back( i.z() );
        }

        displayMesh->loadGeometry( mesh.m_vertices, indices );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_NORMAL, mesh.m_normals );

        renderObject->setMesh( displayMesh );

        addRenderObject( renderObject );
    }

    void FancyMeshComponent::handleMeshLoading( const Ra::Asset::GeometryData* data )
    {
        std::string name( m_name );
        std::string roName;
        std::string meshName;
        std::string matName;

        if ( data->getName() == "" )
        {
            name = m_name;

            roName = name + "_RO";
            meshName = name + "_Mesh";
            matName = name + "_Mat";
        }
        else
        {
            name = data->getName();
            roName = name;
            meshName = name;
            matName = name + "_Mat";
            m_name = m_name + "|" + data->getName();
        }

        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( roName, this, Ra::Engine::RenderObjectType::FANCY );
        renderObject->setVisible( true );
        renderObject->setLocalTransform( data->getFrame() );

            Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( roName, this, Ra::Engine::RenderObjectType::FANCY );
            renderObject->setVisible( true );
            renderObject->setLocalTransform( data->getFrame() );

        m_mesh.clear();
        for( const auto& v : data->getVertices() )
        {
            m_mesh.m_vertices.push_back( data->getFrame() * v );
        }
        for( const auto& face : data->getFaces() ) {
            m_mesh.m_triangles.push_back( Ra::Core::Vector3i( face[0], face[1], face[2] ) );
        }
        Ra::Core::Geometry::areaWeightedNormal( m_mesh.m_vertices, m_mesh.m_triangles, m_mesh.m_normals );

        // FIXME(Charly): Find a cleaner way to build geometry
        std::vector<uint> indices;
        for ( const auto& face : data->getFaces() )
        {
            indices.push_back( face[0] );
            indices.push_back( face[1] );
            indices.push_back( face[2] );
        }

        Ra::Core::Vector3Array positions;
        Ra::Core::Vector3Array normals;
        Ra::Core::Vector4Array tangents;
        Ra::Core::Vector4Array bitangents;
        Ra::Core::Vector4Array texcoords;
        Ra::Core::Vector4Array colors;

        positions = m_mesh.m_vertices;
        normals   = m_mesh.m_normals;
        for ( const auto& v : data->getTangents() )     tangents.push_back( v );
        for ( const auto& v : data->getBiTangents() )   bitangents.push_back( v );
        for ( const auto& v : data->getTexCoords() )    texcoords.push_back( v );
        for ( const auto& v : data->getColors() )       colors.push_back( v );

        mesh->loadGeometry( positions, indices );

        mesh->addData( Ra::Engine::Mesh::VERTEX_NORMAL, normals );
        mesh->addData( Ra::Engine::Mesh::VERTEX_TANGENT, tangents );
        mesh->addData( Ra::Engine::Mesh::VERTEX_BITANGENT, bitangents );
        mesh->addData( Ra::Engine::Mesh::VERTEX_TEXCOORD, texcoords );
        mesh->addData( Ra::Engine::Mesh::VERTEX_COLOR, colors );
        // FIXME(Charly): Should not weights be part of the geometry ?
        //        mesh->addData( Ra::Engine::Mesh::VERTEX_WEIGHTS, meshData.weights );

        renderObject->setMesh( mesh );

        m_meshIndex = addRenderObject(renderObject);

        // FIXME(Charly)
        // Build m_mesh
        //        int triangleCount = meshData.indices.size() / 3;
        //        int vertexCount = meshData.positions.size();
        //        m_mesh.m_vertices.resize(vertexCount);
        //        m_mesh.m_normals.resize(vertexCount);
        //        m_mesh.m_triangles.resize(triangleCount);

        //        for (int i = 0; i < vertexCount; i++)
        //        {
        //            Ra::Core::Vector4 pos = meshData.positions[i];
        //            Ra::Core::Vector4 normals = meshData.normals[i];
        //            m_mesh.m_vertices[i] = Ra::Core::Vector3(pos(0), pos(1), pos(2));
        //            m_mesh.m_normals[i] = Ra::Core::Vector3(normals(0), normals(1), normals(2));
        //        }

        //        for (int i = 0; i < triangleCount; i++)
        //            m_mesh.m_triangles[i] = Ra::Core::Triangle(meshData.indices[i * 3], meshData.indices[i * 3 + 1], meshData.indices[i * 3 + 2]);

        Ra::Engine::RenderTechnique* rt = new Ra::Engine::RenderTechnique;
        Ra::Engine::Material* mat = new Ra::Engine::Material( matName );
        auto m = data->getMaterial();
        if ( m.hasDiffuse() )   mat->setKd( m.m_diffuse );
        if ( m.hasSpecular() )  mat->setKs( m.m_specular );
        if ( m.hasShininess() ) mat->setNs( m.m_shininess );
        if ( m.hasDiffuseTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_DIFFUSE, m.m_texDiffuse );
        if ( m.hasSpecularTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SPECULAR, m.m_texSpecular );
        if ( m.hasShininessTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SHININESS, m.m_texShininess );
        if ( m.hasOpacityTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_ALPHA, m.m_texOpacity );
        if ( m.hasNormalTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_NORMAL, m.m_texNormal );

        rt->material = mat;
        rt->shaderConfig = Ra::Engine::ShaderConfiguration( "BlinnPhong", "../Shaders" );

        renderObject->setRenderTechnique( rt );

    }

    Ra::Core::Index FancyMeshComponent::getMeshIndex() const
    {
        return m_meshIndex;
    }

    Ra::Core::TriangleMesh FancyMeshComponent::getMesh() const
    {
        return m_mesh;
    }

    void FancyMeshComponent::rayCastQuery( const Ra::Core::Ray& r) const
    {
        auto result  = Ra::Core::MeshUtils::castRay( m_mesh, r );
        int tidx = result.m_hitTriangle;
        if (tidx >= 0)
        {
            LOG(logINFO) << " Hit triangle " << tidx;
            LOG(logINFO) << " Nearest vertex " << result.m_nearestVertex;
        }
    }

} // namespace FancyMeshPlugin
<commit_msg>texturing fully disabled<commit_after>#include "FancyMeshComponent.hpp"

#include <Core/String/StringUtils.hpp>
#include <Core/Mesh/MeshUtils.hpp>

#include <Core/Geometry/Normal/Normal.hpp>

#include <Engine/Renderer/RenderObject/RenderObjectManager.hpp>
#include <Engine/Renderer/Mesh/Mesh.hpp>
#include <Engine/Renderer/RenderObject/RenderObject.hpp>
#include <Engine/Renderer/RenderObject/RenderObjectTypes.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderConfiguration.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderProgramManager.hpp>
#include <Engine/Renderer/RenderObject/Primitives/DrawPrimitives.hpp>

#include <Engine/Assets/FileData.hpp>
#include <Engine/Assets/GeometryData.hpp>

namespace FancyMeshPlugin
{
    FancyMeshComponent::FancyMeshComponent( const std::string& name )
        : Ra::Engine::Component( name )
    {
    }

    FancyMeshComponent::~FancyMeshComponent()
    {
        // TODO(Charly): Should we ask the RO manager to delete our render object ?
    }

    void FancyMeshComponent::initialize()
    {
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh, const std::string& name )
    {
        Ra::Engine::RenderTechnique* technique = new Ra::Engine::RenderTechnique;
        technique->material = new Ra::Engine::Material( "Default" );
        technique->shaderConfig = Ra::Engine::ShaderConfiguration( "Default", "../Shaders" );

        addMeshRenderObject(mesh, name, technique);
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh,
                                                  const std::string& name,
                                                  Ra::Engine::RenderTechnique* technique )
    {
        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( name, this, Ra::Engine::RenderObjectType::FANCY );
        renderObject->setVisible( true );

        renderObject->setRenderTechnique( technique );

        std::shared_ptr<Ra::Engine::Mesh> displayMesh( new Ra::Engine::Mesh( name ) );
        std::vector<uint> indices;
        indices.reserve( mesh.m_triangles.size() * 3 );
        for ( const auto& i : mesh.m_triangles )
        {
            indices.push_back( i.x() );
            indices.push_back( i.y() );
            indices.push_back( i.z() );
        }

        displayMesh->loadGeometry( mesh.m_vertices, indices );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_NORMAL, mesh.m_normals );

        renderObject->setMesh( displayMesh );

        addRenderObject( renderObject );
    }

    void FancyMeshComponent::handleMeshLoading( const Ra::Asset::GeometryData* data )
    {
        std::string name( m_name );
        std::string roName;
        std::string meshName;
        std::string matName;

        if ( data->getName() == "" )
        {
            name = m_name;

            roName = name + "_RO";
            meshName = name + "_Mesh";
            matName = name + "_Mat";
        }
        else
        {
            name = data->getName();
            roName = name;
            meshName = name;
            matName = name + "_Mat";
            m_name = m_name + "|" + data->getName();
        }

        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( roName, this, Ra::Engine::RenderObjectType::FANCY );
        renderObject->setVisible( true );
        renderObject->setLocalTransform( data->getFrame() );

            Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( roName, this, Ra::Engine::RenderObjectType::FANCY );
            renderObject->setVisible( true );
            renderObject->setLocalTransform( data->getFrame() );

        m_mesh.clear();
        for( const auto& v : data->getVertices() )
        {
            m_mesh.m_vertices.push_back( data->getFrame() * v );
        }
        for( const auto& face : data->getFaces() ) {
            m_mesh.m_triangles.push_back( Ra::Core::Vector3i( face[0], face[1], face[2] ) );
        }
        Ra::Core::Geometry::uniformNormal( m_mesh.m_vertices, m_mesh.m_triangles, m_mesh.m_normals );

        // FIXME(Charly): Find a cleaner way to build geometry
        std::vector<uint> indices;
        for ( const auto& face : data->getFaces() )
        {
            indices.push_back( face[0] );
            indices.push_back( face[1] );
            indices.push_back( face[2] );
        }

        Ra::Core::Vector3Array positions;
        Ra::Core::Vector3Array normals;
        Ra::Core::Vector4Array tangents;
        Ra::Core::Vector4Array bitangents;
        Ra::Core::Vector4Array texcoords;
        Ra::Core::Vector4Array colors;

        positions = m_mesh.m_vertices;
        normals   = m_mesh.m_normals;
        for ( const auto& v : data->getTangents() )     tangents.push_back( v );
        for ( const auto& v : data->getBiTangents() )   bitangents.push_back( v );
        for ( const auto& v : data->getTexCoords() )    texcoords.push_back( v );
        for ( const auto& v : data->getColors() )       colors.push_back( v );

        mesh->loadGeometry( positions, indices );

        mesh->addData( Ra::Engine::Mesh::VERTEX_NORMAL, normals );
        mesh->addData( Ra::Engine::Mesh::VERTEX_TANGENT, tangents );
        mesh->addData( Ra::Engine::Mesh::VERTEX_BITANGENT, bitangents );
        mesh->addData( Ra::Engine::Mesh::VERTEX_TEXCOORD, texcoords );
        mesh->addData( Ra::Engine::Mesh::VERTEX_COLOR, colors );
        // FIXME(Charly): Should not weights be part of the geometry ?
        //        mesh->addData( Ra::Engine::Mesh::VERTEX_WEIGHTS, meshData.weights );

        renderObject->setMesh( mesh );

        m_meshIndex = addRenderObject(renderObject);

        // FIXME(Charly)
        // Build m_mesh
        //        int triangleCount = meshData.indices.size() / 3;
        //        int vertexCount = meshData.positions.size();
        //        m_mesh.m_vertices.resize(vertexCount);
        //        m_mesh.m_normals.resize(vertexCount);
        //        m_mesh.m_triangles.resize(triangleCount);

        //        for (int i = 0; i < vertexCount; i++)
        //        {
        //            Ra::Core::Vector4 pos = meshData.positions[i];
        //            Ra::Core::Vector4 normals = meshData.normals[i];
        //            m_mesh.m_vertices[i] = Ra::Core::Vector3(pos(0), pos(1), pos(2));
        //            m_mesh.m_normals[i] = Ra::Core::Vector3(normals(0), normals(1), normals(2));
        //        }

        //        for (int i = 0; i < triangleCount; i++)
        //            m_mesh.m_triangles[i] = Ra::Core::Triangle(meshData.indices[i * 3], meshData.indices[i * 3 + 1], meshData.indices[i * 3 + 2]);

        Ra::Engine::RenderTechnique* rt = new Ra::Engine::RenderTechnique;
        Ra::Engine::Material* mat = new Ra::Engine::Material( matName );
        auto m = data->getMaterial();
        if ( m.hasDiffuse() )   mat->setKd( m.m_diffuse );
        if ( m.hasSpecular() )  mat->setKs( m.m_specular );
        if ( m.hasShininess() ) mat->setNs( m.m_shininess );
        //if ( m.hasDiffuseTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_DIFFUSE, m.m_texDiffuse );
        //if ( m.hasSpecularTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SPECULAR, m.m_texSpecular );
        //if ( m.hasShininessTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SHININESS, m.m_texShininess );
        //if ( m.hasOpacityTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_ALPHA, m.m_texOpacity );
        //if ( m.hasNormalTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_NORMAL, m.m_texNormal );

        rt->material = mat;
        rt->shaderConfig = Ra::Engine::ShaderConfiguration( "BlinnPhong", "../Shaders" );

        renderObject->setRenderTechnique( rt );

    }

    Ra::Core::Index FancyMeshComponent::getMeshIndex() const
    {
        return m_meshIndex;
    }

    Ra::Core::TriangleMesh FancyMeshComponent::getMesh() const
    {
        return m_mesh;
    }

    void FancyMeshComponent::rayCastQuery( const Ra::Core::Ray& r) const
    {
        auto result  = Ra::Core::MeshUtils::castRay( m_mesh, r );
        int tidx = result.m_hitTriangle;
        if (tidx >= 0)
        {
            LOG(logINFO) << " Hit triangle " << tidx;
            LOG(logINFO) << " Nearest vertex " << result.m_nearestVertex;
        }
    }

} // namespace FancyMeshPlugin
<|endoftext|>


<commit_before>// REQUIRES: static-analyzer
// RUN: clang-tidy %s -checks='-*,clang-analyzer-*' -- | FileCheck %s
extern void *malloc(unsigned long);
extern void free(void *);

void f() {
  int *p = new int(42);
  delete p;
  delete p;
  // CHECK: warning: Attempt to free released memory [clang-analyzer-cplusplus.NewDelete]
}

void g() {
  void *q = malloc(132);
  free(q);
  free(q);
  // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
}
<commit_msg>Fix a lit test failure after MallocChecker changes<commit_after>// REQUIRES: static-analyzer
// RUN: clang-tidy %s -checks='-*,clang-analyzer-*' -- | FileCheck %s
extern void *malloc(unsigned long);
extern void free(void *);

void f() {
  int *p = new int(42);
  delete p;
  delete p;
  // CHECK: warning: Attempt to delete released memory [clang-analyzer-cplusplus.NewDelete]
}

void g() {
  void *q = malloc(132);
  free(q);
  free(q);
  // CHECK: warning: Attempt to free released memory [clang-analyzer-unix.Malloc]
}
<|endoftext|>


<commit_before>#include <osg/ref_ptr>

#include <osgIntrospection/Reflection>
#include <osgIntrospection/Type>
#include <osgIntrospection/MethodInfo>
#include <osgIntrospection/PropertyInfo>

#include <osgDB/DynamicLibrary>

#include <iostream>
#include <algorithm>

using namespace osgIntrospection;

// borrowed from osgDB...
std::string createLibraryNameForWrapper(const std::string& ext)
{
#if defined(WIN32)
    // !! recheck evolving Cygwin DLL extension naming protocols !! NHV
    #ifdef __CYGWIN__
        return "cygosgwrapper_"+ext+".dll";
    #elif defined(__MINGW32__)
        return "libosgwrapper_"+ext+".dll";
    #else
        #ifdef _DEBUG
            return "osgwrapper_"+ext+"d.dll";
        #else
            return "osgwrapper_"+ext+".dll";
        #endif
    #endif
#elif macintosh
    return "osgwrapper_"+ext;
#elif defined(__hpux__)
    // why don't we use PLUGIN_EXT from the makefiles here?
    return "osgwrapper_"+ext+".sl";
#else
    return "osgwrapper_"+ext+".so";
#endif

}

bool type_order(const Type *v1, const Type *v2)
{
    if (!v1->isDefined()) return v2->isDefined();
    if (!v2->isDefined()) return false;
    return v1->getQualifiedName().compare(v2->getQualifiedName()) < 0;
}

void print_types()
{
    // get the map of types that have been reflected
    const TypeMap &tm = Reflection::getTypes();

    // create a sortable list of types
    TypeList types(tm.size());
    TypeList::iterator j = types.begin();
    for (TypeMap::const_iterator i=tm.begin(); i!=tm.end(); ++i, ++j)
        *j = i->second;

    // sort the map
    std::sort(types.begin(), types.end(), &type_order);

    // iterate through the type map and display some
    // details for each type
    for (TypeList::const_iterator i=types.begin(); i!=types.end(); ++i)
    {
        // ignore pointer types and undefined types
        if (!(*i)->isDefined() || (*i)->isPointer() || (*i)->isReference())
            continue;

        // print the type name
        std::cout << (*i)->getQualifiedName() << "\n";

        // check whether the type is abstract
        if ((*i)->isAbstract()) std::cout << "\t[abstract]\n";

        // check whether the type is atomic
        if ((*i)->isAtomic()) std::cout << "\t[atomic]\n";

        // check whether the type is an enumeration. If yes, display
        // the list of enumeration labels
        if ((*i)->isEnum())
        {
            std::cout << "\t[enum]\n";
            std::cout << "\tenumeration values:\n";
            const EnumLabelMap &emap = (*i)->getEnumLabels();
            for (EnumLabelMap::const_iterator j=emap.begin(); j!=emap.end(); ++j)
            {
                std::cout << "\t\t" << j->second << " = " << j->first << "\n";
            }
        }

        // if the type has one or more base types, then display their
        // names
        if ((*i)->getNumBaseTypes() > 0)
        {
            std::cout << "\tderived from: ";
            for (int j=0; j<(*i)->getNumBaseTypes(); ++j)
            {
                const Type &base = (*i)->getBaseType(j);
                if (base.isDefined())
                    std::cout << base.getQualifiedName() << "    ";
                else
                    std::cout << "[undefined type]    ";
            }
            std::cout << "\n";
        }

        // display a list of methods defined for the current type
        const MethodInfoList &mil = (*i)->getMethods();
        if (!mil.empty())
        {
            std::cout << "\t* methods:\n";
            for (MethodInfoList::const_iterator j=mil.begin(); j!=mil.end(); ++j)
            {
                // get the MethodInfo object that describes the current
                // method
                const MethodInfo &mi = **j;

                std::cout << "\t    ";

                // display if the method is virtual
                if (mi.isVirtual())
                    std::cout << "virtual ";

                // display the method's return type if defined
                if (mi.getReturnType().isDefined())
                    std::cout << mi.getReturnType().getQualifiedName() << " ";
                else
                    std::cout << "[UNDEFINED TYPE] ";

                // display the method's name
                std::cout << mi.getName() << "(";

                // display method's parameters
                const ParameterInfoList &params = mi.getParameters();
                for (ParameterInfoList::const_iterator k=params.begin(); k!=params.end(); ++k)
                {
                    // get the ParameterInfo object that describes the
                    // current parameter
                    const ParameterInfo &pi = **k;

                    // display the parameter's modifier
                    if (pi.isIn())
                        std::cout << "IN";
                    if (pi.isOut())
                        std::cout << "OUT";
                    if (pi.isIn() || pi.isOut())
                        std::cout << " ";

                    // display the parameter's type name
                    if (pi.getParameterType().isDefined())
                        std::cout << pi.getParameterType().getQualifiedName();

                    // display the parameter's name if defined
                    if (!pi.getName().empty())
                        std::cout << " " << pi.getName();

                    if ((k+1)!=params.end())
                        std::cout << ", ";
                }
                std::cout << ")";
                if (mi.isConst())
                    std::cout << " const";
                if (mi.isPureVirtual())
                    std::cout << " = 0";
                std::cout << "\n";
            }
        }

        // display a list of properties defined for the current type
        const PropertyInfoList &pil = (*i)->getProperties();
        if (!pil.empty())
        {
            std::cout << "\t* properties:\n";
            for (PropertyInfoList::const_iterator j=pil.begin(); j!=pil.end(); ++j)
            {
                // get the PropertyInfo object that describes the current
                // property
                const PropertyInfo &pi = **j;

                std::cout << "\t    ";

                std::cout << "{";
                std::cout << (pi.canGet()? "G": " ");
                std::cout << (pi.canSet()? "S": " ");
                std::cout << (pi.canCount()? "C": " ");
                std::cout << (pi.canAdd()? "A": " ");
                std::cout << "}  ";

                // display the property's name
                std::cout << pi.getName();

                // display the property's value type if defined
                std::cout << " (";
                if (pi.getPropertyType().isDefined())
                    std::cout << pi.getPropertyType().getQualifiedName();
                else
                    std::cout << "UNDEFINED TYPE";
                std::cout << ") ";

                // check whether the property is an array property
                if (pi.isArray())
                {
                    std::cout << "  [ARRAY]";
                }

                // check whether the property is an indexed property
                if (pi.isIndexed())
                {
                    std::cout << "  [INDEXED]\n\t\t       indices:\n";

                    const ParameterInfoList &ind = pi.getIndexParameters();

                    // print the list of indices
                    int num = 1;
                    for (ParameterInfoList::const_iterator k=ind.begin(); k!=ind.end(); ++k, ++num)
                    {
                        std::cout << "\t\t           " << num << ") ";
                        const ParameterInfo &par = **k;
                        std::cout << par.getParameterType().getQualifiedName() << " " << par.getName();
                        std::cout << "\n";
                    }
                }

                std::cout << "\n";
            }
        }
        std::cout << "\n" << std::string(75, '-') << "\n";
    }
}

int main()
{
    // load the library of wrappers that reflect the
    // classes defined in the 'osg' namespace. In the
    // future this will be done automatically under
    // certain circumstances (like deserialization).
    osg::ref_ptr<osgDB::DynamicLibrary> osg_reflectors =
        osgDB::DynamicLibrary::loadLibrary(createLibraryNameForWrapper("osg"));

    // display a detailed list of reflected types
    try
    {
        print_types();
    }
    catch(const osgIntrospection::Exception &e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

<commit_msg>From Mike Wittman, updates to support new protected method support<commit_after>#include <osg/ref_ptr>

#include <osgIntrospection/Reflection>
#include <osgIntrospection/Type>
#include <osgIntrospection/MethodInfo>
#include <osgIntrospection/PropertyInfo>

#include <osgDB/DynamicLibrary>

#include <iostream>
#include <algorithm>

using namespace osgIntrospection;

// borrowed from osgDB...
std::string createLibraryNameForWrapper(const std::string& ext)
{
#if defined(WIN32)
    // !! recheck evolving Cygwin DLL extension naming protocols !! NHV
    #ifdef __CYGWIN__
        return "cygosgwrapper_"+ext+".dll";
    #elif defined(__MINGW32__)
        return "libosgwrapper_"+ext+".dll";
    #else
        #ifdef _DEBUG
            return "osgwrapper_"+ext+"d.dll";
        #else
            return "osgwrapper_"+ext+".dll";
        #endif
    #endif
#elif macintosh
    return "osgwrapper_"+ext;
#elif defined(__hpux__)
    // why don't we use PLUGIN_EXT from the makefiles here?
    return "osgwrapper_"+ext+".sl";
#else
    return "osgwrapper_"+ext+".so";
#endif

}

bool type_order(const Type *v1, const Type *v2)
{
    if (!v1->isDefined()) return v2->isDefined();
    if (!v2->isDefined()) return false;
    return v1->getQualifiedName().compare(v2->getQualifiedName()) < 0;
}

void print_method(const MethodInfo &mi)
{
    std::cout << "\t    ";

    // display if the method is virtual
    if (mi.isVirtual())
        std::cout << "virtual ";

    // display the method's return type if defined
    if (mi.getReturnType().isDefined())
        std::cout << mi.getReturnType().getQualifiedName() << " ";
    else
        std::cout << "[UNDEFINED TYPE] ";

    // display the method's name
    std::cout << mi.getName() << "(";

    // display method's parameters
    const ParameterInfoList &params = mi.getParameters();
    for (ParameterInfoList::const_iterator k=params.begin(); k!=params.end(); ++k)
    {
        // get the ParameterInfo object that describes the
        // current parameter
        const ParameterInfo &pi = **k;

        // display the parameter's modifier
        if (pi.isIn())
            std::cout << "IN";
        if (pi.isOut())
            std::cout << "OUT";
        if (pi.isIn() || pi.isOut())
            std::cout << " ";

        // display the parameter's type name
        if (pi.getParameterType().isDefined())
            std::cout << pi.getParameterType().getQualifiedName();

        // display the parameter's name if defined
        if (!pi.getName().empty())
            std::cout << " " << pi.getName();

        if ((k+1)!=params.end())
            std::cout << ", ";
    }
    std::cout << ")";
    if (mi.isConst())
        std::cout << " const";
    if (mi.isPureVirtual())
        std::cout << " = 0";
    std::cout << "\n";
}

void print_type(const Type &type)
{
    // ignore pointer types and undefined types
    if (!type.isDefined() || type.isPointer() || type.isReference())
        return;

    // print the type name
    std::cout << type.getQualifiedName() << "\n";

    // check whether the type is abstract
    if (type.isAbstract()) std::cout << "\t[abstract]\n";

    // check whether the type is atomic
    if (type.isAtomic()) std::cout << "\t[atomic]\n";

    // check whether the type is an enumeration. If yes, display
    // the list of enumeration labels
    if (type.isEnum())
    {
        std::cout << "\t[enum]\n";
        std::cout << "\tenumeration values:\n";
        const EnumLabelMap &emap = type.getEnumLabels();
        for (EnumLabelMap::const_iterator j=emap.begin(); j!=emap.end(); ++j)
        {
            std::cout << "\t\t" << j->second << " = " << j->first << "\n";
        }
    }

    // if the type has one or more base types, then display their
    // names
    if (type.getNumBaseTypes() > 0)
    {
        std::cout << "\tderived from: ";
        for (int j=0; j<type.getNumBaseTypes(); ++j)
        {
            const Type &base = type.getBaseType(j);
            if (base.isDefined())
                std::cout << base.getQualifiedName() << "    ";
            else
                std::cout << "[undefined type]    ";
        }
        std::cout << "\n";
    }

    // display a list of public methods defined for the current type
    const MethodInfoList &mil = type.getMethods();
    if (!mil.empty())
    {
        std::cout << "\t* public methods:\n";
        for (MethodInfoList::const_iterator j=mil.begin(); j!=mil.end(); ++j)
        {
            // get the MethodInfo object that describes the current
            // method
            const MethodInfo &mi = **j;

            print_method(mi);
        }
    }

    // display a list of protected methods defined for the current type
    const MethodInfoList &bmil = type.getMethods(Type::PROTECTED_FUNCTIONS);
    if (!bmil.empty())
    {
        std::cout << "\t* protected methods:\n";
        for (MethodInfoList::const_iterator j=bmil.begin(); j!=bmil.end(); ++j)
        {
            // get the MethodInfo object that describes the current
            // method
            const MethodInfo &mi = **j;

            print_method(mi);
        }
    }

    // display a list of properties defined for the current type
    const PropertyInfoList &pil = type.getProperties();
    if (!pil.empty())
    {
        std::cout << "\t* properties:\n";
        for (PropertyInfoList::const_iterator j=pil.begin(); j!=pil.end(); ++j)
        {
            // get the PropertyInfo object that describes the current
            // property
            const PropertyInfo &pi = **j;

            std::cout << "\t    ";

            std::cout << "{";
            std::cout << (pi.canGet()? "G": " ");
            std::cout << (pi.canSet()? "S": " ");
            std::cout << (pi.canCount()? "C": " ");
            std::cout << (pi.canAdd()? "A": " ");
            std::cout << "}  ";

            // display the property's name
            std::cout << pi.getName();

            // display the property's value type if defined
            std::cout << " (";
            if (pi.getPropertyType().isDefined())
                std::cout << pi.getPropertyType().getQualifiedName();
            else
                std::cout << "UNDEFINED TYPE";
            std::cout << ") ";

            // check whether the property is an array property
            if (pi.isArray())
            {
                std::cout << "  [ARRAY]";
            }

            // check whether the property is an indexed property
            if (pi.isIndexed())
            {
                std::cout << "  [INDEXED]\n\t\t       indices:\n";

                const ParameterInfoList &ind = pi.getIndexParameters();

                // print the list of indices
                int num = 1;
                for (ParameterInfoList::const_iterator k=ind.begin(); k!=ind.end(); ++k, ++num)
                {
                    std::cout << "\t\t           " << num << ") ";
                    const ParameterInfo &par = **k;
                    std::cout << par.getParameterType().getQualifiedName() << " " << par.getName();
                    std::cout << "\n";
                }
            }

            std::cout << "\n";
        }
    }
    std::cout << "\n" << std::string(75, '-') << "\n";
}

void print_types()
{
    // get the map of types that have been reflected
    const TypeMap &tm = Reflection::getTypes();

    // create a sortable list of types
    TypeList types(tm.size());
    TypeList::iterator j = types.begin();
    for (TypeMap::const_iterator i=tm.begin(); i!=tm.end(); ++i, ++j)
        *j = i->second;

    // sort the map
    std::sort(types.begin(), types.end(), &type_order);

    // iterate through the type map and display some
    // details for each type
    for (TypeList::const_iterator i=types.begin(); i!=types.end(); ++i)
    {
        print_type(**i);
    }
}

int main()
{
    // load the library of wrappers that reflect the
    // classes defined in the 'osg' namespace. In the
    // future this will be done automatically under
    // certain circumstances (like deserialization).
    osg::ref_ptr<osgDB::DynamicLibrary> osg_reflectors =
        osgDB::DynamicLibrary::loadLibrary(createLibraryNameForWrapper("osg"));

    // display a detailed list of reflected types
    try
    {
        print_types();
    }
    catch(const osgIntrospection::Exception &e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

<|endoftext|>


<commit_before>#include "WrapperGenerator.h"

using namespace std;

void WrapperGenerator::initOpToGenMap() {
    shared_ptr<TracingInnerWrapperGenerator> traceGen;
    shared_ptr<CachingIPCInnerWrapperGenerator> cachingIPCGen;
    shared_ptr<NonCachingIPCInnerWrapperGenerator> nonCachingIPCGen;

    traceGen = make_shared<TracingInnerWrapperGenerator>(operationMap);
    cachingIPCGen = make_shared<CachingIPCInnerWrapperGenerator>();
    nonCachingIPCGen = make_shared<NonCachingIPCInnerWrapperGenerator>();

    wrapperToGenMap = WrapperGenMap({{"MUTEX_LOCK", traceGen},
                                     {"MUTEX_UNLOCK", traceGen},
                                     {"CV_WAIT", traceGen},
                                     {"CV_BROADCAST", traceGen},
                                     {"CV_SIGNAL", traceGen},
                                     {"QUEUE_ENQUEUE", traceGen},
                                     {"QUEUE_DEQUEUE", traceGen},
                                     {"MESSAGE_SEND", traceGen},
                                     {"MESSAGE_RECEIVE", traceGen},
                                     {"MKNOD", cachingIPCGen},
                                     {"OPEN", cachingIPCGen},
                                     {"PIPE", cachingIPCGen},
                                     {"MSGGET", cachingIPCGen},
                                     {"READ", nonCachingIPCGen},
                                     {"WRITE", nonCachingIPCGen},
                                     {"MSGRCV", nonCachingIPCGen},
                                     {"MSGSND", nonCachingIPCGen}});
}

WrapperGenerator::WrapperGenerator(shared_ptr<unordered_map<string,
                                   FunctionPrototype>> _prototypeMap,
                                   std::shared_ptr<std::unordered_map<std::string,
                                   std::string>> _operationMap,
                                   string pathPrefix):
                                   prototypeMap(_prototypeMap),
                                   operationMap(_operationMap),
                                   vprofInternalOps({{MKNOD, true}, {READ, true},
                                                     {WRITE, true}, {PIPE, true},
                                                     {MSGGET, true}, {MSGSND, true},
                                                     {MSGRCV, true}}) {
    initOpToGenMap();

    headerFile.open(pathPrefix + "VProfEventWrappers.h");
    implementationFile.open(pathPrefix + "VProfEventWrappers.cpp");

    const string generatedFileMessage =
        " ///////////////////////////////////////////////////// \n"
        " // Note that this file was generated by VProfiler. // \n"
        " // Please do not change the contents of this file! // \n"
        " ///////////////////////////////////////////////////// \n\n";

    headerFile << generatedFileMessage;
    implementationFile << generatedFileMessage;
}

bool WrapperGenerator::isIPCOperation(const Operation op) const {
    return vprofInternalOps.find(op) != vprofInternalOps.end();
}

void instrumentIPCFunction(std::string &functionName, FunctionPrototype &prototype) {
}

vector<string> WrapperGenerator::getFilenames() {
    vector<string> result;

    for (auto kv : *prototypeMap) {
        result.push_back(kv.second.filename);
    }

    sort(result.begin(), result.end());
    result.erase(unique(result.begin(), result.end()), result.end());
    return result;
}

void WrapperGenerator::GenerateHeader() {
    vector<string> includeNames = getFilenames();
    headerFile << "#ifndef VPROFEVENTWRAPPERS_H\n#define VPROFEVENTWRAPPERS_H\n";
    for (string &includeName : includeNames) {
        headerFile << "#include \"" + includeName + "\"\n";
    }
    headerFile << "#include \"trace_tool.h\"\n\n"
                  "#ifdef __cplusplus\nextern \"C\" {\n#endif";

    for (auto kv : *prototypeMap) {
        headerFile << kv.second.functionPrototype + ";\n\n";
    }

    headerFile << "#ifdef __cplusplus\n}\n#endif\n\n#endif";

    headerFile.close();
}

void WrapperGenerator::GenerateImplementations() {
    string operation;
    implementationFile << "#include \"VProfEventWrappers.h\"\n\n";

    for (auto kv : *prototypeMap) {
        operation = (*operationMap)[kv.first];

        implementationFile << kv.second.functionPrototype + " {\n\t";

        if (kv.second.returnType != "void") {
            implementationFile << kv.second.returnType + " result;\n\t";
        }

        operationToGenMap[operation]->GenerateWrapperPrologue(kv.first, kv.second);

        if (kv.second.returnType != "void") {
            implementationFile << "result = ";
        }

        implementationFile << kv.second.innerCallPrefix + "(";

        for (int i = 0, j = kv.second.paramVars.size(); i < j; i++) {
            implementationFile << kv.second.paramVars[i];

            if (i != (j - 1)) {
                implementationFile << ", ";
            }
        }

        implementationFile <<");\n\t";

        operationToGenMap[operation]->GenerateWrapperEpilogue(kv.first, kv.second);

        if (kv.second.returnType != "void") {
            implementationFile << "\treturn result;\n";
        }

        implementationFile << "}\n\n";
    }

    implementationFile.close();
}

void WrapperGenerator::GenerateWrappers() {
    GenerateHeader();
    GenerateImplementations();
}
<commit_msg>Few changes before band<commit_after>#include "WrapperGenerator.h"

using namespace std;

void WrapperGenerator::initOpToGenMap() {
    shared_ptr<TracingInnerWrapperGenerator> traceGen;
    shared_ptr<CachingIPCInnerWrapperGenerator> cachingIPCGen;
    shared_ptr<NonCachingIPCInnerWrapperGenerator> nonCachingIPCGen;

    traceGen = make_shared<TracingInnerWrapperGenerator>(operationMap);
    cachingIPCGen = make_shared<CachingIPCInnerWrapperGenerator>();
    nonCachingIPCGen = make_shared<NonCachingIPCInnerWrapperGenerator>();

    operationToGenerator = WrapperGenMap({{"MUTEX_LOCK", traceGen},
                                          {"MUTEX_UNLOCK", traceGen},
                                          {"CV_WAIT", traceGen},
                                          {"CV_BROADCAST", traceGen},
                                          {"CV_SIGNAL", traceGen},
                                          {"QUEUE_ENQUEUE", traceGen},
                                          {"QUEUE_DEQUEUE", traceGen},
                                          {"MESSAGE_SEND", traceGen},
                                          {"MESSAGE_RECEIVE", traceGen},
                                          {"MKNOD", cachingIPCGen},
                                          {"OPEN", cachingIPCGen},
                                          {"PIPE", cachingIPCGen},
                                          {"MSGGET", cachingIPCGen},
                                          {"READ", nonCachingIPCGen},
                                          {"WRITE", nonCachingIPCGen},
                                          {"MSGRCV", nonCachingIPCGen},
                                          {"MSGSND", nonCachingIPCGen}});
}

WrapperGenerator::WrapperGenerator(shared_ptr<unordered_map<string,
                                   FunctionPrototype>> _prototypeMap,
                                   std::shared_ptr<std::unordered_map<std::string,
                                   std::string>> _operationMap,
                                   string pathPrefix):
                                   prototypeMap(_prototypeMap),
                                   operationMap(_operationMap) {
    initOpToGenMap();

    headerFile.open(pathPrefix + "VProfEventWrappers.h");
    implementationFile.open(pathPrefix + "VProfEventWrappers.cpp");

    const string generatedFileMessage =
        " ///////////////////////////////////////////////////// \n"
        " // Note that this file was generated by VProfiler. // \n"
        " // Please do not change the contents of this file! // \n"
        " ///////////////////////////////////////////////////// \n\n";

    headerFile << generatedFileMessage;
    implementationFile << generatedFileMessage;
}

vector<string> WrapperGenerator::getFilenames() {
    vector<string> result;

    for (auto kv : *prototypeMap) {
        result.push_back(kv.second.filename);
    }

    sort(result.begin(), result.end());
    result.erase(unique(result.begin(), result.end()), result.end());
    return result;
}

void WrapperGenerator::GenerateHeader() {
    vector<string> includeNames = getFilenames();
    headerFile << "#ifndef VPROFEVENTWRAPPERS_H\n#define VPROFEVENTWRAPPERS_H\n";
    for (string &includeName : includeNames) {
        headerFile << "#include \"" + includeName + "\"\n";
    }
    headerFile << "#include \"trace_tool.h\"\n\n"
                  "#ifdef __cplusplus\nextern \"C\" {\n#endif";

    for (auto kv : *prototypeMap) {
        headerFile << kv.second.functionPrototype + ";\n\n";
    }

    headerFile << "#ifdef __cplusplus\n}\n#endif\n\n#endif";

    headerFile.close();
}

void WrapperGenerator::GenerateImplementations() {
    string operation;
    implementationFile << "#include \"VProfEventWrappers.h\"\n\n";

    for (auto kv : *prototypeMap) {
        operation = (*operationMap)[kv.first];

        implementationFile << kv.second.functionPrototype + " {\n\t";

        if (kv.second.returnType != "void") {
            implementationFile << kv.second.returnType + " result;\n\t";
        }

        operationToGenerator[operation]->GenerateWrapperPrologue(kv.first, kv.second);

        if (kv.second.returnType != "void") {
            implementationFile << "result = ";
        }

        implementationFile << kv.second.innerCallPrefix + "(";

        for (int i = 0, j = kv.second.paramVars.size(); i < j; i++) {
            implementationFile << kv.second.paramVars[i];

            if (i != (j - 1)) {
                implementationFile << ", ";
            }
        }

        implementationFile <<");\n\t";

        operationToGenerator[operation]->GenerateWrapperEpilogue(kv.first, kv.second);

        if (kv.second.returnType != "void") {
            implementationFile << "\treturn result;\n";
        }

        implementationFile << "}\n\n";
    }

    implementationFile.close();
}

void WrapperGenerator::GenerateWrappers() {
    GenerateHeader();
    GenerateImplementations();
}
<|endoftext|>


<commit_before>#pragma once
#ifndef ARGUMENT_LIB_HPP__
#define ARGUMENT_LIB_HPP__ "0.0.0@fArgumentLib.hpp"
/**
*	DESCRIPTION:
*		Module contains implementation of argument parser and helprer structures.
*	AUTHOR:
*		Mikhail Demchenko
*		mailto:dev.echo.mike@gmail.com
*		https://github.com/echo-Mike
**/
/**
*   MIT License
*
*   Copyright (c) 2017-2018 Mikhail Demchenko dev.echo.mike@gmail.com
*
*   Permission is hereby granted, free of charge, to any person obtaining a copy
*   of this software and associated documentation files (the "Software"), to deal
*   in the Software without restriction, including without limitation the rights
*   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*   copies of the Software, and to permit persons to whom the Software is
*   furnished to do so, subject to the following conditions:
*
*   The above copyright notice and this permission notice shall be included in all
*   copies or substantial portions of the Software.
*
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*   SOFTWARE.
**/
//STD
#include <cstring>

#ifdef TEST
    #include <cstdio>
    struct FArgumentLibLoggerSingleton
    {
        static std::FILE* getInstance(const char* path)
        {
            static FArgumentLibLoggerSingleton s(path);
            return s.h;
        }
    private:
        std::FILE* h;
        FArgumentLibLoggerSingleton(const char* path) : h(std::fopen(path,"w+")) {}
        ~FArgumentLibLoggerSingleton()
        {
            std::fflush(h);
            std::fclose(h);
        }
    };
#endif

#if defined(TEST) && !defined(LOG)
#define LOG(format, ...) \
do { \
	std::fprintf(FArgumentLibLoggerSingleton::getInstance(".\\fArgumentLibTestLog.txt"), "[%-35s: %-25s: line:%-4d] " format "\n", __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
} while(0);
#endif

//Main lib namespace
namespace Arguments
{
    //Set of possible option prefixes
    static const char *opt_ionPrefixes = "-/";

    //Set of types of otions
    enum class ArgTypes : char {
        Null = 0,   //Type of last option in option list
        Flag,   //The flag option type
        Value   //Option with leading value type
        //MultiValue
    };

    struct Option {
        const char* shortCommand;
        const char* longCommand;
        ArgTypes type;
        int data;
    };

    /**
    *   @brief Identifies null-terminated string 'arg' as option/
    *   @param[in]  arg Pointer to first char of examined null-terminated string.
    *   @return Pointer to first option char in 'arg' or nullptr if not an option/
    **/
    char* isOption(char* arg)
    {
        auto size = std::strspn(arg, opt_ionPrefixes);
        return (size == 0) ? nullptr : arg + size;
    }

    /**
    *   @brief Attempts to find flag argument in argument list
    *   @param[in]  argc    Argument list length.
    *   @param[in]  argv    Argument list.
    *   @param[in:out]  opt Option to find.
    *   @param[in]  start   Position in argument list to start with.
    *   @return Noreturn
    **/
    void findFlagArg(int argc, char* argv[], Option& opt, int start = 0)
    {
        opt.data = false;
        // Flag argument must be at maximum at the end
        if (start >= argc)
            return;
        char* opt_ = nullptr;
        for (auto index = start; index < argc; ++index)
        {
            opt_ = isOption(argv[index]);
            if (opt_)
            {
                if (std::strstr(opt_, opt.shortCommand) != NULL ||
                    !std::strcmp(opt_, opt.longCommand))
                {
                    opt.data = true;
                    return;
                }
            }
        }
    }

    /**
    *   @brief Attempts to find value argument in argument list
    *   @param[in]  argc    Argument list length.
    *   @param[in]  argv    Argument list.
    *   @param[in:out]  opt Option to find.
    *   @param[in]  start   Position in argument list to start with.
    *   @return Noreturn
    **/
    void findValueArg(int argc, char* argv[], Option& opt, int start = 0)
    {
        opt.data = -1;
        // Value argument must have one following argument at minimum
        if (start >= argc - 1)
            return;
        char* opt_ = nullptr;
        for (auto index = start; index < argc - 1; ++index)
        {
            opt_ = isOption(argv[index]);
            if (opt_) {
                if (!std::strcmp(opt_, opt.shortCommand) ||
                    !std::strcmp(opt_, opt.longCommand))
                {
                    opt.data = index + 1;
                    return;
                }
            }
        }
    }

    /**
    *   @brief Main argumant parsing function.
    *   @param[in]  argc    Argument list length.
    *   @param[in]  argv    Argument list.
    *   @param[in:out]  optv Option list.
    *   @retunr Noreturn
    **/
    void parseArgs(int argc, char* argv[], Option optv[])
    {
        int index = 0;
        while (optv[index].type != ArgTypes::Null)
        {
            switch (optv[index].type) {
                case ArgTypes::Flag:
                    findFlagArg(argc, argv, optv[index]);
                    break;
                case ArgTypes::Value:
                    findValueArg(argc, argv, optv[index]);
                    break;
                default:
                    return;
            }
            ++index;
        }
    }
}
#endif<commit_msg>[=][ARG]Grammar and style corrections<commit_after>#ifndef ARGUMENT_LIB_HPP_
#define ARGUMENT_LIB_HPP_ "0.0.0@fArgumentLib.hpp"
/**
 * DESCRIPTION:
 *     Module contains implementation of argument parser and helper structures.
 * AUTHOR:
 *     Mikhail Demchenko
 *     mailto:dev.echo.mike@gmail.com
 *     https://github.com/echo-Mike
 */

/**
 * MIT License
 *
 * Copyright (c) 2017-2018 Mikhail Demchenko dev.echo.mike@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// STD
#include <cstring>

#ifdef TEST
    #include <cstdio>
    struct FArgumentLibLoggerSingleton
    {
        static std::FILE* getInstance(const char* path)
        {
            static FArgumentLibLoggerSingleton s(path);
            return s.h;
        }
      private:
        std::FILE* h;
        FArgumentLibLoggerSingleton(const char* path) : h(std::fopen(path,"w+")) {}
        ~FArgumentLibLoggerSingleton()
        {
            std::fflush(h);
            std::fclose(h);
        }
    };
#endif

#if defined(TEST) && !defined(LOG)
#define LOG(format, ...) \
do { \
    std::fprintf(FArgumentLibLoggerSingleton::getInstance(".\\fArgumentLibTestLog.txt"), "[%-35s: %-25s: line:%-4d] " format "\n", __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
} while(0);
#endif

/**
 * @namespace Arguments
 * @brief Main namespace of argument parser library
 */
namespace Arguments
{
    // Set of possible option prefixes
    static const char* opt_ionPrefixes = "-/";

    // Set of types of options
    enum class ArgTypes : char
    {
        Null = 0, //Type of last option in option list
        Flag,     //The flag option type
        Value     //Option with leading value type
    };

    struct Option
    {
        const char* shortCommand;
        const char* longCommand;
        ArgTypes type;
        int data;
    };

    /**
     * @brief Identifies null-terminated string 'arg' as an option
     * @param[in] arg Pointer to first char of examined null-terminated string
     * @return Pointer to first option char in 'arg' or nullptr if not an option
     */
    char* isOption(char* arg)
    {
        auto size = std::strspn(arg, opt_ionPrefixes);
        return (size == 0) ? nullptr : arg + size;
    }

    /**
     * @brief Attempts to find flag argument in argument list
     * @param[in] argc Argument list length
     * @param[in] argv Argument list
     * @param[in:out] opt Option to find
     * @param[in] start Position in argument list to start with
     */
    void findFlagArg(int argc, char* argv[], Option& opt, int start = 0)
    {
        opt.data = false;
        // Flag argument must be at maximum at the end
        if (start >= argc)
            return;
        char* opt_ = nullptr;
        for (auto index = start; index < argc; ++index)
        {
            opt_ = isOption(argv[index]);
            if (opt_)
            {
                if (std::strstr(opt_, opt.shortCommand) != NULL ||
                    !std::strcmp(opt_, opt.longCommand))
                {
                    opt.data = true;
                    return;
                }
            }
        }
    }

    /**
     * @brief Attempts to find value argument in argument list
     * @param[in] argc Argument list length
     * @param[in] argv Argument list
     * @param[in:out] opt Option to find
     * @param[in] start Position in argument list to start with
     */
    void findValueArg(int argc, char* argv[], Option& opt, int start = 0)
    {
        opt.data = -1;
        // Value argument must have one following argument at minimum
        if (start >= argc - 1)
            return;
        char* opt_ = nullptr;
        for (auto index = start; index < argc - 1; ++index)
        {
            opt_ = isOption(argv[index]);
            if (opt_)
            {
                if (!std::strcmp(opt_, opt.shortCommand) ||
                    !std::strcmp(opt_, opt.longCommand))
                {
                    opt.data = index + 1;
                    return;
                }
            }
        }
    }

    /**
     * @brief Main argument parsing function.
     * @param[in] argc Argument list length
     * @param[in] argv Argument list
     * @param[in:out] optv Option list
     */
    void parseArgs(int argc, char* argv[], Option optv[])
    {
        int index = 0;
        while (optv[index].type != ArgTypes::Null)
        {
            switch (optv[index].type)
            {
                case ArgTypes::Flag:
                    findFlagArg(argc, argv, optv[index]);
                    break;
                case ArgTypes::Value:
                    findValueArg(argc, argv, optv[index]);
                    break;
                default:
                    return;
            }
            ++index;
        }
    }
}
#endif /* ARGUMENT_LIB_HPP_ */<|endoftext|>