<commit_before>#include <cstdio>
#include <vector>
#include <deque>
#include <string>
#include <algorithm>
#include <sstream>

/* definitions */
const int stone_size = 8;
const int field_size = 32;
const int empty_val = 257; // 障害物やzkの無いことを表す
const int filled_val = 256; // 障害物を表す
FILE* dumpout = stdout; // dump系関数の出力先

struct Position {
  /*座標を表現するクラス*/
  int y, x;
  bool operator==(const Position&obj) const {
    return y == obj.y && x == obj.x;
  }
  bool operator<(const Position&obj) const {
    if (y == obj.y) {
      return x < obj.x;
    }
    return y < obj.y;
  }
};

struct Stone {
  /* 石 */
  int raw[stone_size][stone_size]; // empty_val -> 空き, otherwise -> うまり
  std::deque<Position> fills; // 埋まってる座標を持っておく
};

struct Field {
  /* フィールド */
  int raw[field_size][field_size];
  std::deque<std::string> answer; // 答えとなる石の置き方を持っておく
};

int number_of_stones; // 与えられる石の数
Stone stones[256 * 8]; // 石を持っておくインスタンス（回転反転を考慮して8倍とってある）
Field initial_field; // 初期フィールド状態
std::deque<Position> initial_empties; // 初期フィールドで空いている場所を探す

int rotated(int deg) {
  /* 石をdeg度まわした石の番号のバイアスを返す */
  return number_of_stones * (deg/90);
}
int fliped() {
  /* 石を反転した時の石の番号のバイアスを返す */
  return number_of_stones * 4;
}
int operated(bool flip, int deg) {
  /* 石を操作した時の石の番号のバイアスを返す */
  if (flip) {
    if (deg == 0) {
      return fliped();
    }
    return fliped() + rotated(deg);
  }
  return rotated(deg);
}
int rotated(int n, int deg) {
  /* 石をdeg度まわした石の番号を返す */
  return n + rotated(deg);
}
int fliped(int n) {
  /* 石を反転した時の石の番号を返す */
  return n + fliped();
}
int operated(int n, bool flip, int deg) {
  /* 石を操作した時の石の番号のバイアスを返す */
  return n + operated(flip, deg);
}
int all_stones_num() {
  /* 全部で石が何個になるか */
  return 8*number_of_stones;
}

/* util */
std::string to_s(int n) {
  /* std::to_stringとかぶるけど、本番環境では必要になりそう*/
	std::stringstream ss;
	ss << n;
	return ss.str();
}
int get() {
  return getc(stdin) - '0';
}
void read_br() {
  /* CRLFを読み飛ばす */
  get();
  get();
};

/* dump */
void dump_stone(int n) {
  for (int i = 0; i < 8; ++i) {
    for (int j = 0; j < 8; ++j) {
      if (stones[n].raw[i][j] == empty_val) {
        /* 空き */
        putc('.', dumpout);
      } else {
        /* うまり */
        putc('@', dumpout);
      }
    }
    putc('\n', dumpout);
  }
}

void dump_field(Field& f, std::deque<Position>& ps) {
  for (int i = 0; i < field_size; ++i) {
    for (int j = 0; j < field_size; ++j) {
      if (std::find(ps.begin(), ps.end(), Position{i, j}) != ps.end()) {
        /* 次の候補 */
        putc('_', dumpout);
      } else if (f.raw[i][j] == empty_val) {
        /* あき */
        putc('.', dumpout);
      } else if (f.raw[i][j] == filled_val) {
        /* 障害物 */
        putc('#', dumpout);
      } else {
        /* 石 */
        putc('@', dumpout);
      }
    }
    putc('\n', dumpout);
  }
}
void dump_field(Field& f) {
  for (int i = 0; i < field_size; ++i) {
    for (int j = 0; j < field_size; ++j) {
      if (f.raw[i][j] == empty_val) {
        /* あき */
        putc('.', dumpout);
      } else if (f.raw[i][j] == filled_val) {
        /* 障害物 */
        putc('#', dumpout);
      } else {
        /* 石 */
        putc('@', dumpout);
      }
    }
    putc('\n', dumpout);
  }
}

/* stone manipurates */
void init_stone(int n) {
  /* 石を初期化しておく */
  for (int i = 0; i < 8; ++i) {
    for (int j = 0; j < 8; ++j) {
      stones[n].raw[i][j] = empty_val;
    }
  }
}
void rotate_stone(int n, int deg) {
  /* 石を回す。deg = 90でよばれて、内部で180, 270をよぶ */
  init_stone(rotated(n, deg));
  for (int i = 0; i < stones[n].fills.size(); ++i) {
    int newy = stones[n].fills[i].x;
    int newx = 7 - stones[n].fills[i].y;
    stones[rotated(n, deg)].fills.push_back(Position{newy, newx});
    stones[rotated(n, deg)].raw[newy][newx] = stones[n].raw[stones[n].fills[i].y][stones[n].fills[i].x];
  }

  if (deg != 270) {
    rotate_stone(n, deg+90);
  }
}

void flip_stone(int n) {
  /* 石を反転させる */
  init_stone(fliped(n));
  for (int i = 0; i < stones[n].fills.size(); ++i) {
    int newy = stones[n].fills[i].y;
    int newx = 7 - stones[n].fills[i].x;
    stones[fliped(n)].fills.push_back(Position{newy, newx});
    stones[fliped(n)].raw[newy][newx] = stones[n].raw[stones[n].fills[i].y][stones[n].fills[i].x];
  }
}

/* parsing */
void get_field() {
  /* 初期フィールドを得る */
  for (int i = 0; i < field_size; ++i) {
    for (int j = 0; j < field_size; ++j) {
      if (get() == 0) {
        initial_field.raw[i][j] = empty_val;
        initial_empties.push_back(Position{i, j});
      } else {
        initial_field.raw[i][j] = filled_val;
      }
    }
    read_br();
  }
}

void get_stone(int index) {
  /* 石をひとつ読む */
  for (int i = 0; i < stone_size; ++i) {
    for (int j = 0; j < stone_size; ++j) {
      if (get() == 0) {
        stones[index].raw[i][j] = empty_val;
      } else {
        stones[index].raw[i][j] = index;
        stones[index].fills.push_back(Position{i, j});
      }
    }
    read_br();
  }
}
void get_stones() {
  /* 石をnumber_of_stones個よむ */
  for (int i = 0; i < number_of_stones; ++i) {
    get_stone(i);
    read_br();

    flip_stone(i);
    rotate_stone(i, 90);
    rotate_stone(fliped(i), 90);
  }
}
void get_input() {
  /* 入力を読む */
  get_field(); read_br();
  scanf("%d\n", &number_of_stones);
  get_stones();
}

/* helper */
void create_candidates(std::deque<Position>& next_candidates, int n, std::deque<Position>& empties) {
  /* 石の埋まっている場所とフィールド上の候補から、次に石を置く可能性のある場所に置く*/
  // next_candidates.resize(empties.size() * stones[n].fills.size());
  for (auto p1 : empties) {
    for (auto p2 : stones[n].fills) {
      next_candidates.push_back(Position{ p1.y - p2.y, p1.x - p2.x });
    }
  }
}

bool pos_check(int y, int x) {
  /* 与えられた座標が、fieldからはみ出ていたらfalseを返す */
  return (0 <= y && y < field_size) && (0 <= x < field_size);
}

std::string create_answer_format(int n, bool flip, int deg, Position p) {
  /* 石を置いた様子から回答フォーマットに沿った文字列を返す */
  return to_s(p.x) + " " + to_s(p.y) + " " + (flip ? "T" : "H") + " " + to_s(deg);
}

void print_anser(Field& f) {
  for (auto l : f.answer) {
    printf("%s\r\n", l.c_str());
  }
}

/* solver */
int put_stone(int m, bool flip, int deg, Position base, Field& f, std::deque<Position>& next_candidates) {
  /* 石を置く処理。ついでに次に石を置けそうな場所を探す */
  int score = 0;
  int n = operated(m, flip, deg);
  bool flag = false; // となりに石があるかフラグ。本来不要
  Field backup = f;
  for (auto p : stones[n].fills) { // zkごとにおけるかどうかを判定する
    int y = base.y + p.y;
    int x = base.x + p.x;
    if (!pos_check(y, x) || f.raw[y][x] != empty_val) { // 置きたい場所が空いてないと置けない
      next_candidates.clear();
      f = backup;
      return 0;
    }

    score += 1;
    f.raw[y][x] = m;

    /* 置いたところは候補から外す */
    auto exists = std::find(next_candidates.begin(), next_candidates.end(), Position{y, x});
    if (exists != next_candidates.end()) {
      next_candidates.erase(exists);
    }

    /* 隣接している空きマスを次の候補に */
    int dy[] = {-1, 0, 0, 1};
    int dx[] = {0, -1, 1, 0};
    for (int i = 0; i < 4; ++i) {
      if (!flag &&
          pos_check(y + dy[i], x + dx[i]) &&
          f.raw[y + dy[i]][x + dx[i]] > n) {
        flag = true;
      }
      if (pos_check(y + dy[i], x + dx[i]) &&
          f.raw[y + dy[i]][x + dx[i]] == empty_val) {
        Position newpos{y+dy[i], x+dx[i]};
        if (std::find(next_candidates.begin(), next_candidates.end(), newpos) == next_candidates.end()) {
          next_candidates.push_back(newpos);
        }
      }
    }
  }

  if (!flag) {
      next_candidates.clear();
      f = backup;
      return 0;
  }

  return score;
}
void dfs(int nowscore, int n, bool fliped, int deg, Position p, Field f, std::deque<Position> next_empties) {
  /* n番の石をfliped + degの状態で、f上のpに置くところから深く */
  if (n >= number_of_stones) {
    return;
  }

  int score;

  if ((score = put_stone(n, fliped, deg, p, f, next_empties)) > 0) {
    score += nowscore;
    fprintf(stderr, "score - %d\n", score);
    /* 石を置いた時の処理 */
    f.answer[n] = create_answer_format(n, fliped, deg, p);

    printf("score: %d\n", score);
    dump_field(f, next_empties);
    print_anser(f);
    fflush(dumpout);
  }

  /* 次の石を置く処理 */
  std::deque<Position> next_candidates;

  for (int j = 0; j <= 270; j += 90) { // 回転
    for (bool k = false; !k; k = true) { // 反転
      for (int i = n + 1; i < number_of_stones; ++i) {
        create_candidates(next_candidates, operated(i, k, j), next_empties); // 石を置く場所の候補を生成
        for (auto p : next_candidates) {
         dfs(score, i, k, j, p, f, next_empties);
        }
      }
    }
  }
}
void solve() {
  /* とりあえずこれを呼んでsolveする */
  std::deque<Position> first_candidates; // 最初の石を置く場所
  std::deque<Position> empty_positions;
  empty_positions.empty();

  for (int j = 0; j <= 270; j += 90) { // 回転
    for (bool k = false; !k; k = true) { // 反転
      for (int i = 0; i < number_of_stones; ++i) {
        create_candidates(first_candidates, operated(i, k, j), initial_empties); // 一個目の石を置く場所の候補を生成
        for (auto p : first_candidates) {
          dfs(0, i, k, j, p, initial_field, empty_positions);
        }
      }
    }
  }
}

