<commit_before>/**
 *  @file MultiNewton.cpp
 *
 *  Damped Newton solver for 1D multi-domain problems
 */

/*
 *  Copyright 2001 California Institute of Technology
 */

#include <vector>
using namespace std;

#include "cantera/oneD/MultiNewton.h"

#include "cantera/base/ctexceptions.h"
#include "cantera/base/vec_functions.h"
#include "cantera/base/stringUtils.h"

#include <cstdio>
#include <cmath>
#include <ctime>

using namespace std;

namespace Cantera
{

//----------------------------------------------------------
//                  function declarations
//----------------------------------------------------------

// declarations for functions in newton_utils.h
doublereal bound_step(const doublereal* x,
                      const doublereal* step, Domain1D& r, int loglevel=0);
doublereal norm_square(const doublereal* x,
                       const doublereal* step, Domain1D& r);

//-----------------------------------------------------------
//                  constants
//-----------------------------------------------------------

const string dashedline =
    "-----------------------------------------------------------------";

const doublereal DampFactor = sqrt(2.0);
const size_t NDAMP = 7;

//-----------------------------------------------------------
//                 MultiNewton methods
//-----------------------------------------------------------

MultiNewton::MultiNewton(int sz)
    : m_maxAge(5)
{
    m_n  = sz;
    m_elapsed = 0.0;
}

MultiNewton::~MultiNewton()
{
    for (size_t i = 0; i < m_workarrays.size(); i++) {
        delete[] m_workarrays[i];
    }
}

/**
 * Prepare for a new solution vector length.
 */
void MultiNewton::resize(size_t sz)
{
    m_n = sz;
    for (size_t i = 0; i < m_workarrays.size(); i++) {
        delete[] m_workarrays[i];
    }
    m_workarrays.clear();
}

/**
 * Compute the weighted 2-norm of 'step'.
 */
doublereal MultiNewton::norm2(const doublereal* x,
                              const doublereal* step, OneDim& r) const
{
    doublereal f, sum = 0.0;//, fmx = 0.0;
    size_t nd = r.nDomains();
    for (size_t n = 0; n < nd; n++) {
        f = norm_square(x + r.start(n), step + r.start(n),
                        r.domain(n));
        sum += f;
    }
    sum /= r.size();
    return sqrt(sum);
}

/**
 * Compute the undamped Newton step.  The residual function is
 * evaluated at x, but the Jacobian is not recomputed.
 */
void MultiNewton::step(doublereal* x, doublereal* step,
                       OneDim& r, MultiJac& jac, int loglevel)
{
    size_t iok;
    size_t sz = r.size();
    r.eval(npos, x, step);
#undef DEBUG_STEP
#ifdef DEBUG_STEP
    vector_fp ssave(sz, 0.0);
    for (size_t n = 0; n < sz; n++) {
        step[n] = -step[n];
        ssave[n] = step[n];
    }
#else
    for (size_t n = 0; n < sz; n++) {
        step[n] = -step[n];
    }
#endif

    iok = jac.solve(step, step);

    // if iok is non-zero, then solve failed
    if (iok != 0) {
        iok--;
        size_t nd = r.nDomains();
        size_t n;
        for (n = nd-1; n != npos; n--)
            if (iok >= r.start(n)) {
                break;
            }
        Domain1D& dom = r.domain(n);
        size_t offset = iok - r.start(n);
        size_t pt = offset/dom.nComponents();
        size_t comp = offset - pt*dom.nComponents();
        throw CanteraError("MultiNewton::step",
                           "Jacobian is singular for domain "+
                           dom.id() + ", component "
                           +dom.componentName(comp)+" at point "
                           +int2str(pt)+"\n(Matrix row "
                           +int2str(iok)+") \nsee file bandmatrix.csv\n");
    } else if (int(iok) < 0)
        throw CanteraError("MultiNewton::step",
                           "iok = "+int2str(iok));

#ifdef DEBUG_STEP
    bool ok = false;
    Domain1D* d;
    if (!ok) {
        for (size_t n = 0; n < sz; n++) {
            d = r.pointDomain(n);
            int nvd = d->nComponents();
            int pt = (n - d->loc())/nvd;
            cout << "step: " << pt << "  " <<
                 r.pointDomain(n)->componentName(n - d->loc() - nvd*pt)
                 << "    " << x[n] << "     " << ssave[n] << "   " << step[n] << endl;
        }
    }
#endif
}

/**
 * Return the factor by which the undamped Newton step 'step0'
 * must be multiplied in order to keep all solution components in
 * all domains between their specified lower and upper bounds.
 */
doublereal MultiNewton::boundStep(const doublereal* x0,
                                  const doublereal* step0, const OneDim& r, int loglevel)
{
    doublereal fbound = 1.0;
    for (size_t i = 0; i < r.nDomains(); i++) {
        fbound = std::min(fbound,
                          bound_step(x0 + r.start(i), step0 + r.start(i),
                                     r.domain(i), loglevel));
    }
    return fbound;
}

/**
 * On entry, step0 must contain an undamped Newton step for the
 * solution x0. This method attempts to find a damping coefficient
 * such that the next undamped step would have a norm smaller than
 * that of step0. If successful, the new solution after taking the
 * damped step is returned in x1, and the undamped step at x1 is
 * returned in step1.
 */
int MultiNewton::dampStep(const doublereal* x0, const doublereal* step0,
                          doublereal* x1, doublereal* step1, doublereal& s1,
                          OneDim& r, MultiJac& jac, int loglevel, bool writetitle)
{

    // write header
    if (loglevel > 0 && writetitle) {
        writelog("\n\nDamped Newton iteration:\n");
        writelog(dashedline);

        sprintf(m_buf,"\n%s  %9s   %9s     %9s   %9s   %9s  %5s %5s\n",
                "m","F_damp","F_bound","log10(ss)",
                "log10(s0)","log10(s1)","N_jac","Age");
        writelog(m_buf);
        writelog(dashedline+"\n");
    }

    // compute the weighted norm of the undamped step size step0
    doublereal s0 = norm2(x0, step0, r);

    // compute the multiplier to keep all components in bounds
    doublereal fbound = boundStep(x0, step0, r, loglevel-1);

    // if fbound is very small, then x0 is already close to the
    // boundary and step0 points out of the allowed domain. In
    // this case, the Newton algorithm fails, so return an error
    // condition.
    if (fbound < 1.e-10) {
        if (loglevel > 0) {
            writelog("\nAt limits.\n");
        }
        return -3;
    }

    //--------------------------------------------
    //           Attempt damped step
    //--------------------------------------------

    // damping coefficient starts at 1.0
    doublereal damp = 1.0;

    doublereal ff;

    size_t m;
    for (m = 0; m < NDAMP; m++) {

        ff = fbound*damp;

        // step the solution by the damped step size
        for (size_t j = 0; j < m_n; j++) {
            x1[j] = ff*step0[j] + x0[j];
        }

        // compute the next undamped step that would result if x1
        // is accepted
        step(x1, step1, r, jac, loglevel-1);

        // compute the weighted norm of step1
        s1 = norm2(x1, step1, r);

        // write log information
        if (loglevel > 0) {
            doublereal ss = r.ssnorm(x1,step1);
            sprintf(m_buf,"\n%s  %9.5f   %9.5f   %9.5f   %9.5f   %9.5f %4d  %d/%d",
                    int2str(m).c_str(), damp, fbound, log10(ss+SmallNumber),
                    log10(s0+SmallNumber),
                    log10(s1+SmallNumber),
                    jac.nEvals(), jac.age(), m_maxAge);
            writelog(m_buf);
        }

        // if the norm of s1 is less than the norm of s0, then
        // accept this damping coefficient. Also accept it if this
        // step would result in a converged solution. Otherwise,
        // decrease the damping coefficient and try again.

        if (s1 < 1.0 || s1 < s0) {
            break;
        }
        damp /= DampFactor;
    }

    // If a damping coefficient was found, return 1 if the
    // solution after stepping by the damped step would represent
    // a converged solution, and return 0 otherwise. If no damping
    // coefficient could be found, return -2.
    if (m < NDAMP) {
        if (s1 > 1.0) {
            return 0;
        } else {
            return 1;
        }
    } else {
        return -2;
    }
}

/**
 * Find the solution to F(X) = 0 by damped Newton iteration.  On
 * entry, x0 contains an initial estimate of the solution.  On
 * successful return, x1 contains the converged solution.
 */
int MultiNewton::solve(doublereal* x0, doublereal* x1,
                       OneDim& r, MultiJac& jac, int loglevel)
{
    clock_t t0 = clock();
    int m = 0;
    bool forceNewJac = false;
    doublereal s1=1.e30;

    doublereal* x    = getWorkArray();
    doublereal* stp  = getWorkArray();
    doublereal* stp1 = getWorkArray();

    copy(x0, x0 + m_n, x);

    bool frst = true;
    doublereal rdt = r.rdt();
    int j0 = jac.nEvals();

    while (1 > 0) {

        // Check whether the Jacobian should be re-evaluated.
        if (jac.age() > m_maxAge) {
            if (loglevel > 0) {
                writelog("\nMaximum Jacobian age reached ("+int2str(m_maxAge)+")\n");
            }
            forceNewJac = true;
        }

        if (forceNewJac) {
            r.eval(npos, x, stp, 0.0, 0);
            jac.eval(x, stp, 0.0);
            jac.updateTransient(rdt, DATA_PTR(r.transientMask()));
            forceNewJac = false;
        }

        // compute the undamped Newton step
        step(x, stp, r, jac, loglevel-1);

        // increment the Jacobian age
        jac.incrementAge();

        // damp the Newton step
        m = dampStep(x, stp, x1, stp1, s1, r, jac, loglevel-1, frst);
        if (loglevel == 1 && m >= 0) {
            if (frst) {
                sprintf(m_buf,"\n\n    %10s    %10s   %5s ",
                        "log10(ss)","log10(s1)","N_jac");
                writelog(m_buf);
                sprintf(m_buf,"\n    ------------------------------------");
                writelog(m_buf);
            }
            doublereal ss = r.ssnorm(x, stp);
            sprintf(m_buf,"\n    %10.4f    %10.4f       %d ",
                    log10(ss),log10(s1),jac.nEvals());
            writelog(m_buf);
        }
        frst = false;

        // Successful step, but not converged yet. Take the damped
        // step, and try again.
        if (m == 0) {
            copy(x1, x1 + m_n, x);
        }

        // convergence
        else if (m == 1) {
            goto done;
        }

        // If dampStep fails, first try a new Jacobian if an old
        // one was being used. If it was a new Jacobian, then
        // return -1 to signify failure.
        else if (m < 0) {
            if (jac.age() > 1) {
                forceNewJac = true;
                if (loglevel > 0)
                    writelog("\nRe-evaluating Jacobian, since no damping "
                             "coefficient\ncould be found with this Jacobian.\n");
            } else {
                goto done;
            }
        }
    }

done:
    if (m < 0) {
        copy(x, x + m_n, x1);
    }
    if (m > 0 && jac.nEvals() == j0) {
        m = 100;
    }
    releaseWorkArray(x);
    releaseWorkArray(stp);
    releaseWorkArray(stp1);
    m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC);
    return m;
}

