<commit_before>/*
* (C) 2015,2017 Jack Lloyd
* (C) 2015 Simon Warta (Kullo GmbH)
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/exceptn.h>
#include <botan/internal/filesystem.h>
#include <algorithm>

#if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
  #include <filesystem>
#elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
  #include <boost/filesystem.hpp>
#elif defined(BOTAN_TARGET_OS_HAS_READDIR)
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <dirent.h>
  #include <deque>
  #include <memory>
  #include <functional>
#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
  #define NOMINMAX 1
  #define _WINSOCKAPI_ // stop windows.h including winsock.h
  #include <windows.h>
  #include <deque>
  #include <memory>
#endif

namespace Botan {

namespace {

#if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
std::vector<std::string> impl_stl_filesystem(const std::string& dir)
   {
   using namespace std::tr2::sys;

   std::vector<std::string> out;

   path p(dir);

   if (is_directory(p))
      {
      for (recursive_directory_iterator itr(p), end; itr != end; ++itr)
         {
         if (is_regular_file(itr->path()))
            {
            out.push_back(itr->path().string());
            }
         }
      }

   return out;
   }

#elif defined(BOTAN_HAS_BOOST_FILESYSTEM)

std::vector<std::string> impl_boost_filesystem(const std::string& dir_path)
{
   namespace fs = boost::filesystem;

   std::vector<std::string> out;

   for(fs::recursive_directory_iterator dir(dir_path), end; dir != end; ++dir)
      {
      if(fs::is_regular_file(dir->path()))
         {
         out.push_back(dir->path().string());
         }
      }

   return out;
}

#elif defined(BOTAN_TARGET_OS_HAS_READDIR)
std::vector<std::string> impl_readdir(const std::string& dir_path)
   {
   std::vector<std::string> out;
   std::deque<std::string> dir_list;
   dir_list.push_back(dir_path);

   while(!dir_list.empty())
      {
      const std::string cur_path = dir_list[0];
      dir_list.pop_front();

      std::unique_ptr<DIR, std::function<int (DIR*)>> dir(::opendir(cur_path.c_str()), ::closedir);

      if(dir)
         {
         while(struct dirent* dirent = ::readdir(dir.get()))
            {
            const std::string filename = dirent->d_name;
            if(filename == "." || filename == "..")
               continue;
            const std::string full_path = cur_path + "/" + filename;

            struct stat stat_buf;

            if(::stat(full_path.c_str(), &stat_buf) == -1)
               continue;

            if(S_ISDIR(stat_buf.st_mode))
               dir_list.push_back(full_path);
            else if(S_ISREG(stat_buf.st_mode))
               out.push_back(full_path);
            }
         }
      }

   return out;
   }

#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)

std::vector<std::string> impl_win32(const std::string& dir_path)
   {
   std::vector<std::string> out;
   std::deque<std::string> dir_list;
   dir_list.push_back(dir_path);

   while(!dir_list.empty())
      {
      const std::string cur_path = dir_list[0];
      dir_list.pop_front();

      WIN32_FIND_DATA find_data;
      HANDLE dir = ::FindFirstFile(cur_path.c_str(), &find_data);

      if(dir != INVALID_HANDLE_VALUE)
         {
         do
            {
            const std::string filename = find_data.cFileName;
            if(filename == "." || filename == "..")
               continue;
            const std::string full_path = cur_path + "/" + filename;

            if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
               dir_list.push_back(full_path);
            else if(find_data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
               out.push_back(full_path);
            }
         while(::FindNextFile(dir, &find_data));
         }

      ::FindClose(dir);
      }

   return out;
}
#endif

}

std::vector<std::string> get_files_recursive(const std::string& dir)
   {
   std::vector<std::string> files;

#if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   files = impl_stl_filesystem(dir);
#elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
   files = impl_boost_filesystem(dir);
#elif defined(BOTAN_TARGET_OS_HAS_READDIR)
   files = impl_readdir(dir);
#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
   files = impl_win32(dir);
#else
   BOTAN_UNUSED(dir);
   throw No_Filesystem_Access();
#endif

   std::sort(files.begin(), files.end());

   return files;
   }

}
<commit_msg>Make it actually work<commit_after>/*
* (C) 2015,2017 Jack Lloyd
* (C) 2015 Simon Warta (Kullo GmbH)
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/exceptn.h>
#include <botan/internal/filesystem.h>
#include <algorithm>

#if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
  #include <filesystem>
#elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
  #include <boost/filesystem.hpp>
#elif defined(BOTAN_TARGET_OS_HAS_READDIR)
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <dirent.h>
  #include <deque>
  #include <memory>
  #include <functional>
#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
  #define NOMINMAX 1
  #define _WINSOCKAPI_ // stop windows.h including winsock.h
  #include <windows.h>
  #include <deque>
  #include <memory>
#endif

namespace Botan {

namespace {

#if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
std::vector<std::string> impl_stl_filesystem(const std::string& dir)
   {
   using namespace std::tr2::sys;

   std::vector<std::string> out;

   path p(dir);

   if (is_directory(p))
      {
      for (recursive_directory_iterator itr(p), end; itr != end; ++itr)
         {
         if (is_regular_file(itr->path()))
            {
            out.push_back(itr->path().string());
            }
         }
      }

   return out;
   }

#elif defined(BOTAN_HAS_BOOST_FILESYSTEM)

std::vector<std::string> impl_boost_filesystem(const std::string& dir_path)
{
   namespace fs = boost::filesystem;

   std::vector<std::string> out;

   for(fs::recursive_directory_iterator dir(dir_path), end; dir != end; ++dir)
      {
      if(fs::is_regular_file(dir->path()))
         {
         out.push_back(dir->path().string());
         }
      }

   return out;
}

#elif defined(BOTAN_TARGET_OS_HAS_READDIR)
std::vector<std::string> impl_readdir(const std::string& dir_path)
   {
   std::vector<std::string> out;
   std::deque<std::string> dir_list;
   dir_list.push_back(dir_path);

   while(!dir_list.empty())
      {
      const std::string cur_path = dir_list[0];
      dir_list.pop_front();

      std::unique_ptr<DIR, std::function<int (DIR*)>> dir(::opendir(cur_path.c_str()), ::closedir);

      if(dir)
         {
         while(struct dirent* dirent = ::readdir(dir.get()))
            {
            const std::string filename = dirent->d_name;
            if(filename == "." || filename == "..")
               continue;
            const std::string full_path = cur_path + "/" + filename;

            struct stat stat_buf;

            if(::stat(full_path.c_str(), &stat_buf) == -1)
               continue;

            if(S_ISDIR(stat_buf.st_mode))
               dir_list.push_back(full_path);
            else if(S_ISREG(stat_buf.st_mode))
               out.push_back(full_path);
            }
         }
      }

   return out;
   }

#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)

std::vector<std::string> impl_win32(const std::string& dir_path)
   {
   std::vector<std::string> out;
   std::deque<std::string> dir_list;
   dir_list.push_back(dir_path);

   while(!dir_list.empty())
      {
      const std::string cur_path = dir_list[0];
      dir_list.pop_front();

      WIN32_FIND_DATA find_data;
      HANDLE dir = ::FindFirstFile((cur_path + "/*").c_str(), &find_data);

      if(dir != INVALID_HANDLE_VALUE)
         {
         do
            {
            const std::string filename = find_data.cFileName;
            if(filename == "." || filename == "..")
               continue;
            const std::string full_path = cur_path + "/" + filename;

            if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
               {
               dir_list.push_back(full_path);
               }
            else
               {
               out.push_back(full_path);
               }
            }
         while(::FindNextFile(dir, &find_data));
         }

      ::FindClose(dir);
      }

   return out;
}
#endif

}

std::vector<std::string> get_files_recursive(const std::string& dir)
   {
   std::vector<std::string> files;

#if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   files = impl_stl_filesystem(dir);
#elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
   files = impl_boost_filesystem(dir);
#elif defined(BOTAN_TARGET_OS_HAS_READDIR)
   files = impl_readdir(dir);
#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
   files = impl_win32(dir);
#else
   BOTAN_UNUSED(dir);
   throw No_Filesystem_Access();
#endif

   std::sort(files.begin(), files.end());

   return files;
   }

}
<|endoftext|>


<commit_before>#include "archive_reader.hpp"

#include <archive.h>
#include <archive_entry.h>
#include <stdexcept>
#include <boost/filesystem.hpp>
#include <boost/scope_exit.hpp>

using namespace moor;

ArchiveReader::ArchiveReader(const std::string& _archive_file_name)
  :m_archive_file_name(_archive_file_name), m_archive(archive_read_new())
   , m_open(true)
{
  if (!boost::filesystem::exists(m_archive_file_name))
    throw std::runtime_error("Archive file not found.");

  init();
  checkError(archive_read_open_file(m_archive, m_archive_file_name.c_str()
    , 10240), true);

}

ArchiveReader::ArchiveReader(unsigned char* _in_buffer, const size_t _size)
  :m_archive_file_name(""), m_archive(archive_read_new()) , m_open(true)
{
  init();
  checkError(archive_read_open_memory(m_archive, _in_buffer, _size), true);
}

ArchiveReader::ArchiveReader(std::vector<unsigned char>&& _in_buffer)
  :m_archive_file_name(""), m_in_buffer(std::move(_in_buffer))
   , m_archive(archive_read_new()), m_open(true)
{
  init();
  checkError(archive_read_open_memory(m_archive, &*m_in_buffer.begin()
    , m_in_buffer.size()), true);
}

void ArchiveReader::init()
{
  checkError(archive_read_support_format_all(m_archive), true);
  checkError(archive_read_support_compression_all(m_archive), true);
}

ArchiveReader::~ArchiveReader()
{
  close();
}

int copy_data(struct archive *ar, struct archive *aw)
{
  int r;
  const void *buff;
  size_t size;
  __LA_INT64_T offset;

  for (;;)
  {
    r = archive_read_data_block(ar, &buff, &size, &offset);
    if (r == ARCHIVE_EOF)
      return (ARCHIVE_OK);
    if (r != ARCHIVE_OK)
      return (r);
    r = archive_write_data_block(aw, buff, size, offset);
    if (r != ARCHIVE_OK)
      return (r);
  }
}

bool ArchiveReader::ExtractNext (const std::string& _root_path)
{
  int flags;

  /* Select which attributes we want to restore. */
  flags = ARCHIVE_EXTRACT_TIME;
  flags |= ARCHIVE_EXTRACT_PERM;
  flags |= ARCHIVE_EXTRACT_ACL;
  flags |= ARCHIVE_EXTRACT_FFLAGS;

  struct archive* a = archive_write_disk_new();
  archive_write_disk_set_options(a, flags);
  archive_write_disk_set_standard_lookup(a);

  struct archive_entry* entry;
  auto r = archive_read_next_header(m_archive, &entry);
  BOOST_SCOPE_EXIT (&a)
  {
    if(a != NULL)
    {
      archive_write_finish_entry(a);
      archive_write_close(a);
      archive_write_free(a);
    }
  }
  BOOST_SCOPE_EXIT_END
  if (r == ARCHIVE_EOF)
    return false;
  else
    checkError(r);

  archive_entry_set_pathname(entry,
      (boost::filesystem::path(_root_path) /
      archive_entry_pathname(entry)).string().c_str());
  checkError(archive_write_header(a, entry));
  if (archive_entry_size(entry) > 0)
    checkError(copy_data(m_archive, a));

  return true;
}

std::pair<std::string, std::vector<unsigned char>> ArchiveReader::ExtractNext()
{
  auto result = std::make_pair(std::string(""), std::vector<unsigned char>());

  struct archive_entry* entry;
  auto r = archive_read_next_header(m_archive, &entry);
  if (r == ARCHIVE_EOF)
    return result;
  else
    checkError(r);

  result.first = archive_entry_pathname(entry);
  auto entry_size = archive_entry_size(entry);
  if (entry_size > 0)
  {
    int r;
    size_t read_index = 0;
    char c;
    result.second.resize(entry_size);
    for (;;)
    {
      r = archive_read_data(m_archive, &result.second[read_index]
        , result.second.size() - read_index);
      if (r == 0)
        break;
      if (r < ARCHIVE_OK)
        checkError (r);

      read_index += r;
    }
  }

  return result;
}

void ArchiveReader::checkError(const int _err_code
  , const bool _close_before_throw)
{
  if (_close_before_throw && _err_code == ARCHIVE_FATAL)
    close();
  if (_err_code != ARCHIVE_OK && _err_code != ARCHIVE_WARN)
    throw std::runtime_error(archive_error_string(m_archive));
}

void ArchiveReader::close()
{
  if (m_open)
  {
    if (m_archive != NULL)
    {
      archive_read_close(m_archive);
      archive_read_free (m_archive);
    }

    m_open = false;
  }
}
<commit_msg>bug fix<commit_after>#include "archive_reader.hpp"

#include <archive.h>
#include <archive_entry.h>
#include <stdexcept>
#include <boost/filesystem.hpp>
#include <boost/scope_exit.hpp>

using namespace moor;

ArchiveReader::ArchiveReader(const std::string& _archive_file_name)
  :m_archive_file_name(_archive_file_name), m_archive(archive_read_new())
   , m_open(true)
{
  if (!boost::filesystem::exists(m_archive_file_name))
    throw std::runtime_error("Archive file not found.");

  init();
  checkError(archive_read_open_file(m_archive, m_archive_file_name.c_str()
    , 10240), true);

}

