<commit_before>/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/** @file
 * Device model for an IDE disk
 */

#ifndef __IDE_DISK_HH__
#define __IDE_DISK_HH__

#include "base/statistics.hh"
#include "dev/disk_image.hh"
#include "dev/ide_atareg.h"
#include "dev/ide_ctrl.hh"
#include "dev/ide_wdcreg.h"
#include "dev/io_device.hh"
#include "sim/eventq.hh"

#define DMA_BACKOFF_PERIOD 200

#define MAX_DMA_SIZE    (65536)  // 64K
#define MAX_MULTSECT    (128)

#define PRD_BASE_MASK  0xfffffffe
#define PRD_COUNT_MASK 0xfffe
#define PRD_EOT_MASK   0x8000

typedef struct PrdEntry {
    uint32_t baseAddr;
    uint16_t byteCount;
    uint16_t endOfTable;
} PrdEntry_t;

class PrdTableEntry {
  public:
    PrdEntry_t entry;

    uint32_t getBaseAddr()
    {
        return (entry.baseAddr & PRD_BASE_MASK);
    }

    uint32_t getByteCount()
    {
        return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
                (entry.byteCount & PRD_COUNT_MASK));
    }

    uint16_t getEOT()
    {
        return (entry.endOfTable & PRD_EOT_MASK);
    }
};

#define DATA_OFFSET     (0)
#define ERROR_OFFSET    (1)
#define FEATURES_OFFSET (1)
#define NSECTOR_OFFSET  (2)
#define SECTOR_OFFSET   (3)
#define LCYL_OFFSET     (4)
#define HCYL_OFFSET     (5)
#define SELECT_OFFSET   (6)
#define DRIVE_OFFSET    (6)
#define STATUS_OFFSET   (7)
#define COMMAND_OFFSET  (7)

#define CONTROL_OFFSET  (2)
#define ALTSTAT_OFFSET  (2)

#define SELECT_DEV_BIT  0x10
#define CONTROL_RST_BIT 0x04
#define CONTROL_IEN_BIT 0x02
#define STATUS_BSY_BIT  0x80
#define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT  0x08
#define STATUS_SEEK_BIT 0x10
#define STATUS_DF_BIT   0x20
#define DRIVE_LBA_BIT   0x40

#define DEV0 (0)
#define DEV1 (1)

typedef struct CommandReg {
    uint16_t data;
    uint8_t error;
    uint8_t sec_count;
    uint8_t sec_num;
    uint8_t cyl_low;
    uint8_t cyl_high;
    union {
        uint8_t drive;
        uint8_t head;
    };
    uint8_t command;
} CommandReg_t;

typedef enum Events {
    None = 0,
    Transfer,
    ReadWait,
    WriteWait,
    PrdRead,
    DmaRead,
    DmaWrite
} Events_t;

typedef enum DevAction {
    ACT_NONE = 0,
    ACT_CMD_WRITE,
    ACT_CMD_COMPLETE,
    ACT_CMD_ERROR,
    ACT_SELECT_WRITE,
    ACT_STAT_READ,
    ACT_DATA_READY,
    ACT_DATA_READ_BYTE,
    ACT_DATA_READ_SHORT,
    ACT_DATA_WRITE_BYTE,
    ACT_DATA_WRITE_SHORT,
    ACT_DMA_READY,
    ACT_DMA_DONE,
    ACT_SRST_SET,
    ACT_SRST_CLEAR
} DevAction_t;

typedef enum DevState {
    // Device idle
    Device_Idle_S = 0,
    Device_Idle_SI,
    Device_Idle_NS,

    // Software reset
    Device_Srst,

    // Non-data commands
    Command_Execution,

    // PIO data-in (data to host)
    Prepare_Data_In,
    Data_Ready_INTRQ_In,
    Transfer_Data_In,

    // PIO data-out (data from host)
    Prepare_Data_Out,
    Data_Ready_INTRQ_Out,
    Transfer_Data_Out,

    // DMA protocol
    Prepare_Data_Dma,
    Transfer_Data_Dma
} DevState_t;

typedef enum DmaState {
    Dma_Idle = 0,
    Dma_Start,
    Dma_Transfer
} DmaState_t;

class PhysicalMemory;
class IdeController;

/**
 * IDE Disk device model
 */
class IdeDisk : public SimObject
{
  protected:
    /** The IDE controller for this disk. */
    IdeController *ctrl;
    /** The DMA interface to use for transfers */
    DMAInterface<Bus> *dmaInterface;
    /** The image that contains the data of this disk. */
    DiskImage *image;
    /** Pointer to physical memory for DMA transfers */
    PhysicalMemory *physmem;

  protected:
    /** The disk delay in microseconds. */
    int diskDelay;

  private:
    /** Drive identification structure for this disk */
    struct ataparams driveID;
    /** Data buffer for transfers */
    uint8_t *dataBuffer;
    /** Number of bytes in command data transfer */
    uint32_t cmdBytes;
    /** Number of bytes left in command data transfer */
    uint32_t cmdBytesLeft;
    /** Number of bytes left in DRQ block */
    uint32_t drqBytesLeft;
    /** Current sector in access */
    uint32_t curSector;
    /** Command block registers */
    CommandReg_t cmdReg;
    /** Status register */
    uint8_t status;
    /** Interrupt enable bit */
    bool nIENBit;
    /** Device state */
    DevState_t devState;
    /** Dma state */
    DmaState_t dmaState;
    /** Dma transaction is a read */
    bool dmaRead;
    /** PRD table base address */
    uint32_t curPrdAddr;
    /** PRD entry */
    PrdTableEntry curPrd;
    /** Number of bytes transfered by DMA interface for current transfer */
    uint32_t dmaInterfaceBytes;
    /** Device ID (master=0/slave=1) */
    int devID;
    /** Interrupt pending */
    bool intrPending;

    Stats::Scalar<> dmaReadFullPages;
    Stats::Scalar<> dmaReadBytes;
    Stats::Scalar<> dmaReadTxs;
    Stats::Scalar<> dmaWriteFullPages;
    Stats::Scalar<> dmaWriteBytes;
    Stats::Scalar<> dmaWriteTxs;

  public:
    /**
     * Create and initialize this Disk.
     * @param name The name of this disk.
     * @param img The disk image of this disk.
     * @param phys Pointer to physical memory
     * @param id The disk ID (master=0/slave=1)
     * @param disk_delay The disk delay in milliseconds
     */
    IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys,
            int id, Tick disk_delay);

    /**
     * Delete the data buffer.
     */
    ~IdeDisk();

    /**
     * Reset the device state
     */
    void reset(int id);

    /**
     * Register statistics.
     */
    void regStats();

    /**
     * Set the controller for this device
     * @param c The IDE controller
     */
    void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) {
        if (ctrl) panic("Cannot change the controller once set!\n");
        ctrl = c;
        dmaInterface = dmaIntr;
    }

    // Device register read/write
    void read(const Addr &offset, IdeRegType regtype, uint8_t *data);
    void write(const Addr &offset, IdeRegType regtype, const uint8_t *data);

    // Start/abort functions
    void startDma(const uint32_t &prdTableBase);
    void abortDma();

  private:
    void startCommand();

    // Interrupt management
    void intrPost();
    void intrClear();

    // DMA stuff
    void doDmaTransfer();
    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
    EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;

    void doDmaRead();
    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
    EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;

    void doDmaWrite();
    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
    EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;

    void dmaPrdReadDone();
    friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
    EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;

    void dmaReadDone();
    friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
    EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;

    void dmaWriteDone();
    friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
    EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;

    // Disk image read/write
    void readDisk(uint32_t sector, uint8_t *data);
    void writeDisk(uint32_t sector, uint8_t *data);

    // State machine management
    void updateState(DevAction_t action);

    // Utility functions
    bool isBSYSet() { return (status & STATUS_BSY_BIT); }
    bool isIENSet() { return nIENBit; }
    bool isDEVSelect();

    void setComplete()
    {
        // clear out the status byte
        status = 0;
        // set the DRDY bit
        status |= STATUS_DRDY_BIT;
        // set the SEEK bit
        status |= STATUS_SEEK_BIT;
    }

    uint32_t getLBABase()
    {
        return  (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
                       (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
    }

    inline Addr pciToDma(Addr pciAddr);

    uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft);

    /**
     * Serialize this object to the given output stream.
     * @param os The stream to serialize to.
     */
    void serialize(std::ostream &os);

    /**
     * Reconstruct the state of this object from a checkpoint.
     * @param cp The checkpoint to use.
     * @param section The section name describing this object.
     */
    void unserialize(Checkpoint *cp, const std::string &section);
};

#endif // __IDE_DISK_HH__
<commit_msg>make the dma buffer equal to the max  dma size<commit_after>/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/** @file
 * Device model for an IDE disk
 */

#ifndef __IDE_DISK_HH__
#define __IDE_DISK_HH__

#include "base/statistics.hh"
#include "dev/disk_image.hh"
#include "dev/ide_atareg.h"
#include "dev/ide_ctrl.hh"
#include "dev/ide_wdcreg.h"
#include "dev/io_device.hh"
#include "sim/eventq.hh"

#define DMA_BACKOFF_PERIOD 200

#define MAX_DMA_SIZE    (131072)  // 128K
#define MAX_MULTSECT    (128)

#define PRD_BASE_MASK  0xfffffffe
#define PRD_COUNT_MASK 0xfffe
#define PRD_EOT_MASK   0x8000

typedef struct PrdEntry {
    uint32_t baseAddr;
    uint16_t byteCount;
    uint16_t endOfTable;
} PrdEntry_t;

class PrdTableEntry {
  public:
    PrdEntry_t entry;

    uint32_t getBaseAddr()
    {
        return (entry.baseAddr & PRD_BASE_MASK);
    }

    uint32_t getByteCount()
    {
        return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
                (entry.byteCount & PRD_COUNT_MASK));
    }

    uint16_t getEOT()
    {
        return (entry.endOfTable & PRD_EOT_MASK);
    }
};

#define DATA_OFFSET     (0)
#define ERROR_OFFSET    (1)
#define FEATURES_OFFSET (1)
#define NSECTOR_OFFSET  (2)
#define SECTOR_OFFSET   (3)
#define LCYL_OFFSET     (4)
#define HCYL_OFFSET     (5)
#define SELECT_OFFSET   (6)
#define DRIVE_OFFSET    (6)
#define STATUS_OFFSET   (7)
#define COMMAND_OFFSET  (7)

