<commit_before>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm.h"
#include "ghost/tsmttsm_gen.h"
#include "ghost/tsmttsm_avx2_gen.h"
#include "ghost/tsmttsm_avx_gen.h"
#include "ghost/tsmttsm_sse_gen.h"
#include "ghost/timing.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_parameters_t &a, const ghost_tsmttsm_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,ghost_hash(a.xstor,a.wstor,a.alignment))) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,ghost_hash(b.xstor,b.wstor,b.alignment)));
}

static map<ghost_tsmttsm_parameters_t, ghost_tsmttsm_kernel_t> ghost_tsmttsm_kernels;

ghost_error_t ghost_tsmttsm_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    /*if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored col-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }*/
    if (x->traits.location != GHOST_LOCATION_HOST || v->traits.location != GHOST_LOCATION_HOST || w->traits.location != GHOST_LOCATION_HOST) {
        if (printerror) {
            ERROR_LOG("TSMTTSM only implemented for host densemats!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);
    UNUSED(reduce);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    const char *vtrans;
    if (conjv && v->traits.datatype & GHOST_DT_COMPLEX) {
        vtrans = "C";
    } else {
        vtrans = "T";
    }

    if ((ret = ghost_tsmttsm_valid(x,v,vtrans,w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        INFO_LOG("TSMTTSM cannot be applied. Checking whether GEMM is fine!");
        if ((ret = ghost_gemm_valid(x,v,vtrans,w,"N",alpha,beta,reduce,GHOST_GEMM_DEFAULT,1)) != GHOST_SUCCESS) {
            ERROR_LOG("GEMM cannot be applied!");
            return ret;
        } else {
            return ghost_gemm(x,v,vtrans,w,"N",alpha,beta,reduce,GHOST_GEMM_NOT_SPECIAL);
        }
    }

    if (ghost_tsmttsm_kernels.empty()) {
#include "tsmttsm.def"
#include "tsmttsm_avx2.def"
#include "tsmttsm_avx.def"
#include "tsmttsm_sse.def"
    }

    ghost_tsmttsm_parameters_t p;
    ghost_tsmttsm_kernel_t kernel = NULL;

#ifdef GHOST_HAVE_MIC
    p.impl = GHOST_IMPLEMENTATION_MIC;
#elif defined(GHOST_HAVE_AVX2)
    p.impl = GHOST_IMPLEMENTATION_AVX2;
#elif defined(GHOST_HAVE_AVX)
    p.impl = GHOST_IMPLEMENTATION_AVX;
#elif defined(GHOST_HAVE_SSE)
    p.impl = GHOST_IMPLEMENTATION_SSE;
#else
    p.impl = GHOST_IMPLEMENTATION_PLAIN;
#endif

    /*if (x->traits.ncolspadded < 4 || x->traits.flags & GHOST_DENSEMAT_VIEW) {
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }*/
    //p.impl = GHOST_IMPLEMENTATION_PLAIN;

    p.alignment = GHOST_ALIGNED;
    p.dt = x->traits.datatype;
    p.xstor = x->traits.storage;
    p.wstor = w->traits.storage;

    p.vcols = v->traits.ncols;

    if (p.impl == GHOST_IMPLEMENTATION_SSE) {
        if (!IS_ALIGNED(x->val,16) || !IS_ALIGNED(v->val,16) || !IS_ALIGNED(w->val,16) ||
                (x->stride*x->elSize)%16 || (v->stride*v->elSize)%16 || (w->stride*w->elSize)%16) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
    }
    if (p.impl == GHOST_IMPLEMENTATION_AVX || p.impl == GHOST_IMPLEMENTATION_AVX2) {
        if (!IS_ALIGNED(x->val,32) || !IS_ALIGNED(v->val,32) || !IS_ALIGNED(w->val,32) ||
                (x->stride*x->elSize)%32 || (v->stride*v->elSize)%32 || (w->stride*w->elSize)%32) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
    }
    if (p.impl == GHOST_IMPLEMENTATION_PLAIN || p.impl == GHOST_IMPLEMENTATION_MIC) {
        if (!IS_ALIGNED(x->val,64) || !IS_ALIGNED(v->val,64) || !IS_ALIGNED(w->val,64) ||
                (x->stride*x->elSize)%64 || (v->stride*v->elSize)%64 || (w->stride*w->elSize)%64) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
    }
    p.wcols = w->traits.ncols;

    INFO_LOG("Inital search for kernel %d %d %d %d %d %d!",p.dt,p.wcols,p.vcols,p.xstor,p.wstor,p.alignment);
    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try plain implementation");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
        p.vcols = v->traits.ncols;
        p.wcols = w->traits.ncols;
        if (!IS_ALIGNED(x->val,64) || !IS_ALIGNED(v->val,64) || !IS_ALIGNED(w->val,64) ||
                (x->stride*x->elSize)%64 || (v->stride*v->elSize)%64 || (w->stride*w->elSize)%64) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try unaligned kernel");
        p.alignment = GHOST_UNALIGNED;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        INFO_LOG("Could not find TSMTTSM kernel with %d %d %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols,p.xstor,p.wstor);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

    if (reduce != GHOST_GEMM_NO_REDUCE && v->context) {
        x->reduce(x,v->context->mpicomm,reduce);
    }

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.n = w->traits.ncols;
    tsmttsm_perfargs.m = v->traits.ncols;
    if (v->context) {
        tsmttsm_perfargs.k = v->context->gnrows;
    } else {
        tsmttsm_perfargs.k = v->traits.nrows;
    }
    tsmttsm_perfargs.dt = x->traits.datatype;
    tsmttsm_perfargs.betaiszero = ghost_iszero(beta,p.dt);
    tsmttsm_perfargs.alphaisone = ghost_isone(alpha,p.dt);
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GBs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GB/s");
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<commit_msg>Adjust AVX tsmttsm kernel selection<commit_after>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm.h"
#include "ghost/tsmttsm_gen.h"
#include "ghost/tsmttsm_avx2_gen.h"
#include "ghost/tsmttsm_avx_gen.h"
#include "ghost/tsmttsm_sse_gen.h"
#include "ghost/timing.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_parameters_t &a, const ghost_tsmttsm_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,ghost_hash(a.xstor,a.wstor,a.alignment))) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,ghost_hash(b.xstor,b.wstor,b.alignment)));
}

static map<ghost_tsmttsm_parameters_t, ghost_tsmttsm_kernel_t> ghost_tsmttsm_kernels;

ghost_error_t ghost_tsmttsm_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    /*if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored col-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }*/
    if (x->traits.location != GHOST_LOCATION_HOST || v->traits.location != GHOST_LOCATION_HOST || w->traits.location != GHOST_LOCATION_HOST) {
        if (printerror) {
            ERROR_LOG("TSMTTSM only implemented for host densemats!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);
    UNUSED(reduce);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    const char *vtrans;
    if (conjv && v->traits.datatype & GHOST_DT_COMPLEX) {
        vtrans = "C";
    } else {
        vtrans = "T";
    }

    if ((ret = ghost_tsmttsm_valid(x,v,vtrans,w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        INFO_LOG("TSMTTSM cannot be applied. Checking whether GEMM is fine!");
        if ((ret = ghost_gemm_valid(x,v,vtrans,w,"N",alpha,beta,reduce,GHOST_GEMM_DEFAULT,1)) != GHOST_SUCCESS) {
            ERROR_LOG("GEMM cannot be applied!");
            return ret;
        } else {
            return ghost_gemm(x,v,vtrans,w,"N",alpha,beta,reduce,GHOST_GEMM_NOT_SPECIAL);
        }
    }

    if (ghost_tsmttsm_kernels.empty()) {
#include "tsmttsm.def"
#include "tsmttsm_avx2.def"
#include "tsmttsm_avx.def"
#include "tsmttsm_sse.def"
    }

    ghost_tsmttsm_parameters_t p;
    ghost_tsmttsm_kernel_t kernel = NULL;

#ifdef GHOST_HAVE_MIC
    p.impl = GHOST_IMPLEMENTATION_MIC;
#elif defined(GHOST_HAVE_AVX2)
    p.impl = GHOST_IMPLEMENTATION_AVX2;
#elif defined(GHOST_HAVE_AVX)
    p.impl = GHOST_IMPLEMENTATION_AVX;
#elif defined(GHOST_HAVE_SSE)
    p.impl = GHOST_IMPLEMENTATION_SSE;
#else
    p.impl = GHOST_IMPLEMENTATION_PLAIN;
#endif

    /*if (x->traits.ncolspadded < 4 || x->traits.flags & GHOST_DENSEMAT_VIEW) {
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }*/
    //p.impl = GHOST_IMPLEMENTATION_PLAIN;

    p.alignment = GHOST_ALIGNED;
    p.dt = x->traits.datatype;
    p.xstor = x->traits.storage;
    p.wstor = w->traits.storage;

    p.vcols = v->traits.ncols;

    if (p.impl == GHOST_IMPLEMENTATION_SSE) {
        if (!IS_ALIGNED(x->val,16) || !IS_ALIGNED(v->val,16) || !IS_ALIGNED(w->val,16) ||
                (x->stride*x->elSize)%16 || (v->stride*v->elSize)%16 || (w->stride*w->elSize)%16) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
    }
    if (p.impl == GHOST_IMPLEMENTATION_AVX || p.impl == GHOST_IMPLEMENTATION_AVX2) {
        if (!IS_ALIGNED(x->val,32) || !IS_ALIGNED(v->val,32) || !IS_ALIGNED(w->val,32) ||
                ((x->stride*x->elSize)%32 && (x->stride*x->elSize)>32) ||
                ((v->stride*v->elSize)%32 && (v->stride*v->elSize)>32) ||
                ((w->stride*w->elSize)%32 && (w->stride*w->elSize)>32) ){
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
    }
    if (p.impl == GHOST_IMPLEMENTATION_PLAIN || p.impl == GHOST_IMPLEMENTATION_MIC) {
        if (!IS_ALIGNED(x->val,64) || !IS_ALIGNED(v->val,64) || !IS_ALIGNED(w->val,64) ||
                (x->stride*x->elSize)%64 || (v->stride*v->elSize)%64 || (w->stride*w->elSize)%64) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
    }
    p.wcols = w->traits.ncols;

    INFO_LOG("Inital search for kernel %d %d %d %d %d %d!",p.dt,p.wcols,p.vcols,p.xstor,p.wstor,p.alignment);
    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try plain implementation");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
        p.vcols = v->traits.ncols;
        p.wcols = w->traits.ncols;
        if (!IS_ALIGNED(x->val,64) || !IS_ALIGNED(v->val,64) || !IS_ALIGNED(w->val,64) ||
                (x->stride*x->elSize)%64 || (v->stride*v->elSize)%64 || (w->stride*w->elSize)%64) {
            p.alignment = GHOST_UNALIGNED;
            PERFWARNING_LOG("Switching to the unaligned kernel!");
        }
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try unaligned kernel");
        p.alignment = GHOST_UNALIGNED;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        INFO_LOG("Could not find TSMTTSM kernel with %d %d %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols,p.xstor,p.wstor);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

    if (reduce != GHOST_GEMM_NO_REDUCE && v->context) {
        x->reduce(x,v->context->mpicomm,reduce);
    }

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.n = w->traits.ncols;
    tsmttsm_perfargs.m = v->traits.ncols;
    if (v->context) {
        tsmttsm_perfargs.k = v->context->gnrows;
    } else {
        tsmttsm_perfargs.k = v->traits.nrows;
    }
    tsmttsm_perfargs.dt = x->traits.datatype;
    tsmttsm_perfargs.betaiszero = ghost_iszero(beta,p.dt);
    tsmttsm_perfargs.alphaisone = ghost_isone(alpha,p.dt);
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GBs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GB/s");
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<|endoftext|>


<commit_before>#include <iostream>

#include <SmurffCpp/Utils/HDF5Group.h>

#include <Utils/Error.h>
#include <Utils/StringUtils.h>

namespace smurff {

bool HDF5Group::hasDataSet(const std::string& section, const std::string& tag) const
{
   if (!m_group.exist(section)) return false;
   auto section_group = m_group.getGroup(section);
   return (section_group.exist(tag));
}

bool HDF5Group::hasSection(const std::string& section) const
{
   return m_group.exist(section);
}

h5::Group HDF5Group::addGroup(const std::string& name)
{
   if (!m_group.exist(name)) m_group.createGroup(name);
   return getGroup(name);
}

h5::Group HDF5Group::getGroup(const std::string& name) const
{
   return m_group.getGroup(name);
}

void HDF5Group::read(const std::string& section, const std::string& tag, Matrix &X) const
{
   auto dataset = m_group.getGroup(section).getDataSet(tag);
   std::vector<size_t> dims = dataset.getDimensions();
   X.resize(dims[0], dims[1]);
   dataset.read(X.data());

   if (!X.IsRowMajor)
   {
      Matrix colMajor = Eigen::Map<Eigen::Matrix<
            typename Matrix::Scalar,
            Matrix::RowsAtCompileTime,
            Matrix::ColsAtCompileTime,
            Matrix::ColsAtCompileTime==1?Eigen::ColMajor:Eigen::RowMajor,
            Matrix::MaxRowsAtCompileTime,
            Matrix::MaxColsAtCompileTime>>(X.data(), dims[0], dims[1]);

      std::swap(colMajor, X);
   }
}

void HDF5Group::read(const std::string& section, const std::string& tag, Vector &X) const
{
   auto dataset = m_group.getGroup(section).getDataSet(tag);
   std::vector<size_t> dims = dataset.getDimensions();
   THROWERROR_ASSERT(dims[0] == 1);
   X.resize(dims[1]);
   dataset.read(X.data());
}

void HDF5Group::read(const std::string& section, const std::string& tag, SparseMatrix &X) const
{
   auto sparse_group = m_group.getGroup(section).getGroup(tag);

   std::string format;
   sparse_group.getAttribute("h5sparse_format").read(format);
   THROWERROR_ASSERT(( SparseMatrix::IsRowMajor && format == "csr") || \
                     (!SparseMatrix::IsRowMajor && format == "csc"));

   std::vector<Eigen::Index> shape(2);
   sparse_group.getAttribute("h5sparse_shape").read(shape);
   X.resize(shape.at(0), shape.at(1));
   X.makeCompressed();

   auto data = sparse_group.getDataSet("data");
   THROWERROR_ASSERT(data.getDataType() == h5::AtomicType<SparseMatrix::value_type>());
   X.resizeNonZeros(data.getElementCount());
   data.read(X.valuePtr());

   auto indptr = sparse_group.getDataSet("indptr");
   THROWERROR_ASSERT(indptr.getDataType() == h5::AtomicType<SparseMatrix::Index>());
   indptr.read(X.outerIndexPtr());

   auto indices = sparse_group.getDataSet("indices");
   THROWERROR_ASSERT(indices.getDataType() == h5::AtomicType<SparseMatrix::Index>());
   indices.read(X.innerIndexPtr());
}

void HDF5Group::read(const std::string& section, const std::string& tag, DenseTensor &) const
{
   THROWERROR_NOTIMPL();
}

void HDF5Group::read(const std::string& section, const std::string& tag, SparseTensor &) const
{
   THROWERROR_NOTIMPL();
}

void HDF5Group::write(const std::string& section, const std::string& tag, const Vector &V)
{
   write(section, tag, Matrix(V));
}

void HDF5Group::write(const std::string& section, const std::string& tag, const Matrix &M)
{
   if (!m_group.exist(section))
      m_group.createGroup(section);

   h5::Group group = m_group.getGroup(section);
   h5::DataSet dataset = group.createDataSet<Matrix::Scalar>(tag, h5::DataSpace({static_cast<size_t>(M.rows()),  static_cast<size_t>(M.cols())}));

   Eigen::Ref<
        const Eigen::Matrix<
            Matrix::Scalar,
            Matrix::RowsAtCompileTime,
            Matrix::ColsAtCompileTime,
            Matrix::ColsAtCompileTime==1?Eigen::ColMajor:Eigen::RowMajor,
            Matrix::MaxRowsAtCompileTime,
            Matrix::MaxColsAtCompileTime>,
        0,
        Eigen::InnerStride<1>> row_major(M);

    dataset.write(row_major.data());
}

void HDF5Group::write(const std::string& section, const std::string& tag, const SparseMatrix &X)
{
   if (!m_group.exist(section))
      m_group.createGroup(section);

   h5::Group sparse_group = m_group.getGroup(section).createGroup(tag);

   sparse_group.createAttribute<std::string>("h5sparse_format", (SparseMatrix::IsRowMajor ? "csr" : "csc"));
   std::vector<Eigen::Index> shape{X.innerSize(), X.outerSize()};
   sparse_group.createAttribute<Eigen::Index>("h5sparse_shape", h5::DataSpace::From(shape)).write(shape);

   auto data = sparse_group.createDataSet<SparseMatrix::value_type>("data", h5::DataSpace(X.nonZeros()));
   data.write(X.valuePtr());

   auto indptr = sparse_group.createDataSet<SparseMatrix::Index>("indptr", h5::DataSpace(X.outerSize() + 1));
   indptr.write(X.outerIndexPtr());

   auto indices = sparse_group.createDataSet<SparseMatrix::Index>("indices", h5::DataSpace(X.nonZeros()));
   indices.write(X.innerIndexPtr());
}

void HDF5Group::write(const std::string& section, const std::string& tag, const DenseTensor &X)
{
   THROWERROR_NOTIMPL();
}

void HDF5Group::write(const std::string& section, const std::string& tag, const SparseTensor &X)
{
   THROWERROR_NOTIMPL();
}

} // end namespace smurff
<commit_msg>FIX: h5sparse format rows/cols was switched<commit_after>#include <iostream>

#include <SmurffCpp/Utils/HDF5Group.h>

#include <Utils/Error.h>
#include <Utils/StringUtils.h>

namespace smurff {

bool HDF5Group::hasDataSet(const std::string& section, const std::string& tag) const
{
   if (!m_group.exist(section)) return false;
   auto section_group = m_group.getGroup(section);
   return (section_group.exist(tag));
}

bool HDF5Group::hasSection(const std::string& section) const
{
   return m_group.exist(section);
}

h5::Group HDF5Group::addGroup(const std::string& name)
{
   if (!m_group.exist(name)) m_group.createGroup(name);
   return getGroup(name);
}

h5::Group HDF5Group::getGroup(const std::string& name) const
{
   return m_group.getGroup(name);
}

void HDF5Group::read(const std::string& section, const std::string& tag, Matrix &X) const
{
   auto dataset = m_group.getGroup(section).getDataSet(tag);
   std::vector<size_t> dims = dataset.getDimensions();
   X.resize(dims[0], dims[1]);
   dataset.read(X.data());

   if (!X.IsRowMajor)
   {
      Matrix colMajor = Eigen::Map<Eigen::Matrix<
            typename Matrix::Scalar,
            Matrix::RowsAtCompileTime,
            Matrix::ColsAtCompileTime,
            Matrix::ColsAtCompileTime==1?Eigen::ColMajor:Eigen::RowMajor,
            Matrix::MaxRowsAtCompileTime,
            Matrix::MaxColsAtCompileTime>>(X.data(), dims[0], dims[1]);

      std::swap(colMajor, X);
   }
}

void HDF5Group::read(const std::string& section, const std::string& tag, Vector &X) const
{
   auto dataset = m_group.getGroup(section).getDataSet(tag);
   std::vector<size_t> dims = dataset.getDimensions();
   THROWERROR_ASSERT(dims[0] == 1);
   X.resize(dims[1]);
   dataset.read(X.data());
}

void HDF5Group::read(const std::string& section, const std::string& tag, SparseMatrix &X) const
{
   auto sparse_group = m_group.getGroup(section).getGroup(tag);

   std::string format;
   sparse_group.getAttribute("h5sparse_format").read(format);
   THROWERROR_ASSERT(( SparseMatrix::IsRowMajor && format == "csr") || \
                     (!SparseMatrix::IsRowMajor && format == "csc"));

   std::vector<Eigen::Index> shape(2);
   sparse_group.getAttribute("h5sparse_shape").read(shape);
   X.resize(shape.at(0), shape.at(1));
   X.makeCompressed();

   auto data = sparse_group.getDataSet("data");
   THROWERROR_ASSERT(data.getDataType() == h5::AtomicType<SparseMatrix::value_type>());
   X.resizeNonZeros(data.getElementCount());
   data.read(X.valuePtr());

   auto indptr = sparse_group.getDataSet("indptr");
   THROWERROR_ASSERT(indptr.getDataType() == h5::AtomicType<SparseMatrix::Index>());
   indptr.read(X.outerIndexPtr());

   auto indices = sparse_group.getDataSet("indices");
   THROWERROR_ASSERT(indices.getDataType() == h5::AtomicType<SparseMatrix::Index>());
   indices.read(X.innerIndexPtr());
}

void HDF5Group::read(const std::string& section, const std::string& tag, DenseTensor &) const
{
   THROWERROR_NOTIMPL();
}

void HDF5Group::read(const std::string& section, const std::string& tag, SparseTensor &) const
{
   THROWERROR_NOTIMPL();
}

void HDF5Group::write(const std::string& section, const std::string& tag, const Vector &V)
{
   write(section, tag, Matrix(V));
}

void HDF5Group::write(const std::string& section, const std::string& tag, const Matrix &M)
{
   if (!m_group.exist(section))
      m_group.createGroup(section);

   h5::Group group = m_group.getGroup(section);
   h5::DataSet dataset = group.createDataSet<Matrix::Scalar>(tag, h5::DataSpace({static_cast<size_t>(M.rows()),  static_cast<size_t>(M.cols())}));

   Eigen::Ref<
        const Eigen::Matrix<
            Matrix::Scalar,
            Matrix::RowsAtCompileTime,
            Matrix::ColsAtCompileTime,
            Matrix::ColsAtCompileTime==1?Eigen::ColMajor:Eigen::RowMajor,
            Matrix::MaxRowsAtCompileTime,
            Matrix::MaxColsAtCompileTime>,
        0,
        Eigen::InnerStride<1>> row_major(M);

    dataset.write(row_major.data());
}

void HDF5Group::write(const std::string& section, const std::string& tag, const SparseMatrix &X)
{
   if (!m_group.exist(section))
      m_group.createGroup(section);

   h5::Group sparse_group = m_group.getGroup(section).createGroup(tag);

   sparse_group.createAttribute<std::string>("h5sparse_format", (SparseMatrix::IsRowMajor ? "csr" : "csc"));
   std::vector<Eigen::Index> shape{X.rows(), X.cols()};
   sparse_group.createAttribute<Eigen::Index>("h5sparse_shape", h5::DataSpace::From(shape)).write(shape);

   auto data = sparse_group.createDataSet<SparseMatrix::value_type>("data", h5::DataSpace(X.nonZeros()));
   data.write(X.valuePtr());

   auto indptr = sparse_group.createDataSet<SparseMatrix::Index>("indptr", h5::DataSpace(X.outerSize() + 1));
   indptr.write(X.outerIndexPtr());

   auto indices = sparse_group.createDataSet<SparseMatrix::Index>("indices", h5::DataSpace(X.nonZeros()));
   indices.write(X.innerIndexPtr());
}

void HDF5Group::write(const std::string& section, const std::string& tag, const DenseTensor &X)
{
   THROWERROR_NOTIMPL();
}

void HDF5Group::write(const std::string& section, const std::string& tag, const SparseTensor &X)
{
   THROWERROR_NOTIMPL();
}

} // end namespace smurff
<|endoftext|>


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

#include <algorithm>
#include <iostream>
#include <map>
#include <unordered_set>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "EmailSender.h"
#include "IniFile.h"
#include "MARC.h"
#include "UBTools.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
   ::Usage("marc_input marc_output missed_expectations_file email_address");
}

enum FieldPresence { ALWAYS, SOMETIMES, IGNORE };

struct FieldInfo {
    std::string name_;
    FieldPresence presence_;
public:
    FieldInfo(const std::string &name, const FieldPresence presence): name_(name), presence_(presence) { }
};

class JournalInfo {
    bool not_in_database_yet_;
    std::vector<FieldInfo> field_infos_;
public:
    using const_iterator = std::vector<FieldInfo>::const_iterator;
    using iterator = std::vector<FieldInfo>::iterator;
public:
    explicit JournalInfo(const bool not_in_database_yet): not_in_database_yet_(not_in_database_yet) { }
    JournalInfo() = default;
    JournalInfo(const JournalInfo &rhs) = default;

    size_t size() const { return field_infos_.size(); }
    bool isInDatabase() const { return not not_in_database_yet_; }
    void addField(const std::string &field_name, const FieldPresence field_presence)
        { field_infos_.emplace_back(field_name, field_presence); }
    const_iterator begin() const { return field_infos_.cbegin(); }
    const_iterator end() const { return field_infos_.cend(); }
    iterator begin() { return field_infos_.begin(); }
    iterator end() { return field_infos_.end(); }
    iterator find(const std::string &field_name) {
        return std::find_if(field_infos_.begin(), field_infos_.end(),
                            [&field_name](const FieldInfo &field_info){ return field_name == field_info.name_; });
    }
};

FieldPresence StringToFieldPresence(const std::string &s) {
    if (s == "always")
        return ALWAYS;
    if (s == "sometimes")
        return SOMETIMES;
    if (s == "ignore")
        return IGNORE;
    LOG_ERROR("unknown enumerated value \"" + s + "\"!");
}

std::string FieldPresenceToString(const FieldPresence field_presence) {
    switch (field_presence) {
    case ALWAYS:
        return "always";
    case SOMETIMES:
        return "sometimes";
    case IGNORE:
        return "ignore";
    default:
        LOG_ERROR("we should *never get here!");
    }
}

void LoadFromDatabaseOrCreateFromScratch(DbConnection * const db_connection, const std::string &journal_name,
                                         JournalInfo * const journal_info)
{
    db_connection->queryOrDie("SELECT metadata_field_name,field_presence FROM metadata_presence_tracer WHERE journal_name='"
                              + db_connection->escapeString(journal_name) + "'");
    DbResultSet result_set(db_connection->getLastResultSet());
    if (result_set.empty()) {
        LOG_INFO("\"" + journal_name + "\" was not yet in the database.");
        *journal_info = JournalInfo(/* not_in_database_yet = */true);
        return;
    }

    *journal_info = JournalInfo(/* not_in_database_yet = */false);
    while (auto row = result_set.getNextRow())
        journal_info->addField(row["metadata_field_name"], StringToFieldPresence(row["field_presence"]));
}

// Two-way mapping required as the map is uni-directional
const std::map<std::string, std::string> EQUIVALENT_TAGS_MAP{
    { "700", "100" }, { "100", "700" }
};

void AnalyseNewJournalRecord(const MARC::Record &record, const bool first_record, JournalInfo * const journal_info) {
    std::unordered_set<std::string> seen_tags;
    MARC::Tag last_tag;
    for (const auto &field : record) {
        auto current_tag(field.getTag());
        if (current_tag == last_tag)
            continue;

        seen_tags.emplace(current_tag.toString());

        if (first_record)
            journal_info->addField(current_tag.toString(), ALWAYS);
        else if (journal_info->find(current_tag.toString()) == journal_info->end())
            journal_info->addField(current_tag.toString(), SOMETIMES);

        last_tag = current_tag;
    }

    for (auto &field_info : *journal_info) {
        if (seen_tags.find(field_info.name_) == seen_tags.end())
            field_info.presence_ = SOMETIMES;
    }
}

bool RecordMeetsExpectations(const MARC::Record &record, const std::string &journal_name, const JournalInfo &journal_info) {
    std::unordered_set<std::string> seen_tags;
    MARC::Tag last_tag;
    for (const auto &field : record) {
        const auto current_tag(field.getTag());
        if (current_tag == last_tag)
            continue;
        seen_tags.emplace(current_tag.toString());
        last_tag = current_tag;
    }

    bool missed_at_least_one_expectation(false);
    for (const auto &field_info : journal_info) {
        if (field_info.presence_ != ALWAYS)
            continue;   // we only care about required fields that are missing

        const auto equivalent_tag(EQUIVALENT_TAGS_MAP.find(field_info.name_));
        if (seen_tags.find(field_info.name_) != seen_tags.end())
            ;// required tag found
        else if (equivalent_tag != EQUIVALENT_TAGS_MAP.end() and seen_tags.find(equivalent_tag->second) != seen_tags.end())
            ;// equivalent tag found
        else {
            LOG_WARNING("Record w/ control number " + record.getControlNumber() + " in \"" + journal_name
                     + "\" is missing the always expected " + field_info.name_ + " field.");
            missed_at_least_one_expectation = true;
        }
    }

    return not missed_at_least_one_expectation;
}

void WriteToDatabase(DbConnection * const db_connection, const std::string &journal_name, const JournalInfo &journal_info) {
    for (const auto &field_info : journal_info)
        db_connection->queryOrDie("INSERT INTO metadata_presence_tracer SET journal_name='" + journal_name
                                  + "', metadata_field_name='" + db_connection->escapeString(field_info.name_)
                                  + "', field_presence='" + FieldPresenceToString(field_info.presence_) + "'");
}

void SendEmail(const std::string &email_address, const std::string &message_subject, const std::string &message_body) {
    const auto reply_code(EmailSender::SendEmail("zts_harvester_delivery_pipeline@uni-tuebingen.de",
                          email_address, message_subject, message_body,
                          EmailSender::MEDIUM, EmailSender::PLAIN_TEXT, /* reply_to = */ "",
                          /* use_ssl = */ true, /* use_authentication = */ true));

    if (reply_code >= 300)
        LOG_WARNING("failed to send email, the response code was: " + std::to_string(reply_code));
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 5)
        Usage();

    DbConnection db_connection;
    auto reader(MARC::Reader::Factory(argv[1]));
    auto valid_records_writer(MARC::Writer::Factory(argv[2]));
    auto delinquent_records_writer(MARC::Writer::Factory(argv[3]));
    std::map<std::string, JournalInfo> journal_name_to_info_map;
    const std::string email_address(argv[4]);

    unsigned total_record_count(0), new_record_count(0), missed_expectation_count(0);
    while (const auto record = reader->read()) {
        ++total_record_count;
        bool validation_failed(false);

        // Intentionally true to allow early breaking
        while (true) {
            const auto journal_name(record.getSuperiorTitle());
            if (journal_name.empty()) {
                LOG_WARNING("Record w/ control number \"" + record.getControlNumber() + "\" is missing a superior title!");
                validation_failed = true;
                break;
            }

            auto journal_name_and_info(journal_name_to_info_map.find(journal_name));
            bool first_record(false); // True if the current record is the first encounter of a journal
            if (journal_name_and_info == journal_name_to_info_map.end()) {
                first_record = true;
                JournalInfo new_journal_info;
                LoadFromDatabaseOrCreateFromScratch(&db_connection, journal_name, &new_journal_info);
                journal_name_to_info_map[journal_name] = new_journal_info;
                journal_name_and_info = journal_name_to_info_map.find(journal_name);
            }

            if (journal_name_and_info->second.isInDatabase()) {
                if (not RecordMeetsExpectations(record, journal_name_and_info->first, journal_name_and_info->second)) {
                    validation_failed = true;
                    ++missed_expectation_count;
                    break;
                }
            } else {
                AnalyseNewJournalRecord(record, first_record, &journal_name_and_info->second);
                ++new_record_count;
            }

            // Break unconditionally
            break;
        }

        if (validation_failed)
            delinquent_records_writer->write(record);
        else
            valid_records_writer->write(record);
    }

    for (const auto &journal_name_and_info : journal_name_to_info_map) {
        if (not journal_name_and_info.second.isInDatabase())
            WriteToDatabase(&db_connection, journal_name_and_info.first, journal_name_and_info.second);
    }

    if (missed_expectation_count > 0) {
        // send notification to the email address
        SendEmail(email_address, "validate_harvested_records encountered warnings",
                  "Some records missed expectations with respect to MARC fields. "
                  "Check the log at '/usr/local/var/log/tuefind/zts_harvester_delivery_pipeline.log' for details.");
    }

    LOG_INFO("Processed " + std::to_string(total_record_count) + " record(s) of which " + std::to_string(new_record_count)
             + " was/were (a) record(s) of new journals and " + std::to_string(missed_expectation_count)
             + " record(s) missed expectations.");

    return EXIT_SUCCESS;
}
<commit_msg>Added a new mode to alter expectations for MARC fields.<commit_after>/** \brief Utility for validating and fixing up records harvested by zts_harvester
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <map>
#include <unordered_set>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "EmailSender.h"
#include "IniFile.h"
#include "MARC.h"
#include "UBTools.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
   ::Usage("(marc_input marc_output missed_expectations_file email_address| update_db journal_name field_name field_presence)\n"
           "\tThis tool has two operating modes 1) checking MARC data for missed expectations and 2) altering these expectations.\n"
           "\tin the \"update_db\" mode, \"field_name\" must be a 3-character MARC tag and \"field_presence\" must be one of\n"
           "\tALWAYS, SOMETIMES, IGNORE.  Please note that only existing entries can be changed!");
}

enum FieldPresence { ALWAYS, SOMETIMES, IGNORE };

bool StringToFieldPresence(const std::string &field_presence_str, FieldPresence * const field_presence) {
    if (field_presence_str == "ALWAYS") {
        *field_presence = ALWAYS;
        return true;
    }

    if (field_presence_str == "SOMETIMES") {
        *field_presence = SOMETIMES;
        return true;
    }

    if (field_presence_str == "IGNORE") {
        *field_presence = IGNORE;
        return true;
    }

    return false;
}

struct FieldInfo {
    std::string name_;
    FieldPresence presence_;
public:
    FieldInfo(const std::string &name, const FieldPresence presence): name_(name), presence_(presence) { }
};

class JournalInfo {
    bool not_in_database_yet_;
    std::vector<FieldInfo> field_infos_;
public:
    using const_iterator = std::vector<FieldInfo>::const_iterator;
    using iterator = std::vector<FieldInfo>::iterator;
public:
    explicit JournalInfo(const bool not_in_database_yet): not_in_database_yet_(not_in_database_yet) { }
    JournalInfo() = default;
    JournalInfo(const JournalInfo &rhs) = default;

    size_t size() const { return field_infos_.size(); }
    bool isInDatabase() const { return not not_in_database_yet_; }
    void addField(const std::string &field_name, const FieldPresence field_presence)
        { field_infos_.emplace_back(field_name, field_presence); }
    const_iterator begin() const { return field_infos_.cbegin(); }
    const_iterator end() const { return field_infos_.cend(); }
    iterator begin() { return field_infos_.begin(); }
    iterator end() { return field_infos_.end(); }
    iterator find(const std::string &field_name) {
        return std::find_if(field_infos_.begin(), field_infos_.end(),
                            [&field_name](const FieldInfo &field_info){ return field_name == field_info.name_; });
    }
};

FieldPresence StringToFieldPresence(const std::string &s) {
    if (s == "always")
        return ALWAYS;
    if (s == "sometimes")
        return SOMETIMES;
    if (s == "ignore")
        return IGNORE;
    LOG_ERROR("unknown enumerated value \"" + s + "\"!");
}

std::string FieldPresenceToString(const FieldPresence field_presence) {
    switch (field_presence) {
    case ALWAYS:
        return "always";
    case SOMETIMES:
        return "sometimes";
    case IGNORE:
        return "ignore";
    default:
        LOG_ERROR("we should *never get here!");
    }
}

void LoadFromDatabaseOrCreateFromScratch(DbConnection * const db_connection, const std::string &journal_name,
                                         JournalInfo * const journal_info)
{
    db_connection->queryOrDie("SELECT metadata_field_name,field_presence FROM metadata_presence_tracer WHERE journal_name='"
                              + db_connection->escapeString(journal_name) + "'");
    DbResultSet result_set(db_connection->getLastResultSet());
    if (result_set.empty()) {
        LOG_INFO("\"" + journal_name + "\" was not yet in the database.");
        *journal_info = JournalInfo(/* not_in_database_yet = */true);
        return;
    }

    *journal_info = JournalInfo(/* not_in_database_yet = */false);
    while (auto row = result_set.getNextRow())
        journal_info->addField(row["metadata_field_name"], StringToFieldPresence(row["field_presence"]));
}

// Two-way mapping required as the map is uni-directional
const std::map<std::string, std::string> EQUIVALENT_TAGS_MAP{
    { "700", "100" }, { "100", "700" }
};

void AnalyseNewJournalRecord(const MARC::Record &record, const bool first_record, JournalInfo * const journal_info) {
    std::unordered_set<std::string> seen_tags;
    MARC::Tag last_tag;
    for (const auto &field : record) {
        auto current_tag(field.getTag());
        if (current_tag == last_tag)
            continue;

        seen_tags.emplace(current_tag.toString());

        if (first_record)
            journal_info->addField(current_tag.toString(), ALWAYS);
        else if (journal_info->find(current_tag.toString()) == journal_info->end())
            journal_info->addField(current_tag.toString(), SOMETIMES);

        last_tag = current_tag;
    }

    for (auto &field_info : *journal_info) {
        if (seen_tags.find(field_info.name_) == seen_tags.end())
            field_info.presence_ = SOMETIMES;
    }
}

bool RecordMeetsExpectations(const MARC::Record &record, const std::string &journal_name, const JournalInfo &journal_info) {
    std::unordered_set<std::string> seen_tags;
    MARC::Tag last_tag;
    for (const auto &field : record) {
        const auto current_tag(field.getTag());
        if (current_tag == last_tag)
            continue;
        seen_tags.emplace(current_tag.toString());
        last_tag = current_tag;
    }

    bool missed_at_least_one_expectation(false);
    for (const auto &field_info : journal_info) {
        if (field_info.presence_ != ALWAYS)
            continue;   // we only care about required fields that are missing

        const auto equivalent_tag(EQUIVALENT_TAGS_MAP.find(field_info.name_));
        if (seen_tags.find(field_info.name_) != seen_tags.end())
            ;// required tag found
        else if (equivalent_tag != EQUIVALENT_TAGS_MAP.end() and seen_tags.find(equivalent_tag->second) != seen_tags.end())
            ;// equivalent tag found
        else {
            LOG_WARNING("Record w/ control number " + record.getControlNumber() + " in \"" + journal_name
                     + "\" is missing the always expected " + field_info.name_ + " field.");
            missed_at_least_one_expectation = true;
        }
    }

    return not missed_at_least_one_expectation;
}

void WriteToDatabase(DbConnection * const db_connection, const std::string &journal_name, const JournalInfo &journal_info) {
    for (const auto &field_info : journal_info)
        db_connection->queryOrDie("INSERT INTO metadata_presence_tracer SET journal_name='" + journal_name
                                  + "', metadata_field_name='" + db_connection->escapeString(field_info.name_)
                                  + "', field_presence='" + FieldPresenceToString(field_info.presence_) + "'");
}

void SendEmail(const std::string &email_address, const std::string &message_subject, const std::string &message_body) {
    const auto reply_code(EmailSender::SendEmail("zts_harvester_delivery_pipeline@uni-tuebingen.de",
                          email_address, message_subject, message_body,
                          EmailSender::MEDIUM, EmailSender::PLAIN_TEXT, /* reply_to = */ "",
                          /* use_ssl = */ true, /* use_authentication = */ true));

    if (reply_code >= 300)
        LOG_WARNING("failed to send email, the response code was: " + std::to_string(reply_code));
}

void UpdateDB(DbConnection * const db_connection, const std::string &journal_name, const std::string &field_name, const std::string &field_presence_str) {
    FieldPresence field_presence;
    if (not StringToFieldPresence(field_presence_str, &field_presence))
        LOG_ERROR("\"" + field_presence_str + "\" is not a valid field_presence!");
    if (field_name.length() != MARC::Record::TAG_LENGTH)
        LOG_ERROR("\"" + field_name + "\" is not a valid field name!");

    DbTransaction transcation(db_connection);
    db_connection->queryOrDie("SELECT field_presence FROM metadata_presence_tracer WHERE journal_name="
                              + db_connection->escapeAndQuoteString(journal_name) + " AND field_name='" + field_name + "'");
    const DbResultSet result_set(db_connection->getLastResultSet());
    if (result_set.empty())
        LOG_ERROR("can't update non-existent database entry!");
    db_connection->queryOrDie("UPDATE metadata_presence_tracer SET field_presence='" + field_presence_str + "' WHERE journal_name="
                              + db_connection->escapeAndQuoteString(journal_name) + " AND field_name='" + field_name + "'");
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 5)
        Usage();

    DbConnection db_connection;

    if (std::strcmp(argv[1], "update_db") == 0) {
        UpdateDB(&db_connection, argv[2], argv[3], argv[4]);
        return EXIT_SUCCESS;
    }

    auto reader(MARC::Reader::Factory(argv[1]));
    auto valid_records_writer(MARC::Writer::Factory(argv[2]));
    auto delinquent_records_writer(MARC::Writer::Factory(argv[3]));
    std::map<std::string, JournalInfo> journal_name_to_info_map;
    const std::string email_address(argv[4]);

    unsigned total_record_count(0), new_record_count(0), missed_expectation_count(0);
    while (const auto record = reader->read()) {
        ++total_record_count;
        bool validation_failed(false);

        // Intentionally true to allow early breaking
        while (true) {
            const auto journal_name(record.getSuperiorTitle());
            if (journal_name.empty()) {
                LOG_WARNING("Record w/ control number \"" + record.getControlNumber() + "\" is missing a superior title!");
                validation_failed = true;
                break;
            }

            auto journal_name_and_info(journal_name_to_info_map.find(journal_name));
            bool first_record(false); // True if the current record is the first encounter of a journal
            if (journal_name_and_info == journal_name_to_info_map.end()) {
                first_record = true;
                JournalInfo new_journal_info;
                LoadFromDatabaseOrCreateFromScratch(&db_connection, journal_name, &new_journal_info);
                journal_name_to_info_map[journal_name] = new_journal_info;
                journal_name_and_info = journal_name_to_info_map.find(journal_name);
            }

            if (journal_name_and_info->second.isInDatabase()) {
                if (not RecordMeetsExpectations(record, journal_name_and_info->first, journal_name_and_info->second)) {
                    validation_failed = true;
                    ++missed_expectation_count;
                    break;
                }
            } else {
                AnalyseNewJournalRecord(record, first_record, &journal_name_and_info->second);
                ++new_record_count;
            }

            // Break unconditionally
            break;
        }

        if (validation_failed)
            delinquent_records_writer->write(record);
        else
            valid_records_writer->write(record);
    }

    for (const auto &journal_name_and_info : journal_name_to_info_map) {
        if (not journal_name_and_info.second.isInDatabase())
            WriteToDatabase(&db_connection, journal_name_and_info.first, journal_name_and_info.second);
    }

    if (missed_expectation_count > 0) {
        // send notification to the email address
        SendEmail(email_address, "validate_harvested_records encountered warnings",
                  "Some records missed expectations with respect to MARC fields. "
                  "Check the log at '/usr/local/var/log/tuefind/zts_harvester_delivery_pipeline.log' for details.");
    }

    LOG_INFO("Processed " + std::to_string(total_record_count) + " record(s) of which " + std::to_string(new_record_count)
             + " was/were (a) record(s) of new journals and " + std::to_string(missed_expectation_count)
             + " record(s) missed expectations.");

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <queue>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
#include <stack>

using namespace std;

stack<string> lv1;
stack<string> lv2;
stack<string> lv3;

string temp;
int templv;
int temptime=0;
int usernum;
int users=0;
int read(int now){
	if(now < temptime) return 0;

	do{
		printf("test\n");
		if(temp.empty()){

		}else{

			switch(templv){
				case 1:
					lv1.push(temp);break;
				case 2:
					lv2.push(temp);break;
				case 3:
					lv3.push(temp);break;
			}
		}
		if(users<usernum)
			cin >>temptime>>templv>>temp;
		else
			return 0;
		users++;
	}while(temptime<=now);

}
int main(int argc, char const *argv[])
{
		int time;
		scanf("%d%d",&usernum,&time);
		for (int i = 0; i < time; ++i)
		{
			read(i);
			cout<<i<<"\n"<<lv1.size()<<lv2.size()<<lv3.size()<<endl;
			if(users==usernum) break;
		}

	return 0;
}<commit_msg>update uoj2254<commit_after>#include <stdio.h>
#include <queue>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
#include <stack>

using namespace std;

stack<string> lv1;
stack<string> lv2;
stack<string> lv3;

string temp;
int templv;
int temptime=0;
int usernum;
int users=0;
int read(int now){
	if(now < temptime) return 0;

	do{
		printf("test\n");
		if(temp.empty()){

		}else{

			switch(templv){
				case 1:
					lv1.push(temp);break;
				case 2:
					lv2.push(temp);break;
				case 3:
					lv3.push(temp);break;
			}
		}
		if(users<usernum)
			cin >>temptime>>templv>>temp;
		else
			return 0;
		users++;
	}while(temptime<=now);

}
int main(int argc, char const *argv[])
{
		int time;
		scanf("%d%d",&usernum,&time);
		for (int i = 0; i < time; ++i)
		{
			read(i);
			cout<<i<<"\n"<<lv1.size()<<lv2.size()<<lv3.size()<<endl;

		}

	return 0;
}<|endoftext|>


<commit_before>#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <irrlicht/Keycodes.h>
#include <stdio.h>
#include <unistd.h>

#define RETURN 13
#define BS 8
#define SPACE 32

XKeyEvent createKeyEvent(Display *display,
                         Window &win,
                         Window &winRoot,
                         bool press,
                         int keycode,
                         int modifiers)
{
  // Largely lifted from
  // http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html
  XKeyEvent event;
  event.display = display;
  event.window = win;
  event.root = winRoot;
  event.subwindow = None;
  event.time = CurrentTime;
  event.x = 1;
  event.y = 1;
  event.x_root = 1;
  event.y_root = 1;
  event.same_screen = True;
  event.keycode = XKeysymToKeycode(display, keycode);
  event.state = modifiers;

  if(press)
    event.type = KeyPress;
  else
    event.type = KeyRelease;

  return event;
}

class X11Display {
  public:
    Display *display;
    X11Display(const char* dispName);
};

X11Display::X11Display(const char* dispName) :
  display(XOpenDisplay(dispName)){}

int mapKeyCode(int irrcode){
  switch(irrcode){
    //FIXME: only to get rid of arrow spam
    case 37 ... 40:
      return -1;
    case irr::KEY_BACK :
      return XK_BackSpace;
    case irr::KEY_TAB :
      return XK_Tab;
    case irr::KEY_RETURN :
      return XK_Return;
    case irr::KEY_MINUS :
      return XK_minus;
    case irr::KEY_OEM_7 :
      return XK_apostrophe;
    default:
      return irrcode;
  }
}

int sendKeyEvent(const char* disp, int keycode)
{
  if(-1==keycode)
    return 0;
  printf("sendKeyEvent keycode: %d\n", keycode);
  Window winFocus;
  int revert;

  Display *display = XOpenDisplay(disp);
  if(NULL == display)
    return -1;
  Window winRoot = XDefaultRootWindow(display);
  //XSetInputFocus(display, 1, revert, CurrentTime);
  XGetInputFocus(display, &winFocus, &revert);
  XKeyEvent event = createKeyEvent(display, winFocus, winRoot, true, keycode, 0);
  XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent*)&event);
  event = createKeyEvent(display, winFocus, winRoot, false, keycode, 0);
  XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent*)&event);
  XCloseDisplay(display);
  return 0;
}
<commit_msg>Constructor, destructor, no segfault<commit_after>#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <irrlicht/Keycodes.h>
#include <stdio.h>
#include <unistd.h>

#define RETURN 13
#define BS 8
#define SPACE 32

XKeyEvent createKeyEvent(Display *display,
                         Window &win,
                         Window &winRoot,
                         bool press,
                         int keycode,
                         int modifiers)
{
  // Largely lifted from
  // http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html
  XKeyEvent event;
  event.display = display;
  event.window = win;
  event.root = winRoot;
  event.subwindow = None;
  event.time = CurrentTime;
  event.x = 1;
  event.y = 1;
  event.x_root = 1;
  event.y_root = 1;
  event.same_screen = True;
  event.keycode = XKeysymToKeycode(display, keycode);
  event.state = modifiers;

  if(press)
    event.type = KeyPress;
  else
    event.type = KeyRelease;

  return event;
}

class X11Display {
  public:
    Display *display;
    X11Display(const char* dispName);
    ~X11Display();
};

X11Display::X11Display(const char* dispName) :
  display(XOpenDisplay(dispName)){}

X11Display::~X11Display() { XCloseDisplay(display); }

int mapKeyCode(int irrcode){
  switch(irrcode){
    //FIXME: only to get rid of arrow spam
    case 37 ... 40:
      return -1;
    case irr::KEY_BACK :
      return XK_BackSpace;
    case irr::KEY_TAB :
      return XK_Tab;
    case irr::KEY_RETURN :
      return XK_Return;
    case irr::KEY_MINUS :
      return XK_minus;
    case irr::KEY_OEM_7 :
      return XK_apostrophe;
    default:
      return irrcode;
  }
}

int sendKeyEvent(const char* disp, int keycode)
{
  if(-1==keycode)
    return 0;
  printf("sendKeyEvent keycode: %d\n", keycode);
  Window winFocus;
  int revert;

  X11Display X11Display(disp);

  Display *display = XOpenDisplay(disp);
  if(NULL == display)
    return -1;
  Window winRoot = XDefaultRootWindow(display);
  //XSetInputFocus(display, 1, revert, CurrentTime);
  XGetInputFocus(display, &winFocus, &revert);
  XKeyEvent event = createKeyEvent(display, winFocus, winRoot, true, keycode, 0);
  XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent*)&event);
  event = createKeyEvent(display, winFocus, winRoot, false, keycode, 0);
  XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent*)&event);
  XCloseDisplay(display);
  return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <queue>
