<commit_before>#include "StdTuvokDefines.h"
#include <algorithm>
#include <cstdarg>
#include <fstream>
#include <functional>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#include "ShaderDescriptor.h"
#include "Basics/SysTools.h"
#include "Basics/SystemInfo.h"
#include "Controller/Controller.h"

namespace tuvok {

enum shader_type { SHADER_VERTEX_DISK, SHADER_VERTEX_STRING,
                   SHADER_FRAGMENT_DISK, SHADER_FRAGMENT_STRING };

struct ShaderDescriptor::sinfo {
  std::vector<std::pair<std::string, enum shader_type> > vertex;
  std::vector<std::pair<std::string, enum shader_type> > fragment;
  bool operator==(const ShaderDescriptor::sinfo& sdi) const;
};
bool ShaderDescriptor::sinfo::operator==(const ShaderDescriptor::sinfo& sdi)
const {
  return vertex.size() == sdi.vertex.size() &&
         fragment.size() == sdi.fragment.size() &&
         std::equal(vertex.begin(), vertex.end(), sdi.vertex.begin()) &&
         std::equal(fragment.begin(), fragment.end(), sdi.fragment.begin());
}

ShaderDescriptor::ShaderDescriptor() : si(new struct sinfo()) { }
ShaderDescriptor::ShaderDescriptor(const ShaderDescriptor& sd) : si(sd.si) {}
ShaderDescriptor::ShaderDescriptor(const std::vector<std::string>& vertex,
                                   const std::vector<std::string>& fragment) :
  si(new struct sinfo())
{
  typedef std::vector<std::string> sv;
  for(sv::const_iterator v = vertex.begin(); v != vertex.end(); ++v) {
    this->si->vertex.push_back(std::make_pair(*v, SHADER_VERTEX_DISK));
  }
  for(sv::const_iterator f = fragment.begin(); f != fragment.end(); ++f) {
    this->si->fragment.push_back(std::make_pair(*f, SHADER_FRAGMENT_DISK));
  }
}

// SysTools::FileExists can take a std::string OR a std::wstring.  This makes
// it hard to use in a function composition, because the compiler cannot figure
// out which one we want, and it's not a template or anything so we cannot just
// be explicit.
// This serves to rename it to avoid the ambiguity.
static bool exists(std::string s) { return SysTools::FileExists(s); }
// we could technically achieve this by composing std::plus with
// std::plus, but my god is that a nightmare in c++03.
static std::string concat(std::string a, std::string b, std::string c) {
  return a + b + c;
}

// Searches for the given filename in the given directories.  Returns the fully
// qualified path of the file's location.
static std::string find_filename(std::vector<std::string> directories,
                                 std::string filename)
{
  // if we're on Mac, first try to see if the file is in our bundle.
#ifdef DETECTED_OS_APPLE
  if (SysTools::FileExists(SysTools::GetFromResourceOnMac(filename))) {
    filename = SysTools::GetFromResourceOnMac(filename);
    MESSAGE("Found %s in bundle, using that.", filename.c_str());
    return filename;
  }
#endif

  typedef std::vector<std::string> sv;
  // check for garbage directories and warn the user about them
  sv::iterator end = std::remove_if(directories.begin(), directories.end(),
                                    std::not1(std::ptr_fun(exists)));
  for(sv::const_iterator e = end; e != directories.end(); ++e) {
    if (!e->empty())
      WARNING("Directory %s does not exist!", e->c_str());
  }
  // also, we know they're junk, so don't search in them
  directories.erase(end, directories.end());

  // okay, now prepend each directory into our flename and see if we find a
  // match.
  using namespace std::placeholders;
  const std::string dirsep = "/";
  // the functor is a composition: 'exists(add(_1, dirsep, filename))'
  sv::const_iterator fn =
    std::find_if(directories.begin(), directories.end(),
                 std::bind(
                   std::ptr_fun(exists),
                   std::bind(concat, _1, dirsep, filename)
                 ));

  if(fn == directories.end()) { // file not found.
    throw std::runtime_error("could not find file");
  }
  return *fn + dirsep + filename;
}

ShaderDescriptor ShaderDescriptor::Create(
  std::vector<std::string> directories,
  std::vector<std::pair<uint32_t, std::string> > fragmentDataBindings,
  ...
) {
  ShaderDescriptor rv;
  va_list args;
  va_start(args, directories);

  const char* filename;
  // we expect two NULLs: first terminates vertex list, second fragment list.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->vertex.push_back(std::make_pair(std::string(filename),
                              SHADER_VERTEX_DISK));
    }
  } while(filename != NULL);

  // now second: fragment shaders.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->fragment.push_back(std::make_pair(std::string(filename),
                                SHADER_FRAGMENT_DISK));
    }
  } while(filename != NULL);
  va_end(args);

  // now try to clean up all those paths.
  // The user gave us some directories to search, but let's make sure we also
  // search the location of our binary.
  std::vector<std::string> dirs = SysTools::GetSubDirList(
    Controller::Instance().SysInfo()->GetProgramPath()
  );
  directories.insert(directories.end(), dirs.begin(), dirs.end());
  directories.push_back(Controller::Instance().SysInfo()->GetProgramPath());

  typedef std::vector<std::pair<std::string, enum shader_type> > sv;
  for(sv::iterator v = rv.si->vertex.begin(); v != rv.si->vertex.end(); ++v) {
    v->first = find_filename(directories, v->first);
  }
  for(sv::iterator f = rv.si->fragment.begin(); f != rv.si->fragment.end();
      ++f) {
    f->first = find_filename(directories, f->first);
  }

  rv.fragmentDataBindings = fragmentDataBindings;

  return rv;
}
ShaderDescriptor ShaderDescriptor::Create(
  std::vector<std::string> directories, ...
) {
  ShaderDescriptor rv;
  va_list args;
  va_start(args, directories);

  const char* filename;
  // we expect two NULLs: first terminates vertex list, second fragment list.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->vertex.push_back(std::make_pair(std::string(filename),
                              SHADER_VERTEX_DISK));
    }
  } while(filename != NULL);

  // now second: fragment shaders.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->fragment.push_back(std::make_pair(std::string(filename),
                                SHADER_FRAGMENT_DISK));
    }
  } while(filename != NULL);
  va_end(args);

  // now try to clean up all those paths.
  // The user gave us some directories to search, but let's make sure we also
  // search the location of our binary.
  std::vector<std::string> dirs = SysTools::GetSubDirList(
    Controller::Instance().SysInfo()->GetProgramPath()
  );
  directories.insert(directories.end(), dirs.begin(), dirs.end());
  directories.push_back(Controller::Instance().SysInfo()->GetProgramPath());

  typedef std::vector<std::pair<std::string, enum shader_type> > sv;
  for(sv::iterator v = rv.si->vertex.begin(); v != rv.si->vertex.end(); ++v) {
    v->first = find_filename(directories, v->first);
  }
  for(sv::iterator f = rv.si->fragment.begin(); f != rv.si->fragment.end();
      ++f) {
    f->first = find_filename(directories, f->first);
  }

  return rv;
}

/// Adds a vertex shader in a string (i.e. not from a filename)
void ShaderDescriptor::AddVertexShaderString(const std::string shader) {
  this->si->vertex.push_back(std::make_pair(shader, SHADER_VERTEX_STRING));
}

/// Adds a fragment shader in a string (i.e. not from a filename)
void ShaderDescriptor::AddFragmentShaderString(const std::string shader) {
  this->si->fragment.push_back(std::make_pair(shader, SHADER_FRAGMENT_STRING));
}

/// Two shaders are equal if they utilize the same set of filenames/strings
/// to compose the shader.
bool ShaderDescriptor::operator ==(const ShaderDescriptor& sd) const
{
  return this->si == sd.si;
}

static std::string readfile(const std::string& filename) {
  // open in append mode so the file pointer will be at EOF and we can
  // therefore easily/quickly figure out the file size.
  std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::ate);
  if(!ifs.is_open()) {
    T_ERROR("Could not open shader '%s'", filename.c_str());
    throw std::runtime_error("file could not be opened");
  }
  std::ifstream::pos_type len = ifs.tellg();
  ifs.seekg(0, std::ios::beg);

  std::vector<char> file(size_t(len+std::ifstream::pos_type(1)), 0);
  size_t offset=0;
  do {
    std::streamsize length = std::streamsize(len) - std::streamsize(offset);
    ifs.read(&file[offset], length);
    offset += size_t(ifs.gcount());
  } while(!ifs.eof() && std::ifstream::pos_type(offset) < len);
  ifs.close();

  return std::string(&file[0]);
}

typedef std::vector<std::pair<std::string, enum shader_type> > slist;
// internal implementation: we keep track of which object (ShaderDescriptor) we
// came from, the location within that object, and what type we are.  The
// latter helps us with equality; no location in the vertex shader list is
// equal to any location in the fragment shader list.
struct ShaderDescriptor::SIterator::siterinfo {
  const ShaderDescriptor* sd;
  slist::const_iterator location;
  enum VertFrag { ITER_VERTEX, ITER_FRAGMENT } vf;

  siterinfo(const ShaderDescriptor* sdesc, slist::const_iterator loc,
            enum VertFrag typ) : sd(sdesc), location(loc), vf(typ) { }
  bool operator==(const siterinfo& sit) const {
    return this->vf == sit.vf &&
           this->location == sit.location;
  }
};

ShaderDescriptor::SIterator::SIterator(const ShaderDescriptor::SIterator& sit) :
  si(sit.si) { }
