<commit_before>// Author: Enrico Guiraud, Danilo Piparo CERN  09/2018

/*************************************************************************
 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RCOLUMNVALUE
#define ROOT_RCOLUMNVALUE

#include <ROOT/RDF/RCustomColumnBase.hxx>
#include <ROOT/RDF/Utils.hxx> // IsRVec_t, TypeID2TypeName
#include <ROOT/RIntegerSequence.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <ROOT/RVec.hxx>
#include <ROOT/TypeTraits.hxx> // TakeFirstParameter_t
#include <RtypesCore.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>

#include <cstring> // strcmp
#include <initializer_list>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>

namespace ROOT {
namespace Internal {
namespace RDF {
using namespace ROOT::VecOps;

/**
\class ROOT::Internal::RDF::RColumnValue
\ingroup dataframe
\brief Helper class that updates and returns TTree branches as well as RDataFrame temporary columns
\tparam T The type of the column

RDataFrame nodes must access two different types of values during the event loop:
values of real branches, for which TTreeReader{Values,Arrays} act as proxies, or
temporary columns whose values are generated on the fly. While the type of the
value is known at compile time (or just-in-time), it is only at runtime that nodes
can check whether a certain value is generated on the fly or not.

RColumnValue abstracts this difference by providing the same interface for
both cases and handling the reading or generation of new values transparently.
Only one of the two data members fReaderProxy or fValuePtr will be non-null
for a given RColumnValue, depending on whether the value comes from a real
TTree branch or from a temporary column respectively.

RDataFrame nodes can store tuples of RColumnValues and retrieve an updated
value for the column via the `Get` method.
**/
template <typename T>
class R__CLING_PTRCHECK(off) RColumnValue {
// R__CLING_PTRCHECK is disabled because all pointers are hand-crafted by RDF.

   using MustUseRVec_t = IsRVec_t<T>;

   // ColumnValue_t is the type of the column or the type of the elements of an array column
   using ColumnValue_t = typename std::conditional<MustUseRVec_t::value, TakeFirstParameter_t<T>, T>::type;
   using TreeReader_t = typename std::conditional<MustUseRVec_t::value, TTreeReaderArray<ColumnValue_t>,
                                                  TTreeReaderValue<ColumnValue_t>>::type;

   /// RColumnValue has a slightly different behaviour whether the column comes from a TTreeReader, a RDataFrame Define
   /// or a RDataSource. It stores which it is as an enum.
   enum class EColumnKind { kTree, kCustomColumn, kDataSource, kInvalid };
   // Set to the correct value by MakeProxy or SetTmpColumn
   EColumnKind fColumnKind = EColumnKind::kInvalid;
   /// The slot this value belongs to. Only needed when querying custom column values, it is set in `SetTmpColumn`.
   unsigned int fSlot = std::numeric_limits<unsigned int>::max();

   // Each element of the following stacks will be in use by a _single task_.
   // Each task will push one element when it starts and pop it when it ends.
   // Stacks will typically be very small (1-2 elements typically) and will only grow over size 1 in case of interleaved
   // task execution i.e. when more than one task needs readers in this worker thread.

   /// Owning ptrs to a TTreeReaderValue or TTreeReaderArray. Only used for Tree columns.
   std::unique_ptr<TreeReader_t> fTreeReader;
   /// Non-owning ptrs to the value of a custom column.
   T *fCustomValuePtr;
   /// Non-owning ptrs to the value of a data-source column.
   T **fDSValuePtr;
   /// Non-owning ptrs to the node responsible for the custom column. Needed when querying custom values.
   RCustomColumnBase *fCustomColumn;
   /// Enumerator for the different properties of the branch storage in memory
   enum class EStorageType : char { kContiguous, kUnknown, kSparse };
   /// Signal whether we ever checked that the branch we are reading with a TTreeReaderArray stores array elements
   /// in contiguous memory. Only used when T == RVec<U>.
   EStorageType fStorageType = EStorageType::kUnknown;
   /// If MustUseRVec, i.e. we are reading an array, we return a reference to this RVec to clients
   RVec<ColumnValue_t> fRVec;
   bool fCopyWarningPrinted = false;

public:
   RColumnValue(){};

   void SetTmpColumn(unsigned int slot, RCustomColumnBase *customColumn)
   {
      fCustomColumn = customColumn;
      // Here we compare names and not typeinfos since they may come from two different contexts: a compiled
      // and a jitted one.
      if (0 != strcmp(customColumn->GetTypeId().name(), typeid(T).name()))
         throw std::runtime_error(
            std::string("RColumnValue: type specified for column \"" + customColumn->GetName() + "\" is ") +
            TypeID2TypeName(typeid(T)) + " but temporary column has type " +
            TypeID2TypeName(customColumn->GetTypeId()));

      if (customColumn->IsDataSourceColumn()) {
         fColumnKind = EColumnKind::kDataSource;
         fDSValuePtr = static_cast<T **>(customColumn->GetValuePtr(slot));
      } else {
         fColumnKind = EColumnKind::kCustomColumn;
         fCustomValuePtr = static_cast<T *>(customColumn->GetValuePtr(slot));
      }
      fSlot = slot;
   }

   void MakeProxy(TTreeReader *r, const std::string &bn)
   {
      fColumnKind = EColumnKind::kTree;
      fTreeReader = std::make_unique<TreeReader_t>(*r, bn.c_str());
   }

   /// This overload is used to return scalar quantities (i.e. types that are not read into a RVec)
   // This method is executed inside the event-loop, many times per entry
   // If need be, the if statement can be avoided using thunks
   // (have both branches inside functions and have a pointer to the branch to be executed)
   template <typename U = T, typename std::enable_if<!RColumnValue<U>::MustUseRVec_t::value, int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         return *(fTreeReader->Get());
      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload is used to return arrays (i.e. types that are read into a RVec).
   /// In this case the returned T is always a RVec<ColumnValue_t>.
   /// RVec<bool> is treated differently, in a separate overload.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && !std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         // We only use TTreeReaderArrays to read columns that users flagged as type `RVec`, so we need to check
         // that the branch stores the array as contiguous memory that we can actually wrap in an `RVec`.
         // Currently we need the first entry to have been loaded to perform the check
         // TODO Move check to `MakeProxy` once Axel implements this kind of check in TTreeReaderArray using
         // TBranchProxy

         if (EStorageType::kUnknown == fStorageType && readerArray.GetSize() > 1) {
            // We can decide since the array is long enough
            fStorageType =
               (1 == (&readerArray[1] - &readerArray[0])) ? EStorageType::kContiguous : EStorageType::kSparse;
         }

         const auto readerArraySize = readerArray.GetSize();
         if (EStorageType::kContiguous == fStorageType ||
             (EStorageType::kUnknown == fStorageType && readerArray.GetSize() < 2)) {
            if (readerArraySize > 0) {
               // trigger loading of the contents of the TTreeReaderArray
               // the address of the first element in the reader array is not necessarily equal to
               // the address returned by the GetAddress method
               auto readerArrayAddr = &readerArray.At(0);
               T rvec(readerArrayAddr, readerArraySize);
               std::swap(fRVec, rvec);
            } else {
               T emptyVec{};
               std::swap(fRVec, emptyVec);
            }
         } else {
            // The storage is not contiguous or we don't know yet: we cannot but copy into the rvec
#ifndef NDEBUG
            if (!fCopyWarningPrinted) {
               Warning("RColumnValue::Get",
                       "Branch %s hangs from a non-split branch. A copy is being performed in order "
                       "to properly read the content.",
                       readerArray.GetBranchName());
               fCopyWarningPrinted = true;
            }
#else
            (void)fCopyWarningPrinted;
#endif
            if (readerArraySize > 0) {
               T rvec(readerArray.begin(), readerArray.end());
               std::swap(fRVec, rvec);
            } else {
               T emptyVec{};
               std::swap(fRVec, emptyVec);
            }
         }
         return fRVec;

      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload covers the RVec<bool> case. In this case we always copy the contents of TTreeReaderArray<bool>
   /// into RVec<bool> (never take a view into the memory buffer) because the underlying memory buffer might be the
   /// one of a std::vector<bool>, which is not a contiguous slab of bool values.
   /// Note that this also penalizes the case in which the column type is actually bool[], but the possible performance
   /// gains in this edge case is probably not worth the extra complication required to differentiate the two cases.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         const auto readerArraySize = readerArray.GetSize();
         if (readerArraySize > 0) {
            // always perform a copy
            T rvec(readerArray.begin(), readerArray.end());
            std::swap(fRVec, rvec);
         } else {
            T emptyVec{};
            std::swap(fRVec, emptyVec);
         }
         return fRVec;
      } else {
         // business as usual
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   void Reset()
   {
      // This method should by all means not be removed, together with all
      // of its callers, otherwise a race condition takes place in which a
      // TTreeReader and its TTreeReader{Value,Array}s could be deleted
      // concurrently:
      // - Thread #1) a task ends and pushes back processing slot
      // - Thread #2) a task starts and overwrites thread-local TTreeReaderValues
      // - Thread #1) first task deletes TTreeReader
      // See https://github.com/root-project/root/commit/26e8ace6e47de6794ac9ec770c3bbff9b7f2e945
      if (EColumnKind::kTree == fColumnKind) {
         fTreeReader.reset();
      }
   }
};

// Some extern instantiations to speed-up compilation/interpretation time
// These are not active if c++17 is enabled because of a bug in our clang
// See ROOT-9499.
#if __cplusplus < 201703L
extern template class RColumnValue<int>;
extern template class RColumnValue<unsigned int>;
extern template class RColumnValue<char>;
extern template class RColumnValue<unsigned char>;
extern template class RColumnValue<float>;
extern template class RColumnValue<double>;
extern template class RColumnValue<Long64_t>;
extern template class RColumnValue<ULong64_t>;
extern template class RColumnValue<std::vector<int>>;
extern template class RColumnValue<std::vector<unsigned int>>;
extern template class RColumnValue<std::vector<char>>;
extern template class RColumnValue<std::vector<unsigned char>>;
extern template class RColumnValue<std::vector<float>>;
extern template class RColumnValue<std::vector<double>>;
extern template class RColumnValue<std::vector<Long64_t>>;
extern template class RColumnValue<std::vector<ULong64_t>>;
#endif

template <typename T>
struct TRDFValueTuple {
};

template <typename... BranchTypes>
struct TRDFValueTuple<TypeList<BranchTypes...>> {
   using type = std::tuple<RColumnValue<BranchTypes>...>;
};

template <typename BranchType>
using RDFValueTuple_t = typename TRDFValueTuple<BranchType>::type;