/**
 * Get a pointer to an array of length m_n for temporary work
 * space.
 */
doublereal* MultiNewton::getWorkArray()
{
    doublereal* w = 0;

    if (!m_workarrays.empty()) {
        w = m_workarrays.back();
        m_workarrays.pop_back();
    } else {
        w = new doublereal[m_n];
    }
    return w;
}

/**
 * Release a work array by pushing its pointer onto the stack of
 * available arrays.
 */
void MultiNewton::releaseWorkArray(doublereal* work)
{
    m_workarrays.push_back(work);
}
}

// $Log: Newton.cpp,v
<commit_msg>[1D] Fixed a case where the Newton solver could get stuck<commit_after>/**
 *  @file MultiNewton.cpp
 *
 *  Damped Newton solver for 1D multi-domain problems
 */

/*
 *  Copyright 2001 California Institute of Technology
 */

#include <vector>
using namespace std;

#include "cantera/oneD/MultiNewton.h"

#include "cantera/base/ctexceptions.h"
#include "cantera/base/vec_functions.h"
#include "cantera/base/stringUtils.h"

#include <cstdio>
#include <cmath>
#include <ctime>

using namespace std;

namespace Cantera
{

//----------------------------------------------------------
//                  function declarations
//----------------------------------------------------------

// declarations for functions in newton_utils.h
doublereal bound_step(const doublereal* x,
                      const doublereal* step, Domain1D& r, int loglevel=0);
doublereal norm_square(const doublereal* x,
                       const doublereal* step, Domain1D& r);

//-----------------------------------------------------------
//                  constants
//-----------------------------------------------------------

const string dashedline =
    "-----------------------------------------------------------------";

const doublereal DampFactor = sqrt(2.0);
const size_t NDAMP = 7;

//-----------------------------------------------------------
//                 MultiNewton methods
//-----------------------------------------------------------

MultiNewton::MultiNewton(int sz)
    : m_maxAge(5)
{
    m_n  = sz;
    m_elapsed = 0.0;
}

MultiNewton::~MultiNewton()
{
    for (size_t i = 0; i < m_workarrays.size(); i++) {
        delete[] m_workarrays[i];
    }
}

/**
 * Prepare for a new solution vector length.
 */
void MultiNewton::resize(size_t sz)
{
    m_n = sz;
    for (size_t i = 0; i < m_workarrays.size(); i++) {
        delete[] m_workarrays[i];
    }
    m_workarrays.clear();
}

/**
 * Compute the weighted 2-norm of 'step'.
 */
doublereal MultiNewton::norm2(const doublereal* x,
                              const doublereal* step, OneDim& r) const
{
    doublereal f, sum = 0.0;//, fmx = 0.0;
    size_t nd = r.nDomains();
    for (size_t n = 0; n < nd; n++) {
        f = norm_square(x + r.start(n), step + r.start(n),
                        r.domain(n));
        sum += f;
    }
    sum /= r.size();
    return sqrt(sum);
}

/**
 * Compute the undamped Newton step.  The residual function is
 * evaluated at x, but the Jacobian is not recomputed.
 */
void MultiNewton::step(doublereal* x, doublereal* step,
                       OneDim& r, MultiJac& jac, int loglevel)
{
    size_t iok;
    size_t sz = r.size();
    r.eval(npos, x, step);
#undef DEBUG_STEP
#ifdef DEBUG_STEP
    vector_fp ssave(sz, 0.0);
    for (size_t n = 0; n < sz; n++) {
        step[n] = -step[n];
        ssave[n] = step[n];
    }
#else
    for (size_t n = 0; n < sz; n++) {
        step[n] = -step[n];
    }
#endif

    iok = jac.solve(step, step);

    // if iok is non-zero, then solve failed
    if (iok != 0) {
        iok--;
        size_t nd = r.nDomains();
        size_t n;
        for (n = nd-1; n != npos; n--)
            if (iok >= r.start(n)) {
                break;
            }
        Domain1D& dom = r.domain(n);
        size_t offset = iok - r.start(n);
        size_t pt = offset/dom.nComponents();
        size_t comp = offset - pt*dom.nComponents();
        throw CanteraError("MultiNewton::step",
                           "Jacobian is singular for domain "+
                           dom.id() + ", component "
                           +dom.componentName(comp)+" at point "
                           +int2str(pt)+"\n(Matrix row "
                           +int2str(iok)+") \nsee file bandmatrix.csv\n");
    } else if (int(iok) < 0)
        throw CanteraError("MultiNewton::step",
                           "iok = "+int2str(iok));

#ifdef DEBUG_STEP
    bool ok = false;
    Domain1D* d;
    if (!ok) {
        for (size_t n = 0; n < sz; n++) {
            d = r.pointDomain(n);
            int nvd = d->nComponents();
            int pt = (n - d->loc())/nvd;
            cout << "step: " << pt << "  " <<
                 r.pointDomain(n)->componentName(n - d->loc() - nvd*pt)
                 << "    " << x[n] << "     " << ssave[n] << "   " << step[n] << endl;
        }
    }
#endif
}

/**
 * Return the factor by which the undamped Newton step 'step0'
 * must be multiplied in order to keep all solution components in
 * all domains between their specified lower and upper bounds.
 */
doublereal MultiNewton::boundStep(const doublereal* x0,
                                  const doublereal* step0, const OneDim& r, int loglevel)
{
    doublereal fbound = 1.0;
    for (size_t i = 0; i < r.nDomains(); i++) {
        fbound = std::min(fbound,
                          bound_step(x0 + r.start(i), step0 + r.start(i),
                                     r.domain(i), loglevel));
    }
    return fbound;
}

/**
 * On entry, step0 must contain an undamped Newton step for the
 * solution x0. This method attempts to find a damping coefficient
 * such that the next undamped step would have a norm smaller than
 * that of step0. If successful, the new solution after taking the
 * damped step is returned in x1, and the undamped step at x1 is
 * returned in step1.
 */
int MultiNewton::dampStep(const doublereal* x0, const doublereal* step0,
                          doublereal* x1, doublereal* step1, doublereal& s1,
                          OneDim& r, MultiJac& jac, int loglevel, bool writetitle)
{

    // write header
    if (loglevel > 0 && writetitle) {
        writelog("\n\nDamped Newton iteration:\n");
        writelog(dashedline);

        sprintf(m_buf,"\n%s  %9s   %9s     %9s   %9s   %9s  %5s %5s\n",
                "m","F_damp","F_bound","log10(ss)",
                "log10(s0)","log10(s1)","N_jac","Age");
        writelog(m_buf);
        writelog(dashedline+"\n");
    }

    // compute the weighted norm of the undamped step size step0
    doublereal s0 = norm2(x0, step0, r);

    // compute the multiplier to keep all components in bounds
    doublereal fbound = boundStep(x0, step0, r, loglevel-1);

    // if fbound is very small, then x0 is already close to the
    // boundary and step0 points out of the allowed domain. In
    // this case, the Newton algorithm fails, so return an error
    // condition.
    if (fbound < 1.e-10) {
        if (loglevel > 0) {
            writelog("\nAt limits.\n");
        }
        return -3;
    }

    //--------------------------------------------
    //           Attempt damped step
    //--------------------------------------------

    // damping coefficient starts at 1.0
    doublereal damp = 1.0;

    doublereal ff;

    size_t m;
    for (m = 0; m < NDAMP; m++) {

        ff = fbound*damp;

        // step the solution by the damped step size
        for (size_t j = 0; j < m_n; j++) {
            x1[j] = ff*step0[j] + x0[j];
        }

        // compute the next undamped step that would result if x1
        // is accepted
        step(x1, step1, r, jac, loglevel-1);

        // compute the weighted norm of step1
        s1 = norm2(x1, step1, r);

        // write log information
        if (loglevel > 0) {
            doublereal ss = r.ssnorm(x1,step1);
            sprintf(m_buf,"\n%s  %9.5f   %9.5f   %9.5f   %9.5f   %9.5f %4d  %d/%d",
                    int2str(m).c_str(), damp, fbound, log10(ss+SmallNumber),
                    log10(s0+SmallNumber),
                    log10(s1+SmallNumber),
                    jac.nEvals(), jac.age(), m_maxAge);
            writelog(m_buf);
        }

        // if the norm of s1 is less than the norm of s0, then
        // accept this damping coefficient. Also accept it if this
        // step would result in a converged solution. Otherwise,
        // decrease the damping coefficient and try again.

        if (s1 < 1.0 || s1 < s0) {
            break;
        }
        damp /= DampFactor;
    }

    // If a damping coefficient was found, return 1 if the
    // solution after stepping by the damped step would represent
    // a converged solution, and return 0 otherwise. If no damping
    // coefficient could be found, return -2.
    if (m < NDAMP) {
        if (s1 > 1.0) {
            return 0;
        } else {
            return 1;
        }
    } else {
        return -2;
    }
}

/**
 * Find the solution to F(X) = 0 by damped Newton iteration.  On
 * entry, x0 contains an initial estimate of the solution.  On
 * successful return, x1 contains the converged solution.
 */
int MultiNewton::solve(doublereal* x0, doublereal* x1,
                       OneDim& r, MultiJac& jac, int loglevel)
{
    clock_t t0 = clock();
    int m = 0;
    bool forceNewJac = false;
    doublereal s1=1.e30;

    doublereal* x    = getWorkArray();
    doublereal* stp  = getWorkArray();
    doublereal* stp1 = getWorkArray();

    copy(x0, x0 + m_n, x);

    bool frst = true;
    doublereal rdt = r.rdt();
    int j0 = jac.nEvals();
    int nJacReeval = 0;

    while (1 > 0) {

        // Check whether the Jacobian should be re-evaluated.
        if (jac.age() > m_maxAge) {
            if (loglevel > 0) {
                writelog("\nMaximum Jacobian age reached ("+int2str(m_maxAge)+")\n");
            }
            forceNewJac = true;
        }

        if (forceNewJac) {
            r.eval(npos, x, stp, 0.0, 0);
            jac.eval(x, stp, 0.0);
            jac.updateTransient(rdt, DATA_PTR(r.transientMask()));
            forceNewJac = false;
        }

        // compute the undamped Newton step
        step(x, stp, r, jac, loglevel-1);

        // increment the Jacobian age
        jac.incrementAge();

        // damp the Newton step
        m = dampStep(x, stp, x1, stp1, s1, r, jac, loglevel-1, frst);
        if (loglevel == 1 && m >= 0) {
            if (frst) {
                sprintf(m_buf,"\n\n    %10s    %10s   %5s ",
                        "log10(ss)","log10(s1)","N_jac");
                writelog(m_buf);
                sprintf(m_buf,"\n    ------------------------------------");
                writelog(m_buf);
            }
            doublereal ss = r.ssnorm(x, stp);
            sprintf(m_buf,"\n    %10.4f    %10.4f       %d ",
                    log10(ss),log10(s1),jac.nEvals());
            writelog(m_buf);
        }
        frst = false;

        // Successful step, but not converged yet. Take the damped
        // step, and try again.
        if (m == 0) {
            copy(x1, x1 + m_n, x);
        }

        // convergence
        else if (m == 1) {
            goto done;
        }

        // If dampStep fails, first try a new Jacobian if an old
        // one was being used. If it was a new Jacobian, then
        // return -1 to signify failure.
        else if (m < 0) {
            if (jac.age() > 1) {
                forceNewJac = true;
                if (nJacReeval > 3) {
                    goto done;
                }
                nJacReeval++;
                if (loglevel > 0)
                    writelog("\nRe-evaluating Jacobian, since no damping "
                             "coefficient\ncould be found with this Jacobian.\n");
            } else {
                goto done;
            }
        }
    }

done:
    if (m < 0) {
        copy(x, x + m_n, x1);
    }
    if (m > 0 && jac.nEvals() == j0) {
        m = 100;
    }
    releaseWorkArray(x);
    releaseWorkArray(stp);
    releaseWorkArray(stp1);
    m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC);
    return m;
}

