<commit_before>/* vi: set et sw=4 ts=4 cino=t0,(0: */
/*
 * This file is part of libaccounts-qt
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This 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 "account-service.h"
#include "manager.h"
#include "utils.h"
#include <libaccounts-glib/ag-account.h>
#include <libaccounts-glib/ag-account-service.h>

namespace Accounts
{

/*!
 * @class AccountService
 *
 * @brief Account settings for a specific service
 *
 * @details The AccountService class provides access to the account settings
 * for a specific service type. It is meant to be easier to use than the
 * Account class because it hides the complexity of the account structure and
 * gives access to only the limited subset of account settings which are
 * relevant to a service.
 *
 * To get an AccountService one can use the Manager methods accountServices()
 * or enabledAccountServices(), which both return a QList of account services.
 * Note that if the Manager was instantiated for a specific service type, these
 * lists will contain only those account services matching that service type.
 * The AccountService can also be instantiated with its AccountService(Account
 * *account, Service *service) constructor: this is useful if one already has
 * an Account instance.
 *
 * This is intended to be a convenient wrapper over the accounts settings
 * specific for a service; as such, it doesn't offer all the editing
 * possibilities offered by the Account class, such as enabling the service
 * itself: these operations should ideally not be performed by consumer
 * applications, but by the account editing UI only.
 *
 * Example code:
 * @code
 * // Instantiate an account manager interested in e-mail services only.
 * Accounts::Manager *manager = new Accounts::Manager("e-mail");
 *
 * // Get the list of enabled AccountService objects of type e-mail.
 * Accounts::AccountServiceList services = manager->enabledAccountServices();
 *
 * // Loop through the account services and do something useful with them.
 * foreach (Accounts::AccountService *service, services) {
 *     QString server = service->value("pop3/hostname").toString();
 *     int port = service->value("pop3/port").toInt();
 *
 *     // Suppose that the e-mail address is stored in the global account
 *     // settings; let's get it from there:
 *     QString fromAddress = service->account()->valueAsString("username");
 *
 *     ...
 * }
 * @endcode
 *
 * User applications (with the notable exception of the accounts editing
 * application) should never use account services which are not enabled, and
 * should stop using an account when the account service becomes disabled. The
 * latter can be done by connecting to the changed() signal and checking if
 * enabled() still returns true.
 * Note that if the account gets deleted, it will always get disabled first;
 * so, there is no need to connect to the Account::removed() signal; one can
 * just monitor the changed() signal from the AccountService objects.
 */

/*!
 * @fn AccountService::enabled(bool isEnabled)
 *
 * Emitted when the enabledness state of the account service has changed.
 */

/*!
 * @fn AccountService::changed()
 * Emitted when some setting has changed on the account service.
 * You can use the changedFields() method to retrieve the list of the
 * settings which have changed.
 */

class AccountServicePrivate
{
    Q_DECLARE_PUBLIC(AccountService)

public:
    AccountServicePrivate(Account *account,
                          Service *service,
                          AccountService *accountService);
    ~AccountServicePrivate();

private:
    static void onEnabled(AccountService *accountService, gboolean isEnabled);
    static void onChanged(AccountService *accountService);

    ServiceList m_serviceList;
    AgAccountService *m_accountService;
    Manager *m_manager;
    QString prefix;
    mutable AccountService *q_ptr;
};

} // namespace

using namespace Accounts;

static QChar slash = QChar::fromLatin1('/');

AccountServicePrivate::AccountServicePrivate(Account *account,
                                             Service *service,
                                             AccountService *accountService):
    m_manager(account->manager()),
    q_ptr(accountService)
{
    m_accountService = ag_account_service_new(account->account(),
                                              service->service());
    g_signal_connect_swapped(m_accountService, "enabled",
                             G_CALLBACK(&onEnabled), accountService);
    g_signal_connect_swapped(m_accountService, "changed",
                             G_CALLBACK(&onChanged), accountService);
}

AccountServicePrivate::~AccountServicePrivate()
{
    Q_Q(AccountService);
    g_signal_handlers_disconnect_by_func(m_accountService,
                                         (void *)&onEnabled, q);
    g_signal_handlers_disconnect_by_func(m_accountService,
                                         (void *)&onChanged, q);
    g_object_unref(m_accountService);
    m_accountService = 0;
}

void AccountServicePrivate::onEnabled(AccountService *accountService,
                                      gboolean isEnabled)
{
    TRACE();

    Q_EMIT accountService->enabled(isEnabled);
}

void AccountServicePrivate::onChanged(AccountService *accountService)
{
    TRACE();

    Q_EMIT accountService->changed();
}

/*!
 * Constructor.
 * @param account An Account.
 * @param service A Service supported by @account.
 */
AccountService::AccountService(Account *account, Service *service):
    d_ptr(new AccountServicePrivate(account, service, this))
{
}

/*!
 * Destructor.
 */
AccountService::~AccountService()
{
    delete d_ptr;
}

/*!
 * Return the Account. Do not delete this object explicitly.
 */
Account *AccountService::account() const
{
    Q_D(const AccountService);
    AgAccount *account = ag_account_service_get_account(d->m_accountService);
    AgAccountId account_id = account->id;

    return d->m_manager->account(account_id);
}

/*!
 * Return the Service. Do not delete this object explicitly.
 */
Service *AccountService::service() const
{
    Q_D(const AccountService);
    AgService *service = ag_account_service_get_service(d->m_accountService);
    return d->m_manager->serviceInstance(service);
}

/*!
 * Check whether the account service is enabled.
 */
bool AccountService::enabled() const
{
    Q_D(const AccountService);
    return ag_account_service_get_enabled(d->m_accountService);
}

/*!
 * Return all the keys in the current group.
 */
QStringList AccountService::allKeys() const
{
    Q_D(const AccountService);
    QStringList allKeys;
    AgAccountSettingIter iter;
    const gchar *key;
    const GValue *val;

    /* iterate the settings */
    QByteArray tmp = d->prefix.toLatin1();
    ag_account_service_settings_iter_init(d->m_accountService,
                                          &iter, tmp.constData());
    while (ag_account_service_settings_iter_next(&iter, &key, &val))
    {
        allKeys.append(ASCII(key));
    }
    return allKeys;
}

/*!
 * Enter a group. This method never fails.
 * @param prefix
 */
void AccountService::beginGroup(const QString &prefix)
{
    Q_D(AccountService);
    d->prefix += prefix + slash;
}

/*!
 * Return all the groups which are direct children of the current group.
 */
QStringList AccountService::childGroups() const
{
    QStringList groups, all_keys;

    all_keys = allKeys();
    foreach (QString key, all_keys)
    {
        if (key.contains(slash)) {
            QString group = key.section(slash, 0, 0);
            if (!groups.contains(group))
                groups.append(group);
        }
    }
    return groups;
}

/*!
 * Return all the keys which are direct children of the current group.
 */
QStringList AccountService::childKeys() const
{
    QStringList keys, all_keys;

    all_keys = allKeys();
    foreach (QString key, all_keys)
    {
        if (!key.contains(slash))
            keys.append(key);
    }
    return keys;
}

/*!
 * Remove all the keys.
 * @see remove(const QString &key)
 */
void AccountService::clear()
{
    Q_D(AccountService);
    /* clear() must ignore the group: so, temporarily reset it and call
     * remove("") */
    QString saved_prefix = d->prefix;
    d->prefix = QString();
    remove(QString());
    d->prefix = saved_prefix;
}

/*!
 * Check whether the given key is in the current group.
 * @param key The key name of the setting.
 */
bool AccountService::contains(const QString &key) const
{
    return childKeys().contains(key);
}

/*!
 * Exit a group.
 */
void AccountService::endGroup()
{
    Q_D(AccountService);
    d->prefix = d->prefix.section(slash, 0, -3,
                                  QString::SectionIncludeTrailingSep);
    if (d->prefix[0] == slash) d->prefix.remove(0, 1);
}

/*!
 * Return the name of the current group.
 */
QString AccountService::group() const
{
    Q_D(const AccountService);
    if (d->prefix.endsWith(slash))
        return d->prefix.left(d->prefix.size() - 1);
    return d->prefix;
}

/*!
 * Remove the given key. If the key is the empty string, all keys in the
 * current group are removed.
 * @param key The key name of the setting.
 */
void AccountService::remove(const QString &key)
{
    Q_D(AccountService);
    if (key.isEmpty())
    {
        /* delete all keys in the group */
        QStringList keys = allKeys();
        foreach (QString key, keys)
        {
            if (!key.isEmpty())
                remove(key);
        }
    }
    else
    {
        QString full_key = d->prefix + key;
        QByteArray tmpkey = full_key.toLatin1();
        ag_account_service_set_value(d->m_accountService,
                                     tmpkey.constData(),
                                     NULL);
    }
}

/*!
 * Change the value of an account setting.
 * @param key The name of the setting.
 * @param value The new value of the setting.
 */
void AccountService::setValue(const QString &key, const QVariant &value)
{
    Q_D(AccountService);
    TRACE();
    GValue val= {0, {{0}}};

    if (!variantToGValue(value, &val)) {
        return;
    }

    QString full_key = d->prefix + key;
    QByteArray tmpkey = full_key.toLatin1();
    ag_account_service_set_value(d->m_accountService,
                                 tmpkey.constData(),
                                 &val);
    g_value_unset(&val);
}

void AccountService::setValue(const char *key, const QVariant &value)
{
    setValue(ASCII(key), value);
}

/*!
 * Retrieves the value of an account setting.
 * @param key The key whose value must be retrieved
 * @param source Indicates whether the value comes from the account, the
 * service template or was unset.
 *
 * Returns the value of the setting, or an invalid QVariant if unset.
 */
QVariant AccountService::value(const QString &key, SettingSource *source) const
{
    Q_D(const AccountService);
    GValue val= {0, {{0}}};
    g_value_init(&val, G_TYPE_STRING);
    QString full_key = d->prefix + key;
    QByteArray ba = full_key.toLatin1();
    AgSettingSource agSource =
        ag_account_service_get_value(d->m_accountService,
                                     ba.constData(), &val);
    if (source != 0) {
        switch (agSource) {
        case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break;
        case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break;
        default: *source = NONE; break;
        }
    }

    QVariant variant;
    if (agSource == AG_SETTING_SOURCE_NONE)
        return variant;

    variant = UTF8(g_value_get_string(&val));
    g_value_unset(&val);

    return variant;
}

QVariant AccountService::value(const char *key, SettingSource *source) const
{
    return value(ASCII(key), source);
}

/*!
 * This method should be called only in the context of a handler of the
 * AccountService::changed() signal, and can be used to retrieve the set of
 * changes.
 *
 * @return a QStringList of the keys which have changed.
 */
QStringList AccountService::changedFields() const
{
    Q_D(const AccountService);

    gchar **changedFields =
        ag_account_service_get_changed_fields(d->m_accountService);

    QStringList keyList;
    if (changedFields == 0)
        return keyList;

    gchar **keys = changedFields;
    while (*keys != 0) {
        keyList.append(QString(ASCII(*keys)));
        keys++;
    }

    g_strfreev(changedFields);
    return keyList;
}

