<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "virtual_allocator.hpp"
#include "paging.hpp"

namespace {

constexpr const size_t virtual_start = paging::virtual_paging_start + (paging::physical_memory_pages * paging::PAGE_SIZE);
constexpr const size_t first_virtual_address = virtual_start % 0x100000 == 0 ? virtual_start : (virtual_start / 0x100000 + 1) * 0x100000;

size_t next_virtual_address = first_virtual_address;
size_t allocated_pages = first_virtual_address / paging::PAGE_SIZE;

} //end of anonymous namespace

void virtual_allocator::init(){

}

size_t virtual_allocator::allocate(size_t pages){
    allocated_pages += pages;

    auto address = next_virtual_address;
    next_virtual_address += pages * paging::PAGE_SIZE;
    return address;
}

size_t virtual_allocator::available(){
    return kernel_virtual_size;
}

size_t virtual_allocator::allocated(){
    return allocated_pages * paging::PAGE_SIZE;
}

size_t virtual_allocator::free(){
    return available() - allocated();
}
<commit_msg>Prepare virtual allocator implementation<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "stl/array.hpp"

#include "virtual_allocator.hpp"
#include "paging.hpp"

namespace {

constexpr const size_t virtual_start = paging::virtual_paging_start + (paging::physical_memory_pages * paging::PAGE_SIZE);
constexpr const size_t first_virtual_address = virtual_start % 0x100000 == 0 ? virtual_start : (virtual_start / 0x100000 + 1) * 0x100000;
constexpr const size_t last_virtual_address = virtual_allocator::kernel_virtual_size;
constexpr const size_t managed_space = last_virtual_address - first_virtual_address;
constexpr const size_t unit = paging::PAGE_SIZE;

size_t next_virtual_address = first_virtual_address;
size_t allocated_pages = first_virtual_address / paging::PAGE_SIZE;

struct static_bitmap {
    typedef uint64_t data_type;

    static constexpr const size_t bits_per_word = sizeof(data_type) * 8;

    size_t words;
    data_type* data;

    template<typename Array>
    void init(Array& array){
        words = array.size();
        data = array.data();
    }

    static constexpr size_t word_offset(size_t bit){
        return bit / bits_per_word;
    }

    static constexpr size_t bit_offset(size_t bit){
        return bit % bits_per_word;
    }

    static constexpr data_type bit_mask(size_t bit){
        return static_cast<data_type>(1) << bit_offset(bit);
    }

    void clear_all(){
        for(size_t i = 0; i < words; ++i){
            data[i] = 0;
        }
    }

    void set_all(){
        for(size_t i = 0; i < words; ++i){
            data[i] = ~static_cast<data_type>(0);
        }
    }

    size_t free_bit() const {
        for(size_t w = 0; w < words; ++w){
            if(data[w] > 0){
                for(size_t b = 0; b < bits_per_word; ++b){
                    if(data[w] & bit_mask(b)){
                        return w * bits_per_word + b;
                    }
                }
            }
        }

        //TODO Use an assert here
        return 0;
    }

    bool is_set(size_t bit) const {
        return data[word_offset(bit)] & bit_mask(bit);
    }

    void set(size_t bit){
        data[word_offset(bit)] |= bit_mask(bit);
    }

    void unset(size_t bit){
        data[word_offset(bit)] &= ~bit_mask(bit);
    }
};

constexpr size_t array_size(int block){
    return (managed_space / (block * unit) + 1) / (sizeof(uint64_t) * 8) + 1;
}

static constexpr const size_t levels = 8;
static constexpr const size_t max_block = 128;

std::array<uint64_t, array_size(1)> data_bitmap_1;
std::array<uint64_t, array_size(2)> data_bitmap_2;
std::array<uint64_t, array_size(4)> data_bitmap_4;
std::array<uint64_t, array_size(8)> data_bitmap_8;
std::array<uint64_t, array_size(16)> data_bitmap_16;
std::array<uint64_t, array_size(32)> data_bitmap_32;
std::array<uint64_t, array_size(64)> data_bitmap_64;
std::array<uint64_t, array_size(128)> data_bitmap_128;

std::array<static_bitmap, levels> bitmaps;

size_t level(size_t pages){
    if(pages > 64){
        return 7;
    } else if(pages > 32){
        return 6;
    } else if(pages > 16){
        return 5;
    } else if(pages > 8){
        return 4;
    } else if(pages > 4){
        return 3;
    } else if(pages > 2){
        return 2;
    } else if(pages > 1){
        return 1;
    } else {
        return 0;
    }
}

size_t get_free_block_index(size_t level){
    auto& bitmap = bitmaps[level];
    return bitmap.free_bit();
}

} //end of anonymous namespace

void virtual_allocator::init(){
    //Give room to the bitmaps
    bitmaps[0].init(data_bitmap_1);
    bitmaps[1].init(data_bitmap_2);
    bitmaps[2].init(data_bitmap_4);
    bitmaps[3].init(data_bitmap_8);
    bitmaps[4].init(data_bitmap_16);
    bitmaps[5].init(data_bitmap_32);
    bitmaps[6].init(data_bitmap_64);
    bitmaps[7].init(data_bitmap_128);

    //By default all blocks are free
    for(auto& bitmap : bitmaps){
        bitmap.set_all();
    }
}

size_t virtual_allocator::allocate(size_t pages){
    allocated_pages += pages;

    if(pages > max_block){
        //TODO Special algorithm for big pages
    } else {
        auto l = level(pages);
        auto index = get_free_block_index(l);
    }

    auto address = next_virtual_address;
    next_virtual_address += pages * paging::PAGE_SIZE;
    return address;
}

size_t virtual_allocator::available(){
    return kernel_virtual_size;
}

size_t virtual_allocator::allocated(){
    return allocated_pages * paging::PAGE_SIZE;
}

size_t virtual_allocator::free(){
    return available() - allocated();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svpframe.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-24 10:27:17 $
 *
 *  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 _SVP_SVPFRAME_HXX

#include <vcl/salframe.hxx>
#include <vcl/sysdata.hxx>

#include "svpelement.hxx"

#include <list>

class SvpSalInstance;
class SvpSalGraphics;

class SvpSalFrame : public SalFrame, public SvpElement
{
    SvpSalInstance*                     m_pInstance;
    SvpSalFrame*                        m_pParent;       // pointer to parent frame
    std::list< SvpSalFrame* >           m_aChildren;     // List of child frames
    ULONG                               m_nStyle;
    bool                                m_bVisible;
    long                                m_nMinWidth;
    long                                m_nMinHeight;
    long                                m_nMaxWidth;
    long                                m_nMaxHeight;

    SystemEnvData                       m_aSystemChildData;

    basebmp::BitmapDeviceSharedPtr      m_aFrame;
    std::list< SvpSalGraphics* >        m_aGraphics;

    static SvpSalFrame*       s_pFocusFrame;
public:
    SvpSalFrame( SvpSalInstance* pInstance,
                 SalFrame* pParent,
                 ULONG nSalFrameStyle,
                 SystemParentData* pSystemParent = NULL );
    virtual ~SvpSalFrame();

    void GetFocus();
    void LoseFocus();
    void PostPaint() const;

    // SvpElement
    virtual const basebmp::BitmapDeviceSharedPtr& getDevice() const { return m_aFrame; }

    // SalFrame
    virtual SalGraphics*        GetGraphics();
    virtual void                ReleaseGraphics( SalGraphics* pGraphics );

    virtual BOOL                PostEvent( void* pData );

    virtual void                SetTitle( const XubString& rTitle );
    virtual void                SetIcon( USHORT nIcon );
    virtual void                SetMenu( SalMenu* pMenu );
    virtual void                                DrawMenuBar();

    virtual void                SetExtendedFrameStyle( SalExtStyle nExtStyle );
    virtual void                Show( BOOL bVisible, BOOL bNoActivate = FALSE );
    virtual void                Enable( BOOL bEnable );
    virtual void                SetMinClientSize( long nWidth, long nHeight );
    virtual void                SetMaxClientSize( long nWidth, long nHeight );
    virtual void                SetPosSize( long nX, long nY, long nWidth, long nHeight, USHORT nFlags );
    virtual void                GetClientSize( long& rWidth, long& rHeight );
    virtual void                GetWorkArea( Rectangle& rRect );
    virtual SalFrame*           GetParent() const;
    virtual void                SetWindowState( const SalFrameState* pState );
    virtual BOOL                GetWindowState( SalFrameState* pState );
    virtual void                ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay );
    virtual void                StartPresentation( BOOL bStart );
    virtual void                SetAlwaysOnTop( BOOL bOnTop );
    virtual void                ToTop( USHORT nFlags );
    virtual void                SetPointer( PointerStyle ePointerStyle );
    virtual void                CaptureMouse( BOOL bMouse );
    virtual void                SetPointerPos( long nX, long nY );
    virtual void                Flush();
    virtual void                Sync();
    virtual void                SetInputContext( SalInputContext* pContext );
    virtual void                EndExtTextInput( USHORT nFlags );
    virtual String              GetKeyName( USHORT nKeyCode );
    virtual String              GetSymbolKeyName( const XubString& rFontName, USHORT nKeyCode );
    virtual BOOL                MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode );
    virtual LanguageType        GetInputLanguage();
    virtual SalBitmap*          SnapShot();
    virtual void                UpdateSettings( AllSettings& rSettings );
    virtual void                Beep( SoundType eSoundType );
    virtual const SystemEnvData*    GetSystemData() const;
    virtual SalPointerState     GetPointerState();
    virtual void                SetParent( SalFrame* pNewParent );
    virtual bool                SetPluginParent( SystemParentData* pNewParent );
    virtual void                SetBackgroundBitmap( SalBitmap* pBitmap );
    virtual void                ResetClipRegion();
    virtual void                BeginSetClipRegion( ULONG nRects );
    virtual void                UnionClipRegion( long nX, long nY, long nWidth, long nHeight );
    virtual void                EndSetClipRegion();
};
#endif // _SVP_SVPFRAME_HXX
<commit_msg>INTEGRATION: CWS aquavcl05_DEV300 (1.2.148); FILE MERGED 2008/02/14 21:48:01 pl 1.2.148.1: fix warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svpframe.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-05 17:12:12 $
 *
 *  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 _SVP_SVPFRAME_HXX

#include <vcl/salframe.hxx>
#include <vcl/sysdata.hxx>

#include "svpelement.hxx"

#include <list>

class SvpSalInstance;
class SvpSalGraphics;

class SvpSalFrame : public SalFrame, public SvpElement
{
    SvpSalInstance*                     m_pInstance;
    SvpSalFrame*                        m_pParent;       // pointer to parent frame
    std::list< SvpSalFrame* >           m_aChildren;     // List of child frames
    ULONG                               m_nStyle;
    bool                                m_bVisible;
    long                                m_nMinWidth;
    long                                m_nMinHeight;
    long                                m_nMaxWidth;
    long                                m_nMaxHeight;

    SystemEnvData                       m_aSystemChildData;

    basebmp::BitmapDeviceSharedPtr      m_aFrame;
    std::list< SvpSalGraphics* >        m_aGraphics;

    static SvpSalFrame*       s_pFocusFrame;
public:
    SvpSalFrame( SvpSalInstance* pInstance,
                 SalFrame* pParent,
                 ULONG nSalFrameStyle,
                 SystemParentData* pSystemParent = NULL );
    virtual ~SvpSalFrame();

    void GetFocus();
    void LoseFocus();
    void PostPaint() const;

    // SvpElement
    virtual const basebmp::BitmapDeviceSharedPtr& getDevice() const { return m_aFrame; }