#include <vector>
#include <utility>

#include <string>
#include <stack>

using space std;

stack<string> lv1;
stack<string> lv2;
stack<string> lv3;

string temp;
int templv;
int temptime=0;

int read(int now){
	if(now < temptime) return 0;

	do{

		if(temp.empty()){

		}else{

			switch(templv){
				case 1:
					lv1.push(temp);break;
				case 2:
					lv2.push(temp);break;
				case 3:
					lv3.push(temp);break;
			}
		}
		cin >>temptime>>templv>>temp;
	}while(temptime>=now);

}
int main(int argc, char const *argv[])
{
		whlie(1){
			read();
			cout<<lv1.size()<<lv2.size()<<lv3.size();
		}

	return 0;
}<commit_msg>update uoj2254<commit_after>#include <stdio.h>
#include <queue>
#include <vector>
#include <utility>

#include <string>
#include <stack>

using namespace std;

stack<string> lv1;
stack<string> lv2;
stack<string> lv3;

string temp;
int templv;
int temptime=0;

int read(int now){
	if(now < temptime) return 0;

	do{

		if(temp.empty()){

		}else{

			switch(templv){
				case 1:
					lv1.push(temp);break;
				case 2:
					lv2.push(temp);break;
				case 3:
					lv3.push(temp);break;
			}
		}
		cin >>temptime>>templv>>temp;
	}while(temptime>=now);

}
int main(int argc, char const *argv[])
{
		whlie(1){
			read();
			cout<<lv1.size()<<lv2.size()<<lv3.size();
		}

	return 0;
}<|endoftext|>