#define CONTROL_OFFSET  (2)
#define ALTSTAT_OFFSET  (2)

#define SELECT_DEV_BIT  0x10
#define CONTROL_RST_BIT 0x04
#define CONTROL_IEN_BIT 0x02
#define STATUS_BSY_BIT  0x80
#define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT  0x08
#define STATUS_SEEK_BIT 0x10
#define STATUS_DF_BIT   0x20
#define DRIVE_LBA_BIT   0x40

#define DEV0 (0)
#define DEV1 (1)

typedef struct CommandReg {
    uint16_t data;
    uint8_t error;
    uint8_t sec_count;
    uint8_t sec_num;
    uint8_t cyl_low;
    uint8_t cyl_high;
    union {
        uint8_t drive;
        uint8_t head;
    };
    uint8_t command;
} CommandReg_t;

typedef enum Events {
    None = 0,
    Transfer,
    ReadWait,
    WriteWait,
    PrdRead,
    DmaRead,
    DmaWrite
} Events_t;

typedef enum DevAction {
    ACT_NONE = 0,
    ACT_CMD_WRITE,
    ACT_CMD_COMPLETE,
    ACT_CMD_ERROR,
    ACT_SELECT_WRITE,
    ACT_STAT_READ,
    ACT_DATA_READY,
    ACT_DATA_READ_BYTE,
    ACT_DATA_READ_SHORT,
    ACT_DATA_WRITE_BYTE,
    ACT_DATA_WRITE_SHORT,
    ACT_DMA_READY,
    ACT_DMA_DONE,
    ACT_SRST_SET,
    ACT_SRST_CLEAR
} DevAction_t;

typedef enum DevState {
    // Device idle
    Device_Idle_S = 0,
    Device_Idle_SI,
    Device_Idle_NS,

    // Software reset
    Device_Srst,

    // Non-data commands
    Command_Execution,

    // PIO data-in (data to host)
    Prepare_Data_In,
    Data_Ready_INTRQ_In,
    Transfer_Data_In,

    // PIO data-out (data from host)
    Prepare_Data_Out,
    Data_Ready_INTRQ_Out,
    Transfer_Data_Out,

    // DMA protocol
    Prepare_Data_Dma,
    Transfer_Data_Dma
} DevState_t;

typedef enum DmaState {
    Dma_Idle = 0,
    Dma_Start,
    Dma_Transfer
} DmaState_t;

class PhysicalMemory;
class IdeController;

/**
 * IDE Disk device model
 */
class IdeDisk : public SimObject
{
  protected:
    /** The IDE controller for this disk. */
    IdeController *ctrl;
    /** The DMA interface to use for transfers */
    DMAInterface<Bus> *dmaInterface;
    /** The image that contains the data of this disk. */
    DiskImage *image;
    /** Pointer to physical memory for DMA transfers */
    PhysicalMemory *physmem;

  protected:
    /** The disk delay in microseconds. */
    int diskDelay;

  private:
    /** Drive identification structure for this disk */
    struct ataparams driveID;
    /** Data buffer for transfers */
    uint8_t *dataBuffer;
    /** Number of bytes in command data transfer */
    uint32_t cmdBytes;
    /** Number of bytes left in command data transfer */
    uint32_t cmdBytesLeft;
    /** Number of bytes left in DRQ block */
    uint32_t drqBytesLeft;
    /** Current sector in access */
    uint32_t curSector;
    /** Command block registers */
    CommandReg_t cmdReg;
    /** Status register */
    uint8_t status;
    /** Interrupt enable bit */
    bool nIENBit;
    /** Device state */
    DevState_t devState;
    /** Dma state */
    DmaState_t dmaState;
    /** Dma transaction is a read */
    bool dmaRead;
    /** PRD table base address */
    uint32_t curPrdAddr;
    /** PRD entry */
    PrdTableEntry curPrd;
    /** Number of bytes transfered by DMA interface for current transfer */
    uint32_t dmaInterfaceBytes;
    /** Device ID (master=0/slave=1) */
    int devID;
    /** Interrupt pending */
    bool intrPending;

    Stats::Scalar<> dmaReadFullPages;
    Stats::Scalar<> dmaReadBytes;
    Stats::Scalar<> dmaReadTxs;
    Stats::Scalar<> dmaWriteFullPages;
    Stats::Scalar<> dmaWriteBytes;
    Stats::Scalar<> dmaWriteTxs;

  public:
    /**
     * Create and initialize this Disk.
     * @param name The name of this disk.
     * @param img The disk image of this disk.
     * @param phys Pointer to physical memory
     * @param id The disk ID (master=0/slave=1)
     * @param disk_delay The disk delay in milliseconds
     */
    IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys,
            int id, Tick disk_delay);

    /**
     * Delete the data buffer.
     */
    ~IdeDisk();

    /**
     * Reset the device state
     */
    void reset(int id);

    /**
     * Register statistics.
     */
    void regStats();

    /**
     * Set the controller for this device
     * @param c The IDE controller
     */
    void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) {
        if (ctrl) panic("Cannot change the controller once set!\n");
        ctrl = c;
        dmaInterface = dmaIntr;
    }

    // Device register read/write
    void read(const Addr &offset, IdeRegType regtype, uint8_t *data);
    void write(const Addr &offset, IdeRegType regtype, const uint8_t *data);

    // Start/abort functions
    void startDma(const uint32_t &prdTableBase);
    void abortDma();

  private:
    void startCommand();

    // Interrupt management
    void intrPost();
    void intrClear();

    // DMA stuff
    void doDmaTransfer();
    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
    EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;

    void doDmaRead();
    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
    EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;

    void doDmaWrite();
    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
    EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;

    void dmaPrdReadDone();
    friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
    EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;

    void dmaReadDone();
    friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
    EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;

    void dmaWriteDone();
    friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
    EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;

    // Disk image read/write
    void readDisk(uint32_t sector, uint8_t *data);
    void writeDisk(uint32_t sector, uint8_t *data);

    // State machine management
    void updateState(DevAction_t action);

    // Utility functions
    bool isBSYSet() { return (status & STATUS_BSY_BIT); }
    bool isIENSet() { return nIENBit; }
    bool isDEVSelect();

    void setComplete()
    {
        // clear out the status byte
        status = 0;
        // set the DRDY bit
        status |= STATUS_DRDY_BIT;
        // set the SEEK bit
        status |= STATUS_SEEK_BIT;
    }

    uint32_t getLBABase()
    {
        return  (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
                       (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
    }

    inline Addr pciToDma(Addr pciAddr);

    uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft);

    /**
     * Serialize this object to the given output stream.
     * @param os The stream to serialize to.
     */
    void serialize(std::ostream &os);

    /**
     * Reconstruct the state of this object from a checkpoint.
     * @param cp The checkpoint to use.
     * @param section The section name describing this object.
     */
    void unserialize(Checkpoint *cp, const std::string &section);
};

#endif // __IDE_DISK_HH__
<|endoftext|>