ShaderDescriptor::SIterator::SIterator(
  struct ShaderDescriptor::SIterator::siterinfo sit
) : si(new ShaderDescriptor::SIterator::siterinfo(sit)) { }
ShaderDescriptor::SIterator& ShaderDescriptor::SIterator::operator++() {
  ++this->si->location;
  return *this;
}
ShaderDescriptor::SIterator& ShaderDescriptor::SIterator::operator++(int n) {
  std::advance(this->si->location, n);
  return *this;
}
bool
ShaderDescriptor::SIterator::operator==(const ShaderDescriptor::SIterator& sit)
const {
  return *(this->si) == (*sit.si);
}
bool
ShaderDescriptor::SIterator::operator!=(const ShaderDescriptor::SIterator& sit)
const {
  return !(*this == sit);
}
std::pair<std::string, std::string>
ShaderDescriptor::SIterator::operator*() const {
  std::pair<std::string, std::string> rv(
    std::make_pair(this->si->location->first, "(in-memory)")
  );
  if(this->si->location->second == SHADER_VERTEX_DISK ||
     this->si->location->second == SHADER_FRAGMENT_DISK) {
    // load it from disk and replace those parameters.
    rv.first = readfile(this->si->location->first);
    rv.second = this->si->location->first;
  }
  return rv;
}

ShaderDescriptor::SIterator ShaderDescriptor::begin_vertex() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->vertex.begin(),
      ShaderDescriptor::SIterator::siterinfo::ITER_VERTEX
    )
  );
}
ShaderDescriptor::SIterator ShaderDescriptor::end_vertex() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->vertex.end(),
      ShaderDescriptor::SIterator::siterinfo::ITER_VERTEX
    )
  );
}

ShaderDescriptor::SIterator ShaderDescriptor::begin_fragment() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->fragment.begin(),
      ShaderDescriptor::SIterator::siterinfo::ITER_FRAGMENT
    )
  );
}
ShaderDescriptor::SIterator ShaderDescriptor::end_fragment() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->fragment.end(),
      ShaderDescriptor::SIterator::siterinfo::ITER_FRAGMENT
    )
  );
}

} // namespace tuvok

/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Interactive Visualization and Data Analysis Group.

   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.
*/
<commit_msg><commit_after>#include "StdTuvokDefines.h"
#include <algorithm>
#include <cstdarg>
#include <fstream>
#include <functional>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#include "ShaderDescriptor.h"
#include "Basics/SysTools.h"
#include "Basics/SystemInfo.h"
#include "Controller/Controller.h"

namespace tuvok {

enum shader_type { SHADER_VERTEX_DISK, SHADER_VERTEX_STRING,
                   SHADER_FRAGMENT_DISK, SHADER_FRAGMENT_STRING };

struct ShaderDescriptor::sinfo {
  std::vector<std::pair<std::string, enum shader_type> > vertex;
  std::vector<std::pair<std::string, enum shader_type> > fragment;
  bool operator==(const ShaderDescriptor::sinfo& sdi) const;
};
bool ShaderDescriptor::sinfo::operator==(const ShaderDescriptor::sinfo& sdi)
const {
  return vertex.size() == sdi.vertex.size() &&
         fragment.size() == sdi.fragment.size() &&
         std::equal(vertex.begin(), vertex.end(), sdi.vertex.begin()) &&
         std::equal(fragment.begin(), fragment.end(), sdi.fragment.begin());
}

ShaderDescriptor::ShaderDescriptor() : si(new struct sinfo()) { }
ShaderDescriptor::ShaderDescriptor(const ShaderDescriptor& sd) : si(sd.si) {}
ShaderDescriptor::ShaderDescriptor(const std::vector<std::string>& vertex,
                                   const std::vector<std::string>& fragment) :
  si(new struct sinfo())
{
  typedef std::vector<std::string> sv;
  for(sv::const_iterator v = vertex.begin(); v != vertex.end(); ++v) {
    this->si->vertex.push_back(std::make_pair(*v, SHADER_VERTEX_DISK));
  }
  for(sv::const_iterator f = fragment.begin(); f != fragment.end(); ++f) {
    this->si->fragment.push_back(std::make_pair(*f, SHADER_FRAGMENT_DISK));
  }
}

// SysTools::FileExists can take a std::string OR a std::wstring.  This makes
// it hard to use in a function composition, because the compiler cannot figure
// out which one we want, and it's not a template or anything so we cannot just
// be explicit.
// This serves to rename it to avoid the ambiguity.
static bool exists(std::string s) { return SysTools::FileExists(s); }
// we could technically achieve this by composing std::plus with
// std::plus, but my god is that a nightmare in c++03.
static std::string concat(std::string a, std::string b, std::string c) {
  return a + b + c;
}

// Searches for the given filename in the given directories.  Returns the fully
// qualified path of the file's location.
static std::string find_filename(std::vector<std::string> directories,
                                 std::string filename)
{
  // if we're on Mac, first try to see if the file is in our bundle.
#ifdef DETECTED_OS_APPLE
  if (SysTools::FileExists(SysTools::GetFromResourceOnMac(filename))) {
    filename = SysTools::GetFromResourceOnMac(filename);
    MESSAGE("Found %s in bundle, using that.", filename.c_str());
    return filename;
  }
#endif

  typedef std::vector<std::string> sv;
  // check for garbage directories and warn the user about them
  sv::iterator end = std::remove_if(directories.begin(), directories.end(),
                                    std::not1(std::ptr_fun(exists)));
  for(sv::const_iterator e = end; e != directories.end(); ++e) {
    if (!e->empty())
      WARNING("Directory %s does not exist!", e->c_str());
  }
  // also, we know they're junk, so don't search in them
  directories.erase(end, directories.end());

  // okay, now prepend each directory into our flename and see if we find a
  // match.
  using namespace std::placeholders;
  const std::string dirsep = "/";
  // the functor is a composition: 'exists(add(_1, dirsep, filename))'
  sv::const_iterator fn =
    std::find_if(directories.begin(), directories.end(),
                 std::bind(
                   std::ptr_fun(exists),
                   std::bind(concat, _1, dirsep, filename)
                 ));

  if(fn == directories.end()) { // file not found.
    throw std::runtime_error("could not find file");
  }
  return *fn + dirsep + filename;
}

ShaderDescriptor ShaderDescriptor::Create(
  std::vector<std::string> directories,
  std::vector<std::pair<uint32_t, std::string> > fragmentDataBindings,
  ...
) {
  ShaderDescriptor rv;
  va_list args;
  va_start(args, fragmentDataBindings);

  const char* filename;
  // we expect two NULLs: first terminates vertex list, second fragment list.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->vertex.push_back(std::make_pair(std::string(filename),
                              SHADER_VERTEX_DISK));
    }
  } while(filename != NULL);

  // now second: fragment shaders.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->fragment.push_back(std::make_pair(std::string(filename),
                                SHADER_FRAGMENT_DISK));
    }
  } while(filename != NULL);
  va_end(args);

  // now try to clean up all those paths.
  // The user gave us some directories to search, but let's make sure we also
  // search the location of our binary.
  std::vector<std::string> dirs = SysTools::GetSubDirList(
    Controller::Instance().SysInfo()->GetProgramPath()
  );
  directories.insert(directories.end(), dirs.begin(), dirs.end());
  directories.push_back(Controller::Instance().SysInfo()->GetProgramPath());

  typedef std::vector<std::pair<std::string, enum shader_type> > sv;
  for(sv::iterator v = rv.si->vertex.begin(); v != rv.si->vertex.end(); ++v) {
    v->first = find_filename(directories, v->first);
  }
  for(sv::iterator f = rv.si->fragment.begin(); f != rv.si->fragment.end();
      ++f) {
    f->first = find_filename(directories, f->first);
  }

  rv.fragmentDataBindings = fragmentDataBindings;

  return rv;
}
ShaderDescriptor ShaderDescriptor::Create(
  std::vector<std::string> directories, ...
) {
  ShaderDescriptor rv;
  va_list args;
  va_start(args, directories);

  const char* filename;
  // we expect two NULLs: first terminates vertex list, second fragment list.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->vertex.push_back(std::make_pair(std::string(filename),
                              SHADER_VERTEX_DISK));
    }
  } while(filename != NULL);

  // now second: fragment shaders.
  do {
    filename = va_arg(args, const char*);
    if(filename != NULL) {
      rv.si->fragment.push_back(std::make_pair(std::string(filename),
                                SHADER_FRAGMENT_DISK));
    }
  } while(filename != NULL);
  va_end(args);

  // now try to clean up all those paths.
  // The user gave us some directories to search, but let's make sure we also
  // search the location of our binary.
  std::vector<std::string> dirs = SysTools::GetSubDirList(
    Controller::Instance().SysInfo()->GetProgramPath()
  );
  directories.insert(directories.end(), dirs.begin(), dirs.end());
  directories.push_back(Controller::Instance().SysInfo()->GetProgramPath());

  typedef std::vector<std::pair<std::string, enum shader_type> > sv;
  for(sv::iterator v = rv.si->vertex.begin(); v != rv.si->vertex.end(); ++v) {
    v->first = find_filename(directories, v->first);
  }
  for(sv::iterator f = rv.si->fragment.begin(); f != rv.si->fragment.end();
      ++f) {
    f->first = find_filename(directories, f->first);
  }

  return rv;
}

/// Adds a vertex shader in a string (i.e. not from a filename)
void ShaderDescriptor::AddVertexShaderString(const std::string shader) {
  this->si->vertex.push_back(std::make_pair(shader, SHADER_VERTEX_STRING));
}

/// Adds a fragment shader in a string (i.e. not from a filename)
void ShaderDescriptor::AddFragmentShaderString(const std::string shader) {
  this->si->fragment.push_back(std::make_pair(shader, SHADER_FRAGMENT_STRING));
}

/// Two shaders are equal if they utilize the same set of filenames/strings
/// to compose the shader.
bool ShaderDescriptor::operator ==(const ShaderDescriptor& sd) const
{
  return this->si == sd.si;
}

static std::string readfile(const std::string& filename) {
  // open in append mode so the file pointer will be at EOF and we can
  // therefore easily/quickly figure out the file size.
  std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::ate);
  if(!ifs.is_open()) {
    T_ERROR("Could not open shader '%s'", filename.c_str());
    throw std::runtime_error("file could not be opened");
  }
  std::ifstream::pos_type len = ifs.tellg();
  ifs.seekg(0, std::ios::beg);

  std::vector<char> file(size_t(len+std::ifstream::pos_type(1)), 0);
  size_t offset=0;
  do {
    std::streamsize length = std::streamsize(len) - std::streamsize(offset);
    ifs.read(&file[offset], length);
    offset += size_t(ifs.gcount());
  } while(!ifs.eof() && std::ifstream::pos_type(offset) < len);
  ifs.close();

  return std::string(&file[0]);
}

