<commit_before>#include <cstddef>
#include <ostream>
#include <insertionfinder/algorithm.hpp>
#include <insertionfinder/insertion.hpp>
#include <insertionfinder/termcolor.hpp>
using std::size_t;
using InsertionFinder::Algorithm;
using InsertionFinder::Insertion;

std::ostream& operator<<(std::ostream& out, const Insertion& insertion) {
    insertion.print(out);
    return out;
}

void Insertion::print(std::ostream& out) const {
    const Algorithm& skeleton = this->skeleton;
    size_t insert_place = this->insert_place;
    if (insert_place > 0) {
        skeleton.print(out, 0, insert_place);
        out << ' ';
    }
    out << termcolor::green << "[@]" << termcolor::reset;
    if (insert_place < skeleton.length()) {
        out << ' ';
        skeleton.print(out, insert_place, skeleton.length());
    }
    out << std::endl
        << termcolor::bold << "Insert at @: " << termcolor::reset
        << termcolor::green << *this->insertion << termcolor::reset;
}

void Insertion::print(std::ostream& out, size_t index) const {
    const Algorithm& skeleton = this->skeleton;
    size_t insert_place = this->insert_place;
    if (insert_place > 0) {
        skeleton.print(out, 0, insert_place);
        out << ' ';
    }
    out << termcolor::green << "[@" << index + 1 << ']' << termcolor::reset;
    if (insert_place < skeleton.length()) {
        out << ' ';
        skeleton.print(out, insert_place, skeleton.length());
    }
    out << std::endl
        << termcolor::bold << "Insert at @" << index + 1 << ": " << termcolor::reset
        << termcolor::green << *this->insertion << termcolor::reset;
}
<commit_msg>show cancelled moves in each insertion<commit_after>#include <cstddef>
#include <ostream>
#include <insertionfinder/algorithm.hpp>
#include <insertionfinder/insertion.hpp>
#include <insertionfinder/termcolor.hpp>
using std::size_t;
using InsertionFinder::Algorithm;
using InsertionFinder::Insertion;

std::ostream& operator<<(std::ostream& out, const Insertion& insertion) {
    insertion.print(out);
    return out;
}

void Insertion::print(std::ostream& out) const {
    Algorithm result = this->skeleton.insert(*this->insertion, this->insert_place).first;
    size_t insert_place = this->insert_place;
    if (insert_place > 0) {
        this->skeleton.print(out, 0, insert_place);
        out << ' ';
    }
    out << termcolor::green << "[@]" << termcolor::reset;
    if (insert_place < this->skeleton.length()) {
        out << ' ';
        this->skeleton.print(out, insert_place, this->skeleton.length());
    }
    out << std::endl
        << termcolor::bold << "Insert at @: " << termcolor::reset
        << termcolor::green << *this->insertion << termcolor::reset
        << termcolor::italic << " (+" << this->insertion->length() << " -"
        << this->skeleton.length() + this->insertion->length() - result.length() << ')' << termcolor::reset;
}

