<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QSignalSpy>
#include <QTimer>
#include <QHostAddress>
#include <QDebug>
#include <QThread>

#include <QtDeclarative/qdeclarativeengine.h>

#include "../shared/debugutil_p.h"

#define PORT 13770
#define STR_PORT "13770"

class tst_QDeclarativeDebugClient : public QObject
{
    Q_OBJECT

private:
    QDeclarativeDebugConnection *m_conn;

private slots:
    void initTestCase();

    void name();
    void status();
    void sendMessage();
    void parallelConnect();
    void sequentialConnect();
};

void tst_QDeclarativeDebugClient::initTestCase()
{
    const QString waitingMsg = QString("QDeclarativeDebugServer: Waiting for connection on port %1...").arg(PORT);
    QTest::ignoreMessage(QtWarningMsg, waitingMsg.toAscii().constData());
    new QDeclarativeEngine(this);

    m_conn = new QDeclarativeDebugConnection(this);

    QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::handshake()", m_conn);
    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");

    m_conn->connectToHost("127.0.0.1", PORT);

    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
    bool ok = m_conn->waitForConnected();
    QVERIFY(ok);

    QTRY_VERIFY(QDeclarativeDebugService::hasDebuggingClient());
    QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);
}

void tst_QDeclarativeDebugClient::name()
{
    QString name = "tst_QDeclarativeDebugClient::name()";

    QDeclarativeDebugClient client(name, m_conn);
    QCOMPARE(client.name(), name);
}

void tst_QDeclarativeDebugClient::status()
{
    {
        QDeclarativeDebugConnection dummyConn;
        QDeclarativeDebugClient client("tst_QDeclarativeDebugClient::status()", &dummyConn);
        QCOMPARE(client.status(), QDeclarativeDebugClient::NotConnected);
    }

    QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::status()", m_conn);
    QCOMPARE(client.status(), QDeclarativeDebugClient::Unavailable);

    {
        QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::status()");
        QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);
    }

    QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Unavailable);

    // duplicate plugin name
    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugClient: Conflicting plugin name \"tst_QDeclarativeDebugClient::status()\" ");
    QDeclarativeDebugClient client2("tst_QDeclarativeDebugClient::status()", m_conn);
    QCOMPARE(client2.status(), QDeclarativeDebugClient::NotConnected);

    QDeclarativeDebugClient client3("tst_QDeclarativeDebugClient::status3()", 0);
    QCOMPARE(client3.status(), QDeclarativeDebugClient::NotConnected);
}

void tst_QDeclarativeDebugClient::sendMessage()
{
    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::sendMessage()");
    QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::sendMessage()", m_conn);

    QByteArray msg = "hello!";

    QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);

    client.sendMessage(msg);
    QByteArray resp = client.waitForResponse();
    QCOMPARE(resp, msg);
}

void tst_QDeclarativeDebugClient::parallelConnect()
{
    QDeclarativeDebugConnection connection2;

    connection2.connectToHost("127.0.0.1", PORT);
    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Another client is already connected");
    // will connect & immediately disconnect
    QVERIFY(connection2.waitForConnected());
    QTRY_COMPARE(connection2.state(), QAbstractSocket::UnconnectedState);
    QVERIFY(m_conn->isConnected());
}

void tst_QDeclarativeDebugClient::sequentialConnect()
{
    QDeclarativeDebugConnection connection2;
    QDeclarativeDebugTestClient client2("tst_QDeclarativeDebugClient::handshake()", &connection2);
    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");

    m_conn->close();
    QVERIFY(!m_conn->isConnected());
    QCOMPARE(m_conn->state(), QAbstractSocket::UnconnectedState);

    // Make sure that the disconnect is actually delivered to the server
    QGuiApplication::processEvents();

    connection2.connectToHost("127.0.0.1", PORT);
    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
    QVERIFY(connection2.waitForConnected());
    QVERIFY(connection2.isConnected());
    QTRY_VERIFY(client2.status() == QDeclarativeDebugClient::Enabled);
}

int main(int argc, char *argv[])
{
    int _argc = argc + 1;
    char **_argv = new char*[_argc];
    for (int i = 0; i < argc; ++i)
        _argv[i] = argv[i];

    _argv[_argc - 1] = "-qmljsdebugger=port:" STR_PORT;

    QGuiApplication app(_argc, _argv);
    tst_QDeclarativeDebugClient tc;
    return QTest::qExec(&tc, _argc, _argv);
    delete _argv;
}

#include "tst_qdeclarativedebugclient.moc"

<commit_msg>Stabilize debug client test.<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QSignalSpy>
#include <QTimer>
#include <QHostAddress>
#include <QDebug>
#include <QThread>

#include <QtDeclarative/qdeclarativeengine.h>

#include "../shared/debugutil_p.h"

#define PORT 13770
#define STR_PORT "13770"

class tst_QDeclarativeDebugClient : public QObject
{
    Q_OBJECT

private:
    QDeclarativeDebugConnection *m_conn;

private slots:
    void initTestCase();

    void name();
    void status();
    void sendMessage();
    void parallelConnect();
    void sequentialConnect();
};

void tst_QDeclarativeDebugClient::initTestCase()
{
    const QString waitingMsg = QString("QDeclarativeDebugServer: Waiting for connection on port %1...").arg(PORT);
    QTest::ignoreMessage(QtWarningMsg, waitingMsg.toAscii().constData());
    new QDeclarativeEngine(this);

    m_conn = new QDeclarativeDebugConnection(this);

    QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::handshake()", m_conn);
    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");

    m_conn->connectToHost("127.0.0.1", PORT);

    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
    bool ok = m_conn->waitForConnected();
    QVERIFY(ok);

    QTRY_VERIFY(QDeclarativeDebugService::hasDebuggingClient());
    QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);
}

void tst_QDeclarativeDebugClient::name()
{
    QString name = "tst_QDeclarativeDebugClient::name()";

    QDeclarativeDebugClient client(name, m_conn);
    QCOMPARE(client.name(), name);
}

void tst_QDeclarativeDebugClient::status()
{
    {
        QDeclarativeDebugConnection dummyConn;
        QDeclarativeDebugClient client("tst_QDeclarativeDebugClient::status()", &dummyConn);
        QCOMPARE(client.status(), QDeclarativeDebugClient::NotConnected);
    }

    QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::status()", m_conn);
    QCOMPARE(client.status(), QDeclarativeDebugClient::Unavailable);

    {
        QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::status()");
        QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);
    }

    QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Unavailable);

    // duplicate plugin name
    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugClient: Conflicting plugin name \"tst_QDeclarativeDebugClient::status()\" ");
    QDeclarativeDebugClient client2("tst_QDeclarativeDebugClient::status()", m_conn);
    QCOMPARE(client2.status(), QDeclarativeDebugClient::NotConnected);

    QDeclarativeDebugClient client3("tst_QDeclarativeDebugClient::status3()", 0);
    QCOMPARE(client3.status(), QDeclarativeDebugClient::NotConnected);
}

void tst_QDeclarativeDebugClient::sendMessage()
{
    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::sendMessage()");
    QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::sendMessage()", m_conn);

    QByteArray msg = "hello!";

    QTRY_COMPARE(client.status(), QDeclarativeDebugClient::Enabled);

    client.sendMessage(msg);
    QByteArray resp = client.waitForResponse();
    QCOMPARE(resp, msg);
}

void tst_QDeclarativeDebugClient::parallelConnect()
{
    QDeclarativeDebugConnection connection2;

    connection2.connectToHost("127.0.0.1", PORT);
    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Another client is already connected");
    // will connect & immediately disconnect
    QVERIFY(connection2.waitForConnected());
    QTRY_COMPARE(connection2.state(), QAbstractSocket::UnconnectedState);
    QVERIFY(m_conn->isConnected());
}

void tst_QDeclarativeDebugClient::sequentialConnect()
{
    QDeclarativeDebugConnection connection2;
    QDeclarativeDebugTestClient client2("tst_QDeclarativeDebugClient::handshake()", &connection2);
    QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()");

    m_conn->close();
    QVERIFY(!m_conn->isConnected());
    QCOMPARE(m_conn->state(), QAbstractSocket::UnconnectedState);

    // Make sure that the disconnect is actually delivered to the server
    QTest::qWait(100);

    connection2.connectToHost("127.0.0.1", PORT);
    QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established");
    QVERIFY(connection2.waitForConnected());
    QVERIFY(connection2.isConnected());
    QTRY_VERIFY(client2.status() == QDeclarativeDebugClient::Enabled);
}

int main(int argc, char *argv[])
{
    int _argc = argc + 1;
    char **_argv = new char*[_argc];
    for (int i = 0; i < argc; ++i)
        _argv[i] = argv[i];

    _argv[_argc - 1] = "-qmljsdebugger=port:" STR_PORT;

    QGuiApplication app(_argc, _argv);
    tst_QDeclarativeDebugClient tc;
    return QTest::qExec(&tc, _argc, _argv);
    delete _argv;
}

#include "tst_qdeclarativedebugclient.moc"

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: propertyeditor.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2004-05-07 16:05:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_
#define _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

#ifndef _SV_TABCTRL_HXX
#include <vcl/tabctrl.hxx>
#endif
#ifndef _EXTENSIONS_PROPCTRLR_PCRCOMMON_HXX_
#include "pcrcommon.hxx"
#endif

#include <map>

//............................................................................
namespace pcr
{
//............................................................................

    class IBrowserControl;
    class IPropertyLineListener;
    struct OLineDescriptor;

    //========================================================================
    //= OPropertyEditor
    //========================================================================
    class OPropertyEditor : public Control
    {
    private:
                TabControl                  m_aTabControl;
                IPropertyLineListener*      m_pListener;
                sal_uInt16                  m_nNextId;
                Link                        m_aPageActivationHandler;

                struct HiddenPage
                {
                    sal_uInt16  nPos;
                    TabPage*    pPage;
                    HiddenPage() : nPos( 0 ), pPage( NULL ) { }
                    HiddenPage( sal_uInt16 _nPos, TabPage* _pPage ) : nPos( _nPos ), pPage( _pPage ) { }
                };
                ::std::map< sal_uInt16, HiddenPage >
                                            m_aHiddenPages;

    protected:
                virtual void                Resize();
                virtual void                GetFocus();

    public:
                                            OPropertyEditor (Window* pParent, WinBits nWinStyle = WB_DIALOGCONTROL);
                                            OPropertyEditor (Window* pParent, const ResId& rResId);

                                            ~OPropertyEditor();

                virtual sal_uInt16          CalcVisibleLines();
                virtual void                EnableUpdate();
                virtual void                DisableUpdate();

                virtual void                SetLineListener(IPropertyLineListener *);