/// Clear the proxies of a tuple of RColumnValues
template <typename ValueTuple, std::size_t... S>
void ResetRDFValueTuple(ValueTuple &values, std::index_sequence<S...>)
{
   // hack to expand a parameter pack without c++17 fold expressions.
   std::initializer_list<int> expander{(std::get<S>(values).Reset(), 0)...};
   (void)expander; // avoid "unused variable" warnings
}

} // ns RDF
} // ns Internal
} // ns ROOT

#endif // ROOT_RCOLUMNVALUE
<commit_msg>[DF][ROOT-9736] Allow custom columns deal with inherited types<commit_after>// Author: Enrico Guiraud, Danilo Piparo CERN  09/2018

/*************************************************************************
 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RCOLUMNVALUE
#define ROOT_RCOLUMNVALUE

#include <ROOT/RDF/RCustomColumnBase.hxx>
#include <ROOT/RDF/Utils.hxx> // IsRVec_t, TypeID2TypeName
#include <ROOT/RIntegerSequence.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <ROOT/RVec.hxx>
#include <ROOT/TypeTraits.hxx> // TakeFirstParameter_t
#include <RtypesCore.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>

#include <cstring> // strcmp
#include <initializer_list>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>

namespace ROOT {
namespace Internal {
namespace RDF {
using namespace ROOT::VecOps;

/**
\class ROOT::Internal::RDF::RColumnValue
\ingroup dataframe
\brief Helper class that updates and returns TTree branches as well as RDataFrame temporary columns
\tparam T The type of the column

RDataFrame nodes must access two different types of values during the event loop:
values of real branches, for which TTreeReader{Values,Arrays} act as proxies, or
temporary columns whose values are generated on the fly. While the type of the
value is known at compile time (or just-in-time), it is only at runtime that nodes
can check whether a certain value is generated on the fly or not.

RColumnValue abstracts this difference by providing the same interface for
both cases and handling the reading or generation of new values transparently.
Only one of the two data members fReaderProxy or fValuePtr will be non-null
for a given RColumnValue, depending on whether the value comes from a real
TTree branch or from a temporary column respectively.

RDataFrame nodes can store tuples of RColumnValues and retrieve an updated
value for the column via the `Get` method.
**/
template <typename T>
class R__CLING_PTRCHECK(off) RColumnValue {
// R__CLING_PTRCHECK is disabled because all pointers are hand-crafted by RDF.

   using MustUseRVec_t = IsRVec_t<T>;

   // ColumnValue_t is the type of the column or the type of the elements of an array column
   using ColumnValue_t = typename std::conditional<MustUseRVec_t::value, TakeFirstParameter_t<T>, T>::type;
   using TreeReader_t = typename std::conditional<MustUseRVec_t::value, TTreeReaderArray<ColumnValue_t>,
                                                  TTreeReaderValue<ColumnValue_t>>::type;

   /// RColumnValue has a slightly different behaviour whether the column comes from a TTreeReader, a RDataFrame Define
   /// or a RDataSource. It stores which it is as an enum.
   enum class EColumnKind { kTree, kCustomColumn, kDataSource, kInvalid };
   // Set to the correct value by MakeProxy or SetTmpColumn
   EColumnKind fColumnKind = EColumnKind::kInvalid;
   /// The slot this value belongs to. Only needed when querying custom column values, it is set in `SetTmpColumn`.
   unsigned int fSlot = std::numeric_limits<unsigned int>::max();

   // Each element of the following stacks will be in use by a _single task_.
   // Each task will push one element when it starts and pop it when it ends.
   // Stacks will typically be very small (1-2 elements typically) and will only grow over size 1 in case of interleaved
   // task execution i.e. when more than one task needs readers in this worker thread.

   /// Owning ptrs to a TTreeReaderValue or TTreeReaderArray. Only used for Tree columns.
   std::unique_ptr<TreeReader_t> fTreeReader;
   /// Non-owning ptrs to the value of a custom column.
   T *fCustomValuePtr;
   /// Non-owning ptrs to the value of a data-source column.
   T **fDSValuePtr;
   /// Non-owning ptrs to the node responsible for the custom column. Needed when querying custom values.
   RCustomColumnBase *fCustomColumn;
   /// Enumerator for the different properties of the branch storage in memory
   enum class EStorageType : char { kContiguous, kUnknown, kSparse };
   /// Signal whether we ever checked that the branch we are reading with a TTreeReaderArray stores array elements
   /// in contiguous memory. Only used when T == RVec<U>.
   EStorageType fStorageType = EStorageType::kUnknown;
   /// If MustUseRVec, i.e. we are reading an array, we return a reference to this RVec to clients
   RVec<ColumnValue_t> fRVec;
   bool fCopyWarningPrinted = false;

public:
   RColumnValue(){};

   void SetTmpColumn(unsigned int slot, RCustomColumnBase *customColumn)
   {
      fCustomColumn = customColumn;
      // Here we compare names and not typeinfos since they may come from two different contexts: a compiled
      // and a jitted one.
      const auto diffTypes = (0 != strcmp(customColumn->GetTypeId().name(), typeid(T).name()));
      auto inheritedType = [&](){
         auto colTClass = TClass::GetClass(customColumn->GetTypeId());
         return colTClass && colTClass->InheritsFrom(TClass::GetClass<T>());
      };

      if (diffTypes && !inheritedType())
         throw std::runtime_error(
            std::string("RColumnValue: type specified for column \"" + customColumn->GetName() + "\" is ") +
            TypeID2TypeName(typeid(T)) + " but temporary column has type " +
            TypeID2TypeName(customColumn->GetTypeId()));

      if (customColumn->IsDataSourceColumn()) {
         fColumnKind = EColumnKind::kDataSource;
         fDSValuePtr = static_cast<T **>(customColumn->GetValuePtr(slot));
      } else {
         fColumnKind = EColumnKind::kCustomColumn;
         fCustomValuePtr = static_cast<T *>(customColumn->GetValuePtr(slot));
      }
      fSlot = slot;
   }

   void MakeProxy(TTreeReader *r, const std::string &bn)
   {
      fColumnKind = EColumnKind::kTree;
      fTreeReader = std::make_unique<TreeReader_t>(*r, bn.c_str());
   }

   /// This overload is used to return scalar quantities (i.e. types that are not read into a RVec)
   // This method is executed inside the event-loop, many times per entry
   // If need be, the if statement can be avoided using thunks
   // (have both branches inside functions and have a pointer to the branch to be executed)
   template <typename U = T, typename std::enable_if<!RColumnValue<U>::MustUseRVec_t::value, int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         return *(fTreeReader->Get());
      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload is used to return arrays (i.e. types that are read into a RVec).
   /// In this case the returned T is always a RVec<ColumnValue_t>.
   /// RVec<bool> is treated differently, in a separate overload.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && !std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         // We only use TTreeReaderArrays to read columns that users flagged as type `RVec`, so we need to check
         // that the branch stores the array as contiguous memory that we can actually wrap in an `RVec`.
         // Currently we need the first entry to have been loaded to perform the check
         // TODO Move check to `MakeProxy` once Axel implements this kind of check in TTreeReaderArray using
         // TBranchProxy

         if (EStorageType::kUnknown == fStorageType && readerArray.GetSize() > 1) {
            // We can decide since the array is long enough
            fStorageType =
               (1 == (&readerArray[1] - &readerArray[0])) ? EStorageType::kContiguous : EStorageType::kSparse;
         }

         const auto readerArraySize = readerArray.GetSize();
         if (EStorageType::kContiguous == fStorageType ||
             (EStorageType::kUnknown == fStorageType && readerArray.GetSize() < 2)) {
            if (readerArraySize > 0) {
               // trigger loading of the contents of the TTreeReaderArray
               // the address of the first element in the reader array is not necessarily equal to
               // the address returned by the GetAddress method
               auto readerArrayAddr = &readerArray.At(0);
               T rvec(readerArrayAddr, readerArraySize);
               std::swap(fRVec, rvec);
            } else {
               T emptyVec{};
               std::swap(fRVec, emptyVec);
            }
         } else {
            // The storage is not contiguous or we don't know yet: we cannot but copy into the rvec
#ifndef NDEBUG
            if (!fCopyWarningPrinted) {
               Warning("RColumnValue::Get",
                       "Branch %s hangs from a non-split branch. A copy is being performed in order "
                       "to properly read the content.",
                       readerArray.GetBranchName());
               fCopyWarningPrinted = true;
            }
#else
            (void)fCopyWarningPrinted;
#endif
            if (readerArraySize > 0) {
               T rvec(readerArray.begin(), readerArray.end());
               std::swap(fRVec, rvec);
            } else {
               T emptyVec{};
               std::swap(fRVec, emptyVec);
            }
         }
         return fRVec;

      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload covers the RVec<bool> case. In this case we always copy the contents of TTreeReaderArray<bool>
   /// into RVec<bool> (never take a view into the memory buffer) because the underlying memory buffer might be the
   /// one of a std::vector<bool>, which is not a contiguous slab of bool values.
   /// Note that this also penalizes the case in which the column type is actually bool[], but the possible performance
   /// gains in this edge case is probably not worth the extra complication required to differentiate the two cases.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         const auto readerArraySize = readerArray.GetSize();
         if (readerArraySize > 0) {
            // always perform a copy
            T rvec(readerArray.begin(), readerArray.end());
            std::swap(fRVec, rvec);
         } else {
            T emptyVec{};
            std::swap(fRVec, emptyVec);
         }
         return fRVec;
      } else {
         // business as usual
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   void Reset()
   {
      // This method should by all means not be removed, together with all
      // of its callers, otherwise a race condition takes place in which a
      // TTreeReader and its TTreeReader{Value,Array}s could be deleted
      // concurrently:
      // - Thread #1) a task ends and pushes back processing slot
      // - Thread #2) a task starts and overwrites thread-local TTreeReaderValues
      // - Thread #1) first task deletes TTreeReader
      // See https://github.com/root-project/root/commit/26e8ace6e47de6794ac9ec770c3bbff9b7f2e945
      if (EColumnKind::kTree == fColumnKind) {
         fTreeReader.reset();
      }
   }
};

// Some extern instantiations to speed-up compilation/interpretation time
// These are not active if c++17 is enabled because of a bug in our clang
// See ROOT-9499.
#if __cplusplus < 201703L
extern template class RColumnValue<int>;
extern template class RColumnValue<unsigned int>;
extern template class RColumnValue<char>;
extern template class RColumnValue<unsigned char>;
extern template class RColumnValue<float>;
extern template class RColumnValue<double>;
extern template class RColumnValue<Long64_t>;
extern template class RColumnValue<ULong64_t>;
extern template class RColumnValue<std::vector<int>>;
extern template class RColumnValue<std::vector<unsigned int>>;
extern template class RColumnValue<std::vector<char>>;
extern template class RColumnValue<std::vector<unsigned char>>;
extern template class RColumnValue<std::vector<float>>;
extern template class RColumnValue<std::vector<double>>;
extern template class RColumnValue<std::vector<Long64_t>>;
extern template class RColumnValue<std::vector<ULong64_t>>;
#endif