/**
 * Get a pointer to an array of length m_n for temporary work
 * space.
 */
doublereal* MultiNewton::getWorkArray()
{
    doublereal* w = 0;

    if (!m_workarrays.empty()) {
        w = m_workarrays.back();
        m_workarrays.pop_back();
    } else {
        w = new doublereal[m_n];
    }
    return w;
}

/**
 * Release a work array by pushing its pointer onto the stack of
 * available arrays.
 */
void MultiNewton::releaseWorkArray(doublereal* work)
{
    m_workarrays.push_back(work);
}
}

// $Log: Newton.cpp,v
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2016 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#pragma once

#include <ox/std/std.hpp>
#include "filestore.hpp"

namespace ox {
namespace fs {

using namespace std;

enum FsType {
	OxFS_16 = 1,
	OxFS_32 = 2,
	OxFS_64 = 3
};

enum FileType {
	NormalFile = 1,
	Directory  = 2
};

struct FileStat {
	uint64_t inode;
	uint64_t size;
	uint8_t  fileType;
};

class FileSystem {
	public:
		virtual ~FileSystem() {};

		virtual int read(uint64_t inode, void *buffer, uint64_t size) = 0;

		virtual uint8_t *read(uint64_t inode, uint64_t *size) = 0;

		virtual int remove(uint64_t inode) = 0;

		virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = NormalFile) = 0;

		virtual FileStat stat(uint64_t inode) = 0;
};

FileSystem *createFileSystem(void *buff);

template<typename FileStore, FsType FS_TYPE>
class FileSystemTemplate: public FileSystem {

	private:
		struct DirectoryEntry {
			typename FileStore::InodeId_t inode;

			char *getName() {
				return (char*) (this + 1);
			}

			void setName(const char *name) {
				auto data = getName();
				auto nameLen = ox_strlen(name);
				ox_memcpy(data, &name, nameLen);
				data[nameLen] = 0;
			}
		};

		struct Directory {
			/**
			 * Number of files in this directory.
			 */
			typename FileStore::InodeId_t size = 0;

			DirectoryEntry *files() {
				return (DirectoryEntry*) (this + 1);
			}
		};

		// static members
		static typename FileStore::InodeId_t INODE_ROOT_DIR;

		FileStore *store = nullptr;

	public:
		FileSystemTemplate(void *buff);

		int mkdir(const char *path);

		int read(const char *path, void *buffer);

		uint8_t *read(uint64_t inode, uint64_t *size) override;

		int read(uint64_t inode, void *buffer, uint64_t size) override;

		int remove(uint64_t inode) override;

		int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) override;

		FileStat stat(const char *path);

		FileStat stat(uint64_t inode) override;

		static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories);
};

template<typename FileStore, FsType FS_TYPE>
FileSystemTemplate<FileStore, FS_TYPE>::FileSystemTemplate(void *buff) {
	store = (FileStore*) buff;
}

template<typename FileStore, FsType FS_TYPE>
typename FileStore::InodeId_t FileSystemTemplate<FileStore, FS_TYPE>::INODE_ROOT_DIR = 2;

template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *path) {
	return 0;
}

template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(const char *path) {
	FileStat stat;
	return stat;
}

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(uint64_t inode) {
	FileStat stat;
	auto s = store->stat(inode);
	stat.size = s.size;
	stat.inode = s.inodeId;
	stat.fileType = s.fileType;
	return stat;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, void *buffer, uint64_t size) {
	auto err = 1;
	auto s = store->stat(inode);
	if (size == s.size) {
		err = store->read(inode, buffer, nullptr);
	}
	return err;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, uint64_t *size) {
	auto s = store->stat(inode);
	auto buff = new uint8_t[s.size];
	if (size) {
		*size = s.size;
	}
	if (store->read(inode, buff, nullptr)) {
		delete []buff;
		buff = nullptr;
	}
	return buff;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode) {
	return store->remove(inode);
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) {
	return store->write(inode, buffer, size, fileType);
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories) {
	buffer = FileStore::format((uint8_t*) buffer, size, (uint32_t) FS_TYPE);
	auto fs = createFileSystem(buffer);

	if (buffer && useDirectories) {
		char dirBuff[sizeof(Directory) + sizeof(DirectoryEntry) + 2];
		auto *dir = (Directory*) dirBuff;
		dir->files();
		fs->write(INODE_ROOT_DIR, dirBuff, useDirectories);
	}

	return (uint8_t*) buffer;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

typedef FileSystemTemplate<FileStore16, OxFS_16> FileSystem16;
typedef FileSystemTemplate<FileStore32, OxFS_32> FileSystem32;
typedef FileSystemTemplate<FileStore64, OxFS_64> FileSystem64;

}
}
<commit_msg>Fix memory leak in FileSystem::format<commit_after>/*
 * Copyright 2015 - 2016 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#pragma once

#include <ox/std/std.hpp>
#include "filestore.hpp"

namespace ox {
namespace fs {

using namespace std;

enum FsType {
	OxFS_16 = 1,
	OxFS_32 = 2,
	OxFS_64 = 3
};

enum FileType {
	NormalFile = 1,
	Directory  = 2
};

struct FileStat {
	uint64_t inode;
	uint64_t size;
	uint8_t  fileType;
};

class FileSystem {
	public:
		virtual ~FileSystem() {};

		virtual int read(uint64_t inode, void *buffer, uint64_t size) = 0;

		virtual uint8_t *read(uint64_t inode, uint64_t *size) = 0;

		virtual int remove(uint64_t inode) = 0;

		virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = NormalFile) = 0;

		virtual FileStat stat(uint64_t inode) = 0;
};

FileSystem *createFileSystem(void *buff);

template<typename FileStore, FsType FS_TYPE>
class FileSystemTemplate: public FileSystem {

	private:
		struct DirectoryEntry {
			typename FileStore::InodeId_t inode;

			char *getName() {
				return (char*) (this + 1);
			}

			void setName(const char *name) {
				auto data = getName();
				auto nameLen = ox_strlen(name);
				ox_memcpy(data, &name, nameLen);
				data[nameLen] = 0;
			}
		};

		struct Directory {
			/**
			 * Number of files in this directory.
			 */
			typename FileStore::InodeId_t size = 0;

			DirectoryEntry *files() {
				return (DirectoryEntry*) (this + 1);
			}
		};

		// static members
		static typename FileStore::InodeId_t INODE_ROOT_DIR;

		FileStore *store = nullptr;

	public:
		FileSystemTemplate(void *buff);

		int mkdir(const char *path);

		int read(const char *path, void *buffer);

		uint8_t *read(uint64_t inode, uint64_t *size) override;

		int read(uint64_t inode, void *buffer, uint64_t size) override;

		int remove(uint64_t inode) override;

		int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) override;

		FileStat stat(const char *path);

		FileStat stat(uint64_t inode) override;

		static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories);
};

template<typename FileStore, FsType FS_TYPE>
FileSystemTemplate<FileStore, FS_TYPE>::FileSystemTemplate(void *buff) {
	store = (FileStore*) buff;
}

template<typename FileStore, FsType FS_TYPE>
typename FileStore::InodeId_t FileSystemTemplate<FileStore, FS_TYPE>::INODE_ROOT_DIR = 2;

template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *path) {
	return 0;
}