    // SalFrame
    virtual SalGraphics*        GetGraphics();
    virtual void                ReleaseGraphics( SalGraphics* pGraphics );

    virtual BOOL                PostEvent( void* pData );

    virtual void                SetTitle( const XubString& rTitle );
    virtual void                SetIcon( USHORT nIcon );
    virtual void                SetMenu( SalMenu* pMenu );
    virtual void                                DrawMenuBar();

    virtual void                SetExtendedFrameStyle( SalExtStyle nExtStyle );
    virtual void                Show( BOOL bVisible, BOOL bNoActivate = FALSE );
    virtual void                Enable( BOOL bEnable );
    virtual void                SetMinClientSize( long nWidth, long nHeight );
    virtual void                SetMaxClientSize( long nWidth, long nHeight );
    virtual void                SetPosSize( long nX, long nY, long nWidth, long nHeight, USHORT nFlags );
    virtual void                GetClientSize( long& rWidth, long& rHeight );
    virtual void                GetWorkArea( Rectangle& rRect );
    virtual SalFrame*           GetParent() const;
    virtual void                SetWindowState( const SalFrameState* pState );
    virtual BOOL                GetWindowState( SalFrameState* pState );
    virtual void                ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay );
    virtual void                StartPresentation( BOOL bStart );
    virtual void                SetAlwaysOnTop( BOOL bOnTop );
    virtual void                ToTop( USHORT nFlags );
    virtual void                SetPointer( PointerStyle ePointerStyle );
    virtual void                CaptureMouse( BOOL bMouse );
    virtual void                SetPointerPos( long nX, long nY );
    using SalFrame::Flush;
    virtual void                Flush();
    virtual void                Sync();
    virtual void                SetInputContext( SalInputContext* pContext );
    virtual void                EndExtTextInput( USHORT nFlags );
    virtual String              GetKeyName( USHORT nKeyCode );
    virtual String              GetSymbolKeyName( const XubString& rFontName, USHORT nKeyCode );
    virtual BOOL                MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode );
    virtual LanguageType        GetInputLanguage();
    virtual SalBitmap*          SnapShot();
    virtual void                UpdateSettings( AllSettings& rSettings );
    virtual void                Beep( SoundType eSoundType );
    virtual const SystemEnvData*    GetSystemData() const;
    virtual SalPointerState     GetPointerState();
    virtual void                SetParent( SalFrame* pNewParent );
    virtual bool                SetPluginParent( SystemParentData* pNewParent );
    virtual void                SetBackgroundBitmap( SalBitmap* pBitmap );
    virtual void                ResetClipRegion();
    virtual void                BeginSetClipRegion( ULONG nRects );
    virtual void                UnionClipRegion( long nX, long nY, long nWidth, long nHeight );
    virtual void                EndSetClipRegion();
};
#endif // _SVP_SVPFRAME_HXX
<|endoftext|>


<commit_before>/*
    qgpgmekeyformailboxjob.cpp

    This file is part of qgpgme, the Qt API binding for gpgme
    Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
    Software engineering by Intevation GmbH

    QGpgME is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    QGpgME 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
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#ifdef HAVE_CONFIG_H
 #include "config.h"
#endif

#include "qgpgmegpgcardjob.h"

#include <QStringList>
#include <QFileInfo>
#include <QDir>
#include <QProcess>
#include "util.h"

/* We cannot have a timeout because key generation can
 * take ages. Well maybe 10 minutes. */
#define TIMEOUT_VALUE (600000)

#include <tuple>

using namespace GpgME;
using namespace QGpgME;

QGpgMEGpgCardJob::QGpgMEGpgCardJob()
    : mixin_type(/* needed for the mixer */
                 Context::createForEngine(GpgME::SpawnEngine).release())
{
    lateInitialization();
}

QGpgMEGpgCardJob::~QGpgMEGpgCardJob() {}

static QString getGpgCardPath()
{
    auto bindir = QString::fromLocal8Bit(dirInfo("bindir"));
    if (bindir.isEmpty()) {
        return QString();
    }

    const QFileInfo fi(QDir(bindir).absoluteFilePath(QStringLiteral("gpg-card")));
    if (fi.exists() && fi.isExecutable()) {
        return fi.absoluteFilePath();
    }
    return QString();
}

static QGpgMEGpgCardJob::result_type do_work(const QStringList &cmds, const QString &path)
{
    QStringList args;
    args << QStringLiteral("--with-colons");
    args += cmds;

    QProcess proc;

    proc.setProgram(path);
    proc.setArguments(args);
    proc.start();
    if (!proc.waitForStarted()) {
        return std::make_tuple (QString(), QString(), 1, QString(), Error());
    }

    if (!proc.waitForFinished(TIMEOUT_VALUE)) {
        return std::make_tuple (QString(), QString(), 1, QString(), Error());
    }
    if (proc.exitStatus() == QProcess::NormalExit) {
        return std::make_tuple (QString::fromUtf8(proc.readAllStandardOutput()),
                                QString::fromUtf8(proc.readAllStandardError()), proc.exitCode(),
                                QString(), Error());
    }
    return std::make_tuple (QString::fromUtf8(proc.readAllStandardOutput()),
            QString::fromUtf8(proc.readAllStandardError()), 1,
            QString(), Error());
}

Error QGpgMEGpgCardJob::start(const QStringList &cmds)
{
    const auto cardpath = getGpgCardPath ();
    if (cardpath.isEmpty()) {
        return Error(make_error(GPG_ERR_NOT_SUPPORTED));
    }
    run(std::bind(&do_work, cmds, cardpath));
    return Error();
}

Error QGpgMEGpgCardJob::exec(const QStringList &cmds, QString &std_out, QString &std_err, int &exitCode)
{
    const auto cardpath = getGpgCardPath ();
    if (cardpath.isEmpty()) {
        return Error(make_error(GPG_ERR_NOT_SUPPORTED));
    }
    const result_type r = do_work(cmds, cardpath);
    resultHook(r);
    std_out = std::get<0>(r);
    std_err = std::get<1>(r);
    exitCode = std::get<2>(r);
    return exitCode == 0 ? Error() : Error(make_error(GPG_ERR_GENERAL));
}

#include "qgpgmegpgcardjob.moc"
<commit_msg>qt: Log execution args of gpg-card<commit_after>/*
    qgpgmegpgcardjob.cpp

    This file is part of qgpgme, the Qt API binding for gpgme
    Copyright (c) 2020 g10 Code GmbH

    QGpgME is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    QGpgME 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
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#ifdef HAVE_CONFIG_H
 #include "config.h"
#endif

#include "qgpgmegpgcardjob.h"

#include <QStringList>
#include <QFileInfo>
#include <QDir>
#include <QProcess>
#include "util.h"
#include "gpgme_backend_debug.h"

/* We cannot have a timeout because key generation can
 * take ages. Well maybe 10 minutes. */
#define TIMEOUT_VALUE (600000)

#include <tuple>

using namespace GpgME;
using namespace QGpgME;

QGpgMEGpgCardJob::QGpgMEGpgCardJob()
    : mixin_type(/* needed for the mixer */
                 Context::createForEngine(GpgME::SpawnEngine).release())
{
    lateInitialization();
}

QGpgMEGpgCardJob::~QGpgMEGpgCardJob() {}

static QString getGpgCardPath()
{
    auto bindir = QString::fromLocal8Bit(dirInfo("bindir"));
    if (bindir.isEmpty()) {
        return QString();
    }

    const QFileInfo fi(QDir(bindir).absoluteFilePath(QStringLiteral("gpg-card")));
    if (fi.exists() && fi.isExecutable()) {
        return fi.absoluteFilePath();
    }
    return QString();
}

static QGpgMEGpgCardJob::result_type do_work(const QStringList &cmds, const QString &path)
{
    QStringList args;
    args << QStringLiteral("--with-colons");
    args += cmds;

    QProcess proc;

    proc.setProgram(path);
    proc.setArguments(args);

    qCDebug(GPGPME_BACKEND_LOG) << "Executing:" << path << args;
    proc.start();
    if (!proc.waitForStarted()) {
        return std::make_tuple (QString(), QString(), 1, QString(), Error());
    }

    if (!proc.waitForFinished(TIMEOUT_VALUE)) {
        return std::make_tuple (QString(), QString(), 1, QString(), Error());
    }
    if (proc.exitStatus() == QProcess::NormalExit) {
        return std::make_tuple (QString::fromUtf8(proc.readAllStandardOutput()),
                                QString::fromUtf8(proc.readAllStandardError()), proc.exitCode(),
                                QString(), Error());
    }
    return std::make_tuple (QString::fromUtf8(proc.readAllStandardOutput()),
            QString::fromUtf8(proc.readAllStandardError()), 1,
            QString(), Error());
}

Error QGpgMEGpgCardJob::start(const QStringList &cmds)
{
    const auto cardpath = getGpgCardPath ();
    if (cardpath.isEmpty()) {
        return Error(make_error(GPG_ERR_NOT_SUPPORTED));
    }
    run(std::bind(&do_work, cmds, cardpath));
    return Error();
}

Error QGpgMEGpgCardJob::exec(const QStringList &cmds, QString &std_out, QString &std_err, int &exitCode)
{
    const auto cardpath = getGpgCardPath ();
    if (cardpath.isEmpty()) {
        return Error(make_error(GPG_ERR_NOT_SUPPORTED));
    }
    const result_type r = do_work(cmds, cardpath);
    resultHook(r);
    std_out = std::get<0>(r);
    std_err = std::get<1>(r);
    exitCode = std::get<2>(r);
    return exitCode == 0 ? Error() : Error(make_error(GPG_ERR_GENERAL));
}

#include "qgpgmegpgcardjob.moc"
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Simon A. F. Lund <safl@safl.dk>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */
#include <cphvb.h>
#include "cphvb_ve_simple.h"
#include <cphvb_mcache.h>

static cphvb_component *myself = NULL;
static cphvb_userfunc_impl reduce_impl = NULL;
static cphvb_intp reduce_impl_id = 0;
static cphvb_userfunc_impl random_impl = NULL;
static cphvb_intp random_impl_id = 0;
static cphvb_userfunc_impl matmul_impl = NULL;
static cphvb_intp matmul_impl_id = 0;