void Insertion::print(std::ostream& out, size_t index) const {
    Algorithm result = this->skeleton.insert(*this->insertion, this->insert_place).first;
    size_t insert_place = this->insert_place;
    if (insert_place > 0) {
        this->skeleton.print(out, 0, insert_place);
        out << ' ';
    }
    out << termcolor::green << "[@" << index + 1 << ']' << termcolor::reset;
    if (insert_place < this->skeleton.length()) {
        out << ' ';
        this->skeleton.print(out, insert_place, this->skeleton.length());
    }
    out << std::endl
        << termcolor::bold << "Insert at @" << index + 1 << ": " << termcolor::reset
        << termcolor::green << *this->insertion << termcolor::reset
        << termcolor::italic << " (+" << this->insertion->length() << " -"
        << this->skeleton.length() + this->insertion->length() - result.length() << ')' << termcolor::reset;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: wizard.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-10-06 10:40:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _WIZARD_HXX_
#define _WIZARD_HXX_

#include <rtl/ustring.hxx>
#include <svtools/roadmapwizard.hxx>
#include <vcl/window.hxx>
#include <tools/resid.hxx>

namespace desktop
{

class WizardResId : public ResId
{
public:
    WizardResId( USHORT nId );
};

class FirstStartWizard : public svt::RoadmapWizard
{

public:
    static const WizardState STATE_WELCOME;
    static const WizardState STATE_LICENSE;
    static const WizardState STATE_MIGRATION;
    static const WizardState STATE_USER;
    static const WizardState STATE_UPDATE_CHECK;
    static const WizardState STATE_REGISTRATION;

    static ResMgr* pResMgr;
    static ResMgr* GetResManager();

    FirstStartWizard(Window* pParent);

    virtual short Execute();
    virtual long PreNotify( NotifyEvent& rNEvt );

    static rtl::OUString getLicensePath();

    void overrideCheck(sal_Bool bOverride);

private:
    sal_Bool m_bOverride;
    WizardState _currentState;
    PathId m_aDefaultPath;
    PathId m_aMigrationPath;
    String m_sNext;
    String m_sCancel;
    sal_Bool m_bDone;
    sal_Bool m_bAccepted;
    sal_Bool m_bAutomaticUpdChk;
    Link m_lnkCancel;

    void storeAcceptDate();
    void disableWizard();
    void enableQuickstart();

    DECL_LINK(DeclineHdl, PushButton*);

    void cleanOldOfficeRegKeys();
    sal_Bool showOnlineUpdatePage();

public:
    static sal_Bool isFirstStart();
    static sal_Bool isLicenseAccepted();

protected:
    // from svt::WizardMachine
    virtual TabPage* createPage(WizardState _nState);
    virtual sal_Bool prepareLeaveCurrentState( CommitPageReason _eReason );
    virtual sal_Bool leaveState(WizardState _nState );
    virtual sal_Bool onFinish(sal_Int32 _nResult);
    virtual void     enterState(WizardState _nState);

    // from svt::RoadmapWizard
    virtual String       getStateDisplayName( WizardState _nState );
};
}
#endif
<commit_msg>INTEGRATION: CWS c09tosrc (1.7.178); FILE MERGED 2007/06/20 09:24:09 as 1.7.178.1: #144874# megre changes also into the master<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: wizard.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-06 12:37:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _WIZARD_HXX_
#define _WIZARD_HXX_

#include <rtl/ustring.hxx>
#include <svtools/roadmapwizard.hxx>
#include <vcl/window.hxx>
#include <tools/resid.hxx>

namespace desktop
{

class WizardResId : public ResId
{
public:
    WizardResId( USHORT nId );
};

class FirstStartWizard : public svt::RoadmapWizard
{

public:
    static const WizardState STATE_WELCOME;
    static const WizardState STATE_LICENSE;
    static const WizardState STATE_MIGRATION;
    static const WizardState STATE_USER;
    static const WizardState STATE_UPDATE_CHECK;
    static const WizardState STATE_REGISTRATION;

    static ResMgr* pResMgr;
    static ResMgr* GetResManager();

    FirstStartWizard(Window* pParent);

    virtual short Execute();
    virtual long PreNotify( NotifyEvent& rNEvt );

    static rtl::OUString getLicensePath();

    void overrideCheck(sal_Bool bOverride);

private:
    sal_Bool m_bOverride;
    WizardState _currentState;
    ::svt::RoadmapWizardTypes::PathId m_aDefaultPath;
    ::svt::RoadmapWizardTypes::PathId m_aMigrationPath;
    String m_sNext;
    String m_sCancel;
    sal_Bool m_bDone;
    sal_Bool m_bLicenseNeedsAcceptence;
    sal_Bool m_bLicenseWasAccepted;
    sal_Bool m_bAutomaticUpdChk;
    Link m_lnkCancel;

    void storeAcceptDate();
    void disableWizard();
    void enableQuickstart();

    DECL_LINK(DeclineHdl, PushButton*);

    void cleanOldOfficeRegKeys();
    sal_Bool showOnlineUpdatePage();
    ::svt::RoadmapWizardTypes::PathId defineWizardPagesDependingFromContext();

public:
    static sal_Bool isWizardNeeded();
    static sal_Bool needsLicenseAcceptence();

private:
    static sal_Bool impl_isFirstStart();
    static sal_Bool impl_isLicenseAccepted();

protected:
    // from svt::WizardMachine
    virtual TabPage* createPage(WizardState _nState);
    virtual sal_Bool prepareLeaveCurrentState( CommitPageReason _eReason );
    virtual sal_Bool leaveState(WizardState _nState );
    virtual sal_Bool onFinish(sal_Int32 _nResult);
    virtual void     enterState(WizardState _nState);

    // from svt::RoadmapWizard
    virtual String       getStateDisplayName( WizardState _nState );
};
}
#endif
<|endoftext|>


<commit_before>/* Copyright (c) 2013 Fabian Schuiki */
#pragma once
#include "math.hpp"
#include "integer.hpp"
#define GAMMA_HAS_FIXED_POINT

namespace gamma {

#define recast(bits,thing) ((typename integer::signed_integer<bits>::type)(thing))

/** Class for signed fixed-point arithmetics. */
template<int Ia, int Da> struct fixed_point
{
	typedef fixed_point<Ia,Da> self;

	const static int integral_bits = Ia;
	const static int decimal_bits = Da;
	const static int bits = integral_bits + decimal_bits;

	typedef typename integer::signed_integer<bits>::type value_type;
	#define expand_bits(b, thing) ((si(bits + b))(thing))
	#define expand_bytes(b, thing) expand_bits(b*8, thing)

	const static value_type factor = 1 << (value_type)decimal_bits;
	const static value_type decimal_mask = factor - 1;

	value_type v;

	fixed_point() {}
	fixed_point(const self& f) : v(f.v) {}
	template<typename R> explicit fixed_point(R r, int db = 0) : v(recast(sizeof(r)*8+Da, r) * factor / (1 << (int64_t)db)) {}
	template<int Ib, int Db> explicit fixed_point(const fixed_point<Ia,Da>& f) : v(recast(Ib+Db+Da, f.v) * factor / f.factor) {}

	self operator- () const { return (self){-v}; }
	template<typename R> self& operator= (R r) { v = recast(sizeof(r)*8+Da, r) * factor; return *this; }
	self& operator= (const self& f) { v = f.v; return *this; }
	template<int Ib, int Db> self& operator= (const fixed_point<Ia,Da>& f) { v = recast(Ib+Db+Da, f.v) * factor / f.factor; return *this; }

	template<typename R> self& operator+= (R r) { v += r * (value_type)factor; return *this; }
	template<typename R> self& operator-= (R r) { v -= r * (value_type)factor; return *this; }
	template<typename R> self& operator*= (R r) { v *= r; return *this; }
	template<typename R> self& operator/= (R r) { v /= r; return *this; }

	template<int Ib, int Db> self& operator+= (fixed_point<Ib,Db>& f) { v += recast(Ib+Db+Da, f.v) * factor / f.factor; return *this; }
	template<int Ib, int Db> self& operator-= (fixed_point<Ib,Db>& f) { v -= recast(Ib+Db+Da, f.v) * factor / f.factor; return *this; }
	template<int Ib, int Db> self& operator*= (fixed_point<Ib,Db>& f) { v = recast(Ia+Da+Ib+Db, v) * f.v / f.factor; return *this; }
	template<int Ib, int Db> self& operator/= (fixed_point<Ib,Db>& f) { v = recast(Ia+Da+Db, v) * f.factor / f.v; return *this; }

	template<typename R> operator R() const { return (R)v / factor; }
	template<int Ib, int Db> operator fixed_point<Ib,Db>() const { fixed_point<Ib,Db> r; r.v = recast(Ia+Da+Db, v) * r.factor / factor; return r; }

	self round() const { self r; r.v = (v & ~decimal_mask); if ((v & decimal_mask) >= factor/2) r.v += factor; return r; }
	self floor() const { self r; r.v = (v & ~decimal_mask); return r; }
	self ceil()  const { self r; r.v = (v & ~decimal_mask); if ((v & decimal_mask) > 0) r.v += factor; return r; }
};

#define return_wrapped(value) fixed_point<Ia,Da> _r; _r.v = (value); return _r;

template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator+ (R r, fixed_point<Ia,Da> f) { return_wrapped(r * recast(Ia+Da+Da, f.factor) + f.v); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator- (R r, fixed_point<Ia,Da> f) { return_wrapped(r * recast(Ia+Da+Da, f.factor) - f.v); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator* (R r, fixed_point<Ia,Da> f) { return_wrapped(r * f.v); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator/ (R r, fixed_point<Ia,Da> f) { return_wrapped(r * recast(Ia+Da+Da+Da, f.factor) * f.factor / f.v); }

template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator+ (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v + r * recast(Ia+Da+Da, f.factor)); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator- (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v - r * recast(Ia+Da+Da, f.factor)); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator* (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v * r); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator/ (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v / r); }

template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator+ (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(a.v + (recast(Ib+Db+Da, b.v) * a.factor / b.factor)); }
template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator- (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(a.v - (recast(Ib+Db+Da, b.v) * a.factor / b.factor)); }
template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator* (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(recast(Ia+Da+Ib+Db, a.v) * b.v / b.factor); }
template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator/ (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(recast(Ia+Da+Db, a.v) * b.factor / b.v); }

template<int Ia, int Da, int Ib, int Db> bool operator>  (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor >  recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator<  (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor <  recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator>= (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor >= recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator<= (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor <= recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator== (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor == recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator!= (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor != recast(Ib+Db+Da, b.v) * a.factor; }

template<typename R, int Ia, int Da> bool operator>  (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) >  f.v; }
template<typename R, int Ia, int Da> bool operator<  (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) <  f.v; }
template<typename R, int Ia, int Da> bool operator>= (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) >= f.v; }
template<typename R, int Ia, int Da> bool operator<= (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) <= f.v; }
template<typename R, int Ia, int Da> bool operator== (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) == f.v; }
template<typename R, int Ia, int Da> bool operator!= (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) != f.v; }

template<typename R, int Ia, int Da> bool operator>  (fixed_point<Ia,Da> f, R r) { return f.v >  r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator<  (fixed_point<Ia,Da> f, R r) { return f.v <  r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator>= (fixed_point<Ia,Da> f, R r) { return f.v >= r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator<= (fixed_point<Ia,Da> f, R r) { return f.v <= r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator== (fixed_point<Ia,Da> f, R r) { return f.v == r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator!= (fixed_point<Ia,Da> f, R r) { return f.v != r * recast(Ia+Da+Da, f.factor); }

#undef recast

} // namespace gamma<commit_msg>fixed an issue in fixed_point<commit_after>/* Copyright (c) 2013 Fabian Schuiki */
#pragma once
#include "math.hpp"
#include "integer.hpp"
#define GAMMA_HAS_FIXED_POINT

namespace gamma {

#define recast(bits,thing) ((typename integer::signed_integer<bits>::type)(thing))

/** Class for signed fixed-point arithmetics. */
template<int Ia, int Da> struct fixed_point
{
	typedef fixed_point<Ia,Da> self;

	const static int integral_bits = Ia;
	const static int decimal_bits = Da;
	const static int bits = integral_bits + decimal_bits;

	typedef typename integer::signed_integer<bits>::type value_type;
	#define expand_bits(b, thing) ((si(bits + b))(thing))
	#define expand_bytes(b, thing) expand_bits(b*8, thing)

	const static value_type factor = 1 << (value_type)decimal_bits;
	const static value_type decimal_mask = factor - 1;

	value_type v;

	fixed_point() {}
	fixed_point(const self& f) : v(f.v) {}
	template<typename R> explicit fixed_point(R r, int db = 0) : v(recast(sizeof(r)*8+Da, r) * factor / (1 << (int64_t)db)) {}
	template<int Ib, int Db> explicit fixed_point(const fixed_point<Ia,Da>& f) : v(recast(Ib+Db+Da, f.v) * factor / f.factor) {}

	self operator- () const { return (self){-v}; }
	template<typename R> self& operator= (R r) { v = recast(sizeof(r)*8+Da, r) * factor; return *this; }
	self& operator= (const self& f) { v = f.v; return *this; }
	template<int Ib, int Db> self& operator= (const fixed_point<Ia,Da>& f) { v = recast(Ib+Db+Da, f.v) * factor / f.factor; return *this; }

	template<typename R> self& operator+= (R r) { v += r * (value_type)factor; return *this; }
	template<typename R> self& operator-= (R r) { v -= r * (value_type)factor; return *this; }
	template<typename R> self& operator*= (R r) { v *= r; return *this; }
	template<typename R> self& operator/= (R r) { v /= r; return *this; }

	template<int Ib, int Db> self& operator+= (fixed_point<Ib,Db> f) { v += recast(Ib+Db+Da, f.v) * factor / f.factor; return *this; }
	template<int Ib, int Db> self& operator-= (fixed_point<Ib,Db> f) { v -= recast(Ib+Db+Da, f.v) * factor / f.factor; return *this; }
	template<int Ib, int Db> self& operator*= (fixed_point<Ib,Db> f) { v = recast(Ia+Da+Ib+Db, v) * f.v / f.factor; return *this; }
	template<int Ib, int Db> self& operator/= (fixed_point<Ib,Db> f) { v = recast(Ia+Da+Db, v) * f.factor / f.v; return *this; }

	template<typename R> operator R() const { return (R)v / factor; }
	template<int Ib, int Db> operator fixed_point<Ib,Db>() const { fixed_point<Ib,Db> r; r.v = recast(Ia+Da+Db, v) * r.factor / factor; return r; }

	self round() const { self r; r.v = (v & ~decimal_mask); if ((v & decimal_mask) >= factor/2) r.v += factor; return r; }
	self floor() const { self r; r.v = (v & ~decimal_mask); return r; }
	self ceil()  const { self r; r.v = (v & ~decimal_mask); if ((v & decimal_mask) > 0) r.v += factor; return r; }
};

#define return_wrapped(value) fixed_point<Ia,Da> _r; _r.v = (value); return _r;

template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator+ (R r, fixed_point<Ia,Da> f) { return_wrapped(r * recast(Ia+Da+Da, f.factor) + f.v); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator- (R r, fixed_point<Ia,Da> f) { return_wrapped(r * recast(Ia+Da+Da, f.factor) - f.v); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator* (R r, fixed_point<Ia,Da> f) { return_wrapped(r * f.v); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator/ (R r, fixed_point<Ia,Da> f) { return_wrapped(r * recast(Ia+Da+Da+Da, f.factor) * f.factor / f.v); }

template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator+ (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v + r * recast(Ia+Da+Da, f.factor)); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator- (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v - r * recast(Ia+Da+Da, f.factor)); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator* (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v * r); }
template<typename R, int Ia, int Da> fixed_point<Ia,Da> operator/ (fixed_point<Ia,Da> f, R r) { return_wrapped(f.v / r); }

template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator+ (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(a.v + (recast(Ib+Db+Da, b.v) * a.factor / b.factor)); }
template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator- (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(a.v - (recast(Ib+Db+Da, b.v) * a.factor / b.factor)); }
template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator* (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(recast(Ia+Da+Ib+Db, a.v) * b.v / b.factor); }
template<int Ia, int Da, int Ib, int Db> fixed_point<Ia,Da> operator/ (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return_wrapped(recast(Ia+Da+Db, a.v) * b.factor / b.v); }

template<int Ia, int Da, int Ib, int Db> bool operator>  (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor >  recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator<  (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor <  recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator>= (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor >= recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator<= (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor <= recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator== (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor == recast(Ib+Db+Da, b.v) * a.factor; }
template<int Ia, int Da, int Ib, int Db> bool operator!= (fixed_point<Ia,Da> a, fixed_point<Ib,Db> b) { return recast(Ia+Da+Db, a.v) * b.factor != recast(Ib+Db+Da, b.v) * a.factor; }

template<typename R, int Ia, int Da> bool operator>  (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) >  f.v; }
template<typename R, int Ia, int Da> bool operator<  (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) <  f.v; }
template<typename R, int Ia, int Da> bool operator>= (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) >= f.v; }
template<typename R, int Ia, int Da> bool operator<= (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) <= f.v; }
template<typename R, int Ia, int Da> bool operator== (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) == f.v; }
template<typename R, int Ia, int Da> bool operator!= (R r, fixed_point<Ia,Da> f) { return r * recast(Ia+Da+Da, f.factor) != f.v; }

template<typename R, int Ia, int Da> bool operator>  (fixed_point<Ia,Da> f, R r) { return f.v >  r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator<  (fixed_point<Ia,Da> f, R r) { return f.v <  r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator>= (fixed_point<Ia,Da> f, R r) { return f.v >= r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator<= (fixed_point<Ia,Da> f, R r) { return f.v <= r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator== (fixed_point<Ia,Da> f, R r) { return f.v == r * recast(Ia+Da+Da, f.factor); }
template<typename R, int Ia, int Da> bool operator!= (fixed_point<Ia,Da> f, R r) { return f.v != r * recast(Ia+Da+Da, f.factor); }

#undef recast

} // namespace gamma<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements a MeshCoP Leader.
 */

#if OPENTHREAD_FTD

#define WPP_NAME "leader.tmh"

#include "leader.hpp"

#include <stdio.h>

#include <openthread/platform/random.h>

#include "coap/coap_header.hpp"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/logging.hpp"
#include "common/owner-locator.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/thread_uri_paths.hpp"

namespace ot {
namespace MeshCoP {

Leader::Leader(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mPetition(OT_URI_PATH_LEADER_PETITION, Leader::HandlePetition, this)
    , mKeepAlive(OT_URI_PATH_LEADER_KEEP_ALIVE, Leader::HandleKeepAlive, this)
    , mTimer(aInstance, HandleTimer, this)
    , mDelayTimerMinimal(DelayTimerTlv::kDelayTimerMinimal)
    , mSessionId(0xffff)
{
    GetNetif().GetCoap().AddResource(mPetition);
    GetNetif().GetCoap().AddResource(mKeepAlive);
}

void Leader::HandlePetition(void *               aContext,
                            otCoapHeader *       aHeader,
                            otMessage *          aMessage,
                            const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandlePetition(*static_cast<Coap::Header *>(aHeader),
                                                    *static_cast<Message *>(aMessage),
                                                    *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandlePetition(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    CommissioningData data;
    CommissionerIdTlv commissionerId;
    StateTlv::State   state = StateTlv::kReject;

    otLogInfoMeshCoP(GetInstance(), "received petition");

    SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerId, sizeof(commissionerId), commissionerId));
    VerifyOrExit(commissionerId.IsValid());

    if (mTimer.IsRunning())
    {
        VerifyOrExit(
            !strncmp(commissionerId.GetCommissionerId(), mCommissionerId.GetCommissionerId(), sizeof(mCommissionerId)));

        ResignCommissioner();
    }

    data.mBorderAgentLocator.Init();
    data.mBorderAgentLocator.SetBorderAgentLocator(HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7]));

    data.mCommissionerSessionId.Init();
    data.mCommissionerSessionId.SetCommissionerSessionId(++mSessionId);

    data.mSteeringData.Init();
    data.mSteeringData.SetLength(1);
    data.mSteeringData.Clear();

    SuccessOrExit(
        GetNetif().GetNetworkDataLeader().SetCommissioningData(reinterpret_cast<uint8_t *>(&data), data.GetLength()));

    mCommissionerId = commissionerId;

    state = StateTlv::kAccept;
    mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition));

exit:
    OT_UNUSED_VARIABLE(aMessageInfo);
    SendPetitionResponse(aHeader, aMessageInfo, state);
}

otError Leader::SendPetitionResponse(const Coap::Header &    aRequestHeader,
                                     const Ip6::MessageInfo &aMessageInfo,
                                     StateTlv::State         aState)
{
    ThreadNetif &            netif = GetNetif();
    otError                  error = OT_ERROR_NONE;
    Coap::Header             responseHeader;
    StateTlv                 state;
    CommissionerSessionIdTlv sessionId;
    Message *                message;

    responseHeader.SetDefaultResponseHeader(aRequestHeader);
    responseHeader.SetPayloadMarker();

    VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), responseHeader)) != NULL, error = OT_ERROR_NO_BUFS);

    state.Init();
    state.SetState(aState);
    SuccessOrExit(error = message->Append(&state, sizeof(state)));

    if (mTimer.IsRunning())
    {
        uint16_t len = sizeof(Tlv) + mCommissionerId.GetLength();
        SuccessOrExit(error = message->Append(&mCommissionerId, len));
    }

    if (aState == StateTlv::kAccept)
    {
        sessionId.Init();
        sessionId.SetCommissionerSessionId(mSessionId);
        SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId)));
    }

    SuccessOrExit(error = netif.GetCoap().SendMessage(*message, aMessageInfo));

    otLogInfoMeshCoP(GetInstance(), "sent petition response");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }

    return error;
}

void Leader::HandleKeepAlive(void *               aContext,
                             otCoapHeader *       aHeader,
                             otMessage *          aMessage,
                             const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandleKeepAlive(*static_cast<Coap::Header *>(aHeader),
                                                     *static_cast<Message *>(aMessage),
                                                     *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandleKeepAlive(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    NetworkData::Leader &    netdata = GetNetif().GetNetworkDataLeader();
    StateTlv                 state;
    CommissionerSessionIdTlv sessionId;
    BorderAgentLocatorTlv *  borderAgentLocator;
    StateTlv::State          responseState;

    otLogInfoMeshCoP(GetInstance(), "received keep alive");

    SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kState, sizeof(state), state));
    VerifyOrExit(state.IsValid());

    SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId));
    VerifyOrExit(sessionId.IsValid());

    borderAgentLocator =
        static_cast<BorderAgentLocatorTlv *>(netdata.GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));

    if ((borderAgentLocator == NULL) || (sessionId.GetCommissionerSessionId() != mSessionId))
    {
        responseState = StateTlv::kReject;
    }
    else if (state.GetState() != StateTlv::kAccept)
    {
        responseState = StateTlv::kReject;
        ResignCommissioner();
    }
    else
    {
        uint16_t rloc = HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7]);

        if (borderAgentLocator->GetBorderAgentLocator() != rloc)
        {
            borderAgentLocator->SetBorderAgentLocator(rloc);
            netdata.IncrementVersion();
        }

        responseState = StateTlv::kAccept;
        mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition));
    }

    SendKeepAliveResponse(aHeader, aMessageInfo, responseState);