/* main */
int main() {
  get_input();
  initial_field.answer.resize(number_of_stones);
  solve();
}
<commit_msg>すっきりー！　すっきりー！<commit_after><|endoftext|>


<commit_before>#include <stdexcept>
#include <fstream>
#include <xorg/gtest/xorg-gtest.h>

#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

#include "input-driver-test.h"

class LegacyInputDriverTest : public InputDriverTest {
public:
    virtual void ConfigureInputDevice(std::string &driver) {
        config.AddInputSection(driver, "--device--", "Option \"CorePointer\" \"on\"\n");
    }

    virtual void SetUpConfigAndLog() {
        std::string param = GetParam();

        std::stringstream s;
        s << "/tmp/Xorg-" << GetParam() << ".log";
        log_file = s.str();
        server.SetOption("-logfile",log_file);

        s.str(std::string());
        s << "/tmp/" << GetParam() << ".conf";
        config_file = s.str();

        ConfigureInputDevice(param);
        config.WriteConfig(config_file);
        server.SetOption("-config", config_file);
    }
};

TEST_P(LegacyInputDriverTest, SimpleDeviceSection)
{
    std::string param;
    int ndevices;
    XIDeviceInfo *info;

    param = GetParam();
    info = XIQueryDevice(Display(), XIAllDevices, &ndevices);

    int expected_devices;

    /* apparently when the acecad driver is loaded neither mouse nor kbd
     * loads - probably a bug but that's current behaviour on RHEL 6.3 */
    if (param.compare("acecad") == 0)
        expected_devices = 4;
    else
        expected_devices = 6;

    ASSERT_EQ(ndevices, expected_devices);

    bool found = false;
    while(ndevices--) {
        if (strcmp(info[ndevices].name, "--device--") == 0) {
            ASSERT_EQ(found, false) << "Duplicate device" << std::endl;
            found = true;
        }
    }

    /* No joke, they all fail. some fail for missing Device option, others
     * for not finding the device, etc. */
    ASSERT_EQ(found, false);

    XIFreeDeviceInfo(info);
}

INSTANTIATE_TEST_CASE_P(, LegacyInputDriverTest,
        ::testing::Values("acecad", "aiptek", "elographics",
                          "fpit", "hyperpen",  "mutouch",
                          "penmount"));

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>legacy-drivers: acecad should load with a (bogus) Device option<commit_after>#include <stdexcept>
#include <fstream>
#include <xorg/gtest/xorg-gtest.h>

#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

#include "input-driver-test.h"

class LegacyInputDriverTest : public InputDriverTest {
public:
    virtual void ConfigureInputDevice(std::string &driver) {
        config.AddInputSection(driver, "--device--", "Option \"CorePointer\" \"on\"\n");
    }

    virtual void SetUpConfigAndLog() {
        std::string param = GetParam();

        std::stringstream s;
        s << "/tmp/Xorg-" << GetParam() << ".log";
        log_file = s.str();
        server.SetOption("-logfile",log_file);

        s.str(std::string());
        s << "/tmp/" << GetParam() << ".conf";
        config_file = s.str();

        ConfigureInputDevice(param);
        config.WriteConfig(config_file);
        server.SetOption("-config", config_file);
    }
};

TEST_P(LegacyInputDriverTest, SimpleDeviceSection)
{
    std::string param;
    int ndevices;
    XIDeviceInfo *info;

    param = GetParam();
    info = XIQueryDevice(Display(), XIAllDevices, &ndevices);

    int expected_devices;

    /* apparently when the acecad driver is loaded neither mouse nor kbd
     * loads - probably a bug but that's current behaviour on RHEL 6.3 */
    if (param.compare("acecad") == 0)
        expected_devices = 4;
    else
        expected_devices = 6;

    ASSERT_EQ(ndevices, expected_devices);

    bool found = false;
    while(ndevices--) {
        if (strcmp(info[ndevices].name, "--device--") == 0) {
            ASSERT_EQ(found, false) << "Duplicate device" << std::endl;
            found = true;
        }
    }

    /* No joke, they all fail. some fail for missing Device option, others
     * for not finding the device, etc. */
    ASSERT_EQ(found, false);

    XIFreeDeviceInfo(info);
}

INSTANTIATE_TEST_CASE_P(, LegacyInputDriverTest,
        ::testing::Values("acecad", "aiptek", "elographics",
                          "fpit", "hyperpen",  "mutouch",
                          "penmount"));

/***********************************************************************
 *                                                                     *
 *                               ACECAD                                *
 *                                                                     *
 ***********************************************************************/

class AcecadInputDriverTest : public LegacyInputDriverTest {
    public:
        virtual void ConfigureInputDevice(std::string &driver) {
            config.AddInputSection(driver, "--device--",
                                   "Option \"CorePointer\" \"on\"\n"
                                   "Option \"Device\" \"/dev/input/event0\"\n");
        }
};

TEST_P(AcecadInputDriverTest, WithOptionDevice)
{
    std::string param;
    int ndevices;
    XIDeviceInfo *info;

    param = GetParam();
    info = XIQueryDevice(Display(), XIAllDevices, &ndevices);

    /* when the acecad driver succeeds (even with bogus device)
     * mouse and keyboard load too */
    ASSERT_EQ(ndevices, 7);

    bool found = false;
    while(ndevices--) {
        if (strcmp(info[ndevices].name, "--device--") == 0) {
            ASSERT_EQ(found, false) << "Duplicate device" << std::endl;
            found = true;
        }
    }

    ASSERT_EQ(found, true);
    XIFreeDeviceInfo(info);
}

INSTANTIATE_TEST_CASE_P(, AcecadInputDriverTest, ::testing::Values(std::string("acecad")));

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2008-2010 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2008-2010 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"

#include <TelepathyQt4/DBusProxy>

#include "TelepathyQt4/_gen/dbus-proxy.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Constants>

#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusError>
#include <QDBusServiceWatcher>
#include <QTimer>

namespace Tp
{

// ==== DBusProxy ======================================================

// Features in TpProxy but not here:
// * tracking which interfaces we have (in tpqt4, subclasses do that)
// * being Introspectable, a Peer and a Properties implementation
// * disconnecting from signals when invalidated (probably has to be in the
//   generated code)
// * making methods always raise an error when called after invalidated
//   (has to be in the generated code)

struct TELEPATHY_QT4_NO_EXPORT DBusProxy::Private
{
    Private(const QDBusConnection &dbusConnection, const QString &busName,
            const QString &objectPath);

    QDBusConnection dbusConnection;
    QString busName;
    QString objectPath;
    QString invalidationReason;
    QString invalidationMessage;
};

DBusProxy::Private::Private(const QDBusConnection &dbusConnection,
            const QString &busName, const QString &objectPath)
    : dbusConnection(dbusConnection),
      busName(busName),
      objectPath(objectPath)
{
    debug() << "Creating new DBusProxy";
}

/**
 * \class DBusProxy
 * \ingroup clientproxies
 * \headerfile TelepathyQt4/dbus-proxy.h <TelepathyQt4/DBusProxy>
 *
 * \brief The DBusProxy class is a base class representing a remote object available over D-Bus.
 *
 * All Telepathy-Qt4 client convenience classes that wrap Telepathy interfaces
 * inherit from this class in order to provide basic D-Bus interface
 * information.
 */

/**
 * Construct a new DBusProxy object.
 *
 * \param dbusConnection QDBusConnection to use.
 * \param busName D-Bus bus name of the service that provides the remote object.
 * \param objectPath The object path.
 * \param featureCore The object core feature.
 */
DBusProxy::DBusProxy(const QDBusConnection &dbusConnection,
        const QString &busName, const QString &objectPath, const Feature &featureCore)
    : Object(),
      ReadyObject(this, featureCore),
      mPriv(new Private(dbusConnection, busName, objectPath))
{
    if (!dbusConnection.isConnected()) {
        invalidate(QLatin1String(TELEPATHY_ERROR_DISCONNECTED),
                QLatin1String("DBus connection disconnected"));
    }
}

/**
 * Class destructor.
 */
DBusProxy::~DBusProxy()
{
    delete mPriv;
}

/**
 * Return the D-Bus connection through which the remote object is
 * accessed.
 *
 * \return A QDBusConnection object.
 */
QDBusConnection DBusProxy::dbusConnection() const
{
    return mPriv->dbusConnection;
}

/**
 * Return the D-Bus object path of the remote object within the service.
 *
 * \return The D-Bus object path.
 */
QString DBusProxy::objectPath() const
{
    return mPriv->objectPath;
}

/**
 * Return the D-Bus bus name (either a unique name or a well-known
 * name) of the service that provides the remote object.
 *
 * \return The D-Bus bus name.
 */
QString DBusProxy::busName() const
{
    return mPriv->busName;
}

/**
 * Sets the D-Bus bus name. This is used by subclasses after converting
 * well-known names to unique names.
 *
 * \param busName The D-Bus bus name to set.
 */
void DBusProxy::setBusName(const QString &busName)
{
    mPriv->busName = busName;
}

/**
 * Return whether this proxy is still valid (has not emitted invalidated()).
 *
 * \return \c true if still valid, \c false otherwise.
 */
bool DBusProxy::isValid() const
{
    return mPriv->invalidationReason.isEmpty();
}

/**
 * Return the error name indicating the reason this proxy became invalid.
 *
 * \return A D-Bus error name, or QString() if this object is still valid.
 */
QString DBusProxy::invalidationReason() const
{
    return mPriv->invalidationReason;
}

/**
 * Return a debugging message indicating the reason this proxy became invalid.
 *
 * \return A debugging message, or QString() if this object is still valid.
 */
QString DBusProxy::invalidationMessage() const
{
    return mPriv->invalidationMessage;
}

/**
 * \fn void DBusProxy::invalidated(Tp::DBusProxy *proxy,
 *          const QString &errorName, const QString &errorMessage)
 *
 * Emitted when this object is no longer usable.
 *
 * After this signal is emitted, any D-Bus method calls on the object
 * will fail, but it may be possible to retrieve information that has
 * already been retrieved and cached.
 *
 * \param proxy This proxy.
 * \param errorName The name of a D-Bus error describing the reason for the invalidation.
 * \param errorMessage A debugging message associated with the error.
 */

/**
 * Called by subclasses when the DBusProxy should become invalid.
 *
 * This method takes care of setting the invalidationReason,
 * invalidationMessage, and emitting the invalidated signal.
 *
 * \param reason A D-Bus error name (a string in a subset of ASCII,
 *               prefixed with a reversed domain name)
 * \param message A debugging message associated with the error
 */
void DBusProxy::invalidate(const QString &reason, const QString &message)
{
    if (!isValid()) {
        debug().nospace() << "Already invalidated by "
            << mPriv->invalidationReason
            << ", not replacing with " << reason
            << " \"" << message << "\"";
        return;
    }

    Q_ASSERT(!reason.isEmpty());

    debug().nospace() << "proxy invalidated: " << reason
        << ": " << message;

    mPriv->invalidationReason = reason;
    mPriv->invalidationMessage = message;

    Q_ASSERT(!isValid());

    // Defer emitting the invalidated signal until we next
    // return to the mainloop.
    QTimer::singleShot(0, this, SLOT(emitInvalidated()));
}

void DBusProxy::invalidate(const QDBusError &error)
{
    invalidate(error.name(), error.message());
}

void DBusProxy::emitInvalidated()
{
    Q_ASSERT(!isValid());

    emit invalidated(this, mPriv->invalidationReason, mPriv->invalidationMessage);
}

// ==== StatefulDBusProxy ==============================================

struct TELEPATHY_QT4_NO_EXPORT StatefulDBusProxy::Private
{
    Private(const QString &originalName)
        : originalName(originalName) {}

