<commit_before>#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class UF {
private:
    char *V;
    int N;
public:
    UF(int N);
    void connect(char a, char b);
    void show(void);
};

int main(void) {
    ios::sync_with_stdio(false);

    int N;

    cin >> N;

    for (int i = 1; i <= N; i++) {
        int V, E;

        cin >> V >> E;
        cin.ignore();

        UF uf(V);

        for (int j = 0; j < E; j++) {
            char a, b;

            cin >> a;
            cin.ignore();

            cin >> b;
            cin.ignore();

            uf.connect(a, b);
        }

        cout << "Case #" << i << ":\n";
        uf.show();
        cout << '\n';
    }

    return 0;
}

UF::UF(int N) {
    this->N = N;
    this->V = new char[this->N];

    for (int i = 0; i < N; i++) {
        this->V[i] = 'a' + i;
    }
}

void UF::connect(char a, char b) {
    char a_value = this->V[a - 'a'];
    char b_value = this->V[b - 'a'];

    if (a_value == b_value) return;

    for (int i = 0; i < this->N; i++) {
        if (this->V[i] == b_value) this->V[i] = a_value;
    }
}

void UF::show(void) {
    vector<char> components[this->N];

    for (int i = 0; i < this->N; i++) {
        components[this->V[i] - 'a'].push_back(char(i + 'a'));
    }

    for (int i = 0; i < this->N; i++) {
        sort(components[i].begin(), components[i].end());
    }

    sort(components, components + this->N, [](const vector<char> &a, const vector<char> &b) -> bool {
        if (a.size() > 0 && b.size() > 0) return a[0] < b[0];
        else if (a.size() > 0 && b.size() == 0) return true;
        else if (a.size() == 0 && b.size() > 0) return false;
        else return false;
    } );

    int connectedComponents = 0;
    for (int i = 0; i < this->N; i++) {
        if (components[i].size() > 0) {
            connectedComponents++;
            for (int j = 0; j < components[i].size(); j++) {
                cout << components[i][j] << ',';
            }
            cout << '\n';
        }
    }

    cout << connectedComponents << " connected components\n";
}
<commit_msg>Grafos: 1082.<commit_after>#include <iostream>
#include <vector>

using namespace std;

class UF {
private:
    char *V;
    int N;
public:
    UF(int N);
    void connect(char a, char b);
    void show(void);
};

int main(void) {
    ios::sync_with_stdio(false);

    int N;

    cin >> N;

    for (int i = 1; i <= N; i++) {
        int V, E;

        cin >> V >> E;
        cin.ignore();

        UF uf(V);

        for (int j = 0; j < E; j++) {
            char a, b;

            cin >> a;
            cin.ignore();

            cin >> b;
            cin.ignore();

            uf.connect(a, b);
        }

        cout << "Case #" << i << ":\n";
        uf.show();
        cout << '\n';
    }

    return 0;
}

UF::UF(int N) {
    this->N = N;
    this->V = new char[this->N];

    for (int i = 0; i < N; i++) {
        this->V[i] = 'a' + i;
    }
}

void UF::connect(char a, char b) {
    char a_value = this->V[a - 'a'];
    char b_value = this->V[b - 'a'];

    if (a_value == b_value) return;

    if (b_value < a_value) {
        this->connect(b, a);
        return;
    }

    for (int i = 0; i < this->N; i++) {
        if (this->V[i] == b_value) this->V[i] = a_value;
    }
}