exit:
    return;
}

otError Leader::SendKeepAliveResponse(const Coap::Header &    aRequestHeader,
                                      const Ip6::MessageInfo &aMessageInfo,
                                      StateTlv::State         aState)
{
    ThreadNetif &netif = GetNetif();
    otError      error = OT_ERROR_NONE;
    Coap::Header responseHeader;
    StateTlv     state;
    Message *    message;

    responseHeader.SetDefaultResponseHeader(aRequestHeader);
    responseHeader.SetPayloadMarker();

    VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), responseHeader)) != NULL, error = OT_ERROR_NO_BUFS);

    state.Init();
    state.SetState(aState);
    SuccessOrExit(error = message->Append(&state, sizeof(state)));

    SuccessOrExit(error = netif.GetCoap().SendMessage(*message, aMessageInfo));

    otLogInfoMeshCoP(GetInstance(), "sent keep alive response");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }

    return error;
}

otError Leader::SendDatasetChanged(const Ip6::Address &aAddress)
{
    ThreadNetif &    netif = GetNetif();
    otError          error = OT_ERROR_NONE;
    Coap::Header     header;
    Ip6::MessageInfo messageInfo;
    Message *        message;

    header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST);
    header.SetToken(Coap::Header::kDefaultTokenLength);
    header.AppendUriPathOptions(OT_URI_PATH_DATASET_CHANGED);

    VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS);

    messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16());
    messageInfo.SetPeerAddr(aAddress);
    messageInfo.SetPeerPort(kCoapUdpPort);
    SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo));

    otLogInfoMeshCoP(GetInstance(), "sent dataset changed");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }

    return error;
}

otError Leader::SetDelayTimerMinimal(uint32_t aDelayTimerMinimal)
{
    otError error = OT_ERROR_NONE;
    VerifyOrExit((aDelayTimerMinimal != 0 && aDelayTimerMinimal < DelayTimerTlv::kDelayTimerDefault),
                 error = OT_ERROR_INVALID_ARGS);
    mDelayTimerMinimal = aDelayTimerMinimal;

exit:
    return error;
}

uint32_t Leader::GetDelayTimerMinimal(void) const
{
    return mDelayTimerMinimal;
}

void Leader::HandleTimer(Timer &aTimer)
{
    aTimer.GetOwner<Leader>().HandleTimer();
}

void Leader::HandleTimer(void)
{
    VerifyOrExit(GetNetif().GetMle().GetRole() == OT_DEVICE_ROLE_LEADER);

    ResignCommissioner();

exit:
    return;
}

void Leader::SetEmptyCommissionerData(void)
{
    CommissionerSessionIdTlv mCommissionerSessionId;

    mCommissionerSessionId.Init();
    mCommissionerSessionId.SetCommissionerSessionId(++mSessionId);

    GetNetif().GetNetworkDataLeader().SetCommissioningData(reinterpret_cast<uint8_t *>(&mCommissionerSessionId),
                                                           sizeof(Tlv) + mCommissionerSessionId.GetLength());
}