<commit_before>/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

#include "scenemodel.h"
#include <gluon/gameobject.h>
#include <typeinfo>
#include <objectmanager.h>

#include <debughelper.h>
#include <qmimedata.h>
#include <KLocalizedString>

using namespace Gluon;
using namespace Gluon::Creator;

SceneModel::SceneModel(QObject* parent): QAbstractItemModel(parent)
{
    m_root = 0;
    connect(ObjectManager::instance(), SIGNAL(newObject(Gluon::GameObject*)), SIGNAL(layoutChanged()));
}

GameObject* SceneModel::rootGameObject()
{
    if(m_root) return m_root->childGameObject(0);
    return 0;
}

void SceneModel::setRootGameObject(GameObject* obj)
{
    if(obj)
    {
        if(m_root) delete m_root;
        m_root = new GameObject(this);
        m_root->addChild(obj);
        reset();
    }
}

QVariant SceneModel::data(const QModelIndex& index, int role) const
{
    if (index.isValid() && role == Qt::DisplayRole)
    {
        GameObject *item = static_cast<GameObject*>(index.internalPointer());

        if(item)
            return item->name();
    }

    return QVariant();
}

int SceneModel::columnCount(const QModelIndex&) const
{
    return 1;
}

int SceneModel::rowCount(const QModelIndex& parent) const
{
    GameObject *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    if(parentItem) return parentItem->childCount();
    return 0;
}

