<commit_before>/*
 * Copyright 2004-2015 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is 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 "astutil.h"
#include "expr.h"
#include "optimizations.h"
#include "passes.h"
#include "resolveIntents.h"
#include "stmt.h"
#include "stringutil.h"
#include "symbol.h"
#include "type.h"

static Type* getWrapRecordBaseType(Type* type);

//
// removes _array and _domain wrapper records
//
void
removeWrapRecords() {
  //
  // do not remove wrap records if dead code elimination is disabled
  // (or weakened because inlining or copy propagation is disabled)
  // because code associated with accesses to the removed
  // _valueType field will remain
  //
  if (fNoDeadCodeElimination || fNoInline || fNoCopyPropagation)
    return;

  //
  // replace use of _valueType field with type
  //
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_GET_PRIV_CLASS)) {
      SET_LINENO(call);
      call->get(1)->replace(new SymExpr(call->get(1)->typeInfo()->symbol));
    }
  }

  //
  // remove defs of _valueType field
  //
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_SET_MEMBER) ||
        call->isPrimitive(PRIM_GET_MEMBER) ||
        call->isPrimitive(PRIM_GET_MEMBER_VALUE)) {
      if (SymExpr* se = toSymExpr(call->get(2))) {
        if (!strcmp(se->var->name, "_valueType")) {
          se->getStmtExpr()->remove();
        }
      }
    }
  }

  //
  // remove _valueType fields
  //
  forv_Vec(AggregateType, ct, gAggregateTypes) {
    for_fields(field, ct) {
      if (!strcmp(field->name, "_valueType"))
        field->defPoint->remove();
    }
  }

  //
  // remove formals for _valueType fields in constructors
  //
  compute_call_sites();
  forv_Vec(FnSymbol, fn, gFnSymbols) {
    for_formals(formal, fn) {
      if (!strcmp(formal->name, "_valueType")) {
        forv_Vec(CallExpr, call, *fn->calledBy) {
          formal_to_actual(call, formal)->remove();
        }
        formal->defPoint->remove();
      }
    }
  }

  //
  // replace accesses of _value with wrap record
  //
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_SET_MEMBER)) {
      if (SymExpr* se = toSymExpr(call->get(1))) {
        if (isRecordWrappedType(se->var->type)) {
          call->primitive = primitives[PRIM_MOVE];
          call->get(2)->remove();
        }
      }
    } else if (call->isPrimitive(PRIM_GET_MEMBER)) {
      if (SymExpr* se = toSymExpr(call->get(1))) {
        if (isRecordWrappedType(se->var->type)) {
          call->primitive = primitives[PRIM_ADDR_OF];
          call->get(2)->remove();
        }
      }
    } else if (call->isPrimitive(PRIM_GET_MEMBER_VALUE)) {
      if (SymExpr* se = toSymExpr(call->get(1))) {
        if (isRecordWrappedType(se->var->type)) {
          call->replace(se->remove());
        }
        if (se->var->type->symbol->hasFlag(FLAG_REF)) {
          Type* vt = se->getValType();
          if (isRecordWrappedType(vt)) {
            SET_LINENO(call);
            call->replace(new CallExpr(PRIM_DEREF, se->remove()));
          }
        }
      }
    }
  }

  //
  // scalar replace wrap records
  //
  forv_Vec(VarSymbol, var, gVarSymbols) {
    if (Type* type = getWrapRecordBaseType(var->type))
      if (!var->defPoint->parentSymbol->hasFlag(FLAG_REF))
        var->type = type;
  }
  forv_Vec(ArgSymbol, arg, gArgSymbols) {
    if (Type* type = getWrapRecordBaseType(arg->type)) {
      arg->intent = blankIntentForType(type); // see test/arrays/deitz/part7/test_out_array
      arg->type = type;
    }
  }
  forv_Vec(FnSymbol, fn, gFnSymbols) {
    if (Type* type = getWrapRecordBaseType(fn->retType))
      fn->retType = type;
  }

  //
  // fix array element type for arrays of arrays and arrays of domains
  //
  forv_Vec(AggregateType, ct, gAggregateTypes) {
    if (ct->symbol->hasFlag(FLAG_DATA_CLASS)) {
      if (TypeSymbol* ts = getDataClassType(ct->symbol)) {
        if (isRecordWrappedType(ts->typeInfo())) {
          setDataClassType(ct->symbol, ts->type->getField("_value")->type->symbol);
        }
      }
    }
  }
}

static Type*
getWrapRecordBaseType(Type* type) {
  if (isRecordWrappedType(type)) {
    return type->getField("_value")->type;
  } else if (type->symbol->hasFlag(FLAG_REF)) {
    Type* vt = type->getValType();
    if (isRecordWrappedType(vt)) {
      return vt->getField("_value")->type->refType;
    }
  }
  return NULL;
}

<commit_msg>Remove all uses of _valueType from function body in removeWrapRecords.<commit_after>/*
 * Copyright 2004-2015 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is 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 "astutil.h"
#include "expr.h"
#include "optimizations.h"
#include "passes.h"
#include "resolveIntents.h"
#include "stmt.h"
#include "stringutil.h"
#include "symbol.h"
#include "type.h"
#include "stlUtil.h"

static Type* getWrapRecordBaseType(Type* type);

//
// removes _array and _domain wrapper records
//
void
removeWrapRecords() {
  //
  // do not remove wrap records if dead code elimination is disabled
  // (or weakened because inlining or copy propagation is disabled)
  // because code associated with accesses to the removed
  // _valueType field will remain
  //
  if (fNoDeadCodeElimination || fNoInline || fNoCopyPropagation)
    return;

  //
  // replace use of _valueType field with type
  //
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_GET_PRIV_CLASS)) {
      SET_LINENO(call);
      call->get(1)->replace(new SymExpr(call->get(1)->typeInfo()->symbol));
    }
  }

  //
  // remove defs of _valueType field
  //
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_SET_MEMBER) ||
        call->isPrimitive(PRIM_GET_MEMBER) ||
        call->isPrimitive(PRIM_GET_MEMBER_VALUE)) {
      if (SymExpr* se = toSymExpr(call->get(2))) {
        if (!strcmp(se->var->name, "_valueType")) {
          se->getStmtExpr()->remove();
        }
      }
    }
  }

  //
  // remove _valueType fields
  //
  forv_Vec(AggregateType, ct, gAggregateTypes) {
    for_fields(field, ct) {
      if (!strcmp(field->name, "_valueType"))
        field->defPoint->remove();
    }
  }

  //
  // remove formals for _valueType fields in constructors
  //
  compute_call_sites();
  forv_Vec(FnSymbol, fn, gFnSymbols) {
    for_formals(formal, fn) {
      if (!strcmp(formal->name, "_valueType")) {
        forv_Vec(CallExpr, call, *fn->calledBy) {
          formal_to_actual(call, formal)->remove();
        }
        // Remove all uses of _valueType within the body of this function.
        std::vector<SymExpr*> symExprs;
        collectSymExprsSTL(fn->body, symExprs);
        for_vector(SymExpr, se, symExprs) {
          // Ignore dead ones.
          if (se->parentSymbol == NULL)
            continue;
          // Weed out all but the formal we're interested in.
          if (se->var != formal)
            continue;
          // OK, remove the entire statement accessing the _valueType formal.
          Expr* stmt = se->getStmtExpr();
          stmt->remove();
        }
        formal->defPoint->remove();
      }
    }
  }

  //
  // replace accesses of _value with wrap record
  //
  forv_Vec(CallExpr, call, gCallExprs) {
    if (call->isPrimitive(PRIM_SET_MEMBER)) {
      if (SymExpr* se = toSymExpr(call->get(1))) {
        if (isRecordWrappedType(se->var->type)) {
          call->primitive = primitives[PRIM_MOVE];
          call->get(2)->remove();
        }
      }
    } else if (call->isPrimitive(PRIM_GET_MEMBER)) {
      if (SymExpr* se = toSymExpr(call->get(1))) {
        if (isRecordWrappedType(se->var->type)) {
          call->primitive = primitives[PRIM_ADDR_OF];
          call->get(2)->remove();
        }
      }
    } else if (call->isPrimitive(PRIM_GET_MEMBER_VALUE)) {
      if (SymExpr* se = toSymExpr(call->get(1))) {
        if (isRecordWrappedType(se->var->type)) {
          call->replace(se->remove());
        }
        if (se->var->type->symbol->hasFlag(FLAG_REF)) {
          Type* vt = se->getValType();
          if (isRecordWrappedType(vt)) {
            SET_LINENO(call);
            call->replace(new CallExpr(PRIM_DEREF, se->remove()));
          }
        }
      }
    }
  }

  //
  // scalar replace wrap records
  //
  forv_Vec(VarSymbol, var, gVarSymbols) {
    if (Type* type = getWrapRecordBaseType(var->type))
      if (!var->defPoint->parentSymbol->hasFlag(FLAG_REF))
        var->type = type;
  }
  forv_Vec(ArgSymbol, arg, gArgSymbols) {
    if (Type* type = getWrapRecordBaseType(arg->type)) {
      arg->intent = blankIntentForType(type); // see test/arrays/deitz/part7/test_out_array
      arg->type = type;
    }
  }
  forv_Vec(FnSymbol, fn, gFnSymbols) {
    if (Type* type = getWrapRecordBaseType(fn->retType))
      fn->retType = type;
  }

  //
  // fix array element type for arrays of arrays and arrays of domains
  //
  forv_Vec(AggregateType, ct, gAggregateTypes) {
    if (ct->symbol->hasFlag(FLAG_DATA_CLASS)) {
      if (TypeSymbol* ts = getDataClassType(ct->symbol)) {
        if (isRecordWrappedType(ts->typeInfo())) {
          setDataClassType(ct->symbol, ts->type->getField("_value")->type->symbol);
        }
      }
    }
  }
}

static Type*
getWrapRecordBaseType(Type* type) {
  if (isRecordWrappedType(type)) {
    return type->getField("_value")->type;
  } else if (type->symbol->hasFlag(FLAG_REF)) {
    Type* vt = type->getValType();
    if (isRecordWrappedType(vt)) {
      return vt->getField("_value")->type->refType;
    }
  }
  return NULL;
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtBluetooth module 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 <QtTest/QtTest>
#include <QUuid>

#include <QDebug>

#include <qbluetoothdeviceinfo.h>
#include <qbluetoothserviceinfo.h>
#include <qbluetoothaddress.h>
#include <qbluetoothlocaldevice.h>
#include <qbluetoothuuid.h>

QTBLUETOOTH_USE_NAMESPACE

Q_DECLARE_METATYPE(QBluetoothUuid::ProtocolUuid)
Q_DECLARE_METATYPE(QUuid)
Q_DECLARE_METATYPE(QBluetoothServiceInfo::Protocol)

class tst_QBluetoothServiceInfo : public QObject
{
    Q_OBJECT

public:
    tst_QBluetoothServiceInfo();
    ~tst_QBluetoothServiceInfo();

private slots:
    void initTestCase();

    void tst_construction();

    void tst_assignment_data();
    void tst_assignment();
};

tst_QBluetoothServiceInfo::tst_QBluetoothServiceInfo()
{
}

tst_QBluetoothServiceInfo::~tst_QBluetoothServiceInfo()
{
}

void tst_QBluetoothServiceInfo::initTestCase()
{
    qRegisterMetaType<QBluetoothUuid::ProtocolUuid>("QBluetoothUuid::ProtocolUuid");
    qRegisterMetaType<QUuid>("QUuid");
    qRegisterMetaType<QBluetoothServiceInfo::Protocol>("QBluetoothServiceInfo::Protocol");
    // start Bluetooth if not started
    QBluetoothLocalDevice *device = new QBluetoothLocalDevice();
    device->powerOn();
    delete device;
}

void tst_QBluetoothServiceInfo::tst_construction()
{
    const QString serviceName("My Service");
    const QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("001122334455"), "Test Device", 0);

    {
        QBluetoothServiceInfo serviceInfo;

        QVERIFY(!serviceInfo.isValid());
        QVERIFY(!serviceInfo.isComplete());
    }

    {
        QBluetoothServiceInfo serviceInfo;
        serviceInfo.setServiceName(serviceName);
        serviceInfo.setDevice(deviceInfo);

        QVERIFY(serviceInfo.isValid());

        QCOMPARE(serviceInfo.serviceName(), serviceName);
        QCOMPARE(serviceInfo.device().address(), deviceInfo.address());

        QBluetoothServiceInfo copyInfo(serviceInfo);

        QVERIFY(copyInfo.isValid());

        QCOMPARE(copyInfo.serviceName(), serviceName);
        QCOMPARE(copyInfo.device().address(), deviceInfo.address());
    }
}

void tst_QBluetoothServiceInfo::tst_assignment_data()
{
    QTest::addColumn<QUuid>("uuid");
    QTest::addColumn<QBluetoothUuid::ProtocolUuid>("protocolUuid");
    QTest::addColumn<QBluetoothServiceInfo::Protocol>("serviceInfoProtocol");

    QTest::newRow("assignment_data")
        << QUuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee)
        << QBluetoothUuid::L2cap << QBluetoothServiceInfo::L2capProtocol;
}

void tst_QBluetoothServiceInfo::tst_assignment()
{
    QFETCH(QUuid, uuid);
    QFETCH(QBluetoothUuid::ProtocolUuid, protocolUuid);
    QFETCH(QBluetoothServiceInfo::Protocol, serviceInfoProtocol);

    const QString serviceName("My Service");
    const QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("001122334455"), "Test Device", 0);

    QBluetoothServiceInfo serviceInfo;
    serviceInfo.setServiceName(serviceName);
    serviceInfo.setDevice(deviceInfo);

    QVERIFY(serviceInfo.isValid());

    {
        QBluetoothServiceInfo copyInfo = serviceInfo;

        QVERIFY(copyInfo.isValid());

        QCOMPARE(copyInfo.serviceName(), serviceName);
        QCOMPARE(copyInfo.device().address(), deviceInfo.address());
    }

    {
        QBluetoothServiceInfo copyInfo;

        QVERIFY(!copyInfo.isValid());

        copyInfo = serviceInfo;

        QVERIFY(copyInfo.isValid());

        QCOMPARE(copyInfo.serviceName(), serviceName);
        QCOMPARE(copyInfo.device().address(), deviceInfo.address());
    }

    {
        QBluetoothServiceInfo copyInfo1;
        QBluetoothServiceInfo copyInfo2;

        QVERIFY(!copyInfo1.isValid());
        QVERIFY(!copyInfo2.isValid());

        copyInfo1 = copyInfo2 = serviceInfo;

        QVERIFY(copyInfo1.isValid());
        QVERIFY(copyInfo2.isValid());

        QCOMPARE(copyInfo1.serviceName(), serviceName);
        QCOMPARE(copyInfo2.serviceName(), serviceName);
        QCOMPARE(copyInfo1.device().address(), deviceInfo.address());
        QCOMPARE(copyInfo2.device().address(), deviceInfo.address());
    }

    {
        QBluetoothServiceInfo copyInfo;
        QVERIFY(!copyInfo.isValid());
        copyInfo = serviceInfo;

        copyInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, uuid);
        QVERIFY(copyInfo.contains(QBluetoothServiceInfo::ProtocolDescriptorList));
        QVERIFY(copyInfo.isComplete());
        QVERIFY(copyInfo.attributes().count() > 0);

        copyInfo.removeAttribute(QBluetoothServiceInfo::ProtocolDescriptorList);
        QVERIFY(!copyInfo.contains(QBluetoothServiceInfo::ProtocolDescriptorList));
        QVERIFY(!copyInfo.isComplete());
    }

    {
        QBluetoothServiceInfo copyInfo;
        QVERIFY(!copyInfo.isValid());
        copyInfo = serviceInfo;

        QVERIFY(copyInfo.serverChannel() == -1);
        QVERIFY(copyInfo.protocolServiceMultiplexer() == -1);

        QBluetoothServiceInfo::Sequence protocolDescriptorList;
        QBluetoothServiceInfo::Sequence protocol;
        protocol << QVariant::fromValue(QBluetoothUuid(protocolUuid));
        protocolDescriptorList.append(QVariant::fromValue(protocol));
        protocol.clear();

        protocolDescriptorList.append(QVariant::fromValue(protocol));
        copyInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
                                 protocolDescriptorList);
        QVERIFY(copyInfo.serverChannel() == -1);
        QVERIFY(copyInfo.protocolServiceMultiplexer() != -1);
        QVERIFY(copyInfo.socketProtocol() == serviceInfoProtocol);
    }

    {
        QBluetoothServiceInfo copyInfo;
        QVERIFY(!copyInfo.isValid());
        copyInfo = serviceInfo;
        QVERIFY(!copyInfo.isRegistered());

        if (!QBluetoothLocalDevice::allDevices().count()) {
            QSKIP("Skipping test due to missing Bluetooth device");
        } else {
            QVERIFY(copyInfo.registerService());
            QVERIFY(copyInfo.isRegistered());

            QVERIFY(copyInfo.unregisterService());
            QVERIFY(!copyInfo.isRegistered());
        }
    }
}

QTEST_MAIN(tst_QBluetoothServiceInfo)

#include "tst_qbluetoothserviceinfo.moc"
<commit_msg>Modify setAttribute parameter, it no longer accepts QUuid.<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtBluetooth module 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 <QtTest/QtTest>
#include <QUuid>

#include <QDebug>

#include <qbluetoothdeviceinfo.h>
#include <qbluetoothserviceinfo.h>
#include <qbluetoothaddress.h>
#include <qbluetoothlocaldevice.h>
#include <qbluetoothuuid.h>

QTBLUETOOTH_USE_NAMESPACE

Q_DECLARE_METATYPE(QBluetoothUuid::ProtocolUuid)
Q_DECLARE_METATYPE(QUuid)
Q_DECLARE_METATYPE(QBluetoothServiceInfo::Protocol)

class tst_QBluetoothServiceInfo : public QObject
{
    Q_OBJECT

public:
    tst_QBluetoothServiceInfo();
    ~tst_QBluetoothServiceInfo();

private slots:
    void initTestCase();

    void tst_construction();

    void tst_assignment_data();
    void tst_assignment();
};

tst_QBluetoothServiceInfo::tst_QBluetoothServiceInfo()
{
}

tst_QBluetoothServiceInfo::~tst_QBluetoothServiceInfo()
{
}

void tst_QBluetoothServiceInfo::initTestCase()
{
    qRegisterMetaType<QBluetoothUuid::ProtocolUuid>("QBluetoothUuid::ProtocolUuid");
    qRegisterMetaType<QUuid>("QUuid");
    qRegisterMetaType<QBluetoothServiceInfo::Protocol>("QBluetoothServiceInfo::Protocol");
    // start Bluetooth if not started
    QBluetoothLocalDevice *device = new QBluetoothLocalDevice();
    device->powerOn();
    delete device;
}

void tst_QBluetoothServiceInfo::tst_construction()
{
    const QString serviceName("My Service");
    const QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("001122334455"), "Test Device", 0);

    {
        QBluetoothServiceInfo serviceInfo;

        QVERIFY(!serviceInfo.isValid());
        QVERIFY(!serviceInfo.isComplete());
    }

    {
        QBluetoothServiceInfo serviceInfo;
        serviceInfo.setServiceName(serviceName);
        serviceInfo.setDevice(deviceInfo);

        QVERIFY(serviceInfo.isValid());

        QCOMPARE(serviceInfo.serviceName(), serviceName);
        QCOMPARE(serviceInfo.device().address(), deviceInfo.address());

        QBluetoothServiceInfo copyInfo(serviceInfo);

        QVERIFY(copyInfo.isValid());

        QCOMPARE(copyInfo.serviceName(), serviceName);
        QCOMPARE(copyInfo.device().address(), deviceInfo.address());
    }
}

void tst_QBluetoothServiceInfo::tst_assignment_data()
{
    QTest::addColumn<QUuid>("uuid");
    QTest::addColumn<QBluetoothUuid::ProtocolUuid>("protocolUuid");
    QTest::addColumn<QBluetoothServiceInfo::Protocol>("serviceInfoProtocol");

    QTest::newRow("assignment_data")
        << QUuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee)
        << QBluetoothUuid::L2cap << QBluetoothServiceInfo::L2capProtocol;
}

void tst_QBluetoothServiceInfo::tst_assignment()
{
    QFETCH(QUuid, uuid);
    QFETCH(QBluetoothUuid::ProtocolUuid, protocolUuid);
    QFETCH(QBluetoothServiceInfo::Protocol, serviceInfoProtocol);

    const QString serviceName("My Service");
    const QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("001122334455"), "Test Device", 0);

    QBluetoothServiceInfo serviceInfo;
    serviceInfo.setServiceName(serviceName);
    serviceInfo.setDevice(deviceInfo);

    QVERIFY(serviceInfo.isValid());

    {
        QBluetoothServiceInfo copyInfo = serviceInfo;

        QVERIFY(copyInfo.isValid());

        QCOMPARE(copyInfo.serviceName(), serviceName);
        QCOMPARE(copyInfo.device().address(), deviceInfo.address());
    }

    {
        QBluetoothServiceInfo copyInfo;

        QVERIFY(!copyInfo.isValid());

        copyInfo = serviceInfo;

        QVERIFY(copyInfo.isValid());

        QCOMPARE(copyInfo.serviceName(), serviceName);
        QCOMPARE(copyInfo.device().address(), deviceInfo.address());
    }

    {
        QBluetoothServiceInfo copyInfo1;
        QBluetoothServiceInfo copyInfo2;

        QVERIFY(!copyInfo1.isValid());
        QVERIFY(!copyInfo2.isValid());

        copyInfo1 = copyInfo2 = serviceInfo;

        QVERIFY(copyInfo1.isValid());
        QVERIFY(copyInfo2.isValid());

        QCOMPARE(copyInfo1.serviceName(), serviceName);
        QCOMPARE(copyInfo2.serviceName(), serviceName);
        QCOMPARE(copyInfo1.device().address(), deviceInfo.address());
        QCOMPARE(copyInfo2.device().address(), deviceInfo.address());
    }

    {
        QBluetoothServiceInfo copyInfo;
        QVERIFY(!copyInfo.isValid());
        copyInfo = serviceInfo;

        copyInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, QBluetoothUuid(uuid));
        QVERIFY(copyInfo.contains(QBluetoothServiceInfo::ProtocolDescriptorList));
        QVERIFY(copyInfo.isComplete());
        QVERIFY(copyInfo.attributes().count() > 0);

        copyInfo.removeAttribute(QBluetoothServiceInfo::ProtocolDescriptorList);
        QVERIFY(!copyInfo.contains(QBluetoothServiceInfo::ProtocolDescriptorList));
        QVERIFY(!copyInfo.isComplete());
    }

    {
        QBluetoothServiceInfo copyInfo;
        QVERIFY(!copyInfo.isValid());
        copyInfo = serviceInfo;

        QVERIFY(copyInfo.serverChannel() == -1);
        QVERIFY(copyInfo.protocolServiceMultiplexer() == -1);

        QBluetoothServiceInfo::Sequence protocolDescriptorList;
        QBluetoothServiceInfo::Sequence protocol;
        protocol << QVariant::fromValue(QBluetoothUuid(protocolUuid));
        protocolDescriptorList.append(QVariant::fromValue(protocol));
        protocol.clear();

        protocolDescriptorList.append(QVariant::fromValue(protocol));
        copyInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
                                 protocolDescriptorList);
        QVERIFY(copyInfo.serverChannel() == -1);
        QVERIFY(copyInfo.protocolServiceMultiplexer() != -1);
        QVERIFY(copyInfo.socketProtocol() == serviceInfoProtocol);
    }

    {
        QBluetoothServiceInfo copyInfo;
        QVERIFY(!copyInfo.isValid());
        copyInfo = serviceInfo;
        QVERIFY(!copyInfo.isRegistered());

        if (!QBluetoothLocalDevice::allDevices().count()) {
            QSKIP("Skipping test due to missing Bluetooth device");
        } else {
            QVERIFY(copyInfo.registerService());
            QVERIFY(copyInfo.isRegistered());

            QVERIFY(copyInfo.unregisterService());
            QVERIFY(!copyInfo.isRegistered());
        }
    }
}

QTEST_MAIN(tst_QBluetoothServiceInfo)

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


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <thrift/lib/cpp2/transport/http2/common/HTTP2RoutingHandler.h>

#include <limits>

#include <folly/portability/GFlags.h>

#include <proxygen/httpserver/HTTPServerOptions.h>
#include <proxygen/lib/http/codec/HTTP2Codec.h>
#include <proxygen/lib/http/session/HTTPDownstreamSession.h>
#include <proxygen/lib/http/session/HTTPSession.h>
#include <proxygen/lib/http/session/SimpleController.h>
#include <thrift/lib/cpp2/transport/http2/server/ThriftRequestHandler.h>
#include <wangle/acceptor/ManagedConnection.h>

DEFINE_uint32(stream_timeout_ms, 1000, "Stream timeout in milliseconds");

namespace {
const uint32_t kMaxConcurrentIncomingStreams = 100000;
// Determined experimentally
const uint32_t kMaxReadBufferSize = 7800;
} // namespace

namespace apache {
namespace thrift {

using std::chrono::milliseconds;

namespace {
// Class for managing lifetime of objects supporting an HTTP2 session.
class HTTP2RoutingSessionManager : public proxygen::HTTPSession::InfoCallback,
                                   public proxygen::SimpleController {
 public:
  explicit HTTP2RoutingSessionManager(ThriftProcessor* processor)
      : proxygen::HTTPSession::InfoCallback(),
        proxygen::SimpleController(/*acceptor=*/nullptr),
        processor_(processor) {}

  ~HTTP2RoutingSessionManager() override = default;

  proxygen::HTTPDownstreamSession* createSession(
      folly::AsyncTransportWrapper::UniquePtr sock,
      folly::SocketAddress* peerAddress,
      std::unique_ptr<proxygen::HTTP2Codec> h2codec,
      wangle::TransportInfo const& tinfo) {
    // Obtain the proper routing address
    folly::SocketAddress localAddress;
    try {
      sock->getLocalAddress(&localAddress);
    } catch (...) {
      VLOG(3) << "couldn't get local address for socket";
      localAddress = folly::SocketAddress("0.0.0.0", 0);
    }
    VLOG(4) << "Created new session for peer " << *peerAddress;

    // Create the DownstreamSession.  Note that "this" occurs twice
    // because it acts as both a controller as well as a info
    // callback.
    auto session = new proxygen::HTTPDownstreamSession(
        proxygen::WheelTimerInstance(milliseconds(FLAGS_stream_timeout_ms)),
        std::move(sock),
        localAddress,
        *peerAddress,
        this,
        std::move(h2codec),
        tinfo,
        this);

    return session;
  }

  // We do not override onDestroy() to self destroy because this object
  // doubles as both the InfoCallback and the SimpleController.  The
  // session destructor calls onDestroy() first and then detachSession()
  // so we self destroy at detachSession().

  // begin SimpleController methods
  proxygen::HTTPTransactionHandler* getRequestHandler(
      proxygen::HTTPTransaction& txn,
      proxygen::HTTPMessage* msg) override {
    folly::SocketAddress clientAddr, vipAddr;
    txn.getPeerAddress(clientAddr);
    txn.getLocalAddress(vipAddr);
    msg->setClientAddress(clientAddr);
    msg->setDstAddress(vipAddr);

    return new ThriftRequestHandler(processor_);
  }

  void detachSession(const proxygen::HTTPSessionBase*) override {
    VLOG(4) << "HTTP2RoutingSessionManager::detachSession";
    // Session destroyed, so self destroy.
    delete this;
  }

  // end SimpleController methods

 private:
  ThriftProcessor* processor_;
};

} // anonymous namespace