ArchiveReader::ArchiveReader(unsigned char* _in_buffer, const size_t _size)
  :m_archive_file_name(""), m_archive(archive_read_new()) , m_open(true)
{
  init();
  checkError(archive_read_open_memory(m_archive, _in_buffer, _size), true);
}

ArchiveReader::ArchiveReader(std::vector<unsigned char>&& _in_buffer)
  :m_archive_file_name(""), m_in_buffer(std::move(_in_buffer))
   , m_archive(archive_read_new()), m_open(true)
{
  init();
  checkError(archive_read_open_memory(m_archive, &*m_in_buffer.begin()
    , m_in_buffer.size()), true);
}

void ArchiveReader::init()
{
  checkError(archive_read_support_format_all(m_archive), true);
  checkError(archive_read_support_compression_all(m_archive), true);
}

ArchiveReader::~ArchiveReader()
{
  close();
}

int copy_data(struct archive *ar, struct archive *aw)
{
  int r;
  const void *buff;
  size_t size;
  __LA_INT64_T offset;

  for (;;)
  {
    r = archive_read_data_block(ar, &buff, &size, &offset);
    if (r == ARCHIVE_EOF)
      return (ARCHIVE_OK);
    if (r != ARCHIVE_OK)
      return (r);
    r = archive_write_data_block(aw, buff, size, offset);
    if (r != ARCHIVE_OK)
      return (r);
  }
}

bool ArchiveReader::ExtractNext (const std::string& _root_path)
{
  int flags;

  /* Select which attributes we want to restore. */
  flags = ARCHIVE_EXTRACT_TIME;
  flags |= ARCHIVE_EXTRACT_PERM;
  flags |= ARCHIVE_EXTRACT_ACL;
  flags |= ARCHIVE_EXTRACT_FFLAGS;

  struct archive* a = archive_write_disk_new();
  archive_write_disk_set_options(a, flags);
  archive_write_disk_set_standard_lookup(a);

  struct archive_entry* entry;
  auto r = archive_read_next_header(m_archive, &entry);
  BOOST_SCOPE_EXIT (&a)
  {
    if(a != NULL)
    {
      archive_write_finish_entry(a);
      archive_write_close(a);
      archive_write_free(a);
    }
  }
  BOOST_SCOPE_EXIT_END
  if (r == ARCHIVE_EOF)
    return false;
  else
    checkError(r);

  archive_entry_set_pathname(entry,
      (boost::filesystem::path(_root_path) /
      archive_entry_pathname(entry)).string().c_str());
  checkError(archive_write_header(a, entry));
  if (archive_entry_size(entry) > 0)
    checkError(copy_data(m_archive, a));

  return true;
}

std::pair<std::string, std::vector<unsigned char>> ArchiveReader::ExtractNext()
{
  auto result = std::make_pair(std::string(""), std::vector<unsigned char>());

  struct archive_entry* entry;
  auto r = archive_read_next_header(m_archive, &entry);
  if (r == ARCHIVE_EOF)
    return result;
  else
    checkError(r);

  result.first = archive_entry_pathname(entry);
  auto entry_size = archive_entry_size(entry);
  if (entry_size > 0)
  {
    int r;
    size_t read_index = 0;
    result.second.resize(entry_size);
    for (;;)
    {
      r = archive_read_data(m_archive, &result.second[read_index]
        , result.second.size() - read_index);
      if (r == 0)
        break;
      if (r < ARCHIVE_OK)
        checkError (r);

      read_index += r;
      if (read_index == entry_size)
        break;
    }
  }

  return result;
}

void ArchiveReader::checkError(const int _err_code
  , const bool _close_before_throw)
{
  if (_close_before_throw && _err_code == ARCHIVE_FATAL)
    close();
  if (_err_code != ARCHIVE_OK && _err_code != ARCHIVE_WARN)
    throw std::runtime_error(archive_error_string(m_archive));
}

