<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#define MMUL_FUNCTOR( name, ...)                                \
struct name {                                                   \
    template<typename A, typename B, typename C>                \
    static void apply(A&& a, B&& b, C& c){                      \
        __VA_ARGS__;                                            \
    }                                                           \
};

MMUL_FUNCTOR( default_mmul, c = etl::mul(a, b) )
MMUL_FUNCTOR( lazy_mmul, c = etl::lazy_mul(a, b) )
MMUL_FUNCTOR( strassen_mmul, c = etl::strassen_mul(a, b) )
MMUL_FUNCTOR( std_mmul, etl::impl::standard::mm_mul(a, b, c) )
MMUL_FUNCTOR( eblas_mmul_float, etl::impl::eblas::fast_sgemm(a, b, c) )
MMUL_FUNCTOR( eblas_mmul_double, etl::impl::eblas::fast_dgemm(a, b, c) )

#define MMUL_TEST_CASE_SECTION_DEFAULT   MMUL_TEST_CASE_SECTIONS( default_mmul, default_mmul )
#define MMUL_TEST_CASE_SECTION_LAZY      MMUL_TEST_CASE_SECTIONS( lazy_mmul, lazy_mmul )
#define MMUL_TEST_CASE_SECTION_STD       MMUL_TEST_CASE_SECTIONS( std_mmul, std_mmul )
#define MMUL_TEST_CASE_SECTION_STRASSEN  MMUL_TEST_CASE_SECTIONS( strassen_mmul, strassen_mmul )
#define MMUL_TEST_CASE_SECTION_EBLAS     MMUL_TEST_CASE_SECTIONS( eblas_mmul_float, eblas_mmul_double )

#ifdef ETL_BLAS_MODE
MMUL_FUNCTOR( blas_mmul_float, etl::impl::blas::sgemm(a, b, c) )
MMUL_FUNCTOR( blas_mmul_double, etl::impl::blas::dgemm(a, b, c) )
#define MMUL_TEST_CASE_SECTION_BLAS  MMUL_TEST_CASE_SECTIONS( blas_mmul_float, blas_mmul_double )
#else
#define MMUL_TEST_CASE_SECTION_BLAS
#endif

#define MMUL_TEST_CASE_DECL( name, description ) \
    template<typename T, typename Impl> \
    static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_TE____T_E_S_T____ )(); \
    TEST_CASE( name, description )

#define MMUL_TEST_CASE_SECTION( Tn, Impln) \
        SECTION( #Tn #Impln ) \
        { \
            INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_TE____T_E_S_T____ )<Tn, Impln>(); \
        }

#define MMUL_TEST_CASE_DEFN \
    template<typename T, typename Impl> \
    static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_TE____T_E_S_T____ )()

#define MMUL_TEST_CASE_SECTIONS( S1, S2 ) \
    MMUL_TEST_CASE_SECTION( float, S1 ) \
    MMUL_TEST_CASE_SECTION( double, S2 )

#define MMUL_TEST_CASE( name, description ) \
    MMUL_TEST_CASE_DECL( name, description ) \
    { \
        MMUL_TEST_CASE_SECTION_DEFAULT \
        MMUL_TEST_CASE_SECTION_STD \
        MMUL_TEST_CASE_SECTION_LAZY \
        MMUL_TEST_CASE_SECTION_STRASSEN \
        MMUL_TEST_CASE_SECTION_BLAS \
        MMUL_TEST_CASE_SECTION_EBLAS \
    } \
    MMUL_TEST_CASE_DEFN
<commit_msg>Fix include + section name<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "etl/etl.hpp"

#define MMUL_FUNCTOR( name, ...)                                \
struct name {                                                   \
    template<typename A, typename B, typename C>                \
    static void apply(A&& a, B&& b, C& c){                      \
        __VA_ARGS__;                                            \
    }                                                           \
};

MMUL_FUNCTOR( default_mmul, c = etl::mul(a, b) )
MMUL_FUNCTOR( lazy_mmul, c = etl::lazy_mul(a, b) )
MMUL_FUNCTOR( strassen_mmul, c = etl::strassen_mul(a, b) )
MMUL_FUNCTOR( std_mmul, etl::impl::standard::mm_mul(a, b, c) )
MMUL_FUNCTOR( eblas_mmul_float, etl::impl::eblas::fast_sgemm(a, b, c) )
MMUL_FUNCTOR( eblas_mmul_double, etl::impl::eblas::fast_dgemm(a, b, c) )

#define MMUL_TEST_CASE_SECTION_DEFAULT   MMUL_TEST_CASE_SECTIONS( default_mmul, default_mmul )
#define MMUL_TEST_CASE_SECTION_LAZY      MMUL_TEST_CASE_SECTIONS( lazy_mmul, lazy_mmul )
#define MMUL_TEST_CASE_SECTION_STD       MMUL_TEST_CASE_SECTIONS( std_mmul, std_mmul )
#define MMUL_TEST_CASE_SECTION_STRASSEN  MMUL_TEST_CASE_SECTIONS( strassen_mmul, strassen_mmul )
#define MMUL_TEST_CASE_SECTION_EBLAS     MMUL_TEST_CASE_SECTIONS( eblas_mmul_float, eblas_mmul_double )

#ifdef ETL_BLAS_MODE
MMUL_FUNCTOR( blas_mmul_float, etl::impl::blas::sgemm(a, b, c) )
MMUL_FUNCTOR( blas_mmul_double, etl::impl::blas::dgemm(a, b, c) )
#define MMUL_TEST_CASE_SECTION_BLAS  MMUL_TEST_CASE_SECTIONS( blas_mmul_float, blas_mmul_double )
#else
#define MMUL_TEST_CASE_SECTION_BLAS
#endif

#define MMUL_TEST_CASE_DECL( name, description ) \
    template<typename T, typename Impl> \
    static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_TE____T_E_S_T____ )(); \
    TEST_CASE( name, description )

#define MMUL_TEST_CASE_SECTION( Tn, Impln) \
        SECTION( #Tn "_" #Impln ) \
        { \
            INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_TE____T_E_S_T____ )<Tn, Impln>(); \
        }

#define MMUL_TEST_CASE_DEFN \
    template<typename T, typename Impl> \
    static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_TE____T_E_S_T____ )()

#define MMUL_TEST_CASE_SECTIONS( S1, S2 ) \
    MMUL_TEST_CASE_SECTION( float, S1 ) \
    MMUL_TEST_CASE_SECTION( double, S2 )

#define MMUL_TEST_CASE( name, description ) \
    MMUL_TEST_CASE_DECL( name, description ) \
    { \
        MMUL_TEST_CASE_SECTION_DEFAULT \
        MMUL_TEST_CASE_SECTION_STD \
        MMUL_TEST_CASE_SECTION_LAZY \
        MMUL_TEST_CASE_SECTION_STRASSEN \
        MMUL_TEST_CASE_SECTION_BLAS \
        MMUL_TEST_CASE_SECTION_EBLAS \
    } \
    MMUL_TEST_CASE_DEFN
<|endoftext|>


<commit_before>#include "bvs/bvsinfo.h"

std::string BVS::Info::getFPS() const
{
	static double avgFPS = 15;

	// apply exponential smoothing with alpha = 0.2
	double duration = lastRoundDuration.count();
	duration = duration > 1000 ? 1000 : duration;
	avgFPS = (1000/duration + 4 * avgFPS)/5;

	std::string fps = std::to_string(avgFPS);
	if (fps.length()>6) fps.resize(fps.length()-5);

	return fps;
}

<commit_msg>info: add infinity check for fps calculation<commit_after>#include "bvs/bvsinfo.h"

#include<limits>

std::string BVS::Info::getFPS() const
{
	static double avgFPS = 15;
	if (avgFPS==std::numeric_limits<double>::infinity()) avgFPS = 15;

	// apply exponential smoothing with alpha = 0.2
	double duration = lastRoundDuration.count();
	duration = duration > 1000 ? 1000 : duration;
	avgFPS = (1000/duration + 4 * avgFPS)/5;

	std::string fps = std::to_string(avgFPS);
	if (fps.length()>6) fps.resize(fps.length()-5);

	return fps;
}

<|endoftext|>