                virtual void                SetHelpId( sal_uInt32 nHelpId );
                virtual sal_uInt16          AppendPage( const String& r,sal_uInt32 nHelpId=0);
                virtual void                SetPage( sal_uInt16 );
                virtual void                RemovePage(sal_uInt16 nID);
                virtual sal_uInt16          GetCurPage();
                virtual void                ClearAll();

                virtual void                SetPropertyValue(const ::rtl::OUString & rEntryName, const ::rtl::OUString & rValue );
                virtual ::rtl::OUString     GetPropertyValue(const ::rtl::OUString & rEntryName ) const;
                virtual sal_uInt16          GetPropertyPos(const ::rtl::OUString& rEntryName ) const;
                virtual void                SetPropertyData(const ::rtl::OUString& rEntryName, void* pData);
                virtual IBrowserControl*    GetPropertyControl( const ::rtl::OUString& rEntryName );
                        void                EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable );
                        void                EnablePropertyInput( const ::rtl::OUString& _rEntryName, bool _bEnableInput, bool _bEnableBrowseButton );

                        void                ShowPropertyPage( sal_uInt16 _nPageId, bool _bShow );

                virtual sal_uInt16          InsertEntry(const OLineDescriptor&, sal_uInt16 nPos = EDITOR_LIST_APPEND);
                virtual void                ChangeEntry(const OLineDescriptor&, sal_uInt16 nPos);

                virtual void                SetFirstVisibleEntry(sal_uInt16 nPos);
                virtual sal_uInt16          GetFirstVisibleEntry();

                virtual void                SetSelectedEntry(sal_uInt16 nPos);
                virtual sal_uInt16          GetSelectedEntry();

        void    setPageActivationHandler(const Link& _rHdl) { m_aPageActivationHandler = _rHdl; }
        Link    getPageActivationHandler() const { return m_aPageActivationHandler; }
        // #95343# -------------------------------
        sal_Int32 getMinimumWidth();

        void    CommitModified();

    protected:
        DECL_LINK(OnPageDeactivate, TabControl*);
        DECL_LINK(OnPageActivate, TabControl*);
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

<commit_msg>INTEGRATION: CWS dba13 (1.8.34); FILE MERGED 2004/06/29 08:28:26 fs 1.8.34.1: removed unnecessary ctor during #i30861#<commit_after>/*************************************************************************
 *
 *  $RCSfile: propertyeditor.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-06 13:46:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_
#define _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

#ifndef _SV_TABCTRL_HXX
#include <vcl/tabctrl.hxx>
#endif
#ifndef _EXTENSIONS_PROPCTRLR_PCRCOMMON_HXX_
#include "pcrcommon.hxx"
#endif

#include <map>

//............................................................................
namespace pcr
{
//............................................................................

    class IBrowserControl;
    class IPropertyLineListener;
    struct OLineDescriptor;

    //========================================================================
    //= OPropertyEditor
    //========================================================================
    class OPropertyEditor : public Control
    {
    private:
                TabControl                  m_aTabControl;
                IPropertyLineListener*      m_pListener;
                sal_uInt16                  m_nNextId;
                Link                        m_aPageActivationHandler;

                struct HiddenPage
                {
                    sal_uInt16  nPos;
                    TabPage*    pPage;
                    HiddenPage() : nPos( 0 ), pPage( NULL ) { }
                    HiddenPage( sal_uInt16 _nPos, TabPage* _pPage ) : nPos( _nPos ), pPage( _pPage ) { }
                };
                ::std::map< sal_uInt16, HiddenPage >
                                            m_aHiddenPages;

    protected:
                virtual void                Resize();
                virtual void                GetFocus();

    public:
                                            OPropertyEditor (Window* pParent, WinBits nWinStyle = WB_DIALOGCONTROL);

                                            ~OPropertyEditor();

                virtual sal_uInt16          CalcVisibleLines();
                virtual void                EnableUpdate();
                virtual void                DisableUpdate();

                virtual void                SetLineListener(IPropertyLineListener *);

                virtual void                SetHelpId( sal_uInt32 nHelpId );
                virtual sal_uInt16          AppendPage( const String& r,sal_uInt32 nHelpId=0);
                virtual void                SetPage( sal_uInt16 );
                virtual void                RemovePage(sal_uInt16 nID);
                virtual sal_uInt16          GetCurPage();
                virtual void                ClearAll();

                virtual void                SetPropertyValue(const ::rtl::OUString & rEntryName, const ::rtl::OUString & rValue );
                virtual ::rtl::OUString     GetPropertyValue(const ::rtl::OUString & rEntryName ) const;
                virtual sal_uInt16          GetPropertyPos(const ::rtl::OUString& rEntryName ) const;
                virtual void                SetPropertyData(const ::rtl::OUString& rEntryName, void* pData);
                virtual IBrowserControl*    GetPropertyControl( const ::rtl::OUString& rEntryName );
                        void                EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable );
                        void                EnablePropertyInput( const ::rtl::OUString& _rEntryName, bool _bEnableInput, bool _bEnableBrowseButton );

                        void                ShowPropertyPage( sal_uInt16 _nPageId, bool _bShow );

                virtual sal_uInt16          InsertEntry(const OLineDescriptor&, sal_uInt16 nPos = EDITOR_LIST_APPEND);
                virtual void                ChangeEntry(const OLineDescriptor&, sal_uInt16 nPos);

                virtual void                SetFirstVisibleEntry(sal_uInt16 nPos);
                virtual sal_uInt16          GetFirstVisibleEntry();

                virtual void                SetSelectedEntry(sal_uInt16 nPos);
                virtual sal_uInt16          GetSelectedEntry();

        void    setPageActivationHandler(const Link& _rHdl) { m_aPageActivationHandler = _rHdl; }
        Link    getPageActivationHandler() const { return m_aPageActivationHandler; }
        // #95343# -------------------------------
        sal_Int32 getMinimumWidth();

        void    CommitModified();

    protected:
        DECL_LINK(OnPageDeactivate, TabControl*);
        DECL_LINK(OnPageActivate, TabControl*);
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_PROPERTYEDITOR_HXX_

<|endoftext|>


<commit_before>#ifndef _VKDEFS_HPP
#define _VKDEFS_HPP
/*-------------------------------------------------------------------------
 * Vulkan CTS Framework
 * --------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Vulkan utilites.
 *//*--------------------------------------------------------------------*/

#include "tcuDefs.hpp"

#if (DE_OS == DE_OS_ANDROID) && defined(__ARM_ARCH_7A__)
#	define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#else
#	define VKAPI_ATTR
#endif

#if (DE_OS == DE_OS_WIN32) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED))
#	define VKAPI_CALL __stdcall
#else
#	define VKAPI_CALL
#endif

#define VK_DEFINE_HANDLE(NAME, TYPE)					typedef struct NAME##_s* NAME
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(NAME, TYPE)	typedef Handle<TYPE> NAME

#define VK_DEFINE_PLATFORM_TYPE(NAME, COMPATIBLE)		\
namespace pt {											\
struct NAME {											\
	COMPATIBLE internal;								\
	explicit NAME (COMPATIBLE internal_)				\
		: internal(internal_) {}						\
};														\
} // pt

#define VK_MAKE_VERSION(MAJOR, MINOR, PATCH)	(((deUint32)(MAJOR) << 22u) | ((deUint32)(MINOR) << 12u) | (deUint32)(PATCH))
#define VK_BIT(NUM)								(1u<<(deUint32)(NUM))

#define VK_VERSION_MAJOR(version)				((uint32_t)(version) >> 22)
#define VK_VERSION_MINOR(version)				(((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version)				((uint32_t)(version) & 0xfff)

#define VK_CHECK(EXPR)							vk::checkResult((EXPR), #EXPR, __FILE__, __LINE__)
#define VK_CHECK_MSG(EXPR, MSG)					vk::checkResult((EXPR), MSG, __FILE__, __LINE__)

/*--------------------------------------------------------------------*//*!
 * \brief Vulkan utilities
 *//*--------------------------------------------------------------------*/
namespace vk
{

typedef deUint64	VkDeviceSize;
typedef deUint32	VkSampleMask;
typedef deUint32	VkBool32;
typedef deUint32	VkFlags;

// enum HandleType { HANDLE_TYPE_INSTANCE, ... };
#include "vkHandleType.inl"

template<HandleType Type>
class Handle
{
public:
				Handle		(void) {} // \note Left uninitialized on purpose
				Handle		(deUint64 internal) : m_internal(internal) {}

	Handle&		operator=	(deUint64 internal)					{ m_internal = internal; return *this;			}

	bool		operator==	(const Handle<Type>& other) const	{ return this->m_internal == other.m_internal;	}
	bool		operator!=	(const Handle<Type>& other) const	{ return this->m_internal != other.m_internal;	}

	bool		operator!	(void) const						{ return !m_internal;							}

	deUint64	getInternal	(void) const						{ return m_internal;							}

	enum { HANDLE_TYPE = Type };

private:
	deUint64	m_internal;
};

#include "vkBasicTypes.inl"

#define VK_CORE_FORMAT_LAST		((vk::VkFormat)(vk::VK_FORMAT_ASTC_12x12_SRGB_BLOCK+1))

enum SpirvVersion
{
	SPIRV_VERSION_1_0	= 0,	//!< SPIR-V 1.0
	SPIRV_VERSION_1_1	= 1,	//!< SPIR-V 1.1
	SPIRV_VERSION_1_2	= 2,	//!< SPIR-V 1.2
	SPIRV_VERSION_1_3	= 3,	//!< SPIR-V 1.3

	SPIRV_VERSION_LAST
};

typedef struct
{
	deUint32	magic;
	deUint32	version;
	deUint32	generator;
	deUint32	bound;
} SpirvBinaryHeader;

namespace wsi
{

enum Type
{
	TYPE_XLIB = 0,
	TYPE_XCB,
	TYPE_WAYLAND,
	TYPE_MIR,
	TYPE_ANDROID,
	TYPE_WIN32,

	TYPE_LAST
};

} // wsi

typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkVoidFunction)					(void);

typedef VKAPI_ATTR void*	(VKAPI_CALL* PFN_vkAllocationFunction)				(void*						pUserData,
																				 size_t						size,
																				 size_t						alignment,
																				 VkSystemAllocationScope	allocationScope);
typedef VKAPI_ATTR void*	(VKAPI_CALL* PFN_vkReallocationFunction)			(void*						pUserData,
																				 void*						pOriginal,
																				 size_t						size,
																				 size_t						alignment,
																				 VkSystemAllocationScope	allocationScope);
typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkFreeFunction)					(void*						pUserData,
																				 void*						pMem);
typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkInternalAllocationNotification)	(void*						pUserData,
																				 size_t						size,
																				 VkInternalAllocationType	allocationType,
																				 VkSystemAllocationScope	allocationScope);
typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkInternalFreeNotification)		(void*						pUserData,
																				 size_t						size,
																				 VkInternalAllocationType	allocationType,
																				 VkSystemAllocationScope	allocationScope);

typedef VKAPI_ATTR VkBool32	(VKAPI_CALL* PFN_vkDebugReportCallbackEXT)			(VkDebugReportFlagsEXT		flags,
																				 VkDebugReportObjectTypeEXT	objectType,
																				 deUint64					object,
																				 size_t						location,
																				 deInt32					messageCode,
																				 const char*				pLayerPrefix,
																				 const char*				pMessage,
																				 void*						pUserData);

#include "vkStructTypes.inl"

extern "C"
{
#include "vkFunctionPointerTypes.inl"
}

class PlatformInterface
{
public:
#include "vkVirtualPlatformInterface.inl"

protected:
						PlatformInterface	(void) {}

private:
						PlatformInterface	(const PlatformInterface&);
	PlatformInterface&	operator=			(const PlatformInterface&);
};

class InstanceInterface
{
public:
#include "vkVirtualInstanceInterface.inl"

protected:
						InstanceInterface	(void) {}

private:
						InstanceInterface	(const InstanceInterface&);
	InstanceInterface&	operator=			(const InstanceInterface&);
};

class DeviceInterface
{
public:
#include "vkVirtualDeviceInterface.inl"

protected:
						DeviceInterface		(void) {}

private:
						DeviceInterface		(const DeviceInterface&);
	DeviceInterface&	operator=			(const DeviceInterface&);
};

class Error : public tcu::TestError
{
public:
					Error				(VkResult error, const char* message, const char* expr, const char* file, int line);
					Error				(VkResult error, const std::string& message);
	virtual			~Error				(void) throw();

	VkResult		getError			(void) const { return m_error; }

private:
	const VkResult	m_error;
};

class OutOfMemoryError : public tcu::ResourceError
{
public:
					OutOfMemoryError	(VkResult error, const char* message, const char* expr, const char* file, int line);
					OutOfMemoryError	(VkResult error, const std::string& message);
	virtual			~OutOfMemoryError	(void) throw();

	VkResult		getError			(void) const { return m_error; }

private:
	const VkResult	m_error;
};

void			checkResult			(VkResult result, const char* message, const char* file, int line);

} // vk

#endif // _VKDEFS_HPP
<commit_msg>Fix compile error caused by usage of unit32_t instead of deUint32<commit_after>#ifndef _VKDEFS_HPP
#define _VKDEFS_HPP
/*-------------------------------------------------------------------------
 * Vulkan CTS Framework
 * --------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Vulkan utilites.
 *//*--------------------------------------------------------------------*/

#include "tcuDefs.hpp"

#if (DE_OS == DE_OS_ANDROID) && defined(__ARM_ARCH_7A__)
#	define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#else
#	define VKAPI_ATTR
#endif

#if (DE_OS == DE_OS_WIN32) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED))
#	define VKAPI_CALL __stdcall
#else
#	define VKAPI_CALL
#endif

#define VK_DEFINE_HANDLE(NAME, TYPE)					typedef struct NAME##_s* NAME
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(NAME, TYPE)	typedef Handle<TYPE> NAME

#define VK_DEFINE_PLATFORM_TYPE(NAME, COMPATIBLE)		\
namespace pt {											\
struct NAME {											\
	COMPATIBLE internal;								\
	explicit NAME (COMPATIBLE internal_)				\
		: internal(internal_) {}						\
};														\
} // pt

#define VK_MAKE_VERSION(MAJOR, MINOR, PATCH)	(((deUint32)(MAJOR) << 22u) | ((deUint32)(MINOR) << 12u) | (deUint32)(PATCH))
#define VK_BIT(NUM)								(1u<<(deUint32)(NUM))

#define VK_VERSION_MAJOR(version)				((deUint32)(version) >> 22)
#define VK_VERSION_MINOR(version)				(((deUint32)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version)				((deUint32)(version) & 0xfff)

#define VK_CHECK(EXPR)							vk::checkResult((EXPR), #EXPR, __FILE__, __LINE__)
#define VK_CHECK_MSG(EXPR, MSG)					vk::checkResult((EXPR), MSG, __FILE__, __LINE__)

/*--------------------------------------------------------------------*//*!
 * \brief Vulkan utilities
 *//*--------------------------------------------------------------------*/
namespace vk
{

typedef deUint64	VkDeviceSize;
typedef deUint32	VkSampleMask;
typedef deUint32	VkBool32;
typedef deUint32	VkFlags;

// enum HandleType { HANDLE_TYPE_INSTANCE, ... };
#include "vkHandleType.inl"

template<HandleType Type>
class Handle
{
public:
				Handle		(void) {} // \note Left uninitialized on purpose
				Handle		(deUint64 internal) : m_internal(internal) {}

	Handle&		operator=	(deUint64 internal)					{ m_internal = internal; return *this;			}

	bool		operator==	(const Handle<Type>& other) const	{ return this->m_internal == other.m_internal;	}
	bool		operator!=	(const Handle<Type>& other) const	{ return this->m_internal != other.m_internal;	}

	bool		operator!	(void) const						{ return !m_internal;							}

	deUint64	getInternal	(void) const						{ return m_internal;							}

	enum { HANDLE_TYPE = Type };

private:
	deUint64	m_internal;
};

#include "vkBasicTypes.inl"

#define VK_CORE_FORMAT_LAST		((vk::VkFormat)(vk::VK_FORMAT_ASTC_12x12_SRGB_BLOCK+1))

enum SpirvVersion
{
	SPIRV_VERSION_1_0	= 0,	//!< SPIR-V 1.0
	SPIRV_VERSION_1_1	= 1,	//!< SPIR-V 1.1
	SPIRV_VERSION_1_2	= 2,	//!< SPIR-V 1.2
	SPIRV_VERSION_1_3	= 3,	//!< SPIR-V 1.3

	SPIRV_VERSION_LAST
};

typedef struct
{
	deUint32	magic;
	deUint32	version;
	deUint32	generator;
	deUint32	bound;
} SpirvBinaryHeader;

namespace wsi
{

enum Type
{
	TYPE_XLIB = 0,
	TYPE_XCB,
	TYPE_WAYLAND,
	TYPE_MIR,
	TYPE_ANDROID,
	TYPE_WIN32,

	TYPE_LAST
};

} // wsi

typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkVoidFunction)					(void);

typedef VKAPI_ATTR void*	(VKAPI_CALL* PFN_vkAllocationFunction)				(void*						pUserData,
																				 size_t						size,
																				 size_t						alignment,
																				 VkSystemAllocationScope	allocationScope);
typedef VKAPI_ATTR void*	(VKAPI_CALL* PFN_vkReallocationFunction)			(void*						pUserData,
																				 void*						pOriginal,
																				 size_t						size,
																				 size_t						alignment,
																				 VkSystemAllocationScope	allocationScope);
typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkFreeFunction)					(void*						pUserData,
																				 void*						pMem);
typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkInternalAllocationNotification)	(void*						pUserData,
																				 size_t						size,
																				 VkInternalAllocationType	allocationType,
																				 VkSystemAllocationScope	allocationScope);
typedef VKAPI_ATTR void		(VKAPI_CALL* PFN_vkInternalFreeNotification)		(void*						pUserData,
																				 size_t						size,
																				 VkInternalAllocationType	allocationType,
																				 VkSystemAllocationScope	allocationScope);

typedef VKAPI_ATTR VkBool32	(VKAPI_CALL* PFN_vkDebugReportCallbackEXT)			(VkDebugReportFlagsEXT		flags,
																				 VkDebugReportObjectTypeEXT	objectType,
																				 deUint64					object,
																				 size_t						location,
																				 deInt32					messageCode,
																				 const char*				pLayerPrefix,
																				 const char*				pMessage,
																				 void*						pUserData);

#include "vkStructTypes.inl"

extern "C"
{
#include "vkFunctionPointerTypes.inl"
}

class PlatformInterface
{
public:
#include "vkVirtualPlatformInterface.inl"

protected:
						PlatformInterface	(void) {}

private:
						PlatformInterface	(const PlatformInterface&);
	PlatformInterface&	operator=			(const PlatformInterface&);
};

class InstanceInterface
{
public:
#include "vkVirtualInstanceInterface.inl"

protected:
						InstanceInterface	(void) {}

private:
						InstanceInterface	(const InstanceInterface&);
	InstanceInterface&	operator=			(const InstanceInterface&);
};

class DeviceInterface
{
public:
#include "vkVirtualDeviceInterface.inl"

protected:
						DeviceInterface		(void) {}

private:
						DeviceInterface		(const DeviceInterface&);
	DeviceInterface&	operator=			(const DeviceInterface&);
};

class Error : public tcu::TestError
{
public:
					Error				(VkResult error, const char* message, const char* expr, const char* file, int line);
					Error				(VkResult error, const std::string& message);
	virtual			~Error				(void) throw();

	VkResult		getError			(void) const { return m_error; }

private:
	const VkResult	m_error;
};

class OutOfMemoryError : public tcu::ResourceError
{
public:
					OutOfMemoryError	(VkResult error, const char* message, const char* expr, const char* file, int line);
					OutOfMemoryError	(VkResult error, const std::string& message);
	virtual			~OutOfMemoryError	(void) throw();

	VkResult		getError			(void) const { return m_error; }

private:
	const VkResult	m_error;
};

void			checkResult			(VkResult result, const char* message, const char* file, int line);

} // vk

#endif // _VKDEFS_HPP
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of dirtsand.                                             *
 *                                                                            *
 * dirtsand is free software: you can redistribute it and/or modify           *
 * it under the terms of the GNU Affero General Public License as             *
 * published by the Free Software Foundation, either version 3 of the         *
 * License, or (at your option) any later version.                            *
 *                                                                            *
 * dirtsand 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 Affero General Public License for more details.                        *
 *                                                                            *
 * You should have received a copy of the GNU Affero General Public License   *
 * along with dirtsand.  If not, see <http://www.gnu.org/licenses/>.          *
 ******************************************************************************/

#include "FileServer.h"
#include "FileManifest.h"
#include "settings.h"
#include "errors.h"
#include <list>
#include <map>
#include <thread>
#include <mutex>
#include <chrono>
#include <memory>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

struct FileRequest
{
    int m_fd;
    off_t m_size;
    off_t m_pos;

    typedef std::tuple<bool, off_t> chunk_t;

