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

#ifndef DESOLIN_INTERNAL_REPS_HPP
#define DESOLIN_INTERNAL_REPS_HPP

#include <cassert>
#include <desolin/Desolin_fwd.hpp>
#include <desolin/file-access/mtl_entry.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>

namespace desolin
{

namespace detail
{

template<typename T_element>
class InternalValue
{
protected:
  bool allocated;

public:
  InternalValue(const bool isAllocated) : allocated(isAllocated)
  {
  }

  inline bool isAllocated() const
  {
    return allocated;
  }

  virtual void allocate() = 0;

  virtual ~InternalValue() {}
};

template<typename T_element>
class InternalScalar : public InternalValue<T_element>
{
public:
  InternalScalar(const bool allocated) : InternalValue<T_element>(allocated)
  {
  }

  virtual void accept(InternalScalarVisitor<T_element>& visitor) = 0;

  virtual T_element getElementValue() = 0;
};

template<typename T_element>
class InternalVector : public InternalValue<T_element>
{
protected:
  const int rows;

public:
  InternalVector(const bool allocated, const int rowCount) : InternalValue<T_element>(allocated), rows(rowCount)
  {
  }

  const inline int getRowCount() const
  {
    return rows;
  }

  virtual void accept(InternalVectorVisitor<T_element>& visitor) = 0;

  virtual T_element getElementValue(const ElementIndex<vector>& index) = 0;
};

template<typename T_element>
class InternalMatrix : public InternalValue<T_element>
{
protected:
  const int rows;
  const int cols;

public:
  InternalMatrix(const bool allocated, const int rowCount, const int colCount) : InternalValue<T_element>(allocated), rows(rowCount), cols(colCount)
  {
  }

  const inline int getRowCount() const
  {
    return rows;
  }

  const inline int getColCount() const
  {
    return cols;
  }

  virtual void accept(InternalMatrixVisitor<T_element>& visitor) = 0;

  virtual T_element getElementValue(const ElementIndex<matrix>& index) = 0;
};

template<typename T_element>
class ConventionalScalar : public InternalScalar<T_element>
{
private:
  T_element value;

public:
  ConventionalScalar() : InternalScalar<T_element>(true), value(T_element(0))
  {
  }

  ConventionalScalar(const T_element initialValue) : InternalScalar<T_element>(true), value(initialValue)
  {
  }

  virtual void allocate()
  {
    this->allocated=true;
  }

  virtual void accept(InternalScalarVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  virtual T_element getElementValue()
  {
    assert(this->allocated);
    return value;
  }

  T_element* getValue()
  {
    assert(this->allocated);
    return &value;
  }
};

template<typename T_element>
class ConventionalVector : public InternalVector<T_element>
{
private:
  std::vector<T_element> value;

public:
  ConventionalVector(const int rowCount) : InternalVector<T_element>(false, rowCount)
  {
  }

  ConventionalVector(const int rowCount, const T_element initialValue) : InternalVector<T_element>(true, rowCount), value(rowCount, initialValue)
  {
  }

  virtual void allocate()
  {
    if(!this->allocated)
    {
      value.resize(this->rows, T_element(0));
      this->allocated=true;
    }
  }

  virtual void accept(InternalVectorVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  T_element* getValue()
  {
    assert(this->allocated);
    return &value[0];
  }

  virtual T_element getElementValue(const ElementIndex<vector>& index)
  {
    assert(this->allocated);
    return value[index.getRow()];
  }
};

template<typename T_element>
class ConventionalMatrix : public InternalMatrix<T_element>
{
private:
  std::vector<T_element> value;

public:
  ConventionalMatrix(const int rowCount, const int colCount) : InternalMatrix<T_element>(false, rowCount, colCount)
  {
  }

  template<typename StreamType>
  ConventionalMatrix(StreamType& stream) : InternalMatrix<T_element>(true, stream.nrows(), stream.ncols()), value(stream.nrows()*stream.ncols())
  {
    while(!stream.eof())
    {
        entry2<double> entry;
        stream >> entry;
	value[this->getColCount()*entry.row + entry.col] = entry.value;
    }
  }

  virtual void allocate()
  {
    if(!this->allocated)
    {
      value.resize(this->rows * this->cols, T_element(0));
      this->allocated=true;
    }
  }

  virtual void accept(InternalMatrixVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  T_element* getValue()
  {
    assert(this->allocated);
    return &value[0];
  }

  virtual T_element getElementValue(const ElementIndex<matrix>& index)
  {
    assert(this->allocated);
    return value[(this->cols*index.getRow())+index.getCol()];
  }
};

template<typename T_element>
class CRSMatrix : public InternalMatrix<T_element>
{
private:
  std::vector<int> col_ind;
  std::vector<int> row_ptr;
  std::vector<T_element> val;

public:
  CRSMatrix(const int rowCount, const int colCount) : InternalMatrix<T_element>(false, rowCount, colCount)
  {
  }

  template<typename StreamType>
  CRSMatrix(StreamType& stream) : InternalMatrix<T_element>(true, stream.nrows(), stream.ncols())
  {
    typedef boost::numeric::ublas::mapped_matrix<T_element> TempMatrixType;
    TempMatrixType matrix(this->getRowCount(), this->getColCount());

    while(!stream.eof())
    {
        entry2<double> entry;
        stream >> entry;
        matrix(entry.row, entry.col) = entry.value;
    }

    for(int row=0; row<this->getRowCount(); ++row)
    {
      row_ptr.push_back(val.size());
      typedef boost::numeric::ublas::matrix_row<TempMatrixType> row_t;
      row_t mr(matrix, row);
      for(typename row_t::const_iterator colIter(mr.begin()); colIter!=mr.end(); ++colIter)
      {
        col_ind.push_back(colIter.index());
        val.push_back(*colIter);
      }
    }
    row_ptr.push_back(val.size());
  }

  virtual void allocate()
  {
    if(!this->allocated)
    {
      row_ptr.resize(this->getRowCount()+1, 0);
      this->allocated=true;
    }
  }

  virtual void accept(InternalMatrixVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  unsigned nnz() const
  {
    return col_ind.size();
  }

  unsigned row_ptr_size() const
  {
    return row_ptr.size();
  }

  int* get_col_ind()
  {
    return &col_ind[0];
  }

  int* get_row_ptr()
  {
    return &row_ptr[0];
  }

  T_element* get_val()
  {
    return &val[0];
  }

  virtual T_element getElementValue(const ElementIndex<matrix>& index)
  {
    assert(this->allocated);
    for(int valPtr = row_ptr[index.getRow()]; valPtr < row_ptr[index.getRow()+1]; ++valPtr)
      if (col_ind[valPtr] == index.getCol())
        return val[valPtr];

    return T_element();
  }
};

template<typename T_elementType>
class InternalScalarVisitor
{
public:
  virtual void visit(ConventionalScalar<T_elementType>& value) = 0;
  virtual ~InternalScalarVisitor() {}
};

template<typename T_elementType>
class InternalVectorVisitor
{
public:
  virtual void visit(ConventionalVector<T_elementType>& value) = 0;
  virtual ~InternalVectorVisitor() {}
};

template<typename T_elementType>
class InternalMatrixVisitor
{
public:
  virtual void visit(ConventionalMatrix<T_elementType>& value) = 0;
  virtual void visit(CRSMatrix<T_elementType>& value) = 0;
  virtual ~InternalMatrixVisitor() {}
};

}

}
#endif
<commit_msg>Rewrite CRS loader not to use Boost ublas.<commit_after>/****************************************************************************/
/* Copyright 2005-2006, Francis Russell                                     */
/*                                                                          */
/* Licensed under the Apache License, Version 2.0 (the License);            */
/* you may not use this file except in compliance with the License.         */
/* You may obtain a copy of the License at                                  */
/*                                                                          */
/*     http://www.apache.org/licenses/LICENSE-2.0                           */
/*                                                                          */
/* Unless required by applicable law or agreed to in writing, software      */
/* distributed under the License is distributed on an AS IS BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and      */
/* limitations under the License.                                           */
/*                                                                          */
/****************************************************************************/

#ifndef DESOLIN_INTERNAL_REPS_HPP
#define DESOLIN_INTERNAL_REPS_HPP

#include <cassert>
#include <map>
#include <vector>
#include <desolin/Desolin_fwd.hpp>
#include <desolin/file-access/mtl_entry.hpp>

namespace desolin
{

namespace detail
{

template<typename T_element>
class InternalValue
{
protected:
  bool allocated;

public:
  InternalValue(const bool isAllocated) : allocated(isAllocated)
  {
  }

  inline bool isAllocated() const
  {
    return allocated;
  }

  virtual void allocate() = 0;

  virtual ~InternalValue() {}
};

template<typename T_element>
class InternalScalar : public InternalValue<T_element>
{
public:
  InternalScalar(const bool allocated) : InternalValue<T_element>(allocated)
  {
  }