<commit_msg>Doc: use @note on some AccountService paragraphs<commit_after>/* vi: set et sw=4 ts=4 cino=t0,(0: */
/*
 * This file is part of libaccounts-qt
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This 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 "account-service.h"
#include "manager.h"
#include "utils.h"
#include <libaccounts-glib/ag-account.h>
#include <libaccounts-glib/ag-account-service.h>

namespace Accounts
{

/*!
 * @class AccountService
 *
 * @brief Account settings for a specific service
 *
 * @details The AccountService class provides access to the account settings
 * for a specific service type. It is meant to be easier to use than the
 * Account class because it hides the complexity of the account structure and
 * gives access to only the limited subset of account settings which are
 * relevant to a service.
 *
 * To get an AccountService one can use the Manager methods accountServices()
 * or enabledAccountServices(), which both return a QList of account services.
 * Note that if the Manager was instantiated for a specific service type, these
 * lists will contain only those account services matching that service type.
 * The AccountService can also be instantiated with its AccountService(Account
 * *account, Service *service) constructor: this is useful if one already has
 * an Account instance.
 *
 * This is intended to be a convenient wrapper over the accounts settings
 * specific for a service; as such, it doesn't offer all the editing
 * possibilities offered by the Account class, such as enabling the service
 * itself: these operations should ideally not be performed by consumer
 * applications, but by the account editing UI only.
 *
 * Example code:
 * @code
 * // Instantiate an account manager interested in e-mail services only.
 * Accounts::Manager *manager = new Accounts::Manager("e-mail");
 *
 * // Get the list of enabled AccountService objects of type e-mail.
 * Accounts::AccountServiceList services = manager->enabledAccountServices();
 *
 * // Loop through the account services and do something useful with them.
 * foreach (Accounts::AccountService *service, services) {
 *     QString server = service->value("pop3/hostname").toString();
 *     int port = service->value("pop3/port").toInt();
 *
 *     // Suppose that the e-mail address is stored in the global account
 *     // settings; let's get it from there:
 *     QString fromAddress = service->account()->valueAsString("username");
 *
 *     ...
 * }
 * @endcode
 *
 * @note User applications (with the notable exception of the accounts editing
 * application) should never use account services which are not enabled, and
 * should stop using an account when the account service becomes disabled. The
 * latter can be done by connecting to the changed() signal and checking if
 * enabled() still returns true.
 * @note Note that if the account gets deleted, it will always get disabled
 * first; so, there is no need to connect to the Account::removed() signal; one
 * can just monitor the changed() signal from the AccountService objects.
 */

/*!
 * @fn AccountService::enabled(bool isEnabled)
 *
 * Emitted when the enabledness state of the account service has changed.
 */

/*!
 * @fn AccountService::changed()
 * Emitted when some setting has changed on the account service.
 * You can use the changedFields() method to retrieve the list of the
 * settings which have changed.
 */

class AccountServicePrivate
{
    Q_DECLARE_PUBLIC(AccountService)

public:
    AccountServicePrivate(Account *account,
                          Service *service,
                          AccountService *accountService);
    ~AccountServicePrivate();

private:
    static void onEnabled(AccountService *accountService, gboolean isEnabled);
    static void onChanged(AccountService *accountService);

    ServiceList m_serviceList;
    AgAccountService *m_accountService;
    Manager *m_manager;
    QString prefix;
    mutable AccountService *q_ptr;
};

} // namespace

using namespace Accounts;

static QChar slash = QChar::fromLatin1('/');

AccountServicePrivate::AccountServicePrivate(Account *account,
                                             Service *service,
                                             AccountService *accountService):
    m_manager(account->manager()),
    q_ptr(accountService)
{
    m_accountService = ag_account_service_new(account->account(),
                                              service->service());
    g_signal_connect_swapped(m_accountService, "enabled",
                             G_CALLBACK(&onEnabled), accountService);
    g_signal_connect_swapped(m_accountService, "changed",
                             G_CALLBACK(&onChanged), accountService);
}

AccountServicePrivate::~AccountServicePrivate()
{
    Q_Q(AccountService);
    g_signal_handlers_disconnect_by_func(m_accountService,
                                         (void *)&onEnabled, q);
    g_signal_handlers_disconnect_by_func(m_accountService,
                                         (void *)&onChanged, q);
    g_object_unref(m_accountService);
    m_accountService = 0;
}

void AccountServicePrivate::onEnabled(AccountService *accountService,
                                      gboolean isEnabled)
{
    TRACE();

    Q_EMIT accountService->enabled(isEnabled);
}

void AccountServicePrivate::onChanged(AccountService *accountService)
{
    TRACE();

    Q_EMIT accountService->changed();
}

/*!
 * Constructor.
 * @param account An Account.
 * @param service A Service supported by @account.
 */
AccountService::AccountService(Account *account, Service *service):
    d_ptr(new AccountServicePrivate(account, service, this))
{
}

/*!
 * Destructor.
 */
AccountService::~AccountService()
{
    delete d_ptr;
}

/*!
 * Return the Account. Do not delete this object explicitly.
 */
Account *AccountService::account() const
{
    Q_D(const AccountService);
    AgAccount *account = ag_account_service_get_account(d->m_accountService);
    AgAccountId account_id = account->id;

    return d->m_manager->account(account_id);
}

/*!
 * Return the Service. Do not delete this object explicitly.
 */
Service *AccountService::service() const
{
    Q_D(const AccountService);
    AgService *service = ag_account_service_get_service(d->m_accountService);
    return d->m_manager->serviceInstance(service);
}

/*!
 * Check whether the account service is enabled.
 */
bool AccountService::enabled() const
{
    Q_D(const AccountService);
    return ag_account_service_get_enabled(d->m_accountService);
}

/*!
 * Return all the keys in the current group.
 */
QStringList AccountService::allKeys() const
{
    Q_D(const AccountService);
    QStringList allKeys;
    AgAccountSettingIter iter;
    const gchar *key;
    const GValue *val;

    /* iterate the settings */
    QByteArray tmp = d->prefix.toLatin1();
    ag_account_service_settings_iter_init(d->m_accountService,
                                          &iter, tmp.constData());
    while (ag_account_service_settings_iter_next(&iter, &key, &val))
    {
        allKeys.append(ASCII(key));
    }
    return allKeys;
}

/*!
 * Enter a group. This method never fails.
 * @param prefix
 */
void AccountService::beginGroup(const QString &prefix)
{
    Q_D(AccountService);
    d->prefix += prefix + slash;
}

/*!
 * Return all the groups which are direct children of the current group.
 */
QStringList AccountService::childGroups() const
{
    QStringList groups, all_keys;

    all_keys = allKeys();
    foreach (QString key, all_keys)
    {
        if (key.contains(slash)) {
            QString group = key.section(slash, 0, 0);
            if (!groups.contains(group))
                groups.append(group);
        }
    }
    return groups;
}

/*!
 * Return all the keys which are direct children of the current group.
 */
QStringList AccountService::childKeys() const
{
    QStringList keys, all_keys;

    all_keys = allKeys();
    foreach (QString key, all_keys)
    {
        if (!key.contains(slash))
            keys.append(key);
    }
    return keys;
}

/*!
 * Remove all the keys.
 * @see remove(const QString &key)
 */
void AccountService::clear()
{
    Q_D(AccountService);
    /* clear() must ignore the group: so, temporarily reset it and call
     * remove("") */
    QString saved_prefix = d->prefix;
    d->prefix = QString();
    remove(QString());
    d->prefix = saved_prefix;
}

/*!
 * Check whether the given key is in the current group.
 * @param key The key name of the setting.
 */
bool AccountService::contains(const QString &key) const
{
    return childKeys().contains(key);
}

/*!
 * Exit a group.
 */
void AccountService::endGroup()
{
    Q_D(AccountService);
    d->prefix = d->prefix.section(slash, 0, -3,
                                  QString::SectionIncludeTrailingSep);
    if (d->prefix[0] == slash) d->prefix.remove(0, 1);
}

/*!
 * Return the name of the current group.
 */
QString AccountService::group() const
{
    Q_D(const AccountService);
    if (d->prefix.endsWith(slash))
        return d->prefix.left(d->prefix.size() - 1);
    return d->prefix;
}

/*!
 * Remove the given key. If the key is the empty string, all keys in the
 * current group are removed.
 * @param key The key name of the setting.
 */
void AccountService::remove(const QString &key)
{
    Q_D(AccountService);
    if (key.isEmpty())
    {
        /* delete all keys in the group */
        QStringList keys = allKeys();
        foreach (QString key, keys)
        {
            if (!key.isEmpty())
                remove(key);
        }
    }
    else
    {
        QString full_key = d->prefix + key;
        QByteArray tmpkey = full_key.toLatin1();
        ag_account_service_set_value(d->m_accountService,
                                     tmpkey.constData(),
                                     NULL);
    }
}

/*!
 * Change the value of an account setting.
 * @param key The name of the setting.
 * @param value The new value of the setting.
 */
void AccountService::setValue(const QString &key, const QVariant &value)
{
    Q_D(AccountService);
    TRACE();
    GValue val= {0, {{0}}};

    if (!variantToGValue(value, &val)) {
        return;
    }

    QString full_key = d->prefix + key;
    QByteArray tmpkey = full_key.toLatin1();
    ag_account_service_set_value(d->m_accountService,
                                 tmpkey.constData(),
                                 &val);
    g_value_unset(&val);
}

void AccountService::setValue(const char *key, const QVariant &value)
{
    setValue(ASCII(key), value);
}

/*!
 * Retrieves the value of an account setting.
 * @param key The key whose value must be retrieved
 * @param source Indicates whether the value comes from the account, the
 * service template or was unset.
 *
 * Returns the value of the setting, or an invalid QVariant if unset.
 */
QVariant AccountService::value(const QString &key, SettingSource *source) const
{
    Q_D(const AccountService);
    GValue val= {0, {{0}}};
    g_value_init(&val, G_TYPE_STRING);
    QString full_key = d->prefix + key;
    QByteArray ba = full_key.toLatin1();
    AgSettingSource agSource =
        ag_account_service_get_value(d->m_accountService,
                                     ba.constData(), &val);
    if (source != 0) {
        switch (agSource) {
        case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break;
        case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break;
        default: *source = NONE; break;
        }
    }

    QVariant variant;
    if (agSource == AG_SETTING_SOURCE_NONE)
        return variant;

    variant = UTF8(g_value_get_string(&val));
    g_value_unset(&val);

    return variant;
}

QVariant AccountService::value(const char *key, SettingSource *source) const
{
    return value(ASCII(key), source);
}

/*!
 * This method should be called only in the context of a handler of the
 * AccountService::changed() signal, and can be used to retrieve the set of
 * changes.
 *
 * @return a QStringList of the keys which have changed.
 */
