<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_mpipl_chip_cleanup.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
//
//  (C) Copyright International Business Machines Corp. 2012
//  All Rights Reserved -- Property of IBM
//  *** IBM Confidential ***
//
///  TITLE       : p9_mpipl_chip_cleanup.H
///  DESCRIPTION : To enable MCD recovery
///
///  HWP HWP OWNER: Joshua Hannan            Email: jlhannan@us.ibm.com
///  HWP FW Owner: Thi N Tran                Email: thi@us.ibm.com
///  HWP Team: NEST
///  HWP Level: 2
///  HWP Consumed by: FSP/HB
//
//------------------------------------------------------------------------------

#ifndef _P9_MPIPL_CHIP_CLEANUP_H_
#define _P9_MPIPL_CHIP_CLEANUP_H_

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <fapi2.H>

//------------------------------------------------------------------------------
// Structure Definition(s)
//------------------------------------------------------------------------------

// function pointer typedef definition for HWP call support
typedef fapi2::ReturnCode (*p9_mpipl_chip_cleanup_FP_t) (fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& );

extern "C"
{
    ///  @brief To enable MCD recovery

    ///  @param[in] 'i_target' Reference to processor chip target

    ///  @return FAPI_RC_SUCCESS if the mpipl_chip_cleanup completes successfully
    fapi2::ReturnCode p9_mpipl_chip_cleanup(fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);
} //extern "C"

#endif
<commit_msg>Make p9_mpipl_chip_cleanup to be a no-op<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_mpipl_chip_cleanup.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
//
//  (C) Copyright International Business Machines Corp. 2012
//  All Rights Reserved -- Property of IBM
//  *** IBM Confidential ***
//
///  TITLE       : p9_mpipl_chip_cleanup.H
///  DESCRIPTION : To enable MCD recovery
///
///  HWP HWP OWNER: Joshua Hannan            Email: jlhannan@us.ibm.com
///  HWP FW Owner: Thi N Tran                Email: thi@us.ibm.com
///  HWP Team: NEST
///  HWP Level: 2
///  HWP Consumed by: FSP/HB
//
//------------------------------------------------------------------------------

#ifndef _P9_MPIPL_CHIP_CLEANUP_H_
#define _P9_MPIPL_CHIP_CLEANUP_H_

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <fapi2.H>

//------------------------------------------------------------------------------
// Structure Definition(s)
//------------------------------------------------------------------------------

// function pointer typedef definition for HWP call support
typedef fapi2::ReturnCode (*p9_mpipl_chip_cleanup_FP_t) (fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& );

extern "C"
{
    ///  @brief To enable MCD recovery
    ///  @param[in] 'i_target' Reference to processor chip target
    ///  @return FAPI_RC_SUCCESS if the mpipl_chip_cleanup completes successfully
    fapi2::ReturnCode p9_mpipl_chip_cleanup(fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);
} //extern "C"

#endif
<|endoftext|>


<commit_before>/****************************************************************************
 *   Copyright (C) 2011  Instituto Nokia de Tecnologia (INdT)               *
 *                                                                          *
 *   This file may be used under the terms of the GNU Lesser                *
 *   General Public License version 2.1 as published by the Free Software   *
 *   Foundation and appearing in the file LICENSE.LGPL included in the      *
 *   packaging of this file.  Please review the following information to    *
 *   ensure the GNU Lesser General Public License version 2.1 requirements  *
 *   will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.   *
 *                                                                          *
 *   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 Lesser General Public License for more details.                    *
 ****************************************************************************/

#include "BookmarkModel.h"

#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>

BookmarkModel::BookmarkModel(QSqlDatabase database, QObject *parent)
    : QSqlTableModel(parent,  database)
{
    connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SIGNAL(countChanged()));
    connect(this, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SIGNAL(countChanged()));
}

void BookmarkModel::generateRoleNames()
{
    for (int i = 0; i < this->columnCount(); i++)
        m_roles[Qt::UserRole + i] = this->headerData(i, Qt::Horizontal).toByteArray();

    setRoleNames(m_roles);
}

QString BookmarkModel::tableCreateQuery() const
{
    const QLatin1String bookmarkQuery("CREATE TABLE IF NOT EXISTS bookmarks (id INTEGER PRIMARY KEY AUTOINCREMENT,"
                                  "name VARCHAR, url VARCHAR, dateAdded DATE);");

    return bookmarkQuery;

}

void BookmarkModel::setFilter(const QString& filter)
{
    QSqlTableModel::setFilter(filter);
}

bool BookmarkModel::select()
{
    return QSqlTableModel::select();
}

void BookmarkModel::insert(const QString& name, const QString& url)
{
    if (contains(url))
        return;
    QSqlRecord record = this->record();
    record.setValue(QLatin1String("name"), name);
    record.setValue(QLatin1String("url"), url);

    insertRecord(-1, record);
}

void BookmarkModel::remove(const QString& url)
{
    if (!contains(url))
        return;
    QSqlQuery sqlQuery(database());
    sqlQuery.prepare(QString(QLatin1String("SELECT id FROM bookmarks WHERE url = '%1'")).arg(url));
    sqlQuery.exec();
    sqlQuery.first();
    int indexToDelete = -1;
    for (int row = 0; row < rowCount(); ++row) {
        if (index(row, 0).data(Qt::DisplayRole).toInt() == sqlQuery.value(0).toInt()) {
            indexToDelete = row;
            break;
        }
    }
    removeRow(indexToDelete);
}

void BookmarkModel::update(int index, const QString& name, const QString& url)
{
    setData(this->index(index, 1), name);
    setData(this->index(index, 2), url);
}

bool BookmarkModel::contains(const QString& url)
{
    QSqlQuery sqlQuery(database());
    sqlQuery.prepare(QString(QLatin1String("SELECT id FROM bookmarks WHERE url = '%1'")).arg(url));
    sqlQuery.exec();
    return sqlQuery.first();
}

QVariant BookmarkModel::data(const QModelIndex& index, int role) const
{
    QVariant value;
    if (role < Qt::UserRole)
        value = QSqlQueryModel::data(index, role);
    else {
        const int columnId = role - Qt::UserRole;
        const QModelIndex modelIndex = this->index(index.row(), columnId);
        value = QSqlTableModel::data(modelIndex, Qt::DisplayRole);
    }
    return value;
}
<commit_msg>Use bounded values on BookmarkModel SQL queries to avoid SQL injections or syntax errors.<commit_after>/****************************************************************************
 *   Copyright (C) 2011  Instituto Nokia de Tecnologia (INdT)               *
 *                                                                          *
 *   This file may be used under the terms of the GNU Lesser                *
 *   General Public License version 2.1 as published by the Free Software   *
 *   Foundation and appearing in the file LICENSE.LGPL included in the      *
 *   packaging of this file.  Please review the following information to    *
 *   ensure the GNU Lesser General Public License version 2.1 requirements  *
 *   will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.   *
 *                                                                          *
 *   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 Lesser General Public License for more details.                    *
 ****************************************************************************/

#include "BookmarkModel.h"

#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>

BookmarkModel::BookmarkModel(QSqlDatabase database, QObject *parent)
    : QSqlTableModel(parent,  database)
{
    connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SIGNAL(countChanged()));
    connect(this, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SIGNAL(countChanged()));
}

void BookmarkModel::generateRoleNames()
{
    for (int i = 0; i < this->columnCount(); i++)
        m_roles[Qt::UserRole + i] = this->headerData(i, Qt::Horizontal).toByteArray();

    setRoleNames(m_roles);
}

QString BookmarkModel::tableCreateQuery() const
{
    const QLatin1String bookmarkQuery("CREATE TABLE IF NOT EXISTS bookmarks (id INTEGER PRIMARY KEY AUTOINCREMENT,"
                                  "name VARCHAR, url VARCHAR, dateAdded DATE);");

    return bookmarkQuery;

}

void BookmarkModel::setFilter(const QString& filter)
{
    QSqlTableModel::setFilter(filter);
}

bool BookmarkModel::select()
{
    return QSqlTableModel::select();
}

void BookmarkModel::insert(const QString& name, const QString& url)
{
    if (contains(url))
        return;
    QSqlRecord record = this->record();
    record.setValue(QLatin1String("name"), name);
    record.setValue(QLatin1String("url"), url);

    insertRecord(-1, record);
}

void BookmarkModel::remove(const QString& url)
{
    if (!contains(url))
        return;
    QSqlQuery sqlQuery(database());
    sqlQuery.prepare(QLatin1String("SELECT id FROM bookmarks WHERE url = ?"));
    sqlQuery.addBindValue(url);
    sqlQuery.exec();
    sqlQuery.first();
    int indexToDelete = -1;
    for (int row = 0; row < rowCount(); ++row) {
        if (index(row, 0).data(Qt::DisplayRole).toInt() == sqlQuery.value(0).toInt()) {
            indexToDelete = row;
            break;
        }
    }
    removeRow(indexToDelete);
}

void BookmarkModel::update(int index, const QString& name, const QString& url)
{
    setData(this->index(index, 1), name);
    setData(this->index(index, 2), url);
}

bool BookmarkModel::contains(const QString& url)
{
    QSqlQuery sqlQuery(database());
    sqlQuery.prepare(QLatin1String("SELECT id FROM bookmarks WHERE url = ?"));
    sqlQuery.addBindValue(url);
    sqlQuery.exec();
    return sqlQuery.first();
}

QVariant BookmarkModel::data(const QModelIndex& index, int role) const
{
    QVariant value;
    if (role < Qt::UserRole)
        value = QSqlQueryModel::data(index, role);
    else {
        const int columnId = role - Qt::UserRole;
        const QModelIndex modelIndex = this->index(index.row(), columnId);
        value = QSqlTableModel::data(modelIndex, Qt::DisplayRole);
    }
    return value;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorFilter.h"
#include "SkReadBuffer.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTDArray.h"
#include "SkUnPreMultiply.h"
#include "SkWriteBuffer.h"
#include "SkPM4f.h"
#include "SkNx.h"

#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
#endif

bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
    return false;
}

bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
    return false;
}

bool SkColorFilter::asComponentTable(SkBitmap*) const {
    return false;
}

#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*) const {
    return nullptr;
}
#endif