  virtual void accept(InternalScalarVisitor<T_element>& visitor) = 0;

  virtual T_element getElementValue() = 0;
};

template<typename T_element>
class InternalVector : public InternalValue<T_element>
{
protected:
  const int rows;

public:
  InternalVector(const bool allocated, const int rowCount) : InternalValue<T_element>(allocated), rows(rowCount)
  {
  }

  const inline int getRowCount() const
  {
    return rows;
  }

  virtual void accept(InternalVectorVisitor<T_element>& visitor) = 0;

  virtual T_element getElementValue(const ElementIndex<vector>& index) = 0;
};

template<typename T_element>
class InternalMatrix : public InternalValue<T_element>
{
protected:
  const int rows;
  const int cols;

public:
  InternalMatrix(const bool allocated, const int rowCount, const int colCount) : InternalValue<T_element>(allocated), rows(rowCount), cols(colCount)
  {
  }

  const inline int getRowCount() const
  {
    return rows;
  }

  const inline int getColCount() const
  {
    return cols;
  }

  virtual void accept(InternalMatrixVisitor<T_element>& visitor) = 0;

  virtual T_element getElementValue(const ElementIndex<matrix>& index) = 0;
};

template<typename T_element>
class ConventionalScalar : public InternalScalar<T_element>
{
private:
  T_element value;

public:
  ConventionalScalar() : InternalScalar<T_element>(true), value(T_element(0))
  {
  }

  ConventionalScalar(const T_element initialValue) : InternalScalar<T_element>(true), value(initialValue)
  {
  }

  virtual void allocate()
  {
    this->allocated=true;
  }

  virtual void accept(InternalScalarVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  virtual T_element getElementValue()
  {
    assert(this->allocated);
    return value;
  }

  T_element* getValue()
  {
    assert(this->allocated);
    return &value;
  }
};

template<typename T_element>
class ConventionalVector : public InternalVector<T_element>
{
private:
  std::vector<T_element> value;

public:
  ConventionalVector(const int rowCount) : InternalVector<T_element>(false, rowCount)
  {
  }

  ConventionalVector(const int rowCount, const T_element initialValue) : InternalVector<T_element>(true, rowCount), value(rowCount, initialValue)
  {
  }

  virtual void allocate()
  {
    if(!this->allocated)
    {
      value.resize(this->rows, T_element(0));
      this->allocated=true;
    }
  }

  virtual void accept(InternalVectorVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  T_element* getValue()
  {
    assert(this->allocated);
    return &value[0];
  }

  virtual T_element getElementValue(const ElementIndex<vector>& index)
  {
    assert(this->allocated);
    return value[index.getRow()];
  }
};

template<typename T_element>
class ConventionalMatrix : public InternalMatrix<T_element>
{
private:
  std::vector<T_element> value;

public:
  ConventionalMatrix(const int rowCount, const int colCount) : InternalMatrix<T_element>(false, rowCount, colCount)
  {
  }

  template<typename StreamType>
  ConventionalMatrix(StreamType& stream) : InternalMatrix<T_element>(true, stream.nrows(), stream.ncols()), value(stream.nrows()*stream.ncols())
  {
    while(!stream.eof())
    {
        entry2<double> entry;
        stream >> entry;
	value[this->getColCount()*entry.row + entry.col] = entry.value;
    }
  }

  virtual void allocate()
  {
    if(!this->allocated)
    {
      value.resize(this->rows * this->cols, T_element(0));
      this->allocated=true;
    }
  }

  virtual void accept(InternalMatrixVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  T_element* getValue()
  {
    assert(this->allocated);
    return &value[0];
  }

  virtual T_element getElementValue(const ElementIndex<matrix>& index)
  {
    assert(this->allocated);
    return value[(this->cols*index.getRow())+index.getCol()];
  }
};

template<typename T_element>
class CRSMatrix : public InternalMatrix<T_element>
{
private:
  std::vector<int> col_ind;
  std::vector<int> row_ptr;
  std::vector<T_element> val;

public:
  CRSMatrix(const int rowCount, const int colCount) : InternalMatrix<T_element>(false, rowCount, colCount)
  {
  }

  template<typename StreamType>
  CRSMatrix(StreamType& stream) : InternalMatrix<T_element>(true, stream.nrows(), stream.ncols())
  {
    std::vector< std::map<std::size_t, T_element> > matrixData(this->getRowCount());

    while(!stream.eof())
    {
      entry2<double> entry;
      stream >> entry;
      assert(entry.row >= 0 && entry.col >=0);
      matrixData[entry.row][entry.col] = entry.value;
    }

    for(int row=0; row<this->getRowCount(); ++row)
    {
      row_ptr.push_back(val.size());
      const std::map<std::size_t, T_element>& mr(matrixData[row]);
      for(typename std::map<std::size_t, T_element>::const_iterator colIter(mr.begin()); colIter!=mr.end(); ++colIter)
      {
        col_ind.push_back(colIter->first);
        val.push_back(colIter->second);
      }
    }
    row_ptr.push_back(val.size());
  }

  virtual void allocate()
  {
    if(!this->allocated)
    {
      row_ptr.resize(this->getRowCount()+1, 0);
      this->allocated=true;
    }
  }

  virtual void accept(InternalMatrixVisitor<T_element>& visitor)
  {
    visitor.visit(*this);
  }

  unsigned nnz() const
  {
    return col_ind.size();
  }

  unsigned row_ptr_size() const
  {
    return row_ptr.size();
  }

  int* get_col_ind()
  {
    return &col_ind[0];
  }

  int* get_row_ptr()
  {
    return &row_ptr[0];
  }

  T_element* get_val()
  {
    return &val[0];
  }

  virtual T_element getElementValue(const ElementIndex<matrix>& index)
  {
    assert(this->allocated);
    for(int valPtr = row_ptr[index.getRow()]; valPtr < row_ptr[index.getRow()+1]; ++valPtr)
      if (col_ind[valPtr] == index.getCol())
        return val[valPtr];

    return T_element();
  }
};

template<typename T_elementType>
class InternalScalarVisitor
{
public:
  virtual void visit(ConventionalScalar<T_elementType>& value) = 0;
  virtual ~InternalScalarVisitor() {}
};

template<typename T_elementType>
class InternalVectorVisitor
{
public:
  virtual void visit(ConventionalVector<T_elementType>& value) = 0;
  virtual ~InternalVectorVisitor() {}
};

template<typename T_elementType>
class InternalMatrixVisitor
{
public:
  virtual void visit(ConventionalMatrix<T_elementType>& value) = 0;
  virtual void visit(CRSMatrix<T_elementType>& value) = 0;
  virtual ~InternalMatrixVisitor() {}
};

}

}
#endif
<|endoftext|>


<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)
//=======================================================================

#pragma once

#include "cuda_runtime.h"

namespace etl {

namespace impl {

namespace cuda {

template <typename T>
struct cuda_memory {
    T* memory;
    cuda_memory(T* memory)
            : memory(memory) {}
    T* get() const {
        return memory;
    }
    ~cuda_memory() {
        cudaFree(memory);
    }
};

template <typename E>
auto cuda_allocate(const E& expr, bool copy = false) -> cuda_memory<value_t<E>> {
    value_t<E>* memory;

    auto cuda_status = cudaMalloc(&memory, etl::size(expr) * sizeof(value_t<E>));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << etl::size(expr) * sizeof(value_t<E>) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, expr.memory_start(), etl::size(expr) * sizeof(value_t<E>), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(const E& expr) -> cuda_memory<value_t<E>> {
    return cuda_allocate(expr, true);
}

template <typename E>
auto cuda_allocate(E* ptr, std::size_t n, bool copy = false) -> cuda_memory<E> {
    E* memory;

    auto cuda_status = cudaMalloc(&memory, n * sizeof(E));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << n * sizeof(E) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, ptr, n * sizeof(E), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(E* ptr, std::size_t n) -> cuda_memory<E> {
    return cuda_allocate(ptr, n, true);
}

} //end of namespace cublas

} //end of namespace impl

} //end of namespace etl
<commit_msg>Improve cuda_memory wrapper<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)
//=======================================================================

#pragma once

#include "cuda_runtime.h"

namespace etl {

namespace impl {

namespace cuda {

template <typename T>
struct cuda_memory {
    T* memory;

    cuda_memory(T* memory) : memory(memory) {}

    T* get() const {
        return memory;
    }

    bool is_set() const {
        return memory;
    }