typedef std::vector<std::pair<std::string, enum shader_type> > slist;
// internal implementation: we keep track of which object (ShaderDescriptor) we
// came from, the location within that object, and what type we are.  The
// latter helps us with equality; no location in the vertex shader list is
// equal to any location in the fragment shader list.
struct ShaderDescriptor::SIterator::siterinfo {
  const ShaderDescriptor* sd;
  slist::const_iterator location;
  enum VertFrag { ITER_VERTEX, ITER_FRAGMENT } vf;

  siterinfo(const ShaderDescriptor* sdesc, slist::const_iterator loc,
            enum VertFrag typ) : sd(sdesc), location(loc), vf(typ) { }
  bool operator==(const siterinfo& sit) const {
    return this->vf == sit.vf &&
           this->location == sit.location;
  }
};

ShaderDescriptor::SIterator::SIterator(const ShaderDescriptor::SIterator& sit) :
  si(sit.si) { }
ShaderDescriptor::SIterator::SIterator(
  struct ShaderDescriptor::SIterator::siterinfo sit
) : si(new ShaderDescriptor::SIterator::siterinfo(sit)) { }
ShaderDescriptor::SIterator& ShaderDescriptor::SIterator::operator++() {
  ++this->si->location;
  return *this;
}
ShaderDescriptor::SIterator& ShaderDescriptor::SIterator::operator++(int n) {
  std::advance(this->si->location, n);
  return *this;
}
bool
ShaderDescriptor::SIterator::operator==(const ShaderDescriptor::SIterator& sit)
const {
  return *(this->si) == (*sit.si);
}
bool
ShaderDescriptor::SIterator::operator!=(const ShaderDescriptor::SIterator& sit)
const {
  return !(*this == sit);
}
std::pair<std::string, std::string>
ShaderDescriptor::SIterator::operator*() const {
  std::pair<std::string, std::string> rv(
    std::make_pair(this->si->location->first, "(in-memory)")
  );
  if(this->si->location->second == SHADER_VERTEX_DISK ||
     this->si->location->second == SHADER_FRAGMENT_DISK) {
    // load it from disk and replace those parameters.
    rv.first = readfile(this->si->location->first);
    rv.second = this->si->location->first;
  }
  return rv;
}

ShaderDescriptor::SIterator ShaderDescriptor::begin_vertex() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->vertex.begin(),
      ShaderDescriptor::SIterator::siterinfo::ITER_VERTEX
    )
  );
}
ShaderDescriptor::SIterator ShaderDescriptor::end_vertex() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->vertex.end(),
      ShaderDescriptor::SIterator::siterinfo::ITER_VERTEX
    )
  );
}

ShaderDescriptor::SIterator ShaderDescriptor::begin_fragment() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->fragment.begin(),
      ShaderDescriptor::SIterator::siterinfo::ITER_FRAGMENT
    )
  );
}
ShaderDescriptor::SIterator ShaderDescriptor::end_fragment() const {
  return ShaderDescriptor::SIterator(
    ShaderDescriptor::SIterator::siterinfo(
      this, this->si->fragment.end(),
      ShaderDescriptor::SIterator::siterinfo::ITER_FRAGMENT
    )
  );
}

} // namespace tuvok

/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Interactive Visualization and Data Analysis Group.

   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.
*/
<|endoftext|>


<commit_before><commit_msg>Stopped messing with response<commit_after><|endoftext|>


<commit_before>#include "xchainer/memory.h"

#include <cassert>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/error.h"

namespace xchainer {
namespace internal {

bool IsPointerCudaMemory(const void* ptr) {
#ifdef XCHAINER_ENABLE_CUDA
    cudaPointerAttributes attr = {};
    cudaError_t status = cudaPointerGetAttributes(&attr, ptr);
    switch (status) {
        case cudaSuccess:
            if (attr.isManaged) {
                return true;
            } else {
                throw XchainerError("Non-managed GPU memory is not supported");
            }
        case cudaErrorInvalidValue:
            return false;
        default:
            cuda::CheckError(status);
            break;
    }
    assert(false);  // should never be reached
#else
    return false;
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> Allocate(const Device& device, size_t bytesize) {
    if (device == MakeDevice("cpu")) {
        return std::make_unique<uint8_t[]>(bytesize);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        void* raw_ptr = nullptr;
        // Be careful to be exception-safe, i.e., do not throw before creating shared_ptr
        cudaError_t status = cudaMallocManaged(&raw_ptr, bytesize, cudaMemAttachGlobal);
        if (status == cudaSuccess) {
            return std::shared_ptr<void>{raw_ptr, cudaFree};
        } else {
            cuda::CheckError(status);
        }
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void MemoryCopy(void* dst_ptr, const void* src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    bool is_dst_cuda_memory = IsPointerCudaMemory(dst_ptr);
    bool is_src_cuda_memory = IsPointerCudaMemory(src_ptr);
    if (is_dst_cuda_memory) {
        if (is_src_cuda_memory) {
            // Copy from device to device is faster even in unified memory
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToDevice));
        } else {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyHostToDevice));
        }
    } else {
        if (is_src_cuda_memory) {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToHost));
        } else {
            std::memcpy(dst_ptr, src_ptr, bytesize);
        }
    }
#else
    std::memcpy(dst_ptr, src_ptr, bytesize);
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> MemoryFromBuffer(const Device& device, const std::shared_ptr<void>& src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    if (device == MakeDevice("cpu")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyDeviceToHost));
            return dst_ptr;
        } else {
            return src_ptr;
        }
    } else if (device == MakeDevice("cuda")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            return src_ptr;
        } else {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyHostToDevice));
            return dst_ptr;
        }
    } else {
        throw DeviceError("invalid device");
    }
#else
    return src_ptr;
#endif  // XCHAINER_ENABLE_CUDA
}

}  // namespace internal
}  // namespace xchainer
<commit_msg>Avoid warning: control reaches end of non-void function [-Wreturn-type]<commit_after>#include "xchainer/memory.h"

#include <cassert>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/error.h"

namespace xchainer {
namespace internal {

bool IsPointerCudaMemory(const void* ptr) {
#ifdef XCHAINER_ENABLE_CUDA
    cudaPointerAttributes attr = {};
    cudaError_t status = cudaPointerGetAttributes(&attr, ptr);
    switch (status) {
        case cudaSuccess:
            if (attr.isManaged) {
                return true;
            } else {
                throw XchainerError("Non-managed GPU memory is not supported");
            }
        case cudaErrorInvalidValue:
            return false;
        default:
            cuda::CheckError(status);
            break;
    }
    assert(false);  // should never be reached
#else
    return false;
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> Allocate(const Device& device, size_t bytesize) {
    if (device == MakeDevice("cpu")) {
        return std::make_unique<uint8_t[]>(bytesize);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        void* raw_ptr = nullptr;
        // Be careful to be exception-safe, i.e., do not throw before creating shared_ptr
        cudaError_t status = cudaMallocManaged(&raw_ptr, bytesize, cudaMemAttachGlobal);
        if (status == cudaSuccess) {
            return std::shared_ptr<void>{raw_ptr, cudaFree};
        } else {
            cuda::CheckError(status);
        }
        assert(false);  // should never be reached
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void MemoryCopy(void* dst_ptr, const void* src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    bool is_dst_cuda_memory = IsPointerCudaMemory(dst_ptr);
    bool is_src_cuda_memory = IsPointerCudaMemory(src_ptr);
    if (is_dst_cuda_memory) {
        if (is_src_cuda_memory) {
            // Copy from device to device is faster even in unified memory
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToDevice));
        } else {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyHostToDevice));
        }
    } else {
        if (is_src_cuda_memory) {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToHost));
        } else {
            std::memcpy(dst_ptr, src_ptr, bytesize);
        }
    }
#else
    std::memcpy(dst_ptr, src_ptr, bytesize);
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> MemoryFromBuffer(const Device& device, const std::shared_ptr<void>& src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    if (device == MakeDevice("cpu")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyDeviceToHost));
            return dst_ptr;
        } else {
            return src_ptr;
        }
    } else if (device == MakeDevice("cuda")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            return src_ptr;
        } else {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyHostToDevice));
            return dst_ptr;
        }
    } else {
        throw DeviceError("invalid device");
    }
#else
    return src_ptr;
#endif  // XCHAINER_ENABLE_CUDA
}

}  // namespace internal
}  // namespace xchainer
<|endoftext|>


<commit_before>#include "Optimiser.h"

using namespace Moses;
using namespace std;

namespace Mira {
	void MiraOptimiser::updateWeights(Moses::ScoreComponentCollection& weights,
                         	const std::vector< std::vector<Moses::ScoreComponentCollection> >& scores,
                         	const std::vector< std::vector<float> >& losses,
                         	const Moses::ScoreComponentCollection& oracleScores) {

	for(unsigned batch = 0; batch < scores.size(); batch++) {
	  for(unsigned analyseSentence = 0; analyseSentence < scores[batch].size(); analyseSentence++) {

            float scoreChange = 0.0;
            float norm = 0.0;

            for(unsigned score = 0; score < scores[batch][analyseSentence].size(); score++) {
              float currentScoreChange = oracleScores[score] - scores[batch][analyseSentence][score];
              scoreChange += currentScoreChange * weights[score];
              norm += currentScoreChange * currentScoreChange;
            }

            float delta;
            if(norm == 0.0) //just in case... :-)
              delta = 0.0;
            else {
              delta = (losses[batch][analyseSentence] - scoreChange) / norm;
              cout << "scoreChange: " << scoreChange
                   << "\ndelta: " << delta
                   << "\nloss: " << losses[batch][analyseSentence] << endl;
            }
            //now get in shape
            if(delta > upperBound_)
              delta = upperBound_;
            else if(delta < lowerBound_)
              delta = lowerBound_;

						// do this:	weights += delta * (oracleScores - scores[batch][analyseSentence]);
						Moses::ScoreComponentCollection tempColl = oracleScores;
						tempColl.MinusEquals(scores[batch][analyseSentence]);
						tempColl.MultiplyEquals(delta);
						weights.MinusEquals(tempColl);

					//StaticData::GetInstanceNonConst().SetWeightsScoreComponentCollection(weights);
            //calculate max. for criterion
            /*
 	    float sumWeightedFeatures = 0.0;
            for(unsigned score = 0; score < scores[analyseSentence]->size(); score++) {
              sumWeightedFeatures += oracleScores[score]*newWeights[score];
            }

	    if((losses[analyseSentence] - sumWeightedFeatures) > maxTranslation_) {
              maxTranslation_ = losses[analyseSentence] - sumWeightedFeatures;
	    }
	    */
          }
	}
  }
}