void ArchiveReader::close()
{
  if (m_open)
  {
    if (m_archive != NULL)
    {
      archive_read_close(m_archive);
      archive_read_free (m_archive);
    }

    m_open = false;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Mohammad Mehdi Saboorian
 *
 * This is part of moor, a wrapper for libarchive
 *
 * 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.
 */

#include "archive_writer.hpp"
#include "archive_entry.hpp"
#include "archive_read_disk.hpp"
#include "memory_writer_callback.hpp"

#include <archive.h>
#include <archive_entry.h>

#include <fstream>
#include <stdexcept>
#include <system_error>

#include <sys/types.h>
#include <sys/stat.h>

using namespace moor;

ArchiveWriter::ArchiveWriter(const std::string& archive_file_name_,
                             const Format format_,
                             const Filter filter_)
  : Archive(archive_write_new(), archive_file_name_),
    m_entry(archive_entry_new()),
    m_format(format_),
    m_filter(filter_),
    m_open(true)
{
  // Set archive format
  checkError(archive_write_set_format(m_archive, static_cast<int>(m_format)), true);

  // Set archive compression
  checkError(archive_write_add_filter(m_archive, static_cast<int>(m_filter)), true);
  checkError(archive_write_open_filename(m_archive, cfilename()), true);
}

ArchiveWriter::ArchiveWriter(std::vector<unsigned char>& out_buffer_,
                             const Format format_,
                             const Filter filter_)
  : Archive(archive_write_new()),
    m_entry(archive_entry_new()),
    m_format(format_),
    m_filter(filter_),
    m_open(true)
{
  // Set archive format
  checkError(archive_write_set_format(m_archive, static_cast<int>(m_format)), true);

  // Set archive filter
  checkError(archive_write_add_filter(m_archive, static_cast<int>(m_filter)), true);
  checkError(write_open_memory(m_archive, &out_buffer_), true);
}

ArchiveWriter::ArchiveWriter(unsigned char* out_buffer_,
                             size_t* size_,
                             const Format format_,
                             const Filter filter_)
  : Archive(archive_write_new()),
    m_entry(archive_entry_new()),
    m_format(format_),
    m_filter(filter_),
    m_open(true)
{
  // Set archive format
  checkError(archive_write_set_format(m_archive, static_cast<int>(m_format)), true);

  // Set archive filter
  checkError(archive_write_add_filter(m_archive, static_cast<int>(m_filter)), true);
  checkError(archive_write_open_memory(m_archive, out_buffer_, *size_, size_), true);
}

ArchiveWriter::~ArchiveWriter()
{

}

void ArchiveWriter::addHeader(const std::string& entry_name_,
                              const FileType entry_type_,
                              const long long size_,
                              const int permission_)
{
  m_entry = archive_entry_clear(m_entry);
  archive_entry_set_pathname(m_entry, entry_name_.c_str());
  archive_entry_set_perm(m_entry, permission_);
  archive_entry_set_filetype(m_entry, static_cast<int>(entry_type_));
  archive_entry_set_size(m_entry, size_);
  checkError(archive_write_header(m_archive, m_entry));
}

void ArchiveWriter::addHeader(const std::string& filePath,
                              const struct stat* statBuf)
{
  ArchiveReadDisk a;

  m_entry = archive_entry_clear(m_entry);
  archive_entry_set_pathname(m_entry, filePath.c_str());
  checkError(archive_read_disk_entry_from_file(a, m_entry, -1, statBuf));
  checkError(archive_write_header(m_archive, m_entry));
}

void ArchiveWriter::addContent(const char b)
{
  archive_write_data(m_archive, &b, 1);
}

void ArchiveWriter::addContent(const void* data, const unsigned long long size)
{
  archive_write_data(m_archive, data, size);
}

void ArchiveWriter::addFinish()
{
  archive_write_finish_entry(m_archive);
}

void ArchiveWriter::writeFileData(const char* path)
{
  static char buf[16384];

  std::ifstream file(path, std::ios::in);
  while (file.good())
  {
    file.read(buf, sizeof(buf));
    archive_write_data(m_archive,
                       buf,
                       static_cast<size_t>(file.gcount()));
  }

#if 0
      int fd = open(archive_entry_sourcepath(m_entry), O_RDONLY);
      auto len = read(fd, buf, sizeof(buf));
      while (len > 0)
      {
          archive_write_data(m_archive, buf, len);
          len = read(fd, buf, sizeof(buf));
      }
      ::close(fd);
#endif
}

void ArchiveWriter::addFile(const std::string& file_path)
{
  struct stat file_stat;
  if (stat(file_path.c_str(), &file_stat) < 0)
  {
      throw std::system_error(std::error_code(errno, std::generic_category()));
  }

  addHeader(file_path, &file_stat);

  if (!S_ISREG(file_stat.st_mode))
  {
    throw std::system_error(std::make_error_code(std::errc::not_supported));
  }

  writeFileData(file_path.c_str());
  addFinish();
}

void ArchiveWriter::addFile(const std::string& entry_name,
                            const void* data,
                            unsigned long long size)
{
  addHeader(entry_name, FileType::Regular, size);
  addContent(data, size);
  addFinish();
}

void ArchiveWriter::addDiskPath(const std::string& path, ArchiveMatch* match)
{
  ArchiveReadDisk disk;

  checkError(disk.open(path.c_str()), true);
  if (match)
  {
      int rc = disk.setMatchFilter(*match);
      checkError(rc, true);
  }

  while (true)
  {
      int r = archive_read_next_header2(disk, m_entry);
      if (r == ARCHIVE_EOF)
      {
          break;
      }

      checkError(r, true);

      archive_read_disk_descend(disk);

      #if 0
      if (!m_prefix.empty())
      {
        std::string dest(m_prefix);
        dest += path;
        archive_entry_set_pathname(m_entry, dest.c_str());
      }
      #endif

      r = archive_write_header(m_archive, m_entry);
      checkError(r, true);

      writeFileData(archive_entry_sourcepath(m_entry));
  }
}

void ArchiveWriter::addDirectory(const std::string& directory_name)
{
  addHeader(directory_name, FileType::Directory, 0777);
  addFinish();
}

void ArchiveWriter::close()
{
  if (m_open)
  {
    m_open = false;

    if (m_archive)
    {
      archive_write_close(m_archive);
      archive_write_free(m_archive);
    }

    if (m_entry)
    {
      archive_entry_free(m_entry);
    }
  }
}
<commit_msg>Use the right archive for file read error<commit_after>/*
 * Copyright (c) 2013 Mohammad Mehdi Saboorian
 *
 * This is part of moor, a wrapper for libarchive
 *
 * 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.
 */

#include "archive_writer.hpp"
#include "archive_entry.hpp"
#include "archive_read_disk.hpp"
#include "memory_writer_callback.hpp"

#include <archive.h>
#include <archive_entry.h>

#include <fstream>
#include <stdexcept>
#include <system_error>

#include <sys/types.h>
#include <sys/stat.h>

using namespace moor;

ArchiveWriter::ArchiveWriter(const std::string& archive_file_name_,
                             const Format format_,
                             const Filter filter_)
  : Archive(archive_write_new(), archive_file_name_),
    m_entry(archive_entry_new()),
    m_format(format_),
    m_filter(filter_),
    m_open(true)
{
  // Set archive format
  checkError(archive_write_set_format(m_archive, static_cast<int>(m_format)), true);

  // Set archive compression
  checkError(archive_write_add_filter(m_archive, static_cast<int>(m_filter)), true);
  checkError(archive_write_open_filename(m_archive, cfilename()), true);
}

ArchiveWriter::ArchiveWriter(std::vector<unsigned char>& out_buffer_,
                             const Format format_,
                             const Filter filter_)
  : Archive(archive_write_new()),
    m_entry(archive_entry_new()),
    m_format(format_),
    m_filter(filter_),
    m_open(true)
{
  // Set archive format
  checkError(archive_write_set_format(m_archive, static_cast<int>(m_format)), true);

  // Set archive filter
  checkError(archive_write_add_filter(m_archive, static_cast<int>(m_filter)), true);
  checkError(write_open_memory(m_archive, &out_buffer_), true);
}

ArchiveWriter::ArchiveWriter(unsigned char* out_buffer_,
                             size_t* size_,
                             const Format format_,
                             const Filter filter_)
  : Archive(archive_write_new()),
    m_entry(archive_entry_new()),
    m_format(format_),
    m_filter(filter_),
    m_open(true)
{
  // Set archive format
  checkError(archive_write_set_format(m_archive, static_cast<int>(m_format)), true);

  // Set archive filter
  checkError(archive_write_add_filter(m_archive, static_cast<int>(m_filter)), true);
  checkError(archive_write_open_memory(m_archive, out_buffer_, *size_, size_), true);
}

ArchiveWriter::~ArchiveWriter()
{

}

void ArchiveWriter::addHeader(const std::string& entry_name_,
                              const FileType entry_type_,
                              const long long size_,
                              const int permission_)
{
  m_entry = archive_entry_clear(m_entry);
  archive_entry_set_pathname(m_entry, entry_name_.c_str());
  archive_entry_set_perm(m_entry, permission_);
  archive_entry_set_filetype(m_entry, static_cast<int>(entry_type_));
  archive_entry_set_size(m_entry, size_);
  checkError(archive_write_header(m_archive, m_entry));
}

void ArchiveWriter::addHeader(const std::string& filePath,
                              const struct stat* statBuf)
{
  ArchiveReadDisk a;

  m_entry = archive_entry_clear(m_entry);
  archive_entry_set_pathname(m_entry, filePath.c_str());
  checkError(archive_read_disk_entry_from_file(a, m_entry, -1, statBuf));
  checkError(archive_write_header(m_archive, m_entry));
}

void ArchiveWriter::addContent(const char b)
{
  archive_write_data(m_archive, &b, 1);
}

void ArchiveWriter::addContent(const void* data, const unsigned long long size)
{
  archive_write_data(m_archive, data, size);
}

void ArchiveWriter::addFinish()
{
  archive_write_finish_entry(m_archive);
}

void ArchiveWriter::writeFileData(const char* path)
{
  static char buf[16384];

  std::ifstream file(path, std::ios::in);
  while (file.good())
  {
    file.read(buf, sizeof(buf));
    archive_write_data(m_archive,
                       buf,
                       static_cast<size_t>(file.gcount()));
  }

#if 0
      int fd = open(archive_entry_sourcepath(m_entry), O_RDONLY);
      auto len = read(fd, buf, sizeof(buf));
      while (len > 0)
      {
          archive_write_data(m_archive, buf, len);
          len = read(fd, buf, sizeof(buf));
      }
      ::close(fd);
#endif
}

void ArchiveWriter::addFile(const std::string& file_path)
{
  struct stat file_stat;
  if (stat(file_path.c_str(), &file_stat) < 0)
  {
      throw std::system_error(std::error_code(errno, std::generic_category()));
  }

  addHeader(file_path, &file_stat);

  if (!S_ISREG(file_stat.st_mode))
  {
    throw std::system_error(std::make_error_code(std::errc::not_supported));
  }

  writeFileData(file_path.c_str());
  addFinish();
}

void ArchiveWriter::addFile(const std::string& entry_name,
                            const void* data,
                            unsigned long long size)
{
  addHeader(entry_name, FileType::Regular, size);
  addContent(data, size);
  addFinish();
}

void ArchiveWriter::addDiskPath(const std::string& path, ArchiveMatch* match)
{
  ArchiveReadDisk disk;

  checkError(disk.open(path.c_str()), true);
  if (match)
  {
    disk.checkError(disk.setMatchFilter(*match), true);
  }

  while (true)
  {
    int r = archive_read_next_header2(disk, m_entry);
    if (r == ARCHIVE_EOF)
    {
        break;
    }

    disk.checkError(r, true);

    archive_read_disk_descend(disk);

    r = archive_write_header(m_archive, m_entry);
    checkError(r, true);

    writeFileData(archive_entry_sourcepath(m_entry));
  }
}

void ArchiveWriter::addDirectory(const std::string& directory_name)
{
  addHeader(directory_name, FileType::Directory, 0777);
  addFinish();
}

void ArchiveWriter::close()
{
  if (m_open)
  {
    m_open = false;

    if (m_archive)
    {
      archive_write_close(m_archive);
      archive_write_free(m_archive);
    }

    if (m_entry)
    {
      archive_entry_free(m_entry);
    }
  }
}
<|endoftext|>


<commit_before>#include "ShaderGeneratorCommon.h"
#include <iostream>
#include <sstream>

namespace Effekseer
{
namespace Shader
{

namespace
{
const char* material_lineargamma_functions = R"(

#define FLT_EPSILON 1.192092896e-07

float3 PositivePow(float3 base, float3 power)
{
	return pow(max(abs(base), float3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}

// based on http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
half3 SRGBToLinear(half3 c)
{
	return min(c, c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878));
}

half4 SRGBToLinear(half4 c)
{
	return half4(SRGBToLinear(c.rgb), c.a);
}

half3 LinearToSRGB(half3 c)
{
	return max(1.055 * PositivePow(c, float3(0.416666667,0.416666667,0.416666667)) - 0.055, 0.0);
}

half4 LinearToSRGB(half4 c)
{
	return half4(LinearToSRGB(c.rgb), c.a);
}

half4 ConvertFromSRGBTexture(half4 c)
{
	if (predefined_uniform.z == 0.0f)
	{
		return c;
	}

	return LinearToSRGB(c);
}

half4 ConvertToScreen(half4 c)
{
	if (predefined_uniform.z == 0.0f)
	{
		return c;
	}

	return SRGBToLinear(c);
}

)";

}

static const char* material_gradient_functions = R"(

struct Gradient
{
	int colorCount;
	int alphaCount;
	int reserved1;
	int reserved2;
	float4 colors[8];
	float2 alphas[8];
};

float LinearStep(float s, float e, float v) {
	return clamp((v - s) / (e - s), 0.0, 1.0);
}

float4 SampleGradient(Gradient gradient, float t) {
	float t_clamp = clamp(t, 0.0, 1.0);
	float3 color = gradient.colors[0].xyz;
	for(int i = 1; i < 8; i++) {
		float ratio = LinearStep(gradient.colors[i-1].w, gradient.colors[i].w, t_clamp);
		color = LERP(color, gradient.colors[i].xyz, ratio);
	}

	float alpha = gradient.alphas[0].x;
	for(int i = 1; i < 8; i++) {
		float ratio = LinearStep(gradient.alphas[i-1].y, gradient.alphas[i].y, t_clamp);
		alpha = LERP(alpha, gradient.alphas[i].x, ratio);
	}
	return float4(color, alpha);
}

Gradient GradientParameter(float4 param_v, float4 param_c1, float4 param_c2, float4 param_c3, float4 param_c4, float4 param_c5, float4 param_c6, float4 param_c7, float4 param_c8, float4 param_a1, float4 param_a2, float4 param_a3, float4 param_a4)
{
	Gradient g;
	g.colorCount = int(param_v.x);
	g.alphaCount = int(param_v.y);
	g.reserved1 = int(param_v.z);
	g.reserved2 = int(param_v.w);
	g.colors[0] = param_c1;
	g.colors[1] = param_c2;
	g.colors[2] = param_c3;
	g.colors[3] = param_c4;
	g.colors[4] = param_c5;
	g.colors[5] = param_c6;
	g.colors[6] = param_c7;
	g.colors[7] = param_c8;
	g.alphas[0].xy = param_a1.xy;
	g.alphas[1].xy = param_a1.zw;
	g.alphas[2].xy = param_a2.xy;
	g.alphas[3].xy = param_a2.zw;
	g.alphas[4].xy = param_a3.xy;
	g.alphas[5].xy = param_a3.zw;
	g.alphas[6].xy = param_a4.xy;
	g.alphas[7].xy = param_a4.zw;
	return g;
}

)";

static const char* material_noise_functions = R"(

float Rand2(float2 n) {
	return FRAC(sin(dot(n, float2(12.9898, 78.233))) * 43758.5453123);
}

float SimpleNoise_Block(float2 uv) {
	int2 uvi = int2(floor(uv));
	float2 uvf = FRAC(uv);
	uvf = uvf * uvf * (3.0 - 2.0 * uvf);
	float x0 = LERP(Rand2(float2(uvi + int2(0, 0))), Rand2(float2(uvi + int2(1, 0))), uvf.x);
	float x1 = LERP(Rand2(float2(uvi + int2(0, 1))), Rand2(float2(uvi + int2(1, 1))), uvf.x);
	return LERP(x0, x1, uvf.y);
}

float SimpleNoise(float2 uv, float scale) {
	const int loop = 3;
	float ret = 0.0;
	for(int i = 0; i < loop; i++) {
		float duration = pow(2.0, float(i));
		float intensity = pow(0.5, float(loop-i));
		ret += SimpleNoise_Block(uv * scale / duration) * intensity;
	}

	return ret;
}

)";

std::string GetFixedGradient(const char* name, const Gradient& gradient)
{
	std::stringstream ss;

	ss << "Gradient " << name << "() {" << std::endl;
	ss << "Gradient g;" << std::endl;
	ss << "g.colorCount = " << gradient.ColorCount << ";" << std::endl;
	ss << "g.alphaCount = " << gradient.AlphaCount << ";" << std::endl;
	ss << "g.reserved1 = 0;" << std::endl;
	ss << "g.reserved2 = 0;" << std::endl;

	const auto getColorKey = [](const Effekseer::Gradient& gradient, size_t index)
	{
		if (gradient.ColorCount == 0)
		{
			Effekseer::Gradient::ColorKey key;
			key.Color = {1.0f, 1.0f, 1.0f};
			key.Intensity = 1.0f;
			key.Position = 0.0;
			return key;
		}
		else
		{
			if (gradient.ColorCount <= index)
			{
				auto key = gradient.Colors[gradient.ColorCount - 1];
				key.Position += index;
				return key;
			}

			return gradient.Colors[index];
		}
	};

	const auto getAlphaKey = [](const Effekseer::Gradient& gradient, size_t index)
	{
		if (gradient.AlphaCount == 0)
		{
			Effekseer::Gradient::AlphaKey key;
			key.Alpha = 1.0f;
			key.Position = 0.0;
			return key;
		}
		else
		{
			if (gradient.AlphaCount <= index)
			{
				auto key = gradient.Alphas[gradient.AlphaCount - 1];
				key.Position += index;
				return key;
			}

			return gradient.Alphas[index];
		}
	};

	for (int32_t i = 0; i < gradient.Colors.size(); i++)
	{
		const auto key = getColorKey(gradient, i);
		ss << "g.colors[" << i << "].x = " << key.Color[0] * key.Intensity << ";" << std::endl;
		ss << "g.colors[" << i << "].y = " << key.Color[1] * key.Intensity << ";" << std::endl;
		ss << "g.colors[" << i << "].z = " << key.Color[2] * key.Intensity << ";" << std::endl;
		ss << "g.colors[" << i << "].w = " << key.Position << ";" << std::endl;
	}

	for (int32_t i = 0; i < gradient.Alphas.size(); i++)
	{
		const auto key = getAlphaKey(gradient, i);
		ss << "g.alphas[" << i << "].x = " << key.Alpha << ";" << std::endl;
		ss << "g.alphas[" << i << "].y = " << key.Position << ";" << std::endl;
	}

	ss << "return g; }" << std::endl;

	return ss.str();
}

const char* GetGradientFunctions()
{
	return material_gradient_functions;
}

const char* GetNoiseFunctions()
{
	return material_noise_functions;
}

const char* GetLinearGammaFunctions()
{
	return material_lineargamma_functions;
}

} // namespace Shader
} // namespace Effekseer<commit_msg>Remove floating point suffix for glsl<commit_after>#include "ShaderGeneratorCommon.h"
#include <iostream>
#include <sstream>

namespace Effekseer
{
namespace Shader
{

namespace
{
const char* material_lineargamma_functions = R"(

#define FLT_EPSILON 1.192092896e-07

float3 PositivePow(float3 base, float3 power)
{
	return pow(max(abs(base), float3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}

// based on http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
half3 SRGBToLinear(half3 c)
{
	return min(c, c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878));
}

half4 SRGBToLinear(half4 c)
{
	return half4(SRGBToLinear(c.rgb), c.a);
}

half3 LinearToSRGB(half3 c)
{
	return max(1.055 * PositivePow(c, float3(0.416666667,0.416666667,0.416666667)) - 0.055, 0.0);
}

half4 LinearToSRGB(half4 c)
{
	return half4(LinearToSRGB(c.rgb), c.a);
}

half4 ConvertFromSRGBTexture(half4 c)
{
	if (predefined_uniform.z == 0.0)
	{
		return c;
	}

	return LinearToSRGB(c);
}

half4 ConvertToScreen(half4 c)
{
	if (predefined_uniform.z == 0.0)
	{
		return c;
	}

	return SRGBToLinear(c);
}

)";

}

static const char* material_gradient_functions = R"(

struct Gradient
{
	int colorCount;
	int alphaCount;
	int reserved1;
	int reserved2;
	float4 colors[8];
	float2 alphas[8];
};

float LinearStep(float s, float e, float v) {
	return clamp((v - s) / (e - s), 0.0, 1.0);
}

float4 SampleGradient(Gradient gradient, float t) {
	float t_clamp = clamp(t, 0.0, 1.0);
	float3 color = gradient.colors[0].xyz;
	for(int i = 1; i < 8; i++) {
		float ratio = LinearStep(gradient.colors[i-1].w, gradient.colors[i].w, t_clamp);
		color = LERP(color, gradient.colors[i].xyz, ratio);
	}

	float alpha = gradient.alphas[0].x;
	for(int i = 1; i < 8; i++) {
		float ratio = LinearStep(gradient.alphas[i-1].y, gradient.alphas[i].y, t_clamp);
		alpha = LERP(alpha, gradient.alphas[i].x, ratio);
	}
	return float4(color, alpha);
}

Gradient GradientParameter(float4 param_v, float4 param_c1, float4 param_c2, float4 param_c3, float4 param_c4, float4 param_c5, float4 param_c6, float4 param_c7, float4 param_c8, float4 param_a1, float4 param_a2, float4 param_a3, float4 param_a4)
{
	Gradient g;
	g.colorCount = int(param_v.x);
	g.alphaCount = int(param_v.y);
	g.reserved1 = int(param_v.z);
	g.reserved2 = int(param_v.w);
	g.colors[0] = param_c1;
	g.colors[1] = param_c2;
	g.colors[2] = param_c3;
	g.colors[3] = param_c4;
	g.colors[4] = param_c5;
	g.colors[5] = param_c6;
	g.colors[6] = param_c7;
	g.colors[7] = param_c8;
	g.alphas[0].xy = param_a1.xy;
	g.alphas[1].xy = param_a1.zw;
	g.alphas[2].xy = param_a2.xy;
	g.alphas[3].xy = param_a2.zw;
	g.alphas[4].xy = param_a3.xy;
	g.alphas[5].xy = param_a3.zw;
	g.alphas[6].xy = param_a4.xy;
	g.alphas[7].xy = param_a4.zw;
	return g;
}

)";

static const char* material_noise_functions = R"(

float Rand2(float2 n) {
	return FRAC(sin(dot(n, float2(12.9898, 78.233))) * 43758.5453123);
}

float SimpleNoise_Block(float2 uv) {
	int2 uvi = int2(floor(uv));
	float2 uvf = FRAC(uv);
	uvf = uvf * uvf * (3.0 - 2.0 * uvf);
	float x0 = LERP(Rand2(float2(uvi + int2(0, 0))), Rand2(float2(uvi + int2(1, 0))), uvf.x);
	float x1 = LERP(Rand2(float2(uvi + int2(0, 1))), Rand2(float2(uvi + int2(1, 1))), uvf.x);
	return LERP(x0, x1, uvf.y);
}

float SimpleNoise(float2 uv, float scale) {
	const int loop = 3;
	float ret = 0.0;
	for(int i = 0; i < loop; i++) {
		float duration = pow(2.0, float(i));
		float intensity = pow(0.5, float(loop-i));
		ret += SimpleNoise_Block(uv * scale / duration) * intensity;
	}

	return ret;
}

)";