void UF::show(void) {
    vector<char> components[this->N];

    for (int i = 0; i < this->N; i++) {
        components[this->V[i] - 'a'].push_back(char(i + 'a'));
    }

    int connectedComponents = 0;
    for (int i = 0; i < this->N; i++) {
        if (components[i].size() > 0) {
            connectedComponents++;
            for (int j = 0; j < components[i].size(); j++) {
                cout << components[i][j] << ',';
            }
            cout << '\n';
        }
    }

    cout << connectedComponents << " connected components\n";
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: HtmlReader.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: oj $ $Date: 2002-07-09 12:31:32 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBAUI_HTMLREADER_HXX
#define DBAUI_HTMLREADER_HXX

#ifndef DBAUI_DATABASEEXPORT_HXX
#include "DExport.hxx"
#endif
#ifndef _PARHTML_HXX //autogen
#include <svtools/parhtml.hxx>
#endif
#ifndef _SVX_SVXENUM_HXX
#include <svx/svxenum.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _COM_SUN_STAR_AWT_FONTDESCRIPTOR_HPP_
#include <com/sun/star/awt/FontDescriptor.hpp>
#endif

namespace dbaui
{
    //===============================================================================================
    // OHTMLReader
    //===============================================================================================
    class OHTMLReader : public HTMLParser, public ODatabaseExport
    {

        sal_Int32           m_nTableCount;
        sal_Int16           m_nWidth;
        sal_Int16           m_nColumnWidth;     // max. Spaltenbreite
        sal_Bool            m_bMetaOptions;     // true when we scaned the meta information
        sal_Bool            m_bSDNum;
    protected:
        virtual void        NextToken( int nToken ); // Basisklasse
        virtual sal_Bool    CreateTable(int nToken);

        /** createPage creates the tabpage for this type
            @param  _pParent    teh parent window
        */
        virtual OWizTypeSelect* createPage(Window* _pParent);

        void                TableDataOn(SvxCellHorJustify& eVal,String *pValue,int nToken);
        void                TableFontOn(::com::sun::star::awt::FontDescriptor& _rFont,sal_Int32 &_rTextColor);
        sal_Int16           GetWidthPixel( const HTMLOption* pOption );
        rtl_TextEncoding    GetEncodingByMIME( const String& rMime );
        void                setTextEncoding();
        ~OHTMLReader();
    public:
        OHTMLReader(SvStream& rIn,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& _rxNumberF,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rM,
                    const TColumnVector* rList = 0,
                    const OTypeInfoMap* _pInfoMap = 0);
        // wird f"ur auto. Typ-Erkennung gebraucht
        OHTMLReader(SvStream& rIn,
                    sal_Int32 nRows,
                    const TPositions &_rColumnPositions,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& _rxNumberF,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rM,
                    const TColumnVector* rList = 0,
                    const OTypeInfoMap* _pInfoMap = 0);

        virtual     SvParserState CallParser();// Basisklasse
        virtual     void          release();
        // birgt nur korrekte Daten, wenn der 2. CTOR benutzt wurde
    };

    SV_DECL_IMPL_REF( OHTMLReader );
}
#endif // DBAUI_HTMLREADER_HXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.7.478); FILE MERGED 2005/09/05 17:34:18 rt 1.7.478.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: HtmlReader.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 15:17:56 $
 *
 *  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 DBAUI_HTMLREADER_HXX
#define DBAUI_HTMLREADER_HXX

#ifndef DBAUI_DATABASEEXPORT_HXX
#include "DExport.hxx"
#endif
#ifndef _PARHTML_HXX //autogen
#include <svtools/parhtml.hxx>
#endif
#ifndef _SVX_SVXENUM_HXX
#include <svx/svxenum.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _COM_SUN_STAR_AWT_FONTDESCRIPTOR_HPP_
#include <com/sun/star/awt/FontDescriptor.hpp>
#endif

namespace dbaui
{
    //===============================================================================================
    // OHTMLReader
    //===============================================================================================
    class OHTMLReader : public HTMLParser, public ODatabaseExport
    {

        sal_Int32           m_nTableCount;
        sal_Int16           m_nWidth;
        sal_Int16           m_nColumnWidth;     // max. Spaltenbreite
        sal_Bool            m_bMetaOptions;     // true when we scaned the meta information
        sal_Bool            m_bSDNum;
    protected:
        virtual void        NextToken( int nToken ); // Basisklasse
        virtual sal_Bool    CreateTable(int nToken);

        /** createPage creates the tabpage for this type
            @param  _pParent    teh parent window
        */
        virtual OWizTypeSelect* createPage(Window* _pParent);

        void                TableDataOn(SvxCellHorJustify& eVal,String *pValue,int nToken);
        void                TableFontOn(::com::sun::star::awt::FontDescriptor& _rFont,sal_Int32 &_rTextColor);
        sal_Int16           GetWidthPixel( const HTMLOption* pOption );
        rtl_TextEncoding    GetEncodingByMIME( const String& rMime );
        void                setTextEncoding();
        ~OHTMLReader();
    public:
        OHTMLReader(SvStream& rIn,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& _rxNumberF,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rM,
                    const TColumnVector* rList = 0,
                    const OTypeInfoMap* _pInfoMap = 0);
        // wird f"ur auto. Typ-Erkennung gebraucht
        OHTMLReader(SvStream& rIn,
                    sal_Int32 nRows,
                    const TPositions &_rColumnPositions,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& _rxNumberF,
                    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rM,
                    const TColumnVector* rList = 0,
                    const OTypeInfoMap* _pInfoMap = 0);

        virtual     SvParserState CallParser();// Basisklasse
        virtual     void          release();
        // birgt nur korrekte Daten, wenn der 2. CTOR benutzt wurde
    };

    SV_DECL_IMPL_REF( OHTMLReader );
}
#endif // DBAUI_HTMLREADER_HXX

<|endoftext|>


<commit_before>//==================================================
// Copyright (c) 2015 Deividas Kazlauskas
//
// See the file license.txt for copying permission.
//==================================================

#ifndef DYNAMICVIRTUALMATCHFUNCTOR_8CHO77L5
#define DYNAMICVIRTUALMATCHFUNCTOR_8CHO77L5

#include <functional>
#include <memory>
#include <vector>
#include <mutex>
#include <algorithm>

#include <templatious/util/Exceptions.hpp>
#include <templatious/detail/VirtualMatchFunctor.hpp>

namespace templatious {

TEMPLATIOUS_BOILERPLATE_EXCEPTION(
    DynamicVMatchFunctorNoIdToRemoveException,
    "Couldn't find the specified id to remove." );

/**
 * Dynamic virtual match functor. This class can attach
 * VirtualMatchFunctors for processing with default
 * or custom priority. Threadsafe to attach/detach
 * and match virtual packs.
 */
struct DynamicVMatchFunctor : public VirtualMatchFunctor {
    DynamicVMatchFunctor(bool isBroadcast = false) :
        _isBroadcast(isBroadcast), _idCount(0) {}

    DynamicVMatchFunctor(const DynamicVMatchFunctor&) = delete;

    DynamicVMatchFunctor(DynamicVMatchFunctor&& d) :
        _idCount(d._idCount)
    {
        d.swapTo(*this);
    }

    /**
     * Attach virtual match functor to the processing queue.
     * Returns the id of attached functor to possibly refer
     * to it in the future. Threadsafe.
     * @param[in] vmf unique pointer to a VirtualMatchFunctor
     * to attach.
     * @param[in] priority Priority to set for processing.
     * Match functors with higher priority are processed earlier
     * than the ones with lower priority. Defaults to 128.
     */
    int attach(std::unique_ptr<VirtualMatchFunctor> vmf,int priority = 128) {
        LockGuard l(_mtx);

        int offset = _fctors.size();
        int id = _idCount++;
        _fctors.push_back(std::move(vmf));
        _queue.push_back(QueueUnit(id,offset,priority));
        std::sort( _queue.begin(), _queue.end(),
            [](const QueueUnit& a,const QueueUnit& b) {
                return a._priority > b._priority;
            });

        return id;
    }

    /**
     * Detach virtual match functor with the specified id
     * and return it to the caller wrapped around
     * std::unique_ptr. Throws if no such id exists. Threadsafe.
     * @param[in] id The id of a functor to return.
     */
    std::unique_ptr<VirtualMatchFunctor> detach(int id) {
        LockGuard l(_mtx);

        // it breaks my heart to write boilerplates
        // now, but, I'd rather this be standalone
        // class than be dependant on the entire
        // ecosystem of templatious
        auto end = _queue.end();
        auto i = _queue.begin();
        for (; i != end; ++i) {
            if (i->_id == id) {
                break;
            }
        }

        if (i == end) {
            throw DynamicVMatchFunctorNoIdToRemoveException();
        }

        QueueUnit qu = *i;
        _queue.erase(i);

        i = _queue.begin();
        end = _queue.end();
        // adjust for removal
        for (; i != end; ++i) {
            if (i->_offset > qu._offset) {
                --i->_offset;
            }
        }

        auto fIter = _fctors.begin() + qu._offset;
        ValueType result = std::move(*fIter);
        _fctors.erase(fIter);
        return std::move(result);
    }

    /**
     * Clear all the existing VMatch functors. Threadsafe.
     */
    void clear() {
        LockGuard l(_mtx);
        _fctors.clear();
        _queue.clear();
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(VirtualPack& vp) override {
        LockGuard l(_mtx);

        auto end = _queue.end();
        for (auto i = _queue.begin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            if (curr->tryMatch(vp)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(VirtualPack& vp) const override {
        LockGuard l(_mtx);

        auto end = _queue.end();
        for (auto i = _queue.begin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            if (curr->tryMatch(vp)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(const VirtualPack& vp) override {
        LockGuard l(_mtx);

        auto end = _queue.end();
        for (auto i = _queue.begin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            if (curr->tryMatch(vp)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(const VirtualPack& vp) const override {
        LockGuard l(_mtx);

        auto end = _queue.cend();
        for (auto i = _queue.cbegin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            if (curr->tryMatch(vp)) {
                return true;
            }
        }
        return false;
    }
private:
    struct QueueUnit {
        QueueUnit(int id,int offset,int priority) :
            _id(id), _offset(offset), _priority(priority) {}

        int _id;
        int _offset;
        int _priority;
    };

    void swapTo(DynamicVMatchFunctor& other) {
        LockGuard l(_mtx);
        other._fctors = std::move(_fctors);
        other._queue = std::move(_queue);
    }

    typedef std::unique_ptr< VirtualMatchFunctor > ValueType;
    typedef std::lock_guard< std::mutex > LockGuard;
    mutable std::mutex _mtx;
    bool _isBroadcast;
    int _idCount;
    std::vector< ValueType > _fctors;
    std::vector< QueueUnit > _queue;
};

}

#endif /* end of include guard: DYNAMICVIRTUALMATCHFUNCTOR_8CHO77L5 */
<commit_msg>the dyn fctor<commit_after>//==================================================
// Copyright (c) 2015 Deividas Kazlauskas
//
// See the file license.txt for copying permission.
//==================================================

#ifndef DYNAMICVIRTUALMATCHFUNCTOR_8CHO77L5
#define DYNAMICVIRTUALMATCHFUNCTOR_8CHO77L5

#include <functional>
#include <memory>
#include <vector>
#include <mutex>
#include <algorithm>

#include <templatious/util/Exceptions.hpp>
#include <templatious/detail/VirtualMatchFunctor.hpp>

namespace templatious {

TEMPLATIOUS_BOILERPLATE_EXCEPTION(
    DynamicVMatchFunctorNoIdToRemoveException,
    "Couldn't find the specified id to remove." );

/**
 * Dynamic virtual match functor. This class can attach
 * VirtualMatchFunctors for processing with default
 * or custom priority. Threadsafe to attach/detach
 * and match virtual packs.
 */
struct DynamicVMatchFunctor : public VirtualMatchFunctor {
    DynamicVMatchFunctor(bool isBroadcast = false) :
        _isBroadcast(isBroadcast), _idCount(0) {}

    DynamicVMatchFunctor(const DynamicVMatchFunctor&) = delete;

    DynamicVMatchFunctor(DynamicVMatchFunctor&& d) :
        _idCount(d._idCount)
    {
        d.swapTo(*this);
    }

    /**
     * Attach virtual match functor to the processing queue.
     * Returns the id of attached functor to possibly refer
     * to it in the future. Threadsafe.
     * @param[in] vmf unique pointer to a VirtualMatchFunctor
     * to attach.
     * @param[in] priority Priority to set for processing.
     * Match functors with higher priority are processed earlier
     * than the ones with lower priority. Defaults to 128.
     */
    int attach(std::unique_ptr<VirtualMatchFunctor> vmf,int priority = 128) {
        LockGuard l(_mtx);

        int offset = _fctors.size();
        int id = _idCount++;
        _fctors.push_back(std::move(vmf));
        _queue.push_back(QueueUnit(id,offset,priority));
        std::sort( _queue.begin(), _queue.end(),
            [](const QueueUnit& a,const QueueUnit& b) {
                return a._priority > b._priority;
            });

        return id;
    }

    /**
     * Detach virtual match functor with the specified id
     * and return it to the caller wrapped around
     * std::unique_ptr. Throws if no such id exists. Threadsafe.
     * @param[in] id The id of a functor to return.
     */
    std::unique_ptr<VirtualMatchFunctor> detach(int id) {
        LockGuard l(_mtx);

        // it breaks my heart to write boilerplates
        // now, but, I'd rather this be standalone
        // class than be dependant on the entire
        // ecosystem of templatious
        auto end = _queue.end();
        auto i = _queue.begin();
        for (; i != end; ++i) {
            if (i->_id == id) {
                break;
            }
        }

        if (i == end) {
            throw DynamicVMatchFunctorNoIdToRemoveException();
        }

        QueueUnit qu = *i;
        _queue.erase(i);

        i = _queue.begin();
        end = _queue.end();
        // adjust for removal
        for (; i != end; ++i) {
            if (i->_offset > qu._offset) {
                --i->_offset;
            }
        }

        auto fIter = _fctors.begin() + qu._offset;
        ValueType result = std::move(*fIter);
        _fctors.erase(fIter);
        return std::move(result);
    }

    /**
     * Clear all the existing VMatch functors. Threadsafe.
     */
    void clear() {
        LockGuard l(_mtx);
        _fctors.clear();
        _queue.clear();
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(VirtualPack& vp) override {
        LockGuard l(_mtx);

        auto end = _queue.end();
        bool matched = false;
        for (auto i = _queue.begin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            matched |= curr->tryMatch(vp);
            if (matched && !_isBroadcast) {
                return true;
            }
        }
        return matched;
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(VirtualPack& vp) const override {
        LockGuard l(_mtx);

        auto end = _queue.end();
        bool matched = false;
        for (auto i = _queue.begin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            matched |= curr->tryMatch(vp);
            if (matched && !_isBroadcast) {
                return true;
            }
        }
        return matched;
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(const VirtualPack& vp) override {
        LockGuard l(_mtx);

        auto end = _queue.end();
        bool matched = false;
        for (auto i = _queue.begin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            matched |= curr->tryMatch(vp);
            if (matched && !_isBroadcast) {
                return true;
            }
        }
        return matched;
    }

    /**
     * Try to match virtual pack to this match functor.
     * Only one pack can be processed at a time by
     * multiple threads.
     * @param[in] vp VirtualPack to match.
     */
    bool tryMatch(const VirtualPack& vp) const override {
        LockGuard l(_mtx);

        auto end = _queue.cend();
        bool matched = false;
        for (auto i = _queue.cbegin(); i != end; ++i) {
            auto& curr = _fctors[i->_offset];
            matched |= curr->tryMatch(vp);
            if (matched && !_isBroadcast) {
                return true;
            }
        }
        return matched;
    }
private:
    struct QueueUnit {
        QueueUnit(int id,int offset,int priority) :
            _id(id), _offset(offset), _priority(priority) {}

        int _id;
        int _offset;
        int _priority;
    };

    void swapTo(DynamicVMatchFunctor& other) {
        LockGuard l(_mtx);
        other._fctors = std::move(_fctors);
        other._queue = std::move(_queue);
    }

    typedef std::unique_ptr< VirtualMatchFunctor > ValueType;
    typedef std::lock_guard< std::mutex > LockGuard;
    mutable std::mutex _mtx;
    bool _isBroadcast;
    int _idCount;
    std::vector< ValueType > _fctors;
    std::vector< QueueUnit > _queue;
};

}

#endif /* end of include guard: DYNAMICVIRTUALMATCHFUNCTOR_8CHO77L5 */
<|endoftext|>


<commit_before>// Display how the compiler resolved lookup and overload of specific function
//
//  Usage:
//  show-call <cmake-output-dir> <file1> <file2> ...
//
//  Where <cmake-output-dir> is a CMake build directory in which a file named
//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
//  CMake to get this output).
//
//  <file1> ... specify the paths of files in the CMake source tree. This path
//  is looked up in the compile command database. If the path of a file is
//  absolute, it needs to point into CMake's source tree. If the path is
//  relative, the current working directory needs to be in the CMake source
//  tree and the file must be in a subdirectory of the current working
//  directory. "./" prefixes in the relative files will be automatically
//  removed, but the rest of a relative path must be a suffix of a path in
//  the compile command line database.
//
//  For example, to use show-call on all files in a subtree of the
//  source tree, use:
//
//    /path/in/subtree $ find . -name '*.cpp'|
//        xargs show-call /path/to/build
//
//===----------------------------------------------------------------------===//

#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;

// Set up the command line options
cl::opt<std::string> BuildPath(
  cl::Positional,
  cl::desc("<build-path>"));

cl::list<std::string> SourcePaths(
  cl::Positional,
  cl::desc("<source0> [... <sourceN>]"),
  cl::OneOrMore);

cl::opt<unsigned> CallAtLine(
  "call-at-line",
  cl::desc("Only display call(s) at this line"),
  cl::init(0));

namespace {
void dumpCallInfo(const char *CallKind, const SourceManager &SM, const CallExpr *call) {

  const SourceLocation Loc = call->getLocStart();
  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
  FileID FID = LocInfo.first;
  unsigned FileOffset = LocInfo.second;

  unsigned LineNumber = SM.getLineNumber(FID, FileOffset);

  if (LineNumber != CallAtLine && CallAtLine != 0)
    return;

  errs() << "\n=================================\n"
         << CallKind << " call"
         << " (File:" << SM.getFilename(Loc)
         << " Line:" << LineNumber
         << " Col:" << SM.getColumnNumber(FID, FileOffset) << ")"
         << "\n---------------------------------\n";

  errs() << "Call site:\n";
  call->dump();

  errs() << "\nCalled function: ";
  const FunctionDecl *FD = cast<FunctionDecl>(call->getCalleeDecl());
  FD->printQualifiedName(errs());

  SplitQualType T_split = FD->getType().split();
  errs() << ' ' << QualType::getAsString(T_split);

  if (FD->isDefaulted()) {
    errs() << " (defaulted)\n";
  } else {
    const SourceLocation DLoc = FD->getLocStart();
    std::pair<FileID, unsigned> DLocInfo = SM.getDecomposedLoc(DLoc);
    FileID DFID = DLocInfo.first;
    unsigned DFileOffset = DLocInfo.second;
    errs() << " declared at " << SM.getFilename(DLoc) << ':'
           << SM.getLineNumber(DFID, DFileOffset) << '\n';
  }
}

class SCCallBack : public MatchFinder::MatchCallback {
public:
  SCCallBack(Replacements *Replace) : Replace(Replace) { }

  virtual void run(const MatchFinder::MatchResult &Result) {
    SourceManager &SM = *Result.SourceManager;

    if (const CallExpr *call =
            Result.Nodes.getNodeAs<CallExpr>("call")) {

      const char *callKind = "Function";

      if (isa<CXXMemberCallExpr>(call))
        callKind = "Member";
      else if (isa<CXXOperatorCallExpr>(call))
        callKind = "Operator";

      dumpCallInfo(callKind, SM, call);

      return;
    }

    assert(false && "Unhandled match !");
  }

  void dummy() {
    (void)Replace; // This to prevent an "unused member variable" warning;
  }

private:
  Replacements *Replace;
};
} // end anonymous namespace

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();

  std::unique_ptr<CompilationDatabase> Compilations(
      FixedCompilationDatabase::loadFromCommandLine(argc, argv));

  cl::ParseCommandLineOptions(argc, argv);

  if (!Compilations) { // Couldn't find a compilation DB from the command line
    std::string ErrorMessage;
    Compilations.reset(!BuildPath.empty()
                           ? CompilationDatabase::autoDetectFromDirectory(
                                 BuildPath, ErrorMessage)
                           : CompilationDatabase::autoDetectFromSource(
                                 SourcePaths[0], ErrorMessage));

    //  Still no compilation DB? - bail.
    if (!Compilations)
      llvm::report_fatal_error(ErrorMessage);
  }

  RefactoringTool Tool(*Compilations, SourcePaths);
  ast_matchers::MatchFinder Finder;
  SCCallBack Callback(&Tool.getReplacements());

  Finder.addMatcher(callExpr().bind("call"), &Callback);
  //Finder.addMatcher(
  //    callExpr(callee(methodDecl(hasName("operator=")))).bind("call"),
  //    &Callback);
  //Finder.addMatcher(
  //    memberCallExpr(on(hasType(asString("N::C *"))),
  //                   callee(methodDecl(hasName("f")))).bind("call"),
  //    &Callback);

  return Tool.run(newFrontendActionFactory(&Finder).get());
}
<commit_msg>Improve cosmetic of the callee dump<commit_after>// Display how the compiler resolved lookup and overload of specific function
//
//  Usage:
//  show-call <cmake-output-dir> <file1> <file2> ...
//
//  Where <cmake-output-dir> is a CMake build directory in which a file named
//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
//  CMake to get this output).
//
//  <file1> ... specify the paths of files in the CMake source tree. This path
//  is looked up in the compile command database. If the path of a file is
//  absolute, it needs to point into CMake's source tree. If the path is
//  relative, the current working directory needs to be in the CMake source
//  tree and the file must be in a subdirectory of the current working
//  directory. "./" prefixes in the relative files will be automatically
//  removed, but the rest of a relative path must be a suffix of a path in
//  the compile command line database.
//
//  For example, to use show-call on all files in a subtree of the
//  source tree, use:
//
//    /path/in/subtree $ find . -name '*.cpp'|
//        xargs show-call /path/to/build
//
//===----------------------------------------------------------------------===//

#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;

// Set up the command line options
cl::opt<std::string> BuildPath(
  cl::Positional,
  cl::desc("<build-path>"));

cl::list<std::string> SourcePaths(
  cl::Positional,
  cl::desc("<source0> [... <sourceN>]"),
  cl::OneOrMore);

cl::opt<unsigned> CallAtLine(
  "call-at-line",
  cl::desc("Only display call(s) at this line"),
  cl::init(0));

namespace {
void dumpCallInfo(const char *CallKind, const SourceManager &SM, const CallExpr *call) {

  const SourceLocation Loc = call->getLocStart();
  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
  FileID FID = LocInfo.first;
  unsigned FileOffset = LocInfo.second;

  unsigned LineNumber = SM.getLineNumber(FID, FileOffset);

  if (LineNumber != CallAtLine && CallAtLine != 0)
    return;

  errs() << "\n=================================\n"
         << CallKind << " call"
         << " (File:" << SM.getFilename(Loc)
         << " Line:" << LineNumber
         << " Col:" << SM.getColumnNumber(FID, FileOffset) << ")"
         << "\n---------------------------------\n";

  errs() << "Call site:\n";
  call->dump();

  errs() << "\nCallee:\n";
  const FunctionDecl *FD = cast<FunctionDecl>(call->getCalleeDecl());
  FD->printQualifiedName(errs());

  SplitQualType T_split = FD->getType().split();
  errs() << " with prototype \"" << QualType::getAsString(T_split) << '"';

  if (FD->isDefaulted()) {
    errs() << " (defaulted)\n";
  } else {
    const SourceLocation DLoc = FD->getLocStart();
    std::pair<FileID, unsigned> DLocInfo = SM.getDecomposedLoc(DLoc);
    FileID DFID = DLocInfo.first;
    unsigned DFileOffset = DLocInfo.second;
    errs() << " declared at " << SM.getFilename(DLoc) << ':'
           << SM.getLineNumber(DFID, DFileOffset) << '\n';
  }
}

class SCCallBack : public MatchFinder::MatchCallback {
public:
  SCCallBack(Replacements *Replace) : Replace(Replace) { }

  virtual void run(const MatchFinder::MatchResult &Result) {
    SourceManager &SM = *Result.SourceManager;

    if (const CallExpr *call =
            Result.Nodes.getNodeAs<CallExpr>("call")) {

      const char *callKind = "Function";

      if (isa<CXXMemberCallExpr>(call))
        callKind = "Member";
      else if (isa<CXXOperatorCallExpr>(call))
        callKind = "Operator";

      dumpCallInfo(callKind, SM, call);

      return;
    }

    assert(false && "Unhandled match !");
  }

  void dummy() {
    (void)Replace; // This to prevent an "unused member variable" warning;
  }

private:
  Replacements *Replace;
};
} // end anonymous namespace

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();

  std::unique_ptr<CompilationDatabase> Compilations(
      FixedCompilationDatabase::loadFromCommandLine(argc, argv));

  cl::ParseCommandLineOptions(argc, argv);

  if (!Compilations) { // Couldn't find a compilation DB from the command line
    std::string ErrorMessage;
    Compilations.reset(!BuildPath.empty()
                           ? CompilationDatabase::autoDetectFromDirectory(
                                 BuildPath, ErrorMessage)
                           : CompilationDatabase::autoDetectFromSource(
                                 SourcePaths[0], ErrorMessage));

    //  Still no compilation DB? - bail.
    if (!Compilations)
      llvm::report_fatal_error(ErrorMessage);
  }

  RefactoringTool Tool(*Compilations, SourcePaths);
  ast_matchers::MatchFinder Finder;
  SCCallBack Callback(&Tool.getReplacements());

  Finder.addMatcher(callExpr().bind("call"), &Callback);
  //Finder.addMatcher(
  //    callExpr(callee(methodDecl(hasName("operator=")))).bind("call"),
  //    &Callback);
  //Finder.addMatcher(
  //    memberCallExpr(on(hasType(asString("N::C *"))),
  //                   callee(methodDecl(hasName("f")))).bind("call"),
  //    &Callback);

  return Tool.run(newFrontendActionFactory(&Finder).get());
}
<|endoftext|>


<commit_before>/*
 * Main SDR sequencer thread
 *
 * This file is part of softrig, a simple software defined radio transceiver.
 *
 * Copyright 2017 Alexandru Csete OZ9AEC.
 *
 * 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.
 *
 * 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.
 */
#include <QThread>

#include "interfaces/audio_output.h"
#include "nanosdr/common/datatypes.h"
#include "nanosdr/common/sdr_data.h"
#include "nanosdr/common/time.h"
#include "nanosdr/interfaces/sdr_device.h"
#include "nanosdr/fft_thread.h"
#include "nanosdr/receiver.h"
#include "sdr_thread.h"

#if 1
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
#define SDR_THREAD_DEBUG(...) fprintf(stderr, __VA_ARGS__)
#else
#define SDR_THREAD_DEBUG(...)
#endif

SdrThread::SdrThread(QObject *parent) : QObject(parent)
{
    is_running = false;
    buflen = 30720;            // 20 msec @ 1.536 Msps

    sdr_dev = 0;
    rx = 0;
    fft_data_buf = 0;
    fft_swap_buf = 0;
    input_samples = 0;
    output_samples = 0;
    aout_buffer = 0;
    resetStats();

    audio_out.init();

    fft = new FftThread();
    fft->init(FFT_SIZE, 20);

    thread = new QThread();
    moveToThread(thread);
    connect(thread, SIGNAL(started()), this, SLOT(process()));
    connect(thread, SIGNAL(finished()), this, SLOT(thread_finished()));
    thread->setObjectName("SoftrigSdrThread\n");
    thread->start();
}

SdrThread::~SdrThread()
{
    if (is_running)
        stop();

    thread->requestInterruption();
    thread->quit();
    thread->wait(10000);
    delete thread;

    delete fft;
}

int SdrThread::start(void)
{
    if (is_running)
        return SDR_THREAD_OK;

    SDR_THREAD_DEBUG("Starting SDR thread...\n");

    sdr_dev = sdr_device_create_rtlsdr();
    if (sdr_dev->init(1536000, "") != SDR_DEVICE_OK)
    {
        // FIXME: Emit error string
        return SDR_THREAD_EDEV;
    }
    sdr_dev->set_gain(SDR_DEVICE_RX_LNA_GAIN, 70);

    rx = new Receiver();
    rx->init(1536000, 48000, 100, buflen);

    is_running = true;

    resetStats();
    sdr_dev->start();
    fft->start();
    audio_out.start();

    return SDR_THREAD_OK;
}

void SdrThread::stop(void)
{
    if (!is_running)
        return;

    SDR_THREAD_DEBUG("Stopping SDR thread...\n");

    stats.tstop = time_ms();
    /* *INDENT-OFF* */
    SDR_THREAD_DEBUG("Receiver statistics:\n"
                     "  Time: %" PRIu64 " ms\n"
                     "  Samples in:  %" PRIu64 " samples = %" PRIu64 " sps\n"
                     "  Samples out: %" PRIu64 " samples = %" PRIu64 " sps\n",
                     stats.tstop - stats.tstart,
                     stats.samples_in,
                     (1000 * stats.samples_in) / (stats.tstop - stats.tstart),
                     stats.samples_out,
                     (1000 * stats.samples_out) / (stats.tstop - stats.tstart));
    /* *INDENT-ON* */
    audio_out.stop();
    fft->stop();
    sdr_dev->stop();
    delete sdr_dev;

    delete rx;

    is_running = false;
}

void SdrThread::process(void)
{
    quint32    samples_in = buflen;
    quint32    samples_read;
    int        samples_out;

    SDR_THREAD_DEBUG("SDR process entered\n");

    fft_data_buf = new complex_t[FFT_SIZE];
    fft_swap_buf = new complex_t[FFT_SIZE];
    input_samples = new complex_t[buflen];
    output_samples = new real_t[buflen];
    aout_buffer = new qint16[buflen];

    while (!thread->isInterruptionRequested())
    {
        if (!is_running)
        {
            QThread::msleep(100);
            continue;
        }

        if (sdr_dev->get_num_samples() < samples_in)
        {
            QThread::usleep(2000);
            continue;
        }

        samples_read = sdr_dev->read_samples(input_samples, samples_in);
        if (samples_read == 0)
        {
            QThread::usleep(2000);
            continue;
        }
        stats.samples_in += samples_read;

        // TODO: Decimate

        fft->add_fft_input(samples_read, input_samples);
        samples_out = rx->process(samples_read, input_samples, output_samples);
        // TODO: SSI
        // NOTE: samples_out = -1 means SSI below squelch level

        if (samples_out > 0)
        {
            int    i;

            for (i = 0; i < samples_out; i++)
                aout_buffer[i] = (qint16)(32767.0f * output_samples[i]);

            audio_out.write((const char *) aout_buffer, samples_out * 2);
            stats.samples_out += samples_out;
        }
    }

    /* *INDENT-OFF* */
    delete[] fft_data_buf;
    delete[] fft_swap_buf;
    delete[] aout_buffer;
    delete[] output_samples;
    delete[] input_samples;
    /* *INDENT-ON* */
}

void SdrThread::thread_finished(void)
{
    SDR_THREAD_DEBUG("SDR thread finished\n");
}

void SdrThread::setRxFrequency(qint64 freq)
{
    if (!is_running)
        return;

    if (sdr_dev->set_freq(freq))
        SDR_THREAD_DEBUG("Error setting frequency\n");
}

void SdrThread::setDemod(sdr_demod_t demod)
{
    if (!is_running)           // FIXME
        return;

    rx->set_demod(demod);
}

void SdrThread::setRxFilter(real_t low_cut, real_t high_cut)
{
    if (!is_running)           // FIXME
        return;

    rx->set_filter(low_cut, high_cut);
}

void SdrThread::setRxCwOffset(real_t offset)
{
    if (!is_running)           // FIXME
        return;

    rx->set_cw_offset(offset);
}

void SdrThread::resetStats(void)
{
    stats.tstart = time_ms();
    stats.tstop = 0;
    stats.samples_in = 0;
    stats.samples_out = 0;
}

quint32 SdrThread::getFftData(real_t *fft_data_out)
{
    quint32    fft_samples;
    quint32    i;
    real_t     pwr;

    if ((fft_samples = fft->get_fft_output(fft_data_buf)) == 0)
        return 0;

    // shift buffer
    int    cidx = fft_samples / 2;
    memcpy(fft_swap_buf, &fft_data_buf[cidx], sizeof(complex_t) * cidx);
    memcpy(&fft_swap_buf[cidx], fft_data_buf, sizeof(complex_t) * cidx);

#define FFT_PWR_SCALE   (1.0f / ((float)FFT_SIZE * (float)FFT_SIZE))
    for (i = 0; i < fft_samples; i++)
    {
        pwr = FFT_PWR_SCALE * (fft_swap_buf[i].im * fft_swap_buf[i].im +
                               fft_swap_buf[i].re * fft_swap_buf[i].re);
        fft_data_out[i] = 10.0 * log10f(pwr + 1.0e-20);
    }

    return fft_samples;
}
<commit_msg>Reduce device gain<commit_after>/*
 * Main SDR sequencer thread
 *
 * This file is part of softrig, a simple software defined radio transceiver.
 *
 * Copyright 2017 Alexandru Csete OZ9AEC.
 *
 * 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.
 *
 * 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.
 */
#include <QThread>

#include "interfaces/audio_output.h"
#include "nanosdr/common/datatypes.h"
#include "nanosdr/common/sdr_data.h"
#include "nanosdr/common/time.h"
#include "nanosdr/interfaces/sdr_device.h"
#include "nanosdr/fft_thread.h"
#include "nanosdr/receiver.h"
#include "sdr_thread.h"

#if 1
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
#define SDR_THREAD_DEBUG(...) fprintf(stderr, __VA_ARGS__)
#else
#define SDR_THREAD_DEBUG(...)
#endif

SdrThread::SdrThread(QObject *parent) : QObject(parent)
{
    is_running = false;
    buflen = 30720;            // 20 msec @ 1.536 Msps

    sdr_dev = 0;
    rx = 0;
    fft_data_buf = 0;
    fft_swap_buf = 0;
    input_samples = 0;
    output_samples = 0;
    aout_buffer = 0;
    resetStats();

    audio_out.init();

    fft = new FftThread();
    fft->init(FFT_SIZE, 20);

    thread = new QThread();
    moveToThread(thread);
    connect(thread, SIGNAL(started()), this, SLOT(process()));
    connect(thread, SIGNAL(finished()), this, SLOT(thread_finished()));
    thread->setObjectName("SoftrigSdrThread\n");
    thread->start();
}

SdrThread::~SdrThread()
{
    if (is_running)
        stop();

    thread->requestInterruption();
    thread->quit();
    thread->wait(10000);
    delete thread;

    delete fft;
}

int SdrThread::start(void)
{
    if (is_running)
        return SDR_THREAD_OK;

    SDR_THREAD_DEBUG("Starting SDR thread...\n");

    sdr_dev = sdr_device_create_rtlsdr();
    if (sdr_dev->init(1536000, "") != SDR_DEVICE_OK)
    {
        // FIXME: Emit error string
        return SDR_THREAD_EDEV;
    }
    sdr_dev->set_gain(SDR_DEVICE_RX_LNA_GAIN, 60);

    rx = new Receiver();
    rx->init(1536000, 48000, 100, buflen);

    is_running = true;

    resetStats();
    sdr_dev->start();
    fft->start();
    audio_out.start();

    return SDR_THREAD_OK;
}

void SdrThread::stop(void)
{
    if (!is_running)
        return;

    SDR_THREAD_DEBUG("Stopping SDR thread...\n");

    stats.tstop = time_ms();
    /* *INDENT-OFF* */
    SDR_THREAD_DEBUG("Receiver statistics:\n"
                     "  Time: %" PRIu64 " ms\n"
                     "  Samples in:  %" PRIu64 " samples = %" PRIu64 " sps\n"
                     "  Samples out: %" PRIu64 " samples = %" PRIu64 " sps\n",
                     stats.tstop - stats.tstart,
                     stats.samples_in,
                     (1000 * stats.samples_in) / (stats.tstop - stats.tstart),
                     stats.samples_out,
                     (1000 * stats.samples_out) / (stats.tstop - stats.tstart));
    /* *INDENT-ON* */
    audio_out.stop();
    fft->stop();
    sdr_dev->stop();
    delete sdr_dev;

    delete rx;

    is_running = false;
}

void SdrThread::process(void)
{
    quint32    samples_in = buflen;
    quint32    samples_read;
    int        samples_out;

    SDR_THREAD_DEBUG("SDR process entered\n");

    fft_data_buf = new complex_t[FFT_SIZE];
    fft_swap_buf = new complex_t[FFT_SIZE];
    input_samples = new complex_t[buflen];
    output_samples = new real_t[buflen];
    aout_buffer = new qint16[buflen];

    while (!thread->isInterruptionRequested())
    {
        if (!is_running)
        {
            QThread::msleep(100);
            continue;
        }

        if (sdr_dev->get_num_samples() < samples_in)
        {
            QThread::usleep(2000);
            continue;
        }

        samples_read = sdr_dev->read_samples(input_samples, samples_in);
        if (samples_read == 0)
        {
            QThread::usleep(2000);
            continue;
        }
        stats.samples_in += samples_read;

        // TODO: Decimate

        fft->add_fft_input(samples_read, input_samples);
        samples_out = rx->process(samples_read, input_samples, output_samples);
        // TODO: SSI
        // NOTE: samples_out = -1 means SSI below squelch level

        if (samples_out > 0)
        {
            int    i;

            for (i = 0; i < samples_out; i++)
                aout_buffer[i] = (qint16)(32767.0f * output_samples[i]);

            audio_out.write((const char *) aout_buffer, samples_out * 2);
            stats.samples_out += samples_out;
        }
    }

    /* *INDENT-OFF* */
    delete[] fft_data_buf;
    delete[] fft_swap_buf;
    delete[] aout_buffer;
    delete[] output_samples;
    delete[] input_samples;
    /* *INDENT-ON* */
}

void SdrThread::thread_finished(void)
{
    SDR_THREAD_DEBUG("SDR thread finished\n");
}

void SdrThread::setRxFrequency(qint64 freq)
{
    if (!is_running)
        return;

    if (sdr_dev->set_freq(freq))
        SDR_THREAD_DEBUG("Error setting frequency\n");
}

void SdrThread::setDemod(sdr_demod_t demod)
{
    if (!is_running)           // FIXME
        return;

    rx->set_demod(demod);
}

void SdrThread::setRxFilter(real_t low_cut, real_t high_cut)
{
    if (!is_running)           // FIXME
        return;

    rx->set_filter(low_cut, high_cut);
}

void SdrThread::setRxCwOffset(real_t offset)
{
    if (!is_running)           // FIXME
        return;

    rx->set_cw_offset(offset);
}

void SdrThread::resetStats(void)
{
    stats.tstart = time_ms();
    stats.tstop = 0;
    stats.samples_in = 0;
    stats.samples_out = 0;
}

quint32 SdrThread::getFftData(real_t *fft_data_out)
{
    quint32    fft_samples;
    quint32    i;
    real_t     pwr;

    if ((fft_samples = fft->get_fft_output(fft_data_buf)) == 0)
        return 0;

    // shift buffer
    int    cidx = fft_samples / 2;
    memcpy(fft_swap_buf, &fft_data_buf[cidx], sizeof(complex_t) * cidx);
    memcpy(&fft_swap_buf[cidx], fft_data_buf, sizeof(complex_t) * cidx);

#define FFT_PWR_SCALE   (1.0f / ((float)FFT_SIZE * (float)FFT_SIZE))
    for (i = 0; i < fft_samples; i++)
    {
        pwr = FFT_PWR_SCALE * (fft_swap_buf[i].im * fft_swap_buf[i].im +
                               fft_swap_buf[i].re * fft_swap_buf[i].re);
        fft_data_out[i] = 10.0 * log10f(pwr + 1.0e-20);
    }

    return fft_samples;
}
<|endoftext|>


<commit_before>#ifndef _SDD_INTERNAL_MEM_UNIQUE_TABLE_HH_
#define _SDD_INTERNAL_MEM_UNIQUE_TABLE_HH_

/// @cond INTERNAL_DOC

#include <boost/intrusive/unordered_set.hpp>

namespace sdd { namespace internal { namespace mem {

/*-------------------------------------------------------------------------------------------*/

template <typename Unique>
class unique_table
{
  // Can't copy a unique_table.
  unique_table(const unique_table&) = delete;
  unique_table& operator=(const unique_table&) = delete;

private:

  /// @brief We choose a faster, unsafe mode.
  typedef boost::intrusive::link_mode<boost::intrusive::normal_link> link_mode;

  /// @brief Tell Boost.Intrusive how to access to the member hook.
  typedef boost::intrusive::member_hook< Unique
                                       , boost::intrusive::unordered_set_member_hook<link_mode>
                                       , &Unique::member_hook_>
          member_hook;

  /// @brief Tell Boost.Intrusive we want to use the standard hash mechanism.
  typedef boost::intrusive::hash<std::hash<Unique>> hash_option;

  /// @brief The type of the set that helps to unify data.
  typedef typename boost::intrusive::make_unordered_set<Unique, member_hook, hash_option>::type
          set_type;

  /// @brief A type needed by Boost.Intrusive.
  typedef typename set_type::bucket_type bucket_type;

  /// @brief A type needed by Boost.Intrusive.
  typedef typename set_type::bucket_traits bucket_traits;

  /// @brief The buckets needed by Boost.Intrusive.
  bucket_type* buckets_;

  /// @brief The actual container of unified data.
  set_type* set_;

//  /// @brief The number of hits.
//  std::size_t hits_;
//
//  /// @brief The number of misses.
//  std::size_t misses_;
//
//  /// @brief The number of deleted entries.
//  std::size_t deleted_;

public:

  unique_table(std::size_t initial_size)
  	: buckets_(new bucket_type[set_type::suggested_upper_bucket_count(initial_size)])
    , set_(new set_type(bucket_traits( buckets_
                                     , set_type::suggested_upper_bucket_count(initial_size))))
  {
  }

  unique_table()
    : unique_table(1000000)
  {
  }

  ~unique_table()
  {
    delete set_;
    delete[] buckets_;
  }

  const Unique&
  operator()(Unique* u_ptr)
  {
    if (load_factor() >= 0.9)
    {
      rehash();
    }

    auto insertion = set_->insert(*u_ptr);
    if (not insertion.second)
    {
      delete u_ptr;
    }
    return *insertion.first;
  }

  void
  erase(Unique& x)
  noexcept
  {
    set_->erase_and_dispose(x, [](Unique* ptr){delete ptr;});
  }

  double
  load_factor()
  const noexcept
  {
    return static_cast<double>(set_->size()) / static_cast<double>(set_->bucket_count());
  }

  std::size_t
  size()
  const noexcept
  {
    return set_->size();
  }

private:

  void
  rehash()
  {
    const std::size_t new_size = set_->bucket_count() * 2;
    bucket_type* new_buckets = new bucket_type[new_size];
    set_->rehash(bucket_traits(new_buckets, new_size));
    delete[] buckets_;
    buckets_ = new_buckets;
  }
};

/*-------------------------------------------------------------------------------------------*/

namespace /* anonymous */ {

template <typename Unique>
inline
internal::mem::unique_table<Unique>&
global_unique_table()
noexcept
{
  static internal::mem::unique_table<Unique> unique_table;
  return unique_table;
}

} // namespace anonymous

/*-------------------------------------------------------------------------------------------*/

template <typename Unique>
inline
const Unique&
unify(Unique* u_ptr)
{
  return global_unique_table<Unique>()(u_ptr);
}

/*-------------------------------------------------------------------------------------------*/

}}} // namespace sdd::internal::mem

/// @endcond

#endif // _SDD_INTERNAL_MEM_UNIQUE_TABLE_HH_
<commit_msg>Unique_table's statistics.<commit_after>#ifndef _SDD_INTERNAL_MEM_UNIQUE_TABLE_HH_
#define _SDD_INTERNAL_MEM_UNIQUE_TABLE_HH_

/// @cond INTERNAL_DOC

#include <boost/intrusive/unordered_set.hpp>

namespace sdd { namespace internal { namespace mem {

/*-------------------------------------------------------------------------------------------*/

template <typename Unique>
class unique_table
{
  // Can't copy a unique_table.
  unique_table(const unique_table&) = delete;
  unique_table& operator=(const unique_table&) = delete;

private:

  /// @brief We choose a faster, unsafe mode.
  typedef boost::intrusive::link_mode<boost::intrusive::normal_link> link_mode;

  /// @brief Tell Boost.Intrusive how to access to the member hook.
  typedef boost::intrusive::member_hook< Unique
                                       , boost::intrusive::unordered_set_member_hook<link_mode>
                                       , &Unique::member_hook_>
          member_hook;

  /// @brief Tell Boost.Intrusive we want to use the standard hash mechanism.
  typedef boost::intrusive::hash<std::hash<Unique>> hash_option;

  /// @brief The type of the set that helps to unify data.
  typedef typename boost::intrusive::make_unordered_set<Unique, member_hook, hash_option>::type
          set_type;

  /// @brief A type needed by Boost.Intrusive.
  typedef typename set_type::bucket_type bucket_type;

  /// @brief A type needed by Boost.Intrusive.
  typedef typename set_type::bucket_traits bucket_traits;

  /// @brief The buckets needed by Boost.Intrusive.
  bucket_type* buckets_;

  /// @brief The actual container of unified data.
  set_type* set_;

  /// @brief The number of hits.
  std::size_t hit_;

  /// @brief The number of misses.
  std::size_t miss_;

  /// @brief The number of rehash.
  std::size_t rehash_;

public:

  unique_table(std::size_t initial_size)
  	: buckets_(new bucket_type[set_type::suggested_upper_bucket_count(initial_size)])
    , set_(new set_type(bucket_traits( buckets_
                                     , set_type::suggested_upper_bucket_count(initial_size))))
  {
  }

  unique_table()
    : unique_table(1000000)
  {
  }

  ~unique_table()
  {
    delete set_;
    delete[] buckets_;
  }

  const Unique&
  operator()(Unique* u_ptr)
  {
    if (load_factor() >= 0.9)
    {
      ++rehash_;
      rehash();
    }

    auto insertion = set_->insert(*u_ptr);
    if (not insertion.second)
    {
      ++hit_;
      delete u_ptr;
    }
    else
    {
      ++miss_;
    }
    return *insertion.first;
  }

  void
  erase(Unique& x)
  noexcept
  {
    set_->erase_and_dispose(x, [](Unique* ptr){delete ptr;});
  }

  double
  load_factor()
  const noexcept
  {
    return static_cast<double>(set_->size()) / static_cast<double>(set_->bucket_count());
  }

  std::size_t
  size()
  const noexcept
  {
    return set_->size();
  }

private:

  void
  rehash()
  {
    const std::size_t new_size = set_->bucket_count() * 2;
    bucket_type* new_buckets = new bucket_type[new_size];
    set_->rehash(bucket_traits(new_buckets, new_size));
    delete[] buckets_;
    buckets_ = new_buckets;
  }
};

/*-------------------------------------------------------------------------------------------*/

namespace /* anonymous */ {

template <typename Unique>
inline
internal::mem::unique_table<Unique>&
global_unique_table()
noexcept
{
  static internal::mem::unique_table<Unique> unique_table;
  return unique_table;
}

} // namespace anonymous

/*-------------------------------------------------------------------------------------------*/

template <typename Unique>
inline
const Unique&
unify(Unique* u_ptr)
{
  return global_unique_table<Unique>()(u_ptr);
}

/*-------------------------------------------------------------------------------------------*/

}}} // namespace sdd::internal::mem

/// @endcond

#endif // _SDD_INTERNAL_MEM_UNIQUE_TABLE_HH_
<|endoftext|>


<commit_before>/*
 * copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <dlfcn.h>
#include <signal.h>

#include <cstdio>
#include <cstring>
#include <string>

#include "jni.h"
#include "ScopedLocalRef.h"
#include "toStringArray.h"
#include "UniquePtr.h"

namespace art {

// Determine whether or not the specified method is public.
static bool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) {
  ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(c, method_id, JNI_FALSE));
  if (reflected.get() == NULL) {
    fprintf(stderr, "Failed to get reflected method\n");
    return false;
  }
  // We now have a Method instance.  We need to call its
  // getModifiers() method.
  jclass method_class = env->FindClass("java/lang/reflect/Method");
  if (method_class == NULL) {
    fprintf(stderr, "Failed to find class java.lang.reflect.Method\n");
    return false;
  }
  jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I");
  if (mid == NULL) {
    fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
    return false;
  }
  int modifiers = env->CallIntMethod(reflected.get(), mid);
  static const int PUBLIC = 0x0001;  // java.lang.reflect.Modifiers.PUBLIC
  if ((modifiers & PUBLIC) == 0) {
    return false;
  }
  return true;
}

static int InvokeMain(JNIEnv* env, char** argv) {
  // We want to call main() with a String array with our arguments in
  // it.  Create an array and populate it.  Note argv[0] is not
  // included.
  ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1));
  if (args.get() == NULL) {
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Find [class].main(String[]).

  // Convert "com.android.Blah" to "com/android/Blah".
  std::string class_name(argv[0]);
  std::replace(class_name.begin(), class_name.end(), '.', '/');

  ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str()));
  if (klass.get() == NULL) {
    fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  jmethodID method = env->GetStaticMethodID(klass.get(), "main", "([Ljava/lang/String;)V");
  if (method == NULL) {
    fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Make sure the method is public.  JNI doesn't prevent us from
  // calling a private method, so we have to check it explicitly.
  if (!IsMethodPublic(env, klass.get(), method)) {
    fprintf(stderr, "Sorry, main() is not public in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Invoke main().
  env->CallStaticVoidMethod(klass.get(), method, args.get());

  // Check whether there was an uncaught exception. We don't log any uncaught exception here;
  // detaching this thread will do that for us, but it will clear the exception (and invalidate
  // our JNIEnv), so we need to check here.
  return env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS;
}

// Parse arguments.  Most of it just gets passed through to the runtime.
// The JNI spec defines a handful of standard arguments.
static int dalvikvm(int argc, char** argv) {
  setvbuf(stdout, NULL, _IONBF, 0);

  // Skip over argv[0].
  argv++;
  argc--;

  // If we're adding any additional stuff, e.g. function hook specifiers,
  // add them to the count here.
  //
  // We're over-allocating, because this includes the options to the runtime
  // plus the options to the program.
  int option_count = argc;
  UniquePtr<JavaVMOption[]> options(new JavaVMOption[option_count]());

  // Copy options over.  Everything up to the name of the class starts
  // with a '-' (the function hook stuff is strictly internal).
  //
  // [Do we need to catch & handle "-jar" here?]
  bool need_extra = false;
  const char* lib = "libdvm.so";
  const char* debug = NULL;
  const char* what = NULL;
  int curr_opt, arg_idx;
  for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) {
    if (argv[arg_idx][0] != '-' && !need_extra) {
      break;
    }
    if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) {
      lib = argv[arg_idx] + strlen("-XXlib:");
      continue;
    }

    options[curr_opt++].optionString = argv[arg_idx];

    // Some options require an additional argument.
    need_extra = false;
    if (strcmp(argv[arg_idx], "-classpath") == 0 || strcmp(argv[arg_idx], "-cp") == 0) {
      need_extra = true;
      what = argv[arg_idx];
    }
  }

  if (need_extra) {
    fprintf(stderr, "%s must be followed by an additional argument giving a value\n", what);
    return EXIT_FAILURE;
  }

  // Make sure they provided a class name.
  if (arg_idx == argc) {
    fprintf(stderr, "Class name required\n");
    return EXIT_FAILURE;
  }

  // insert additional internal options here

  if (curr_opt >= option_count) {
    fprintf(stderr, "curr_opt(%d) >= option_count(%d)\n", curr_opt, option_count);
    abort();
    return EXIT_FAILURE;
  }

  // Find the JNI_CreateJavaVM implementation.
  std::string library(lib);
  if (debug != NULL) {
    library += debug;
  }
  void* handle = dlopen(library.c_str(), RTLD_NOW);
  if (handle == NULL) {
    fprintf(stderr, "Failed to dlopen library %s: %s\n", library.c_str(), dlerror());
    return EXIT_FAILURE;
  }
  const char* symbol = "JNI_CreateJavaVM";
  void* sym = dlsym(handle, symbol);
  if (handle == NULL) {
    fprintf(stderr, "Failed to find symbol %s: %s\n", symbol, dlerror());
    return EXIT_FAILURE;
  }
  typedef int (*Fn)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
  Fn JNI_CreateJavaVM = reinterpret_cast<Fn>(sym);

  JavaVMInitArgs init_args;
  init_args.version = JNI_VERSION_1_6;
  init_args.options = options.get();
  init_args.nOptions = curr_opt;
  init_args.ignoreUnrecognized = JNI_FALSE;

  // Start the runtime. The current thread becomes the main thread.
  JavaVM* vm = NULL;
  JNIEnv* env = NULL;
  if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) {
    fprintf(stderr, "Failed to initialize runtime (check log for details)\n");
    return EXIT_FAILURE;
  }

  int rc = InvokeMain(env, &argv[arg_idx]);

#if defined(NDEBUG)
  // The DestroyJavaVM call will detach this thread for us. In debug builds, we don't want to
  // detach because detaching disables the CheckSafeToLockOrUnlock checking.
  if (vm->DetachCurrentThread() != JNI_OK) {
    fprintf(stderr, "Warning: unable to detach main thread\n");
    rc = EXIT_FAILURE;
  }
#endif

  if (vm->DestroyJavaVM() != 0) {
    fprintf(stderr, "Warning: runtime did not shut down cleanly\n");
    rc = EXIT_FAILURE;
  }

  dlclose(handle);
  return rc;
}

} // namespace art

int main(int argc, char** argv) {
  return art::dalvikvm(argc, argv);
}
<commit_msg>Use libnativehelper to find JNI_CreateJavaVM<commit_after>/*
 * copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <signal.h>

#include <cstdio>
#include <cstring>
#include <string>

#include "jni.h"
#include "JniInvocation.h"
#include "ScopedLocalRef.h"
#include "toStringArray.h"
#include "UniquePtr.h"

namespace art {

// Determine whether or not the specified method is public.
static bool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) {
  ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(c, method_id, JNI_FALSE));
  if (reflected.get() == NULL) {
    fprintf(stderr, "Failed to get reflected method\n");
    return false;
  }
  // We now have a Method instance.  We need to call its
  // getModifiers() method.
  jclass method_class = env->FindClass("java/lang/reflect/Method");
  if (method_class == NULL) {
    fprintf(stderr, "Failed to find class java.lang.reflect.Method\n");
    return false;
  }
  jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I");
  if (mid == NULL) {
    fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
    return false;
  }
  int modifiers = env->CallIntMethod(reflected.get(), mid);
  static const int PUBLIC = 0x0001;  // java.lang.reflect.Modifiers.PUBLIC
  if ((modifiers & PUBLIC) == 0) {
    return false;
  }
  return true;
}

static int InvokeMain(JNIEnv* env, char** argv) {
  // We want to call main() with a String array with our arguments in
  // it.  Create an array and populate it.  Note argv[0] is not
  // included.
  ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1));
  if (args.get() == NULL) {
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Find [class].main(String[]).

  // Convert "com.android.Blah" to "com/android/Blah".
  std::string class_name(argv[0]);
  std::replace(class_name.begin(), class_name.end(), '.', '/');

  ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str()));
  if (klass.get() == NULL) {
    fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  jmethodID method = env->GetStaticMethodID(klass.get(), "main", "([Ljava/lang/String;)V");
  if (method == NULL) {
    fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Make sure the method is public.  JNI doesn't prevent us from
  // calling a private method, so we have to check it explicitly.
  if (!IsMethodPublic(env, klass.get(), method)) {
    fprintf(stderr, "Sorry, main() is not public in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Invoke main().
  env->CallStaticVoidMethod(klass.get(), method, args.get());

  // Check whether there was an uncaught exception. We don't log any uncaught exception here;
  // detaching this thread will do that for us, but it will clear the exception (and invalidate
  // our JNIEnv), so we need to check here.
  return env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS;
}

// Parse arguments.  Most of it just gets passed through to the runtime.
// The JNI spec defines a handful of standard arguments.
static int dalvikvm(int argc, char** argv) {
  setvbuf(stdout, NULL, _IONBF, 0);

  // Skip over argv[0].
  argv++;
  argc--;

  // If we're adding any additional stuff, e.g. function hook specifiers,
  // add them to the count here.
  //
  // We're over-allocating, because this includes the options to the runtime
  // plus the options to the program.
  int option_count = argc;
  UniquePtr<JavaVMOption[]> options(new JavaVMOption[option_count]());

  // Copy options over.  Everything up to the name of the class starts
  // with a '-' (the function hook stuff is strictly internal).
  //
  // [Do we need to catch & handle "-jar" here?]
  bool need_extra = false;
  const char* lib = "libdvm.so";
  const char* what = NULL;
  int curr_opt, arg_idx;
  for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) {
    if (argv[arg_idx][0] != '-' && !need_extra) {
      break;
    }
    if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) {
      lib = argv[arg_idx] + strlen("-XXlib:");
      continue;
    }

    options[curr_opt++].optionString = argv[arg_idx];

    // Some options require an additional argument.
    need_extra = false;
    if (strcmp(argv[arg_idx], "-classpath") == 0 || strcmp(argv[arg_idx], "-cp") == 0) {
      need_extra = true;
      what = argv[arg_idx];
    }
  }

  if (need_extra) {
    fprintf(stderr, "%s must be followed by an additional argument giving a value\n", what);
    return EXIT_FAILURE;
  }

  // Make sure they provided a class name.
  if (arg_idx == argc) {
    fprintf(stderr, "Class name required\n");
    return EXIT_FAILURE;
  }

  // insert additional internal options here

  if (curr_opt >= option_count) {
    fprintf(stderr, "curr_opt(%d) >= option_count(%d)\n", curr_opt, option_count);
    abort();
    return EXIT_FAILURE;
  }

  // Find the JNI_CreateJavaVM implementation.
  JniInvocation jni_invocation;
  if (!jni_invocation.Init(lib)) {
    fprintf(stderr, "Failed to initialize JNI invocation API from %s\n", lib);
    return EXIT_FAILURE;
  }

  JavaVMInitArgs init_args;
  init_args.version = JNI_VERSION_1_6;
  init_args.options = options.get();
  init_args.nOptions = curr_opt;
  init_args.ignoreUnrecognized = JNI_FALSE;

  // Start the runtime. The current thread becomes the main thread.
  JavaVM* vm = NULL;
  JNIEnv* env = NULL;
  if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) {
    fprintf(stderr, "Failed to initialize runtime (check log for details)\n");
    return EXIT_FAILURE;
  }

  int rc = InvokeMain(env, &argv[arg_idx]);

#if defined(NDEBUG)
  // The DestroyJavaVM call will detach this thread for us. In debug builds, we don't want to
  // detach because detaching disables the CheckSafeToLockOrUnlock checking.
  if (vm->DetachCurrentThread() != JNI_OK) {
    fprintf(stderr, "Warning: unable to detach main thread\n");
    rc = EXIT_FAILURE;
  }
#endif

  if (vm->DestroyJavaVM() != 0) {
    fprintf(stderr, "Warning: runtime did not shut down cleanly\n");
    rc = EXIT_FAILURE;
  }

  return rc;
}

} // namespace art

int main(int argc, char** argv) {
  return art::dalvikvm(argc, argv);
}
<|endoftext|>


<commit_before>#include <QtWidgets>
#include <QtCore>

#include <qrkernel/settingsManager.h>
#include "dialogs/suggestToCreateDiagramDialog.h"
#include "mainwindow/mainWindow.h"
#include "startWidget.h"
#include "suggestToCreateDiagramWidget.h"
#include "recentProjectsListWidget.h"
#include "recentProjectItem.h"

using namespace qReal;

StartWidget::StartWidget(MainWindow *mainWindow, ProjectManager *projectManager)
	: QWidget()
	, mMainWindow(mainWindow)
	, mProjectManager(projectManager)
	, mProjectListSize(5)
	, mStartWidgetProjectsLayout(new QVBoxLayout())
	, mStartWidgetSessionsLayout(new QHBoxLayout())
{
	QLabel *sessions = new QLabel(tr("Sessions"));
	QLabel *recentProjects = new QLabel(tr("Recent projects"));

	initRecentProjects();

	QVBoxLayout *sessionsLayout = new QVBoxLayout();
	QVBoxLayout *recentProjectsLayout = new QVBoxLayout();
	QHBoxLayout *mainLayout = new QHBoxLayout();

	sessionsLayout->addWidget(sessions);
	sessionsLayout->addLayout(mStartWidgetSessionsLayout);

	recentProjectsLayout->addWidget(recentProjects);
	recentProjectsLayout->addLayout( mStartWidgetProjectsLayout);

	recentProjectsLayout->addStretch(0);

	mainLayout->addLayout(sessionsLayout);
	QWidget *horizontalLineWidget = new QWidget();
	horizontalLineWidget->setFixedWidth(1);
	horizontalLineWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
	horizontalLineWidget->setStyleSheet(QString("background-color: #c0c0c0;"));
	mainLayout->addWidget(horizontalLineWidget);
	mainLayout->addLayout(recentProjectsLayout);

	setLayout(mainLayout);
	QPalette pal(palette());
	QColor const color = QColor::fromHsl(180, 50, 240, 255);
	pal.setColor(QPalette::Background, color);
	setAutoFillBackground(true);
	setPalette(pal);

	sessionsLayout->addWidget(createCommandButton(tr("Open existing project")
			, this, SLOT(openExistingProject()), QKeySequence::Open));

	QCommandLinkButton *openIDLink = new QCommandLinkButton(tr("&Open interpreted diagram"));
	QCommandLinkButton *createIDLink = new QCommandLinkButton(tr("&Create interpreted diagram"));

	mInterpreterButton = openIDLink;
	mCreateInterpreterButton = createIDLink;

	sessionsLayout->addWidget(mCreateInterpreterButton);
	sessionsLayout->addWidget(mInterpreterButton);

	Id const theOnlyDiagram = mMainWindow->editorManager().theOnlyDiagram();
	if (!theOnlyDiagram.isNull()) {
		Id const editor = mMainWindow->editorManager().editors()[0];
		QString diagramIdString = mMainWindow->editorManager().diagramNodeNameString(editor, theOnlyDiagram);

		QSignalMapper *newProjectMapper = new QSignalMapper(this);
		QCommandLinkButton *newLink = createCommandButton(tr("New project")
			, newProjectMapper, SLOT(map()), QKeySequence::New);
		newProjectMapper->setMapping(newLink, diagramIdString);
		connect(newProjectMapper, SIGNAL(mapped(QString)), this, SLOT(createProjectWithDiagram(QString)));

		sessionsLayout->addWidget(newLink);
	}

	sessionsLayout->addStretch(0);
}

void StartWidget::openRecentProject(QString const &fileName)
{
	if (mProjectManager->open(fileName)) {
		emit closeStartTab(0);
	}
}

void StartWidget::openExistingProject()
{
	if (mProjectManager->suggestToOpenExisting()) {
		emit closeStartTab(0);
	}
}

void StartWidget::createProjectWithDiagram(QString const &idString)
{
	if (mMainWindow->createProject(idString)){
		emit closeStartTab(0);
	}
}

void StartWidget::initRecentProjects()
{
	int i = 0;
	QString const recentProjects = SettingsManager::value("recentProjects").toString();
	foreach (QString const &project, recentProjects.split(";", QString::SkipEmptyParts)) {
		QString const name = project.split("/").last().split("\\").last();
		if ("autosave.qrs"== name) {
			QString currentProject = QString("%1").arg(tr("•  default (current session)"), project);
			QLabel *currentProjectLabel = new QLabel(currentProject, this);
			mStartWidgetSessionsLayout->addSpacing(25);
			mStartWidgetSessionsLayout->addWidget(currentProjectLabel);
		} else {
			RecentProjectItem *projectWidget = new RecentProjectItem(this, name, project);
					mStartWidgetProjectsLayout->addWidget(projectWidget);

			++i;

			if (i == mProjectListSize) {
				break;
			}
		}
	}
}

void StartWidget::openInterpretedDiagram()
{
	hide();
	QString const fileName = mProjectManager->openFileName(tr("Select file with metamodel to open"));
	ProxyEditorManager &editorManagerProxy = mMainWindow->editorManagerProxy();

	if (!fileName.isEmpty() && mProjectManager->open(fileName)) {
			editorManagerProxy.setProxyManager(new InterpreterEditorManager(fileName));
			QStringList interpreterDiagramsList;
			foreach (Id const &editor, editorManagerProxy.editors()) {
					foreach (Id const &diagram, editorManagerProxy.diagrams(editor)) {
							QString const diagramNodeName = editorManagerProxy.diagramNodeName(editor.editor(), diagram.diagram());
							if (diagramNodeName.isEmpty()) {
									continue;
							}

							interpreterDiagramsList.append("qrm:/" + editor.editor() + "/"
											+ diagram.diagram() + "/" + diagramNodeName);
					}
			}

			foreach (QString const &interpreterIdString, interpreterDiagramsList) {
					// TODO: ???
					mMainWindow->models()->repoControlApi().exterminate();
					mMainWindow->models()->reinit();
					mMainWindow->loadPlugins();
					mMainWindow->createDiagram(interpreterIdString);
			}
	} else {
			show();
			editorManagerProxy.setProxyManager(new EditorManager());
	}
}

void StartWidget::createInterpretedDiagram()
{
	hide();
	ProxyEditorManager &editorManagerProxy = mMainWindow->editorManagerProxy();
	editorManagerProxy.setProxyManager(new InterpreterEditorManager(""));
	bool ok = false;
	QString name = QInputDialog::getText(this, tr("Enter the diagram name:"), tr("diagram name:")
					, QLineEdit::Normal, "", &ok);
	while (ok && name.isEmpty()) {
		name = QInputDialog::getText(this, tr("Enter the diagram name:"), tr("diagram name:")
						, QLineEdit::Normal, "", &ok);
	}

	if (ok) {
		QPair<Id, Id> editorAndDiagram = editorManagerProxy.createEditorAndDiagram(name);
		mMainWindow->addEditorElementsToPalette(editorAndDiagram.first, editorAndDiagram.second);
		mMainWindow->models()->repoControlApi().exterminate();
		mMainWindow->models()->reinit();
		mMainWindow->loadPlugins();
	} else {
		show();
		editorManagerProxy.setProxyManager(new EditorManager());
	}
}

QCommandLinkButton *StartWidget::createCommandButton(QString const &text
			, QObject const *reciever, char const *slot, QKeySequence::StandardKey standartHotkey)
{
	QCommandLinkButton * const result = new QCommandLinkButton(text);
	connect(result, SIGNAL(clicked()), reciever, slot);
	QAction * const buttonAction = new QAction(this);
	buttonAction->setShortcuts(standartHotkey);
	connect(buttonAction, SIGNAL(triggered()), result, SLOT(animateClick()));
	addAction(buttonAction);
	result->setToolTip(QKeySequence(standartHotkey).toString());
	return result;
}

void StartWidget::setVisibleForInterpreterButton(bool const visible)
{
	mInterpreterButton->setVisible(visible);
	mCreateInterpreterButton->setVisible(visible);
}
<commit_msg>Added plugins list into start tab<commit_after>#include <QtWidgets>
#include <QtCore>

#include <qrkernel/settingsManager.h>
#include "dialogs/suggestToCreateDiagramDialog.h"
#include "mainwindow/mainWindow.h"
#include "startWidget.h"
#include "suggestToCreateDiagramWidget.h"
#include "recentProjectsListWidget.h"
#include "recentProjectItem.h"

using namespace qReal;

StartWidget::StartWidget(MainWindow *mainWindow, ProjectManager *projectManager)
	: QWidget()
	, mMainWindow(mainWindow)
	, mProjectManager(projectManager)
	, mProjectListSize(5)
	, mStartWidgetProjectsLayout(new QVBoxLayout())
	, mStartWidgetSessionsLayout(new QHBoxLayout())
{
	QLabel *sessions = new QLabel(tr("Sessions"));
	QLabel *recentProjects = new QLabel(tr("Recent projects"));

	initRecentProjects();

	QVBoxLayout *sessionsLayout = new QVBoxLayout();
	QVBoxLayout *recentProjectsLayout = new QVBoxLayout();
	QHBoxLayout *mainLayout = new QHBoxLayout();

	sessionsLayout->addWidget(sessions);
	sessionsLayout->addLayout(mStartWidgetSessionsLayout);

	recentProjectsLayout->addWidget(recentProjects);
	recentProjectsLayout->addLayout(mStartWidgetProjectsLayout);

	recentProjectsLayout->addStretch(0);

	mainLayout->addLayout(sessionsLayout);
	QWidget *horizontalLineWidget = new QWidget();
	horizontalLineWidget->setFixedWidth(1);
	horizontalLineWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
	horizontalLineWidget->setStyleSheet(QString("background-color: #c0c0c0;"));
	mainLayout->addWidget(horizontalLineWidget);
	mainLayout->addLayout(recentProjectsLayout);

	setLayout(mainLayout);
	QPalette pal(palette());
	QColor const color = QColor::fromHsl(180, 50, 240, 255);
	pal.setColor(QPalette::Background, color);
	setAutoFillBackground(true);
	setPalette(pal);

	sessionsLayout->addWidget(createCommandButton(tr("Open existing project")
			, this, SLOT(openExistingProject()), QKeySequence::Open));

	QSignalMapper *closeTabMapper = new QSignalMapper(this);
	connect(closeTabMapper, SIGNAL(mapped(int)), this, SIGNAL(closeStartTab(int)), Qt::QueuedConnection);

	QCommandLinkButton *openIDLink = new QCommandLinkButton(tr("&Open interpreted diagram"));
	QCommandLinkButton *createIDLink = new QCommandLinkButton(tr("&Create interpreted diagram"));
	connect(openIDLink, SIGNAL(clicked()), this, SLOT(openInterpretedDiagram()));
	connect(createIDLink, SIGNAL(clicked()), this, SLOT(createInterpretedDiagram()));
	connect(openIDLink, SIGNAL(clicked()), closeTabMapper, SLOT(map()));
	connect(createIDLink, SIGNAL(clicked()), closeTabMapper, SLOT(map()));

	mInterpreterButton = openIDLink;
	mCreateInterpreterButton = createIDLink;

	sessionsLayout->addWidget(mCreateInterpreterButton);
	sessionsLayout->addWidget(mInterpreterButton);

	Id const theOnlyDiagram = mMainWindow->editorManager().theOnlyDiagram();
	if (!theOnlyDiagram.isNull()) {
		Id const editor = mMainWindow->editorManager().editors()[0];
		QString diagramIdString = mMainWindow->editorManager().diagramNodeNameString(editor, theOnlyDiagram);

		QSignalMapper *newProjectMapper = new QSignalMapper(this);
		QCommandLinkButton *newLink = createCommandButton(tr("New project")
			, newProjectMapper, SLOT(map()), QKeySequence::New);
		newProjectMapper->setMapping(newLink, diagramIdString);
		connect(newProjectMapper, SIGNAL(mapped(QString)), this, SLOT(createProjectWithDiagram(QString)));

		sessionsLayout->addWidget(newLink);
	} else {
		SuggestToCreateDiagramWidget *suggestWidget = new SuggestToCreateDiagramWidget(mainWindow, this);
		closeTabMapper->setMapping(suggestWidget, 0);
		connect(suggestWidget, SIGNAL(userDataSelected(QString)), mainWindow, SLOT(createDiagram(QString)));
		connect(suggestWidget, SIGNAL(userDataSelected(QString)), closeTabMapper, SLOT(map()));
		sessionsLayout->insertWidget(1 /* after header */, suggestWidget);
	}

	sessionsLayout->addStretch(0);
}

void StartWidget::openRecentProject(QString const &fileName)
{
	if (mProjectManager->open(fileName)) {
		emit closeStartTab(0);
	}
}

void StartWidget::openExistingProject()
{
	if (mProjectManager->suggestToOpenExisting()) {
		emit closeStartTab(0);
	}
}

void StartWidget::createProjectWithDiagram(QString const &idString)
{
	if (mMainWindow->createProject(idString)){
		emit closeStartTab(0);
	}
}

void StartWidget::initRecentProjects()
{
	int i = 0;
	QString const recentProjects = SettingsManager::value("recentProjects").toString();
	foreach (QString const &project, recentProjects.split(";", QString::SkipEmptyParts)) {
		QString const name = project.split("/").last().split("\\").last();
		if ("autosave.qrs"== name) {
			QString currentProject = QString("%1").arg(tr("•  default (current session)"), project);
			QLabel *currentProjectLabel = new QLabel(currentProject, this);
			mStartWidgetSessionsLayout->addSpacing(25);
			mStartWidgetSessionsLayout->addWidget(currentProjectLabel);
		} else {
			RecentProjectItem *projectWidget = new RecentProjectItem(this, name, project);
					mStartWidgetProjectsLayout->addWidget(projectWidget);

			++i;

			if (i == mProjectListSize) {
				break;
			}
		}
	}
}

void StartWidget::openInterpretedDiagram()
{
	hide();
	QString const fileName = mProjectManager->openFileName(tr("Select file with metamodel to open"));
	ProxyEditorManager &editorManagerProxy = mMainWindow->editorManagerProxy();

	if (!fileName.isEmpty() && mProjectManager->open(fileName)) {
			editorManagerProxy.setProxyManager(new InterpreterEditorManager(fileName));
			QStringList interpreterDiagramsList;
			foreach (Id const &editor, editorManagerProxy.editors()) {
					foreach (Id const &diagram, editorManagerProxy.diagrams(editor)) {
							QString const diagramNodeName = editorManagerProxy.diagramNodeName(editor.editor(), diagram.diagram());
							if (diagramNodeName.isEmpty()) {
									continue;
							}

							interpreterDiagramsList.append("qrm:/" + editor.editor() + "/"
											+ diagram.diagram() + "/" + diagramNodeName);
					}
			}

			foreach (QString const &interpreterIdString, interpreterDiagramsList) {
					// TODO: ???
					mMainWindow->models()->repoControlApi().exterminate();
					mMainWindow->models()->reinit();
					mMainWindow->loadPlugins();
					mMainWindow->createDiagram(interpreterIdString);
			}
	} else {
			show();
			editorManagerProxy.setProxyManager(new EditorManager());
	}
}

void StartWidget::createInterpretedDiagram()
{
	hide();
	ProxyEditorManager &editorManagerProxy = mMainWindow->editorManagerProxy();
	editorManagerProxy.setProxyManager(new InterpreterEditorManager(""));
	bool ok = false;
	QString name = QInputDialog::getText(this, tr("Enter the diagram name:"), tr("diagram name:")
					, QLineEdit::Normal, "", &ok);
	while (ok && name.isEmpty()) {
		name = QInputDialog::getText(this, tr("Enter the diagram name:"), tr("diagram name:")
						, QLineEdit::Normal, "", &ok);
	}

	if (ok) {
		QPair<Id, Id> editorAndDiagram = editorManagerProxy.createEditorAndDiagram(name);
		mMainWindow->addEditorElementsToPalette(editorAndDiagram.first, editorAndDiagram.second);
		mMainWindow->models()->repoControlApi().exterminate();
		mMainWindow->models()->reinit();
		mMainWindow->loadPlugins();
	} else {
		show();
		editorManagerProxy.setProxyManager(new EditorManager());
	}
}

QCommandLinkButton *StartWidget::createCommandButton(QString const &text
			, QObject const *reciever, char const *slot, QKeySequence::StandardKey standartHotkey)
{
	QCommandLinkButton * const result = new QCommandLinkButton(text);
	connect(result, SIGNAL(clicked()), reciever, slot);
	QAction * const buttonAction = new QAction(this);
	buttonAction->setShortcuts(standartHotkey);
	connect(buttonAction, SIGNAL(triggered()), result, SLOT(animateClick()));
	addAction(buttonAction);
	result->setToolTip(QKeySequence(standartHotkey).toString());
	return result;
}

void StartWidget::setVisibleForInterpreterButton(bool const visible)
{
	mInterpreterButton->setVisible(visible);
	mCreateInterpreterButton->setVisible(visible);
}
<|endoftext|>