void Leader::ResignCommissioner(void)
{
    mTimer.Stop();
    SetEmptyCommissionerData();

    otLogInfoMeshCoP(GetInstance(), "commissioner inactive");
}

} // namespace MeshCoP
} // namespace ot

#endif // OPENTHREAD_FTD
<commit_msg>[commissioner-dataset] initialize mSessionId to a random value (#2793)<commit_after>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements a MeshCoP Leader.
 */

#if OPENTHREAD_FTD

#define WPP_NAME "leader.tmh"

#include "leader.hpp"

#include <stdio.h>

#include <openthread/platform/random.h>

#include "coap/coap_header.hpp"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/logging.hpp"
#include "common/owner-locator.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/thread_uri_paths.hpp"

namespace ot {
namespace MeshCoP {

Leader::Leader(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mPetition(OT_URI_PATH_LEADER_PETITION, Leader::HandlePetition, this)
    , mKeepAlive(OT_URI_PATH_LEADER_KEEP_ALIVE, Leader::HandleKeepAlive, this)
    , mTimer(aInstance, HandleTimer, this)
    , mDelayTimerMinimal(DelayTimerTlv::kDelayTimerMinimal)
    , mSessionId(Random::GetUint16())
{
    GetNetif().GetCoap().AddResource(mPetition);
    GetNetif().GetCoap().AddResource(mKeepAlive);
}

void Leader::HandlePetition(void *               aContext,
                            otCoapHeader *       aHeader,
                            otMessage *          aMessage,
                            const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandlePetition(*static_cast<Coap::Header *>(aHeader),
                                                    *static_cast<Message *>(aMessage),
                                                    *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandlePetition(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    CommissioningData data;
    CommissionerIdTlv commissionerId;
    StateTlv::State   state = StateTlv::kReject;

    otLogInfoMeshCoP(GetInstance(), "received petition");

    SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerId, sizeof(commissionerId), commissionerId));
    VerifyOrExit(commissionerId.IsValid());

    if (mTimer.IsRunning())
    {
        VerifyOrExit(
            !strncmp(commissionerId.GetCommissionerId(), mCommissionerId.GetCommissionerId(), sizeof(mCommissionerId)));

        ResignCommissioner();
    }

    data.mBorderAgentLocator.Init();
    data.mBorderAgentLocator.SetBorderAgentLocator(HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7]));

    data.mCommissionerSessionId.Init();
    data.mCommissionerSessionId.SetCommissionerSessionId(++mSessionId);

    data.mSteeringData.Init();
    data.mSteeringData.SetLength(1);
    data.mSteeringData.Clear();

    SuccessOrExit(
        GetNetif().GetNetworkDataLeader().SetCommissioningData(reinterpret_cast<uint8_t *>(&data), data.GetLength()));

    mCommissionerId = commissionerId;

    state = StateTlv::kAccept;
    mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition));

exit:
    OT_UNUSED_VARIABLE(aMessageInfo);
    SendPetitionResponse(aHeader, aMessageInfo, state);
}

otError Leader::SendPetitionResponse(const Coap::Header &    aRequestHeader,
                                     const Ip6::MessageInfo &aMessageInfo,
                                     StateTlv::State         aState)
{
    ThreadNetif &            netif = GetNetif();
    otError                  error = OT_ERROR_NONE;
    Coap::Header             responseHeader;
    StateTlv                 state;
    CommissionerSessionIdTlv sessionId;
    Message *                message;

    responseHeader.SetDefaultResponseHeader(aRequestHeader);
    responseHeader.SetPayloadMarker();

    VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), responseHeader)) != NULL, error = OT_ERROR_NO_BUFS);

    state.Init();
    state.SetState(aState);
    SuccessOrExit(error = message->Append(&state, sizeof(state)));

    if (mTimer.IsRunning())
    {
        uint16_t len = sizeof(Tlv) + mCommissionerId.GetLength();
        SuccessOrExit(error = message->Append(&mCommissionerId, len));
    }

    if (aState == StateTlv::kAccept)
    {
        sessionId.Init();
        sessionId.SetCommissionerSessionId(mSessionId);
        SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId)));
    }

    SuccessOrExit(error = netif.GetCoap().SendMessage(*message, aMessageInfo));

    otLogInfoMeshCoP(GetInstance(), "sent petition response");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }

    return error;
}

void Leader::HandleKeepAlive(void *               aContext,
                             otCoapHeader *       aHeader,
                             otMessage *          aMessage,
                             const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandleKeepAlive(*static_cast<Coap::Header *>(aHeader),
                                                     *static_cast<Message *>(aMessage),
                                                     *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandleKeepAlive(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    NetworkData::Leader &    netdata = GetNetif().GetNetworkDataLeader();
    StateTlv                 state;
    CommissionerSessionIdTlv sessionId;
    BorderAgentLocatorTlv *  borderAgentLocator;
    StateTlv::State          responseState;

    otLogInfoMeshCoP(GetInstance(), "received keep alive");

    SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kState, sizeof(state), state));
    VerifyOrExit(state.IsValid());

    SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId));
    VerifyOrExit(sessionId.IsValid());

    borderAgentLocator =
        static_cast<BorderAgentLocatorTlv *>(netdata.GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));

    if ((borderAgentLocator == NULL) || (sessionId.GetCommissionerSessionId() != mSessionId))
    {
        responseState = StateTlv::kReject;
    }
    else if (state.GetState() != StateTlv::kAccept)
    {
        responseState = StateTlv::kReject;
        ResignCommissioner();
    }
    else
    {
        uint16_t rloc = HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7]);

        if (borderAgentLocator->GetBorderAgentLocator() != rloc)
        {
            borderAgentLocator->SetBorderAgentLocator(rloc);
            netdata.IncrementVersion();
        }

        responseState = StateTlv::kAccept;
        mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition));
    }

    SendKeepAliveResponse(aHeader, aMessageInfo, responseState);

exit:
    return;
}

otError Leader::SendKeepAliveResponse(const Coap::Header &    aRequestHeader,
                                      const Ip6::MessageInfo &aMessageInfo,
                                      StateTlv::State         aState)
{
    ThreadNetif &netif = GetNetif();
    otError      error = OT_ERROR_NONE;
    Coap::Header responseHeader;
    StateTlv     state;
    Message *    message;

    responseHeader.SetDefaultResponseHeader(aRequestHeader);
    responseHeader.SetPayloadMarker();

    VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), responseHeader)) != NULL, error = OT_ERROR_NO_BUFS);

    state.Init();
    state.SetState(aState);
    SuccessOrExit(error = message->Append(&state, sizeof(state)));

    SuccessOrExit(error = netif.GetCoap().SendMessage(*message, aMessageInfo));

    otLogInfoMeshCoP(GetInstance(), "sent keep alive response");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }

    return error;
}

otError Leader::SendDatasetChanged(const Ip6::Address &aAddress)
{
    ThreadNetif &    netif = GetNetif();
    otError          error = OT_ERROR_NONE;
    Coap::Header     header;
    Ip6::MessageInfo messageInfo;
    Message *        message;

    header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST);
    header.SetToken(Coap::Header::kDefaultTokenLength);
    header.AppendUriPathOptions(OT_URI_PATH_DATASET_CHANGED);

    VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS);

    messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16());
    messageInfo.SetPeerAddr(aAddress);
    messageInfo.SetPeerPort(kCoapUdpPort);
    SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo));

    otLogInfoMeshCoP(GetInstance(), "sent dataset changed");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }

    return error;
}

otError Leader::SetDelayTimerMinimal(uint32_t aDelayTimerMinimal)
{
    otError error = OT_ERROR_NONE;
    VerifyOrExit((aDelayTimerMinimal != 0 && aDelayTimerMinimal < DelayTimerTlv::kDelayTimerDefault),
                 error = OT_ERROR_INVALID_ARGS);
    mDelayTimerMinimal = aDelayTimerMinimal;

exit:
    return error;
}

uint32_t Leader::GetDelayTimerMinimal(void) const
{
    return mDelayTimerMinimal;
}

void Leader::HandleTimer(Timer &aTimer)
{
    aTimer.GetOwner<Leader>().HandleTimer();
}

void Leader::HandleTimer(void)
{
    VerifyOrExit(GetNetif().GetMle().GetRole() == OT_DEVICE_ROLE_LEADER);

    ResignCommissioner();

exit:
    return;
}

void Leader::SetEmptyCommissionerData(void)
{
    CommissionerSessionIdTlv mCommissionerSessionId;

    mCommissionerSessionId.Init();
    mCommissionerSessionId.SetCommissionerSessionId(++mSessionId);

    GetNetif().GetNetworkDataLeader().SetCommissioningData(reinterpret_cast<uint8_t *>(&mCommissionerSessionId),
                                                           sizeof(Tlv) + mCommissionerSessionId.GetLength());
}

void Leader::ResignCommissioner(void)
{
    mTimer.Stop();
    SetEmptyCommissionerData();

    otLogInfoMeshCoP(GetInstance(), "commissioner inactive");
}

} // namespace MeshCoP
} // namespace ot

#endif // OPENTHREAD_FTD
<|endoftext|>


<commit_before>// The Art of C++ / taopq
// Copyright (c) 2016-2019 Daniel Frey

#include "../getenv.hpp"
#include "../macros.hpp"

#include <tao/pq/connection.hpp>