std::string GetFixedGradient(const char* name, const Gradient& gradient)
{
	std::stringstream ss;

	ss << "Gradient " << name << "() {" << std::endl;
	ss << "Gradient g;" << std::endl;
	ss << "g.colorCount = " << gradient.ColorCount << ";" << std::endl;
	ss << "g.alphaCount = " << gradient.AlphaCount << ";" << std::endl;
	ss << "g.reserved1 = 0;" << std::endl;
	ss << "g.reserved2 = 0;" << std::endl;

	const auto getColorKey = [](const Effekseer::Gradient& gradient, size_t index)
	{
		if (gradient.ColorCount == 0)
		{
			Effekseer::Gradient::ColorKey key;
			key.Color = {1.0f, 1.0f, 1.0f};
			key.Intensity = 1.0f;
			key.Position = 0.0;
			return key;
		}
		else
		{
			if (gradient.ColorCount <= index)
			{
				auto key = gradient.Colors[gradient.ColorCount - 1];
				key.Position += index;
				return key;
			}

			return gradient.Colors[index];
		}
	};

	const auto getAlphaKey = [](const Effekseer::Gradient& gradient, size_t index)
	{
		if (gradient.AlphaCount == 0)
		{
			Effekseer::Gradient::AlphaKey key;
			key.Alpha = 1.0f;
			key.Position = 0.0;
			return key;
		}
		else
		{
			if (gradient.AlphaCount <= index)
			{
				auto key = gradient.Alphas[gradient.AlphaCount - 1];
				key.Position += index;
				return key;
			}

			return gradient.Alphas[index];
		}
	};

	for (int32_t i = 0; i < gradient.Colors.size(); i++)
	{
		const auto key = getColorKey(gradient, i);
		ss << "g.colors[" << i << "].x = " << key.Color[0] * key.Intensity << ";" << std::endl;
		ss << "g.colors[" << i << "].y = " << key.Color[1] * key.Intensity << ";" << std::endl;
		ss << "g.colors[" << i << "].z = " << key.Color[2] * key.Intensity << ";" << std::endl;
		ss << "g.colors[" << i << "].w = " << key.Position << ";" << std::endl;
	}

	for (int32_t i = 0; i < gradient.Alphas.size(); i++)
	{
		const auto key = getAlphaKey(gradient, i);
		ss << "g.alphas[" << i << "].x = " << key.Alpha << ";" << std::endl;
		ss << "g.alphas[" << i << "].y = " << key.Position << ";" << std::endl;
	}

	ss << "return g; }" << std::endl;

	return ss.str();
}

const char* GetGradientFunctions()
{
	return material_gradient_functions;
}

const char* GetNoiseFunctions()
{
	return material_noise_functions;
}

const char* GetLinearGammaFunctions()
{
	return material_lineargamma_functions;
}

} // namespace Shader
} // namespace Effekseer<|endoftext|>


<commit_before>#ifndef HAVE_LLVM
#error "This code needs LLVM enabled"
#endif

#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>

// ignore unused parameters in LLVM libraries
#if (__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/IRReader/IRReader.h>

#if LLVM_VERSION_MAJOR >= 4
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#else
#include <llvm/Bitcode/ReaderWriter.h>
#endif

#if (__clang__)
#pragma clang diagnostic pop // ignore -Wunused-parameter
#else
#pragma GCC diagnostic pop
#endif

#include "dg/analysis/PointsTo/PointerAnalysisFI.h"
#include "dg/analysis/PointsTo/PointerAnalysisFS.h"
#include "dg/analysis/PointsTo/Pointer.h"

#include "dg/llvm/analysis/PointsTo/PointerAnalysis.h"
#include "dg/llvm/analysis/ReachingDefinitions/ReachingDefinitions.h"

#include "TimeMeasure.h"

using namespace dg;
using namespace dg::analysis;
using namespace dg::analysis::rd;
using llvm::errs;

static bool verbose = false;
static const char *entryFunc = "main";

static std::string
getInstName(const llvm::Value *val)
{
    std::ostringstream ostr;
    llvm::raw_os_ostream ro(ostr);

    assert(val);
    ro << *val;
    ro.flush();

    // break the string if it is too long
    return ostr.str();
}

static void printRDNodeType(enum RDNodeType type)
{
#define ELEM(t) case(t): do {printf("%s", #t); }while(0); break;
    switch(type) {
        ELEM(RDNodeType::ALLOC)
        ELEM(RDNodeType::DYN_ALLOC)
        ELEM(RDNodeType::STORE)
        ELEM(RDNodeType::PHI)
        ELEM(RDNodeType::CALL)
        ELEM(RDNodeType::CALL_RETURN)
        ELEM(RDNodeType::FORK)
        ELEM(RDNodeType::JOIN)
        ELEM(RDNodeType::RETURN)
        ELEM(RDNodeType::NOOP)
        ELEM(RDNodeType::NONE)
        default:
            printf("unknown reaching definitions subgraph type");
    };
#undef ELEM
}

static inline void printAddress(RDNode *node, bool dot)
{
    if (dot)
        printf(" [%p]\\n", static_cast<void*>(node));
    else
        printf(" [%p]\n", static_cast<void*>(node));
}

static void
printName(RDNode *node, bool dot)
{
    if (node == rd::UNKNOWN_MEMORY) {
        printf("UNKNOWN MEMORY");
        return;
    }

    const char *name = nullptr;
#if 0
#ifdef DEBUG_ENABLED
    name = node->getName();
#endif
#endif
    std::string nm;
    if (!name) {
        if (!node->getUserData<llvm::Value>()) {
            printRDNodeType(node->getType());
            printAddress(node, dot);
            return;
        }

        nm = getInstName(node->getUserData<llvm::Value>());
        name = nm.c_str();
    }

    // escape the " character
    for (int i = 0; name[i] != '\0'; ++i) {
        // crop long names
        if (i >= 70) {
            printf(" ...");
            break;
        }

        if (name[i] == '"')
            putchar('\\');

        putchar(name[i]);
    }
}

/*
static void
dumpMap(RDNode *node, bool dot = false)
{
    RDMap& map = node->getReachingDefinitions();
    for (const auto& it : map) {
        for (RDNode *site : it.second) {
            printName(it.first.target, dot);
            // don't print offsets with unknown memory
            if (it.first.target == rd::UNKNOWN_MEMORY) {
                printf(" => ");
            } else {
                if (it.first.offset.isUnknown())
                    printf(" | UNKNOWN | => ");
                else if (it.first.len.isUnknown())
                    printf(" | %lu - UNKNOWN | => ", *it.first.offset);
                else
                    printf(" | %lu - %lu | => ", *it.first.offset,
                           *it.first.offset + *it.first.len - 1);
            }

            printName(site, dot);
            if (dot)
                printf("\\n");
            else
                putchar('\n');
        }
    }
}
*/
static void
dumpDDIMap(RDBBlock *block, bool dot = false)
{
    auto& map = block->definitions;
    for (const auto& it : map) {
       printName(it.first, dot);
       for (auto& it2 : it.second) {
           printf("  [%lu - %lu] => \n",
                  *it2.first.start, *it2.first.end);
           for (auto where : it2.second) {
               printf("    ");
               printName(where, dot);
           }
       }

       if (dot)
           printf("\\n");
       else
           putchar('\n');
    }
}

static void
dumpDefSites(const std::set<DefSite>& defs, const char *kind, bool dot = false)
{
    printf("-------------\\n");
    for (const DefSite& def : defs) {
        printf("%s: ", kind);
        printName(def.target, dot);
            if (def.offset.isUnknown())
                printf(" [ UNKNOWN ]");
            else
                printf(" [ %lu - %lu ]", *def.offset,
                       *def.offset + *def.len - 1);

            if (dot)
                printf("\\n");
            else
                putchar('\n');
    }
}

static void
dumpDefines(RDNode *node, bool dot = false)
{
    if (!node->getDefines().empty())
        dumpDefSites(node->getDefines(), "DEF", dot);
}

static void
dumpOverwrites(RDNode *node, bool dot = false)
{
    if (!node->getOverwrites().empty())
        dumpDefSites(node->getOverwrites(), "DEF strong", dot);
}

static void
dumpUses(RDNode *node, bool dot = false)
{
    if (!node->getUses().empty())
        dumpDefSites(node->getUses(), "USE", dot);
}

static void
dumpRDNode(RDNode *n)
{
    printf("NODE: ");
    printName(n, false);
    if (n->getSize() > 0)
        printf(" [size: %lu]", n->getSize());
    putchar('\n');
    //dumpMap(n);
    printf("---\n");
}

static void nodeToDot(RDNode *node) {
    printf("\tNODE%p [label=\"%lu ", static_cast<void*>(node), node->getID());
    printName(node, true);
    if (node->getSize() > 0) {
        printf("\\n[size: %lu]\\n", node->getSize());
        printf("\\n-------------\\n");
    }

    if (verbose) {
        printf("\\nblock: %p\\n", node->getBBlock());
        printf("\\n-------------\\n");

        dumpDefines(node, true);
        dumpOverwrites(node, true);
        dumpUses(node, true);
        printf("\\n-------------\\n");
    }

    //dumpMap(node, true /* dot */);

    printf("\" shape=box]\n");

}

static void dumpDotOnlyNodes(LLVMReachingDefinitions *RD, bool dump_rd)
{
    auto nodes = RD->getNodes();
    /* dump nodes */
    for(RDNode *node : nodes) {
        nodeToDot(node);
    }
}

static void dumpDotWithBlocks(LLVMReachingDefinitions *RD, bool dump_rd) {

    for (auto I = RD->getGraph()->blocks_begin(),
              E = RD->getGraph()->blocks_end(); I != E; ++I) {
        printf("subgraph cluster_%p {\n", *I);
        /* dump nodes */
        for(RDNode *node : I->getNodes()) {
            nodeToDot(node);
        }

        // dump def-use edges
        for(RDNode *node : I->getNodes()) {
            for (RDNode *def : node->defuse) {
                printf("\tNODE%p->NODE%p [style=dotted]",
                       static_cast<void*>(def), static_cast<void*>(node));
            }
        }
        printf("label=\"\\nblock: %p\\n", *I);
        dumpDDIMap(*I, true);
        printf("\"\nlabelloc=b\n");
        printf("}\n");
    }

    /* dump block edges
    for (auto I = RD->getGraph()->blocks_begin(),
              E = RD->getGraph()->blocks_end(); I != E; ++I) {
        for (auto succ : I->getSuccessors())
            printf("\tNODE%p -> NODE%p [penwidth=2]\n",
                   static_cast<void*>(*I),
                   static_cast<void*>(succ));
    }
    */
}

static void
dumpRDdot(LLVMReachingDefinitions *RD, bool dump_rd)
{

    printf("digraph \"Reaching Definitions Subgraph\" {\n");

    if (RD->getGraph()->getBBlocks().empty())
        dumpDotOnlyNodes(RD, dump_rd);
    else
        dumpDotWithBlocks(RD, dump_rd);

    /* dump edges */
    for (RDNode *node : RD->getNodes()) {
        for (RDNode *succ : node->getSuccessors())
            printf("\tNODE%p -> NODE%p [penwidth=2]\n",
                   static_cast<void*>(node),
                   static_cast<void*>(succ));
    }

    printf("}\n");
}

static void
dumpRD(LLVMReachingDefinitions *RD, bool todot, bool dump_rd)
{
    assert(RD);

    if (todot)
        dumpRDdot(RD, dump_rd);
    else {
        for (RDNode *node : RD->getNodes())
            dumpRDNode(node);
    }
}