    FileRequest(int fd) : m_fd(fd), m_pos()
    {
        struct stat stat_buf;
        if (fstat(m_fd, &stat_buf) < 0)
            m_size = 0;
        else
            m_size = stat_buf.st_size;
    }

    ~FileRequest()
    {
        close(m_fd);
    }

    chunk_t nextChunk()
    {
        off_t left = m_size - m_pos;
        if (left > CHUNK_SIZE) {
            return std::make_tuple(false, CHUNK_SIZE);
        } else {
            return std::make_tuple(true, left);
        }
    }
};

struct FileServer_Private
{
    DS::SocketHandle m_sock;
    DS::BufferStream m_buffer;
    uint32_t m_readerId;

    std::map<uint32_t, std::unique_ptr<FileRequest>> m_downloads;

    ~FileServer_Private()
    {
        m_downloads.clear();
    }
};

static std::list<FileServer_Private*> s_clients;
static std::mutex s_clientMutex;

enum FileServer_MsgIds
{
    e_CliToFile_PingRequest = 0, e_CliToFile_BuildIdRequest = 10,
    e_CliToFile_ManifestRequest = 20, e_CliToFile_DownloadRequest = 21,
    e_CliToFile_ManifestEntryAck = 22, e_CliToFile_DownloadChunkAck = 23,

    e_FileToCli_PingReply = 0, e_FileToCli_BuildIdReply = 10,
    e_FileToCli_BuildIdUpdate = 11, e_FileToCli_ManifestReply = 20,
    e_FileToCli_FileDownloadReply = 21,
};

#define START_REPLY(msgId) \
    client.m_buffer.truncate(); \
    client.m_buffer.write<uint32_t>(0); \
    client.m_buffer.write<uint32_t>(msgId)

#define SEND_REPLY() \
    client.m_buffer.seek(0, SEEK_SET); \
    client.m_buffer.write<uint32_t>(client.m_buffer.size()); \
    DS::SendBuffer(client.m_sock, client.m_buffer.buffer(), client.m_buffer.size())

#define SEND_FD_REPLY(fd, off, sz) \
    client.m_buffer.seek(0, SEEK_SET); \
    client.m_buffer.write<uint32_t>(client.m_buffer.size() + sz); \
    DS::SendFile(client.m_sock, client.m_buffer.buffer(), client.m_buffer.size(), (fd), &(off), (sz))

void file_init(FileServer_Private& client)
{
    /* File server header:  size, buildId, serverType */
    uint32_t size = DS::RecvValue<uint32_t>(client.m_sock);
    if (size != 12)
        throw DS::InvalidConnectionHeader();
    DS::RecvValue<uint32_t>(client.m_sock);
    DS::RecvValue<uint32_t>(client.m_sock);
}

void cb_ping(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_PingReply);

    // Ping time
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    SEND_REPLY();
}

void cb_buildId(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_BuildIdReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    // Result
    client.m_buffer.write<uint32_t>(DS::e_NetSuccess);

    // Build ID
    client.m_buffer.write<uint32_t>(DS::Settings::BuildId());

    SEND_REPLY();
}

void cb_manifest(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_ManifestReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    // Manifest name
    char16_t mfsbuf[260];
    DS::RecvBuffer(client.m_sock, mfsbuf, sizeof(mfsbuf));
    mfsbuf[259] = 0;
    ST::string mfsname = ST::string::from_utf16(mfsbuf, ST_AUTO_SIZE, ST::substitute_invalid);

    // Build ID
    uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock);
    if (buildId && buildId != DS::Settings::BuildId()) {
        ST::printf(stderr, "[File] Wrong Build ID from {}: {}\n",
                   DS::SockIpAddress(client.m_sock), buildId);
        DS::CloseSock(client.m_sock);
        return;
    }

    // Manifest may not have any path characters
    if (mfsname.find(".") != -1 || mfsname.find("/") != -1
            || mfsname.find("\\") != -1 || mfsname.find(":") != -1) {
        ST::printf(stderr, "[File] Invalid manifest request from {}: {}\n",
                   DS::SockIpAddress(client.m_sock), mfsname);
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File count
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();
        return;
    }

    DS::FileManifest manifest;
    mfsname = DS::Settings::FileRoot() + mfsname + ".mfs";
    DS::NetResultCode result = manifest.loadManifest(mfsname.c_str());
    client.m_buffer.write<uint32_t>(result);

    if (result != DS::e_NetSuccess) {
        ST::printf(stderr, "[File] {} requested invalid manifest {}\n",
                   DS::SockIpAddress(client.m_sock), mfsname);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File count
        client.m_buffer.write<uint32_t>(0);     // Data packet size
    } else {
        client.m_buffer.write<uint32_t>(++client.m_readerId);
        client.m_buffer.write<uint32_t>(manifest.fileCount());
        uint32_t sizeLocation = client.m_buffer.tell();
        client.m_buffer.write<uint32_t>(0);
        uint32_t dataSize = manifest.encodeToStream(&client.m_buffer);
        client.m_buffer.seek(sizeLocation, SEEK_SET);
        client.m_buffer.write<uint32_t>(dataSize);
    }

    SEND_REPLY();
}

void cb_manifestAck(FileServer_Private& client)
{
    /* This is TCP, nobody cares about this ack... */
    DS::RecvValue<uint32_t>(client.m_sock);     // Trans ID
    DS::RecvValue<uint32_t>(client.m_sock);     // Reader ID
}

void cb_downloadStart(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_FileDownloadReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    // Download filename
    char16_t buffer[260];
    DS::RecvBuffer(client.m_sock, buffer, sizeof(buffer));
    buffer[259] = 0;
    ST::string filename = ST::string::from_utf16(buffer, ST_AUTO_SIZE, ST::substitute_invalid);

    // Build ID
    uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock);
    if (buildId && buildId != DS::Settings::BuildId()) {
        ST::printf(stderr, "[File] Wrong Build ID from {}: {}\n",
                   DS::SockIpAddress(client.m_sock), buildId);
        DS::CloseSock(client.m_sock);
        return;
    }

    // Ensure filename is jailed to our data path
    if (filename.find("..") != -1) {
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File size
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();
        return;
    }
    filename = filename.replace("\\", "/");

    filename = DS::Settings::FileRoot() + filename;
    int fd = open(filename.c_str(), O_RDONLY);

    if (fd < 0) {
        ST::printf(stderr, "[File] Could not open file {}\n[File] Requested by {}\n",
                   filename, DS::SockIpAddress(client.m_sock));
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File size
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();
        return;
    }

    std::unique_ptr<FileRequest> req(new FileRequest(fd));
    client.m_buffer.write<uint32_t>(DS::e_NetSuccess);
    client.m_buffer.write<uint32_t>(++client.m_readerId);
    client.m_buffer.write<uint32_t>(req->m_size);

    FileRequest::chunk_t c = req->nextChunk();
    client.m_buffer.write<uint32_t>(std::get<1>(c));
    SEND_FD_REPLY(req->m_fd, req->m_pos, std::get<1>(c));
    if (!std::get<0>(c)) {
        client.m_downloads[client.m_readerId] = std::move(req);
    }
}

void cb_downloadNext(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_FileDownloadReply);

    uint32_t transId = DS::RecvValue<uint32_t>(client.m_sock);
    uint32_t readerId = DS::RecvValue<uint32_t>(client.m_sock);
    auto fi = client.m_downloads.find(readerId);
    if (fi == client.m_downloads.end()) {
        // The last chunk was already sent, we don't care anymore
        return;
    }

    client.m_buffer.write<uint32_t>(transId);
    client.m_buffer.write<uint32_t>(DS::e_NetSuccess);
    client.m_buffer.write<uint32_t>(fi->first);
    client.m_buffer.write<uint32_t>(fi->second->m_size);

    FileRequest::chunk_t c = fi->second->nextChunk();
    client.m_buffer.write<uint32_t>(std::get<1>(c));
    SEND_FD_REPLY(fi->second->m_fd, fi->second->m_pos, std::get<1>(c));
    if (std::get<0>(c)) {
        client.m_downloads.erase(fi);
    }
}

void wk_fileServ(DS::SocketHandle sockp)
{
    FileServer_Private client;

    s_clientMutex.lock();
    client.m_sock = sockp;
    client.m_readerId = 0;
    s_clients.push_back(&client);
    s_clientMutex.unlock();

    try {
        file_init(client);

        for ( ;; ) {
            DS::RecvValue<uint32_t>(client.m_sock);  // Message size
            uint32_t msgId = DS::RecvValue<uint32_t>(client.m_sock);
            switch (msgId) {
            case e_CliToFile_PingRequest:
                cb_ping(client);
                break;
            case e_CliToFile_BuildIdRequest:
                cb_buildId(client);
                break;
            case e_CliToFile_ManifestRequest:
                cb_manifest(client);
                break;
            case e_CliToFile_ManifestEntryAck:
                cb_manifestAck(client);
                break;
            case e_CliToFile_DownloadRequest:
                cb_downloadStart(client);
                break;
            case e_CliToFile_DownloadChunkAck:
                cb_downloadNext(client);
                break;
            default:
                /* Invalid message */
                ST::printf(stderr, "[File] Got invalid message ID {} from {}\n",
                           msgId, DS::SockIpAddress(client.m_sock));
                DS::CloseSock(client.m_sock);
                throw DS::SockHup();
            }
        }
    } catch (const DS::SockHup&) {
        // Socket closed...
    } catch (const std::exception& ex) {
        ST::printf(stderr, "[File] Error processing client message from {}: {}\n",
                   DS::SockIpAddress(sockp), ex.what());
    }

    s_clientMutex.lock();
    auto client_iter = s_clients.begin();
    while (client_iter != s_clients.end()) {
        if (*client_iter == &client)
            client_iter = s_clients.erase(client_iter);
        else
            ++client_iter;
    }
    s_clientMutex.unlock();

    DS::FreeSock(client.m_sock);
}

void DS::FileServer_Init()
{ }

void DS::FileServer_Add(DS::SocketHandle client)
{
    std::thread threadh(&wk_fileServ, client);
    threadh.detach();
}