template <typename T>
struct TRDFValueTuple {
};

template <typename... BranchTypes>
struct TRDFValueTuple<TypeList<BranchTypes...>> {
   using type = std::tuple<RColumnValue<BranchTypes>...>;
};

template <typename BranchType>
using RDFValueTuple_t = typename TRDFValueTuple<BranchType>::type;

/// Clear the proxies of a tuple of RColumnValues
template <typename ValueTuple, std::size_t... S>
void ResetRDFValueTuple(ValueTuple &values, std::index_sequence<S...>)
{
   // hack to expand a parameter pack without c++17 fold expressions.
   std::initializer_list<int> expander{(std::get<S>(values).Reset(), 0)...};
   (void)expander; // avoid "unused variable" warnings
}

} // ns RDF
} // ns Internal
} // ns ROOT

#endif // ROOT_RCOLUMNVALUE
<|endoftext|>


<commit_before>#include "unit.h"

namespace allpix {
    /**
     * The matching converter function is automatically found if available. To add a new conversion the \ref from_string_impl
     * function should be overloaded. The string is passed as first argument to this function, the second argument should be
     * an \ref allpix::type_tag with the type to convert to.
     */
    template <typename T> T from_string(std::string str) {
        // Use tag dispatch to select the correct helper function
        return from_string_impl(str, type_tag<T>());
    }

    template <typename T, typename = std::enable_if_t<!std::is_arithmetic<T>::value>, typename = void>
    constexpr T from_string_impl(const std::string&, type_tag<T>) {
        static_assert(std::is_same<T, void>::value,
                      "Conversion to this type is not implemented: an overload should be added to support this conversion");
        return T();
    }

    /**
     * The unit system is used through \ref Units::get to parse unit suffixes and convert the values to the appropriate
     * standard framework unit.
     */
    template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
    T from_string_impl(std::string str, type_tag<T>) {
        str = from_string_helper(str);

        // Find an optional set of units
        auto unit_idx = str.size() - 1;
        for(; unit_idx > 0; --unit_idx) {
            if(!isalpha(str[unit_idx]) && str[unit_idx] != '*' && str[unit_idx] != '/') {
                break;
            }
        }
        std::string units = str.substr(unit_idx + 1);

        // Get the actual arithmetic value
        std::istringstream sstream(str.substr(0, unit_idx + 1));
        T ret_value = 0;
        sstream >> ret_value;

        // Check if the reading was succesfull and everything was read
        if(sstream.fail() || sstream.peek() != EOF) {
            throw std::invalid_argument("conversion not possible");
        }

        // Apply all the units if they exists
        if(!units.empty()) {
            ret_value = allpix::Units::get(ret_value, units);
        }
        return ret_value;
    }

    /**
     * The matching converter function is automatically found if available. To add a new conversion the \ref to_string_impl
     * function should be overloaded. The string is passed as first argument to this function, the second argument should be
     * an \ref allpix::empty_tag (required to search in the allpix namespace).
     */
    template <typename T> std::string to_string(T inp) {
        // Use tag dispatch to select the correct implementation
        return to_string_impl(inp, empty_tag());
    }

    template <typename T, typename = std::enable_if_t<!std::is_arithmetic<T>::value>, typename = void>
    constexpr void to_string_impl(T, empty_tag) {
        static_assert(std::is_same<T, void>::value,
                      "Conversion to this type is not implemented: an overload should be added to support this conversion");
    }
    template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
    std::string to_string_impl(T inp, empty_tag) {
        std::ostringstream out;
        out << inp;
        return out.str();
    }

    template <typename T> std::vector<T> split(std::string str, const std::string& delims) {
        str = trim(str, delims);

        // If the input string is empty, simply return empty container
        if(str.empty()) {
            return std::vector<T>();
        }

        // Else we have data, clear the default elements and chop the string:
        std::vector<T> elems;

        // Loop through the string
        std::size_t prev = 0, pos;
        while((pos = str.find_first_of(delims, prev)) != std::string::npos) {
            if(pos > prev) {
                elems.push_back(from_string<T>(str.substr(prev, pos - prev)));
            }
            prev = pos + 1;
        }
        if(prev < str.length()) {
            elems.push_back(from_string<T>(str.substr(prev, std::string::npos)));
        }

        return elems;
    }
} // namespace allpix
<commit_msg>fix redefine default template argument<commit_after>#include "unit.h"

namespace allpix {
    /**
     * The matching converter function is automatically found if available. To add a new conversion the \ref from_string_impl
     * function should be overloaded. The string is passed as first argument to this function, the second argument should be
     * an \ref allpix::type_tag with the type to convert to.
     */
    template <typename T> T from_string(std::string str) {
        // Use tag dispatch to select the correct helper function
        return from_string_impl(str, type_tag<T>());
    }

    template <typename T, typename> constexpr T from_string_impl(const std::string&, type_tag<T>) {
        static_assert(std::is_same<T, void>::value,
                      "Conversion to this type is not implemented: an overload should be added to support this conversion");
        return T();
    }

    /**
     * The unit system is used through \ref Units::get to parse unit suffixes and convert the values to the appropriate
     * standard framework unit.
     */
    template <typename T, typename> T from_string_impl(std::string str, type_tag<T>) {
        str = from_string_helper(str);

        // Find an optional set of units
        auto unit_idx = str.size() - 1;
        for(; unit_idx > 0; --unit_idx) {
            if(!isalpha(str[unit_idx]) && str[unit_idx] != '*' && str[unit_idx] != '/') {
                break;
            }
        }
        std::string units = str.substr(unit_idx + 1);

        // Get the actual arithmetic value
        std::istringstream sstream(str.substr(0, unit_idx + 1));
        T ret_value = 0;
        sstream >> ret_value;

        // Check if the reading was succesfull and everything was read
        if(sstream.fail() || sstream.peek() != EOF) {
            throw std::invalid_argument("conversion not possible");
        }

        // Apply all the units if they exists
        if(!units.empty()) {
            ret_value = allpix::Units::get(ret_value, units);
        }
        return ret_value;
    }

    /**
     * The matching converter function is automatically found if available. To add a new conversion the \ref to_string_impl
     * function should be overloaded. The string is passed as first argument to this function, the second argument should be
     * an \ref allpix::empty_tag (required to search in the allpix namespace).
     */
    template <typename T> std::string to_string(T inp) {
        // Use tag dispatch to select the correct implementation
        return to_string_impl(inp, empty_tag());
    }

    template <typename T, typename, typename> constexpr void to_string_impl(T, empty_tag) {
        static_assert(std::is_same<T, void>::value,
                      "Conversion to this type is not implemented: an overload should be added to support this conversion");
    }
    template <typename T, typename> std::string to_string_impl(T inp, empty_tag) {
        std::ostringstream out;
        out << inp;
        return out.str();
    }

    template <typename T> std::vector<T> split(std::string str, const std::string& delims) {
        str = trim(str, delims);

        // If the input string is empty, simply return empty container
        if(str.empty()) {
            return std::vector<T>();
        }

        // Else we have data, clear the default elements and chop the string:
        std::vector<T> elems;

        // Loop through the string
        std::size_t prev = 0, pos;
        while((pos = str.find_first_of(delims, prev)) != std::string::npos) {
            if(pos > prev) {
                elems.push_back(from_string<T>(str.substr(prev, pos - prev)));
            }
            prev = pos + 1;
        }
        if(prev < str.length()) {
            elems.push_back(from_string<T>(str.substr(prev, std::string::npos)));
        }

        return elems;
    }
} // namespace allpix
<|endoftext|>


<commit_before>/*
 * Author: Csaszar, Peter <csjpeter@gmail.com>
 * Copyright (C) 2011-2016 Csaszar, Peter
 */

#include "csjp_http.h"

/* TODO
 * - convert header keys to lowercase before storing them
 * - support multiline header values
 * - HTTP 1.1 continue, keep-alive, chunked transfer support
 */

namespace csjp {

HTTPRequest::HTTPRequest(
		const String & method,
		const String & uri,
		const String & body,
		const String & version) :
	method(method),
	uri(uri),
	version(version),
	body(body)
{
	requestLine.catf("% % HTTP/%",
			method.length ? method.c_str() : "GET",
			uri.length ? uri.c_str() : "/",
			version.length ? version.c_str() : "1.0");
}

HTTPRequest HTTPRequest::get(
		const String & uri,
		const String & version)
{
	(void)uri;
	(void)version;
	return HTTPRequest(String("GET"), uri, String(""), version);
}

HTTPRequest HTTPRequest::post(
		const String & body,
		const String & uri,
		const String & version)
{
	return HTTPRequest(String("POST"), uri, body, version);
}

HTTPRequest::operator String () const
{
	String request;
	request.catf("%\r\n", requestLine);
	for(auto & h : headers.properties){
		if(h.key == "content-length")
			continue;
		request.catf("%: %\r\n", h.key, h.value);
	}
	request.catf("content-length: %\r\n", body.length);
	request.catf("\r\n%", body);
	return request;
}

unsigned HTTPRequest::parse(const StringChunk & data)
{
	if(!method.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n"))
			return false;
		requestLine <<= data.read(0, pos);
		Array<StringChunk> result(3);
		if(!subStringByRegexp(requestLine, result,
				"\\([^ ]*\\) \\([^ ]*\\) HTTP/\\(.*\\)$"))
			throw HttpProtocolError(
					"Invalid HTTP request line: %",
					requestLine);
		method <<= result[0];
		uri <<= result[1];
		version <<= result[2];
	}

	if(!headers.value.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n\r\n", requestLine.length+2))
			return false;
		headers.value <<= data.read(requestLine.length+2, pos);
		Array<StringChunk> array = split(headers.value, "\r\n");
		for(auto & str : array){
			if(!str.findFirst(pos, ":"))
				throw HttpProtocolError(
						"Invalid header line: %", str);
			StringChunk key(str.str, pos);
			key.trim(" \t");
			StringChunk value(str.str + pos + 1,
					str.length - pos - 1);
			value.trim(" \t");
			headers[key] = value;
		}
	}

	if(!body.length){
		size_t readIn = requestLine.length+2 + headers.value.length+4;
		size_t bodyLength = 0;
		bodyLength <<= headers["content-length"];
		if(data.length < readIn + bodyLength)
			return false;
		body <<= data.read(readIn, readIn + bodyLength);
	}

	return true;
}

HTTPResponse::HTTPResponse(
		HTTPStatusCode code,
		const String & body,
		const String & version
		) :
	version(version),
	body(body)
{
	statusCode <<= code;
	reasonPhrase <<= code.phrase();
	statusLine.catf("HTTP-% % %",
			version.length ? version.c_str() : "1.0",
			statusCode, reasonPhrase);
}

HTTPResponse::HTTPResponse(
		const String & body,
		const String & version) :
	version(version),
	body(body)
{
	HTTPStatusCode code = HTTPStatusCode::Enum::OK;
	statusCode <<= code;
	reasonPhrase <<= code.phrase();
	statusLine.catf("HTTP-% % %",
			version.length ? version.c_str() : "1.0",
			statusCode, reasonPhrase);
}

HTTPResponse::operator String () const
{
	String response;
	response.catf("%\r\n", statusLine);
	for(auto & h : headers.properties){
		if(h.key == "content-length")
			continue;
		response.catf("%: %\r\n", h.key, h.value);
	}
	response.catf("content-length: %\r\n", body.length);
	response.catf("\r\n%", body);
	return response;
}

unsigned HTTPResponse::parse(const StringChunk & data)
{
	if(!statusCode.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n"))
			return false;
		statusLine <<= data.read(0, pos);
		Array<StringChunk> result(3);
		if(!subStringByRegexp(statusLine, result,
				"HTTP-\\([^ ]*\\) \\([^ ]*\\) \\(.*\\)$"))
			throw HttpProtocolError(
					"Invalid HTTP status line: %",
					statusLine);
		version <<= result[0];
		statusCode <<= result[1];
		reasonPhrase <<= result[2];
	}

	if(!headers.value.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n\r\n", statusLine.length+2))
			return false;
		headers.value <<= data.read(statusLine.length+2, pos);
		Array<StringChunk> array = split(headers.value, "\r\n");
		for(auto & str : array){
			if(!str.findFirst(pos, ":"))
				throw HttpProtocolError(
						"Invalid header line: %", str);
			StringChunk key(str.str, pos);
			key.trim(" \t");
			StringChunk value(str.str + pos + 1,
					str.length - pos - 1);
			value.trim(" \t");
			headers[key] = value;
		}
	}

	if(!body.length){
		size_t readIn = statusLine.length+2 + headers.value.length+4;
		size_t bodyLength = 0;
		bodyLength <<= headers["content-length"];
		if(data.length < readIn + bodyLength)
			return false;
		body <<= data.read(readIn, readIn + bodyLength);
	}

	return true;
}

}