<commit_before>/*
 Test wrappers around POSIX functions.

 Copyright (c) 2012-2014, Victor Zverovich
 All rights reserved.

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

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

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

// Disable bogus MSVC warnings.
#define _CRT_SECURE_NO_WARNINGS

#include "posix-test.h"

#include <errno.h>
#include <fcntl.h>
#include <climits>

#ifdef _WIN32
# include <io.h>
# undef max
# undef ERROR
#endif

#include "gtest-extra.h"

using fmt::BufferedFile;
using fmt::ErrorCode;
using fmt::File;

namespace {
int open_count;
int close_count;
int dup_count;
int dup2_count;
int fdopen_count;
int read_count;
int write_count;
int pipe_count;
int fopen_count;
int fclose_count;
int fileno_count;
std::size_t read_nbyte;
std::size_t write_nbyte;
bool sysconf_error;

enum FStatSimulation { NONE, MAX_SIZE, ERROR } fstat_sim;
}

#define EMULATE_EINTR(func, error_result) \
  if (func##_count != 0) { \
    if (func##_count++ != 3) { \
      errno = EINTR; \
      return error_result; \
    } \
  }

#ifndef _WIN32
int test::open(const char *path, int oflag, int mode) {
  EMULATE_EINTR(open, -1);
  return ::open(path, oflag, mode);
}

static off_t max_file_size() { return std::numeric_limits<off_t>::max(); }

int test::fstat(int fd, struct stat *buf) {
  int result = ::fstat(fd, buf);
  if (fstat_sim == MAX_SIZE)
    buf->st_size = max_file_size();
  return result;
}

long test::sysconf(int name) {
  long result = ::sysconf(name);
  if (!sysconf_error)
    return result;
  // Simulate an error.
  errno = EINVAL;
  return -1;
}
#else
errno_t test::sopen_s(
    int* pfh, const char *filename, int oflag, int shflag, int pmode) {
  EMULATE_EINTR(open, EINTR);
  return _sopen_s(pfh, filename, oflag, shflag, pmode);
}

static LONGLONG max_file_size() { return std::numeric_limits<LONGLONG>::max(); }

DWORD test::GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
  if (fstat_sim == ERROR) {
    SetLastError(ERROR_ACCESS_DENIED);
    return FALSE;
  }
  if (fstat_sim == MAX_SIZE) {
    DWORD max = std::numeric_limits<DWORD>::max();
    *lpFileSizeHigh = max >> 1;
    return max;
  }
  return ::GetFileSize(hFile, lpFileSizeHigh);
}
#endif

int test::close(int fildes) {
  // Close the file first because close shouldn't be retried.
  int result = ::FMT_POSIX(close(fildes));
  EMULATE_EINTR(close, -1);
  return result;
}

int test::dup(int fildes) {
  EMULATE_EINTR(dup, -1);
  return ::FMT_POSIX(dup(fildes));
}

int test::dup2(int fildes, int fildes2) {
  EMULATE_EINTR(dup2, -1);
  return ::FMT_POSIX(dup2(fildes, fildes2));
}

FILE *test::fdopen(int fildes, const char *mode) {
  EMULATE_EINTR(fdopen, 0);
  return ::FMT_POSIX(fdopen(fildes, mode));
}

test::ssize_t test::read(int fildes, void *buf, test::size_t nbyte) {
  read_nbyte = nbyte;
  EMULATE_EINTR(read, -1);
  return ::FMT_POSIX(read(fildes, buf, nbyte));
}

test::ssize_t test::write(int fildes, const void *buf, test::size_t nbyte) {
  write_nbyte = nbyte;
  EMULATE_EINTR(write, -1);
  return ::FMT_POSIX(write(fildes, buf, nbyte));
}

#ifndef _WIN32
int test::pipe(int fildes[2]) {
  EMULATE_EINTR(pipe, -1);
  return ::pipe(fildes);
}
#else
int test::pipe(int *pfds, unsigned psize, int textmode) {
  EMULATE_EINTR(pipe, -1);
  return _pipe(pfds, psize, textmode);
}
#endif

FILE *test::fopen(const char *filename, const char *mode) {
  EMULATE_EINTR(fopen, 0);
  return ::fopen(filename, mode);
}

int test::fclose(FILE *stream) {
  EMULATE_EINTR(fclose, EOF);
  return ::fclose(stream);
}

int test::fileno(FILE *stream) {
  EMULATE_EINTR(fileno, -1);
  return ::FMT_POSIX(fileno(stream));
}

#ifndef _WIN32
# define EXPECT_RETRY(statement, func, message) \
    func##_count = 1; \
    statement; \
    EXPECT_EQ(4, func##_count); \
    func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual) EXPECT_EQ(expected, actual)
#else
# define EXPECT_RETRY(statement, func, message) \
    func##_count = 1; \
    EXPECT_SYSTEM_ERROR(statement, EINTR, message); \
    func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual)
#endif

void write_file(fmt::StringRef filename, fmt::StringRef content) {
  fmt::BufferedFile f(filename, "w");
  f.print("{}", content);
}

TEST(UtilTest, StaticAssert) {
  FMT_STATIC_ASSERT(true, "success");
  // Static assertion failure is tested in compile-test because it causes
  // a compile-time error.
}

TEST(UtilTest, GetPageSize) {
#ifdef _WIN32
  SYSTEM_INFO si = {};
  GetSystemInfo(&si);
  EXPECT_EQ(si.dwPageSize, fmt::getpagesize());
#else
  EXPECT_EQ(sysconf(_SC_PAGESIZE), fmt::getpagesize());
  sysconf_error = true;
  EXPECT_SYSTEM_ERROR(
      fmt::getpagesize(), EINVAL, "cannot get memory page size");
  sysconf_error = false;
#endif
}

TEST(FileTest, OpenRetry) {
  write_file("test", "there must be something here");
  File *f = 0;
  EXPECT_RETRY(f = new File("test", File::RDONLY),
               open, "cannot open file test");
#ifndef _WIN32
  char c = 0;
  f->read(&c, 1);
#endif
  delete f;
}

TEST(FileTest, CloseNoRetryInDtor) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  File *f = new File(std::move(read_end));
  int saved_close_count = 0;
  EXPECT_WRITE(stderr, {
    close_count = 1;
    delete f;
    saved_close_count = close_count;
    close_count = 0;
  }, format_system_error(EINTR, "cannot close file") + "\n");
  EXPECT_EQ(2, saved_close_count);
}

TEST(FileTest, CloseNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  close_count = 1;
  EXPECT_SYSTEM_ERROR(read_end.close(), EINTR, "cannot close file");
  EXPECT_EQ(2, close_count);
  close_count = 0;
}

TEST(FileTest, Size) {
  std::string content = "top secret, destroy before reading";
  write_file("test", content);
  File f("test", File::RDONLY);
  EXPECT_GE(f.size(), 0);
  fmt::ULongLong file_size = f.size();
  EXPECT_EQ(content.size(), file_size);
#ifdef _WIN32
  fmt::MemoryWriter message;
  fmt::internal::format_windows_error(
      message, ERROR_ACCESS_DENIED, "cannot get file size");
  fstat_sim = ERROR;
  EXPECT_THROW_MSG(f.size(), fmt::WindowsError, message.str());
  fstat_sim = NONE;
#else
  f.close();
  EXPECT_SYSTEM_ERROR(f.size(), EBADF, "cannot get file attributes");
#endif
}

TEST(FileTest, MaxSize) {
  write_file("test", "");
  File f("test", File::RDONLY);
  fstat_sim = MAX_SIZE;
  EXPECT_GE(f.size(), 0);
  EXPECT_EQ(max_file_size(), f.size());
  fstat_sim = NONE;
}

TEST(FileTest, ReadRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  enum { SIZE = 4 };
  write_end.write("test", SIZE);
  write_end.close();
  char buffer[SIZE];
  std::streamsize count = 0;
  EXPECT_RETRY(count = read_end.read(buffer, SIZE),
      read, "cannot read from file");
  EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
}

TEST(FileTest, WriteRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  enum { SIZE = 4 };
  std::streamsize count = 0;
  EXPECT_RETRY(count = write_end.write("test", SIZE),
      write, "cannot write to file");
  write_end.close();
#ifndef _WIN32
  EXPECT_EQ(static_cast<std::streamsize>(SIZE), count);
  char buffer[SIZE + 1];
  read_end.read(buffer, SIZE);
  buffer[SIZE] = '\0';
  EXPECT_STREQ("test", buffer);
#endif
}

#ifdef _WIN32
TEST(FileTest, ConvertReadCount) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  char c;
  std::size_t size = UINT_MAX;
  if (sizeof(unsigned) != sizeof(std::size_t))
    ++size;
  read_count = 1;
  read_nbyte = 0;
  EXPECT_THROW(read_end.read(&c, size), fmt::SystemError);
  read_count = 0;
  EXPECT_EQ(UINT_MAX, read_nbyte);
}

TEST(FileTest, ConvertWriteCount) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  char c;
  std::size_t size = UINT_MAX;
  if (sizeof(unsigned) != sizeof(std::size_t))
    ++size;
  write_count = 1;
  write_nbyte = 0;
  EXPECT_THROW(write_end.write(&c, size), fmt::SystemError);
  write_count = 0;
  EXPECT_EQ(UINT_MAX, write_nbyte);
}
#endif

TEST(FileTest, DupNoRetry) {
  int stdout_fd = FMT_POSIX(fileno(stdout));
  dup_count = 1;
  EXPECT_SYSTEM_ERROR(File::dup(stdout_fd), EINTR,
      fmt::format("cannot duplicate file descriptor {}", stdout_fd));
  dup_count = 0;
}

TEST(FileTest, Dup2Retry) {
  int stdout_fd = FMT_POSIX(fileno(stdout));
  File f1 = File::dup(stdout_fd), f2 = File::dup(stdout_fd);
  EXPECT_RETRY(f1.dup2(f2.descriptor()), dup2,
      fmt::format("cannot duplicate file descriptor {} to {}",
      f1.descriptor(), f2.descriptor()));
}

TEST(FileTest, Dup2NoExceptRetry) {
  int stdout_fd = FMT_POSIX(fileno(stdout));
  File f1 = File::dup(stdout_fd), f2 = File::dup(stdout_fd);
  ErrorCode ec;
  dup2_count = 1;
  f1.dup2(f2.descriptor(), ec);
#ifndef _WIN32
  EXPECT_EQ(4, dup2_count);
#else
  EXPECT_EQ(EINTR, ec.get());
#endif
  dup2_count = 0;
}

TEST(FileTest, PipeNoRetry) {
  File read_end, write_end;
  pipe_count = 1;
  EXPECT_SYSTEM_ERROR(
      File::pipe(read_end, write_end), EINTR, "cannot create pipe");
  pipe_count = 0;
}

TEST(FileTest, FdopenNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  fdopen_count = 1;
  EXPECT_SYSTEM_ERROR(read_end.fdopen("r"),
      EINTR, "cannot associate stream with file descriptor");
  fdopen_count = 0;
}

TEST(BufferedFileTest, OpenRetry) {
  write_file("test", "there must be something here");
  BufferedFile *f = 0;
  EXPECT_RETRY(f = new BufferedFile("test", "r"),
               fopen, "cannot open file test");
#ifndef _WIN32
  char c = 0;
  if (fread(&c, 1, 1, f->get()) < 1)
    throw fmt::SystemError(errno, "fread failed");
#endif
  delete f;
}

TEST(BufferedFileTest, CloseNoRetryInDtor) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  BufferedFile *f = new BufferedFile(read_end.fdopen("r"));
  int saved_fclose_count = 0;
  EXPECT_WRITE(stderr, {
    fclose_count = 1;
    delete f;
    saved_fclose_count = fclose_count;
    fclose_count = 0;
  }, format_system_error(EINTR, "cannot close file") + "\n");
  EXPECT_EQ(2, saved_fclose_count);
}

TEST(BufferedFileTest, CloseNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  BufferedFile f = read_end.fdopen("r");
  fclose_count = 1;
  EXPECT_SYSTEM_ERROR(f.close(), EINTR, "cannot close file");
  EXPECT_EQ(2, fclose_count);
  fclose_count = 0;
}

TEST(BufferedFileTest, FilenoNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  BufferedFile f = read_end.fdopen("r");
  fileno_count = 1;
  EXPECT_SYSTEM_ERROR(f.fileno(), EINTR, "cannot get file descriptor");
  EXPECT_EQ(2, fileno_count);
  fileno_count = 0;
}
<commit_msg>Fix test<commit_after>/*
 Test wrappers around POSIX functions.

 Copyright (c) 2012-2014, Victor Zverovich
 All rights reserved.

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

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

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

// Disable bogus MSVC warnings.
#define _CRT_SECURE_NO_WARNINGS

#include "posix-test.h"

#include <errno.h>
#include <fcntl.h>
#include <climits>

#ifdef _WIN32
# include <io.h>
# undef max
# undef ERROR
#endif

#include "gtest-extra.h"

using fmt::BufferedFile;
using fmt::ErrorCode;
using fmt::File;

namespace {
int open_count;
int close_count;
int dup_count;
int dup2_count;
int fdopen_count;
int read_count;
int write_count;
int pipe_count;
int fopen_count;
int fclose_count;
int fileno_count;
std::size_t read_nbyte;
std::size_t write_nbyte;
bool sysconf_error;

enum FStatSimulation { NONE, MAX_SIZE, ERROR } fstat_sim;
}

#define EMULATE_EINTR(func, error_result) \
  if (func##_count != 0) { \
    if (func##_count++ != 3) { \
      errno = EINTR; \
      return error_result; \
    } \
  }

#ifndef _WIN32
int test::open(const char *path, int oflag, int mode) {
  EMULATE_EINTR(open, -1);
  return ::open(path, oflag, mode);
}

static off_t max_file_size() { return std::numeric_limits<off_t>::max(); }

int test::fstat(int fd, struct stat *buf) {
  int result = ::fstat(fd, buf);
  if (fstat_sim == MAX_SIZE)
    buf->st_size = max_file_size();
  return result;
}

long test::sysconf(int name) {
  long result = ::sysconf(name);
  if (!sysconf_error)
    return result;
  // Simulate an error.
  errno = EINVAL;
  return -1;
}
#else
errno_t test::sopen_s(
    int* pfh, const char *filename, int oflag, int shflag, int pmode) {
  EMULATE_EINTR(open, EINTR);
  return _sopen_s(pfh, filename, oflag, shflag, pmode);
}

static LONGLONG max_file_size() { return std::numeric_limits<LONGLONG>::max(); }

DWORD test::GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
  if (fstat_sim == ERROR) {
    SetLastError(ERROR_ACCESS_DENIED);
    return INVALID_FILE_SIZE;
  }
  if (fstat_sim == MAX_SIZE) {
    DWORD max = std::numeric_limits<DWORD>::max();
    *lpFileSizeHigh = max >> 1;
    return max;
  }
  return ::GetFileSize(hFile, lpFileSizeHigh);
}
#endif

int test::close(int fildes) {
  // Close the file first because close shouldn't be retried.
  int result = ::FMT_POSIX(close(fildes));
  EMULATE_EINTR(close, -1);
  return result;
}

int test::dup(int fildes) {
  EMULATE_EINTR(dup, -1);
  return ::FMT_POSIX(dup(fildes));
}

int test::dup2(int fildes, int fildes2) {
  EMULATE_EINTR(dup2, -1);
  return ::FMT_POSIX(dup2(fildes, fildes2));
}

FILE *test::fdopen(int fildes, const char *mode) {
  EMULATE_EINTR(fdopen, 0);
  return ::FMT_POSIX(fdopen(fildes, mode));
}

test::ssize_t test::read(int fildes, void *buf, test::size_t nbyte) {
  read_nbyte = nbyte;
  EMULATE_EINTR(read, -1);
  return ::FMT_POSIX(read(fildes, buf, nbyte));
}

test::ssize_t test::write(int fildes, const void *buf, test::size_t nbyte) {
  write_nbyte = nbyte;
  EMULATE_EINTR(write, -1);
  return ::FMT_POSIX(write(fildes, buf, nbyte));
}

#ifndef _WIN32
int test::pipe(int fildes[2]) {
  EMULATE_EINTR(pipe, -1);
  return ::pipe(fildes);
}
#else
int test::pipe(int *pfds, unsigned psize, int textmode) {
  EMULATE_EINTR(pipe, -1);
  return _pipe(pfds, psize, textmode);
}
#endif

FILE *test::fopen(const char *filename, const char *mode) {
  EMULATE_EINTR(fopen, 0);
  return ::fopen(filename, mode);
}

int test::fclose(FILE *stream) {
  EMULATE_EINTR(fclose, EOF);
  return ::fclose(stream);
}

int test::fileno(FILE *stream) {
  EMULATE_EINTR(fileno, -1);
  return ::FMT_POSIX(fileno(stream));
}

#ifndef _WIN32
# define EXPECT_RETRY(statement, func, message) \
    func##_count = 1; \
    statement; \
    EXPECT_EQ(4, func##_count); \
    func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual) EXPECT_EQ(expected, actual)
#else
# define EXPECT_RETRY(statement, func, message) \
    func##_count = 1; \
    EXPECT_SYSTEM_ERROR(statement, EINTR, message); \
    func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual)
#endif

void write_file(fmt::StringRef filename, fmt::StringRef content) {
  fmt::BufferedFile f(filename, "w");
  f.print("{}", content);
}

TEST(UtilTest, StaticAssert) {
  FMT_STATIC_ASSERT(true, "success");
  // Static assertion failure is tested in compile-test because it causes
  // a compile-time error.
}

TEST(UtilTest, GetPageSize) {
#ifdef _WIN32
  SYSTEM_INFO si = {};
  GetSystemInfo(&si);
  EXPECT_EQ(si.dwPageSize, fmt::getpagesize());
#else
  EXPECT_EQ(sysconf(_SC_PAGESIZE), fmt::getpagesize());
  sysconf_error = true;
  EXPECT_SYSTEM_ERROR(
      fmt::getpagesize(), EINVAL, "cannot get memory page size");
  sysconf_error = false;
#endif
}

TEST(FileTest, OpenRetry) {
  write_file("test", "there must be something here");
  File *f = 0;
  EXPECT_RETRY(f = new File("test", File::RDONLY),
               open, "cannot open file test");
#ifndef _WIN32
  char c = 0;
  f->read(&c, 1);
#endif
  delete f;
}

TEST(FileTest, CloseNoRetryInDtor) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  File *f = new File(std::move(read_end));
  int saved_close_count = 0;
  EXPECT_WRITE(stderr, {
    close_count = 1;
    delete f;
    saved_close_count = close_count;
    close_count = 0;
  }, format_system_error(EINTR, "cannot close file") + "\n");
  EXPECT_EQ(2, saved_close_count);
}

TEST(FileTest, CloseNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  close_count = 1;
  EXPECT_SYSTEM_ERROR(read_end.close(), EINTR, "cannot close file");
  EXPECT_EQ(2, close_count);
  close_count = 0;
}

TEST(FileTest, Size) {
  std::string content = "top secret, destroy before reading";
  write_file("test", content);
  File f("test", File::RDONLY);
  EXPECT_GE(f.size(), 0);
  fmt::ULongLong file_size = f.size();
  EXPECT_EQ(content.size(), file_size);
#ifdef _WIN32
  fmt::MemoryWriter message;
  fmt::internal::format_windows_error(
      message, ERROR_ACCESS_DENIED, "cannot get file size");
  fstat_sim = ERROR;
  EXPECT_THROW_MSG(f.size(), fmt::WindowsError, message.str());
  fstat_sim = NONE;
#else
  f.close();
  EXPECT_SYSTEM_ERROR(f.size(), EBADF, "cannot get file attributes");
#endif
}

TEST(FileTest, MaxSize) {
  write_file("test", "");
  File f("test", File::RDONLY);
  fstat_sim = MAX_SIZE;
  EXPECT_GE(f.size(), 0);
  EXPECT_EQ(max_file_size(), f.size());
  fstat_sim = NONE;
}

TEST(FileTest, ReadRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  enum { SIZE = 4 };
  write_end.write("test", SIZE);
  write_end.close();
  char buffer[SIZE];
  std::streamsize count = 0;
  EXPECT_RETRY(count = read_end.read(buffer, SIZE),
      read, "cannot read from file");
  EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
}

TEST(FileTest, WriteRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  enum { SIZE = 4 };
  std::streamsize count = 0;
  EXPECT_RETRY(count = write_end.write("test", SIZE),
      write, "cannot write to file");
  write_end.close();
#ifndef _WIN32
  EXPECT_EQ(static_cast<std::streamsize>(SIZE), count);
  char buffer[SIZE + 1];
  read_end.read(buffer, SIZE);
  buffer[SIZE] = '\0';
  EXPECT_STREQ("test", buffer);
#endif
}

#ifdef _WIN32
TEST(FileTest, ConvertReadCount) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  char c;
  std::size_t size = UINT_MAX;
  if (sizeof(unsigned) != sizeof(std::size_t))
    ++size;
  read_count = 1;
  read_nbyte = 0;
  EXPECT_THROW(read_end.read(&c, size), fmt::SystemError);
  read_count = 0;
  EXPECT_EQ(UINT_MAX, read_nbyte);
}

TEST(FileTest, ConvertWriteCount) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  char c;
  std::size_t size = UINT_MAX;
  if (sizeof(unsigned) != sizeof(std::size_t))
    ++size;
  write_count = 1;
  write_nbyte = 0;
  EXPECT_THROW(write_end.write(&c, size), fmt::SystemError);
  write_count = 0;
  EXPECT_EQ(UINT_MAX, write_nbyte);
}
#endif

TEST(FileTest, DupNoRetry) {
  int stdout_fd = FMT_POSIX(fileno(stdout));
  dup_count = 1;
  EXPECT_SYSTEM_ERROR(File::dup(stdout_fd), EINTR,
      fmt::format("cannot duplicate file descriptor {}", stdout_fd));
  dup_count = 0;
}

TEST(FileTest, Dup2Retry) {
  int stdout_fd = FMT_POSIX(fileno(stdout));
  File f1 = File::dup(stdout_fd), f2 = File::dup(stdout_fd);
  EXPECT_RETRY(f1.dup2(f2.descriptor()), dup2,
      fmt::format("cannot duplicate file descriptor {} to {}",
      f1.descriptor(), f2.descriptor()));
}

TEST(FileTest, Dup2NoExceptRetry) {
  int stdout_fd = FMT_POSIX(fileno(stdout));
  File f1 = File::dup(stdout_fd), f2 = File::dup(stdout_fd);
  ErrorCode ec;
  dup2_count = 1;
  f1.dup2(f2.descriptor(), ec);
#ifndef _WIN32
  EXPECT_EQ(4, dup2_count);
#else
  EXPECT_EQ(EINTR, ec.get());
#endif
  dup2_count = 0;
}

TEST(FileTest, PipeNoRetry) {
  File read_end, write_end;
  pipe_count = 1;
  EXPECT_SYSTEM_ERROR(
      File::pipe(read_end, write_end), EINTR, "cannot create pipe");
  pipe_count = 0;
}

TEST(FileTest, FdopenNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  fdopen_count = 1;
  EXPECT_SYSTEM_ERROR(read_end.fdopen("r"),
      EINTR, "cannot associate stream with file descriptor");
  fdopen_count = 0;
}

TEST(BufferedFileTest, OpenRetry) {
  write_file("test", "there must be something here");
  BufferedFile *f = 0;
  EXPECT_RETRY(f = new BufferedFile("test", "r"),
               fopen, "cannot open file test");
#ifndef _WIN32
  char c = 0;
  if (fread(&c, 1, 1, f->get()) < 1)
    throw fmt::SystemError(errno, "fread failed");
#endif
  delete f;
}

TEST(BufferedFileTest, CloseNoRetryInDtor) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  BufferedFile *f = new BufferedFile(read_end.fdopen("r"));
  int saved_fclose_count = 0;
  EXPECT_WRITE(stderr, {
    fclose_count = 1;
    delete f;
    saved_fclose_count = fclose_count;
    fclose_count = 0;
  }, format_system_error(EINTR, "cannot close file") + "\n");
  EXPECT_EQ(2, saved_fclose_count);
}

TEST(BufferedFileTest, CloseNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  BufferedFile f = read_end.fdopen("r");
  fclose_count = 1;
  EXPECT_SYSTEM_ERROR(f.close(), EINTR, "cannot close file");
  EXPECT_EQ(2, fclose_count);
  fclose_count = 0;
}

TEST(BufferedFileTest, FilenoNoRetry) {
  File read_end, write_end;
  File::pipe(read_end, write_end);
  BufferedFile f = read_end.fdopen("r");
  fileno_count = 1;
  EXPECT_SYSTEM_ERROR(f.fileno(), EINTR, "cannot get file descriptor");
  EXPECT_EQ(2, fileno_count);
  fileno_count = 0;
}
<|endoftext|>


<commit_before>#include "model/obj.hpp"

#include <iomanip>
#include <iostream>
#include <ostream>
#include <sstream>
#include <type_traits>

#ifndef OBJ_PATH
#define OBJ_PATH "share/cube.obj"
#endif
#ifndef MTL_PATH
#define MTL_PATH "share/cube.mtl"
#endif

int main(int argc, const char **argv) {
	using namespace Model;
	const char *obj_fname, *mtl_fname;
	if(argc >= 3) {
		mtl_fname = argv[2];
	} else {
		mtl_fname = MTL_PATH;
	}
	if(argc >= 2) {
		obj_fname = argv[1];
	} else {
		obj_fname = OBJ_PATH;
	}
	obj_t obj;
	endl(std::cout << "File: " << obj_fname);
	switch(obj_t::load(obj_fname, obj)) {
		case obj_t::e_err_io:
			std::cout << "Status: I/O Error\n" << std::endl;
			break;
		case obj_t::e_ok:
			std::cout << "Status: OK\n" << std::endl;
			break;
		case obj_t::e_err_unknown:
			std::cout << "Status: Unknown\n" << std::endl;
			break;
		default:
			break;
	}
	int counter = 0, fCounter = 0, iCounter = 0, sCounter = 0;
	for(auto beg = std::begin(obj.types); beg != std::end(obj.types); beg++) {
		int nb = obj.nBools[counter], nf = obj.nFloats[counter],
			ni = obj.nInts[counter], ns = obj.nStrings[counter];
		std::cout << std::setw(4) << counter << ". " << *beg << " ";
		for(int i = 0; i < nb; ++i) {
			std::cout << obj.bools[fCounter++] << " ";
		}
		for(int i = 0; i < nf; ++i) {
			std::cout << obj.floats[fCounter++] << " ";
		}
		for(int i = 0; i < ni; ++i) {
			std::cout << obj.ints[iCounter++] << " ";
		}
		for(int i = 0; i < ns; ++i) {
			std::cout << obj.strings[sCounter++] << " ";
		}
		counter++;
		endl(std::cout);
	}
	/*std::cout << "Contiguous data: " << std::endl;
	endl(std::cout << "Bools:" << obj.bools.size());
	for(auto it : obj.bools) std::cout << it << " ";
	endl(std::cout << "\nFloats:" << obj.floats.size());
	for(auto it : obj.floats) std::cout << it << " ";
	endl(std::cout << "\nIntegers:" << obj.ints.size());
	for(auto it : obj.ints) std::cout << it << " ";
	endl(std::cout << "\nStrings:" << obj.strings.size());
	for(auto it : obj.strings) std::cout << it << " ";
	endl(std::cout);*/

	/*auto f_it = std::begin(obj.floats);
	auto i_it = std::begin(obj.ints);
	auto nf_it = std::begin(obj.nFloats);
	auto ni_it = std::begin(obj.nInts);
	for(auto t_it = std::begin(obj.types);
			t_it != std::end(obj.types); t_it++) {
		bool vmatch = *t_it == e_el_v,
			 vnmatch = *t_it == e_el_vn,
			 f2match = *t_it == e_el_f2;
		if(*nf_it > 0) {
			if(vmatch) {
				std::cout << "\nVertex: ";
			} else if(vnmatch) {
				std::cout << "\nVertex norm: ";
			}
			for(int i = 0, iMax = *nf_it; i < iMax; ++i) {
				if(vmatch || vnmatch) {
					std::cout << *f_it << " ";
				}
				f_it++;
			}
		}
		if(*ni_it > 0) {
			if(f2match) {
				std::cout << "\nFace: ";
			}
			for(int i = 0, iMax = *ni_it; i < iMax; ++i) {
				if(f2match) {
					std::cout << *i_it << " ";
				}
				i_it++;
			}
		}
		nf_it++;
		ni_it++;
	}
	std::cout << "\n\n";*/

	for(int i = 0; i < 7; i++) {
		std::vector<int> begs, ends;
		switch(i) {
			case 0: begs = obj.v_beg; ends = obj.v_end;
				std::cout << "Vertex range: " << std::endl;
				break;
			case 1: begs = obj.vn_beg; ends = obj.vn_end;
				std::cout << "Normal range: " << std::endl;
				break;
			case 2: begs = obj.vp_beg; ends = obj.vp_end;
				std::cout << "Texture range: " << std::endl;
				break;
			case 3: begs = obj.f0_beg; ends = obj.f0_end;
				std::cout << "Face(0) range: " << std::endl;
				break;
			case 4: begs = obj.f1_beg; ends = obj.f1_end;
				std::cout << "Face(1) range: " << std::endl;
				break;
			case 5: begs = obj.f2_beg; ends = obj.f2_end;
				std::cout << "Face(2) range: " << std::endl;
				break;
			case 6: begs = obj.f3_beg; ends = obj.f3_end;
				std::cout << "Face(3) range: " << std::endl;
				break;
			default: break;
		}
		auto beg_start = std::begin(begs), beg_stop = std::end(begs),
			 end_start = std::begin(ends), end_stop = std::end(ends);
		while(beg_start != beg_stop) {
			std::cout << "{" << *beg_start++ << ", "
				<< *end_start++ << "}" << std::endl;
		}
	}

	material_t mtl;
	std::cout << "\nFile: " << mtl_fname << std::endl;
	switch(mtl.load(mtl_fname, mtl)) {
		case material_t::e_ok: {
			std::cout << "Status: OK" << std::endl;
		} break;
		case material_t::e_err_io: {
			std::cout << "Status: I/O error" << std::endl;
		} break;
		case material_t::e_err_unknown: {
			std::cout << "Status: Unknown" << std::endl;
		} break;
		default: {} break;
	}

	int w = 3, h = 3;
	mesh_t mesh(w, h, [](float u, float v, std::vector<float> &vertices) {
		vertices.emplace_back(u);
		vertices.emplace_back(v);
		vertices.emplace_back(0);
	});

	std::cout << "\nMesh points: ";
	for(auto f : mesh.vertices) {
		std::cout << f << ' ';
	}
	std::cout << "\nMesh faces: ";
	for(auto i : mesh.faces) {
		std::cout << i << ' ';
	}
	endl(std::cout);
}
<commit_msg>Made mesh printout easier to read<commit_after>#include "model/obj.hpp"