template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(const char *path) {
	FileStat stat;
	return stat;
}

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(uint64_t inode) {
	FileStat stat;
	auto s = store->stat(inode);
	stat.size = s.size;
	stat.inode = s.inodeId;
	stat.fileType = s.fileType;
	return stat;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, void *buffer, uint64_t size) {
	auto err = 1;
	auto s = store->stat(inode);
	if (size == s.size) {
		err = store->read(inode, buffer, nullptr);
	}
	return err;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, uint64_t *size) {
	auto s = store->stat(inode);
	auto buff = new uint8_t[s.size];
	if (size) {
		*size = s.size;
	}
	if (store->read(inode, buff, nullptr)) {
		delete []buff;
		buff = nullptr;
	}
	return buff;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode) {
	return store->remove(inode);
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) {
	return store->write(inode, buffer, size, fileType);
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories) {
	buffer = FileStore::format((uint8_t*) buffer, size, (uint32_t) FS_TYPE);
	auto fs = createFileSystem(buffer);

	if (buffer && useDirectories) {
		char dirBuff[sizeof(Directory) + sizeof(DirectoryEntry) + 2];
		auto *dir = (Directory*) dirBuff;
		dir->files();
		fs->write(INODE_ROOT_DIR, dirBuff, useDirectories);
	}

	delete fs;

	return (uint8_t*) buffer;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif

typedef FileSystemTemplate<FileStore16, OxFS_16> FileSystem16;
typedef FileSystemTemplate<FileStore32, OxFS_32> FileSystem32;
typedef FileSystemTemplate<FileStore64, OxFS_64> FileSystem64;

}
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "primitives/block.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"
#include "arith_uint256.h"
#include "patternsearch.h"

uint256 CBlockHeader::GetHash() const
{
    uint256 midHash = GetMidHash();
    uint256 cacheBlockHash=Hash(BEGIN(nVersion), END(nFinalCalculation));
    if(!patternsearch::pattern_verify( midHash, nStartLocation, nFinalCalculation)){
        return uint256S("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
    }else{
        return cacheBlockHash;
    }
}

uint256 CBlockHeader::GetMidHash() const
{
    return Hash(BEGIN(nVersion), END(nNonce));
    //return SerializeHash(*this);
}

uint256 CBlockHeader::FindBestPatternHash(int& collisions,char *scratchpad,int nThreads) {

        uint256 smallestHashSoFar = uint256S("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
        uint32_t smallestHashLocation=0;
        uint32_t smallestHashFinalCalculation=0;

        if(nThreads==0){
            return smallestHashSoFar;
        }

        uint256 midHash = GetMidHash();

        //Threads can only be a power of 2
 /*       int newThreadNumber = 1;
        while(newThreadNumber < nThreads){
            newThreadNumber*=2;
        }
        nThreads=newThreadNumber;*/

        std::vector< std::pair<uint32_t,uint32_t> > results =patternsearch::pattern_search( midHash,scratchpad,nThreads);
        //uint32_t candidateStartLocation=0;
        //uint32_t candidateFinalCalculation=0;

        collisions=results.size();
        uint256 fullHash = smallestHashSoFar;

        for (unsigned i=0; i < results.size(); i++) {

            nStartLocation = results[i].first;
            nFinalCalculation = results[i].second;
            fullHash = Hash(BEGIN(nVersion), END(nFinalCalculation));
            //LogPrintf("Consider Candidate:%s\n",fullHash.ToString());
            //LogPrintf("against:%s\n",smallestHashSoFar.ToString());

            if(UintToArith256(fullHash)<UintToArith256(smallestHashSoFar)){
                //LogPrintf("New Best Candidate:%s\n",fullHash.ToString());
                //if better, update location
                //printf("best hash so far for the nonce\n");
                smallestHashSoFar=fullHash;
                smallestHashLocation=results[i].first;
                smallestHashFinalCalculation=results[i].second;
            }
        }

        nStartLocation = smallestHashLocation;
        nFinalCalculation = smallestHashFinalCalculation;
        return smallestHashSoFar;
    }

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
    /* WARNING! If you're reading this because you're learning about crypto
       and/or designing a new system that will use merkle trees, keep in mind
       that the following merkle tree algorithm has a serious flaw related to
       duplicate txids, resulting in a vulnerability (CVE-2012-2459).

       The reason is that if the number of hashes in the list at a given time
       is odd, the last one is duplicated before computing the next level (which
       is unusual in Merkle trees). This results in certain sequences of
       transactions leading to the same merkle root. For example, these two
       trees:

                    A               A
                  /  \            /   \
                B     C         B       C
               / \    |        / \     / \
              D   E   F       D   E   F   F
             / \ / \ / \     / \ / \ / \ / \
             1 2 3 4 5 6     1 2 3 4 5 6 5 6

       for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
       6 are repeated) result in the same root hash A (because the hash of both
       of (F) and (F,F) is C).

       The vulnerability results from being able to send a block with such a
       transaction list, with the same merkle root, and the same block hash as
       the original without duplication, resulting in failed validation. If the
       receiving node proceeds to mark that block as permanently invalid
       however, it will fail to accept further unmodified (and thus potentially
       valid) versions of the same block. We defend against this by detecting
       the case where we would hash two identical hashes at the end of the list
       together, and treating that identically to the block having an invalid
       merkle root. Assuming no double-SHA256 collisions, this will detect all
       known ways of changing the transactions without affecting the merkle
       root.
    */
    vMerkleTree.clear();
    vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
    for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
        vMerkleTree.push_back(it->GetHash());
    int j = 0;
    bool mutated = false;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        for (int i = 0; i < nSize; i += 2)
        {
            int i2 = std::min(i+1, nSize-1);
            if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                // Two identical hashes at the end of the list at a particular level.
                mutated = true;
            }
            vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                       BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
        }
        j += nSize;
    }
    if (fMutated) {
        *fMutated = mutated;
    }
    return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
}

std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
{
    if (vMerkleTree.empty())
        BuildMerkleTree();
    std::vector<uint256> vMerkleBranch;
    int j = 0;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        int i = std::min(nIndex^1, nSize-1);
        vMerkleBranch.push_back(vMerkleTree[j+i]);
        nIndex >>= 1;
        j += nSize;
    }
    return vMerkleBranch;
}

uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
    if (nIndex == -1)
        return uint256();
    for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
    {
        if (nIndex & 1)
            hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
        else
            hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
        nIndex >>= 1;
    }
    return hash;
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (unsigned int i = 0; i < vtx.size(); i++)
    {
        s << "  " << vtx[i].ToString() << "\n";
    }
    s << "  vMerkleTree: ";
    for (unsigned int i = 0; i < vMerkleTree.size(); i++)
        s << " " << vMerkleTree[i].ToString();
    s << "\n";
    return s.str();
}
<commit_msg>Revert "Allow arbitrary number of threads"<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "primitives/block.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"
#include "arith_uint256.h"
#include "patternsearch.h"

uint256 CBlockHeader::GetHash() const
{
    uint256 midHash = GetMidHash();
    uint256 cacheBlockHash=Hash(BEGIN(nVersion), END(nFinalCalculation));
    if(!patternsearch::pattern_verify( midHash, nStartLocation, nFinalCalculation)){
        return uint256S("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
    }else{
        return cacheBlockHash;
    }
}

uint256 CBlockHeader::GetMidHash() const
{
    return Hash(BEGIN(nVersion), END(nNonce));
    //return SerializeHash(*this);
}

uint256 CBlockHeader::FindBestPatternHash(int& collisions,char *scratchpad,int nThreads) {

        uint256 smallestHashSoFar = uint256S("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
        uint32_t smallestHashLocation=0;
        uint32_t smallestHashFinalCalculation=0;

        if(nThreads==0){
            return smallestHashSoFar;
        }

        uint256 midHash = GetMidHash();

        //Threads can only be a power of 2
        int newThreadNumber = 1;
        while(newThreadNumber < nThreads){
            newThreadNumber*=2;
        }
        nThreads=newThreadNumber;

        std::vector< std::pair<uint32_t,uint32_t> > results =patternsearch::pattern_search( midHash,scratchpad,nThreads);
        //uint32_t candidateStartLocation=0;
        //uint32_t candidateFinalCalculation=0;

        collisions=results.size();
        uint256 fullHash = smallestHashSoFar;

        for (unsigned i=0; i < results.size(); i++) {

            nStartLocation = results[i].first;
            nFinalCalculation = results[i].second;
            fullHash = Hash(BEGIN(nVersion), END(nFinalCalculation));
            //LogPrintf("Consider Candidate:%s\n",fullHash.ToString());
            //LogPrintf("against:%s\n",smallestHashSoFar.ToString());

            if(UintToArith256(fullHash)<UintToArith256(smallestHashSoFar)){
                //LogPrintf("New Best Candidate:%s\n",fullHash.ToString());
                //if better, update location
                //printf("best hash so far for the nonce\n");
                smallestHashSoFar=fullHash;
                smallestHashLocation=results[i].first;
                smallestHashFinalCalculation=results[i].second;
            }
        }

        nStartLocation = smallestHashLocation;
        nFinalCalculation = smallestHashFinalCalculation;
        return smallestHashSoFar;
    }

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
    /* WARNING! If you're reading this because you're learning about crypto
       and/or designing a new system that will use merkle trees, keep in mind
       that the following merkle tree algorithm has a serious flaw related to
       duplicate txids, resulting in a vulnerability (CVE-2012-2459).

       The reason is that if the number of hashes in the list at a given time
       is odd, the last one is duplicated before computing the next level (which
       is unusual in Merkle trees). This results in certain sequences of
       transactions leading to the same merkle root. For example, these two
       trees:

                    A               A
                  /  \            /   \
                B     C         B       C
               / \    |        / \     / \
              D   E   F       D   E   F   F
             / \ / \ / \     / \ / \ / \ / \
             1 2 3 4 5 6     1 2 3 4 5 6 5 6

       for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
       6 are repeated) result in the same root hash A (because the hash of both
       of (F) and (F,F) is C).

       The vulnerability results from being able to send a block with such a
       transaction list, with the same merkle root, and the same block hash as
       the original without duplication, resulting in failed validation. If the
       receiving node proceeds to mark that block as permanently invalid
       however, it will fail to accept further unmodified (and thus potentially
       valid) versions of the same block. We defend against this by detecting
       the case where we would hash two identical hashes at the end of the list
       together, and treating that identically to the block having an invalid
       merkle root. Assuming no double-SHA256 collisions, this will detect all
       known ways of changing the transactions without affecting the merkle
       root.
    */
    vMerkleTree.clear();
    vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
    for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
        vMerkleTree.push_back(it->GetHash());
    int j = 0;
    bool mutated = false;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        for (int i = 0; i < nSize; i += 2)
        {
            int i2 = std::min(i+1, nSize-1);
            if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                // Two identical hashes at the end of the list at a particular level.
                mutated = true;
            }
            vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                       BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
        }
        j += nSize;
    }
    if (fMutated) {
        *fMutated = mutated;
    }
    return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
}