<commit_msg>lower case http header keys<commit_after>/*
 * Author: Csaszar, Peter <csjpeter@gmail.com>
 * Copyright (C) 2011-2016 Csaszar, Peter
 */

#include "csjp_http.h"

/* TODO
 * - support multiline header values
 * - HTTP 1.1 continue, keep-alive, chunked transfer support
 */

namespace csjp {

HTTPRequest::HTTPRequest(
		const String & method,
		const String & uri,
		const String & body,
		const String & version) :
	method(method),
	uri(uri),
	version(version),
	body(body)
{
	requestLine.catf("% % HTTP/%",
			method.length ? method.c_str() : "GET",
			uri.length ? uri.c_str() : "/",
			version.length ? version.c_str() : "1.0");
}

HTTPRequest HTTPRequest::get(
		const String & uri,
		const String & version)
{
	(void)uri;
	(void)version;
	return HTTPRequest(String("GET"), uri, String(""), version);
}

HTTPRequest HTTPRequest::post(
		const String & body,
		const String & uri,
		const String & version)
{
	return HTTPRequest(String("POST"), uri, body, version);
}

HTTPRequest::operator String () const
{
	String request;
	request.catf("%\r\n", requestLine);
	for(auto & h : headers.properties){
		if(h.key == "content-length")
			continue;
		String k(h.key);
		k.lower();
		request.catf("%: %\r\n", k, h.value);
	}
	request.catf("content-length: %\r\n", body.length);
	request.catf("\r\n%", body);
	return request;
}

unsigned HTTPRequest::parse(const StringChunk & data)
{
	if(!method.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n"))
			return false;
		requestLine <<= data.read(0, pos);
		Array<StringChunk> result(3);
		if(!subStringByRegexp(requestLine, result,
				"\\([^ ]*\\) \\([^ ]*\\) HTTP/\\(.*\\)$"))
			throw HttpProtocolError(
					"Invalid HTTP request line: %",
					requestLine);
		method <<= result[0];
		uri <<= result[1];
		version <<= result[2];
	}

	if(!headers.value.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n\r\n", requestLine.length+2))
			return false;
		headers.value <<= data.read(requestLine.length+2, pos);
		Array<StringChunk> array = split(headers.value, "\r\n");
		for(auto & str : array){
			if(!str.findFirst(pos, ":"))
				throw HttpProtocolError(
						"Invalid header line: %", str);
			String key;
			key <<= str.read(0, pos);
			key.trim(" \t");
			key.lower();
			StringChunk value(str.str + pos + 1,
					str.length - pos - 1);
			value.trim(" \t");
			headers[key] = value;
		}
	}

	if(!body.length){
		size_t readIn = requestLine.length+2 + headers.value.length+4;
		size_t bodyLength = 0;
		bodyLength <<= headers["content-length"];
		if(data.length < readIn + bodyLength)
			return false;
		body <<= data.read(readIn, readIn + bodyLength);
	}

	return true;
}

HTTPResponse::HTTPResponse(
		HTTPStatusCode code,
		const String & body,
		const String & version
		) :
	version(version),
	body(body)
{
	statusCode <<= code;
	reasonPhrase <<= code.phrase();
	statusLine.catf("HTTP-% % %",
			version.length ? version.c_str() : "1.0",
			statusCode, reasonPhrase);
}

HTTPResponse::HTTPResponse(
		const String & body,
		const String & version) :
	version(version),
	body(body)
{
	HTTPStatusCode code = HTTPStatusCode::Enum::OK;
	statusCode <<= code;
	reasonPhrase <<= code.phrase();
	statusLine.catf("HTTP-% % %",
			version.length ? version.c_str() : "1.0",
			statusCode, reasonPhrase);
}

HTTPResponse::operator String () const
{
	String response;
	response.catf("%\r\n", statusLine);
	for(auto & h : headers.properties){
		if(h.key == "content-length")
			continue;
		String k(h.key);
		k.lower();
		response.catf("%: %\r\n", k, h.value);
	}
	response.catf("content-length: %\r\n", body.length);
	response.catf("\r\n%", body);
	return response;
}

unsigned HTTPResponse::parse(const StringChunk & data)
{
	if(!statusCode.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n"))
			return false;
		statusLine <<= data.read(0, pos);
		Array<StringChunk> result(3);
		if(!subStringByRegexp(statusLine, result,
				"HTTP-\\([^ ]*\\) \\([^ ]*\\) \\(.*\\)$"))
			throw HttpProtocolError(
					"Invalid HTTP status line: %",
					statusLine);
		version <<= result[0];
		statusCode <<= result[1];
		reasonPhrase <<= result[2];
	}

	if(!headers.value.length){
		size_t pos;
		if(!data.findFirst(pos, "\r\n\r\n", statusLine.length+2))
			return false;
		headers.value <<= data.read(statusLine.length+2, pos);
		Array<StringChunk> array = split(headers.value, "\r\n");
		for(auto & str : array){
			if(!str.findFirst(pos, ":"))
				throw HttpProtocolError(
						"Invalid header line: %", str);
			String key;
			key <<= str.read(0, pos);
			key.trim(" \t");
			StringChunk value(str.str + pos + 1,
					str.length - pos - 1);
			value.trim(" \t");
			key.lower();
			headers[key] = value;
		}
	}

	if(!body.length){
		size_t readIn = statusLine.length+2 + headers.value.length+4;
		size_t bodyLength = 0;
		bodyLength <<= headers["content-length"];
		if(data.length < readIn + bodyLength)
			return false;
		body <<= data.read(readIn, readIn + bodyLength);
	}

	return true;
}

}

<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/

#include "cvtest.h"

CvTS test_system("cv");

const char* blacklist[] =
{
    "_3d-fundam",                  //ticket 484

    "calibrate-camera-artificial", //ticket 472
    //"calibrate-camera-cpp",        //ticket 564
    //"calibrate-stereo-c",          //ticket 565
    "cascade-detector",            //ticket 432
    "chessboard-detector",         //ticket 569
    "chessboard-subpixel",         //ticket 473
    "color-luv",                   //ticket 502

    "descriptor_sift",             //ticket 567
    "descriptor_surf",             //ticket 568
    "detector_surf",               //ticket 578

    "filter-generic",
    "flann_saved",                 //ticket 618

    //"hist-backproj",               //ticket 579
    //"hist-bayesianprob",           //ticket 619
    //"hist-backprojpatch",          //ticket 620
    "hog-detector",                //ticket 428

    "inpaint",                     //ticket 570

    "mhi-global",                  //ticket 457
    "morph-ex",                    //ticket 612
    "MSER",                        //ticket 437
    "operations",                  //ticket 613
    "optflow-estimate-rigid",      //ticket 433
    "posit",                       //ticket 430

    "segmentation-pyramid",        //ticket 464
    "shape-minarearect",           //ticket 436
    //"stereobm",                    //ticket 614
    //"stereosgbm",                  //ticket 615
    //"stereogc",                    //ticket 439
    "subdiv",                      //ticket 454

    "track-camshift",              //ticket 483

    "warp-affine",                 //ticket 572
    "warp-perspective",            //ticket 575
    "warp-remap",                  //ticket 576
    "warp-resize",                 //ticket 429
    "warp-undistort",              //ticket 577
    0
};

int main(int argC,char *argV[])
{
    return test_system.run( argC, argV, blacklist );
}