<commit_msg>now i am using scoreComponentCollection :)<commit_after>#include "Optimiser.h"

using namespace Moses;
using namespace std;

namespace Mira {
	void MiraOptimiser::updateWeights(Moses::ScoreComponentCollection& weights,
                         	const std::vector< std::vector<Moses::ScoreComponentCollection> >& scores,
                         	const std::vector< std::vector<float> >& losses,
                         	const Moses::ScoreComponentCollection& oracleScores) {

	for(unsigned batch = 0; batch < scores.size(); batch++) {
	  for(unsigned analyseSentence = 0; analyseSentence < scores[batch].size(); analyseSentence++) {

            /* do this:
            for(unsigned score = 0; score < scores[batch][analyseSentence].size(); score++) {
              float currentScoreChange = oracleScores[score] - scores[batch][analyseSentence][score];
              scoreChange += currentScoreChange * weights[score];
              norm += currentScoreChange * currentScoreChange;
            }
            */
            Moses::ScoreComponentCollection currentScoreColl = oracleScores;
            currentScoreColl.MinusEquals(scores[batch][analyseSentence]);
	    currentScoreColl.MultiplyEquals(weights);
	    float scoreChange = currentScoreChange.InnerProduct(weights);
	    float norm = currentScoreChange.InnerProduct(currentScoreChange);

            float delta;
            if(norm == 0.0) //just in case... :-)
              delta = 0.0;
            else {
              delta = (losses[batch][analyseSentence] - scoreChange) / norm;
              cout << "scoreChange: " << scoreChange
                   << "\ndelta: " << delta
                   << "\nloss: " << losses[batch][analyseSentence] << endl;
            }
            //now get in shape
            if(delta > upperBound_)
              delta = upperBound_;
            else if(delta < lowerBound_)
              delta = lowerBound_;

	    // do this:	weights += delta * (oracleScores - scores[batch][analyseSentence])
            Moses::ScoreComponentCollection tempColl = oracleScores;
            tempColl.MinusEquals(scores[batch][analyseSentence]);
	    tempColl.MultiplyEquals(delta);
	    weights.MinusEquals(tempColl);

            //calculate max. for criterion
            /*
 	    float sumWeightedFeatures = 0.0;
            for(unsigned score = 0; score < scores[analyseSentence]->size(); score++) {
              sumWeightedFeatures += oracleScores[score]*newWeights[score];
            }

	    if((losses[analyseSentence] - sumWeightedFeatures) > maxTranslation_) {
              maxTranslation_ = losses[analyseSentence] - sumWeightedFeatures;
	    }
	    */
          }
	}
  }
}

<|endoftext|>


<commit_before>/** \brief Implementation of writer classes for MARC files.
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "MarcRecord.h"
#include "Compiler.h"
#include "FileUtil.h"
#include "MarcWriter.h"
#include "StringUtil.h"
#include "util.h"

#define DEBUG 1

static const size_t MAX_MARC_21_RECORD_LENGTH(99999);
static char write_buffer[MAX_MARC_21_RECORD_LENGTH]; // Possibly too big for the stack!

// Returns true if we can add the new field to our record w/o overflowing the maximum size of a binary
// MARC-21 record, o/w we return false.
static bool inline NewFieldDoesFit(const size_t base_address, const size_t current_record_length,
                                   const size_t next_field_length)
{
    return base_address + DirectoryEntry::DIRECTORY_ENTRY_LENGTH + current_record_length + next_field_length
           + 1 /* for the field terminator byte */ <= MAX_MARC_21_RECORD_LENGTH;
}

/**
 * We determine the record dimensions by adding sizes of fields one-by-one (starting with the field represented by
 * "directory_iter") while we do not overflow the maximum
 * size of a binary MARC-21 record.
 */
static void inline DetermineRecordDimensions(const size_t control_number_field_length,
                                             std::vector<DirectoryEntry>::const_iterator directory_iter,
                                             const std::vector<DirectoryEntry>::const_iterator &end_iter,
                                             size_t * const number_of_directory_entries, size_t * const base_address,
                                             size_t * const record_length)
{
    *number_of_directory_entries = 0;
    *base_address = DirectoryEntry::DIRECTORY_ENTRY_LENGTH /* for the control number field */
                    + Leader::LEADER_LENGTH + 1 /* for directory separator byte */;
    *record_length = control_number_field_length + 1 /* for end of record byte */;

    // Now we add fields one-by-one while taking care not to overflow the maximum record size:
    for (/* empty */;
         directory_iter < end_iter
         and NewFieldDoesFit(*base_address, *record_length, directory_iter->getFieldLength());
         ++directory_iter)
    {
        *base_address += DirectoryEntry::DIRECTORY_ENTRY_LENGTH;
        *record_length += directory_iter->getFieldLength();
        ++*number_of_directory_entries;
    }

    *record_length += *base_address;
}

static void inline WriteToBuffer(char *&dest, const std::string &data) {
    #if DEBUG
    if (unlikely(dest + data.size() > write_buffer + sizeof(write_buffer)))
        logger->error("write past end of write_buffer! (1)");
    #endif
    std::memcpy(dest, data.data(), data.size());
    dest += data.size();
}

static void inline WriteToBuffer(char *&dest, const char * const source, const size_t length) {
    #if DEBUG
    if (unlikely(dest + length > write_buffer + sizeof(write_buffer)))
        logger->error("write past end of write_buffer! (2)");
    #endif
    std::memcpy(dest, source, length);
    dest += length;
}

static void inline WriteDirEntryToBuffer(char *&directory_pointer, const DirectoryEntry &dir_entry) {
    const MarcTag &tag(dir_entry.getTag());
    WriteToBuffer(directory_pointer, tag.c_str(), DirectoryEntry::TAG_LENGTH);
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldLength()), 4, '0'));
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldOffset()), 5, '0'));
}

void BinaryMarcWriter::write(const MarcRecord &record) {
    const std::string control_number(record.getControlNumber());
    const size_t control_number_field_length(control_number.size() + 1);

    auto dir_entry(record.directory_entries_.cbegin());
    if (unlikely(dir_entry == record.directory_entries_.cend()))
        logger->error("BinaryMarcWriter::write: can't write a record w/ an empty directory!");
    if (unlikely(dir_entry->getTag() != "001"))
        logger->error("BinaryMarcWriter::write: first directory entry has to be 001! Found: "
                      + dir_entry->getTag().to_string() + " (Control number: " + record.getControlNumber() + ")");
    ++dir_entry;

    while (dir_entry < record.directory_entries_.cend()) {
        size_t number_of_directory_entries, record_length, base_address_of_data;
        DetermineRecordDimensions(control_number_field_length, dir_entry, record.directory_entries_.cend(),
                                  &number_of_directory_entries, &base_address_of_data, &record_length);
        const std::vector<DirectoryEntry>::const_iterator end_iter(dir_entry + number_of_directory_entries);

        char *leader_pointer(write_buffer);
        record.leader_.setBaseAddressOfData(base_address_of_data);
        record.leader_.setRecordLength(record_length);

        // In the case of a multi-part records all but the last record need to have the multi-part flag set:
        record.leader_.setMultiPartRecord(end_iter != record.directory_entries_.cend());

        WriteToBuffer(leader_pointer, record.leader_.toString());

        // Write a control number directory entry for each record as the first entry in the directory section:
        char *directory_pointer(write_buffer + Leader::LEADER_LENGTH);
        WriteDirEntryToBuffer(directory_pointer, record.directory_entries_.front());

        char *field_data_pointer(write_buffer + base_address_of_data);

        // Write the control number field data:
        WriteToBuffer(field_data_pointer, record.field_data_.data(), control_number_field_length);

        // Now write the field data for all fields after the 001-field:
        for (; dir_entry < end_iter; ++dir_entry) {
            WriteDirEntryToBuffer(directory_pointer, *dir_entry);
            WriteToBuffer(field_data_pointer, record.field_data_.data() + dir_entry->getFieldOffset(),
                          dir_entry->getFieldLength());
        }

        WriteToBuffer(directory_pointer, "\x1E", 1);  // End of directory.
        WriteToBuffer(field_data_pointer, "\x1D", 1); // End of field data.

        output_->write(write_buffer, record_length);
    }
}

XmlMarcWriter::XmlMarcWriter(File * const output_file, const unsigned indent_amount,
                             const XmlWriter::TextConversionType text_conversion_type)
{
    xml_writer_ = new MarcXmlWriter(output_file, indent_amount, text_conversion_type);
}

