<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include "vcl/strhelper.hxx"
#include "sal/alloca.h"

namespace psp {

inline int isSpace( char cChar )
{
    return
        cChar == ' '    || cChar == '\t'    ||
        cChar == '\r'   || cChar == '\n'    ||
        cChar == 0x0c   || cChar == 0x0b;
}

inline int isSpace( sal_Unicode cChar )
{
    return
        cChar == ' '    || cChar == '\t'    ||
        cChar == '\r'   || cChar == '\n'    ||
        cChar == 0x0c   || cChar == 0x0b;
}

inline int isProtect( char cChar )
{
    return cChar == '`' || cChar == '\'' || cChar == '"';
}

inline int isProtect( sal_Unicode cChar )
{
    return cChar == '`' || cChar == '\'' || cChar == '"';
}

inline void CopyUntil( char*& pTo, const char*& pFrom, char cUntil, int bIncludeUntil = 0 )
{
    do
    {
        if( *pFrom == '\\' )
        {
            pFrom++;
            if( *pFrom )
            {
                *pTo = *pFrom;
                pTo++;
            }
        }
        else if( bIncludeUntil || ! isProtect( *pFrom ) )
        {
            *pTo = *pFrom;
            pTo++;
        }
        pFrom++;
    } while( *pFrom && *pFrom != cUntil );
    // copy the terminating character unless zero or protector
    if( ! isProtect( *pFrom ) || bIncludeUntil )
    {
        *pTo = *pFrom;
        if( *pTo )
            pTo++;
    }
    if( *pFrom )
        pFrom++;
}

inline void CopyUntil( sal_Unicode*& pTo, const sal_Unicode*& pFrom, sal_Unicode cUntil, int bIncludeUntil = 0 )
{
    do
    {
        if( *pFrom == '\\' )
        {
            pFrom++;
            if( *pFrom )
            {
                *pTo = *pFrom;
                pTo++;
            }
        }
        else if( bIncludeUntil || ! isProtect( *pFrom ) )
        {
            *pTo = *pFrom;
            pTo++;
        }
        pFrom++;
    } while( *pFrom && *pFrom != cUntil );
    // copy the terminating character unless zero or protector
    if( ! isProtect( *pFrom ) || bIncludeUntil )
    {
        *pTo = *pFrom;
        if( *pTo )
            pTo++;
    }
    if( *pFrom )
        pFrom++;
}

String GetCommandLineToken( int nToken, const String& rLine )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return String();

    int nActualToken = 0;
    sal_Unicode* pBuffer = (sal_Unicode*)alloca( sizeof(sal_Unicode)*( nLen + 1 ) );
    const sal_Unicode* pRun = rLine.GetBuffer();
    sal_Unicode* pLeap = NULL;

    while( *pRun && nActualToken <= nToken )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        pLeap = pBuffer;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
                CopyUntil( pLeap, pRun, '`' );
            else if( *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'' );
            else if( *pRun == '"' )
                CopyUntil( pLeap, pRun, '"' );
            else
            {
                *pLeap = *pRun;
                pLeap++;
                pRun++;
            }
        }
        if( nActualToken != nToken )
            pBuffer[0] = 0;
        nActualToken++;
    }

    *pLeap = 0;

    String aRet( pBuffer );
    return aRet;
}

ByteString GetCommandLineToken( int nToken, const ByteString& rLine )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return ByteString();

    int nActualToken = 0;
    char* pBuffer = (char*)alloca( nLen + 1 );
    const char* pRun = rLine.GetBuffer();
    char* pLeap = NULL;

    while( *pRun && nActualToken <= nToken )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        pLeap = pBuffer;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
                CopyUntil( pLeap, pRun, '`' );
            else if( *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'' );
            else if( *pRun == '"' )
                CopyUntil( pLeap, pRun, '"' );
            else
            {
                *pLeap = *pRun;
                pLeap++;
                pRun++;
            }
        }
        if( nActualToken != nToken )
            pBuffer[0] = 0;
        nActualToken++;
    }

    *pLeap = 0;

    ByteString aRet( pBuffer );
    return aRet;
}

int GetCommandLineTokenCount( const String& rLine )
{
    if( ! rLine.Len() )
        return 0;

    int nTokenCount = 0;
    const sal_Unicode *pRun = rLine.GetBuffer();

    while( *pRun )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        if( ! *pRun )
            break;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
            {
                do pRun++; while( *pRun && *pRun != '`' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '\'' )
            {
                do pRun++; while( *pRun && *pRun != '\'' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '"' )
            {
                do pRun++; while( *pRun && *pRun != '"' );
                if( *pRun )
                    pRun++;
            }
            else
                pRun++;
        }
        nTokenCount++;
    }

    return nTokenCount;
}

int GetCommandLineTokenCount( const ByteString& rLine )
{
    if( ! rLine.Len() )
        return 0;

    int nTokenCount = 0;
    const char *pRun = rLine.GetBuffer();

    while( *pRun )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        if( ! *pRun )
            break;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
            {
                do pRun++; while( *pRun && *pRun != '`' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '\'' )
            {
                do pRun++; while( *pRun && *pRun != '\'' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '"' )
            {
                do pRun++; while( *pRun && *pRun != '"' );
                if( *pRun )
                    pRun++;
            }
            else
                pRun++;
        }
        nTokenCount++;
    }

    return nTokenCount;
}

String WhitespaceToSpace( const String& rLine, BOOL bProtect )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return String();

    sal_Unicode *pBuffer = (sal_Unicode*)alloca( sizeof(sal_Unicode)*(nLen + 1) );
    const sal_Unicode *pRun = rLine.GetBuffer();
    sal_Unicode *pLeap = pBuffer;

    while( *pRun )
    {
        if( *pRun && isSpace( *pRun ) )
        {
            *pLeap = ' ';
            pLeap++;
            pRun++;
        }
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( bProtect && *pRun == '`' )
                CopyUntil( pLeap, pRun, '`', TRUE );
            else if( bProtect && *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'', TRUE );
            else if( bProtect && *pRun == '"' )
                CopyUntil( pLeap, pRun, '"', TRUE );
            else
            {
                *pLeap = *pRun;
                *pLeap++;
                *pRun++;
            }
        }
    }

    *pLeap = 0;

    // there might be a space at beginning or end
    pLeap--;
    if( *pLeap == ' ' )
        *pLeap = 0;

    String aRet( *pBuffer == ' ' ? pBuffer+1 : pBuffer );
    return aRet;
}

ByteString WhitespaceToSpace( const ByteString& rLine, BOOL bProtect )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return ByteString();

    char *pBuffer = (char*)alloca( nLen + 1 );
    const char *pRun = rLine.GetBuffer();
    char *pLeap = pBuffer;

    while( *pRun )
    {
        if( *pRun && isSpace( *pRun ) )
        {
            *pLeap = ' ';
            pLeap++;
            pRun++;
        }
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( bProtect && *pRun == '`' )
                CopyUntil( pLeap, pRun, '`', TRUE );
            else if( bProtect && *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'', TRUE );
            else if( bProtect && *pRun == '"' )
                CopyUntil( pLeap, pRun, '"', TRUE );
            else
            {
                *pLeap = *pRun;
                *pLeap++;
                *pRun++;
            }
        }
    }

    *pLeap = 0;

    // there might be a space at beginning or end
    pLeap--;
    if( *pLeap == ' ' )
        *pLeap = 0;

    ByteString aRet( *pBuffer == ' ' ? pBuffer+1 : pBuffer );
    return aRet;
}

} // namespace
<commit_msg>#i113069# fix useless dereference<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include "vcl/strhelper.hxx"
#include "sal/alloca.h"

namespace psp {

inline int isSpace( char cChar )
{
    return
        cChar == ' '    || cChar == '\t'    ||
        cChar == '\r'   || cChar == '\n'    ||
        cChar == 0x0c   || cChar == 0x0b;
}

inline int isSpace( sal_Unicode cChar )
{
    return
        cChar == ' '    || cChar == '\t'    ||
        cChar == '\r'   || cChar == '\n'    ||
        cChar == 0x0c   || cChar == 0x0b;
}

inline int isProtect( char cChar )
{
    return cChar == '`' || cChar == '\'' || cChar == '"';
}

inline int isProtect( sal_Unicode cChar )
{
    return cChar == '`' || cChar == '\'' || cChar == '"';
}

inline void CopyUntil( char*& pTo, const char*& pFrom, char cUntil, int bIncludeUntil = 0 )
{
    do
    {
        if( *pFrom == '\\' )
        {
            pFrom++;
            if( *pFrom )
            {
                *pTo = *pFrom;
                pTo++;
            }
        }
        else if( bIncludeUntil || ! isProtect( *pFrom ) )
        {
            *pTo = *pFrom;
            pTo++;
        }
        pFrom++;
    } while( *pFrom && *pFrom != cUntil );
    // copy the terminating character unless zero or protector
    if( ! isProtect( *pFrom ) || bIncludeUntil )
    {
        *pTo = *pFrom;
        if( *pTo )
            pTo++;
    }
    if( *pFrom )
        pFrom++;
}

inline void CopyUntil( sal_Unicode*& pTo, const sal_Unicode*& pFrom, sal_Unicode cUntil, int bIncludeUntil = 0 )
{
    do
    {
        if( *pFrom == '\\' )
        {
            pFrom++;
            if( *pFrom )
            {
                *pTo = *pFrom;
                pTo++;
            }
        }
        else if( bIncludeUntil || ! isProtect( *pFrom ) )
        {
            *pTo = *pFrom;
            pTo++;
        }
        pFrom++;
    } while( *pFrom && *pFrom != cUntil );
    // copy the terminating character unless zero or protector
    if( ! isProtect( *pFrom ) || bIncludeUntil )
    {
        *pTo = *pFrom;
        if( *pTo )
            pTo++;
    }
    if( *pFrom )
        pFrom++;
}

String GetCommandLineToken( int nToken, const String& rLine )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return String();

    int nActualToken = 0;
    sal_Unicode* pBuffer = (sal_Unicode*)alloca( sizeof(sal_Unicode)*( nLen + 1 ) );
    const sal_Unicode* pRun = rLine.GetBuffer();
    sal_Unicode* pLeap = NULL;

    while( *pRun && nActualToken <= nToken )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        pLeap = pBuffer;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
                CopyUntil( pLeap, pRun, '`' );
            else if( *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'' );
            else if( *pRun == '"' )
                CopyUntil( pLeap, pRun, '"' );
            else
            {
                *pLeap = *pRun;
                pLeap++;
                pRun++;
            }
        }
        if( nActualToken != nToken )
            pBuffer[0] = 0;
        nActualToken++;
    }

    *pLeap = 0;

    String aRet( pBuffer );
    return aRet;
}