#include <iomanip>
#include <iostream>
#include <ostream>
#include <sstream>
#include <type_traits>

#ifndef OBJ_PATH
#define OBJ_PATH "share/cube.obj"
#endif
#ifndef MTL_PATH
#define MTL_PATH "share/cube.mtl"
#endif

int main(int argc, const char **argv) {
	using namespace Model;
	const char *obj_fname, *mtl_fname;
	if(argc >= 3) {
		mtl_fname = argv[2];
	} else {
		mtl_fname = MTL_PATH;
	}
	if(argc >= 2) {
		obj_fname = argv[1];
	} else {
		obj_fname = OBJ_PATH;
	}
	obj_t obj;
	endl(std::cout << "File: " << obj_fname);
	switch(obj_t::load(obj_fname, obj)) {
		case obj_t::e_err_io:
			std::cout << "Status: I/O Error\n" << std::endl;
			break;
		case obj_t::e_ok:
			std::cout << "Status: OK\n" << std::endl;
			break;
		case obj_t::e_err_unknown:
			std::cout << "Status: Unknown\n" << std::endl;
			break;
		default:
			break;
	}
	int counter = 0, fCounter = 0, iCounter = 0, sCounter = 0;
	for(auto beg = std::begin(obj.types); beg != std::end(obj.types); beg++) {
		int nb = obj.nBools[counter], nf = obj.nFloats[counter],
			ni = obj.nInts[counter], ns = obj.nStrings[counter];
		std::cout << std::setw(4) << counter << ". " << *beg << " ";
		for(int i = 0; i < nb; ++i) {
			std::cout << obj.bools[fCounter++] << " ";
		}
		for(int i = 0; i < nf; ++i) {
			std::cout << obj.floats[fCounter++] << " ";
		}
		for(int i = 0; i < ni; ++i) {
			std::cout << obj.ints[iCounter++] << " ";
		}
		for(int i = 0; i < ns; ++i) {
			std::cout << obj.strings[sCounter++] << " ";
		}
		counter++;
		endl(std::cout);
	}
	/*std::cout << "Contiguous data: " << std::endl;
	endl(std::cout << "Bools:" << obj.bools.size());
	for(auto it : obj.bools) std::cout << it << " ";
	endl(std::cout << "\nFloats:" << obj.floats.size());
	for(auto it : obj.floats) std::cout << it << " ";
	endl(std::cout << "\nIntegers:" << obj.ints.size());
	for(auto it : obj.ints) std::cout << it << " ";
	endl(std::cout << "\nStrings:" << obj.strings.size());
	for(auto it : obj.strings) std::cout << it << " ";
	endl(std::cout);*/

	/*auto f_it = std::begin(obj.floats);
	auto i_it = std::begin(obj.ints);
	auto nf_it = std::begin(obj.nFloats);
	auto ni_it = std::begin(obj.nInts);
	for(auto t_it = std::begin(obj.types);
			t_it != std::end(obj.types); t_it++) {
		bool vmatch = *t_it == e_el_v,
			 vnmatch = *t_it == e_el_vn,
			 f2match = *t_it == e_el_f2;
		if(*nf_it > 0) {
			if(vmatch) {
				std::cout << "\nVertex: ";
			} else if(vnmatch) {
				std::cout << "\nVertex norm: ";
			}
			for(int i = 0, iMax = *nf_it; i < iMax; ++i) {
				if(vmatch || vnmatch) {
					std::cout << *f_it << " ";
				}
				f_it++;
			}
		}
		if(*ni_it > 0) {
			if(f2match) {
				std::cout << "\nFace: ";
			}
			for(int i = 0, iMax = *ni_it; i < iMax; ++i) {
				if(f2match) {
					std::cout << *i_it << " ";
				}
				i_it++;
			}
		}
		nf_it++;
		ni_it++;
	}
	std::cout << "\n\n";*/

	for(int i = 0; i < 7; i++) {
		std::vector<int> begs, ends;
		switch(i) {
			case 0: begs = obj.v_beg; ends = obj.v_end;
				std::cout << "Vertex range: " << std::endl;
				break;
			case 1: begs = obj.vn_beg; ends = obj.vn_end;
				std::cout << "Normal range: " << std::endl;
				break;
			case 2: begs = obj.vp_beg; ends = obj.vp_end;
				std::cout << "Texture range: " << std::endl;
				break;
			case 3: begs = obj.f0_beg; ends = obj.f0_end;
				std::cout << "Face(0) range: " << std::endl;
				break;
			case 4: begs = obj.f1_beg; ends = obj.f1_end;
				std::cout << "Face(1) range: " << std::endl;
				break;
			case 5: begs = obj.f2_beg; ends = obj.f2_end;
				std::cout << "Face(2) range: " << std::endl;
				break;
			case 6: begs = obj.f3_beg; ends = obj.f3_end;
				std::cout << "Face(3) range: " << std::endl;
				break;
			default: break;
		}
		auto beg_start = std::begin(begs), beg_stop = std::end(begs),
			 end_start = std::begin(ends), end_stop = std::end(ends);
		while(beg_start != beg_stop) {
			std::cout << "{" << *beg_start++ << ", "
				<< *end_start++ << "}" << std::endl;
		}
	}

	material_t mtl;
	std::cout << "\nFile: " << mtl_fname << std::endl;
	switch(mtl.load(mtl_fname, mtl)) {
		case material_t::e_ok: {
			std::cout << "Status: OK" << std::endl;
		} break;
		case material_t::e_err_io: {
			std::cout << "Status: I/O error" << std::endl;
		} break;
		case material_t::e_err_unknown: {
			std::cout << "Status: Unknown" << std::endl;
		} break;
		default: {} break;
	}

	int w = 3, h = 3;
	mesh_t mesh(w, h, [](float s, float t, std::vector<float> &vertices) {
		auto theta = s*M_PI*2, phi = t*M_PI;
		vertices.emplace_back(cos(theta)*sin(phi));
		vertices.emplace_back(sin(theta)*sin(phi));
		vertices.emplace_back(cos(phi));
	});

	std::cout << "\nMesh points: \n";
	int i = 0;
	for(auto v : mesh.vertices) {
		std::cout << v << ' ';
		if(i++ % 3 == 2) {
			endl(std::cout);
		}
	}
	std::cout << "\nMesh faces: \n";
	for(auto f : mesh.faces) {
		// Divide by 3 to get vertex index
		std::cout << f/3 << ' ';
		if(i++ % 3 == 2) {
			endl(std::cout);
		}
	}
	endl(std::cout);
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include <Eigen/StdVector>
#include "main.h"
#include <Eigen/Geometry>

template<typename MatrixType>
void check_stdvector_matrix(const MatrixType& m)
{
  int rows = m.rows();
  int cols = m.cols();
  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
  std::vector<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
  v[5] = x;
  w[6] = v[5];
  VERIFY_IS_APPROX(w[6], v[5]);
  v = w;
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(w[i], v[i]);
  }

  v.resize(21);
  v[20] = x;
  VERIFY_IS_APPROX(v[20], x);
  v.resize(22,y);
  VERIFY_IS_APPROX(v[21], y);
  v.push_back(x);
  VERIFY_IS_APPROX(v[22], x);
  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));

  // do a lot of push_back such that the vector gets internally resized
  // (with memory reallocation)
  MatrixType* ref = &w[0];
  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
    v.push_back(w[i%w.size()]);
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(v[i]==w[(i-23)%w.size()]);
  }
}