    ~cuda_memory() {
        cudaFree(memory);
    }
};

template <typename E>
auto cuda_allocate(const E& expr, bool copy = false) -> cuda_memory<value_t<E>> {
    value_t<E>* memory;

    auto cuda_status = cudaMalloc(&memory, etl::size(expr) * sizeof(value_t<E>));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << etl::size(expr) * sizeof(value_t<E>) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, expr.memory_start(), etl::size(expr) * sizeof(value_t<E>), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(const E& expr) -> cuda_memory<value_t<E>> {
    return cuda_allocate(expr, true);
}

template <typename E>
auto cuda_allocate(E* ptr, std::size_t n, bool copy = false) -> cuda_memory<E> {
    E* memory;

    auto cuda_status = cudaMalloc(&memory, n * sizeof(E));

    if (cuda_status != cudaSuccess) {
        std::cout << "cuda: Failed to allocate GPU memory: " << cudaGetErrorString(cuda_status) << std::endl;
        std::cout << "      Tried to allocate " << n * sizeof(E) << "B" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (copy) {
        cudaMemcpy(memory, ptr, n * sizeof(E), cudaMemcpyHostToDevice);
    }

    return {memory};
}

template <typename E>
auto cuda_allocate_copy(E* ptr, std::size_t n) -> cuda_memory<E> {
    return cuda_allocate(ptr, n, true);
}

} //end of namespace cublas

} //end of namespace impl

} //end of namespace etl
<|endoftext|>


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

#pragma once

namespace etl {

/*!
 * \brief Define traits to get vectorization information for types when no vector mode is available.
 */
template <typename T>
struct no_intrinsic_traits {
    static constexpr bool vectorizable     = false;      ///< Boolean flag indicating if the type is vectorizable or not
    static constexpr std::size_t size      = 1;          ///< Numbers of elements done at once
    static constexpr std::size_t alignment = alignof(T); ///< Necessary number of bytes of alignment for this type

    using intrinsic_type = T; ///< The intrinsic type
};

/*!
 * \brief Vectorization support when no vectorization is enabled.
 *
 * This class is purely here to ensure compilation, it will never be called at runtime
 */
struct no_vec {
    /*!
     * \brief The traits for this vectorization implementation
     */
    template <typename T>
    using traits = no_intrinsic_traits<T>;

    /*!
     * \brief The vector type for this vectorization implementation
     */
    template <typename T>
    using vec_type = typename traits<T>::intrinsic_type;

    /*!
     * \brief Unaligned store value to memory
     * \param memory The target memory
     * \param value The value to store
     */
    template <typename F, typename M>
    static inline void storeu(F* memory, M value) {
        cpp_unused(memory);
        cpp_unused(value);
    }

    /*!
     * \brief Aligned store value to memory
     * \param memory The target memory
     * \param value The value to store
     */
    template <typename F, typename M>
    static inline void store(F* memory, M value) {
        cpp_unused(memory);
        cpp_unused(value);
    }

    /*!
     * \brief Aligned load a vector from memory
     * \param memory The target memory
     * \return Vector of values from memory
     */
    template <typename F>
    static F load(const F* memory) {
        cpp_unused(memory);
        return F();
    }

    /*!
     * \brief Unaligned load a vector from memory
     * \param memory The target memory
     * \return Vector of values from memory
     */
    template <typename F>
    static F loadu(const F* memory) {
        cpp_unused(memory);
        return F();
    }

    /*!
     * \brief Create a vector containing the given value
     * \param value The value
     * \return Vector of value
     */
    template <typename F>
    static F set(F value) {
        cpp_unused(value);
        return F();
    }

    /*!
     * \brief Vector addition or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M add(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector subtraction or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M sub(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector multiplication of a and b and add the result to c
     * \param a The left hand side of the multiplication
     * \param b The right hand side of the multiplication
     * \param c The right hand side of the addition
     * \return Vector of the results
     */
    template <typename M>
    static M fmadd(M a, M b, M c) {
        cpp_unused(a);
        cpp_unused(b);
        cpp_unused(c);
        return M();
    }

    /*!
     * \brief Vector multiplication or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M mul(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector division or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M div(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector maximum or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M max(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector minimum or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M min(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector square root
     * \param value The input values
     * \return The square root of the input values
     */
    template <typename M>
    static M sqrt(M value) {
        cpp_unused(value);
        return M();
    }

    /*!
     * \brief Compute the negative value of the input
     * \param value The input values
     * \return The negative values of the input values
     */
    template <typename M>
    static M minus(M value) {
        cpp_unused(value);
        return M();
    }

    /*!
     * \brief Perform an horizontal sum of the given vector
     */
    template <typename T = float, typename M>
    static T hadd(M value) {
        cpp_unused(value);
        return T();
    }

    /*!
     * \brief Return a vector type filled with zeroes of the correct type
     */
    template<typename T>
    static T zero(){
        return T();
    }
};

} //end of namespace etl
<commit_msg>Fix no vectorization mode<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

namespace etl {

/*!
 * \brief Define traits to get vectorization information for types when no vector mode is available.
 */
template <typename T>
struct no_intrinsic_traits {
    static constexpr bool vectorizable     = false;      ///< Boolean flag indicating if the type is vectorizable or not
    static constexpr std::size_t size      = 1;          ///< Numbers of elements done at once
    static constexpr std::size_t alignment = alignof(T); ///< Necessary number of bytes of alignment for this type

    using intrinsic_type = T; ///< The intrinsic type
};

/*!
 * \brief Vectorization support when no vectorization is enabled.
 *
 * This class is purely here to ensure compilation, it will never be called at runtime
 */
struct no_vec {
    /*!
     * \brief The traits for this vectorization implementation
     */
    template <typename T>
    using traits = no_intrinsic_traits<T>;

    /*!
     * \brief The vector type for this vectorization implementation
     */
    template <typename T>
    using vec_type = typename traits<T>::intrinsic_type;

    /*!
     * \brief Unaligned store value to memory
     * \param memory The target memory
     * \param value The value to store
     */
    template <typename F, typename M>
    static inline void storeu(F* memory, M value) {
        cpp_unused(memory);
        cpp_unused(value);
    }

    /*!
     * \brief Aligned store value to memory
     * \param memory The target memory
     * \param value The value to store
     */
    template <typename F, typename M>
    static inline void store(F* memory, M value) {
        cpp_unused(memory);
        cpp_unused(value);
    }

    /*!
     * \brief Aligned load a vector from memory
     * \param memory The target memory
     * \return Vector of values from memory
     */
    template <typename F>
    static F load(const F* memory) {
        cpp_unused(memory);
        return F();
    }

    /*!
     * \brief Unaligned load a vector from memory
     * \param memory The target memory
     * \return Vector of values from memory
     */
    template <typename F>
    static F loadu(const F* memory) {
        cpp_unused(memory);
        return F();
    }

    /*!
     * \brief Create a vector containing the given value
     * \param value The value
     * \return Vector of value
     */
    template <typename F>
    static F set(F value) {
        cpp_unused(value);
        return F();
    }

    /*!
     * \brief Vector addition or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M add(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector subtraction or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M sub(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector multiplication of a and b and add the result to c
     * \param a The left hand side of the multiplication
     * \param b The right hand side of the multiplication
     * \param c The right hand side of the addition
     * \return Vector of the results
     */
    template <typename M>
    static M fmadd(M a, M b, M c) {
        cpp_unused(a);
        cpp_unused(b);
        cpp_unused(c);
        return M();
    }

    /*!
     * \brief Vector multiplication or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M mul(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector division or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M div(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector maximum or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M max(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector minimum or lhs and rhs
     * \param lhs The left hand side of the operation
     * \param rhs The right hand side of the operation
     * \return Vector of the results
     */
    template <typename M>
    static M min(M lhs, M rhs) {
        cpp_unused(lhs);
        cpp_unused(rhs);
        return M();
    }

    /*!
     * \brief Vector square root
     * \param value The input values
     * \return The square root of the input values
     */
    template <typename M>
    static M sqrt(M value) {
        cpp_unused(value);
        return M();
    }

    /*!
     * \brief Compute the negative value of the input
     * \param value The input values
     * \return The negative values of the input values
     */
    template <typename M>
    static M minus(M value) {
        cpp_unused(value);
        return M();
    }

    /*!
     * \brief Perform an horizontal sum of the given vector
     */
    template <typename M>
    static M hadd(M value) {
        cpp_unused(value);
        return M();
    }