/* End of file. */
<commit_msg>moved color-lab test to blacklist (issue #627)<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/

#include "cvtest.h"

CvTS test_system("cv");

const char* blacklist[] =
{
    "_3d-fundam",                  //ticket 484

    "calibrate-camera-artificial", //ticket 472
    //"calibrate-camera-cpp",        //ticket 564
    //"calibrate-stereo-c",          //ticket 565
    "cascade-detector",            //ticket 432
    "chessboard-detector",         //ticket 569
    "chessboard-subpixel",         //ticket 473
    "color-luv",                   //ticket 502

    "descriptor_sift",             //ticket 567
    "descriptor_surf",             //ticket 568
    "detector_surf",               //ticket 578

    "filter-generic",
    "flann_saved",                 //ticket 618

    //"hist-backproj",               //ticket 579
    //"hist-bayesianprob",           //ticket 619
    //"hist-backprojpatch",          //ticket 620
    "hog-detector",                //ticket 428

    "inpaint",                     //ticket 570

    "mhi-global",                  //ticket 457
    "morph-ex",                    //ticket 612
    "MSER",                        //ticket 437
    "operations",                  //ticket 613
    "optflow-estimate-rigid",      //ticket 433
    "posit",                       //ticket 430

    "segmentation-pyramid",        //ticket 464
    "shape-minarearect",           //ticket 436
    //"stereobm",                    //ticket 614
    //"stereosgbm",                  //ticket 615
    //"stereogc",                    //ticket 439
    "subdiv",                      //ticket 454

    "track-camshift",              //ticket 483

    "warp-affine",                 //ticket 572
    "warp-perspective",            //ticket 575
    "warp-remap",                  //ticket 576
    "warp-resize",                 //ticket 429
    "warp-undistort",              //ticket 577
    "color-lab",                   //ticket 627
    0
};

int main(int argC,char *argV[])
{
    return test_system.run( argC, argV, blacklist );
}

/* End of file. */
<|endoftext|>


<commit_before>#include <cpp/code-generator.hh>
#include <ast/all.hh>

namespace cpp
{
    CodeGenerator::CodeGenerator(std::ostream& o)
        : o_(o)
        , params_(false)
        , current_class_(nullptr)
    {}

    CodeGenerator::~CodeGenerator()
    {}

    void CodeGenerator::generate_main()
    {
        o_ << "int main()" << misc::iendl;
        o_ << "{" << misc::indentendl;

        for (auto mod : modules_)
            o_ << "__" << mod << "__::__init();" << misc::iendl;

        o_ << misc::dedentendl << "}" << misc::iendl;
    }

    void CodeGenerator::operator()(ast::ExprList& ast)
    {
        auto beg = ast.list_get().begin();
        auto end = ast.list_get().end();

        for (auto it = beg; it != end; ++it)
        {
            if (it != beg)
                code_ << ", ";

            (*it)->accept(*this);
        }
    }

    void CodeGenerator::operator()(ast::StmtList& ast)
    {
        auto beg = ast.list_get().begin();
        auto end = ast.list_get().end();

        for (auto it = beg; it != end; ++it)
        {
            if (it != beg)
                code_ << misc::iendl;

            (*it)->accept(*this);

            if (!dynamic_cast<ast::FunctionDec*> (*it)
                && !dynamic_cast<ast::WhileStmt*> (*it)
                && !dynamic_cast<ast::IfStmt*> (*it))
                code_ << ";";
        }
    }

    void CodeGenerator::operator()(ast::ModuleStmt& ast)
    {
        modules_.push_back(ast.name_get());

        o_ << "namespace __" << ast.name_get() << "__" << misc::iendl;
        o_ << "{" << misc::indentendl;

        code_ << misc::indent;

        ast.content_get()->accept(*this);

        o_ << code_.str();

        o_ << misc::dedentendl;
        o_ << "}" << misc::iendl;
    }

    void CodeGenerator::operator()(ast::ReturnStmt& ast)
    {
        code_ << "return ";

        ast::DefaultVisitor::operator()(ast);
    }

    void CodeGenerator::operator()(ast::ContinueStmt&)
    {
        code_ << "continue";
    }

    void CodeGenerator::operator()(ast::BreakStmt&)
    {
        code_ << "break";
    }

    void CodeGenerator::operator()(ast::IfStmt& ast)
    {
        code_ << "if (";
        ast.cond_get()->accept(*this);
        code_ << ")" << misc::iendl << "{" << misc::indentendl;

        ast.true_stmt_get()->accept(*this);

        code_ << misc::dedentendl << "}";

        if (ast.else_stmt_get())
        {
            code_ << misc::iendl << "else" << misc::iendl << "{"
                  << misc::indentendl;

            ast.else_stmt_get()->accept(*this);

            code_ << misc::dedentendl << "}";
        }
    }

    void CodeGenerator::operator()(ast::WhileStmt& ast)
    {
        code_ << "while (";

        ast.cond_get()->accept(*this);

        code_ << ")" << misc::iendl << "{" << misc::indentendl;

        ast.loop_get()->accept(*this);

        code_ << misc::dedentendl << "}";
    }

    void CodeGenerator::operator()(ast::FunctionDec& ast)
    {
        // Generating all functions prototypes
        for (auto proto : ast.to_generate_get())
        {
            ast.type_set(proto);

            code_ << ast.type_get()->return_type_get()->cpp_type() << " ";

            // If function is the method add the name of the class followed
            // by "::"
            if (current_class_)
                code_ << current_class_->name_get() << "::";

            code_ << ast.name_get() << "(";

            params_ = true;
            if (ast.args_get())
                ast.args_get()->accept(*this);
            params_ = false;

            code_ << ")" << misc::iendl << "{" << misc::indentendl;

            ast.body_get()->accept(*this);

            code_ << misc::dedentendl << "}" << misc::iendl;
        }
    }

    void CodeGenerator::operator()(ast::ClassDec& ast)
    {
        type::Class* old = current_class_;

        current_class_ = ast.type_class_get();

        ast.def_get()->accept(*this);

        current_class_ = old;
    }

    void CodeGenerator::operator()(ast::IdVar& ast)
    {
        if (current_class_ && ast.id_get() == "self")
        {
            code_ << "this";
            return;
        }

        if (params_ || (!ast.def_get() && ast.type_get()))
            code_ << ast.type_get()->cpp_type() << " ";

        if (builtin::BuiltinLibrary::instance().is_builtin(ast.id_get()))
            code_ << builtin::BuiltinLibrary::instance().cpp_builtin(ast.id_get());
        else
            code_ << ast.id_get();
    }

    void CodeGenerator::operator()(ast::OpExpr& ast)
    {
        code_ << ast.to_cpp() << "(";

        ast.left_expr_get()->accept(*this);

        code_ << ", ";

        ast.right_expr_get()->accept(*this);

        code_ << ")";
    }

    void CodeGenerator::operator()(ast::AssignExpr& ast)
    {
        ast.lvalue_get()->accept(*this);

        code_ << " = ";

        ast.rvalue_get()->accept(*this);
    }

    void CodeGenerator::operator()(ast::StringExpr& ast)
    {
        code_ << "new __repy_string(\"" << ast.str_get() << "\")";
    }

    void CodeGenerator::operator()(ast::NumeralExpr& ast)
    {
        code_ << ast.value_get();
    }

    void CodeGenerator::operator()(ast::FunctionVar& ast)
    {
        if (ast.constructor_get())
            code_ << "new ";

        ast.var_get()->accept(*this);

        code_ << "(";

        if (ast.params_get())
            ast.params_get()->accept(*this);

        code_ << ")";
    }

    void CodeGenerator::operator()(ast::FieldVar& ast)
    {
        ast.var_get()->accept(*this);

        code_ << "->" << ast.name_get();
    }

    void CodeGenerator::operator()(ast::MethodVar& ast)
    {
        ast.var_get()->accept(*this);

        code_ << "->" << ast.name_get() << "(";

        if (ast.params_get())
            ast.params_get()->accept(*this);

        code_ << ")";
    }
} // namespace cpp
<commit_msg>[CGENERATOR] Add constructor prototype generated properly<commit_after>#include <cpp/code-generator.hh>
#include <ast/all.hh>

namespace cpp
{
    CodeGenerator::CodeGenerator(std::ostream& o)
        : o_(o)
        , params_(false)
        , current_class_(nullptr)
    {}

    CodeGenerator::~CodeGenerator()
    {}

    void CodeGenerator::generate_main()
    {
        o_ << "int main()" << misc::iendl;
        o_ << "{" << misc::indentendl;

        for (auto mod : modules_)
            o_ << "__" << mod << "__::__init();" << misc::iendl;

        o_ << misc::dedentendl << "}" << misc::iendl;
    }

    void CodeGenerator::operator()(ast::ExprList& ast)
    {
        auto beg = ast.list_get().begin();
        auto end = ast.list_get().end();

        for (auto it = beg; it != end; ++it)
        {
            if (it != beg)
                code_ << ", ";

            (*it)->accept(*this);
        }
    }

    void CodeGenerator::operator()(ast::StmtList& ast)
    {
        auto beg = ast.list_get().begin();
        auto end = ast.list_get().end();

        for (auto it = beg; it != end; ++it)
        {
            if (it != beg)
                code_ << misc::iendl;

            (*it)->accept(*this);

            if (!dynamic_cast<ast::FunctionDec*> (*it)
                && !dynamic_cast<ast::WhileStmt*> (*it)
                && !dynamic_cast<ast::IfStmt*> (*it))
                code_ << ";";
        }
    }

    void CodeGenerator::operator()(ast::ModuleStmt& ast)
    {
        modules_.push_back(ast.name_get());

        o_ << "namespace __" << ast.name_get() << "__" << misc::iendl;
        o_ << "{" << misc::indentendl;

        code_ << misc::indent;

        ast.content_get()->accept(*this);

        o_ << code_.str();

        o_ << misc::dedentendl;
        o_ << "}" << misc::iendl;
    }

    void CodeGenerator::operator()(ast::ReturnStmt& ast)
    {
        code_ << "return ";

        ast::DefaultVisitor::operator()(ast);
    }

    void CodeGenerator::operator()(ast::ContinueStmt&)
    {
        code_ << "continue";
    }

    void CodeGenerator::operator()(ast::BreakStmt&)
    {
        code_ << "break";
    }

    void CodeGenerator::operator()(ast::IfStmt& ast)
    {
        code_ << "if (";
        ast.cond_get()->accept(*this);
        code_ << ")" << misc::iendl << "{" << misc::indentendl;

        ast.true_stmt_get()->accept(*this);

        code_ << misc::dedentendl << "}";

        if (ast.else_stmt_get())
        {
            code_ << misc::iendl << "else" << misc::iendl << "{"
                  << misc::indentendl;

            ast.else_stmt_get()->accept(*this);

            code_ << misc::dedentendl << "}";
        }
    }

    void CodeGenerator::operator()(ast::WhileStmt& ast)
    {
        code_ << "while (";

        ast.cond_get()->accept(*this);

        code_ << ")" << misc::iendl << "{" << misc::indentendl;

        ast.loop_get()->accept(*this);

        code_ << misc::dedentendl << "}";
    }

    void CodeGenerator::operator()(ast::FunctionDec& ast)
    {
        // Generating all functions prototypes
        for (auto proto : ast.to_generate_get())
        {
            ast.type_set(proto);

            if (!(ast.name_get() == "__init__" && current_class_))
                code_ << ast.type_get()->return_type_get()->cpp_type() << " ";

            // If function is the method add the name of the class followed
            // by "::"
            if (current_class_)
                code_ << current_class_->name_get() << "::";

            if (ast.name_get() == "__init__" && current_class_)
                code_ << current_class_->name_get() << "(";
            else
                code_ << ast.name_get() << "(";

            params_ = true;
            if (ast.args_get())
                ast.args_get()->accept(*this);
            params_ = false;

            code_ << ")" << misc::iendl << "{" << misc::indentendl;

            ast.body_get()->accept(*this);

            code_ << misc::dedentendl << "}" << misc::iendl;
        }
    }

    void CodeGenerator::operator()(ast::ClassDec& ast)
    {
        type::Class* old = current_class_;

        current_class_ = ast.type_class_get();

        ast.def_get()->accept(*this);

        current_class_ = old;
    }

    void CodeGenerator::operator()(ast::IdVar& ast)
    {
        if (current_class_ && ast.id_get() == "self")
        {
            code_ << "this";
            return;
        }

        if (params_ || (!ast.def_get() && ast.type_get()))
            code_ << ast.type_get()->cpp_type() << " ";

        if (builtin::BuiltinLibrary::instance().is_builtin(ast.id_get()))
            code_ << builtin::BuiltinLibrary::instance().cpp_builtin(ast.id_get());
        else
            code_ << ast.id_get();
    }

    void CodeGenerator::operator()(ast::OpExpr& ast)
    {
        code_ << ast.to_cpp() << "(";

        ast.left_expr_get()->accept(*this);

        code_ << ", ";

        ast.right_expr_get()->accept(*this);

        code_ << ")";
    }

    void CodeGenerator::operator()(ast::AssignExpr& ast)
    {
        ast.lvalue_get()->accept(*this);

        code_ << " = ";

        ast.rvalue_get()->accept(*this);
    }

    void CodeGenerator::operator()(ast::StringExpr& ast)
    {
        code_ << "new __repy_string(\"" << ast.str_get() << "\")";
    }

    void CodeGenerator::operator()(ast::NumeralExpr& ast)
    {
        code_ << ast.value_get();
    }

    void CodeGenerator::operator()(ast::FunctionVar& ast)
    {
        if (ast.constructor_get())
            code_ << "new ";

        ast.var_get()->accept(*this);

        code_ << "(";

        if (ast.params_get())
            ast.params_get()->accept(*this);

        code_ << ")";
    }

    void CodeGenerator::operator()(ast::FieldVar& ast)
    {
        ast.var_get()->accept(*this);

        code_ << "->" << ast.name_get();
    }

    void CodeGenerator::operator()(ast::MethodVar& ast)
    {
        ast.var_get()->accept(*this);

        code_ << "->" << ast.name_get() << "(";

        if (ast.params_get())
            ast.params_get()->accept(*this);

        code_ << ")";
    }
} // namespace cpp
<|endoftext|>


<commit_before>
#include <iostream>
#include <string.h>
#include <SDL.h>
#include <SDL_audio.h>
#include <akPGTA.h>
#include <queue>

#include "FileUtils.h"
#include "utils.h"

#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif

void FixWorkingDirectory()
{
    char temp[128] = {};
    const char *dir = getcwd(temp, sizeof(temp));
    const char *bin_pos = strstr(dir, "bin");
    const char *build_pos = strstr(dir, "build");
    if (bin_pos)
    {
        chdir("..");
    }
    else if (build_pos)
    {
        chdir("../..");
    }
}

class AudioBuffer
{
    struct AudioChunk
    {
        static const int MAX_SAMPLES = 508;
        int64_t numSamples;
        int16_t samples[MAX_SAMPLES];
    };

public:
    AudioBuffer()
    {
        const int numBuffers = 64;
        AudioChunk* buffers = new AudioChunk[numBuffers];
        std::queue<AudioChunk*> freeList;
        for (int i = 0; i < numBuffers; ++i)
        {
            freeList.emplace(buffers + i);
        }

        m_freeBuffers = std::move(freeList);
        m_buffers = buffers;
    }

    ~AudioBuffer()
    {
        delete[] m_buffers;
    }

    int PushSamples(const int16_t* samples, int numSamples)
    {
        if (!samples || numSamples < 0)
        {
            printf("AudioBuffer::PushSamples: invalid args samples %p, numSamples %i!\n", samples, numSamples);
            return -1;
        }

        int numSamplesPushed = 0;
        while (numSamples > 0)
        {
            if (m_freeBuffers.empty())
            {
                printf("AudioBuffer::PushSamples: buffer overflow pushing %i samples!\n", numSamples);
                break;
            }

            AudioChunk* chunk = m_freeBuffers.front();
            m_freeBuffers.pop();

            const int numSamplesToCopy = (numSamples - AudioChunk::MAX_SAMPLES >= 0) ? AudioChunk::MAX_SAMPLES : numSamples;
            numSamples -= AudioChunk::MAX_SAMPLES;
            numSamplesPushed += numSamplesToCopy;

            chunk->numSamples = numSamplesToCopy;
            memcpy(chunk->samples, samples, numSamplesToCopy * sizeof(int16_t));
            samples += numSamplesToCopy;
            m_loadedBuffers.push(chunk);
        }
        return numSamplesPushed;
    }

    int PopSamples(int16_t* samples, int numSamples)
    {
        if (!samples || numSamples < 0)
        {
            printf("AudioBuffer::PopSamples: invalid args samples %p, numSamples %i!\n", samples, numSamples);
            return -1;
        }

        int numSamplesPopped = 0;
        while (numSamples > 0)
        {
            if (m_loadedBuffers.empty())
            {
                printf("AudioBuffer::PushSamples: buffer underflow popping %i samples!\n", numSamples);
                break;
            }

            AudioChunk* chunk = m_loadedBuffers.front();
            const int numSamplesInChunk = static_cast<int>(chunk->numSamples);
            if (numSamplesInChunk <= numSamples)
            {
                memcpy(samples, chunk->samples, numSamplesInChunk * sizeof(int16_t));
                samples += numSamplesInChunk;
                numSamples -= numSamplesInChunk;
                numSamplesPopped += numSamplesInChunk;

                m_loadedBuffers.pop();
                m_freeBuffers.push(chunk);
            }
            else
            {
                numSamplesPopped += numSamples;
                memcpy(samples, chunk->samples, numSamples * sizeof(int16_t));
                memmove(chunk->samples, chunk->samples + numSamples, numSamples * sizeof(int16_t));
                chunk->numSamples = numSamples;
                break;
            }
        }
        return numSamplesPopped;
    }

private:
    std::queue<AudioChunk*> m_loadedBuffers;
    std::queue<AudioChunk*> m_freeBuffers;
    AudioChunk* m_buffers;
};

int pgtaMain(SDL_AudioDeviceID audioDevice, AudioBuffer* audioOut)
{
    PGTA::PGTADevice pgtaDevice;
    if (!pgtaDevice.Initialize())
    {
        return -1;
    }

    // load track data to memory
    // "tracks/demo.track"
    std::string trackSource;
    if (!ReadBinaryFileToString("tracks/demo.track", trackSource))
    {
        return -1;
    }

    HPGTATrack demoTrack = nullptr;
    const char* source = trackSource.data();
    if (pgtaDevice.CreateTracks(1, &source, &demoTrack) <= 0 || !demoTrack)
    {
        return -1;
    }

    PGTAConfig config;
    config.audioDesc.samplesPerSecond = 44100;
    config.audioDesc.bytesPerSample = 2;
    config.audioDesc.channels = 1;
    config.numBuffers = 4;
    config.bufferSizeInSamples = 8192;
    PGTA::PGTAContext pgtaContext(pgtaDevice.CreateContext(config));

    //pgtaContext.BindTrack(demoTrack);

    utils::RunLoop(10.0f, [&](double absoluteTime, float delta)
    {
        int32_t numBuffers = 0;
        const PGTABuffer* buffers = pgtaContext.Update(delta, &numBuffers);
        for (int32_t i = 0; i < numBuffers; ++i)
        {
            const PGTABuffer& buf = buffers[i];
            const int16_t* samples = reinterpret_cast<const int16_t*>(buf.samples);
            SDL_LockAudioDevice(audioDevice);
            if (audioOut->PushSamples(samples, buf.numSamples) < 0)
            {
                printf("PushSamples failed!\n");
            }
            SDL_UnlockAudioDevice(audioDevice);
        }

        return (buffers != nullptr);
    });

    return 0;
}

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    FixWorkingDirectory();

    AudioBuffer audioBuffer;

    SDL_AudioSpec audioSpec;
    SDL_zero(audioSpec);
    audioSpec.freq = 44100;
    audioSpec.format = AUDIO_S16;
    audioSpec.channels = 1;
    audioSpec.samples = 4096;
    audioSpec.callback = [](void *userdata, Uint8* stream, int len)
    {
        AudioBuffer* buffer = reinterpret_cast<AudioBuffer*>(userdata);
        int16_t* samples = reinterpret_cast<int16_t*>(stream);
        if (buffer->PopSamples(samples, len * sizeof(int16_t)) < 0)
        {
            printf("PopSamples failed!\n");
        }
    };
    audioSpec.userdata = &audioBuffer;
    SDL_AudioDeviceID audioDevice = SDL_OpenAudioDevice(nullptr, false, &audioSpec, nullptr, 0);

    int ret = 0;
    if (audioDevice > 0)
    {
        SDL_PauseAudioDevice(audioDevice, 0);
        ret = pgtaMain(audioDevice, &audioBuffer);
        SDL_CloseAudioDevice(audioDevice);
    }

    SDL_Quit();
    return ret;
}
<commit_msg>increased num samples per chunk to 1020<commit_after>
#include <iostream>
#include <string.h>
#include <SDL.h>
#include <SDL_audio.h>
#include <akPGTA.h>
#include <queue>