<commit_before>/*
 * This file is part of the Polkit-qt project
 * Copyright (C) 2009 Jaroslav Reznik <jreznik@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "subject.h"

#include <polkit/polkit.h>

using namespace PolkitQt;

class Subject::Private
{
    public:
        Private(PolkitSubject *s) :subject(s) {}

        PolkitSubject *subject;
};

Subject::Subject()
        : d(new Private(0))
{
    g_type_init();
}

Subject::Subject(PolkitSubject *subject)
        : d(new Private(subject))
{
    g_type_init();
}

Subject::~Subject()
{
    g_object_unref(d->subject);
}

PolkitSubject * Subject::subject() const
{
    return d->subject;
}

QString Subject::toString() const
{
    Q_ASSERT(d->subject);
    return QString::fromUtf8(polkit_subject_to_string(d->subject));
}

Subject * Subject::fromString(const QString & string)
{
   // should be in polkit library!!! but for strange reason it's neccessary to have it here
    g_type_init();

    Subject *subject = new Subject();
    GError *error = NULL;
    subject->d->subject = polkit_subject_from_string(string.toUtf8().data(), &error);
    if (error != NULL)
    {
        return NULL;
    }
    return subject;
}

UnixProcess::UnixProcess(qint64 pid)
        : Subject()
{
    setSubject(polkit_unix_process_new(pid));
}

UnixProcess::UnixProcess(qint64 pid, quint64 startTime)
        : Subject()
{
    setSubject(polkit_unix_process_new_full(pid, startTime));
}

UnixProcess::UnixProcess(PolkitUnixProcess *pkUnixProcess)
        : Subject((PolkitSubject *)pkUnixProcess)
{

}

qint64 UnixProcess::pid() const
{
    return polkit_unix_process_get_pid((PolkitUnixProcess *) subject());
}

qint64 UnixProcess::startTime() const
{
    return polkit_unix_process_get_start_time((PolkitUnixProcess *) subject());
}

void UnixProcess::setPid(qint64 pid)
{
    polkit_unix_process_set_pid((PolkitUnixProcess *) subject(), pid);
}

// ----- SystemBusName
SystemBusName::SystemBusName(const QString &name)
        : Subject()
{
    setSubject(polkit_system_bus_name_new(name.toUtf8().data()));
}

SystemBusName::SystemBusName(PolkitSystemBusName *pkSystemBusName)
        : Subject((PolkitSubject *) pkSystemBusName)
{

}

QString SystemBusName::name() const
{
    return QString::fromUtf8(polkit_system_bus_name_get_name((PolkitSystemBusName *) subject()));
}

void SystemBusName::setName(const QString &name)
{
    polkit_system_bus_name_set_name((PolkitSystemBusName *) subject(), name.toUtf8().data());
}

// ----- SystemSession
UnixSession::UnixSession(const QString &sessionId)
        : Subject()
{
    setSubject(polkit_unix_session_new(sessionId.toUtf8().data()));
}

UnixSession::UnixSession(qint64 pid)
        : Subject()
{
    // TODO: error handling
    setSubject(polkit_unix_session_new_for_process_sync(pid, NULL, NULL));
}

UnixSession::UnixSession(PolkitSystemBusName *pkUnixSession)
        : Subject((PolkitSubject *) pkUnixSession)
{

}

QString UnixSession::sessionId() const
{
    return QString::fromUtf8(polkit_unix_session_get_session_id((PolkitUnixSession *) subject()));
}

void UnixSession::setSessionId(const QString &sessionId)
{
    polkit_unix_session_set_session_id((PolkitUnixSession *) subject(), sessionId.toUtf8().data());
}
<commit_msg>Implement missing function<commit_after>/*
 * This file is part of the Polkit-qt project
 * Copyright (C) 2009 Jaroslav Reznik <jreznik@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "subject.h"

#include <polkit/polkit.h>

using namespace PolkitQt;

class Subject::Private
{
    public:
        Private(PolkitSubject *s) :subject(s) {}

        PolkitSubject *subject;
};

Subject::Subject()
        : d(new Private(0))
{
    g_type_init();
}

Subject::Subject(PolkitSubject *subject)
        : d(new Private(subject))
{
    g_type_init();
}

Subject::~Subject()
{
    g_object_unref(d->subject);
}

PolkitSubject * Subject::subject() const
{
    return d->subject;
}

void Subject::setSubject(PolkitSubject* subject)
{
    d->subject = subject;
}

QString Subject::toString() const
{
    Q_ASSERT(d->subject);
    return QString::fromUtf8(polkit_subject_to_string(d->subject));
}

Subject * Subject::fromString(const QString & string)
{
   // should be in polkit library!!! but for strange reason it's neccessary to have it here
    g_type_init();

    Subject *subject = new Subject();
    GError *error = NULL;
    subject->d->subject = polkit_subject_from_string(string.toUtf8().data(), &error);
    if (error != NULL)
    {
        return NULL;
    }
    return subject;
}

UnixProcess::UnixProcess(qint64 pid)
        : Subject()
{
    setSubject(polkit_unix_process_new(pid));
}

UnixProcess::UnixProcess(qint64 pid, quint64 startTime)
        : Subject()
{
    setSubject(polkit_unix_process_new_full(pid, startTime));
}

UnixProcess::UnixProcess(PolkitUnixProcess *pkUnixProcess)
        : Subject((PolkitSubject *)pkUnixProcess)
{

}

qint64 UnixProcess::pid() const
{
    return polkit_unix_process_get_pid((PolkitUnixProcess *) subject());
}

qint64 UnixProcess::startTime() const
{
    return polkit_unix_process_get_start_time((PolkitUnixProcess *) subject());
}

void UnixProcess::setPid(qint64 pid)
{
    polkit_unix_process_set_pid((PolkitUnixProcess *) subject(), pid);
}

// ----- SystemBusName
SystemBusName::SystemBusName(const QString &name)
        : Subject()
{
    setSubject(polkit_system_bus_name_new(name.toUtf8().data()));
}

SystemBusName::SystemBusName(PolkitSystemBusName *pkSystemBusName)
        : Subject((PolkitSubject *) pkSystemBusName)
{

}

QString SystemBusName::name() const
{
    return QString::fromUtf8(polkit_system_bus_name_get_name((PolkitSystemBusName *) subject()));
}

void SystemBusName::setName(const QString &name)
{
    polkit_system_bus_name_set_name((PolkitSystemBusName *) subject(), name.toUtf8().data());
}

// ----- SystemSession
UnixSession::UnixSession(const QString &sessionId)
        : Subject()
{
    setSubject(polkit_unix_session_new(sessionId.toUtf8().data()));
}

UnixSession::UnixSession(qint64 pid)
        : Subject()
{
    // TODO: error handling
    setSubject(polkit_unix_session_new_for_process_sync(pid, NULL, NULL));
}

UnixSession::UnixSession(PolkitSystemBusName *pkUnixSession)
        : Subject((PolkitSubject *) pkUnixSession)
{

}

QString UnixSession::sessionId() const
{
    return QString::fromUtf8(polkit_unix_session_get_session_id((PolkitUnixSession *) subject()));
}

void UnixSession::setSessionId(const QString &sessionId)
{
    polkit_unix_session_set_session_id((PolkitUnixSession *) subject(), sessionId.toUtf8().data());
}
<|endoftext|>


<commit_before>/*
    This file is part of the OfiLabs X2 project.

    Copyright (C) 2010 Helder Correia <helder.pereira.correia@gmail.com>

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

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

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

#include <QtGui>
#include <cmath>

class PlasmaEffect : public QWidget
{
    Q_OBJECT

public:
    typedef double (*transformation)(double);
    PlasmaEffect(int width, int height, QWidget *parent = 0);
    int interval() const;

public slots:
    void setRedAsBase();
    void setGreenAsBase();
    void setBlueAsBase();
    void setParameters(qreal alpha, qreal alphaAdjust, qreal beta, qreal betaAdjust);
    void setBaseFunction(transformation function);
    void start();
    void stop();
    void setInterval(int msec);

protected:
    virtual void keyPressEvent(QKeyEvent *event);
    virtual void paintEvent(QPaintEvent *);
    virtual void resizeEvent(QResizeEvent *event);
    virtual void timerEvent(QTimerEvent *event);

private:
    int m_plasmaWidth;
    int m_plasmaHeight;
    bool m_fullScreen;

    QImage m_image;
    int *m_pattern;
    QVector<QRgb> m_palette;
    int m_timerInterval;
    QBasicTimer m_animationTimer;
    transformation m_baseFunction;

    qreal m_alpha;
    qreal m_alphaAdjust;
    qreal m_beta;
    qreal m_betaAdjust;

    int m_redComponent;
    int m_greenComponent;
    int m_blueComponent;

    int m_redComponentChangeFactor;
    int m_greenComponentChangeFactor;
    int m_blueComponentChangeFactor;

    void paintNextFrame();
    void setUp();
};

PlasmaEffect::PlasmaEffect(int width, int height, QWidget *parent) : QWidget(parent),
    m_fullScreen(false),
    m_pattern(0), m_palette(256),
    m_timerInterval(40),
    m_baseFunction(sin),
    m_alpha(20), m_alphaAdjust(0.15), m_beta(100), m_betaAdjust(0.015),
    m_redComponent(0), m_greenComponent(255), m_blueComponent(0),
    m_redComponentChangeFactor(2), m_greenComponentChangeFactor(-2),
    m_blueComponentChangeFactor(2)
{
    setAttribute(Qt::WA_StaticContents, true);
    setAttribute(Qt::WA_OpaquePaintEvent, true);
    setAttribute(Qt::WA_NoSystemBackground, true);

    resize(width, height);
    start();
}

int PlasmaEffect::interval() const
{
    return m_timerInterval;
}

void PlasmaEffect::setRedAsBase()
{
    m_redComponent = 255; m_redComponentChangeFactor = -2;
    m_greenComponent = 0; m_greenComponentChangeFactor = 2;
    m_blueComponent = 0; m_blueComponentChangeFactor = 2;
    setUp();
}

void PlasmaEffect::setGreenAsBase()
{
    m_redComponent = 0; m_redComponentChangeFactor = 2;
    m_greenComponent = 255; m_greenComponentChangeFactor = -2;
    m_blueComponent = 0; m_blueComponentChangeFactor = 2;
    setUp();
}

void PlasmaEffect::setBlueAsBase()
{
    m_redComponent = 0; m_redComponentChangeFactor = 2;
    m_greenComponent = 0; m_greenComponentChangeFactor = 2;
    m_blueComponent = 255; m_blueComponentChangeFactor = -2;
    setUp();
}

void PlasmaEffect::setParameters(qreal alpha, qreal alphaAdjust, qreal beta, qreal betaAdjust)
{
    m_alpha = alpha; m_alphaAdjust = alphaAdjust;
    m_beta = beta; m_betaAdjust = betaAdjust;
    setUp();
}

void PlasmaEffect::setBaseFunction(transformation function)
{
    m_baseFunction = function;
    setUp();
}

void PlasmaEffect::start()
{
    m_animationTimer.start(m_timerInterval, this);
}

void PlasmaEffect::stop()
{
    m_animationTimer.stop();
}

void PlasmaEffect::setInterval(int msec)
{
    m_animationTimer.stop();
    m_timerInterval = msec;
    m_animationTimer.start(msec, this);
}

void PlasmaEffect::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {

    case Qt::Key_Left:
        if (event->modifiers() & Qt::ShiftModifier)
            m_betaAdjust -= 0.0008;
        else
            m_alphaAdjust -= 0.002;
        setUp();
        break;
    case Qt::Key_Right:
        if (event->modifiers() & Qt::ShiftModifier)
            m_betaAdjust += 0.0008;
        else
            m_alphaAdjust += 0.002;
        setUp();
        break;

    case Qt::Key_Up:
        if (event->modifiers() & Qt::ShiftModifier)
            m_beta += 8;
        else
            m_alpha += 2;
        setUp();
        break;
    case Qt::Key_Down:
        if (event->modifiers() & Qt::ShiftModifier)
            m_beta -= 8;
        else
            m_alpha -= 2;
        setUp();
        break;

    case Qt::Key_R: setRedAsBase(); break;
    case Qt::Key_G: setGreenAsBase(); break;
    case Qt::Key_B: setBlueAsBase(); break;

    case Qt::Key_S: setBaseFunction(sin); break;
    case Qt::Key_T: setBaseFunction(tan); break;

    case Qt::Key_F:
        if (m_fullScreen) {
            showNormal();
            m_fullScreen = false;
        } else {
            showFullScreen();
            m_fullScreen = true;
        }
        break;

    case Qt::Key_Space:
        if (m_animationTimer.isActive())
            stop();
        else
            start();
        break;
    case Qt::Key_O:
        if (!(m_timerInterval > 250))
            setInterval(interval() + 5);
        break;
    case Qt::Key_P:
        if (!(m_timerInterval < 10))
            setInterval(interval() - 5);
        break;

    case Qt::Key_1: setParameters(0, -0.046, -4, 0.0086); break;
    case Qt::Key_2: setParameters(-16, -0.012, 4, -0.0266); break;
    case Qt::Key_3: setParameters(-58, -0.002, 4, -0.1146); break;
    case Qt::Key_4: setParameters(-58, -0.002, -4, -0.0138); break;
    case Qt::Key_5: setParameters(4, 0.102, 12, -0.0686); break;
    case Qt::Key_6: setParameters(-2, 0.244, 1780, -0.0007); break;
    case Qt::Key_7: setParameters(-34, 0.092, 1780, -0.0007); break;
    case Qt::Key_8: setParameters(-130, 0.008, -12, -0.043); break;
    case Qt::Key_9: setParameters(-38, 0.002, 12, -0.0662); break;
    case Qt::Key_0: setParameters(20, 0.15, 100, 0.015); break;

    case Qt::Key_Escape:
        QApplication::quit();
        break;

    default:
        QWidget::keyPressEvent(event);
    }
}

void PlasmaEffect::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawImage(QPoint(0, 0), m_image);
}

void PlasmaEffect::resizeEvent(QResizeEvent *event)
{
    m_plasmaWidth = event->size().width();
    m_plasmaHeight = event->size().height();
    m_image = QImage(m_plasmaWidth, m_plasmaHeight, QImage::Format_Indexed8);
    m_image.setColorTable(m_palette);
    if (m_pattern)
        delete m_pattern;
    m_pattern = new int[m_plasmaWidth*m_plasmaHeight];

    setUp();

    if (!m_animationTimer.isActive())
        paintNextFrame();
}

void PlasmaEffect::timerEvent(QTimerEvent *)
{
    paintNextFrame();
}

void PlasmaEffect::paintNextFrame()
{
    for (int i = 0; i < 255; ++i)
        m_palette[i] = m_palette[i + 1];
    m_palette[255] = m_palette[0];

    uchar *scanLine;
    for (int line = 0; line < m_plasmaHeight; ++line) {
        scanLine = m_image.scanLine(line);
        for (int offset = 0; offset < m_plasmaWidth; ++offset)
    	scanLine[offset] = m_palette[m_pattern[line * m_plasmaWidth + offset]];
    }

    m_image.setColorTable(m_palette);
    update();
}

void PlasmaEffect::setUp()
{
    int maxDimension = qMax(m_plasmaWidth, m_plasmaHeight);
    int *f = new int[maxDimension];

    for (int x = 0; x < maxDimension; ++x)
        f[x] = qRound(m_alpha * m_baseFunction(x * m_alphaAdjust) + m_beta * cos(x * m_betaAdjust));

    QRgb rgb;
    int r = m_redComponent, g = m_greenComponent, b = m_blueComponent;
    for (int i = 0; i < 128; ++i) {
        rgb = QColor(r, g, b).rgb();
        m_palette[i] = m_palette[255-i] = rgb;
        r += m_redComponentChangeFactor;
        g += m_greenComponentChangeFactor;
        b += m_blueComponentChangeFactor;
    }

    for (int y = 0; y < m_plasmaHeight; ++y)
        for (int x = 0; x < m_plasmaWidth; ++x)
            m_pattern[y * m_plasmaWidth + x] = abs(f[x] + f[y]) % (255);

    delete[] f;
}

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    PlasmaEffect plasma(640, 360);
    plasma.setInterval(35);
    plasma.start();
#ifdef Q_OS_SYMBIAN
    plasma.showMaximized(); // http://bugreports.qt.nokia.com/browse/QTBUG-8190
#else
    plasma.show();
#endif

    return application.exec();
}

#include "plasmaeffect.moc"

<commit_msg>Use qRgb() instead of QColor().rgb().<commit_after>/*
    This file is part of the OfiLabs X2 project.

    Copyright (C) 2010 Helder Correia <helder.pereira.correia@gmail.com>

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

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

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

#include <QtGui>
#include <cmath>

class PlasmaEffect : public QWidget
{
    Q_OBJECT

public:
    typedef double (*transformation)(double);
    PlasmaEffect(int width, int height, QWidget *parent = 0);
    int interval() const;

public slots:
    void setRedAsBase();
    void setGreenAsBase();
    void setBlueAsBase();
    void setParameters(qreal alpha, qreal alphaAdjust, qreal beta, qreal betaAdjust);
    void setBaseFunction(transformation function);
    void start();
    void stop();
    void setInterval(int msec);

protected:
    virtual void keyPressEvent(QKeyEvent *event);
    virtual void paintEvent(QPaintEvent *);
    virtual void resizeEvent(QResizeEvent *event);
    virtual void timerEvent(QTimerEvent *event);

private:
    int m_plasmaWidth;
    int m_plasmaHeight;
    bool m_fullScreen;

    QImage m_image;
    int *m_pattern;
    QVector<QRgb> m_palette;
    int m_timerInterval;
    QBasicTimer m_animationTimer;
    transformation m_baseFunction;

    qreal m_alpha;
    qreal m_alphaAdjust;
    qreal m_beta;
    qreal m_betaAdjust;

    int m_redComponent;
    int m_greenComponent;
    int m_blueComponent;

    int m_redComponentChangeFactor;
    int m_greenComponentChangeFactor;
    int m_blueComponentChangeFactor;

    void paintNextFrame();
    void setUp();
};

PlasmaEffect::PlasmaEffect(int width, int height, QWidget *parent) : QWidget(parent),
    m_fullScreen(false),
    m_pattern(0), m_palette(256),
    m_timerInterval(40),
    m_baseFunction(sin),
    m_alpha(20), m_alphaAdjust(0.15), m_beta(100), m_betaAdjust(0.015),
    m_redComponent(0), m_greenComponent(255), m_blueComponent(0),
    m_redComponentChangeFactor(2), m_greenComponentChangeFactor(-2),
    m_blueComponentChangeFactor(2)
{
    setAttribute(Qt::WA_StaticContents, true);
    setAttribute(Qt::WA_OpaquePaintEvent, true);
    setAttribute(Qt::WA_NoSystemBackground, true);

    resize(width, height);
    start();
}

int PlasmaEffect::interval() const
{
    return m_timerInterval;
}

void PlasmaEffect::setRedAsBase()
{
    m_redComponent = 255; m_redComponentChangeFactor = -2;
    m_greenComponent = 0; m_greenComponentChangeFactor = 2;
    m_blueComponent = 0; m_blueComponentChangeFactor = 2;
    setUp();
}

void PlasmaEffect::setGreenAsBase()
{
    m_redComponent = 0; m_redComponentChangeFactor = 2;
    m_greenComponent = 255; m_greenComponentChangeFactor = -2;
    m_blueComponent = 0; m_blueComponentChangeFactor = 2;
    setUp();
}

void PlasmaEffect::setBlueAsBase()
{
    m_redComponent = 0; m_redComponentChangeFactor = 2;
    m_greenComponent = 0; m_greenComponentChangeFactor = 2;
    m_blueComponent = 255; m_blueComponentChangeFactor = -2;
    setUp();
}

void PlasmaEffect::setParameters(qreal alpha, qreal alphaAdjust, qreal beta, qreal betaAdjust)
{
    m_alpha = alpha; m_alphaAdjust = alphaAdjust;
    m_beta = beta; m_betaAdjust = betaAdjust;
    setUp();
}

void PlasmaEffect::setBaseFunction(transformation function)
{
    m_baseFunction = function;
    setUp();
}

void PlasmaEffect::start()
{
    m_animationTimer.start(m_timerInterval, this);
}

void PlasmaEffect::stop()
{
    m_animationTimer.stop();
}

void PlasmaEffect::setInterval(int msec)
{
    m_animationTimer.stop();
    m_timerInterval = msec;
    m_animationTimer.start(msec, this);
}

void PlasmaEffect::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {

    case Qt::Key_Left:
        if (event->modifiers() & Qt::ShiftModifier)
            m_betaAdjust -= 0.0008;
        else
            m_alphaAdjust -= 0.002;
        setUp();
        break;
    case Qt::Key_Right:
        if (event->modifiers() & Qt::ShiftModifier)
            m_betaAdjust += 0.0008;
        else
            m_alphaAdjust += 0.002;
        setUp();
        break;

    case Qt::Key_Up:
        if (event->modifiers() & Qt::ShiftModifier)
            m_beta += 8;
        else
            m_alpha += 2;
        setUp();
        break;
    case Qt::Key_Down:
        if (event->modifiers() & Qt::ShiftModifier)
            m_beta -= 8;
        else
            m_alpha -= 2;
        setUp();
        break;

    case Qt::Key_R: setRedAsBase(); break;
    case Qt::Key_G: setGreenAsBase(); break;
    case Qt::Key_B: setBlueAsBase(); break;

    case Qt::Key_S: setBaseFunction(sin); break;
    case Qt::Key_T: setBaseFunction(tan); break;

    case Qt::Key_F:
        if (m_fullScreen) {
            showNormal();
            m_fullScreen = false;
        } else {
            showFullScreen();
            m_fullScreen = true;
        }
        break;

    case Qt::Key_Space:
        if (m_animationTimer.isActive())
            stop();
        else
            start();
        break;
    case Qt::Key_O:
        if (!(m_timerInterval > 250))
            setInterval(interval() + 5);
        break;
    case Qt::Key_P:
        if (!(m_timerInterval < 10))
            setInterval(interval() - 5);
        break;

    case Qt::Key_1: setParameters(0, -0.046, -4, 0.0086); break;
    case Qt::Key_2: setParameters(-16, -0.012, 4, -0.0266); break;
    case Qt::Key_3: setParameters(-58, -0.002, 4, -0.1146); break;
    case Qt::Key_4: setParameters(-58, -0.002, -4, -0.0138); break;
    case Qt::Key_5: setParameters(4, 0.102, 12, -0.0686); break;
    case Qt::Key_6: setParameters(-2, 0.244, 1780, -0.0007); break;
    case Qt::Key_7: setParameters(-34, 0.092, 1780, -0.0007); break;
    case Qt::Key_8: setParameters(-130, 0.008, -12, -0.043); break;
    case Qt::Key_9: setParameters(-38, 0.002, 12, -0.0662); break;
    case Qt::Key_0: setParameters(20, 0.15, 100, 0.015); break;

    case Qt::Key_Escape:
        QApplication::quit();
        break;

    default:
        QWidget::keyPressEvent(event);
    }
}

void PlasmaEffect::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawImage(QPoint(0, 0), m_image);
}

void PlasmaEffect::resizeEvent(QResizeEvent *event)
{
    m_plasmaWidth = event->size().width();
    m_plasmaHeight = event->size().height();
    m_image = QImage(m_plasmaWidth, m_plasmaHeight, QImage::Format_Indexed8);
    m_image.setColorTable(m_palette);
    if (m_pattern)
        delete m_pattern;
    m_pattern = new int[m_plasmaWidth*m_plasmaHeight];

    setUp();

    if (!m_animationTimer.isActive())
        paintNextFrame();
}

void PlasmaEffect::timerEvent(QTimerEvent *)
{
    paintNextFrame();
}

void PlasmaEffect::paintNextFrame()
{
    for (int i = 0; i < 255; ++i)
        m_palette[i] = m_palette[i + 1];
    m_palette[255] = m_palette[0];

    uchar *scanLine;
    for (int line = 0; line < m_plasmaHeight; ++line) {
        scanLine = m_image.scanLine(line);
        for (int offset = 0; offset < m_plasmaWidth; ++offset)
    	scanLine[offset] = m_palette[m_pattern[line * m_plasmaWidth + offset]];
    }

    m_image.setColorTable(m_palette);
    update();
}

void PlasmaEffect::setUp()
{
    int maxDimension = qMax(m_plasmaWidth, m_plasmaHeight);
    int *f = new int[maxDimension];

    for (int x = 0; x < maxDimension; ++x)
        f[x] = qRound(m_alpha * m_baseFunction(x * m_alphaAdjust) + m_beta * cos(x * m_betaAdjust));

    int r = m_redComponent, g = m_greenComponent, b = m_blueComponent;
    for (int i = 0; i < 128; ++i) {
        m_palette[i] = m_palette[255-i] = qRgb(r, g, b);
        r += m_redComponentChangeFactor;
        g += m_greenComponentChangeFactor;
        b += m_blueComponentChangeFactor;
    }

    for (int y = 0; y < m_plasmaHeight; ++y)
        for (int x = 0; x < m_plasmaWidth; ++x)
            m_pattern[y * m_plasmaWidth + x] = abs(f[x] + f[y]) % (255);

    delete[] f;
}

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    PlasmaEffect plasma(640, 360);
    plasma.setInterval(35);
    plasma.start();
#ifdef Q_OS_SYMBIAN
    plasma.showMaximized(); // http://bugreports.qt.nokia.com/browse/QTBUG-8190
#else
    plasma.show();
#endif

    return application.exec();
}

#include "plasmaeffect.moc"

<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: Molecule_test.C,v 1.14 2002/12/12 11:34:42 oliver Exp $

#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/KERNEL/atom.h>
#include <BALL/CONCEPT/textPersistenceManager.h>
#include <BALL/KERNEL/molecule.h>
#include <BALL/KERNEL/system.h>
///////////////////////////

START_TEST(Molecule, "$Id: Molecule_test.C,v 1.14 2002/12/12 11:34:42 oliver Exp $")

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

using namespace BALL;
String filename;
using std::ofstream;
using std::ios;

Molecule* b;

CHECK(Molecule())
	b = new Molecule;
	TEST_NOT_EQUAL(b, 0)
RESULT

CHECK(~Molecule())
	delete b;
RESULT

CHECK(Molecule(const Molecule& molecule, bool deep = true))
	Atom a1;
	Molecule m("a"), m2;
	m.append(a1);
	m2 = Molecule(m);
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule(const String& name))
	Molecule m("a");
	TEST_EQUAL(m.getName(), "a")
	Molecule m2("");
	TEST_EQUAL(m2.getName(), "")
RESULT

CHECK(clear())
	System s;
	Molecule m("a");
	Atom a1;
	m.append(a1);
	s.append(m);
	m.clear();
	TEST_EQUAL(m.getName(), "")
	TEST_EQUAL(s.countAtoms(), 0)
RESULT

CHECK(destroy())
	System s;
	Molecule m("a");
	Atom a1;
	m.append(a1);
	s.append(m);
	m.destroy();
	TEST_EQUAL(m.getName(), "")
	TEST_EQUAL(s.countAtoms(), 0)
RESULT

CHECK(Molecule::set(const Molecule& molecule, bool deep = true))
	Molecule m("a"), m2;
	Atom a1;
	m.append(a1);
	m2.set(m);
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule::Molecule& operator = (const Molecule& molecule))
	Molecule m("a"), m2;
	Atom a1;
	m.append(a1);
	m2 = m;
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule::get(Molecule& molecule, bool deep = true) const )
	Molecule m("a"), m2;
	Atom a1;
	m.append(a1);
	m.get(m2);
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule::swap(Molecule& molecule))
	Molecule m("a");
	Molecule m2("b");
	Atom a1, a2, a3;
	m.append(a1);
	m.append(a2);
	m2.append(a3);
	m.swap(m2);
	TEST_EQUAL(m.getName(), "b")
	TEST_EQUAL(m.countAtoms(), 1)
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 2)
RESULT

CHECK(Molecule::getSystem())
	System s;
	Molecule m("a");
	s.append(m);
	m.getSystem()->setName("b");
	TEST_EQUAL(s.getName(), "b")
RESULT

CHECK(Molecule::getSystem() const )
	System s1("aya");
	Molecule m("a");
	s1.append(m);
	const System s(s1);
	TEST_EQUAL(m.getSystem()->getName(), "aya")
RESULT

CHECK(Molecule::prepend(Atom& atom))
	Molecule m;
	Atom a1;
	Atom a2;
	m.insert(a1);
	TEST_EQUAL(m.getAtom(0), &a1)
	m.prepend(a2);
	TEST_EQUAL(m.getAtom(0), &a2)
	TEST_EQUAL(m.getAtom(1), &a1)
RESULT

CHECK(Molecule::append(Atom& atom))
	Molecule m;
	Atom a1;
	Atom a2;
	m.insert(a1);
	m.append(a2);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a2)
RESULT

CHECK(Molecule::insert(Atom& atom))
	Molecule m;
	Atom a1;
	Atom a2;
	m.insert(a1);
	m.insert(a2);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a2)
RESULT

CHECK(Molecule::insertBefore(Atom& atom, Composite& before))
	Molecule m;
	Atom a1;
	Atom a2;
	Atom a3;
	m.insert(a1);
	m.append(a2);
	m.insertBefore(a3, a2);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a3)
	TEST_EQUAL(m.getAtom(2), &a2)
RESULT

CHECK(Molecule::insertAfter(Atom& atom, Composite& after))
	Molecule m;
	Atom a1;
	Atom a2;
	Atom a3;
	m.insert(a1);
	m.append(a2);
	m.insertAfter(a3, a1);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a3)
	TEST_EQUAL(m.getAtom(2), &a2)
RESULT

CHECK(Molecule::remove(Atom& atom))
	Molecule m("a");
	Atom a1;
	Atom a2;
	m.append(a1);
	m.append(a2);
	m.remove(a1);
	TEST_EQUAL(m.countAtoms(), 1)
	TEST_EQUAL(m.getAtom(0), &a2)
RESULT

CHECK(Molecule::prepend(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.prepend(bf2);
	m.prepend(bf3);
	TEST_EQUAL(m.getAtomContainer(1), &bf2)
	TEST_EQUAL(m.getAtomContainer(0), &bf3)
RESULT

CHECK(Molecule::append(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.append(bf2);
	m.append(bf3);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf3)
RESULT

CHECK(Molecule::insert(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.insert(bf2);
	m.insert(bf3);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf3)
RESULT

CHECK(Molecule::insertBefore(AtomContainer& atom_container, Composite& before))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	m.append(bf3);
	m.insertBefore(bf4, bf3);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf4)
	TEST_EQUAL(m.getAtomContainer(2), &bf3)
RESULT

CHECK(Molecule::insertAfter(AtomContainer& atom_container, Composite& after))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	m.append(bf3);
	m.insertAfter(bf4, bf2);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf4)
	TEST_EQUAL(m.getAtomContainer(2), &bf3)
RESULT

CHECK(Molecule::spliceBefore(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	bf4.append(bf3);
	bf4.spliceBefore(m);
	TEST_EQUAL(m.getAtomContainer(0), 0)
	TEST_EQUAL(bf4.getAtomContainer(0), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(1), &bf3)
	bf4.spliceBefore(bf4);
	TEST_EQUAL(bf4.getAtomContainer(0), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(1), &bf3)
RESULT

CHECK(Molecule::spliceAfter(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	bf4.append(bf3);
	bf4.spliceAfter(m);
	TEST_EQUAL(m.getAtomContainer(0), 0)
	TEST_EQUAL(bf4.getAtomContainer(1), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(0), &bf3)
	bf4.spliceBefore(bf4);
	TEST_EQUAL(bf4.getAtomContainer(1), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(0), &bf3)
RESULT

CHECK(Molecule::splice(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	AtomContainer bf5;
	AtomContainer bfx;
	AtomContainer bfy;
	m.append(bf2);
	m.append(bfx);
	m.append(bf3);
	bfx.append(bfy);
	bf4.append(bf5);
	m.splice(bfx);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bfy)
	TEST_EQUAL(m.getAtomContainer(2), &bf3)
	m.splice(bf4);
	TEST_EQUAL(m.getAtomContainer(0), &bf5)
	TEST_EQUAL(m.getAtomContainer(1), &bf2)
RESULT

CHECK(Molecule::remove(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.append(bf2);
	m.append(bf3);
	m.remove(bf2);
	TEST_EQUAL(m.getAtomContainer(0), &bf3)
RESULT

CHECK(Molecule::isValid() const )
	Molecule m("a");
	Atom a1;
	m.append(a1);
	TEST_EQUAL(m.isValid(), true)
RESULT

CHECK(Molecule::dump(std::ostream& s = std::cout, Size depth = 0) const )
	Molecule m("molecule1");
	Atom a1, a2;
	a1.setName("atom1");
	a2.setName("atom2");
	m.append(a1);
	m.append(a2);
	NEW_TMP_FILE(filename)
	std::ofstream outfile(filename.c_str(), std::ios::out);
	m.dump(outfile);
	outfile.close();
	TEST_FILE_REGEXP(filename.c_str(), "data/Molecule_test.txt")
RESULT

TextPersistenceManager pm;
using namespace RTTI;
pm.registerClass(getStreamName<Atom>(), Atom::createDefault);
pm.registerClass(getStreamName<Molecule>(), Molecule::createDefault);
NEW_TMP_FILE(filename)
CHECK(persistentWrite(PersistenceManager&, String, bool))
	std::ofstream	ofile(filename.c_str(), std::ios::out);
	Atom* f2= new Atom();
	f2->setName("name2");
	Atom* f3= new Atom();
	f3->setName("name3");
	Molecule* f1 = new Molecule("name1");
	f1->insert(*f2);
	f1->insert(*f3);
	pm.setOstream(ofile);
	*f1 >> pm;
	ofile.close();
	delete f1;
RESULT

CHECK(persistentRead(PersistenceManager&))
	std::ifstream	ifile(filename.c_str());
	pm.setIstream(ifile);
	PersistentObject*	ptr = pm.readObject();
	TEST_NOT_EQUAL(ptr, 0)
	if (ptr != 0)
	{
		TEST_EQUAL(isKindOf<Molecule>(*ptr), true)
		Molecule*	f1 = castTo<Molecule>(*ptr);
		TEST_EQUAL(f1->getName(), "name1")
		TEST_EQUAL(f1->countAtoms(), 2)
		TEST_EQUAL(f1->getAtom(0)->getName(), "name2")
		TEST_EQUAL(f1->getAtom(1)->getName(), "name3")
		delete f1;
	}
	else
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
RESULT

CHECK(operator ==)
	Molecule b1;
	Molecule b2;
	TEST_EQUAL(b1 == b2, false)
	b1 = b2;
	TEST_EQUAL(b1 == b1, true)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>changed: adapted to changes in AtomContainer::dump<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: Molecule_test.C,v 1.15 2003/02/10 16:42:42 oliver Exp $

#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/KERNEL/atom.h>
#include <BALL/CONCEPT/textPersistenceManager.h>
#include <BALL/KERNEL/molecule.h>
#include <BALL/KERNEL/system.h>
///////////////////////////

START_TEST(Molecule, "$Id: Molecule_test.C,v 1.15 2003/02/10 16:42:42 oliver Exp $")

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

using namespace BALL;

String filename;
using std::ofstream;
using std::ios;

Molecule* b;

CHECK(Molecule())
	b = new Molecule;
	TEST_NOT_EQUAL(b, 0)
RESULT

CHECK(~Molecule())
	delete b;
RESULT

CHECK(Molecule(const Molecule& molecule, bool deep = true))
	Atom a1;
	Molecule m("a"), m2;
	m.append(a1);
	m2 = Molecule(m);
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule(const String& name))
	Molecule m("a");
	TEST_EQUAL(m.getName(), "a")
	Molecule m2("");
	TEST_EQUAL(m2.getName(), "")
RESULT

CHECK(clear())
	System s;
	Molecule m("a");
	Atom a1;
	m.append(a1);
	s.append(m);
	m.clear();
	TEST_EQUAL(m.getName(), "")
	TEST_EQUAL(s.countAtoms(), 0)
RESULT

CHECK(destroy())
	System s;
	Molecule m("a");
	Atom a1;
	m.append(a1);
	s.append(m);
	m.destroy();
	TEST_EQUAL(m.getName(), "")
	TEST_EQUAL(s.countAtoms(), 0)
RESULT

CHECK(Molecule::set(const Molecule& molecule, bool deep = true))
	Molecule m("a"), m2;
	Atom a1;
	m.append(a1);
	m2.set(m);
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule::Molecule& operator = (const Molecule& molecule))
	Molecule m("a"), m2;
	Atom a1;
	m.append(a1);
	m2 = m;
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule::get(Molecule& molecule, bool deep = true) const )
	Molecule m("a"), m2;
	Atom a1;
	m.append(a1);
	m.get(m2);
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 1)
RESULT

CHECK(Molecule::swap(Molecule& molecule))
	Molecule m("a");
	Molecule m2("b");
	Atom a1, a2, a3;
	m.append(a1);
	m.append(a2);
	m2.append(a3);
	m.swap(m2);
	TEST_EQUAL(m.getName(), "b")
	TEST_EQUAL(m.countAtoms(), 1)
	TEST_EQUAL(m2.getName(), "a")
	TEST_EQUAL(m2.countAtoms(), 2)
RESULT

CHECK(Molecule::getSystem())
	System s;
	Molecule m("a");
	s.append(m);
	m.getSystem()->setName("b");
	TEST_EQUAL(s.getName(), "b")
RESULT

CHECK(Molecule::getSystem() const )
	System s1("aya");
	Molecule m("a");
	s1.append(m);
	const System s(s1);
	TEST_EQUAL(m.getSystem()->getName(), "aya")
RESULT

CHECK(Molecule::prepend(Atom& atom))
	Molecule m;
	Atom a1;
	Atom a2;
	m.insert(a1);
	TEST_EQUAL(m.getAtom(0), &a1)
	m.prepend(a2);
	TEST_EQUAL(m.getAtom(0), &a2)
	TEST_EQUAL(m.getAtom(1), &a1)
RESULT

CHECK(Molecule::append(Atom& atom))
	Molecule m;
	Atom a1;
	Atom a2;
	m.insert(a1);
	m.append(a2);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a2)
RESULT

CHECK(Molecule::insert(Atom& atom))
	Molecule m;
	Atom a1;
	Atom a2;
	m.insert(a1);
	m.insert(a2);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a2)
RESULT

CHECK(Molecule::insertBefore(Atom& atom, Composite& before))
	Molecule m;
	Atom a1;
	Atom a2;
	Atom a3;
	m.insert(a1);
	m.append(a2);
	m.insertBefore(a3, a2);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a3)
	TEST_EQUAL(m.getAtom(2), &a2)
RESULT

CHECK(Molecule::insertAfter(Atom& atom, Composite& after))
	Molecule m;
	Atom a1;
	Atom a2;
	Atom a3;
	m.insert(a1);
	m.append(a2);
	m.insertAfter(a3, a1);
	TEST_EQUAL(m.getAtom(0), &a1)
	TEST_EQUAL(m.getAtom(1), &a3)
	TEST_EQUAL(m.getAtom(2), &a2)
RESULT

CHECK(Molecule::remove(Atom& atom))
	Molecule m("a");
	Atom a1;
	Atom a2;
	m.append(a1);
	m.append(a2);
	m.remove(a1);
	TEST_EQUAL(m.countAtoms(), 1)
	TEST_EQUAL(m.getAtom(0), &a2)
RESULT

CHECK(Molecule::prepend(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.prepend(bf2);
	m.prepend(bf3);
	TEST_EQUAL(m.getAtomContainer(1), &bf2)
	TEST_EQUAL(m.getAtomContainer(0), &bf3)
RESULT

CHECK(Molecule::append(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.append(bf2);
	m.append(bf3);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf3)
RESULT

CHECK(Molecule::insert(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.insert(bf2);
	m.insert(bf3);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf3)
RESULT

CHECK(Molecule::insertBefore(AtomContainer& atom_container, Composite& before))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	m.append(bf3);
	m.insertBefore(bf4, bf3);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf4)
	TEST_EQUAL(m.getAtomContainer(2), &bf3)
RESULT

CHECK(Molecule::insertAfter(AtomContainer& atom_container, Composite& after))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	m.append(bf3);
	m.insertAfter(bf4, bf2);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bf4)
	TEST_EQUAL(m.getAtomContainer(2), &bf3)
RESULT

CHECK(Molecule::spliceBefore(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	bf4.append(bf3);
	bf4.spliceBefore(m);
	TEST_EQUAL(m.getAtomContainer(0), 0)
	TEST_EQUAL(bf4.getAtomContainer(0), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(1), &bf3)
	bf4.spliceBefore(bf4);
	TEST_EQUAL(bf4.getAtomContainer(0), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(1), &bf3)
RESULT

CHECK(Molecule::spliceAfter(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	m.append(bf2);
	bf4.append(bf3);
	bf4.spliceAfter(m);
	TEST_EQUAL(m.getAtomContainer(0), 0)
	TEST_EQUAL(bf4.getAtomContainer(1), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(0), &bf3)
	bf4.spliceBefore(bf4);
	TEST_EQUAL(bf4.getAtomContainer(1), &bf2)
	TEST_EQUAL(bf4.getAtomContainer(0), &bf3)
RESULT

CHECK(Molecule::splice(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	AtomContainer bf4;
	AtomContainer bf5;
	AtomContainer bfx;
	AtomContainer bfy;
	m.append(bf2);
	m.append(bfx);
	m.append(bf3);
	bfx.append(bfy);
	bf4.append(bf5);
	m.splice(bfx);
	TEST_EQUAL(m.getAtomContainer(0), &bf2)
	TEST_EQUAL(m.getAtomContainer(1), &bfy)
	TEST_EQUAL(m.getAtomContainer(2), &bf3)
	m.splice(bf4);
	TEST_EQUAL(m.getAtomContainer(0), &bf5)
	TEST_EQUAL(m.getAtomContainer(1), &bf2)
RESULT

CHECK(Molecule::remove(AtomContainer& atom_container))
	Molecule m;
	AtomContainer bf2;
	AtomContainer bf3;
	m.append(bf2);
	m.append(bf3);
	m.remove(bf2);
	TEST_EQUAL(m.getAtomContainer(0), &bf3)
RESULT

CHECK(Molecule::isValid() const )
	Molecule m("a");
	Atom a1;
	m.append(a1);
	TEST_EQUAL(m.isValid(), true)
RESULT

CHECK(Molecule::dump(std::ostream& s = std::cout, Size depth = 0) const )
	Molecule m("molecule1");
	Atom a1, a2;
	a1.setName("atom1");
	a2.setName("atom2");
	m.append(a1);
	m.append(a2);
	NEW_TMP_FILE(filename)
	std::ofstream outfile(filename.c_str(), std::ios::out);
	m.dump(outfile);
	outfile.close();
	TEST_FILE_REGEXP(filename.c_str(), "data/Molecule_test.txt")
RESULT

TextPersistenceManager pm;
using namespace RTTI;
pm.registerClass(getStreamName<Atom>(), Atom::createDefault);
pm.registerClass(getStreamName<Molecule>(), Molecule::createDefault);
NEW_TMP_FILE(filename)
CHECK(persistentWrite(PersistenceManager&, String, bool))
	std::ofstream	ofile(filename.c_str(), std::ios::out);
	Atom* f2= new Atom();
	f2->setName("name2");
	Atom* f3= new Atom();
	f3->setName("name3");
	Molecule* f1 = new Molecule("name1");
	f1->insert(*f2);
	f1->insert(*f3);
	pm.setOstream(ofile);
	*f1 >> pm;
	ofile.close();
	delete f1;
RESULT

CHECK(persistentRead(PersistenceManager&))
	std::ifstream	ifile(filename.c_str());
	pm.setIstream(ifile);
	PersistentObject*	ptr = pm.readObject();
	TEST_NOT_EQUAL(ptr, 0)
	if (ptr != 0)
	{
		TEST_EQUAL(isKindOf<Molecule>(*ptr), true)
		Molecule*	f1 = castTo<Molecule>(*ptr);
		TEST_EQUAL(f1->getName(), "name1")
		TEST_EQUAL(f1->countAtoms(), 2)
		TEST_EQUAL(f1->getAtom(0)->getName(), "name2")
		TEST_EQUAL(f1->getAtom(1)->getName(), "name3")
		delete f1;
	}
	else
	{
		throw Exception::NullPointer(__FILE__, __LINE__);
	}
RESULT

CHECK(operator ==)
	Molecule b1;
	Molecule b2;
	TEST_EQUAL(b1 == b2, false)
	b1 = b2;
	TEST_EQUAL(b1 == b1, true)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2010 Digital Bazaar, Inc. All rights reserved.
 */