    /*!
     * \brief Return a vector type filled with zeroes of the correct type
     */
    template<typename T>
    static T zero(){
        return T();
    }
};

} //end of namespace etl
<|endoftext|>


<commit_before>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_file.hpp
 * @brief       iris unit test ファイルクラス ファイル
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2011-2018, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
#define INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_

//======================================================================
// include
#include "iutest_internal_defs.hpp"
#include "iutest_stream.hpp"

namespace iutest
{

//======================================================================
// class
/**
 * @brief   ファイルクラスインターフェイス
*/
class IFile : public detail::IOutStream, public detail::IInStream
{
public:
    //! ファイルオープンモードフラグ
    enum OpenFlag
    {
        OpenRead    = 0x00000001,   //!< 読み込み
        OpenWrite   = 0x00000002,   //!< 書き込み
        OpenAppend  = 0x00000003    //!< 追記
    };
public:
    virtual ~IFile() {}
public:
    //! 開く
    virtual bool Open(const char* filename, int mode) = 0;
    //! 閉じる
    virtual void Close() = 0;
};

namespace detail
{

/**
 * @brief   ファイル処理クラスインターフェイス
*/
class IFileSystem
{
public:
    IFileSystem()
    {
        SetInstance(this);
    }
    virtual ~IFileSystem()
    {
        SetInstance(NULL);
    }

public:
    virtual void Initialize() {}

public:
    static IFileSystem* GetInstance() { return GetInstanceVariable().pInstance; }

public:
    static IFile* New()
    {
        IFileSystem* fs = GetInstance();
        if( fs == NULL )
        {
            return NULL;
        }
        IFile* p = fs->Create();
        return p;
    }
    static void Free(IFile* ptr)
    {
        IFileSystem* fs = GetInstance();
        if( fs == NULL )
        {
            return;
        }
        fs->Delete(ptr);
    }

    static bool ReadAll(const char* filename, ::std::string& dst)
    {
        IFile* fp = detail::IFileSystem::New();
        if(fp == NULL)
        {
            return false;
        }

        if(!fp->Open(filename, IFile::OpenRead))
        {
            detail::IFileSystem::Free(fp);
            return false;
        }

        dst = fp->ReadAll();
        detail::IFileSystem::Free(fp);
        return true;
    }

private:
    virtual IFile*  Create() = 0;
    virtual void    Delete(IFile*) = 0;

private:
    struct InstanceVariable
    {
        IFileSystem* pInstance;
    };

    static InstanceVariable& GetInstanceVariable() { static InstanceVariable v; return v; }
    static void SetInstance(IFileSystem* pFileSystem) { GetInstanceVariable().pInstance = pFileSystem; }
};

}   // end of namespace detail
}   // end of namespace iutest

namespace iutest
{

/**
 * @brief   ファイル処理クラスインターフェイス
*/
template<typename FILE>
class FileSystem : public detail::IFileSystem
{
private:
    virtual IFile*  Create() IUTEST_CXX_OVERRIDE        { return new FILE; }
    virtual void    Delete(IFile* ptr) IUTEST_CXX_OVERRIDE  { detail::Delete<FILE>(static_cast<FILE*>(ptr)); }
};

#if IUTEST_HAS_FOPEN

/**
 * @brief   標準ファイルクラス
*/
class StdioFile : public IFile
{
protected:
    FILE* m_fp;
public:
    StdioFile() IUTEST_CXX_NOEXCEPT_SPEC : m_fp(NULL) {}
    virtual ~StdioFile() { Close(); }
public:
    /**
     * @brief   開く
     * @param [in]  filename    = ファイルパス
     * @param [in]  mode        = モード
     * @return  成否
    */
    virtual bool Open(const char* filename, int mode) IUTEST_CXX_OVERRIDE
    {
        Close();
IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()
        switch( mode )
        {
        case IFile::OpenRead:
            m_fp = fopen(filename, "rb");
            break;
        case IFile::OpenWrite:
            m_fp = fopen(filename, "wb");
            break;
        case IFile::OpenAppend:
            m_fp = fopen(filename, "ab");
            break;
        default:
            break;
        }
IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()
        return m_fp != NULL;
    }
    /**
     * @brief   閉じる
    */
    virtual void Close() IUTEST_CXX_OVERRIDE
    {
        if( m_fp != NULL )
        {
            fclose(m_fp);
            m_fp = NULL;
        }
    }
    /**
     * @brief   書き込み
     * @param [in]  buf     = 書き込みバッファ
     * @param [in]  size    = バッファサイズ
     * @param [in]  cnt     = 書き込み回数
    */
    virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        if( fwrite(buf, size, cnt, m_fp) < cnt )
        {
            return false;
        }
        return true;
    }

    /**
     * @brief   読み込み
     * @param [in]  buf     = 読み込みバッファ
     * @param [in]  size    = 読み込みデータサイズ
     * @param [in]  cnt     = 読み込み回数
    */
    virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        if( fread(buf, size, cnt, m_fp) < cnt )
        {
            return false;
        }
        return true;
    }

    //! サイズ取得
    virtual size_t GetSize() IUTEST_CXX_OVERRIDE
    {
#if IUTEST_HAS_FILE_STAT
        return GetSize(m_fp);
#else
        return GetSizeBySeekSet(m_fp);
#endif
    }

public:
    static size_t GetSize(FILE* fp)
    {
        if( fp == NULL )
        {
            return 0;
        }
#if IUTEST_HAS_FILE_STAT
        internal::posix::StatStruct st;
        if (internal::posix::Stat(fp, &st) != 0)
        {
            return 0;
        }
        return st.st_size;
#else
        IUTEST_UNUSED_VAR(fp);
        return static_cast<size_t>(-1);
#endif
    }
    static size_t GetSizeBySeekSet(FILE* fp)
    {
        if( fp == NULL )
        {
            return 0;
        }
        const long pre = ftell(fp);
        if( pre != -1 )
        {
            if( fseek(fp, 0, SEEK_END) == 0 )
            {
                const size_t size = static_cast<size_t>(ftell(fp));
                IUTEST_UNUSED_RETURN(fseek(fp, pre, SEEK_SET));
                return size;
            }
        }
        return static_cast<size_t>(-1);
    }
};

class StdErrorFile : public StdioFile
{
public:
    StdErrorFile() IUTEST_CXX_NOEXCEPT_SPEC {}
    virtual ~StdErrorFile() { Close(); }
public:
    /**
     * @brief   開く
     * @param [in]  filename    = ファイルパス
     * @param [in]  mode        = モード
     * @return  成否
    */
    virtual bool Open(const char* , int ) IUTEST_CXX_OVERRIDE
    {
        m_fp = stderr;
        return true;
    }
    /**
     * @brief   閉じる
    */
    virtual void Close() IUTEST_CXX_OVERRIDE
    {
        m_fp = NULL;
    }
};

#endif

#if IUTEST_HAS_STRINGSTREAM

/**
 * @brief   文字列バッファ書き込み IFile インターフェースクラス
*/
class StringStreamFile : public IFile
{
public:
    virtual ~StringStreamFile() { Close(); }
public:
    /**
     * @brief   開く
     * @return  成否
    */
    virtual bool Open(const char* , int ) IUTEST_CXX_OVERRIDE
    {
        ss.clear();
        return true;
    }

    /**
     * @brief   閉じる
    */
    virtual void Close() IUTEST_CXX_OVERRIDE
    {
    }

    /**
     * @brief   書き込み
     * @param [in]  buf     = 書き込みバッファ
     * @param [in]  size    = バッファサイズ
     * @param [in]  cnt     = 書き込み回数
    */
    virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        for( size_t i=0; i < cnt; ++i )
        {
            ss.write(static_cast<const char*>(buf), size);
        }
        return true;
    }

    /**
     * @brief   読み込み
     * @param [in]  buf     = 読み込みバッファ
     * @param [in]  size    = 読み込みデータサイズ
     * @param [in]  cnt     = 読み込み回数
    */
    virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        char* p = static_cast<char*>(buf);
        for( size_t i = 0; i < cnt; ++i )
        {
            ss.read(p, size);
            p += size;
        }
        return true;
    }

    //! サイズ取得
    virtual size_t GetSize() IUTEST_CXX_OVERRIDE
    {
        ::std::stringstream::pos_type pre = ss.tellg();
        ss.seekg(0, ::std::ios::end);
        ::std::stringstream::pos_type size = ss.tellg();
        ss.seekg(pre, ::std::ios::beg);
        return static_cast<size_t>(size);
    }