    QString originalName;
};

/**
 * \class StatefulDBusProxy
 * \ingroup clientproxies
 * \headerfile TelepathyQt4/dbus-proxy.h <TelepathyQt4/StatefulDBusProxy>
 *
 * \brief The StatefulDBusProxy class is a base class representing a remote object whose API is
 * stateful.
 *
 * These objects do not remain useful if the service providing them exits or
 * crashes, so they emit invalidated() if this happens.
 *
 * Examples include the Connection and Channel classes.
 */

/**
 * Construct a new StatefulDBusProxy object.
 *
 * \param dbusConnection QDBusConnection to use.
 * \param busName D-Bus bus name of the service that provides the remote object.
 * \param objectPath The object path.
 * \param featureCore The object core feature.
 */
StatefulDBusProxy::StatefulDBusProxy(const QDBusConnection &dbusConnection,
        const QString &busName, const QString &objectPath, const Feature &featureCore)
    : DBusProxy(dbusConnection, busName, objectPath, featureCore),
      mPriv(new Private(busName))
{
    QDBusServiceWatcher *serviceWatcher = new QDBusServiceWatcher(busName,
            dbusConnection, QDBusServiceWatcher::WatchForUnregistration, this);
    connect(serviceWatcher,
            SIGNAL(serviceOwnerChanged(QString,QString,QString)),
            SLOT(onServiceOwnerChanged(QString,QString,QString)));

    QString error, message;
    QString uniqueName = uniqueNameFrom(dbusConnection, busName, error, message);

    if (uniqueName.isEmpty()) {
        invalidate(error, message);
        return;
    }

    setBusName(uniqueName);
}

/**
 * Class destructor.
 */
StatefulDBusProxy::~StatefulDBusProxy()
{
    delete mPriv;
}

QString StatefulDBusProxy::uniqueNameFrom(const QDBusConnection &bus, const QString &name)
{
    QString error, message;
    QString uniqueName = uniqueNameFrom(bus, name, error, message);
    if (uniqueName.isEmpty()) {
        warning() << "StatefulDBusProxy::uniqueNameFrom(): Failed to get unique name of" << name;
        warning() << "  error:" << error << "message:" << message;
    }

    return uniqueName;
}

QString StatefulDBusProxy::uniqueNameFrom(const QDBusConnection &bus, const QString &name,
        QString &error, QString &message)
{
    if (name.startsWith(QLatin1String(":"))) {
        return name;
    }

    // For a stateful interface, it makes no sense to follow name-owner
    // changes, so we want to bind to the unique name.
    QDBusReply<QString> reply = bus.interface()->serviceOwner(name);
    if (reply.isValid()) {
        return reply.value();
    } else {
        error = reply.error().name();
        message = reply.error().message();
        return QString();
    }
}

void StatefulDBusProxy::onServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
    // We only want to invalidate this object if it is not already invalidated,
    // and its (not any other object's) name owner changed signal is emitted.
    if (isValid() && name == mPriv->originalName && newOwner.isEmpty()) {
        invalidate(QLatin1String(TELEPATHY_DBUS_ERROR_NAME_HAS_NO_OWNER),
                QLatin1String("Name owner lost (service crashed?)"));
    }
}

// ==== StatelessDBusProxy =============================================

/**
 * \class StatelessDBusProxy
 * \ingroup clientproxies
 * \headerfile TelepathyQt4/dbus-proxy.h <TelepathyQt4/DBusProxy>
 *
 * \brief The StatelessDBusProxy class is a base class representing a remote object whose API is
 * basically stateless.
 *
 * These objects can remain valid even if the service providing them exits
 * and is restarted.
 *
 * Examples include the AccountManager, Account and ConnectionManager.
 */

/**
 * Construct a new StatelessDBusProxy object.
 *
 * \param dbusConnection QDBusConnection to use.
 * \param busName D-Bus bus name of the service that provides the remote object.
 * \param objectPath The object path.
 * \param featureCore The object core feature.
 */
StatelessDBusProxy::StatelessDBusProxy(const QDBusConnection &dbusConnection,
        const QString &busName, const QString &objectPath, const Feature &featureCore)
    : DBusProxy(dbusConnection, busName, objectPath, featureCore),
      mPriv(0)
{
    if (busName.startsWith(QLatin1String(":"))) {
        warning() <<
            "Using StatelessDBusProxy for a unique name does not make sense";
    }
}

/**
 * Class destructor.
 */
StatelessDBusProxy::~StatelessDBusProxy()
{
}

} // Tp
<commit_msg>DBusProxy: Move signals docs to the bottom of the class implementation.<commit_after>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2008-2010 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2008-2010 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"

#include <TelepathyQt4/DBusProxy>

#include "TelepathyQt4/_gen/dbus-proxy.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Constants>

#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusError>
#include <QDBusServiceWatcher>
#include <QTimer>

namespace Tp
{

// ==== DBusProxy ======================================================

// Features in TpProxy but not here:
// * tracking which interfaces we have (in tpqt4, subclasses do that)
// * being Introspectable, a Peer and a Properties implementation
// * disconnecting from signals when invalidated (probably has to be in the
//   generated code)
// * making methods always raise an error when called after invalidated
//   (has to be in the generated code)

struct TELEPATHY_QT4_NO_EXPORT DBusProxy::Private
{
    Private(const QDBusConnection &dbusConnection, const QString &busName,
            const QString &objectPath);

    QDBusConnection dbusConnection;
    QString busName;
    QString objectPath;
    QString invalidationReason;
    QString invalidationMessage;
};

DBusProxy::Private::Private(const QDBusConnection &dbusConnection,
            const QString &busName, const QString &objectPath)
    : dbusConnection(dbusConnection),
      busName(busName),
      objectPath(objectPath)
{
    debug() << "Creating new DBusProxy";
}

/**
 * \class DBusProxy
 * \ingroup clientproxies
 * \headerfile TelepathyQt4/dbus-proxy.h <TelepathyQt4/DBusProxy>
 *
 * \brief The DBusProxy class is a base class representing a remote object available over D-Bus.
 *
 * All Telepathy-Qt4 client convenience classes that wrap Telepathy interfaces
 * inherit from this class in order to provide basic D-Bus interface
 * information.
 */

/**
 * Construct a new DBusProxy object.
 *
 * \param dbusConnection QDBusConnection to use.
 * \param busName D-Bus bus name of the service that provides the remote object.
 * \param objectPath The object path.
 * \param featureCore The object core feature.
 */
DBusProxy::DBusProxy(const QDBusConnection &dbusConnection,
        const QString &busName, const QString &objectPath, const Feature &featureCore)
    : Object(),
      ReadyObject(this, featureCore),
      mPriv(new Private(dbusConnection, busName, objectPath))
{
    if (!dbusConnection.isConnected()) {
        invalidate(QLatin1String(TELEPATHY_ERROR_DISCONNECTED),
                QLatin1String("DBus connection disconnected"));
    }
}

/**
 * Class destructor.
 */
DBusProxy::~DBusProxy()
{
    delete mPriv;
}

/**
 * Return the D-Bus connection through which the remote object is
 * accessed.
 *
 * \return A QDBusConnection object.
 */
QDBusConnection DBusProxy::dbusConnection() const
{
    return mPriv->dbusConnection;
}

/**
 * Return the D-Bus object path of the remote object within the service.
 *
 * \return The D-Bus object path.
 */
QString DBusProxy::objectPath() const
{
    return mPriv->objectPath;
}

/**
 * Return the D-Bus bus name (either a unique name or a well-known
 * name) of the service that provides the remote object.
 *
 * \return The D-Bus bus name.
 */
QString DBusProxy::busName() const
{
    return mPriv->busName;
}

/**
 * Sets the D-Bus bus name. This is used by subclasses after converting
 * well-known names to unique names.
 *
 * \param busName The D-Bus bus name to set.
 */
void DBusProxy::setBusName(const QString &busName)
{
    mPriv->busName = busName;
}

/**
 * Return whether this proxy is still valid (has not emitted invalidated()).
 *
 * \return \c true if still valid, \c false otherwise.
 */
bool DBusProxy::isValid() const
{
    return mPriv->invalidationReason.isEmpty();
}

/**
 * Return the error name indicating the reason this proxy became invalid.
 *
 * \return A D-Bus error name, or QString() if this object is still valid.
 */
QString DBusProxy::invalidationReason() const
{
    return mPriv->invalidationReason;
}

/**
 * Return a debugging message indicating the reason this proxy became invalid.
 *
 * \return A debugging message, or QString() if this object is still valid.
 */
QString DBusProxy::invalidationMessage() const
{
    return mPriv->invalidationMessage;
}

/**
 * Called by subclasses when the DBusProxy should become invalid.
 *
 * This method takes care of setting the invalidationReason,
 * invalidationMessage, and emitting the invalidated signal.
 *
 * \param reason A D-Bus error name (a string in a subset of ASCII,
 *               prefixed with a reversed domain name)
 * \param message A debugging message associated with the error
 */
void DBusProxy::invalidate(const QString &reason, const QString &message)
{
    if (!isValid()) {
        debug().nospace() << "Already invalidated by "
            << mPriv->invalidationReason
            << ", not replacing with " << reason
            << " \"" << message << "\"";
        return;
    }

    Q_ASSERT(!reason.isEmpty());

    debug().nospace() << "proxy invalidated: " << reason
        << ": " << message;

    mPriv->invalidationReason = reason;
    mPriv->invalidationMessage = message;

    Q_ASSERT(!isValid());

    // Defer emitting the invalidated signal until we next
    // return to the mainloop.
    QTimer::singleShot(0, this, SLOT(emitInvalidated()));
}

void DBusProxy::invalidate(const QDBusError &error)
{
    invalidate(error.name(), error.message());
}

void DBusProxy::emitInvalidated()
{
    Q_ASSERT(!isValid());

    emit invalidated(this, mPriv->invalidationReason, mPriv->invalidationMessage);
}

/**
 * \fn void DBusProxy::invalidated(Tp::DBusProxy *proxy,
 *          const QString &errorName, const QString &errorMessage)
 *
 * Emitted when this object is no longer usable.
 *
 * After this signal is emitted, any D-Bus method calls on the object
 * will fail, but it may be possible to retrieve information that has
 * already been retrieved and cached.
 *
 * \param proxy This proxy.
 * \param errorName The name of a D-Bus error describing the reason for the invalidation.
 * \param errorMessage A debugging message associated with the error.
 */

// ==== StatefulDBusProxy ==============================================

struct TELEPATHY_QT4_NO_EXPORT StatefulDBusProxy::Private
{
    Private(const QString &originalName)
        : originalName(originalName) {}