ByteString GetCommandLineToken( int nToken, const ByteString& rLine )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return ByteString();

    int nActualToken = 0;
    char* pBuffer = (char*)alloca( nLen + 1 );
    const char* pRun = rLine.GetBuffer();
    char* pLeap = NULL;

    while( *pRun && nActualToken <= nToken )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        pLeap = pBuffer;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
                CopyUntil( pLeap, pRun, '`' );
            else if( *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'' );
            else if( *pRun == '"' )
                CopyUntil( pLeap, pRun, '"' );
            else
            {
                *pLeap = *pRun;
                pLeap++;
                pRun++;
            }
        }
        if( nActualToken != nToken )
            pBuffer[0] = 0;
        nActualToken++;
    }

    *pLeap = 0;

    ByteString aRet( pBuffer );
    return aRet;
}

int GetCommandLineTokenCount( const String& rLine )
{
    if( ! rLine.Len() )
        return 0;

    int nTokenCount = 0;
    const sal_Unicode *pRun = rLine.GetBuffer();

    while( *pRun )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        if( ! *pRun )
            break;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
            {
                do pRun++; while( *pRun && *pRun != '`' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '\'' )
            {
                do pRun++; while( *pRun && *pRun != '\'' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '"' )
            {
                do pRun++; while( *pRun && *pRun != '"' );
                if( *pRun )
                    pRun++;
            }
            else
                pRun++;
        }
        nTokenCount++;
    }

    return nTokenCount;
}

int GetCommandLineTokenCount( const ByteString& rLine )
{
    if( ! rLine.Len() )
        return 0;

    int nTokenCount = 0;
    const char *pRun = rLine.GetBuffer();

    while( *pRun )
    {
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        if( ! *pRun )
            break;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '`' )
            {
                do pRun++; while( *pRun && *pRun != '`' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '\'' )
            {
                do pRun++; while( *pRun && *pRun != '\'' );
                if( *pRun )
                    pRun++;
            }
            else if( *pRun == '"' )
            {
                do pRun++; while( *pRun && *pRun != '"' );
                if( *pRun )
                    pRun++;
            }
            else
                pRun++;
        }
        nTokenCount++;
    }

    return nTokenCount;
}

String WhitespaceToSpace( const String& rLine, BOOL bProtect )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return String();

    sal_Unicode *pBuffer = (sal_Unicode*)alloca( sizeof(sal_Unicode)*(nLen + 1) );
    const sal_Unicode *pRun = rLine.GetBuffer();
    sal_Unicode *pLeap = pBuffer;

    while( *pRun )
    {
        if( *pRun && isSpace( *pRun ) )
        {
            *pLeap = ' ';
            pLeap++;
            pRun++;
        }
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( bProtect && *pRun == '`' )
                CopyUntil( pLeap, pRun, '`', TRUE );
            else if( bProtect && *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'', TRUE );
            else if( bProtect && *pRun == '"' )
                CopyUntil( pLeap, pRun, '"', TRUE );
            else
            {
                *pLeap = *pRun;
                ++pLeap;
                ++pRun;
            }
        }
    }

    *pLeap = 0;

    // there might be a space at beginning or end
    pLeap--;
    if( *pLeap == ' ' )
        *pLeap = 0;

    String aRet( *pBuffer == ' ' ? pBuffer+1 : pBuffer );
    return aRet;
}

ByteString WhitespaceToSpace( const ByteString& rLine, BOOL bProtect )
{
    int nLen = rLine.Len();
    if( ! nLen )
        return ByteString();

    char *pBuffer = (char*)alloca( nLen + 1 );
    const char *pRun = rLine.GetBuffer();
    char *pLeap = pBuffer;

    while( *pRun )
    {
        if( *pRun && isSpace( *pRun ) )
        {
            *pLeap = ' ';
            pLeap++;
            pRun++;
        }
        while( *pRun && isSpace( *pRun ) )
            pRun++;
        while( *pRun && ! isSpace( *pRun ) )
        {
            if( *pRun == '\\' )
            {
                // escapement
                pRun++;
                *pLeap = *pRun;
                pLeap++;
                if( *pRun )
                    pRun++;
            }
            else if( bProtect && *pRun == '`' )
                CopyUntil( pLeap, pRun, '`', TRUE );
            else if( bProtect && *pRun == '\'' )
                CopyUntil( pLeap, pRun, '\'', TRUE );
            else if( bProtect && *pRun == '"' )
                CopyUntil( pLeap, pRun, '"', TRUE );
            else
            {
                *pLeap = *pRun;
                ++pLeap;
                ++pRun;
            }
        }
    }

    *pLeap = 0;

    // there might be a space at beginning or end
    pLeap--;
    if( *pLeap == ' ' )
        *pLeap = 0;

    ByteString aRet( *pBuffer == ' ' ? pBuffer+1 : pBuffer );
    return aRet;
}

} // namespace
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "coreplugin.h"
#include "designmode.h"
#include "editmode.h"
#include "helpmanager.h"
#include "mainwindow.h"
#include "mimedatabase.h"
#include "modemanager.h"
#include "infobar.h"
#include "iwizardfactory.h"

#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/findplugin.h>
#include <coreplugin/locator/locator.h>

#include <utils/savefile.h>

#include <QtPlugin>
#include <QDebug>
#include <QDateTime>

using namespace Core;
using namespace Core::Internal;

CorePlugin::CorePlugin() : m_editMode(0), m_designMode(0)
{
    qRegisterMetaType<Core::Id>();
    m_mainWindow = new MainWindow;
    m_findPlugin = new FindPlugin;
    m_locator = new Locator;
}

CorePlugin::~CorePlugin()
{
    IWizardFactory::destroyFeatureProvider();

    delete m_findPlugin;
    delete m_locator;

    if (m_editMode) {
        removeObject(m_editMode);
        delete m_editMode;
    }

    if (m_designMode) {
        if (m_designMode->designModeIsRequired())
            removeObject(m_designMode);
        delete m_designMode;
    }

    delete m_mainWindow;
}

void CorePlugin::parseArguments(const QStringList &arguments)
{
    for (int i = 0; i < arguments.size(); ++i) {
        if (arguments.at(i) == QLatin1String("-color")) {
            const QString colorcode(arguments.at(i + 1));
            m_mainWindow->setOverrideColor(QColor(colorcode));
            i++; // skip the argument
        }
        if (arguments.at(i) == QLatin1String("-presentationMode"))
            ActionManager::setPresentationModeEnabled(true);
    }
}

bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    qsrand(QDateTime::currentDateTime().toTime_t());
    parseArguments(arguments);
    const bool success = m_mainWindow->init(errorMessage);
    if (success) {
        m_editMode = new EditMode;
        addObject(m_editMode);
        ModeManager::activateMode(m_editMode->id());
        m_designMode = new DesignMode;
        InfoBar::initializeGloballySuppressed();
    }

    // Make sure we respect the process's umask when creating new files
    Utils::SaveFile::initializeUmask();

    m_findPlugin->initialize(arguments, errorMessage);
    m_locator->initialize(this, arguments, errorMessage);

    return success;
}

void CorePlugin::extensionsInitialized()
{
    MimeDatabase::syncUserModifiedMimeTypes();
    if (m_designMode->designModeIsRequired())
        addObject(m_designMode);
    m_findPlugin->extensionsInitialized();
    m_locator->extensionsInitialized();
    m_mainWindow->extensionsInitialized();
}

bool CorePlugin::delayedInitialize()
{
    HelpManager::setupHelpManager();
    m_locator->delayedInitialize();
    return true;
}

QObject *CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args)
{
    IDocument *res = m_mainWindow->openFiles(
                args, ICore::OpenFilesFlags(ICore::SwitchMode | ICore::CanContainLineNumbers));
    m_mainWindow->raiseWindow();
    return res;
}

void CorePlugin::fileOpenRequest(const QString &f)
{
    remoteCommand(QStringList(), QStringList(f));
}

ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown()
{
    m_findPlugin->aboutToShutdown();
    m_mainWindow->aboutToShutdown();
    return SynchronousShutdown;
}
<commit_msg>MacroExpander: Add variables for date and time<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "coreplugin.h"
#include "designmode.h"
#include "editmode.h"
#include "helpmanager.h"
#include "mainwindow.h"
#include "mimedatabase.h"
#include "modemanager.h"
#include "infobar.h"
#include "iwizardfactory.h"

#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/findplugin.h>
#include <coreplugin/locator/locator.h>

#include <utils/macroexpander.h>
#include <utils/savefile.h>

#include <QtPlugin>
#include <QDebug>
#include <QDateTime>

using namespace Core;
using namespace Core::Internal;

CorePlugin::CorePlugin() : m_editMode(0), m_designMode(0)
{
    qRegisterMetaType<Core::Id>();
    m_mainWindow = new MainWindow;
    m_findPlugin = new FindPlugin;
    m_locator = new Locator;
}

CorePlugin::~CorePlugin()
{
    IWizardFactory::destroyFeatureProvider();

    delete m_findPlugin;
    delete m_locator;

    if (m_editMode) {
        removeObject(m_editMode);
        delete m_editMode;
    }

    if (m_designMode) {
        if (m_designMode->designModeIsRequired())
            removeObject(m_designMode);
        delete m_designMode;
    }

    delete m_mainWindow;
}

void CorePlugin::parseArguments(const QStringList &arguments)
{
    for (int i = 0; i < arguments.size(); ++i) {
        if (arguments.at(i) == QLatin1String("-color")) {
            const QString colorcode(arguments.at(i + 1));
            m_mainWindow->setOverrideColor(QColor(colorcode));
            i++; // skip the argument
        }
        if (arguments.at(i) == QLatin1String("-presentationMode"))
            ActionManager::setPresentationModeEnabled(true);
    }
}

bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    qsrand(QDateTime::currentDateTime().toTime_t());
    parseArguments(arguments);
    const bool success = m_mainWindow->init(errorMessage);
    if (success) {
        m_editMode = new EditMode;
        addObject(m_editMode);
        ModeManager::activateMode(m_editMode->id());
        m_designMode = new DesignMode;
        InfoBar::initializeGloballySuppressed();
    }

    // Make sure we respect the process's umask when creating new files
    Utils::SaveFile::initializeUmask();

    m_findPlugin->initialize(arguments, errorMessage);
    m_locator->initialize(this, arguments, errorMessage);

    Utils::MacroExpander *expander = Utils::globalMacroExpander();
    expander->registerVariable("CurrentDate:ISO", tr("The current date (ISO)."),
                               []() { return QDate::currentDate().toString(Qt::ISODate); });
    expander->registerVariable("CurrentTime:ISO", tr("The current time (ISO)."),
                               []() { return QTime::currentTime().toString(Qt::ISODate); });
    expander->registerVariable("CurrentDate:RFC", tr("The current date (RFC2822)."),
                               []() { return QDate::currentDate().toString(Qt::RFC2822Date); });
    expander->registerVariable("CurrentTime:RFC", tr("The current time (RFC2822)."),
                               []() { return QTime::currentTime().toString(Qt::RFC2822Date); });
    expander->registerVariable("CurrentDate:Locale", tr("The current date (Locale)."),
                               []() { return QDate::currentDate().toString(Qt::DefaultLocaleShortDate); });
    expander->registerVariable("CurrentTime:Locale", tr("The current time (Locale)."),
                               []() { return QTime::currentTime().toString(Qt::DefaultLocaleShortDate); });
    expander->registerPrefix("CurrentDate:", tr("The current date (QDate formatstring)"),
                             [](const QString &fmt) { return QDate::currentDate().toString(fmt); });
    expander->registerPrefix("CurrentTime:", tr("The current time (QTime formatstring)"),
                             [](const QString &fmt) { return QTime::currentTime().toString(fmt); });

    return success;
}

void CorePlugin::extensionsInitialized()
{
    MimeDatabase::syncUserModifiedMimeTypes();
    if (m_designMode->designModeIsRequired())
        addObject(m_designMode);
    m_findPlugin->extensionsInitialized();
    m_locator->extensionsInitialized();
    m_mainWindow->extensionsInitialized();
}

bool CorePlugin::delayedInitialize()
{
    HelpManager::setupHelpManager();
    m_locator->delayedInitialize();
    return true;
}

QObject *CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args)
{
    IDocument *res = m_mainWindow->openFiles(
                args, ICore::OpenFilesFlags(ICore::SwitchMode | ICore::CanContainLineNumbers));
    m_mainWindow->raiseWindow();
    return res;
}

void CorePlugin::fileOpenRequest(const QString &f)
{
    remoteCommand(QStringList(), QStringList(f));
}

ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown()
{
    m_findPlugin->aboutToShutdown();
    m_mainWindow->aboutToShutdown();
    return SynchronousShutdown;
}
<|endoftext|>


<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
// Boost
#include <boost/date_time/date_iterator.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/basic/BasConst_Inventory.hpp>
#include <stdair/bom/BomManager.hpp>
#include <stdair/bom/BomRoot.hpp>
#include <stdair/bom/Inventory.hpp>
#include <stdair/bom/AirlineFeature.hpp>
#include <stdair/bom/FlightPeriod.hpp>
#include <stdair/bom/SegmentPeriod.hpp>
#include <stdair/factory/FacBomManager.hpp>
#include <stdair/service/Logger.hpp>
// AirSched
#include <airsched/bom/FlightPeriodStruct.hpp>
#include <airsched/bom/SegmentPeriodHelper.hpp>
#include <airsched/command/InventoryGenerator.hpp>

namespace AIRSCHED {

  // ////////////////////////////////////////////////////////////////////
  void InventoryGenerator::
  createFlightPeriod (stdair::BomRoot& ioBomRoot,
                      const FlightPeriodStruct& iFlightPeriodStruct) {

    const stdair::AirlineCode_T& lAirlineCode = iFlightPeriodStruct._airlineCode;

    // Instantiate an inventory object (if not exist)
    // for the given key (airline code)
    stdair::Inventory* lInventory_ptr = stdair::BomManager::
      getObjectPtr<stdair::Inventory> (ioBomRoot, lAirlineCode);
    if (lInventory_ptr == NULL) {
      stdair::InventoryKey lKey (lAirlineCode);

      lInventory_ptr =
        &stdair::FacBom<stdair::Inventory>::instance().create (lKey);
      stdair::FacBomManager::addToListAndMap (ioBomRoot, *lInventory_ptr);
      stdair::FacBomManager::linkWithParent (ioBomRoot, *lInventory_ptr);

      // Add the airline feature object to the inventory
      const stdair::AirlineFeatureKey lAirlineFeatureKey (lAirlineCode);
      stdair::AirlineFeature& lAirlineFeature =
        stdair::FacBom<stdair::AirlineFeature>::instance().create (lAirlineFeatureKey);
      lInventory_ptr->setAirlineFeature (lAirlineFeature);
    }
    assert (lInventory_ptr != NULL);

    // Create the flight-period key.
    const stdair::PeriodStruct lPeriod (iFlightPeriodStruct._dateRange,
                                        iFlightPeriodStruct._dow);
    const stdair::FlightPeriodKey
      lFlightPeriodKey (iFlightPeriodStruct._flightNumber, lPeriod);

    // Check that the flight-period object is not already created.
    stdair::FlightPeriod* lFlightPeriod_ptr = stdair::BomManager::
      getObjectPtr<stdair::FlightPeriod> (*lInventory_ptr,
                                          lFlightPeriodKey.toString());
    if (lFlightPeriod_ptr != NULL) {
      throw stdair::ObjectCreationgDuplicationException ("");
    }
    assert (lFlightPeriod_ptr == NULL);

    // Instantiate a flight-period object with the given key.
    lFlightPeriod_ptr = &stdair::FacBom<stdair::FlightPeriod>::
      instance().create (lFlightPeriodKey);
    stdair::FacBomManager::addToListAndMap (*lInventory_ptr, *lFlightPeriod_ptr);
    stdair::FacBomManager::linkWithParent (*lInventory_ptr, *lFlightPeriod_ptr);

    // Create the segment-periods.
    createSegmentPeriods (*lFlightPeriod_ptr, iFlightPeriodStruct);
  }

  // ////////////////////////////////////////////////////////////////////
  void InventoryGenerator::
  createSegmentPeriods (stdair::FlightPeriod& ioFlightPeriod,
                        const FlightPeriodStruct& iFlightPeriodStruct) {

    // Iterate on the segment strutures.
    const SegmentStructList_T& lSegmentList = iFlightPeriodStruct._segmentList;
    for (SegmentStructList_T::const_iterator itSegment = lSegmentList.begin();
         itSegment != lSegmentList.end(); ++itSegment) {

      const SegmentStruct& lSegment = *itSegment;

      // Set the segment-period primary key.
      const stdair::AirportCode_T& lBoardingPoint = lSegment._boardingPoint;
      const stdair::AirportCode_T& lOffPoint = lSegment._offPoint;
      const stdair::SegmentPeriodKey lSegmentPeriodKey (lBoardingPoint,
                                                          lOffPoint);

      // Instantiate a segment-perioed with the key.
      stdair::SegmentPeriod& lSegmentPeriod = stdair::
        FacBom<stdair::SegmentPeriod>::instance().create (lSegmentPeriodKey);
      stdair::FacBomManager::addToListAndMap (ioFlightPeriod, lSegmentPeriod);
      stdair::FacBomManager::linkWithParent (ioFlightPeriod, lSegmentPeriod);

      // Set the segment-period attributes.
      SegmentPeriodHelper::fill (lSegmentPeriod, lSegment);
      SegmentPeriodHelper::fill (lSegmentPeriod, iFlightPeriodStruct._legList);
    }
  }

}
<commit_msg>[Dev] Use the StdAir FacBomManager to specify the Inventory/AirlineFeature links and add a list/map of AirlineFeature objects at the BOM root level.<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
// Boost
#include <boost/date_time/date_iterator.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/basic/BasConst_Inventory.hpp>
#include <stdair/bom/BomManager.hpp>
#include <stdair/bom/BomRoot.hpp>
#include <stdair/bom/Inventory.hpp>
#include <stdair/bom/AirlineFeature.hpp>
#include <stdair/bom/FlightPeriod.hpp>
#include <stdair/bom/SegmentPeriod.hpp>
#include <stdair/factory/FacBomManager.hpp>
#include <stdair/service/Logger.hpp>
// AirSched
#include <airsched/bom/FlightPeriodStruct.hpp>
#include <airsched/bom/SegmentPeriodHelper.hpp>
#include <airsched/command/InventoryGenerator.hpp>

namespace AIRSCHED {

  // ////////////////////////////////////////////////////////////////////
  void InventoryGenerator::
  createFlightPeriod (stdair::BomRoot& ioBomRoot,
                      const FlightPeriodStruct& iFlightPeriodStruct) {

    const stdair::AirlineCode_T& lAirlineCode = iFlightPeriodStruct._airlineCode;

    // Instantiate an inventory object (if not exist)
    // for the given key (airline code)
    stdair::Inventory* lInventory_ptr = stdair::BomManager::
      getObjectPtr<stdair::Inventory> (ioBomRoot, lAirlineCode);
    if (lInventory_ptr == NULL) {
      stdair::InventoryKey lKey (lAirlineCode);

      lInventory_ptr =
        &stdair::FacBom<stdair::Inventory>::instance().create (lKey);
      stdair::FacBomManager::addToListAndMap (ioBomRoot, *lInventory_ptr);
      stdair::FacBomManager::linkWithParent (ioBomRoot, *lInventory_ptr);

      // Add the airline feature object to the inventory
      const stdair::AirlineFeatureKey lAirlineFeatureKey (lAirlineCode);
      stdair::AirlineFeature& lAirlineFeature =
        stdair::FacBom<stdair::AirlineFeature>::instance().create (lAirlineFeatureKey);
      stdair::FacBomManager::setAirlineFeature (*lInventory_ptr,
                                                lAirlineFeature);
      stdair::FacBomManager::linkWithParent (*lInventory_ptr, lAirlineFeature);
      // Link the airline feature object with the top of the BOM tree
      stdair::FacBomManager::addToListAndMap (ioBomRoot, lAirlineFeature);
    }
    assert (lInventory_ptr != NULL);

    // Create the flight-period key.
    const stdair::PeriodStruct lPeriod (iFlightPeriodStruct._dateRange,
                                        iFlightPeriodStruct._dow);
    const stdair::FlightPeriodKey
      lFlightPeriodKey (iFlightPeriodStruct._flightNumber, lPeriod);

    // Check that the flight-period object is not already created.
    stdair::FlightPeriod* lFlightPeriod_ptr = stdair::BomManager::
      getObjectPtr<stdair::FlightPeriod> (*lInventory_ptr,
                                          lFlightPeriodKey.toString());
    if (lFlightPeriod_ptr != NULL) {
      throw stdair::ObjectCreationgDuplicationException ("");
    }
    assert (lFlightPeriod_ptr == NULL);

    // Instantiate a flight-period object with the given key.
    lFlightPeriod_ptr = &stdair::FacBom<stdair::FlightPeriod>::
      instance().create (lFlightPeriodKey);
    stdair::FacBomManager::addToListAndMap (*lInventory_ptr, *lFlightPeriod_ptr);
    stdair::FacBomManager::linkWithParent (*lInventory_ptr, *lFlightPeriod_ptr);

    // Create the segment-periods.
    createSegmentPeriods (*lFlightPeriod_ptr, iFlightPeriodStruct);
  }