template<typename TransformType>
void check_stdvector_transform(const TransformType&)
{
  typedef typename TransformType::MatrixType MatrixType;
  TransformType x(MatrixType::Random()), y(MatrixType::Random());
  std::vector<TransformType> v(10), w(20, y);
  v[5] = x;
  w[6] = v[5];
  VERIFY_IS_APPROX(w[6], v[5]);
  v = w;
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(w[i], v[i]);
  }

  v.resize(21);
  v[20] = x;
  VERIFY_IS_APPROX(v[20], x);
  v.resize(22,y);
  VERIFY_IS_APPROX(v[21], y);
  v.push_back(x);
  VERIFY_IS_APPROX(v[22], x);
  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));

  // do a lot of push_back such that the vector gets internally resized
  // (with memory reallocation)
  TransformType* ref = &w[0];
  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
    v.push_back(w[i%w.size()]);
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
  }
}

template<typename QuaternionType>
void check_stdvector_quaternion(const QuaternionType&)
{
  typedef typename QuaternionType::Coefficients Coefficients;
  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
  std::vector<QuaternionType> v(10), w(20, y);
  v[5] = x;
  w[6] = v[5];
  VERIFY_IS_APPROX(w[6], v[5]);
  v = w;
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(w[i], v[i]);
  }

  v.resize(21);
  v[20] = x;
  VERIFY_IS_APPROX(v[20], x);
  v.resize(22,y);
  VERIFY_IS_APPROX(v[21], y);
  v.push_back(x);
  VERIFY_IS_APPROX(v[22], x);
  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));

  // do a lot of push_back such that the vector gets internally resized
  // (with memory reallocation)
  QuaternionType* ref = &w[0];
  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
    v.push_back(w[i%w.size()]);
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
  }
}