    QString originalName;
};

/**
 * \class StatefulDBusProxy
 * \ingroup clientproxies
 * \headerfile TelepathyQt4/dbus-proxy.h <TelepathyQt4/StatefulDBusProxy>
 *
 * \brief The StatefulDBusProxy class is a base class representing a remote object whose API is
 * stateful.
 *
 * These objects do not remain useful if the service providing them exits or
 * crashes, so they emit invalidated() if this happens.
 *
 * Examples include the Connection and Channel classes.
 */

/**
 * Construct a new StatefulDBusProxy object.
 *
 * \param dbusConnection QDBusConnection to use.
 * \param busName D-Bus bus name of the service that provides the remote object.
 * \param objectPath The object path.
 * \param featureCore The object core feature.
 */
StatefulDBusProxy::StatefulDBusProxy(const QDBusConnection &dbusConnection,
        const QString &busName, const QString &objectPath, const Feature &featureCore)
    : DBusProxy(dbusConnection, busName, objectPath, featureCore),
      mPriv(new Private(busName))
{
    QDBusServiceWatcher *serviceWatcher = new QDBusServiceWatcher(busName,
            dbusConnection, QDBusServiceWatcher::WatchForUnregistration, this);
    connect(serviceWatcher,
            SIGNAL(serviceOwnerChanged(QString,QString,QString)),
            SLOT(onServiceOwnerChanged(QString,QString,QString)));

    QString error, message;
    QString uniqueName = uniqueNameFrom(dbusConnection, busName, error, message);

    if (uniqueName.isEmpty()) {
        invalidate(error, message);
        return;
    }

    setBusName(uniqueName);
}

/**
 * Class destructor.
 */
StatefulDBusProxy::~StatefulDBusProxy()
{
    delete mPriv;
}

QString StatefulDBusProxy::uniqueNameFrom(const QDBusConnection &bus, const QString &name)
{
    QString error, message;
    QString uniqueName = uniqueNameFrom(bus, name, error, message);
    if (uniqueName.isEmpty()) {
        warning() << "StatefulDBusProxy::uniqueNameFrom(): Failed to get unique name of" << name;
        warning() << "  error:" << error << "message:" << message;
    }

    return uniqueName;
}

QString StatefulDBusProxy::uniqueNameFrom(const QDBusConnection &bus, const QString &name,
        QString &error, QString &message)
{
    if (name.startsWith(QLatin1String(":"))) {
        return name;
    }

    // For a stateful interface, it makes no sense to follow name-owner
    // changes, so we want to bind to the unique name.
    QDBusReply<QString> reply = bus.interface()->serviceOwner(name);
    if (reply.isValid()) {
        return reply.value();
    } else {
        error = reply.error().name();
        message = reply.error().message();
        return QString();
    }
}

void StatefulDBusProxy::onServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
    // We only want to invalidate this object if it is not already invalidated,
    // and its (not any other object's) name owner changed signal is emitted.
    if (isValid() && name == mPriv->originalName && newOwner.isEmpty()) {
        invalidate(QLatin1String(TELEPATHY_DBUS_ERROR_NAME_HAS_NO_OWNER),
                QLatin1String("Name owner lost (service crashed?)"));
    }
}

// ==== StatelessDBusProxy =============================================

/**
 * \class StatelessDBusProxy
 * \ingroup clientproxies
 * \headerfile TelepathyQt4/dbus-proxy.h <TelepathyQt4/DBusProxy>
 *
 * \brief The StatelessDBusProxy class is a base class representing a remote object whose API is
 * basically stateless.
 *
 * These objects can remain valid even if the service providing them exits
 * and is restarted.
 *
 * Examples include the AccountManager, Account and ConnectionManager.
 */

/**
 * Construct a new StatelessDBusProxy object.
 *
 * \param dbusConnection QDBusConnection to use.
 * \param busName D-Bus bus name of the service that provides the remote object.
 * \param objectPath The object path.
 * \param featureCore The object core feature.
 */
StatelessDBusProxy::StatelessDBusProxy(const QDBusConnection &dbusConnection,
        const QString &busName, const QString &objectPath, const Feature &featureCore)
    : DBusProxy(dbusConnection, busName, objectPath, featureCore),
      mPriv(0)
{
    if (busName.startsWith(QLatin1String(":"))) {
        warning() <<
            "Using StatelessDBusProxy for a unique name does not make sense";
    }
}

/**
 * Class destructor.
 */
StatelessDBusProxy::~StatelessDBusProxy()
{
}

} // Tp
<|endoftext|>


<commit_before>#include <sys/stat.h>
#include <sstream>
#include "java_generator.h"
#include "../ds/hot.h"
#include "../common/string_helper.h"
#include "../common/os.h"
#include "../common/type_helper.h"
#include <map>
#include <sstream>

namespace naeem {
  namespace hottentot {
    namespace generator {
      namespace java {
        void
        JavaGenerator::GenerateEnums(::naeem::hottentot::generator::ds::Module *pModule) {
          //loop on methods
          // for (int i = 0; i < pMadule->services_.size(); i++) {
          //   for(int j = 0 ; j < pModule->services_.at(i)->methods_.size() ; j++){
          //     ::naeem::hottentot::generator::ds::Method* pMethod = pModule->services_.at(i)->methods_.at(j);

          //   }
          // }

          //TODO make struct for PDT arg and return type in methods
          //loop on structs in everey module
          for (int i = 0; i < pModule->enums_.size(); i++) {
            ::naeem::hottentot::generator::ds::Enum *pEnum = pModule->enums_.at(i);
            std::string basePackageName = pModule->package_;
            std::string replacableEnumTmpStr = enumTmpStr_;
            ::naeem::hottentot::generator::Context.enums_.push_back(pEnum);
            std::map<uint16_t, std::string>::iterator it;
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%BASE_PACKAGE_NAME%]" , basePackageName , 1);
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%INDENT%]" , indent_ , 1);
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%ENUM_NAME%]" , pEnum->GetName() , 1);
            std::string membersStr = "";
            uint8_t mapCounter = 1;
            for (std::map<uint16_t, std::string>::iterator it
             = pEnum->revItems_.begin();
             it != pEnum->revItems_.end();
             ++it) {
              std::string itemName = it->second;
              uint16_t itemValue = it->first;
              std::stringstream itemValueStr;
              itemValueStr << itemValue;
              membersStr += indent_ +  itemName + "((short) " + itemValueStr.str() +  ")";
              if(mapCounter != pEnum->revItems_.size()){
                membersStr += ",\n";
              }else {
                membersStr += ";";
              }
              mapCounter++;
            }
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%MEMBERS%]" , membersStr , 1);            std::string path = outDir_ + "/" + pEnum->GetName().c_str() + ".java";
            ::naeem::hottentot::generator::common::Os::WriteFile(path , replacableEnumTmpStr);
          }
        }

      } //END NAMESPACE JAVA
    } //END NAMESPACE GENERATOR
  } //END NAMESPACE HOTTENTOT
}  //END NAMESPACE NAEEM<commit_msg>minor changes<commit_after>#include <sys/stat.h>
#include <sstream>
#include "java_generator.h"
#include "../ds/hot.h"
#include "../common/string_helper.h"
#include "../common/os.h"
#include "../common/type_helper.h"
#include <map>
#include <sstream>
#include "runtime.h"

namespace naeem {
  namespace hottentot {
    namespace generator {
      namespace java {
        void
        JavaGenerator::GenerateEnums(::naeem::hottentot::generator::ds::Module *pModule) {
          //loop on methods
          // for (int i = 0; i < pMadule->services_.size(); i++) {
          //   for(int j = 0 ; j < pModule->services_.at(i)->methods_.size() ; j++){
          //     ::naeem::hottentot::generator::ds::Method* pMethod = pModule->services_.at(i)->methods_.at(j);

          //   }
          // }

          //TODO make struct for PDT arg and return type in methods
          //loop on structs in everey module
          for (int i = 0; i < pModule->enums_.size(); i++) {
            ::naeem::hottentot::generator::ds::Enum *pEnum = pModule->enums_.at(i);
            std::string basePackageName = pModule->package_;
            std::string replacableEnumTmpStr = enumTmpStr_;
            ::naeem::hottentot::generator::Runtime.enums_.push_back(pEnum);
            std::map<uint16_t, std::string>::iterator it;
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%BASE_PACKAGE_NAME%]" , basePackageName , 1);
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%INDENT%]" , indent_ , 1);
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%ENUM_NAME%]" , pEnum->GetName() , 1);
            std::string membersStr = "";
            uint8_t mapCounter = 1;
            for (std::map<uint16_t, std::string>::iterator it
             = pEnum->revItems_.begin();
             it != pEnum->revItems_.end();
             ++it) {
              std::string itemName = it->second;
              uint16_t itemValue = it->first;
              std::stringstream itemValueStr;
              itemValueStr << itemValue;
              membersStr += indent_ +  itemName + "((short) " + itemValueStr.str() +  ")";
              if(mapCounter != pEnum->revItems_.size()){
                membersStr += ",\n";
              }else {
                membersStr += ";";
              }
              mapCounter++;
            }
            ::naeem::hottentot::generator::common::StringHelper::Replace(replacableEnumTmpStr , "[%MEMBERS%]" , membersStr , 1);            std::string path = outDir_ + "/" + pEnum->GetName().c_str() + ".java";
            ::naeem::hottentot::generator::common::Os::WriteFile(path , replacableEnumTmpStr);
          }
        }

      } //END NAMESPACE JAVA
    } //END NAMESPACE GENERATOR
  } //END NAMESPACE HOTTENTOT
}  //END NAMESPACE NAEEM<|endoftext|>


<commit_before>/*******************************************************************************
 * tests/net/group_test.cpp
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#include <c7a/net/group.hpp>
#include <c7a/net/flow_control_channel.hpp>
#include <c7a/net/dispatcher.hpp>
#include <c7a/net/manager.hpp>
#include <c7a/net/collective_communication.hpp>
#include <gtest/gtest.h>

#include <thread>
#include <vector>
#include <string>
#include <random>

using namespace c7a::net;

static void ThreadInitializeAsyncRead(Group* net) {
    // send a message to all other clients except ourselves.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->connection(i).GetSocket().send(&i, sizeof(size_t));
    }

    size_t received = 0;
    Dispatcher dispatcher;

    Dispatcher::AsyncReadCallback callback =
        [net, &received](Connection& /* s */, const Buffer& buffer) {
            ASSERT_EQ(*(reinterpret_cast<const size_t*>(buffer.data())),
                      net->MyRank());
            received++;
        };

    // add async reads to net dispatcher
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        dispatcher.AsyncRead(net->connection(i), sizeof(size_t), callback);
    }

    while (received < net->Size() - 1) {
        dispatcher.Dispatch();
    }
}

static void ThreadInitializeSendCyclic(Group* net) {

    size_t id = net->MyRank();

    if (id != 0) {
        size_t res;
        net->ReceiveFrom<size_t>(id - 1, &res);
        ASSERT_EQ(id - 1, res);
    }

    if (id != net->Size() - 1) {
        net->SendTo(id + 1, id);
    }
}

static void ThreadInitializeBroadcastIntegral(Group* net) {

    static const bool debug = false;

    //Broadcast our ID to everyone
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->SendTo(i, net->MyRank());
    }

    //Receive the id from everyone. Make sure that the id is correct.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;

        size_t val;
        ClientId id;

        net->ReceiveFromAny<size_t>(&id, &val);

        LOG << "Received " << val << " from " << id;

        ASSERT_EQ((int)id, (int)val);
    }
}