void XmlMarcWriter::write(const MarcRecord &record) {
    xml_writer_->openTag("record");

    record.leader_.setRecordLength(0);
    record.leader_.setBaseAddressOfData(0);
    xml_writer_->writeTagsWithData("leader", record.leader_.toString(), /* suppress_newline = */ true);

    for (unsigned entry_no(0); entry_no < record.directory_entries_.size(); ++entry_no) {
        const DirectoryEntry &dir_entry(record.directory_entries_[entry_no]);
        if (dir_entry.isControlFieldEntry())
            xml_writer_->writeTagsWithData("controlfield",
                                           { std::make_pair("tag", dir_entry.getTag().to_string()) },
                                           record.getFieldData(entry_no),
                    /* suppress_newline = */ true);
        else { // We have a data field.
            const std::string data(record.getFieldData(entry_no));
            xml_writer_->openTag("datafield",
                                { std::make_pair("tag", dir_entry.getTag().to_string()),
                                  std::make_pair("ind1", std::string(1, data[0])),
                                  std::make_pair("ind2", std::string(1, data[1]))
                                });

            std::string::const_iterator ch(data.cbegin() + 2 /* Skip over the indicators. */);

            while (ch != data.cend()) {
                if (*ch != '\x1F')
                    std::runtime_error("in XmlMarcWriter::write: expected subfield code delimiter not found! Found "
                                       + std::string(1, *ch) + "! (Control number is " + record.getControlNumber()
                                       + ".)");

                ++ch;
                if (ch == data.cend())
                    std::runtime_error("in XmlMarcWriter::write: unexpected subfield data end while expecting a "
                                       "subfield code!");
                const std::string subfield_code(1, *ch++);

                std::string subfield_data;
                while (ch != data.cend() and *ch != '\x1F')
                    subfield_data += *ch++;
                if (subfield_data.empty())
                    continue;

                xml_writer_->writeTagsWithData("subfield", { std::make_pair("code", subfield_code) },
                                              subfield_data, /* suppress_newline = */ true);
            }

            xml_writer_->closeTag(); // Close "datafield".
        }
    }

    xml_writer_->closeTag(); // Close "record".
}

std::unique_ptr<MarcWriter> MarcWriter::Factory(const std::string &output_filename, WriterType writer_type,
                                                const WriterMode writer_mode)
{
    std::unique_ptr<File> output(writer_mode == WriterMode::OVERWRITE ? FileUtil::OpenOutputFileOrDie(output_filename)
                                                                      : FileUtil::OpenForAppendingOrDie(output_filename));
    if (writer_type == AUTO) {
        if (StringUtil::EndsWith(output_filename, ".mrc") or StringUtil::EndsWith(output_filename, ".marc"))
            writer_type = BINARY;
        else if (StringUtil::EndsWith(output_filename, ".xml"))
            writer_type = XML;
        else
            throw std::runtime_error("in MarcWriter::Factory: WriterType is AUTO but filename \""
                                     + output_filename + "\" does not end in \".mrc\" or \".xml\"!");
    }
    return (writer_type == XML) ? std::unique_ptr<MarcWriter>(new XmlMarcWriter(output.release()))
                                : std::unique_ptr<MarcWriter>(new BinaryMarcWriter(output.release()));
}
<commit_msg>Fixing naming conflict<commit_after>/** \brief Implementation of writer classes for MARC files.
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "MarcRecord.h"
#include "Compiler.h"
#include "FileUtil.h"
#include "MarcWriter.h"
#include "StringUtil.h"
#include "util.h"

#define MARC_WRITER_DEBUG 1

static const size_t MAX_MARC_21_RECORD_LENGTH(99999);
static char write_buffer[MAX_MARC_21_RECORD_LENGTH]; // Possibly too big for the stack!

// Returns true if we can add the new field to our record w/o overflowing the maximum size of a binary
// MARC-21 record, o/w we return false.
static bool inline NewFieldDoesFit(const size_t base_address, const size_t current_record_length,
                                   const size_t next_field_length)
{
    return base_address + DirectoryEntry::DIRECTORY_ENTRY_LENGTH + current_record_length + next_field_length
           + 1 /* for the field terminator byte */ <= MAX_MARC_21_RECORD_LENGTH;
}

/**
 * We determine the record dimensions by adding sizes of fields one-by-one (starting with the field represented by
 * "directory_iter") while we do not overflow the maximum
 * size of a binary MARC-21 record.
 */
static void inline DetermineRecordDimensions(const size_t control_number_field_length,
                                             std::vector<DirectoryEntry>::const_iterator directory_iter,
                                             const std::vector<DirectoryEntry>::const_iterator &end_iter,
                                             size_t * const number_of_directory_entries, size_t * const base_address,
                                             size_t * const record_length)
{
    *number_of_directory_entries = 0;
    *base_address = DirectoryEntry::DIRECTORY_ENTRY_LENGTH /* for the control number field */
                    + Leader::LEADER_LENGTH + 1 /* for directory separator byte */;
    *record_length = control_number_field_length + 1 /* for end of record byte */;

    // Now we add fields one-by-one while taking care not to overflow the maximum record size:
    for (/* empty */;
         directory_iter < end_iter
         and NewFieldDoesFit(*base_address, *record_length, directory_iter->getFieldLength());
         ++directory_iter)
    {
        *base_address += DirectoryEntry::DIRECTORY_ENTRY_LENGTH;
        *record_length += directory_iter->getFieldLength();
        ++*number_of_directory_entries;
    }

    *record_length += *base_address;
}

static void inline WriteToBuffer(char *&dest, const std::string &data) {
    #if MARC_WRITER_DEBUG
    if (unlikely(dest + data.size() > write_buffer + sizeof(write_buffer)))
        logger->error("write past end of write_buffer! (1)");
    #endif
    std::memcpy(dest, data.data(), data.size());
    dest += data.size();
}

static void inline WriteToBuffer(char *&dest, const char * const source, const size_t length) {
    #if MARC_WRITER_DEBUG
    if (unlikely(dest + length > write_buffer + sizeof(write_buffer)))
        logger->error("write past end of write_buffer! (2)");
    #endif
    std::memcpy(dest, source, length);
    dest += length;
}

static void inline WriteDirEntryToBuffer(char *&directory_pointer, const DirectoryEntry &dir_entry) {
    const MarcTag &tag(dir_entry.getTag());
    WriteToBuffer(directory_pointer, tag.c_str(), DirectoryEntry::TAG_LENGTH);
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldLength()), 4, '0'));
    WriteToBuffer(directory_pointer, StringUtil::PadLeading(std::to_string(dir_entry.getFieldOffset()), 5, '0'));
}

void BinaryMarcWriter::write(const MarcRecord &record) {
    const std::string control_number(record.getControlNumber());
    const size_t control_number_field_length(control_number.size() + 1);

    auto dir_entry(record.directory_entries_.cbegin());
    if (unlikely(dir_entry == record.directory_entries_.cend()))
        logger->error("BinaryMarcWriter::write: can't write a record w/ an empty directory!");
    if (unlikely(dir_entry->getTag() != "001"))
        logger->error("BinaryMarcWriter::write: first directory entry has to be 001! Found: "
                      + dir_entry->getTag().to_string() + " (Control number: " + record.getControlNumber() + ")");
    ++dir_entry;

    while (dir_entry < record.directory_entries_.cend()) {
        size_t number_of_directory_entries, record_length, base_address_of_data;
        DetermineRecordDimensions(control_number_field_length, dir_entry, record.directory_entries_.cend(),
                                  &number_of_directory_entries, &base_address_of_data, &record_length);
        const std::vector<DirectoryEntry>::const_iterator end_iter(dir_entry + number_of_directory_entries);

        char *leader_pointer(write_buffer);
        record.leader_.setBaseAddressOfData(base_address_of_data);
        record.leader_.setRecordLength(record_length);

        // In the case of a multi-part records all but the last record need to have the multi-part flag set:
        record.leader_.setMultiPartRecord(end_iter != record.directory_entries_.cend());

        WriteToBuffer(leader_pointer, record.leader_.toString());

        // Write a control number directory entry for each record as the first entry in the directory section:
        char *directory_pointer(write_buffer + Leader::LEADER_LENGTH);
        WriteDirEntryToBuffer(directory_pointer, record.directory_entries_.front());

        char *field_data_pointer(write_buffer + base_address_of_data);

        // Write the control number field data:
        WriteToBuffer(field_data_pointer, record.field_data_.data(), control_number_field_length);

        // Now write the field data for all fields after the 001-field:
        for (; dir_entry < end_iter; ++dir_entry) {
            WriteDirEntryToBuffer(directory_pointer, *dir_entry);
            WriteToBuffer(field_data_pointer, record.field_data_.data() + dir_entry->getFieldOffset(),
                          dir_entry->getFieldLength());
        }

        WriteToBuffer(directory_pointer, "\x1E", 1);  // End of directory.
        WriteToBuffer(field_data_pointer, "\x1D", 1); // End of field data.

        output_->write(write_buffer, record_length);
    }
}

XmlMarcWriter::XmlMarcWriter(File * const output_file, const unsigned indent_amount,
                             const XmlWriter::TextConversionType text_conversion_type)
{
    xml_writer_ = new MarcXmlWriter(output_file, indent_amount, text_conversion_type);
}

void XmlMarcWriter::write(const MarcRecord &record) {
    xml_writer_->openTag("record");

    record.leader_.setRecordLength(0);
    record.leader_.setBaseAddressOfData(0);
    xml_writer_->writeTagsWithData("leader", record.leader_.toString(), /* suppress_newline = */ true);

    for (unsigned entry_no(0); entry_no < record.directory_entries_.size(); ++entry_no) {
        const DirectoryEntry &dir_entry(record.directory_entries_[entry_no]);
        if (dir_entry.isControlFieldEntry())
            xml_writer_->writeTagsWithData("controlfield",
                                           { std::make_pair("tag", dir_entry.getTag().to_string()) },
                                           record.getFieldData(entry_no),
                    /* suppress_newline = */ true);
        else { // We have a data field.
            const std::string data(record.getFieldData(entry_no));
            xml_writer_->openTag("datafield",
                                { std::make_pair("tag", dir_entry.getTag().to_string()),
                                  std::make_pair("ind1", std::string(1, data[0])),
                                  std::make_pair("ind2", std::string(1, data[1]))
                                });

            std::string::const_iterator ch(data.cbegin() + 2 /* Skip over the indicators. */);

            while (ch != data.cend()) {
                if (*ch != '\x1F')
                    std::runtime_error("in XmlMarcWriter::write: expected subfield code delimiter not found! Found "
                                       + std::string(1, *ch) + "! (Control number is " + record.getControlNumber()
                                       + ".)");

                ++ch;
                if (ch == data.cend())
                    std::runtime_error("in XmlMarcWriter::write: unexpected subfield data end while expecting a "
                                       "subfield code!");
                const std::string subfield_code(1, *ch++);

                std::string subfield_data;
                while (ch != data.cend() and *ch != '\x1F')
                    subfield_data += *ch++;
                if (subfield_data.empty())
                    continue;

                xml_writer_->writeTagsWithData("subfield", { std::make_pair("code", subfield_code) },
                                              subfield_data, /* suppress_newline = */ true);
            }

            xml_writer_->closeTag(); // Close "datafield".
        }
    }

    xml_writer_->closeTag(); // Close "record".
}