void DS::FileServer_Shutdown()
{
    {
        std::lock_guard<std::mutex> clientGuard(s_clientMutex);
        for (auto client_iter = s_clients.begin(); client_iter != s_clients.end(); ++client_iter)
            DS::CloseSock((*client_iter)->m_sock);
    }

    bool complete = false;
    for (int i=0; i<50 && !complete; ++i) {
        s_clientMutex.lock();
        size_t alive = s_clients.size();
        s_clientMutex.unlock();
        if (alive == 0)
            complete = true;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    if (!complete)
        fputs("[File] Clients didn't die after 5 seconds!\n", stderr);
}

void DS::FileServer_DisplayClients()
{
    std::lock_guard<std::mutex> clientGuard(s_clientMutex);
    if (s_clients.size())
        fputs("File Server:\n", stdout);
    for (auto client_iter = s_clients.begin(); client_iter != s_clients.end(); ++client_iter)
        ST::printf("  * {}\n", DS::SockIpAddress((*client_iter)->m_sock));
}
<commit_msg>Send entire files immediately.<commit_after>/******************************************************************************
 * This file is part of dirtsand.                                             *
 *                                                                            *
 * dirtsand is free software: you can redistribute it and/or modify           *
 * it under the terms of the GNU Affero General Public License as             *
 * published by the Free Software Foundation, either version 3 of the         *
 * License, or (at your option) any later version.                            *
 *                                                                            *
 * dirtsand 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 Affero General Public License for more details.                        *
 *                                                                            *
 * You should have received a copy of the GNU Affero General Public License   *
 * along with dirtsand.  If not, see <http://www.gnu.org/licenses/>.          *
 ******************************************************************************/

#include "FileServer.h"
#include "FileManifest.h"
#include "settings.h"
#include "errors.h"
#include <list>
#include <map>
#include <thread>
#include <mutex>
#include <chrono>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

struct FileServer_Private
{
    DS::SocketHandle m_sock;
    DS::BufferStream m_buffer;
    uint32_t m_readerId;
};

static std::list<FileServer_Private*> s_clients;
static std::mutex s_clientMutex;

enum FileServer_MsgIds
{
    e_CliToFile_PingRequest = 0, e_CliToFile_BuildIdRequest = 10,
    e_CliToFile_ManifestRequest = 20, e_CliToFile_DownloadRequest = 21,
    e_CliToFile_ManifestEntryAck = 22, e_CliToFile_DownloadChunkAck = 23,

    e_FileToCli_PingReply = 0, e_FileToCli_BuildIdReply = 10,
    e_FileToCli_BuildIdUpdate = 11, e_FileToCli_ManifestReply = 20,
    e_FileToCli_FileDownloadReply = 21,
};

#define START_REPLY(msgId) \
    client.m_buffer.truncate(); \
    client.m_buffer.write<uint32_t>(0); \
    client.m_buffer.write<uint32_t>(msgId)

#define SEND_REPLY() \
    client.m_buffer.seek(0, SEEK_SET); \
    client.m_buffer.write<uint32_t>(client.m_buffer.size()); \
    DS::SendBuffer(client.m_sock, client.m_buffer.buffer(), client.m_buffer.size())

#define SEND_FD_REPLY(fd, off, sz) \
    client.m_buffer.seek(0, SEEK_SET); \
    client.m_buffer.write<uint32_t>(client.m_buffer.size() + sz); \
    DS::SendFile(client.m_sock, client.m_buffer.buffer(), client.m_buffer.size(), (fd), &(off), (sz))

void file_init(FileServer_Private& client)
{
    /* File server header:  size, buildId, serverType */
    uint32_t size = DS::RecvValue<uint32_t>(client.m_sock);
    if (size != 12)
        throw DS::InvalidConnectionHeader();
    DS::RecvValue<uint32_t>(client.m_sock);
    DS::RecvValue<uint32_t>(client.m_sock);
}

void cb_ping(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_PingReply);

    // Ping time
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    SEND_REPLY();
}

void cb_buildId(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_BuildIdReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    // Result
    client.m_buffer.write<uint32_t>(DS::e_NetSuccess);

    // Build ID
    client.m_buffer.write<uint32_t>(DS::Settings::BuildId());

    SEND_REPLY();
}

void cb_manifest(FileServer_Private& client)
{
    START_REPLY(e_FileToCli_ManifestReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock));

    // Manifest name
    char16_t mfsbuf[260];
    DS::RecvBuffer(client.m_sock, mfsbuf, sizeof(mfsbuf));
    mfsbuf[259] = 0;
    ST::string mfsname = ST::string::from_utf16(mfsbuf, ST_AUTO_SIZE, ST::substitute_invalid);

    // Build ID
    uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock);
    if (buildId && buildId != DS::Settings::BuildId()) {
        ST::printf(stderr, "[File] Wrong Build ID from {}: {}\n",
                   DS::SockIpAddress(client.m_sock), buildId);
        DS::CloseSock(client.m_sock);
        return;
    }

    // Manifest may not have any path characters
    if (mfsname.find(".") != -1 || mfsname.find("/") != -1
            || mfsname.find("\\") != -1 || mfsname.find(":") != -1) {
        ST::printf(stderr, "[File] Invalid manifest request from {}: {}\n",
                   DS::SockIpAddress(client.m_sock), mfsname);
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File count
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();
        return;
    }

    DS::FileManifest manifest;
    mfsname = DS::Settings::FileRoot() + mfsname + ".mfs";
    DS::NetResultCode result = manifest.loadManifest(mfsname.c_str());
    client.m_buffer.write<uint32_t>(result);

    if (result != DS::e_NetSuccess) {
        ST::printf(stderr, "[File] {} requested invalid manifest {}\n",
                   DS::SockIpAddress(client.m_sock), mfsname);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File count
        client.m_buffer.write<uint32_t>(0);     // Data packet size
    } else {
        client.m_buffer.write<uint32_t>(++client.m_readerId);
        client.m_buffer.write<uint32_t>(manifest.fileCount());
        uint32_t sizeLocation = client.m_buffer.tell();
        client.m_buffer.write<uint32_t>(0);
        uint32_t dataSize = manifest.encodeToStream(&client.m_buffer);
        client.m_buffer.seek(sizeLocation, SEEK_SET);
        client.m_buffer.write<uint32_t>(dataSize);
    }

    SEND_REPLY();
}

void cb_manifestAck(FileServer_Private& client)
{
    /* This is TCP, nobody cares about this ack... */
    DS::RecvValue<uint32_t>(client.m_sock);     // Trans ID
    DS::RecvValue<uint32_t>(client.m_sock);     // Reader ID
}

void cb_downloadStart(FileServer_Private& client)
{
    // Trans ID
    uint32_t transId = DS::RecvValue<uint32_t>(client.m_sock);

    // Download filename
    char16_t buffer[260];
    DS::RecvBuffer(client.m_sock, buffer, sizeof(buffer));
    buffer[259] = 0;
    ST::string filename = ST::string::from_utf16(buffer, ST_AUTO_SIZE, ST::substitute_invalid);

    // Build ID
    uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock);
    if (buildId && buildId != DS::Settings::BuildId()) {
        ST::printf(stderr, "[File] Wrong Build ID from {}: {}\n",
                   DS::SockIpAddress(client.m_sock), buildId);
        DS::CloseSock(client.m_sock);
        return;
    }

    // Ensure filename is jailed to our data path
    if (filename.find("..") != -1) {
        START_REPLY(e_FileToCli_FileDownloadReply);
        client.m_buffer.write<uint32_t>(transId);
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File size
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();
        return;
    }
    filename = filename.replace("\\", "/");

    filename = DS::Settings::FileRoot() + filename;
    int fd = open(filename.c_str(), O_RDONLY);

    if (fd < 0) {
        ST::printf(stderr, "[File] Could not open file {}\n[File] Requested by {}\n",
                   filename, DS::SockIpAddress(client.m_sock));
        START_REPLY(e_FileToCli_FileDownloadReply);
        client.m_buffer.write<uint32_t>(transId);
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File size
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();
        return;
    }

    struct stat stat_buf;
    off_t filepos = 0;
    if (fstat(fd, &stat_buf) < 0) {
        ST::printf(stderr, "[File] Could not stat file {}\n[File] Requested by {}\n",
                   filename, DS::SockIpAddress(client.m_sock));
        START_REPLY(e_FileToCli_FileDownloadReply);
        client.m_buffer.write<uint32_t>(transId);
        client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound);
        client.m_buffer.write<uint32_t>(0);     // Reader ID
        client.m_buffer.write<uint32_t>(0);     // File size
        client.m_buffer.write<uint32_t>(0);     // Data packet size
        SEND_REPLY();

        close(fd);
        return;
    }

    // Attempting to use the MOUL protocol's "acking" of file chunks has a severe performance
    // penalty. For me, I see an improvement from 950 KiB/s to 14 MiB/s by simply sending the
    // whole file synchronously. We still have to chunk it, though, so the client's progress
    // bar updates correctly. Besides, this is TCP, who needs acks at this level? The drawback
    // to this is that the connection becomes unresponsive to all other traffic when a download
    // is in progress.
    while (filepos < stat_buf.st_size) {
        off_t remsz = stat_buf.st_size - filepos;
        uint32_t chunksz = remsz > CHUNK_SIZE ? CHUNK_SIZE : (uint32_t)remsz;

        START_REPLY(e_FileToCli_FileDownloadReply);
        client.m_buffer.write<uint32_t>(transId);
        client.m_buffer.write<uint32_t>(DS::e_NetSuccess);
        client.m_buffer.write<uint32_t>(client.m_readerId);     // Reader ID
        client.m_buffer.write<uint32_t>(stat_buf.st_size);      // File size
        client.m_buffer.write<uint32_t>(chunksz);               // Data packet size
        SEND_FD_REPLY(fd, filepos, chunksz);
    }

    ++client.m_readerId;
    close(fd);
}

void cb_downloadNext(FileServer_Private& client)
{
    /* This is TCP, nobody cares about this ack... */
    DS::RecvValue<uint32_t>(client.m_sock);     // TransID
    DS::RecvValue<uint32_t>(client.m_sock);     // Reader ID
}

void wk_fileServ(DS::SocketHandle sockp)
{
    FileServer_Private client;

    s_clientMutex.lock();
    client.m_sock = sockp;
    client.m_readerId = 0;
    s_clients.push_back(&client);
    s_clientMutex.unlock();

    try {
        file_init(client);

        for ( ;; ) {
            DS::RecvValue<uint32_t>(client.m_sock);  // Message size
            uint32_t msgId = DS::RecvValue<uint32_t>(client.m_sock);
            switch (msgId) {
            case e_CliToFile_PingRequest:
                cb_ping(client);
                break;
            case e_CliToFile_BuildIdRequest:
                cb_buildId(client);
                break;
            case e_CliToFile_ManifestRequest:
                cb_manifest(client);
                break;
            case e_CliToFile_ManifestEntryAck:
                cb_manifestAck(client);
                break;
            case e_CliToFile_DownloadRequest:
                cb_downloadStart(client);
                break;
            case e_CliToFile_DownloadChunkAck:
                cb_downloadNext(client);
                break;
            default:
                /* Invalid message */
                ST::printf(stderr, "[File] Got invalid message ID {} from {}\n",
                           msgId, DS::SockIpAddress(client.m_sock));
                DS::CloseSock(client.m_sock);
                throw DS::SockHup();
            }
        }
    } catch (const DS::SockHup&) {
        // Socket closed...
    } catch (const std::exception& ex) {
        ST::printf(stderr, "[File] Error processing client message from {}: {}\n",
                   DS::SockIpAddress(sockp), ex.what());
    }

    s_clientMutex.lock();
    auto client_iter = s_clients.begin();
    while (client_iter != s_clients.end()) {
        if (*client_iter == &client)
            client_iter = s_clients.erase(client_iter);
        else
            ++client_iter;
    }
    s_clientMutex.unlock();

    DS::FreeSock(client.m_sock);
}