  // ////////////////////////////////////////////////////////////////////
  void InventoryGenerator::
  createSegmentPeriods (stdair::FlightPeriod& ioFlightPeriod,
                        const FlightPeriodStruct& iFlightPeriodStruct) {

    // Iterate on the segment strutures.
    const SegmentStructList_T& lSegmentList = iFlightPeriodStruct._segmentList;
    for (SegmentStructList_T::const_iterator itSegment = lSegmentList.begin();
         itSegment != lSegmentList.end(); ++itSegment) {

      const SegmentStruct& lSegment = *itSegment;

      // Set the segment-period primary key.
      const stdair::AirportCode_T& lBoardingPoint = lSegment._boardingPoint;
      const stdair::AirportCode_T& lOffPoint = lSegment._offPoint;
      const stdair::SegmentPeriodKey lSegmentPeriodKey (lBoardingPoint,
                                                          lOffPoint);

      // Instantiate a segment-perioed with the key.
      stdair::SegmentPeriod& lSegmentPeriod = stdair::
        FacBom<stdair::SegmentPeriod>::instance().create (lSegmentPeriodKey);
      stdair::FacBomManager::addToListAndMap (ioFlightPeriod, lSegmentPeriod);
      stdair::FacBomManager::linkWithParent (ioFlightPeriod, lSegmentPeriod);

      // Set the segment-period attributes.
      SegmentPeriodHelper::fill (lSegmentPeriod, lSegment);
      SegmentPeriodHelper::fill (lSegmentPeriod, iFlightPeriodStruct._legList);
    }
  }

}
<|endoftext|>


<commit_before>///
/// @file   ParallelPrimeSieve.cpp
/// @brief  Sieve primes in parallel using OpenMP.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/config.hpp>
#include <primesieve/ParallelPrimeSieve.hpp>
#include <primesieve/PrimeSieve.hpp>
#include <primesieve/pmath.hpp>

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cstddef>

#ifdef _OPENMP
  #include <omp.h>
  #include <primesieve/ParallelPrimeSieve-lock.hpp>
#endif

using namespace std;

namespace primesieve {

ParallelPrimeSieve::ParallelPrimeSieve() :
  lock_(NULL),
  shm_(NULL),
  numThreads_(getMaxThreads())
{ }

void ParallelPrimeSieve::init(SharedMemory& shm)
{
  setStart(shm.start);
  setStop(shm.stop);
  setSieveSize(shm.sieveSize);
  setFlags(shm.flags);
  setNumThreads(shm.threads);
  shm_ = &shm;
}

int ParallelPrimeSieve::getNumThreads() const
{
  return numThreads_;
}

void ParallelPrimeSieve::setNumThreads(int threads)
{
  numThreads_ = inBetween(1, threads, getMaxThreads());
}

/// Get an ideal number of threads for
/// the start_ and stop_ numbers.
///
int ParallelPrimeSieve::idealNumThreads() const
{
  if (start_ > stop_)
    return 1;

  uint64_t threshold = max(config::MIN_THREAD_DISTANCE, isqrt(stop_) / 5);
  uint64_t threads = getDistance() / threshold;
  threads = inBetween(1, threads, numThreads_);

  return static_cast<int>(threads);
}

/// Get a thread distance which ensures a good load
/// balance when using multiple threads.
///
uint64_t ParallelPrimeSieve::getThreadDistance(int threads) const
{
  assert(threads > 0);
  uint64_t unbalanced = getDistance() / threads;
  uint64_t balanced = isqrt(stop_) * 1000;
  uint64_t fastest = min(balanced, unbalanced);
  uint64_t threadDistance = inBetween(config::MIN_THREAD_DISTANCE, fastest, config::MAX_THREAD_DISTANCE);
  uint64_t chunks = getDistance() / threadDistance;

  if (chunks < threads * 5u)
    threadDistance = max(config::MIN_THREAD_DISTANCE, unbalanced);

  threadDistance += 30 - threadDistance % 30;
  return threadDistance;
}

/// Align n to modulo 30 + 2 to prevent prime k-tuplet
/// (twin primes, prime triplets, ...) gaps.
///
uint64_t ParallelPrimeSieve::align(uint64_t n) const
{
  if (add_overflow_safe(n, 32) >= stop_)
    return stop_;

  n = add_overflow_safe(n, 32) - n % 30;
  return min(n, stop_);
}

#ifdef _OPENMP

int ParallelPrimeSieve::getMaxThreads()
{
  return max(1, omp_get_max_threads());
}

double ParallelPrimeSieve::getWallTime() const
{
  return omp_get_wtime();
}

/// Sieve the primes and prime k-tuplets within [start_, stop_]
/// in parallel using OpenMP multi-threading.
///
void ParallelPrimeSieve::sieve()
{
  reset();
  OmpInitLock ompInit(&lock_);

  if (start_ > stop_)
    return;

  int threads = idealNumThreads();

  if (threads == 1)
    PrimeSieve::sieve();
  else
  {
    uint64_t threadDistance = getThreadDistance(threads);
    uint64_t count0 = 0, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0;
    int64_t iters = 1 + (getDistance() - 1) / threadDistance;
    double t1 = getWallTime();

    #pragma omp parallel for schedule(dynamic) num_threads(threads) \
        reduction(+: count0, count1, count2, count3, count4, count5)
    for (int64_t i = 0; i < iters; i++)
    {
      uint64_t threadStart = start_ + i * threadDistance;
      uint64_t threadStop = add_overflow_safe(threadStart, threadDistance);
      if (i > 0) threadStart = align(threadStart) + 1;
      threadStop = align(threadStop);

      PrimeSieve ps(*this, omp_get_thread_num());
      ps.sieve(threadStart, threadStop);

      count0 += ps.getCount(0);
      count1 += ps.getCount(1);
      count2 += ps.getCount(2);
      count3 += ps.getCount(3);
      count4 += ps.getCount(4);
      count5 += ps.getCount(5);
    }

    seconds_ = getWallTime() - t1;

    counts_[0] = count0;
    counts_[1] = count1;
    counts_[2] = count2;
    counts_[3] = count3;
    counts_[4] = count4;
    counts_[5] = count5;
  }

  if (shm_)
  {
    // communicate the sieving results to
    // the primesieve GUI application
    copy(counts_.begin(), counts_.end(), shm_->counts);
    shm_->seconds = seconds_;
  }
}

/// Calculate the sieving status.
/// @param processed  Sum of recently processed segments.
///
bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  OmpLockGuard lock(getLock<omp_lock_t*>(), waitForLock);
  if (lock.isSet())
  {
    PrimeSieve::updateStatus(processed);
    if (shm_)
      shm_->status = getStatus();
  }
  return lock.isSet();
}

/// Used to synchronize threads for prime number generation

void ParallelPrimeSieve::setLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_set_lock(lock);
}

void ParallelPrimeSieve::unsetLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_unset_lock(lock);
}

#endif /* _OPENMP */

/// If OpenMP is disabled then ParallelPrimeSieve behaves like
/// the single threaded PrimeSieve.
///
#if !defined(_OPENMP)

int ParallelPrimeSieve::getMaxThreads()
{
  return 1;
}

void ParallelPrimeSieve::sieve()
{
  PrimeSieve::sieve();

  if (shm_)
  {
    // communicate the sieving results to the
    // primesieve GUI application
    copy(counts_.begin(), counts_.end(), shm_->counts);
    shm_->seconds = seconds_;
  }
}

double ParallelPrimeSieve::getWallTime() const
{
  return PrimeSieve::getWallTime();
}

bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  bool isUpdate = PrimeSieve::updateStatus(processed, waitForLock);
  if (shm_)
    shm_->status = getStatus();
  return isUpdate;
}

void ParallelPrimeSieve::setLock() { }

void ParallelPrimeSieve::unsetLock() { }

#endif

} // namespace
<commit_msg>Refactor<commit_after>///
/// @file   ParallelPrimeSieve.cpp
/// @brief  Sieve primes in parallel using OpenMP.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/config.hpp>
#include <primesieve/ParallelPrimeSieve.hpp>
#include <primesieve/PrimeSieve.hpp>
#include <primesieve/pmath.hpp>

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cstddef>

#ifdef _OPENMP
  #include <omp.h>
  #include <primesieve/ParallelPrimeSieve-lock.hpp>
#endif

using namespace std;