std::unique_ptr<MarcWriter> MarcWriter::Factory(const std::string &output_filename, WriterType writer_type,
                                                const WriterMode writer_mode)
{
    std::unique_ptr<File> output(writer_mode == WriterMode::OVERWRITE ? FileUtil::OpenOutputFileOrDie(output_filename)
                                                                      : FileUtil::OpenForAppendingOrDie(output_filename));
    if (writer_type == AUTO) {
        if (StringUtil::EndsWith(output_filename, ".mrc") or StringUtil::EndsWith(output_filename, ".marc"))
            writer_type = BINARY;
        else if (StringUtil::EndsWith(output_filename, ".xml"))
            writer_type = XML;
        else
            throw std::runtime_error("in MarcWriter::Factory: WriterType is AUTO but filename \""
                                     + output_filename + "\" does not end in \".mrc\" or \".xml\"!");
    }
    return (writer_type == XML) ? std::unique_ptr<MarcWriter>(new XmlMarcWriter(output.release()))
                                : std::unique_ptr<MarcWriter>(new BinaryMarcWriter(output.release()));
}
<|endoftext|>


<commit_before>// Parse test application
// Based upon: parsetest.cpp from xmlpp

// needed includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <cppdom/cppdom.h>

// namespace includes
using namespace cppdom;
using namespace std;

// dumps the node
void dump_node( XMLNode &node, int level = 0 )
{
   XMLString name = node.getName();
   XMLNodeType type = node.getType();
   XMLString c_data;

   for(int i=0;i<level;i++) cout << " ";

   char c = ' ';
   switch(type)
   {
   case xml_nt_node:
      c = '+';
      break;
   case xml_nt_leaf:
      c = '-';
      break;
   case xml_nt_document:
      c = '\\';
      break;
   case xml_nt_cdata:
      c = '#';
      c_data = node.getCdata();
      break;
   }

   if(type == xml_nt_cdata)
      cout << c << name.c_str() << "[" << c_data << "]" << endl;
   else
      cout << c << name.c_str() << endl;

   XMLAttributes attr = node.getAttrmap();

   // guru: added output of attributes
   for (XMLAttributes::iterator j = attr.begin(); j!=attr.end(); j++)
   {
      for (int i=0; i<level; i++)
         cout << " ";
      cout << "   ";
      cout << j->first << ": " << j->second << endl;
   }

   XMLNodeList& nlist = node.getChildren();

   XMLNodeList::const_iterator iter, stop;
   iter = nlist.begin();
   stop = nlist.end();

   while (iter != stop)
   {
      XMLNodePtr node = *iter;

      dump_node ( *node, level+1 );

      ++iter;
   }
};

void process_xml( std::string filename )
{
   cout << "processing [" << filename << "] ..." << endl;

   XMLContextPtr context( new XMLContext );
   XMLDocument node( context );
   ifstream istr( filename.c_str() );

   // Verify that file opened
   if(!istr)
   {
      std::cerr << "Bad file: " << filename << std::endl;
      return;
   }

   try
   {
      clock_t tstart = ::clock();

      node.load( istr, context );

      clock_t tstop = ::clock();
      cout << " needed " <<
         (tstop-tstart)/static_cast<float>(CLOCKS_PER_SEC)
         << " seconds." << endl;

      dump_node( node );

      ofstream ostr( "parsetest.xml" );
      node.save( ostr );
      ostr.close();

   }
   catch (xmlerror e)
   {
      XMLLocation where( context->get_location() );
      XMLString errmsg;
      e.getStrError(errmsg);

      // print out where the error occured
      cout << filename << ":" << where.getLine() << " ";
      cout << "at position " << where.getPos();
      cout << ": error: " << errmsg.c_str();
      cout << endl;

      // print out line where the error occured
      ifstream errfile( filename.c_str() );
      if(!errfile)
      {
         std::cerr << "Can't open file [" << filename << "] to output error" << std::endl;
      }

      int linenr = where.get_line();
      char linebuffer[1024];
      for(int i=0; i<linenr && !errfile.eof(); i++)
         errfile.getline(linebuffer,1024);

      int pos = where.get_pos();
      if (pos>=80)
         pos %= 80;

      std::string err_line( linebuffer + (where.get_pos()-pos) );
      if (err_line.length()>=79)
         err_line.erase(79);
      cout << err_line << std::flush;
      cout << err_line.c_str() << std::endl;
      cout << linebuffer << std::endl;
      for(int j=2;j<pos;j++)
         std::cout << " ";
      cout << '^' << endl;
   }
}

int main(int argc, char* argv[])
{
   for(int i=1;i<argc;i++)
   {
      process_xml( std::string(argv[i]) );
   }

   return 0;
}
<commit_msg>updated to current cppdom api changes<commit_after>// Parse test application
// Based upon: parsetest.cpp from xmlpp

// needed includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <cppdom/cppdom.h>

// namespace includes
using namespace cppdom;
using namespace std;

// dumps the node
void dump_node( XMLNode &node, int level = 0 )
{
   XMLString name = node.getName();
   XMLNodeType type = node.getType();
   XMLString c_data;

   for(int i=0;i<level;i++) cout << " ";

   char c = ' ';
   switch(type)
   {
   case xml_nt_node:
      c = '+';
      break;
   case xml_nt_leaf:
      c = '-';
      break;
   case xml_nt_document:
      c = '\\';
      break;
   case xml_nt_cdata:
      c = '#';
      c_data = node.getCdata();
      break;
   }

   if(type == xml_nt_cdata)
      cout << c << name.c_str() << "[" << c_data << "]" << endl;
   else
      cout << c << name.c_str() << endl;

   XMLAttributes attr = node.getAttrMap();

   // guru: added output of attributes
   for (XMLAttributes::iterator j = attr.begin(); j!=attr.end(); j++)
   {
      for (int i=0; i<level; i++)
         cout << " ";
      cout << "   ";
      cout << j->first << ": " << j->second << endl;
   }

   XMLNodeList& nlist = node.getChildren();

   XMLNodeList::const_iterator iter, stop;
   iter = nlist.begin();
   stop = nlist.end();

   while (iter != stop)
   {
      XMLNodePtr node = *iter;

      dump_node ( *node, level+1 );

      ++iter;
   }
};

void process_xml( std::string filename )
{
   cout << "processing [" << filename << "] ..." << endl;

   XMLContextPtr context( new XMLContext );
   XMLDocument node( context );
   ifstream istr( filename.c_str() );

   // Verify that file opened
   if(!istr)
   {
      std::cerr << "Bad file: " << filename << std::endl;
      return;
   }

   try
   {
      clock_t tstart = ::clock();

      node.load( istr, context );

      clock_t tstop = ::clock();
      cout << " needed " <<
         (tstop-tstart)/static_cast<float>(CLOCKS_PER_SEC)
         << " seconds." << endl;

      dump_node( node );

      ofstream ostr( "parsetest.xml" );
      node.save( ostr );
      ostr.close();

   }
   catch (XMLError e)
   {
      XMLLocation where( context->getLocation() );
      XMLString errmsg;
      e.getStrError(errmsg);

      // print out where the error occured
      cout << filename << ":" << where.getLine() << " ";
      cout << "at position " << where.getPos();
      cout << ": error: " << errmsg.c_str();
      cout << endl;

      // print out line where the error occured
      ifstream errfile( filename.c_str() );
      if(!errfile)
      {
         std::cerr << "Can't open file [" << filename << "] to output error" << std::endl;
      }

      int linenr = where.getLine();
      char linebuffer[1024];
      for(int i=0; i<linenr && !errfile.eof(); i++)
         errfile.getline( linebuffer,1024 );

      int pos = where.getPos();
      if (pos>=80)
         pos %= 80;

      std::string err_line( linebuffer + (where.getPos()-pos) );
      if (err_line.length()>=79)
         err_line.erase(79);
      cout << err_line << std::flush;
      cout << err_line.c_str() << std::endl;
      cout << linebuffer << std::endl;
      for(int j=2;j<pos;j++)
         std::cout << " ";
      cout << '^' << endl;
   }
}

int main(int argc, char* argv[])
{
   for(int i=1;i<argc;i++)
   {
      process_xml( std::string(argv[i]) );
   }

   return 0;
}
<|endoftext|>


<commit_before>/*
*
*	Author: Philipp Zschoche
*	GitHub: https://github.com/zschoche
*
*/
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
#ifndef __SYSLOG_LOGGERS_HPP__
#define __SYSLOG_LOGGERS_HPP__

#include <syslog.h>
#include "logger.hpp"

namespace   mlog
{
	class syslog_logger : public logger
	{
	public:
		enum syslog_level {
			EMERG =		LOG_EMERG,	/* system is unusable */
			ALERT =		LOG_ALERT,	/* action must be taken immediately */
			CRIT =		LOG_CRIT,	/* critical conditions */
			ERR	=	LOG_ERR,	/* error conditions */
			WARNING =	LOG_WARNING,	/* warning conditions */
			NOTICE =	LOG_NOTICE,	/* normal but significant condition */
			INFO =		LOG_INFO,	/* informational */
			DEBUG = 	LOG_DEBUG	/* debug */
		};

		  syslog_logger(const char* ident = nullptr, int option = LOG_CONS | LOG_PID | LOG_NDELAY, int facility = LOG_LOCAL1)
		  :level(syslog_level::NOTICE) {
     			setlogmask(LOG_UPTO(syslog_level::DEBUG)); // mlog handle that by its own.
			openlog(ident, option, facility);
		}

		virtual ~syslog_logger() {
			closelog();
			logger::~logger();
		}

		void write_to_log(log_metadata &&metadata,
				  std::string &&log_text) {
			syslog(level, "%s", metadata.to_string(log_text).c_str());
		}