QModelIndex SceneModel::parent(const QModelIndex& child) const
{
    if (!child.isValid())
        return QModelIndex();

    GameObject *childItem = static_cast<GameObject*>(child.internalPointer());
    GameObject *parentItem = childItem->parentGameObject();

    if (parentItem == m_root)
        return QModelIndex();

    return createIndex(rowIndex(parentItem), 0, parentItem);
}

QModelIndex SceneModel::index(int row, int column, const QModelIndex& parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    GameObject *parentItem;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    GameObject *childItem = parentItem->childGameObject(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QVariant SceneModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section)
    Q_UNUSED(orientation)
    Q_UNUSED(role)

    return QVariant();
}

int SceneModel::rowIndex(GameObject* object) const
{
    if(object && object->parentGameObject())
    {
        return object->parentGameObject()->childIndex(object);
    }
    return 0;
}

Qt::DropActions SceneModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

Qt::ItemFlags SceneModel::flags(const QModelIndex& index) const
{
    if (index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
        return Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
}

bool SceneModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
    DEBUG_FUNC_NAME

    DEBUG_TEXT(data->data("application/x-qabstractitemmodeldatalist"));
    return true;
}

bool SceneModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        static_cast<GluonObject*>(index.internalPointer())->setName(value.toString());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