    //! 全読み込み
    virtual ::std::string ReadAll() IUTEST_CXX_OVERRIDE
    {
        return ss.str();
    }
protected:
    ::std::stringstream ss;
};

#endif

namespace detail
{

/**
 * @brief   何もしない IFile インターフェースクラス
*/
class NoEffectFile : public IFile
{
public:
    virtual bool Open(const char*, int) IUTEST_CXX_OVERRIDE { return true; }
    virtual void Close() IUTEST_CXX_OVERRIDE {}
    virtual bool Write(const void*, size_t, size_t) IUTEST_CXX_OVERRIDE { return true;  }
    virtual bool Read(void*, size_t, size_t) IUTEST_CXX_OVERRIDE { return true; }
    virtual size_t GetSize() IUTEST_CXX_OVERRIDE { return 0; }
};

}   // end of namespace detail
}   // end of namespace iutest

#endif // INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
<commit_msg>fix file get size #128<commit_after>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_file.hpp
 * @brief       iris unit test ファイルクラス ファイル
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2011-2018, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
#define INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_

//======================================================================
// include
#include "iutest_internal_defs.hpp"
#include "iutest_stream.hpp"

namespace iutest
{

//======================================================================
// class
/**
 * @brief   ファイルクラスインターフェイス
*/
class IFile : public detail::IOutStream, public detail::IInStream
{
public:
    //! ファイルオープンモードフラグ
    enum OpenFlag
    {
        OpenRead    = 0x00000001,   //!< 読み込み
        OpenWrite   = 0x00000002,   //!< 書き込み
        OpenAppend  = 0x00000003    //!< 追記
    };
public:
    virtual ~IFile() {}
public:
    //! 開く
    virtual bool Open(const char* filename, int mode) = 0;
    //! 閉じる
    virtual void Close() = 0;
};

namespace detail
{

/**
 * @brief   ファイル処理クラスインターフェイス
*/
class IFileSystem
{
public:
    IFileSystem()
    {
        SetInstance(this);
    }
    virtual ~IFileSystem()
    {
        SetInstance(NULL);
    }

public:
    virtual void Initialize() {}

public:
    static IFileSystem* GetInstance() { return GetInstanceVariable().pInstance; }

public:
    static IFile* New()
    {
        IFileSystem* fs = GetInstance();
        if( fs == NULL )
        {
            return NULL;
        }
        IFile* p = fs->Create();
        return p;
    }
    static void Free(IFile* ptr)
    {
        IFileSystem* fs = GetInstance();
        if( fs == NULL )
        {
            return;
        }
        fs->Delete(ptr);
    }

    static bool ReadAll(const char* filename, ::std::string& dst)
    {
        IFile* fp = detail::IFileSystem::New();
        if(fp == NULL)
        {
            return false;
        }

        if(!fp->Open(filename, IFile::OpenRead))
        {
            detail::IFileSystem::Free(fp);
            return false;
        }

        dst = fp->ReadAll();
        detail::IFileSystem::Free(fp);
        return true;
    }

private:
    virtual IFile*  Create() = 0;
    virtual void    Delete(IFile*) = 0;

private:
    struct InstanceVariable
    {
        IFileSystem* pInstance;
    };

    static InstanceVariable& GetInstanceVariable() { static InstanceVariable v; return v; }
    static void SetInstance(IFileSystem* pFileSystem) { GetInstanceVariable().pInstance = pFileSystem; }
};

}   // end of namespace detail
}   // end of namespace iutest

namespace iutest
{

/**
 * @brief   ファイル処理クラスインターフェイス
*/
template<typename FILE>
class FileSystem : public detail::IFileSystem
{
private:
    virtual IFile*  Create() IUTEST_CXX_OVERRIDE        { return new FILE; }
    virtual void    Delete(IFile* ptr) IUTEST_CXX_OVERRIDE  { detail::Delete<FILE>(static_cast<FILE*>(ptr)); }
};

#if IUTEST_HAS_FOPEN

/**
 * @brief   標準ファイルクラス
*/
class StdioFile : public IFile
{
protected:
    FILE* m_fp;
public:
    StdioFile() IUTEST_CXX_NOEXCEPT_SPEC : m_fp(NULL) {}
    virtual ~StdioFile() { Close(); }
public:
    /**
     * @brief   開く
     * @param [in]  filename    = ファイルパス
     * @param [in]  mode        = モード
     * @return  成否
    */
    virtual bool Open(const char* filename, int mode) IUTEST_CXX_OVERRIDE
    {
        Close();
IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()
        switch( mode )
        {
        case IFile::OpenRead:
            m_fp = fopen(filename, "rb");
            break;
        case IFile::OpenWrite:
            m_fp = fopen(filename, "wb");
            break;
        case IFile::OpenAppend:
            m_fp = fopen(filename, "ab");
            break;
        default:
            break;
        }
IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()
        return m_fp != NULL;
    }
    /**
     * @brief   閉じる
    */
    virtual void Close() IUTEST_CXX_OVERRIDE
    {
        if( m_fp != NULL )
        {
            fclose(m_fp);
            m_fp = NULL;
        }
    }
    /**
     * @brief   書き込み
     * @param [in]  buf     = 書き込みバッファ
     * @param [in]  size    = バッファサイズ
     * @param [in]  cnt     = 書き込み回数
    */
    virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        if( fwrite(buf, size, cnt, m_fp) < cnt )
        {
            return false;
        }
        return true;
    }

    /**
     * @brief   読み込み
     * @param [in]  buf     = 読み込みバッファ
     * @param [in]  size    = 読み込みデータサイズ
     * @param [in]  cnt     = 読み込み回数
    */
    virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        if( fread(buf, size, cnt, m_fp) < cnt )
        {
            return false;
        }
        return true;
    }

    //! サイズ取得
    virtual size_t GetSize() IUTEST_CXX_OVERRIDE
    {
#if IUTEST_HAS_FILE_STAT
        return GetSize(m_fp);
#else
        return GetSizeBySeekSet(m_fp);
#endif
    }

public:
    static size_t GetSize(FILE* fp)
    {
        if( fp == NULL )
        {
            return 0;
        }
#if IUTEST_HAS_FILE_STAT
        internal::posix::StatStruct st;
        if (internal::posix::Stat(fp, &st) != 0)
        {
            return GetSizeBySeekSet(fp);
        }
        return st.st_size;
#else
        IUTEST_UNUSED_VAR(fp);
        return 0;
#endif
    }
    static size_t GetSizeBySeekSet(FILE* fp)
    {
        if( fp == NULL )
        {
            return 0;
        }
        const long pre = ftell(fp);
        if( (pre != -1) && (fseek(fp, 0, SEEK_END) == 0) )
        {
            const size_t size = static_cast<size_t>(ftell(fp));
            IUTEST_UNUSED_RETURN(fseek(fp, pre, SEEK_SET));
            return size;
        }
        return 0;
    }
};

class StdErrorFile : public StdioFile
{
public:
    StdErrorFile() IUTEST_CXX_NOEXCEPT_SPEC {}
    virtual ~StdErrorFile() { Close(); }
public:
    /**
     * @brief   開く
     * @param [in]  filename    = ファイルパス
     * @param [in]  mode        = モード
     * @return  成否
    */
    virtual bool Open(const char* , int ) IUTEST_CXX_OVERRIDE
    {
        m_fp = stderr;
        return true;
    }
    /**
     * @brief   閉じる
    */
    virtual void Close() IUTEST_CXX_OVERRIDE
    {
        m_fp = NULL;
    }
};

#endif

#if IUTEST_HAS_STRINGSTREAM

/**
 * @brief   文字列バッファ書き込み IFile インターフェースクラス
*/
class StringStreamFile : public IFile
{
public:
    virtual ~StringStreamFile() { Close(); }
public:
    /**
     * @brief   開く
     * @return  成否
    */
    virtual bool Open(const char* , int ) IUTEST_CXX_OVERRIDE
    {
        ss.clear();
        return true;
    }

    /**
     * @brief   閉じる
    */
    virtual void Close() IUTEST_CXX_OVERRIDE
    {
    }

    /**
     * @brief   書き込み
     * @param [in]  buf     = 書き込みバッファ
     * @param [in]  size    = バッファサイズ
     * @param [in]  cnt     = 書き込み回数
    */
    virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        for( size_t i=0; i < cnt; ++i )
        {
            ss.write(static_cast<const char*>(buf), size);
        }
        return true;
    }

    /**
     * @brief   読み込み
     * @param [in]  buf     = 読み込みバッファ
     * @param [in]  size    = 読み込みデータサイズ
     * @param [in]  cnt     = 読み込み回数
    */
    virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
    {
        char* p = static_cast<char*>(buf);
        for( size_t i = 0; i < cnt; ++i )
        {
            ss.read(p, size);
            p += size;
        }
        return true;
    }

    //! サイズ取得
    virtual size_t GetSize() IUTEST_CXX_OVERRIDE
    {
        ::std::stringstream::pos_type pre = ss.tellg();
        ss.seekg(0, ::std::ios::end);
        ::std::stringstream::pos_type size = ss.tellg();
        ss.seekg(pre, ::std::ios::beg);
        return static_cast<size_t>(size);
    }

    //! 全読み込み
    virtual ::std::string ReadAll() IUTEST_CXX_OVERRIDE
    {
        return ss.str();
    }
protected:
    ::std::stringstream ss;
};

#endif

namespace detail
{

/**
 * @brief   何もしない IFile インターフェースクラス
*/
class NoEffectFile : public IFile
{
public:
    virtual bool Open(const char*, int) IUTEST_CXX_OVERRIDE { return true; }
    virtual void Close() IUTEST_CXX_OVERRIDE {}
    virtual bool Write(const void*, size_t, size_t) IUTEST_CXX_OVERRIDE { return true;  }
    virtual bool Read(void*, size_t, size_t) IUTEST_CXX_OVERRIDE { return true; }
    virtual size_t GetSize() IUTEST_CXX_OVERRIDE { return 0; }
};

}   // end of namespace detail
}   // end of namespace iutest

#endif // INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Un Shyam
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.

*/

#ifndef TORRENT_DISABLE_ENCRYPTION

#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED

#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/rc4.h>

#include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	class dh_key_exchange
	{
	public:
		dh_key_exchange();
		~dh_key_exchange();
		bool good() const { return m_dh; }

		// Get local public key, always 96 bytes
		char const* get_local_key() const;

		// read remote_pubkey, generate and store shared secret in
		// m_dh_secret.
		int compute_secret(const char* remote_pubkey);

		char const* get_secret() const { return m_dh_secret; }

		sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; }