cphvb_error cphvb_ve_simple_init(cphvb_component *self)
{
    myself = self;
    cphvb_mcache_init( 10 );
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_execute( cphvb_intp instruction_count, cphvb_instruction* instruction_list )
{
    cphvb_intp count;
    cphvb_instruction* inst;
    cphvb_error res;

    for (count=0; count < instruction_count; count++) {

        inst = &instruction_list[count];
        if (inst->status == CPHVB_SUCCESS) {        // SKIP instruction
            continue;
        }
//cphvb_pprint_instr(inst);

        res = cphvb_mcache_malloc( inst );          // Allocate memory for operands
        if ( res != CPHVB_SUCCESS ) {
            printf("Unhandled error returned by cphvb_mcache_malloc() called from cphvb_ve_simple_execute()\n");
            return res;
        }

        switch (inst->opcode) {                     // Dispatch instruction

            case CPHVB_NONE:                        // NOOP.
            case CPHVB_DISCARD:
            case CPHVB_SYNC:
                inst->status = CPHVB_SUCCESS;
                break;
            case CPHVB_FREE:                        // Store data-pointer in malloc-cache
                inst->status = cphvb_mcache_free( inst );
                break;

            case CPHVB_USERFUNC:                    // External libraries

                if (inst->userfunc->id == reduce_impl_id) {

                    inst->status = reduce_impl(inst->userfunc, NULL);

                } else if(inst->userfunc->id == random_impl_id) {

                    inst->status = random_impl(inst->userfunc, NULL);

                } else if(inst->userfunc->id == matmul_impl_id) {

                    inst->status = matmul_impl(inst->userfunc, NULL);

                } else {                            // Unsupported userfunc

                    inst->status = CPHVB_USERFUNC_NOT_SUPPORTED;

                }

                break;

            default:                            // Built-in operations
                inst->status = cphvb_compute_apply( inst );

        }

        if (inst->status != CPHVB_SUCCESS) {    // Instruction failed
            break;
        }

    }

    if (count == instruction_count) {
        return CPHVB_SUCCESS;
    } else {
        return CPHVB_PARTIAL_SUCCESS;
    }

}

cphvb_error cphvb_ve_simple_shutdown( void )
{
    // De-allocate the malloc-cache
    cphvb_mcache_clear();
    cphvb_mcache_delete();

    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_reg_func(char *fun, cphvb_intp *id)
{
    if(strcmp("cphvb_reduce", fun) == 0)
    {
    	if (reduce_impl == NULL)
    	{
			cphvb_component_get_func(myself, fun, &reduce_impl);
			if (reduce_impl == NULL)
				return CPHVB_USERFUNC_NOT_SUPPORTED;

			reduce_impl_id = *id;
			return CPHVB_SUCCESS;
        }
        else
        {
        	*id = reduce_impl_id;
        	return CPHVB_SUCCESS;
        }
    }
    else if(strcmp("cphvb_random", fun) == 0)
    {
    	if (random_impl == NULL)
    	{
			cphvb_component_get_func(myself, fun, &random_impl);
			if (random_impl == NULL)
				return CPHVB_USERFUNC_NOT_SUPPORTED;

			random_impl_id = *id;
			return CPHVB_SUCCESS;
        }
        else
        {
        	*id = random_impl_id;
        	return CPHVB_SUCCESS;
        }
    }
    else if(strcmp("cphvb_matmul", fun) == 0)
    {
    	if (matmul_impl == NULL)
    	{
            cphvb_component_get_func(myself, fun, &matmul_impl);
            if (matmul_impl == NULL)
                return CPHVB_USERFUNC_NOT_SUPPORTED;

            matmul_impl_id = *id;
            return CPHVB_SUCCESS;
        }
        else
        {
        	*id = matmul_impl_id;
        	return CPHVB_SUCCESS;
        }
    }

    return CPHVB_USERFUNC_NOT_SUPPORTED;
}

cphvb_error cphvb_reduce( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_reduce( arg, ve_arg );
}

cphvb_error cphvb_random( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_random( arg, ve_arg );
}

cphvb_error cphvb_matmul( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_matmul( arg, ve_arg );

}
<commit_msg>removed some debug prints<commit_after>/*
 * Copyright 2011 Simon A. F. Lund <safl@safl.dk>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */
#include <cphvb.h>
#include "cphvb_ve_simple.h"
#include <cphvb_mcache.h>

static cphvb_component *myself = NULL;
static cphvb_userfunc_impl reduce_impl = NULL;
static cphvb_intp reduce_impl_id = 0;
static cphvb_userfunc_impl random_impl = NULL;
static cphvb_intp random_impl_id = 0;
static cphvb_userfunc_impl matmul_impl = NULL;
static cphvb_intp matmul_impl_id = 0;

cphvb_error cphvb_ve_simple_init(cphvb_component *self)
{
    myself = self;
    cphvb_mcache_init( 10 );
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_execute( cphvb_intp instruction_count, cphvb_instruction* instruction_list )
{
    cphvb_intp count;
    cphvb_instruction* inst;
    cphvb_error res;

    for (count=0; count < instruction_count; count++) {

        inst = &instruction_list[count];
        if (inst->status == CPHVB_SUCCESS) {        // SKIP instruction
            continue;
        }

        res = cphvb_mcache_malloc( inst );          // Allocate memory for operands
        if ( res != CPHVB_SUCCESS ) {
            printf("Unhandled error returned by cphvb_mcache_malloc() called from cphvb_ve_simple_execute()\n");
            return res;
        }

        switch (inst->opcode) {                     // Dispatch instruction

            case CPHVB_NONE:                        // NOOP.
            case CPHVB_DISCARD:
            case CPHVB_SYNC:
                inst->status = CPHVB_SUCCESS;
                break;
            case CPHVB_FREE:                        // Store data-pointer in malloc-cache
                inst->status = cphvb_mcache_free( inst );
                break;

            case CPHVB_USERFUNC:                    // External libraries

                if (inst->userfunc->id == reduce_impl_id) {

                    inst->status = reduce_impl(inst->userfunc, NULL);

                } else if(inst->userfunc->id == random_impl_id) {

                    inst->status = random_impl(inst->userfunc, NULL);

                } else if(inst->userfunc->id == matmul_impl_id) {

                    inst->status = matmul_impl(inst->userfunc, NULL);

                } else {                            // Unsupported userfunc

                    inst->status = CPHVB_USERFUNC_NOT_SUPPORTED;

                }

                break;

            default:                            // Built-in operations
                inst->status = cphvb_compute_apply( inst );

        }

        if (inst->status != CPHVB_SUCCESS) {    // Instruction failed
            break;
        }

    }

    if (count == instruction_count) {
        return CPHVB_SUCCESS;
    } else {
        return CPHVB_PARTIAL_SUCCESS;
    }

}

cphvb_error cphvb_ve_simple_shutdown( void )
{
    // De-allocate the malloc-cache
    cphvb_mcache_clear();
    cphvb_mcache_delete();

    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_reg_func(char *fun, cphvb_intp *id)
{
    if(strcmp("cphvb_reduce", fun) == 0)
    {
    	if (reduce_impl == NULL)
    	{
			cphvb_component_get_func(myself, fun, &reduce_impl);
			if (reduce_impl == NULL)
				return CPHVB_USERFUNC_NOT_SUPPORTED;

			reduce_impl_id = *id;
			return CPHVB_SUCCESS;
        }
        else
        {
        	*id = reduce_impl_id;
        	return CPHVB_SUCCESS;
        }
    }
    else if(strcmp("cphvb_random", fun) == 0)
    {
    	if (random_impl == NULL)
    	{
			cphvb_component_get_func(myself, fun, &random_impl);
			if (random_impl == NULL)
				return CPHVB_USERFUNC_NOT_SUPPORTED;

			random_impl_id = *id;
			return CPHVB_SUCCESS;
        }
        else
        {
        	*id = random_impl_id;
        	return CPHVB_SUCCESS;
        }
    }
    else if(strcmp("cphvb_matmul", fun) == 0)
    {
    	if (matmul_impl == NULL)
    	{
            cphvb_component_get_func(myself, fun, &matmul_impl);
            if (matmul_impl == NULL)
                return CPHVB_USERFUNC_NOT_SUPPORTED;

            matmul_impl_id = *id;
            return CPHVB_SUCCESS;
        }
        else
        {
        	*id = matmul_impl_id;
        	return CPHVB_SUCCESS;
        }
    }

    return CPHVB_USERFUNC_NOT_SUPPORTED;
}

cphvb_error cphvb_reduce( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_reduce( arg, ve_arg );
}

cphvb_error cphvb_random( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_random( arg, ve_arg );
}

cphvb_error cphvb_matmul( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_matmul( arg, ve_arg );

}
<|endoftext|>


<commit_before>#include "GEK/Math/Matrix3x2.hpp"

namespace Gek
{
    namespace Math
    {
        const Matrix3x2<float> Matrix3x2<float>::Identity = Matrix3x2<float>(
            1.0f, 0.0f,
            0.0f, 1.0f,
            0.0f, 0.0f);
    }; // namespace Math
}; // namespace Gek
<commit_msg>Fixing strict template specialization, need to use similar fix for other templates<commit_after>#include "GEK/Math/Matrix3x2.hpp"

namespace Gek
{
    namespace Math
    {
        template <>
        const Float3x2 Float3x2::Identity = Float3x2(
            1.0f, 0.0f,
            0.0f, 1.0f,
            0.0f, 0.0f);
    }; // namespace Math
}; // namespace Gek
<|endoftext|>


<commit_before>#include "WindowHelpers.h"

bool WindowHelpers::ToolTipCreated = false;
NOTIFYICONDATA WindowHelpers::Tray;

WindowHelpers::WindowHelpers() {
}

HWND WindowHelpers::getHandler() {
	return hwndWindow;
}

void WindowHelpers::TaskbarNotify(HWND hWnd) {
	if (!ToolTipCreated) {
		ShowWindow(hWnd, SHOW_WINDOW);

		if (IsWindowsVistaOrGreater()) {
			Tray.cbSize = sizeof(Tray);
			Tray.uVersion = NOTIFYICON_VERSION_4;
		}

		else if (IsWindowsXPOrGreater()) {
			Tray.cbSize = NOTIFYICONDATA_V3_SIZE;
			Tray.uVersion = NOTIFYICON_VERSION;
		}

		Shell_NotifyIcon(NIM_SETVERSION, &Tray);

		Tray.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
		Tray.hWnd = hWnd;
		strcpy_s(Tray.szTip, helpers::GetString(IDS_TITLE));
		Tray.uCallbackMessage = WM_CONTEXTMSGEVENT;
		Tray.uFlags = NIF_ICON | NIF_TIP | NIF_SHOWTIP | NIF_MESSAGE | NIF_GUID;
		Tray.uID = 01;
		Shell_NotifyIcon(NIM_ADD, &Tray);
		ToolTipCreated = true;
	}
}

int WindowHelpers::CreateWndProc() {
	HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(helpers::GetConsoleWindow(), GWLP_HINSTANCE);

	WNDCLASS wc = { 0 };
	wc.hbrBackground = CreateSolidBrush(RGB(240, 240, 240));
	wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
	wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = TEXT(NOCAPSCLASS);
	wc.style = CS_HREDRAW | CS_VREDRAW;

	if (!RegisterClass(&wc))
	{
		printf("Problem with WNDClass\n");
		return 1;
	}

	hwndWindow = CreateWindow(TEXT(NOCAPSCLASS),
		TEXT("Options"),
		WS_OVERLAPPED | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX,
		520, 20, 300, 400,
		NULL,
		LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU2)),
		hInstance, NULL);

	UpdateWindow(hwndWindow);
	TaskbarNotify(hwndWindow);

	MSG msg;
	while (GetMessage(&msg, hwndWindow, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

void WindowHelpers::CreateUI(HWND hwnd) {
	std::map<DWORD_PTR, KeyObject::key_t> keys = KeyManager::GetKeyMap();
	std::map<DWORD_PTR, KeyObject::key_t>::iterator it;

	int startX = 3;
	for (it = keys.begin(); it != keys.end(); it++)
	{
		CreateWindow(TEXT("button"), TEXT(it->second.title.c_str()),
			WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
			3, startX, 300, 20,
			hwnd, (HMENU) it->first, NULL, NULL);

		CheckDlgButton(hwnd, static_cast<int>(it->first), it->second.enabled ? BST_CHECKED : BST_UNCHECKED);
		startX += 23;
	}

	HFONT defaultFont;
	defaultFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
	SendMessage(hwnd, WM_SETFONT, WPARAM(defaultFont), TRUE);
}

LRESULT CALLBACK WindowHelpers::WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	switch (message) {
	case WM_CREATE:
		CreateUI(hwnd);
		break;

	case WM_CONTEXTMSGEVENT:
		switch (lparam) {
		case WM_RBUTTONUP:
			POINT cursor;
			GetCursorPos(&cursor);
			HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));

			std::map<DWORD_PTR, KeyObject::key_t> keys = KeyManager::GetKeyMap();
			std::map<DWORD_PTR, KeyObject::key_t>::iterator it;
			for (it = keys.begin(); it != keys.end(); it++)
			{
				InsertMenu(hMenu, 0, MFT_STRING, it->first, it->second.title.c_str());
				CheckMenuItem(hMenu, static_cast<int>(it->first), it->second.enabled ? MF_CHECKED : MF_UNCHECKED);
			}

			InsertMenu(hMenu, 0, MFT_SEPARATOR, -1, "-");
			InsertMenu(hMenu, 0, MFT_STRING, ID__SHOWOPTIONS, helpers::GetString(IDS_SHOWOPTIONS));

			SetForegroundWindow(hwnd);
			TrackPopupMenu((HMENU)GetSubMenu(hMenu, 0), TPM_LEFTALIGN, cursor.x, cursor.y, 0, hwnd, NULL);
			break;
		}
		break;

	case WM_COMMAND:
		switch (wparam) {
		case ID_FILE_QUT:
		case ID__QUIT:
			PostMessage(helpers::GetConsoleWindow(), WM_CLOSE, 0, 0);
			PostQuitMessage(0);
			break;

		case ID__SOURCECODE:
			ShellExecute(0, 0, "https://github.com/Toyz/NoCapsLock", 0, 0, SW_SHOW);
			break;

		case ID__SHOWOPTIONS:
			ShowWindow(hwnd, 1);
			break;

		case ID_HELP_ABOUT:
			MessageBox(
				NULL,
				"NoCapsLock is created by\n\nToyz\n\nSourse code is located on github",
				"About",
				MB_OK
			);

			break;

		default:
			KeyObject::key_t KeyMeta = KeyManager::FindKey(wparam);

			if (KeyMeta.title != "") {
				KeyMeta.enabled = !KeyMeta.enabled;
				CheckDlgButton(hwnd, static_cast<int>(wparam), KeyMeta.enabled ? BST_CHECKED : BST_UNCHECKED);
				KeyManager::UpdateByKey(wparam, KeyMeta);
			}
		}

		break;

	case WM_CLOSE:
		ShowWindow(hwnd, 0);
		return true;
	}

	return DefWindowProc(hwnd, message, wparam, lparam);
}

void WindowHelpers::ChangeTrayTitle(const char * title) {
	strcpy_s(Tray.szTip, title);
	Tray.uFlags = NIF_ICON | NIF_TIP | NIF_SHOWTIP | NIF_MESSAGE | NIF_GUID;
	Shell_NotifyIcon(NIM_MODIFY, &Tray);
}
<commit_msg>Alert user when closing<commit_after>#include "WindowHelpers.h"

bool WindowHelpers::ToolTipCreated = false;
NOTIFYICONDATA WindowHelpers::Tray;

WindowHelpers::WindowHelpers() {
}

HWND WindowHelpers::getHandler() {
	return hwndWindow;
}

void WindowHelpers::TaskbarNotify(HWND hWnd) {
	if (!ToolTipCreated) {
		ShowWindow(hWnd, SHOW_WINDOW);

		if (IsWindowsVistaOrGreater()) {
			Tray.cbSize = sizeof(Tray);
			Tray.uVersion = NOTIFYICON_VERSION_4;
		}

		else if (IsWindowsXPOrGreater()) {
			Tray.cbSize = NOTIFYICONDATA_V3_SIZE;
			Tray.uVersion = NOTIFYICON_VERSION;
		}

		Shell_NotifyIcon(NIM_SETVERSION, &Tray);

		Tray.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
		Tray.hWnd = hWnd;
		strcpy_s(Tray.szTip, helpers::GetString(IDS_TITLE));
		Tray.uCallbackMessage = WM_CONTEXTMSGEVENT;
		Tray.uFlags = NIF_ICON | NIF_TIP | NIF_SHOWTIP | NIF_MESSAGE | NIF_GUID;
		Tray.uID = 01;
		Shell_NotifyIcon(NIM_ADD, &Tray);
		ToolTipCreated = true;
	}
}

int WindowHelpers::CreateWndProc() {
	HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(helpers::GetConsoleWindow(), GWLP_HINSTANCE);

	WNDCLASS wc = { 0 };
	wc.hbrBackground = CreateSolidBrush(RGB(240, 240, 240));
	wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
	wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = TEXT(NOCAPSCLASS);
	wc.style = CS_HREDRAW | CS_VREDRAW;

	if (!RegisterClass(&wc))
	{
		printf("Problem with WNDClass\n");
		return 1;
	}

	hwndWindow = CreateWindow(TEXT(NOCAPSCLASS),
		TEXT("Options"),
		WS_OVERLAPPED | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX,
		520, 20, 300, 400,
		NULL,
		LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU2)),
		hInstance, NULL);

	UpdateWindow(hwndWindow);
	TaskbarNotify(hwndWindow);

	MSG msg;
	while (GetMessage(&msg, hwndWindow, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

void WindowHelpers::CreateUI(HWND hwnd) {
	std::map<DWORD_PTR, KeyObject::key_t> keys = KeyManager::GetKeyMap();
	std::map<DWORD_PTR, KeyObject::key_t>::iterator it;

	int startX = 3;
	for (it = keys.begin(); it != keys.end(); it++)
	{
		CreateWindow(TEXT("button"), TEXT(it->second.title.c_str()),
			WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
			3, startX, 300, 20,
			hwnd, (HMENU) it->first, NULL, NULL);

		CheckDlgButton(hwnd, static_cast<int>(it->first), it->second.enabled ? BST_CHECKED : BST_UNCHECKED);
		startX += 23;
	}

	HFONT defaultFont;
	defaultFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
	SendMessage(hwnd, WM_SETFONT, WPARAM(defaultFont), TRUE);
}

LRESULT CALLBACK WindowHelpers::WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	switch (message) {
	case WM_CREATE:
		CreateUI(hwnd);
		break;

	case WM_CONTEXTMSGEVENT:
		switch (lparam) {
		case WM_RBUTTONUP:
			POINT cursor;
			GetCursorPos(&cursor);
			HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));

			std::map<DWORD_PTR, KeyObject::key_t> keys = KeyManager::GetKeyMap();
			std::map<DWORD_PTR, KeyObject::key_t>::iterator it;
			for (it = keys.begin(); it != keys.end(); it++)
			{
				InsertMenu(hMenu, 0, MFT_STRING, it->first, it->second.title.c_str());
				CheckMenuItem(hMenu, static_cast<int>(it->first), it->second.enabled ? MF_CHECKED : MF_UNCHECKED);
			}

			InsertMenu(hMenu, 0, MFT_SEPARATOR, -1, "-");
			InsertMenu(hMenu, 0, MFT_STRING, ID__SHOWOPTIONS, helpers::GetString(IDS_SHOWOPTIONS));

			SetForegroundWindow(hwnd);
			TrackPopupMenu((HMENU)GetSubMenu(hMenu, 0), TPM_LEFTALIGN, cursor.x, cursor.y, 0, hwnd, NULL);
			break;
		}
		break;

	case WM_COMMAND:
		switch (wparam) {
		case ID_FILE_QUT:
		case ID__QUIT: {
			int msgboxID = MessageBox(
				NULL,
				"Are you sure you wish to quit the progam?",
				"Are you sure?",
				MB_ICONEXCLAMATION | MB_YESNO
			);

			if (msgboxID == IDYES) {
				PostMessage(helpers::GetConsoleWindow(), WM_CLOSE, 0, 0);
				PostQuitMessage(0);
			}
			break;
		}

		case ID__SOURCECODE:
			ShellExecute(0, 0, "https://github.com/Toyz/NoCapsLock", 0, 0, SW_SHOW);
			break;

		case ID__SHOWOPTIONS:
			ShowWindow(hwnd, 1);
			break;

		case ID_HELP_ABOUT:
			MessageBox(
				NULL,
				"NoCapsLock is created by\n\nToyz\n\nSourse code is located on github",
				"About",
				MB_OK
			);

			break;

		default:
			KeyObject::key_t KeyMeta = KeyManager::FindKey(wparam);

			if (KeyMeta.title != "") {
				KeyMeta.enabled = !KeyMeta.enabled;
				CheckDlgButton(hwnd, static_cast<int>(wparam), KeyMeta.enabled ? BST_CHECKED : BST_UNCHECKED);
				KeyManager::UpdateByKey(wparam, KeyMeta);
			}
		}

		break;

	case WM_CLOSE:
		ShowWindow(hwnd, 0);
		return true;
	}

	return DefWindowProc(hwnd, message, wparam, lparam);
}