bool SceneModel::insertRows(int row, int count, const QModelIndex& parent)
{
    beginInsertRows(parent, row, row + count - 1);

    GameObject* obj = static_cast<GameObject*>(parent.internalPointer());
    for (int i = 0; i < count; ++i) {
        obj->addChild(new GameObject());
    }

    endInsertRows();
    return true;
}

bool SceneModel::removeRows(int row, int count, const QModelIndex& parent)
{

}

#include "scenemodel.moc"

<commit_msg>You can't do checks like that... but it still crashes on save for some to me utterly inexplicable reason - help!<commit_after>/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

#include "scenemodel.h"
#include <gluon/gameobject.h>
#include <typeinfo>
#include <objectmanager.h>

#include <debughelper.h>
#include <qmimedata.h>
#include <KLocalizedString>

using namespace Gluon;
using namespace Gluon::Creator;

SceneModel::SceneModel(QObject* parent): QAbstractItemModel(parent)
{
    m_root = 0;
    connect(ObjectManager::instance(), SIGNAL(newObject(Gluon::GameObject*)), SIGNAL(layoutChanged()));
}

GameObject* SceneModel::rootGameObject()
{
    if(m_root) return m_root->childGameObject(0);
    return 0;
}

void SceneModel::setRootGameObject(GameObject* obj)
{
    if(obj)
    {
        if(m_root) delete m_root;
        m_root = new GameObject(this);
        m_root->addChild(obj);
        reset();
    }
}