int main(int argc, char *argv[])
{
    llvm::Module *M;
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;
    bool todot = false;
    bool threads = false;
    bool dump_rd = false;
    const char *module = nullptr;
    Offset::type field_senitivity = Offset::UNKNOWN;
    bool rd_strong_update_unknown = false;
    Offset::type max_set_size = Offset::UNKNOWN;

    enum {
        FLOW_SENSITIVE = 1,
        FLOW_INSENSITIVE,
    } type = FLOW_INSENSITIVE;

    enum class RdaType {
        DENSE,
        SEMISPARSE
    } rda = RdaType::DENSE;

    // parse options
    for (int i = 1; i < argc; ++i) {
        // run given points-to analysis
        if (strcmp(argv[i], "-pta") == 0) {
            if (strcmp(argv[i+1], "fs") == 0)
                type = FLOW_SENSITIVE;
        } else if (strcmp(argv[i], "-rda") == 0) {
            if (strcmp(argv[i+1], "ss") == 0)
                rda = RdaType::SEMISPARSE;
        } else if (strcmp(argv[i], "-pta-field-sensitive") == 0) {
            field_senitivity = static_cast<Offset::type>(atoll(argv[i + 1]));
        } else if (strcmp(argv[i], "-rd-max-set-size") == 0) {
            max_set_size = static_cast<Offset::type>(atoll(argv[i + 1]));
            if (max_set_size == 0) {
                llvm::errs() << "Invalid -rd-max-set-size argument\n";
                abort();
            }
        } else if (strcmp(argv[i], "-rd-strong-update-unknown") == 0) {
            rd_strong_update_unknown = true;
        } else if (strcmp(argv[i], "-dot") == 0) {
            todot = true;
        } else if (strcmp(argv[i], "-threads") == 0) {
            threads = true;
        } else if (strcmp(argv[i], "-v") == 0) {
            verbose = true;
        } else if (strcmp(argv[i], "-dump-rd") == 0) {
            dump_rd = true;
        } else if (strcmp(argv[i], "-entry") == 0) {
            entryFunc = argv[i+1];
        } else {
            module = argv[i];
        }
    }

    if (!module) {
        errs() << "Usage: % IR_module [-pts fs|fi] [-dot] [-v] [output_file]\n";
        return 1;
    }

#if ((LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR <= 5))
    M = llvm::ParseIRFile(module, SMD, context);
#else
    auto _M = llvm::parseIRFile(module, SMD, context);
    // _M is unique pointer, we need to get Module *
    M = _M.get();
#endif

    if (!M) {
        llvm::errs() << "Failed parsing '" << module << "' file:\n";
        SMD.print(argv[0], errs());
        return 1;
    }

    debug::TimeMeasure tm;

    LLVMPointerAnalysis PTA(M, entryFunc, field_senitivity, threads);

    tm.start();

    if (type == FLOW_INSENSITIVE) {
        PTA.run<pta::PointerAnalysisFI>();
    } else {
        PTA.run<pta::PointerAnalysisFS>();
    }

    tm.stop();
    tm.report("INFO: Points-to analysis took");

    LLVMReachingDefinitionsAnalysisOptions opts;
    opts.threads = threads;
    opts.entryFunction = entryFunc;
    opts.strongUpdateUnknown = rd_strong_update_unknown;
    opts.maxSetSize = max_set_size;

    LLVMReachingDefinitions RD(M, &PTA, opts);
    tm.start();
    if (rda == RdaType::SEMISPARSE) {
        RD.run<dg::analysis::rd::SSAReachingDefinitionsAnalysis>();
    } else
        RD.run<dg::analysis::rd::ReachingDefinitionsAnalysis>();
    tm.stop();
    tm.report("INFO: Reaching definitions analysis took");

    dumpRD(&RD, todot, dump_rd);

    return 0;
}
<commit_msg>llvm-rd-dump: improve printing<commit_after>#ifndef HAVE_LLVM
#error "This code needs LLVM enabled"
#endif

#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>

// ignore unused parameters in LLVM libraries
#if (__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/IRReader/IRReader.h>

#if LLVM_VERSION_MAJOR >= 4
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#else
#include <llvm/Bitcode/ReaderWriter.h>
#endif

#if (__clang__)
#pragma clang diagnostic pop // ignore -Wunused-parameter
#else
#pragma GCC diagnostic pop
#endif

#include "dg/analysis/PointsTo/PointerAnalysisFI.h"
#include "dg/analysis/PointsTo/PointerAnalysisFS.h"
#include "dg/analysis/PointsTo/Pointer.h"

#include "dg/llvm/analysis/PointsTo/PointerAnalysis.h"
#include "dg/llvm/analysis/ReachingDefinitions/ReachingDefinitions.h"

#include "TimeMeasure.h"

using namespace dg;
using namespace dg::analysis;
using namespace dg::analysis::rd;
using llvm::errs;

static bool verbose = false;
static const char *entryFunc = "main";

static std::string
getInstName(const llvm::Value *val)
{
    std::ostringstream ostr;
    llvm::raw_os_ostream ro(ostr);

    assert(val);
    ro << *val;
    ro.flush();

    // break the string if it is too long
    return ostr.str();
}

static void printRDNodeType(enum RDNodeType type)
{
#define ELEM(t) case(t): do {printf("%s", #t); }while(0); break;
    switch(type) {
        ELEM(RDNodeType::ALLOC)
        ELEM(RDNodeType::DYN_ALLOC)
        ELEM(RDNodeType::STORE)
        ELEM(RDNodeType::PHI)
        ELEM(RDNodeType::CALL)
        ELEM(RDNodeType::CALL_RETURN)
        ELEM(RDNodeType::FORK)
        ELEM(RDNodeType::JOIN)
        ELEM(RDNodeType::RETURN)
        ELEM(RDNodeType::NOOP)
        ELEM(RDNodeType::NONE)
        default:
            printf("unknown reaching definitions subgraph type");
    };
#undef ELEM
}

static inline void printAddress(RDNode *node, bool dot)
{
    if (dot)
        printf(" [%p]\\n", static_cast<void*>(node));
    else
        printf(" [%p]\n", static_cast<void*>(node));
}

static void
printName(RDNode *node, bool dot)
{
    if (node == rd::UNKNOWN_MEMORY) {
        printf("UNKNOWN MEMORY");
        return;
    }

    const char *name = nullptr;
#if 0
#ifdef DEBUG_ENABLED
    name = node->getName();
#endif
#endif
    std::string nm;
    if (!name) {
        if (!node->getUserData<llvm::Value>()) {
            printRDNodeType(node->getType());
            printAddress(node, dot);
            return;
        }

        nm = getInstName(node->getUserData<llvm::Value>());
        name = nm.c_str();
    }

    // escape the " character
    for (int i = 0; name[i] != '\0'; ++i) {
        // crop long names
        if (i >= 70) {
            printf(" ...");
            break;
        }

        if (name[i] == '"')
            putchar('\\');

        putchar(name[i]);
    }
}

/*
static void
dumpMap(RDNode *node, bool dot = false)
{
    RDMap& map = node->getReachingDefinitions();
    for (const auto& it : map) {
        for (RDNode *site : it.second) {
            printName(it.first.target, dot);
            // don't print offsets with unknown memory
            if (it.first.target == rd::UNKNOWN_MEMORY) {
                printf(" => ");
            } else {
                if (it.first.offset.isUnknown())
                    printf(" | UNKNOWN | => ");
                else if (it.first.len.isUnknown())
                    printf(" | %lu - UNKNOWN | => ", *it.first.offset);
                else
                    printf(" | %lu - %lu | => ", *it.first.offset,
                           *it.first.offset + *it.first.len - 1);
            }

            printName(site, dot);
            if (dot)
                printf("\\n");
            else
                putchar('\n');
        }
    }
}
*/

template <typename T>
static void printInterval(T& I, const char *pref = nullptr,
                          const char *suff = nullptr) {
    if (pref)
        printf("%s", pref);

    if (I.start.isUnknown())
        printf("[? - ");
    else
        printf("[%lu - ", *I.start);

    if (I.end.isUnknown())
        printf("?]");
    else
        printf("%lu]", *I.end);

    if (suff)
        printf("%s", suff);
}

static void
dumpDDIMap(RDBBlock *block, bool dot = false)
{
    auto& map = block->definitions;
    for (const auto& it : map) {
       printf("\\l----  ");
       printName(it.first, dot);
       printf("  ----\\l");
       for (auto& it2 : it.second) {
           printInterval(it2.first, "  ", " => \\l");
           for (auto where : it2.second) {
               printf("      ");
               printName(where, dot);
               if (dot)
                   printf("\\n");
               else
                   putchar('\n');
           }
       }
    }
}

static void
dumpDefSites(const std::set<DefSite>& defs, const char *kind, bool dot = false)
{
    printf("-------------\\n");
    for (const DefSite& def : defs) {
        printf("%s: ", kind);
        printName(def.target, dot);
            if (def.offset.isUnknown())
                printf(" [? - ");
            else
                printf(" [%lu - ", *def.offset);

            if (def.len.isUnknown())
                printf("?]");
            else
                printf("%lu]", *def.offset + (*def.len - 1));

            if (dot)
                printf("\\n");
            else
                putchar('\n');
    }
}

static void
dumpDefines(RDNode *node, bool dot = false)
{
    if (!node->getDefines().empty())
        dumpDefSites(node->getDefines(), "DEF", dot);
}

static void
dumpOverwrites(RDNode *node, bool dot = false)
{
    if (!node->getOverwrites().empty())
        dumpDefSites(node->getOverwrites(), "DEF strong", dot);
}

static void
dumpUses(RDNode *node, bool dot = false)
{
    if (!node->getUses().empty())
        dumpDefSites(node->getUses(), "USE", dot);
}

static void
dumpRDNode(RDNode *n)
{
    printf("NODE: ");
    printName(n, false);
    if (n->getSize() > 0)
        printf(" [size: %lu]", n->getSize());
    putchar('\n');
    //dumpMap(n);
    printf("---\n");
}

static void nodeToDot(RDNode *node) {
    printf("\tNODE%p [label=\"%u ", static_cast<void*>(node), node->getID());
    printName(node, true);
    if (node->getSize() > 0) {
        printf("\\n[size: %lu]\\n", node->getSize());
        printf("\\n-------------\\n");
    }

    if (verbose) {
        printf("\\nblock: %p\\n", node->getBBlock());
        printf("\\n-------------\\n");

        dumpDefines(node, true);
        dumpOverwrites(node, true);
        dumpUses(node, true);
        printf("\\n-------------\\n");
    }

    //dumpMap(node, true /* dot */);

    printf("\" shape=box]\n");

}

static void dumpDotOnlyNodes(LLVMReachingDefinitions *RD)
{
    auto nodes = RD->getNodes();
    /* dump nodes */
    for(RDNode *node : nodes) {
        nodeToDot(node);
    }
}

static void dumpDotWithBlocks(LLVMReachingDefinitions *RD) {

    for (auto I = RD->getGraph()->blocks_begin(),
              E = RD->getGraph()->blocks_end(); I != E; ++I) {
        printf("subgraph cluster_%p {\n", *I);
        /* dump nodes */
        for(RDNode *node : I->getNodes()) {
            nodeToDot(node);
        }

        // dump def-use edges
        for(RDNode *node : I->getNodes()) {
            for (RDNode *def : node->defuse) {
                printf("\tNODE%p->NODE%p [style=dotted]",
                       static_cast<void*>(def), static_cast<void*>(node));
            }
        }
        printf("label=\"\\nblock: %p\\n", *I);
        dumpDDIMap(*I, true);
        printf("\"\nlabelloc=b\n");
        printf("}\n");
    }

    /* dump block edges
    for (auto I = RD->getGraph()->blocks_begin(),
              E = RD->getGraph()->blocks_end(); I != E; ++I) {
        for (auto succ : I->getSuccessors())
            printf("\tNODE%p -> NODE%p [penwidth=2]\n",
                   static_cast<void*>(*I),
                   static_cast<void*>(succ));
    }
    */
}

static void
dumpRDdot(LLVMReachingDefinitions *RD)
{

    printf("digraph \"Reaching Definitions Subgraph\" {\n");

    if (RD->getGraph()->getBBlocks().empty())
        dumpDotOnlyNodes(RD);
    else
        dumpDotWithBlocks(RD);

    /* dump edges */
    for (RDNode *node : RD->getNodes()) {
        for (RDNode *succ : node->getSuccessors())
            printf("\tNODE%p -> NODE%p [penwidth=2]\n",
                   static_cast<void*>(node),
                   static_cast<void*>(succ));
    }

    printf("}\n");
}

static void
dumpRD(LLVMReachingDefinitions *RD, bool todot)
{
    assert(RD);

    if (todot)
        dumpRDdot(RD);
    else {
        for (RDNode *node : RD->getNodes())
            dumpRDNode(node);
    }
}