void test_stdvector()
{
  // some non vectorizable fixed sizes
  CALL_SUBTEST(check_stdvector_matrix(Vector2f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix3f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix3d()));

  // some vectorizable fixed sizes
  CALL_SUBTEST(check_stdvector_matrix(Matrix2f()));
  CALL_SUBTEST(check_stdvector_matrix(Vector4f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix4f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix4d()));

  // some dynamic sizes
  CALL_SUBTEST(check_stdvector_matrix(MatrixXd(1,1)));
  CALL_SUBTEST(check_stdvector_matrix(VectorXd(20)));
  CALL_SUBTEST(check_stdvector_matrix(RowVectorXf(20)));
  CALL_SUBTEST(check_stdvector_matrix(MatrixXcf(10,10)));

  // some Transform
  CALL_SUBTEST(check_stdvector_transform(Transform2f()));
  CALL_SUBTEST(check_stdvector_transform(Transform3f()));
  CALL_SUBTEST(check_stdvector_transform(Transform3d()));
  //CALL_SUBTEST(check_stdvector_transform(Transform4d()));

  // some Quaternion
  CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
  CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
}
<commit_msg>"forgot to commit the required changes in stdvector unit test"<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include <Eigen/StdVector>
#include "main.h"
#include <Eigen/Geometry>

template<typename MatrixType>
void check_stdvector_matrix(const MatrixType& m)
{
  int rows = m.rows();
  int cols = m.cols();
  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
  std::vector<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
  v[5] = x;
  w[6] = v[5];
  VERIFY_IS_APPROX(w[6], v[5]);
  v = w;
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(w[i], v[i]);
  }

  v.resize(21);
  v[20] = x;
  VERIFY_IS_APPROX(v[20], x);
  v.resize(22,y);
  VERIFY_IS_APPROX(v[21], y);
  v.push_back(x);
  VERIFY_IS_APPROX(v[22], x);
  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));

  // do a lot of push_back such that the vector gets internally resized
  // (with memory reallocation)
  MatrixType* ref = &w[0];
  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
    v.push_back(w[i%w.size()]);
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(v[i]==w[(i-23)%w.size()]);
  }
}

template<typename TransformType>
void check_stdvector_transform(const TransformType&)
{
  typedef typename TransformType::MatrixType MatrixType;
  TransformType x(MatrixType::Random()), y(MatrixType::Random());
  std::vector<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
  v[5] = x;
  w[6] = v[5];
  VERIFY_IS_APPROX(w[6], v[5]);
  v = w;
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(w[i], v[i]);
  }

  v.resize(21);
  v[20] = x;
  VERIFY_IS_APPROX(v[20], x);
  v.resize(22,y);
  VERIFY_IS_APPROX(v[21], y);
  v.push_back(x);
  VERIFY_IS_APPROX(v[22], x);
  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));

  // do a lot of push_back such that the vector gets internally resized
  // (with memory reallocation)
  TransformType* ref = &w[0];
  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
    v.push_back(w[i%w.size()]);
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
  }
}

template<typename QuaternionType>
void check_stdvector_quaternion(const QuaternionType&)
{
  typedef typename QuaternionType::Coefficients Coefficients;
  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
  std::vector<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
  v[5] = x;
  w[6] = v[5];
  VERIFY_IS_APPROX(w[6], v[5]);
  v = w;
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(w[i], v[i]);
  }

  v.resize(21);
  v[20] = x;
  VERIFY_IS_APPROX(v[20], x);
  v.resize(22,y);
  VERIFY_IS_APPROX(v[21], y);
  v.push_back(x);
  VERIFY_IS_APPROX(v[22], x);
  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));

  // do a lot of push_back such that the vector gets internally resized
  // (with memory reallocation)
  QuaternionType* ref = &w[0];
  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
    v.push_back(w[i%w.size()]);
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
  }
}