#include "monarch/modest/ModuleLoader.h"

#include "monarch/rt/DynamicLibrary.h"

#include <cstring>

using namespace monarch::modest;
using namespace monarch::rt;

ModuleLoader::ModuleLoader()
{
}

ModuleLoader::~ModuleLoader()
{
}

ModuleInfo* ModuleLoader::loadModule(const char* filename)
{
   ModuleInfo* rval = NULL;

   // open library
   void* handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
   if(handle != NULL)
   {
      CreateModestModuleFn create;
      FreeModestModuleFn free;

      // clear error
      char* error = dlerror();

      // try to get create module function
      create = (CreateModestModuleFn)dlsym(handle, "createModestModule");
      if((error = dlerror()) == NULL)
      {
         // clear error
         error = dlerror();

         // try to get free module function
         free = (FreeModestModuleFn)dlsym(handle, "freeModestModule");
         error = dlerror();
      }

      if(error == NULL)
      {
         rval = loadModule(create, free);
         rval->handle = handle;
      }
      else
      {
         // could not load create or free functions
         ExceptionRef e = new Exception(
            "Could not load module.", "monarch.modest.BadModule");
         e->getDetails()["filename"] = filename;
         e->getDetails()["error"] = error;
         Exception::set(e);
      }
   }
   else
   {
      // failed to open module
      char* error = dlerror();
      ExceptionRef e = new Exception(
         "Could not open module file.", "monarch.modest.BadModuleFile");
      e->getDetails()["filename"] = filename;
      e->getDetails()["error"] = error;
      Exception::set(e);
   }

   return rval;
}