QVariant SceneModel::data(const QModelIndex& index, int role) const
{
    if (index.isValid() && role == Qt::DisplayRole)
    {
        GameObject *item = static_cast<GameObject*>(index.internalPointer());

        if(item)
            return item->name();
    }

    return QVariant();
}

int SceneModel::columnCount(const QModelIndex&) const
{
    return 1;
}

int SceneModel::rowCount(const QModelIndex& parent) const
{
    GameObject *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    if(parentItem) return parentItem->childCount();
    return 0;
}

QModelIndex SceneModel::parent(const QModelIndex& child) const
{
    if (!child.isValid())
        return QModelIndex();

    GameObject *childItem = static_cast<GameObject*>(child.internalPointer());

    if(!childItem)
        return QModelIndex();

    GameObject *parentItem = childItem->parentGameObject();

    if (parentItem == m_root)
        return QModelIndex();

    return createIndex(rowIndex(parentItem), 0, parentItem);
}

QModelIndex SceneModel::index(int row, int column, const QModelIndex& parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    GameObject *parentItem;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    GameObject *childItem = parentItem->childGameObject(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QVariant SceneModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section)
    Q_UNUSED(orientation)
    Q_UNUSED(role)

    return QVariant();
}

int SceneModel::rowIndex(GameObject* object) const
{
    if(object)
    {
        if(object->parentGameObject())
        {
            return object->parentGameObject()->childIndex(object);
        }
    }
    return 0;
}

Qt::DropActions SceneModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

Qt::ItemFlags SceneModel::flags(const QModelIndex& index) const
{
    if (index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
        return Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
}

bool SceneModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
    DEBUG_FUNC_NAME

    DEBUG_TEXT(data->data("application/x-qabstractitemmodeldatalist"));
    return true;
}

bool SceneModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        static_cast<GluonObject*>(index.internalPointer())->setName(value.toString());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

bool SceneModel::insertRows(int row, int count, const QModelIndex& parent)
{
    beginInsertRows(parent, row, row + count - 1);

    GameObject* obj = static_cast<GameObject*>(parent.internalPointer());
    for (int i = 0; i < count; ++i) {
        obj->addChild(new GameObject());
    }

    endInsertRows();
    return true;
}

bool SceneModel::removeRows(int row, int count, const QModelIndex& parent)
{

}

#include "scenemodel.moc"

<|endoftext|>


<commit_before>#pragma once

//
// fastcgi.hpp
// ~~~~~~~~
//
// Copyright (c) 2017 Mohsen Khaki (mohsen dot khaki at gmail dot com)
//
// Distributed under the MIT License
//

#include <cstdint>
#include <algorithm>

namespace FastCGI
{

enum class Type : uint8_t
{
	BEGIN_REQUEST     = 1, /* [in]                              */
	ABORT_REQUEST     = 2, /* [in]                              */
	END_REQUEST       = 3, /* [out]                             */
	PARAM             = 4, /* [in]  environment variables       */
	STDIN             = 5, /* [in]  post data                   */
	STDOUT            = 6, /* [out] response                    */
	STDERR            = 7, /* [out] errors                      */
	DATA              = 8, /* [in]  filter data                 */
	GET_VALUES        = 9, /* [in]                              */
	GET_VALUES_RESULT = 10, /* [out]                             */
	UNKNOWN_TYPE      = 11, /* [out]                             */
};

struct RecordHeader
{
	uint8_t version = 0;
	Type    type = Type::UNKNOWN_TYPE;
	uint8_t requestIDB1 = 0;
	uint8_t requestIDB0 = 0;
	uint8_t contentLengthB1 = 0;
	uint8_t contentLengthB0 = 0;
	uint8_t paddingLength = 0;
	uint8_t reserved;

	uint16_t requestID() const
	{
		return (static_cast<uint16_t>(requestIDB1) << 8) | requestIDB0;
	}

	void requestID(uint16_t id)
	{
		requestIDB0 = id & 0xff;
		id >>= 8;
		requestIDB1 = id & 0xff;
	}

	uint16_t contentLength() const
	{
		return (static_cast<uint16_t>(contentLengthB1) << 8) | contentLengthB0;
	}

	void contentLength(uint16_t length)
	{
		paddingLength = static_cast<uint8_t>(((static_cast<uint32_t>(length) + 7u) & ~uint32_t(7u)) - length);
		contentLengthB0 = length & 0xff;
		length >>= 8;
		contentLengthB1 = length & 0xff;
	}
};

enum BeginRequestFlag : uint8_t
{
	KEEP_CONN = 0x01,
};

enum class BeginRequestRoles : uint16_t
{
	RESPONDER = 1,
	AUTHORIZER = 2,
	FILTER = 3,
};

enum class EndRequestProtocolStatus : uint8_t
{
	REQUEST_COMPLETE = 0,
	CANT_MPX_CONN = 1,
	OVERLOADED = 2,
	UNKNOWN_ROLE = 3,
};

struct Length
{
	uint8_t lengthB3 = 0;
	uint8_t lengthB2 = 0;
	uint8_t lengthB1 = 0;
	uint8_t lengthB0 = 0;
	uint32_t length() const
	{
		return (static_cast<uint32_t>(lengthB3 & 0x7fu) << 24) |
		       (static_cast<uint32_t>(lengthB2) << 16) |
		       (static_cast<uint32_t>(lengthB1) <<  8) | lengthB0;
	}
};

struct NameValue
{
	NameValue()
	{
	}
	NameValue(const char* name, const uint32_t nameLength, const char* value, const uint32_t valueLength)
		: name(name), nameLength(nameLength), value(value), valueLength(valueLength)
	{
	}
	const char* name = nullptr;
	uint32_t nameLength = 0;
	const char* value = nullptr;
	uint32_t valueLength = 0;
};

struct NameValueIterator
{
	NameValueIterator()
	{
	}
	NameValueIterator(const char* buffer, const size_t length)
	{
		initialize(buffer, length);
	}
	bool invalid() const
	{
		return length_ == 0;
	}
	NameValueIterator operator++(int) const
	{
		return NameValueIterator(buffer_ + sectionLength_, length_ - sectionLength_);
	}
	NameValueIterator& operator++()
	{
		if (length_ > sectionLength_)
		{
			initialize(buffer_ + sectionLength_, length_ - sectionLength_);
		}
		else
		{
			initialize(buffer_ + sectionLength_, 0);
		}
		return *this;
	}

	bool operator==(const NameValueIterator& other) const
	{
		return buffer_ == other.buffer_ && length_ == other.length_;
	}
	bool operator!=(const NameValueIterator& other) const
	{
		return !(*this == other);
	}

	const NameValue& operator*() const
	{
		return nameValue_;
	}
	const NameValue* operator->() const
	{
		return &nameValue_;
	}

	void initialize(const char* buffer, const size_t length)
	{
		buffer_ = buffer;
		length_ = length;
		if (length > 0)
		{
			uint32_t nameLength = readLength(buffer);
			uint32_t valueLength = readLength(buffer);
			nameValue_ = NameValue(buffer, nameLength, buffer + nameLength, valueLength);
			sectionLength_ = (buffer + nameLength + valueLength - buffer_);
		}
	}

	static uint32_t readLength(const char*& buffer)
	{
		uint8_t lengthB0 = *reinterpret_cast<const uint8_t*>(buffer);
		if ((lengthB0 & 0x80u) == 0)
		{
			buffer += 1;
			return lengthB0;
		}
		Length length;
		std::copy(buffer, buffer + sizeof(length), reinterpret_cast<char*>(&length));
		buffer += sizeof(length);
		return length.length();
	}