void test_stdvector()
{
  // some non vectorizable fixed sizes
  CALL_SUBTEST(check_stdvector_matrix(Vector2f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix3f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix3d()));

  // some vectorizable fixed sizes
  CALL_SUBTEST(check_stdvector_matrix(Matrix2f()));
  CALL_SUBTEST(check_stdvector_matrix(Vector4f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix4f()));
  CALL_SUBTEST(check_stdvector_matrix(Matrix4d()));

  // some dynamic sizes
  CALL_SUBTEST(check_stdvector_matrix(MatrixXd(1,1)));
  CALL_SUBTEST(check_stdvector_matrix(VectorXd(20)));
  CALL_SUBTEST(check_stdvector_matrix(RowVectorXf(20)));
  CALL_SUBTEST(check_stdvector_matrix(MatrixXcf(10,10)));

  // some Transform
  CALL_SUBTEST(check_stdvector_transform(Transform2f()));
  CALL_SUBTEST(check_stdvector_transform(Transform3f()));
  CALL_SUBTEST(check_stdvector_transform(Transform3d()));
  //CALL_SUBTEST(check_stdvector_transform(Transform4d()));

  // some Quaternion
  CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
  CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include "libtorrent/pch.hpp"

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/lexical_cast.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <vector>
#include <map>
#include <utility>
#include <numeric>
#include <cstdio>

#include "libtorrent/peer_connection.hpp"
#include "libtorrent/bt_peer_connection.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/extensions/smart_ban.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/aux_/session_impl.hpp"

namespace libtorrent { namespace
{

	struct smart_ban_plugin : torrent_plugin, boost::enable_shared_from_this<smart_ban_plugin>
	{
		smart_ban_plugin(torrent& t)
			: m_torrent(t)
			, m_salt(rand())
		{
		}

		void on_piece_pass(int p)
		{
#ifdef TORRENT_LOGGING
			(*m_torrent.session().m_logger) << time_now_string() << " PIECE PASS [ p: " << p
				<< " | block_crc_size: " << m_block_crc.size() << " ]\n";
#endif
			// has this piece failed earlier? If it has, go through the
			// CRCs from the time it failed and ban the peers that
			// sent bad blocks
			std::map<piece_block, block_entry>::iterator i = m_block_crc.lower_bound(piece_block(p, 0));
			if (i == m_block_crc.end() || i->first.piece_index != p) return;

			int size = m_torrent.torrent_file().piece_size(p);
			peer_request r = {p, 0, (std::min)(16*1024, size)};
			piece_block pb(p, 0);
			while (size > 0)
			{
				if (i->first.block_index == pb.block_index)
				{
					m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_ok_block
						, shared_from_this(), *i, _1, _2));
					m_block_crc.erase(i++);
				}
				else
				{
					TORRENT_ASSERT(i->first.block_index > pb.block_index);
				}

				if (i == m_block_crc.end() || i->first.piece_index != p)
					break;

				r.start += 16*1024;
				size -= 16*1024;
				r.length = (std::min)(16*1024, size);
				++pb.block_index;
			}

#ifndef NDEBUG
			// make sure we actually removed all the entries for piece 'p'
			i = m_block_crc.lower_bound(piece_block(p, 0));
			TORRENT_ASSERT(i == m_block_crc.end() || i->first.piece_index != p);
#endif

			if (m_torrent.is_seed())
			{
				std::map<piece_block, block_entry>().swap(m_block_crc);
				return;
			}
		}

		void on_piece_failed(int p)
		{
			// The piece failed the hash check. Record
			// the CRC and origin peer of every block

			std::vector<void*> downloaders;
			m_torrent.picker().get_downloaders(downloaders, p);

			int size = m_torrent.torrent_file().piece_size(p);
			peer_request r = {p, 0, (std::min)(16*1024, size)};
			piece_block pb(p, 0);
			for (std::vector<void*>::iterator i = downloaders.begin()
				, end(downloaders.end()); i != end; ++i)
			{
				if (*i != 0)
				{
					m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_failed_block
						, shared_from_this(), pb, (policy::peer*)*i, _1, _2));
				}

				r.start += 16*1024;
				size -= 16*1024;
				r.length = (std::min)(16*1024, size);
				++pb.block_index;
			}
			TORRENT_ASSERT(size <= 0);
		}

	private:

		// this entry ties a specific block CRC to
		// a peer.
		struct block_entry
		{
			policy::peer* peer;
			unsigned long crc;
		};

		void on_read_failed_block(piece_block b, policy::peer* p, int ret, disk_io_job const& j)
		{
			TORRENT_ASSERT(p);
			// ignore read errors
			if (ret != j.buffer_size) return;

			adler32_crc crc;
			crc.update(j.buffer, j.buffer_size);
			crc.update((char const*)&m_salt, sizeof(m_salt));

			block_entry e = {p, crc.final()};

			// since this callback is called directory from the disk io
			// thread, the session mutex is not locked when we get here
			aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex);

			std::map<piece_block, block_entry>::iterator i = m_block_crc.lower_bound(b);
			if (i != m_block_crc.end() && i->first == b && i->second.peer == p)
			{
				// this peer has sent us this block before
				if (i->second.crc != e.crc)
				{
					// this time the crc of the block is different
					// from the first time it sent it
					// at least one of them must be bad

					if (p == 0) return;
					if (!m_torrent.get_policy().has_peer(p)) return;

#ifdef TORRENT_LOGGING
					char const* client = "-";
					peer_info info;
					if (p->connection)
					{
						p->connection->get_peer_info(info);
						client = info.client.c_str();
					}
					(*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.piece_index
						<< " | b: " << b.block_index
						<< " | c: " << client
						<< " | crc1: " << i->second.crc
						<< " | crc2: " << e.crc
						<< " | ip: " << p->ip << " ]\n";
#endif
					p->banned = true;
					if (p->connection) p->connection->disconnect("banning peer for sending bad data");
				}
				// we already have this exact entry in the map
				// we don't have to insert it
				return;
			}

			m_block_crc.insert(i, std::make_pair(b, e));

#ifdef TORRENT_LOGGING
			char const* client = "-";
			peer_info info;
			if (p->connection)
			{
				p->connection->get_peer_info(info);
				client = info.client.c_str();
			}
			(*m_torrent.session().m_logger) << time_now_string() << " STORE BLOCK CRC [ p: " << b.piece_index
				<< " | b: " << b.block_index
				<< " | c: " << client
				<< " | crc: " << e.crc
				<< " | ip: " << p->ip << " ]\n";
#endif
		}

		void on_read_ok_block(std::pair<piece_block, block_entry> b, int ret, disk_io_job const& j)
		{
			// since this callback is called directory from the disk io
			// thread, the session mutex is not locked when we get here
			aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex);

			// ignore read errors
			if (ret != j.buffer_size) return;

			adler32_crc crc;
			crc.update(j.buffer, j.buffer_size);
			crc.update((char const*)&m_salt, sizeof(m_salt));
			unsigned long ok_crc = crc.final();

			if (b.second.crc == ok_crc) return;

			policy::peer* p = b.second.peer;

			if (p == 0) return;
			if (!m_torrent.get_policy().has_peer(p)) return;

#ifdef TORRENT_LOGGING
			char const* client = "-";
			peer_info info;
			if (p->connection)
			{
				p->connection->get_peer_info(info);
				client = info.client.c_str();
			}
			(*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.first.piece_index
				<< " | b: " << b.first.block_index
				<< " | c: " << client
				<< " | ok_crc: " << ok_crc
				<< " | bad_crc: " << b.second.crc
				<< " | ip: " << p->ip << " ]\n";
#endif
			p->banned = true;
			if (p->connection) p->connection->disconnect("banning peer for sending bad data");
		}

		torrent& m_torrent;

		// This table maps a piece_block (piece and block index
		// pair) to a peer and the block CRC. The CRC is calculated
		// from the data in the block + the salt
		std::map<piece_block, block_entry> m_block_crc;

		// This salt is a random value used to calculate the block CRCs
		// Since the CRC function that is used is not a one way function
		// the salt is required to avoid attacks where bad data is sent
		// that is forged to match the CRC of the good data.
		int m_salt;
	};

} }

namespace libtorrent
{

	boost::shared_ptr<torrent_plugin> create_smart_ban_plugin(torrent* t, void*)
	{
		return boost::shared_ptr<torrent_plugin>(new smart_ban_plugin(*t));
	}

}

<commit_msg>fix smart ban assert when closing a torrent with a failing piece<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include "libtorrent/pch.hpp"

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/lexical_cast.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <vector>
#include <map>
#include <utility>
#include <numeric>
#include <cstdio>

#include "libtorrent/peer_connection.hpp"
#include "libtorrent/bt_peer_connection.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/extensions/smart_ban.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/aux_/session_impl.hpp"

namespace libtorrent { namespace
{

	struct smart_ban_plugin : torrent_plugin, boost::enable_shared_from_this<smart_ban_plugin>
	{
		smart_ban_plugin(torrent& t)
			: m_torrent(t)
			, m_salt(rand())
		{
		}

		void on_piece_pass(int p)
		{
#ifdef TORRENT_LOGGING
			(*m_torrent.session().m_logger) << time_now_string() << " PIECE PASS [ p: " << p
				<< " | block_crc_size: " << m_block_crc.size() << " ]\n";
#endif
			// has this piece failed earlier? If it has, go through the
			// CRCs from the time it failed and ban the peers that
			// sent bad blocks
			std::map<piece_block, block_entry>::iterator i = m_block_crc.lower_bound(piece_block(p, 0));
			if (i == m_block_crc.end() || i->first.piece_index != p) return;

			int size = m_torrent.torrent_file().piece_size(p);
			peer_request r = {p, 0, (std::min)(16*1024, size)};
			piece_block pb(p, 0);
			while (size > 0)
			{
				if (i->first.block_index == pb.block_index)
				{
					m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_ok_block
						, shared_from_this(), *i, _1, _2));
					m_block_crc.erase(i++);
				}
				else
				{
					TORRENT_ASSERT(i->first.block_index > pb.block_index);
				}

				if (i == m_block_crc.end() || i->first.piece_index != p)
					break;

				r.start += 16*1024;
				size -= 16*1024;
				r.length = (std::min)(16*1024, size);
				++pb.block_index;
			}

#ifndef NDEBUG
			// make sure we actually removed all the entries for piece 'p'
			i = m_block_crc.lower_bound(piece_block(p, 0));
			TORRENT_ASSERT(i == m_block_crc.end() || i->first.piece_index != p);
#endif

			if (m_torrent.is_seed())
			{
				std::map<piece_block, block_entry>().swap(m_block_crc);
				return;
			}
		}