void WindowHelpers::ChangeTrayTitle(const char * title) {
	strcpy_s(Tray.szTip, title);
	Tray.uFlags = NIF_ICON | NIF_TIP | NIF_SHOWTIP | NIF_MESSAGE | NIF_GUID;
	Shell_NotifyIcon(NIM_MODIFY, &Tray);
}
<|endoftext|>


<commit_before>//===-- SILSROA.cpp - Scalar Replacement of Aggregates  -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Change aggregate values into scalar values. Currently it takes every
// allocation and chops them up into their smallest non-captured pieces.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-sroa"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/Range.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SILPasses/Transforms.h"
#include "swift/SILPasses/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include <type_traits>

using namespace swift;

STATISTIC(NumEscapingAllocas, "Number of aggregate allocas not chopped up "
          "due to uses.");
STATISTIC(NumChoppedAllocas, "Number of chopped up aggregate allocas.");
STATISTIC(NumUnhandledAllocas, "Number of non struct, tuple allocas.");

namespace {

class SROAMemoryUseAnalyzer {
  // The allocation we are analyzing.
  AllocStackInst *AI;

  // Loads from AI.
  llvm::SmallVector<LoadInst *, 4> Loads;
  // Stores to AI.
  llvm::SmallVector<StoreInst *, 4> Stores;
  // Dealloc instructions for AI.
  llvm::SmallVector<DeallocStackInst *, 4> Deallocs;
  // Instructions which extract from aggregates.
  llvm::SmallVector<SILInstruction *, 4> ExtractInsts;

  // TupleType if we are visiting a tuple.
  TupleType *TT = nullptr;
  // StructDecl if we are visiting a struct.
  StructDecl *SD = nullptr;
public:
  SROAMemoryUseAnalyzer(AllocStackInst *AI) : AI(AI) {
    assert(AI && "AI should never be null here.");
  }

  bool analyze();
  void chopUpAlloca(std::vector<AllocStackInst *> &Worklist);

private:
  SILInstruction *createAgg(SILBuilder &B, SILLocation Loc, SILType Ty,
                                  ArrayRef<SILValue> Elements);
  SILInstruction *createAggProjection(SILBuilder &B, SILLocation Loc,
                                      SILValue Operand, unsigned EltNo);
  unsigned getEltNoForProjection(SILInstruction *Inst);
  void createAllocas(llvm::SmallVector<AllocStackInst *, 4> &NewAllocations);
};

} // end anonymous namespace

SILInstruction *
SROAMemoryUseAnalyzer::createAgg(SILBuilder &B, SILLocation Loc,
                                 SILType Ty,
                                 ArrayRef<SILValue> Elements) {
  if (TT)
    return B.createTuple(Loc, Ty, Elements);

  assert(SD && "SD must not be null here since it or TT must be set to call"
         " this method.");
  return B.createStruct(Loc, Ty, Elements);
}