namespace primesieve {

ParallelPrimeSieve::ParallelPrimeSieve() :
  lock_(NULL),
  shm_(NULL),
  numThreads_(getMaxThreads())
{ }

void ParallelPrimeSieve::init(SharedMemory& shm)
{
  setStart(shm.start);
  setStop(shm.stop);
  setSieveSize(shm.sieveSize);
  setFlags(shm.flags);
  setNumThreads(shm.threads);
  shm_ = &shm;
}

int ParallelPrimeSieve::getNumThreads() const
{
  return numThreads_;
}

void ParallelPrimeSieve::setNumThreads(int threads)
{
  numThreads_ = inBetween(1, threads, getMaxThreads());
}

/// Get an ideal number of threads for
/// the start_ and stop_ numbers.
///
int ParallelPrimeSieve::idealNumThreads() const
{
  if (start_ > stop_)
    return 1;

  uint64_t threshold = max(config::MIN_THREAD_DISTANCE, isqrt(stop_) / 5);
  uint64_t threads = getDistance() / threshold;
  threads = inBetween(1, threads, numThreads_);

  return static_cast<int>(threads);
}

/// Get a thread distance which ensures a good load
/// balance when using multiple threads.
///
uint64_t ParallelPrimeSieve::getThreadDistance(int threads) const
{
  assert(threads > 0);
  uint64_t unbalanced = getDistance() / threads;
  uint64_t balanced = isqrt(stop_) * 1000;
  uint64_t fastest = min(balanced, unbalanced);
  uint64_t threadDistance = inBetween(config::MIN_THREAD_DISTANCE, fastest, config::MAX_THREAD_DISTANCE);
  uint64_t chunks = getDistance() / threadDistance;

  if (chunks < threads * 5u)
    threadDistance = max(config::MIN_THREAD_DISTANCE, unbalanced);

  threadDistance += 30 - threadDistance % 30;
  return threadDistance;
}

/// Align n to modulo 30 + 2 to prevent prime k-tuplet
/// (twin primes, prime triplets, ...) gaps.
///
uint64_t ParallelPrimeSieve::align(uint64_t n) const
{
  if (add_overflow_safe(n, 32) >= stop_)
    return stop_;

  n = add_overflow_safe(n, 32) - n % 30;
  n = min(n, stop_);

  return n;
}

#ifdef _OPENMP

int ParallelPrimeSieve::getMaxThreads()
{
  return max(1, omp_get_max_threads());
}

double ParallelPrimeSieve::getWallTime() const
{
  return omp_get_wtime();
}

/// Sieve the primes and prime k-tuplets within [start_, stop_]
/// in parallel using OpenMP multi-threading.
///
void ParallelPrimeSieve::sieve()
{
  reset();
  OmpInitLock ompInit(&lock_);

  if (start_ > stop_)
    return;

  int threads = idealNumThreads();

  if (threads == 1)
    PrimeSieve::sieve();
  else
  {
    uint64_t threadDistance = getThreadDistance(threads);
    uint64_t count0 = 0, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0;
    int64_t iters = 1 + (getDistance() - 1) / threadDistance;
    double t1 = getWallTime();

    #pragma omp parallel for schedule(dynamic) num_threads(threads) \
        reduction(+: count0, count1, count2, count3, count4, count5)
    for (int64_t i = 0; i < iters; i++)
    {
      uint64_t threadStart = start_ + i * threadDistance;
      uint64_t threadStop = add_overflow_safe(threadStart, threadDistance);
      if (i > 0) threadStart = align(threadStart) + 1;
      threadStop = align(threadStop);

      PrimeSieve ps(*this, omp_get_thread_num());
      ps.sieve(threadStart, threadStop);

      count0 += ps.getCount(0);
      count1 += ps.getCount(1);
      count2 += ps.getCount(2);
      count3 += ps.getCount(3);
      count4 += ps.getCount(4);
      count5 += ps.getCount(5);
    }

    seconds_ = getWallTime() - t1;

    counts_[0] = count0;
    counts_[1] = count1;
    counts_[2] = count2;
    counts_[3] = count3;
    counts_[4] = count4;
    counts_[5] = count5;
  }

  if (shm_)
  {
    // communicate the sieving results to
    // the primesieve GUI application
    copy(counts_.begin(), counts_.end(), shm_->counts);
    shm_->seconds = seconds_;
  }
}

/// Calculate the sieving status.
/// @param processed  Sum of recently processed segments.
///
bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  OmpLockGuard lock(getLock<omp_lock_t*>(), waitForLock);
  if (lock.isSet())
  {
    PrimeSieve::updateStatus(processed);
    if (shm_)
      shm_->status = getStatus();
  }
  return lock.isSet();
}

/// Used to synchronize threads for prime number generation

void ParallelPrimeSieve::setLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_set_lock(lock);
}

void ParallelPrimeSieve::unsetLock()
{
  omp_lock_t* lock = getLock<omp_lock_t*>();
  omp_unset_lock(lock);
}

#endif /* _OPENMP */

/// If OpenMP is disabled then ParallelPrimeSieve behaves like
/// the single threaded PrimeSieve.
///
#if !defined(_OPENMP)

int ParallelPrimeSieve::getMaxThreads()
{
  return 1;
}

void ParallelPrimeSieve::sieve()
{
  PrimeSieve::sieve();

  if (shm_)
  {
    // communicate the sieving results to the
    // primesieve GUI application
    copy(counts_.begin(), counts_.end(), shm_->counts);
    shm_->seconds = seconds_;
  }
}

double ParallelPrimeSieve::getWallTime() const
{
  return PrimeSieve::getWallTime();
}

bool ParallelPrimeSieve::updateStatus(uint64_t processed, bool waitForLock)
{
  bool isUpdate = PrimeSieve::updateStatus(processed, waitForLock);
  if (shm_)
    shm_->status = getStatus();
  return isUpdate;
}

void ParallelPrimeSieve::setLock() { }

void ParallelPrimeSieve::unsetLock() { }

#endif

} // namespace
<|endoftext|>


<commit_before>//===--- ScheduleDAGSDNodes.cpp - Implement the ScheduleDAGSDNodes class --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements the ScheduleDAG class, which is a base class used by
// scheduling implementation classes.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "pre-RA-sched"
#include "ScheduleDAGSDNodes.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf)
  : ScheduleDAG(mf) {
}

/// Run - perform scheduling.
///
void ScheduleDAGSDNodes::Run(SelectionDAG *dag, MachineBasicBlock *bb,
                             MachineBasicBlock::iterator insertPos) {
  DAG = dag;
  ScheduleDAG::Run(bb, insertPos);
}

SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) {
  SUnit *SU = NewSUnit(Old->getNode());
  SU->OrigNode = Old->OrigNode;
  SU->Latency = Old->Latency;
  SU->isTwoAddress = Old->isTwoAddress;
  SU->isCommutable = Old->isCommutable;
  SU->hasPhysRegDefs = Old->hasPhysRegDefs;
  SU->hasPhysRegClobbers = Old->hasPhysRegClobbers;
  Old->isCloned = true;
  return SU;
}

/// CheckForPhysRegDependency - Check if the dependency between def and use of
/// a specified operand is a physical register dependency. If so, returns the
/// register and the cost of copying the register.
static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op,
                                      const TargetRegisterInfo *TRI,
                                      const TargetInstrInfo *TII,
                                      unsigned &PhysReg, int &Cost) {
  if (Op != 2 || User->getOpcode() != ISD::CopyToReg)
    return;

  unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
  if (TargetRegisterInfo::isVirtualRegister(Reg))
    return;

  unsigned ResNo = User->getOperand(2).getResNo();
  if (Def->isMachineOpcode()) {
    const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
    if (ResNo >= II.getNumDefs() &&
        II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
      PhysReg = Reg;
      const TargetRegisterClass *RC =
        TRI->getPhysicalRegisterRegClass(Reg, Def->getValueType(ResNo));
      Cost = RC->getCopyCost();
    }
  }
}

void ScheduleDAGSDNodes::BuildSchedUnits() {
  // During scheduling, the NodeId field of SDNode is used to map SDNodes
  // to their associated SUnits by holding SUnits table indices. A value
  // of -1 means the SDNode does not yet have an associated SUnit.
  unsigned NumNodes = 0;
  for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
       E = DAG->allnodes_end(); NI != E; ++NI) {
    NI->setNodeId(-1);
    ++NumNodes;
  }

  // Reserve entries in the vector for each of the SUnits we are creating.  This
  // ensure that reallocation of the vector won't happen, so SUnit*'s won't get
  // invalidated.
  // FIXME: Multiply by 2 because we may clone nodes during scheduling.
  // This is a temporary workaround.
  SUnits.reserve(NumNodes * 2);

  // Check to see if the scheduler cares about latencies.
  bool UnitLatencies = ForceUnitLatencies();

  for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
       E = DAG->allnodes_end(); NI != E; ++NI) {
    if (isPassiveNode(NI))  // Leaf node, e.g. a TargetImmediate.
      continue;

    // If this node has already been processed, stop now.
    if (NI->getNodeId() != -1) continue;

    SUnit *NodeSUnit = NewSUnit(NI);

    // See if anything is flagged to this node, if so, add them to flagged
    // nodes.  Nodes can have at most one flag input and one flag output.  Flags
    // are required to be the last operand and result of a node.

    // Scan up to find flagged preds.
    SDNode *N = NI;
    while (N->getNumOperands() &&
           N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) {
      N = N->getOperand(N->getNumOperands()-1).getNode();
      assert(N->getNodeId() == -1 && "Node already inserted!");
      N->setNodeId(NodeSUnit->NodeNum);
    }

    // Scan down to find any flagged succs.
    N = NI;
    while (N->getValueType(N->getNumValues()-1) == MVT::Flag) {
      SDValue FlagVal(N, N->getNumValues()-1);

      // There are either zero or one users of the Flag result.
      bool HasFlagUse = false;
      for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
           UI != E; ++UI)
        if (FlagVal.isOperandOf(*UI)) {
          HasFlagUse = true;
          assert(N->getNodeId() == -1 && "Node already inserted!");
          N->setNodeId(NodeSUnit->NodeNum);
          N = *UI;
          break;
        }
      if (!HasFlagUse) break;
    }

    // If there are flag operands involved, N is now the bottom-most node
    // of the sequence of nodes that are flagged together.
    // Update the SUnit.
    NodeSUnit->setNode(N);
    assert(N->getNodeId() == -1 && "Node already inserted!");
    N->setNodeId(NodeSUnit->NodeNum);

    // Assign the Latency field of NodeSUnit using target-provided information.
    if (UnitLatencies)
      NodeSUnit->Latency = 1;
    else
      ComputeLatency(NodeSUnit);
  }
}