ModuleInfo* ModuleLoader::loadModule(
   CreateModestModuleFn cm, FreeModestModuleFn fm)
{
   ModuleInfo* rval = NULL;

   // create ModuleInfo
   rval = new ModuleInfo();
   rval->handle = NULL;
   rval->module = cm();
   rval->freeModule = fm;

   return rval;
}

void ModuleLoader::unloadModule(ModuleInfo* mi)
{
   // free module
   mi->freeModule(mi->module);

   if(mi->handle != NULL)
   {
      // close handle
      dlclose(mi->handle);
   }

   // delete module info
   delete mi;
}
<commit_msg>Added exceptions for more error cases.<commit_after>/*
 * Copyright (c) 2007-2010 Digital Bazaar, Inc. All rights reserved.
 */
#include "monarch/modest/ModuleLoader.h"

#include "monarch/rt/DynamicLibrary.h"

#include <cstring>

using namespace monarch::modest;
using namespace monarch::rt;

ModuleLoader::ModuleLoader()
{
}

ModuleLoader::~ModuleLoader()
{
}

ModuleInfo* ModuleLoader::loadModule(const char* filename)
{
   ModuleInfo* rval = NULL;

   // open library
   void* handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
   if(handle != NULL)
   {
      CreateModestModuleFn create;
      FreeModestModuleFn free;

      // clear error
      char* error = dlerror();

      // try to get create module function
      create = (CreateModestModuleFn)dlsym(handle, "createModestModule");
      if((error = dlerror()) == NULL)
      {
         // clear error
         error = dlerror();

         // try to get free module function
         free = (FreeModestModuleFn)dlsym(handle, "freeModestModule");
         error = dlerror();
      }

      if(error == NULL)
      {
         rval = loadModule(create, free);
         if(rval != NULL)
         {
            rval->handle = handle;
         }
         else
         {
            // could not load module due to loadModule(c,f) exception
            ExceptionRef e = new Exception(
               "Could not load module.", "monarch.modest.BadModule");
            e->getDetails()["filename"] = filename;
            Exception::push(e);
         }
      }
      else
      {
         // could not load create or free functions
         ExceptionRef e = new Exception(
            "Could not load module.", "monarch.modest.BadModule");
         e->getDetails()["filename"] = filename;
         e->getDetails()["error"] = error;
         Exception::set(e);
      }
   }
   else
   {
      // failed to open module
      char* error = dlerror();
      ExceptionRef e = new Exception(
         "Could not open module file.", "monarch.modest.BadModuleFile");
      e->getDetails()["filename"] = filename;
      e->getDetails()["error"] = error;
      Exception::set(e);
   }

   return rval;
}