		void write_to_log(const log_metadata& metadata,
				  const std::string& log_text) {
			syslog(level, "%s", metadata.to_string(log_text).c_str());
		}

		syslog_level level;

	};
} /*   mlog */

#endif /* ___HPP__ */
#endif

<commit_msg>This wasn't a good idea. at all. -.-<commit_after>/*
*
*	Author: Philipp Zschoche
*	GitHub: https://github.com/zschoche
*
*/
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
#ifndef __SYSLOG_LOGGERS_HPP__
#define __SYSLOG_LOGGERS_HPP__

#include <syslog.h>
#include "logger.hpp"

namespace   mlog
{
	class syslog_logger : public logger
	{
	public:
		enum syslog_level {
			EMERG =		LOG_EMERG,	/* system is unusable */
			ALERT =		LOG_ALERT,	/* action must be taken immediately */
			CRIT =		LOG_CRIT,	/* critical conditions */
			ERR	=	LOG_ERR,	/* error conditions */
			WARNING =	LOG_WARNING,	/* warning conditions */
			NOTICE =	LOG_NOTICE,	/* normal but significant condition */
			INFO =		LOG_INFO,	/* informational */
			DEBUG = 	LOG_DEBUG	/* debug */
		};

		  syslog_logger(const char* ident = nullptr, int option = LOG_CONS | LOG_PID | LOG_NDELAY, int facility = LOG_LOCAL1)
		  :level(syslog_level::NOTICE) {
     			setlogmask(LOG_UPTO(syslog_level::DEBUG)); // mlog handle that by its own.
			openlog(ident, option, facility);
		}

		virtual ~syslog_logger() {
			closelog();
		}

		void write_to_log(log_metadata &&metadata,
				  std::string &&log_text) {
			syslog(level, "%s", metadata.to_string(log_text).c_str());
		}

		void write_to_log(const log_metadata& metadata,
				  const std::string& log_text) {
			syslog(level, "%s", metadata.to_string(log_text).c_str());
		}

		syslog_level level;

	};
} /*   mlog */

#endif /* ___HPP__ */
#endif

<|endoftext|>


<commit_before>#include "backend.h"

#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/security/server_credentials.h>
#include <memory>
#include <mutex>

#include "action/action.h"
#include "action/action_service_impl.h"
#include "connection_initiator.h"
#include "core/corerpc_impl.h"
#include "dronecore.h"
#include "log.h"
#include "mission/mission.h"
#include "mission/mission_service_impl.h"
#include "telemetry/telemetry_service_impl.h"

namespace dronecore {
namespace backend {

class DroneCoreBackend::Impl
{
public:
    Impl() {}
    ~Impl() {}

    bool run(const int mavlink_listen_port)
    {
        _connection_initiator.start(_dc, 14540);
        _connection_initiator.wait();

        grpc::ServerBuilder builder;
        setup_port(builder);

        CoreServiceImpl core(_dc);
        builder.RegisterService(&core);

        Action action(_dc.system());
        ActionServiceImpl<dronecore::Action> actionService(action);
        builder.RegisterService(&actionService);

        Mission mission(_dc.system());
        MissionServiceImpl<dronecore::Mission> missionService(mission);

        builder.RegisterService(&missionService);

        Telemetry telemetry(_dc.system());
        TelemetryServiceImpl<> telemetryService(telemetry);

        builder.RegisterService(&telemetryService);

        _server = builder.BuildAndStart();
        LogInfo() << "Server started";
        _server->Wait();

        return true;
    }

private:
    void setup_port(grpc::ServerBuilder &builder)
    {
        std::string server_address("0.0.0.0:50051");
        builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
        LogInfo() << "Server set to listen on " << server_address;
    }

    dronecore::DroneCore _dc;
    dronecore::backend::ConnectionInitiator<dronecore::DroneCore> _connection_initiator;
    std::unique_ptr<grpc::Server> _server;
};

DroneCoreBackend::DroneCoreBackend() : _impl(new Impl()) {}
DroneCoreBackend::~DroneCoreBackend() = default;

bool DroneCoreBackend::run(const int mavlink_listen_port) { return _impl->run(mavlink_listen_port); }

} // namespace backend
} // namespace dronecore
<commit_msg>backend: update mission proto file<commit_after>#include "backend.h"

#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/security/server_credentials.h>
#include <memory>
#include <mutex>

#include "action/action.h"
#include "action/action_service_impl.h"
#include "connection_initiator.h"
#include "core/corerpc_impl.h"
#include "dronecore.h"
#include "log.h"
#include "mission/mission_service_impl.h"
#include "telemetry/telemetry_service_impl.h"

namespace dronecore {
namespace backend {

class DroneCoreBackend::Impl
{
public:
    Impl() {}
    ~Impl() {}

    bool run(const int mavlink_listen_port)
    {
        _connection_initiator.start(_dc, 14540);
        _connection_initiator.wait();

        grpc::ServerBuilder builder;
        setup_port(builder);

        CoreServiceImpl core(_dc);
        builder.RegisterService(&core);

        Action action(_dc.system());
        ActionServiceImpl<dronecore::Action> actionService(action);
        builder.RegisterService(&actionService);

        Mission mission(_dc.system());
        MissionServiceImpl<dronecore::Mission> missionService(mission);

        builder.RegisterService(&missionService);

        Telemetry telemetry(_dc.system());
        TelemetryServiceImpl<> telemetryService(telemetry);

        builder.RegisterService(&telemetryService);

        _server = builder.BuildAndStart();
        LogInfo() << "Server started";
        _server->Wait();

        return true;
    }

private:
    void setup_port(grpc::ServerBuilder &builder)
    {
        std::string server_address("0.0.0.0:50051");
        builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
        LogInfo() << "Server set to listen on " << server_address;
    }

    dronecore::DroneCore _dc;
    dronecore::backend::ConnectionInitiator<dronecore::DroneCore> _connection_initiator;
    std::unique_ptr<grpc::Server> _server;
};

DroneCoreBackend::DroneCoreBackend() : _impl(new Impl()) {}
DroneCoreBackend::~DroneCoreBackend() = default;

bool DroneCoreBackend::run(const int mavlink_listen_port) { return _impl->run(mavlink_listen_port); }

} // namespace backend
} // namespace dronecore
<|endoftext|>


<commit_before>#include "itkImageFileWriter.h"

#include "AnisotropicAnomalousDiffusionImageFilter.h"
#include "itkCastImageFilter.h"

#include "itkPluginUtilities.h"

#include "AADDiffusionWeightedDataCLP.h"

// Use an anonymous namespace to keep class types and function names
// from colliding when module is used as shared object module.  Every
// thing should be in an anonymous namespace except for the module
// entry point, e.g. main()
//
namespace
{

template <class T>
int DoIt( int argc, char * argv[], T )
{
    PARSE_ARGS;

    typedef    float InputPixelType;
    typedef    T OutputPixelType;

    typedef itk::Image<InputPixelType,  3> InputImageType;
    typedef itk::Image<OutputPixelType, 3> OutputImageType;

    typedef itk::ImageFileReader<InputImageType>  ReaderType;
    typedef itk::ImageFileWriter<OutputImageType> WriterType;
    typedef itk::CastImageFilter<InputImageType, OutputImageType> CastType;

    typedef itk::AnisotropicAnomalousDiffusionImageFilter<InputImageType, InputImageType> FilterType;

    typename ReaderType::Pointer reader = ReaderType::New();
    itk::PluginFilterWatcher watchReader(reader, "Read Volume",CLPProcessInformation);

    reader->SetFileName( inputVolume.c_str() );

    typename FilterType::Pointer filter = FilterType::New();
    itk::PluginFilterWatcher watchFilter(filter, "Anisotropic Anomalous Diffusion",CLPProcessInformation);

    filter->SetInput( reader->GetOutput() );
    filter->SetIterations(iterations);
    filter->SetCondutance(condutance);
    filter->SetTimeStep(timeStep);
    filter->SetQ(q);

    typename CastType::Pointer cast = CastType::New();
    cast->SetInput( filter->GetOutput() );

    typename WriterType::Pointer writer = WriterType::New();
    itk::PluginFilterWatcher watchWriter(writer, "Write Volume",CLPProcessInformation);

    writer->SetFileName( outputVolume.c_str() );
    writer->SetInput( cast->GetOutput() );
    writer->SetUseCompression(1);
    writer->Update();

    return EXIT_SUCCESS;
}

} // end of anonymous namespace