void HTTP2RoutingHandler::stopListening() {
  listening_ = false;
}

bool HTTP2RoutingHandler::canAcceptConnection(
    const std::vector<uint8_t>& bytes) {
  return listening_ &&
      /*
       * HTTP/2.0 requests start with the following sequence:
       *   Octal: 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
       *  String: "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
       *
       * For more, see: https://tools.ietf.org/html/rfc7540#section-3.5
       */
      ((bytes[0] == 0x50 && bytes[1] == 0x52 && bytes[2] == 0x49) ||

       // TODO: this is not valid HTTP/2, accepting a connection like this
       // Will just result in an error

       /*
        * HTTP requests start with the following sequence:
        *   Octal: "0x485454502f..."
        *  String: "HTTP/X.X"
        *
        * For more, see: https://tools.ietf.org/html/rfc2616#section-3
        */
       (bytes[0] == 0x48 && bytes[1] == 0x54 && bytes[2] == 0x54));
}

bool HTTP2RoutingHandler::canAcceptEncryptedConnection(
    const std::string& protocolName) {
  return listening_ && (protocolName == "h2" || protocolName == "http");
}

void HTTP2RoutingHandler::handleConnection(
    wangle::ConnectionManager* connectionManager,
    folly::AsyncTransportWrapper::UniquePtr sock,
    folly::SocketAddress const* peerAddress,
    wangle::TransportInfo const& tinfo,
    std::shared_ptr<Cpp2Worker>) {
  // Create the DownstreamSession manager.
  auto sessionManager = new HTTP2RoutingSessionManager(processor_);
  // Create the DownstreamSession
  // A const_cast is needed to match wangle and proxygen APIs
  auto h2codec = std::make_unique<proxygen::HTTP2Codec>(
    proxygen::TransportDirection::DOWNSTREAM);
  h2codec->setAddDateHeaderToResponse(false);
  auto session = sessionManager->createSession(
      std::move(sock),
      const_cast<folly::SocketAddress*>(peerAddress),
      std::move(h2codec),
      tinfo);
  session->setMaxReadBufferSize(kMaxReadBufferSize);
  session->setByteEventTracker(nullptr);
  // TODO: Improve the way max incoming streams is set
  // HTTPServerOptions::maxConcurrentIncomingStreams is one option
  session->setMaxConcurrentIncomingStreams(kMaxConcurrentIncomingStreams);

  // Set flow control parameters.
  session->setFlowControl(
      options_->initialReceiveWindow,
      options_->receiveStreamWindowSize,
      options_->receiveSessionWindowSize);
  // ThriftRequestHandler ignores egress pause/resume events, so no need to
  // limit the session write buffer
  session->setWriteBufferLimit(std::numeric_limits<uint32_t>::max());

  // Route the connection.
  connectionManager->addConnection(session);
  session->startNow();

  auto observer = serverConfigs_.getObserver();
  if (observer) {
    observer->connAccepted();
    observer->activeConnections(
        connectionManager->getNumConnections() *
        serverConfigs_.getNumIOWorkerThreads());
  }
}

} // namespace thrift
} // namespace apache
<commit_msg>Re-enable H2 priority<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <thrift/lib/cpp2/transport/http2/common/HTTP2RoutingHandler.h>