ModuleInfo* ModuleLoader::loadModule(
   CreateModestModuleFn cm, FreeModestModuleFn fm)
{
   ModuleInfo* rval = NULL;

   Module* module = cm();

   if(module != NULL)
   {
      // create ModuleInfo
      rval = new ModuleInfo();
      rval->handle = NULL;
      rval->module = module;
      rval->freeModule = fm;
   }
   else
   {
      // create returned NULL
      ExceptionRef e = new Exception(
         "Failed to create module.", "monarch.modest.ModuleCreationFailure");
      Exception::push(e);
   }

   return rval;
}

void ModuleLoader::unloadModule(ModuleInfo* mi)
{
   // free module
   mi->freeModule(mi->module);

   if(mi->handle != NULL)
   {
      // close handle
      dlclose(mi->handle);
   }

   // delete module info
   delete mi;
}
<|endoftext|>


<commit_before>#include <iostream>

#include "SDL/SDL.h"
#include "SDL_image.h"
#include "SDL_gfxPrimitives.h"
#include "map.h"
#include "game.h"
#include "surface.h"

using namespace std;

Game::Game() {
  playing=true;
  screen=NULL;
  tileset=NULL;
  map_camera=NULL;
  unit=NULL;
  devastator=NULL;
}

int Game::execute() {
  init();

  SDL_Event event;

  while(playing) {
    while(SDL_PollEvent(&event)) {
      onEvent(&event);
    }

    updateState();
    render();
    // SDL rest?
  }

  return cleanup();
}