SILInstruction *
SROAMemoryUseAnalyzer::createAggProjection(SILBuilder &B, SILLocation Loc,
                                           SILValue Operand,
                                           unsigned EltNo) {
  if (TT)
    return B.createTupleExtract(Loc, Operand, EltNo);

  assert(SD && "SD should not be null since either it or TT must be set at "
         "this point.");

  auto Properties = SD->getStoredProperties();
  unsigned Counter = 0;
  for (auto *D : Properties)
    if (Counter++ == EltNo)
      return B.createStructExtract(Loc, Operand, D);
  llvm_unreachable("Unknown field.");
}

unsigned SROAMemoryUseAnalyzer::getEltNoForProjection(SILInstruction *Inst) {
  if (TT)
    return cast<TupleElementAddrInst>(Inst)->getFieldNo();

  assert(SD && "SD should not be null since either it or TT must be set at "
         "this point.");
  StructElementAddrInst *SEA = cast<StructElementAddrInst>(Inst);
  VarDecl *Field = SEA->getField();
  unsigned EltNo = 0;
  for (auto *D : SD->getStoredProperties()) {
    if (D == Field)
      return EltNo;
    ++EltNo;
  }
  llvm_unreachable("Unknown field.");
}

bool SROAMemoryUseAnalyzer::analyze() {
  // We only know how to split structs and tuples... So if we have a scalar or a
  // different sort of aggregate, bail.
  SILType Type = SILValue(AI, 1).getType();

  TT = Type.getAs<TupleType>();
  SD = Type.getStructOrBoundGenericStruct();
  bool HasUnrefField = AI->getElementType().aggregateHasUnreferenceableStorage();

  // Check that the allocated type is a struct or a tuple and that there are
  // no unreferenced fields.
  if (HasUnrefField || (!TT && !SD)) {
    ++NumUnhandledAllocas;
    return false;
  }

  // Go through uses of the memory allocation of AI...
  for (auto *Operand : getNonDebugUses(SILValue(AI, 1))) {
    SILInstruction *User = Operand->getUser();
    DEBUG(llvm::dbgs() << "    Visiting use: " << *User);

    // If we store the alloca pointer, we can not analyze its uses so bail...
    // It is ok if we store into the alloca pointer though.
    if (auto *SI = dyn_cast<StoreInst>(User)) {
      if (SI->getDest().getDef() == AI) {
        DEBUG(llvm::dbgs() << "        Found a store into the "
              "projection.\n");
        Stores.push_back(SI);
        continue;
      } else {
        DEBUG(llvm::dbgs() << "        Found a store of the "
              "projection pointer. Escapes!.\n");
        ++NumEscapingAllocas;
        return false;
      }
    }

    // If the use is a load, keep track of it for splitting later...
    if (auto *LI = dyn_cast<LoadInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found a load of the projection.\n");
      Loads.push_back(LI);
      continue;
    }

    // If the use is a struct_element_addr, add it to the worklist so we check
    // if it or one of its descendents escape.
    if (auto *ASI = dyn_cast<StructElementAddrInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found a struct subprojection!\n");
      ExtractInsts.push_back(ASI);
      continue;
    }

    // If the use is a tuple_element_addr, add it to the worklist so we check
    // if it or one of its descendents escape.
    if (auto *TSI = dyn_cast<TupleElementAddrInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found a tuple subprojection!\n");
      ExtractInsts.push_back(TSI);
      continue;
    }

    // Otherwise we do not understand this instruction, so bail.
    DEBUG(llvm::dbgs() << "        Found unknown user, pointer escapes!\n");
    ++NumEscapingAllocas;
    return false;
  }

  // Analysis was successful. We can break up this allocation!
  ++NumChoppedAllocas;
  return true;
}

void
SROAMemoryUseAnalyzer::
createAllocas(llvm::SmallVector<AllocStackInst *, 4> &NewAllocations) {
  SILBuilderWithScope<16> B(AI);
  SILType Type = AI->getType(1).getObjectType();

  if (TT) {
    for (unsigned EltNo : indices(TT->getElementTypes())) {
      SILType EltTy = Type.getTupleElementType(EltNo);
      NewAllocations.push_back(B.createAllocStack(AI->getLoc(), EltTy));
    }
  } else {
    assert(SD && "SD should not be null since either it or TT must be set at "
           "this point.");
    SILModule &M = AI->getModule();
    for (auto *D : SD->getStoredProperties())
      NewAllocations.push_back(B.createAllocStack(AI->getLoc(),
                                                  Type.getFieldType(D, M)));
  }
}

void SROAMemoryUseAnalyzer::chopUpAlloca(std::vector<AllocStackInst *> &Worklist) {
  // Create allocations for this instruction.
  llvm::SmallVector<AllocStackInst *, 4> NewAllocations;
  createAllocas(NewAllocations);
  // Add the new allocations to the worklist for recursive processing.
  //
  // TODO: Change this into an assert. For some reason I am running into compile
  // issues when I try it now.
  for (auto *AI : NewAllocations)
    Worklist.push_back(AI);

  // Change any aggregate loads into field loads + aggregate structure.
  for (auto *LI : Loads) {
    SILBuilderWithScope<16> B(LI);
    llvm::SmallVector<SILValue, 4> Elements;
    for (auto *NewAI : NewAllocations)
      Elements.push_back(B.createLoad(LI->getLoc(), SILValue(NewAI, 1)));
    auto *Agg = createAgg(B, LI->getLoc(), LI->getType().getObjectType(),
                          Elements);
    SILValue(LI).replaceAllUsesWith(Agg);
    LI->eraseFromParent();
  }

  // Change any aggregate stores into extracts + field stores.
  for (auto *SI : Stores) {
    SILBuilderWithScope<16> B(SI);
    for (unsigned EltNo : indices(NewAllocations))
      B.createStore(SI->getLoc(),
                    createAggProjection(B, SI->getLoc(), SI->getSrc(), EltNo),
                    SILValue(NewAllocations[EltNo], 1));
    SI->eraseFromParent();
  }

  // Forward any field extracts to the new allocation.
  for (auto *Ext : ExtractInsts) {
    SILValue NewValue = SILValue(NewAllocations[getEltNoForProjection(Ext)], 1);
    SILValue(Ext).replaceAllUsesWith(NewValue);
    Ext->eraseFromParent();
  }

  // Find all dealloc instruction that touch the local storage handle for AI
  // and then chop them up.
  for (auto *Operand : getNonDebugUses(SILValue(AI, 0))) {
    SILInstruction *User = Operand->getUser();
    SILBuilder B(User);

    // If the use is a DSI, add it to our memory analysis so that if we can chop
    // up allocas, we also chop up the relevant dealloc stack insts.
    if (auto *DSI = dyn_cast<DeallocStackInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found DeallocStackInst!\n");
      // Create the allocations in reverse order.
      for (auto *NewAI : swift::reversed(NewAllocations))
        B.createDeallocStack(DSI->getLoc(), SILValue(NewAI))
          ->setDebugScope(DSI->getDebugScope());
      DSI->eraseFromParent();
    }
  }

  eraseFromParentWithDebugInsts(AI);
}

static bool runSROAOnFunction(SILFunction &Fn) {
  std::vector<AllocStackInst *> Worklist;
  bool Changed = false;

  // For each basic block BB in Fn...
  for (auto &BB : Fn)
    // For each instruction in BB...
    for (auto &I : BB)
      // If the instruction is an alloc stack inst, add it to the worklist.
      if (auto *AI = dyn_cast<AllocStackInst>(&I))
        Worklist.push_back(AI);

  while (!Worklist.empty()) {
    AllocStackInst *AI = Worklist.back();
    Worklist.pop_back();

    SROAMemoryUseAnalyzer Analyzer(AI);

    if (!Analyzer.analyze())
      continue;

    Changed = true;
    Analyzer.chopUpAlloca(Worklist);
  }
  return Changed;
}

namespace {
class SILSROA : public SILFunctionTransform {

  /// The entry point to the transformation.
  void run() override {
    SILFunction *F = getFunction();
    DEBUG(llvm::dbgs() << "***** SROA on function: " << F->getName() <<
          " *****\n");

    if (runSROAOnFunction(*F))
      invalidateAnalysis(SILAnalysis::PreserveKind::ProgramFlow);
  }

  StringRef getName() override { return "SROA"; }
};
} // end anonymous namespace

SILTransform *swift::createSROA() {
  return new SILSROA();
}
<commit_msg>Fix an iterator invalidation bug. :boom:<commit_after>//===-- SILSROA.cpp - Scalar Replacement of Aggregates  -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Change aggregate values into scalar values. Currently it takes every
// allocation and chops them up into their smallest non-captured pieces.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-sroa"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/Range.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SILPasses/Transforms.h"
#include "swift/SILPasses/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include <type_traits>

using namespace swift;

STATISTIC(NumEscapingAllocas, "Number of aggregate allocas not chopped up "
          "due to uses.");
STATISTIC(NumChoppedAllocas, "Number of chopped up aggregate allocas.");
STATISTIC(NumUnhandledAllocas, "Number of non struct, tuple allocas.");

namespace {

class SROAMemoryUseAnalyzer {
  // The allocation we are analyzing.
  AllocStackInst *AI;

  // Loads from AI.
  llvm::SmallVector<LoadInst *, 4> Loads;
  // Stores to AI.
  llvm::SmallVector<StoreInst *, 4> Stores;
  // Dealloc instructions for AI.
  llvm::SmallVector<DeallocStackInst *, 4> Deallocs;
  // Instructions which extract from aggregates.
  llvm::SmallVector<SILInstruction *, 4> ExtractInsts;

  // TupleType if we are visiting a tuple.
  TupleType *TT = nullptr;
  // StructDecl if we are visiting a struct.
  StructDecl *SD = nullptr;
public:
  SROAMemoryUseAnalyzer(AllocStackInst *AI) : AI(AI) {
    assert(AI && "AI should never be null here.");
  }

  bool analyze();
  void chopUpAlloca(std::vector<AllocStackInst *> &Worklist);

private:
  SILInstruction *createAgg(SILBuilder &B, SILLocation Loc, SILType Ty,
                                  ArrayRef<SILValue> Elements);
  SILInstruction *createAggProjection(SILBuilder &B, SILLocation Loc,
                                      SILValue Operand, unsigned EltNo);
  unsigned getEltNoForProjection(SILInstruction *Inst);
  void createAllocas(llvm::SmallVector<AllocStackInst *, 4> &NewAllocations);
};

} // end anonymous namespace

SILInstruction *
SROAMemoryUseAnalyzer::createAgg(SILBuilder &B, SILLocation Loc,
                                 SILType Ty,
                                 ArrayRef<SILValue> Elements) {
  if (TT)
    return B.createTuple(Loc, Ty, Elements);

  assert(SD && "SD must not be null here since it or TT must be set to call"
         " this method.");
  return B.createStruct(Loc, Ty, Elements);
}

SILInstruction *
SROAMemoryUseAnalyzer::createAggProjection(SILBuilder &B, SILLocation Loc,
                                           SILValue Operand,
                                           unsigned EltNo) {
  if (TT)
    return B.createTupleExtract(Loc, Operand, EltNo);

  assert(SD && "SD should not be null since either it or TT must be set at "
         "this point.");

  auto Properties = SD->getStoredProperties();
  unsigned Counter = 0;
  for (auto *D : Properties)
    if (Counter++ == EltNo)
      return B.createStructExtract(Loc, Operand, D);
  llvm_unreachable("Unknown field.");
}