		void on_piece_failed(int p)
		{
			// The piece failed the hash check. Record
			// the CRC and origin peer of every block

			// if the torrent is aborted, no point in starting
			// a bunch of read operations on it
			if (m_torrent.is_aborted()) return;

			std::vector<void*> downloaders;
			m_torrent.picker().get_downloaders(downloaders, p);

			int size = m_torrent.torrent_file().piece_size(p);
			peer_request r = {p, 0, (std::min)(16*1024, size)};
			piece_block pb(p, 0);
			for (std::vector<void*>::iterator i = downloaders.begin()
				, end(downloaders.end()); i != end; ++i)
			{
				if (*i != 0)
				{
					m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_failed_block
						, shared_from_this(), pb, (policy::peer*)*i, _1, _2));
				}

				r.start += 16*1024;
				size -= 16*1024;
				r.length = (std::min)(16*1024, size);
				++pb.block_index;
			}
			TORRENT_ASSERT(size <= 0);
		}

	private:

		// this entry ties a specific block CRC to
		// a peer.
		struct block_entry
		{
			policy::peer* peer;
			unsigned long crc;
		};

		void on_read_failed_block(piece_block b, policy::peer* p, int ret, disk_io_job const& j)
		{
			TORRENT_ASSERT(p);
			// ignore read errors
			if (ret != j.buffer_size) return;

			adler32_crc crc;
			crc.update(j.buffer, j.buffer_size);
			crc.update((char const*)&m_salt, sizeof(m_salt));

			block_entry e = {p, crc.final()};

			// since this callback is called directory from the disk io
			// thread, the session mutex is not locked when we get here
			aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex);

			std::map<piece_block, block_entry>::iterator i = m_block_crc.lower_bound(b);
			if (i != m_block_crc.end() && i->first == b && i->second.peer == p)
			{
				// this peer has sent us this block before
				if (i->second.crc != e.crc)
				{
					// this time the crc of the block is different
					// from the first time it sent it
					// at least one of them must be bad

					if (p == 0) return;
					if (!m_torrent.get_policy().has_peer(p)) return;

#ifdef TORRENT_LOGGING
					char const* client = "-";
					peer_info info;
					if (p->connection)
					{
						p->connection->get_peer_info(info);
						client = info.client.c_str();
					}
					(*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.piece_index
						<< " | b: " << b.block_index
						<< " | c: " << client
						<< " | crc1: " << i->second.crc
						<< " | crc2: " << e.crc
						<< " | ip: " << p->ip << " ]\n";
#endif
					p->banned = true;
					if (p->connection) p->connection->disconnect("banning peer for sending bad data");
				}
				// we already have this exact entry in the map
				// we don't have to insert it
				return;
			}

			m_block_crc.insert(i, std::make_pair(b, e));

#ifdef TORRENT_LOGGING
			char const* client = "-";
			peer_info info;
			if (p->connection)
			{
				p->connection->get_peer_info(info);
				client = info.client.c_str();
			}
			(*m_torrent.session().m_logger) << time_now_string() << " STORE BLOCK CRC [ p: " << b.piece_index
				<< " | b: " << b.block_index
				<< " | c: " << client
				<< " | crc: " << e.crc
				<< " | ip: " << p->ip << " ]\n";
#endif
		}

		void on_read_ok_block(std::pair<piece_block, block_entry> b, int ret, disk_io_job const& j)
		{
			// since this callback is called directory from the disk io
			// thread, the session mutex is not locked when we get here
			aux::session_impl::mutex_t::scoped_lock l(m_torrent.session().m_mutex);

			// ignore read errors
			if (ret != j.buffer_size) return;

			adler32_crc crc;
			crc.update(j.buffer, j.buffer_size);
			crc.update((char const*)&m_salt, sizeof(m_salt));
			unsigned long ok_crc = crc.final();

			if (b.second.crc == ok_crc) return;

			policy::peer* p = b.second.peer;

			if (p == 0) return;
			if (!m_torrent.get_policy().has_peer(p)) return;

#ifdef TORRENT_LOGGING
			char const* client = "-";
			peer_info info;
			if (p->connection)
			{
				p->connection->get_peer_info(info);
				client = info.client.c_str();
			}
			(*m_torrent.session().m_logger) << time_now_string() << " BANNING PEER [ p: " << b.first.piece_index
				<< " | b: " << b.first.block_index
				<< " | c: " << client
				<< " | ok_crc: " << ok_crc
				<< " | bad_crc: " << b.second.crc
				<< " | ip: " << p->ip << " ]\n";
#endif
			p->banned = true;
			if (p->connection) p->connection->disconnect("banning peer for sending bad data");
		}

		torrent& m_torrent;

		// This table maps a piece_block (piece and block index
		// pair) to a peer and the block CRC. The CRC is calculated
		// from the data in the block + the salt
		std::map<piece_block, block_entry> m_block_crc;

		// This salt is a random value used to calculate the block CRCs
		// Since the CRC function that is used is not a one way function
		// the salt is required to avoid attacks where bad data is sent
		// that is forged to match the CRC of the good data.
		int m_salt;
	};

} }

namespace libtorrent
{

	boost::shared_ptr<torrent_plugin> create_smart_ban_plugin(torrent* t, void*)
	{
		return boost::shared_ptr<torrent_plugin>(new smart_ban_plugin(*t));
	}

}

<|endoftext|>


<commit_before>#include "blinktask.hpp"
#include "led.hpp"

static BlinkTask blinkTask;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
}
<commit_msg>Typo<commit_after>#include "blinktask.hpp"
#include "led.hpp"

static BlinkTask blinkTask;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {}
<|endoftext|>


<commit_before>#include "config.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cstring>

using namespace std;

//// parameters
// for bam file and reads
int min_flank_length = 5;
int32_t min_bundle_gap = 50;
int min_num_hits_in_bundle = 20;
uint32_t min_mapping_quality = 1;
int32_t min_splice_boundary_hits = 1;
bool use_second_alignment = false;
bool strand_reverse = false;

// for identifying subgraphs
double max_indel_ratio = 0.2;
double min_subregion_overlap = 2;
int32_t min_subregion_gap = 3;
int32_t min_subregion_length = 15;

// for revising splice graph
double min_inner_vertex_weight = 10;
double min_inner_boundary_weight = 4.0;
double min_splice_edge_weight = 1.5;
bool extend_isolated_boundary = true;

// for decomposing splice graph
double max_split_error_ratio = 0.25;
double max_decompose_error_ratio = 0.01;
double min_removable_weight = 5.0;

// for selecting paths
double min_transcript_coverage = 1.5;
int min_transcript_length = 200;

// for identifying new boundaries
bool identify_extra_boundary = false;
int min_boundary_length = 80;
int min_boundary_score = 100;
double min_boundary_ave_ratio = 3.0;
double min_boundary_sigma = 5.0;

// for subsetsum and router
int max_dp_table_size = 10000;
int min_router_count = 1;

// for simulation
int simulation_num_vertices = 0;
int simulation_num_edges = 0;
int simulation_max_edge_weight = 0;

// input and output
string algo = "scallop";
string input_file;
string ref_file;
string ref_file1;
string ref_file2;
string output_file;

// for controling
int32_t average_read_length = 100;
bool output_tex_files = false;
string fixed_gene_name = "";

int print_parameters()
{
	printf("parameters:\n");

	// for bam file and reads
	printf("min_flank_length = %d\n", min_flank_length);
	printf("min_bundle_gap = %d\n", min_bundle_gap);
	printf("min_num_hits_in_bundle = %d\n", min_num_hits_in_bundle);
	printf("min_mapping_quality = %d\n", min_mapping_quality);
	printf("min_splice_boundary_hits = %d\n", min_splice_boundary_hits);

	// for identifying subgraphs
	printf("max_indel_ratio = %.2lf\n", max_indel_ratio);
	printf("min_subregion_gap = %d\n", min_subregion_gap);
	printf("min_subregion_length = %d\n", min_subregion_length);
	printf("min_subregion_overlap = %.2lf\n", min_subregion_overlap);

	// for splice graph
	printf("min_splice_edge_weight = %.2lf\n", min_splice_edge_weight);
	printf("min_inner_vertex_weight = %.2lf\n", min_inner_vertex_weight);
	printf("min_inner_boundary_weight = %.2lf\n", min_inner_boundary_weight);
	printf("min_transcript_coverage = %.2lf\n", min_transcript_coverage);
	printf("min_transcript_length = %d\n", min_transcript_length);
	printf("max_split_error_ratio = %.2lf\n", max_split_error_ratio);
	printf("max_decompose_error_ratio = %.2lf\n", max_decompose_error_ratio);
	printf("min_removable_weight = %.2lf\n", min_removable_weight);
	printf("extend_isolated_bounary = %c\n", extend_isolated_boundary ? 'T' : 'F');

	// for identifying new boundaries
	printf("identify_extra_boundary = %c\n", identify_extra_boundary ? 'T' : 'F');
	printf("min_boundary_length = %d\n", min_boundary_length);
	printf("min_boundary_score = %d\n", min_boundary_score);
	printf("min_boundary_ave_ratio = %.2lf\n", min_boundary_ave_ratio);
	printf("min_boundary_signma = %.2lf\n", min_boundary_sigma);

	// for subsetsum and router
	printf("max_dp_table_size = %d\n", max_dp_table_size);
	printf("min_router_count = %d\n", min_router_count);

	// for simulation
	printf("simulation_num_vertices = %d\n", simulation_num_vertices);
	printf("simulation_num_edges = %d\n", simulation_num_edges);
	printf("simulation_max_edge_weight = %d\n", simulation_max_edge_weight);

	// for input and output
	printf("algo = %s\n", algo.c_str());
	printf("input_file = %s\n", input_file.c_str());
	printf("ref_file = %s\n", ref_file.c_str());
	printf("ref_file1 = %s\n", ref_file1.c_str());
	printf("ref_file2 = %s\n", ref_file2.c_str());
	printf("output_file = %s\n", output_file.c_str());

	// for controling
	printf("average_read_length = %d\n", average_read_length);
	printf("strand_reverse = %c\n", strand_reverse ? 'T' : 'F');
	printf("output_tex_files = %c\n", output_tex_files ? 'T' : 'F');
	printf("fixed_gene_name = %s\n", fixed_gene_name.c_str());
	printf("use_second_alignment = %c\n", use_second_alignment ? 'T' : 'F');

	printf("\n");

	return 0;
}

int print_command_line(int argc, const char ** argv)
{
	printf("command line: ");
	for(int i = 0; i < argc; i++)
	{
		printf("%s ", argv[i]);
	}
	printf("\n");
	return 0;
}