int Game::init() {
  if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
    return false;
  }

  screen = SDL_SetVideoMode(800, 600, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
  if(screen == NULL) {
     return false;
  }

  int flags = IMG_INIT_JPG | IMG_INIT_PNG;
  int initted=IMG_Init(flags);
  if( initted & flags != flags) {
    cout << "could not init SDL_Image" << endl;
    cout << "Reason: " << IMG_GetError() << endl;
    return false;
  }

  tileset = Surface::load("tileset.png");

  if (tileset == NULL) {
    cout << "Failed to read tileset data" << endl;
    return false;
  }

  map.setBoundaries(128,128);
  map_camera = new MapCamera(0, 0, screen, &map);

  unitRepository = new UnitRepository();

  unit = unitRepository->create(UNIT_FRIGATE, HOUSE_SARDAUKAR, 64, 64);
  devastator = unitRepository->create(UNIT_TRIKE, HOUSE_ATREIDES, 128, 128);

  return true;
}

void Game::onEvent(SDL_Event* event) {
  if(event->type == SDL_QUIT) {
    playing = false;
  }

  keyboard.onEvent(event);

}

void Game::render() {
  SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
  map_camera->draw(&map, tileset, screen);

 // todo draw with camera
  map_camera->draw(unit, screen);
  map_camera->draw(devastator, screen);

  if (mouse.left_button_held()) {
    rectangleRGBA(screen, mouse.getRectX(), mouse.getRectY(), mouse.x(), mouse.y(), 255, 255, 255, 255);
  }

  SDL_Flip(screen);
}

void Game::updateState() {
  SDL_PumpEvents();
  if (keyboard.isUpPressed()) map_camera->moveUp();
  if (keyboard.isDownPressed()) map_camera->moveDown();
  if (keyboard.isLeftPressed()) map_camera->moveLeft();
  if (keyboard.isRightPressed()) map_camera->moveRight();

  if (keyboard.isQPressed()) playing = false;

  mouse.update_state();

  if (mouse.x() <= 1) map_camera->moveLeft();
  if (mouse.x() >= (screen->w - 1)) map_camera->moveRight();
  if (mouse.y() <= 1) map_camera->moveUp();
  if (mouse.y() >= (screen->h - 1)) map_camera->moveDown();

  if (isInRect(devastator->getDrawX(), devastator->getDrawY(), devastator->width(), devastator->height())) {
    if(mouse.left_button_pressed() && !mouse.left_button_held()) {
      devastator->select();
    }
  }

  if (isInRect(unit->getDrawX(), unit->getDrawY(), unit->width(), unit->height())) {
    if(mouse.left_button_pressed() && !mouse.left_button_held()) {
      unit->select();
    }
  }

  if(mouse.right_button_pressed()) {
    devastator->unselect();
    unit->unselect();
  }

  if (mouse.dragged_rectangle()) {
    int rectX = map_camera->worldCoordinateX(mouse.getRectX());
    int rectY = map_camera->worldCoordinateY(mouse.getRectY());
    int endX = map_camera->worldCoordinateX(mouse.x());
    int endY = map_camera->worldCoordinateY(mouse.y());

    if (endX < rectX) swap(endX, rectX);
    if (endY < rectY) swap(endY, rectY);

    // bug: when user 'clicks' it deselects always now...

    unit->unselect();
    devastator->unselect();

    if (isUnitInRect(devastator, rectX, rectY, endX, endY)) {
        devastator->select();
    }

    if (isUnitInRect(unit, rectX, rectY, endX, endY)) {
        unit->select();
    }
  }

}