	private:
		int get_local_key_size() const
		{
			TORRENT_ASSERT(m_dh);
			return BN_num_bytes(m_dh->pub_key);
		}

		DH* m_dh;

		char m_dh_local_key[96];
		char m_dh_secret[96];
		sha1_hash m_xor_mask;
	};

	class RC4_handler // Non copyable
	{
	public:
		// Input longkeys must be 20 bytes
		RC4_handler(const sha1_hash& rc4_local_longkey,
					 const sha1_hash& rc4_remote_longkey)

		{
			RC4_set_key(&m_local_key, 20,
						 reinterpret_cast<unsigned char const*>(rc4_local_longkey.begin()));
			RC4_set_key(&m_remote_key, 20,
						 reinterpret_cast<unsigned char const*>(rc4_remote_longkey.begin()));

			// Discard first 1024 bytes
			char buf[1024];
			encrypt(buf, 1024);
			decrypt(buf, 1024);
		};

		~RC4_handler() {};

		void encrypt(char* pos, int len)
		{
			TORRENT_ASSERT(len >= 0);
			TORRENT_ASSERT(pos);

			RC4 (&m_local_key, len, reinterpret_cast<unsigned char const*>(pos),
				 reinterpret_cast<unsigned char*>(pos));
		}

		void decrypt(char* pos, int len)
		{
			TORRENT_ASSERT(len >= 0);
			TORRENT_ASSERT(pos);

			RC4 (&m_remote_key, len, reinterpret_cast<unsigned char const*>(pos),
				 reinterpret_cast<unsigned char*>(pos));
		}

	private:
		RC4_KEY m_local_key; // Key to encrypt outgoing data
		RC4_KEY m_remote_key; // Key to decrypt incoming data
	};

} // namespace libtorrent

#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED
#endif // TORRENT_DISABLE_ENCRYPTION

<commit_msg>formatting fixes for pe_crypto.cpp<commit_after>/*

Copyright (c) 2007, Un Shyam
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.

*/

#ifndef TORRENT_DISABLE_ENCRYPTION

#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED

#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/rc4.h>

#include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	class dh_key_exchange
	{
	public:
		dh_key_exchange();
		~dh_key_exchange();
		bool good() const { return m_dh; }

		// Get local public key, always 96 bytes
		char const* get_local_key() const;

		// read remote_pubkey, generate and store shared secret in
		// m_dh_secret.
		int compute_secret(const char* remote_pubkey);

		char const* get_secret() const { return m_dh_secret; }

		sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; }

	private:
		int get_local_key_size() const
		{
			TORRENT_ASSERT(m_dh);
			return BN_num_bytes(m_dh->pub_key);
		}

		DH* m_dh;

		char m_dh_local_key[96];
		char m_dh_secret[96];
		sha1_hash m_xor_mask;
	};

	class RC4_handler // Non copyable
	{
	public:
		// Input longkeys must be 20 bytes
		RC4_handler(const sha1_hash& rc4_local_longkey,
			const sha1_hash& rc4_remote_longkey)
		{
			RC4_set_key(&m_local_key, 20,
				reinterpret_cast<unsigned char const*>(rc4_local_longkey.begin()));
			RC4_set_key(&m_remote_key, 20,
				reinterpret_cast<unsigned char const*>(rc4_remote_longkey.begin()));

			// Discard first 1024 bytes
			char buf[1024];
			encrypt(buf, 1024);
			decrypt(buf, 1024);
		};

		~RC4_handler() {};

		void encrypt(char* pos, int len)
		{
			TORRENT_ASSERT(len >= 0);
			TORRENT_ASSERT(pos);

			RC4(&m_local_key, len, reinterpret_cast<unsigned char const*>(pos),
				reinterpret_cast<unsigned char*>(pos));
		}

		void decrypt(char* pos, int len)
		{
			TORRENT_ASSERT(len >= 0);
			TORRENT_ASSERT(pos);

			RC4(&m_remote_key, len, reinterpret_cast<unsigned char const*>(pos),
				reinterpret_cast<unsigned char*>(pos));
		}

	private:
		RC4_KEY m_local_key; // Key to encrypt outgoing data
		RC4_KEY m_remote_key; // Key to decrypt incoming data
	};

} // namespace libtorrent

#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED
#endif // TORRENT_DISABLE_ENCRYPTION

<|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.

*/

#ifndef TORRENT_XML_PARSE_HPP
#define TORRENT_XML_PARSE_HPP

#include <cctype>
#include <cstring>

namespace libtorrent
{
	enum
	{
		xml_start_tag,
		xml_end_tag,
		xml_empty_tag,
		xml_declaration_tag,
		xml_string,
		xml_attribute,
		xml_comment,
		xml_parse_error
	};

	// callback(int type, char const* name, char const* val)
	// str2 is only used for attributes. name is element or attribute
	// name and val is attribute value

	template <class CallbackType>
	void xml_parse(char* p, char* end, CallbackType callback)
	{
		for(;p != end; ++p)
		{
			char const* start = p;
			char const* val_start = 0;
			int token;
			// look for tag start
			for(; *p != '<' && p != end; ++p);

			if (p != start)
			{
				if (p != end)
				{
					TORRENT_ASSERT(*p == '<');
					*p = 0;
				}
				token = xml_string;
				callback(token, start, val_start);
				if (p != end) *p = '<';
			}

			if (p == end) break;

			// skip '<'
			++p;
			if (p != end && p+8 < end && string_begins_no_case("![CDATA[", p))
			{
				// CDATA. match '![CDATA['
				p += 8;
				start = p;
				while (p != end && !string_begins_no_case("]]>", p-2)) ++p;

				// parse error
				if (p == end)
				{
					token = xml_parse_error;
					start = "unexpected end of file";
					callback(token, start, val_start);
					break;
				}

				token = xml_string;
				char tmp = p[-2];
				p[-2] = 0;
				callback(token, start, val_start);
				p[-2] = tmp;
				continue;
			}

			// parse the name of the tag.
			for (start = p; p != end && *p != '>' && !isspace(*p); ++p);

			char* tag_name_end = p;

			// skip the attributes for now
			for (; p != end && *p != '>'; ++p);

			// parse error
			if (p == end)
			{
				token = xml_parse_error;
				start = "unexpected end of file";
				callback(token, start, val_start);
				break;
			}

			TORRENT_ASSERT(*p == '>');
			// save the character that terminated the tag name
			// it could be both '>' and ' '.
			char save = *tag_name_end;
			*tag_name_end = 0;

			char* tag_end = p;
			if (*start == '/')
			{
				++start;
				token = xml_end_tag;
				callback(token, start, val_start);
			}
			else if (*(p-1) == '/')
			{
				*(p-1) = 0;
				token = xml_empty_tag;
				callback(token, start, val_start);
				*(p-1) = '/';
				tag_end = p - 1;
			}
			else if (*start == '?' && *(p-1) == '?')
			{
				*(p-1) = 0;
				++start;
				token = xml_declaration_tag;
				callback(token, start, val_start);
				*(p-1) = '?';
				tag_end = p - 1;
			}
			else if (start + 5 < p && std::memcmp(start, "!--", 3) == 0 && std::memcmp(p-2, "--", 2) == 0)
			{
				start += 3;
				*(p-2) = 0;
				token = xml_comment;
				callback(token, start, val_start);
				*(p-2) = '-';
				tag_end = p - 2;
			}
			else
			{
				token = xml_start_tag;
				callback(token, start, val_start);
			}

			*tag_name_end = save;

			// parse attributes
			for (char* i = tag_name_end; i < tag_end; ++i)
			{
				// find start of attribute name
				for (; i != tag_end && isspace(*i); ++i);
				if (i == tag_end) break;
				start = i;
				// find end of attribute name
				for (; i != tag_end && *i != '=' && !isspace(*i); ++i);
				char* name_end = i;

				// look for equality sign
				for (; i != tag_end && *i != '='; ++i);

				if (i == tag_end)
				{
					token = xml_parse_error;
					val_start = 0;
					start = "garbage inside element brackets";
					callback(token, start, val_start);
					break;
				}

				++i;
				for (; i != tag_end && isspace(*i); ++i);
				// check for parse error (values must be quoted)
				if (i == tag_end || (*i != '\'' && *i != '\"'))
				{
					token = xml_parse_error;
					val_start = 0;
					start = "unquoted attribute value";
					callback(token, start, val_start);
					break;
				}
				char quote = *i;
				++i;
				val_start = i;
				for (; i != tag_end && *i != quote; ++i);
				// parse error (missing end quote)
				if (i == tag_end)
				{
					token = xml_parse_error;
					val_start = 0;
					start = "missing end quote on attribute";
					callback(token, start, val_start);
					break;
				}
				save = *i;
				*i = 0;
				*name_end = 0;
				token = xml_attribute;
				callback(token, start, val_start);
				*name_end = '=';
				*i = save;
			}
		}
	}

}