QStringList AccountService::changedFields() const
{
    Q_D(const AccountService);

    gchar **changedFields =
        ag_account_service_get_changed_fields(d->m_accountService);

    QStringList keyList;
    if (changedFields == 0)
        return keyList;

    gchar **keys = changedFields;
    while (*keys != 0) {
        keyList.append(QString(ASCII(*keys)));
        keys++;
    }

    g_strfreev(changedFields);
    return keyList;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkBioRadImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkBioRadImageIO.h"
#include "itkByteSwapper.h"
#include <itksys/SystemTools.hxx>
#include <string.h>  // for strncpy

#define BIORAD_HEADER_LENGTH    76
#define BIORAD_NOTE_LENGTH      96
#define BIORAD_NOTE_TEXT_LENGTH 80
#define BIORAD_RGB_LUT_LENGTH   768
#define BIORAD_FILE_ID_OFFSET   54
#define BIORAD_MAGIC_NUMBER     12345

namespace itk
{

struct bioradheader {
    unsigned short nx, ny;      // 0   2*2  image width and height in pixels
    unsigned short npic;        // 4   2    number of images in file
    unsigned short ramp1_min, ramp1_max; // 6   2*2  LUT1 ramp min. and max.
    char notes[4];              // 10  4    no notes=0; has notes=non zero
    short byte_format;          // 14  2    bytes=TRUE(1); words=FALSE(0)
    short image_number;         // 16  2    image number within file
    char filename[32];          // 18  32   file name
    short merged;               // 50  2    merged format
    unsigned short color1;      // 52  2    LUT1 color status
    unsigned short file_id;     // 54  2    valid .PIC file=12345
    unsigned short ramp2_min, ramp2_max; // 56  2*2  LUT2 ramp min. and max.
    unsigned short color2;      // 60  2    LUT2 color status
    short edited;               // 62  2    image has been edited=TRUE(1)
    short lens;                 // 64  2    Integer part of lens magnification
    char mag_factor[4];         // 66  4    4 byte real mag. factor (old ver.)
    unsigned char reserved[6];  // 70  6    NOT USED (old ver.=real lens mag.)
};

BioRadImageIO::BioRadImageIO()
{
  this->SetNumberOfDimensions(3);
  m_PixelType = SCALAR;
  m_ComponentType = UCHAR;
  m_ByteOrder = LittleEndian;
  m_FileType = Binary;
  m_NumberOfComponents = 1; // default
}

BioRadImageIO::~BioRadImageIO()
{
}

bool BioRadImageIO::OpenBioRadFileForReading(std::ifstream& os,
                                             const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  os.open( filename, std::ios::in | std::ios::binary );

  if ( os.fail() )
    {
    return false;
    }

  return true;
}

bool BioRadImageIO::OpenBioRadFileForWriting(std::ofstream& os,
                                             const char* filename)
{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

#ifdef __sgi
  // Create the file. This is required on some older sgi's
  std::ofstream tFile(filename,std::ios::out);
  tFile.close();
#endif

  // Actually open the file
  os.open( filename, std::ios::out | std::ios::binary );

  if( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}

// This method will only test if the header looks like a
// BioRad image file.
bool BioRadImageIO::CanReadFile(const char* filename)
{
  std::ifstream file;
  std::string fname(filename);

  if( fname == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = fname.rfind(".pic");
  if ((sprPos != std::string::npos)
      && (sprPos == fname.length() - 4))
    {
    extensionFound = true;
    }
  sprPos = fname.rfind(".PIC");
  if ((sprPos != std::string::npos)
      && (sprPos == fname.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  if ( !this->OpenBioRadFileForReading(file, filename))
    {
    return false;
    }

  // Check to see if its a BioRad file
  unsigned short file_id;
  file.seekg(BIORAD_FILE_ID_OFFSET, std::ios::beg );
  file.read((char*)(&file_id),2);
  ByteSwapper<unsigned short>::SwapFromSystemToLittleEndian(&file_id);

  itkDebugMacro(<< "Magic number: " << file_id);

  file.close();
  return file_id == BIORAD_MAGIC_NUMBER;
}

void BioRadImageIO::Read(void* buffer)
{
  std::ifstream file;

  //read header information file:
  this->OpenBioRadFileForReading(file, m_FileName.c_str());
  file.seekg(BIORAD_HEADER_LENGTH, std::ios::beg);

  if( !this->ReadBufferAsBinary( file, buffer, this->GetImageSizeInBytes()) )
    {
    itkExceptionMacro(<<"Read failed: Wanted " << this->GetImageSizeInBytes()
                      << " bytes, but read " << file.gcount() << " bytes.");
    }

  //byte swapping depending on pixel type:
  if(this->GetComponentType() == USHORT)
    {
    ByteSwapper<unsigned short>::SwapRangeFromSystemToLittleEndian(
        reinterpret_cast<unsigned short *>(buffer),
        this->GetImageSizeInComponents() );
    }

  //closing file:
  file.close();
}

void BioRadImageIO::InternalReadImageInformation(std::ifstream& file)
{
  //read .pic file (header)
  if ( ! this->OpenBioRadFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  // Find info...
  bioradheader h, *p;
  p = &h;
  if( sizeof(h) != BIORAD_HEADER_LENGTH )
    {
    itkExceptionMacro(<< "Problem of alignement on your plateform");
    }
  file.seekg(0, std::ios::beg);
  file.read((char*)p, BIORAD_HEADER_LENGTH);
  // Only byte swap the first 66 bytes
  ByteSwapper<unsigned short>::
    SwapRangeFromSystemToLittleEndian((unsigned short*)p, (BIORAD_HEADER_LENGTH - 10)/2);
  itkDebugMacro(<< "Magic number: " << h.file_id);

  // Set dim X,Y,Z
  m_Dimensions[0] = h.nx;
  itkDebugMacro(<< "h.nx: " << h.nx);
  m_Dimensions[1] = h.ny;
  itkDebugMacro(<< "h.ny: " << h.ny);
  if( h.npic != 1 )
    {
    this->SetNumberOfDimensions(3);
    m_Dimensions[2] = h.npic;
    itkDebugMacro(<< "h.npic: " << h.npic);
    }
  else
    {
    this->SetNumberOfDimensions(2);
    }

  // These are not specified by the format, but we can deduce them:
  // pixel size = scale_factor/lens/mag_factor
  ByteSwapper<float>::SwapFromSystemToLittleEndian((float*)&h.mag_factor);
  float mag_factor = *((float*)(h.mag_factor));
  itkDebugMacro(<< "Mag Factor: " << mag_factor);
  itkDebugMacro(<< "Lens: " << h.lens);
  m_Spacing[0] = m_Spacing[1] = mag_factor/h.lens;
  if (m_NumberOfDimensions == 3)
    {
    m_Spacing[2] = m_Spacing[0];
    }

  // Check the pixel size:
  itkDebugMacro(<< "Byte Format: " << h.byte_format);
  if(h.byte_format == 1)
    {
    SetComponentType(UCHAR);
    }
  else
    {
    // sometime the file set an erronous value for byte_format, check the size
    // of the file in this case, since byte_format = 1 seems to be the default
    file.seekg(0, std::ios::end);
    long gcount = static_cast<long>(file.tellg()) - BIORAD_HEADER_LENGTH;
    if( gcount == h.nx*h.ny*h.npic )
      {
      itkWarningMacro( <<
        "File is declared as two bytes but really is only one byte");
      SetComponentType(UCHAR);
      }
    else if( gcount == h.nx*h.ny*h.npic*2 )
      {
      SetComponentType(USHORT);
      }
    else
      {
      SetComponentType(UNKNOWNCOMPONENTTYPE);
      itkExceptionMacro(<< "Cannot read requested file");
      }
    }
}

void BioRadImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
  file.close();
}

bool BioRadImageIO::CanWriteFile( const char* name )
{
  std::string filename = name;

  if(  filename == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = filename.rfind(".pic");
  if ((sprPos != std::string::npos)
      && (sprPos == filename.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  return true;
}

void BioRadImageIO::Write(const void* buffer)
{
  std::ofstream file;
  if ( !this->OpenBioRadFileForWriting(file, m_FileName.c_str()) )
    {
    return;
    }

  // Check the image region for proper dimensions, etc.
  unsigned int numDims = this->GetNumberOfDimensions();
  if ( numDims != 3 && numDims != 2 )
    {
    itkExceptionMacro(<<"BioRad Writer can only write 2 or 3-dimensional images");
    return;
    }

  // Write the BioRad header information
  bioradheader header, *p;
  p = &header;
  if( sizeof(header) != BIORAD_HEADER_LENGTH )
    {
    itkExceptionMacro(<< "Problem of alignement on your plateform");
    }
  memset(p,0,BIORAD_HEADER_LENGTH); // Set everything to zero
  // In particular `notes' needs to be set to zero to indicate there is no notes
  header.nx = m_Dimensions[0];
  header.ny = m_Dimensions[1];
  if( m_NumberOfDimensions == 3 )
    {
    header.npic = m_Dimensions[2];
    }
  else
    {
    header.npic = 1;
    }
  header.file_id = BIORAD_MAGIC_NUMBER;

  // Always say that image was not edited:
  header.edited = 0;

  // Default dummy values:
  header.lens = 1;
  // Set the if file is in byte format or not:
  switch(this->GetComponentType())
    {
    case UCHAR:
      header.byte_format = 1;
      header.ramp1_min = 0;
      header.ramp1_max = 255;
      header.ramp2_min = 0;
      header.ramp2_max = 255;
      break;
    case USHORT:
      header.byte_format = 0;
      header.ramp1_min = 0;
      header.ramp1_max = 65535;
      header.ramp2_min = 0;
      header.ramp2_max = 65535;
      break;
    default:
      itkExceptionMacro(<<"Component type not supported.");
      return;
    }
  // write the actual header
  ByteSwapper<unsigned short>::SwapRangeFromSystemToLittleEndian(
    reinterpret_cast<unsigned short*>(p), BIORAD_HEADER_LENGTH/2);
  // To be able to deduce pixel spacing:
  float mag_factor = m_Spacing[0];
  ByteSwapper<float>::SwapFromSystemToLittleEndian(&mag_factor);
  memcpy(&header.mag_factor, (char*)(&mag_factor), 4);
  // Set the filename
  // NOTES: This is not very clear what should be written here, some files
  // have either:
  // 1. FILENAME.PIC
  // 2. FILENAME.pic
  // 3. FileName.pic
  // or simply
  // 4. FileName
  std::string filename = itksys::SystemTools::GetFilenameName(m_FileName);
  // The buffer is at most 32 bytes:
  strncpy(header.filename, filename.c_str(), sizeof(header.filename));
  file.write((char*)p, BIORAD_HEADER_LENGTH);

  //preparation for writing buffer:
  const unsigned long numberOfBytes      = this->GetImageSizeInBytes();
  const unsigned long numberOfComponents = this->GetImageSizeInComponents();

  char *tempmemory = new char[numberOfBytes];
  memcpy(tempmemory,buffer,numberOfBytes);
  if(this->GetComponentType() == USHORT)
    {
    ByteSwapper<unsigned short>::SwapRangeFromSystemToBigEndian(
        reinterpret_cast<unsigned short*>(tempmemory), numberOfComponents );
    }

  // Write the actual pixel data
  file.write( static_cast<const char *>(tempmemory) , numberOfBytes );
  delete [] tempmemory;
  file.close();
}

void BioRadImageIO::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
}

} // end namespace itk
<commit_msg>ENH: Some more debug info<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkBioRadImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkBioRadImageIO.h"
#include "itkByteSwapper.h"
#include <itksys/SystemTools.hxx>
#include <string.h>  // for strncpy

#define BIORAD_HEADER_LENGTH    76
#define BIORAD_NOTE_LENGTH      96
#define BIORAD_NOTE_TEXT_LENGTH 80
#define BIORAD_RGB_LUT_LENGTH   768
#define BIORAD_FILE_ID_OFFSET   54
#define BIORAD_MAGIC_NUMBER     12345

namespace itk
{

struct bioradheader {
    unsigned short nx, ny;      // 0   2*2  image width and height in pixels
    unsigned short npic;        // 4   2    number of images in file
    unsigned short ramp1_min, ramp1_max; // 6   2*2  LUT1 ramp min. and max.
    char notes[4];              // 10  4    no notes=0; has notes=non zero
    short byte_format;          // 14  2    bytes=TRUE(1); words=FALSE(0)
    short image_number;         // 16  2    image number within file
    char filename[32];          // 18  32   file name
    short merged;               // 50  2    merged format
    unsigned short color1;      // 52  2    LUT1 color status
    unsigned short file_id;     // 54  2    valid .PIC file=12345
    unsigned short ramp2_min, ramp2_max; // 56  2*2  LUT2 ramp min. and max.
    unsigned short color2;      // 60  2    LUT2 color status
    short edited;               // 62  2    image has been edited=TRUE(1)
    short lens;                 // 64  2    Integer part of lens magnification
    char mag_factor[4];         // 66  4    4 byte real mag. factor (old ver.)
    unsigned char reserved[6];  // 70  6    NOT USED (old ver.=real lens mag.)
};

BioRadImageIO::BioRadImageIO()
{
  this->SetNumberOfDimensions(3);
  m_PixelType = SCALAR;
  m_ComponentType = UCHAR;
  m_ByteOrder = LittleEndian;
  m_FileType = Binary;
  m_NumberOfComponents = 1; // default
}

BioRadImageIO::~BioRadImageIO()
{
}

bool BioRadImageIO::OpenBioRadFileForReading(std::ifstream& os,
                                             const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  os.open( filename, std::ios::in | std::ios::binary );

  if ( os.fail() )
    {
    return false;
    }

  return true;
}

bool BioRadImageIO::OpenBioRadFileForWriting(std::ofstream& os,
                                             const char* filename)
{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

#ifdef __sgi
  // Create the file. This is required on some older sgi's
  std::ofstream tFile(filename,std::ios::out);
  tFile.close();
#endif

  // Actually open the file
  os.open( filename, std::ios::out | std::ios::binary );

  if( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}

// This method will only test if the header looks like a
// BioRad image file.
bool BioRadImageIO::CanReadFile(const char* filename)
{
  std::ifstream file;
  std::string fname(filename);

  if( fname == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = fname.rfind(".pic");
  if ((sprPos != std::string::npos)
      && (sprPos == fname.length() - 4))
    {
    extensionFound = true;
    }
  sprPos = fname.rfind(".PIC");
  if ((sprPos != std::string::npos)
      && (sprPos == fname.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  if ( !this->OpenBioRadFileForReading(file, filename))
    {
    return false;
    }

  // Check to see if its a BioRad file
  unsigned short file_id;
  file.seekg(BIORAD_FILE_ID_OFFSET, std::ios::beg );
  file.read((char*)(&file_id),2);
  ByteSwapper<unsigned short>::SwapFromSystemToLittleEndian(&file_id);

  itkDebugMacro(<< "Magic number: " << file_id);

  file.close();
  return file_id == BIORAD_MAGIC_NUMBER;
}

void BioRadImageIO::Read(void* buffer)
{
  std::ifstream file;

  //read header information file:
  this->OpenBioRadFileForReading(file, m_FileName.c_str());
  file.seekg(BIORAD_HEADER_LENGTH, std::ios::beg);

  if( !this->ReadBufferAsBinary( file, buffer, this->GetImageSizeInBytes()) )
    {
    itkExceptionMacro(<<"Read failed: Wanted " << this->GetImageSizeInBytes()
                      << " bytes, but read " << file.gcount() << " bytes.");
    }

  //byte swapping depending on pixel type:
  if(this->GetComponentType() == USHORT)
    {
    ByteSwapper<unsigned short>::SwapRangeFromSystemToLittleEndian(
        reinterpret_cast<unsigned short *>(buffer),
        this->GetImageSizeInComponents() );
    }

  //closing file:
  file.close();
}

void BioRadImageIO::InternalReadImageInformation(std::ifstream& file)
{
  //read .pic file (header)
  if ( ! this->OpenBioRadFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  // Find info...
  bioradheader h, *p;
  p = &h;
  if( sizeof(h) != BIORAD_HEADER_LENGTH )
    {
    itkExceptionMacro(<< "Problem of alignement on your plateform");
    }
  file.seekg(0, std::ios::beg);
  file.read((char*)p, BIORAD_HEADER_LENGTH);
  // Only byte swap the first 66 bytes
  ByteSwapper<unsigned short>::
    SwapRangeFromSystemToLittleEndian((unsigned short*)p, (BIORAD_HEADER_LENGTH - 10)/2);
  itkDebugMacro(<< "Magic number: " << h.file_id);

  // Set dim X,Y,Z
  m_Dimensions[0] = h.nx;
  itkDebugMacro(<< "h.nx: " << h.nx);
  m_Dimensions[1] = h.ny;
  itkDebugMacro(<< "h.ny: " << h.ny);
  if( h.npic != 1 )
    {
    this->SetNumberOfDimensions(3);
    m_Dimensions[2] = h.npic;
    itkDebugMacro(<< "h.npic: " << h.npic);
    }
  else
    {
    this->SetNumberOfDimensions(2);
    }

  // These are not specified by the format, but we can deduce them:
  // pixel size = scale_factor/lens/mag_factor
  itkDebugMacro(<< "Mag Factor Raw: " << (int)h.mag_factor[0] << ","
    << (int)h.mag_factor[1] << "," << (int)h.mag_factor[2] << "," << (int)h.mag_factor[3]);
  ByteSwapper<float>::SwapFromSystemToLittleEndian((float*)&h.mag_factor);
  itkDebugMacro(<< "Mag Factor BS : " << (int)h.mag_factor[0] << ","
    << (int)h.mag_factor[1] << "," << (int)h.mag_factor[2] << "," << (int)h.mag_factor[3]);
  float mag_factor = *((float*)(h.mag_factor));
  itkDebugMacro(<< "Mag Factor: " << mag_factor);
  itkDebugMacro(<< "Lens: " << h.lens);
  m_Spacing[0] = m_Spacing[1] = mag_factor/h.lens;
  if (m_NumberOfDimensions == 3)
    {
    m_Spacing[2] = m_Spacing[0];
    }

  // Check the pixel size:
  itkDebugMacro(<< "Byte Format: " << h.byte_format);
  if(h.byte_format == 1)
    {
    SetComponentType(UCHAR);
    }
  else
    {
    // sometime the file set an erronous value for byte_format, check the size
    // of the file in this case, since byte_format = 1 seems to be the default
    file.seekg(0, std::ios::end);
    long gcount = static_cast<long>(file.tellg()) - BIORAD_HEADER_LENGTH;
    if( gcount == h.nx*h.ny*h.npic )
      {
      itkWarningMacro( <<
        "File is declared as two bytes but really is only one byte");
      SetComponentType(UCHAR);
      }
    else if( gcount == h.nx*h.ny*h.npic*2 )
      {
      SetComponentType(USHORT);
      }
    else
      {
      SetComponentType(UNKNOWNCOMPONENTTYPE);
      itkExceptionMacro(<< "Cannot read requested file");
      }
    }
}

void BioRadImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
  file.close();
}

bool BioRadImageIO::CanWriteFile( const char* name )
{
  std::string filename = name;

  if(  filename == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  bool extensionFound = false;
  std::string::size_type sprPos = filename.rfind(".pic");
  if ((sprPos != std::string::npos)
      && (sprPos == filename.length() - 4))
    {
    extensionFound = true;
    }

  if( !extensionFound )
    {
    itkDebugMacro(<<"The filename extension is not recognized");
    return false;
    }

  return true;
}

void BioRadImageIO::Write(const void* buffer)
{
  std::ofstream file;
  if ( !this->OpenBioRadFileForWriting(file, m_FileName.c_str()) )
    {
    return;
    }

  // Check the image region for proper dimensions, etc.
  unsigned int numDims = this->GetNumberOfDimensions();
  if ( numDims != 3 && numDims != 2 )
    {
    itkExceptionMacro(<<"BioRad Writer can only write 2 or 3-dimensional images");
    return;
    }

  // Write the BioRad header information
  bioradheader header, *p;
  p = &header;
  if( sizeof(header) != BIORAD_HEADER_LENGTH )
    {
    itkExceptionMacro(<< "Problem of alignement on your plateform");
    }
  memset(p,0,BIORAD_HEADER_LENGTH); // Set everything to zero
  // In particular `notes' needs to be set to zero to indicate there is no notes
  header.nx = m_Dimensions[0];
  header.ny = m_Dimensions[1];
  if( m_NumberOfDimensions == 3 )
    {
    header.npic = m_Dimensions[2];
    }
  else
    {
    header.npic = 1;
    }
  header.file_id = BIORAD_MAGIC_NUMBER;

  // Always say that image was not edited:
  header.edited = 0;

  // Default dummy values:
  header.lens = 1;
  // Set the if file is in byte format or not:
  switch(this->GetComponentType())
    {
    case UCHAR:
      header.byte_format = 1;
      header.ramp1_min = 0;
      header.ramp1_max = 255;
      header.ramp2_min = 0;
      header.ramp2_max = 255;
      break;
    case USHORT:
      header.byte_format = 0;
      header.ramp1_min = 0;
      header.ramp1_max = 65535;
      header.ramp2_min = 0;
      header.ramp2_max = 65535;
      break;
    default:
      itkExceptionMacro(<<"Component type not supported.");
      return;
    }
  // write the actual header
  ByteSwapper<unsigned short>::SwapRangeFromSystemToLittleEndian(
    reinterpret_cast<unsigned short*>(p), BIORAD_HEADER_LENGTH/2);
  // To be able to deduce pixel spacing:
  float mag_factor = m_Spacing[0];
  ByteSwapper<float>::SwapFromSystemToLittleEndian(&mag_factor);
  memcpy(&header.mag_factor, (char*)(&mag_factor), 4);
  // Set the filename
  // NOTES: This is not very clear what should be written here, some files
  // have either:
  // 1. FILENAME.PIC
  // 2. FILENAME.pic
  // 3. FileName.pic
  // or simply
  // 4. FileName
  std::string filename = itksys::SystemTools::GetFilenameName(m_FileName);
  // The buffer is at most 32 bytes:
  strncpy(header.filename, filename.c_str(), sizeof(header.filename));
  file.write((char*)p, BIORAD_HEADER_LENGTH);

  //preparation for writing buffer:
  const unsigned long numberOfBytes      = this->GetImageSizeInBytes();
  const unsigned long numberOfComponents = this->GetImageSizeInComponents();

  char *tempmemory = new char[numberOfBytes];
  memcpy(tempmemory,buffer,numberOfBytes);
  if(this->GetComponentType() == USHORT)
    {
    ByteSwapper<unsigned short>::SwapRangeFromSystemToBigEndian(
        reinterpret_cast<unsigned short*>(tempmemory), numberOfComponents );
    }

  // Write the actual pixel data
  file.write( static_cast<const char *>(tempmemory) , numberOfBytes );
  delete [] tempmemory;
  file.close();
}

void BioRadImageIO::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
}

} // end namespace itk
<|endoftext|>


<commit_before>#ifndef LOG_HPP
#define LOG_HPP

#include "OE/Config.hpp"

#if OE_ANDROID
	#include "OE/Platform/Android/Android.hpp"
#endif
#if OE_WINDOWS
	#include "OE/Platform/Windows/Windows.hpp"
#endif

#include <sstream>
#include <cstring>
#include <string>

namespace OrbitEngine {
	enum LogLevel {
		LOG_DEBUG = 0,
		LOG_INFO,
		LOG_WARNING,
		LOG_ERROR,
		LOG_FATAL
	};

	class Log {
	public:
		static void log(const char* file, int line, const char* message, LogLevel level);
	};
}

#define OE_LOG(message, level) \
{ \
	std::ostringstream _os_; \
	_os_ << message; \
	OrbitEngine::Log::log(__FILE__, __LINE__, _os_.str().c_str(), level); \
}

#if OE_DEBUG && OE_WINDOWS
#define OE_BREAK __debugbreak();
#else
#define OE_BREAK {};
#endif

#define OE_LOG_DEBUG(message) OE_LOG(message, OrbitEngine::LOG_DEBUG)
#define OE_LOG_INFO(message) OE_LOG(message, OrbitEngine::LOG_INFO)
#define OE_LOG_WARNING(message) OE_LOG(message, OrbitEngine::LOG_WARNING)
#define OE_LOG_ERROR(message) OE_LOG(message, OrbitEngine::LOG_ERROR)
#define OE_LOG_FATAL(message) OE_LOG(message, OrbitEngine::LOG_FATAL)

#if OE_WINDOWS
	#define OE_LOG_FATAL_SHOWBOX_AND_EXIT(message) \
	{ \
		OE_LOG_FATAL(message) \
		std::ostringstream os_; \
		os_ << message << "\n\nThe application may now exit."; \
		MessageBox(NULL, \
				   os_.str().c_str(), \
				   "OrbitEngine - FATAL", \
				   MB_ICONERROR | MB_OK); \
		OE_BREAK \
	}
#else
	#define OE_LOG_FATAL_SHOWBOX_AND_EXIT(message) OE_LOG_FATAL(message)
#endif

#ifdef OE_DEBUG
#define OE_ASSERT_MSG(condition, msg) \
{ \
	if(!(condition)){ \
		OE_LOG_FATAL("---------------------") \
		OE_LOG_FATAL("ASSERTION FAILED!") \
		OE_LOG_FATAL("File: " << __FILE__) \
		OE_LOG_FATAL("Line: " << __LINE__) \
		OE_LOG_FATAL("Function: " << __FUNCTION__) \
		OE_LOG_FATAL("Condition: (" << #condition << ")") \
		OE_LOG_FATAL("Details: " << #msg) \
		OE_LOG_FATAL("---------------------") \
		OE_BREAK \
	} \
};
#else
#define OE_ASSERT_MSG(condition, msg)
#endif

#define NOARG
#define OE_ASSERT(condition) OE_ASSERT_MSG(condition, NOARG)

#endif<commit_msg>Disabling logging on Release<commit_after>#ifndef LOG_HPP
#define LOG_HPP

#include "OE/Config.hpp"

#if OE_ANDROID
	#include "OE/Platform/Android/Android.hpp"
#endif
#if OE_WINDOWS
	#include "OE/Platform/Windows/Windows.hpp"
#endif

#include <sstream>
#include <cstring>
#include <string>

namespace OrbitEngine {
	enum LogLevel {
		LOG_DEBUG = 0,
		LOG_INFO,
		LOG_WARNING,
		LOG_ERROR,
		LOG_FATAL
	};

	class Log {
	public:
		static void log(const char* file, int line, const char* message, LogLevel level);
	};
}

#define OE_LOG(message, level) \
{ \
	std::ostringstream _os_; \
	_os_ << message; \
	OrbitEngine::Log::log(__FILE__, __LINE__, _os_.str().c_str(), level); \
}

#if OE_DEBUG && OE_WINDOWS
#define OE_BREAK __debugbreak();
#else
#define OE_BREAK {};
#endif

#define OE_LOG_DEBUG(message) OE_LOG(message, OrbitEngine::LOG_DEBUG)
#define OE_LOG_INFO(message) OE_LOG(message, OrbitEngine::LOG_INFO)
#define OE_LOG_WARNING(message) OE_LOG(message, OrbitEngine::LOG_WARNING)
#define OE_LOG_ERROR(message) OE_LOG(message, OrbitEngine::LOG_ERROR)
#define OE_LOG_FATAL(message) OE_LOG(message, OrbitEngine::LOG_FATAL)

// disable debug messages
#if !OE_DEBUG
	#define OE_LOG_DEBUG(message)
#endif

#if OE_WINDOWS
	#define OE_LOG_FATAL_SHOWBOX_AND_EXIT(message) \
	{ \
		OE_LOG_FATAL(message) \
		std::ostringstream os_; \
		os_ << message << "\n\nThe application may now exit."; \
		MessageBox(NULL, \
				   os_.str().c_str(), \
				   "OrbitEngine - FATAL", \
				   MB_ICONERROR | MB_OK); \
		OE_BREAK \
	}
#else
	#define OE_LOG_FATAL_SHOWBOX_AND_EXIT(message) OE_LOG_FATAL(message)
#endif

#if OE_DEBUG
#define OE_ASSERT_MSG(condition, msg) \
{ \
	if(!(condition)){ \
		OE_LOG_FATAL("---------------------") \
		OE_LOG_FATAL("ASSERTION FAILED!") \
		OE_LOG_FATAL("File: " << __FILE__) \
		OE_LOG_FATAL("Line: " << __LINE__) \
		OE_LOG_FATAL("Function: " << __FUNCTION__) \
		OE_LOG_FATAL("Condition: (" << #condition << ")") \
		OE_LOG_FATAL("Details: " << #msg) \
		OE_LOG_FATAL("---------------------") \
		OE_BREAK \
	} \
};
#else
	#define OE_ASSERT_MSG(condition, msg)
#endif

#define NOARG
#define OE_ASSERT(condition) OE_ASSERT_MSG(condition, NOARG)

#endif<|endoftext|>


<commit_before>#include "data-student.hpp"
using namespace std;

void Student::init(string n, int s, int g, string m) {
	name = n;
	startingYear = s;
	gradutationYear = g;
	addMajors(m);
}

Student::Student() {
	init("", 2000, 2004, "");
}
Student::Student(string n, string s, string e, string m) {
	int startYear = stringToInt(s), endYear = stringToInt(e);
	init(n, startYear, endYear, m);
}

Student::Student(string fn) {
	string yearS, yearE;
	ifstream infile(fn.c_str());
	string nextLine;
	vector<string> lines;

	// load the entire file
	while (infile.peek() != -1) {
		getline(infile, nextLine);
		lines.push_back(nextLine);
	}

	string previousHeading;
	for (vector<string>::iterator i = lines.begin(); i != lines.end(); ++i) {
		string str = *i;
		if (previousHeading.empty())
			previousHeading = "# NAME";
		if (str[0] == '#') {
			previousHeading = *i;
			continue;
		}
		else if (str != "") {
			if (str.substr(0, 2) == "//") {
				// it's a comment
			}
			else if (previousHeading == "# NAME")
				name = str;
			else if (previousHeading == "# MAJORS")
				addMajor(Major(str));
			else if (previousHeading == "# CONCENTRATIONS")
				addConcentration(Concentration(str));
			else if (previousHeading == "# COURSES")
				addCourse(Course(str));
			else if (previousHeading == "# LABS")
				addCourse(Course(str));
		}
	}
}

void Student::addMajor(const Major& m) {
	majors.push_back(m);
}

void Student::addMajors(string str) {
	vector<string> record = split(str, ',');
	for (vector<string>::iterator i = record.begin(); i != record.end(); ++i)
		addMajor(Major(*i));
}

void Student::addConcentration(const Concentration& m) {
	concentrations.push_back(m);
}

void Student::addConcentrations(string str) {
	vector<string> record = split(str, ',');
	for (vector<string>::iterator i = record.begin(); i != record.end(); ++i)
		addConcentration(Concentration(*i));
}

void Student::addCourse(const Course& c) {
	courses.push_back(c);
}

void Student::addCourses(string str) {
	vector<string> record = split(str, ',');
	for (vector<string>::iterator i = record.begin(); i != record.end(); ++i)
		addCourse(Course(*i));
}

bool Student::hasTakenCourse(string str) {
	bool userHasTaken = false;
	Course checkAgainst = getCourse(str);
	for (std::vector<Course>::iterator i = courses.begin(); i != courses.end(); ++i)
		if (*i == checkAgainst)
			userHasTaken = true;
	return userHasTaken;
}

ostream& Student::getData(ostream &os) {
	os << name << ", ";

	if (majors.size()) {
		os << "you are majoring in ";

		for (vector<Major>::iterator i = majors.begin(); i != majors.end(); ++i){
			if (majors.size() == 1) {
				os << *i << " ";
			}
			else if (majors.size() == 2) {
				os << *i;
				if (i != majors.end()-1)
					os << " and ";
				else
					os << " ";
			}
			else {
				if (i != majors.end()-1)
					os << *i << ", ";
				else
					os << "and " << *i << ", ";
			}
		}
	}

	if (concentrations.size()) {
		os << "with concentrations in ";

		for (vector<Concentration>::iterator i = concentrations.begin(); i != concentrations.end(); ++i) {
			if (concentrations.size() == 1) {
				os << *i << " ";
			}
			if (concentrations.size() == 2) {
				os << *i;
				if (i != concentrations.end()-1)
					os << " and ";
				else
					os << " ";
			}
			else {
				if (i != concentrations.end()-1)
					os << *i << ", ";
				else
					os << "and " << *i << ", ";
			}
		}
	}

	if (!majors.size())
		os << "you are taking: " << endl;
	else
		os << "while taking:" << endl;

	for (vector<Course>::iterator i = courses.begin(); i != courses.end(); ++i)
		os << *i << endl;

	return os;
}

void Student::display() {
	cout << *this << endl;
};

ostream& operator<<(ostream& os, Student& item) {
	return item.getData(os);
}
<commit_msg>Improve the Student file parser again<commit_after>#include "data-student.hpp"
using namespace std;

void Student::init(string n, int s, int g, string m) {
	name = n;
	startingYear = s;
	gradutationYear = g;
	addMajors(m);
}

Student::Student() {
	init("", 2000, 2004, "");
}
Student::Student(string n, string s, string e, string m) {
	int startYear = stringToInt(s), endYear = stringToInt(e);
	init(n, startYear, endYear, m);
}

Student::Student(string fn) {
	string yearS, yearE;
	ifstream infile(fn.c_str());
	string nextLine;
	vector<string> lines;

	// load the entire file
	while (infile.peek() != -1) {
		getline(infile, nextLine);
		lines.push_back(nextLine);
	}

	string previousHeading;
	for (vector<string>::iterator i = lines.begin(); i != lines.end(); ++i) {
		string str = *i;
		if (previousHeading.empty())
			previousHeading = "# NAME";
		if (str[0] == '#') {
			std::transform(str.begin(), str.end(), str.begin(), ::toupper);
			previousHeading = *i;
			continue;
		}
		else if (str != "") {
			if (str.substr(0, 2) == "//") {
				// it's a comment
			}
			else if (previousHeading == "# NAME")
				name = str;
			else if (previousHeading == "# MAJORS")
				addMajor(Major(str));
			else if (previousHeading == "# CONCENTRATIONS")
				addConcentration(Concentration(str));
			else if (previousHeading == "# COURSES")
				addCourse(Course(str));
			else if (previousHeading == "# LABS")
				addCourse(Course(str));
		}
	}
}

void Student::addMajor(const Major& m) {
	majors.push_back(m);
}

void Student::addMajors(string str) {
	vector<string> record = split(str, ',');
	for (vector<string>::iterator i = record.begin(); i != record.end(); ++i)
		addMajor(Major(*i));
}

void Student::addConcentration(const Concentration& m) {
	concentrations.push_back(m);
}

void Student::addConcentrations(string str) {
	vector<string> record = split(str, ',');
	for (vector<string>::iterator i = record.begin(); i != record.end(); ++i)
		addConcentration(Concentration(*i));
}

void Student::addCourse(const Course& c) {
	courses.push_back(c);
}

void Student::addCourses(string str) {
	vector<string> record = split(str, ',');
	for (vector<string>::iterator i = record.begin(); i != record.end(); ++i)
		addCourse(Course(*i));
}

bool Student::hasTakenCourse(string str) {
	bool userHasTaken = false;
	Course checkAgainst = getCourse(str);
	for (std::vector<Course>::iterator i = courses.begin(); i != courses.end(); ++i)
		if (*i == checkAgainst)
			userHasTaken = true;
	return userHasTaken;
}

ostream& Student::getData(ostream &os) {
	os << name << ", ";

	if (majors.size()) {
		os << "you are majoring in ";

		for (vector<Major>::iterator i = majors.begin(); i != majors.end(); ++i){
			if (majors.size() == 1) {
				os << *i << " ";
			}
			else if (majors.size() == 2) {
				os << *i;
				if (i != majors.end()-1)
					os << " and ";
				else
					os << " ";
			}
			else {
				if (i != majors.end()-1)
					os << *i << ", ";
				else
					os << "and " << *i << ", ";
			}
		}
	}

	if (concentrations.size()) {
		os << "with concentrations in ";

		for (vector<Concentration>::iterator i = concentrations.begin(); i != concentrations.end(); ++i) {
			if (concentrations.size() == 1) {
				os << *i << " ";
			}
			if (concentrations.size() == 2) {
				os << *i;
				if (i != concentrations.end()-1)
					os << " and ";
				else
					os << " ";
			}
			else {
				if (i != concentrations.end()-1)
					os << *i << ", ";
				else
					os << "and " << *i << ", ";
			}
		}
	}

	if (!majors.size())
		os << "you are taking: " << endl;
	else
		os << "while taking:" << endl;

	for (vector<Course>::iterator i = courses.begin(); i != courses.end(); ++i) {
		if (i != courses.end()-1)
			os << *i << endl;
		else
			os << *i;
	}

	return os;
}

void Student::display() {
	cout << *this << endl;
};

ostream& operator<<(ostream& os, Student& item) {
	return item.getData(os);
}
<|endoftext|>


<commit_before>//
// Created by Lucas on 10/15/2016.
//

#include "first.h"

FirstSet *first(GramaticalRule *gramaticalrule)
{
    int mudou = 0;
    while (mudou)
    {

    }

}
<commit_msg>Iniciando implementação algoritmo First<commit_after>//
// Created by Lucas on 10/15/2016.
//

#include "first.h"

FirstSet *first(GramaticalRule *gramaticalrule)
{
    int mudou = 0;
    do
    {
        GramaticalRule currentrule = gramaticalrule;
        while (currentrule != NULL)
        {

            currentrule = currentrule.next;
        }

    } while (mudou);

}
<|endoftext|>


<commit_before>#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
	printf("hello world!\n");
	return 0;
}
<commit_msg>	modified:   hello.cpp<commit_after>#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
	printf("hello world from linux!\n");
	return 0;
}
<|endoftext|>


<commit_before>/*=============================================================================
  NiftyLink:  A software library to facilitate communication over OpenIGTLink.

  Copyright (c) University College London (UCL). All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

  See LICENSE.txt in the top level directory for details.
=============================================================================*/
#include "NiftyLinkTcpClient.h"
#include "NiftyLinkTcpNetworkWorker.h"
#include <NiftyLinkQThread.h>
#include <NiftyLinkUtils.h>

#include <igtlMessageBase.h>
#include <QsLog.h>
#include <QMutexLocker>

namespace niftk
{

//-----------------------------------------------------------------------------
NiftyLinkTcpClient::NiftyLinkTcpClient(QObject *parent)
: QObject(parent)
, m_State(UNCONNECTED)
, m_Socket(NULL)
, m_Worker(NULL)
, m_Thread(NULL)
, m_RequestedName("")
, m_RequestedPort(-1)
{
  this->setObjectName("NiftyLinkTcpClient");
  QLOG_INFO() << QObject::tr("%1::NiftyLinkTcpClient() - creating.").arg(objectName());

  qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
  qRegisterMetaType<NiftyLinkMessageContainer::Pointer>("NiftyLinkMessageContainer::Pointer");
  qRegisterMetaType<NiftyLinkMessageStatsContainer>("NiftyLinkMessageStatsContainer");

  // This is to make sure we have the best possible system timer.
#if defined(_WIN32) && !defined(__CYGWIN__)
  niftk::InitializeWinTimers();
#endif

  // We create all this here, so we know that m_Socket and m_Worker are always populated.
  m_Socket = new QTcpSocket();
  connect(m_Socket, SIGNAL(connected()), this, SLOT(OnConnected()));
  connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(OnError()));
  m_Worker = new NiftyLinkTcpNetworkWorker("NiftyLinkTcpClientWorker", &m_InboundMessages, &m_OutboundMessages, m_Socket);

  QLOG_INFO() << QObject::tr("%1::NiftyLinkTcpClient() - created.").arg(objectName());
}

//-----------------------------------------------------------------------------
NiftyLinkTcpClient::~NiftyLinkTcpClient()
{
  QString name = objectName();
  QLOG_INFO() << QObject::tr("%1::~NiftyLinkTcpClient() - destroying.").arg(name);

  if (m_State != UNCONNECTED)
  {
    // Not sure if we need this, if we are not connected yet, we could just destroy this object?
    if (m_State == CONNECTING)
    {
      while(m_State != CONNECTED)
      {
        QCoreApplication::processEvents();
        NiftyLinkQThread::SleepCallingThread(1);
      }
    }

    // We have to request, and then wait for eveything to shut-down.
    if (this->IsConnected())
    {
      // This should block/wait until the worker really is shutdown,
      // and everything disconnected, so that we really are ready to destroy this.
      this->DisconnectFromHost();
    }

    while(m_State != SHUTDOWN)
    {
      QCoreApplication::processEvents();
      NiftyLinkQThread::SleepCallingThread(1);
    }

    NiftyLinkQThread::SleepCallingThread(1000);
  }

  QLOG_INFO() << QObject::tr("%1::~NiftyLinkTcpClient() - destroyed.").arg(name);
}

//-----------------------------------------------------------------------------
NiftyLinkTcpClient::ClientState NiftyLinkTcpClient::GetState() const
{
  QMutexLocker locker(&m_Mutex);
  return m_State;
}

//-----------------------------------------------------------------------------
bool NiftyLinkTcpClient::IsConnected() const
{
  QMutexLocker locker(&m_Mutex);
  return m_State == CONNECTED;
}

//-----------------------------------------------------------------------------
int NiftyLinkTcpClient::GetRequestedPort() const
{
  QMutexLocker locker(&m_Mutex);
  return m_RequestedPort;
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::SetNumberMessageReceivedThreshold(qint64 threshold)
{
  m_Worker->SetNumberMessageReceivedThreshold(threshold);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::SetKeepAliveOn(bool isOn)
{
  m_Worker->SetKeepAliveOn(isOn);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::SetCheckForNoIncomingData(bool isOn)
{
  m_Worker->SetCheckForNoIncomingData(isOn);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OutputStats()
{
  m_Worker->OutputStatsToConsole();
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::RequestStats()
{
  m_Worker->RequestStats();
}

//-----------------------------------------------------------------------------
bool NiftyLinkTcpClient::Send(NiftyLinkMessageContainer::Pointer message)
{
  return m_Worker->Send(message);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::DisconnectFromHost()
{
  if (!this->IsConnected())
  {
    QLOG_WARN() << QObject::tr("%1::DisconnectFromHost() - received request to disconnect, when not connected, so I'm ignoring it.").arg(objectName());
    return;
  }

  // This triggers the shutdown process.
  m_Worker->RequestDisconnectSocket();

  // We MUST wait until the thread is shutdown, and then objects deleted.
  while(m_State != SHUTDOWN)
  {
    QCoreApplication::processEvents();
    NiftyLinkQThread::SleepCallingThread(1);
  }
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnMessageReceived(int portNumber)
{
  NiftyLinkMessageContainer::Pointer msg = m_InboundMessages.GetContainer(portNumber);
  emit MessageReceived(msg);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnError()
{
  // Remember, this method is called when the socket is registered with this class, and being processing in this event loop.
  QLOG_ERROR() << QObject::tr("%1::OnError() - code=%2, string=%3").arg(objectName()).arg(m_Socket->error()).arg(m_Socket->errorString());
  emit SocketError(this->m_RequestedName, this->m_RequestedPort, m_Socket->error(), m_Socket->errorString());
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnWorkerSocketError(int portNumber, QAbstractSocket::SocketError errorCode, QString errorString)
{
  // Remember, this method is called when the socket has moved into the worker object, and being processed in the worker thread.
  QLOG_ERROR() << QObject::tr("%1::OnWorkerSocketError() - code=%2, string=%3").arg(objectName()).arg(errorCode).arg(errorString);
  emit SocketError(this->m_RequestedName, this->m_RequestedPort, errorCode, errorString);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::RaiseInternalError(const QString& errorMessage)
{
  QLOG_ERROR() << QObject::tr("%1::RaiseInternalError() - message=%2").arg(objectName()).arg(errorMessage);
  emit ClientError(this->m_RequestedName, this->m_RequestedPort, errorMessage);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::ConnectToHost(const QString& hostName, quint16 portNumber)
{
  QMutexLocker locker(&m_Mutex);

  m_State = CONNECTING;
  m_RequestedName = hostName;
  m_RequestedPort = portNumber;

  // There are no errors reported from this. Listen to the error signal, see OnError().
  m_Socket->connectToHost(m_RequestedName, m_RequestedPort);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnConnected()
{
  QMutexLocker locker(&m_Mutex);

  this->setObjectName(QObject::tr("NiftyLinkTcpClient(%1:%2)").arg(m_Socket->peerName()).arg(m_Socket->peerPort()));
  m_Worker->UpdateObjectName();

  m_Socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);

  m_Thread = new NiftyLinkQThread();
  connect(m_Thread, SIGNAL(finished()), m_Thread, SLOT(deleteLater())); // i.e. the event loop of thread deletes it when control returns to this event loop.
  connect(m_Thread, SIGNAL(finished()), this, SLOT(OnThreadFinished()), Qt::BlockingQueuedConnection);

  m_Worker->moveToThread(m_Thread);
  m_Socket->moveToThread(m_Thread);

  connect(m_Worker, SIGNAL(SocketError(int,QAbstractSocket::SocketError,QString)), this, SLOT(OnWorkerSocketError(int,QAbstractSocket::SocketError,QString)));
  connect(m_Worker, SIGNAL(NoIncomingData()), this, SIGNAL(NoIncomingData()));
  connect(m_Worker, SIGNAL(SentKeepAlive()), this, SIGNAL(SentKeepAlive()));
  connect(m_Worker, SIGNAL(BytesSent(qint64)), this, SIGNAL(BytesSent(qint64)));
  connect(m_Worker, SIGNAL(MessageReceived(int)), this, SLOT(OnMessageReceived(int)));
  connect(m_Worker, SIGNAL(SocketDisconnected()), this, SLOT(OnDisconnected()), Qt::BlockingQueuedConnection);

  m_Thread->start();
  m_State = CONNECTED;

  QLOG_INFO() << QObject::tr("%1::OnConnected() - socket connected.").arg(objectName());
  emit Connected(this->m_RequestedName, this->m_RequestedPort);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnDisconnected()
{
  QMutexLocker locker(&m_Mutex);
  m_State = SHUTTINGDOWN;

  QLOG_INFO() << QObject::tr("%1::OnDisconnected() - worker disconnected.").arg(objectName());
  emit Disconnected(this->m_RequestedName, this->m_RequestedPort);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnThreadFinished()
{
  QMutexLocker locker(&m_Mutex);
  m_State = SHUTDOWN;

  QLOG_INFO() << QObject::tr("%1::OnThreadFinished().").arg(objectName());
}

} // end niftk namespace
<commit_msg>Bug #3609: Reduce scope of locking<commit_after>/*=============================================================================
  NiftyLink:  A software library to facilitate communication over OpenIGTLink.

  Copyright (c) University College London (UCL). All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

  See LICENSE.txt in the top level directory for details.
=============================================================================*/
#include "NiftyLinkTcpClient.h"
#include "NiftyLinkTcpNetworkWorker.h"
#include <NiftyLinkQThread.h>
#include <NiftyLinkUtils.h>

#include <igtlMessageBase.h>
#include <QsLog.h>
#include <QMutexLocker>

namespace niftk
{

//-----------------------------------------------------------------------------
NiftyLinkTcpClient::NiftyLinkTcpClient(QObject *parent)
: QObject(parent)
, m_State(UNCONNECTED)
, m_Socket(NULL)
, m_Worker(NULL)
, m_Thread(NULL)
, m_RequestedName("")
, m_RequestedPort(-1)
{
  this->setObjectName("NiftyLinkTcpClient");
  QLOG_INFO() << QObject::tr("%1::NiftyLinkTcpClient() - creating.").arg(objectName());

  qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
  qRegisterMetaType<NiftyLinkMessageContainer::Pointer>("NiftyLinkMessageContainer::Pointer");
  qRegisterMetaType<NiftyLinkMessageStatsContainer>("NiftyLinkMessageStatsContainer");

  // This is to make sure we have the best possible system timer.
#if defined(_WIN32) && !defined(__CYGWIN__)
  niftk::InitializeWinTimers();
#endif

  // We create all this here, so we know that m_Socket and m_Worker are always populated.
  m_Socket = new QTcpSocket();
  connect(m_Socket, SIGNAL(connected()), this, SLOT(OnConnected()));
  connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(OnError()));
  m_Worker = new NiftyLinkTcpNetworkWorker("NiftyLinkTcpClientWorker", &m_InboundMessages, &m_OutboundMessages, m_Socket);

  QLOG_INFO() << QObject::tr("%1::NiftyLinkTcpClient() - created.").arg(objectName());
}

//-----------------------------------------------------------------------------
NiftyLinkTcpClient::~NiftyLinkTcpClient()
{
  QString name = objectName();
  QLOG_INFO() << QObject::tr("%1::~NiftyLinkTcpClient() - destroying.").arg(name);

  if (m_State != UNCONNECTED)
  {
    // Not sure if we need this, if we are not connected yet, we could just destroy this object?
    if (m_State == CONNECTING)
    {
      while(m_State != CONNECTED)
      {
        QCoreApplication::processEvents();
        NiftyLinkQThread::SleepCallingThread(1);
      }
    }

    // We have to request, and then wait for eveything to shut-down.
    if (this->IsConnected())
    {
      // This should block/wait until the worker really is shutdown,
      // and everything disconnected, so that we really are ready to destroy this.
      this->DisconnectFromHost();
    }

    while(m_State != SHUTDOWN)
    {
      QCoreApplication::processEvents();
      NiftyLinkQThread::SleepCallingThread(1);
    }
    NiftyLinkQThread::SleepCallingThread(1000);
  }

  QLOG_INFO() << QObject::tr("%1::~NiftyLinkTcpClient() - destroyed.").arg(name);
}

//-----------------------------------------------------------------------------
NiftyLinkTcpClient::ClientState NiftyLinkTcpClient::GetState() const
{
  QMutexLocker locker(&m_Mutex);
  return m_State;
}

//-----------------------------------------------------------------------------
bool NiftyLinkTcpClient::IsConnected() const
{
  QMutexLocker locker(&m_Mutex);
  return m_State == CONNECTED;
}

//-----------------------------------------------------------------------------
int NiftyLinkTcpClient::GetRequestedPort() const
{
  QMutexLocker locker(&m_Mutex);
  return m_RequestedPort;
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::SetNumberMessageReceivedThreshold(qint64 threshold)
{
  m_Worker->SetNumberMessageReceivedThreshold(threshold);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::SetKeepAliveOn(bool isOn)
{
  m_Worker->SetKeepAliveOn(isOn);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::SetCheckForNoIncomingData(bool isOn)
{
  m_Worker->SetCheckForNoIncomingData(isOn);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OutputStats()
{
  m_Worker->OutputStatsToConsole();
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::RequestStats()
{
  m_Worker->RequestStats();
}

//-----------------------------------------------------------------------------
bool NiftyLinkTcpClient::Send(NiftyLinkMessageContainer::Pointer message)
{
  return m_Worker->Send(message);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::DisconnectFromHost()
{
  if (!this->IsConnected())
  {
    QLOG_WARN() << QObject::tr("%1::DisconnectFromHost() - received request to disconnect, when not connected, so I'm ignoring it.").arg(objectName());
    return;
  }

  // This triggers the shutdown process.
  m_Worker->RequestDisconnectSocket();

  // We MUST wait until the thread is shutdown, and then objects deleted.
  while(m_State != SHUTDOWN)
  {
    QCoreApplication::processEvents();
    NiftyLinkQThread::SleepCallingThread(1);
  }
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnMessageReceived(int portNumber)
{
  NiftyLinkMessageContainer::Pointer msg = m_InboundMessages.GetContainer(portNumber);
  emit MessageReceived(msg);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnError()
{
  // Remember, this method is called when the socket is registered with this class, and being processing in this event loop.
  QLOG_ERROR() << QObject::tr("%1::OnError() - code=%2, string=%3").arg(objectName()).arg(m_Socket->error()).arg(m_Socket->errorString());
  emit SocketError(this->m_RequestedName, this->m_RequestedPort, m_Socket->error(), m_Socket->errorString());
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnWorkerSocketError(int portNumber, QAbstractSocket::SocketError errorCode, QString errorString)
{
  // Remember, this method is called when the socket has moved into the worker object, and being processed in the worker thread.
  QLOG_ERROR() << QObject::tr("%1::OnWorkerSocketError() - code=%2, string=%3").arg(objectName()).arg(errorCode).arg(errorString);
  emit SocketError(this->m_RequestedName, this->m_RequestedPort, errorCode, errorString);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::RaiseInternalError(const QString& errorMessage)
{
  QLOG_ERROR() << QObject::tr("%1::RaiseInternalError() - message=%2").arg(objectName()).arg(errorMessage);
  emit ClientError(this->m_RequestedName, this->m_RequestedPort, errorMessage);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::ConnectToHost(const QString& hostName, quint16 portNumber)
{
  {
    QMutexLocker locker(&m_Mutex);
    m_State = CONNECTING;
    m_RequestedName = hostName;
    m_RequestedPort = portNumber;
  }

  // There are no errors reported from this. Listen to the error signal, see OnError().
  m_Socket->connectToHost(m_RequestedName, m_RequestedPort);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnConnected()
{
  this->setObjectName(QObject::tr("NiftyLinkTcpClient(%1:%2)").arg(m_Socket->peerName()).arg(m_Socket->peerPort()));
  m_Worker->UpdateObjectName();

  m_Socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);

  m_Thread = new NiftyLinkQThread();
  connect(m_Thread, SIGNAL(finished()), m_Thread, SLOT(deleteLater())); // i.e. the event loop of thread deletes it when control returns to this event loop.
  connect(m_Thread, SIGNAL(finished()), this, SLOT(OnThreadFinished()), Qt::BlockingQueuedConnection);

  m_Worker->moveToThread(m_Thread);
  m_Socket->moveToThread(m_Thread);

  connect(m_Worker, SIGNAL(SocketError(int,QAbstractSocket::SocketError,QString)), this, SLOT(OnWorkerSocketError(int,QAbstractSocket::SocketError,QString)));
  connect(m_Worker, SIGNAL(NoIncomingData()), this, SIGNAL(NoIncomingData()));
  connect(m_Worker, SIGNAL(SentKeepAlive()), this, SIGNAL(SentKeepAlive()));
  connect(m_Worker, SIGNAL(BytesSent(qint64)), this, SIGNAL(BytesSent(qint64)));
  connect(m_Worker, SIGNAL(MessageReceived(int)), this, SLOT(OnMessageReceived(int)));
  connect(m_Worker, SIGNAL(SocketDisconnected()), this, SLOT(OnDisconnected()), Qt::BlockingQueuedConnection);

  {
    QMutexLocker locker(&m_Mutex);
    m_Thread->start();
    m_State = CONNECTED;
  }

  QLOG_INFO() << QObject::tr("%1::OnConnected() - socket connected.").arg(objectName());
  emit Connected(this->m_RequestedName, this->m_RequestedPort);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnDisconnected()
{
  QMutexLocker locker(&m_Mutex);
  m_State = SHUTTINGDOWN;

  QLOG_INFO() << QObject::tr("%1::OnDisconnected() - worker disconnected.").arg(objectName());
  emit Disconnected(this->m_RequestedName, this->m_RequestedPort);
}

//-----------------------------------------------------------------------------
void NiftyLinkTcpClient::OnThreadFinished()
{
  QMutexLocker locker(&m_Mutex);
  m_State = SHUTDOWN;

  QLOG_INFO() << QObject::tr("%1::OnThreadFinished().").arg(objectName());
}

} // end niftk namespace
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/stream_texture_factory_impl_android.h"

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop_proxy.h"
#include "base/synchronization/lock.h"
#include "content/common/android/surface_texture_peer.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStreamTextureClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h"
#include "ui/gfx/size.h"

namespace {

static void DeleteStreamTextureHost(content::StreamTextureHost* host) {
  delete host;
}

// Implementation of the StreamTextureProxy class. This class listens to all
// the stream texture updates and forward them to the WebStreamTextureClient.
class StreamTextureProxyImpl : public webkit_media::StreamTextureProxy,
                               public content::StreamTextureHost::Listener {
 public:
  explicit StreamTextureProxyImpl(content::StreamTextureHost* host);
  virtual ~StreamTextureProxyImpl();

  // webkit_media::StreamTextureProxy implementation:
  virtual bool Initialize(int stream_id, int width, int height) OVERRIDE;
  virtual bool IsInitialized() OVERRIDE { return initialized_; }
  virtual void SetClient(WebKit::WebStreamTextureClient* client) OVERRIDE;

  // StreamTextureHost::Listener implementation:
  virtual void OnFrameAvailable() OVERRIDE;
  virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;

 private:
  scoped_ptr<content::StreamTextureHost> host_;
  scoped_refptr<base::MessageLoopProxy> loop_;

  base::Lock client_lock_;
  WebKit::WebStreamTextureClient* client_;
  bool initialized_;

  DISALLOW_COPY_AND_ASSIGN(StreamTextureProxyImpl);
};

StreamTextureProxyImpl::StreamTextureProxyImpl(
    content::StreamTextureHost* host)
    : host_(host),
      client_(NULL),
      initialized_(false) {
  DCHECK(host);
  host->SetListener(this);
}

StreamTextureProxyImpl::~StreamTextureProxyImpl() {
  SetClient(NULL);
  // The StreamTextureHost instance needs to be deleted on the thread
  // it receives messages on (where it uses a WeakPtr).
  if (loop_.get()) {
    loop_->PostTask(FROM_HERE, base::Bind(&DeleteStreamTextureHost,
                                          host_.release()));
  }
}

void StreamTextureProxyImpl::SetClient(WebKit::WebStreamTextureClient* client) {
  base::AutoLock lock(client_lock_);
  client_ = client;
}

bool StreamTextureProxyImpl::Initialize(int stream_id, int width, int height) {
  loop_ = base::MessageLoopProxy::current();
  initialized_ = true;
  return host_->Initialize(stream_id, gfx::Size(width, height));
}

void StreamTextureProxyImpl::OnFrameAvailable() {
  base::AutoLock lock(client_lock_);
  if (client_)
    client_->didReceiveFrame();
}

void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
  base::AutoLock lock(client_lock_);
  if (client_)
    client_->didUpdateMatrix(matrix);
}

}  // anonymous namespace

namespace content {

StreamTextureFactoryImpl::StreamTextureFactoryImpl(
    WebKit::WebGraphicsContext3D* context,
    GpuChannelHost* channel,
    int view_id)
    : context_(context),
      channel_(channel),
      view_id_(view_id) {
  DCHECK(context_);
  DCHECK(channel);
}

StreamTextureFactoryImpl::~StreamTextureFactoryImpl() {
}

webkit_media::StreamTextureProxy* StreamTextureFactoryImpl::CreateProxy() {
  DCHECK(channel_.get());
  StreamTextureHost* host = new StreamTextureHost(channel_.get());
  return new StreamTextureProxyImpl(host);
}

void StreamTextureFactoryImpl::EstablishPeer(int stream_id, int player_id) {
  DCHECK(channel_.get());
  channel_->Send(new GpuChannelMsg_EstablishStreamTexture(
      stream_id, SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE,
      view_id_, player_id));
}

unsigned StreamTextureFactoryImpl::CreateStreamTexture(unsigned* texture_id) {
  unsigned stream_id = 0;
  if (context_->makeContextCurrent()) {
    *texture_id = context_->createTexture();
    // TODO(qinmin): upstream the implementation of
    // WebGraphicsContext::createStreamTextureCHROMIUM().
    // stream_id = context_->createStreamTextureCHROMIUM(*texture_id);
    context_->flush();
  }
  return stream_id;
}

void StreamTextureFactoryImpl::DestroyStreamTexture(unsigned texture_id) {
  if (context_->makeContextCurrent()) {
    // TODO(qinmin): upstream the implementation of
    // WebGraphicsContext::destroyStreamTextureCHROMIUM().
    // context_->destroyStreamTextureCHROMIUM(texture_id);
    context_->deleteTexture(texture_id);
    context_->flush();
  }
}

}  // namespace content
<commit_msg>Uncomment calls to createStreamTextureChomium and destroyStreamTextureChromium<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/stream_texture_factory_impl_android.h"

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop_proxy.h"
#include "base/synchronization/lock.h"
#include "content/common/android/surface_texture_peer.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStreamTextureClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h"
#include "ui/gfx/size.h"

namespace {

static void DeleteStreamTextureHost(content::StreamTextureHost* host) {
  delete host;
}

// Implementation of the StreamTextureProxy class. This class listens to all
// the stream texture updates and forward them to the WebStreamTextureClient.
class StreamTextureProxyImpl : public webkit_media::StreamTextureProxy,
                               public content::StreamTextureHost::Listener {
 public:
  explicit StreamTextureProxyImpl(content::StreamTextureHost* host);
  virtual ~StreamTextureProxyImpl();

  // webkit_media::StreamTextureProxy implementation:
  virtual bool Initialize(int stream_id, int width, int height) OVERRIDE;
  virtual bool IsInitialized() OVERRIDE { return initialized_; }
  virtual void SetClient(WebKit::WebStreamTextureClient* client) OVERRIDE;

  // StreamTextureHost::Listener implementation:
  virtual void OnFrameAvailable() OVERRIDE;
  virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;

 private:
  scoped_ptr<content::StreamTextureHost> host_;
  scoped_refptr<base::MessageLoopProxy> loop_;

  base::Lock client_lock_;
  WebKit::WebStreamTextureClient* client_;
  bool initialized_;

  DISALLOW_COPY_AND_ASSIGN(StreamTextureProxyImpl);
};

StreamTextureProxyImpl::StreamTextureProxyImpl(
    content::StreamTextureHost* host)
    : host_(host),
      client_(NULL),
      initialized_(false) {
  DCHECK(host);
  host->SetListener(this);
}

StreamTextureProxyImpl::~StreamTextureProxyImpl() {
  SetClient(NULL);
  // The StreamTextureHost instance needs to be deleted on the thread
  // it receives messages on (where it uses a WeakPtr).
  if (loop_.get()) {
    loop_->PostTask(FROM_HERE, base::Bind(&DeleteStreamTextureHost,
                                          host_.release()));
  }
}

void StreamTextureProxyImpl::SetClient(WebKit::WebStreamTextureClient* client) {
  base::AutoLock lock(client_lock_);
  client_ = client;
}

bool StreamTextureProxyImpl::Initialize(int stream_id, int width, int height) {
  loop_ = base::MessageLoopProxy::current();
  initialized_ = true;
  return host_->Initialize(stream_id, gfx::Size(width, height));
}

void StreamTextureProxyImpl::OnFrameAvailable() {
  base::AutoLock lock(client_lock_);
  if (client_)
    client_->didReceiveFrame();
}

void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
  base::AutoLock lock(client_lock_);
  if (client_)
    client_->didUpdateMatrix(matrix);
}

}  // anonymous namespace

namespace content {

StreamTextureFactoryImpl::StreamTextureFactoryImpl(
    WebKit::WebGraphicsContext3D* context,
    GpuChannelHost* channel,
    int view_id)
    : context_(context),
      channel_(channel),
      view_id_(view_id) {
  DCHECK(context_);
  DCHECK(channel);
}

StreamTextureFactoryImpl::~StreamTextureFactoryImpl() {
}

webkit_media::StreamTextureProxy* StreamTextureFactoryImpl::CreateProxy() {
  DCHECK(channel_.get());
  StreamTextureHost* host = new StreamTextureHost(channel_.get());
  return new StreamTextureProxyImpl(host);
}

void StreamTextureFactoryImpl::EstablishPeer(int stream_id, int player_id) {
  DCHECK(channel_.get());
  channel_->Send(new GpuChannelMsg_EstablishStreamTexture(
      stream_id, SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE,
      view_id_, player_id));
}

unsigned StreamTextureFactoryImpl::CreateStreamTexture(unsigned* texture_id) {
  unsigned stream_id = 0;
  if (context_->makeContextCurrent()) {
    *texture_id = context_->createTexture();
    stream_id = context_->createStreamTextureCHROMIUM(*texture_id);
    context_->flush();
  }
  return stream_id;
}

void StreamTextureFactoryImpl::DestroyStreamTexture(unsigned texture_id) {
  if (context_->makeContextCurrent()) {
    context_->destroyStreamTextureCHROMIUM(texture_id);
    context_->deleteTexture(texture_id);
    context_->flush();
  }
}

}  // namespace content
<|endoftext|>