std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
{
    if (vMerkleTree.empty())
        BuildMerkleTree();
    std::vector<uint256> vMerkleBranch;
    int j = 0;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        int i = std::min(nIndex^1, nSize-1);
        vMerkleBranch.push_back(vMerkleTree[j+i]);
        nIndex >>= 1;
        j += nSize;
    }
    return vMerkleBranch;
}

uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
    if (nIndex == -1)
        return uint256();
    for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
    {
        if (nIndex & 1)
            hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
        else
            hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
        nIndex >>= 1;
    }
    return hash;
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (unsigned int i = 0; i < vtx.size(); i++)
    {
        s << "  " << vtx[i].ToString() << "\n";
    }
    s << "  vMerkleTree: ";
    for (unsigned int i = 0; i < vMerkleTree.size(); i++)
        s << " " << vMerkleTree[i].ToString();
    s << "\n";
    return s.str();
}
<|endoftext|>


<commit_before>/***
DEVSIM
Copyright 2013 Devsim LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***/

#include "dsTimer.hh"

#include <sys/time.h>
#include <sstream>

dsTimer::dsTimer(const std::string &msg, OutputStream::OutputType outtype) : msg_(msg), output_type_(outtype), tic_(std::chrono::system_clock::now())
{
  std::ostringstream os;
  os << "\nBEGIN " << msg_ << "\n";
  OutputStream::WriteOut(output_type_, os.str());
}

dsTimer::~dsTimer()
{
  auto toc = std::chrono::system_clock::now();
  auto timediff = std::chrono::duration_cast<std::chrono::milliseconds>(toc - tic_).count();

  std::ostringstream os;
  os << "\nEND " << msg_ << " (" << timediff << " ms)\n";
  OutputStream::WriteOut(output_type_, os.str());
}

<commit_msg>Use fractions of seconds<commit_after>/***
DEVSIM
Copyright 2013 Devsim LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***/

#include "dsTimer.hh"

#include <sys/time.h>
#include <sstream>

dsTimer::dsTimer(const std::string &msg, OutputStream::OutputType outtype) : msg_(msg), output_type_(outtype), tic_(std::chrono::system_clock::now())
{
  std::ostringstream os;
  os << "\nBEGIN " << msg_ << "\n";
  OutputStream::WriteOut(output_type_, os.str());
}

dsTimer::~dsTimer()
{
  auto toc = std::chrono::system_clock::now();

  typedef std::chrono::duration<double> seconds;

  auto timediff = std::chrono::duration_cast<seconds>(toc - tic_).count();

  std::ostringstream os;
  os << "\nEND " << msg_ << " (" << timediff << " sec)\n";
  OutputStream::WriteOut(output_type_, os.str());
}

<|endoftext|>


<commit_before>#include "curecoinunits.h"

#include <QStringList>

curecoinUnits::curecoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<curecoinUnits::Unit> curecoinUnits::availableUnits()
{
    QList<curecoinUnits::Unit> unitlist;
    unitlist.append(BTC);
    unitlist.append(mBTC);
    unitlist.append(uBTC);
    return unitlist;
}

bool curecoinUnits::valid(int unit)
{
    switch(unit)
    {
    case BTC:
    case mBTC:
    case uBTC:
        return true;
    default:
        return false;
    }
}

QString curecoinUnits::name(int unit)
{
    switch(unit)
    {
    case BTC: return QString("CUR");
    case mBTC: return QString("mBOC");
    case uBTC: return QString::fromUtf8("μBOC");
    default: return QString("???");
    }
}

QString curecoinUnits::description(int unit)
{
    switch(unit)
    {
    case BTC: return QString("curecoins");
    case mBTC: return QString("Milli-curecoins (1 / 1,000)");
    case uBTC: return QString("Micro-curecoins (1 / 1,000,000)");
    default: return QString("???");
    }
}

qint64 curecoinUnits::factor(int unit)
{
    switch(unit)
    {
    case BTC:  return 1000000;
    case mBTC: return 1000;
    case uBTC: return 1;
    default:   return 1000000;
    }
}

int curecoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case BTC: return 8; // 21,000,000 (# digits, without commas)
    case mBTC: return 11; // 21,000,000,000
    case uBTC: return 14; // 21,000,000,000,000
    default: return 0;
    }
}

int curecoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case BTC: return 6;
    case mBTC: return 3;
    case uBTC: return 0;
    default: return 0;
    }
}

QString curecoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

QString curecoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool curecoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int curecoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant curecoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<commit_msg>Update curecoinunits.cpp<commit_after>#include "curecoinunits.h"

#include <QStringList>

curecoinUnits::curecoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<curecoinUnits::Unit> curecoinUnits::availableUnits()
{
    QList<curecoinUnits::Unit> unitlist;
    unitlist.append(BTC);
    unitlist.append(mBTC);
    unitlist.append(uBTC);
    return unitlist;
}

bool curecoinUnits::valid(int unit)
{
    switch(unit)
    {
    case BTC:
    case mBTC:
    case uBTC:
        return true;
    default:
        return false;
    }
}

QString curecoinUnits::name(int unit)
{
    switch(unit)
    {
    case BTC: return QString("CUR");
    case mBTC: return QString("mCUR");
    case uBTC: return QString::fromUtf8("μCUR");
    default: return QString("???");
    }
}

QString curecoinUnits::description(int unit)
{
    switch(unit)
    {
    case BTC: return QString("curecoins");
    case mBTC: return QString("Milli-curecoins (1 / 1,000)");
    case uBTC: return QString("Micro-curecoins (1 / 1,000,000)");
    default: return QString("???");
    }
}

qint64 curecoinUnits::factor(int unit)
{
    switch(unit)
    {
    case BTC:  return 1000000;
    case mBTC: return 1000;
    case uBTC: return 1;
    default:   return 1000000;
    }
}

int curecoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case BTC: return 8; // 21,000,000 (# digits, without commas)
    case mBTC: return 11; // 21,000,000,000
    case uBTC: return 14; // 21,000,000,000,000
    default: return 0;
    }
}

int curecoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case BTC: return 6;
    case mBTC: return 3;
    case uBTC: return 0;
    default: return 0;
    }
}

QString curecoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

QString curecoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool curecoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int curecoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant curecoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<|endoftext|>


<commit_before>#include "mini_ion.h"

namespace Halide { namespace Runtime { namespace Internal { namespace Ion {

struct allocation_record {
    void *original;
};

// Allocate an ION buffer, and map it, returning the mapped pointer.
WEAK void *ion_alloc(void *user_context, size_t len, int heap_id, int *out_fd) {
    const size_t align = 128;

    // Align the allocation size.
    len = (len + align - 1) & ~(align - 1);

    // Allocate enough space to hold information about the allocation prior to the pointer we return.
    len += align;

    void *original = halide_malloc(user_context, len);

    // Store the original ptr before the pointer we return.
    allocation_record rec = { original };
    void *ret = reinterpret_cast<char *>(original) + align;
    halide_assert(user_context, sizeof(allocation_record) <= align);
    memcpy(reinterpret_cast<allocation_record *>(ret) - 1, &rec, sizeof(rec));

    if (ret && out_fd) {
        *out_fd = -1;
    }
    return ret;
}

// Free a previously allocated ION buffer.
WEAK void ion_free(void *user_context, void *ion) {
    if (!ion) return;
    allocation_record rec = *(reinterpret_cast<allocation_record *>(ion) - 1);
    halide_free(user_context, rec.original);
}

}}}}  // namespace Halide::Runtime::Internal::Ion
<commit_msg>fake_ion should align allocations to 128 bytes<commit_after>#include "mini_ion.h"

namespace Halide { namespace Runtime { namespace Internal { namespace Ion {

struct allocation_record {
    void *original;
};

// Allocate an ION buffer, and map it, returning the mapped pointer.
WEAK void *ion_alloc(void *user_context, size_t len, int heap_id, int *out_fd) {
    const size_t align = 128;

    void *original = halide_malloc(user_context, len + align + sizeof(allocation_record));

    // Store the original ptr before the pointer we return.
    void *ret = reinterpret_cast<void *>(((reinterpret_cast<uintptr_t>(original) + align) / align) * align);

    allocation_record rec = { original };
    memcpy(reinterpret_cast<allocation_record *>(ret) - 1, &rec, sizeof(rec));

    if (ret && out_fd) {
        *out_fd = -1;
    }
    return ret;
}

// Free a previously allocated ION buffer.
WEAK void ion_free(void *user_context, void *ion) {
    if (!ion) return;
    allocation_record rec = *(reinterpret_cast<allocation_record *>(ion) - 1);
    halide_free(user_context, rec.original);
}

}}}}  // namespace Halide::Runtime::Internal::Ion
<|endoftext|>


<commit_before>#include "ConnectionProvider.h"
#include <QtCore>
#include <TelepathyQt4/Types>
#include <TelepathyQt4/Debug__>
#include <TelepathyQt4/PendingReady>

namespace TelepathyIM
{
	ConnectionProvider::ConnectionProvider(Foundation::Framework* framework): framework_(framework), dbus_daemon_(NULL), state_(STATE_INITIALIZING)
	{
		// We want to start dbus daemon only on Windows platform
#ifdef WIN32
		StartDBusDaemon();
#endif

		InitializeTelepathyConnectionManager("gabble");
	}