int main( int argc, char * argv[] )
{
    PARSE_ARGS;

    itk::ImageIOBase::IOPixelType     pixelType;
    itk::ImageIOBase::IOComponentType componentType;

    try
    {
        itk::GetImageType(inputVolume, pixelType, componentType);

        // This filter handles all types on input, but only produces
        // signed types
        switch( componentType )
        {
        case itk::ImageIOBase::UCHAR:
            return DoIt( argc, argv, static_cast<unsigned char>(0) );
            break;
        case itk::ImageIOBase::CHAR:
            return DoIt( argc, argv, static_cast<char>(0) );
            break;
        case itk::ImageIOBase::USHORT:
            return DoIt( argc, argv, static_cast<unsigned short>(0) );
            break;
        case itk::ImageIOBase::SHORT:
            return DoIt( argc, argv, static_cast<short>(0) );
            break;
        case itk::ImageIOBase::UINT:
            return DoIt( argc, argv, static_cast<unsigned int>(0) );
            break;
        case itk::ImageIOBase::INT:
            return DoIt( argc, argv, static_cast<int>(0) );
            break;
        case itk::ImageIOBase::ULONG:
            return DoIt( argc, argv, static_cast<unsigned long>(0) );
            break;
        case itk::ImageIOBase::LONG:
            return DoIt( argc, argv, static_cast<long>(0) );
            break;
        case itk::ImageIOBase::FLOAT:
            return DoIt( argc, argv, static_cast<float>(0) );
            break;
        case itk::ImageIOBase::DOUBLE:
            return DoIt( argc, argv, static_cast<double>(0) );
            break;
        case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:
        default:
            std::cout << "unknown component type" << std::endl;
            break;
        }
    }

    catch( itk::ExceptionObject & excep )
    {
        std::cerr << argv[0] << ": exception caught !" << std::endl;
        std::cerr << excep << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<commit_msg>Complete implementation of AAD filter on DWI data processing.<commit_after>#include "AnisotropicAnomalousDiffusionImageFilter.h"

#include "itkPluginUtilities.h"

#include <itkMetaDataObject.h>
#include <itkImageFileWriter.h>
#include <itkNrrdImageIO.h>
#include <itkCastImageFilter.h>
#if ITK_VERSION_MAJOR < 4
#include "itkCompose3DCovariantVectorImageFilter.h"
#else
#include "itkComposeImageFilter.h"
#endif

#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkTensorFractionalAnisotropyImageFilter.h>
#include <itkTensorRelativeAnisotropyImageFilter.h>

#include "AADDiffusionWeightedDataCLP.h"

// Use an anonymous namespace to keep class types and function names
// from colliding when module is used as shared object module.  Every
// thing should be in an anonymous namespace except for the module
// entry point, e.g. main()
//

namespace
{

template <class T>
int DoIt( int argc, char * argv[], T )
{
    PARSE_ARGS;

    const unsigned int Dimension = 3;
    unsigned int numberOfImages = 0;
    unsigned int numberOfGradientImages = 0;
    bool readb0 = false;
    double b0 = 0;
    typedef short                                           PixelType;
    typedef itk::VectorImage<PixelType, Dimension>          VectorImageType;
    typedef itk::Image< PixelType, Dimension >              ScalarImageType;
    itk::ImageFileReader<VectorImageType>::Pointer reader = itk::ImageFileReader<VectorImageType>::New();
    VectorImageType::Pointer img;
    typedef itk::AnisotropicAnomalousDiffusionImageFilter<ScalarImageType, ScalarImageType> AADFilterType;
    // Set the properties for NrrdReader
    reader->SetFileName( inputVolume.c_str());
    // Read in the nrrd data. The file contains the reference image and the gradient
    // images.
    try
    {
        reader->Update();
        img = reader->GetOutput();
    }
    catch (itk::ExceptionObject &ex)
    {
        std::cout << ex << std::endl;
        return EXIT_FAILURE;
    }
    // Here we instantiate the DiffusionTensor3DReconstructionImageFilter class.
    // The class is templated over the pixel types of the reference, gradient
    // and the to be created tensor pixel's precision. (We use double here). It
    // takes as input the Reference (B0 image aquired in the absence of diffusion
    // sensitizing gradients), 'n' Gradient images and their directions and produces
    // as output an image of tensors with pixel-type DiffusionTensor3D.
    //
    typedef itk::DiffusionTensor3DReconstructionImageFilter<
            PixelType, PixelType, double > TensorReconstructionImageFilterType;
    // -------------------------------------------------------------------------
    // Parse the Nrrd headers to get the B value and the gradient directions used
    // for diffusion weighting.
    //
    // The Nrrd headers should look like :
    // The tags specify the B value and the gradient directions. If gradient
    // directions are (0,0,0), it indicates that it is a reference image.
    //
    // DWMRI_b-value:=800
    // DWMRI_gradient_0000:= 0 0 0
    // DWMRI_gradient_0001:=-1.000000       0.000000        0.000000
    // DWMRI_gradient_0002:=-0.166000       0.986000        0.000000
    // DWMRI_gradient_0003:=0.110000        0.664000        0.740000
    // ...
    //
    itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary();
    std::vector<std::string> imgMetaKeys = imgMetaDictionary.GetKeys();
    std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin();
    std::string metaString;
    TensorReconstructionImageFilterType::GradientDirectionType vect3d;
    TensorReconstructionImageFilterType::GradientDirectionContainerType::Pointer
            DiffusionVectors =
            TensorReconstructionImageFilterType::GradientDirectionContainerType::New();
    for (; itKey != imgMetaKeys.end(); ++itKey)
    {
        double x,y,z;
        itk::ExposeMetaData<std::string> (imgMetaDictionary, *itKey, metaString);
        if (itKey->find("DWMRI_gradient") != std::string::npos)
        {
            std::cout << *itKey << " ---> " << metaString << std::endl;
            sscanf(metaString.c_str(), "%lf %lf %lf\n", &x, &y, &z);
            vect3d[0] = x; vect3d[1] = y; vect3d[2] = z;
            DiffusionVectors->InsertElement( numberOfImages, vect3d );
            ++numberOfImages;
            // If the direction is 0.0, this is a reference image
            if (vect3d[0] == 0.0 &&
                    vect3d[1] == 0.0 &&
                    vect3d[2] == 0.0)
            {
                continue;
            }
            ++numberOfGradientImages;
        }
        else if (itKey->find("DWMRI_b-value") != std::string::npos)
        {
            std::cout << *itKey << " ---> " << metaString << std::endl;
            readb0 = true;
            b0 = atof(metaString.c_str());
        }
    }
    std::cout << "Number of gradient images: "
              << numberOfGradientImages
              << " and Number of reference images: "
              << numberOfImages - numberOfGradientImages
              << std::endl;
    if(!readb0)
    {
        std::cerr << "BValue not specified in header file" << std::endl;
        return EXIT_FAILURE;
    }

    std::vector< ScalarImageType::Pointer > imageContainer;
    // iterator to iterate over the DWI Vector image just read in.
    typedef itk::ImageRegionConstIterator< VectorImageType >         DWIIteratorType;
    DWIIteratorType dwiit( img, img->GetBufferedRegion() );
    typedef itk::ImageRegionIterator< ScalarImageType > IteratorType;

#if ITK_VERSION_MAJOR < 4
    typedef itk::Compose3DCovariantVectorImageFilter<ScalarImageType,
            VectorImageType> ScalarToVectorFilterType;
#else
    typedef itk::ComposeImageFilter<ScalarImageType,
            VectorImageType> ScalarToVectorFilterType;
#endif
    typename ScalarToVectorFilterType::Pointer scalarToVectorImageFilter = ScalarToVectorFilterType::New();
    for( unsigned int i = 0; i<numberOfImages; i++ )
    {
        ScalarImageType::Pointer image = ScalarImageType::New();
        image->CopyInformation( img );
        image->SetBufferedRegion( img->GetBufferedRegion() );
        image->SetRequestedRegion( img->GetRequestedRegion() );
        image->Allocate();
        IteratorType it( image, image->GetBufferedRegion() );
        dwiit.GoToBegin();
        it.GoToBegin();
        while (!it.IsAtEnd())
        {
            it.Set(dwiit.Get()[i]);
            ++it;
            ++dwiit;
        }
        imageContainer.push_back( image );

    }

    for(unsigned int countImage=0; countImage<numberOfImages; countImage++){
        typename AADFilterType::Pointer filter = AADFilterType::New();
        filter->SetInput( imageContainer[countImage] );
        filter->SetIterations(iterations);
        filter->SetCondutance(condutance);
        filter->SetTimeStep(timeStep);
        filter->SetQ(q);
        filter->Update();

        scalarToVectorImageFilter->SetInput(countImage, filter->GetOutput());
    }

    scalarToVectorImageFilter->Update();
    VectorImageType::Pointer diffusionImage = scalarToVectorImageFilter->GetOutput();

    // let's write it out

    typename itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();

    itk::MetaDataDictionary metaDataDictionary;
    metaDataDictionary = reader->GetMetaDataDictionary();

    io->SetFileTypeToBinary();
    io->SetMetaDataDictionary( metaDataDictionary );

    typedef itk::ImageFileWriter<VectorImageType> WriterType;
    typename WriterType::Pointer nrrdWriter = WriterType::New();
    nrrdWriter->UseInputMetaDataDictionaryOff();
    nrrdWriter->SetInput( diffusionImage );
    nrrdWriter->SetImageIO(io);
    nrrdWriter->SetFileName( outputVolume.c_str() );
    nrrdWriter->UseCompressionOn();
    try
    {
        nrrdWriter->Update();
    }
    catch( itk::ExceptionObject e )
    {
        std::cerr << argv[0] << ": exception caught !" << std::endl;
        std::cerr << e << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;

}

} // end of anonymous namespace

int main( int argc, char * argv[] )
{
    PARSE_ARGS;

    itk::ImageIOBase::IOPixelType     pixelType;
    itk::ImageIOBase::IOComponentType componentType;

    try
    {
        itk::GetImageType(inputVolume, pixelType, componentType);

        // This filter handles all types on input, but only produces
        // signed types
        switch( componentType )
        {
        case itk::ImageIOBase::UCHAR:
            return DoIt( argc, argv, static_cast<unsigned char>(0) );
            break;
        case itk::ImageIOBase::CHAR:
            return DoIt( argc, argv, static_cast<char>(0) );
            break;
        case itk::ImageIOBase::USHORT:
            return DoIt( argc, argv, static_cast<unsigned short>(0) );
            break;
        case itk::ImageIOBase::SHORT:
            return DoIt( argc, argv, static_cast<short>(0) );
            break;
        case itk::ImageIOBase::UINT:
            return DoIt( argc, argv, static_cast<unsigned int>(0) );
            break;
        case itk::ImageIOBase::INT:
            return DoIt( argc, argv, static_cast<int>(0) );
            break;
        case itk::ImageIOBase::ULONG:
            return DoIt( argc, argv, static_cast<unsigned long>(0) );
            break;
        case itk::ImageIOBase::LONG:
            return DoIt( argc, argv, static_cast<long>(0) );
            break;
        case itk::ImageIOBase::FLOAT:
            return DoIt( argc, argv, static_cast<float>(0) );
            break;
        case itk::ImageIOBase::DOUBLE:
            return DoIt( argc, argv, static_cast<double>(0) );
            break;
        case itk::ImageIOBase::UNKNOWNCOMPONENTTYPE:
        default:
            std::cout << "unknown component type" << std::endl;
            break;
        }
    }

    catch( itk::ExceptionObject & excep )
    {
        std::cerr << argv[0] << ": exception caught !" << std::endl;
        std::cerr << excep << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<|endoftext|>