#include <limits>

#include <folly/portability/GFlags.h>

#include <proxygen/httpserver/HTTPServerOptions.h>
#include <proxygen/lib/http/codec/HTTP2Codec.h>
#include <proxygen/lib/http/session/HTTPDownstreamSession.h>
#include <proxygen/lib/http/session/HTTPSession.h>
#include <proxygen/lib/http/session/SimpleController.h>
#include <thrift/lib/cpp2/transport/http2/server/ThriftRequestHandler.h>
#include <wangle/acceptor/ManagedConnection.h>

DEFINE_uint32(stream_timeout_ms, 1000, "Stream timeout in milliseconds");

namespace {
const uint32_t kMaxConcurrentIncomingStreams = 100000;
// Determined experimentally
const uint32_t kMaxReadBufferSize = 7800;
} // namespace

namespace apache {
namespace thrift {

using std::chrono::milliseconds;

namespace {
// Class for managing lifetime of objects supporting an HTTP2 session.
class HTTP2RoutingSessionManager : public proxygen::HTTPSession::InfoCallback,
                                   public proxygen::SimpleController {
 public:
  explicit HTTP2RoutingSessionManager(ThriftProcessor* processor)
      : proxygen::HTTPSession::InfoCallback(),
        proxygen::SimpleController(/*acceptor=*/nullptr),
        processor_(processor) {}

  ~HTTP2RoutingSessionManager() override = default;

  proxygen::HTTPDownstreamSession* createSession(
      folly::AsyncTransportWrapper::UniquePtr sock,
      folly::SocketAddress* peerAddress,
      std::unique_ptr<proxygen::HTTP2Codec> h2codec,
      wangle::TransportInfo const& tinfo) {
    // Obtain the proper routing address
    folly::SocketAddress localAddress;
    try {
      sock->getLocalAddress(&localAddress);
    } catch (...) {
      VLOG(3) << "couldn't get local address for socket";
      localAddress = folly::SocketAddress("0.0.0.0", 0);
    }
    VLOG(4) << "Created new session for peer " << *peerAddress;

    // Create the DownstreamSession.  Note that "this" occurs twice
    // because it acts as both a controller as well as a info
    // callback.
    auto session = new proxygen::HTTPDownstreamSession(
        proxygen::WheelTimerInstance(milliseconds(FLAGS_stream_timeout_ms)),
        std::move(sock),
        localAddress,
        *peerAddress,
        this,
        std::move(h2codec),
        tinfo,
        this);

    return session;
  }

  // We do not override onDestroy() to self destroy because this object
  // doubles as both the InfoCallback and the SimpleController.  The
  // session destructor calls onDestroy() first and then detachSession()
  // so we self destroy at detachSession().

  // begin SimpleController methods
  proxygen::HTTPTransactionHandler* getRequestHandler(
      proxygen::HTTPTransaction& txn,
      proxygen::HTTPMessage* msg) override {
    folly::SocketAddress clientAddr, vipAddr;
    txn.getPeerAddress(clientAddr);
    txn.getLocalAddress(vipAddr);
    msg->setClientAddress(clientAddr);
    msg->setDstAddress(vipAddr);

    return new ThriftRequestHandler(processor_);
  }

  void detachSession(const proxygen::HTTPSessionBase*) override {
    VLOG(4) << "HTTP2RoutingSessionManager::detachSession";
    // Session destroyed, so self destroy.
    delete this;
  }

  // end SimpleController methods

 private:
  ThriftProcessor* processor_;
};

} // anonymous namespace

void HTTP2RoutingHandler::stopListening() {
  listening_ = false;
}

bool HTTP2RoutingHandler::canAcceptConnection(
    const std::vector<uint8_t>& bytes) {
  return listening_ &&
      /*
       * HTTP/2.0 requests start with the following sequence:
       *   Octal: 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
       *  String: "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
       *
       * For more, see: https://tools.ietf.org/html/rfc7540#section-3.5
       */
      ((bytes[0] == 0x50 && bytes[1] == 0x52 && bytes[2] == 0x49) ||

       // TODO: this is not valid HTTP/2, accepting a connection like this
       // Will just result in an error

       /*
        * HTTP requests start with the following sequence:
        *   Octal: "0x485454502f..."
        *  String: "HTTP/X.X"
        *
        * For more, see: https://tools.ietf.org/html/rfc2616#section-3
        */
       (bytes[0] == 0x48 && bytes[1] == 0x54 && bytes[2] == 0x54));
}

bool HTTP2RoutingHandler::canAcceptEncryptedConnection(
    const std::string& protocolName) {
  return listening_ && (protocolName == "h2" || protocolName == "http");
}

void HTTP2RoutingHandler::handleConnection(
    wangle::ConnectionManager* connectionManager,
    folly::AsyncTransportWrapper::UniquePtr sock,
    folly::SocketAddress const* peerAddress,
    wangle::TransportInfo const& tinfo,
    std::shared_ptr<Cpp2Worker>) {
  // Create the DownstreamSession manager.
  auto sessionManager = new HTTP2RoutingSessionManager(processor_);
  // Create the DownstreamSession
  // A const_cast is needed to match wangle and proxygen APIs
  auto h2codec = std::make_unique<proxygen::HTTP2Codec>(
    proxygen::TransportDirection::DOWNSTREAM);
  h2codec->setAddDateHeaderToResponse(false);
  auto session = sessionManager->createSession(
      std::move(sock),
      const_cast<folly::SocketAddress*>(peerAddress),
      std::move(h2codec),
      tinfo);
  session->setMaxReadBufferSize(kMaxReadBufferSize);
  session->setByteEventTracker(nullptr);
  // Enable HTTP/2 priorities
  session->setHTTP2PrioritiesEnabled(true);
  // TODO: Improve the way max incoming streams is set
  // HTTPServerOptions::maxConcurrentIncomingStreams is one option
  session->setMaxConcurrentIncomingStreams(kMaxConcurrentIncomingStreams);

  // Set flow control parameters.
  session->setFlowControl(
      options_->initialReceiveWindow,
      options_->receiveStreamWindowSize,
      options_->receiveSessionWindowSize);
  // ThriftRequestHandler ignores egress pause/resume events, so no need to
  // limit the session write buffer
  session->setWriteBufferLimit(std::numeric_limits<uint32_t>::max());

  // Route the connection.
  connectionManager->addConnection(session);
  session->startNow();

  auto observer = serverConfigs_.getObserver();
  if (observer) {
    observer->connAccepted();
    observer->activeConnections(
        connectionManager->getNumConnections() *
        serverConfigs_.getNumIOWorkerThreads());
  }
}

} // namespace thrift
} // namespace apache
<|endoftext|>