unsigned SROAMemoryUseAnalyzer::getEltNoForProjection(SILInstruction *Inst) {
  if (TT)
    return cast<TupleElementAddrInst>(Inst)->getFieldNo();

  assert(SD && "SD should not be null since either it or TT must be set at "
         "this point.");
  StructElementAddrInst *SEA = cast<StructElementAddrInst>(Inst);
  VarDecl *Field = SEA->getField();
  unsigned EltNo = 0;
  for (auto *D : SD->getStoredProperties()) {
    if (D == Field)
      return EltNo;
    ++EltNo;
  }
  llvm_unreachable("Unknown field.");
}

bool SROAMemoryUseAnalyzer::analyze() {
  // We only know how to split structs and tuples... So if we have a scalar or a
  // different sort of aggregate, bail.
  SILType Type = SILValue(AI, 1).getType();

  TT = Type.getAs<TupleType>();
  SD = Type.getStructOrBoundGenericStruct();
  bool HasUnrefField = AI->getElementType().aggregateHasUnreferenceableStorage();

  // Check that the allocated type is a struct or a tuple and that there are
  // no unreferenced fields.
  if (HasUnrefField || (!TT && !SD)) {
    ++NumUnhandledAllocas;
    return false;
  }

  // Go through uses of the memory allocation of AI...
  for (auto *Operand : getNonDebugUses(SILValue(AI, 1))) {
    SILInstruction *User = Operand->getUser();
    DEBUG(llvm::dbgs() << "    Visiting use: " << *User);

    // If we store the alloca pointer, we can not analyze its uses so bail...
    // It is ok if we store into the alloca pointer though.
    if (auto *SI = dyn_cast<StoreInst>(User)) {
      if (SI->getDest().getDef() == AI) {
        DEBUG(llvm::dbgs() << "        Found a store into the "
              "projection.\n");
        Stores.push_back(SI);
        continue;
      } else {
        DEBUG(llvm::dbgs() << "        Found a store of the "
              "projection pointer. Escapes!.\n");
        ++NumEscapingAllocas;
        return false;
      }
    }

    // If the use is a load, keep track of it for splitting later...
    if (auto *LI = dyn_cast<LoadInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found a load of the projection.\n");
      Loads.push_back(LI);
      continue;
    }

    // If the use is a struct_element_addr, add it to the worklist so we check
    // if it or one of its descendents escape.
    if (auto *ASI = dyn_cast<StructElementAddrInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found a struct subprojection!\n");
      ExtractInsts.push_back(ASI);
      continue;
    }

    // If the use is a tuple_element_addr, add it to the worklist so we check
    // if it or one of its descendents escape.
    if (auto *TSI = dyn_cast<TupleElementAddrInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found a tuple subprojection!\n");
      ExtractInsts.push_back(TSI);
      continue;
    }

    // Otherwise we do not understand this instruction, so bail.
    DEBUG(llvm::dbgs() << "        Found unknown user, pointer escapes!\n");
    ++NumEscapingAllocas;
    return false;
  }

  // Analysis was successful. We can break up this allocation!
  ++NumChoppedAllocas;
  return true;
}

void
SROAMemoryUseAnalyzer::
createAllocas(llvm::SmallVector<AllocStackInst *, 4> &NewAllocations) {
  SILBuilderWithScope<16> B(AI);
  SILType Type = AI->getType(1).getObjectType();

  if (TT) {
    for (unsigned EltNo : indices(TT->getElementTypes())) {
      SILType EltTy = Type.getTupleElementType(EltNo);
      NewAllocations.push_back(B.createAllocStack(AI->getLoc(), EltTy));
    }
  } else {
    assert(SD && "SD should not be null since either it or TT must be set at "
           "this point.");
    SILModule &M = AI->getModule();
    for (auto *D : SD->getStoredProperties())
      NewAllocations.push_back(B.createAllocStack(AI->getLoc(),
                                                  Type.getFieldType(D, M)));
  }
}

void SROAMemoryUseAnalyzer::chopUpAlloca(std::vector<AllocStackInst *> &Worklist) {
  // Create allocations for this instruction.
  llvm::SmallVector<AllocStackInst *, 4> NewAllocations;
  createAllocas(NewAllocations);
  // Add the new allocations to the worklist for recursive processing.
  //
  // TODO: Change this into an assert. For some reason I am running into compile
  // issues when I try it now.
  for (auto *AI : NewAllocations)
    Worklist.push_back(AI);

  // Change any aggregate loads into field loads + aggregate structure.
  for (auto *LI : Loads) {
    SILBuilderWithScope<16> B(LI);
    llvm::SmallVector<SILValue, 4> Elements;
    for (auto *NewAI : NewAllocations)
      Elements.push_back(B.createLoad(LI->getLoc(), SILValue(NewAI, 1)));
    auto *Agg = createAgg(B, LI->getLoc(), LI->getType().getObjectType(),
                          Elements);
    SILValue(LI).replaceAllUsesWith(Agg);
    LI->eraseFromParent();
  }

  // Change any aggregate stores into extracts + field stores.
  for (auto *SI : Stores) {
    SILBuilderWithScope<16> B(SI);
    for (unsigned EltNo : indices(NewAllocations))
      B.createStore(SI->getLoc(),
                    createAggProjection(B, SI->getLoc(), SI->getSrc(), EltNo),
                    SILValue(NewAllocations[EltNo], 1));
    SI->eraseFromParent();
  }

  // Forward any field extracts to the new allocation.
  for (auto *Ext : ExtractInsts) {
    SILValue NewValue = SILValue(NewAllocations[getEltNoForProjection(Ext)], 1);
    SILValue(Ext).replaceAllUsesWith(NewValue);
    Ext->eraseFromParent();
  }

  // Find all dealloc instruction that touch the local storage handle for AI
  // and then chop them up.
  llvm::SmallVector<DeallocStackInst *, 4> ToRemove;
  for (auto *Operand : getNonDebugUses(SILValue(AI, 0))) {
    SILInstruction *User = Operand->getUser();
    SILBuilder B(User);

    // If the use is a DSI, add it to our memory analysis so that if we can chop
    // up allocas, we also chop up the relevant dealloc stack insts.
    if (auto *DSI = dyn_cast<DeallocStackInst>(User)) {
      DEBUG(llvm::dbgs() << "        Found DeallocStackInst!\n");
      // Create the allocations in reverse order.
      for (auto *NewAI : swift::reversed(NewAllocations)) {
        auto NewDSI = B.createDeallocStack(DSI->getLoc(), SILValue(NewAI));
        NewDSI->setDebugScope(DSI->getDebugScope());
      }
      ToRemove.push_back(DSI);
    }
  }

  // Remove the old DeallocStackInst instructions.
  for (auto *DSI : ToRemove) {
      DSI->eraseFromParent();
  }

  eraseFromParentWithDebugInsts(AI);
}

static bool runSROAOnFunction(SILFunction &Fn) {
  std::vector<AllocStackInst *> Worklist;
  bool Changed = false;

  // For each basic block BB in Fn...
  for (auto &BB : Fn)
    // For each instruction in BB...
    for (auto &I : BB)
      // If the instruction is an alloc stack inst, add it to the worklist.
      if (auto *AI = dyn_cast<AllocStackInst>(&I))
        Worklist.push_back(AI);

  while (!Worklist.empty()) {
    AllocStackInst *AI = Worklist.back();
    Worklist.pop_back();

    SROAMemoryUseAnalyzer Analyzer(AI);

    if (!Analyzer.analyze())
      continue;

    Changed = true;
    Analyzer.chopUpAlloca(Worklist);
  }
  return Changed;
}

namespace {
class SILSROA : public SILFunctionTransform {

  /// The entry point to the transformation.
  void run() override {
    SILFunction *F = getFunction();
    DEBUG(llvm::dbgs() << "***** SROA on function: " << F->getName() <<
          " *****\n");

    if (runSROAOnFunction(*F))
      invalidateAnalysis(SILAnalysis::PreserveKind::ProgramFlow);
  }

  StringRef getName() override { return "SROA"; }
};
} // end anonymous namespace

SILTransform *swift::createSROA() {
  return new SILSROA();
}
<|endoftext|>


<commit_before>#line 2 "togo/core/io/io.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief IO interface.
@ingroup lib_core_io
*/

#pragma once

#include <togo/core/config.hpp>
#include <togo/core/types.hpp>
#include <togo/core/utility/types.hpp>
#include <togo/core/utility/constraints.hpp>
#include <togo/core/io/types.hpp>
#include <togo/core/io/proto.hpp>

namespace togo {
namespace io {

/**
	@addtogroup lib_core_io
	@{
*/

/// Stream IO status.
inline IOStatus status(IStreamBase const& stream) {
	return stream.status();
}

/// Stream position.
inline u64 position(IStreamSeekable& stream) {
	return stream.position();
}

/// Seek stream to absolute position.
inline u64 seek_to(IStreamSeekable& stream, u64 const pos) {
	return stream.seek_to(pos);
}

/// Seek stream by an offset relative to the current position.
inline u64 seek_relative(IStreamSeekable& stream, s64 const offset) {
	return stream.seek_relative(offset);
}

/// Read bytes into a buffer.
///
/// If read_size is non-null, its pointee will be assigned to the
/// number of bytes that were read from the stream, which may be less
/// than requested if the status is fail or EOF.
inline IOStatus read(
	IReader& stream,
	void* const buffer,
	unsigned const size,
	unsigned* const read_size = nullptr
) {
	return stream.read(buffer, size, read_size);
}

/// Write bytes from a buffer.
inline IOStatus write(
	IWriter& stream,
	void const* const buffer,
	unsigned const size
) {
	return stream.write(buffer, size);
}

/// Read an arithmetic value.
template<class T>
inline IOStatus read_value(IReader& stream, T& value) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::read(stream, &value, sizeof(T));
}

/// Write an arithmetic value.
template<class T>
inline IOStatus write_value(IWriter& stream, T const& value) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::write(stream, &value, sizeof(T));
}

/// Read an arithmetic array.
template<class T>
inline IOStatus read_array(IReader& stream, ArrayRef<T> const& data) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::read(stream, begin(data), data.size() * sizeof(T));
}

/// Write an arithmetic array.
template<class T>
inline IOStatus write_array(IWriter& stream, ArrayRef<T const> const& data) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::write(stream, begin(data), data.size() * sizeof(T));
}

/** @} */ // end of doc-group lib_core_io

} // namespace io
} // namespace togo
<commit_msg>lib/core/io: added endian variants to arithmetic IO.<commit_after>#line 2 "togo/core/io/io.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief IO interface.
@ingroup lib_core_io
*/

#pragma once

#include <togo/core/config.hpp>
#include <togo/core/types.hpp>
#include <togo/core/utility/types.hpp>
#include <togo/core/utility/constraints.hpp>
#include <togo/core/utility/endian.hpp>
#include <togo/core/io/types.hpp>
#include <togo/core/io/proto.hpp>