static void ThreadInitializeSendReceive(Group* net) {
    static const bool debug = false;

    // send a message to all other clients except ourselves.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->SendStringTo(i, "Hello " + std::to_string(net->MyRank())
                          + " -> " + std::to_string(i));
    }
    // receive the n-1 messages from clients in order
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;

        std::string msg;
        net->ReceiveStringFrom(i, &msg);
        sLOG << "Received from client" << i << "msg" << msg;

        ASSERT_EQ(msg, "Hello " + std::to_string(i)
                  + " -> " + std::to_string(net->MyRank()));
    }

    // *****************************************************************

    // send another message to all other clients except ourselves. Now with connection access.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->connection(i).SendString("Hello " + std::to_string(net->MyRank())
                                      + " -> " + std::to_string(i));
    }
    // receive the n-1 messages from clients in any order
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;

        ClientId from;
        std::string msg;
        net->ReceiveStringFromAny(&from, &msg);
        sLOG << "Received from client" << i << "msg" << msg;

        ASSERT_EQ(msg, "Hello " + std::to_string(from)
                  + " -> " + std::to_string(net->MyRank()));
    }
}

static void ThreadInitializeSendReceiveALot(Group* net) {
    for (int i = 0; i < 100; i++) {
        ThreadInitializeSendReceive(net);
    }
}

static void ThreadInitializeSendReceiveAsyncALot(Group* net) {
    for (int i = 0; i < 100; i++) {
        ThreadInitializeAsyncRead(net);
    }
}

static void RealGroupConstructAndCall(
    std::function<void(Group*)> thread_function) {
    // randomize base port number for test
    std::random_device random_device;
    std::default_random_engine generator(random_device());
    std::uniform_int_distribution<int> distribution(10000, 30000);
    const size_t port_base = distribution(generator);

    std::vector<Endpoint> endpoints = {
        Endpoint("127.0.0.1:" + std::to_string(port_base + 0)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 1)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 2)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 3)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 4)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 5))
    };

    sLOG1 << "Group test uses ports " << port_base << "-" << port_base + 5;

    const int count = endpoints.size();

    std::vector<std::thread> threads(count);

    // lambda to construct Group and call user thread function.

    std::vector<Manager> groups(count);

    for (int i = 0; i < count; i++) {
        threads[i] = std::thread(
            [i, &endpoints, thread_function, &groups]() {
                // construct Group i with endpoints
                groups[i].Initialize(i, endpoints);
                // run thread function
                thread_function(&groups[i].GetFlowGroup());
            });
    }

    for (int i = 0; i < count; i++) {
        threads[i].join();
    }
    for (int i = 0; i < count; i++) {
        groups[i].Close();
    }
}

TEST(Group, RealInitializeAndClose) {
    // Construct a real Group of 6 workers which do nothing but terminate.
    RealGroupConstructAndCall([](Group*) { });
}

TEST(Group, RealInitializeSendReceive) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all neighbors.
    RealGroupConstructAndCall(ThreadInitializeSendReceive);
}

TEST(Group, RealInitializeSendReceiveALot) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all neighbors.
    RealGroupConstructAndCall(ThreadInitializeSendReceive);
}

TEST(Group, RealInitializeSendReceiveAsync) { //TODO(ej) test hangs from time to time
    // Construct a real Group of 6 workers which execute the thread function
    // which sends and receives asynchronous messages between all workers.
    RealGroupConstructAndCall(ThreadInitializeAsyncRead);
}

TEST(Group, RealInitializeSendReceiveAsyncALot) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all neighbors.
    RealGroupConstructAndCall(ThreadInitializeSendReceive);
}

TEST(Group, RealInitializeBroadcast) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all workers.
    RealGroupConstructAndCall(ThreadInitializeBroadcastIntegral);
}
TEST(Group, RealSendCyclic) {
    RealGroupConstructAndCall(ThreadInitializeSendCyclic);
}

TEST(Group, InitializeAndClose) {
    // Construct a Group of 6 workers which do nothing but terminate.
    Group::ExecuteLocalMock(6, [](Group*) { });
}

TEST(Group, InitializeSendReceive) {
    // Construct a Group of 6 workers which execute the thread function
    // which sends and receives asynchronous messages between all workers.
    Group::ExecuteLocalMock(6, ThreadInitializeSendReceive);
}

TEST(Group, InitializeBroadcast) {
    // Construct a Group of 6 workers which execute the thread function
    // above which sends and receives a message from all workers.
    Group::ExecuteLocalMock(6, ThreadInitializeBroadcastIntegral);
}

TEST(Group, SendCyclic) {
    Group::ExecuteLocalMock(6, ThreadInitializeSendCyclic);
}

TEST(Group, TestPrefixSum) {
    for (size_t p = 1; p <= 8; ++p) {
        // Construct Group of p workers which perform a PrefixSum collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value = 1;
                PrefixSum(*net, local_value);
                ASSERT_EQ(local_value, net->MyRank() + 1);
            });
    }
}

TEST(Group, TestAllReduce) {
    for (size_t p = 0; p <= 8; ++p) {
        // Construct Group of p workers which perform an AllReduce collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value = net->MyRank();
                AllReduce(*net, local_value);
                ASSERT_EQ(local_value, net->Size() * (net->Size() - 1) / 2);
            });
    }
}

TEST(Group, TestBroadcast) {
    for (size_t p = 0; p <= 8; ++p) {
        // Construct Group of p workers which perform an Broadcast collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value;
                if (net->MyRank() == 0) local_value = 42;
                Broadcast(*net, local_value);
                ASSERT_EQ(local_value, 42u);
            });
    }
}

TEST(Group, TestReduceToRoot) {
    for (size_t p = 0; p <= 8; ++p) {
        // Construct Group of p workers which perform an Broadcast collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value = net->MyRank();
                ReduceToRoot(*net, local_value);
                if (net->MyRank() == 0)
                    ASSERT_EQ(local_value, net->Size() * (net->Size() - 1) / 2);
            });
    }
}

TEST(Group, TestBarrier) {
    static const bool debug = false;
    std::mutex sync_mtx;            // Synchronisation mutex for the barrier
    std::mutex local_mtx;           // Mutex for writing to the results array
    std::condition_variable cv;     // Condition variable for the barrier

    for (int p = 0; p <= 8; ++p) {
        int workers = p;
        int workers_copy = workers; // Will be decremented by the barrier function

        std::vector<char> result(2 * workers);
        int k = 0;                  // The counter for the result array
        sLOG << "I'm in test" << workers;

        Group::ExecuteLocalMock(
            workers, [&](Group* net) {
                local_mtx.lock();
                result[k++] = 'B'; // B stands for 'Before barrier'
                local_mtx.unlock();

                sLOG << "Before Barrier, worker" << net->MyRank();

                ThreadBarrier(sync_mtx, cv, workers_copy);

                local_mtx.lock();
                result[k++] = 'A'; // A stands for 'After barrier'
                local_mtx.unlock();

                sLOG << "After Barrier, worker" << net->MyRank();
            });
        for (int i = 0; i < workers; ++i) {
            sLOG << "Checking position" << i;
            ASSERT_EQ(result[i], 'B');
        }
        for (int i = workers; i < 2 * workers; ++i) {
            sLOG << "Checking position" << i;
            ASSERT_EQ(result[i], 'A');
        }
    }
}

/******************************************************************************/
<commit_msg>Trivial changes int -> size_t.<commit_after>/*******************************************************************************
 * tests/net/group_test.cpp
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#include <c7a/net/group.hpp>
#include <c7a/net/flow_control_channel.hpp>
#include <c7a/net/dispatcher.hpp>
#include <c7a/net/manager.hpp>
#include <c7a/net/collective_communication.hpp>
#include <gtest/gtest.h>

#include <thread>
#include <vector>
#include <string>
#include <random>

using namespace c7a::net;

static void ThreadInitializeAsyncRead(Group* net) {
    // send a message to all other clients except ourselves.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->connection(i).GetSocket().send(&i, sizeof(size_t));
    }

    size_t received = 0;
    Dispatcher dispatcher;

    Dispatcher::AsyncReadCallback callback =
        [net, &received](Connection& /* s */, const Buffer& buffer) {
            ASSERT_EQ(*(reinterpret_cast<const size_t*>(buffer.data())),
                      net->MyRank());
            received++;
        };

    // add async reads to net dispatcher
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        dispatcher.AsyncRead(net->connection(i), sizeof(size_t), callback);
    }

    while (received < net->Size() - 1) {
        dispatcher.Dispatch();
    }
}

static void ThreadInitializeSendCyclic(Group* net) {

    size_t id = net->MyRank();

    if (id != 0) {
        size_t res;
        net->ReceiveFrom<size_t>(id - 1, &res);
        ASSERT_EQ(id - 1, res);
    }

    if (id != net->Size() - 1) {
        net->SendTo(id + 1, id);
    }
}

static void ThreadInitializeBroadcastIntegral(Group* net) {

    static const bool debug = false;

    //Broadcast our ID to everyone
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->SendTo(i, net->MyRank());
    }

    //Receive the id from everyone. Make sure that the id is correct.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;

        size_t val;
        ClientId id;

        net->ReceiveFromAny<size_t>(&id, &val);

        LOG << "Received " << val << " from " << id;

        ASSERT_EQ((int)id, (int)val);
    }
}

static void ThreadInitializeSendReceive(Group* net) {
    static const bool debug = false;

    // send a message to all other clients except ourselves.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->SendStringTo(i, "Hello " + std::to_string(net->MyRank())
                          + " -> " + std::to_string(i));
    }
    // receive the n-1 messages from clients in order
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;

        std::string msg;
        net->ReceiveStringFrom(i, &msg);
        sLOG << "Received from client" << i << "msg" << msg;

        ASSERT_EQ(msg, "Hello " + std::to_string(i)
                  + " -> " + std::to_string(net->MyRank()));
    }

    // *****************************************************************

    // send another message to all other clients except ourselves. Now with connection access.
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;
        net->connection(i).SendString("Hello " + std::to_string(net->MyRank())
                                      + " -> " + std::to_string(i));
    }
    // receive the n-1 messages from clients in any order
    for (size_t i = 0; i != net->Size(); ++i)
    {
        if (i == net->MyRank()) continue;

        ClientId from;
        std::string msg;
        net->ReceiveStringFromAny(&from, &msg);
        sLOG << "Received from client" << i << "msg" << msg;

        ASSERT_EQ(msg, "Hello " + std::to_string(from)
                  + " -> " + std::to_string(net->MyRank()));
    }
}

static void ThreadInitializeSendReceiveALot(Group* net) {
    for (int i = 0; i < 100; i++) {
        ThreadInitializeSendReceive(net);
    }
}

static void ThreadInitializeSendReceiveAsyncALot(Group* net) {
    for (int i = 0; i < 100; i++) {
        ThreadInitializeAsyncRead(net);
    }
}

static void RealGroupConstructAndCall(
    std::function<void(Group*)> thread_function) {
    // randomize base port number for test
    std::random_device random_device;
    std::default_random_engine generator(random_device());
    std::uniform_int_distribution<int> distribution(10000, 30000);
    const size_t port_base = distribution(generator);

    std::vector<Endpoint> endpoints = {
        Endpoint("127.0.0.1:" + std::to_string(port_base + 0)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 1)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 2)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 3)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 4)),
        Endpoint("127.0.0.1:" + std::to_string(port_base + 5))
    };

    sLOG1 << "Group test uses ports" << port_base << "-" << port_base + 5;

    const size_t count = endpoints.size();

    std::vector<std::thread> threads(count);

    // lambda to construct Group and call user thread function.

    std::vector<Manager> groups(count);

    for (size_t i = 0; i < count; i++) {
        threads[i] = std::thread(
            [i, &endpoints, thread_function, &groups]() {
                // construct Group i with endpoints
                groups[i].Initialize(i, endpoints);
                // run thread function
                thread_function(&groups[i].GetFlowGroup());
            });
    }

    for (size_t i = 0; i < count; i++) {
        threads[i].join();
    }
    for (size_t i = 0; i < count; i++) {
        groups[i].Close();
    }
}