#endif

<commit_msg>fix windows isspace issue<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.

*/

#ifndef TORRENT_XML_PARSE_HPP
#define TORRENT_XML_PARSE_HPP

#include <cctype>
#include <cstring>

namespace libtorrent
{
	enum
	{
		xml_start_tag,
		xml_end_tag,
		xml_empty_tag,
		xml_declaration_tag,
		xml_string,
		xml_attribute,
		xml_comment,
		xml_parse_error
	};

	// callback(int type, char const* name, char const* val)
	// str2 is only used for attributes. name is element or attribute
	// name and val is attribute value

	template <class CallbackType>
	void xml_parse(char* p, char* end, CallbackType callback)
	{
		for(;p != end; ++p)
		{
			char const* start = p;
			char const* val_start = 0;
			int token;
			// look for tag start
			for(; *p != '<' && p != end; ++p);

			if (p != start)
			{
				if (p != end)
				{
					TORRENT_ASSERT(*p == '<');
					*p = 0;
				}
				token = xml_string;
				callback(token, start, val_start);
				if (p != end) *p = '<';
			}

			if (p == end) break;

			// skip '<'
			++p;
			if (p != end && p+8 < end && string_begins_no_case("![CDATA[", p))
			{
				// CDATA. match '![CDATA['
				p += 8;
				start = p;
				while (p != end && !string_begins_no_case("]]>", p-2)) ++p;

				// parse error
				if (p == end)
				{
					token = xml_parse_error;
					start = "unexpected end of file";
					callback(token, start, val_start);
					break;
				}

				token = xml_string;
				char tmp = p[-2];
				p[-2] = 0;
				callback(token, start, val_start);
				p[-2] = tmp;
				continue;
			}

			// parse the name of the tag.
			for (start = p; p != end && *p != '>' && !is_space(*p); ++p);

			char* tag_name_end = p;

			// skip the attributes for now
			for (; p != end && *p != '>'; ++p);

			// parse error
			if (p == end)
			{
				token = xml_parse_error;
				start = "unexpected end of file";
				callback(token, start, val_start);
				break;
			}

			TORRENT_ASSERT(*p == '>');
			// save the character that terminated the tag name
			// it could be both '>' and ' '.
			char save = *tag_name_end;
			*tag_name_end = 0;

			char* tag_end = p;
			if (*start == '/')
			{
				++start;
				token = xml_end_tag;
				callback(token, start, val_start);
			}
			else if (*(p-1) == '/')
			{
				*(p-1) = 0;
				token = xml_empty_tag;
				callback(token, start, val_start);
				*(p-1) = '/';
				tag_end = p - 1;
			}
			else if (*start == '?' && *(p-1) == '?')
			{
				*(p-1) = 0;
				++start;
				token = xml_declaration_tag;
				callback(token, start, val_start);
				*(p-1) = '?';
				tag_end = p - 1;
			}
			else if (start + 5 < p && std::memcmp(start, "!--", 3) == 0 && std::memcmp(p-2, "--", 2) == 0)
			{
				start += 3;
				*(p-2) = 0;
				token = xml_comment;
				callback(token, start, val_start);
				*(p-2) = '-';
				tag_end = p - 2;
			}
			else
			{
				token = xml_start_tag;
				callback(token, start, val_start);
			}

			*tag_name_end = save;

			// parse attributes
			for (char* i = tag_name_end; i < tag_end; ++i)
			{
				// find start of attribute name
				for (; i != tag_end && isspace(*i); ++i);
				if (i == tag_end) break;
				start = i;
				// find end of attribute name
				for (; i != tag_end && *i != '=' && !isspace(*i); ++i);
				char* name_end = i;

				// look for equality sign
				for (; i != tag_end && *i != '='; ++i);

				if (i == tag_end)
				{
					token = xml_parse_error;
					val_start = 0;
					start = "garbage inside element brackets";
					callback(token, start, val_start);
					break;
				}

				++i;
				for (; i != tag_end && isspace(*i); ++i);
				// check for parse error (values must be quoted)
				if (i == tag_end || (*i != '\'' && *i != '\"'))
				{
					token = xml_parse_error;
					val_start = 0;
					start = "unquoted attribute value";
					callback(token, start, val_start);
					break;
				}
				char quote = *i;
				++i;
				val_start = i;
				for (; i != tag_end && *i != quote; ++i);
				// parse error (missing end quote)
				if (i == tag_end)
				{
					token = xml_parse_error;
					val_start = 0;
					start = "missing end quote on attribute";
					callback(token, start, val_start);
					break;
				}
				save = *i;
				*i = 0;
				*name_end = 0;
				token = xml_attribute;
				callback(token, start, val_start);
				*name_end = '=';
				*i = save;
			}
		}
	}

}

#endif

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2002 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "PNGImageFile.h"
#include <string>
#include <iostream>
#include "pack.h"
#include "../zlib/zlib.h"

#ifdef WIN32
#include <winsock2.h>
#endif

//
// PNGImageFile
//

unsigned char PNGImageFile::pngHeader[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };

PNGImageFile::PNGImageFile(std::istream* stream) : ImageFile(stream), valid(true)
{
	char buffer[8];
	stream->read(buffer, 8);
	if (strncmp((char*)pngHeader, buffer, 8) != 0) {
		valid = false;
		return;
	}

	PNGChunk *c = PNGChunk::readChunk(stream);
	if (c->getType() != PNGChunk::IHDR) {
		valid = false;
		delete c;
		return;
	}

	unsigned char* data = c->getData();
	int width, height;
	data = (unsigned char *)nboUnpackInt(data, width);
	data = (unsigned char *)nboUnpackInt(data, height);

	data = (unsigned char *)nboUnpackUByte(data, bitDepth);
	data = (unsigned char *)nboUnpackUByte(data, colorDepth);
	data = (unsigned char *)nboUnpackUByte(data, compressionMethod);
	data = (unsigned char *)nboUnpackUByte(data, filterMethod);
	data = (unsigned char *)nboUnpackUByte(data, interlaceMethod);

	int lineBufferSize;

	switch (colorDepth) {
		case 0:
			lineBufferSize = (width * (8/bitDepth))+1;
		break;

		case 2:
			lineBufferSize = (width * 3 * (8/bitDepth))+1;
		break;

		case 3:
			lineBufferSize = (width * (8/bitDepth))+1;
		break;

		case 4:
			lineBufferSize = (width * 2 * (8/bitDepth))+1;
		break;

		case 6:
			lineBufferSize = (width * 4 * (8/bitDepth))+1;
		break;
	}
	lineBuffers[0] = new unsigned char[lineBufferSize];
	lineBuffers[1] = new unsigned char[lineBufferSize];
	activeBufferIndex = 0;

	init(3, width, height);
	valid = true;
}

PNGImageFile::~PNGImageFile()
{
	if (valid) {
		delete lineBuffers[0];
		delete lineBuffers[1];
	}
}

std::string				PNGImageFile::getExtension()
{
	return ".png";
}

bool					PNGImageFile::read(void* buffer)
{
	PNGChunk *c;
	int	bufferPos = 0;

	c = PNGChunk::readChunk(getStream());
	while ((c->getType() != PNGChunk::IDAT) && (c->getType() != PNGChunk::IEND)) {
		if (c->getType() == PNGChunk::PLTE)
			readPalette(c);
		delete c;
		c = PNGChunk::readChunk(getStream());
	}

	unsigned char *line = getLineBuffer();

	int err;
	z_stream stream;
	stream.next_out = line;
	stream.avail_out = lineBufferSize;
	stream.zalloc = (alloc_func)NULL;
	stream.zfree = (free_func)NULL;

	while (c->getType() == PNGChunk::IDAT) {

		stream.next_in = c->getData();
		stream.avail_in = c->getLength();

		err = inflateInit(&stream);
		if (err != Z_OK) {
			delete[] line;
			delete c;
			return false;
		}

		err = inflate(&stream, Z_FINISH);
		while (err == Z_BUF_ERROR) {
			//ignore filter bit for now, assume None!!!
			//also assume rgb (2)
			memcpy( ((unsigned char *)buffer)+bufferPos, line+1, lineBufferSize+1 );

			switchLineBuffers();
			line = getLineBuffer();
			stream.next_out = line;
			stream.avail_out = lineBufferSize;
			err = inflate(&stream, Z_FINISH);
		}
		if (err != Z_STREAM_END) {
			delete[] line;
			delete c;
			return false;
		}
		inflateEnd(&stream);

		delete c;
		c = PNGChunk::readChunk(getStream());
	}

	delete[] line;

	delete c;
	return true;
}