<commit_before>#include <sirius.h>

double test_alltoall(int num_gkvec, int num_bands)
{
    Communicator comm(MPI_COMM_WORLD);

    splindex<block> spl_gkvec(num_gkvec, comm.size(), comm.rank());
    splindex<block> spl_bands(num_bands, comm.size(), comm.rank());

    matrix<double_complex> a(spl_gkvec.local_size(), num_bands);
    matrix<double_complex> b(num_gkvec, spl_bands.local_size());

    for (int i = 0; i < num_bands; i++)
    {
        for (int j = 0; j < (int)spl_gkvec.local_size(); j++) a(j, i) = type_wrapper<double_complex>::random();
    }
    b.zero();

    auto h = a.hash();

    std::vector<int> sendcounts(comm.size());
    std::vector<int> sdispls(comm.size());
    std::vector<int> recvcounts(comm.size());
    std::vector<int> rdispls(comm.size());

    sdispls[0] = 0;
    rdispls[0] = 0;
    for (int rank = 0; rank < comm.size(); rank++)
    {
        sendcounts[rank] = int(spl_gkvec.local_size() * spl_bands.local_size(rank));
        if (rank) sdispls[rank] = sdispls[rank - 1] + sendcounts[rank - 1];

        recvcounts[rank] = int(spl_gkvec.local_size(rank) * spl_bands.local_size());
        if (rank) rdispls[rank] = rdispls[rank - 1] + recvcounts[rank - 1];
    }

    sirius::Timer t("alltoall", comm);
    comm.alltoall(&a(0, 0), &sendcounts[0], &sdispls[0], &b(0, 0), &recvcounts[0], &rdispls[0]);
    double tval = t.stop();

    sdispls[0] = 0;
    rdispls[0] = 0;
    for (int rank = 0; rank < comm.size(); rank++)
    {
        sendcounts[rank] = int(spl_gkvec.local_size(rank) * spl_bands.local_size());
        if (rank) sdispls[rank] = sdispls[rank - 1] + sendcounts[rank - 1];

        recvcounts[rank] = int(spl_gkvec.local_size() * spl_bands.local_size(rank));
        if (rank) rdispls[rank] = rdispls[rank - 1] + recvcounts[rank - 1];
    }

    t.start();
    comm.alltoall(&b(0, 0), &sendcounts[0], &sdispls[0], &a(0, 0), &recvcounts[0], &rdispls[0]);
    tval += t.stop();

    if (a.hash() != h) printf("wrong hash\n");

    double perf = 2 * num_gkvec * num_bands * sizeof(double_complex) / tval / (1 << 30);

    return perf;
}

void test_alltoall_v2()
{
    Communicator comm(MPI_COMM_WORLD);

    std::vector<int> counts_in(comm.size(), 16);
    std::vector<double> sbuf(16);

    std::vector<int> counts_out(comm.size(), 0);
    counts_out[0] = 16 * comm.size();

    std::vector<double> rbuf(counts_out[comm.rank()]);

    auto a2a_desc = comm.map_alltoall(counts_in, counts_out);
    comm.alltoall(&sbuf[0], &a2a_desc.sendcounts[0], &a2a_desc.sdispls[0], &rbuf[0], &a2a_desc.recvcounts[0], &a2a_desc.rdispls[0]);

    PRINT("test_alltoall_v2 done");
    comm.barrier();
}

void test_alltoall_v3()
{
    Communicator comm(MPI_COMM_WORLD);

    std::vector<int> counts_in(comm.size(), 16);
    std::vector<double_complex> sbuf(16);

    std::vector<int> counts_out(comm.size(), 0);
    if (comm.size() == 1)
    {
        counts_out[0] = 16 * comm.size();
    }
    else
    {
        counts_out[0] = 8 * comm.size();
        counts_out[1] = 8 * comm.size();
    }

    std::vector<double_complex> rbuf(counts_out[comm.rank()]);

    auto a2a_desc = comm.map_alltoall(counts_in, counts_out);
    comm.alltoall(&sbuf[0], &a2a_desc.sendcounts[0], &a2a_desc.sdispls[0], &rbuf[0], &a2a_desc.recvcounts[0], &a2a_desc.rdispls[0]);

    PRINT("test_alltoall_v3 done");
    comm.barrier();
}

int main(int argn, char **argv)
{
    cmd_args args;
    args.register_key("--num_gkvec=", "{int} number of Gk-vectors");
    args.register_key("--num_bands=", "{int} number of bands");
    args.register_key("--repeat=", "{int} repeat test number of times");

    args.parse_args(argn, argv);
    if (argn == 1)
    {
        printf("Usage: %s [options]\n", argv[0]);
        args.print_help();
        exit(0);
    }

    int num_gkvec = args.value<int>("num_gkvec");
    int num_bands = args.value<int>("num_bands");
    int repeat = args.value<int>("repeat", 1);

    Platform::initialize(true);

    std::vector<double> perf(repeat);
    double avg = 0;
    for (int i = 0; i < repeat; i++)
    {
        perf[i] = test_alltoall(num_gkvec, num_bands);
        avg += perf[i];
    }
    avg /= repeat;
    double variance = 0;
    for (int i = 0; i < repeat; i++) variance += std::pow(perf[i] - avg, 2);
    variance /= repeat;
    double sigma = std::sqrt(variance);
    if (Platform::rank() == 0)
    {
        printf("average performance: %12.4f GB/sec.\n", avg);
        printf("sigma: %12.4f GB/sec.\n", sigma);
    }

    //test_alltoall_v2();
    //test_alltoall_v3();

    Platform::finalize();
}
<commit_msg>allow groups in a2a test<commit_after>#include <sirius.h>

double test_alltoall(int num_gkvec__, int num_bands__, int num_groups__)
{
    Communicator comm_world(MPI_COMM_WORLD);

    int np = comm_world.size() / num_groups__;
    if (np * num_groups__ != comm_world.size())
    {
        TERMINATE("wrong number of MPI ranks");
    }

    int num_bands = num_bands__ / num_groups__;
    if (num_bands * num_groups__ != num_bands__)
    {
        TERMINATE("wrong number of bands");
    }

    std::vector<int> mpi_grid_dims = {np, num_groups__};
    MPI_grid* mpi_grid = new MPI_grid(mpi_grid_dims, comm_world);

    Communicator comm = mpi_grid->communicator(1 << 0);

    splindex<block> spl_gkvec(num_gkvec__, comm.size(), comm.rank());
    splindex<block> spl_bands(num_bands, comm.size(), comm.rank());

    matrix<double_complex> a(spl_gkvec.local_size(), num_bands);
    matrix<double_complex> b(num_gkvec__, spl_bands.local_size());

    for (int i = 0; i < num_bands; i++)
    {
        for (int j = 0; j < (int)spl_gkvec.local_size(); j++) a(j, i) = type_wrapper<double_complex>::random();
    }
    b.zero();

    auto h = a.hash();

    std::vector<int> sendcounts(comm.size());
    std::vector<int> sdispls(comm.size());
    std::vector<int> recvcounts(comm.size());
    std::vector<int> rdispls(comm.size());

    sdispls[0] = 0;
    rdispls[0] = 0;
    for (int rank = 0; rank < comm.size(); rank++)
    {
        sendcounts[rank] = int(spl_gkvec.local_size() * spl_bands.local_size(rank));
        if (rank) sdispls[rank] = sdispls[rank - 1] + sendcounts[rank - 1];

        recvcounts[rank] = int(spl_gkvec.local_size(rank) * spl_bands.local_size());
        if (rank) rdispls[rank] = rdispls[rank - 1] + recvcounts[rank - 1];
    }

    sirius::Timer t("alltoall", comm);
    comm.alltoall(&a(0, 0), &sendcounts[0], &sdispls[0], &b(0, 0), &recvcounts[0], &rdispls[0]);
    double tval = t.stop();

    sdispls[0] = 0;
    rdispls[0] = 0;
    for (int rank = 0; rank < comm.size(); rank++)
    {
        sendcounts[rank] = int(spl_gkvec.local_size(rank) * spl_bands.local_size());
        if (rank) sdispls[rank] = sdispls[rank - 1] + sendcounts[rank - 1];

        recvcounts[rank] = int(spl_gkvec.local_size() * spl_bands.local_size(rank));
        if (rank) rdispls[rank] = rdispls[rank - 1] + recvcounts[rank - 1];
    }

    t.start();
    comm.alltoall(&b(0, 0), &sendcounts[0], &sdispls[0], &a(0, 0), &recvcounts[0], &rdispls[0]);
    tval += t.stop();

    if (a.hash() != h) printf("wrong hash\n");

    double perf = 2 * num_gkvec__ * num_bands__ * sizeof(double_complex) / tval / (1 << 30);

    delete mpi_grid;

    return perf;
}

void test_alltoall_v2()
{
    Communicator comm(MPI_COMM_WORLD);

    std::vector<int> counts_in(comm.size(), 16);
    std::vector<double> sbuf(16);

    std::vector<int> counts_out(comm.size(), 0);
    counts_out[0] = 16 * comm.size();

    std::vector<double> rbuf(counts_out[comm.rank()]);

    auto a2a_desc = comm.map_alltoall(counts_in, counts_out);
    comm.alltoall(&sbuf[0], &a2a_desc.sendcounts[0], &a2a_desc.sdispls[0], &rbuf[0], &a2a_desc.recvcounts[0], &a2a_desc.rdispls[0]);

    PRINT("test_alltoall_v2 done");
    comm.barrier();
}

void test_alltoall_v3()
{
    Communicator comm(MPI_COMM_WORLD);

    std::vector<int> counts_in(comm.size(), 16);
    std::vector<double_complex> sbuf(16);

    std::vector<int> counts_out(comm.size(), 0);
    if (comm.size() == 1)
    {
        counts_out[0] = 16 * comm.size();
    }
    else
    {
        counts_out[0] = 8 * comm.size();
        counts_out[1] = 8 * comm.size();
    }

    std::vector<double_complex> rbuf(counts_out[comm.rank()]);

    auto a2a_desc = comm.map_alltoall(counts_in, counts_out);
    comm.alltoall(&sbuf[0], &a2a_desc.sendcounts[0], &a2a_desc.sdispls[0], &rbuf[0], &a2a_desc.recvcounts[0], &a2a_desc.rdispls[0]);

    PRINT("test_alltoall_v3 done");
    comm.barrier();
}