TEST(Group, RealInitializeAndClose) {
    // Construct a real Group of 6 workers which do nothing but terminate.
    RealGroupConstructAndCall([](Group*) { });
}

TEST(Group, RealInitializeSendReceive) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all neighbors.
    RealGroupConstructAndCall(ThreadInitializeSendReceive);
}

TEST(Group, RealInitializeSendReceiveALot) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all neighbors.
    RealGroupConstructAndCall(ThreadInitializeSendReceive);
}

TEST(Group, RealInitializeSendReceiveAsync) { //TODO(ej) test hangs from time to time
    // Construct a real Group of 6 workers which execute the thread function
    // which sends and receives asynchronous messages between all workers.
    RealGroupConstructAndCall(ThreadInitializeAsyncRead);
}

TEST(Group, RealInitializeSendReceiveAsyncALot) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all neighbors.
    RealGroupConstructAndCall(ThreadInitializeSendReceive);
}

TEST(Group, RealInitializeBroadcast) {
    // Construct a real Group of 6 workers which execute the thread function
    // above which sends and receives a message from all workers.
    RealGroupConstructAndCall(ThreadInitializeBroadcastIntegral);
}
TEST(Group, RealSendCyclic) {
    RealGroupConstructAndCall(ThreadInitializeSendCyclic);
}

TEST(Group, InitializeAndClose) {
    // Construct a Group of 6 workers which do nothing but terminate.
    Group::ExecuteLocalMock(6, [](Group*) { });
}

TEST(Group, InitializeSendReceive) {
    // Construct a Group of 6 workers which execute the thread function
    // which sends and receives asynchronous messages between all workers.
    Group::ExecuteLocalMock(6, ThreadInitializeSendReceive);
}

TEST(Group, InitializeBroadcast) {
    // Construct a Group of 6 workers which execute the thread function
    // above which sends and receives a message from all workers.
    Group::ExecuteLocalMock(6, ThreadInitializeBroadcastIntegral);
}

TEST(Group, SendCyclic) {
    Group::ExecuteLocalMock(6, ThreadInitializeSendCyclic);
}

TEST(Group, TestPrefixSum) {
    for (size_t p = 1; p <= 8; ++p) {
        // Construct Group of p workers which perform a PrefixSum collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value = 1;
                PrefixSum(*net, local_value);
                ASSERT_EQ(local_value, net->MyRank() + 1);
            });
    }
}

TEST(Group, TestAllReduce) {
    for (size_t p = 0; p <= 8; ++p) {
        // Construct Group of p workers which perform an AllReduce collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value = net->MyRank();
                AllReduce(*net, local_value);
                ASSERT_EQ(local_value, net->Size() * (net->Size() - 1) / 2);
            });
    }
}

TEST(Group, TestBroadcast) {
    for (size_t p = 0; p <= 8; ++p) {
        // Construct Group of p workers which perform an Broadcast collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value;
                if (net->MyRank() == 0) local_value = 42;
                Broadcast(*net, local_value);
                ASSERT_EQ(local_value, 42u);
            });
    }
}

TEST(Group, TestReduceToRoot) {
    for (size_t p = 0; p <= 8; ++p) {
        // Construct Group of p workers which perform an Broadcast collective
        Group::ExecuteLocalMock(
            p, [](Group* net) {
                size_t local_value = net->MyRank();
                ReduceToRoot(*net, local_value);
                if (net->MyRank() == 0)
                    ASSERT_EQ(local_value, net->Size() * (net->Size() - 1) / 2);
            });
    }
}

TEST(Group, TestBarrier) {
    static const bool debug = false;
    std::mutex sync_mtx;            // Synchronisation mutex for the barrier
    std::mutex local_mtx;           // Mutex for writing to the results array
    std::condition_variable cv;     // Condition variable for the barrier

    for (int p = 0; p <= 8; ++p) {
        int workers = p;
        int workers_copy = workers; // Will be decremented by the barrier function

        std::vector<char> result(2 * workers);
        int k = 0;                  // The counter for the result array
        sLOG << "I'm in test" << workers;

        Group::ExecuteLocalMock(
            workers, [&](Group* net) {
                local_mtx.lock();
                result[k++] = 'B'; // B stands for 'Before barrier'
                local_mtx.unlock();

                sLOG << "Before Barrier, worker" << net->MyRank();

                ThreadBarrier(sync_mtx, cv, workers_copy);

                local_mtx.lock();
                result[k++] = 'A'; // A stands for 'After barrier'
                local_mtx.unlock();

                sLOG << "After Barrier, worker" << net->MyRank();
            });
        for (int i = 0; i < workers; ++i) {
            sLOG << "Checking position" << i;
            ASSERT_EQ(result[i], 'B');
        }
        for (int i = workers; i < 2 * workers; ++i) {
            sLOG << "Checking position" << i;
            ASSERT_EQ(result[i], 'A');
        }
    }
}

/******************************************************************************/
<|endoftext|>


<commit_before>#include "BoundsInference.h"
#include "IRMutator.h"
#include "Scope.h"
#include "Bounds.h"
#include "Debug.h"
#include <sstream>

namespace Halide {
namespace Internal {

using std::string;
using std::ostringstream;
using std::vector;
using std::map;

// Inject let stmts defining the bounds of a function required at each loop level
class BoundsInference : public IRMutator {
public:
    const vector<string> &funcs;
    const map<string, Function> &env;
    Scope<int> in_update;

    BoundsInference(const vector<string> &f, const map<string, Function> &e) : funcs(f), env(e) {}

    using IRMutator::visit;

    virtual void visit(const For *for_loop) {

        // Compute the region required of each function within this loop body
        map<string, Region> regions = regions_called(for_loop->body);

        Stmt body = mutate(for_loop->body);

        debug(3) << "Bounds inference considering loop over " << for_loop->name << '\n';

        // Inject let statements defining those bounds
        for (size_t i = 0; i < funcs.size(); i++) {
            if (in_update.contains(funcs[i])) continue;
            const Region &region = regions[funcs[i]];
            const Function &f = env.find(funcs[i])->second;
            if (region.empty()) continue;
            debug(3) << "Injecting bounds for " << funcs[i] << '\n';
            assert(region.size() == f.args().size() && "Dimensionality mismatch between function and region required");
            for (size_t j = 0; j < region.size(); j++) {
                const string &arg_name = f.args()[j];
                body = LetStmt::make(f.name() + "." + arg_name + ".min", region[j].min, body);
                body = LetStmt::make(f.name() + "." + arg_name + ".extent", region[j].extent, body);
            }
        }

        if (body.same_as(for_loop->body)) {
            stmt = for_loop;
        } else {
            stmt = For::make(for_loop->name, for_loop->min, for_loop->extent, for_loop->for_type, body);
        }
    }

    virtual void visit(const Pipeline *pipeline) {
        Stmt produce = mutate(pipeline->produce);

        Stmt update;
        if (pipeline->update.defined()) {
            // Even though there are calls to a function within the
            // update step of a pipeline, we shouldn't modify the
            // bounds computed - they've already been fixed. Any
            // dependencies required should have been scheduled within
            // the initialization, not the update step, so these
            // bounds can't be of use to anyone anyway.
            in_update.push(pipeline->name, 0);
            update = mutate(pipeline->update);
            in_update.pop(pipeline->name);
        }
        Stmt consume = mutate(pipeline->consume);
        stmt = Pipeline::make(pipeline->name, produce, update, consume);
    }
};

Stmt bounds_inference(Stmt s, const vector<string> &order, const map<string, Function> &env) {
    // Add a outermost::make loop to make sure we get outermost bounds definitions too
    s = For::make("outermost", 0, 1, For::Serial, s);

    s = BoundsInference(order, env).mutate(s);

    // We can remove the loop over root now
    const For *root_loop = s.as<For>();
    assert(root_loop);
    s = root_loop->body;

    // For the output function, the bounds required is the size of the buffer
    Function f = env.find(order[order.size()-1])->second;
    for (size_t i = 0; i < f.args().size(); i++) {
        debug(2) << f.name() << ", " << f.args()[i] << "\n";
        ostringstream buf_min_name, buf_extent_name;
        buf_min_name << f.name() << ".min." << i;
        buf_extent_name << f.name() << ".extent." << i;
        Expr buf_min = Variable::make(Int(32), buf_min_name.str());
        Expr buf_extent = Variable::make(Int(32), buf_extent_name.str());
        s = LetStmt::make(f.name() + "." + f.args()[i] + ".min", buf_min, s);
        s = LetStmt::make(f.name() + "." + f.args()[i] + ".extent", buf_extent, s);
    }

    return s;
}

}
}
<commit_msg>Resoect constraints when defining bounds of the output.<commit_after>#include "BoundsInference.h"
#include "IRMutator.h"
#include "Scope.h"
#include "Bounds.h"
#include "Debug.h"
#include <sstream>

namespace Halide {
namespace Internal {

using std::string;
using std::ostringstream;
using std::vector;
using std::map;

// Inject let stmts defining the bounds of a function required at each loop level
class BoundsInference : public IRMutator {
public:
    const vector<string> &funcs;
    const map<string, Function> &env;
    Scope<int> in_update;

    BoundsInference(const vector<string> &f, const map<string, Function> &e) : funcs(f), env(e) {}

    using IRMutator::visit;

    virtual void visit(const For *for_loop) {

        // Compute the region required of each function within this loop body
        map<string, Region> regions = regions_called(for_loop->body);

        Stmt body = mutate(for_loop->body);

        debug(3) << "Bounds inference considering loop over " << for_loop->name << '\n';

        // Inject let statements defining those bounds
        for (size_t i = 0; i < funcs.size(); i++) {
            if (in_update.contains(funcs[i])) continue;
            const Region &region = regions[funcs[i]];
            const Function &f = env.find(funcs[i])->second;
            if (region.empty()) continue;
            debug(3) << "Injecting bounds for " << funcs[i] << '\n';
            assert(region.size() == f.args().size() && "Dimensionality mismatch between function and region required");
            for (size_t j = 0; j < region.size(); j++) {
                const string &arg_name = f.args()[j];
                body = LetStmt::make(f.name() + "." + arg_name + ".min", region[j].min, body);
                body = LetStmt::make(f.name() + "." + arg_name + ".extent", region[j].extent, body);
            }
        }

        if (body.same_as(for_loop->body)) {
            stmt = for_loop;
        } else {
            stmt = For::make(for_loop->name, for_loop->min, for_loop->extent, for_loop->for_type, body);
        }
    }