void SkColorFilter::filterSpan4f(const SkPM4f[], int count, SkPM4f span[]) const {
    const int N = 128;
    SkPMColor tmp[N];
    while (count > 0) {
        int n = SkTMin(count, N);
        for (int i = 0; i < n; ++i) {
            SkNx_cast<uint8_t>(Sk4f::Load(span[i].fVec) * Sk4f(255) + Sk4f(0.5f)).store(&tmp[i]);
        }
        this->filterSpan(tmp, n, tmp);
        for (int i = 0; i < n; ++i) {
            span[i] = SkPM4f::FromPMColor(tmp[i]);
        }
        span += n;
        count -= n;
    }
}

SkColor SkColorFilter::filterColor(SkColor c) const {
    SkPMColor dst, src = SkPreMultiplyColor(c);
    this->filterSpan(&src, 1, &dst);
    return SkUnPreMultiply::PMColorToColor(dst);
}

SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
    SkPM4f dst, src = c.premul();
    this->filterSpan4f(&src, 1, &dst);
    return dst.unpremul();
}

///////////////////////////////////////////////////////////////////////////////////////////////////

/*
 *  Since colorfilters may be used on the GPU backend, and in that case we may string together
 *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
 *
 *  Since we don't yet know *what* those limits might be when we construct the final shader,
 *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
 *  the limnits are, we can change this constant (or remove it).
 */
#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4

class SkComposeColorFilter : public SkColorFilter {
public:
    uint32_t getFlags() const override {
        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
        return fOuter->getFlags() & fInner->getFlags();
    }

    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
        fInner->filterSpan(shader, count, result);
        fOuter->filterSpan(result, count, result);
    }

    void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
        fInner->filterSpan4f(shader, count, result);
        fOuter->filterSpan4f(result, count, result);
    }

#ifndef SK_IGNORE_TO_STRING
    void toString(SkString* str) const override {
        SkString outerS, innerS;
        fOuter->toString(&outerS);
        fInner->toString(&innerS);
        str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str());
    }
#endif

#if SK_SUPPORT_GPU
    sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context) const override {
        sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context));
        sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context));
        if (!innerFP || !outerFP) {
            return nullptr;
        }
        sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
        return GrFragmentProcessor::RunInSeries(series, 2);
    }
#endif

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)

protected:
    void flatten(SkWriteBuffer& buffer) const override {
        buffer.writeFlattenable(fOuter.get());
        buffer.writeFlattenable(fInner.get());
    }

private:
    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
                         int composedFilterCount)
        : fOuter(std::move(outer))
        , fInner(std::move(inner))
        , fComposedFilterCount(composedFilterCount)
    {
        SkASSERT(composedFilterCount >= 2);
        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
    }

    int privateComposedFilterCount() const override {
        return fComposedFilterCount;
    }

    sk_sp<SkColorFilter> fOuter;
    sk_sp<SkColorFilter> fInner;
    const int            fComposedFilterCount;

    friend class SkColorFilter;

    typedef SkColorFilter INHERITED;
};

sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
    return MakeComposeFilter(std::move(outer), std::move(inner));
}

///////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
                                                      sk_sp<SkColorFilter> inner) {
    if (!outer) {
        return inner;
    }
    if (!inner) {
        return outer;
    }

    // Give the subclass a shot at a more optimal composition...
    auto composition = outer->makeComposed(inner);
    if (composition) {
        return composition;
    }

    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
        return nullptr;
    }
    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
}

#include "SkModeColorFilter.h"

SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
<commit_msg>Fix bug in filterSpan4f - read the source, rather than the dest<commit_after>/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorFilter.h"
#include "SkReadBuffer.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTDArray.h"
#include "SkUnPreMultiply.h"
#include "SkWriteBuffer.h"
#include "SkPM4f.h"
#include "SkNx.h"

#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
#endif

bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
    return false;
}

bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
    return false;
}

bool SkColorFilter::asComponentTable(SkBitmap*) const {
    return false;
}

#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*) const {
    return nullptr;
}
#endif

void SkColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const {
    const int N = 128;
    SkPMColor tmp[N];
    while (count > 0) {
        int n = SkTMin(count, N);
        for (int i = 0; i < n; ++i) {
            SkNx_cast<uint8_t>(Sk4f::Load(src[i].fVec) * Sk4f(255) + Sk4f(0.5f)).store(&tmp[i]);
        }
        this->filterSpan(tmp, n, tmp);
        for (int i = 0; i < n; ++i) {
            result[i] = SkPM4f::FromPMColor(tmp[i]);
        }
        src += n;
        result += n;
        count -= n;
    }
}

SkColor SkColorFilter::filterColor(SkColor c) const {
    SkPMColor dst, src = SkPreMultiplyColor(c);
    this->filterSpan(&src, 1, &dst);
    return SkUnPreMultiply::PMColorToColor(dst);
}

SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
    SkPM4f dst, src = c.premul();
    this->filterSpan4f(&src, 1, &dst);
    return dst.unpremul();
}

///////////////////////////////////////////////////////////////////////////////////////////////////

/*
 *  Since colorfilters may be used on the GPU backend, and in that case we may string together
 *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
 *
 *  Since we don't yet know *what* those limits might be when we construct the final shader,
 *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
 *  the limnits are, we can change this constant (or remove it).
 */
#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4

class SkComposeColorFilter : public SkColorFilter {
public:
    uint32_t getFlags() const override {
        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
        return fOuter->getFlags() & fInner->getFlags();
    }

    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
        fInner->filterSpan(shader, count, result);
        fOuter->filterSpan(result, count, result);
    }

    void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
        fInner->filterSpan4f(shader, count, result);
        fOuter->filterSpan4f(result, count, result);
    }

#ifndef SK_IGNORE_TO_STRING
    void toString(SkString* str) const override {
        SkString outerS, innerS;
        fOuter->toString(&outerS);
        fInner->toString(&innerS);
        str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str());
    }
#endif

#if SK_SUPPORT_GPU
    sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context) const override {
        sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context));
        sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context));
        if (!innerFP || !outerFP) {
            return nullptr;
        }
        sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
        return GrFragmentProcessor::RunInSeries(series, 2);
    }
#endif

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)

protected:
    void flatten(SkWriteBuffer& buffer) const override {
        buffer.writeFlattenable(fOuter.get());
        buffer.writeFlattenable(fInner.get());
    }

private:
    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
                         int composedFilterCount)
        : fOuter(std::move(outer))
        , fInner(std::move(inner))
        , fComposedFilterCount(composedFilterCount)
    {
        SkASSERT(composedFilterCount >= 2);
        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
    }

    int privateComposedFilterCount() const override {
        return fComposedFilterCount;
    }

    sk_sp<SkColorFilter> fOuter;
    sk_sp<SkColorFilter> fInner;
    const int            fComposedFilterCount;

    friend class SkColorFilter;

    typedef SkColorFilter INHERITED;
};

sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
    return MakeComposeFilter(std::move(outer), std::move(inner));
}

///////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
                                                      sk_sp<SkColorFilter> inner) {
    if (!outer) {
        return inner;
    }
    if (!inner) {
        return outer;
    }

    // Give the subclass a shot at a more optimal composition...
    auto composition = outer->makeComposed(inner);
    if (composition) {
        return composition;
    }

    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
        return nullptr;
    }
    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
}

#include "SkModeColorFilter.h"

SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkLatticeIter.h"
#include "SkRect.h"

/**
 *  Divs must be in increasing order with no duplicates.
 */
static bool valid_divs(const int* divs, int count, int start, int end) {
    int prev = start - 1;
    for (int i = 0; i < count; i++) {
        if (prev >= divs[i] || divs[i] >= end) {
            return false;
        }
        prev = divs[i];
    }

    return true;
}

bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) {
    SkIRect totalBounds = SkIRect::MakeWH(width, height);
    SkASSERT(lattice.fBounds);
    const SkIRect latticeBounds = *lattice.fBounds;
    if (!totalBounds.contains(latticeBounds)) {
        return false;
    }

    bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount &&
                                              latticeBounds.fLeft == lattice.fXDivs[0]);
    bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount &&
                                              latticeBounds.fTop == lattice.fYDivs[0]);
    if (zeroXDivs && zeroYDivs) {
        return false;
    }

    return valid_divs(lattice.fXDivs, lattice.fXCount, latticeBounds.fLeft, latticeBounds.fRight)
        && valid_divs(lattice.fYDivs, lattice.fYCount, latticeBounds.fTop, latticeBounds.fBottom);
}

/**
 *  Count the number of pixels that are in "scalable" patches.
 */
static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsScalable,
                                 int start, int end) {
    if (0 == numDivs) {
        return firstIsScalable ? end - start : 0;
    }

    int i;
    int count;
    if (firstIsScalable) {
        count = divs[0] - start;
        i = 1;
    } else {
        count = 0;
        i = 0;
    }

    for (; i < numDivs; i += 2) {
        // Alternatively, we could use |top| and |bottom| as variable names, instead of
        // |left| and |right|.
        int left = divs[i];
        int right = (i + 1 < numDivs) ? divs[i + 1] : end;
        count += right - left;
    }

    return count;
}

/**
 *  Set points for the src and dst rects on subsequent draw calls.
 */
static void set_points(float* dst, float* src, const int* divs, int divCount, int srcFixed,
                       int srcScalable, float srcStart, float srcEnd, float dstStart, float dstEnd,
                       bool isScalable) {

    float dstLen = dstEnd - dstStart;
    float scale;
    if (srcFixed <= dstLen) {
        // This is the "normal" case, where we scale the "scalable" patches and leave
        // the other patches fixed.
        scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable);
    } else {
        // In this case, we eliminate the "scalable" patches and scale the "fixed" patches.
        scale = dstLen / ((float) srcFixed);
    }

    src[0] = srcStart;
    dst[0] = dstStart;
    for (int i = 0; i < divCount; i++) {
        src[i + 1] = (float) (divs[i]);
        float srcDelta = src[i + 1] - src[i];
        float dstDelta;
        if (srcFixed <= dstLen) {
            dstDelta = isScalable ? scale * srcDelta : srcDelta;
        } else {
            dstDelta = isScalable ? 0.0f : scale * srcDelta;
        }
        dst[i + 1] = dst[i] + dstDelta;

        // Alternate between "scalable" and "fixed" patches.
        isScalable = !isScalable;
    }

    src[divCount + 1] = srcEnd;
    dst[divCount + 1] = dstEnd;
}

SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst) {
    const int* xDivs = lattice.fXDivs;
    const int origXCount = lattice.fXCount;
    const int* yDivs = lattice.fYDivs;
    const int origYCount = lattice.fYCount;
    SkASSERT(lattice.fBounds);
    const SkIRect src = *lattice.fBounds;

    // In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
    // If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
    // first real rectangle "scalable" in the x-direction.
    //
    // The same interpretation applies to the y-dimension.
    //
    // As we move left to right across the image, alternating patches will be "fixed" or
    // "scalable" in the x-direction.  Similarly, as move top to bottom, alternating
    // patches will be "fixed" or "scalable" in the y-direction.
    int xCount = origXCount;
    int yCount = origYCount;
    bool xIsScalable = (xCount > 0 && src.fLeft == xDivs[0]);
    if (xIsScalable) {
        // Once we've decided that the first patch is "scalable", we don't need the
        // xDiv.  It is always implied that we start at the edge of the bounds.
        xDivs++;
        xCount--;
    }
    bool yIsScalable = (yCount > 0 && src.fTop == yDivs[0]);
    if (yIsScalable) {
        // Once we've decided that the first patch is "scalable", we don't need the
        // yDiv.  It is always implied that we start at the edge of the bounds.
        yDivs++;
        yCount--;
    }

    // Count "scalable" and "fixed" pixels in each dimension.
    int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, src.fLeft, src.fRight);
    int xCountFixed = src.width() - xCountScalable;
    int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, src.fTop, src.fBottom);
    int yCountFixed = src.height() - yCountScalable;

    fSrcX.reset(xCount + 2);
    fDstX.reset(xCount + 2);
    set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountScalable,
               src.fLeft, src.fRight, dst.fLeft, dst.fRight, xIsScalable);

    fSrcY.reset(yCount + 2);
    fDstY.reset(yCount + 2);
    set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountScalable,
               src.fTop, src.fBottom, dst.fTop, dst.fBottom, yIsScalable);

    fCurrX = fCurrY = 0;
    fNumRectsInLattice = (xCount + 1) * (yCount + 1);
    fNumRectsToDraw = fNumRectsInLattice;

    if (lattice.fRectTypes) {
        fRectTypes.push_back_n(fNumRectsInLattice);
        fColors.push_back_n(fNumRectsInLattice);

        const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes;
        const SkColor* colors = lattice.fColors;

        bool hasPadRow = (yCount != origYCount);
        bool hasPadCol = (xCount != origXCount);
        if (hasPadRow) {
            // The first row of rects are all empty, skip the first row of flags.
            flags += origXCount + 1;
            colors += origXCount + 1;
        }

        int i = 0;
        for (int y = 0; y < yCount + 1; y++) {
            for (int x = 0; x < origXCount + 1; x++) {
                if (0 == x && hasPadCol) {
                    // The first column of rects are all empty.  Skip a rect.
                    flags++;
                    colors++;
                    continue;
                }

                fRectTypes[i] = *flags;
                fColors[i] = *colors;
                flags++;
                colors++;
                i++;
            }
        }

        for (int j = 0; j < fRectTypes.count(); j++) {
            if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) {
                fNumRectsToDraw--;
            }
        }
    }
}

bool SkLatticeIter::Valid(int width, int height, const SkIRect& center) {
    return !center.isEmpty() && SkIRect::MakeWH(width, height).contains(center);
}

SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) {
    SkASSERT(SkIRect::MakeWH(w, h).contains(c));

    fSrcX.reset(4);
    fSrcY.reset(4);
    fDstX.reset(4);
    fDstY.reset(4);

    fSrcX[0] = 0;
    fSrcX[1] = SkIntToScalar(c.fLeft);
    fSrcX[2] = SkIntToScalar(c.fRight);
    fSrcX[3] = SkIntToScalar(w);

    fSrcY[0] = 0;
    fSrcY[1] = SkIntToScalar(c.fTop);
    fSrcY[2] = SkIntToScalar(c.fBottom);
    fSrcY[3] = SkIntToScalar(h);

    fDstX[0] = dst.fLeft;
    fDstX[1] = dst.fLeft + SkIntToScalar(c.fLeft);
    fDstX[2] = dst.fRight - SkIntToScalar(w - c.fRight);
    fDstX[3] = dst.fRight;

    fDstY[0] = dst.fTop;
    fDstY[1] = dst.fTop + SkIntToScalar(c.fTop);
    fDstY[2] = dst.fBottom - SkIntToScalar(h - c.fBottom);
    fDstY[3] = dst.fBottom;

    if (fDstX[1] > fDstX[2]) {
        fDstX[1] = fDstX[0] + (fDstX[3] - fDstX[0]) * c.fLeft / (w - c.width());
        fDstX[2] = fDstX[1];
    }

    if (fDstY[1] > fDstY[2]) {
        fDstY[1] = fDstY[0] + (fDstY[3] - fDstY[0]) * c.fTop / (h - c.height());
        fDstY[2] = fDstY[1];
    }

    fCurrX = fCurrY = 0;
    fNumRectsInLattice = 9;
    fNumRectsToDraw = 9;
}

bool SkLatticeIter::next(SkRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) {
    int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
    if (currRect == fNumRectsInLattice) {
        return false;
    }

    const int x = fCurrX;
    const int y = fCurrY;
    SkASSERT(x >= 0 && x < fSrcX.count() - 1);
    SkASSERT(y >= 0 && y < fSrcY.count() - 1);

    if (fSrcX.count() - 1 == ++fCurrX) {
        fCurrX = 0;
        fCurrY += 1;
    }

    if (fRectTypes.count() > 0
        && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) {
        return this->next(src, dst, isFixedColor, fixedColor);
    }

    src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
    dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
    if (isFixedColor && fixedColor) {
        *isFixedColor = fRectTypes.count() > 0
                     && SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]);
        if (*isFixedColor) {
            *fixedColor = fColors[currRect];
        }
    }
    return true;
}

void SkLatticeIter::mapDstScaleTranslate(const SkMatrix& matrix) {
    SkASSERT(matrix.isScaleTranslate());
    SkScalar tx = matrix.getTranslateX();
    SkScalar sx = matrix.getScaleX();
    for (int i = 0; i < fDstX.count(); i++) {
        fDstX[i] = fDstX[i] * sx + tx;
    }

    SkScalar ty = matrix.getTranslateY();
    SkScalar sy = matrix.getScaleY();
    for (int i = 0; i < fDstY.count(); i++) {
        fDstY[i] = fDstY[i] * sy + ty;
    }
}
<commit_msg>only read color array if flag is fixed color<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkLatticeIter.h"
#include "SkRect.h"

/**
 *  Divs must be in increasing order with no duplicates.
 */
static bool valid_divs(const int* divs, int count, int start, int end) {
    int prev = start - 1;
    for (int i = 0; i < count; i++) {
        if (prev >= divs[i] || divs[i] >= end) {
            return false;
        }
        prev = divs[i];
    }

    return true;
}

bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) {
    SkIRect totalBounds = SkIRect::MakeWH(width, height);
    SkASSERT(lattice.fBounds);
    const SkIRect latticeBounds = *lattice.fBounds;
    if (!totalBounds.contains(latticeBounds)) {
        return false;
    }

    bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount &&
                                              latticeBounds.fLeft == lattice.fXDivs[0]);
    bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount &&
                                              latticeBounds.fTop == lattice.fYDivs[0]);
    if (zeroXDivs && zeroYDivs) {
        return false;
    }

    return valid_divs(lattice.fXDivs, lattice.fXCount, latticeBounds.fLeft, latticeBounds.fRight)
        && valid_divs(lattice.fYDivs, lattice.fYCount, latticeBounds.fTop, latticeBounds.fBottom);
}

/**
 *  Count the number of pixels that are in "scalable" patches.
 */
static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsScalable,
                                 int start, int end) {
    if (0 == numDivs) {
        return firstIsScalable ? end - start : 0;
    }

    int i;
    int count;
    if (firstIsScalable) {
        count = divs[0] - start;
        i = 1;
    } else {
        count = 0;
        i = 0;
    }

    for (; i < numDivs; i += 2) {
        // Alternatively, we could use |top| and |bottom| as variable names, instead of
        // |left| and |right|.
        int left = divs[i];
        int right = (i + 1 < numDivs) ? divs[i + 1] : end;
        count += right - left;
    }

    return count;
}

/**
 *  Set points for the src and dst rects on subsequent draw calls.
 */
static void set_points(float* dst, float* src, const int* divs, int divCount, int srcFixed,
                       int srcScalable, float srcStart, float srcEnd, float dstStart, float dstEnd,
                       bool isScalable) {

    float dstLen = dstEnd - dstStart;
    float scale;
    if (srcFixed <= dstLen) {
        // This is the "normal" case, where we scale the "scalable" patches and leave
        // the other patches fixed.
        scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable);
    } else {
        // In this case, we eliminate the "scalable" patches and scale the "fixed" patches.
        scale = dstLen / ((float) srcFixed);
    }

    src[0] = srcStart;
    dst[0] = dstStart;
    for (int i = 0; i < divCount; i++) {
        src[i + 1] = (float) (divs[i]);
        float srcDelta = src[i + 1] - src[i];
        float dstDelta;
        if (srcFixed <= dstLen) {
            dstDelta = isScalable ? scale * srcDelta : srcDelta;
        } else {
            dstDelta = isScalable ? 0.0f : scale * srcDelta;
        }
        dst[i + 1] = dst[i] + dstDelta;

        // Alternate between "scalable" and "fixed" patches.
        isScalable = !isScalable;
    }

    src[divCount + 1] = srcEnd;
    dst[divCount + 1] = dstEnd;
}

SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst) {
    const int* xDivs = lattice.fXDivs;
    const int origXCount = lattice.fXCount;
    const int* yDivs = lattice.fYDivs;
    const int origYCount = lattice.fYCount;
    SkASSERT(lattice.fBounds);
    const SkIRect src = *lattice.fBounds;

    // In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
    // If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
    // first real rectangle "scalable" in the x-direction.
    //
    // The same interpretation applies to the y-dimension.
    //
    // As we move left to right across the image, alternating patches will be "fixed" or
    // "scalable" in the x-direction.  Similarly, as move top to bottom, alternating
    // patches will be "fixed" or "scalable" in the y-direction.
    int xCount = origXCount;
    int yCount = origYCount;
    bool xIsScalable = (xCount > 0 && src.fLeft == xDivs[0]);
    if (xIsScalable) {
        // Once we've decided that the first patch is "scalable", we don't need the
        // xDiv.  It is always implied that we start at the edge of the bounds.
        xDivs++;
        xCount--;
    }
    bool yIsScalable = (yCount > 0 && src.fTop == yDivs[0]);
    if (yIsScalable) {
        // Once we've decided that the first patch is "scalable", we don't need the
        // yDiv.  It is always implied that we start at the edge of the bounds.
        yDivs++;
        yCount--;
    }

    // Count "scalable" and "fixed" pixels in each dimension.
    int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, src.fLeft, src.fRight);
    int xCountFixed = src.width() - xCountScalable;
    int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, src.fTop, src.fBottom);
    int yCountFixed = src.height() - yCountScalable;

    fSrcX.reset(xCount + 2);
    fDstX.reset(xCount + 2);
    set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountScalable,
               src.fLeft, src.fRight, dst.fLeft, dst.fRight, xIsScalable);

    fSrcY.reset(yCount + 2);
    fDstY.reset(yCount + 2);
    set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountScalable,
               src.fTop, src.fBottom, dst.fTop, dst.fBottom, yIsScalable);

    fCurrX = fCurrY = 0;
    fNumRectsInLattice = (xCount + 1) * (yCount + 1);
    fNumRectsToDraw = fNumRectsInLattice;

    if (lattice.fRectTypes) {
        fRectTypes.push_back_n(fNumRectsInLattice);
        fColors.push_back_n(fNumRectsInLattice);

        const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes;
        const SkColor* colors = lattice.fColors;

        bool hasPadRow = (yCount != origYCount);
        bool hasPadCol = (xCount != origXCount);
        if (hasPadRow) {
            // The first row of rects are all empty, skip the first row of flags.
            flags += origXCount + 1;
            colors += origXCount + 1;
        }

        int i = 0;
        for (int y = 0; y < yCount + 1; y++) {
            for (int x = 0; x < origXCount + 1; x++) {
                if (0 == x && hasPadCol) {
                    // The first column of rects are all empty.  Skip a rect.
                    flags++;
                    colors++;
                    continue;
                }

                fRectTypes[i] = *flags;
                fColors[i] = SkCanvas::Lattice::kFixedColor == *flags ? *colors : 0;
                flags++;
                colors++;
                i++;
            }
        }

        for (int j = 0; j < fRectTypes.count(); j++) {
            if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) {
                fNumRectsToDraw--;
            }
        }
    }
}

bool SkLatticeIter::Valid(int width, int height, const SkIRect& center) {
    return !center.isEmpty() && SkIRect::MakeWH(width, height).contains(center);
}

SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) {
    SkASSERT(SkIRect::MakeWH(w, h).contains(c));

    fSrcX.reset(4);
    fSrcY.reset(4);
    fDstX.reset(4);
    fDstY.reset(4);

    fSrcX[0] = 0;
    fSrcX[1] = SkIntToScalar(c.fLeft);
    fSrcX[2] = SkIntToScalar(c.fRight);
    fSrcX[3] = SkIntToScalar(w);

    fSrcY[0] = 0;
    fSrcY[1] = SkIntToScalar(c.fTop);
    fSrcY[2] = SkIntToScalar(c.fBottom);
    fSrcY[3] = SkIntToScalar(h);

    fDstX[0] = dst.fLeft;
    fDstX[1] = dst.fLeft + SkIntToScalar(c.fLeft);
    fDstX[2] = dst.fRight - SkIntToScalar(w - c.fRight);
    fDstX[3] = dst.fRight;

    fDstY[0] = dst.fTop;
    fDstY[1] = dst.fTop + SkIntToScalar(c.fTop);
    fDstY[2] = dst.fBottom - SkIntToScalar(h - c.fBottom);
    fDstY[3] = dst.fBottom;

    if (fDstX[1] > fDstX[2]) {
        fDstX[1] = fDstX[0] + (fDstX[3] - fDstX[0]) * c.fLeft / (w - c.width());
        fDstX[2] = fDstX[1];
    }

    if (fDstY[1] > fDstY[2]) {
        fDstY[1] = fDstY[0] + (fDstY[3] - fDstY[0]) * c.fTop / (h - c.height());
        fDstY[2] = fDstY[1];
    }

    fCurrX = fCurrY = 0;
    fNumRectsInLattice = 9;
    fNumRectsToDraw = 9;
}

bool SkLatticeIter::next(SkRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) {
    int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
    if (currRect == fNumRectsInLattice) {
        return false;
    }

    const int x = fCurrX;
    const int y = fCurrY;
    SkASSERT(x >= 0 && x < fSrcX.count() - 1);
    SkASSERT(y >= 0 && y < fSrcY.count() - 1);

    if (fSrcX.count() - 1 == ++fCurrX) {
        fCurrX = 0;
        fCurrY += 1;
    }

    if (fRectTypes.count() > 0
        && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) {
        return this->next(src, dst, isFixedColor, fixedColor);
    }

    src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
    dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
    if (isFixedColor && fixedColor) {
        *isFixedColor = fRectTypes.count() > 0
                     && SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]);
        if (*isFixedColor) {
            *fixedColor = fColors[currRect];
        }
    }
    return true;
}

void SkLatticeIter::mapDstScaleTranslate(const SkMatrix& matrix) {
    SkASSERT(matrix.isScaleTranslate());
    SkScalar tx = matrix.getTranslateX();
    SkScalar sx = matrix.getScaleX();
    for (int i = 0; i < fDstX.count(); i++) {
        fDstX[i] = fDstX[i] * sx + tx;
    }

    SkScalar ty = matrix.getTranslateY();
    SkScalar sy = matrix.getScaleY();
    for (int i = 0; i < fDstY.count(); i++) {
        fDstY[i] = fDstY[i] * sy + ty;
    }
}
<|endoftext|>


<commit_before>#pragma once
/** @file Vec.hpp
 * @brief A wrapper class to provide simple vector operations for
 * primitive types and classes that only require op[].
 */

#include <iostream>
#include <type_traits>
#include <cstdarg>
#include <math.h>
#include <assert.h>

//! Predeclaration of SmallVec
template <unsigned DIM, typename DATA>
class SmallVec;

/** @class Vec
 * A general class that endows types with vector operations. If the base type
 * is a primitive type, the Vec stores information as an array of that type.
 * If the base type is not a primitive type, then it must implement the bracket
 * operator (lvalue and rvalue)
 *
 * All of the following result in nearly the same public Vec interface
 * Vec<3, double> v1;
 * Vec<3, double[3]> v2;
 * Vec<3, MyClassThatImplementsOpBracketWithDoubles> v3;
 */
template <unsigned DIM, typename DATA>
using Vec = typename std::conditional<std::is_fundamental<DATA>::value,
                                      SmallVec<DIM, DATA[DIM]>,
                                      SmallVec<DIM, DATA>>::type;

#define for_i for(unsigned i=0; i!=dimension; ++i)

/** @class SmallVec
 * @brief Class representing ND points and vectors.
 *
 * SmallVec contains methods that support use of the underlying type
 * as points in ND space. The underlying data is stored as type POINT,
 * which must only provide the operators:
 * value_type& operator[](unsigned i)
 * const value_type& operator[](unsigned i) const
 */
template <unsigned DIM, typename POINT>
class SmallVec {
  static_assert(DIM > 0, "SmallVec DIM must be greater than 0");

  POINT a;

 public:
  static constexpr unsigned dimension = DIM;
  typedef POINT point_type;
  typedef typename std::decay<decltype(a[0])>::type value_type;

  // CONSTRUCTORS

  SmallVec() {
    for_i a[i] = value_type(0);
  }
  SmallVec(const SmallVec& b) {
    for_i a[i] = b[i];
  }
  explicit SmallVec(const point_type& b) {
    for_i a[i] = b[i];
  }
  explicit SmallVec(value_type b) {
    for_i a[i] = b;
  }
  SmallVec(value_type b0, value_type b1) {
    static_assert(dimension == 2, "Calling 2-value Vec constructor for Non-2D Vec");
    a[0] = b0; a[1] = b1;
  }
  SmallVec(value_type b0, value_type b1, value_type b2) {
    static_assert(dimension == 3, "Calling 3-value Vec constructor for Non-3D Vec");
    a[0] = b0; a[1] = b1; a[2] = b2;
  }
  SmallVec(value_type b0, value_type b1, value_type b2, value_type b3) {
    static_assert(dimension == 4, "Calling 4-value Vec constructor for Non-4D Vec");
    a[0] = b0; a[1] = b1; a[2] = b2; a[3] = b3;
  }

  inline bool operator==(const SmallVec& b) const {
    for_i if (a[i] != b[i]) return false;
    return true;
  }

  // MODIFIERS

  /** Return a negated version of @a p. */
  inline SmallVec operator-() const {
    return SmallVec(-a[0], -a[1], -a[2]);
  }
  /** Scalar assignment */
  inline SmallVec& operator=(const value_type b) {
    for_i a[i] = b;
    return *this;
  }
  /** Add scalar @a b to this SmallVec */
  inline SmallVec& operator+=(const value_type b) {
    for_i a[i] += b;
    return *this;
  }
  /** Subtract scalar @a b from this SmallVec */
  inline SmallVec& operator-=(const value_type b) {
    for_i a[i] -= b;
    return *this;
  }
  /** Scale this SmallVec up by scalar @a b */
  inline SmallVec& operator*=(const value_type b) {
    for_i a[i] *= b;
    return *this;
  }
  /** Scale this SmallVec down by scalar @a b */
  inline SmallVec& operator/=(const value_type b) {
    for_i a[i] /= b;
    return *this;
  }
  /** Add SmallVec @a b to this SmallVec */
  inline SmallVec& operator+=(const SmallVec& b) {
    for_i a[i] += b[i];
    return *this;
  }
  /** Subtract SmallVec @a b from this SmallVec */
  inline SmallVec& operator-=(const SmallVec& b) {
    for_i a[i] -= b[i];
    return *this;
  }
  /** Scale this SmallVec up by factors in @a b */
  inline SmallVec& operator*=(const SmallVec& b) {
    for_i a[i] *= b[i];
    return *this;
  }
  /** Scale this SmallVec down by factors in @a b */
  inline SmallVec& operator/=(const SmallVec& b) {
    for_i a[i] /= b[i];
    return *this;
  }
  /** Compute the dot product of this SmallVec with another SmallVec */
  inline value_type dot(const SmallVec& b) const {
    value_type d(0);
    for_i d += a[i]*b[i];
    return d;
  }

  // ACCESSORS