#include "FileUtils.h"
#include "utils.h"

#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif

void FixWorkingDirectory()
{
    char temp[128] = {};
    const char *dir = getcwd(temp, sizeof(temp));
    const char *bin_pos = strstr(dir, "bin");
    const char *build_pos = strstr(dir, "build");
    if (bin_pos)
    {
        chdir("..");
    }
    else if (build_pos)
    {
        chdir("../..");
    }
}

class AudioBuffer
{
    struct AudioChunk
    {
        static const int MAX_SAMPLES = 1020;
        int64_t numSamples;
        int16_t samples[MAX_SAMPLES];
    };

public:
    AudioBuffer()
    {
        const int numBuffers = 64;
        AudioChunk* buffers = new AudioChunk[numBuffers];
        std::queue<AudioChunk*> freeList;
        for (int i = 0; i < numBuffers; ++i)
        {
            freeList.emplace(buffers + i);
        }

        m_freeBuffers = std::move(freeList);
        m_buffers = buffers;
    }

    ~AudioBuffer()
    {
        delete[] m_buffers;
    }

    int PushSamples(const int16_t* samples, int numSamples)
    {
        if (!samples || numSamples < 0)
        {
            printf("AudioBuffer::PushSamples: invalid args samples %p, numSamples %i!\n", samples, numSamples);
            return -1;
        }

        int numSamplesPushed = 0;
        while (numSamples > 0)
        {
            if (m_freeBuffers.empty())
            {
                printf("AudioBuffer::PushSamples: buffer overflow pushing %i samples!\n", numSamples);
                break;
            }

            AudioChunk* chunk = m_freeBuffers.front();
            m_freeBuffers.pop();

            const int numSamplesToCopy = (numSamples - AudioChunk::MAX_SAMPLES >= 0) ? AudioChunk::MAX_SAMPLES : numSamples;
            numSamples -= AudioChunk::MAX_SAMPLES;
            numSamplesPushed += numSamplesToCopy;

            chunk->numSamples = numSamplesToCopy;
            memcpy(chunk->samples, samples, numSamplesToCopy * sizeof(int16_t));
            samples += numSamplesToCopy;
            m_loadedBuffers.push(chunk);
        }
        return numSamplesPushed;
    }