int main(int argn, char **argv)
{
    cmd_args args;
    args.register_key("--num_gkvec=", "{int} number of Gk-vectors");
    args.register_key("--num_bands=", "{int} number of bands");
    args.register_key("--repeat=", "{int} repeat test number of times");
    args.register_key("--num_groups=", "{int} number of MPI groups");

    args.parse_args(argn, argv);
    if (argn == 1)
    {
        printf("Usage: %s [options]\n", argv[0]);
        args.print_help();
        exit(0);
    }

    int num_gkvec = args.value<int>("num_gkvec");
    int num_bands = args.value<int>("num_bands");
    int repeat = args.value<int>("repeat", 1);
    int num_groups = args.value<int>("num_groups", 1);

    Platform::initialize(true);

    std::vector<double> perf(repeat);
    double avg = 0;
    for (int i = 0; i < repeat; i++)
    {
        perf[i] = test_alltoall(num_gkvec, num_bands, num_groups);
        avg += perf[i];
    }
    avg /= repeat;
    double variance = 0;
    for (int i = 0; i < repeat; i++) variance += std::pow(perf[i] - avg, 2);
    variance /= repeat;
    double sigma = std::sqrt(variance);
    if (Platform::rank() == 0)
    {
        printf("average performance: %12.4f GB/sec.\n", avg);
        printf("sigma: %12.4f GB/sec.\n", sigma);
    }

    //test_alltoall_v2();
    //test_alltoall_v3();

    Platform::finalize();
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2000 by W.C.A. Wijngaards
    Copyright (C) 2000 by Andrew Zabolotny

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define CS_SYSDEF_PROVIDE_PATH
#define CS_SYSDEF_PROVIDE_GETOPT
#include "cssysdef.h"
#include "cstool/initapp.h"
#include "ivideo/fontserv.h"
#include "iutil/objreg.h"
#include "iutil/eventh.h"
#include "iutil/comp.h"
#include "isys/plugin.h"

CS_IMPLEMENT_APPLICATION

static iObjectRegistry* object_reg;

char *programversion = "0.0.1";
char *programname;

static struct option long_options[] =
{
  {"first", required_argument, 0, 'f'},
  {"glyphs", required_argument, 0, 'g'},
  {"size", required_argument, 0, 's'},
  {"output", required_argument, 0, 'o'},
  {"text", no_argument, 0, 't'},
  {"display", no_argument, 0, 'd'},
  {"help", no_argument, 0, 'h'},
  {"version", no_argument, 0, 'V'},
  {"verbose", no_argument, 0, 'v'},
  {0, no_argument, 0, 0}
};

static struct
{
  bool verbose;
  bool sourcecode;
  bool display;
  int fontsize;
  int first;
  int glyphs;
  char *output;
} opt =
{
  false,
  false,
  false,
  -1,
  0,
  256,
  NULL
};

static int lastglyph;

static int display_help ()
{
  printf ("Crystal Space font conversion/generation utility v%s\n", programversion);
  printf ("Copyright (C) 2000 by W.C.A. Wijngaards and Andrew Zabolotny\n\n");
  printf ("Usage: %s {option/s} [truetype font file] [...]\n\n", programname);
  printf ("This program allows to convert TTF font files to bitmap format CSF\n");
  printf ("which is faster to load although it is non-scalable. By default the\n");
  printf ("program will convert all the fonts given on command line to CSF.\n\n");
  printf ("  -d   --display     Display font rather than converting it\n");
  printf ("  -f#  --first=#     Start conversion at glyph # (default = 0)\n");
  printf ("  -g#  --glyphs=#    Convert just # (default = 256) glyphs of the font\n");
  printf ("  -s#  --size=#      Set font size # in points\n");
  printf ("  -o#  --output=#    Output CSF font to file #\n");
  printf ("  -t   --text        Generate text output (C++ code) rather than binary\n");
  printf ("  -h   --help        Display this help text\n");
  printf ("  -v   --verbose     Comment on what's happening\n");
  printf ("  -V   --version     Display program version\n");
  return 1;
}

static bool Display (iFontServer *fs, iFont *font)
{
  int c, l, i;
  for (c = opt.first; c < lastglyph; c++)
  {
    int w, h;
    uint8 *bitmap = font->GetGlyphBitmap (c, w, h);
    if (!bitmap || !w || !h)
      continue;

    printf ("---- Character:%d\n", c);
    for (l = 0; l < h; l++)
    {
      uint8 *line = bitmap + l * ((w + 7) / 8);
      for (i = 0; i < w; i++)
        printf ("%s", (line [i / 8] & (0x80 >> (i & 7))) ? "@" : ".");
      printf ("\n");
    }
  }
  font->DecRef ();
  fs->DecRef ();
  return true;
}

static bool Convert (const char *fontfile)
{
  if (opt.verbose)
    printf ("Loading font %s, size = %d\n", fontfile, opt.fontsize);

  iPluginManager* plugin_mgr = CS_QUERY_REGISTRY (object_reg, iPluginManager);

  iFontServer *fs = CS_QUERY_PLUGIN_ID (plugin_mgr, CS_FUNCID_FONTSERVER, iFontServer);
  if (!fs)
  {
    printf ("Font server plugin has not been loaded.\n");
    return false;
  }

  iFont *font = fs->LoadFont (fontfile);
  if (font == NULL)
  {
    printf ("Cannot load font file %s\n", fontfile);
    return false;
  }

  if (opt.fontsize > 0)
  {
    font->SetSize (opt.fontsize);
    int oldsize = opt.fontsize;
    opt.fontsize = font->GetSize ();
    if (opt.fontsize != oldsize)
      printf ("Could not set font size %d, using size %d\n",
        oldsize, opt.fontsize);
  }
  else
    opt.fontsize = font->GetSize ();

  // max height of font
  int maxheight, maxwidth;
  font->GetMaxSize (maxwidth, maxheight);

  if (maxwidth > 255)
  {
    fprintf (stderr, "Font too large (%dx%d): CSF format supports only widths < 256\n", maxwidth, maxheight);
    return false;
  }

  if (opt.display)
    return Display (fs, font);

  char fontname [MAXPATHLEN + 1];
  char outfile [MAXPATHLEN + 1];
  csSplitPath (fontfile, NULL, 0, fontname, sizeof (fontname));
  if (fontname [0] == '*')
    strcpy (fontname, fontname + 1);
  char *dot = strchr (fontname, '.');
  if (dot) *dot = 0;
  sprintf (outfile, "%s%d.%s", fontname, opt.fontsize, opt.sourcecode ? "inc" : "csf");

  FILE *out = fopen (outfile, opt.sourcecode ? "w" : "wb");
  if (!out)
  {
    printf ("Could not open output file %s\n", outfile);
    return false;
  }

  int i, c, w, h;

  if (opt.sourcecode)
  {
    /// make a text version
    fprintf (out, "// %s.%d %dx%d font\n", fontname, opt.fontsize, maxwidth, maxheight);
    fprintf (out, "// FontDef: { \"%s%d\", %d, %d, %d, %d, font_%s%d, width_%s%d }\n",
      fontname, opt.fontsize, maxwidth, maxheight, opt.first, opt.glyphs,
      fontname, opt.fontsize, fontname, opt.fontsize);
    fprintf (out, "\n");
  }
  else
    fprintf (out, "CSF [Font=%s.%d Width=%d Height=%d First=%d Glyphs=%d]\n",
      fontname, opt.fontsize, maxwidth, maxheight, opt.first, opt.glyphs);

  int arrsize = 0;
  uint8 width [256];
  for (c = opt.first; c < lastglyph; c++)
  {
    uint8 *bitmap = font->GetGlyphBitmap (c, w, h);
    width [c] = (bitmap && h) ? w : 0;
    arrsize += ((width [c] + 7) / 8) * h;
  }

  // Character widths go first
  if (opt.sourcecode)
  {
    fprintf (out, "unsigned char width_%s%d [%d] =\n{\n  ",
      fontname, opt.fontsize, opt.glyphs);
    for (i = opt.first; i < lastglyph; i++)
    {
      fprintf (out, "%2d%s", width [i], (i < lastglyph - 1) ? "," : "");
      if ((i & 15) == 15)
      {
        fprintf (out, "\t// %02x..%02x\n", i - 15, i);
        if (i < lastglyph - 1)
          fprintf (out, "  ");
      }
    }
    if (opt.glyphs & 15)
      fprintf (out, "\n");
    fprintf (out, "};\n\n");
    fprintf (out, "unsigned char font_%s%d [%d] =\n{\n",
      fontname, opt.fontsize, arrsize);
  }
  else
    fwrite (width + opt.first, opt.glyphs, 1, out);

  // Output every character in turn
  for (c = opt.first; c < lastglyph; c++)
  {
    // get bitmap
    uint8 *bitmap = font->GetGlyphBitmap (c, w, h);
    if (opt.verbose)
    {
      if (!c) printf ("character ");
      printf ("%d%s", c, (c < lastglyph - 1) ? "," : "\n");
    }

    int bpc = ((width [c] + 7) / 8) * h;

    if (bitmap)
      if (opt.sourcecode)
      {
        fprintf (out, "  ");
        for (i = 0; i < bpc; i++)
          fprintf (out, "0x%02x%s", bitmap [i], (i >= bpc - 1) && (c >= lastglyph - 1) ? "" : ",");
        fprintf (out, "\t// %02x\n", c);
      }
      else if (width [c])
        fwrite (bitmap, bpc, 1, out);
  }

  fprintf (out, "};\n\n");
  fclose (out);
  font->DecRef ();
  fs->DecRef ();
  return true;
}

int main (int argc, char* argv[])
{
#if defined (__EMX__)	// Expand wildcards on OS/2+GCC+EMX
  _wildcard (&argc, &argv);
#endif

  object_reg = csInitializer::CreateEnvironment ();
  if (!object_reg) return -1;

  csInitializer::SetupCommandLineParser (object_reg, argc, argv);
  if (!csInitializer::RequestPlugins (object_reg,
  	CS_REQUEST_VFS,
	CS_REQUEST_PLUGIN ("crystalspace.font.server.freetype:FontServer", iFontServer),
	CS_REQUEST_END))
  {
    fprintf (stderr, "couldn't init app! (perhaps some plugins are missing?)");
    return -1;
  }

  if (!csInitializer::Initialize (object_reg))
  {
    fprintf (stderr, "couldn't init app! (perhaps some plugins are missing?)");
    return -1;
  }

  programname = argv [0];

  int c;
  while ((c = getopt_long (argc, argv, "f:g:s:o:tdhvV", long_options, NULL)) != EOF)
    switch (c)
    {
      case '?':
        // unknown option
        return -1;
      case 'f':
        opt.first = atoi (optarg);
        if ((opt.first < 0)
         || (opt.first > 255))
        {
          fprintf (stderr, "ERROR: first glyph should be 0..255\n");
          return -2;
        }
        break;
      case 'g':
        opt.glyphs = atoi (optarg);
        if ((opt.glyphs < 1)
         || (opt.glyphs > 256))
        {
          fprintf (stderr, "ERROR: glyph count should be 1..256\n");
          return -2;
        }
        break;
      case 's':
        opt.fontsize = atoi (optarg);
        if ((opt.fontsize < 1)
         || (opt.fontsize > 1000))
        {
          fprintf (stderr, "ERROR: font size should be 1..1000\n");
          return -2;
        }
        break;
      case 'o':
        opt.output = optarg;
        break;
      case 't':
        opt.sourcecode = true;
        break;
      case 'd':
        opt.display = true;
        break;
      case 'h':
        return display_help ();
      case 'v':
        opt.verbose = true;
        break;
      case 'V':
        printf ("%s version %s\n\n", programname, programversion);
        printf ("This program is distributed in the hope that it will be useful,\n");
        printf ("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
        printf ("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
        printf ("GNU Library General Public License for more details.\n");
        return 0;
    } /* endswitch */

  if (optind >= argc)
    return display_help ();

  lastglyph = opt.first + opt.glyphs;
  if (lastglyph > 256)
  {
    fprintf (stderr, "WARNING: Last glyph = %d, limiting to 256\n", lastglyph);
    lastglyph = 256;
    opt.glyphs = 256 - opt.first;
  }

  // Interpret the non-option arguments as file names
  for (; optind < argc; ++optind)
    if (!Convert (argv [optind]))
      return -2;

  csInitializer::DestroyApplication (object_reg);

  return 0;
}
<commit_msg>Updated to take account of Jorrits changes.<commit_after>/*
    Copyright (C) 2000 by W.C.A. Wijngaards
    Copyright (C) 2000 by Andrew Zabolotny

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define CS_SYSDEF_PROVIDE_PATH
#define CS_SYSDEF_PROVIDE_GETOPT
#include "cssysdef.h"
#include "cstool/initapp.h"
#include "csutil/util.h"
#include "ivideo/fontserv.h"
#include "iutil/objreg.h"
#include "iutil/eventh.h"
#include "iutil/comp.h"
#include "isys/plugin.h"
#include "isys/vfs.h"

CS_IMPLEMENT_APPLICATION

static iObjectRegistry* object_reg;

char *programversion = "0.0.1";
char *programname;

static struct option long_options[] =
{
  {"first", required_argument, 0, 'f'},
  {"glyphs", required_argument, 0, 'g'},
  {"size", required_argument, 0, 's'},
  {"output", required_argument, 0, 'o'},
  {"text", no_argument, 0, 't'},
  {"display", no_argument, 0, 'd'},
  {"help", no_argument, 0, 'h'},
  {"version", no_argument, 0, 'V'},
  {"verbose", no_argument, 0, 'v'},
  {0, no_argument, 0, 0}
};

static struct
{
  bool verbose;
  bool sourcecode;
  bool display;
  int fontsize;
  int first;
  int glyphs;
  char *output;
} opt =
{
  false,
  false,
  false,
  -1,
  0,
  256,
  NULL
};

static int lastglyph;

static int display_help ()
{
  printf ("Crystal Space font conversion/generation utility v%s\n", programversion);
  printf ("Copyright (C) 2000 by W.C.A. Wijngaards and Andrew Zabolotny\n\n");
  printf ("Usage: %s {option/s} [truetype font file] [...]\n\n", programname);
  printf ("This program allows to convert TTF font files to bitmap format CSF\n");
  printf ("which is faster to load although it is non-scalable. By default the\n");
  printf ("program will convert all the fonts given on command line to CSF.\n\n");
  printf ("  -d   --display     Display font rather than converting it\n");
  printf ("  -f#  --first=#     Start conversion at glyph # (default = 0)\n");
  printf ("  -g#  --glyphs=#    Convert just # (default = 256) glyphs of the font\n");
  printf ("  -s#  --size=#      Set font size # in points\n");
  printf ("  -o#  --output=#    Output CSF font to file #\n");
  printf ("  -t   --text        Generate text output (C++ code) rather than binary\n");
  printf ("  -h   --help        Display this help text\n");
  printf ("  -v   --verbose     Comment on what's happening\n");
  printf ("  -V   --version     Display program version\n");
  return 1;
}

static bool Display (iFontServer *fs, iFont *font)
{
  int c, l, i;
  for (c = opt.first; c < lastglyph; c++)
  {
    int w, h;
    uint8 *bitmap = font->GetGlyphBitmap (c, w, h);
    if (!bitmap || !w || !h)
      continue;

    printf ("---- Character:%d\n", c);
    for (l = 0; l < h; l++)
    {
      uint8 *line = bitmap + l * ((w + 7) / 8);
      for (i = 0; i < w; i++)
        printf ("%s", (line [i / 8] & (0x80 >> (i & 7))) ? "@" : ".");
      printf ("\n");
    }
  }
  font->DecRef ();
  fs->DecRef ();
  return true;
}

static bool Convert (const char *fontfile)
{
  if (opt.verbose)
    printf ("Loading font %s, size = %d\n", fontfile, opt.fontsize);

  iPluginManager* plugin_mgr = CS_QUERY_REGISTRY (object_reg, iPluginManager);

  iFontServer *fs = CS_QUERY_PLUGIN_ID (plugin_mgr, CS_FUNCID_FONTSERVER, iFontServer);
  if (!fs)
  {
    printf ("Font server plugin has not been loaded.\n");
    return false;
  }

  iFont *font = fs->LoadFont (fontfile);
  if (font == NULL)
  {
    printf ("Cannot load font file %s\n", fontfile);
    return false;
  }

  if (opt.fontsize > 0)
  {
    font->SetSize (opt.fontsize);
    int oldsize = opt.fontsize;
    opt.fontsize = font->GetSize ();
    if (opt.fontsize != oldsize)
      printf ("Could not set font size %d, using size %d\n",
        oldsize, opt.fontsize);
  }
  else
    opt.fontsize = font->GetSize ();

  // max height of font
  int maxheight, maxwidth;
  font->GetMaxSize (maxwidth, maxheight);

  if (maxwidth > 255)
  {
    fprintf (stderr, "Font too large (%dx%d): CSF format supports only widths < 256\n", maxwidth, maxheight);
    return false;
  }

  if (opt.display)
    return Display (fs, font);

  char fontname [MAXPATHLEN + 1];
  char outfile [MAXPATHLEN + 1];
  csSplitPath (fontfile, NULL, 0, fontname, sizeof (fontname));
  if (fontname [0] == '*')
    strcpy (fontname, fontname + 1);
  char *dot = strchr (fontname, '.');
  if (dot) *dot = 0;
  sprintf (outfile, "%s%d.%s", fontname, opt.fontsize, opt.sourcecode ? "inc" : "csf");

  FILE *out = fopen (outfile, opt.sourcecode ? "w" : "wb");
  if (!out)
  {
    printf ("Could not open output file %s\n", outfile);
    return false;
  }

  int i, c, w, h;

  if (opt.sourcecode)
  {
    /// make a text version
    fprintf (out, "// %s.%d %dx%d font\n", fontname, opt.fontsize, maxwidth, maxheight);
    fprintf (out, "// FontDef: { \"%s%d\", %d, %d, %d, %d, font_%s%d, width_%s%d }\n",
      fontname, opt.fontsize, maxwidth, maxheight, opt.first, opt.glyphs,
      fontname, opt.fontsize, fontname, opt.fontsize);
    fprintf (out, "\n");
  }
  else
    fprintf (out, "CSF [Font=%s.%d Width=%d Height=%d First=%d Glyphs=%d]\n",
      fontname, opt.fontsize, maxwidth, maxheight, opt.first, opt.glyphs);

  int arrsize = 0;
  uint8 width [256];
  for (c = opt.first; c < lastglyph; c++)
  {
    uint8 *bitmap = font->GetGlyphBitmap (c, w, h);
    width [c] = (bitmap && h) ? w : 0;
    arrsize += ((width [c] + 7) / 8) * h;
  }

  // Character widths go first
  if (opt.sourcecode)
  {
    fprintf (out, "unsigned char width_%s%d [%d] =\n{\n  ",
      fontname, opt.fontsize, opt.glyphs);
    for (i = opt.first; i < lastglyph; i++)
    {
      fprintf (out, "%2d%s", width [i], (i < lastglyph - 1) ? "," : "");
      if ((i & 15) == 15)
      {
        fprintf (out, "\t// %02x..%02x\n", i - 15, i);
        if (i < lastglyph - 1)
          fprintf (out, "  ");
      }
    }
    if (opt.glyphs & 15)
      fprintf (out, "\n");
    fprintf (out, "};\n\n");
    fprintf (out, "unsigned char font_%s%d [%d] =\n{\n",
      fontname, opt.fontsize, arrsize);
  }
  else
    fwrite (width + opt.first, opt.glyphs, 1, out);

  // Output every character in turn
  for (c = opt.first; c < lastglyph; c++)
  {
    // get bitmap
    uint8 *bitmap = font->GetGlyphBitmap (c, w, h);
    if (opt.verbose)
    {
      if (!c) printf ("character ");
      printf ("%d%s", c, (c < lastglyph - 1) ? "," : "\n");
    }

    int bpc = ((width [c] + 7) / 8) * h;

    if (bitmap)
      if (opt.sourcecode)
      {
        fprintf (out, "  ");
        for (i = 0; i < bpc; i++)
          fprintf (out, "0x%02x%s", bitmap [i], (i >= bpc - 1) && (c >= lastglyph - 1) ? "" : ",");
        fprintf (out, "\t// %02x\n", c);
      }
      else if (width [c])
        fwrite (bitmap, bpc, 1, out);
  }

  fprintf (out, "};\n\n");
  fclose (out);
  font->DecRef ();
  fs->DecRef ();
  return true;
}

int main (int argc, char* argv[])
{
#if defined (__EMX__)	// Expand wildcards on OS/2+GCC+EMX
  _wildcard (&argc, &argv);
#endif

  object_reg = csInitializer::CreateEnvironment ();
  if (!object_reg) return -1;

  csInitializer::SetupCommandLineParser (object_reg, argc, argv);
  if (!csInitializer::RequestPlugins (object_reg,
  	CS_REQUEST_VFS,
	CS_REQUEST_PLUGIN ("crystalspace.font.server.freetype:FontServer", iFontServer),
	CS_REQUEST_END))
  {
    fprintf (stderr, "couldn't init app! (perhaps some plugins are missing?)");
    return -1;
  }

  if (!csInitializer::Initialize (object_reg))
  {
    fprintf (stderr, "couldn't init app! (perhaps some plugins are missing?)");
    return -1;
  }

  programname = argv [0];

  int c;
  while ((c = getopt_long (argc, argv, "f:g:s:o:tdhvV", long_options, NULL)) != EOF)
    switch (c)
    {
      case '?':
        // unknown option
        return -1;
      case 'f':
        opt.first = atoi (optarg);
        if ((opt.first < 0)
         || (opt.first > 255))
        {
          fprintf (stderr, "ERROR: first glyph should be 0..255\n");
          return -2;
        }
        break;
      case 'g':
        opt.glyphs = atoi (optarg);
        if ((opt.glyphs < 1)
         || (opt.glyphs > 256))
        {
          fprintf (stderr, "ERROR: glyph count should be 1..256\n");
          return -2;
        }
        break;
      case 's':
        opt.fontsize = atoi (optarg);
        if ((opt.fontsize < 1)
         || (opt.fontsize > 1000))
        {
          fprintf (stderr, "ERROR: font size should be 1..1000\n");
          return -2;
        }
        break;
      case 'o':
        opt.output = optarg;
        break;
      case 't':
        opt.sourcecode = true;
        break;
      case 'd':
        opt.display = true;
        break;
      case 'h':
        return display_help ();
      case 'v':
        opt.verbose = true;
        break;
      case 'V':
        printf ("%s version %s\n\n", programname, programversion);
        printf ("This program is distributed in the hope that it will be useful,\n");
        printf ("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
        printf ("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
        printf ("GNU Library General Public License for more details.\n");
        return 0;
    } /* endswitch */

  if (optind >= argc)
    return display_help ();

  lastglyph = opt.first + opt.glyphs;
  if (lastglyph > 256)
  {
    fprintf (stderr, "WARNING: Last glyph = %d, limiting to 256\n", lastglyph);
    lastglyph = 256;
    opt.glyphs = 256 - opt.first;
  }

  // Interpret the non-option arguments as file names
  for (; optind < argc; ++optind)
    if (!Convert (argv [optind]))
      return -2;

  csInitializer::DestroyApplication (object_reg);

  return 0;
}
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include "pelagicontain-lib.h"
#include <glibmm.h>
#include <dbus-c++/dbus.h>
#include <dbus-c++/glib-integration.h>

#include <signal.h>
#include <unistd.h>
#include "CommandLineParser.h"
#include "paminterface.h"
#include "pelagicontain.h"
#include "pelagicontaintodbusadapter.h"
#include "generators.h" /* used for gen_ct_name */

#include <sys/stat.h>
#include "systemcallinterface.h"

#ifdef ENABLE_PULSEGATEWAY
#include "pulsegateway.h"
#endif

#ifdef ENABLE_NETWORKGATEWAY
#include "networkgateway.h"
#endif

#ifdef ENABLE_DBUSGATEWAY
#include "dbusgateway.h"
#endif

#ifdef ENABLE_DEVICENODEGATEWAY
#include "devicenodegateway.h"
#endif

#ifdef ENABLE_CGROUPSGATEWAY
#include "cgroupsgateway.h"
#endif

#include "UNIXSignalGlibHandler.h"

#include "pelagicore-DBusCpp.h"

LOG_DEFINE_APP_IDS("PCON", "Pelagicontain");
LOG_DECLARE_DEFAULT_CONTEXT(Pelagicontain_DefaultLogContext, "PCON", "Main context");

/**
 * Remove the dirs created by main when we cleanup
 */
void removeDirs(const std::string& containerDir)
{
    std::string gatewayDir = containerDir + "/gateways";
    if (rmdir(gatewayDir.c_str()) == -1) {
        log_error() << "Cannot delete dir " << gatewayDir << " , " << strerror(errno);
    }

    if (rmdir(containerDir.c_str()) == -1) {
        log_error() << "Cannot delete dir " << containerDir << " , " << strerror(errno);
    }
}

void signalHandler(int signum)
{
    log_debug() << "caught signal " << signum;
    if (!pcPid) {
        if (pelagicontain) {
            // pelagicontain might not have been initialized (preloaded), so we can't just
            // run shutdownContainer. But in the case it is initialized we DO want to run
            // it. Unfortunately, there is currently no way to check that.
            // pelagicontain->shutdownContainer();
            delete pelagicontain;
            removeDirs();
        }
        exit(signum);
    } else {
        // But if pcPid is set, then it is definately initialized
        // This will shutdown pelagicontain and make it exit the main loop
        // back to main() which will take care of the rest of the cleanup
        pelagicontain->shutdown();
    }
}

int main(int argc, char * *argv)
{
    const char *summary = "Pelagicore container utility. "
            "Requires an absolute path to the container root, "
            "the command to run inside the container and "
            "an alphanumerical cookie string as first, second and"
            "third argument respectively";
    const char *paramsDescription = "[container root directory (abs path)] [cookie]";

    pelagicore::CommandLineParser commandLineParser(summary,
            paramsDescription,
            PACKAGE_VERSION,
            "");

    std::string containerRoot;
    std::string cookie;
    const char *configFilePath = PELAGICONTAIN_DEFAULT_CONFIG;
    commandLineParser.addOption(configFilePath,
            "with-config-file",
            'c',
            "Config file");

    //    const char* terminalCommand = "konsole -e";
    const char *terminalCommand = "";
    commandLineParser.addOption(terminalCommand,
            "terminal",
            't',
            "Example: konsole -e");

    if ( commandLineParser.parse(argc, argv) ) {
        return -1;
    }

    if (argc < 3) {
        log_error() << "Invalid arguments";
        commandLineParser.printHelp();
        return -1;
    } else {
        containerRoot = std::string(argv[1]);
        cookie = std::string(argv[2]);
    }

    if (containerRoot.c_str()[0] != '/') {
        log_error() << "Path to container root must be absolute";
        commandLineParser.printHelp();
        return -1;
    }

    std::string containerName = Generator::gen_ct_name();
    std::string containerConfig(configFilePath);

    // Create gateway directory for container in containerRoot/gateways.
    // This dir will contain various sockets etc acting as gateways
    // in/out of the container.
    std::string containerDir = containerRoot + "/" + containerName;
    std::string gatewayDir = containerDir + "/gateways";

    Container container(containerName,
                        containerConfig,
                        containerRoot);

    if (isError(container.initialize())) {
        log_error() << "Could not setup container for preloading";
        removeDirs(containerDir);
        return -1;
    }

    auto mainContext = Glib::MainContext::get_default();
    Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create(mainContext);

    DBus::Glib::BusDispatcher dispatcher;
    DBus::default_dispatcher = &dispatcher;
    dispatcher.attach( mainContext->gobj() );

    std::string configFilePathString = configFilePath;
    PelagicontainWorkspace workspace(containerRoot, configFilePathString);
    pelagicontain::PelagicontainLib lib(workspace);
    lib.setMainLoopContext(mainContext);

    //    std::string busName = "com.pelagicore.Pelagicontain" + cookie;
    //    pelagicore::GLibDBusCppFactory dbusGlibFactory;
    //    dbusGlibFactory.getConnection().request_name( busName.c_str() );
    //    dbusGlibFactory.registerAdapter<PelagicontainToDBusAdapter>( "/com/pelagicore/Pelagicontain", lib.getPelagicontain() );

#ifdef ENABLE_NETWORKGATEWAY
        NetworkGateway networkGateway(controllerInterface, systemcallInterface);
        pelagicontain.addGateway(networkGateway);
#endif

#ifdef ENABLE_PULSEGATEWAY
        PulseGateway pulseGateway(gatewayDir, containerName, controllerInterface);
        pelagicontain.addGateway(pulseGateway);
#endif

#ifdef ENABLE_DEVICENODEGATEWAY
        DeviceNodeGateway deviceNodeGateway(controllerInterface);
        pelagicontain.addGateway(deviceNodeGateway);
#endif

#ifdef ENABLE_DBUSGATEWAY
        DBusGateway sessionBusGateway(controllerInterface,
                                                         systemcallInterface,
                                                         DBusGateway::SessionProxy,
                                                         gatewayDir,
                                                         containerName);

        pelagicontain.addGateway(sessionBusGateway);

        DBusGateway systemBusGateway(controllerInterface,
                                                         systemcallInterface,
                                                         DBusGateway::SystemProxy,
                                                         gatewayDir,
                                                         containerName);
        pelagicontain.addGateway(systemBusGateway);
#endif

#ifdef ENABLE_CGROUPSGATEWAY
        pelagicontain->addGateway(new CgroupsGateway(controllerInterface,
                                                    systemcallInterface,
                                                    containerName));
#endif

        pid_t pcPid = pelagicontain.preload(&container);

		if (!pcPid) {
			// Fatal failure, only do necessary cleanup
			log_error() << "Could not start container, will shut down";
		} else {
			log_debug() << "Started container with PID " << pcPid;
			// setup IPC between Pelagicontain and Controller
			if (!isError(pelagicontain.establishConnection())) {

				if (terminalCommand != nullptr) {
					std::string s = pelagicore::formatString("%s -e lxc-attach -n %s", terminalCommand, container.name());
					system(s.c_str());
				}

				ml->run();
				// When we return here Pelagicontain has exited the mainloop
				log_debug() << "Exited mainloop";
			} else {
				// Fatal failure, only do necessary cleanup
				log_error() << "Got no connection from Controller";
				pelagicontain.shutdownContainer();
			}
		}
    }
    lib.getPelagicontain().getContainerState().addListener([&] (ContainerState state) {
                if (state == ContainerState::TERMINATED) {
                    log_debug() <<
                    "Container terminated => stop main loop and quit";
                    ml->quit();
                }
            });

    if ( !isError( lib.init() ) ) {

        // Register signalHandler with signals
        std::vector<int> signals = {SIGINT, SIGTERM};
        pelagicore::UNIXSignalGlibHandler handler( signals, [&] (int signum) {
                    log_debug() << "caught signal " << signum;
                    switch (signum) {
                    case SIGCHLD :
                        break;
                    default :
                        lib.shutdown();
                        break;
                    }
                }, ml->get_context()->gobj() );

        if ( (terminalCommand != nullptr) && (strlen(terminalCommand) != 0) ) {
            lib.openTerminal(terminalCommand);
        }

        log_debug() << "Entering main loop";
        ml->run();
        log_debug() << "Main loop exited";
    } else {
        log_error() << "Could not initialize pelagicontain";
    }
}
<commit_msg>pelagicontain (helper): remove dead code and correct usage help text<commit_after>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include "pelagicontain-lib.h"
#include <glibmm.h>
#include <dbus-c++/dbus.h>
#include <dbus-c++/glib-integration.h>

#include <signal.h>
#include <unistd.h>
#include "CommandLineParser.h"
#include "paminterface.h"
#include "pelagicontain.h"
#include "pelagicontaintodbusadapter.h"
#include "generators.h" /* used for gen_ct_name */

#include <sys/stat.h>
#include "systemcallinterface.h"

#ifdef ENABLE_PULSEGATEWAY
#include "pulsegateway.h"
#endif

#ifdef ENABLE_NETWORKGATEWAY
#include "networkgateway.h"
#endif

#ifdef ENABLE_DBUSGATEWAY
#include "dbusgateway.h"
#endif

#ifdef ENABLE_DEVICENODEGATEWAY
#include "devicenodegateway.h"
#endif

#ifdef ENABLE_CGROUPSGATEWAY
#include "cgroupsgateway.h"
#endif

#include "UNIXSignalGlibHandler.h"

#include "pelagicore-DBusCpp.h"

LOG_DEFINE_APP_IDS("PCON", "Pelagicontain");
LOG_DECLARE_DEFAULT_CONTEXT(Pelagicontain_DefaultLogContext, "PCON", "Main context");

/**
 * Remove the dirs created by main when we cleanup
 */
void removeDirs(const std::string& containerDir)
{
    std::string gatewayDir = containerDir + "/gateways";
    if (rmdir(gatewayDir.c_str()) == -1) {
        log_error() << "Cannot delete dir " << gatewayDir << " , " << strerror(errno);
    }

    if (rmdir(containerDir.c_str()) == -1) {
        log_error() << "Cannot delete dir " << containerDir << " , " << strerror(errno);
    }
}

void signalHandler(int signum)
{
    log_debug() << "caught signal " << signum;
    if (!pcPid) {
        if (pelagicontain) {
            // pelagicontain might not have been initialized (preloaded), so we can't just
            // run shutdownContainer. But in the case it is initialized we DO want to run
            // it. Unfortunately, there is currently no way to check that.
            // pelagicontain->shutdownContainer();
            delete pelagicontain;
            removeDirs();
        }
        exit(signum);
    } else {
        // But if pcPid is set, then it is definately initialized
        // This will shutdown pelagicontain and make it exit the main loop
        // back to main() which will take care of the rest of the cleanup
        pelagicontain->shutdown();
    }
}

int main(int argc, char * *argv)
{
    const char *summary = "Pelagicore container utility. "
            "Requires an absolute path to the container root";

    const char *paramsDescription = "[container root directory (abs path)]";

    pelagicore::CommandLineParser commandLineParser(summary,
            paramsDescription,
            PACKAGE_VERSION,
            "");

    std::string containerRoot;
    const char *configFilePath = PELAGICONTAIN_DEFAULT_CONFIG;
    commandLineParser.addOption(configFilePath,
            "with-config-file",
            'c',
            "Config file");

    //    const char* terminalCommand = "konsole -e";
    const char *terminalCommand = "";
    commandLineParser.addOption(terminalCommand,
            "terminal",
            't',
            "Example: konsole -e");

    if ( commandLineParser.parse(argc, argv) ) {
        return -1;
    }

    if (argc < 2) {
        log_error() << "Invalid arguments";
        commandLineParser.printHelp();
        return -1;
    } else {
        containerRoot = std::string(argv[1]);
    }

    if (containerRoot.c_str()[0] != '/') {
        log_error() << "Path to container root must be absolute";
        commandLineParser.printHelp();
        return -1;
    }

    std::string containerName = Generator::gen_ct_name();
    std::string containerConfig(configFilePath);

    // Create gateway directory for container in containerRoot/gateways.
    // This dir will contain various sockets etc acting as gateways
    // in/out of the container.
    std::string containerDir = containerRoot + "/" + containerName;
    std::string gatewayDir = containerDir + "/gateways";

    Container container(containerName,
                        containerConfig,
                        containerRoot);

    if (isError(container.initialize())) {
        log_error() << "Could not setup container for preloading";
        removeDirs(containerDir);
        return -1;
    }

    auto mainContext = Glib::MainContext::get_default();
    Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create(mainContext);

    DBus::Glib::BusDispatcher dispatcher;
    DBus::default_dispatcher = &dispatcher;
    dispatcher.attach( mainContext->gobj() );

    std::string configFilePathString = configFilePath;
    PelagicontainWorkspace workspace(containerRoot, configFilePathString);
    pelagicontain::PelagicontainLib lib(workspace);
    lib.setMainLoopContext(mainContext);

    //    std::string busName = "com.pelagicore.Pelagicontain" + cookie;
    //    pelagicore::GLibDBusCppFactory dbusGlibFactory;
    //    dbusGlibFactory.getConnection().request_name( busName.c_str() );
    //    dbusGlibFactory.registerAdapter<PelagicontainToDBusAdapter>( "/com/pelagicore/Pelagicontain", lib.getPelagicontain() );

#ifdef ENABLE_NETWORKGATEWAY
        NetworkGateway networkGateway(controllerInterface, systemcallInterface);
        pelagicontain.addGateway(networkGateway);
#endif

#ifdef ENABLE_PULSEGATEWAY
        PulseGateway pulseGateway(gatewayDir, containerName, controllerInterface);
        pelagicontain.addGateway(pulseGateway);
#endif

#ifdef ENABLE_DEVICENODEGATEWAY
        DeviceNodeGateway deviceNodeGateway(controllerInterface);
        pelagicontain.addGateway(deviceNodeGateway);
#endif

#ifdef ENABLE_DBUSGATEWAY
        DBusGateway sessionBusGateway(controllerInterface,
                                                         systemcallInterface,
                                                         DBusGateway::SessionProxy,
                                                         gatewayDir,
                                                         containerName);

        pelagicontain.addGateway(sessionBusGateway);

        DBusGateway systemBusGateway(controllerInterface,
                                                         systemcallInterface,
                                                         DBusGateway::SystemProxy,
                                                         gatewayDir,
                                                         containerName);
        pelagicontain.addGateway(systemBusGateway);
#endif

#ifdef ENABLE_CGROUPSGATEWAY
        pelagicontain->addGateway(new CgroupsGateway(controllerInterface,
                                                    systemcallInterface,
                                                    containerName));
#endif

        pid_t pcPid = pelagicontain.preload(&container);

		if (!pcPid) {
			// Fatal failure, only do necessary cleanup
			log_error() << "Could not start container, will shut down";
		} else {
			log_debug() << "Started container with PID " << pcPid;
			// setup IPC between Pelagicontain and Controller
			if (!isError(pelagicontain.establishConnection())) {

				if (terminalCommand != nullptr) {
					std::string s = pelagicore::formatString("%s -e lxc-attach -n %s", terminalCommand, container.name());
					system(s.c_str());
				}

				ml->run();
				// When we return here Pelagicontain has exited the mainloop
				log_debug() << "Exited mainloop";
			} else {
				// Fatal failure, only do necessary cleanup
				log_error() << "Got no connection from Controller";
				pelagicontain.shutdownContainer();
			}
		}
    }
    lib.getPelagicontain().getContainerState().addListener([&] (ContainerState state) {
                if (state == ContainerState::TERMINATED) {
                    log_debug() <<
                    "Container terminated => stop main loop and quit";
                    ml->quit();
                }
            });

    if ( !isError( lib.init() ) ) {

        // Register signalHandler with signals
        std::vector<int> signals = {SIGINT, SIGTERM};
        pelagicore::UNIXSignalGlibHandler handler( signals, [&] (int signum) {
                    log_debug() << "caught signal " << signum;
                    switch (signum) {
                    case SIGCHLD :
                        break;
                    default :
                        lib.shutdown();
                        break;
                    }
                }, ml->get_context()->gobj() );

        if ( (terminalCommand != nullptr) && (strlen(terminalCommand) != 0) ) {
            lib.openTerminal(terminalCommand);
        }

        log_debug() << "Entering main loop";
        ml->run();
        log_debug() << "Main loop exited";
    } else {
        log_error() << "Could not initialize pelagicontain";
    }
}
<|endoftext|>