	NameValue nameValue_;
	const char* buffer_ = nullptr;
	size_t sectionLength_ = 0;
	size_t length_ = 0;

};

struct BeginRequest
{
	uint8_t roleB1 = 0;
	uint8_t roleB0 = 0;
	uint8_t flags = 0;
	uint8_t reserved[5];
	BeginRequestRoles role() const
	{
		return static_cast<BeginRequestRoles>((static_cast<uint16_t>(roleB1) << 8) | roleB0);
	}
	void role(const BeginRequestRoles role)
	{
		uint16_t roleValue = static_cast<uint16_t>(role);
		roleB0 = roleValue & 0xff;
		roleValue >>= 8;
		roleB1 = roleValue & 0xff;
	}
};

struct EndRequest
{
	uint8_t appStatusB3 = 0;
	uint8_t appStatusB2 = 0;
	uint8_t appStatusB1 = 0;
	uint8_t appStatusB0 = 0;
	EndRequestProtocolStatus protocolStatus = EndRequestProtocolStatus::REQUEST_COMPLETE;
	uint8_t reserved[3];
	int32_t appStatus() const
	{
		return (static_cast<uint32_t>(appStatusB3) << 24) |
		    (static_cast<uint32_t>(appStatusB2) << 16) |
		    (static_cast<uint32_t>(appStatusB1) <<  8) | appStatusB0;
	}
	void appStatus(const int32_t status)
	{
		uint32_t statusValue = static_cast<uint32_t>(status);
		appStatusB0 = statusValue & 0xff;
		statusValue >>= 8;
		appStatusB1 = statusValue & 0xff;
		statusValue >>= 8;
		appStatusB2 = statusValue & 0xff;
		statusValue >>= 8;
		appStatusB3 = statusValue & 0xff;
	}
};

struct UnknownType
{
	uint8_t type;
	uint8_t reserved[7];
};

template<Type TYPE>
struct Atom {};

class Decoder
{
public:
	template<class HANDLER>
	void write(const char* buffer, size_t lengthInBytes, HANDLER& handler)
	{
		if (!buffer_.empty())
		{
			while (expected_ > buffer_.size())
			{
				const size_t length = std::min(expected_, lengthInBytes);
				buffer_.insert(buffer_.end(), buffer, buffer + length);
				buffer += length;
				lengthInBytes -= length;
				if (!decode(buffer_.data(), buffer_.size(), expected_, handler) || lengthInBytes == 0)
				{
					return;
				}
				if (buffer_.size() >= expected_)
				{
					buffer_.clear();
					expected_ = 0;
					break;
				}
			}
		}
		while (true)
		{
			if (!decode(buffer, lengthInBytes, expected_, handler))
			{
				return;
			}
			if (lengthInBytes < expected_)
			{
				buffer_.assign(buffer, buffer + lengthInBytes);
				return;
			}
			lengthInBytes -= expected_;
			buffer += expected_;
		}
	}
private:
	template<class HANDLER>
	static bool decode(const char* buffer, size_t length, size_t& expected, HANDLER& handler)
	{
		if (length < sizeof(RecordHeader))
		{
			expected = sizeof(RecordHeader);
			return true;
		}
		RecordHeader header;
		std::copy(buffer, buffer + sizeof(RecordHeader), reinterpret_cast<char*>(&header));
		const size_t contentLength = header.contentLength();
		expected = sizeof(RecordHeader) + contentLength + header.paddingLength;
		if (expected > length)
		{
			return true;
		}
		buffer += sizeof(RecordHeader);
		switch (header.type)
		{
		case Type::BEGIN_REQUEST:
		{
			BeginRequest beginRequest;
			std::copy(buffer, buffer + sizeof(beginRequest), reinterpret_cast<char*>(&beginRequest));
			return handler(Atom<Type::BEGIN_REQUEST>(), header, beginRequest);
		}
		case Type::ABORT_REQUEST:
		{
			return handler(Atom<Type::ABORT_REQUEST>(), header);
		}
		case Type::END_REQUEST:
		{
			EndRequest endRequest;
			std::copy(buffer, buffer + sizeof(endRequest), reinterpret_cast<char*>(&endRequest));
			return handler(Atom<Type::END_REQUEST>(), header, endRequest);
		}
		case Type::PARAM:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::PARAM>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::STDIN:
		{
			return handler(Atom<Type::STDIN>(), header, buffer, contentLength);
		}
		case Type::STDOUT:
		{
			return handler(Atom<Type::STDOUT>(), header, buffer, contentLength);
		}
		case Type::STDERR:
		{
			return handler(Atom<Type::STDERR>(), header, buffer, contentLength);
		}
		case Type::DATA:
		{
			return handler(Atom<Type::DATA>(), header, buffer, contentLength);
		}
		case Type::GET_VALUES:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::GET_VALUES_RESULT:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES_RESULT>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::UNKNOWN_TYPE:
		{
			return handler(Atom<Type::UNKNOWN_TYPE>(), header, buffer, contentLength);
		}
		}
		return handler(header, buffer, contentLength);
	}
	std::vector<char> buffer_;
	size_t expected_ = 0;
};

}
<commit_msg>Fix the usage of left over bytes<commit_after>#pragma once

//
// fastcgi.hpp
// ~~~~~~~~
//
// Copyright (c) 2017 Mohsen Khaki (mohsen dot khaki at gmail dot com)
//
// Distributed under the MIT License
//

#include <cstdint>
#include <algorithm>

namespace FastCGI
{

enum class Type : uint8_t
{
	BEGIN_REQUEST     = 1, /* [in]                              */
	ABORT_REQUEST     = 2, /* [in]                              */
	END_REQUEST       = 3, /* [out]                             */
	PARAM             = 4, /* [in]  environment variables       */
	STDIN             = 5, /* [in]  post data                   */
	STDOUT            = 6, /* [out] response                    */
	STDERR            = 7, /* [out] errors                      */
	DATA              = 8, /* [in]  filter data                 */
	GET_VALUES        = 9, /* [in]                              */
	GET_VALUES_RESULT = 10, /* [out]                             */
	UNKNOWN_TYPE      = 11, /* [out]                             */
};

struct RecordHeader
{
	uint8_t version = 0;
	Type    type = Type::UNKNOWN_TYPE;
	uint8_t requestIDB1 = 0;
	uint8_t requestIDB0 = 0;
	uint8_t contentLengthB1 = 0;
	uint8_t contentLengthB0 = 0;
	uint8_t paddingLength = 0;
	uint8_t reserved;

	uint16_t requestID() const
	{
		return (static_cast<uint16_t>(requestIDB1) << 8) | requestIDB0;
	}

	void requestID(uint16_t id)
	{
		requestIDB0 = id & 0xff;
		id >>= 8;
		requestIDB1 = id & 0xff;
	}

	uint16_t contentLength() const
	{
		return (static_cast<uint16_t>(contentLengthB1) << 8) | contentLengthB0;
	}

	void contentLength(uint16_t length)
	{
		paddingLength = static_cast<uint8_t>(((static_cast<uint32_t>(length) + 7u) & ~uint32_t(7u)) - length);
		contentLengthB0 = length & 0xff;
		length >>= 8;
		contentLengthB1 = length & 0xff;
	}
};

enum BeginRequestFlag : uint8_t
{
	KEEP_CONN = 0x01,
};

enum class BeginRequestRoles : uint16_t
{
	RESPONDER = 1,
	AUTHORIZER = 2,
	FILTER = 3,
};

enum class EndRequestProtocolStatus : uint8_t
{
	REQUEST_COMPLETE = 0,
	CANT_MPX_CONN = 1,
	OVERLOADED = 2,
	UNKNOWN_ROLE = 3,
};

struct Length
{
	uint8_t lengthB3 = 0;
	uint8_t lengthB2 = 0;
	uint8_t lengthB1 = 0;
	uint8_t lengthB0 = 0;
	uint32_t length() const
	{
		return (static_cast<uint32_t>(lengthB3 & 0x7fu) << 24) |
		       (static_cast<uint32_t>(lengthB2) << 16) |
		       (static_cast<uint32_t>(lengthB1) <<  8) | lengthB0;
	}
};

struct NameValue
{
	NameValue()
	{
	}
	NameValue(const char* name, const uint32_t nameLength, const char* value, const uint32_t valueLength)
		: name(name), nameLength(nameLength), value(value), valueLength(valueLength)
	{
	}
	const char* name = nullptr;
	uint32_t nameLength = 0;
	const char* value = nullptr;
	uint32_t valueLength = 0;
};

struct NameValueIterator
{
	NameValueIterator()
	{
	}
	NameValueIterator(const char* buffer, const size_t length)
	{
		initialize(buffer, length);
	}
	bool invalid() const
	{
		return length_ == 0;
	}
	NameValueIterator operator++(int) const
	{
		return NameValueIterator(buffer_ + sectionLength_, length_ - sectionLength_);
	}
	NameValueIterator& operator++()
	{
		if (length_ > sectionLength_)
		{
			initialize(buffer_ + sectionLength_, length_ - sectionLength_);
		}
		else
		{
			initialize(buffer_ + sectionLength_, 0);
		}
		return *this;
	}

	bool operator==(const NameValueIterator& other) const
	{
		return buffer_ == other.buffer_ && length_ == other.length_;
	}
	bool operator!=(const NameValueIterator& other) const
	{
		return !(*this == other);
	}

	const NameValue& operator*() const
	{
		return nameValue_;
	}
	const NameValue* operator->() const
	{
		return &nameValue_;
	}

	void initialize(const char* buffer, const size_t length)
	{
		buffer_ = buffer;
		length_ = length;
		if (length > 0)
		{
			uint32_t nameLength = readLength(buffer);
			uint32_t valueLength = readLength(buffer);
			nameValue_ = NameValue(buffer, nameLength, buffer + nameLength, valueLength);
			sectionLength_ = (buffer + nameLength + valueLength - buffer_);
		}
	}

	static uint32_t readLength(const char*& buffer)
	{
		uint8_t lengthB0 = *reinterpret_cast<const uint8_t*>(buffer);
		if ((lengthB0 & 0x80u) == 0)
		{
			buffer += 1;
			return lengthB0;
		}
		Length length;
		std::copy(buffer, buffer + sizeof(length), reinterpret_cast<char*>(&length));
		buffer += sizeof(length);
		return length.length();
	}