    int PopSamples(int16_t* samples, int numSamples)
    {
        if (!samples || numSamples < 0)
        {
            printf("AudioBuffer::PopSamples: invalid args samples %p, numSamples %i!\n", samples, numSamples);
            return -1;
        }

        int numSamplesPopped = 0;
        while (numSamples > 0)
        {
            if (m_loadedBuffers.empty())
            {
                printf("AudioBuffer::PushSamples: buffer underflow popping %i samples!\n", numSamples);
                break;
            }

            AudioChunk* chunk = m_loadedBuffers.front();
            const int numSamplesInChunk = static_cast<int>(chunk->numSamples);
            if (numSamplesInChunk <= numSamples)
            {
                memcpy(samples, chunk->samples, numSamplesInChunk * sizeof(int16_t));
                samples += numSamplesInChunk;
                numSamples -= numSamplesInChunk;
                numSamplesPopped += numSamplesInChunk;

                m_loadedBuffers.pop();
                m_freeBuffers.push(chunk);
            }
            else
            {
                numSamplesPopped += numSamples;
                memcpy(samples, chunk->samples, numSamples * sizeof(int16_t));
                memmove(chunk->samples, chunk->samples + numSamples, numSamples * sizeof(int16_t));
                chunk->numSamples = numSamples;
                break;
            }
        }
        return numSamplesPopped;
    }

private:
    std::queue<AudioChunk*> m_loadedBuffers;
    std::queue<AudioChunk*> m_freeBuffers;
    AudioChunk* m_buffers;
};

int pgtaMain(SDL_AudioDeviceID audioDevice, AudioBuffer* audioOut)
{
    PGTA::PGTADevice pgtaDevice;
    if (!pgtaDevice.Initialize())
    {
        return -1;
    }

    // load track data to memory
    // "tracks/demo.track"
    std::string trackSource;
    if (!ReadBinaryFileToString("tracks/demo.track", trackSource))
    {
        return -1;
    }

    HPGTATrack demoTrack = nullptr;
    const char* source = trackSource.data();
    if (pgtaDevice.CreateTracks(1, &source, &demoTrack) <= 0 || !demoTrack)
    {
        return -1;
    }

    PGTAConfig config;
    config.audioDesc.samplesPerSecond = 44100;
    config.audioDesc.bytesPerSample = 2;
    config.audioDesc.channels = 1;
    config.numBuffers = 4;
    config.bufferSizeInSamples = 8192;
    PGTA::PGTAContext pgtaContext(pgtaDevice.CreateContext(config));

    //pgtaContext.BindTrack(demoTrack);

    utils::RunLoop(10.0f, [&](double absoluteTime, float delta)
    {
        int32_t numBuffers = 0;
        const PGTABuffer* buffers = pgtaContext.Update(delta, &numBuffers);
        for (int32_t i = 0; i < numBuffers; ++i)
        {
            const PGTABuffer& buf = buffers[i];
            const int16_t* samples = reinterpret_cast<const int16_t*>(buf.samples);
            SDL_LockAudioDevice(audioDevice);
            if (audioOut->PushSamples(samples, buf.numSamples) < 0)
            {
                printf("PushSamples failed!\n");
            }
            SDL_UnlockAudioDevice(audioDevice);
        }

        return (buffers != nullptr);
    });

    return 0;
}

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    FixWorkingDirectory();

    AudioBuffer audioBuffer;

    SDL_AudioSpec audioSpec;
    SDL_zero(audioSpec);
    audioSpec.freq = 44100;
    audioSpec.format = AUDIO_S16;
    audioSpec.channels = 1;
    audioSpec.samples = 4096;
    audioSpec.callback = [](void *userdata, Uint8* stream, int len)
    {
        AudioBuffer* buffer = reinterpret_cast<AudioBuffer*>(userdata);
        int16_t* samples = reinterpret_cast<int16_t*>(stream);
        if (buffer->PopSamples(samples, len * sizeof(int16_t)) < 0)
        {
            printf("PopSamples failed!\n");
        }
    };
    audioSpec.userdata = &audioBuffer;
    SDL_AudioDeviceID audioDevice = SDL_OpenAudioDevice(nullptr, false, &audioSpec, nullptr, 0);

    int ret = 0;
    if (audioDevice > 0)
    {
        SDL_PauseAudioDevice(audioDevice, 0);
        ret = pgtaMain(audioDevice, &audioBuffer);
        SDL_CloseAudioDevice(audioDevice);
    }

    SDL_Quit();
    return ret;
}
<|endoftext|>


<commit_before>#include "event/Event.hpp"

namespace gfs {
    namespace event {
    }
}
<commit_msg>remove Event.cpp<commit_after><|endoftext|>


<commit_before>
#ifndef __EVENT_QUEUE_HPP__
#define __EVENT_QUEUE_HPP__

#include <pthread.h>
#include <libaio.h>
#include "alloc_blackhole.hpp"

// Event handling
typedef int resource_t;
enum event_type_t {
    et_disk_event, et_sock_event
};
enum event_op_t {
    eo_read, eo_write
};
struct event_t {
    event_type_t event_type;
    resource_t source;
    event_op_t op;

    void *state;  // State associated with the communication

    /* For event_type == et_disk_event */
    int result;   // Result of the io operation
    void *buf;    // Location of the buffer where data was copied (for read events)
};
struct event_queue_t;
typedef void (*event_handler_t)(event_queue_t*, event_t*);

// Event queue structure
struct worker_pool_t;
struct event_queue_t {
    int queue_id;
    pthread_t aio_thread;
    io_context_t aio_context;
    pthread_t epoll_thread;
    int epoll_fd;
    event_handler_t event_handler;
    alloc_blackhole_t allocator;
    worker_pool_t *parent_pool;
    volatile bool dying;
};

// Event queue initialization/destruction
void create_event_queue(event_queue_t *event_queue, int queue_id, event_handler_t event_handler,
                        worker_pool_t *parent_pool);
void destroy_event_queue(event_queue_t *event_queue);

void queue_watch_resource(event_queue_t *event_queue, resource_t resource,
                          event_op_t event_op, void *state);
void queue_forget_resource(event_queue_t *event_queue, resource_t resource);

#endif // __EVENT_QUEUE_HPP__

<commit_msg>Adding a todo for allocator safety<commit_after>
#ifndef __EVENT_QUEUE_HPP__
#define __EVENT_QUEUE_HPP__

#include <pthread.h>
#include <libaio.h>
#include "alloc_blackhole.hpp"

// Event handling
typedef int resource_t;
enum event_type_t {
    et_disk_event, et_sock_event
};
enum event_op_t {
    eo_read, eo_write
};
struct event_t {
    event_type_t event_type;
    resource_t source;
    event_op_t op;

    void *state;  // State associated with the communication

    /* For event_type == et_disk_event */
    int result;   // Result of the io operation
    void *buf;    // Location of the buffer where data was copied (for read events)
};
struct event_queue_t;
typedef void (*event_handler_t)(event_queue_t*, event_t*);

// Event queue structure
struct worker_pool_t;
struct event_queue_t {
    int queue_id;
    pthread_t aio_thread;
    io_context_t aio_context;
    pthread_t epoll_thread;
    int epoll_fd;
    event_handler_t event_handler;
    // TODO: we have a single non thread-safe allocator per event
    // queue, but event queue contains two threads (albeit on the same
    // processor, but still will cause problems). Currently it's not a
    // problem since we only allocate from the epoll thread, but will
    // become a problem if/when we need to allocate from the AIO IO
    // thread.
    alloc_blackhole_t allocator;
    worker_pool_t *parent_pool;
    volatile bool dying;
};

// Event queue initialization/destruction
void create_event_queue(event_queue_t *event_queue, int queue_id, event_handler_t event_handler,
                        worker_pool_t *parent_pool);
void destroy_event_queue(event_queue_t *event_queue);

void queue_watch_resource(event_queue_t *event_queue, resource_t resource,
                          event_op_t event_op, void *state);
void queue_forget_resource(event_queue_t *event_queue, resource_t resource);

#endif // __EVENT_QUEUE_HPP__

<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/MIRIAMUI/Attic/CModifiedWidget.cpp,v $
//   $Revision: 1.1 $
//   $Name:  $
//   $Author: aekamal $
//   $Date: 2008/02/20 19:06:27 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include <qlayout.h>
#include <qpushbutton.h>

#include "model/CModel.h"
#include "MIRIAM/CAuthor.h"
#include "utilities/CCopasiVector.h"
#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiObject.h"
#include "report/CKeyFactory.h"
#include "UI/qtUtilities.h"
#include "UI/CQMessageBox.h"
#include "UI/CQDateTimeEditTableItem.h"

#include "CModifiedWidget.h"

#define COL_MARK               0
#define COL_DATE_MODIFIED      1