<commit_before>#include <vector>
#include <iostream>
#include <random>

#include <SFML/Graphics.hpp>

#include "Universe.hpp"
#include "Body.hpp"

#define MASS 10
#define BASE_LINE 2
#define CLUSTER_RADIUS 100
#define CLUSTER_NUMBER 1000
#define CLUSTER_MASS 1000

#ifndef M_PI
	#define M_PI 3.14
#endif

#define MAX_DELTA_T (1.0f/30)

using namespace sf;
using namespace std;

int main()
{
	unsigned int width(1024), height(768);
	View view(FloatRect(0, 0, width, height));

	RenderWindow window(VideoMode(width, height), "Gravity Simulation by Johan");
	window.setView(view);

	// Drawable elements
	Universe universe;
	CircleShape base_line(BASE_LINE);

	// Logic vars
	Clock timer;
	float delta_t(0);
	uint64_t mass(MASS);
	uint64_t num_planets(0);
	Vector2f mousePosition;
	Vector2f start, end;

	// Interface vars
	bool running = true;
	bool is_placing = false;
	bool is_moving = false;
	bool control = false;
	bool shift = false;

	// Some inits
	VertexArray line(Lines, 2);
	line[0].color = Color::Blue;
	line[1].color = Color::Green;
	base_line.setFillColor(Color::Blue);

	while (running)
	{
		Event evt;
		while (window.pollEvent(evt))
		{
			if (evt.type == Event::Closed)
			{
				running = false;
			}

			if (evt.type == Event::Resized)
			{
				view.setSize(evt.size.width, evt.size.height);
				window.setView(view);
			}

			if (evt.type == Event::KeyPressed)
			{
				if (evt.key.code == Keyboard::Escape)
				{
					running = false;
				}

				switch (evt.key.code)
				{
				case Keyboard::PageUp:
				case Keyboard::Add:
					mass *= 10;
					cout << "Mass is now " << mass << endl;
					break;

				case Keyboard::PageDown:
				case Keyboard::Subtract:
					if (mass > 10)
					{
						mass /= 10;
					}
					else
					{
						mass = MASS;
					}
					cout << "Mass is now " << mass << endl;
					break;

				case Keyboard::T:
					universe.togglePath();
					break;

				case Keyboard::Space:
					if (is_placing)
					{
						cout << "Planet placement cancelled" << endl;
					}

					is_placing = false;
					break;

				case Keyboard::LControl:
					control = true;
					break;

				case Keyboard::LShift:
					shift = true;
					break;

				case Keyboard::C:
					universe.createProtodisk(CLUSTER_NUMBER, CLUSTER_RADIUS, CLUSTER_MASS, view.getCenter());
					break;

				case Keyboard::Delete:
					universe.eraseAll();

				default:
					break;
				}
			}

			if (evt.type == Event::KeyReleased)
			{
				switch (evt.key.code)
				{
				case Keyboard::LControl:
					control = false;

				case Keyboard::LShift:
					shift = false;

				default:
					break;
				}
			}

			if (evt.type == Event::MouseButtonPressed)
			{
				if (shift)
				{
					universe.eraseAt(window.mapPixelToCoords(Vector2i(evt.mouseButton.x, evt.mouseButton.y)));
				}
				else if (control)
				{
					is_moving = true;
				}
				else
				{
					is_placing = true;

					line[0].position = window.mapPixelToCoords(Vector2i(evt.mouseButton.x, evt.mouseButton.y));
					line[1].position = line[0].position;
					start = Vector2f(evt.mouseButton.x, evt.mouseButton.y);
					end = start;

					Vector2f base_pos = Vector2f(line[0].position.x-BASE_LINE, line[0].position.y-BASE_LINE);
					base_line.setPosition(base_pos);
				}
			}

			if (evt.type == Event::MouseMoved)
			{
				if (is_placing)
				{
					line[1].position = window.mapPixelToCoords(Vector2i(evt.mouseMove.x, evt.mouseMove.y));
					end = Vector2f(evt.mouseMove.x, evt.mouseMove.y);
				}

				if (is_moving)
				{
					view.move(mousePosition - window.mapPixelToCoords(Vector2i(evt.mouseMove.x, evt.mouseMove.y)));
					window.setView(view);
				}

				mousePosition = window.mapPixelToCoords(Vector2i(evt.mouseMove.x, evt.mouseMove.y));
			}

			if (evt.type == Event::MouseButtonReleased)
			{
				if (is_placing)
				{
					is_placing = false;

					Vector2f direction = end - start;
					float radius = Body::radiusForMass(mass);
					Vector2f position = Vector2f(line[0].position.x-radius,
						line[0].position.y-radius);

					universe.addPlanet(position, mass, direction);
				}

				if (is_moving)
				{
					is_moving = false;
				}
			}

			if (evt.type == Event::MouseWheelMoved)
			{
				float factor = (evt.mouseWheel.delta < 1 ? 1.10 : 0.90);
				view.zoom(factor);
				window.setView(view);
			}
		}

		if (num_planets != universe.getPlanetNumber())
		{
			num_planets = universe.getPlanetNumber();
			cout << "Planet number : " << num_planets << endl;
		}

		// Delta T
		delta_t = timer.restart().asSeconds();

		if (delta_t > MAX_DELTA_T)
		{
			delta_t = MAX_DELTA_T;
		}

		window.clear();

		// Vector Preview - wow - need an arrow - hard
		if (is_placing)
		{
			window.draw(line);
			window.draw(base_line);
		}

		// Planets
		universe.move(delta_t);
		universe.draw(window);

		window.display();

		// sleep(milliseconds(1));
	}

	return 0;
}
<commit_msg>removed debug output<commit_after>#include <vector>
#include <iostream>
#include <random>