void ScheduleDAGSDNodes::AddSchedEdges() {
  // Pass 2: add the preds, succs, etc.
  for (unsigned su = 0, e = SUnits.size(); su != e; ++su) {
    SUnit *SU = &SUnits[su];
    SDNode *MainNode = SU->getNode();

    if (MainNode->isMachineOpcode()) {
      unsigned Opc = MainNode->getMachineOpcode();
      const TargetInstrDesc &TID = TII->get(Opc);
      for (unsigned i = 0; i != TID.getNumOperands(); ++i) {
        if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) {
          SU->isTwoAddress = true;
          break;
        }
      }
      if (TID.isCommutable())
        SU->isCommutable = true;
    }

    // Find all predecessors and successors of the group.
    for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) {
      if (N->isMachineOpcode() &&
          TII->get(N->getMachineOpcode()).getImplicitDefs()) {
        SU->hasPhysRegClobbers = true;
        if (CountResults(N) > TII->get(N->getMachineOpcode()).getNumDefs())
          SU->hasPhysRegDefs = true;
      }

      for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
        SDNode *OpN = N->getOperand(i).getNode();
        if (isPassiveNode(OpN)) continue;   // Not scheduled.
        SUnit *OpSU = &SUnits[OpN->getNodeId()];
        assert(OpSU && "Node has no SUnit!");
        if (OpSU == SU) continue;           // In the same group.

        MVT OpVT = N->getOperand(i).getValueType();
        assert(OpVT != MVT::Flag && "Flagged nodes should be in same sunit!");
        bool isChain = OpVT == MVT::Other;

        unsigned PhysReg = 0;
        int Cost = 1;
        // Determine if this is a physical register dependency.
        CheckForPhysRegDependency(OpN, N, i, TRI, TII, PhysReg, Cost);
        assert((PhysReg == 0 || !isChain) &&
               "Chain dependence via physreg data?");
        // FIXME: See ScheduleDAGSDNodes::EmitCopyFromReg. For now, scheduler
        // emits a copy from the physical register to a virtual register unless
        // it requires a cross class copy (cost < 0). That means we are only
        // treating "expensive to copy" register dependency as physical register
        // dependency. This may change in the future though.
        if (Cost >= 0)
          PhysReg = 0;
        SU->addPred(SDep(OpSU, isChain ? SDep::Order : SDep::Data,
                         OpSU->Latency, PhysReg));
      }
    }
  }
}

/// BuildSchedGraph - Build the SUnit graph from the selection dag that we
/// are input.  This SUnit graph is similar to the SelectionDAG, but
/// excludes nodes that aren't interesting to scheduling, and represents
/// flagged together nodes with a single SUnit.
void ScheduleDAGSDNodes::BuildSchedGraph() {
  // Populate the SUnits array.
  BuildSchedUnits();
  // Compute all the scheduling dependencies between nodes.
  AddSchedEdges();
}

void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) {
  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();

  // Compute the latency for the node.  We use the sum of the latencies for
  // all nodes flagged together into this SUnit.
  SU->Latency = 0;
  bool SawMachineOpcode = false;
  for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode())
    if (N->isMachineOpcode()) {
      SawMachineOpcode = true;
      SU->Latency +=
        InstrItins.getLatency(TII->get(N->getMachineOpcode()).getSchedClass());
    }
}

/// CountResults - The results of target nodes have register or immediate
/// operands first, then an optional chain, and optional flag operands (which do
/// not go into the resulting MachineInstr).
unsigned ScheduleDAGSDNodes::CountResults(SDNode *Node) {
  unsigned N = Node->getNumValues();
  while (N && Node->getValueType(N - 1) == MVT::Flag)
    --N;
  if (N && Node->getValueType(N - 1) == MVT::Other)
    --N;    // Skip over chain result.
  return N;
}

/// CountOperands - The inputs to target nodes have any actual inputs first,
/// followed by special operands that describe memory references, then an
/// optional chain operand, then an optional flag operand.  Compute the number
/// of actual operands that will go into the resulting MachineInstr.
unsigned ScheduleDAGSDNodes::CountOperands(SDNode *Node) {
  unsigned N = ComputeMemOperandsEnd(Node);
  while (N && isa<MemOperandSDNode>(Node->getOperand(N - 1).getNode()))
    --N; // Ignore MEMOPERAND nodes
  return N;
}

/// ComputeMemOperandsEnd - Find the index one past the last MemOperandSDNode
/// operand
unsigned ScheduleDAGSDNodes::ComputeMemOperandsEnd(SDNode *Node) {
  unsigned N = Node->getNumOperands();
  while (N && Node->getOperand(N - 1).getValueType() == MVT::Flag)
    --N;
  if (N && Node->getOperand(N - 1).getValueType() == MVT::Other)
    --N; // Ignore chain if it exists.
  return N;
}

void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const {
  if (!SU->getNode()) {
    cerr << "PHYS REG COPY\n";
    return;
  }

  SU->getNode()->dump(DAG);
  cerr << "\n";
  SmallVector<SDNode *, 4> FlaggedNodes;
  for (SDNode *N = SU->getNode()->getFlaggedNode(); N; N = N->getFlaggedNode())
    FlaggedNodes.push_back(N);
  while (!FlaggedNodes.empty()) {
    cerr << "    ";
    FlaggedNodes.back()->dump(DAG);
    cerr << "\n";
    FlaggedNodes.pop_back();
  }
}
<commit_msg>Don't set SUnit::hasPhysRegDefs to true unless the defs are actually have uses, which reflects the way it's used.<commit_after>//===--- ScheduleDAGSDNodes.cpp - Implement the ScheduleDAGSDNodes class --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements the ScheduleDAG class, which is a base class used by
// scheduling implementation classes.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "pre-RA-sched"
#include "ScheduleDAGSDNodes.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf)
  : ScheduleDAG(mf) {
}

/// Run - perform scheduling.
///
void ScheduleDAGSDNodes::Run(SelectionDAG *dag, MachineBasicBlock *bb,
                             MachineBasicBlock::iterator insertPos) {
  DAG = dag;
  ScheduleDAG::Run(bb, insertPos);
}

SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) {
  SUnit *SU = NewSUnit(Old->getNode());
  SU->OrigNode = Old->OrigNode;
  SU->Latency = Old->Latency;
  SU->isTwoAddress = Old->isTwoAddress;
  SU->isCommutable = Old->isCommutable;
  SU->hasPhysRegDefs = Old->hasPhysRegDefs;
  SU->hasPhysRegClobbers = Old->hasPhysRegClobbers;
  Old->isCloned = true;
  return SU;
}

/// CheckForPhysRegDependency - Check if the dependency between def and use of
/// a specified operand is a physical register dependency. If so, returns the
/// register and the cost of copying the register.
static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op,
                                      const TargetRegisterInfo *TRI,
                                      const TargetInstrInfo *TII,
                                      unsigned &PhysReg, int &Cost) {
  if (Op != 2 || User->getOpcode() != ISD::CopyToReg)
    return;

  unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
  if (TargetRegisterInfo::isVirtualRegister(Reg))
    return;

  unsigned ResNo = User->getOperand(2).getResNo();
  if (Def->isMachineOpcode()) {
    const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
    if (ResNo >= II.getNumDefs() &&
        II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
      PhysReg = Reg;
      const TargetRegisterClass *RC =
        TRI->getPhysicalRegisterRegClass(Reg, Def->getValueType(ResNo));
      Cost = RC->getCopyCost();
    }
  }
}

void ScheduleDAGSDNodes::BuildSchedUnits() {
  // During scheduling, the NodeId field of SDNode is used to map SDNodes
  // to their associated SUnits by holding SUnits table indices. A value
  // of -1 means the SDNode does not yet have an associated SUnit.
  unsigned NumNodes = 0;
  for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
       E = DAG->allnodes_end(); NI != E; ++NI) {
    NI->setNodeId(-1);
    ++NumNodes;
  }

  // Reserve entries in the vector for each of the SUnits we are creating.  This
  // ensure that reallocation of the vector won't happen, so SUnit*'s won't get
  // invalidated.
  // FIXME: Multiply by 2 because we may clone nodes during scheduling.
  // This is a temporary workaround.
  SUnits.reserve(NumNodes * 2);

  // Check to see if the scheduler cares about latencies.
  bool UnitLatencies = ForceUnitLatencies();

  for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
       E = DAG->allnodes_end(); NI != E; ++NI) {
    if (isPassiveNode(NI))  // Leaf node, e.g. a TargetImmediate.
      continue;

    // If this node has already been processed, stop now.
    if (NI->getNodeId() != -1) continue;

    SUnit *NodeSUnit = NewSUnit(NI);

    // See if anything is flagged to this node, if so, add them to flagged
    // nodes.  Nodes can have at most one flag input and one flag output.  Flags
    // are required to be the last operand and result of a node.

    // Scan up to find flagged preds.
    SDNode *N = NI;
    while (N->getNumOperands() &&
           N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) {
      N = N->getOperand(N->getNumOperands()-1).getNode();
      assert(N->getNodeId() == -1 && "Node already inserted!");
      N->setNodeId(NodeSUnit->NodeNum);
    }

    // Scan down to find any flagged succs.
    N = NI;
    while (N->getValueType(N->getNumValues()-1) == MVT::Flag) {
      SDValue FlagVal(N, N->getNumValues()-1);

      // There are either zero or one users of the Flag result.
      bool HasFlagUse = false;
      for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
           UI != E; ++UI)
        if (FlagVal.isOperandOf(*UI)) {
          HasFlagUse = true;
          assert(N->getNodeId() == -1 && "Node already inserted!");
          N->setNodeId(NodeSUnit->NodeNum);
          N = *UI;
          break;
        }
      if (!HasFlagUse) break;
    }

    // If there are flag operands involved, N is now the bottom-most node
    // of the sequence of nodes that are flagged together.
    // Update the SUnit.
    NodeSUnit->setNode(N);
    assert(N->getNodeId() == -1 && "Node already inserted!");
    N->setNodeId(NodeSUnit->NodeNum);

    // Assign the Latency field of NodeSUnit using target-provided information.
    if (UnitLatencies)
      NodeSUnit->Latency = 1;
    else
      ComputeLatency(NodeSUnit);
  }
}