    virtual void visit(const Pipeline *pipeline) {
        Stmt produce = mutate(pipeline->produce);

        Stmt update;
        if (pipeline->update.defined()) {
            // Even though there are calls to a function within the
            // update step of a pipeline, we shouldn't modify the
            // bounds computed - they've already been fixed. Any
            // dependencies required should have been scheduled within
            // the initialization, not the update step, so these
            // bounds can't be of use to anyone anyway.
            in_update.push(pipeline->name, 0);
            update = mutate(pipeline->update);
            in_update.pop(pipeline->name);
        }
        Stmt consume = mutate(pipeline->consume);
        stmt = Pipeline::make(pipeline->name, produce, update, consume);
    }
};

Stmt bounds_inference(Stmt s, const vector<string> &order, const map<string, Function> &env) {
    // Add a outermost::make loop to make sure we get outermost bounds definitions too
    s = For::make("outermost", 0, 1, For::Serial, s);

    s = BoundsInference(order, env).mutate(s);

    // We can remove the loop over root now
    const For *root_loop = s.as<For>();
    assert(root_loop);
    s = root_loop->body;

    // For the output function, the bounds required is the (possibly constrained) size of the buffer
    Function f = env.find(order[order.size()-1])->second;
    Parameter b = f.output_buffer();
    for (size_t i = 0; i < f.args().size(); i++) {
        debug(2) << f.name() << ", " << f.args()[i] << "\n";

        string prefix = f.name() + "." + f.args()[i];
        char dim = '0' + i;

        if (b.min_constraint(i).defined()) {
            s = LetStmt::make(prefix + ".min", b.min_constraint(i), s);
        } else {
            string buf_min_name = f.name() + ".min." + dim;
            Expr buf_min = Variable::make(Int(32), buf_min_name);
            s = LetStmt::make(prefix + ".min", buf_min, s);
        }

        if (b.extent_constraint(i).defined()) {
            s = LetStmt::make(prefix + ".extent", b.extent_constraint(i), s);
        } else {
            string buf_extent_name = f.name() + ".extent." + dim;
            Expr buf_extent = Variable::make(Int(32), buf_extent_name);
            s = LetStmt::make(prefix + ".extent", buf_extent, s);
        }

    }

    return s;
}

}
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-2014 Damien Tardy-Panis
 *
 * This file is subject to the terms and conditions defined in
 * file 'LICENSE', which is part of this source code package.
 **/

#include "Channel.h"

#include <QDebug>

Channel::Channel(QObject *parent) :
    XmlItem(parent),
    m_id(""),
    m_name(""),
    m_description(""),
    m_imageUrl(""),
    m_imageMediumUrl(""),
    m_imageBigUrl(""),
    m_dj(""),
    m_djMail(""),
    m_genres(""),
    m_listeners(-1),
    m_sortGenre(""),
    m_maximumListeners(0),
    m_mp3Pls(QMap<StreamQuality, QUrl>()),
    m_aacPls(QMap<StreamQuality, QUrl>()),
    m_aacpPls(QMap<StreamQuality, QUrl>())
{
}

QHash<int, QByteArray> Channel::roleNames()
{
    QHash<int, QByteArray> roleNames = XmlItem::roleNames();

    roleNames[IdRole] = "id";
    roleNames[NameRole] = "name";
    roleNames[DescriptionRole] = "description";
    roleNames[ImageUrlRole] = "imageUrl";
    roleNames[ImageMediumUrlRole] = "imageMediumUrl";
    roleNames[ImageBigUrlRole] = "imageBigUrl";
    roleNames[DjRole] = "dj";
    roleNames[DjMailRole] = "djMail";
    roleNames[GenresRole] = "genres";
    roleNames[ListenersRole] = "listeners";
    roleNames[SortGenreRole] = "sortGenre";
    roleNames[MaximumListenersRole] = "maximumListeners";

    return roleNames;
}

QHash<int, QByteArray> Channel::bookmarkRoleNames()
{
    QHash<int, QByteArray> bookmarkRoleNames = XmlItem::bookmarkRoleNames();

    bookmarkRoleNames[IdRole] = "id";
    bookmarkRoleNames[NameRole] = "name";

    return bookmarkRoleNames;
}

QHash<int, QByteArray> Channel::idRoleNames()
{
    QHash<int, QByteArray> idRoleNames;

    idRoleNames[IdRole] = "id";

    return idRoleNames;
}

QVariant Channel::data(int role) const
{
    switch(role) {
    case IdRole:
        return id();
    case NameRole:
        return name();
    case DescriptionRole:
        return description();
    case ImageUrlRole:
        return imageUrl();
    case ImageMediumUrlRole:
        return imageMediumUrl();
    case ImageBigUrlRole:
        return imageBigUrl();
    case DjRole:
        return dj();
    case DjMailRole:
        return djMail();
    case GenresRole:
        return genres();
    case ListenersRole:
        return listeners();
    case SortGenreRole:
        return sortGenre();
    case MaximumListenersRole:
        return maximumListeners();
    }

    return XmlItem::data(role);
}

bool Channel::setData(const QVariant &value, int role)
{
    switch(role) {
    case IdRole:
        setId(value.toString());
        return true;
    case NameRole:
        setName(value.toString());
        return true;
    case DescriptionRole:
        setDescription(value.toString());
        return true;
    case ImageUrlRole:
        setImageUrl(value.toUrl());
        return true;
    case ImageMediumUrlRole:
        setImageMediumUrl(value.toUrl());
        return true;
    case ImageBigUrlRole:
        setImageBigUrl(value.toUrl());
        return true;
    case DjRole:
        setDj(value.toString());
        return true;
    case DjMailRole:
        setDjMail(value.toString());
        return true;
    case GenresRole:
        setGenres(value.toStringList());
        return true;
    case ListenersRole:
        setListeners(value.toInt());
        return true;
    case SortGenreRole:
        setSortGenre(value.toString());
        return true;
    case MaximumListenersRole:
        setMaximumListeners(value.toInt());
        return true;
    }

    return XmlItem::setData(value, role);
}

XmlItem *Channel::create(QObject *parent)
{
    return new Channel(parent);
}

XmlItem *Channel::clone()
{
    Channel* newChannel = (Channel*) XmlItem::clone();

    StreamQuality quality;
    StreamFormat format;
    QUrl pls;

    for (int f = FirstFormat; f <= LastFormat; ++f) {
        format = (StreamFormat) f;
        QMapIterator<StreamQuality, QUrl> iterator(plsContainer(format));
        while (iterator.hasNext()) {
            iterator.next();
            quality = iterator.key();
            pls = iterator.value();
            newChannel->addPls(pls, format, quality);
        }
    }

    return newChannel;
}

void Channel::addPls(QUrl pls, StreamFormat format, StreamQuality quality)
{
    switch (format) {
    case Mp3Format:
        m_mp3Pls.insertMulti(quality, pls);
        break;
    case AacFormat:
        m_aacPls.insertMulti(quality, pls);
        break;
    case AacPlusFormat:
        m_aacpPls.insertMulti(quality, pls);
        break;
    }
}

QMap<Channel::StreamQuality, QMap<Channel::StreamFormat, QUrl> > Channel::getAllPlsQuality()
{
    QMap<StreamQuality, QMap<StreamFormat, QUrl> > result;
    QMap<StreamFormat, QUrl> qualityPls;
    StreamQuality quality;

    for (int q = FirstQuality; q <= LastQuality; ++q) {
        quality = (StreamQuality) q;
        qualityPls.clear();

        if (m_aacpPls.contains(quality))
            qualityPls.insert(AacPlusFormat, m_aacpPls.value(quality));
        if (m_aacPls.contains(quality))
            qualityPls.insert(AacFormat, m_aacPls.value(quality));
        if (m_mp3Pls.contains(quality))
            qualityPls.insert(Mp3Format, m_mp3Pls.value(quality));

        if (!qualityPls.empty())
            result.insert(quality, qualityPls);
    }

    return result;
}

QString Channel::streamQualityText(Channel::StreamQuality quality)
{
    switch (quality) {
    case TopQuality:
        return "Top";
    case GoodQuality:
        return "Good";
    case LowQuality:
        return "Low";
    }

    return defaultStreamQualityText();
}

Channel::StreamQuality Channel::streamQuality(QString quality)
{
    if (quality.compare("top", Qt::CaseInsensitive) == 0) {
        return TopQuality;
    } else if (quality.compare("good", Qt::CaseInsensitive) == 0) {
        return GoodQuality;
    } else if (quality.compare("low", Qt::CaseInsensitive) == 0) {
        return LowQuality;
    }

    return defaultStreamQuality();
}

QString Channel::streamFormatText(Channel::StreamFormat format)
{
    switch (format) {
    case AacPlusFormat:
        return "AAC+";
    case AacFormat:
        return "AAC";
    case Mp3Format:
        return "MP3";
    }

    return defaultStreamFormatText();
}

Channel::StreamFormat Channel::streamFormat(QString format)
{
    if (format.compare("aac+", Qt::CaseInsensitive) == 0) {
        return AacPlusFormat;
    } else if (format.compare("aac", Qt::CaseInsensitive) == 0) {
        return AacFormat;
    } else if (format.compare("mp3", Qt::CaseInsensitive) == 0) {
        return Mp3Format;
    }

    return defaultStreamFormat();
}

Channel::StreamQuality Channel::defaultStreamQuality()
{
    return GoodQuality;
}

Channel::StreamFormat Channel::defaultStreamFormat()
{
    return AacFormat;
}

QString Channel::defaultStreamQualityText()
{
    return streamQualityText(defaultStreamQuality());
}

QString Channel::defaultStreamFormatText()
{
    return streamFormatText(defaultStreamFormat());
}

QList<QString> Channel::streamQualityTextList()
{
    QList<QString> qualities;
    for (int q = FirstQuality; q <= LastQuality; ++q) {
        qualities.append(streamQualityText( (Channel::StreamQuality) q ));
    }
    return qualities;
}

QList<QString> Channel::streamFormatTextList()
{
    QList<QString> formats;
    for (int f = FirstFormat; f <= LastFormat; ++f) {
        formats.append(streamFormatText( (Channel::StreamFormat) f ));
    }
    return formats;
}

QMap<Channel::StreamQuality, QUrl> Channel::plsContainer(Channel::StreamFormat format)
{
    switch (format) {
    case AacPlusFormat:
        return m_aacpPls;
    case AacFormat:
        return m_aacPls;
    case Mp3Format:
        return m_mp3Pls;
    }

    return QMap<StreamQuality, QUrl>();
}
<commit_msg>mp3 is default stream format as AAC streaming is not working (by default at least)<commit_after>/**
 * Copyright (c) 2013-2014 Damien Tardy-Panis
 *
 * This file is subject to the terms and conditions defined in
 * file 'LICENSE', which is part of this source code package.
 **/

#include "Channel.h"

#include <QDebug>

Channel::Channel(QObject *parent) :
    XmlItem(parent),
    m_id(""),
    m_name(""),
    m_description(""),
    m_imageUrl(""),
    m_imageMediumUrl(""),
    m_imageBigUrl(""),
    m_dj(""),
    m_djMail(""),
    m_genres(""),
    m_listeners(-1),
    m_sortGenre(""),
    m_maximumListeners(0),
    m_mp3Pls(QMap<StreamQuality, QUrl>()),
    m_aacPls(QMap<StreamQuality, QUrl>()),
    m_aacpPls(QMap<StreamQuality, QUrl>())
{
}

QHash<int, QByteArray> Channel::roleNames()
{
    QHash<int, QByteArray> roleNames = XmlItem::roleNames();

    roleNames[IdRole] = "id";
    roleNames[NameRole] = "name";
    roleNames[DescriptionRole] = "description";
    roleNames[ImageUrlRole] = "imageUrl";
    roleNames[ImageMediumUrlRole] = "imageMediumUrl";
    roleNames[ImageBigUrlRole] = "imageBigUrl";
    roleNames[DjRole] = "dj";
    roleNames[DjMailRole] = "djMail";
    roleNames[GenresRole] = "genres";
    roleNames[ListenersRole] = "listeners";
    roleNames[SortGenreRole] = "sortGenre";
    roleNames[MaximumListenersRole] = "maximumListeners";

    return roleNames;
}

QHash<int, QByteArray> Channel::bookmarkRoleNames()
{
    QHash<int, QByteArray> bookmarkRoleNames = XmlItem::bookmarkRoleNames();

    bookmarkRoleNames[IdRole] = "id";
    bookmarkRoleNames[NameRole] = "name";

    return bookmarkRoleNames;
}

QHash<int, QByteArray> Channel::idRoleNames()
{
    QHash<int, QByteArray> idRoleNames;

    idRoleNames[IdRole] = "id";

    return idRoleNames;
}

QVariant Channel::data(int role) const
{
    switch(role) {
    case IdRole:
        return id();
    case NameRole:
        return name();
    case DescriptionRole:
        return description();
    case ImageUrlRole:
        return imageUrl();
    case ImageMediumUrlRole:
        return imageMediumUrl();
    case ImageBigUrlRole:
        return imageBigUrl();
    case DjRole:
        return dj();
    case DjMailRole:
        return djMail();
    case GenresRole:
        return genres();
    case ListenersRole:
        return listeners();
    case SortGenreRole:
        return sortGenre();
    case MaximumListenersRole:
        return maximumListeners();
    }

    return XmlItem::data(role);
}

bool Channel::setData(const QVariant &value, int role)
{
    switch(role) {
    case IdRole:
        setId(value.toString());
        return true;
    case NameRole:
        setName(value.toString());
        return true;
    case DescriptionRole:
        setDescription(value.toString());
        return true;
    case ImageUrlRole:
        setImageUrl(value.toUrl());
        return true;
    case ImageMediumUrlRole:
        setImageMediumUrl(value.toUrl());
        return true;
    case ImageBigUrlRole:
        setImageBigUrl(value.toUrl());
        return true;
    case DjRole:
        setDj(value.toString());
        return true;
    case DjMailRole:
        setDjMail(value.toString());
        return true;
    case GenresRole:
        setGenres(value.toStringList());
        return true;
    case ListenersRole:
        setListeners(value.toInt());
        return true;
    case SortGenreRole:
        setSortGenre(value.toString());
        return true;
    case MaximumListenersRole:
        setMaximumListeners(value.toInt());
        return true;
    }

    return XmlItem::setData(value, role);
}

XmlItem *Channel::create(QObject *parent)
{
    return new Channel(parent);
}

XmlItem *Channel::clone()
{
    Channel* newChannel = (Channel*) XmlItem::clone();

    StreamQuality quality;
    StreamFormat format;
    QUrl pls;

    for (int f = FirstFormat; f <= LastFormat; ++f) {
        format = (StreamFormat) f;
        QMapIterator<StreamQuality, QUrl> iterator(plsContainer(format));
        while (iterator.hasNext()) {
            iterator.next();
            quality = iterator.key();
            pls = iterator.value();
            newChannel->addPls(pls, format, quality);
        }
    }

    return newChannel;
}

void Channel::addPls(QUrl pls, StreamFormat format, StreamQuality quality)
{
    switch (format) {
    case Mp3Format:
        m_mp3Pls.insertMulti(quality, pls);
        break;
    case AacFormat:
        m_aacPls.insertMulti(quality, pls);
        break;
    case AacPlusFormat:
        m_aacpPls.insertMulti(quality, pls);
        break;
    }
}

QMap<Channel::StreamQuality, QMap<Channel::StreamFormat, QUrl> > Channel::getAllPlsQuality()
{
    QMap<StreamQuality, QMap<StreamFormat, QUrl> > result;
    QMap<StreamFormat, QUrl> qualityPls;
    StreamQuality quality;

    for (int q = FirstQuality; q <= LastQuality; ++q) {
        quality = (StreamQuality) q;
        qualityPls.clear();

        if (m_aacpPls.contains(quality))
            qualityPls.insert(AacPlusFormat, m_aacpPls.value(quality));
        if (m_aacPls.contains(quality))
            qualityPls.insert(AacFormat, m_aacPls.value(quality));
        if (m_mp3Pls.contains(quality))
            qualityPls.insert(Mp3Format, m_mp3Pls.value(quality));

        if (!qualityPls.empty())
            result.insert(quality, qualityPls);
    }

    return result;
}

QString Channel::streamQualityText(Channel::StreamQuality quality)
{
    switch (quality) {
    case TopQuality:
        return "Top";
    case GoodQuality:
        return "Good";
    case LowQuality:
        return "Low";
    }

    return defaultStreamQualityText();
}

Channel::StreamQuality Channel::streamQuality(QString quality)
{
    if (quality.compare("top", Qt::CaseInsensitive) == 0) {
        return TopQuality;
    } else if (quality.compare("good", Qt::CaseInsensitive) == 0) {
        return GoodQuality;
    } else if (quality.compare("low", Qt::CaseInsensitive) == 0) {
        return LowQuality;
    }

    return defaultStreamQuality();
}

QString Channel::streamFormatText(Channel::StreamFormat format)
{
    switch (format) {
    case AacPlusFormat:
        return "AAC+";
    case AacFormat:
        return "AAC";
    case Mp3Format:
        return "MP3";
    }

    return defaultStreamFormatText();
}

Channel::StreamFormat Channel::streamFormat(QString format)
{
    if (format.compare("aac+", Qt::CaseInsensitive) == 0) {
        return AacPlusFormat;
    } else if (format.compare("aac", Qt::CaseInsensitive) == 0) {
        return AacFormat;
    } else if (format.compare("mp3", Qt::CaseInsensitive) == 0) {
        return Mp3Format;
    }

    return defaultStreamFormat();
}

Channel::StreamQuality Channel::defaultStreamQuality()
{
    return GoodQuality;
}

Channel::StreamFormat Channel::defaultStreamFormat()
{
    return Mp3Format;
}

QString Channel::defaultStreamQualityText()
{
    return streamQualityText(defaultStreamQuality());
}

QString Channel::defaultStreamFormatText()
{
    return streamFormatText(defaultStreamFormat());
}

QList<QString> Channel::streamQualityTextList()
{
    QList<QString> qualities;
    for (int q = FirstQuality; q <= LastQuality; ++q) {
        qualities.append(streamQualityText( (Channel::StreamQuality) q ));
    }
    return qualities;
}

QList<QString> Channel::streamFormatTextList()
{
    QList<QString> formats;
    for (int f = FirstFormat; f <= LastFormat; ++f) {
        formats.append(streamFormatText( (Channel::StreamFormat) f ));
    }
    return formats;
}

QMap<Channel::StreamQuality, QUrl> Channel::plsContainer(Channel::StreamFormat format)
{
    switch (format) {
    case AacPlusFormat:
        return m_aacpPls;
    case AacFormat:
        return m_aacPls;
    case Mp3Format:
        return m_mp3Pls;
    }

    return QMap<StreamQuality, QUrl>();
}
<|endoftext|>


<commit_before>#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <port.hpp>
#include <usi.hpp>
#include <radio.hpp>
#include <interrupt/PCINT0.hpp>
#include <sensorvalue.hpp>
#include <txuart.hpp>

typedef Radio<CC1101::CC1101<USI, Pin<Port<A>, 7>>> radio;
typedef TXUart<Pin<Port<B>, 0>, 1000000, 38400> txuart;

static void txbyte(unsigned char byte)
{
	static char nibble[] = "0123456789abcdef";
	txuart::txbyte(nibble[byte >> 4]);
	txuart::txbyte(nibble[byte & 15]);
}

static void txdata(unsigned char* data, unsigned char len)
{
	cli();
	for (;len > 0; --len) {
		txbyte(*data++);
	}
	txuart::txbyte('\n');
	sei();
}

static void receive()
{
	while (radio::USI::DI::is_set()) {
		radio::select();
		unsigned char rxbytes = radio::status<CC1101::RXBYTES>();
		unsigned char d[rxbytes];
		radio::read_rxfifo(d, rxbytes);
		if (rxbytes == 34) {
			SensorValue<RSSI>::encode(static_cast<int>(d[32]) - 148, d + d[0]);
			d[0] += 2;
			txdata(d, d[0]);
		}
	}
}

static void receive_loop()
{
	radio::select();
	radio::wcmd<CC1101::SRX>();
	radio::release();
	PCINT0Interrupt::set(receive);

	while(1) {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		sleep_mode();
		PCINT0Interrupt::pending();
	}
}

int main()
{
	txuart::Pin::mode(OUTPUT);
	txuart::Pin::set();

	radio::setup();
	radio::setup_for_rx();
	radio::select();
	radio::set<CC1101::IOCFG2>(0x7);
	radio::set<CC1101::IOCFG1>(0x7);
	radio::release();

	GIMSK |= _BV(PCIE0);
	PCMSK0 |= _BV(radio::USI::DI::pin);

	sei();

	receive_loop();
}
<commit_msg>receiver: uart at 230400 baud with 8mHz system clock<commit_after>#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <port.hpp>
#include <usi.hpp>
#include <radio.hpp>
#include <interrupt/PCINT0.hpp>
#include <sensorvalue.hpp>
#include <txuart.hpp>

typedef Radio<CC1101::CC1101<USI, Pin<Port<A>, 7>>> radio;
typedef TXUart<Pin<Port<B>, 0>, 8000000, 230400> txuart;

static void txbyte(unsigned char byte)
{
	static char nibble[] = "0123456789abcdef";
	txuart::txbyte(nibble[byte >> 4]);
	txuart::txbyte(nibble[byte & 15]);
}

static void txdata(unsigned char* data, unsigned char len)
{
	cli();
	for (;len > 0; --len) {
		txbyte(*data++);
	}
	txuart::txbyte('\n');
	sei();
}

static void receive()
{
	while (radio::USI::DI::is_set()) {
		radio::select();
		unsigned char rxbytes = radio::status<CC1101::RXBYTES>();
		unsigned char d[rxbytes];
		radio::read_rxfifo(d, rxbytes);
		if (rxbytes == 34) {
			SensorValue<RSSI>::encode(static_cast<int>(d[32]) - 148, d + d[0]);
			d[0] += 2;
			txdata(d, d[0]);
		}
	}
}

static void receive_loop()
{
	radio::select();
	radio::wcmd<CC1101::SRX>();
	radio::release();
	PCINT0Interrupt::set(receive);

	while(1) {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		sleep_mode();
		PCINT0Interrupt::pending();
	}
}

int main()
{
	txuart::Pin::mode(OUTPUT);
	txuart::Pin::set();

	radio::setup();
	radio::setup_for_rx();
	radio::select();
	radio::set<CC1101::IOCFG2>(0x7);
	radio::set<CC1101::IOCFG1>(0x7);
	radio::release();

	GIMSK |= _BV(PCIE0);
	PCMSK0 |= _BV(radio::USI::DI::pin);

	sei();

	receive_loop();
}
<|endoftext|>