	ConnectionProvider::~ConnectionProvider()
	{
		DeleteConnections();

// We want to stopt dbus daemon only on Windows platform
#ifdef WIN32
		StopDBusDaemon();
#endif
	}

	void ConnectionProvider::DeleteConnections()
	{
		for (ConnectionVector::iterator i = connections_.begin(); i != connections_.end(); ++i)
		{
			//! @todo Check that there is enough time to actual close the connection to servers
			(*i)->Close();
			delete *i;
			*i = NULL;
		}
		connections_.clear();
	}

	QStringList ConnectionProvider::GetSupportedProtocols() const
	{
		return supported_protocols_;
	}

	Communication::ConnectionInterface* ConnectionProvider::OpenConnection(const Communication::CredentialsInterface& credentials)
	{
		if (state_ != STATE_READY)
		{
			LogError("Cannot open IM connection because Telepathy IM connection provider is not ready.");
			throw Core::Exception("Telepathy IM connection provider is not ready.");
		}

		Connection* connection = new Connection(tp_connection_manager_, credentials);
		connections_.push_back(connection);

		//! @todo FIX THESE
		connect(connection, SIGNAL( ConnectionReady(Communication::ConnectionInterface&) ), SLOT( OnConnectionReady(Communication::ConnectionInterface&) ));
		connect(connection, SIGNAL( ConnectionClosed(Communication::ConnectionInterface&) ), SLOT( OnConnectionClosed(Communication::ConnectionInterface&) ));
		connect(connection, SIGNAL( ConnectionError(Communication::ConnectionInterface&) ), SLOT( OnConnectionError(Communication::ConnectionInterface&) ));

		return connection;
	}

	Communication::ConnectionVector ConnectionProvider::GetConnections() const
	{
		Communication::ConnectionVector v;
		for (ConnectionVector::const_iterator i = connections_.begin(); i != connections_.end(); ++i)
		{
			v.push_back(*i);
		}
		return v;
	}

	void ConnectionProvider::StartDBusDaemon()
	{
		QString path = "dbus\\dbus-daemon.exe";
		QString arguments = "--config-file=data\\session.conf";

		dbus_daemon_ = new QProcess(this);
		QStringList env = QProcess::systemEnvironment();
		QString env_item = "DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=";
		env_item.append( QString(DBUS_SESSION_PORT_, 10));
		env << env_item;
		dbus_daemon_->setEnvironment(env);

		connect( dbus_daemon_, SIGNAL(readyReadStandardOutput()), SLOT(OnDBusDaemonStdout()) );
		connect( dbus_daemon_, SIGNAL(finished(int)), SLOT(OnDBusDaemonExited(int)) );

		QString command = path.append(" ").append(arguments);
		dbus_daemon_->start(command);
		bool ok = dbus_daemon_->waitForStarted(500);
		if (!ok)
		{
			LogError("Cannot start dbus daemon process.");
			throw Core::Exception("Cannot start up dbus daemon process.");
		}

		// wait some time so that dbus daemon have a time to start up properly
		QTime wait_time = QTime::currentTime().addSecs(1);
		while( QTime::currentTime() < wait_time )
			QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
	}

	void ConnectionProvider::StopDBusDaemon()
	{
		if (dbus_daemon_)
		{
			dbus_daemon_->kill(); // terminate seems not to be enough
			bool ok = dbus_daemon_->waitForFinished(1000);
			if (!ok)
			{
				LogError("Cannot terminate dbus daemon process.");
				return;
			}
			delete dbus_daemon_;
			dbus_daemon_ = NULL;
		}
	}

	//! @todo support more that one connection manager
	//!       current implementation uses only gabble
	void ConnectionProvider::InitializeTelepathyConnectionManager(const QString &name)
	{
		Tp::registerTypes();
		Tp::enableDebug(true);
		Tp::enableWarnings(true);
//		qRegisterMetaType<Tp::FarsightChannel::Status>(); // for streamed media

		tp_connection_manager_ = Tp::ConnectionManager::create(name);
		connect(tp_connection_manager_->becomeReady(Tp::ConnectionManager::FeatureCore), SIGNAL( finished(Tp::PendingOperation *) ), SLOT( OnConnectionManagerReady(Tp::PendingOperation*) ));
	}

	void ConnectionProvider::OnConnectionManagerReady(Tp::PendingOperation *op)
	{
		if (op->isError())
		{
			std::string message = "Cannot initialize Telepathy ConnectionManager object: ";
			message.append( op->errorMessage().toStdString() );
			LogError( message );

			QString reason;
			reason.append(message.c_str());

			state_ = STATE_ERROR;
			return;
		}

		LogInfo("Telepathy connection provider is ready.");
		state_ = STATE_READY;
		supported_protocols_.append("jabber");
		emit( ProtocolListUpdated(supported_protocols_) );
	}

	void ConnectionProvider::OnDBusDaemonStdout()
	{
		//! ???
	}

	void ConnectionProvider::OnDBusDaemonExited( int )
	{
		// ???
	}

	void ConnectionProvider::OnConnectionReady(Communication::ConnectionInterface &connection)
	{

	}

	void ConnectionProvider::OnConnectionClosed(Communication::ConnectionInterface &connection)
	{

	}

	void ConnectionProvider::OnConnectionError(Communication::ConnectionInterface &connection)
	{

	}

} // end of namespace: TelepathyIM
<commit_msg>Added debug log messages.<commit_after>#include "ConnectionProvider.h"
#include <QtCore>
#include <TelepathyQt4/Types>
#include <TelepathyQt4/Debug__>
#include <TelepathyQt4/PendingReady>

namespace TelepathyIM
{
	ConnectionProvider::ConnectionProvider(Foundation::Framework* framework): framework_(framework), dbus_daemon_(NULL), state_(STATE_INITIALIZING)
	{
		// We want to start dbus daemon only on Windows platform
#ifdef WIN32
		StartDBusDaemon();
#endif

		InitializeTelepathyConnectionManager("gabble");
	}

	ConnectionProvider::~ConnectionProvider()
	{
		DeleteConnections();

// We want to stopt dbus daemon only on Windows platform
#ifdef WIN32
		StopDBusDaemon();
#endif
	}

	void ConnectionProvider::DeleteConnections()
	{
		for (ConnectionVector::iterator i = connections_.begin(); i != connections_.end(); ++i)
		{
			//! @todo Check that there is enough time to actual close the connection to servers
			(*i)->Close();
			delete *i;
			*i = NULL;
		}
		connections_.clear();
	}

	QStringList ConnectionProvider::GetSupportedProtocols() const
	{
		return supported_protocols_;
	}

	Communication::ConnectionInterface* ConnectionProvider::OpenConnection(const Communication::CredentialsInterface& credentials)
	{
		if (state_ != STATE_READY)
		{
			LogError("Cannot open IM connection because Telepathy IM connection provider is not ready.");
			throw Core::Exception("Telepathy IM connection provider is not ready.");
		}

		Connection* connection = new Connection(tp_connection_manager_, credentials);
		connections_.push_back(connection);

		//! @todo FIX THESE
		connect(connection, SIGNAL( ConnectionReady(Communication::ConnectionInterface&) ), SLOT( OnConnectionReady(Communication::ConnectionInterface&) ));
		connect(connection, SIGNAL( ConnectionClosed(Communication::ConnectionInterface&) ), SLOT( OnConnectionClosed(Communication::ConnectionInterface&) ));
		connect(connection, SIGNAL( ConnectionError(Communication::ConnectionInterface&) ), SLOT( OnConnectionError(Communication::ConnectionInterface&) ));

		return connection;
	}

	Communication::ConnectionVector ConnectionProvider::GetConnections() const
	{
		Communication::ConnectionVector v;
		for (ConnectionVector::const_iterator i = connections_.begin(); i != connections_.end(); ++i)
		{
			v.push_back(*i);
		}
		return v;
	}

	void ConnectionProvider::StartDBusDaemon()
	{
		QString path = "dbus\\dbus-daemon.exe";
		QString arguments = "--config-file=data\\session.conf";

		dbus_daemon_ = new QProcess(this);
		QStringList env = QProcess::systemEnvironment();
		QString env_item = "DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=";
		env_item.append( QString(DBUS_SESSION_PORT_, 10));
		env << env_item;
		dbus_daemon_->setEnvironment(env);

		connect( dbus_daemon_, SIGNAL(readyReadStandardOutput()), SLOT(OnDBusDaemonStdout()) );
		connect( dbus_daemon_, SIGNAL(finished(int)), SLOT(OnDBusDaemonExited(int)) );

		QString command = path.append(" ").append(arguments);
		dbus_daemon_->start(command);
		bool ok = dbus_daemon_->waitForStarted(500);
		if (!ok)
		{
			LogError("Cannot start dbus daemon process.");
			throw Core::Exception("Cannot start up dbus daemon process.");
		}
        LogDebug("DBus daemon is started.");

		// wait some time so that dbus daemon have a time to start up properly
		QTime wait_time = QTime::currentTime().addSecs(1);
		while( QTime::currentTime() < wait_time )
			QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
	}

	void ConnectionProvider::StopDBusDaemon()
	{
		if (dbus_daemon_)
		{
			dbus_daemon_->kill(); // terminate seems not to be enough
			bool ok = dbus_daemon_->waitForFinished(1000);
			if (!ok)
			{
				LogError("Cannot terminate dbus daemon process.");
				return;
			}
			delete dbus_daemon_;
			dbus_daemon_ = NULL;
		}
	}

	//! @todo support more that one connection manager
	//!       current implementation uses only gabble
	void ConnectionProvider::InitializeTelepathyConnectionManager(const QString &name)
	{
		Tp::registerTypes();
		Tp::enableDebug(true);
		Tp::enableWarnings(true);
//		qRegisterMetaType<Tp::FarsightChannel::Status>(); // for streamed media

		tp_connection_manager_ = Tp::ConnectionManager::create(name);
		connect(tp_connection_manager_->becomeReady(Tp::ConnectionManager::FeatureCore), SIGNAL( finished(Tp::PendingOperation *) ), SLOT( OnConnectionManagerReady(Tp::PendingOperation*) ));
	}