/*
 *  Constructs a CModifiedWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
CModifiedWidget::CModifiedWidget(QWidget* parent, const char* name, WFlags f)
    : CopasiTableWidget(parent, false, name, f, false)
{
  if (!name)
    CopasiTableWidget::setName("ModifiedWidget");
  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CModifiedWidget::~CModifiedWidget()
{
  // no need to delete child widgets, Qt does it all for us
}

std::vector<const CCopasiObject*> CModifiedWidget::getObjects() const
  {
    std::vector<const CCopasiObject*> ret;

    const CCopasiVector<CModified>& tmp = CCopasiDataModel::Global->getModel()->getMIRIAMInfo().getModifieds();

    C_INT32 i, imax = tmp.size();
    for (i = 0; i < imax; ++i)
      ret.push_back(tmp[i]);

    return ret;
  }

void CModifiedWidget::init()
{
  mShowNewObjectWarning = false;
  numCols = 2;
  table->setNumCols(numCols);

  //Setting table headers
  QHeader *tableHeader = table->horizontalHeader();
  tableHeader->setLabel(COL_MARK, "Status");
  tableHeader->setLabel(COL_DATE_MODIFIED, "Date and Time Modified");
}

void CModifiedWidget::tableLineFromObject(const CCopasiObject* obj, unsigned C_INT32 row)
{
  if (!obj) return;
  const CModified *pModified = (const CModified*)obj;

  CQDateTimeEditTableItem* pDTWidget = NULL;
  if (dynamic_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED)))
    {
      pDTWidget = static_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED));
    }
  else
    {
      pDTWidget = new CQDateTimeEditTableItem(this, row, COL_DATE_MODIFIED, table);
      pDTWidget->dateEdit()->setRange(QDate(), QDate::currentDate());
      table->setCellWidget(row, COL_DATE_MODIFIED, pDTWidget);
    }
  pDTWidget->setDateTime(QDateTime::fromString(FROM_UTF8(pModified->getDateModified()), Qt::ISODate));
}

void CModifiedWidget::tableLineToObject(unsigned C_INT32 row, CCopasiObject* obj)
{
  if (!obj) return;
  CModified * pModified = static_cast< CModified * >(obj);

  if (dynamic_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED)))
    {
      CQDateTimeEditTableItem * pDTE = static_cast<CQDateTimeEditTableItem *> (table->cellWidget(row, COL_DATE_MODIFIED));
      std::string dt = "";
      if (pDTE->dateTime().toString(Qt::ISODate).ascii())
      {dt = pDTE->dateTime().toString(Qt::ISODate).ascii();}
      pModified->setDateModified(dt);
    }
}

void CModifiedWidget::defaultTableLineContent(unsigned C_INT32 row, unsigned C_INT32 exc)
{
  if (exc != COL_DATE_MODIFIED)
    {
      if (!dynamic_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED)))
        {
          CQDateTimeEditTableItem* pDTE = new CQDateTimeEditTableItem(this, row, COL_DATE_MODIFIED, table);
          pDTE->dateEdit()->setRange(QDate(), QDate::currentDate());
          table->setCellWidget(row, COL_DATE_MODIFIED, pDTE);
        }
    }
}

QString CModifiedWidget::defaultObjectName() const
  {return "Modified";}

CCopasiObject* CModifiedWidget::createNewObject(const std::string & name)
{
  std::string nname = name;
  int i = 0;
  CModified* pModified = NULL;

  while (!(pModified = CCopasiDataModel::Global->getModel()->getMIRIAMInfo().createModified(name)))
    {
      i++;
      nname = name + "_";
      nname += (const char *)QString::number(i).utf8();
    }

  return pModified;
}

void CModifiedWidget::deleteObjects(const std::vector<std::string> & keys)
{

  QString modifiedList = "Are you sure you want to delete listed Modified Date(s) ?\n";
  unsigned C_INT32 i, imax = keys.size();
  for (i = 0; i < imax; i++) //all compartments
    {
      CModified * pModified =
        dynamic_cast< CModified *>(GlobalKeys.get(keys[i]));

      modifiedList.append(FROM_UTF8(pModified->getObjectName()));
      modifiedList.append(", ");
    }

  modifiedList.remove(modifiedList.length() - 2, 2);

  QString msg = modifiedList;

  C_INT32 choice = 0;
  choice = CQMessageBox::question(this,
                                  "CONFIRM DELETE",
                                  msg,
                                  "Continue", "Cancel", 0, 1, 1);

  switch (choice)
    {
    case 0:                                           // Yes or Enter
      {
        for (i = 0; i < imax; i++)
          {
            CCopasiDataModel::Global->getModel()->getMIRIAMInfo().removeModified(keys[i]);
          }

        //for (i = 0; i < imax; i++)
        //protectedNotify(ListViews::MODEL, ListViews::DELETE, keys[i]);

        mChanged = true;
        break;
      }
    default:                                           // No or Escape
      break;
    }
}
<commit_msg>small change<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/MIRIAMUI/Attic/CModifiedWidget.cpp,v $
//   $Revision: 1.2 $
//   $Name:  $
//   $Author: aekamal $
//   $Date: 2008/02/20 19:29:12 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include <qlayout.h>
#include <qpushbutton.h>

#include "model/CModel.h"
#include "MIRIAM/CAuthor.h"
#include "utilities/CCopasiVector.h"
#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiObject.h"
#include "report/CKeyFactory.h"
#include "UI/qtUtilities.h"
#include "UI/CQMessageBox.h"
#include "UI/CQDateTimeEditTableItem.h"

#include "CModifiedWidget.h"

#define COL_MARK               0
#define COL_DATE_MODIFIED      1

/*
 *  Constructs a CModifiedWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
CModifiedWidget::CModifiedWidget(QWidget* parent, const char* name, WFlags f)
    : CopasiTableWidget(parent, false, name, f, false)
{
  if (!name)
    CopasiTableWidget::setName("ModifiedWidget");
  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CModifiedWidget::~CModifiedWidget()
{
  // no need to delete child widgets, Qt does it all for us
}

std::vector<const CCopasiObject*> CModifiedWidget::getObjects() const
  {
    std::vector<const CCopasiObject*> ret;

    const CCopasiVector<CModified>& tmp = CCopasiDataModel::Global->getModel()->getMIRIAMInfo().getModifieds();

    C_INT32 i, imax = tmp.size();
    for (i = 0; i < imax; ++i)
      ret.push_back(tmp[i]);

    return ret;
  }

void CModifiedWidget::init()
{
  mShowNewObjectWarning = false;
  numCols = 2;
  table->setNumCols(numCols);

  //Setting table headers
  QHeader *tableHeader = table->horizontalHeader();
  tableHeader->setLabel(COL_MARK, "Status");
  tableHeader->setLabel(COL_DATE_MODIFIED, "Date and Time Modified");
}

void CModifiedWidget::tableLineFromObject(const CCopasiObject* obj, unsigned C_INT32 row)
{
  if (!obj) return;
  const CModified *pModified = (const CModified*)obj;

  CQDateTimeEditTableItem* pDTE = NULL;
  if (dynamic_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED)))
    {
      pDTE = static_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED));
      pDTE->setDateTime(QDateTime::fromString(FROM_UTF8(pModified->getDateModified()), Qt::ISODate));
    }
}

void CModifiedWidget::tableLineToObject(unsigned C_INT32 row, CCopasiObject* obj)
{
  if (!obj) return;
  CModified * pModified = static_cast< CModified * >(obj);

  if (dynamic_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED)))
    {
      CQDateTimeEditTableItem * pDTE = static_cast<CQDateTimeEditTableItem *> (table->cellWidget(row, COL_DATE_MODIFIED));
      std::string dt = "";
      if (pDTE->dateTime().toString(Qt::ISODate).ascii())
      {dt = pDTE->dateTime().toString(Qt::ISODate).ascii();}
      pModified->setDateModified(dt);
    }
}

void CModifiedWidget::defaultTableLineContent(unsigned C_INT32 row, unsigned C_INT32 exc)
{
  if (exc != COL_DATE_MODIFIED)
    {
      if (!dynamic_cast<CQDateTimeEditTableItem *>(table->cellWidget(row, COL_DATE_MODIFIED)))
        {
          CQDateTimeEditTableItem* pDTE = new CQDateTimeEditTableItem(this, row, COL_DATE_MODIFIED, table);
          pDTE->dateEdit()->setRange(QDate(), QDate::currentDate());
          table->setCellWidget(row, COL_DATE_MODIFIED, pDTE);
        }
    }
}

QString CModifiedWidget::defaultObjectName() const
  {return "Modified";}

CCopasiObject* CModifiedWidget::createNewObject(const std::string & name)
{
  std::string nname = name;
  int i = 0;
  CModified* pModified = NULL;

  while (!(pModified = CCopasiDataModel::Global->getModel()->getMIRIAMInfo().createModified(name)))
    {
      i++;
      nname = name + "_";
      nname += (const char *)QString::number(i).utf8();
    }

  return pModified;
}

void CModifiedWidget::deleteObjects(const std::vector<std::string> & keys)
{

  QString modifiedList = "Are you sure you want to delete listed Modified Date(s) ?\n";
  unsigned C_INT32 i, imax = keys.size();
  for (i = 0; i < imax; i++) //all compartments
    {
      CModified * pModified =
        dynamic_cast< CModified *>(GlobalKeys.get(keys[i]));

      modifiedList.append(FROM_UTF8(pModified->getObjectName()));
      modifiedList.append(", ");
    }

  modifiedList.remove(modifiedList.length() - 2, 2);

  QString msg = modifiedList;

  C_INT32 choice = 0;
  choice = CQMessageBox::question(this,
                                  "CONFIRM DELETE",
                                  msg,
                                  "Continue", "Cancel", 0, 1, 1);

  switch (choice)
    {
    case 0:                                           // Yes or Enter
      {
        for (i = 0; i < imax; i++)
          {
            CCopasiDataModel::Global->getModel()->getMIRIAMInfo().removeModified(keys[i]);
          }

        //for (i = 0; i < imax; i++)
        //protectedNotify(ListViews::MODEL, ListViews::DELETE, keys[i]);

        mChanged = true;
        break;
      }
    default:                                           // No or Escape
      break;
    }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <Context.h>
#include <i18n.h>
#include <CmdUndo.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdUndo::CmdUndo ()
{
  _keyword     = "undo";
  _usage       = "task          undo";
  _description = STRING_CMD_UNDO_USAGE;
  _read_only   = false;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdUndo::execute (std::string& output)
{
  // Detect attempts to modify the task.
  std::vector <Tree*>::iterator i;
  for (i = context.parser.tree ()->_branches.begin (); i != context.parser.tree ()->_branches.end (); ++i)
    if ((*i)->hasTag ("MODIFICATION"))
      throw std::string (STRING_CMD_UNDO_MODS);

  context.tdb2.revert ();
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>CmdUndo<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <Context.h>
#include <i18n.h>
#include <CmdUndo.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdUndo::CmdUndo ()
{
  _keyword     = "undo";
  _usage       = "task          undo";
  _description = STRING_CMD_UNDO_USAGE;
  _read_only   = false;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdUndo::execute (std::string& output)
{
  // Detect attempts to modify the task.
  std::vector <A>::iterator a;
  for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a)
    if (a->hasTag ("MODIFICATION"))
      throw std::string (STRING_CMD_UNDO_MODS);

  context.tdb2.revert ();
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>