namespace togo {
namespace io {

/**
	@addtogroup lib_core_io
	@{
*/

/// Stream IO status.
inline IOStatus status(IStreamBase const& stream) {
	return stream.status();
}

/// Stream position.
inline u64 position(IStreamSeekable& stream) {
	return stream.position();
}

/// Seek stream to absolute position.
inline u64 seek_to(IStreamSeekable& stream, u64 const pos) {
	return stream.seek_to(pos);
}

/// Seek stream by an offset relative to the current position.
inline u64 seek_relative(IStreamSeekable& stream, s64 const offset) {
	return stream.seek_relative(offset);
}

/// Read bytes into a buffer.
///
/// If read_size is non-null, its pointee will be assigned to the
/// number of bytes that were read from the stream, which may be less
/// than requested if the status is fail or EOF.
inline IOStatus read(
	IReader& stream,
	void* const buffer,
	unsigned const size,
	unsigned* const read_size = nullptr
) {
	return stream.read(buffer, size, read_size);
}

/// Write bytes from a buffer.
inline IOStatus write(
	IWriter& stream,
	void const* const buffer,
	unsigned const size
) {
	return stream.write(buffer, size);
}

/// Read an arithmetic value.
template<class T>
inline IOStatus read_value(IReader& stream, T& value) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::read(stream, &value, sizeof(T));
}

/// Write an arithmetic value.
template<class T>
inline IOStatus write_value(IWriter& stream, T const& value) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::write(stream, &value, sizeof(T));
}

/// Read an arithmetic array.
template<class T>
inline IOStatus read_array(IReader& stream, ArrayRef<T> const& data) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::read(stream, begin(data), data.size() * sizeof(T));
}

/// Write an arithmetic array.
template<class T>
inline IOStatus write_array(IWriter& stream, ArrayRef<T const> const& data) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	return io::write(stream, begin(data), data.size() * sizeof(T));
}

/// Read an arithmetic value from endian.
///
/// If endian differs from the system, value is byte-reversed after reading.
template<class T>
inline IOStatus read_value_endian(IReader& stream, T& value, Endian const endian) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	auto status = io::read(stream, &value, sizeof(T));
	reverse_bytes_if(value, endian);
	return status;
}

/// Write an arithmetic value to endian.
///
/// If endian differs from the system, value is written byte-reversed.
template<class T>
inline IOStatus write_value_endian(IWriter& stream, T value, Endian const endian) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	reverse_bytes_if(value, endian);
	return io::write(stream, &value, sizeof(T));
}

/// Read an arithmetic array from endian.
///
/// If endian differs from the system, values are byte-reversed after reading.
template<class T>
inline IOStatus read_array_endian(
	IReader& stream,
	ArrayRef<T> const& data,
	Endian const endian
) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	auto status = io::read_array(stream, data);
	reverse_bytes_if(data, endian);
	return status;
}

/// Write an arithmetic array.
///
/// If endian differs from the system, values are written byte-reversed.
template<class T>
inline IOStatus write_array_endian(
	IWriter& stream,
	ArrayRef<T const> const& data,
	Endian const endian
) {
	TOGO_CONSTRAIN_ARITHMETIC(T);
	if (endian == Endian::system) {
		return io::write_array(stream, data);
	}
	T value;
	IOStatus status{IOStatus::flag_none};
	for (auto it = begin(data); it != end(data) && status; ++it) {
		value = reverse_bytes_copy(*it);
		status = io::write_value(stream, value);
	}
	return status;
}

/** @} */ // end of doc-group lib_core_io

} // namespace io
} // namespace togo
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

// C++ includes
#include <iostream>
#include <iomanip> // for std::setw, std::setiosflags

// Local includes
#include "type_vector.h"

namespace libMesh
{

// ------------------------------------------------------------
// TypeVector<T> class member funcions
template <typename T>
TypeVector<T> TypeVector<T>::unit() const
{

  const Real length = size();

  libmesh_assert (length != static_cast<Real>(0.));

#if LIBMESH_DIM == 1
  return TypeVector<T>(_coords[0]/length);
#endif

#if LIBMESH_DIM == 2
  return TypeVector<T>(_coords[0]/length,
		       _coords[1]/length);
#endif

#if LIBMESH_DIM == 3
  return TypeVector<T>(_coords[0]/length,
		       _coords[1]/length,
		       _coords[2]/length);
#endif

}

template <typename T>
void TypeVector<T>::print(std::ostream& os) const
{
#if LIBMESH_DIM == 1

  os << "x=" << (*this)(0) << '\n';

#endif
#if LIBMESH_DIM == 2

  os << "(x,y)=("
     << std::setw(8) << (*this)(0) << ", "
     << std::setw(8) << (*this)(1) << ")"
     << '\n';

#endif
#if LIBMESH_DIM == 3

  os <<  "(x,y,z)=("
     << std::setw(8) << (*this)(0) << ", "
     << std::setw(8) << (*this)(1) << ", "
     << std::setw(8) << (*this)(2) << ")"
     << '\n';
#endif
}

template <typename T>
void TypeVector<T>::write_unformatted (std::ostream &out,
				       const bool newline) const
{
  libmesh_assert (out);

  out << std::setiosflags(std::ios::showpoint)
      << (*this)(0) << " "
      << (*this)(1) << " "
      << (*this)(2) << " ";

  if (newline)
    out << '\n';
}

template <typename T>
bool TypeVector<T>::operator < (const TypeVector<T>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i) < rhs(i))
        return true;
      if ((*this)(i) > rhs(i))
        return false;
    }
  return false;
}

template <typename T>
bool TypeVector<T>::operator > (const TypeVector<T>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i) > rhs(i))
        return true;
      if ((*this)(i) < rhs(i))
        return false;
    }
  return false;
}

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template <>
bool TypeVector<Complex>::operator < (const TypeVector<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i).real() < rhs(i).real())
        return true;
      if ((*this)(i).real() > rhs(i).real())
        return false;
      if ((*this)(i).imag() < rhs(i).imag())
        return true;
      if ((*this)(i).imag() > rhs(i).imag())
        return false;
    }
  return false;
}

template <>
bool TypeVector<Complex>::operator > (const TypeVector<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i).real() > rhs(i).real())
        return true;
      if ((*this)(i).real() < rhs(i).real())
        return false;
      if ((*this)(i).imag() > rhs(i).imag())
        return true;
      if ((*this)(i).imag() < rhs(i).imag())
        return false;
    }
  return false;
}
#endif

// ------------------------------------------------------------
// Explicit instantiations
template class TypeVector<Real>;

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template class TypeVector<Complex>;
#endif

} // namespace libMesh
<commit_msg>Users who want a carriage return after printing a TypeVector (or Point, etc) can print one themselves; users who don't want a carriage return should be able to omit it.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

// C++ includes
#include <iostream>
#include <iomanip> // for std::setw, std::setiosflags

// Local includes
#include "type_vector.h"

namespace libMesh
{

// ------------------------------------------------------------
// TypeVector<T> class member funcions
template <typename T>
TypeVector<T> TypeVector<T>::unit() const
{

  const Real length = size();

  libmesh_assert (length != static_cast<Real>(0.));

#if LIBMESH_DIM == 1
  return TypeVector<T>(_coords[0]/length);
#endif

#if LIBMESH_DIM == 2
  return TypeVector<T>(_coords[0]/length,
		       _coords[1]/length);
#endif

#if LIBMESH_DIM == 3
  return TypeVector<T>(_coords[0]/length,
		       _coords[1]/length,
		       _coords[2]/length);
#endif

}

template <typename T>
void TypeVector<T>::print(std::ostream& os) const
{
#if LIBMESH_DIM == 1

  os << "x=" << (*this)(0);

#endif
#if LIBMESH_DIM == 2

  os << "(x,y)=("
     << std::setw(8) << (*this)(0) << ", "
     << std::setw(8) << (*this)(1) << ")";

#endif
#if LIBMESH_DIM == 3

  os <<  "(x,y,z)=("
     << std::setw(8) << (*this)(0) << ", "
     << std::setw(8) << (*this)(1) << ", "
     << std::setw(8) << (*this)(2) << ")";
#endif
}

template <typename T>
void TypeVector<T>::write_unformatted (std::ostream &out,
				       const bool newline) const
{
  libmesh_assert (out);

  out << std::setiosflags(std::ios::showpoint)
      << (*this)(0) << " "
      << (*this)(1) << " "
      << (*this)(2) << " ";

  if (newline)
    out << '\n';
}

template <typename T>
bool TypeVector<T>::operator < (const TypeVector<T>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i) < rhs(i))
        return true;
      if ((*this)(i) > rhs(i))
        return false;
    }
  return false;
}

template <typename T>
bool TypeVector<T>::operator > (const TypeVector<T>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i) > rhs(i))
        return true;
      if ((*this)(i) < rhs(i))
        return false;
    }
  return false;
}

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template <>
bool TypeVector<Complex>::operator < (const TypeVector<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i).real() < rhs(i).real())
        return true;
      if ((*this)(i).real() > rhs(i).real())
        return false;
      if ((*this)(i).imag() < rhs(i).imag())
        return true;
      if ((*this)(i).imag() > rhs(i).imag())
        return false;
    }
  return false;
}

template <>
bool TypeVector<Complex>::operator > (const TypeVector<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    {
      if ((*this)(i).real() > rhs(i).real())
        return true;
      if ((*this)(i).real() < rhs(i).real())
        return false;
      if ((*this)(i).imag() > rhs(i).imag())
        return true;
      if ((*this)(i).imag() < rhs(i).imag())
        return false;
    }
  return false;
}
#endif

// ------------------------------------------------------------
// Explicit instantiations
template class TypeVector<Real>;

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template class TypeVector<Complex>;
#endif

} // namespace libMesh
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2020 Winlin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <srs_protocol_kbps.hpp>

#include <srs_kernel_utility.hpp>

SrsKbpsSample::SrsKbpsSample()
{
    bytes = time = -1;
    kbps = 0;
}

SrsKbpsSample::~SrsKbpsSample()
{
}

SrsKbpsSample* SrsKbpsSample::update(int64_t b, srs_utime_t t, int k)
{
    bytes = b;
    time = t;
    kbps = k;
    return this;
}

SrsKbpsSlice::SrsKbpsSlice(SrsWallClock* c)
{
    clk = c;
    io = NULL;
    last_bytes = io_bytes_base = starttime = bytes = delta_bytes = 0;
}

SrsKbpsSlice::~SrsKbpsSlice()
{
}

int64_t SrsKbpsSlice::get_total_bytes()
{
    return bytes + last_bytes - io_bytes_base;
}

void SrsKbpsSlice::sample()
{
    srs_utime_t now = clk->now();
    int64_t total_bytes = get_total_bytes();

    if (sample_30s.time < 0) {
        sample_30s.update(total_bytes, now, 0);
    }
    if (sample_1m.time < 0) {
        sample_1m.update(total_bytes, now, 0);
    }
    if (sample_5m.time < 0) {
        sample_5m.update(total_bytes, now, 0);
    }
    if (sample_60m.time < 0) {
        sample_60m.update(total_bytes, now, 0);
    }

    if (now - sample_30s.time >= 30 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_30s.bytes) * 8 / srsu2ms(now - sample_30s.time));
        sample_30s.update(total_bytes, now, kbps);
    }
    if (now - sample_1m.time >= 60 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_1m.bytes) * 8 / srsu2ms(now - sample_1m.time));
        sample_1m.update(total_bytes, now, kbps);
    }
    if (now - sample_5m.time >= 300 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_5m.bytes) * 8 / srsu2ms(now - sample_5m.time));
        sample_5m.update(total_bytes, now, kbps);
    }
    if (now - sample_60m.time >= 3600 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_60m.bytes) * 8 / srsu2ms(now - sample_60m.time));
        sample_60m.update(total_bytes, now, kbps);
    }
}

ISrsKbpsDelta::ISrsKbpsDelta()
{
}

ISrsKbpsDelta::~ISrsKbpsDelta()
{
}

SrsWallClock::SrsWallClock()
{
}

SrsWallClock::~SrsWallClock()
{
}