  /** Access the @a i th (lvalue) element of this SmallVec
   * @pre i < dimension */
  inline value_type& operator[](unsigned i) {
    //assert(i < dimension);
    return a[i];
  }
  /** Access the @a i th (rvalue) element of this SmallVec
   * @pre i < dimension */
  inline const value_type& operator[](unsigned i) const {
    //assert(i < dimension);
    return a[i];
  }
  static constexpr unsigned size() {
    return dimension;
  }

  /** Compute the dot product of this SmallVec with another SmallVec */
  inline friend value_type dot(const SmallVec& a, const SmallVec& b) {
    return a.dot(b);
  }
  /** Compute cross product of two SmallVecs */
  inline friend SmallVec cross(const SmallVec& a, const SmallVec& b) {
    static_assert(SmallVec::dimension == 3, "Cross product only defined for 3D");
    SmallVec r;
    r[0] = a[1]*b[2] - a[2]*b[1];
    r[1] = -(a[0]*b[2] - a[2]*b[0]);
    r[2] = a[0]*b[1] - a[1]*b[0];
    return r;
  }
  /** Compute the squared L2 norm of this SmallVec */
  inline friend value_type normSq(const SmallVec& b) {
    return b.dot(b);
  }
  /** Compute the L2 norm of this SmallVec */
  inline friend value_type norm(const SmallVec& b) {
    return sqrt(normSq(b));
  }
  /** Write a SmallVec to an output stream */
  inline friend std::ostream& operator<<(std::ostream& s, const SmallVec& a) {
    for_i s << a[i] << " ";
    return s;
  }
};

#undef for_i

// OPERATORS

/** Compute the dot product of two SmallVecs */
template <unsigned D, typename P>
inline typename SmallVec<D,P>::value_type dot(const SmallVec<D,P>& a,
                                              const SmallVec<D,P>& b) {
  return a.dot(b);
}
/** Compute the squared L2 norm of this SmallVec */
template <unsigned D, typename P>
inline typename SmallVec<D,P>::value_type normSq(const SmallVec<D,P>& a) {
  return a.dot(a);
}
/** Compute the L2 norm of this SmallVec */
template <unsigned D, typename P>
inline typename SmallVec<D,P>::value_type norm(const SmallVec<D,P>& a) {
  return sqrt(normSq(a));
}

// ARITHMETIC