int Game::cleanup() {
  delete map_camera;
  delete unitRepository;
  delete unit;
  delete devastator;
  SDL_FreeSurface(screen);
  SDL_FreeSurface(tileset);
  SDL_Quit();
  return 0;
}

bool Game::isUnitInRect(Unit* unit, int x, int y, int end_x, int end_y) {
  // this checks the up-left position of a unit: TODO: do rectangle intersection
  int unit_x = unit->getDrawX();
  int unit_y = unit->getDrawY();
  return (unit_x >= x && unit_x < end_x) && (unit_y >= y && unit_y < end_y);
}

bool Game::isInRect(int x, int y, int width, int height) {
  int mouse_x = mouse.x();
  int mouse_y = mouse.y();
  return (mouse_x >= x && mouse_x < (x + width)) && (mouse_y >= y && mouse_y < (y + height));
}
<commit_msg>bug is fixed, remove comment<commit_after>#include <iostream>

#include "SDL/SDL.h"
#include "SDL_image.h"
#include "SDL_gfxPrimitives.h"
#include "map.h"
#include "game.h"
#include "surface.h"

using namespace std;

Game::Game() {
  playing=true;
  screen=NULL;
  tileset=NULL;
  map_camera=NULL;
  unit=NULL;
  devastator=NULL;
}

int Game::execute() {
  init();

  SDL_Event event;

  while(playing) {
    while(SDL_PollEvent(&event)) {
      onEvent(&event);
    }

    updateState();
    render();
    // SDL rest?
  }

  return cleanup();
}

int Game::init() {
  if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
    return false;
  }

  screen = SDL_SetVideoMode(800, 600, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
  if(screen == NULL) {
     return false;
  }

  int flags = IMG_INIT_JPG | IMG_INIT_PNG;
  int initted=IMG_Init(flags);
  if( initted & flags != flags) {
    cout << "could not init SDL_Image" << endl;
    cout << "Reason: " << IMG_GetError() << endl;
    return false;
  }

  tileset = Surface::load("tileset.png");

  if (tileset == NULL) {
    cout << "Failed to read tileset data" << endl;
    return false;
  }

  map.setBoundaries(128,128);
  map_camera = new MapCamera(0, 0, screen, &map);

  unitRepository = new UnitRepository();

  unit = unitRepository->create(UNIT_FRIGATE, HOUSE_SARDAUKAR, 64, 64);
  devastator = unitRepository->create(UNIT_TRIKE, HOUSE_ATREIDES, 128, 128);

  return true;
}

void Game::onEvent(SDL_Event* event) {
  if(event->type == SDL_QUIT) {
    playing = false;
  }

  keyboard.onEvent(event);

}

void Game::render() {
  SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
  map_camera->draw(&map, tileset, screen);

 // todo draw with camera
  map_camera->draw(unit, screen);
  map_camera->draw(devastator, screen);

  if (mouse.left_button_held()) {
    rectangleRGBA(screen, mouse.getRectX(), mouse.getRectY(), mouse.x(), mouse.y(), 255, 255, 255, 255);
  }

  SDL_Flip(screen);
}

void Game::updateState() {
  SDL_PumpEvents();
  if (keyboard.isUpPressed()) map_camera->moveUp();
  if (keyboard.isDownPressed()) map_camera->moveDown();
  if (keyboard.isLeftPressed()) map_camera->moveLeft();
  if (keyboard.isRightPressed()) map_camera->moveRight();

  if (keyboard.isQPressed()) playing = false;

  mouse.update_state();

  if (mouse.x() <= 1) map_camera->moveLeft();
  if (mouse.x() >= (screen->w - 1)) map_camera->moveRight();
  if (mouse.y() <= 1) map_camera->moveUp();
  if (mouse.y() >= (screen->h - 1)) map_camera->moveDown();

  if (isInRect(devastator->getDrawX(), devastator->getDrawY(), devastator->width(), devastator->height())) {
    if(mouse.left_button_pressed() && !mouse.left_button_held()) {
      devastator->select();
    }
  }

  if (isInRect(unit->getDrawX(), unit->getDrawY(), unit->width(), unit->height())) {
    if(mouse.left_button_pressed() && !mouse.left_button_held()) {
      unit->select();
    }
  }

  if(mouse.right_button_pressed()) {
    devastator->unselect();
    unit->unselect();
  }

  if (mouse.dragged_rectangle()) {
    int rectX = map_camera->worldCoordinateX(mouse.getRectX());
    int rectY = map_camera->worldCoordinateY(mouse.getRectY());
    int endX = map_camera->worldCoordinateX(mouse.x());
    int endY = map_camera->worldCoordinateY(mouse.y());

    if (endX < rectX) swap(endX, rectX);
    if (endY < rectY) swap(endY, rectY);

    unit->unselect();
    devastator->unselect();

    if (isUnitInRect(devastator, rectX, rectY, endX, endY)) {
        devastator->select();
    }

    if (isUnitInRect(unit, rectX, rectY, endX, endY)) {
        unit->select();
    }
  }

}

int Game::cleanup() {
  delete map_camera;
  delete unitRepository;
  delete unit;
  delete devastator;
  SDL_FreeSurface(screen);
  SDL_FreeSurface(tileset);
  SDL_Quit();
  return 0;
}

bool Game::isUnitInRect(Unit* unit, int x, int y, int end_x, int end_y) {
  // this checks the up-left position of a unit: TODO: do rectangle intersection
  int unit_x = unit->getDrawX();
  int unit_y = unit->getDrawY();
  return (unit_x >= x && unit_x < end_x) && (unit_y >= y && unit_y < end_y);
}

bool Game::isInRect(int x, int y, int width, int height) {
  int mouse_x = mouse.x();
  int mouse_y = mouse.y();
  return (mouse_x >= x && mouse_x < (x + width)) && (mouse_y >= y && mouse_y < (y + height));
}
<|endoftext|>


<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa 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 libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#ifndef VALUE_GUARD_HPP
#define VALUE_GUARD_HPP

#include "cppa/util/rm_ref.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/callable_trait.hpp"

#include "cppa/detail/tdata.hpp"

namespace cppa { namespace detail {

template<bool IsFun, typename T>
struct vg_fwd_
{
    static inline T const& _(T const& arg) { return arg; }
    static inline T&& _(T&& arg) { return std::move(arg); }
    static inline T& _(T& arg) { return arg; }
};

template<typename T>
struct vg_fwd_<true, T>
{
    template<typename Arg>
    static inline util::void_type _(Arg&&) { return {}; }
};

// absorbs callables
template<typename T>
struct vg_fwd
        : vg_fwd_<util::is_callable<typename util::rm_ref<T>::type>::value,
                  typename util::rm_ref<T>::type>
{
};

template<typename FilteredPattern>
class value_guard
{
    typename tdata_from_type_list<FilteredPattern>::type m_args;

    template<typename... Args>
    inline bool _eval(util::void_type const&, tdata<> const&, Args&&...) const
    {
        return true;
    }

    template<class Tail, typename Arg0, typename... Args>
    inline bool _eval(util::void_type const&, Tail const& tail,
                      Arg0 const&, Args const&... args         ) const
    {
        return _eval(tail.head, tail.tail(), args...);
    }

    template<typename Head, class Tail, typename Arg0, typename... Args>
    inline bool _eval(Head const& head, Tail const& tail,
                      Arg0 const& arg0, Args const&... args) const
    {
        return head == arg0 && _eval(tail.head, tail.tail(), args...);
    }

 public:

    value_guard() = default;
    value_guard(value_guard const&) = default;

    template<typename... Args>
    value_guard(Args const&... args) : m_args(vg_fwd<Args>::_(args)...)
    {
    }

    template<typename... Args>
    inline bool operator()(Args const&... args) const
    {
        return _eval(m_args.head, m_args.tail(), args...);
    }
};

} } // namespace cppa::detail

#endif // VALUE_GUARD_HPP
<commit_msg>fixed reference_wrapper handling<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa 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 libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#ifndef VALUE_GUARD_HPP
#define VALUE_GUARD_HPP

#include "cppa/util/rm_ref.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/callable_trait.hpp"

#include "cppa/detail/tdata.hpp"

namespace cppa { namespace detail {

template<bool IsFun, typename T>
struct vg_fwd_
{
    static inline T const& _(T const& arg) { return arg; }
    static inline T&& _(T&& arg) { return std::move(arg); }
    static inline T& _(T& arg) { return arg; }
};

template<typename T>
struct vg_fwd_<true, T>
{
    template<typename Arg>
    static inline util::void_type _(Arg&&) { return {}; }
};

// absorbs callables
template<typename T>
struct vg_fwd
        : vg_fwd_<util::is_callable<typename util::rm_ref<T>::type>::value,
                  typename util::rm_ref<T>::type>
{
};

template<typename FilteredPattern>
class value_guard
{
    typename tdata_from_type_list<FilteredPattern>::type m_args;

    template<typename... Args>
    static inline bool _eval(util::void_type const&, tdata<> const&,
                             Args const&...)
    {
        return true;
    }

    template<class Tail, typename Arg0, typename... Args>
    static inline bool _eval(util::void_type const&, Tail const& tail,
                             Arg0 const&, Args const&... args         )
    {
        return _eval(tail.head, tail.tail(), args...);
    }

    template<typename T0, typename T1>
    static inline bool cmp(T0 const& lhs, T1 const& rhs)
    {
        return lhs == rhs;
    }

    template<typename T0, typename T1>
    static inline bool cmp(T0 const& lhs, std::reference_wrapper<T1> const& rhs)
    {
        return lhs == rhs.get();
    }

    template<typename Head, class Tail, typename Arg0, typename... Args>
    static inline bool _eval(Head const& head, Tail const& tail,
                             Arg0 const& arg0, Args const&... args)
    {
        return cmp(head, arg0) && _eval(tail.head, tail.tail(), args...);
    }

 public:

    value_guard() = default;
    value_guard(value_guard const&) = default;

    template<typename... Args>
    value_guard(Args const&... args) : m_args(vg_fwd<Args>::_(args)...)
    {
    }

    template<typename... Args>
    inline bool operator()(Args const&... args) const
    {
        return _eval(m_args.head, m_args.tail(), args...);
    }
};

} } // namespace cppa::detail

#endif // VALUE_GUARD_HPP
<|endoftext|>