PNGPalette* PNGImageFile::readPalette(PNGChunk *c)
{
	int numColors = c->getLength() / sizeof(PNGRGB);
	PNGPalette *p = new PNGPalette(numColors);
	PNGRGB rgb;

	unsigned char *pData = c->getData();
	for (int i = 0; i < numColors; i++) {
		pData = (unsigned char *)nboUnpackUByte(pData, rgb.red);
		pData = (unsigned char *)nboUnpackUByte(pData, rgb.green);
		pData = (unsigned char *)nboUnpackUByte(pData, rgb.blue);
		p->add(rgb);
	}
	return p;
}

unsigned char *PNGImageFile::getLineBuffer(bool active)
{
	return lineBuffers[active ? activeBufferIndex : (1 - activeBufferIndex)];
}

void PNGImageFile::switchLineBuffers()
{
	activeBufferIndex = 1 - activeBufferIndex;
}

PNGPalette::PNGPalette(int nc)
{
	curColor = 0;
	numColors = nc;
	colors = new PNGRGB[nc];
}

PNGPalette::~PNGPalette()
{
	delete [] colors;
}

void PNGPalette::add(PNGRGB& color)
{
	colors[curColor++] = color;
}

int PNGChunk::IHDR = 'IHDR';
int PNGChunk::sRGB = 'sRGB';
int PNGChunk::PLTE = 'PLTE';
int PNGChunk::IDAT = 'IDAT';
int PNGChunk::IEND = 'IEND';

PNGChunk *PNGChunk::readChunk(std::istream *stream)
{
	PNGChunk *c = new PNGChunk();
	stream->read((char *) &c->length, 4);
	c->length = ntohl(c->length);
	stream->read((char *) &c->type, 4);
	c->type = ntohl(c->type);
	if (c->length > 0) {
		c->data = new unsigned char[c->length];
		stream->read((char*) c->data, c->length);
	}
	stream->read((char *) &c->crc, 4);
	c->crc = ntohl(c->crc);
	return c;
}

PNGChunk::PNGChunk()
: length(0), type(0), data(NULL), crc(0)
{
}

PNGChunk::~PNGChunk()
{
	if (data != NULL)
		delete[] data;
}

int PNGChunk::getLength()
{
	return length;
}

int PNGChunk::getType()
{
	return type;
}

unsigned char *PNGChunk::getData()
{
	return data;
}
<commit_msg>Fixed buffer overrun causing audio crash<commit_after>/* bzflag
 * Copyright (c) 1993 - 2002 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "PNGImageFile.h"
#include <string>
#include <iostream>
#include "pack.h"
#include "../zlib/zlib.h"

#ifdef WIN32
#include <winsock2.h>
#endif

//
// PNGImageFile
//

unsigned char PNGImageFile::pngHeader[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };

PNGImageFile::PNGImageFile(std::istream* stream) : ImageFile(stream), valid(true)
{
	char buffer[8];
	stream->read(buffer, 8);
	if (strncmp((char*)pngHeader, buffer, 8) != 0) {
		valid = false;
		return;
	}

	PNGChunk *c = PNGChunk::readChunk(stream);
	if (c->getType() != PNGChunk::IHDR) {
		valid = false;
		delete c;
		return;
	}

	unsigned char* data = c->getData();
	int width, height;
	data = (unsigned char *)nboUnpackInt(data, width);
	data = (unsigned char *)nboUnpackInt(data, height);

	data = (unsigned char *)nboUnpackUByte(data, bitDepth);
	data = (unsigned char *)nboUnpackUByte(data, colorDepth);
	data = (unsigned char *)nboUnpackUByte(data, compressionMethod);
	data = (unsigned char *)nboUnpackUByte(data, filterMethod);
	data = (unsigned char *)nboUnpackUByte(data, interlaceMethod);

	switch (colorDepth) {
		case 0:
			lineBufferSize = (width * (8/bitDepth))+1;
		break;

		case 2:
			lineBufferSize = (width * 3 * (8/bitDepth))+1;
		break;

		case 3:
			lineBufferSize = (width * (8/bitDepth))+1;
		break;

		case 4:
			lineBufferSize = (width * 2 * (8/bitDepth))+1;
		break;

		case 6:
			lineBufferSize = (width * 4 * (8/bitDepth))+1;
		break;
	}

	lineBuffers[0] = new unsigned char[lineBufferSize];
	lineBuffers[1] = new unsigned char[lineBufferSize];
	activeBufferIndex = 0;

	init(3, width, height);
	valid = true;
}

PNGImageFile::~PNGImageFile()
{
	if (valid) {
		delete lineBuffers[0];
		delete lineBuffers[1];
	}
}

std::string				PNGImageFile::getExtension()
{
	return ".png";
}

bool					PNGImageFile::read(void* buffer)
{
	PNGChunk *c;
	int	bufferPos = 0;

	c = PNGChunk::readChunk(getStream());
	while ((c->getType() != PNGChunk::IDAT) && (c->getType() != PNGChunk::IEND)) {
		if (c->getType() == PNGChunk::PLTE)
			readPalette(c);
		delete c;
		c = PNGChunk::readChunk(getStream());
	}

	unsigned char *line = getLineBuffer();

	int err;
	z_stream stream;
	stream.next_out = line;
	stream.avail_out = lineBufferSize;
	stream.zalloc = (alloc_func)NULL;
	stream.zfree = (free_func)NULL;

	while (c->getType() == PNGChunk::IDAT) {

		stream.next_in = c->getData();
		stream.avail_in = c->getLength();

		err = inflateInit(&stream);
		if (err != Z_OK) {
			delete[] line;
			delete c;
			return false;
		}

		err = inflate(&stream, Z_FINISH);
		while (err == Z_BUF_ERROR) {
			//ignore filter bit for now, assume None!!!
			//also assume rgb (2)
			memcpy( ((unsigned char *)buffer)+bufferPos, line+1, lineBufferSize-1 );
			bufferPos += lineBufferSize-1;

			switchLineBuffers();
			line = getLineBuffer();
			stream.next_out = line;
			stream.avail_out = lineBufferSize;
			err = inflate(&stream, Z_FINISH);
		}
		if (err != Z_STREAM_END) {
			delete[] line;
			delete c;
			return false;
		}
		inflateEnd(&stream);

		delete c;
		c = PNGChunk::readChunk(getStream());
	}

	delete[] line;

	delete c;
	return true;
}

PNGPalette* PNGImageFile::readPalette(PNGChunk *c)
{
	int numColors = c->getLength() / sizeof(PNGRGB);
	PNGPalette *p = new PNGPalette(numColors);
	PNGRGB rgb;

	unsigned char *pData = c->getData();
	for (int i = 0; i < numColors; i++) {
		pData = (unsigned char *)nboUnpackUByte(pData, rgb.red);
		pData = (unsigned char *)nboUnpackUByte(pData, rgb.green);
		pData = (unsigned char *)nboUnpackUByte(pData, rgb.blue);
		p->add(rgb);
	}
	return p;
}

unsigned char *PNGImageFile::getLineBuffer(bool active)
{
	return lineBuffers[active ? activeBufferIndex : (1 - activeBufferIndex)];
}

void PNGImageFile::switchLineBuffers()
{
	activeBufferIndex = 1 - activeBufferIndex;
}

PNGPalette::PNGPalette(int nc)
{
	curColor = 0;
	numColors = nc;
	colors = new PNGRGB[nc];
}

PNGPalette::~PNGPalette()
{
	delete [] colors;
}

void PNGPalette::add(PNGRGB& color)
{
	colors[curColor++] = color;
}

int PNGChunk::IHDR = 'IHDR';
int PNGChunk::sRGB = 'sRGB';
int PNGChunk::PLTE = 'PLTE';
int PNGChunk::IDAT = 'IDAT';
int PNGChunk::IEND = 'IEND';

PNGChunk *PNGChunk::readChunk(std::istream *stream)
{
	PNGChunk *c = new PNGChunk();
	stream->read((char *) &c->length, 4);
	c->length = ntohl(c->length);
	stream->read((char *) &c->type, 4);
	c->type = ntohl(c->type);
	if (c->length > 0) {
		c->data = new unsigned char[c->length];
		stream->read((char*) c->data, c->length);
	}
	stream->read((char *) &c->crc, 4);
	c->crc = ntohl(c->crc);
	return c;
}

PNGChunk::PNGChunk()
: length(0), type(0), data(NULL), crc(0)
{
}

PNGChunk::~PNGChunk()
{
	if (data != NULL)
		delete[] data;
}

int PNGChunk::getLength()
{
	return length;
}

int PNGChunk::getType()
{
	return type;
}

unsigned char *PNGChunk::getData()
{
	return data;
}
<|endoftext|>