int main(int argc, char *argv[])
{
    llvm::Module *M;
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;
    bool todot = false;
    bool threads = false;
    const char *module = nullptr;
    Offset::type field_senitivity = Offset::UNKNOWN;
    bool rd_strong_update_unknown = false;
    Offset::type max_set_size = Offset::UNKNOWN;

    enum {
        FLOW_SENSITIVE = 1,
        FLOW_INSENSITIVE,
    } type = FLOW_INSENSITIVE;

    enum class RdaType {
        DENSE,
        SEMISPARSE
    } rda = RdaType::DENSE;

    // parse options
    for (int i = 1; i < argc; ++i) {
        // run given points-to analysis
        if (strcmp(argv[i], "-pta") == 0) {
            if (strcmp(argv[i+1], "fs") == 0)
                type = FLOW_SENSITIVE;
        } else if (strcmp(argv[i], "-rda") == 0) {
            if (strcmp(argv[i+1], "ss") == 0)
                rda = RdaType::SEMISPARSE;
        } else if (strcmp(argv[i], "-pta-field-sensitive") == 0) {
            field_senitivity = static_cast<Offset::type>(atoll(argv[i + 1]));
        } else if (strcmp(argv[i], "-rd-max-set-size") == 0) {
            max_set_size = static_cast<Offset::type>(atoll(argv[i + 1]));
            if (max_set_size == 0) {
                llvm::errs() << "Invalid -rd-max-set-size argument\n";
                abort();
            }
        } else if (strcmp(argv[i], "-rd-strong-update-unknown") == 0) {
            rd_strong_update_unknown = true;
        } else if (strcmp(argv[i], "-dot") == 0) {
            todot = true;
        } else if (strcmp(argv[i], "-threads") == 0) {
            threads = true;
        } else if (strcmp(argv[i], "-v") == 0) {
            verbose = true;
        } else if (strcmp(argv[i], "-entry") == 0) {
            entryFunc = argv[i+1];
        } else {
            module = argv[i];
        }
    }

    if (!module) {
        errs() << "Usage: % IR_module [-pts fs|fi] [-dot] [-v] [output_file]\n";
        return 1;
    }

#if ((LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR <= 5))
    M = llvm::ParseIRFile(module, SMD, context);
#else
    auto _M = llvm::parseIRFile(module, SMD, context);
    // _M is unique pointer, we need to get Module *
    M = _M.get();
#endif

    if (!M) {
        llvm::errs() << "Failed parsing '" << module << "' file:\n";
        SMD.print(argv[0], errs());
        return 1;
    }

    debug::TimeMeasure tm;

    LLVMPointerAnalysis PTA(M, entryFunc, field_senitivity, threads);

    tm.start();

    if (type == FLOW_INSENSITIVE) {
        PTA.run<pta::PointerAnalysisFI>();
    } else {
        PTA.run<pta::PointerAnalysisFS>();
    }

    tm.stop();
    tm.report("INFO: Points-to analysis took");

    LLVMReachingDefinitionsAnalysisOptions opts;
    opts.threads = threads;
    opts.entryFunction = entryFunc;
    opts.strongUpdateUnknown = rd_strong_update_unknown;
    opts.maxSetSize = max_set_size;

    LLVMReachingDefinitions RD(M, &PTA, opts);
    tm.start();
    if (rda == RdaType::SEMISPARSE) {
        RD.run<dg::analysis::rd::SSAReachingDefinitionsAnalysis>();
    } else
        RD.run<dg::analysis::rd::ReachingDefinitionsAnalysis>();
    tm.stop();
    tm.report("INFO: Reaching definitions analysis took");

    dumpRD(&RD, todot);

    return 0;
}
<|endoftext|>


<commit_before>/**
 * @file material.hpp
 */
/* OpenCMISS-Zinc Library
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CMZN_MATERIAL_HPP__
#define CMZN_MATERIAL_HPP__

#include "opencmiss/zinc/material.h"
#include "opencmiss/zinc/shader.h"
#include "opencmiss/zinc/context.hpp"
#include "opencmiss/zinc/field.hpp"

namespace OpenCMISS
{
namespace Zinc
{

class Material
{

protected:
	cmzn_material_id id;

public:

	Material() : id(0)
	{ }

	// takes ownership of C handle, responsibility for destroying it
	explicit Material(cmzn_material_id material_id) :
		id(material_id)
	{ }

	Material(const Material& material) :
		id(cmzn_material_access(material.id))
	{ }

	Material& operator=(const Material& material)
	{
		cmzn_material_id temp_id = cmzn_material_access(material.id);
		if (0 != id)
		{
			cmzn_material_destroy(&id);
		}
		id = temp_id;
		return *this;
	}

	~Material()
	{
		if (0 != id)
		{
			cmzn_material_destroy(&id);
		}
	}

	bool isValid() const
	{
		return (0 != id);
	}

	cmzn_material_id getId() const
	{
		return id;
	}

	enum Attribute
	{
		ATTRIBUTE_INVALID = CMZN_MATERIAL_ATTRIBUTE_INVALID,
		ATTRIBUTE_ALPHA = CMZN_MATERIAL_ATTRIBUTE_ALPHA,
		ATTRIBUTE_AMBIENT = CMZN_MATERIAL_ATTRIBUTE_AMBIENT,
		ATTRIBUTE_DIFFUSE = CMZN_MATERIAL_ATTRIBUTE_DIFFUSE,
		ATTRIBUTE_EMISSION = CMZN_MATERIAL_ATTRIBUTE_EMISSION,
		ATTRIBUTE_SHININESS = CMZN_MATERIAL_ATTRIBUTE_SHININESS,
		ATTRIBUTE_SPECULAR = CMZN_MATERIAL_ATTRIBUTE_SPECULAR
	};

	bool isManaged()
	{
		return cmzn_material_is_managed(id);
	}

	int setManaged(bool value)
	{
		return cmzn_material_set_managed(id, value);
	}

	double getAttributeReal(Attribute attribute)
	{
		return cmzn_material_get_attribute_real(id,
			static_cast<cmzn_material_attribute>(attribute));
	}

	int setAttributeReal(Attribute attribute, double value)
	{
		return cmzn_material_set_attribute_real(id,
			static_cast<cmzn_material_attribute>(attribute), value);
	}

	int getAttributeReal3(Attribute attribute, double *valuesOut3)
	{
		return cmzn_material_get_attribute_real3(id,
			static_cast<cmzn_material_attribute>(attribute), valuesOut3);
	}

	int setAttributeReal3(Attribute attribute, const double *valuesIn3)
	{
		return cmzn_material_set_attribute_real3(id,
			static_cast<cmzn_material_attribute>(attribute), valuesIn3);
	}

	char *getName()
	{
		return cmzn_material_get_name(id);
	}

	int setName(const char *name)
	{
		return cmzn_material_set_name(id, name);
	}

	Field getTextureField(int textureNumber)
	{
		return Field(cmzn_material_get_texture_field(id, textureNumber));
	}

	int setTextureField(int textureNumber, const Field& textureField)
	{
		return cmzn_material_set_texture_field(id, textureNumber, textureField.getId());
	}

	Shaderuniforms getShaderuniforms()
	{
		return Shaderuniforms(cmzn_material_get_shaderuniforms(id));
	}

	int setShaderuniforms(const Shaderuniforms& shaderuniforms)
	{
		return cmzn_material_set_shaderuniforms(id, shaderuniforms.getId());
	}

	Shaderprogram getShaderprogram()
	{
		return Shaderprogram(cmzn_material_get_shaderprogram(id));
	}

	int setShaderprogram(const Shaderprogram& shaderprogram)
	{
		return cmzn_material_set_shaderprogram(id, shaderprogram.getId());
	}

};

inline bool operator==(const Material& a, const Material& b)
{
	return a.getId() == b.getId();
}

class Materialiterator
{
private:

	cmzn_materialiterator_id id;

public:

	Materialiterator() : id(0)
	{ }

	// takes ownership of C handle, responsibility for destroying it
	explicit Materialiterator(cmzn_materialiterator_id iterator_id) :
		id(iterator_id)
	{ }

	Materialiterator(const Materialiterator& materialiterator) :
		id(cmzn_materialiterator_access(materialiterator.id))
	{ }

	Materialiterator& operator=(const Materialiterator& materialiterator)
	{
		cmzn_materialiterator_id temp_id = cmzn_materialiterator_access(materialiterator.id);
		if (0 != id)
		{
			cmzn_materialiterator_destroy(&id);
		}
		id = temp_id;
		return *this;
	}

	~Materialiterator()
	{
		if (0 != id)
		{
			cmzn_materialiterator_destroy(&id);
		}
	}

	bool isValid() const
	{
		return (0 != id);
	}

	Material next()
	{
		return Material(cmzn_materialiterator_next(id));
	}
};

class Materialmodule
{
protected:
	cmzn_materialmodule_id id;

public:

	Materialmodule() : id(0)
	{  }

	// takes ownership of C handle, responsibility for destroying it
	explicit Materialmodule(cmzn_materialmodule_id in_materialmodule_id) :
		id(in_materialmodule_id)
	{  }

	Materialmodule(const Materialmodule& materialModule) :
		id(cmzn_materialmodule_access(materialModule.id))
	{  }

	Materialmodule& operator=(const Materialmodule& materialModule)
	{
		cmzn_materialmodule_id temp_id = cmzn_materialmodule_access(
			materialModule.id);
		if (0 != id)
		{
			cmzn_materialmodule_destroy(&id);
		}
		id = temp_id;
		return *this;
	}

	~Materialmodule()
	{
		if (0 != id)
		{
			cmzn_materialmodule_destroy(&id);
		}
	}

	bool isValid() const
	{
		return (0 != id);
	}

	cmzn_materialmodule_id getId() const
	{
		return id;
	}

	Material createMaterial()
	{
		return Material(cmzn_materialmodule_create_material(id));
	}

	Materialiterator createMaterialiterator()
	{
		return Materialiterator(cmzn_materialmodule_create_materialiterator(id));
	}

	Material findMaterialByName(const char *name)
	{
		return Material(cmzn_materialmodule_find_material_by_name(id, name));
	}

	int beginChange()
	{
		return cmzn_materialmodule_begin_change(id);
	}

	int endChange()
	{
		return cmzn_materialmodule_end_change(id);
	}

	int defineStandardMaterials()
	{
		return cmzn_materialmodule_define_standard_materials(id);
	}

	Material getDefaultMaterial()
	{
		return Material(cmzn_materialmodule_get_default_material(id));
	}

	int setDefaultMaterial(const Material& material)
	{
		return cmzn_materialmodule_set_default_material(id, material.getId());
	}

	Material getDefaultSelectedMaterial()
	{
		return Material(cmzn_materialmodule_get_default_selected_material(id));
	}

	int setDefaultSelectedMaterial(const Material& material)
	{
		return cmzn_materialmodule_set_default_selected_material(id, material.getId());
	}

	Material getDefaultSurfaceMaterial()
	{
		return Material(cmzn_materialmodule_get_default_surface_material(id));
	}

	int setDefaultSurfaceMaterial(const Material& material)
	{
		return cmzn_materialmodule_set_default_surface_material(id, material.getId());
	}
};

inline Materialmodule Context::getMaterialmodule()
{
	return Materialmodule(cmzn_context_get_materialmodule(id));
}

}
}
#endif
<commit_msg>Fix a small error incompilation<commit_after>/**
 * @file material.hpp
 */