void run()
{
   // overwrite the default with an environment variable if needed
   const auto connection_string = tao::pq::internal::getenv( "TAOPQ_TEST_DATABASE", "dbname=template1" );

   // connection_string must be valid
   TEST_THROWS( tao::pq::connection::create( "=" ) );

   // connection_string must reference an existing and accessible database
   TEST_THROWS( tao::pq::connection::create( "dbname=DOES_NOT_EXIST" ) );

   // open a connection
   const auto connection = tao::pq::connection::create( connection_string );

   // open a seconds, independent connection (and discard it immediately)
   (void)tao::pq::connection::create( connection_string );

   // execute an SQL statement
   connection->execute( "DROP TABLE IF EXISTS tao_connection_test" );

   // execution of empty statements fails
   TEST_THROWS( connection->execute( "" ) );

   // execution of invalid statements fails
   TEST_THROWS( connection->execute( "FOO BAR BAZ" ) );

   // a prepared statement's name must be a valid C++ identifier
   TEST_THROWS( connection->prepare( "", "DROP TABLE IF EXISTS tao_connection_test" ) );
   TEST_THROWS( connection->prepare( "0drop_table", "DROP TABLE IF EXISTS tao_connection_test" ) );
   TEST_THROWS( connection->prepare( "drop table", "DROP TABLE IF EXISTS tao_connection_test" ) );

   // prepare a statement
   connection->prepare( "drop_table", "DROP TABLE IF EXISTS tao_connection_test" );

   // execute a prepared statement
   //
   // note: the name of a prepared statement must be a valid identifier, all
   // actual SQL statements can be writen in a form which does not match a valid
   // identifier, so you can always make sure that they can not be confused.
   connection->execute( "drop_table" );

   // a statement which is not a query does not return "affected rows"
   TEST_THROWS( connection->execute( "drop_table" ).rows_affected() );

   // deallocate a prepared statement
   connection->deallocate( "drop_table" );

   // no longer possible
   TEST_THROWS( connection->execute( "drop_table" ) );

   // deallocate must refer to a prepared statement
   TEST_THROWS( connection->deallocate( "drop_table" ) );

   // deallocate must get a valid name
   TEST_THROWS( connection->deallocate( "FOO BAR" ) );

   // create a test table
   connection->execute( "CREATE TABLE tao_connection_test ( a INTEGER PRIMARY KEY, b INTEGER )" );

   // a DELETE statement does not yield a result set
   TEST_THROWS( connection->execute( "DELETE FROM tao_connection_test" ).empty() );

   // out of range access throws
   TEST_THROWS( connection->execute( "SELECT * FROM tao_connection_test" ).at( 0 ) );

   // insert some data
   connection->execute( "INSERT INTO tao_connection_test VALUES ( 1, 42 )" );

   // read data
   TEST_ASSERT( connection->execute( "SELECT b FROM tao_connection_test WHERE a = 1" )[ 0 ][ 0 ].get() == std::string( "42" ) );
}

int main()
{
   try {
      run();
   }
   catch( const std::exception& e ) {
      std::cerr << "exception: " << e.what() << std::endl;
      throw;
   }
   catch( ... ) {
      std::cerr << "unknown exception" << std::endl;
      throw;
   }
}
<commit_msg>Suppress false positive from clang-analyzer<commit_after>// The Art of C++ / taopq
// Copyright (c) 2016-2019 Daniel Frey

#include "../getenv.hpp"
#include "../macros.hpp"

#include <tao/pq/connection.hpp>

void run()
{
   // overwrite the default with an environment variable if needed

   // suppress false positive from clang-analyzer
#ifndef __clang_analyzer__
   const auto connection_string = tao::pq::internal::getenv( "TAOPQ_TEST_DATABASE", "dbname=template1" );
#endif

   // connection_string must be valid
   TEST_THROWS( tao::pq::connection::create( "=" ) );

   // connection_string must reference an existing and accessible database
   TEST_THROWS( tao::pq::connection::create( "dbname=DOES_NOT_EXIST" ) );

   // open a connection
   const auto connection = tao::pq::connection::create( connection_string );

   // open a seconds, independent connection (and discard it immediately)
   (void)tao::pq::connection::create( connection_string );

   // execute an SQL statement
   connection->execute( "DROP TABLE IF EXISTS tao_connection_test" );

   // execution of empty statements fails
   TEST_THROWS( connection->execute( "" ) );

   // execution of invalid statements fails
   TEST_THROWS( connection->execute( "FOO BAR BAZ" ) );

   // a prepared statement's name must be a valid C++ identifier
   TEST_THROWS( connection->prepare( "", "DROP TABLE IF EXISTS tao_connection_test" ) );
   TEST_THROWS( connection->prepare( "0drop_table", "DROP TABLE IF EXISTS tao_connection_test" ) );
   TEST_THROWS( connection->prepare( "drop table", "DROP TABLE IF EXISTS tao_connection_test" ) );

   // prepare a statement
   connection->prepare( "drop_table", "DROP TABLE IF EXISTS tao_connection_test" );

   // execute a prepared statement
   //
   // note: the name of a prepared statement must be a valid identifier, all
   // actual SQL statements can be writen in a form which does not match a valid
   // identifier, so you can always make sure that they can not be confused.
   connection->execute( "drop_table" );

   // a statement which is not a query does not return "affected rows"
   TEST_THROWS( connection->execute( "drop_table" ).rows_affected() );

   // deallocate a prepared statement
   connection->deallocate( "drop_table" );

   // no longer possible
   TEST_THROWS( connection->execute( "drop_table" ) );

   // deallocate must refer to a prepared statement
   TEST_THROWS( connection->deallocate( "drop_table" ) );

   // deallocate must get a valid name
   TEST_THROWS( connection->deallocate( "FOO BAR" ) );

   // create a test table
   connection->execute( "CREATE TABLE tao_connection_test ( a INTEGER PRIMARY KEY, b INTEGER )" );

   // a DELETE statement does not yield a result set
   TEST_THROWS( connection->execute( "DELETE FROM tao_connection_test" ).empty() );

   // out of range access throws
   TEST_THROWS( connection->execute( "SELECT * FROM tao_connection_test" ).at( 0 ) );

   // insert some data
   connection->execute( "INSERT INTO tao_connection_test VALUES ( 1, 42 )" );

   // read data
   TEST_ASSERT( connection->execute( "SELECT b FROM tao_connection_test WHERE a = 1" )[ 0 ][ 0 ].get() == std::string( "42" ) );
}

int main()
{
   try {
      run();
   }
   catch( const std::exception& e ) {
      std::cerr << "exception: " << e.what() << std::endl;
      throw;
   }
   catch( ... ) {
      std::cerr << "unknown exception" << std::endl;
      throw;
   }
}
<|endoftext|>


<commit_before>#include "BasicBlock.h"
#include "MemStream.h"
#include "offsetof_def.h"
#include "MipsJitter.h"
#include "Jitter_CodeGenFactory.h"

#if defined(AOT_BUILD_CACHE) || defined(AOT_USE_CACHE)
#define AOT_ENABLED
#endif

#ifdef AOT_ENABLED

#include <zlib.h>
#include "StdStream.h"
#include "StdStreamUtils.h"

#endif

#ifdef VTUNE_ENABLED
#include <jitprofiling.h>
#include "string_format.h"
#endif

#ifdef AOT_USE_CACHE

struct AOT_BLOCK
{
	AOT_BLOCK_KEY	key;
	void*			fct;
};

extern "C" AOT_BLOCK	_aot_firstBlock;
extern "C" uint32		_aot_blockCount;

#endif

CBasicBlock::CBasicBlock(CMIPS& context, uint32 begin, uint32 end)
: m_begin(begin)
, m_end(end)
, m_context(context)
, m_selfLoopCount(0)
#ifdef AOT_USE_CACHE
, m_function(nullptr)
#endif
{
	assert(m_end >= m_begin);
}

CBasicBlock::~CBasicBlock()
{

}

#ifdef AOT_BUILD_CACHE

Framework::CStdStream*	CBasicBlock::m_aotBlockOutputStream(nullptr);
std::mutex				CBasicBlock::m_aotBlockOutputStreamMutex;

void CBasicBlock::SetAotBlockOutputStream(Framework::CStdStream* outputStream)
{
	assert(m_aotBlockOutputStream == nullptr || outputStream == nullptr);
	m_aotBlockOutputStream = outputStream;
}

#endif

void CBasicBlock::Compile()
{
#ifndef AOT_USE_CACHE

	Framework::CMemStream stream;
	{
		static __declspec(thread) CMipsJitter* jitter = NULL;
		if(jitter == NULL)
		{
			Jitter::CCodeGen* codeGen = Jitter::CreateCodeGen();
			jitter = new CMipsJitter(codeGen);

			for(unsigned int i = 0; i < 4; i++)
			{
				jitter->SetVariableAsConstant(
					offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]),
					0
					);
			}
		}

		jitter->SetStream(&stream);
		jitter->Begin();
		CompileRange(jitter);
//		codeGen.DumpVariables(0);
//		codeGen.EndQuota();
		jitter->End();
	}

	m_function = CMemoryFunction(stream.GetBuffer(), stream.GetSize());

#ifdef VTUNE_ENABLED
	if(iJIT_IsProfilingActive() == iJIT_SAMPLING_ON)
	{
		iJIT_Method_Load jmethod = {};
		jmethod.method_id = iJIT_GetNewMethodID();
		jmethod.class_file_name = "";
		jmethod.source_file_name = __FILE__;

		jmethod.method_load_address = m_function.GetCode();
		jmethod.method_size = m_function.GetSize();
		jmethod.line_number_size = 0;

		auto functionName = string_format("BasicBlock_0x%0.8X_0x%0.8X", m_begin, m_end);

		jmethod.method_name = const_cast<char*>(functionName.c_str());
		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, reinterpret_cast<void*>(&jmethod));
	}
#endif

#endif

#ifdef AOT_ENABLED

	size_t blockSize = ((m_end - m_begin) / 4) + 1;
	auto blockData = new uint32[blockSize];

	for(uint32 i = 0; i < blockSize; i++)
	{
		blockData[i] = m_context.m_pMemoryMap->GetWord(m_begin + (i * 4));
	}

	uint32 blockChecksum = crc32(0, reinterpret_cast<Bytef*>(blockData), blockSize * 4);

#endif