srs_utime_t SrsWallClock::now()
{
    return srs_get_system_time();
}

SrsKbps::SrsKbps(SrsWallClock* c) : is(c), os(c)
{
    clk = c;
}

SrsKbps::~SrsKbps()
{
}

void SrsKbps::set_io(ISrsProtocolStatistic* in, ISrsProtocolStatistic* out)
{
    // set input stream
    // now, set start time.
    if (is.starttime == 0) {
        is.starttime = clk->now();
    }
    // save the old in bytes.
    if (is.io) {
        is.bytes += is.io->get_recv_bytes() - is.io_bytes_base;
    }
    // use new io.
    is.io = in;
    is.last_bytes = is.io_bytes_base = 0;
    if (in) {
        is.last_bytes = is.io_bytes_base = in->get_recv_bytes();
    }
    // resample
    is.sample();

    // set output stream
    // now, set start time.
    if (os.starttime == 0) {
        os.starttime = clk->now();
    }
    // save the old in bytes.
    if (os.io) {
        os.bytes += os.io->get_send_bytes() - os.io_bytes_base;
    }
    // use new io.
    os.io = out;
    os.last_bytes = os.io_bytes_base = 0;
    if (out) {
        os.last_bytes = os.io_bytes_base = out->get_send_bytes();
    }
    // resample
    os.sample();
}

int SrsKbps::get_send_kbps()
{
    srs_utime_t duration = clk->now() - is.starttime;
    if (duration <= 0) {
        return 0;
    }
    int64_t bytes = get_send_bytes();
    return (int)(bytes * 8 / srsu2ms(duration));
}

int SrsKbps::get_recv_kbps()
{
    srs_utime_t duration = clk->now() - os.starttime;
    if (duration <= 0) {
        return 0;
    }
    int64_t bytes = get_recv_bytes();
    return (int)(bytes * 8 / srsu2ms(duration));
}

int SrsKbps::get_send_kbps_30s()
{
    return os.sample_30s.kbps;
}

int SrsKbps::get_recv_kbps_30s()
{
    return is.sample_30s.kbps;
}

int SrsKbps::get_send_kbps_5m()
{
    return os.sample_5m.kbps;
}

int SrsKbps::get_recv_kbps_5m()
{
    return is.sample_5m.kbps;
}

void SrsKbps::add_delta(int64_t in, int64_t out)
{
    // update the total bytes
    is.last_bytes += in;
    os.last_bytes += out;

    // we donot sample, please use sample() to do resample.
}

void SrsKbps::sample()
{
    // update the total bytes
    if (os.io) {
        os.last_bytes = os.io->get_send_bytes();
    }

    if (is.io) {
        is.last_bytes = is.io->get_recv_bytes();
    }

    // resample
    is.sample();
    os.sample();
}

int64_t SrsKbps::get_send_bytes()
{
    // we must calc the send bytes dynamically,
    // to not depends on the sample(which used to calc the kbps).
    // @read https://github.com/ossrs/srs/issues/588

    // session start bytes.
    int64_t bytes = os.bytes;

    // When exists active session, use it to get the last bytes.
    if (os.io) {
        bytes += os.io->get_send_bytes() - os.io_bytes_base;
        return bytes;
    }

    // When no active session, the last_bytes record the last valid bytes.
    // TODO: Maybe the bellow bytes is zero, because the ios.io.out is NULL.
    bytes += os.last_bytes - os.io_bytes_base;

    return bytes;
}

int64_t SrsKbps::get_recv_bytes()
{
    // we must calc the send bytes dynamically,
    // to not depends on the sample(which used to calc the kbps).
    // @read https://github.com/ossrs/srs/issues/588

    // session start bytes.
    int64_t bytes = is.bytes;

    // When exists active session, use it to get the last bytes.
    if (is.io) {
        bytes += is.io->get_recv_bytes() - is.io_bytes_base;
        return bytes;
    }

    // When no active session, the last_bytes record the last valid bytes.
    // TODO: Maybe the bellow bytes is zero, because the ios.io.out is NULL.
    bytes += is.last_bytes - is.io_bytes_base;

    return bytes;
}

void SrsKbps::remark(int64_t* in, int64_t* out)
{
    sample();

    int64_t inv = is.get_total_bytes() - is.delta_bytes;
    is.delta_bytes = is.get_total_bytes();
    if (in) {
        *in = inv;
    }

    int64_t outv = os.get_total_bytes() - os.delta_bytes;
    os.delta_bytes = os.get_total_bytes();
    if (out) {
        *out = outv;
    }
}

int SrsKbps::size_memory()
{
    return sizeof(SrsKbps);
}

<commit_msg>Fix Kbps resample bug<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2020 Winlin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <srs_protocol_kbps.hpp>

#include <srs_kernel_utility.hpp>

SrsKbpsSample::SrsKbpsSample()
{
    bytes = time = -1;
    kbps = 0;
}

SrsKbpsSample::~SrsKbpsSample()
{
}

SrsKbpsSample* SrsKbpsSample::update(int64_t b, srs_utime_t t, int k)
{
    bytes = b;
    time = t;
    kbps = k;
    return this;
}

SrsKbpsSlice::SrsKbpsSlice(SrsWallClock* c)
{
    clk = c;
    io = NULL;
    last_bytes = io_bytes_base = starttime = bytes = delta_bytes = 0;
}

SrsKbpsSlice::~SrsKbpsSlice()
{
}

int64_t SrsKbpsSlice::get_total_bytes()
{
    return bytes + last_bytes - io_bytes_base;
}

void SrsKbpsSlice::sample()
{
    srs_utime_t now = clk->now();
    int64_t total_bytes = get_total_bytes();

    if (sample_30s.time < 0) {
        sample_30s.update(total_bytes, now, 0);
    }
    if (sample_1m.time < 0) {
        sample_1m.update(total_bytes, now, 0);
    }
    if (sample_5m.time < 0) {
        sample_5m.update(total_bytes, now, 0);
    }
    if (sample_60m.time < 0) {
        sample_60m.update(total_bytes, now, 0);
    }

    if (now - sample_30s.time >= 30 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_30s.bytes) * 8 / srsu2ms(now - sample_30s.time));
        sample_30s.update(total_bytes, now, kbps);
    }
    if (now - sample_1m.time >= 60 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_1m.bytes) * 8 / srsu2ms(now - sample_1m.time));
        sample_1m.update(total_bytes, now, kbps);
    }
    if (now - sample_5m.time >= 300 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_5m.bytes) * 8 / srsu2ms(now - sample_5m.time));
        sample_5m.update(total_bytes, now, kbps);
    }
    if (now - sample_60m.time >= 3600 * SRS_UTIME_SECONDS) {
        int kbps = (int)((total_bytes - sample_60m.bytes) * 8 / srsu2ms(now - sample_60m.time));
        sample_60m.update(total_bytes, now, kbps);
    }
}

ISrsKbpsDelta::ISrsKbpsDelta()
{
}

ISrsKbpsDelta::~ISrsKbpsDelta()
{
}

SrsWallClock::SrsWallClock()
{
}

SrsWallClock::~SrsWallClock()
{
}

srs_utime_t SrsWallClock::now()
{
    return srs_get_system_time();
}

SrsKbps::SrsKbps(SrsWallClock* c) : is(c), os(c)
{
    clk = c;
}

SrsKbps::~SrsKbps()
{
}

void SrsKbps::set_io(ISrsProtocolStatistic* in, ISrsProtocolStatistic* out)
{
    // set input stream
    // now, set start time.
    if (is.starttime == 0) {
        is.starttime = clk->now();
    }
    // save the old in bytes.
    if (is.io) {
        is.bytes += is.io->get_recv_bytes() - is.io_bytes_base;
    }
    // use new io.
    is.io = in;
    is.last_bytes = is.io_bytes_base = 0;
    if (in) {
        is.last_bytes = is.io_bytes_base = in->get_recv_bytes();
    }
    // resample
    is.sample();

    // set output stream
    // now, set start time.
    if (os.starttime == 0) {
        os.starttime = clk->now();
    }
    // save the old in bytes.
    if (os.io) {
        os.bytes += os.io->get_send_bytes() - os.io_bytes_base;
    }
    // use new io.
    os.io = out;
    os.last_bytes = os.io_bytes_base = 0;
    if (out) {
        os.last_bytes = os.io_bytes_base = out->get_send_bytes();
    }
    // resample
    os.sample();
}

int SrsKbps::get_send_kbps()
{
    int duration = srsu2ms(clk->now() - is.starttime);
    if (duration <= 0) {
        return 0;
    }

    int64_t bytes = get_send_bytes();
    return (int)(bytes * 8 / duration);
}

int SrsKbps::get_recv_kbps()
{
    int duration = srsu2ms(clk->now() - os.starttime);
    if (duration <= 0) {
        return 0;
    }

    int64_t bytes = get_recv_bytes();
    return (int)(bytes * 8 / duration);
}

int SrsKbps::get_send_kbps_30s()
{
    return os.sample_30s.kbps;
}

int SrsKbps::get_recv_kbps_30s()
{
    return is.sample_30s.kbps;
}

int SrsKbps::get_send_kbps_5m()
{
    return os.sample_5m.kbps;
}

int SrsKbps::get_recv_kbps_5m()
{
    return is.sample_5m.kbps;
}

void SrsKbps::add_delta(int64_t in, int64_t out)
{
    // update the total bytes
    is.last_bytes += in;
    os.last_bytes += out;

    // we donot sample, please use sample() to do resample.
}

void SrsKbps::sample()
{
    // update the total bytes
    if (os.io) {
        os.last_bytes = os.io->get_send_bytes();
    }

    if (is.io) {
        is.last_bytes = is.io->get_recv_bytes();
    }

    // resample
    is.sample();
    os.sample();
}

int64_t SrsKbps::get_send_bytes()
{
    // we must calc the send bytes dynamically,
    // to not depends on the sample(which used to calc the kbps).
    // @read https://github.com/ossrs/srs/issues/588

    // session start bytes.
    int64_t bytes = os.bytes;

    // When exists active session, use it to get the last bytes.
    if (os.io) {
        bytes += os.io->get_send_bytes() - os.io_bytes_base;
        return bytes;
    }

    // When no active session, the last_bytes record the last valid bytes.
    // TODO: Maybe the bellow bytes is zero, because the ios.io.out is NULL.
    bytes += os.last_bytes - os.io_bytes_base;

    return bytes;
}

int64_t SrsKbps::get_recv_bytes()
{
    // we must calc the send bytes dynamically,
    // to not depends on the sample(which used to calc the kbps).
    // @read https://github.com/ossrs/srs/issues/588

    // session start bytes.
    int64_t bytes = is.bytes;

    // When exists active session, use it to get the last bytes.
    if (is.io) {
        bytes += is.io->get_recv_bytes() - is.io_bytes_base;
        return bytes;
    }

    // When no active session, the last_bytes record the last valid bytes.
    // TODO: Maybe the bellow bytes is zero, because the ios.io.out is NULL.
    bytes += is.last_bytes - is.io_bytes_base;

    return bytes;
}

void SrsKbps::remark(int64_t* in, int64_t* out)
{
    sample();

    int64_t inv = is.get_total_bytes() - is.delta_bytes;
    is.delta_bytes = is.get_total_bytes();
    if (in) {
        *in = inv;
    }

    int64_t outv = os.get_total_bytes() - os.delta_bytes;
    os.delta_bytes = os.get_total_bytes();
    if (out) {
        *out = outv;
    }
}

int SrsKbps::size_memory()
{
    return sizeof(SrsKbps);
}

<|endoftext|>