int parse_arguments(int argc, const char ** argv)
{
	for(int i = 1; i < argc; i++)
	{
		// necessary ones
		if(string(argv[i]) == "-i")
		{
			input_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-o")
		{
			output_file = string(argv[i + 1]);
			i++;
		}

		// internal use
		else if(string(argv[i]) == "-a")
		{
			algo = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r")
		{
			ref_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r1")
		{
			ref_file1 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r2")
		{
			ref_file2 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-g")
		{
			fixed_gene_name = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-t")
		{
			output_tex_files = true;
		}

		// user specified
		else if(string(argv[i]) == "--min_flank_length")
		{
			min_flank_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_bundle_gap")
		{
			min_bundle_gap = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_num_hits_in_bundle")
		{
			min_num_hits_in_bundle = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_mapping_quality")
		{
			min_mapping_quality = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_splice_boundary_hits")
		{
			min_splice_boundary_hits = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_indel_ratio")
		{
			max_indel_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_subregion_gap")
		{
			min_subregion_gap = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_subregion_length")
		{
			min_subregion_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_subregion_overlap")
		{
			min_subregion_overlap = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--identify_extra_boundary")
		{
			string s(argv[i + 1]);
			if(s == "true") identify_extra_boundary = true;
			else identify_extra_boundary = false;
			i++;
		}
		else if(string(argv[i]) == "--min_splice_edge_weight")
		{
			min_splice_edge_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_inner_vertex_weight")
		{
			min_inner_vertex_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_inner_boundary_weight")
		{
			min_inner_boundary_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_transcript_coverage")
		{
			min_transcript_coverage = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_transcript_length")
		{
			min_transcript_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_split_error_ratio")
		{
			max_split_error_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_decompose_error_ratio")
		{
			max_decompose_error_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_removable_weight")
		{
			min_removable_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--extend_isolated_boundary")
		{
			string s(argv[i + 1]);
			if(s == "true") extend_isolated_boundary = true;
			else extend_isolated_boundary = false;
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_length")
		{
			min_boundary_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_score")
		{
			min_boundary_score = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_ave_ratio")
		{
			min_boundary_ave_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_sigma")
		{
			min_boundary_sigma = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_dp_table_size")
		{
			max_dp_table_size = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_router_count")
		{
			min_router_count = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--strand_reverse")
		{
			string s(argv[i + 1]);
			if(s == "true") strand_reverse = true;
			else strand_reverse = false;
			i++;
		}
		else if(string(argv[i]) == "--use_second_alignment")
		{
			string s(argv[i + 1]);
			if(s == "true") use_second_alignment = true;
			else use_second_alignment = false;
			i++;
		}
	}

	// TODO
	min_splice_edge_weight = min_transcript_coverage;

	return 0;
}
<commit_msg>change default min transcript length to 500<commit_after>#include "config.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cstring>

using namespace std;

//// parameters
// for bam file and reads
int min_flank_length = 5;
int32_t min_bundle_gap = 50;
int min_num_hits_in_bundle = 20;
uint32_t min_mapping_quality = 1;
int32_t min_splice_boundary_hits = 1;
bool use_second_alignment = false;
bool strand_reverse = false;

// for identifying subgraphs
double max_indel_ratio = 0.2;
double min_subregion_overlap = 2;
int32_t min_subregion_gap = 3;
int32_t min_subregion_length = 15;

// for revising splice graph
double min_inner_vertex_weight = 10;
double min_inner_boundary_weight = 4.0;
double min_splice_edge_weight = 0.5;
bool extend_isolated_boundary = true;

// for decomposing splice graph
double max_split_error_ratio = 0.25;
double max_decompose_error_ratio = 0.01;
double min_removable_weight = 5.0;

// for selecting paths
double min_transcript_coverage = 1.5;
int min_transcript_length = 500;

// for identifying new boundaries
bool identify_extra_boundary = false;
int min_boundary_length = 80;
int min_boundary_score = 100;
double min_boundary_ave_ratio = 3.0;
double min_boundary_sigma = 5.0;

// for subsetsum and router
int max_dp_table_size = 10000;
int min_router_count = 1;

// for simulation
int simulation_num_vertices = 0;
int simulation_num_edges = 0;
int simulation_max_edge_weight = 0;

// input and output
string algo = "scallop";
string input_file;
string ref_file;
string ref_file1;
string ref_file2;
string output_file;

// for controling
int32_t average_read_length = 100;
bool output_tex_files = false;
string fixed_gene_name = "";

int print_parameters()
{
	printf("parameters:\n");

	// for bam file and reads
	printf("min_flank_length = %d\n", min_flank_length);
	printf("min_bundle_gap = %d\n", min_bundle_gap);
	printf("min_num_hits_in_bundle = %d\n", min_num_hits_in_bundle);
	printf("min_mapping_quality = %d\n", min_mapping_quality);
	printf("min_splice_boundary_hits = %d\n", min_splice_boundary_hits);

	// for identifying subgraphs
	printf("max_indel_ratio = %.2lf\n", max_indel_ratio);
	printf("min_subregion_gap = %d\n", min_subregion_gap);
	printf("min_subregion_length = %d\n", min_subregion_length);
	printf("min_subregion_overlap = %.2lf\n", min_subregion_overlap);

	// for splice graph
	printf("min_splice_edge_weight = %.2lf\n", min_splice_edge_weight);
	printf("min_inner_vertex_weight = %.2lf\n", min_inner_vertex_weight);
	printf("min_inner_boundary_weight = %.2lf\n", min_inner_boundary_weight);
	printf("min_transcript_coverage = %.2lf\n", min_transcript_coverage);
	printf("min_transcript_length = %d\n", min_transcript_length);
	printf("max_split_error_ratio = %.2lf\n", max_split_error_ratio);
	printf("max_decompose_error_ratio = %.2lf\n", max_decompose_error_ratio);
	printf("min_removable_weight = %.2lf\n", min_removable_weight);
	printf("extend_isolated_bounary = %c\n", extend_isolated_boundary ? 'T' : 'F');

	// for identifying new boundaries
	printf("identify_extra_boundary = %c\n", identify_extra_boundary ? 'T' : 'F');
	printf("min_boundary_length = %d\n", min_boundary_length);
	printf("min_boundary_score = %d\n", min_boundary_score);
	printf("min_boundary_ave_ratio = %.2lf\n", min_boundary_ave_ratio);
	printf("min_boundary_signma = %.2lf\n", min_boundary_sigma);

	// for subsetsum and router
	printf("max_dp_table_size = %d\n", max_dp_table_size);
	printf("min_router_count = %d\n", min_router_count);

	// for simulation
	printf("simulation_num_vertices = %d\n", simulation_num_vertices);
	printf("simulation_num_edges = %d\n", simulation_num_edges);
	printf("simulation_max_edge_weight = %d\n", simulation_max_edge_weight);

	// for input and output
	printf("algo = %s\n", algo.c_str());
	printf("input_file = %s\n", input_file.c_str());
	printf("ref_file = %s\n", ref_file.c_str());
	printf("ref_file1 = %s\n", ref_file1.c_str());
	printf("ref_file2 = %s\n", ref_file2.c_str());
	printf("output_file = %s\n", output_file.c_str());

	// for controling
	printf("average_read_length = %d\n", average_read_length);
	printf("strand_reverse = %c\n", strand_reverse ? 'T' : 'F');
	printf("output_tex_files = %c\n", output_tex_files ? 'T' : 'F');
	printf("fixed_gene_name = %s\n", fixed_gene_name.c_str());
	printf("use_second_alignment = %c\n", use_second_alignment ? 'T' : 'F');

	printf("\n");

	return 0;
}

int print_command_line(int argc, const char ** argv)
{
	printf("command line: ");
	for(int i = 0; i < argc; i++)
	{
		printf("%s ", argv[i]);
	}
	printf("\n");
	return 0;
}

int parse_arguments(int argc, const char ** argv)
{
	for(int i = 1; i < argc; i++)
	{
		// necessary ones
		if(string(argv[i]) == "-i")
		{
			input_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-o")
		{
			output_file = string(argv[i + 1]);
			i++;
		}

		// internal use
		else if(string(argv[i]) == "-a")
		{
			algo = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r")
		{
			ref_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r1")
		{
			ref_file1 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r2")
		{
			ref_file2 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-g")
		{
			fixed_gene_name = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-t")
		{
			output_tex_files = true;
		}

		// user specified
		else if(string(argv[i]) == "--min_flank_length")
		{
			min_flank_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_bundle_gap")
		{
			min_bundle_gap = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_num_hits_in_bundle")
		{
			min_num_hits_in_bundle = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_mapping_quality")
		{
			min_mapping_quality = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_splice_boundary_hits")
		{
			min_splice_boundary_hits = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_indel_ratio")
		{
			max_indel_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_subregion_gap")
		{
			min_subregion_gap = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_subregion_length")
		{
			min_subregion_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_subregion_overlap")
		{
			min_subregion_overlap = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--identify_extra_boundary")
		{
			string s(argv[i + 1]);
			if(s == "true") identify_extra_boundary = true;
			else identify_extra_boundary = false;
			i++;
		}
		else if(string(argv[i]) == "--min_splice_edge_weight")
		{
			min_splice_edge_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_inner_vertex_weight")
		{
			min_inner_vertex_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_inner_boundary_weight")
		{
			min_inner_boundary_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_transcript_coverage")
		{
			min_transcript_coverage = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_transcript_length")
		{
			min_transcript_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_split_error_ratio")
		{
			max_split_error_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_decompose_error_ratio")
		{
			max_decompose_error_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_removable_weight")
		{
			min_removable_weight = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--extend_isolated_boundary")
		{
			string s(argv[i + 1]);
			if(s == "true") extend_isolated_boundary = true;
			else extend_isolated_boundary = false;
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_length")
		{
			min_boundary_length = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_score")
		{
			min_boundary_score = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_ave_ratio")
		{
			min_boundary_ave_ratio = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_boundary_sigma")
		{
			min_boundary_sigma = atof(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--max_dp_table_size")
		{
			max_dp_table_size = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--min_router_count")
		{
			min_router_count = atoi(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "--strand_reverse")
		{
			string s(argv[i + 1]);
			if(s == "true") strand_reverse = true;
			else strand_reverse = false;
			i++;
		}
		else if(string(argv[i]) == "--use_second_alignment")
		{
			string s(argv[i + 1]);
			if(s == "true") use_second_alignment = true;
			else use_second_alignment = false;
			i++;
		}
	}

	// TODO
	//min_splice_edge_weight = min_transcript_coverage;

	return 0;
}
<|endoftext|>