void ScheduleDAGSDNodes::AddSchedEdges() {
  // Pass 2: add the preds, succs, etc.
  for (unsigned su = 0, e = SUnits.size(); su != e; ++su) {
    SUnit *SU = &SUnits[su];
    SDNode *MainNode = SU->getNode();

    if (MainNode->isMachineOpcode()) {
      unsigned Opc = MainNode->getMachineOpcode();
      const TargetInstrDesc &TID = TII->get(Opc);
      for (unsigned i = 0; i != TID.getNumOperands(); ++i) {
        if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) {
          SU->isTwoAddress = true;
          break;
        }
      }
      if (TID.isCommutable())
        SU->isCommutable = true;
    }

    // Find all predecessors and successors of the group.
    for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) {
      if (N->isMachineOpcode() &&
          TII->get(N->getMachineOpcode()).getImplicitDefs()) {
        SU->hasPhysRegClobbers = true;
        unsigned NumUsed = CountResults(N);
        while (NumUsed != 0 && !N->hasAnyUseOfValue(NumUsed - 1))
          --NumUsed;    // Skip over unused values at the end.
        if (NumUsed > TII->get(N->getMachineOpcode()).getNumDefs())
          SU->hasPhysRegDefs = true;
      }

      for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
        SDNode *OpN = N->getOperand(i).getNode();
        if (isPassiveNode(OpN)) continue;   // Not scheduled.
        SUnit *OpSU = &SUnits[OpN->getNodeId()];
        assert(OpSU && "Node has no SUnit!");
        if (OpSU == SU) continue;           // In the same group.

        MVT OpVT = N->getOperand(i).getValueType();
        assert(OpVT != MVT::Flag && "Flagged nodes should be in same sunit!");
        bool isChain = OpVT == MVT::Other;

        unsigned PhysReg = 0;
        int Cost = 1;
        // Determine if this is a physical register dependency.
        CheckForPhysRegDependency(OpN, N, i, TRI, TII, PhysReg, Cost);
        assert((PhysReg == 0 || !isChain) &&
               "Chain dependence via physreg data?");
        // FIXME: See ScheduleDAGSDNodes::EmitCopyFromReg. For now, scheduler
        // emits a copy from the physical register to a virtual register unless
        // it requires a cross class copy (cost < 0). That means we are only
        // treating "expensive to copy" register dependency as physical register
        // dependency. This may change in the future though.
        if (Cost >= 0)
          PhysReg = 0;
        SU->addPred(SDep(OpSU, isChain ? SDep::Order : SDep::Data,
                         OpSU->Latency, PhysReg));
      }
    }
  }
}

/// BuildSchedGraph - Build the SUnit graph from the selection dag that we
/// are input.  This SUnit graph is similar to the SelectionDAG, but
/// excludes nodes that aren't interesting to scheduling, and represents
/// flagged together nodes with a single SUnit.
void ScheduleDAGSDNodes::BuildSchedGraph() {
  // Populate the SUnits array.
  BuildSchedUnits();
  // Compute all the scheduling dependencies between nodes.
  AddSchedEdges();
}

void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) {
  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();

  // Compute the latency for the node.  We use the sum of the latencies for
  // all nodes flagged together into this SUnit.
  SU->Latency = 0;
  bool SawMachineOpcode = false;
  for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode())
    if (N->isMachineOpcode()) {
      SawMachineOpcode = true;
      SU->Latency +=
        InstrItins.getLatency(TII->get(N->getMachineOpcode()).getSchedClass());
    }
}

/// CountResults - The results of target nodes have register or immediate
/// operands first, then an optional chain, and optional flag operands (which do
/// not go into the resulting MachineInstr).
unsigned ScheduleDAGSDNodes::CountResults(SDNode *Node) {
  unsigned N = Node->getNumValues();
  while (N && Node->getValueType(N - 1) == MVT::Flag)
    --N;
  if (N && Node->getValueType(N - 1) == MVT::Other)
    --N;    // Skip over chain result.
  return N;
}

/// CountOperands - The inputs to target nodes have any actual inputs first,
/// followed by special operands that describe memory references, then an
/// optional chain operand, then an optional flag operand.  Compute the number
/// of actual operands that will go into the resulting MachineInstr.
unsigned ScheduleDAGSDNodes::CountOperands(SDNode *Node) {
  unsigned N = ComputeMemOperandsEnd(Node);
  while (N && isa<MemOperandSDNode>(Node->getOperand(N - 1).getNode()))
    --N; // Ignore MEMOPERAND nodes
  return N;
}

/// ComputeMemOperandsEnd - Find the index one past the last MemOperandSDNode
/// operand
unsigned ScheduleDAGSDNodes::ComputeMemOperandsEnd(SDNode *Node) {
  unsigned N = Node->getNumOperands();
  while (N && Node->getOperand(N - 1).getValueType() == MVT::Flag)
    --N;
  if (N && Node->getOperand(N - 1).getValueType() == MVT::Other)
    --N; // Ignore chain if it exists.
  return N;
}

void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const {
  if (!SU->getNode()) {
    cerr << "PHYS REG COPY\n";
    return;
  }

  SU->getNode()->dump(DAG);
  cerr << "\n";
  SmallVector<SDNode *, 4> FlaggedNodes;
  for (SDNode *N = SU->getNode()->getFlaggedNode(); N; N = N->getFlaggedNode())
    FlaggedNodes.push_back(N);
  while (!FlaggedNodes.empty()) {
    cerr << "    ";
    FlaggedNodes.back()->dump(DAG);
    cerr << "\n";
    FlaggedNodes.pop_back();
  }
}
<|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fnord-base/test/unittest.h"
#include "fnord-msg/MessageEncoder.h"
#include "fnord-tsdb/RecordSet.h"
#include "fnord-cstable/CSTableReader.h"
#include "fnord-cstable/StringColumnReader.h"

using namespace fnord;
using namespace fnord::tsdb;

UNIT_TEST(RecordSetTest);

RefPtr<msg::MessageSchema> testSchema() {
  Vector<msg::MessageSchemaField> fields;

  fields.emplace_back(
      1,
      "one",
      msg::FieldType::STRING,
      250,
      false,
      false);

  fields.emplace_back(
      2,
      "two",
      msg::FieldType::STRING,
      1024,
      false,
      false);

  return new msg::MessageSchema("TestSchema", fields);
}

Buffer testObject(RefPtr<msg::MessageSchema> schema, String one, String two) {
  msg::MessageObject obj;
  obj.addChild(1, one);
  obj.addChild(2, two);

  Buffer buf;
  msg::MessageEncoder::encode(obj, *schema, &buf);

  return buf;
}

TEST_CASE(RecordSetTest, TestAddRowToEmptySet, [] () {
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");
  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);

  recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
  recset.addRecord(0x23232323, testObject(schema, "2a", "2b"));

  EXPECT_FALSE(recset.getState().commitlog.isEmpty());
  EXPECT_TRUE(recset.getState().commitlog_size > 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);
  EXPECT_EQ(recset.commitlogSize(), 2);

  recset.rollCommitlog();

  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 1);
  EXPECT_EQ(recset.commitlogSize(), 2);

  recset.addRecord(0x1211111, testObject(schema, "3a", "3b"));
  recset.addRecord(0x2344444, testObject(schema, "4a", "4b"));

  EXPECT_FALSE(recset.getState().commitlog.isEmpty());
  EXPECT_TRUE(recset.getState().commitlog_size > 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 1);
  EXPECT_EQ(recset.commitlogSize(), 4);

  recset.rollCommitlog();

  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 2);
  EXPECT_EQ(recset.commitlogSize(), 4);

  recset.compact();
  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_FALSE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);
  EXPECT_EQ(recset.commitlogSize(), 0);

  cstable::CSTableReader reader(recset.getState().datafile.get());
  void* data;
  size_t size;
  uint64_t r;
  uint64_t d;
  auto col = reader.getColumnReader("one");
  Set<String> res;
  for (int i = 0; i < reader.numRecords(); ++i) {
    col->next(&r, &d, &data, &size);
    res.emplace(String((char*) data, size));
  }

  EXPECT_EQ(res.count("1a"), 1);
  EXPECT_EQ(res.count("2a"), 1);
  EXPECT_EQ(res.count("3a"), 1);
  EXPECT_EQ(res.count("4a"), 1);
});

TEST_CASE(RecordSetTest, TestCommitlogReopen, [] () {
  auto schema = testSchema();
  RecordSet::RecordSetState state;

  {
    RecordSet recset(schema, "/tmp/__fnord_testrecset");
    recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
    recset.addRecord(0x23232323, testObject(schema, "2a", "2b"));
    state = recset.getState();
  }

  {
    RecordSet recset(schema, "/tmp/__fnord_testrecset", state);
    EXPECT_EQ(recset.getState().commitlog_size, state.commitlog_size);
    EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);
    EXPECT_EQ(recset.commitlogSize(), 2);
  }
});

TEST_CASE(RecordSetTest, TestDuplicateRowsInCommitlog, [] () {
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");

  recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
  recset.addRecord(0x42424242, testObject(schema, "2a", "2b"));
  EXPECT_EQ(recset.commitlogSize(), 1);

  recset.rollCommitlog();
  EXPECT_EQ(recset.commitlogSize(), 1);

  recset.addRecord(0x42424242, testObject(schema, "3a", "3b"));
  recset.addRecord(0x32323232, testObject(schema, "2a", "2b"));
  EXPECT_EQ(recset.commitlogSize(), 2);

  recset.rollCommitlog();
  recset.compact();

  cstable::CSTableReader reader(recset.getState().datafile.get());
  void* data;
  size_t size;
  uint64_t r;
  uint64_t d;
  auto col = reader.getColumnReader("__msgid");
  Set<uint64_t> res;
  for (int i = 0; i < reader.numRecords(); ++i) {
    col->next(&r, &d, &data, &size);
    res.emplace(*((uint64_t*) data));
  }

  EXPECT_EQ(res.size(), 2);
  EXPECT_EQ(res.count(0x42424242), 1);
  EXPECT_EQ(res.count(0x32323232), 1);
});

TEST_CASE(RecordSetTest, TestCompactionWithExistingTable, [] () {
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");

  recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
  recset.addRecord(0x23232323, testObject(schema, "2a", "2b"));
  recset.rollCommitlog();
  recset.compact();

  recset.addRecord(0x52525252, testObject(schema, "3a", "3b"));
  recset.addRecord(0x12121212, testObject(schema, "4a", "4b"));
  recset.rollCommitlog();
  recset.compact();

  cstable::CSTableReader reader(recset.getState().datafile.get());
  void* data;
  size_t size;
  uint64_t r;
  uint64_t d;
  auto col = reader.getColumnReader("__msgid");
  Set<uint64_t> res;
  for (int i = 0; i < reader.numRecords(); ++i) {
    col->next(&r, &d, &data, &size);
    res.emplace(*((uint64_t*) data));
  }

  EXPECT_EQ(res.size(), 4);
  EXPECT_EQ(res.count(0x42424242), 1);
  EXPECT_EQ(res.count(0x32323232), 1);
  EXPECT_EQ(res.count(0x52525252), 1);
  EXPECT_EQ(res.count(0x12121212), 1);
});

TEST_CASE(RecordSetTest, TestInsert10kRows, [] () {
  Random rnd;
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");

  for (int i = 0; i < 10; ++i) {
    for (int i = 0; i < 1000; ++i) {
      recset.addRecord(rnd.random64(), testObject(schema, "1a", "1b"));
    }

    recset.rollCommitlog();
  }

  EXPECT_EQ(recset.getState().old_commitlogs.size(), 10);
  recset.compact();

  cstable::CSTableReader reader(recset.getState().datafile.get());
  EXPECT_EQ(reader.numRecords(), 10000);
});