/* OpenCMISS-Zinc Library
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CMZN_MATERIAL_HPP__
#define CMZN_MATERIAL_HPP__

#include "opencmiss/zinc/material.h"
#include "opencmiss/zinc/context.hpp"
#include "opencmiss/zinc/field.hpp"
#include "opencmiss/zinc/shader.hpp"

namespace OpenCMISS
{
namespace Zinc
{

class Material
{

protected:
	cmzn_material_id id;

public:

	Material() : id(0)
	{ }

	// takes ownership of C handle, responsibility for destroying it
	explicit Material(cmzn_material_id material_id) :
		id(material_id)
	{ }

	Material(const Material& material) :
		id(cmzn_material_access(material.id))
	{ }

	Material& operator=(const Material& material)
	{
		cmzn_material_id temp_id = cmzn_material_access(material.id);
		if (0 != id)
		{
			cmzn_material_destroy(&id);
		}
		id = temp_id;
		return *this;
	}

	~Material()
	{
		if (0 != id)
		{
			cmzn_material_destroy(&id);
		}
	}

	bool isValid() const
	{
		return (0 != id);
	}

	cmzn_material_id getId() const
	{
		return id;
	}

	enum Attribute
	{
		ATTRIBUTE_INVALID = CMZN_MATERIAL_ATTRIBUTE_INVALID,
		ATTRIBUTE_ALPHA = CMZN_MATERIAL_ATTRIBUTE_ALPHA,
		ATTRIBUTE_AMBIENT = CMZN_MATERIAL_ATTRIBUTE_AMBIENT,
		ATTRIBUTE_DIFFUSE = CMZN_MATERIAL_ATTRIBUTE_DIFFUSE,
		ATTRIBUTE_EMISSION = CMZN_MATERIAL_ATTRIBUTE_EMISSION,
		ATTRIBUTE_SHININESS = CMZN_MATERIAL_ATTRIBUTE_SHININESS,
		ATTRIBUTE_SPECULAR = CMZN_MATERIAL_ATTRIBUTE_SPECULAR
	};

	bool isManaged()
	{
		return cmzn_material_is_managed(id);
	}

	int setManaged(bool value)
	{
		return cmzn_material_set_managed(id, value);
	}

	double getAttributeReal(Attribute attribute)
	{
		return cmzn_material_get_attribute_real(id,
			static_cast<cmzn_material_attribute>(attribute));
	}

	int setAttributeReal(Attribute attribute, double value)
	{
		return cmzn_material_set_attribute_real(id,
			static_cast<cmzn_material_attribute>(attribute), value);
	}

	int getAttributeReal3(Attribute attribute, double *valuesOut3)
	{
		return cmzn_material_get_attribute_real3(id,
			static_cast<cmzn_material_attribute>(attribute), valuesOut3);
	}

	int setAttributeReal3(Attribute attribute, const double *valuesIn3)
	{
		return cmzn_material_set_attribute_real3(id,
			static_cast<cmzn_material_attribute>(attribute), valuesIn3);
	}

	char *getName()
	{
		return cmzn_material_get_name(id);
	}

	int setName(const char *name)
	{
		return cmzn_material_set_name(id, name);
	}

	Field getTextureField(int textureNumber)
	{
		return Field(cmzn_material_get_texture_field(id, textureNumber));
	}

	int setTextureField(int textureNumber, const Field& textureField)
	{
		return cmzn_material_set_texture_field(id, textureNumber, textureField.getId());
	}

	Shaderuniforms getShaderuniforms()
	{
		return Shaderuniforms(cmzn_material_get_shaderuniforms(id));
	}

	int setShaderuniforms(const Shaderuniforms& shaderuniforms)
	{
		return cmzn_material_set_shaderuniforms(id, shaderuniforms.getId());
	}

	Shaderprogram getShaderprogram()
	{
		return Shaderprogram(cmzn_material_get_shaderprogram(id));
	}

	int setShaderprogram(const Shaderprogram& shaderprogram)
	{
		return cmzn_material_set_shaderprogram(id, shaderprogram.getId());
	}

};

inline bool operator==(const Material& a, const Material& b)
{
	return a.getId() == b.getId();
}

class Materialiterator
{
private:

	cmzn_materialiterator_id id;

public:

	Materialiterator() : id(0)
	{ }

	// takes ownership of C handle, responsibility for destroying it
	explicit Materialiterator(cmzn_materialiterator_id iterator_id) :
		id(iterator_id)
	{ }

	Materialiterator(const Materialiterator& materialiterator) :
		id(cmzn_materialiterator_access(materialiterator.id))
	{ }

	Materialiterator& operator=(const Materialiterator& materialiterator)
	{
		cmzn_materialiterator_id temp_id = cmzn_materialiterator_access(materialiterator.id);
		if (0 != id)
		{
			cmzn_materialiterator_destroy(&id);
		}
		id = temp_id;
		return *this;
	}

	~Materialiterator()
	{
		if (0 != id)
		{
			cmzn_materialiterator_destroy(&id);
		}
	}

	bool isValid() const
	{
		return (0 != id);
	}

	Material next()
	{
		return Material(cmzn_materialiterator_next(id));
	}
};

class Materialmodule
{
protected:
	cmzn_materialmodule_id id;

public:

	Materialmodule() : id(0)
	{  }

	// takes ownership of C handle, responsibility for destroying it
	explicit Materialmodule(cmzn_materialmodule_id in_materialmodule_id) :
		id(in_materialmodule_id)
	{  }

	Materialmodule(const Materialmodule& materialModule) :
		id(cmzn_materialmodule_access(materialModule.id))
	{  }

	Materialmodule& operator=(const Materialmodule& materialModule)
	{
		cmzn_materialmodule_id temp_id = cmzn_materialmodule_access(
			materialModule.id);
		if (0 != id)
		{
			cmzn_materialmodule_destroy(&id);
		}
		id = temp_id;
		return *this;
	}

	~Materialmodule()
	{
		if (0 != id)
		{
			cmzn_materialmodule_destroy(&id);
		}
	}

	bool isValid() const
	{
		return (0 != id);
	}

	cmzn_materialmodule_id getId() const
	{
		return id;
	}

	Material createMaterial()
	{
		return Material(cmzn_materialmodule_create_material(id));
	}

	Materialiterator createMaterialiterator()
	{
		return Materialiterator(cmzn_materialmodule_create_materialiterator(id));
	}

	Material findMaterialByName(const char *name)
	{
		return Material(cmzn_materialmodule_find_material_by_name(id, name));
	}

	int beginChange()
	{
		return cmzn_materialmodule_begin_change(id);
	}

	int endChange()
	{
		return cmzn_materialmodule_end_change(id);
	}

	int defineStandardMaterials()
	{
		return cmzn_materialmodule_define_standard_materials(id);
	}

	Material getDefaultMaterial()
	{
		return Material(cmzn_materialmodule_get_default_material(id));
	}

	int setDefaultMaterial(const Material& material)
	{
		return cmzn_materialmodule_set_default_material(id, material.getId());
	}

	Material getDefaultSelectedMaterial()
	{
		return Material(cmzn_materialmodule_get_default_selected_material(id));
	}

	int setDefaultSelectedMaterial(const Material& material)
	{
		return cmzn_materialmodule_set_default_selected_material(id, material.getId());
	}

	Material getDefaultSurfaceMaterial()
	{
		return Material(cmzn_materialmodule_get_default_surface_material(id));
	}

	int setDefaultSurfaceMaterial(const Material& material)
	{
		return cmzn_materialmodule_set_default_surface_material(id, material.getId());
	}
};

inline Materialmodule Context::getMaterialmodule()
{
	return Materialmodule(cmzn_context_get_materialmodule(id));
}

}
}
#endif
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
	@brief  Space Invader クラス
	@author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <iostream>
#include "spinv.hpp"
#include "core/glcore.hpp"
#include "gl_fw/glutils.hpp"
#include "utils/unzip.hpp"
#include "widgets/widget_dialog.hpp"

namespace app {

	//-----------------------------------------------------------------//
	/*!
		@brief  初期化
	*/
	//-----------------------------------------------------------------//
	void spinv::initialize()
	{
		texfb_.initialize(InvadersMachine::ScreenWidth, InvadersMachine::ScreenHeight, 32);

        using namespace gui;
        widget_director& wd = director_.at().widget_director_;

		std::string errstr;
		// sounds.zip 展開
		{
			al::sound& sound = director_.at().sound_;

			static const char* sounds[] = {
    			"Ufo", "Walk1", "Walk2", "Walk3",
				"Walk4", "Shot", "UfoHit", "BaseHit", "InvHit"
			};
			utils::unzip zip;
			std::string sda = "sounds.zip";
			if(zip.open(sda)) {
				if(zip.file_count() == 9) {
					for(int i = 0; i < 9; ++i) {
						std::string fn = sounds[i];
						fn += ".wav";
						int h = zip.find(fn);
						if(h < 0) {
							fn = sounds[i];
							fn += ".Wav";
							h = zip.find(fn);
						}
						if(h >= 0) {
							std::vector<char> wav;
							size_t wn = zip.get_filesize(h);
							wav.reserve(wn);
							zip.get_file(h, &wav[0]);
							utils::file_io fin;
							if(fin.open(&wav[0], wn)) {
								se_id_[i] = sound.load(fin, "wav");
								fin.close();
							}
						} else {
							errstr += "load error: '" + fn + "'";
						}
					}
				} else {
					errstr = "Open sound archive files: '" + sda + "'";
				}
			} else {
				errstr = "Can't open sound archive: '" + sda + "'";
			}
		}

	    // Setup scanlines color
		for(int i = 0; i < InvadersMachine::ScreenHeight; i++) {
			uint32_t c = 0xFFFFFFFF;
        	if( i >=  32 && i <  64 ) c = 0xFFFF0000; // Red
        	if( i >= 184 && i < 240 ) c = 0xFF00FF00; // Green
        	scan_line_color_.push_back(c);
    	}

		fb_.reserve(InvadersMachine::ScreenWidth * InvadersMachine::ScreenHeight);

		// invaders.zip 展開（ROM イメージ）
		std::string romerr;
		{
			utils::unzip zip;
			std::string romzip = "invaders.zip";
			if(zip.open(romzip)) {
				rom_.reserve(0x2000);
				static const char* rom_files[] = {
					"invaders.h", "invaders.g", "invaders.f", "invaders.e"
				};
				for(int i = 0; i < 4; ++i) {
					int h = zip.find(rom_files[i]);
					if(h < 0) {
						if(!romerr.empty()) romerr += ", ";
						romerr += rom_files[i];
					}
					zip.get_file(h, &rom_[i * 0x800]);
				}
				spinv_.setROM(&rom_[0]);
			} else {
				errstr = "Can't open ROM archive: '" + romzip + "'";
			}
		}
		if(!romerr.empty()) {
			errstr = "Can't open ROM file: '" + romerr + "'";
		}

		if(!errstr.empty()) {
			gl::core& core = gl::core::get_instance();
			vtx::spos size(500, 100);
			vtx::spos pos = (core.get_rect().size - size) / 2;
            widget::param wp(vtx::irect(pos, size));
            widget_dialog::param wp_;
            wp_.style_ = widget_dialog::style::OK;
            widget_dialog* d = wd.add_widget<widget_dialog>(wp, wp_);
            d->set_text(errstr);
		} else {
			spinv_.reset(ships_, n_easy_);
		}
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  アップデート
	*/
	//-----------------------------------------------------------------//
	void spinv::update()
	{
   		gl::core& core = gl::core::get_instance();

		const gl::device& dev = core.get_device();

        gui::widget_director& wd = director_.at().widget_director_;

		// 1P
		if(dev.get_positive(gl::device::key::_1)) {
			spinv_.fireEvent(InvadersMachine::KeyOnePlayerDown);
		}
		if(dev.get_negative(gl::device::key::_1)) {
			spinv_.fireEvent(InvadersMachine::KeyOnePlayerUp);
		}
		// 2P
		if(dev.get_positive(gl::device::key::_2)) {
			spinv_.fireEvent(InvadersMachine::KeyTwoPlayersDown);
		}
		if(dev.get_negative(gl::device::key::_2)) {
			spinv_.fireEvent(InvadersMachine::KeyTwoPlayersUp);
		}
		// coin
		if(dev.get_positive(gl::device::key::_3)) {
			spinv_.fireEvent(InvadersMachine::CoinInserted);
		}

		// Left
		if(dev.get_positive(gl::device::key::LEFT)) {
   		 	spinv_.fireEvent( InvadersMachine::KeyLeftDown);
		}
		if(dev.get_positive(gl::device::key::GAME_LEFT)) {
			spinv_.fireEvent( InvadersMachine::KeyLeftDown);
		}
		if(dev.get_negative(gl::device::key::LEFT)) {
			spinv_.fireEvent( InvadersMachine::KeyLeftUp);
		}
		if(dev.get_negative(gl::device::key::GAME_LEFT)) {
			spinv_.fireEvent( InvadersMachine::KeyLeftUp);
		}

		// Right
		if(dev.get_positive(gl::device::key::RIGHT)) {
			spinv_.fireEvent( InvadersMachine::KeyRightDown);
		}
		if(dev.get_positive(gl::device::key::GAME_RIGHT)) {
    		spinv_.fireEvent( InvadersMachine::KeyRightDown);
		}
		if(dev.get_negative(gl::device::key::RIGHT)) {
			spinv_.fireEvent( InvadersMachine::KeyRightUp);
		}
		if(dev.get_negative(gl::device::key::GAME_RIGHT)) {
			spinv_.fireEvent( InvadersMachine::KeyRightUp);
		}

		// Fire
		if(dev.get_positive(gl::device::key::SPACE)) {
			spinv_.fireEvent( InvadersMachine::KeyFireDown);
		}
		if(dev.get_positive(gl::device::key::GAME_0)) {
			spinv_.fireEvent( InvadersMachine::KeyFireDown);
		}
		if(dev.get_negative(gl::device::key::SPACE)) {
			spinv_.fireEvent( InvadersMachine::KeyFireUp);
		}
		if(dev.get_negative(gl::device::key::GAME_0)) {
			spinv_.fireEvent( InvadersMachine::KeyFireUp);
		}

		al::sound& sound = director_.at().sound_;
		if(dev.get_positive(gl::device::key::A)) {
			sound.request(0, se_id_[8]);
		}

		// sound request
		{
			static const unsigned mask[9] = {
				InvadersMachine::SoundUfo,
				InvadersMachine::SoundWalk1,
				InvadersMachine::SoundWalk2,
				InvadersMachine::SoundWalk3,
				InvadersMachine::SoundWalk4,
				InvadersMachine::SoundShot,
				InvadersMachine::SoundUfoHit,
				InvadersMachine::SoundBaseHit,
				InvadersMachine::SoundInvaderHit
			};

			unsigned bits = spinv_.getSounds();

			for(int i = 1; i < 9; ++i) {
				if(se_id_[i] && (bits & mask[i])) {
					sound.request(i, se_id_[i]);
				}
			}
			if(bits & InvadersMachine::SoundUfo) {
				if(!sound.status(0)) {
					sound.request(0, se_id_[0], true);
				}
			} else {
				sound.stop(0);
			}
		}

		spinv_.step();

    	const unsigned char* video = spinv_.getVideo();
		if(video) {
			for(int y = 0; y < InvadersMachine::ScreenHeight; ++y) {
				uint32_t c = scan_line_color_[y];
				for(int x = 0; x < InvadersMachine::ScreenWidth; ++x) {
					if( *video ) {
						fb_[y * InvadersMachine::ScreenWidth + x] = c;
					} else {
						fb_[y * InvadersMachine::ScreenWidth + x] = 0;
					}
					++video;
    	    	}
    		}
		}

		texfb_.rendering(gl::texfb::image::RGBA, (const char*)&fb_[0]);
		texfb_.flip();

//		spinv_.getFrameRate();
		wd.update();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  レンダリング
	*/
	//-----------------------------------------------------------------//
	void spinv::render()
	{
   		gl::core& core = gl::core::get_instance();

		const vtx::spos& siz = core.get_rect().size;

		texfb_.setup_matrix(0, 0, siz.x, siz.y);

		float scale = 1.0f;
		float ofsx = 0.0f;
		float ofsy = 0.0f;
		if(siz.x < siz.y) {
			scale = static_cast<float>(siz.x) / static_cast<float>(InvadersMachine::ScreenWidth);
			float h = static_cast<float>(InvadersMachine::ScreenHeight);
			ofsy = (static_cast<float>(siz.y) - h * scale) * 0.5f;
		} else {
			scale = static_cast<float>(siz.y) / static_cast<float>(InvadersMachine::ScreenHeight);
			float w = static_cast<float>(InvadersMachine::ScreenWidth);
			ofsx = (static_cast<float>(siz.x) - w * scale) * 0.5f;
		}
		gl::glTranslate(ofsx, ofsy);
		gl::glScale(scale);
		texfb_.draw();

        director_.at().widget_director_.service();
        director_.at().widget_director_.render();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  廃棄
	*/
	//-----------------------------------------------------------------//
	void spinv::destroy()
	{
	}
}
<commit_msg>update: cleanup<commit_after>//=====================================================================//
/*! @file
	@brief  Space Invader クラス
	@author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <iostream>
#include "spinv.hpp"
#include "core/glcore.hpp"
#include "gl_fw/glutils.hpp"
#include "utils/unzip.hpp"
#include "widgets/widget_dialog.hpp"

#include "utils/format.hpp"

namespace app {

	//-----------------------------------------------------------------//
	/*!
		@brief  初期化
	*/
	//-----------------------------------------------------------------//
	void spinv::initialize()
	{
		texfb_.initialize(InvadersMachine::ScreenWidth, InvadersMachine::ScreenHeight, 32);

        using namespace gui;
        widget_director& wd = director_.at().widget_director_;

		std::string errstr;
		// sounds.zip 展開
		{
			al::sound& sound = director_.at().sound_;

			static const char* sounds[] = {
    			"Ufo", "Walk1", "Walk2", "Walk3",
				"Walk4", "Shot", "UfoHit", "BaseHit", "InvHit"
			};
			utils::unzip zip;
			std::string sda = "sounds.zip";
			if(zip.open(sda)) {
				if(zip.file_count() == 9) {
					for(int i = 0; i < 9; ++i) {
						std::string fn = sounds[i];
						fn += ".wav";
						int h = zip.find(fn);
						if(h < 0) {
							fn = sounds[i];
							fn += ".Wav";
							h = zip.find(fn);
						}
						if(h >= 0) {
							std::vector<char> wav;
							size_t wn = zip.get_filesize(h);
							wav.reserve(wn);
							zip.get_file(h, &wav[0]);
							utils::file_io fin;
							if(fin.open(&wav[0], wn)) {
								se_id_[i] = sound.load(fin, "wav");
								fin.close();
							}
						} else {
							errstr += "load error: '" + fn + "'";
						}
					}
				} else {
					errstr = "Open sound archive files: '" + sda + "'";
				}
			} else {
				errstr = "Can't open sound archive: '" + sda + "'";
			}
		}

	    // Setup scanlines color
		for(int i = 0; i < InvadersMachine::ScreenHeight; i++) {
			uint32_t c = 0xFFFFFFFF;
        	if( i >=  32 && i <  64 ) c = 0xFFFF0000; // Red
        	if( i >= 184 && i < 240 ) c = 0xFF00FF00; // Green
        	scan_line_color_.push_back(c);
    	}

		fb_.reserve(InvadersMachine::ScreenWidth * InvadersMachine::ScreenHeight);

		// invaders.zip 展開（ROM イメージ）
		std::string romerr;
		{
			utils::unzip zip;
			std::string romzip = "invaders.zip";
			if(zip.open(romzip)) {
				rom_.reserve(0x2000);
				static const char* rom_files[] = {
					"invaders.h", "invaders.g", "invaders.f", "invaders.e"
				};
				for(int i = 0; i < 4; ++i) {
					int h = zip.find(rom_files[i]);
					if(h < 0) {
						if(!romerr.empty()) romerr += ", ";
						romerr += rom_files[i];
					}
					zip.get_file(h, &rom_[i * 0x800]);
				}

				uint32_t sum = 0;
				for(uint32_t i = 0; i < 0x2000; ++i) {
					sum += (uint8_t)rom_[i];
				}
				utils::format("SUM: %08X\n") % sum;

				spinv_.setROM(&rom_[0]);
			} else {
				errstr = "Can't open ROM archive: '" + romzip + "'";
			}
		}
		if(!romerr.empty()) {
			errstr = "Can't open ROM file: '" + romerr + "'";
		}

		if(!errstr.empty()) {
			gl::core& core = gl::core::get_instance();
			vtx::spos size(500, 100);
			vtx::spos pos = (core.get_rect().size - size) / 2;
            widget::param wp(vtx::irect(pos, size));
            widget_dialog::param wp_;
            wp_.style_ = widget_dialog::style::OK;
            widget_dialog* d = wd.add_widget<widget_dialog>(wp, wp_);
            d->set_text(errstr);
		} else {
			spinv_.reset(ships_, n_easy_);
		}
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  アップデート
	*/
	//-----------------------------------------------------------------//
	void spinv::update()
	{
   		gl::core& core = gl::core::get_instance();

		const gl::device& dev = core.get_device();

        gui::widget_director& wd = director_.at().widget_director_;

		// 1P
		if(dev.get_positive(gl::device::key::_1)) {
			spinv_.fireEvent(InvadersMachine::KeyOnePlayerDown);
		}
		if(dev.get_negative(gl::device::key::_1)) {
			spinv_.fireEvent(InvadersMachine::KeyOnePlayerUp);
		}
		// 2P
		if(dev.get_positive(gl::device::key::_2)) {
			spinv_.fireEvent(InvadersMachine::KeyTwoPlayersDown);
		}
		if(dev.get_negative(gl::device::key::_2)) {
			spinv_.fireEvent(InvadersMachine::KeyTwoPlayersUp);
		}
		// coin
		if(dev.get_positive(gl::device::key::_3)) {
			spinv_.fireEvent(InvadersMachine::CoinInserted);
		}

		// Left
		if(dev.get_positive(gl::device::key::LEFT)) {
   		 	spinv_.fireEvent( InvadersMachine::KeyLeftDown);
		}
		if(dev.get_positive(gl::device::key::GAME_LEFT)) {
			spinv_.fireEvent( InvadersMachine::KeyLeftDown);
		}
		if(dev.get_negative(gl::device::key::LEFT)) {
			spinv_.fireEvent( InvadersMachine::KeyLeftUp);
		}
		if(dev.get_negative(gl::device::key::GAME_LEFT)) {
			spinv_.fireEvent( InvadersMachine::KeyLeftUp);
		}

		// Right
		if(dev.get_positive(gl::device::key::RIGHT)) {
			spinv_.fireEvent( InvadersMachine::KeyRightDown);
		}
		if(dev.get_positive(gl::device::key::GAME_RIGHT)) {
    		spinv_.fireEvent( InvadersMachine::KeyRightDown);
		}
		if(dev.get_negative(gl::device::key::RIGHT)) {
			spinv_.fireEvent( InvadersMachine::KeyRightUp);
		}
		if(dev.get_negative(gl::device::key::GAME_RIGHT)) {
			spinv_.fireEvent( InvadersMachine::KeyRightUp);
		}

		// Fire
		if(dev.get_positive(gl::device::key::SPACE)) {
			spinv_.fireEvent( InvadersMachine::KeyFireDown);
		}
		if(dev.get_positive(gl::device::key::GAME_0)) {
			spinv_.fireEvent( InvadersMachine::KeyFireDown);
		}
		if(dev.get_negative(gl::device::key::SPACE)) {
			spinv_.fireEvent( InvadersMachine::KeyFireUp);
		}
		if(dev.get_negative(gl::device::key::GAME_0)) {
			spinv_.fireEvent( InvadersMachine::KeyFireUp);
		}

		al::sound& sound = director_.at().sound_;
		if(dev.get_positive(gl::device::key::A)) {
			sound.request(0, se_id_[8]);
		}

		// sound request
		{
			static const unsigned mask[9] = {
				InvadersMachine::SoundUfo,
				InvadersMachine::SoundWalk1,
				InvadersMachine::SoundWalk2,
				InvadersMachine::SoundWalk3,
				InvadersMachine::SoundWalk4,
				InvadersMachine::SoundShot,
				InvadersMachine::SoundUfoHit,
				InvadersMachine::SoundBaseHit,
				InvadersMachine::SoundInvaderHit
			};

			unsigned bits = spinv_.getSounds();

			for(int i = 1; i < 9; ++i) {
				if(se_id_[i] && (bits & mask[i])) {
					sound.request(i, se_id_[i]);
				}
			}
			if(bits & InvadersMachine::SoundUfo) {
				if(!sound.status(0)) {
					sound.request(0, se_id_[0], true);
				}
			} else {
				sound.stop(0);
			}
		}

		spinv_.step();

    	const unsigned char* video = spinv_.getVideo();
		if(video) {
			for(int y = 0; y < InvadersMachine::ScreenHeight; ++y) {
				uint32_t c = scan_line_color_[y];
				for(int x = 0; x < InvadersMachine::ScreenWidth; ++x) {
					if( *video ) {
						fb_[y * InvadersMachine::ScreenWidth + x] = c;
					} else {
						fb_[y * InvadersMachine::ScreenWidth + x] = 0;
					}
					++video;
    	    	}
    		}
		}

		texfb_.rendering(gl::texfb::image::RGBA, (const char*)&fb_[0]);
		texfb_.flip();

//		spinv_.getFrameRate();
		wd.update();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  レンダリング
	*/
	//-----------------------------------------------------------------//
	void spinv::render()
	{
   		gl::core& core = gl::core::get_instance();

		const vtx::spos& siz = core.get_rect().size;

		texfb_.setup_matrix(0, 0, siz.x, siz.y);

		float scale = 1.0f;
		float ofsx = 0.0f;
		float ofsy = 0.0f;
		if(siz.x < siz.y) {
			scale = static_cast<float>(siz.x) / static_cast<float>(InvadersMachine::ScreenWidth);
			float h = static_cast<float>(InvadersMachine::ScreenHeight);
			ofsy = (static_cast<float>(siz.y) - h * scale) * 0.5f;
		} else {
			scale = static_cast<float>(siz.y) / static_cast<float>(InvadersMachine::ScreenHeight);
			float w = static_cast<float>(InvadersMachine::ScreenWidth);
			ofsx = (static_cast<float>(siz.x) - w * scale) * 0.5f;
		}
		gl::glTranslate(ofsx, ofsy);
		gl::glScale(scale);
		texfb_.draw();

        director_.at().widget_director_.service();
        director_.at().widget_director_.render();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  廃棄
	*/
	//-----------------------------------------------------------------//
	void spinv::destroy()
	{
	}
}
<|endoftext|>


<commit_before>#include <cmath>

#include <cstdint>
#include <vector>

#include "depthai-shared/disparity_luts.hpp"

float calculateDisparityToDepthMM(
    unsigned disparity,
    unsigned width,
    float fov,
    float base_line_dist
)
{
    if (disparity == 0)
    {
        return -1.f;
    }
    else
    {
        const float  pi             = std::acos(-1);
        float        focal_length   = width / (2.f * std::tan(fov / 2 / 180.f * pi));
        float z_m = (focal_length * base_line_dist / disparity);
        return z_m * 1000.f;
    }
}

std::vector<uint16_t> generateLUTDisparityToDepthMM(
    unsigned width,
    float fov,
    float base_line_dist
)
{
    std::vector<uint16_t> result(256, 0);

    const float  pi             = std::acos(-1);
    float        focal_length   = width / (2.f * std::tan(fov / 2 / 180.f * pi));

    for (int i = 0; i < DISPARITY_SIZE; ++i)
    {
        float z_m = (focal_length * base_line_dist / i);
        result[i] = std::min(65535.f, z_m * 1000.f); // m -> mm
    }

    return result;
}
<commit_msg>Added algorithm header<commit_after>#include <cmath>
#include <algorithm>
#include <cstdint>
#include <vector>

#include "depthai-shared/disparity_luts.hpp"

float calculateDisparityToDepthMM(
    unsigned disparity,
    unsigned width,
    float fov,
    float base_line_dist
)
{
    if (disparity == 0)
    {
        return -1.f;
    }
    else
    {
        const float  pi             = std::acos(-1);
        float        focal_length   = width / (2.f * std::tan(fov / 2 / 180.f * pi));
        float z_m = (focal_length * base_line_dist / disparity);
        return z_m * 1000.f;
    }
}

std::vector<uint16_t> generateLUTDisparityToDepthMM(
    unsigned width,
    float fov,
    float base_line_dist
)
{
    std::vector<uint16_t> result(256, 0);

    const float  pi             = std::acos(-1);
    float        focal_length   = width / (2.f * std::tan(fov / 2 / 180.f * pi));

    for (int i = 0; i < DISPARITY_SIZE; ++i)
    {
        float z_m = (focal_length * base_line_dist / i);
        result[i] = std::min(65535.f, z_m * 1000.f); // m -> mm
    }

    return result;
}
<|endoftext|>