void DS::FileServer_Init()
{ }

void DS::FileServer_Add(DS::SocketHandle client)
{
    std::thread threadh(&wk_fileServ, client);
    threadh.detach();
}

void DS::FileServer_Shutdown()
{
    {
        std::lock_guard<std::mutex> clientGuard(s_clientMutex);
        for (auto client_iter = s_clients.begin(); client_iter != s_clients.end(); ++client_iter)
            DS::CloseSock((*client_iter)->m_sock);
    }

    bool complete = false;
    for (int i=0; i<50 && !complete; ++i) {
        s_clientMutex.lock();
        size_t alive = s_clients.size();
        s_clientMutex.unlock();
        if (alive == 0)
            complete = true;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    if (!complete)
        fputs("[File] Clients didn't die after 5 seconds!\n", stderr);
}

void DS::FileServer_DisplayClients()
{
    std::lock_guard<std::mutex> clientGuard(s_clientMutex);
    if (s_clients.size())
        fputs("File Server:\n", stdout);
    for (auto client_iter = s_clients.begin(); client_iter != s_clients.end(); ++client_iter)
        ST::printf("  * {}\n", DS::SockIpAddress((*client_iter)->m_sock));
}
<|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

#include "XLUnicodeRichExtendedString.h"
#include "../BaseObject.h"
#include "../GlobalWorkbookInfo.h"
#include "../Biff_records/Font.h"

#include "../../../Common/utils.h"

namespace XLS
{

XLUnicodeRichExtendedString XLUnicodeRichExtendedString::operator=(const XLUnicodeRichExtendedString& other)
{
	XLUnicodeRichExtendedString tmp(other);
	std::swap(*this, tmp);
	return *this;
}

XLUnicodeRichExtendedString::XLUnicodeRichExtendedString(std::list<CFRecordPtr>& cont_recs)
:	cont_recs_(cont_recs),
	fHighByte(true),
	extRst(cont_recs)
{
	code_page_  = 0;
}

const bool XLUnicodeRichExtendedString::appendNextContinue(CFRecord& record, const bool read_high_byte)
{
	if(cont_recs_.empty())
	{
		return false;
	}

	RecordType type = (RecordType)cont_recs_.front()->getTypeId();

	while(!cont_recs_.empty())
	{
		type = (RecordType)cont_recs_.front()->getTypeId();

		if (type == rt_SST || type == rt_Continue)
		{
			if(read_high_byte)
			{
				fHighByte = (0x01 == cont_recs_.front()->getData()[0]);
				record.appendRawData(cont_recs_.front()->getData() + 1, cont_recs_.front()->getDataSize() - 1);
			}
			else
			{
				record.appendRawData(cont_recs_.front());
			}
			cont_recs_.pop_front();
			break;
		}
		else
			cont_recs_.pop_front();

	}
	return true;
}

XLUnicodeRichExtendedString::~XLUnicodeRichExtendedString()
{
}

void XLUnicodeRichExtendedString::set_code_page(short cp)
{
	code_page_ = cp;
}

BiffStructurePtr XLUnicodeRichExtendedString::clone()
{
	return BiffStructurePtr(new XLUnicodeRichExtendedString(*this));
}

int XLUnicodeRichExtendedString::serialize (std::wostream & _stream)
{
	int start_string = 0;
	int Fmt = 0; //форматы со сдвигом !!! .. первый - тот что определен в ячейке.

	CP_XML_WRITER(_stream)
	{
		for (size_t i = 0 ; i < rgRun.size(); i++)
		{
			CP_XML_NODE(L"r")
			{
				serialize_rPr(CP_XML_STREAM(), Fmt );
				Fmt = rgRun[i].ifnt;

				CP_XML_NODE(L"t")
				{
					CP_XML_ATTR(L"xml:space", L"preserve");

					std::wstring str_part = str_.substr( start_string, rgRun[i].ich - start_string );
					start_string = rgRun[i].ich;
					CP_XML_STREAM() << STR::escape_ST_Xstring(xml::utils::replace_text_to_xml(str_part));
				}
			}
		}
		if (start_string < str_.size())
		{
			CP_XML_NODE(L"r")
			{
				serialize_rPr(CP_XML_STREAM(), Fmt );

				CP_XML_NODE(L"t")
				{
					CP_XML_ATTR(L"xml:space", L"preserve");
					std::wstring str_part = str_.substr( start_string, str_.size() - start_string );
					CP_XML_STREAM() << xml::utils::replace_text_to_xml(str_part);
				}
			}
		}
	}

	return 0;
}
int XLUnicodeRichExtendedString::serialize_rPr	(std::wostream & _stream, int iFmt)
{
	if (!pGlobalWorkbookInfoPtr)			return 0;

	int sz = pGlobalWorkbookInfoPtr->m_arFonts.size();
	if (iFmt -1 > sz || iFmt < 1) return 0;

	CP_XML_WRITER(_stream)
	{
		CP_XML_NODE(L"rPr")
		{
			Font * font = dynamic_cast<Font*>(pGlobalWorkbookInfoPtr->m_arFonts[iFmt-1].get());

			if (font) font->serialize_properties(CP_XML_STREAM(), true);
		}
	}

	return 0;
}

void XLUnicodeRichExtendedString::load(CFRecord& record)
{
	pGlobalWorkbookInfoPtr = record.getGlobalWorkbookInfo();

	if (code_page_== 0)
		code_page_ = pGlobalWorkbookInfoPtr ->CodePage;

	unsigned short cch = 0;
	unsigned char flags = 0;
	record >> cch >> flags;

	fHighByte	= GETBIT(flags, 0);

	if (record.getDataSize() == record.getRdPtr())
	{
		if (appendNextContinue(record, true) == false) //fHighByte MUST be specified in the first byte of the continue field of the Continue
			return;
	}

	fExtSt		= GETBIT(flags, 2);
	fRichSt		= GETBIT(flags, 3);

	unsigned short cRun = 0;
	if(fRichSt)
	{
		record >> cRun;
	}
    int cbExtRst = 0;

	if(fExtSt)
	{
		record >> cbExtRst;

		if (cbExtRst < 0)
		{
			fExtSt = false;
			fRichSt = true;
			record.RollRdPtrBack(4);

			record >> cRun;
		}
	}

	if(!record.checkFitReadSafe(static_cast<size_t>(cch) << (fHighByte ? 1 : 0)))
	{
		size_t num_symbols = (std::min)(static_cast<size_t>(cch), (record.getDataSize() - record.getRdPtr()) >> (fHighByte ? 1 : 0));
		loadSymbols(record, num_symbols, fHighByte);
		size_t str_sz = num_symbols;

		std::wstring  str_full(str_);
		do
		{
			if (appendNextContinue(record, true) == false) // fHighByte changes here
				break; //dicionario de kanji.xls
			num_symbols = (std::min)(cch - str_full.length(), (record.getDataSize() - record.getRdPtr()) >> (fHighByte ? 1 : 0));
			loadSymbols(record, num_symbols, fHighByte); // cch has changed, fHighByte has changed
			str_full	+= str_;
			str_sz		+= num_symbols;
		}
		while(str_sz < cch);

		std::swap(str_full, str_); // Thus we avoid additional copy in operator=
	}
	else
	{
		loadSymbols(record, cch, fHighByte);
	}
	if (record.getRdPtr() + cRun * 4 > record.getDataSize() && !cont_recs_.empty())
	{
		unsigned char flags = 0;
		(*cont_recs_.front()) >> flags;
		fHighByte = (0x01 == flags);

		record.appendRawData(cont_recs_.front()->getData() + 1, cont_recs_.front()->getDataSize() - 1);
		cont_recs_.pop_front();
	}
	for(size_t i = 0; i < cRun; ++i)
	{
		FormatRun format;
		record >> format;
		rgRun.push_back(format);
	}

	if(fExtSt && cbExtRst > 0)
	{
		if (record.getRdPtr() + cbExtRst > record.getDataSize() && !cont_recs_.empty())
		{
			unsigned char flags = 0;
			(*cont_recs_.front()) >> flags;
			fHighByte = (0x01 == flags);

			record.appendRawData(cont_recs_.front()->getData() + 1, cont_recs_.front()->getDataSize() - 1);
			cont_recs_.pop_front();
		}
		extRst.load(record);
	}
}

void XLUnicodeRichExtendedString::loadSymbols(CFRecord& record, const size_t cch, const bool is_wide)
{
	size_t raw_length = cch << (is_wide ? 1 : 0);
	if (record.checkFitRead(raw_length))
	{
		if(is_wide)
		{
	#if defined(_WIN32) || defined(_WIN64)
			std::wstring int_str(record.getCurData<wchar_t>(), cch);
			str_ = int_str.c_str();
	#else
			str_ = convertUtf16ToWString(record.getCurData<UTF16>(), cch);
	#endif
		}
		else
		{
			std::string inp_str(record.getCurData<char>(), cch);

			if (record.getGlobalWorkbookInfo()->CodePage == 1200)
			{
				int inp_str_size = inp_str.length();
                UTF16 *out_str = new UTF16[inp_str_size + 1];
				char* out_str_char = (char*) out_str;
				for (int i = 0; i < inp_str_size; i++)
				{
					out_str_char[2*i + 0] = inp_str.c_str()[i];
					out_str_char[2*i + 1] = 0;
				}
				out_str[inp_str_size] = 0;

#if defined(_WIN32) || defined(_WIN64)
                str_ = std::wstring((wchar_t*)out_str, inp_str_size);
#else
                str_ = convertUtf16ToWString(out_str, inp_str_size);
#endif
                delete []out_str;
			}
			else
			{
				str_ = STR::toStdWString(inp_str, record.getGlobalWorkbookInfo()->CodePage);
			}
		}
		record.skipNunBytes(raw_length);
	}
}

CFRecord& operator>>(CFRecord& record, XLUnicodeRichExtendedString& val)
{
	val.load(record);
	return record;
}

const size_t XLUnicodeRichExtendedString::getNonVariablePartSize() const
{
	unsigned short size = sizeof(unsigned short)/*cch*/ + sizeof(unsigned char)/*flags*/;
	if(fRichSt)
	{
        size += sizeof(unsigned short)/*cRun*/; //2 !!!!
	}
	if(fExtSt)
	{
        size += sizeof(int)/*cbExtRst*/; // ??? 4!!!
	}
	return size;
}

const size_t XLUnicodeRichExtendedString::getFullSize() const
{
	unsigned short size = getNonVariablePartSize();

	size += str_.length() << (fHighByte ? 1 : 0);

	size += rgRun.size() * (2 * sizeof(unsigned short))/*FormatRun*/;

	if(fExtSt)
	{
		size += extRst.getSize();
	}

	return size;
}

} // namespace XLS
<commit_msg>fix bug #58095<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

#include "XLUnicodeRichExtendedString.h"
#include "../BaseObject.h"
#include "../GlobalWorkbookInfo.h"
#include "../Biff_records/Font.h"

#include "../../../Common/utils.h"

namespace XLS
{

XLUnicodeRichExtendedString XLUnicodeRichExtendedString::operator=(const XLUnicodeRichExtendedString& other)
{
	XLUnicodeRichExtendedString tmp(other);
	std::swap(*this, tmp);
	return *this;
}

XLUnicodeRichExtendedString::XLUnicodeRichExtendedString(std::list<CFRecordPtr>& cont_recs)
:	cont_recs_(cont_recs),
	fHighByte(true),
	extRst(cont_recs)
{
	code_page_  = 0;
}

const bool XLUnicodeRichExtendedString::appendNextContinue(CFRecord& record, const bool read_high_byte)
{
	if(cont_recs_.empty())
	{
		return false;
	}

	RecordType type = (RecordType)cont_recs_.front()->getTypeId();

	while (!cont_recs_.empty())
	{
		type = (RecordType)cont_recs_.front()->getTypeId();

		if (type == rt_SST || type == rt_Continue)
		{
			if (read_high_byte)
			{
				fHighByte = (0x01 == cont_recs_.front()->getData()[0]);

				record.appendRawData(cont_recs_.front()->getData() + 1, cont_recs_.front()->getDataSize() - 1);
			}
			else
			{
				record.appendRawData(cont_recs_.front());
			}
			cont_recs_.pop_front();
			break;
		}
		else
			cont_recs_.pop_front();

	}
	return true;
}

XLUnicodeRichExtendedString::~XLUnicodeRichExtendedString()
{
}

void XLUnicodeRichExtendedString::set_code_page(short cp)
{
	code_page_ = cp;
}

BiffStructurePtr XLUnicodeRichExtendedString::clone()
{
	return BiffStructurePtr(new XLUnicodeRichExtendedString(*this));
}

int XLUnicodeRichExtendedString::serialize (std::wostream & _stream)
{
	int start_string = 0;
	int Fmt = 0; //форматы со сдвигом !!! .. первый - тот что определен в ячейке.

	CP_XML_WRITER(_stream)
	{
		for (size_t i = 0 ; i < rgRun.size(); i++)
		{
			CP_XML_NODE(L"r")
			{
				serialize_rPr(CP_XML_STREAM(), Fmt );
				Fmt = rgRun[i].ifnt;

				CP_XML_NODE(L"t")
				{
					CP_XML_ATTR(L"xml:space", L"preserve");

					std::wstring str_part = str_.substr( start_string, rgRun[i].ich - start_string );
					start_string = rgRun[i].ich;
					CP_XML_STREAM() << STR::escape_ST_Xstring(xml::utils::replace_text_to_xml(str_part));
				}
			}
		}
		if (start_string < str_.size())
		{
			CP_XML_NODE(L"r")
			{
				serialize_rPr(CP_XML_STREAM(), Fmt );

				CP_XML_NODE(L"t")
				{
					CP_XML_ATTR(L"xml:space", L"preserve");
					std::wstring str_part = str_.substr( start_string, str_.size() - start_string );
					CP_XML_STREAM() << xml::utils::replace_text_to_xml(str_part);
				}
			}
		}
	}

	return 0;
}
int XLUnicodeRichExtendedString::serialize_rPr	(std::wostream & _stream, int iFmt)
{
	if (!pGlobalWorkbookInfoPtr)			return 0;

	int sz = pGlobalWorkbookInfoPtr->m_arFonts.size();
	if (iFmt -1 > sz || iFmt < 1) return 0;

	CP_XML_WRITER(_stream)
	{
		CP_XML_NODE(L"rPr")
		{
			Font * font = dynamic_cast<Font*>(pGlobalWorkbookInfoPtr->m_arFonts[iFmt-1].get());

			if (font) font->serialize_properties(CP_XML_STREAM(), true);
		}
	}

	return 0;
}

void XLUnicodeRichExtendedString::load(CFRecord& record)
{
	pGlobalWorkbookInfoPtr = record.getGlobalWorkbookInfo();

	if (code_page_== 0)
		code_page_ = pGlobalWorkbookInfoPtr ->CodePage;

	unsigned short cch = 0;
	unsigned char flags = 0;
	record >> cch >> flags;

	fHighByte	= GETBIT(flags, 0);

	if (record.getDataSize() == record.getRdPtr())
	{
		if (appendNextContinue(record, true) == false) //fHighByte MUST be specified in the first byte of the continue field of the Continue
			return;
	}

	fExtSt		= GETBIT(flags, 2);
	fRichSt		= GETBIT(flags, 3);

	unsigned short cRun = 0;
	if(fRichSt)
	{
		record >> cRun;
	}
    int cbExtRst = 0;

	if(fExtSt)
	{
		record >> cbExtRst;

		if (cbExtRst < 0)
		{
			fExtSt = false;
			fRichSt = true;
			record.RollRdPtrBack(4);

			record >> cRun;
		}
	}

	if(!record.checkFitReadSafe(static_cast<size_t>(cch) << (fHighByte ? 1 : 0)))
	{
		size_t num_symbols = (std::min)(static_cast<size_t>(cch), (record.getDataSize() - record.getRdPtr()) >> (fHighByte ? 1 : 0));
		loadSymbols(record, num_symbols, fHighByte);
		size_t str_sz = num_symbols;

		std::wstring  str_full(str_);
		do
		{
			if (appendNextContinue(record, true) == false) // fHighByte changes here
				break; //dicionario de kanji.xls
			num_symbols = (std::min)(cch - str_full.length(), (record.getDataSize() - record.getRdPtr()) >> (fHighByte ? 1 : 0));
			loadSymbols(record, num_symbols, fHighByte); // cch has changed, fHighByte has changed
			str_full	+= str_;
			str_sz		+= num_symbols;
		}
		while(str_sz < cch);

		std::swap(str_full, str_); // Thus we avoid additional copy in operator=
	}
	else
	{
		loadSymbols(record, cch, fHighByte);
	}
	if (record.getRdPtr() + cRun * 4 > record.getDataSize() && !cont_recs_.empty())
	{
		record.appendRawData(cont_recs_.front());
		cont_recs_.pop_front();
	}
	for(size_t i = 0; i < cRun; ++i)
	{
		FormatRun format;
		record >> format;
		rgRun.push_back(format);
	}

	if(fExtSt && cbExtRst > 0)
	{
		if (record.getRdPtr() + cbExtRst > record.getDataSize() && !cont_recs_.empty())
		{
			record.appendRawData(cont_recs_.front());
			cont_recs_.pop_front();
		}
		extRst.load(record);
	}
}

void XLUnicodeRichExtendedString::loadSymbols(CFRecord& record, const size_t cch, const bool is_wide)
{
	size_t raw_length = cch << (is_wide ? 1 : 0);
	if (record.checkFitRead(raw_length))
	{
		if(is_wide)
		{
	#if defined(_WIN32) || defined(_WIN64)
			std::wstring int_str(record.getCurData<wchar_t>(), cch);
			str_ = int_str.c_str();
	#else
			str_ = convertUtf16ToWString(record.getCurData<UTF16>(), cch);
	#endif
		}
		else
		{
			std::string inp_str(record.getCurData<char>(), cch);

			if (record.getGlobalWorkbookInfo()->CodePage == 1200)
			{
				int inp_str_size = inp_str.length();
                UTF16 *out_str = new UTF16[inp_str_size + 1];
				char* out_str_char = (char*) out_str;
				for (int i = 0; i < inp_str_size; i++)
				{
					out_str_char[2*i + 0] = inp_str.c_str()[i];
					out_str_char[2*i + 1] = 0;
				}
				out_str[inp_str_size] = 0;

#if defined(_WIN32) || defined(_WIN64)
                str_ = std::wstring((wchar_t*)out_str, inp_str_size);
#else
                str_ = convertUtf16ToWString(out_str, inp_str_size);
#endif
                delete []out_str;
			}
			else
			{
				str_ = STR::toStdWString(inp_str, record.getGlobalWorkbookInfo()->CodePage);
			}
		}
		record.skipNunBytes(raw_length);
	}
}

CFRecord& operator>>(CFRecord& record, XLUnicodeRichExtendedString& val)
{
	val.load(record);
	return record;
}

const size_t XLUnicodeRichExtendedString::getNonVariablePartSize() const
{
	unsigned short size = sizeof(unsigned short)/*cch*/ + sizeof(unsigned char)/*flags*/;
	if(fRichSt)
	{
        size += sizeof(unsigned short)/*cRun*/; //2 !!!!
	}
	if(fExtSt)
	{
        size += sizeof(int)/*cbExtRst*/; // ??? 4!!!
	}
	return size;
}

const size_t XLUnicodeRichExtendedString::getFullSize() const
{
	unsigned short size = getNonVariablePartSize();

	size += str_.length() << (fHighByte ? 1 : 0);

	size += rgRun.size() * (2 * sizeof(unsigned short))/*FormatRun*/;

	if(fExtSt)
	{
		size += extRst.getSize();
	}

	return size;
}

} // namespace XLS
<|endoftext|>


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

#include "util/sampling/uniform_sampler.h"

namespace veles {
namespace util {

UniformSampler::UniformSampler(const QByteArray &data) :
    ISampler(data), window_size_(0), use_default_window_size_(true),
    buffer_(nullptr) {}

UniformSampler::~UniformSampler() {
  if (buffer_ != nullptr) {
    delete[] buffer_;
  }
}

UniformSampler::UniformSampler(const UniformSampler& other) :
    ISampler(other), window_size_(other.window_size_), buffer_(nullptr) {}

UniformSampler* UniformSampler::clone() {
  return new UniformSampler(*this);
}

void UniformSampler::setWindowSize(size_t size) {
  window_size_ = size;
  use_default_window_size_ = size == 0;
  if (buffer_ != nullptr) {
    delete[] buffer_;
    buffer_ = nullptr;
  }
  reinitialisationRequired();
}

size_t UniformSampler::getRealSampleSize() {
  if (!isInitialised()) {
    return 0;
  }
  return window_size_ * windows_count_;
}

void UniformSampler::initialiseSample(size_t size) {
  // default size == sqrt(sample size)
  if (buffer_ != nullptr) {
    delete[] buffer_;
    buffer_ = nullptr;
  }

  if (use_default_window_size_ || window_size_ == 0) {
    window_size_ = (size_t)floor(sqrt(size));
  }
  windows_count_ = (size_t)floor(size / window_size_);

  // Algorithm:
  // First let's mark windows_count_ as m, window_size_ as k and
  // getDataSize() as n.
  // 1. Take m numbers from {0, 1 ... n - m*k} with repetitions,
  //    marked as (c_i) sequence.
  // 2. Sort (c_i) sequence.
  // 3. Produce the result indices (d_i) in the following way:
  //    d_i = c_i + i*k
  //
  // And why that works:
  // - The smallest value of d_0 is 0.
  // - The largest value of d_{m-1} is
  //   n - m*k + (m-1)*k = n - k
  //   which is exactly what we want because the piece length is k.
  // - For each i the distance d_{i+1}-d_i >= k.
  size_t max_index = getDataSize() - windows_count_ * window_size_;
  std::default_random_engine generator;
  std::uniform_int_distribution<size_t> distribution(0, max_index);
  windows_.resize(windows_count_);
  for (size_t i = 0; i < windows_count_; ++i) {
    windows_[i] = distribution(generator);
  }
  std::sort(windows_.begin(), windows_.end());
  for (size_t i = 0; i < windows_count_; ++i) {
    windows_[i] += i*window_size_;
  }
}

char UniformSampler::getSampleByte(size_t index) {
  if (buffer_ != nullptr) {
    return buffer_[index];
  }
  size_t base_index = windows_[index / window_size_];
  return getDataByte(base_index + (index % window_size_));
}

const char* UniformSampler::getData() {
  if (buffer_ == nullptr) {
    size_t size = getSampleSize();
    char *tmp_buffer = new char[size];
    for (size_t i=0; i < size; ++i) {
      tmp_buffer[i] = operator[](i);
    }
    buffer_ = tmp_buffer;
  }
  return buffer_;
}

size_t UniformSampler::getFileOffsetImpl(size_t index) {
  size_t base_index = windows_[index / window_size_];
  return base_index + (index % window_size_);
}

size_t UniformSampler::getSampleOffsetImpl(size_t address) {
  auto previous_window = std::lower_bound(windows_.begin(), windows_.end(),
                                          address);
  size_t base_index = static_cast<size_t>(
    std::distance(windows_.begin(), previous_window) * window_size_);
  return base_index + std::min(window_size_ - 1, address - (*previous_window));
}

void UniformSampler::resampleImpl() {
}

}  // namespace util
}  // namespace veles
<commit_msg>Skip function calls when building data array in uniform sampler<commit_after>/*
 * Copyright 2016 CodiLime
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iterator>
#include <random>
#include <set>

#include "util/sampling/uniform_sampler.h"

namespace veles {
namespace util {

UniformSampler::UniformSampler(const QByteArray &data) :
    ISampler(data), window_size_(0), use_default_window_size_(true),
    buffer_(nullptr) {}

UniformSampler::~UniformSampler() {
  if (buffer_ != nullptr) {
    delete[] buffer_;
  }
}

UniformSampler::UniformSampler(const UniformSampler& other) :
    ISampler(other), window_size_(other.window_size_), buffer_(nullptr) {}

UniformSampler* UniformSampler::clone() {
  return new UniformSampler(*this);
}

void UniformSampler::setWindowSize(size_t size) {
  window_size_ = size;
  use_default_window_size_ = size == 0;
  if (buffer_ != nullptr) {
    delete[] buffer_;
    buffer_ = nullptr;
  }
  reinitialisationRequired();
}

size_t UniformSampler::getRealSampleSize() {
  if (!isInitialised()) {
    return 0;
  }
  return window_size_ * windows_count_;
}

void UniformSampler::initialiseSample(size_t size) {
  // default size == sqrt(sample size)
  if (buffer_ != nullptr) {
    delete[] buffer_;
    buffer_ = nullptr;
  }

  if (use_default_window_size_ || window_size_ == 0) {
    window_size_ = (size_t)floor(sqrt(size));
  }
  windows_count_ = (size_t)floor(size / window_size_);

  // Algorithm:
  // First let's mark windows_count_ as m, window_size_ as k and
  // getDataSize() as n.
  // 1. Take m numbers from {0, 1 ... n - m*k} with repetitions,
  //    marked as (c_i) sequence.
  // 2. Sort (c_i) sequence.
  // 3. Produce the result indices (d_i) in the following way:
  //    d_i = c_i + i*k
  //
  // And why that works:
  // - The smallest value of d_0 is 0.
  // - The largest value of d_{m-1} is
  //   n - m*k + (m-1)*k = n - k
  //   which is exactly what we want because the piece length is k.
  // - For each i the distance d_{i+1}-d_i >= k.
  size_t max_index = getDataSize() - windows_count_ * window_size_;
  std::default_random_engine generator;
  std::uniform_int_distribution<size_t> distribution(0, max_index);
  windows_.resize(windows_count_);
  for (size_t i = 0; i < windows_count_; ++i) {
    windows_[i] = distribution(generator);
  }
  std::sort(windows_.begin(), windows_.end());
  for (size_t i = 0; i < windows_count_; ++i) {
    windows_[i] += i*window_size_;
  }
}

char UniformSampler::getSampleByte(size_t index) {
  if (buffer_ != nullptr) {
    return buffer_[index];
  }
  size_t base_index = windows_[index / window_size_];
  return getDataByte(base_index + (index % window_size_));
}

const char* UniformSampler::getData() {
  if (buffer_ == nullptr) {
    size_t size = getSampleSize();
    const char *raw_data = getRawData();
    char *tmp_buffer = new char[size];
    for (size_t i=0; i < size; ++i) {
      size_t base_index = windows_[i / window_size_];
      tmp_buffer[i] = raw_data[base_index + (i % window_size_)];
    }
    buffer_ = tmp_buffer;
  }
  return buffer_;
}

size_t UniformSampler::getFileOffsetImpl(size_t index) {
  size_t base_index = windows_[index / window_size_];
  return base_index + (index % window_size_);
}

size_t UniformSampler::getSampleOffsetImpl(size_t address) {
  auto previous_window = std::lower_bound(windows_.begin(), windows_.end(),
                                          address);
  size_t base_index = static_cast<size_t>(
    std::distance(windows_.begin(), previous_window) * window_size_);
  return base_index + std::min(window_size_ - 1, address - (*previous_window));
}

void UniformSampler::resampleImpl() {
}

}  // namespace util
}  // namespace veles
<|endoftext|>


<commit_before>/*
    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
    Copyright (C) 2011 Collabora Ltd. <info@collabora.com>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 2.1
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "gstqtvideosinkplugin.h"
#include "gstqtvideosink.h"
#include "gstqtglvideosink.h"
#include "gstqwidgetvideosink.h"

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
# include "gstqtquick2videosink.h"
#endif

GST_DEBUG_CATEGORY(gst_qt_video_sink_debug);

/* entry point to initialize the plug-in */
static gboolean plugin_init(GstPlugin *plugin)
{
    GST_DEBUG_CATEGORY_INIT(gst_qt_video_sink_debug, QTVIDEOSINK_NAME, 0,
                            "Debug category for GstQtVideoSink");

    gst_element_register(plugin, QTVIDEOSINK_NAME,
            GST_RANK_NONE, GST_TYPE_QT_VIDEO_SINK);
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
    gst_element_register(plugin, QTGLVIDEOSINK_NAME,
            GST_RANK_NONE, GST_TYPE_QT_GL_VIDEO_SINK);
#endif
    gst_element_register(plugin, QWIDGETVIDEOSINK_NAME,
            GST_RANK_NONE, GST_TYPE_QWIDGET_VIDEO_SINK);

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    gst_element_register(plugin, "qtquick2videosink",
            GST_RANK_NONE, GST_TYPE_QT_QUICK2_VIDEO_SINK);
#endif

    return TRUE;
}

GST_PLUGIN_DEFINE (
    GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    QTVIDEOSINK_NAME,
    "A video sink that can draw on any Qt surface",
    plugin_init,
    PACKAGE_VERSION,
    "LGPL",
    PACKAGE_NAME,
    PACKAGE_ORIGIN
)
<commit_msg>elements/gstqtvideosink/gstqtvideosinkplugin.cpp add error handling to plugin registration.<commit_after>/*
    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
    Copyright (C) 2011 Collabora Ltd. <info@collabora.com>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 2.1
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "gstqtvideosinkplugin.h"
#include "gstqtvideosink.h"
#include "gstqtglvideosink.h"
#include "gstqwidgetvideosink.h"

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
# include "gstqtquick2videosink.h"
#endif

GST_DEBUG_CATEGORY(gst_qt_video_sink_debug);

/* entry point to initialize the plug-in */
static gboolean plugin_init(GstPlugin *plugin)
{
    GST_DEBUG_CATEGORY_INIT(gst_qt_video_sink_debug, QTVIDEOSINK_NAME, 0,
                            "Debug category for GstQtVideoSink");

    if(!gst_element_register(plugin, QTVIDEOSINK_NAME,
                GST_RANK_NONE, GST_TYPE_QT_VIDEO_SINK)) {
        GST_ERROR("Failed to register " QTVIDEOSINK_NAME);
        return FALSE;
    }
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
    if(!gst_element_register(plugin, QTGLVIDEOSINK_NAME,
                GST_RANK_NONE, GST_TYPE_QT_GL_VIDEO_SINK)) {
        GST_ERROR("Failed to register " QTGLVIDEOSINK_NAME);
        return FALSE;
    }
#endif
    if(!gst_element_register(plugin, QWIDGETVIDEOSINK_NAME,
                GST_RANK_NONE, GST_TYPE_QWIDGET_VIDEO_SINK)) {
        GST_ERROR("Failed to register " QWIDGETVIDEOSINK_NAME);
        return FALSE;
    }

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    if (!gst_element_register(plugin, "qtquick2videosink",
                GST_RANK_NONE, GST_TYPE_QT_QUICK2_VIDEO_SINK)) {
        GST_ERROR("Failed to register qtquick2videosink");
        return FALSE;
    }
#endif

    return TRUE;
}

GST_PLUGIN_DEFINE (
    GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    QTVIDEOSINK_NAME,
    "A video sink that can draw on any Qt surface",
    plugin_init,
    PACKAGE_VERSION,
    "LGPL",
    PACKAGE_NAME,
    PACKAGE_ORIGIN
)
<|endoftext|>