#ifdef AOT_USE_CACHE

	AOT_BLOCK* blocksBegin = &_aot_firstBlock;
	AOT_BLOCK* blocksEnd = blocksBegin + _aot_blockCount;

	AOT_BLOCK blockRef = { blockChecksum, m_begin, m_end, nullptr };

	static const auto blockComparer =
		[] (const AOT_BLOCK& item1, const AOT_BLOCK& item2)
		{
			return item1.key < item2.key;
		};

//	assert(std::is_sorted(blocksBegin, blocksEnd, blockComparer));

	bool blockExists = std::binary_search(blocksBegin, blocksEnd, blockRef, blockComparer);
	auto blockIterator = std::lower_bound(blocksBegin, blocksEnd, blockRef, blockComparer);

	assert(blockExists);
	assert(blockIterator != blocksEnd);
	assert(blockIterator->key.crc == blockChecksum);
	assert(blockIterator->key.begin == m_begin);
	assert(blockIterator->key.end == m_end);

	m_function = reinterpret_cast<void (*)(void*)>(blockIterator->fct);

#endif

#ifdef AOT_BUILD_CACHE
	{
		std::lock_guard<std::mutex> lock(m_aotBlockOutputStreamMutex);

		m_aotBlockOutputStream->Write32(blockChecksum);
		m_aotBlockOutputStream->Write32(m_begin);
		m_aotBlockOutputStream->Write32(m_end);
		m_aotBlockOutputStream->Write(blockData, blockSize * 4);
	}
#endif
}

void CBasicBlock::CompileRange(CMipsJitter* jitter)
{
	for(uint32 address = m_begin; address <= m_end; address += 4)
	{
		m_context.m_pArch->CompileInstruction(
			address,
			jitter,
			&m_context);
		//Sanity check
		assert(jitter->IsStackEmpty());
	}
}

unsigned int CBasicBlock::Execute()
{
	m_function(&m_context);

	if(m_context.m_State.nDelayedJumpAddr != MIPS_INVALID_PC)
	{
		m_context.m_State.nPC = m_context.m_State.nDelayedJumpAddr;
		m_context.m_State.nDelayedJumpAddr = MIPS_INVALID_PC;
	}
	else
	{
		m_context.m_State.nPC = m_end + 4;
	}

	assert(m_context.m_State.nGPR[0].nV0 == 0);
	assert(m_context.m_State.nGPR[0].nV1 == 0);
	assert(m_context.m_State.nGPR[0].nV2 == 0);
	assert(m_context.m_State.nGPR[0].nV3 == 0);
	assert((m_context.m_State.nGPR[CMIPS::RA].nV0 & 3) == 0);
	assert(m_context.m_State.nCOP2[0].nV0 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV1 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV2 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV3 == 0x3F800000);
	assert(m_context.m_State.nCOP2VI[0] == 0);

	return ((m_end - m_begin) / 4) + 1;
}

uint32 CBasicBlock::GetBeginAddress() const
{
	return m_begin;
}

uint32 CBasicBlock::GetEndAddress() const
{
	return m_end;
}

bool CBasicBlock::IsCompiled() const
{
#ifndef AOT_USE_CACHE
	return !m_function.IsEmpty();
#else
	return (m_function != nullptr);
#endif
}

unsigned int CBasicBlock::GetSelfLoopCount() const
{
	return m_selfLoopCount;
}

void CBasicBlock::SetSelfLoopCount(unsigned int selfLoopCount)
{
	m_selfLoopCount = selfLoopCount;
}
<commit_msg>Added assert to make sure PC is aligned on 4 bytes.<commit_after>#include "BasicBlock.h"
#include "MemStream.h"
#include "offsetof_def.h"
#include "MipsJitter.h"
#include "Jitter_CodeGenFactory.h"

#if defined(AOT_BUILD_CACHE) || defined(AOT_USE_CACHE)
#define AOT_ENABLED
#endif

#ifdef AOT_ENABLED

#include <zlib.h>
#include "StdStream.h"
#include "StdStreamUtils.h"

#endif

#ifdef VTUNE_ENABLED
#include <jitprofiling.h>
#include "string_format.h"
#endif

#ifdef AOT_USE_CACHE

struct AOT_BLOCK
{
	AOT_BLOCK_KEY	key;
	void*			fct;
};

extern "C" AOT_BLOCK	_aot_firstBlock;
extern "C" uint32		_aot_blockCount;

#endif

CBasicBlock::CBasicBlock(CMIPS& context, uint32 begin, uint32 end)
: m_begin(begin)
, m_end(end)
, m_context(context)
, m_selfLoopCount(0)
#ifdef AOT_USE_CACHE
, m_function(nullptr)
#endif
{
	assert(m_end >= m_begin);
}

CBasicBlock::~CBasicBlock()
{

}

#ifdef AOT_BUILD_CACHE

Framework::CStdStream*	CBasicBlock::m_aotBlockOutputStream(nullptr);
std::mutex				CBasicBlock::m_aotBlockOutputStreamMutex;

void CBasicBlock::SetAotBlockOutputStream(Framework::CStdStream* outputStream)
{
	assert(m_aotBlockOutputStream == nullptr || outputStream == nullptr);
	m_aotBlockOutputStream = outputStream;
}

#endif

void CBasicBlock::Compile()
{
#ifndef AOT_USE_CACHE

	Framework::CMemStream stream;
	{
		static __declspec(thread) CMipsJitter* jitter = NULL;
		if(jitter == NULL)
		{
			Jitter::CCodeGen* codeGen = Jitter::CreateCodeGen();
			jitter = new CMipsJitter(codeGen);

			for(unsigned int i = 0; i < 4; i++)
			{
				jitter->SetVariableAsConstant(
					offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]),
					0
					);
			}
		}

		jitter->SetStream(&stream);
		jitter->Begin();
		CompileRange(jitter);
//		codeGen.DumpVariables(0);
//		codeGen.EndQuota();
		jitter->End();
	}

	m_function = CMemoryFunction(stream.GetBuffer(), stream.GetSize());

#ifdef VTUNE_ENABLED
	if(iJIT_IsProfilingActive() == iJIT_SAMPLING_ON)
	{
		iJIT_Method_Load jmethod = {};
		jmethod.method_id = iJIT_GetNewMethodID();
		jmethod.class_file_name = "";
		jmethod.source_file_name = __FILE__;

		jmethod.method_load_address = m_function.GetCode();
		jmethod.method_size = m_function.GetSize();
		jmethod.line_number_size = 0;

		auto functionName = string_format("BasicBlock_0x%0.8X_0x%0.8X", m_begin, m_end);

		jmethod.method_name = const_cast<char*>(functionName.c_str());
		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, reinterpret_cast<void*>(&jmethod));
	}
#endif

#endif

#ifdef AOT_ENABLED

	size_t blockSize = ((m_end - m_begin) / 4) + 1;
	auto blockData = new uint32[blockSize];

	for(uint32 i = 0; i < blockSize; i++)
	{
		blockData[i] = m_context.m_pMemoryMap->GetWord(m_begin + (i * 4));
	}

	uint32 blockChecksum = crc32(0, reinterpret_cast<Bytef*>(blockData), blockSize * 4);

#endif

#ifdef AOT_USE_CACHE

	AOT_BLOCK* blocksBegin = &_aot_firstBlock;
	AOT_BLOCK* blocksEnd = blocksBegin + _aot_blockCount;

	AOT_BLOCK blockRef = { blockChecksum, m_begin, m_end, nullptr };

	static const auto blockComparer =
		[] (const AOT_BLOCK& item1, const AOT_BLOCK& item2)
		{
			return item1.key < item2.key;
		};

//	assert(std::is_sorted(blocksBegin, blocksEnd, blockComparer));

	bool blockExists = std::binary_search(blocksBegin, blocksEnd, blockRef, blockComparer);
	auto blockIterator = std::lower_bound(blocksBegin, blocksEnd, blockRef, blockComparer);

	assert(blockExists);
	assert(blockIterator != blocksEnd);
	assert(blockIterator->key.crc == blockChecksum);
	assert(blockIterator->key.begin == m_begin);
	assert(blockIterator->key.end == m_end);

	m_function = reinterpret_cast<void (*)(void*)>(blockIterator->fct);

#endif

#ifdef AOT_BUILD_CACHE
	{
		std::lock_guard<std::mutex> lock(m_aotBlockOutputStreamMutex);

		m_aotBlockOutputStream->Write32(blockChecksum);
		m_aotBlockOutputStream->Write32(m_begin);
		m_aotBlockOutputStream->Write32(m_end);
		m_aotBlockOutputStream->Write(blockData, blockSize * 4);
	}
#endif
}

void CBasicBlock::CompileRange(CMipsJitter* jitter)
{
	for(uint32 address = m_begin; address <= m_end; address += 4)
	{
		m_context.m_pArch->CompileInstruction(
			address,
			jitter,
			&m_context);
		//Sanity check
		assert(jitter->IsStackEmpty());
	}
}

unsigned int CBasicBlock::Execute()
{
	m_function(&m_context);

	if(m_context.m_State.nDelayedJumpAddr != MIPS_INVALID_PC)
	{
		m_context.m_State.nPC = m_context.m_State.nDelayedJumpAddr;
		m_context.m_State.nDelayedJumpAddr = MIPS_INVALID_PC;
	}
	else
	{
		m_context.m_State.nPC = m_end + 4;
	}

	assert(m_context.m_State.nGPR[0].nV0 == 0);
	assert(m_context.m_State.nGPR[0].nV1 == 0);
	assert(m_context.m_State.nGPR[0].nV2 == 0);
	assert(m_context.m_State.nGPR[0].nV3 == 0);
	assert((m_context.m_State.nPC & 3) == 0);
	assert((m_context.m_State.nGPR[CMIPS::RA].nV0 & 3) == 0);
	assert(m_context.m_State.nCOP2[0].nV0 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV1 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV2 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV3 == 0x3F800000);
	assert(m_context.m_State.nCOP2VI[0] == 0);

	return ((m_end - m_begin) / 4) + 1;
}