<commit_msg>basic record materialization<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fnord-base/test/unittest.h"
#include "fnord-msg/MessageEncoder.h"
#include "fnord-tsdb/RecordSet.h"
#include "fnord-cstable/CSTableReader.h"
#include "fnord-cstable/StringColumnReader.h"

using namespace fnord;
using namespace fnord::tsdb;

UNIT_TEST(RecordSetTest);

RefPtr<msg::MessageSchema> testSchema() {
  Vector<msg::MessageSchemaField> fields;

  fields.emplace_back(
      1,
      "one",
      msg::FieldType::STRING,
      250,
      false,
      false);

  fields.emplace_back(
      2,
      "two",
      msg::FieldType::STRING,
      1024,
      false,
      false);

  return new msg::MessageSchema("TestSchema", fields);
}

Buffer testObject(RefPtr<msg::MessageSchema> schema, String one, String two) {
  msg::MessageObject obj;
  obj.addChild(1, one);
  obj.addChild(2, two);

  Buffer buf;
  msg::MessageEncoder::encode(obj, *schema, &buf);

  return buf;
}

TEST_CASE(RecordSetTest, TestAddRowToEmptySet, [] () {
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");
  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);

  recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
  recset.addRecord(0x23232323, testObject(schema, "2a", "2b"));

  EXPECT_FALSE(recset.getState().commitlog.isEmpty());
  EXPECT_TRUE(recset.getState().commitlog_size > 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);
  EXPECT_EQ(recset.commitlogSize(), 2);

  recset.rollCommitlog();

  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 1);
  EXPECT_EQ(recset.commitlogSize(), 2);

  recset.addRecord(0x1211111, testObject(schema, "3a", "3b"));
  recset.addRecord(0x2344444, testObject(schema, "4a", "4b"));

  EXPECT_FALSE(recset.getState().commitlog.isEmpty());
  EXPECT_TRUE(recset.getState().commitlog_size > 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 1);
  EXPECT_EQ(recset.commitlogSize(), 4);

  recset.rollCommitlog();

  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_TRUE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 2);
  EXPECT_EQ(recset.commitlogSize(), 4);

  recset.compact();
  EXPECT_TRUE(recset.getState().commitlog.isEmpty());
  EXPECT_EQ(recset.getState().commitlog_size, 0);
  EXPECT_FALSE(recset.getState().datafile.isEmpty());
  EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);
  EXPECT_EQ(recset.commitlogSize(), 0);

  cstable::CSTableReader reader(recset.getState().datafile.get());
  void* data;
  size_t size;
  uint64_t r;
  uint64_t d;
  auto col = reader.getColumnReader("one");
  Set<String> res;
  for (int i = 0; i < reader.numRecords(); ++i) {
    col->next(&r, &d, &data, &size);
    res.emplace(String((char*) data, size));
  }

  EXPECT_EQ(res.count("1a"), 1);
  EXPECT_EQ(res.count("2a"), 1);
  EXPECT_EQ(res.count("3a"), 1);
  EXPECT_EQ(res.count("4a"), 1);
});

TEST_CASE(RecordSetTest, TestCommitlogReopen, [] () {
  auto schema = testSchema();
  RecordSet::RecordSetState state;

  {
    RecordSet recset(schema, "/tmp/__fnord_testrecset");
    recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
    recset.addRecord(0x23232323, testObject(schema, "2a", "2b"));
    state = recset.getState();
  }

  {
    RecordSet recset(schema, "/tmp/__fnord_testrecset", state);
    EXPECT_EQ(recset.getState().commitlog_size, state.commitlog_size);
    EXPECT_EQ(recset.getState().old_commitlogs.size(), 0);
    EXPECT_EQ(recset.commitlogSize(), 2);
  }
});

TEST_CASE(RecordSetTest, TestDuplicateRowsInCommitlog, [] () {
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");

  recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
  recset.addRecord(0x42424242, testObject(schema, "2a", "2b"));
  EXPECT_EQ(recset.commitlogSize(), 1);

  recset.rollCommitlog();
  EXPECT_EQ(recset.commitlogSize(), 1);

  recset.addRecord(0x42424242, testObject(schema, "3a", "3b"));
  recset.addRecord(0x32323232, testObject(schema, "2a", "2b"));
  EXPECT_EQ(recset.commitlogSize(), 2);

  recset.rollCommitlog();
  recset.compact();

  cstable::CSTableReader reader(recset.getState().datafile.get());
  void* data;
  size_t size;
  uint64_t r;
  uint64_t d;
  auto col = reader.getColumnReader("__msgid");
  Set<uint64_t> res;
  for (int i = 0; i < reader.numRecords(); ++i) {
    col->next(&r, &d, &data, &size);
    res.emplace(*((uint64_t*) data));
  }

  EXPECT_EQ(res.size(), 2);
  EXPECT_EQ(res.count(0x42424242), 1);
  EXPECT_EQ(res.count(0x32323232), 1);
});

TEST_CASE(RecordSetTest, TestCompactionWithExistingTable, [] () {
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");

  recset.addRecord(0x42424242, testObject(schema, "1a", "1b"));
  recset.addRecord(0x23232323, testObject(schema, "2a", "2b"));
  recset.rollCommitlog();
  recset.compact();

  recset.addRecord(0x52525252, testObject(schema, "3a", "3b"));
  recset.addRecord(0x12121212, testObject(schema, "4a", "4b"));
  recset.rollCommitlog();
  recset.compact();

  cstable::CSTableReader reader(recset.getState().datafile.get());
  void* data;
  size_t size;
  uint64_t r;
  uint64_t d;
  auto col = reader.getColumnReader("__msgid");
  Set<uint64_t> res;
  for (int i = 0; i < reader.numRecords(); ++i) {
    col->next(&r, &d, &data, &size);
    res.emplace(*((uint64_t*) data));
  }

  EXPECT_EQ(res.size(), 4);
  EXPECT_EQ(res.count(0x42424242), 1);
  EXPECT_EQ(res.count(0x23232323), 1);
  EXPECT_EQ(res.count(0x52525252), 1);
  EXPECT_EQ(res.count(0x12121212), 1);
});

TEST_CASE(RecordSetTest, TestInsert10kRows, [] () {
  Random rnd;
  auto schema = testSchema();
  RecordSet recset(schema, "/tmp/__fnord_testrecset");

  for (int i = 0; i < 10; ++i) {
    for (int i = 0; i < 1000; ++i) {
      recset.addRecord(rnd.random64(), testObject(schema, "1a", "1b"));
    }

    recset.rollCommitlog();
  }

  EXPECT_EQ(recset.getState().old_commitlogs.size(), 10);
  recset.compact();

  cstable::CSTableReader reader(recset.getState().datafile.get());
  EXPECT_EQ(reader.numRecords(), 10000);
});

<|endoftext|>


<commit_before>#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "ui/ui_dock.h"
#include "ui/ui_dock_private.h"
#include "core/math.h"
#include "api/plugin_instance.h"

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

static void create_docking(void**)
{
	Rect rect = { 0, 0, 0, 0 };
	UIDockingGrid* grid = UIDock_createGrid(&rect);
	assert_non_null(grid);
}

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

void validateRect(Rect r0, Rect r1)
{
	assert_int_equal(r0.x, r1.x);
	assert_int_equal(r0.y, r1.x);
	assert_int_equal(r0.width, r1.width);
	assert_int_equal(r0.height, r1.height);
}

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

static void test_left_attach(void**)
{
	Rect rect = { 0, 0, 1000, 1000 };
	UIDockingGrid* grid = UIDock_createGrid(&rect);

	ViewPluginInstance view0 = {};
	ViewPluginInstance view1 = {};

	// Validate grid

	validateRect(grid->rect, rect);
	assert_int_equal(grid->sizers.size(), 0);
	assert_int_equal(grid->docks.size(), 0);

	UIDock* dock = UIDock_addView(grid, &view0);

	assert_null(dock->topSizer);
	assert_null(dock->bottomSizer);
	assert_null(dock->rightSizer);
	assert_null(dock->leftSizer);
	assert_true(dock->view == &view0);

	assert_int_equal((int)grid->sizers.size(), 0);
	assert_int_equal((int)grid->docks.size(), 1);

	UIDock_dockLeft(grid, dock, &view1);

	assert_int_equal((int)grid->sizers.size(), 1);
	assert_int_equal((int)grid->docks.size(), 2);
}

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

int main()
{
    const UnitTest tests[] =
    {
        unit_test(create_docking),
        unit_test(test_left_attach),
    };

    return run_tests(tests);
}

<commit_msg>Added comment<commit_after>#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "ui/ui_dock.h"
#include "ui/ui_dock_private.h"
#include "core/math.h"
#include "api/plugin_instance.h"

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

static void create_docking(void**)
{
	Rect rect = { 0, 0, 0, 0 };
	UIDockingGrid* grid = UIDock_createGrid(&rect);
	assert_non_null(grid);
}

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

void validateRect(Rect r0, Rect r1)
{
	assert_int_equal(r0.x, r1.x);
	assert_int_equal(r0.y, r1.x);
	assert_int_equal(r0.width, r1.width);
	assert_int_equal(r0.height, r1.height);
}

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

static void test_left_attach(void**)
{
	Rect rect = { 0, 0, 1000, 1000 };
	UIDockingGrid* grid = UIDock_createGrid(&rect);

	ViewPluginInstance view0 = {};
	ViewPluginInstance view1 = {};

	// Validate grid

	validateRect(grid->rect, rect);
	assert_int_equal(grid->sizers.size(), 0);
	assert_int_equal(grid->docks.size(), 0);

	UIDock* dock = UIDock_addView(grid, &view0);

	assert_null(dock->topSizer);
	assert_null(dock->bottomSizer);
	assert_null(dock->rightSizer);
	assert_null(dock->leftSizer);
	assert_true(dock->view == &view0);

	assert_int_equal((int)grid->sizers.size(), 0);
	assert_int_equal((int)grid->docks.size(), 1);

	UIDock_dockLeft(grid, dock, &view1);

	// at this point we should have two views/docks split in the middle
	// with one sizer so lets verify that

	assert_int_equal((int)grid->sizers.size(), 1);
	assert_int_equal((int)grid->docks.size(), 2);

}

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

int main()
{
    const UnitTest tests[] =
    {
        unit_test(create_docking),
        unit_test(test_left_attach),
    };

    return run_tests(tests);
}

<|endoftext|>