	void ConnectionProvider::OnConnectionManagerReady(Tp::PendingOperation *op)
	{
		if (op->isError())
		{
			std::string message = "Cannot initialize Telepathy ConnectionManager object: ";
			message.append( op->errorMessage().toStdString() );
			LogError( message );

			QString reason;
			reason.append(message.c_str());

			state_ = STATE_ERROR;
			return;
		}

		LogInfo("Telepathy connection provider is ready.");
		state_ = STATE_READY;
		supported_protocols_.append("jabber");
		emit( ProtocolListUpdated(supported_protocols_) );
	}

	void ConnectionProvider::OnDBusDaemonStdout()
	{
        QString output = QString(dbus_daemon_->readAllStandardOutput());
        LogDebug(QString("DBus daemon: ").append(output).toStdString());
	}

	void ConnectionProvider::OnDBusDaemonExited( int )
	{
        LogDebug("DBus daemon is exited.");
	}

	void ConnectionProvider::OnConnectionReady(Communication::ConnectionInterface &connection)
	{

	}

	void ConnectionProvider::OnConnectionClosed(Communication::ConnectionInterface &connection)
	{

	}

	void ConnectionProvider::OnConnectionError(Communication::ConnectionInterface &connection)
	{

	}

} // end of namespace: TelepathyIM
<|endoftext|>


<commit_before>//@author A0094446X
#include "stdafx.h"
#include <functional>
#include <QApplication>
#include <QList>
#include "session_manager.h"
#include "task_panel_manager.h"
#include "system_tray_manager.h"
#include "query_manager.h"
#include "main_window_messages.h"
#include "You-Controller/exception.h"
#include "You-Utils/exceptions/query_engine_exception.h"
#include "You-NLP/exception.h"