uint32 CBasicBlock::GetBeginAddress() const
{
	return m_begin;
}

uint32 CBasicBlock::GetEndAddress() const
{
	return m_end;
}

bool CBasicBlock::IsCompiled() const
{
#ifndef AOT_USE_CACHE
	return !m_function.IsEmpty();
#else
	return (m_function != nullptr);
#endif
}

unsigned int CBasicBlock::GetSelfLoopCount() const
{
	return m_selfLoopCount;
}

void CBasicBlock::SetSelfLoopCount(unsigned int selfLoopCount)
{
	m_selfLoopCount = selfLoopCount;
}
<|endoftext|>


<commit_before>/*
 *  ______                   __  __              __
 * /\  _  \           __    /\ \/\ \            /\ \__
 * \ \ \L\ \  __  __ /\_\   \_\ \ \ \____    ___\ \ ,_\   ____
 *  \ \  __ \/\ \/\ \\/\ \  /'_` \ \ '__`\  / __`\ \ \/  /',__\
 *   \ \ \/\ \ \ \_/ |\ \ \/\ \L\ \ \ \L\ \/\ \L\ \ \ \_/\__, `\
 *    \ \_\ \_\ \___/  \ \_\ \___,_\ \_,__/\ \____/\ \__\/\____/
 *     \/_/\/_/\/__/    \/_/\/__,_ /\/___/  \/___/  \/__/\/___/
 * @copyright Copyright 2017 Avidbots Corp.
 * @name	 world.cpp
 * @brief	 implements flatland layer
 * @author Chunshang Li
 *
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2017, Avidbots Corp.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the Avidbots Corp. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#include <Box2D/Box2D.h>
#include <flatland_server/debug_visualization.h>
#include <flatland_server/exceptions.h>
#include <flatland_server/geometry.h>
#include <flatland_server/layer.h>
#include <ros/ros.h>
#include <yaml-cpp/yaml.h>
#include <opencv2/opencv.hpp>
#include <string>

namespace flatland_server {

Layer::Layer(b2World *physics_world, uint8_t layer_index,
             const std::string &name, const cv::Mat &bitmap,
             const std::array<double, 4> &color,
             const std::array<double, 3> &origin, double resolution,
             double occupied_thresh, double free_thresh)
    : Entity(physics_world, name),
      layer_index_(layer_index),
      color_(color),
      origin_(origin),
      resolution_(resolution),
      occupied_thresh_(occupied_thresh),
      free_thresh_(free_thresh) {
  bitmap.copyTo(bitmap_);

  b2BodyDef body_def;
  body_def.type = b2_staticBody;

  physics_body_ = physics_world_->CreateBody(&body_def);

  vectorize_bitmap();
  load_edges();

  ROS_INFO_NAMED("Layer", "Layer %s added", name_.c_str());
}

Layer::~Layer() { physics_body_->GetWorld()->DestroyBody(physics_body_); }

Layer *Layer::make_layer(b2World *physics_world, uint8_t layer_index,
                         boost::filesystem::path world_yaml_dir,
                         YAML::Node layer_node) {
  std::string name;
  cv::Mat bitmap;
  std::array<double, 4> color;
  std::array<double, 3> origin;
  double resolution, occupied_thresh, free_thresh;

  boost::filesystem::path map_yaml_path;

  if (layer_node["name"]) {
    name = layer_node["name"].as<std::string>();
  } else {
    throw YAMLException("Invalid \"properties\" in " + name + " layer");
  }

  if (layer_node["map"]) {
    map_yaml_path =
        boost::filesystem::path(layer_node["map"].as<std::string>());
  } else {
    throw YAMLException("Invalid \"properties\" in " + name + " layer");
  }

  if (layer_node["color"] && layer_node["color"].IsSequence() &&
      layer_node["color"].size() == 4) {
    color[0] = layer_node["color"][0].as<double>();
    color[1] = layer_node["color"][1].as<double>();
    color[2] = layer_node["color"][2].as<double>();
    color[3] = layer_node["color"][3].as<double>();
  } else {
    throw YAMLException("Invalid \"color\" in " + name + " layer");
  }

  // use absolute path if start with '/', use relative otherwise
  if (map_yaml_path.string().front() != '/') {
    map_yaml_path = world_yaml_dir / map_yaml_path;
  }

  // start parsing the map yaml file
  YAML::Node yaml;

  try {
    yaml = YAML::LoadFile(map_yaml_path.string());
  } catch (const YAML::Exception &e) {
    throw YAMLException("Error loading " + map_yaml_path.string(), e.msg,
                        e.mark);
  }

  if (yaml["resolution"]) {
    resolution = yaml["resolution"].as<double>();
  } else {
    throw YAMLException("Invalid \"resolution\" in " + name + " layer");
  }

  if (yaml["origin"] && yaml["origin"].IsSequence() &&
      yaml["origin"].size() == 3) {
    origin[0] = yaml["origin"][0].as<double>();
    origin[1] = yaml["origin"][1].as<double>();
    origin[2] = yaml["origin"][2].as<double>();
  } else {
    throw YAMLException("Invalid \"origin\" in " + name + " layer");
  }

  if (yaml["occupied_thresh"]) {
    occupied_thresh = yaml["occupied_thresh"].as<double>();
  } else {
    throw YAMLException("Invalid \"occupied_thresh\" in " + name + " layer");
  }

  if (yaml["free_thresh"]) {
    free_thresh = yaml["free_thresh"].as<double>();
  } else {
    throw YAMLException("Invalid \"free_thresh\" in " + name + " layer");
  }

  if (yaml["image"]) {
    boost::filesystem::path image_path(yaml["image"].as<std::string>());

    if (image_path.string().front() != '/') {
      image_path = map_yaml_path.parent_path() / image_path;
    }

    cv::Mat map = cv::imread(image_path.string(), CV_LOAD_IMAGE_GRAYSCALE);
    if (map.empty()) {
      throw YAMLException("Failed to load " + image_path.string());
    }

    map.convertTo(bitmap, CV_32FC1, 1.0 / 255.0);
  } else {
    throw YAMLException("Invalid \"image\" in " + name + " layer");
  }

  return new Layer(physics_world, layer_index, name, bitmap, color, origin,
                   resolution, occupied_thresh, free_thresh);
}

void Layer::vectorize_bitmap() {
  cv::Mat padded_map, obstacle_map;

  // thresholds the map, values between the occupied threshold and 1.0 are
  // considered to be occupied
  cv::inRange(bitmap_, occupied_thresh_, 1.0, obstacle_map);

  // cv::namedWindow( "Display window" );
  // cv::imshow( "Display window", bitmap_ );
  // cv::waitKey(0);

  // pad the top and bottom of the map each with an empty row (255=white). This
  // helps to look at the transition from one row of pixel to another
  cv::copyMakeBorder(obstacle_map, padded_map, 1, 1, 0, 0, cv::BORDER_CONSTANT,
                     255);

  // loop through all the rows, looking at 2 at once
  for (int i = 0; i < padded_map.rows - 1; i++) {
    cv::Mat row1 = padded_map.row(i);
    cv::Mat row2 = padded_map.row(i + 1);
    cv::Mat diff;

    // if the two row are the same value, there is no edge
    // if the two rows are not the same value, there is an edge
    // result is still binary, either 255 or 0
    cv::absdiff(row1, row2, diff);

    int start = 0;
    bool started = false;

    // find all the walls, put the connected walls as a single line segment
    for (int j = 0; j <= diff.total(); j++) {
      bool edge_exists = false;
      if (j < diff.total()) {
        edge_exists = diff.at<uint8_t>(0, j);  // 255 maps to true
      }

      if (edge_exists && !started) {
        start = j;
        started = true;
      } else if (started && !edge_exists) {
        b2EdgeShape edge;
        edge.Set(b2Vec2(start, i), b2Vec2(j, i));
        extracted_edges.push_back(edge);

        started = false;
      }
    }
  }

  // pad the left and right of the map each with an empty column (255).
  cv::copyMakeBorder(obstacle_map, padded_map, 0, 0, 1, 1, cv::BORDER_CONSTANT,
                     255);

  // loop through all the columns, looking at 2 at once
  for (int i = 0; i < padded_map.cols - 1; i++) {
    cv::Mat col1 = padded_map.col(i);
    cv::Mat col2 = padded_map.col(i + 1);
    cv::Mat diff;

    cv::absdiff(col1, col2, diff);

    int start = 0;
    bool started = false;

    for (int j = 0; j <= diff.total(); j++) {
      bool edge_exists = false;
      if (j < diff.total()) {
        edge_exists = diff.at<uint8_t>(j, 0);
      }

      if (edge_exists && !started) {
        start = j;
        started = true;
      } else if (started && !edge_exists) {
        b2EdgeShape edge;
        edge.Set(b2Vec2(i, start), b2Vec2(i, j));
        extracted_edges.push_back(edge);

        started = false;
      }
    }
  }
}

void Layer::load_edges() {
  // rotation from the map yaml origin is ignored
  RotateTranslate transform =
      Geometry::createTransform(origin_[0], origin_[1], 0);

  for (const auto &edge : extracted_edges) {
    b2EdgeShape edge_tf;

    // creates a copy
    b2Vec2 v1 = edge.m_vertex1;
    b2Vec2 v2 = edge.m_vertex2;

    v1.y = bitmap_.rows - v1.y;
    v2.y = bitmap_.rows - v2.y;

    v1.x = v1.x * resolution_;
    v1.y = v1.y * resolution_;
    v2.x = v2.x * resolution_;
    v2.y = v2.y * resolution_;

    b2Vec2 v1_tf = Geometry::transform(v1, transform);
    b2Vec2 v2_tf = Geometry::transform(v2, transform);

    edge_tf.Set(v1_tf, v2_tf);

    b2FixtureDef fixture_def;
    fixture_def.shape = &edge_tf;
    fixture_def.filter.categoryBits = 1 << layer_index_;
    fixture_def.filter.maskBits = fixture_def.filter.categoryBits;
    physics_body_->CreateFixture(&fixture_def);
  }
}

};  // namespace flatland_server
<commit_msg>added user data for Layer<commit_after>/*
 *  ______                   __  __              __
 * /\  _  \           __    /\ \/\ \            /\ \__
 * \ \ \L\ \  __  __ /\_\   \_\ \ \ \____    ___\ \ ,_\   ____
 *  \ \  __ \/\ \/\ \\/\ \  /'_` \ \ '__`\  / __`\ \ \/  /',__\
 *   \ \ \/\ \ \ \_/ |\ \ \/\ \L\ \ \ \L\ \/\ \L\ \ \ \_/\__, `\
 *    \ \_\ \_\ \___/  \ \_\ \___,_\ \_,__/\ \____/\ \__\/\____/
 *     \/_/\/_/\/__/    \/_/\/__,_ /\/___/  \/___/  \/__/\/___/
 * @copyright Copyright 2017 Avidbots Corp.
 * @name	 world.cpp
 * @brief	 implements flatland layer
 * @author Chunshang Li
 *
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2017, Avidbots Corp.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the Avidbots Corp. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#include <Box2D/Box2D.h>
#include <flatland_server/debug_visualization.h>
#include <flatland_server/exceptions.h>
#include <flatland_server/geometry.h>
#include <flatland_server/layer.h>
#include <ros/ros.h>
#include <yaml-cpp/yaml.h>
#include <opencv2/opencv.hpp>
#include <string>

namespace flatland_server {

Layer::Layer(b2World *physics_world, uint8_t layer_index,
             const std::string &name, const cv::Mat &bitmap,
             const std::array<double, 4> &color,
             const std::array<double, 3> &origin, double resolution,
             double occupied_thresh, double free_thresh)
    : Entity(physics_world, name),
      layer_index_(layer_index),
      color_(color),
      origin_(origin),
      resolution_(resolution),
      occupied_thresh_(occupied_thresh),
      free_thresh_(free_thresh) {
  bitmap.copyTo(bitmap_);

  b2BodyDef body_def;
  body_def.type = b2_staticBody;

  physics_body_ = physics_world_->CreateBody(&body_def);
  physics_body_->SetUserData(this);

  vectorize_bitmap();
  load_edges();

  ROS_INFO_NAMED("Layer", "Layer %s added", name_.c_str());
}

Layer::~Layer() { physics_body_->GetWorld()->DestroyBody(physics_body_); }

Layer *Layer::make_layer(b2World *physics_world, uint8_t layer_index,
                         boost::filesystem::path world_yaml_dir,
                         YAML::Node layer_node) {
  std::string name;
  cv::Mat bitmap;
  std::array<double, 4> color;
  std::array<double, 3> origin;
  double resolution, occupied_thresh, free_thresh;

  boost::filesystem::path map_yaml_path;

  if (layer_node["name"]) {
    name = layer_node["name"].as<std::string>();
  } else {
    throw YAMLException("Invalid \"properties\" in " + name + " layer");
  }

  if (layer_node["map"]) {
    map_yaml_path =
        boost::filesystem::path(layer_node["map"].as<std::string>());
  } else {
    throw YAMLException("Invalid \"properties\" in " + name + " layer");
  }

  if (layer_node["color"] && layer_node["color"].IsSequence() &&
      layer_node["color"].size() == 4) {
    color[0] = layer_node["color"][0].as<double>();
    color[1] = layer_node["color"][1].as<double>();
    color[2] = layer_node["color"][2].as<double>();
    color[3] = layer_node["color"][3].as<double>();
  } else {
    throw YAMLException("Invalid \"color\" in " + name + " layer");
  }

  // use absolute path if start with '/', use relative otherwise
  if (map_yaml_path.string().front() != '/') {
    map_yaml_path = world_yaml_dir / map_yaml_path;
  }

  // start parsing the map yaml file
  YAML::Node yaml;

  try {
    yaml = YAML::LoadFile(map_yaml_path.string());
  } catch (const YAML::Exception &e) {
    throw YAMLException("Error loading " + map_yaml_path.string(), e.msg,
                        e.mark);
  }

  if (yaml["resolution"]) {
    resolution = yaml["resolution"].as<double>();
  } else {
    throw YAMLException("Invalid \"resolution\" in " + name + " layer");
  }

  if (yaml["origin"] && yaml["origin"].IsSequence() &&
      yaml["origin"].size() == 3) {
    origin[0] = yaml["origin"][0].as<double>();
    origin[1] = yaml["origin"][1].as<double>();
    origin[2] = yaml["origin"][2].as<double>();
  } else {
    throw YAMLException("Invalid \"origin\" in " + name + " layer");
  }

  if (yaml["occupied_thresh"]) {
    occupied_thresh = yaml["occupied_thresh"].as<double>();
  } else {
    throw YAMLException("Invalid \"occupied_thresh\" in " + name + " layer");
  }

  if (yaml["free_thresh"]) {
    free_thresh = yaml["free_thresh"].as<double>();
  } else {
    throw YAMLException("Invalid \"free_thresh\" in " + name + " layer");
  }

  if (yaml["image"]) {
    boost::filesystem::path image_path(yaml["image"].as<std::string>());

    if (image_path.string().front() != '/') {
      image_path = map_yaml_path.parent_path() / image_path;
    }

    cv::Mat map = cv::imread(image_path.string(), CV_LOAD_IMAGE_GRAYSCALE);
    if (map.empty()) {
      throw YAMLException("Failed to load " + image_path.string());
    }

    map.convertTo(bitmap, CV_32FC1, 1.0 / 255.0);
  } else {
    throw YAMLException("Invalid \"image\" in " + name + " layer");
  }

  return new Layer(physics_world, layer_index, name, bitmap, color, origin,
                   resolution, occupied_thresh, free_thresh);
}

void Layer::vectorize_bitmap() {
  cv::Mat padded_map, obstacle_map;

  // thresholds the map, values between the occupied threshold and 1.0 are
  // considered to be occupied
  cv::inRange(bitmap_, occupied_thresh_, 1.0, obstacle_map);

  // cv::namedWindow( "Display window" );
  // cv::imshow( "Display window", bitmap_ );
  // cv::waitKey(0);

  // pad the top and bottom of the map each with an empty row (255=white). This
  // helps to look at the transition from one row of pixel to another
  cv::copyMakeBorder(obstacle_map, padded_map, 1, 1, 0, 0, cv::BORDER_CONSTANT,
                     255);

  // loop through all the rows, looking at 2 at once
  for (int i = 0; i < padded_map.rows - 1; i++) {
    cv::Mat row1 = padded_map.row(i);
    cv::Mat row2 = padded_map.row(i + 1);
    cv::Mat diff;

    // if the two row are the same value, there is no edge
    // if the two rows are not the same value, there is an edge
    // result is still binary, either 255 or 0
    cv::absdiff(row1, row2, diff);

    int start = 0;
    bool started = false;

    // find all the walls, put the connected walls as a single line segment
    for (int j = 0; j <= diff.total(); j++) {
      bool edge_exists = false;
      if (j < diff.total()) {
        edge_exists = diff.at<uint8_t>(0, j);  // 255 maps to true
      }

      if (edge_exists && !started) {
        start = j;
        started = true;
      } else if (started && !edge_exists) {
        b2EdgeShape edge;
        edge.Set(b2Vec2(start, i), b2Vec2(j, i));
        extracted_edges.push_back(edge);

        started = false;
      }
    }
  }

  // pad the left and right of the map each with an empty column (255).
  cv::copyMakeBorder(obstacle_map, padded_map, 0, 0, 1, 1, cv::BORDER_CONSTANT,
                     255);

  // loop through all the columns, looking at 2 at once
  for (int i = 0; i < padded_map.cols - 1; i++) {
    cv::Mat col1 = padded_map.col(i);
    cv::Mat col2 = padded_map.col(i + 1);
    cv::Mat diff;

    cv::absdiff(col1, col2, diff);

    int start = 0;
    bool started = false;

    for (int j = 0; j <= diff.total(); j++) {
      bool edge_exists = false;
      if (j < diff.total()) {
        edge_exists = diff.at<uint8_t>(j, 0);
      }

      if (edge_exists && !started) {
        start = j;
        started = true;
      } else if (started && !edge_exists) {
        b2EdgeShape edge;
        edge.Set(b2Vec2(i, start), b2Vec2(i, j));
        extracted_edges.push_back(edge);

        started = false;
      }
    }
  }
}

void Layer::load_edges() {
  // rotation from the map yaml origin is ignored
  RotateTranslate transform =
      Geometry::createTransform(origin_[0], origin_[1], 0);

  for (const auto &edge : extracted_edges) {
    b2EdgeShape edge_tf;

    // creates a copy
    b2Vec2 v1 = edge.m_vertex1;
    b2Vec2 v2 = edge.m_vertex2;

    v1.y = bitmap_.rows - v1.y;
    v2.y = bitmap_.rows - v2.y;

    v1.x = v1.x * resolution_;
    v1.y = v1.y * resolution_;
    v2.x = v2.x * resolution_;
    v2.y = v2.y * resolution_;

    b2Vec2 v1_tf = Geometry::transform(v1, transform);
    b2Vec2 v2_tf = Geometry::transform(v2, transform);

    edge_tf.Set(v1_tf, v2_tf);

    b2FixtureDef fixture_def;
    fixture_def.shape = &edge_tf;
    fixture_def.filter.categoryBits = 1 << layer_index_;
    fixture_def.filter.maskBits = fixture_def.filter.categoryBits;
    physics_body_->CreateFixture(&fixture_def);
  }
}

};  // namespace flatland_server
<|endoftext|>