/** Unary plus: Return @a p. ("+p" should work if "-p" works.) */
template <unsigned D, typename P>
inline SmallVec<D,P> operator+(const SmallVec<D,P>& a) {
  return a;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator+(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a += b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator-(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a -= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator*(SmallVec<D,P> a, double b) {
  return a *= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator*(double b, SmallVec<D,P> a) {
  return a *= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator*(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a *= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator/(SmallVec<D,P> a, double b) {
  return a /= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator/(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a /= b;
}
<commit_msg>Read op for SmallVec<commit_after>#pragma once
/** @file Vec.hpp
 * @brief A wrapper class to provide simple vector operations for
 * primitive types and classes that only require op[].
 */

#include <iostream>
#include <type_traits>
#include <cstdarg>
#include <math.h>
#include <assert.h>

//! Predeclaration of SmallVec
template <unsigned DIM, typename DATA>
class SmallVec;

/** @class Vec
 * A general class that endows types with vector operations. If the base type
 * is a primitive type, the Vec stores information as an array of that type.
 * If the base type is not a primitive type, then it must implement the bracket
 * operator (lvalue and rvalue)
 *
 * All of the following result in nearly the same public Vec interface
 * Vec<3, double> v1;
 * Vec<3, double[3]> v2;
 * Vec<3, MyClassThatImplementsOpBracketWithDoubles> v3;
 */
template <unsigned DIM, typename DATA>
using Vec = typename std::conditional<std::is_fundamental<DATA>::value,
                                      SmallVec<DIM, DATA[DIM]>,
                                      SmallVec<DIM, DATA>>::type;

#define for_i for(unsigned i=0; i!=dimension; ++i)

/** @class SmallVec
 * @brief Class representing ND points and vectors.
 *
 * SmallVec contains methods that support use of the underlying type
 * as points in ND space. The underlying data is stored as type POINT,
 * which must only provide the operators:
 * value_type& operator[](unsigned i)
 * const value_type& operator[](unsigned i) const
 */
template <unsigned DIM, typename POINT>
class SmallVec {
  static_assert(DIM > 0, "SmallVec DIM must be greater than 0");

  POINT a;

 public:
  static constexpr unsigned dimension = DIM;
  typedef POINT point_type;
  typedef typename std::decay<decltype(a[0])>::type value_type;

  // CONSTRUCTORS

  SmallVec() {
    for_i a[i] = value_type(0);
  }
  SmallVec(const SmallVec& b) {
    for_i a[i] = b[i];
  }
  explicit SmallVec(const point_type& b) {
    for_i a[i] = b[i];
  }
  explicit SmallVec(value_type b) {
    for_i a[i] = b;
  }
  SmallVec(value_type b0, value_type b1) {
    static_assert(dimension == 2, "Calling 2-value Vec constructor for Non-2D Vec");
    a[0] = b0; a[1] = b1;
  }
  SmallVec(value_type b0, value_type b1, value_type b2) {
    static_assert(dimension == 3, "Calling 3-value Vec constructor for Non-3D Vec");
    a[0] = b0; a[1] = b1; a[2] = b2;
  }
  SmallVec(value_type b0, value_type b1, value_type b2, value_type b3) {
    static_assert(dimension == 4, "Calling 4-value Vec constructor for Non-4D Vec");
    a[0] = b0; a[1] = b1; a[2] = b2; a[3] = b3;
  }

  inline bool operator==(const SmallVec& b) const {
    for_i if (a[i] != b[i]) return false;
    return true;
  }

  // MODIFIERS

  /** Return a negated version of @a p. */
  inline SmallVec operator-() const {
    return SmallVec(-a[0], -a[1], -a[2]);
  }
  /** Scalar assignment */
  inline SmallVec& operator=(const value_type b) {
    for_i a[i] = b;
    return *this;
  }
  /** Add scalar @a b to this SmallVec */
  inline SmallVec& operator+=(const value_type b) {
    for_i a[i] += b;
    return *this;
  }
  /** Subtract scalar @a b from this SmallVec */
  inline SmallVec& operator-=(const value_type b) {
    for_i a[i] -= b;
    return *this;
  }
  /** Scale this SmallVec up by scalar @a b */
  inline SmallVec& operator*=(const value_type b) {
    for_i a[i] *= b;
    return *this;
  }
  /** Scale this SmallVec down by scalar @a b */
  inline SmallVec& operator/=(const value_type b) {
    for_i a[i] /= b;
    return *this;
  }
  /** Add SmallVec @a b to this SmallVec */
  inline SmallVec& operator+=(const SmallVec& b) {
    for_i a[i] += b[i];
    return *this;
  }
  /** Subtract SmallVec @a b from this SmallVec */
  inline SmallVec& operator-=(const SmallVec& b) {
    for_i a[i] -= b[i];
    return *this;
  }
  /** Scale this SmallVec up by factors in @a b */
  inline SmallVec& operator*=(const SmallVec& b) {
    for_i a[i] *= b[i];
    return *this;
  }
  /** Scale this SmallVec down by factors in @a b */
  inline SmallVec& operator/=(const SmallVec& b) {
    for_i a[i] /= b[i];
    return *this;
  }
  /** Compute the dot product of this SmallVec with another SmallVec */
  inline value_type dot(const SmallVec& b) const {
    value_type d(0);
    for_i d += a[i]*b[i];
    return d;
  }

  // ACCESSORS

  /** Access the @a i th (lvalue) element of this SmallVec
   * @pre i < dimension */
  inline value_type& operator[](unsigned i) {
    //assert(i < dimension);
    return a[i];
  }
  /** Access the @a i th (rvalue) element of this SmallVec
   * @pre i < dimension */
  inline const value_type& operator[](unsigned i) const {
    //assert(i < dimension);
    return a[i];
  }
  static constexpr unsigned size() {
    return dimension;
  }

  /** Compute the dot product of this SmallVec with another SmallVec */
  inline friend value_type dot(const SmallVec& a, const SmallVec& b) {
    return a.dot(b);
  }
  /** Compute cross product of two SmallVecs */
  inline friend SmallVec cross(const SmallVec& a, const SmallVec& b) {
    static_assert(SmallVec::dimension == 3, "Cross product only defined for 3D");
    SmallVec r;
    r[0] = a[1]*b[2] - a[2]*b[1];
    r[1] = -(a[0]*b[2] - a[2]*b[0]);
    r[2] = a[0]*b[1] - a[1]*b[0];
    return r;
  }
  /** Compute the squared L2 norm of this SmallVec */
  inline friend value_type normSq(const SmallVec& b) {
    return b.dot(b);
  }
  /** Compute the L2 norm of this SmallVec */
  inline friend value_type norm(const SmallVec& b) {
    return sqrt(normSq(b));
  }
  /** Write a SmallVec to an output stream */
  inline friend std::ostream& operator<<(std::ostream& s, const SmallVec& a) {
    for_i s << a[i] << " ";
    return s;
  }
  /** Read a SmallVec from an input stream */
  inline friend std::istream& operator>>(std::istream& s, const SmallVec& a) {
    for_i s >> a[i];
    return s;
  }
};

#undef for_i

// OPERATORS

/** Compute the dot product of two SmallVecs */
template <unsigned D, typename P>
inline typename SmallVec<D,P>::value_type dot(const SmallVec<D,P>& a,
                                              const SmallVec<D,P>& b) {
  return a.dot(b);
}
/** Compute the squared L2 norm of this SmallVec */
template <unsigned D, typename P>
inline typename SmallVec<D,P>::value_type normSq(const SmallVec<D,P>& a) {
  return a.dot(a);
}
/** Compute the L2 norm of this SmallVec */
template <unsigned D, typename P>
inline typename SmallVec<D,P>::value_type norm(const SmallVec<D,P>& a) {
  return sqrt(normSq(a));
}

// ARITHMETIC

/** Unary plus: Return @a p. ("+p" should work if "-p" works.) */
template <unsigned D, typename P>
inline SmallVec<D,P> operator+(const SmallVec<D,P>& a) {
  return a;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator+(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a += b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator-(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a -= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator*(SmallVec<D,P> a, double b) {
  return a *= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator*(double b, SmallVec<D,P> a) {
  return a *= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator*(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a *= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator/(SmallVec<D,P> a, double b) {
  return a /= b;
}
template <unsigned D, typename P>
inline SmallVec<D,P> operator/(SmallVec<D,P> a, const SmallVec<D,P>& b) {
  return a /= b;
}
<|endoftext|>


<commit_before>#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "snarkfront.hpp"

using namespace snarkfront;
using namespace std;

void printUsage(const char* exeName) {
    cout << "usage: " << exeName
         << " -p BN128|Edwards"
            " -b 256|512"
            " -d tree_depth"
            " -i leaf_number"
         << endl;

    exit(EXIT_FAILURE);
}

template <typename PAIRING, typename BUNDLE, typename ZK_PATH>
void runTest(const size_t treeDepth,
             const size_t leafNumber)
{
    BUNDLE bundle(treeDepth);

    while (! bundle.isFull()) {
        const typename BUNDLE::DigType leaf{bundle.treeSize()};

        bundle.addLeaf(
            leaf,
            leafNumber == bundle.treeSize());
    }

    if (leafNumber >= bundle.treeSize()) {
        cout << "leaf number " << leafNumber
             << " is larger than " << bundle.treeSize()
             << endl;

        exit(EXIT_FAILURE);
    }

    const auto& leaf = bundle.authLeaf().front();
    const auto& authPath = bundle.authPath().front();

    cout << "leaf " << leafNumber << " child bits ";
    for (int i = authPath.childBits().size() - 1; i >= 0; --i) {
        cout << authPath.childBits()[i];
    }
    cout << endl;

    cout << "root path" << endl;
    for (int i = authPath.rootPath().size() - 1; i >= 0; --i) {
        cout << "[" << i << "] "
             << asciiHex(authPath.rootPath()[i], true) << endl;
    }

    cout << "siblings" << endl;
    for (int i = authPath.siblings().size() - 1; i >= 0; --i) {
        cout << "[" << i << "] "
             << asciiHex(authPath.siblings()[i], true) << endl;
    }

    typename ZK_PATH::DigType rt;
    bless(rt, authPath.rootHash());

    end_input<PAIRING>();

    typename ZK_PATH::DigType zkLeaf;
    bless(zkLeaf, leaf);

    ZK_PATH zkAuthPath(authPath);
    zkAuthPath.updatePath(zkLeaf);

    assert_true(rt == zkAuthPath.rootHash());

    cout << "variable count " << variable_count<PAIRING>() << endl;
}

template <typename PAIRING>
bool runTest(const string& shaBits,
             const size_t treeDepth,
             const size_t leafNumber)
{
    typedef typename PAIRING::Fr FR;

    if (nameSHA256(shaBits)) {
        runTest<PAIRING,
                MerkleBundle_SHA256<uint32_t>, // count could be size_t
                zk::MerkleAuthPath_SHA256<FR>>(
            treeDepth,
            leafNumber);

    } else if (nameSHA512(shaBits)) {
        runTest<PAIRING,
                MerkleBundle_SHA512<uint64_t>, // count could be size_t
                zk::MerkleAuthPath_SHA512<FR>>(
            treeDepth,
            leafNumber);
    }

    GenericProgressBar progress1(cerr), progress2(cerr, 100);

    cerr << "generate key pair";
    const auto key = keypair<PAIRING>(progress2);
    cerr << endl;

    const auto in = input<PAIRING>();

    cerr << "generate proof";
    const auto p = proof(key, progress2);
    cerr << endl;

    cerr << "verify proof ";
    const bool proofOK = verify(key, in, p, progress1);
    cerr << endl;

    return proofOK;
}

int main(int argc, char *argv[])
{
    Getopt cmdLine(argc, argv, "pb", "di", "");
    if (!cmdLine || cmdLine.empty()) printUsage(argv[0]);

    const auto
        pairing = cmdLine.getString('p'),
        shaBits = cmdLine.getString('b');

    const auto
        treeDepth = cmdLine.getNumber('d'),
        leafNumber = cmdLine.getNumber('i');

    if (!validPairingName(pairing) ||
        !(nameSHA256(shaBits) || nameSHA512(shaBits)) ||
        -1 == treeDepth ||
        -1 == leafNumber)
        printUsage(argv[0]);

    bool result;

    if (pairingBN128(pairing)) {
        // Barreto-Naehrig 128 bits
        init_BN128();
        result = runTest<BN128_PAIRING>(shaBits, treeDepth, leafNumber);

    } else if (pairingEdwards(pairing)) {
        // Edwards 80 bits
        init_Edwards();
        result = runTest<EDWARDS_PAIRING>(shaBits, treeDepth, leafNumber);
    }

    cout << "proof verification " << (result ? "OK" : "FAIL") << endl;

    exit(EXIT_SUCCESS);
}
<commit_msg>50 wide progress bar<commit_after>#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "snarkfront.hpp"

using namespace snarkfront;
using namespace std;

void printUsage(const char* exeName) {
    cout << "usage: " << exeName
         << " -p BN128|Edwards"
            " -b 256|512"
            " -d tree_depth"
            " -i leaf_number"
         << endl;

    exit(EXIT_FAILURE);
}

template <typename PAIRING, typename BUNDLE, typename ZK_PATH>
void runTest(const size_t treeDepth,
             const size_t leafNumber)
{
    BUNDLE bundle(treeDepth);

    while (! bundle.isFull()) {
        const typename BUNDLE::DigType leaf{bundle.treeSize()};

        bundle.addLeaf(
            leaf,
            leafNumber == bundle.treeSize());
    }

    if (leafNumber >= bundle.treeSize()) {
        cout << "leaf number " << leafNumber
             << " is larger than " << bundle.treeSize()
             << endl;

        exit(EXIT_FAILURE);
    }

    const auto& leaf = bundle.authLeaf().front();
    const auto& authPath = bundle.authPath().front();

    cout << "leaf " << leafNumber << " child bits ";
    for (int i = authPath.childBits().size() - 1; i >= 0; --i) {
        cout << authPath.childBits()[i];
    }
    cout << endl;

    cout << "root path" << endl;
    for (int i = authPath.rootPath().size() - 1; i >= 0; --i) {
        cout << "[" << i << "] "
             << asciiHex(authPath.rootPath()[i], true) << endl;
    }

    cout << "siblings" << endl;
    for (int i = authPath.siblings().size() - 1; i >= 0; --i) {
        cout << "[" << i << "] "
             << asciiHex(authPath.siblings()[i], true) << endl;
    }

    typename ZK_PATH::DigType rt;
    bless(rt, authPath.rootHash());

    end_input<PAIRING>();

    typename ZK_PATH::DigType zkLeaf;
    bless(zkLeaf, leaf);

    ZK_PATH zkAuthPath(authPath);
    zkAuthPath.updatePath(zkLeaf);

    assert_true(rt == zkAuthPath.rootHash());

    cout << "variable count " << variable_count<PAIRING>() << endl;
}

template <typename PAIRING>
bool runTest(const string& shaBits,
             const size_t treeDepth,
             const size_t leafNumber)
{
    typedef typename PAIRING::Fr FR;

    if (nameSHA256(shaBits)) {
        runTest<PAIRING,
                MerkleBundle_SHA256<uint32_t>, // count could be size_t
                zk::MerkleAuthPath_SHA256<FR>>(
            treeDepth,
            leafNumber);

    } else if (nameSHA512(shaBits)) {
        runTest<PAIRING,
                MerkleBundle_SHA512<uint64_t>, // count could be size_t
                zk::MerkleAuthPath_SHA512<FR>>(
            treeDepth,
            leafNumber);
    }

    GenericProgressBar progress1(cerr), progress2(cerr, 50);

    cerr << "generate key pair";
    const auto key = keypair<PAIRING>(progress2);
    cerr << endl;

    const auto in = input<PAIRING>();

    cerr << "generate proof";
    const auto p = proof(key, progress2);
    cerr << endl;

    cerr << "verify proof ";
    const bool proofOK = verify(key, in, p, progress1);
    cerr << endl;

    return proofOK;
}

int main(int argc, char *argv[])
{
    Getopt cmdLine(argc, argv, "pb", "di", "");
    if (!cmdLine || cmdLine.empty()) printUsage(argv[0]);

    const auto
        pairing = cmdLine.getString('p'),
        shaBits = cmdLine.getString('b');

    const auto
        treeDepth = cmdLine.getNumber('d'),
        leafNumber = cmdLine.getNumber('i');

    if (!validPairingName(pairing) ||
        !(nameSHA256(shaBits) || nameSHA512(shaBits)) ||
        -1 == treeDepth ||
        -1 == leafNumber)
        printUsage(argv[0]);

    bool result;

    if (pairingBN128(pairing)) {
        // Barreto-Naehrig 128 bits
        init_BN128();
        result = runTest<BN128_PAIRING>(shaBits, treeDepth, leafNumber);

    } else if (pairingEdwards(pairing)) {
        // Edwards 80 bits
        init_Edwards();
        result = runTest<EDWARDS_PAIRING>(shaBits, treeDepth, leafNumber);
    }

    cout << "proof verification " << (result ? "OK" : "FAIL") << endl;

    exit(EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>/****************************************************************************
 **
 ** Copyright (C) Qxt Foundation. Some rights reserved.
 **
 ** This file is part of the QxtCore module of the Qxt library.
 **
 ** This library is free software; you can redistribute it and/or modify it
 ** under the terms of the Common Public License, version 1.0, as published
 ** by IBM, and/or under the terms of the GNU Lesser General Public License,
 ** version 2.1, as published by the Free Software Foundation.
 **
 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
 ** FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** You should have received a copy of the CPL and the LGPL along with this
 ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
 ** included with the source distribution for more information.
 ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
 **
 ** <http://libqxt.org>  <foundation@libqxt.org>
 **
 ****************************************************************************/
#include "qxtslotmapper.h"
#include "qxtmetaobject.h"
#include <QMetaMethod>
#include <QPointer>
#include <QVariant>

/*!
    \class QxtSlotMapper
    \inmodule QxtCore
    \brief The QxtSlotMapper class maps signals with a specific parameter value to certain slots.

    QxtSlotMapper is the counterpart of QSignalMapper. Where QSignalMapper maps
    a parameterless signal into one that has a parameter based on the sender,
    QxtSlotMapper maps a signal with a parameter to a specified slot and
    receiver based on that parameters value. Different slots on potentially
    different receivers can be invoked by the same signal with just different
    value for their parameter.

    The parameter comparison is based on QVariant::operator==(). Thus, any
    built-in Qt type supported by QVariant and QMetaType is supported.

    \sa QVariant, QMetaType::Type

    \image qxtslotmapper.png

    Example usage:
    \code
    QxtSlotMapper mapper;
    mapper.connect(sender, SIGNAL(signal1(int)));
    mapper.connect(sender, SIGNAL(signal2(QString)));

    mapper.addMapping(3, receiver1, SLOT(slot1(int)));
    mapper.addMapping(QString("abc"), receiver2, SLOT(slot2(QString)));
    \endcode

    \sa QSignalMapper
*/

struct QxtSlotMapInfo
{
    QVariant parameter;
    QPointer<QObject> receiver;
    const char* member;
};

class QxtSlotMapperPrivate : public QxtPrivate<QxtSlotMapper>
{
public:
    static int checkSignal(const QObject* sender, const char* signal);

    QList<QxtSlotMapInfo> mappings;
};

int QxtSlotMapperPrivate::checkSignal(const QObject* sender, const char* signal)
{
    if (!sender || !signal)
    {
        qWarning("QxtSlotMapper: Cannot connect %s::%s",
            sender ? sender->metaObject()->className() : "(null)",
            (signal && *signal) ? signal+1 : "(null)");
        return false;
    }

    const QByteArray signalName = QMetaObject::normalizedSignature(signal+1);
    int signalId = sender->metaObject()->indexOfSignal(signalName);
    if (signalId < 0)
    {
        qWarning("QxtSlotMapper: No such signal %s::%s",
            sender->metaObject()->className(), signal+1);
        return false;
    }
    return signalId;
}

/*!
    Constructs a new QxtSlotMapper with \a parent.
*/
QxtSlotMapper::QxtSlotMapper(QObject* parent)
    : QObject(parent)
{
}

/*!
    Destructs the slot mapper.
*/
QxtSlotMapper::~QxtSlotMapper()
{
}

/*!
    Adds mapping from connected signals with \a parameter to \a receiver's \a member.
*/
void QxtSlotMapper::addMapping(const QVariant& parameter, QObject* receiver, const char* member)
{
    QxtSlotMapInfo mapping = { parameter, receiver, member };
    qxt_d().mappings.append(mapping);
}

/*!
    Removes mapping from connected signals with \a parameter to \a receiver's \a member.

    If \a member is \c 0, any mapping with \a parameter to \a receiver is removed.
    If \a receiver is \c 0, any mapping with \a parameter is removed.
*/
void QxtSlotMapper::removeMapping(const QVariant& parameter, QObject* receiver, const char* member)
{
    QMutableListIterator<QxtSlotMapInfo> it(qxt_d().mappings);
    while (it.hasNext())
    {
        const QxtSlotMapInfo& info = it.next();
        if (info.parameter == parameter)
        {
            if ((!receiver || receiver == info.receiver) &&
                (!member || QxtMetaObject::methodName(member) == QxtMetaObject::methodName(info.member)))
            {
                it.remove();
            }
        }
    }
}

/*!
    Connects to \a sender's \a signal. Returns \c true if the connection
    succeeds and \c false otherwise.
*/
bool QxtSlotMapper::connect(const QObject* sender, const char* signal)
{
    QByteArray signalName = QMetaObject::normalizedSignature(signal);
    int signalId = QxtSlotMapperPrivate::checkSignal(sender, signal);
    if (signalId < 0)
        return false;

    int index = signalName.indexOf('(');
    if (index != -1)
    {
        QByteArray typeName = signalName.mid(index + 1);
        int index = typeName.indexOf(')');
        if (index != -1)
            typeName.truncate(index);
        typeName = QMetaObject::normalizedType(typeName);

        int type = QMetaType::type(typeName);
        int methods = metaObject()->methodCount();
        return QMetaObject::connect(sender, signalId, this, methods + type);
    }
    return false;
}

/*!
    \internal
 */
int QxtSlotMapper::qt_metacall(QMetaObject::Call call, int id, void** arguments)
{
    id = QObject::qt_metacall(call, id, arguments);
    if (id < 0 || call != QMetaObject::InvokeMetaMethod)
        return id;

    QVariant param(id, arguments[1]);
    foreach (const QxtSlotMapInfo& info, qxt_d().mappings)
    {
        if (info.receiver && info.parameter == param)
        {
            const QMetaObject* metaObject = info.receiver->metaObject();
            int index = metaObject->indexOfMethod(QxtMetaObject::methodSignature(info.member));
            if (index != -1)
            {
                QMetaMethod method = metaObject->method(index);
                switch (method.parameterTypes().count())
                {
                    case 0:
                        QMetaObject::invokeMethod(info.receiver,
                                                QxtMetaObject::methodName(info.member));
                        break;
                    case 1:
                        QMetaObject::invokeMethod(info.receiver,
                                                QxtMetaObject::methodName(info.member),
                                                QGenericArgument(QMetaType::typeName(param.type()), arguments[1]));
                        break;
                    default:
                        qWarning("QxtSlotMapper does not support slots with more than one parameter");
                        break;
                }
            }
        }
    }
    return -1;
}
<commit_msg>Gramatical improvemenst as suggested by ahigerd on IRC.<commit_after>/****************************************************************************
 **
 ** Copyright (C) Qxt Foundation. Some rights reserved.
 **
 ** This file is part of the QxtCore module of the Qxt library.
 **
 ** This library is free software; you can redistribute it and/or modify it
 ** under the terms of the Common Public License, version 1.0, as published
 ** by IBM, and/or under the terms of the GNU Lesser General Public License,
 ** version 2.1, as published by the Free Software Foundation.
 **
 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
 ** FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** You should have received a copy of the CPL and the LGPL along with this
 ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
 ** included with the source distribution for more information.
 ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
 **
 ** <http://libqxt.org>  <foundation@libqxt.org>
 **
 ****************************************************************************/
#include "qxtslotmapper.h"
#include "qxtmetaobject.h"
#include <QMetaMethod>
#include <QPointer>
#include <QVariant>

/*!
    \class QxtSlotMapper
    \inmodule QxtCore
    \brief The QxtSlotMapper class maps signals with a specific parameter value to certain slots.

    QxtSlotMapper is the counterpart of QSignalMapper. Where QSignalMapper maps
    a parameterless signal into one that has a parameter based on the sender,
    QxtSlotMapper maps a signal with a parameter to a specified slot and
    receiver based on that parameter's value. Different slots on potentially
    different receivers can be invoked by the same signal, according to that
    parameter.

    The parameter comparison is based on QVariant::operator==(). Thus, any
    built-in Qt type supported by QVariant and QMetaType is supported.

    \sa QVariant, QMetaType::Type

    \image qxtslotmapper.png

    Example usage:
    \code
    QxtSlotMapper mapper;
    mapper.connect(sender, SIGNAL(signal1(int)));
    mapper.connect(sender, SIGNAL(signal2(QString)));

    mapper.addMapping(3, receiver1, SLOT(slot1(int)));
    mapper.addMapping(QString("abc"), receiver2, SLOT(slot2(QString)));
    \endcode

    \sa QSignalMapper
*/

struct QxtSlotMapInfo
{
    QVariant parameter;
    QPointer<QObject> receiver;
    const char* member;
};

class QxtSlotMapperPrivate : public QxtPrivate<QxtSlotMapper>
{
public:
    static int checkSignal(const QObject* sender, const char* signal);

    QList<QxtSlotMapInfo> mappings;
};

int QxtSlotMapperPrivate::checkSignal(const QObject* sender, const char* signal)
{
    if (!sender || !signal)
    {
        qWarning("QxtSlotMapper: Cannot connect %s::%s",
            sender ? sender->metaObject()->className() : "(null)",
            (signal && *signal) ? signal+1 : "(null)");
        return false;
    }

    const QByteArray signalName = QMetaObject::normalizedSignature(signal+1);
    int signalId = sender->metaObject()->indexOfSignal(signalName);
    if (signalId < 0)
    {
        qWarning("QxtSlotMapper: No such signal %s::%s",
            sender->metaObject()->className(), signal+1);
        return false;
    }
    return signalId;
}

/*!
    Constructs a new QxtSlotMapper with \a parent.
*/
QxtSlotMapper::QxtSlotMapper(QObject* parent)
    : QObject(parent)
{
}

/*!
    Destructs the slot mapper.
*/
QxtSlotMapper::~QxtSlotMapper()
{
}

/*!
    Adds mapping from connected signals with \a parameter to \a receiver's \a member.
*/
void QxtSlotMapper::addMapping(const QVariant& parameter, QObject* receiver, const char* member)
{
    QxtSlotMapInfo mapping = { parameter, receiver, member };
    qxt_d().mappings.append(mapping);
}

/*!
    Removes mapping from connected signals with \a parameter to \a receiver's \a member.

    If \a member is \c 0, any mapping with \a parameter to \a receiver is removed.
    If \a receiver is \c 0, any mapping with \a parameter is removed.
*/
void QxtSlotMapper::removeMapping(const QVariant& parameter, QObject* receiver, const char* member)
{
    QMutableListIterator<QxtSlotMapInfo> it(qxt_d().mappings);
    while (it.hasNext())
    {
        const QxtSlotMapInfo& info = it.next();
        if (info.parameter == parameter)
        {
            if ((!receiver || receiver == info.receiver) &&
                (!member || QxtMetaObject::methodName(member) == QxtMetaObject::methodName(info.member)))
            {
                it.remove();
            }
        }
    }
}

/*!
    Connects to \a sender's \a signal. Returns \c true if the connection
    succeeds and \c false otherwise.
*/
bool QxtSlotMapper::connect(const QObject* sender, const char* signal)
{
    QByteArray signalName = QMetaObject::normalizedSignature(signal);
    int signalId = QxtSlotMapperPrivate::checkSignal(sender, signal);
    if (signalId < 0)
        return false;

    int index = signalName.indexOf('(');
    if (index != -1)
    {
        QByteArray typeName = signalName.mid(index + 1);
        int index = typeName.indexOf(')');
        if (index != -1)
            typeName.truncate(index);
        typeName = QMetaObject::normalizedType(typeName);

        int type = QMetaType::type(typeName);
        int methods = metaObject()->methodCount();
        return QMetaObject::connect(sender, signalId, this, methods + type);
    }
    return false;
}

/*!
    \internal
 */
int QxtSlotMapper::qt_metacall(QMetaObject::Call call, int id, void** arguments)
{
    id = QObject::qt_metacall(call, id, arguments);
    if (id < 0 || call != QMetaObject::InvokeMetaMethod)
        return id;

    QVariant param(id, arguments[1]);
    foreach (const QxtSlotMapInfo& info, qxt_d().mappings)
    {
        if (info.receiver && info.parameter == param)
        {
            const QMetaObject* metaObject = info.receiver->metaObject();
            int index = metaObject->indexOfMethod(QxtMetaObject::methodSignature(info.member));
            if (index != -1)
            {
                QMetaMethod method = metaObject->method(index);
                switch (method.parameterTypes().count())
                {
                    case 0:
                        QMetaObject::invokeMethod(info.receiver,
                                                QxtMetaObject::methodName(info.member));
                        break;
                    case 1:
                        QMetaObject::invokeMethod(info.receiver,
                                                QxtMetaObject::methodName(info.member),
                                                QGenericArgument(QMetaType::typeName(param.type()), arguments[1]));
                        break;
                    default:
                        qWarning("QxtSlotMapper does not support slots with more than one parameter");
                        break;
                }
            }
        }
    }
    return -1;
}
<|endoftext|>


<commit_before>#include "testconsole.h"

TestConsole::TestConsole(const char * name_p):
    next_status_line(0),
    sb_needs_update(true),
    term(),
    name(name_p),
    num_pages(0),
    current_page(0)
{
 //     term.baud(baud_rate);
 //     term.printf("TestConsole::TestConsole('%')\r\n",name);
    term.HideCursor();
    for(int i = 0; i < MAX_PAGES; i++) {
        page[i] = NULL;   //init all pages to NULL
        previous_page[i] = i;
    }
    active_page = page[current_page];

    for(int i = 0; i < NUM_STATUS_LINES; i++) {
         //fill the buffer will null terminated spaces
        memset(sb_buffer[i], ' ',SZ_SB_BUF);
        sb_buffer[i][SZ_SB_BUF-1] = '\0';  //terminate string
    }
}

//Page& TestConsole::add_page(Page const &page_p){
Page* TestConsole::add_page(const char * name_p){
    if(num_pages >=  MAX_PAGES)
    {
        term.printf("MAX_PAGES Exceeded adding'%s'\r\n", name_p);
        return NULL;  //return valid reference to home page on

    }

        page[num_pages] = new Page(name_p, &term);
        Page* this_page = page[num_pages];
        this_page->page_num = num_pages;   //let the page know what number it is to help with lookups

                if(num_pages == 0) {   //if this is the first page, set it active
                    this_page->set_active();
                }
        //term.printf("Added page '%s'\r\n", this_page->name);
        num_pages++;
        return this_page;

    }

uint8_t TestConsole::page_change(uint8_t new_page){
            if(NULL == page[current_page]) {
                term.printf("invalid page passed to page_chage\r\n");
                return current_page;
                }
            //save a copy of the page so we can go back, but only up the tree
            if(previous_page[current_page] != new_page) previous_page[new_page] = current_page;
            current_page = new_page;
            active_page = page[current_page];

            active_page->display();

            active_page->ack_active();

            term.locate((TERMINAL_WIDTH - strlen(name))/2, 0);
            term.printf("%s", name);

            return current_page;
    }

//here, using knowledge of the page, we process commands
uint8_t TestConsole::process_cmd(char cmd){
    if('x' == cmd) {
        page_change(previous_page[current_page]);
        return 0;
    }

    if('\r' == cmd) {   //refresh the page on enter
        active_page->set_active();
        }

    for(int index=0; index < active_page->num_menuitems; index++) {
        MenuItem const & item = active_page->get_menu_item(index);
        if(active_page->get_command_letter(index) != cmd) continue;

        if(item.type == menu) {
            // for menuitems that goto other menus, just change the page
            page_change(item.target_page);
        } else if(item.action) {
            // otherwise call the callaback
            item.action->doAction();
        }
        return 0;
    }

    return 1;
}

uint8_t TestConsole::tick(void){
    if (Serial.available()){   //if there is a character
          if(process_cmd(Serial.read())){
                term.locate(TERM_LOC_FEEDBACK);
                term.printf("invalid command");
            }
        }

        //go through the list of pages, and see if any are set to become active
        for(uint8_t index=0; index < num_pages; index++){
            if(page[index]->check_active()){
                 page_change(index);
                 sb_needs_update = true;
                }
        }

        if(active_page != NULL)
        {
            active_page->update();
        } else
        {
                term.printf("invalid page %p", active_page);
        }

        if(sb_needs_update) update_status_bar();
    return 0;
    }

void TestConsole::update_status_bar(){
    for(uint8_t i = 0; i < NUM_STATUS_LINES; i++){
    term.locate(0,TERMINAL_HEIGHT-NUM_STATUS_LINES+i);
    Serial.print(sb_buffer[(next_status_line+1+i)%NUM_STATUS_LINES]);
    term.clear_to_eol();
    }
}
void TestConsole::status_bar(const char* format, ...)
{
    char buffer[SZ_SB_BUF];

    va_list argptr;
    va_start(argptr, format);
    vsnprintf(buffer, sizeof(buffer), format, argptr);
    va_end(argptr);

    status_bar_addnext(buffer);
}

void TestConsole::status_bar(const __FlashStringHelper* format)
{
    String str(format);
    status_bar_addnext(str.c_str());
}

void TestConsole::status_bar(String const & str)
{
    status_bar_addnext(str);
}

void TestConsole::status_bar_addnext(char const * tmpbuf)
{
    //only buffer and increment if the message is different from the last
    if(0 != strncmp(tmpbuf, sb_buffer[next_status_line], sizeof(sb_buffer[0]))) {
        increment_status_line();
        strncpy(sb_buffer[next_status_line], tmpbuf, sizeof(sb_buffer[0]));
        sb_needs_update = true;
    }
}
<commit_msg>test_console: init previous_pages to zero, don't allow setting to self<commit_after>#include "testconsole.h"

TestConsole::TestConsole(const char * name_p):
    next_status_line(0),
    sb_needs_update(true),
    term(),
    name(name_p),
    num_pages(0),
    current_page(0)
{
 //     term.baud(baud_rate);
 //     term.printf("TestConsole::TestConsole('%')\r\n",name);
    term.HideCursor();
    for(int i = 0; i < MAX_PAGES; i++) {
        page[i] = NULL;   //init all pages to NULL
        previous_page[i] = 0;  //if never changed, return from each page will go home
    }
    active_page = page[current_page];

    for(int i = 0; i < NUM_STATUS_LINES; i++) {
         //fill the buffer will null terminated spaces
        memset(sb_buffer[i], ' ',SZ_SB_BUF);
        sb_buffer[i][SZ_SB_BUF-1] = '\0';  //terminate string
    }
}

//Page& TestConsole::add_page(Page const &page_p){
Page* TestConsole::add_page(const char * name_p){
    if(num_pages >=  MAX_PAGES)
    {
        term.printf("MAX_PAGES Exceeded adding'%s'\r\n", name_p);
        return NULL;  //return valid reference to home page on

    }

        page[num_pages] = new Page(name_p, &term);
        Page* this_page = page[num_pages];
        this_page->page_num = num_pages;   //let the page know what number it is to help with lookups

                if(num_pages == 0) {   //if this is the first page, set it active
                    this_page->set_active();
                }
        //term.printf("Added page '%s'\r\n", this_page->name);
        num_pages++;
        return this_page;

    }

uint8_t TestConsole::page_change(uint8_t new_page){
            if(NULL == page[current_page]) {
                term.printf("invalid page passed to page_chage\r\n");
                return current_page;
                }

            //save a copy of the page so we can go back, but only up the tree
            if((new_page != current_page) &&
               (previous_page[current_page] != new_page)) {
                   previous_page[new_page] = current_page;
               }
            current_page = new_page;
            active_page = page[current_page];

            active_page->display();

            active_page->ack_active();

            term.locate((TERMINAL_WIDTH - strlen(name))/2, 0);
            term.printf("%s", name);

            return current_page;
    }

//here, using knowledge of the page, we process commands
uint8_t TestConsole::process_cmd(char cmd){
    if('x' == cmd) {
        page_change(previous_page[current_page]);
        return 0;
    }

    if('\r' == cmd) {   //refresh the page on enter
        active_page->set_active();
        }

    for(int index=0; index < active_page->num_menuitems; index++) {
        MenuItem const & item = active_page->get_menu_item(index);
        if(active_page->get_command_letter(index) != cmd) continue;

        if(item.type == menu) {
            // for menuitems that goto other menus, just change the page
            page_change(item.target_page);
        } else if(item.action) {
            // otherwise call the callaback
            item.action->doAction();
        }
        return 0;
    }

    return 1;
}

uint8_t TestConsole::tick(void){
    if (Serial.available()){   //if there is a character
          if(process_cmd(Serial.read())){
                term.locate(TERM_LOC_FEEDBACK);
                term.printf("invalid command");
            }
        }

        //go through the list of pages, and see if any are set to become active
        for(uint8_t index=0; index < num_pages; index++){
            if(page[index]->check_active()){
                 page_change(index);
                 sb_needs_update = true;
                }
        }

        if(active_page != NULL)
        {
            active_page->update();
        } else
        {
                term.printf("invalid page %p", active_page);
        }

        if(sb_needs_update) update_status_bar();
    return 0;
    }

void TestConsole::update_status_bar(){
    for(uint8_t i = 0; i < NUM_STATUS_LINES; i++){
    term.locate(0,TERMINAL_HEIGHT-NUM_STATUS_LINES+i);
    Serial.print(sb_buffer[(next_status_line+1+i)%NUM_STATUS_LINES]);
    term.clear_to_eol();
    }
}
void TestConsole::status_bar(const char* format, ...)
{
    char buffer[SZ_SB_BUF];

    va_list argptr;
    va_start(argptr, format);
    vsnprintf(buffer, sizeof(buffer), format, argptr);
    va_end(argptr);

    status_bar_addnext(buffer);
}

void TestConsole::status_bar(const __FlashStringHelper* format)
{
    String str(format);
    status_bar_addnext(str.c_str());
}

void TestConsole::status_bar(String const & str)
{
    status_bar_addnext(str);
}

void TestConsole::status_bar_addnext(char const * tmpbuf)
{
    //only buffer and increment if the message is different from the last
    if(0 != strncmp(tmpbuf, sb_buffer[next_status_line], sizeof(sb_buffer[0]))) {
        increment_status_line();
        strncpy(sb_buffer[next_status_line], tmpbuf, sizeof(sb_buffer[0]));
        sb_needs_update = true;
    }
}
<|endoftext|>