#include <SFML/Graphics.hpp>

#include "Universe.hpp"
#include "Body.hpp"

#define MASS 10
#define BASE_LINE 2
#define CLUSTER_RADIUS 100
#define CLUSTER_NUMBER 1000
#define CLUSTER_MASS 1000

#ifndef M_PI
	#define M_PI 3.14
#endif

#define MAX_DELTA_T (1.0f/30)

using namespace sf;
using namespace std;

int main()
{
	unsigned int width(1024), height(768);
	View view(FloatRect(0, 0, width, height));

	RenderWindow window(VideoMode(width, height), "Gravity Simulation by Johan");
	window.setView(view);

	// Drawable elements
	Universe universe;
	CircleShape base_line(BASE_LINE);

	// Logic vars
	Clock timer;
	float delta_t(0);
	uint64_t mass(MASS);
	uint64_t num_planets(0);
	Vector2f mousePosition;
	Vector2f start, end;

	// Interface vars
	bool running = true;
	bool is_placing = false;
	bool is_moving = false;
	bool control = false;
	bool shift = false;

	// Some inits
	VertexArray line(Lines, 2);
	line[0].color = Color::Blue;
	line[1].color = Color::Green;
	base_line.setFillColor(Color::Blue);

	while (running)
	{
		Event evt;
		while (window.pollEvent(evt))
		{
			if (evt.type == Event::Closed)
			{
				running = false;
			}

			if (evt.type == Event::Resized)
			{
				view.setSize(evt.size.width, evt.size.height);
				window.setView(view);
			}

			if (evt.type == Event::KeyPressed)
			{
				if (evt.key.code == Keyboard::Escape)
				{
					running = false;
				}

				switch (evt.key.code)
				{
				case Keyboard::PageUp:
				case Keyboard::Add:
					mass *= 10;
					break;

				case Keyboard::PageDown:
				case Keyboard::Subtract:
					if (mass > 10)
					{
						mass /= 10;
					}
					else
					{
						mass = MASS;
					}
					break;

				case Keyboard::T:
					universe.togglePath();
					break;

				case Keyboard::Space:
					is_placing = false;
					break;

				case Keyboard::LControl:
					control = true;
					break;

				case Keyboard::LShift:
					shift = true;
					break;

				case Keyboard::C:
					universe.createProtodisk(CLUSTER_NUMBER, CLUSTER_RADIUS, CLUSTER_MASS, view.getCenter());
					break;

				case Keyboard::Delete:
					universe.eraseAll();

				default:
					break;
				}
			}

			if (evt.type == Event::KeyReleased)
			{
				switch (evt.key.code)
				{
				case Keyboard::LControl:
					control = false;

				case Keyboard::LShift:
					shift = false;

				default:
					break;
				}
			}

			if (evt.type == Event::MouseButtonPressed)
			{
				if (shift)
				{
					universe.eraseAt(window.mapPixelToCoords(Vector2i(evt.mouseButton.x, evt.mouseButton.y)));
				}
				else if (control)
				{
					is_moving = true;
				}
				else
				{
					is_placing = true;

					line[0].position = window.mapPixelToCoords(Vector2i(evt.mouseButton.x, evt.mouseButton.y));
					line[1].position = line[0].position;
					start = Vector2f(evt.mouseButton.x, evt.mouseButton.y);
					end = start;

					Vector2f base_pos = Vector2f(line[0].position.x-BASE_LINE, line[0].position.y-BASE_LINE);
					base_line.setPosition(base_pos);
				}
			}

			if (evt.type == Event::MouseMoved)
			{
				if (is_placing)
				{
					line[1].position = window.mapPixelToCoords(Vector2i(evt.mouseMove.x, evt.mouseMove.y));
					end = Vector2f(evt.mouseMove.x, evt.mouseMove.y);
				}

				if (is_moving)
				{
					view.move(mousePosition - window.mapPixelToCoords(Vector2i(evt.mouseMove.x, evt.mouseMove.y)));
					window.setView(view);
				}

				mousePosition = window.mapPixelToCoords(Vector2i(evt.mouseMove.x, evt.mouseMove.y));
			}

			if (evt.type == Event::MouseButtonReleased)
			{
				if (is_placing)
				{
					is_placing = false;

					Vector2f direction = end - start;
					float radius = Body::radiusForMass(mass);
					Vector2f position = Vector2f(line[0].position.x-radius,
						line[0].position.y-radius);

					universe.addPlanet(position, mass, direction);
				}

				if (is_moving)
				{
					is_moving = false;
				}
			}

			if (evt.type == Event::MouseWheelMoved)
			{
				float factor = (evt.mouseWheel.delta < 1 ? 1.10 : 0.90);
				view.zoom(factor);
				window.setView(view);
			}
		}

		if (num_planets != universe.getPlanetNumber())
		{
			num_planets = universe.getPlanetNumber();
		}

		// Delta T
		delta_t = timer.restart().asSeconds();

		if (delta_t > MAX_DELTA_T)
		{
			delta_t = MAX_DELTA_T;
		}

		window.clear();

		// Vector Preview - wow - need an arrow - hard
		if (is_placing)
		{
			window.draw(line);
			window.draw(base_line);
		}

		// Planets
		universe.move(delta_t);
		universe.draw(window);

		window.display();

		// sleep(milliseconds(1));
	}

	return 0;
}
<|endoftext|>