namespace You {
namespace GUI {

using Task = You::Controller::Task;

MainWindow::MainWindow(QWidget *parent)
	: QMainWindow(parent), sm(new MainWindow::SessionManager(this)),
		stm(new MainWindow::SystemTrayManager(this)),
		tpm(new MainWindow::TaskPanelManager(this)),
		qm(new MainWindow::QueryManager(this)),
		taskList(new TaskList) {
	#pragma warning(push)
	#pragma warning(disable: 4127)
	Q_INIT_RESOURCE(yougui);
	#pragma warning(pop)
	ui.setupUi(this);
	ui.menuBar->setVisible(false);
	ui.mainToolBar->setVisible(false);
	setWindowTitle(QString::fromStdWString(WINDOW_TITLE));
	sm->setup();
	stm->setup();
	qm->setup();
	tpm->setup();
	initializeAllTimerNotifications();

	ui.commandTextBox->installEventFilter(this);
	ui.commandTextBox->setTabChangesFocus(true);
	ui.commandTextBox->setWordWrapMode(QTextOption::NoWrap);
	ui.commandTextBox->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	ui.commandTextBox->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	ui.commandTextBox->setFixedHeight(20);
	ui.commandTextBox->setFocus(Qt::FocusReason::ActiveWindowFocusReason);

	syntaxHighlighter.reset(
		new SyntaxHighlighter(ui.commandTextBox->document()));

	populateTaskPanel();
}

MainWindow::~MainWindow() {
}

void MainWindow::closeEvent(QCloseEvent *event) {
	if (stm->trayIcon.isVisible()) {
		QMessageBox::information(this, tr("Systray"),
			tr("The program will keep running in the "
			"system tray. To terminate the program, "
			"choose Quit in the context menu "
			"of the system tray entry."));
		hide();
		event->ignore();
	}
}

void MainWindow::populateTaskPanel() {
	// Grabs tasks from last session from the list of IDs saved
	QList<Task::ID> IDs = sm->taskIDs;
	TaskList tl;

	if (IDs.size() != 0) {
		tl = qm->getTasks(IDs);
	} else {
		tl = qm->getTasks();
	}
	addTasks(tl);
}

void MainWindow::setVisible(bool visible) {
	stm->minimizeAction->setEnabled(visible);
	stm->maximizeAction->setEnabled(!isMaximized());
	stm->restoreAction->setEnabled(isMaximized() || !visible);
	QWidget::setVisible(visible);
}

const TaskList& MainWindow::getTaskList() const {
	return *taskList;
}

void MainWindow::addTask(const Task& task) {
	initializeSingleTimerNotification(task);
	taskList->push_back(task);
	tpm->addTask(task);
}

void MainWindow::addTasks(const TaskList& tl) {
	std::for_each(tl.begin(), tl.end(),
		std::bind(&MainWindow::addTask, this, std::placeholders::_1));
}

void MainWindow::deleteTask(Task::ID taskID) {
	TaskList::iterator i = std::find_if(taskList->begin(), taskList->end(),
		[=](Task& task) {
			return task.getID() == taskID;
		});

	assert(i != taskList->end());
	taskList->erase(i);
	timerMap.erase(taskID);
	tpm->deleteTask(taskID);
}

void MainWindow::editTask(const Task& task) {
	timerMap.erase(task.getID());
	initializeSingleTimerNotification(task);
	tpm->editTask(task);
	ui.taskTreePanel->viewport()->update();
}

void MainWindow::sendQuery() {
	QString inputString = ui.commandTextBox->toPlainText();
	QPixmap pixmap;
	pixmap.fill(Qt::transparent);
	pixmap.load(RESOURCE_GREEN, 0);
	QString message(READY_MESSAGE);
	ui.statusMessage->setText(message);
	try {
		qm->query(inputString, getTaskList());
	} catch (You::QueryEngine::Exception::EmptyTaskDescriptionException& e) {
		ui.statusMessage->setText(EMPTY_TASK_DESCRIPTION_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch(You::QueryEngine::Exception::TaskNotFoundException& e) {
		ui.statusMessage->setText(TASK_NOT_FOUND_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::NLP::ParseErrorException& e) {
		ui.statusMessage->setText(PARSE_ERROR_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::NLP::ParserException& e) {
		ui.statusMessage->setText(PARSER_EXCEPTION_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::Controller::ContextIndexOutOfRangeException& e) {
		ui.statusMessage->setText(CONTEXT_INDEX_OUT_OF_RANGE_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::Controller::ContextRequiredException& e) {
		ui.statusMessage->setText(CONTEXT_REQUIRED_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (...) {
		ui.statusMessage->setText(UNKNOWN_EXCEPTION_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	}
	ui.statusIcon->setPixmap(pixmap);
	ui.commandTextBox->setPlainText(QString());
}

void MainWindow::commandEnterPressed() {
	sendQuery();
}

void MainWindow::commandEnterButtonClicked() {
	sendQuery();
}

void MainWindow::applicationExitRequested() {
	sm->taskIDs.clear();
	for (int i = 0; i < taskList->size(); i++) {
		sm->taskIDs.push_back(taskList->at(i).getID());
	}
	qApp->quit();
}

void MainWindow::resizeEvent(QResizeEvent* event) {
	double oldWidth = event->oldSize().width();
	double newWidth = event->size().width();
	double ratio = newWidth / oldWidth;
	for (int i = 0; i < ui.taskTreePanel->columnCount(); ++i) {
		double currWidth = ui.taskTreePanel->header()->sectionSize(i);
		double finalWidth = currWidth * ratio;
		if (finalWidth >75)
			ui.taskTreePanel->header()->resizeSection(i, currWidth * ratio);
	}
	QMainWindow::resizeEvent(event);
}

void MainWindow::clearTasks() {
	taskList.reset(new TaskList);
	ui.taskTreePanel->clear();
	ui.taskDescriptor->clear();
	ui.commandTextBox->clear();
}

void MainWindow::taskSelected() {
	QList<QTreeWidgetItem*> selection = ui.taskTreePanel->selectedItems();
	QString contents = "";
	if (selection.size() == 0) {
		ui.taskDescriptor->setText(contents);
	} else {
		QTreeWidgetItem item = *selection.at(0);
		QString index = item.text(1);
		QString description = item.text(2);
		QString deadline = item.text(3);
		QString priority = item.text(4);
		QString dependencies = item.text(5);
		contents = "Index: " + index + "\n" + "Description: " + description
			+ "\n" + "Deadline: " + deadline + "\n" + "Priority: " + priority
			+ "\n" + "Dependencies: " + dependencies;
		ui.taskDescriptor->setText(contents);
	}
}

void MainWindow::initializeAllTimerNotifications() {
	for (int i = 0; i < taskList->size(); i++) {
		initializeSingleTimerNotification(taskList->at(i));
	}
}

void MainWindow::initializeSingleTimerNotification(Task task) {
	Task::Time deadline = task.getDeadline();
	if (deadline != Task::DEFAULT_DEADLINE) {
		Task::Time now = boost::posix_time::second_clock::local_time();
		boost::posix_time::time_duration difference = deadline - now;
		QTimer* timer = new QTimer(this);
		connect(timer, SIGNAL(timeout()), this,
			SLOT(notify(notify(task.getID(), task.getDeadline()))));
		timerMap[task.getID()] = timer;
	}
}

void MainWindow::notify(Task::ID id) {
	for (auto it = taskList->begin(); it != taskList->end(); it++) {
		Task task = *it;
		if (task.getID() == id) {
			stm->trayIcon.showMessage("lol", "lol");
			break;
		}
	}
}

void MainWindow::contextAddTask() {
	ui.commandTextBox->setPlainText(QString("/add "));
	ui.commandTextBox->setFocus();
	ui.commandTextBox->moveCursor(QTextCursor::End);
}

void MainWindow::contextDeleteTask(int id) {
	std::wstringstream wss;
	wss << L"/delete " << id;
	ui.commandTextBox->setPlainText(QString::fromStdWString(wss.str()));
	ui.commandTextBox->setFocus();
	ui.commandTextBox->moveCursor(QTextCursor::End);
}

void MainWindow::contextEditTask(int id) {
	std::wstringstream wss;
	wss << L"/edit " << id << L" set ";
	ui.commandTextBox->setPlainText(QString::fromStdWString(wss.str()));
	ui.commandTextBox->setFocus();
	ui.commandTextBox->moveCursor(QTextCursor::End);
}

MainWindow::BaseManager::BaseManager(MainWindow* parentGUI)
	: parentGUI(parentGUI) {
}

bool MainWindow::eventFilter(QObject *object, QEvent *event) {
	if (object == ui.commandTextBox && event->type() == QEvent::KeyPress) {
		QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
		if (keyEvent->key() == Qt::Key_Return) {
			commandEnterPressed();
			ui.commandTextBox->setFocus();
			return true;
		} else {
			return QMainWindow::eventFilter(object, event);
		}
	} else {
		return QMainWindow::eventFilter(object, event);
	}
}

}  // namespace GUI
}  // namespace You
<commit_msg>Fixed compile issue<commit_after>//@author A0094446X
#include "stdafx.h"
#include <functional>
#include <QApplication>
#include <QList>
#include "session_manager.h"
#include "task_panel_manager.h"
#include "system_tray_manager.h"
#include "query_manager.h"
#include "main_window_messages.h"
#include "window_title.h"
#include "You-Controller/exception.h"
#include "You-Utils/exceptions/query_engine_exception.h"
#include "You-NLP/exception.h"

namespace You {
namespace GUI {

using Task = You::Controller::Task;

MainWindow::MainWindow(QWidget *parent)
	: QMainWindow(parent), sm(new MainWindow::SessionManager(this)),
		stm(new MainWindow::SystemTrayManager(this)),
		tpm(new MainWindow::TaskPanelManager(this)),
		qm(new MainWindow::QueryManager(this)),
		taskList(new TaskList) {
	#pragma warning(push)
	#pragma warning(disable: 4127)
	Q_INIT_RESOURCE(yougui);
	#pragma warning(pop)
	ui.setupUi(this);
	ui.menuBar->setVisible(false);
	ui.mainToolBar->setVisible(false);
	setWindowTitle(QString::fromStdWString(WINDOW_TITLE));
	sm->setup();
	stm->setup();
	qm->setup();
	tpm->setup();
	initializeAllTimerNotifications();

	ui.commandTextBox->installEventFilter(this);
	ui.commandTextBox->setTabChangesFocus(true);
	ui.commandTextBox->setWordWrapMode(QTextOption::NoWrap);
	ui.commandTextBox->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	ui.commandTextBox->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	ui.commandTextBox->setFixedHeight(20);
	ui.commandTextBox->setFocus(Qt::FocusReason::ActiveWindowFocusReason);

	syntaxHighlighter.reset(
		new SyntaxHighlighter(ui.commandTextBox->document()));

	populateTaskPanel();
}

MainWindow::~MainWindow() {
}

void MainWindow::closeEvent(QCloseEvent *event) {
	if (stm->trayIcon.isVisible()) {
		QMessageBox::information(this, tr("Systray"),
			tr("The program will keep running in the "
			"system tray. To terminate the program, "
			"choose Quit in the context menu "
			"of the system tray entry."));
		hide();
		event->ignore();
	}
}

void MainWindow::populateTaskPanel() {
	// Grabs tasks from last session from the list of IDs saved
	QList<Task::ID> IDs = sm->taskIDs;
	TaskList tl;

	if (IDs.size() != 0) {
		tl = qm->getTasks(IDs);
	} else {
		tl = qm->getTasks();
	}
	addTasks(tl);
}

void MainWindow::setVisible(bool visible) {
	stm->minimizeAction->setEnabled(visible);
	stm->maximizeAction->setEnabled(!isMaximized());
	stm->restoreAction->setEnabled(isMaximized() || !visible);
	QWidget::setVisible(visible);
}

const TaskList& MainWindow::getTaskList() const {
	return *taskList;
}

void MainWindow::addTask(const Task& task) {
	initializeSingleTimerNotification(task);
	taskList->push_back(task);
	tpm->addTask(task);
}

void MainWindow::addTasks(const TaskList& tl) {
	std::for_each(tl.begin(), tl.end(),
		std::bind(&MainWindow::addTask, this, std::placeholders::_1));
}

void MainWindow::deleteTask(Task::ID taskID) {
	TaskList::iterator i = std::find_if(taskList->begin(), taskList->end(),
		[=](Task& task) {
			return task.getID() == taskID;
		});

	assert(i != taskList->end());
	taskList->erase(i);
	timerMap.erase(taskID);
	tpm->deleteTask(taskID);
}

void MainWindow::editTask(const Task& task) {
	timerMap.erase(task.getID());
	initializeSingleTimerNotification(task);
	tpm->editTask(task);
	ui.taskTreePanel->viewport()->update();
}

void MainWindow::sendQuery() {
	QString inputString = ui.commandTextBox->toPlainText();
	QPixmap pixmap;
	pixmap.fill(Qt::transparent);
	pixmap.load(RESOURCE_GREEN, 0);
	QString message(READY_MESSAGE);
	ui.statusMessage->setText(message);
	try {
		qm->query(inputString, getTaskList());
	} catch (You::QueryEngine::Exception::EmptyTaskDescriptionException& e) {
		ui.statusMessage->setText(EMPTY_TASK_DESCRIPTION_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch(You::QueryEngine::Exception::TaskNotFoundException& e) {
		ui.statusMessage->setText(TASK_NOT_FOUND_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::NLP::ParseErrorException& e) {
		ui.statusMessage->setText(PARSE_ERROR_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::NLP::ParserException& e) {
		ui.statusMessage->setText(PARSER_EXCEPTION_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::Controller::ContextIndexOutOfRangeException& e) {
		ui.statusMessage->setText(CONTEXT_INDEX_OUT_OF_RANGE_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (You::Controller::ContextRequiredException& e) {
		ui.statusMessage->setText(CONTEXT_REQUIRED_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	} catch (...) {
		ui.statusMessage->setText(UNKNOWN_EXCEPTION_MESSAGE);
		pixmap.load(RESOURCE_RED, 0);
	}
	ui.statusIcon->setPixmap(pixmap);
	ui.commandTextBox->setPlainText(QString());
}

void MainWindow::commandEnterPressed() {
	sendQuery();
}

void MainWindow::commandEnterButtonClicked() {
	sendQuery();
}

void MainWindow::applicationExitRequested() {
	sm->taskIDs.clear();
	for (int i = 0; i < taskList->size(); i++) {
		sm->taskIDs.push_back(taskList->at(i).getID());
	}
	qApp->quit();
}

void MainWindow::resizeEvent(QResizeEvent* event) {
	double oldWidth = event->oldSize().width();
	double newWidth = event->size().width();
	double ratio = newWidth / oldWidth;
	for (int i = 0; i < ui.taskTreePanel->columnCount(); ++i) {
		double currWidth = ui.taskTreePanel->header()->sectionSize(i);
		double finalWidth = currWidth * ratio;
		if (finalWidth >75)
			ui.taskTreePanel->header()->resizeSection(i, currWidth * ratio);
	}
	QMainWindow::resizeEvent(event);
}

void MainWindow::clearTasks() {
	taskList.reset(new TaskList);
	ui.taskTreePanel->clear();
	ui.taskDescriptor->clear();
	ui.commandTextBox->clear();
}

void MainWindow::taskSelected() {
	QList<QTreeWidgetItem*> selection = ui.taskTreePanel->selectedItems();
	QString contents = "";
	if (selection.size() == 0) {
		ui.taskDescriptor->setText(contents);
	} else {
		QTreeWidgetItem item = *selection.at(0);
		QString index = item.text(1);
		QString description = item.text(2);
		QString deadline = item.text(3);
		QString priority = item.text(4);
		QString dependencies = item.text(5);
		contents = "Index: " + index + "\n" + "Description: " + description
			+ "\n" + "Deadline: " + deadline + "\n" + "Priority: " + priority
			+ "\n" + "Dependencies: " + dependencies;
		ui.taskDescriptor->setText(contents);
	}
}

void MainWindow::initializeAllTimerNotifications() {
	for (int i = 0; i < taskList->size(); i++) {
		initializeSingleTimerNotification(taskList->at(i));
	}
}

void MainWindow::initializeSingleTimerNotification(Task task) {
	Task::Time deadline = task.getDeadline();
	if (deadline != Task::DEFAULT_DEADLINE) {
		Task::Time now = boost::posix_time::second_clock::local_time();
		boost::posix_time::time_duration difference = deadline - now;
		QTimer* timer = new QTimer(this);
		connect(timer, SIGNAL(timeout()), this,
			SLOT(notify(notify(task.getID(), task.getDeadline()))));
		timerMap[task.getID()] = timer;
	}
}

void MainWindow::notify(Task::ID id) {
	for (auto it = taskList->begin(); it != taskList->end(); it++) {
		Task task = *it;
		if (task.getID() == id) {
			stm->trayIcon.showMessage("lol", "lol");
			break;
		}
	}
}

void MainWindow::contextAddTask() {
	ui.commandTextBox->setPlainText(QString("/add "));
	ui.commandTextBox->setFocus();
	ui.commandTextBox->moveCursor(QTextCursor::End);
}

void MainWindow::contextDeleteTask(int id) {
	std::wstringstream wss;
	wss << L"/delete " << id;
	ui.commandTextBox->setPlainText(QString::fromStdWString(wss.str()));
	ui.commandTextBox->setFocus();
	ui.commandTextBox->moveCursor(QTextCursor::End);
}

void MainWindow::contextEditTask(int id) {
	std::wstringstream wss;
	wss << L"/edit " << id << L" set ";
	ui.commandTextBox->setPlainText(QString::fromStdWString(wss.str()));
	ui.commandTextBox->setFocus();
	ui.commandTextBox->moveCursor(QTextCursor::End);
}

MainWindow::BaseManager::BaseManager(MainWindow* parentGUI)
	: parentGUI(parentGUI) {
}

bool MainWindow::eventFilter(QObject *object, QEvent *event) {
	if (object == ui.commandTextBox && event->type() == QEvent::KeyPress) {
		QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
		if (keyEvent->key() == Qt::Key_Return) {
			commandEnterPressed();
			ui.commandTextBox->setFocus();
			return true;
		} else {
			return QMainWindow::eventFilter(object, event);
		}
	} else {
		return QMainWindow::eventFilter(object, event);
	}
}

}  // namespace GUI
}  // namespace You
<|endoftext|>