	NameValue nameValue_;
	const char* buffer_ = nullptr;
	size_t sectionLength_ = 0;
	size_t length_ = 0;

};

struct BeginRequest
{
	uint8_t roleB1 = 0;
	uint8_t roleB0 = 0;
	uint8_t flags = 0;
	uint8_t reserved[5];
	BeginRequestRoles role() const
	{
		return static_cast<BeginRequestRoles>((static_cast<uint16_t>(roleB1) << 8) | roleB0);
	}
	void role(const BeginRequestRoles role)
	{
		uint16_t roleValue = static_cast<uint16_t>(role);
		roleB0 = roleValue & 0xff;
		roleValue >>= 8;
		roleB1 = roleValue & 0xff;
	}
};

struct EndRequest
{
	uint8_t appStatusB3 = 0;
	uint8_t appStatusB2 = 0;
	uint8_t appStatusB1 = 0;
	uint8_t appStatusB0 = 0;
	EndRequestProtocolStatus protocolStatus = EndRequestProtocolStatus::REQUEST_COMPLETE;
	uint8_t reserved[3];
	int32_t appStatus() const
	{
		return (static_cast<uint32_t>(appStatusB3) << 24) |
		    (static_cast<uint32_t>(appStatusB2) << 16) |
		    (static_cast<uint32_t>(appStatusB1) <<  8) | appStatusB0;
	}
	void appStatus(const int32_t status)
	{
		uint32_t statusValue = static_cast<uint32_t>(status);
		appStatusB0 = statusValue & 0xff;
		statusValue >>= 8;
		appStatusB1 = statusValue & 0xff;
		statusValue >>= 8;
		appStatusB2 = statusValue & 0xff;
		statusValue >>= 8;
		appStatusB3 = statusValue & 0xff;
	}
};

struct UnknownType
{
	uint8_t type;
	uint8_t reserved[7];
};

template<Type TYPE>
struct Atom {};

class Decoder
{
public:
	template<class HANDLER>
	void write(const char* buffer, size_t lengthInBytes, HANDLER& handler)
	{
		if (!buffer_.empty())
		{
			while (expected_ > buffer_.size())
			{
				const size_t length = std::min(expected_ - buffer_.size(), lengthInBytes);
				buffer_.insert(buffer_.end(), buffer, buffer + length);
				buffer += length;
				lengthInBytes -= length;
				if (!decode(buffer_.data(), buffer_.size(), expected_, handler) || lengthInBytes == 0)
				{
					return;
				}
				if (buffer_.size() >= expected_)
				{
					buffer_.clear();
					expected_ = 0;
					break;
				}
			}
		}
		while (true)
		{
			if (!decode(buffer, lengthInBytes, expected_, handler))
			{
				return;
			}
			if (lengthInBytes < expected_)
			{
				buffer_.assign(buffer, buffer + lengthInBytes);
				return;
			}
			lengthInBytes -= expected_;
			buffer += expected_;
		}
	}
private:
	template<class HANDLER>
	static bool decode(const char* buffer, size_t length, size_t& expected, HANDLER& handler)
	{
		if (length < sizeof(RecordHeader))
		{
			expected = sizeof(RecordHeader);
			return true;
		}
		RecordHeader header;
		std::copy(buffer, buffer + sizeof(RecordHeader), reinterpret_cast<char*>(&header));
		const size_t contentLength = header.contentLength();
		expected = sizeof(RecordHeader) + contentLength + header.paddingLength;
		if (expected > length)
		{
			return true;
		}
		buffer += sizeof(RecordHeader);
		switch (header.type)
		{
		case Type::BEGIN_REQUEST:
		{
			BeginRequest beginRequest;
			std::copy(buffer, buffer + sizeof(beginRequest), reinterpret_cast<char*>(&beginRequest));
			return handler(Atom<Type::BEGIN_REQUEST>(), header, beginRequest);
		}
		case Type::ABORT_REQUEST:
		{
			return handler(Atom<Type::ABORT_REQUEST>(), header);
		}
		case Type::END_REQUEST:
		{
			EndRequest endRequest;
			std::copy(buffer, buffer + sizeof(endRequest), reinterpret_cast<char*>(&endRequest));
			return handler(Atom<Type::END_REQUEST>(), header, endRequest);
		}
		case Type::PARAM:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::PARAM>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::STDIN:
		{
			return handler(Atom<Type::STDIN>(), header, buffer, contentLength);
		}
		case Type::STDOUT:
		{
			return handler(Atom<Type::STDOUT>(), header, buffer, contentLength);
		}
		case Type::STDERR:
		{
			return handler(Atom<Type::STDERR>(), header, buffer, contentLength);
		}
		case Type::DATA:
		{
			return handler(Atom<Type::DATA>(), header, buffer, contentLength);
		}
		case Type::GET_VALUES:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::GET_VALUES_RESULT:
		{
			const char* endParams = buffer + contentLength;
			return handler(Atom<Type::GET_VALUES_RESULT>(), header, NameValueIterator(buffer, contentLength), NameValueIterator(endParams, 0));
		}
		case Type::UNKNOWN_TYPE:
		{
			return handler(Atom<Type::UNKNOWN_TYPE>(), header, buffer, contentLength);
		}
		}
		return handler(header, buffer, contentLength);
	}
	std::vector<char> buffer_;
	size_t expected_ = 0;
};

}
<|endoftext|>


<commit_before>// (C) 2014 Arek Olek

#pragma once

#include <iostream>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>

struct red_points_dashed {
  void operator()(std::ostream& out) const {
    out << "node [shape=point color=brown]" << std::endl;
    out << "edge [style=dashed color=burlywood1]" << std::endl;
  }
};

template <class Graph>
class node_writer {
public:
  node_writer(Graph const& t) : T(t) {}
  template <class V>
  void operator()(std::ostream& out, const V& v) const {
    if(degree(v, T) == 1)
      out << "[color=green]";
    if(degree(v, T) > 2)
      out << "[color=red]";
  }
private:
  Graph const& T;
};

template <class Graph>
node_writer<Graph> make_node_writer(Graph t) {
  return node_writer<Graph>(t);
}

template <class Graph>
class edge_writer {
public:
  edge_writer(Graph const& g, Graph const& t) : G(g), T(t) {}
  template <class E>
  void operator()(std::ostream& out, const E& e) const {
    auto vs = adjacent_vertices(source(e, G), T);
    for(auto vit = vs.first; vit != vs.second; ++vit)
      if(*vit == target(e, G)) {
        out << "[style=solid color=burlywood]";
        break;
      }
  }
private:
  Graph const& G;
  Graph const& T;
};

template <class Graph>
edge_writer<Graph> make_edge_writer(Graph g, Graph t) {
  return edge_writer<Graph>(g, t);
}

template<class Graph>
void show(std::string file, Graph g, Graph t) {
  std::ofstream f(file);
  write_graphviz(f, g,
    make_node_writer(t), make_edge_writer(g, t), red_points_dashed());
  f.close();
}

<commit_msg>refactor debug methods<commit_after>// (C) 2014 Arek Olek

#pragma once

#include <iostream>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>

struct red_points_dashed {
  void operator()(std::ostream& out) const {
    out << "node [shape=point color=brown]" << std::endl;
    out << "edge [style=dashed color=burlywood1]" << std::endl;
  }
};

template <class Graph>
class node_writer {
public:
  node_writer(Graph const& t) : T(t) {}
  template <class V>
  void operator()(std::ostream& out, const V& v) const {
    if(degree(v, T) == 1)
      out << "[color=green]";
    if(degree(v, T) > 2)
      out << "[color=red]";
  }
private:
  Graph const& T;
};

template <class Graph>
node_writer<Graph> make_node_writer(Graph t) {
  return node_writer<Graph>(t);
}

template<class Graph, class Tree>
class edge_writer {
public:
  edge_writer(Graph const& g, Tree const& t) : G(g), T(t) {}
  template <class E>
  void operator()(std::ostream& out, const E& e) const {
    auto vs = adjacent_vertices(source(e, G), T);
    for(auto vit = vs.first; vit != vs.second; ++vit)
      if(*vit == target(e, G)) {
        out << "[style=solid color=burlywood]";
        break;
      }
  }
private:
  Graph const& G;
  Tree const& T;
};

template<class Graph, class Tree>
edge_writer<Graph, Tree> make_edge_writer(Graph g, Tree t) {
  return edge_writer<Graph, Tree>(g, t);
}

template<class Graph, class Tree>
void show(std::string file, Graph g, Tree t) {
  std::ofstream f(file);
  write_graphviz(f, g,
    make_node_writer(t), make_edge_writer(g, t), red_points_dashed());
  f.close();
}

<|endoftext|>


<commit_before>/// @file init_tasks.cpp
///
/// @brief Implementation of init_tasks.hpp
/// @date 12/09/2015
///
/// (c) Koheron 2014-2015

#include "init_tasks.hpp"

#include <cstdio>
#include <cstring>

extern "C" {
  #include <sys/socket.h>
  #include <sys/types.h>
  #include <arpa/inet.h>
  #include <ifaddrs.h>
}

#include "../drivers/core/wr_register.hpp"

InitTasks::InitTasks(Klib::DevMem& dev_mem_)
: dev_mem(dev_mem_)
{}

#define LED_ADDR 0x43C00000
#define MAP_SIZE 4096
#define LED_OFFSET 0x0

void InitTasks::show_ip_on_leds()
{
// http://stackoverflow.com/questions/20800319/how-to-get-my-ip-address-in-c-linux

    struct ifaddrs *addrs;
    getifaddrs(&addrs);
    ifaddrs *tmp = addrs;

    // Turn all the leds ON
    Klib::MemMapID dev_num = dev_mem.AddMemoryMap(LED_ADDR, 16*MAP_SIZE);
    Klib::WriteReg32(dev_mem.GetBaseAddr(dev_num) + LED_OFFSET, 255);

    char interface[] = "eth0";

    while(tmp) {
        // Works only for IPv4 address
        if(tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) {
            struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
            int val = strcmp(tmp->ifa_name,interface);

            if(val != 0) {
                tmp = tmp->ifa_next;
                continue;
            }

            // Interface found
            printf("Interface %s found: %s\n",
                   tmp->ifa_name, inet_ntoa(pAddr->sin_addr));
            uint32_t ip = htonl(pAddr->sin_addr.s_addr);

            // Write IP address in FPGA memory
            // The 8 Least Significant Bits should be connected to the FPGA LEDs
            Klib::WriteReg32(dev_mem.GetBaseAddr(dev_num) + LED_OFFSET, ip);

            break;
        }

        tmp = tmp->ifa_next;
    }

    freeifaddrs(addrs);
    dev_mem.RmMemoryMap(dev_num);
}
<commit_msg>Clean up<commit_after>/// Implementation of init_tasks.hpp
///
/// (c) Koheron

#include "init_tasks.hpp"

#include <cstdio>
#include <cstring>

extern "C" {
  #include <sys/socket.h>
  #include <sys/types.h>
  #include <arpa/inet.h>
  #include <ifaddrs.h>
}

#include "../drivers/core/wr_register.hpp"

InitTasks::InitTasks(Klib::DevMem& dev_mem_)
: dev_mem(dev_mem_)
{}

#define LED_ADDR 0x43C00000
#define MAP_SIZE 4096
#define LED_OFFSET 0x0

void InitTasks::show_ip_on_leds()
{
// http://stackoverflow.com/questions/20800319/how-to-get-my-ip-address-in-c-linux

    struct ifaddrs *addrs;
    getifaddrs(&addrs);
    ifaddrs *tmp = addrs;

    // Turn all the leds ON
    Klib::MemMapID dev_num = dev_mem.AddMemoryMap(LED_ADDR, 16*MAP_SIZE);
    Klib::WriteReg32(dev_mem.GetBaseAddr(dev_num) + LED_OFFSET, 255);

    char interface[] = "eth0";

    while(tmp) {
        // Works only for IPv4 address
        if(tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) {
            struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
            int val = strcmp(tmp->ifa_name,interface);

            if(val != 0) {
                tmp = tmp->ifa_next;
                continue;
            }

            // Interface found
            printf("Interface %s found: %s\n",
                   tmp->ifa_name, inet_ntoa(pAddr->sin_addr));
            uint32_t ip = htonl(pAddr->sin_addr.s_addr);

            // Write IP address in FPGA memory
            // The 8 Least Significant Bits should be connected to the FPGA LEDs
            Klib::WriteReg32(dev_mem.GetBaseAddr(dev_num) + LED_OFFSET, ip);

            break;
        }

        tmp = tmp->ifa_next;
    }

    freeifaddrs(addrs);
    dev_mem.RmMemoryMap(dev_num);
}
<|endoftext|>