<commit_before>#include <string>
#include <sstream>
#include <stdlib.h>
#include <time.h>
#include <map>
#include <string>
#include <unistd.h>

#include "moves.h"

using namespace lmoves ;
std::ostream& lmoves::operator<<(std::ostream& out, tmove value) {
    static std::map<tmove, std::string> strings;
    if(strings.size() == 0) {
#define INSERT_ELEMENT(p) strings[tmove::p] = #p
        INSERT_ELEMENT(DOWN);
        INSERT_ELEMENT(UP);
        INSERT_ELEMENT(RIGHT);
        INSERT_ELEMENT(LEFT);
#undef INSERT_ELEMENT
    }

    return out << strings[value];
}

std::ostream& operator<<(std::ostream& out, Moves const& seq) {
    for(auto m : seq.getSequence()) {
        out << m << ' ';
    }

    return out;
}

// constructor
Moves::Moves(size_t seqLen) {
    while(seqLen-- != 0) {
        this->addRandomMove();
    }
}

// getter
std::vector<tmove> const& Moves::getSequence() const {
    return this->sequence;
}

void Moves::clearSequence() {
	this->sequence.clear();
}

tmove Moves::M_randomMove() {
    return static_cast<tmove>(rand() % static_cast<int>(tmove::NUM_MOVES));
}
void Moves::addMove(tmove m){
    sequence.push_back(m);
}
void Moves::addRandomMove() {
    tmove new_move = this->M_randomMove();
    sequence.push_back(new_move);
}
<commit_msg>add print sequence<commit_after>#include <string>
#include <sstream>
#include <stdlib.h>
#include <time.h>
#include <map>
#include <string>
#include <unistd.h>

#include "moves.h"

using namespace lmoves ;
std::ostream& lmoves::operator<<(std::ostream& out, tmove value) {
    static std::map<tmove, std::string> strings;
    if(strings.size() == 0) {
#define INSERT_ELEMENT(p) strings[tmove::p] = #p
        INSERT_ELEMENT(DOWN);
        INSERT_ELEMENT(UP);
        INSERT_ELEMENT(RIGHT);
        INSERT_ELEMENT(LEFT);
#undef INSERT_ELEMENT
    }

    return out << strings[value];
}

std::ostream& operator<<(std::ostream& out, Moves const& seq) {
    for(auto m : seq.getSequence()) {
        out << m << ' ';
    }

    return out;
}

// constructor
Moves::Moves(size_t seqLen) {
    while(seqLen-- != 0) {
        this->addRandomMove();
    }
}

// getter
std::vector<tmove> const& Moves::getSequence() const {
    return this->sequence;
}

void Moves::clearSequence() {
	this->sequence.clear();
}

tmove Moves::M_randomMove() {
    return static_cast<tmove>(rand() % static_cast<int>(tmove::NUM_MOVES));
}
void Moves::addMove(tmove m){
    sequence.push_back(m);
}
void Moves::addRandomMove() {
    tmove new_move = this->M_randomMove();
    sequence.push_back(new_move);
}
<|endoftext|>


<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.
 *
 * Authors: Ali Saidi
 */

/** @file
 * Isa Fake Device implementation
 */

#include "base/trace.hh"
#include "debug/IsaFake.hh"
#include "dev/isa_fake.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"
#include "sim/system.hh"

using namespace std;

IsaFake::IsaFake(Params *p)
    : BasicPioDevice(p, p->ret_bad_addr ? 0 : p->pio_size)
{
    retData8 = p->ret_data8;
    retData16 = p->ret_data16;
    retData32 = p->ret_data32;
    retData64 = p->ret_data64;
}

Tick
IsaFake::read(PacketPtr pkt)
{
    pkt->allocate();
    pkt->makeAtomicResponse();

    if (params()->warn_access != "")
        warn("Device %s accessed by read to address %#x size=%d\n",
                name(), pkt->getAddr(), pkt->getSize());
    if (params()->ret_bad_addr) {
        DPRINTF(IsaFake, "read to bad address va=%#x size=%d\n",
                pkt->getAddr(), pkt->getSize());
        pkt->setBadAddress();
    } else {
        assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
        DPRINTF(IsaFake, "read  va=%#x size=%d\n",
                pkt->getAddr(), pkt->getSize());
        switch (pkt->getSize()) {
          case sizeof(uint64_t):
             pkt->set(retData64);
             break;
          case sizeof(uint32_t):
             pkt->set(retData32);
             break;
          case sizeof(uint16_t):
             pkt->set(retData16);
             break;
          case sizeof(uint8_t):
             pkt->set(retData8);
             break;
          default:
             if (params()->fake_mem)
                 std::memset(pkt->getPtr<uint8_t>(), 0, pkt->getSize());
             else
                 panic("invalid access size! Device being accessed by cache?\n");
        }
    }
    return pioDelay;
}

Tick
IsaFake::write(PacketPtr pkt)
{
    pkt->makeAtomicResponse();
    if (params()->warn_access != "") {
        uint64_t data;
        switch (pkt->getSize()) {
          case sizeof(uint64_t):
            data = pkt->get<uint64_t>();
            break;
          case sizeof(uint32_t):
            data = pkt->get<uint32_t>();
            break;
          case sizeof(uint16_t):
            data = pkt->get<uint16_t>();
            break;
          case sizeof(uint8_t):
            data = pkt->get<uint8_t>();
            break;
          default:
            panic("invalid access size!\n");
        }
        warn("Device %s accessed by write to address %#x size=%d data=%#x\n",
                name(), pkt->getAddr(), pkt->getSize(), data);
    }
    if (params()->ret_bad_addr) {
        DPRINTF(IsaFake, "write to bad address va=%#x size=%d \n",
                pkt->getAddr(), pkt->getSize());
        pkt->setBadAddress();
    } else {
        DPRINTF(IsaFake, "write - va=%#x size=%d \n",
                pkt->getAddr(), pkt->getSize());

        if (params()->update_data) {
            switch (pkt->getSize()) {
              case sizeof(uint64_t):
                retData64 = pkt->get<uint64_t>();
                break;
              case sizeof(uint32_t):
                retData32 = pkt->get<uint32_t>();
                break;
              case sizeof(uint16_t):
                retData16 = pkt->get<uint16_t>();
                break;
              case sizeof(uint8_t):
                retData8 = pkt->get<uint8_t>();
                break;
              default:
                panic("invalid access size!\n");
            }
        }
    }
    return pioDelay;
}

IsaFake *
IsaFakeParams::create()
{
    return new IsaFake(this);
}
<commit_msg>dev: Output invalid access size in IsaFake panic<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.
 *
 * Authors: Ali Saidi
 */

/** @file
 * Isa Fake Device implementation
 */

#include "base/trace.hh"
#include "debug/IsaFake.hh"
#include "dev/isa_fake.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"
#include "sim/system.hh"

using namespace std;

IsaFake::IsaFake(Params *p)
    : BasicPioDevice(p, p->ret_bad_addr ? 0 : p->pio_size)
{
    retData8 = p->ret_data8;
    retData16 = p->ret_data16;
    retData32 = p->ret_data32;
    retData64 = p->ret_data64;
}

Tick
IsaFake::read(PacketPtr pkt)
{
    pkt->allocate();
    pkt->makeAtomicResponse();

    if (params()->warn_access != "")
        warn("Device %s accessed by read to address %#x size=%d\n",
                name(), pkt->getAddr(), pkt->getSize());
    if (params()->ret_bad_addr) {
        DPRINTF(IsaFake, "read to bad address va=%#x size=%d\n",
                pkt->getAddr(), pkt->getSize());
        pkt->setBadAddress();
    } else {
        assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
        DPRINTF(IsaFake, "read  va=%#x size=%d\n",
                pkt->getAddr(), pkt->getSize());
        switch (pkt->getSize()) {
          case sizeof(uint64_t):
             pkt->set(retData64);
             break;
          case sizeof(uint32_t):
             pkt->set(retData32);
             break;
          case sizeof(uint16_t):
             pkt->set(retData16);
             break;
          case sizeof(uint8_t):
             pkt->set(retData8);
             break;
          default:
             if (params()->fake_mem)
                 std::memset(pkt->getPtr<uint8_t>(), 0, pkt->getSize());
             else
                 panic("invalid access size! Device being accessed by cache?\n");
        }
    }
    return pioDelay;
}

Tick
IsaFake::write(PacketPtr pkt)
{
    pkt->makeAtomicResponse();
    if (params()->warn_access != "") {
        uint64_t data;
        switch (pkt->getSize()) {
          case sizeof(uint64_t):
            data = pkt->get<uint64_t>();
            break;
          case sizeof(uint32_t):
            data = pkt->get<uint32_t>();
            break;
          case sizeof(uint16_t):
            data = pkt->get<uint16_t>();
            break;
          case sizeof(uint8_t):
            data = pkt->get<uint8_t>();
            break;
          default:
            panic("invalid access size: %u\n", pkt->getSize());
        }
        warn("Device %s accessed by write to address %#x size=%d data=%#x\n",
                name(), pkt->getAddr(), pkt->getSize(), data);
    }
    if (params()->ret_bad_addr) {
        DPRINTF(IsaFake, "write to bad address va=%#x size=%d \n",
                pkt->getAddr(), pkt->getSize());
        pkt->setBadAddress();
    } else {
        DPRINTF(IsaFake, "write - va=%#x size=%d \n",
                pkt->getAddr(), pkt->getSize());

        if (params()->update_data) {
            switch (pkt->getSize()) {
              case sizeof(uint64_t):
                retData64 = pkt->get<uint64_t>();
                break;
              case sizeof(uint32_t):
                retData32 = pkt->get<uint32_t>();
                break;
              case sizeof(uint16_t):
                retData16 = pkt->get<uint16_t>();
                break;
              case sizeof(uint8_t):
                retData8 = pkt->get<uint8_t>();
                break;
              default:
                panic("invalid access size!\n");
            }
        }
    }
    return pioDelay;
}

IsaFake *
IsaFakeParams::create()
{
    return new IsaFake(this);
}
<|endoftext|>


<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.
 *
 * Authors: Ali Saidi
 *          Andrew Schultz
 *          Miguel Serrano
 */

#include <sys/time.h>
#include <time.h>

#include <string>

#include "base/bitfield.hh"
#include "base/time.hh"
#include "base/trace.hh"
#include "dev/mc146818.hh"
#include "dev/rtcreg.h"

using namespace std;

MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
                   bool bcd, Tick frequency)
    : EventManager(em), _name(n), event(this, frequency)
{
    memset(clock_data, 0, sizeof(clock_data));
    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
    stat_regB = RTCB_PRDC_IE | RTCB_24HR;
    if (!bcd)
        stat_regB |= RTCB_BIN;

    year = time.tm_year;

    if (bcd) {
        // The datasheet says that the year field can be either BCD or
        // years since 1900.  Linux seems to be happy with years since
        // 1900.
        year = year % 100;
        int tens = year / 10;
        int ones = year % 10;
        year = (tens << 4) + ones;
    }

    // Unix is 0-11 for month, data seet says start at 1
    mon = time.tm_mon + 1;
    mday = time.tm_mday;
    hour = time.tm_hour;
    min = time.tm_min;
    sec = time.tm_sec;

    // Datasheet says 1 is sunday
    wday = time.tm_wday + 1;

    DPRINTFN("Real-time clock set to %s", asctime(&time));
}

MC146818::~MC146818()
{
}

void
MC146818::writeData(const uint8_t addr, const uint8_t data)
{
    if (addr < RTC_STAT_REGA)
        clock_data[addr] = data;
    else {
        switch (addr) {
          case RTC_STAT_REGA:
            // The "update in progress" bit is read only.
            if ((data & ~RTCA_UIP) != (RTCA_32768HZ | RTCA_1024HZ))
                panic("Unimplemented RTC register A value write!\n");
            replaceBits(stat_regA, data, 6, 0);
            break;
          case RTC_STAT_REGB:
            if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
                panic("Write to RTC reg B bits that are not implemented!\n");

            if (data & RTCB_PRDC_IE) {
                if (!event.scheduled())
                    event.scheduleIntr();
            } else {
                if (event.scheduled())
                    deschedule(event);
            }
            stat_regB = data;
            break;
          case RTC_STAT_REGC:
          case RTC_STAT_REGD:
            panic("RTC status registers C and D are not implemented.\n");
            break;
        }
    }
}

uint8_t
MC146818::readData(uint8_t addr)
{
    if (addr < RTC_STAT_REGA)
        return clock_data[addr];
    else {
        switch (addr) {
          case RTC_STAT_REGA:
            // toggle UIP bit for linux
            stat_regA ^= RTCA_UIP;
            return stat_regA;
            break;
          case RTC_STAT_REGB:
            return stat_regB;
            break;
          case RTC_STAT_REGC:
          case RTC_STAT_REGD:
            return 0x00;
            break;
          default:
            panic("Shouldn't be here");
        }
    }
}

void
MC146818::serialize(const string &base, ostream &os)
{
    arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
    paramOut(os, base + ".stat_regA", stat_regA);
    paramOut(os, base + ".stat_regB", stat_regB);
}

void
MC146818::unserialize(const string &base, Checkpoint *cp,
                      const string &section)
{
    arrayParamIn(cp, section, base + ".clock_data", clock_data,
                 sizeof(clock_data));
    paramIn(cp, section, base + ".stat_regA", stat_regA);
    paramIn(cp, section, base + ".stat_regB", stat_regB);

    // We're not unserializing the event here, but we need to
    // rescehedule the event since curTick was moved forward by the
    // checkpoint
    reschedule(event, curTick + event.interval);
}

MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i)
    : parent(_parent), interval(i)
{
    DPRINTF(MC146818, "RTC Event Initilizing\n");
    parent->schedule(this, curTick + interval);
}

void
MC146818::RTCEvent::scheduleIntr()
{
    parent->schedule(this, curTick + interval);
}

void
MC146818::RTCEvent::process()
{
    DPRINTF(MC146818, "RTC Timer Interrupt\n");
    parent->schedule(this, curTick + interval);
    parent->handleEvent();
}

const char *
MC146818::RTCEvent::description() const
{
    return "RTC interrupt";
}
<commit_msg>X86: Don't insist on binary encoding for the RTC since we implement BCD.<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.
 *
 * Authors: Ali Saidi
 *          Andrew Schultz
 *          Miguel Serrano
 */

#include <sys/time.h>
#include <time.h>

#include <string>

#include "base/bitfield.hh"
#include "base/time.hh"
#include "base/trace.hh"
#include "dev/mc146818.hh"
#include "dev/rtcreg.h"

using namespace std;

MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
                   bool bcd, Tick frequency)
    : EventManager(em), _name(n), event(this, frequency)
{
    memset(clock_data, 0, sizeof(clock_data));
    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
    stat_regB = RTCB_PRDC_IE | RTCB_24HR;
    if (!bcd)
        stat_regB |= RTCB_BIN;

    year = time.tm_year;

    if (bcd) {
        // The datasheet says that the year field can be either BCD or
        // years since 1900.  Linux seems to be happy with years since
        // 1900.
        year = year % 100;
        int tens = year / 10;
        int ones = year % 10;
        year = (tens << 4) + ones;
    }

    // Unix is 0-11 for month, data seet says start at 1
    mon = time.tm_mon + 1;
    mday = time.tm_mday;
    hour = time.tm_hour;
    min = time.tm_min;
    sec = time.tm_sec;

    // Datasheet says 1 is sunday
    wday = time.tm_wday + 1;

    DPRINTFN("Real-time clock set to %s", asctime(&time));
}

MC146818::~MC146818()
{
}

void
MC146818::writeData(const uint8_t addr, const uint8_t data)
{
    if (addr < RTC_STAT_REGA)
        clock_data[addr] = data;
    else {
        switch (addr) {
          case RTC_STAT_REGA:
            // The "update in progress" bit is read only.
            if ((data & ~RTCA_UIP) != (RTCA_32768HZ | RTCA_1024HZ))
                panic("Unimplemented RTC register A value write!\n");
            replaceBits(stat_regA, data, 6, 0);
            break;
          case RTC_STAT_REGB:
            if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != RTCB_24HR)
                panic("Write to RTC reg B bits that are not implemented!\n");

            if (data & RTCB_PRDC_IE) {
                if (!event.scheduled())
                    event.scheduleIntr();
            } else {
                if (event.scheduled())
                    deschedule(event);
            }
            stat_regB = data;
            break;
          case RTC_STAT_REGC:
          case RTC_STAT_REGD:
            panic("RTC status registers C and D are not implemented.\n");
            break;
        }
    }
}

uint8_t
MC146818::readData(uint8_t addr)
{
    if (addr < RTC_STAT_REGA)
        return clock_data[addr];
    else {
        switch (addr) {
          case RTC_STAT_REGA:
            // toggle UIP bit for linux
            stat_regA ^= RTCA_UIP;
            return stat_regA;
            break;
          case RTC_STAT_REGB:
            return stat_regB;
            break;
          case RTC_STAT_REGC:
          case RTC_STAT_REGD:
            return 0x00;
            break;
          default:
            panic("Shouldn't be here");
        }
    }
}

void
MC146818::serialize(const string &base, ostream &os)
{
    arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
    paramOut(os, base + ".stat_regA", stat_regA);
    paramOut(os, base + ".stat_regB", stat_regB);
}

void
MC146818::unserialize(const string &base, Checkpoint *cp,
                      const string &section)
{
    arrayParamIn(cp, section, base + ".clock_data", clock_data,
                 sizeof(clock_data));
    paramIn(cp, section, base + ".stat_regA", stat_regA);
    paramIn(cp, section, base + ".stat_regB", stat_regB);

    // We're not unserializing the event here, but we need to
    // rescehedule the event since curTick was moved forward by the
    // checkpoint
    reschedule(event, curTick + event.interval);
}

MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i)
    : parent(_parent), interval(i)
{
    DPRINTF(MC146818, "RTC Event Initilizing\n");
    parent->schedule(this, curTick + interval);
}

void
MC146818::RTCEvent::scheduleIntr()
{
    parent->schedule(this, curTick + interval);
}

void
MC146818::RTCEvent::process()
{
    DPRINTF(MC146818, "RTC Timer Interrupt\n");
    parent->schedule(this, curTick + interval);
    parent->handleEvent();
}

const char *
MC146818::RTCEvent::description() const
{
    return "RTC interrupt";
}
<|endoftext|>


<commit_before>/*
 * LabelPropagation.cpp
 *
 *  Created on: 07.12.2012
 *      Author: cls
 */

#include "LabelPropagation.h"

namespace EnsembleClustering {

LabelPropagation::LabelPropagation() {
	// TODO Auto-generated constructor stub

}

LabelPropagation::~LabelPropagation() {
	// TODO Auto-generated destructor stub
}

Clustering LabelPropagation::run(Graph& G) {

	typedef cluster label;	// a label is the same as a cluster id

	// init random for std::shuffle
	std::random_device rd;
	std::mt19937 randgen(rd());

	int64_t n = G.numberOfNodes();

	// create the clustering to be returned
	// set unique label for each node
	Clustering labels(n);
	labels.allToSingletons();

	int64_t majorityLabelCount = 0;	// number of nodes which already have the majority label
	int64_t nIterations = 0; 	// number of iterations

	/**
	 * == Dealing with isolated nodes ==
	 *
	 * The pseudocode published does not deal with isolated nodes (and therefore does not terminate if they are present).
	 * Isolated nodes stay singletons. They can be ignored in the while loop, but the loop condition must
	 * compare to the number of non-isolated nodes instead of n.
	 *
	 */

	// count connected nodes for loop condition
	int64_t nConnected = 0;
	G.forallNodes([&](node v) {
		if (G.degree(v) > 0) {
			#pragma omp atomic update
			nConnected += 1;
		}
	}, "parallel");

	// PERFORMANCE: precompute and store incident edge weight for all nodes
	NodeMap<double> incidentWeight(n);
	G.forallNodes([&](node v) {
		incidentWeight[v] = G.incidentWeight(v);
	}, "parallel");

	// propagate labels
	while (majorityLabelCount != nConnected) {
		nIterations += 1;
		DEBUG("***** LabelPropagation: iteration #" << nIterations << "*****");
		// DEBUG
		TRACE("number of nodes which already have the majority label: " << majorityLabelCount << " of " << G.numberOfNodes());
		// DEBUG

		// reset majority label count
		majorityLabelCount = 0;

		// DEBUG
		if (nIterations >= 23) {
			ERROR("LabelPropagation reached " << nIterations << " iterations. It usually terminates after less than 5 iterations. Something has gone terribly wrong.");
			GraphIO graphio;
			graphio.writeAdjacencyList(G, "sandbox/LabelPropagationFAIL.adjlist");
			throw std::runtime_error("aborting LabelPropagation to avoid infinite loop");
		}
		// DEBUG

		std::vector<node> shuffledNodes;
		shuffledNodes.resize(n); 	// hold n nodes
		G.forallNodes([&](node v){
			shuffledNodes[v - 1] = v;	// store all nodes in vector
		}, "parallel");
		std::shuffle(shuffledNodes.begin(), shuffledNodes.end(), randgen);
		// DEBUG
		TRACE("shuffledNodes: " << Aux::vectorToString(shuffledNodes));
		// DEBUG

		for (node v : shuffledNodes) {
			// ignore isolated nodes TODO: correct?
			if (G.degree(v) > 0) {

				std::map<label, double> labelWeights; // neighborLabelCounts maps label -> frequency in the neighbors

				// weigh the labels in the neighborhood of v
				G.forallNeighborsOf(v, [&](node w) {
					label lw = labels[w];
					if (labelWeights.find(lw) == labelWeights.end()) {
						labelWeights[lw] = 0.0; // init map entry if not yet in map
					}
					labelWeights[lw] += G.weight(v, w);	// add weight of edge {v, w}
				});

				// consider also self-loop (i.e. v's own weight)
				label lv = labels[v];
				if (labelWeights.find(lv) == labelWeights.end()) {
					labelWeights[lv] = 0.0;	// init map entry if not yet in map
				}
				labelWeights[lv] += G.weight(v);

				// get most frequent label
				label heaviest = 0; // TODO: check if 0 occurs in final clustering
				double maxWeight = 0.0;
				for (auto it = labelWeights.begin(); it != labelWeights.end(); it++) {
					if (it->second > maxWeight) {
						maxWeight = it->second;
						heaviest = it->first;
					}
				}

				TRACE("updating label of " << v << " from " << labels[v] << " to " << heaviest);
				labels.moveToCluster(heaviest, v);

				// stop if v has label of at least half of its neighbors
				label dominantLabel = 0; // = None
				// try to find dominant label
				for (auto it2 = labelWeights.begin(); it2 != labelWeights.end(); it2++) {
					// label is dominant if it weighs more than half of the incident weight (including self-loop)
						if (it2->second > ((incidentWeight[v] + G.weight(v)) / 2.0)) {
						dominantLabel = it2->first;
					}
				}

				if (dominantLabel != 0) {
					if (labels[v] == dominantLabel) {
						majorityLabelCount += 1;
					}
				} else {
					TRACE("no dominant label found for node: " << v);
				}// if no label dominant, do nothing
			} else {
				// node is isolated
				TRACE("ignoring isolated node: " << v);
			}
		} // end for shuffled nodes

	}

	return labels;

}

} /* namespace EnsembleClustering */
<commit_msg>using std::default_random_engine<commit_after>/*
 * LabelPropagation.cpp
 *
 *  Created on: 07.12.2012
 *      Author: cls
 */

#include "LabelPropagation.h"

namespace EnsembleClustering {

LabelPropagation::LabelPropagation() {
	// TODO Auto-generated constructor stub

}

LabelPropagation::~LabelPropagation() {
	// TODO Auto-generated destructor stub
}

Clustering LabelPropagation::run(Graph& G) {

	typedef cluster label;	// a label is the same as a cluster id

	// init random for std::shuffle
	std::default_random_engine rd;
	std::mt19937 randgen(rd());

	int64_t n = G.numberOfNodes();

	// create the clustering to be returned
	// set unique label for each node
	Clustering labels(n);
	labels.allToSingletons();

	int64_t majorityLabelCount = 0;	// number of nodes which already have the majority label
	int64_t nIterations = 0; 	// number of iterations

	/**
	 * == Dealing with isolated nodes ==
	 *
	 * The pseudocode published does not deal with isolated nodes (and therefore does not terminate if they are present).
	 * Isolated nodes stay singletons. They can be ignored in the while loop, but the loop condition must
	 * compare to the number of non-isolated nodes instead of n.
	 *
	 */

	// count connected nodes for loop condition
	int64_t nConnected = 0;
	G.forallNodes([&](node v) {
		if (G.degree(v) > 0) {
			#pragma omp atomic update
			nConnected += 1;
		}
	}, "parallel");

	// PERFORMANCE: precompute and store incident edge weight for all nodes
	NodeMap<double> incidentWeight(n);
	G.forallNodes([&](node v) {
		incidentWeight[v] = G.incidentWeight(v);
	}, "parallel");

	// propagate labels
	while (majorityLabelCount != nConnected) {
		nIterations += 1;
		DEBUG("***** LabelPropagation: iteration #" << nIterations << "*****");
		// DEBUG
		TRACE("number of nodes which already have the majority label: " << majorityLabelCount << " of " << G.numberOfNodes());
		// DEBUG

		// reset majority label count
		majorityLabelCount = 0;

		// DEBUG
		if (nIterations >= 23) {
			ERROR("LabelPropagation reached " << nIterations << " iterations. It usually terminates after less than 5 iterations. Something has gone terribly wrong.");
			GraphIO graphio;
			graphio.writeAdjacencyList(G, "sandbox/LabelPropagationFAIL.adjlist");
			throw std::runtime_error("aborting LabelPropagation to avoid infinite loop");
		}
		// DEBUG

		std::vector<node> shuffledNodes;
		shuffledNodes.resize(n); 	// hold n nodes
		G.forallNodes([&](node v){
			shuffledNodes[v - 1] = v;	// store all nodes in vector
		}, "parallel");
		std::shuffle(shuffledNodes.begin(), shuffledNodes.end(), randgen);
		// DEBUG
		TRACE("shuffledNodes: " << Aux::vectorToString(shuffledNodes));
		// DEBUG

		for (node v : shuffledNodes) {
			// ignore isolated nodes TODO: correct?
			if (G.degree(v) > 0) {

				std::map<label, double> labelWeights; // neighborLabelCounts maps label -> frequency in the neighbors

				// weigh the labels in the neighborhood of v
				G.forallNeighborsOf(v, [&](node w) {
					label lw = labels[w];
					if (labelWeights.find(lw) == labelWeights.end()) {
						labelWeights[lw] = 0.0; // init map entry if not yet in map
					}
					labelWeights[lw] += G.weight(v, w);	// add weight of edge {v, w}
				});

				// consider also self-loop (i.e. v's own weight)
				label lv = labels[v];
				if (labelWeights.find(lv) == labelWeights.end()) {
					labelWeights[lv] = 0.0;	// init map entry if not yet in map
				}
				labelWeights[lv] += G.weight(v);

				// get most frequent label
				label heaviest = 0; // TODO: check if 0 occurs in final clustering
				double maxWeight = 0.0;
				for (auto it = labelWeights.begin(); it != labelWeights.end(); it++) {
					if (it->second > maxWeight) {
						maxWeight = it->second;
						heaviest = it->first;
					}
				}

				TRACE("updating label of " << v << " from " << labels[v] << " to " << heaviest);
				labels.moveToCluster(heaviest, v);

				// stop if v has label of at least half of its neighbors
				label dominantLabel = 0; // = None
				// try to find dominant label
				for (auto it2 = labelWeights.begin(); it2 != labelWeights.end(); it2++) {
					// label is dominant if it weighs more than half of the incident weight (including self-loop)
						if (it2->second > ((incidentWeight[v] + G.weight(v)) / 2.0)) {
						dominantLabel = it2->first;
					}
				}

				if (dominantLabel != 0) {
					if (labels[v] == dominantLabel) {
						majorityLabelCount += 1;
					}
				} else {
					TRACE("no dominant label found for node: " << v);
				}// if no label dominant, do nothing
			} else {
				// node is isolated
				TRACE("ignoring isolated node: " << v);
			}
		} // end for shuffled nodes

	}

	return labels;

}

} /* namespace EnsembleClustering */
<|endoftext|>


<commit_before>#include "conv.hpp"

namespace Shadow {

namespace Vision {

// check for 0 <= a < b
inline bool check_border(int a, int b) {
  return static_cast<unsigned>(a) < static_cast<unsigned>(b);
}

template <>
void Im2Col<DeviceType::kCPU, float>(const float* in_data,
                                     const VecInt& in_shape, int offset,
                                     int kernel_size_h, int kernel_size_w,
                                     int stride_h, int stride_w, int pad_h,
                                     int pad_w, int dilation, int zero_point,
                                     const VecInt& out_shape, float* col_data,
                                     Context* context) {
  in_data += offset;
  int in_c = in_shape[1], in_h = in_shape[2], in_w = in_shape[3];
  int out_h = out_shape[2], out_w = out_shape[3];
  int spatial_dim = in_h * in_w;
  for (int k_c = 0; k_c < in_c; ++k_c, in_data += spatial_dim) {
    for (int k_s = 0; k_s < kernel_size_h * kernel_size_w; ++k_s) {
      int k_h = k_s / kernel_size_w;
      int k_w = k_s % kernel_size_w;
      int im_row = -pad_h + k_h * dilation;
      for (int h = 0; h < out_h; ++h, im_row += stride_h) {
        if (check_border(im_row, in_h)) {
          int im_col = -pad_w + k_w * dilation;
          for (int w = 0; w < out_w; ++w, im_col += stride_w) {
            if (check_border(im_col, in_w)) {
              *(col_data++) = in_data[im_row * in_w + im_col];
            } else {
              *(col_data++) = static_cast<float>(zero_point);
            }
          }
        } else {
          for (int w = 0; w < out_w; ++w) {
            *(col_data++) = static_cast<float>(zero_point);
          }
        }
      }
    }
  }
}

template <>
void Depthwise<DeviceType::kCPU, float>(
    const float* in_data, const VecInt& in_shape, const float* weight_data,
    const float* bias_data, int kernel_size_h, int kernel_size_w, int stride_h,
    int stride_w, int pad_h, int pad_w, int dilation, bool bias_term,
    const VecInt& out_shape, float* out_data, Context* context) {
  int batch = in_shape[0];
  int in_c = in_shape[1], in_h = in_shape[2], in_w = in_shape[3];
  int out_h = out_shape[2], out_w = out_shape[3];
  for (int b = 0; b < batch; ++b) {
    for (int c = 0; c < in_c; ++c) {
      const auto* in_offset_data = in_data + (b * in_c + c) * in_h * in_w;
      auto* out_offset_data = out_data + (b * in_c + c) * out_h * out_w;
      for (int h = 0; h < out_h; ++h) {
        for (int w = 0; w < out_w; ++w) {
          const auto* weight_offset_data =
              weight_data + c * kernel_size_h * kernel_size_w;
          double sum_val = 0;
          for (int kh = 0; kh < kernel_size_h; ++kh) {
            for (int kw = 0; kw < kernel_size_w; ++kw) {
              int h_in = h * stride_h - pad_h + kh * dilation;
              int w_in = w * stride_w - pad_w + kw * dilation;
              if (h_in >= 0 && h_in < in_h && w_in >= 0 && w_in < in_w) {
                sum_val +=
                    in_offset_data[h_in * in_w + w_in] * *weight_offset_data;
              }
              weight_offset_data++;
            }
          }
          if (bias_term) {
            sum_val += bias_data[c];
          }
          out_offset_data[h * out_w + w] = static_cast<float>(sum_val);
        }
      }
    }
  }
}

}  // namespace Vision

}  // namespace Shadow

namespace Shadow {

REGISTER_OP_KERNEL_DEFAULT(ConvCPU, ConvKernelDefault<DeviceType::kCPU>);

#if defined(USE_NNPACK)

class ConvKernelNNPACK : public ConvKernel {
 public:
  ConvKernelNNPACK() {
    default_kernel_ = std::make_shared<ConvKernelDefault<DeviceType::kCPU>>();
  }

  void Run(const std::shared_ptr<Blob>& input,
           const std::shared_ptr<Blob>& weight,
           const std::shared_ptr<Blob>& bias, std::shared_ptr<Blob>& output,
           Workspace* ws, int num_output, int kernel_size_h, int kernel_size_w,
           int stride_h, int stride_w, int pad_h, int pad_w, int dilation,
           int group, bool bias_term, int activate_type) override {
    int batch = input->shape(0), in_c = input->shape(1), in_h = input->shape(2),
        in_w = input->shape(3);

    if (batch == 1 && group == 1 && dilation == 1 && bias_term) {
      auto nnp_activation =
          activate_type == 1 ? nnp_activation_relu : nnp_activation_identity;
      auto nnp_input_size =
          nnp_size{static_cast<size_t>(in_h), static_cast<size_t>(in_w)};
      auto nnp_kernel_size = nnp_size{static_cast<size_t>(kernel_size_h),
                                      static_cast<size_t>(kernel_size_w)};
      auto nnp_stride = nnp_size{static_cast<size_t>(stride_h),
                                 static_cast<size_t>(stride_w)};
      auto nnp_pad = nnp_padding{};
      nnp_pad.top = nnp_pad.bottom = static_cast<size_t>(pad_h);
      nnp_pad.left = nnp_pad.right = static_cast<size_t>(pad_w);

      int out_c = output->shape(1);
      auto status = nnp_convolution_inference(
          nnp_convolution_algorithm_auto,
          nnp_convolution_transform_strategy_compute, in_c, out_c,
          nnp_input_size, nnp_pad, nnp_kernel_size, nnp_stride,
          input->data<float>(), weight->data<float>(), bias->data<float>(),
          output->mutable_data<float>(), nullptr, nullptr, nnp_activation,
          nullptr, pthreadpool_t(ws->Ctx()->nnpack_handle()), nullptr);
      CHECK_EQ(nnp_status_success, status);
    } else {
      default_kernel_->Run(input, weight, bias, output, ws, num_output,
                           kernel_size_h, kernel_size_w, stride_h, stride_w,
                           pad_h, pad_w, dilation, group, bias_term,
                           activate_type);
    }
  }

  DeviceType device_type() const override { return DeviceType::kCPU; }

  std::string kernel_type() const override { return "NNPACK"; }

 private:
  std::shared_ptr<ConvKernelDefault<DeviceType::kCPU>> default_kernel_ =
      nullptr;
};

REGISTER_OP_KERNEL(ConvCPU(NNPACK), ConvKernelNNPACK);

#endif

#if defined(USE_DNNL)

class ConvKernelDNNL : public ConvKernel {
 public:
  void Run(const std::shared_ptr<Blob>& input,
           const std::shared_ptr<Blob>& weight,
           const std::shared_ptr<Blob>& bias, std::shared_ptr<Blob>& output,
           Workspace* ws, int num_output, int kernel_size_h, int kernel_size_w,
           int stride_h, int stride_w, int pad_h, int pad_w, int dilation,
           int group, bool bias_term, int activate_type) override {
    int in_c = input->shape(1);

    const auto& src_desc = idnnl::create_memory_desc<float>(input->shape());
    const auto& dst_desc = idnnl::create_memory_desc<float>(output->shape());
    dnnl::memory::desc weight_desc;
    if (group == 1) {
      weight_desc = idnnl::create_memory_desc<float>(
          {num_output, in_c, kernel_size_h, kernel_size_w},
          dnnl::memory::format_tag::oihw);
    } else {
      weight_desc = idnnl::create_memory_desc<float>(
          {group, num_output / group, in_c / group, kernel_size_h,
           kernel_size_w},
          dnnl::memory::format_tag::goihw);
    }
    const auto& bias_desc = idnnl::create_memory_desc<float>(
        {num_output}, bias_term ? dnnl::memory::format_tag::x
                                : dnnl::memory::format_tag::undef);

    const auto& conv_desc = idnnl::create_convolution_desc(
        src_desc, weight_desc, bias_desc, dst_desc, pad_h, pad_w, stride_h,
        stride_w, dilation, dilation);

    idnnl::common_forward<dnnl::convolution_forward>(
        ws->Ctx()->dnnl_engine(), ws->Ctx()->dnnl_stream(), conv_desc,
        input->data<float>(), weight->data<float>(),
        bias_term ? bias->data<float>() : nullptr,
        output->mutable_data<float>(), activate_type);
  }

  DeviceType device_type() const override { return DeviceType::kCPU; }

  std::string kernel_type() const override { return "DNNL"; }
};

REGISTER_OP_KERNEL_DNNL(ConvCPU, ConvKernelDNNL);

#endif

}  // namespace Shadow
<commit_msg>fix bug: fix nnp_size's height and width when use nnpack<commit_after>#include "conv.hpp"

namespace Shadow {

namespace Vision {

// check for 0 <= a < b
inline bool check_border(int a, int b) {
  return static_cast<unsigned>(a) < static_cast<unsigned>(b);
}

template <>
void Im2Col<DeviceType::kCPU, float>(const float* in_data,
                                     const VecInt& in_shape, int offset,
                                     int kernel_size_h, int kernel_size_w,
                                     int stride_h, int stride_w, int pad_h,
                                     int pad_w, int dilation, int zero_point,
                                     const VecInt& out_shape, float* col_data,
                                     Context* context) {
  in_data += offset;
  int in_c = in_shape[1], in_h = in_shape[2], in_w = in_shape[3];
  int out_h = out_shape[2], out_w = out_shape[3];
  int spatial_dim = in_h * in_w;
  for (int k_c = 0; k_c < in_c; ++k_c, in_data += spatial_dim) {
    for (int k_s = 0; k_s < kernel_size_h * kernel_size_w; ++k_s) {
      int k_h = k_s / kernel_size_w;
      int k_w = k_s % kernel_size_w;
      int im_row = -pad_h + k_h * dilation;
      for (int h = 0; h < out_h; ++h, im_row += stride_h) {
        if (check_border(im_row, in_h)) {
          int im_col = -pad_w + k_w * dilation;
          for (int w = 0; w < out_w; ++w, im_col += stride_w) {
            if (check_border(im_col, in_w)) {
              *(col_data++) = in_data[im_row * in_w + im_col];
            } else {
              *(col_data++) = static_cast<float>(zero_point);
            }
          }
        } else {
          for (int w = 0; w < out_w; ++w) {
            *(col_data++) = static_cast<float>(zero_point);
          }
        }
      }
    }
  }
}

template <>
void Depthwise<DeviceType::kCPU, float>(
    const float* in_data, const VecInt& in_shape, const float* weight_data,
    const float* bias_data, int kernel_size_h, int kernel_size_w, int stride_h,
    int stride_w, int pad_h, int pad_w, int dilation, bool bias_term,
    const VecInt& out_shape, float* out_data, Context* context) {
  int batch = in_shape[0];
  int in_c = in_shape[1], in_h = in_shape[2], in_w = in_shape[3];
  int out_h = out_shape[2], out_w = out_shape[3];
  for (int b = 0; b < batch; ++b) {
    for (int c = 0; c < in_c; ++c) {
      const auto* in_offset_data = in_data + (b * in_c + c) * in_h * in_w;
      auto* out_offset_data = out_data + (b * in_c + c) * out_h * out_w;
      for (int h = 0; h < out_h; ++h) {
        for (int w = 0; w < out_w; ++w) {
          const auto* weight_offset_data =
              weight_data + c * kernel_size_h * kernel_size_w;
          double sum_val = 0;
          for (int kh = 0; kh < kernel_size_h; ++kh) {
            for (int kw = 0; kw < kernel_size_w; ++kw) {
              int h_in = h * stride_h - pad_h + kh * dilation;
              int w_in = w * stride_w - pad_w + kw * dilation;
              if (h_in >= 0 && h_in < in_h && w_in >= 0 && w_in < in_w) {
                sum_val +=
                    in_offset_data[h_in * in_w + w_in] * *weight_offset_data;
              }
              weight_offset_data++;
            }
          }
          if (bias_term) {
            sum_val += bias_data[c];
          }
          out_offset_data[h * out_w + w] = static_cast<float>(sum_val);
        }
      }
    }
  }
}

}  // namespace Vision

}  // namespace Shadow

namespace Shadow {

REGISTER_OP_KERNEL_DEFAULT(ConvCPU, ConvKernelDefault<DeviceType::kCPU>);

#if defined(USE_NNPACK)

class ConvKernelNNPACK : public ConvKernel {
 public:
  ConvKernelNNPACK() {
    default_kernel_ = std::make_shared<ConvKernelDefault<DeviceType::kCPU>>();
  }

  void Run(const std::shared_ptr<Blob>& input,
           const std::shared_ptr<Blob>& weight,
           const std::shared_ptr<Blob>& bias, std::shared_ptr<Blob>& output,
           Workspace* ws, int num_output, int kernel_size_h, int kernel_size_w,
           int stride_h, int stride_w, int pad_h, int pad_w, int dilation,
           int group, bool bias_term, int activate_type) override {
    int batch = input->shape(0), in_c = input->shape(1), in_h = input->shape(2),
        in_w = input->shape(3);

    if (batch == 1 && group == 1 && dilation == 1 && bias_term) {
      auto nnp_activation =
          activate_type == 1 ? nnp_activation_relu : nnp_activation_identity;
      auto nnp_input_size =
          nnp_size{static_cast<size_t>(in_w), static_cast<size_t>(in_h)};
      auto nnp_kernel_size = nnp_size{static_cast<size_t>(kernel_size_w),
                                      static_cast<size_t>(kernel_size_h)};
      auto nnp_stride = nnp_size{static_cast<size_t>(stride_w),
                                 static_cast<size_t>(stride_h)};
      auto nnp_pad = nnp_padding{};
      nnp_pad.top = nnp_pad.bottom = static_cast<size_t>(pad_h);
      nnp_pad.left = nnp_pad.right = static_cast<size_t>(pad_w);

      int out_c = output->shape(1);
      auto status = nnp_convolution_inference(
          nnp_convolution_algorithm_auto,
          nnp_convolution_transform_strategy_compute, in_c, out_c,
          nnp_input_size, nnp_pad, nnp_kernel_size, nnp_stride,
          input->data<float>(), weight->data<float>(), bias->data<float>(),
          output->mutable_data<float>(), nullptr, nullptr, nnp_activation,
          nullptr, pthreadpool_t(ws->Ctx()->nnpack_handle()), nullptr);
      CHECK_EQ(nnp_status_success, status);
    } else {
      default_kernel_->Run(input, weight, bias, output, ws, num_output,
                           kernel_size_h, kernel_size_w, stride_h, stride_w,
                           pad_h, pad_w, dilation, group, bias_term,
                           activate_type);
    }
  }

  DeviceType device_type() const override { return DeviceType::kCPU; }

  std::string kernel_type() const override { return "NNPACK"; }

 private:
  std::shared_ptr<ConvKernelDefault<DeviceType::kCPU>> default_kernel_ =
      nullptr;
};

REGISTER_OP_KERNEL(ConvCPU(NNPACK), ConvKernelNNPACK);

#endif

#if defined(USE_DNNL)

class ConvKernelDNNL : public ConvKernel {
 public:
  void Run(const std::shared_ptr<Blob>& input,
           const std::shared_ptr<Blob>& weight,
           const std::shared_ptr<Blob>& bias, std::shared_ptr<Blob>& output,
           Workspace* ws, int num_output, int kernel_size_h, int kernel_size_w,
           int stride_h, int stride_w, int pad_h, int pad_w, int dilation,
           int group, bool bias_term, int activate_type) override {
    int in_c = input->shape(1);

    const auto& src_desc = idnnl::create_memory_desc<float>(input->shape());
    const auto& dst_desc = idnnl::create_memory_desc<float>(output->shape());
    dnnl::memory::desc weight_desc;
    if (group == 1) {
      weight_desc = idnnl::create_memory_desc<float>(
          {num_output, in_c, kernel_size_h, kernel_size_w},
          dnnl::memory::format_tag::oihw);
    } else {
      weight_desc = idnnl::create_memory_desc<float>(
          {group, num_output / group, in_c / group, kernel_size_h,
           kernel_size_w},
          dnnl::memory::format_tag::goihw);
    }
    const auto& bias_desc = idnnl::create_memory_desc<float>(
        {num_output}, bias_term ? dnnl::memory::format_tag::x
                                : dnnl::memory::format_tag::undef);

    const auto& conv_desc = idnnl::create_convolution_desc(
        src_desc, weight_desc, bias_desc, dst_desc, pad_h, pad_w, stride_h,
        stride_w, dilation, dilation);

    idnnl::common_forward<dnnl::convolution_forward>(
        ws->Ctx()->dnnl_engine(), ws->Ctx()->dnnl_stream(), conv_desc,
        input->data<float>(), weight->data<float>(),
        bias_term ? bias->data<float>() : nullptr,
        output->mutable_data<float>(), activate_type);
  }

  DeviceType device_type() const override { return DeviceType::kCPU; }

  std::string kernel_type() const override { return "DNNL"; }
};

REGISTER_OP_KERNEL_DNNL(ConvCPU, ConvKernelDNNL);

#endif

}  // namespace Shadow
<|endoftext|>


<commit_before>/*
 * Author: Jon Trulson <jtrulson@ics.com>
 * Copyright (c) 2015 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#pragma once

#include <iostream>
#include <string>

#include "dfrph.h"

namespace upm {
  /**
   * @brief DFRobot pH sensors
   * @defgroup dfrph libupm-dfrph
   * @ingroup dfrobot liquid analog
   */

  /**
   * @library dfrph
   * @sensor dfrph
   * @comname Analog pH Sensor
   * @type liquid
   * @man dfrobot
   * @web http://www.dfrobot.com/index.php?route=product/product&product_id=1110
   * @con analog
   *
   * @brief API for the DFRobot pH Sensors
   *
   * This sensor family returns an analog voltage proportional to the
   * acidity or alkalinity of a liquid -- it's pH value.
   *
   * This driver was developed using the DFRobot Analog pH meter and
   * the DFRobot Analog pH Meter Pro.
   *
   *
   * Calibration instructions, taken and slightly reworded from the
   *  DFRobot wiki at:
   *  http://dfrobot.com/wiki/index.php/PH_meter%28SKU:_SEN0161%29
   *
   *  1) Connect equipment: the pH electrode is connected to the BNC
   *  connector on the pH meter board, and then the pH meter board is
   *  connected to the analog port 0 of the controller. When the
   *  controller gets power, you will see the blue LED on board is on.
   *
   *  2) Put the pH electrode into the standard solution whose pH
   *  value is 7.00.  Run the dfrph example and note the pH output
   *  value.  Compare the value with 7.00, and calculate the
   *  difference.  This is the value you should supply to the
   *  setOffset() method.
   *
   *  3) Put the pH electrode into the pH standard solution whose
   *  value is 4.00. Then wait about one minute, and adjust the
   *  potentiometer on the interface board.  Let the value stabilise
   *  at around 4.00. At this time,the acidic calibration has been
   *  completed and you can measure the pH value of an acidic
   *  solution.
   *
   *  4) According to the linear characteristics of pH electrode
   *  itself, after the above calibration,you can directly measure the
   *  pH value of the alkaline solution. If you want to get better
   *  accuracy, you can recalibrate it. Alkaline calibration use the
   *  standard solution whose pH value is 9.18.  Also adjust the
   *  potentiometer and let the value stabilise at around 9.18. After
   *  this calibration, you can measure the pH value of an alkaline
   *  solution.
   *
   * @image html dfrph.jpg
   * @snippet dfrph.cxx Interesting
   */

  class DFRPH {
  public:

    /**
     * DFRPH constructor
     *
     * @param pin Analog pin to use
     * @param vref Analog reference voltage; default is 5.0 V
     */
    DFRPH(int pin, float vref = 5.0);

    /**
     * DFRPH destructor
     */
    ~DFRPH();

    /**
     * Specifies the offset determined from calibration.  The default
     * is 0.0.
     *
     * @param offset The offset value to use
     */
    void setOffset(float offset);

    /**
     * Specifies the scale determined from calibration.  The default
     * is 1.0.
     *
     * @param scale The scale value to use
     */
    void setScale(float scale);

    float volts();

    /**
     * Take a number of samples and return the detected pH value.  The
     * default number of samples is 15.
     *
     * @param samples The number of samples to average over, default 15
     * @return The pH value detected
     */
    float pH(unsigned int samples = 15);

  private:
    /**
     * Don't allow copies of this class
     */
    DFRPH(const DFRPH&) {}

    dfrph_context _dev;
  };
}

<commit_msg>dfrph.hpp: Don't allow copies of DFRPH - cont...<commit_after>/*
 * Author: Jon Trulson <jtrulson@ics.com>
 * Copyright (c) 2015 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#pragma once

#include <iostream>
#include <string>

#include "dfrph.h"

namespace upm {
  /**
   * @brief DFRobot pH sensors
   * @defgroup dfrph libupm-dfrph
   * @ingroup dfrobot liquid analog
   */

  /**
   * @library dfrph
   * @sensor dfrph
   * @comname Analog pH Sensor
   * @type liquid
   * @man dfrobot
   * @web http://www.dfrobot.com/index.php?route=product/product&product_id=1110
   * @con analog
   *
   * @brief API for the DFRobot pH Sensors
   *
   * This sensor family returns an analog voltage proportional to the
   * acidity or alkalinity of a liquid -- it's pH value.
   *
   * This driver was developed using the DFRobot Analog pH meter and
   * the DFRobot Analog pH Meter Pro.
   *
   *
   * Calibration instructions, taken and slightly reworded from the
   *  DFRobot wiki at:
   *  http://dfrobot.com/wiki/index.php/PH_meter%28SKU:_SEN0161%29
   *
   *  1) Connect equipment: the pH electrode is connected to the BNC
   *  connector on the pH meter board, and then the pH meter board is
   *  connected to the analog port 0 of the controller. When the
   *  controller gets power, you will see the blue LED on board is on.
   *
   *  2) Put the pH electrode into the standard solution whose pH
   *  value is 7.00.  Run the dfrph example and note the pH output
   *  value.  Compare the value with 7.00, and calculate the
   *  difference.  This is the value you should supply to the
   *  setOffset() method.
   *
   *  3) Put the pH electrode into the pH standard solution whose
   *  value is 4.00. Then wait about one minute, and adjust the
   *  potentiometer on the interface board.  Let the value stabilise
   *  at around 4.00. At this time,the acidic calibration has been
   *  completed and you can measure the pH value of an acidic
   *  solution.
   *
   *  4) According to the linear characteristics of pH electrode
   *  itself, after the above calibration,you can directly measure the
   *  pH value of the alkaline solution. If you want to get better
   *  accuracy, you can recalibrate it. Alkaline calibration use the
   *  standard solution whose pH value is 9.18.  Also adjust the
   *  potentiometer and let the value stabilise at around 9.18. After
   *  this calibration, you can measure the pH value of an alkaline
   *  solution.
   *
   * @image html dfrph.jpg
   * @snippet dfrph.cxx Interesting
   */

  class DFRPH {
  public:

    /**
     * DFRPH constructor
     *
     * @param pin Analog pin to use
     * @param vref Analog reference voltage; default is 5.0 V
     */
    DFRPH(int pin, float vref = 5.0);

    /**
     * DFRPH destructor
     */
    ~DFRPH();

    /**
     * Specifies the offset determined from calibration.  The default
     * is 0.0.
     *
     * @param offset The offset value to use
     */
    void setOffset(float offset);

    /**
     * Specifies the scale determined from calibration.  The default
     * is 1.0.
     *
     * @param scale The scale value to use
     */
    void setScale(float scale);

    float volts();

    /**
     * Take a number of samples and return the detected pH value.  The
     * default number of samples is 15.
     *
     * @param samples The number of samples to average over, default 15
     * @return The pH value detected
     */
    float pH(unsigned int samples = 15);

  private:
    /**
     * Don't allow copies of this class
     */
    DFRPH(const DFRPH&) {}
    DFRPH &operator=(const DFRPH &) {return *this;}

    dfrph_context _dev;
  };
}

<|endoftext|>


<commit_before>//
// Copyleft 2011 RIME Developers
// License: GPLv3
//
// 2011-11-02 GONG Chen <chen.sst@gmail.com>
//
#include <cstdlib>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <rime/service.h>
#include <rime/algo/dynamics.h>
#include <rime/dict/text_db.h>
#include <rime/dict/tree_db.h>
#include <rime/dict/user_db.h>

namespace rime {

UserDbValue::UserDbValue()
    : commits(0), dee(0.0), tick(0) {
}

UserDbValue::UserDbValue(const std::string& value)
    : commits(0), dee(0.0), tick(0) {
  Unpack(value);
}

std::string UserDbValue::Pack() const {
  return boost::str(boost::format("c=%1% d=%2% t=%3%") %
                    commits % dee % tick);
}

bool UserDbValue::Unpack(const std::string &value) {
  std::vector<std::string> kv;
  boost::split(kv, value, boost::is_any_of(" "));
  BOOST_FOREACH(const std::string &k_eq_v, kv) {
    size_t eq = k_eq_v.find('=');
    if (eq == std::string::npos)
      continue;
    std::string k(k_eq_v.substr(0, eq));
    std::string v(k_eq_v.substr(eq + 1));
    try {
      if (k == "c") {
        commits = boost::lexical_cast<int>(v);
      }
      else if (k == "d") {
        dee = (std::min)(200.0, boost::lexical_cast<double>(v));
      }
      else if (k == "t") {
        tick = boost::lexical_cast<TickCount>(v);
      }
    }
    catch (...) {
      LOG(ERROR) << "failed in parsing key-value from userdb entry '"
                 << k_eq_v << "'.";
      return false;
    }
  }
  return true;
}

template <>
const std::string UserDb<TextDb>::extension(".userdb.txt");

template <>
const std::string UserDb<TextDb>::snapshot_extension(".userdb.txt");

template <>
const std::string UserDb<TreeDb>::extension(".userdb.kct");

template <>
const std::string UserDb<TreeDb>::snapshot_extension(".userdb.kcss");

// key ::= code <space> <Tab> phrase

static bool userdb_entry_parser(const Tsv& row,
                                std::string* key,
                                std::string* value) {
  if (row.size() < 2 ||
      row[0].empty() || row[1].empty()) {
    return false;
  }
  std::string code(row[0]);
  // fix invalid keys created by a buggy version
  if (code[code.length() - 1] != ' ')
    code += ' ';
  *key = code + "\t" + row[1];
  if (row.size() >= 3)
    *value = row[2];
  else
    value->clear();
  return true;
}

static bool userdb_entry_formatter(const std::string& key,
                                   const std::string& value,
                                   Tsv* tsv) {
  Tsv& row(*tsv);
  boost::algorithm::split(row, key,
                          boost::algorithm::is_any_of("\t"));
  if (row.size() != 2 ||
      row[0].empty() || row[1].empty())
    return false;
  row.push_back(value);
  return true;
}

static TextFormat plain_userdb_format = {
  userdb_entry_parser,
  userdb_entry_formatter,
  "Rime user dictionary",
};

template <>
UserDb<TextDb>::UserDb(const std::string& name)
    : TextDb(name + extension, "userdb", plain_userdb_format) {
}

template <>
UserDb<TreeDb>::UserDb(const std::string& name)
    : TreeDb(name + extension, "userdb") {
}

template <class BaseDb>
bool UserDb<BaseDb>::CreateMetadata() {
  Deployer& deployer(Service::instance().deployer());
  return BaseDb::CreateMetadata() &&
      BaseDb::MetaUpdate("/user_id", deployer.user_id);
}

template <>
bool UserDb<TextDb>::Backup(const std::string& snapshot_file) {
  return TextDb::Backup(snapshot_file);
}

template <>
bool UserDb<TextDb>::Restore(const std::string& snapshot_file) {
  return TextDb::Restore(snapshot_file);
}

template <>
bool UserDb<TreeDb>::Backup(const std::string& snapshot_file) {
  // plain userdb format
  if (boost::ends_with(snapshot_file, UserDb<TextDb>::snapshot_extension)) {
    LOG(INFO) << "backing up db '" << name() << "' to " << snapshot_file;
    TsvWriter writer(snapshot_file, plain_userdb_format.formatter);
    writer.file_description = plain_userdb_format.file_description;
    DbSource source(this);
    try {
      writer << source;
    }
    catch (std::exception& ex) {
      LOG(ERROR) << ex.what();
      return false;
    }
    return true;
  }
  // KCSS format
  return TreeDb::Backup(snapshot_file);
}

template <>
bool UserDb<TreeDb>::Restore(const std::string& snapshot_file) {
  // plain userdb format
  if (boost::ends_with(snapshot_file, UserDb<TextDb>::snapshot_extension)) {
    LOG(INFO) << "restoring db '" << name() << "' from " << snapshot_file;
    TsvReader reader(snapshot_file, plain_userdb_format.parser);
    DbSink sink(this);
    try {
      reader >> sink;
    }
    catch (std::exception& ex) {
      LOG(ERROR) << ex.what();
      return false;
    }
    return true;
  }
  // KCSS format
  return TreeDb::Restore(snapshot_file);
}

template <class BaseDb>
bool UserDb<BaseDb>::IsUserDb() {
  std::string db_type;
  return BaseDb::MetaFetch("/db_type", &db_type) && (db_type == "userdb");
}

template <class BaseDb>
std::string UserDb<BaseDb>::GetDbName() {
  std::string name;
  if (!BaseDb::MetaFetch("/db_name", &name))
    return name;
  boost::erase_last(name, extension);
  return name;
}

template <class BaseDb>
std::string UserDb<BaseDb>::GetUserId() {
  std::string user_id("unknown");
  BaseDb::MetaFetch("/user_id", &user_id);
  return user_id;
}

template <class BaseDb>
std::string UserDb<BaseDb>::GetRimeVersion() {
  std::string version;
  BaseDb::MetaFetch("/rime_version", &version);
  return version;
}

template class UserDb<TextDb>;
template class UserDb<TreeDb>;

static TickCount get_tick_count(Db* db) {
  std::string tick;
  if (db && db->MetaFetch("/tick", &tick)) {
    try {
      return boost::lexical_cast<TickCount>(tick);
    }
    catch (...) {
    }
  }
  return 1;
}

UserDbMerger::UserDbMerger(Db* db) : db_(db) {
  our_tick_ = get_tick_count(db);
  their_tick_ = 0;
  max_tick_ = our_tick_;
}

UserDbMerger::~UserDbMerger() {
  CloseMerge();
}

bool UserDbMerger::MetaPut(const std::string& key, const std::string& value) {
  if (key == "/tick") {
    try {
      their_tick_ = boost::lexical_cast<TickCount>(value);
      max_tick_ = (std::max)(our_tick_, their_tick_);
    }
    catch (...) {
    }
  }
  return true;
}

bool UserDbMerger::Put(const std::string& key, const std::string& value) {
  if (!db_) return false;
  UserDbValue v(value);
  if (v.tick < their_tick_) {
    v.dee = algo::formula_d(0, (double)their_tick_, v.dee, (double)v.tick);
  }
  UserDbValue o;
  std::string our_value;
  if (db_->Fetch(key, &our_value)) {
    o.Unpack(our_value);
  }
  if (o.tick < our_tick_) {
    o.dee = algo::formula_d(0, (double)our_tick_, o.dee, (double)o.tick);
  }
  if (std::abs(o.commits) < std::abs(v.commits))
      o.commits = v.commits;
  o.dee = (std::max)(o.dee, v.dee);
  o.tick = max_tick_;
  return db_->Update(key, o.Pack()) && ++merged_entries_;
}

void UserDbMerger::CloseMerge() {
  if (!db_ || !merged_entries_)
    return;
  Deployer& deployer(Service::instance().deployer());
  try {
    db_->MetaUpdate("/tick", boost::lexical_cast<std::string>(max_tick_));
    db_->MetaUpdate("/user_id", deployer.user_id);
  }
  catch (...) {
    LOG(ERROR) << "failed to update tick count.";
    return;
  }
  LOG(INFO) << "total " << merged_entries_ << " entries merged, tick = "
            << max_tick_;
  merged_entries_ = 0;
}

UserDbImporter::UserDbImporter(Db* db)
    : db_(db) {
}

bool UserDbImporter::MetaPut(const std::string& key, const std::string& value) {
  return true;
}

bool UserDbImporter::Put(const std::string& key, const std::string& value) {
  if (!db_) return false;
  UserDbValue v(value);
  UserDbValue o;
  std::string old_value;
  if (db_->Fetch(key, &old_value)) {
    o.Unpack(old_value);
  }
  if (v.commits > 0) {
    o.commits = (std::max)(o.commits, v.commits);
    o.dee = (std::max)(o.dee, v.dee);
  }
  else if (v.commits < 0) {  // mark as deleted
    o.commits = (std::min)(v.commits, -std::abs(o.commits));
  }
  return db_->Update(key, o.Pack());
}

}  // namespace rime
<commit_msg>user_db: increase the upperbound of density to 10000, to keep candidates topmost.<commit_after>//
// Copyleft 2011 RIME Developers
// License: GPLv3
//
// 2011-11-02 GONG Chen <chen.sst@gmail.com>
//
#include <cstdlib>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <rime/service.h>
#include <rime/algo/dynamics.h>
#include <rime/dict/text_db.h>
#include <rime/dict/tree_db.h>
#include <rime/dict/user_db.h>

namespace rime {

UserDbValue::UserDbValue()
    : commits(0), dee(0.0), tick(0) {
}

UserDbValue::UserDbValue(const std::string& value)
    : commits(0), dee(0.0), tick(0) {
  Unpack(value);
}

std::string UserDbValue::Pack() const {
  return boost::str(boost::format("c=%1% d=%2% t=%3%") %
                    commits % dee % tick);
}

bool UserDbValue::Unpack(const std::string &value) {
  std::vector<std::string> kv;
  boost::split(kv, value, boost::is_any_of(" "));
  BOOST_FOREACH(const std::string &k_eq_v, kv) {
    size_t eq = k_eq_v.find('=');
    if (eq == std::string::npos)
      continue;
    std::string k(k_eq_v.substr(0, eq));
    std::string v(k_eq_v.substr(eq + 1));
    try {
      if (k == "c") {
        commits = boost::lexical_cast<int>(v);
      }
      else if (k == "d") {
        dee = (std::min)(10000.0, boost::lexical_cast<double>(v));
      }
      else if (k == "t") {
        tick = boost::lexical_cast<TickCount>(v);
      }
    }
    catch (...) {
      LOG(ERROR) << "failed in parsing key-value from userdb entry '"
                 << k_eq_v << "'.";
      return false;
    }
  }
  return true;
}

template <>
const std::string UserDb<TextDb>::extension(".userdb.txt");

template <>
const std::string UserDb<TextDb>::snapshot_extension(".userdb.txt");

template <>
const std::string UserDb<TreeDb>::extension(".userdb.kct");

template <>
const std::string UserDb<TreeDb>::snapshot_extension(".userdb.kcss");

// key ::= code <space> <Tab> phrase

static bool userdb_entry_parser(const Tsv& row,
                                std::string* key,
                                std::string* value) {
  if (row.size() < 2 ||
      row[0].empty() || row[1].empty()) {
    return false;
  }
  std::string code(row[0]);
  // fix invalid keys created by a buggy version
  if (code[code.length() - 1] != ' ')
    code += ' ';
  *key = code + "\t" + row[1];
  if (row.size() >= 3)
    *value = row[2];
  else
    value->clear();
  return true;
}

static bool userdb_entry_formatter(const std::string& key,
                                   const std::string& value,
                                   Tsv* tsv) {
  Tsv& row(*tsv);
  boost::algorithm::split(row, key,
                          boost::algorithm::is_any_of("\t"));
  if (row.size() != 2 ||
      row[0].empty() || row[1].empty())
    return false;
  row.push_back(value);
  return true;
}

static TextFormat plain_userdb_format = {
  userdb_entry_parser,
  userdb_entry_formatter,
  "Rime user dictionary",
};

template <>
UserDb<TextDb>::UserDb(const std::string& name)
    : TextDb(name + extension, "userdb", plain_userdb_format) {
}

template <>
UserDb<TreeDb>::UserDb(const std::string& name)
    : TreeDb(name + extension, "userdb") {
}

template <class BaseDb>
bool UserDb<BaseDb>::CreateMetadata() {
  Deployer& deployer(Service::instance().deployer());
  return BaseDb::CreateMetadata() &&
      BaseDb::MetaUpdate("/user_id", deployer.user_id);
}

template <>
bool UserDb<TextDb>::Backup(const std::string& snapshot_file) {
  return TextDb::Backup(snapshot_file);
}

template <>
bool UserDb<TextDb>::Restore(const std::string& snapshot_file) {
  return TextDb::Restore(snapshot_file);
}

template <>
bool UserDb<TreeDb>::Backup(const std::string& snapshot_file) {
  // plain userdb format
  if (boost::ends_with(snapshot_file, UserDb<TextDb>::snapshot_extension)) {
    LOG(INFO) << "backing up db '" << name() << "' to " << snapshot_file;
    TsvWriter writer(snapshot_file, plain_userdb_format.formatter);
    writer.file_description = plain_userdb_format.file_description;
    DbSource source(this);
    try {
      writer << source;
    }
    catch (std::exception& ex) {
      LOG(ERROR) << ex.what();
      return false;
    }
    return true;
  }
  // KCSS format
  return TreeDb::Backup(snapshot_file);
}

template <>
bool UserDb<TreeDb>::Restore(const std::string& snapshot_file) {
  // plain userdb format
  if (boost::ends_with(snapshot_file, UserDb<TextDb>::snapshot_extension)) {
    LOG(INFO) << "restoring db '" << name() << "' from " << snapshot_file;
    TsvReader reader(snapshot_file, plain_userdb_format.parser);
    DbSink sink(this);
    try {
      reader >> sink;
    }
    catch (std::exception& ex) {
      LOG(ERROR) << ex.what();
      return false;
    }
    return true;
  }
  // KCSS format
  return TreeDb::Restore(snapshot_file);
}

template <class BaseDb>
bool UserDb<BaseDb>::IsUserDb() {
  std::string db_type;
  return BaseDb::MetaFetch("/db_type", &db_type) && (db_type == "userdb");
}

template <class BaseDb>
std::string UserDb<BaseDb>::GetDbName() {
  std::string name;
  if (!BaseDb::MetaFetch("/db_name", &name))
    return name;
  boost::erase_last(name, extension);
  return name;
}

template <class BaseDb>
std::string UserDb<BaseDb>::GetUserId() {
  std::string user_id("unknown");
  BaseDb::MetaFetch("/user_id", &user_id);
  return user_id;
}

template <class BaseDb>
std::string UserDb<BaseDb>::GetRimeVersion() {
  std::string version;
  BaseDb::MetaFetch("/rime_version", &version);
  return version;
}

template class UserDb<TextDb>;
template class UserDb<TreeDb>;

static TickCount get_tick_count(Db* db) {
  std::string tick;
  if (db && db->MetaFetch("/tick", &tick)) {
    try {
      return boost::lexical_cast<TickCount>(tick);
    }
    catch (...) {
    }
  }
  return 1;
}

UserDbMerger::UserDbMerger(Db* db) : db_(db) {
  our_tick_ = get_tick_count(db);
  their_tick_ = 0;
  max_tick_ = our_tick_;
}

UserDbMerger::~UserDbMerger() {
  CloseMerge();
}

bool UserDbMerger::MetaPut(const std::string& key, const std::string& value) {
  if (key == "/tick") {
    try {
      their_tick_ = boost::lexical_cast<TickCount>(value);
      max_tick_ = (std::max)(our_tick_, their_tick_);
    }
    catch (...) {
    }
  }
  return true;
}

bool UserDbMerger::Put(const std::string& key, const std::string& value) {
  if (!db_) return false;
  UserDbValue v(value);
  if (v.tick < their_tick_) {
    v.dee = algo::formula_d(0, (double)their_tick_, v.dee, (double)v.tick);
  }
  UserDbValue o;
  std::string our_value;
  if (db_->Fetch(key, &our_value)) {
    o.Unpack(our_value);
  }
  if (o.tick < our_tick_) {
    o.dee = algo::formula_d(0, (double)our_tick_, o.dee, (double)o.tick);
  }
  if (std::abs(o.commits) < std::abs(v.commits))
      o.commits = v.commits;
  o.dee = (std::max)(o.dee, v.dee);
  o.tick = max_tick_;
  return db_->Update(key, o.Pack()) && ++merged_entries_;
}

void UserDbMerger::CloseMerge() {
  if (!db_ || !merged_entries_)
    return;
  Deployer& deployer(Service::instance().deployer());
  try {
    db_->MetaUpdate("/tick", boost::lexical_cast<std::string>(max_tick_));
    db_->MetaUpdate("/user_id", deployer.user_id);
  }
  catch (...) {
    LOG(ERROR) << "failed to update tick count.";
    return;
  }
  LOG(INFO) << "total " << merged_entries_ << " entries merged, tick = "
            << max_tick_;
  merged_entries_ = 0;
}

UserDbImporter::UserDbImporter(Db* db)
    : db_(db) {
}

bool UserDbImporter::MetaPut(const std::string& key, const std::string& value) {
  return true;
}

bool UserDbImporter::Put(const std::string& key, const std::string& value) {
  if (!db_) return false;
  UserDbValue v(value);
  UserDbValue o;
  std::string old_value;
  if (db_->Fetch(key, &old_value)) {
    o.Unpack(old_value);
  }
  if (v.commits > 0) {
    o.commits = (std::max)(o.commits, v.commits);
    o.dee = (std::max)(o.dee, v.dee);
  }
  else if (v.commits < 0) {  // mark as deleted
    o.commits = (std::min)(v.commits, -std::abs(o.commits));
  }
  return db_->Update(key, o.Pack());
}

}  // namespace rime
<|endoftext|>


<commit_before>#include <output.hpp>
#include <core.hpp>
#include <debug.hpp>
#include <view.hpp>
#include <view-transform.hpp>
#include <render-manager.hpp>
#include <workspace-manager.hpp>

#include <queue>
#include <linux/input.h>
#include <utility>
#include <animation.hpp>
#include <set>
#include "view-change-viewport-signal.hpp"
#include "../wobbly/wobbly-signal.hpp"

class vswitch_view_transformer : public wf_2D_view
{
    public:
        static const std::string name;
        vswitch_view_transformer(wayfire_view view) : wf_2D_view(view) {}
        virtual uint32_t get_z_order() override { return WF_TRANSFORMER_BLUR - 1; }
};
const std::string vswitch_view_transformer::name = "vswitch-transformer";

static double clamp(double x, double s, double e)
{
    if (x < s)
        return s;
    if (x > e)
        return e;

    return x;
}

class vswitch : public wayfire_plugin_t
{
    private:
        activator_callback callback_left, callback_right, callback_up, callback_down;
        activator_callback callback_win_left, callback_win_right, callback_win_up, callback_win_down;

        gesture_callback gesture_cb;

        wf_duration duration;
        wf_transition dx, dy;
        wayfire_view grabbed_view = nullptr;

        wf_option animation_duration;

    public:
    wayfire_view get_top_view()
    {
        auto ws = output->workspace->get_current_workspace();
        auto views = output->workspace->get_views_on_workspace(ws, WF_LAYER_WORKSPACE, true);

        return views.empty() ? nullptr : views[0];
    }

    void init(wayfire_config *config)
    {
        grab_interface->name = "vswitch";
        grab_interface->abilities_mask = WF_ABILITY_CONTROL_WM;

        callback_left  = [=] () { add_direction(-1,  0); };
        callback_right = [=] () { add_direction( 1,  0); };
        callback_up    = [=] () { add_direction( 0, -1); };
        callback_down  = [=] () { add_direction( 0,  1); };

        callback_win_left  = [=] () { add_direction(-1,  0, get_top_view()); };
        callback_win_right = [=] () { add_direction( 1,  0, get_top_view()); };
        callback_win_up    = [=] () { add_direction( 0, -1, get_top_view()); };
        callback_win_down  = [=] () { add_direction( 0,  1, get_top_view()); };

        auto section   = config->get_section("vswitch");

        auto binding_left  = section->get_option("binding_left",  "<super> KEY_LEFT  | swipe right 4");
        auto binding_right = section->get_option("binding_right", "<super> KEY_RIGHT | swipe left 4");
        auto binding_up    = section->get_option("binding_up",    "<super> KEY_UP    | swipe down 4");
        auto binding_down  = section->get_option("binding_down",  "<super> KEY_DOWN  | swipe up 4");

        auto binding_win_left  = section->get_option("binding_win_left",  "<super> <shift> KEY_LEFT");
        auto binding_win_right = section->get_option("binding_win_right", "<super> <shift> KEY_RIGHT");
        auto binding_win_up    = section->get_option("binding_win_up",    "<super> <shift> KEY_UP");
        auto binding_win_down  = section->get_option("binding_win_down",  "<super> <shift> KEY_DOWN");

        output->add_activator(binding_left,  &callback_left);
        output->add_activator(binding_right, &callback_right);
        output->add_activator(binding_up,    &callback_up);
        output->add_activator(binding_down,  &callback_down);

        output->add_activator(binding_win_left,  &callback_win_left);
        output->add_activator(binding_win_right, &callback_win_right);
        output->add_activator(binding_win_up,    &callback_win_up);
        output->add_activator(binding_win_down,  &callback_win_down);

        animation_duration = section->get_option("duration", "180");
        duration = wf_duration(animation_duration);
    }

    void add_direction(int x, int y, wayfire_view view = nullptr)
    {
        if (!x && !y)
            return;

        if (!output->is_plugin_active(grab_interface->name))
            start_switch();

        if (view && view->role != WF_VIEW_ROLE_TOPLEVEL)
            view = nullptr;

        if (view && !grabbed_view)
            grabbed_view = view;

        /* Make sure that when we add this direction, we won't go outside
         * of the workspace grid */
        GetTuple(vx, vy, output->workspace->get_current_workspace());
        GetTuple(vw, vh, output->workspace->get_workspace_grid_size());
        int tvx = clamp(vx + dx.end + x, 0, vw - 1);
        int tvy = clamp(vy + dy.end + y, 0, vh - 1);

        dx = {duration.progress(dx), 1.0 * tvx - vx};
        dy = {duration.progress(dy), 1.0 * tvy - vy};

        duration.start();
    }

    std::vector<wayfire_view> get_ws_views()
    {
        std::vector<wayfire_view> views;
        output->workspace->for_each_view([&](wayfire_view view)
        {
            if (view != grabbed_view)
                views.push_back(view);
        }, WF_MIDDLE_LAYERS);

        return views;
    }

    bool start_switch()
    {
        if (!output->activate_plugin(grab_interface))
            return false;

        output->render->add_effect(&update_animation, WF_OUTPUT_EFFECT_PRE);
        output->render->auto_redraw(true);

        duration.start();
        dx = dy = {0, 0};

        for (auto view : get_ws_views())
        {
            if (!view->get_transformer(vswitch_view_transformer::name))
            {
                view->add_transformer(
                    nonstd::make_unique<vswitch_view_transformer>(view),
                    vswitch_view_transformer::name);
            }
        }

        return true;
    }

    effect_hook_t update_animation = [=] ()
    {
        if (!duration.running())
            return stop_switch();

        GetTuple(sw, sh, output->get_screen_size());
        for (auto view : get_ws_views())
        {
            auto tr = dynamic_cast<vswitch_view_transformer*> (
                view->get_transformer(vswitch_view_transformer::name).get());

            view->damage();
            tr->translation_x = -duration.progress(dx) * sw;
            tr->translation_y = -duration.progress(dy) * sh;
            view->damage();
        }
    };

    void slide_done()
    {
        GetTuple(vx, vy, output->workspace->get_current_workspace());
        auto old_ws = output->workspace->get_current_workspace();

        vx += dx.end;
        vy += dy.end;

        auto output_g = output->get_relative_geometry();
        output->workspace->set_workspace(std::make_tuple(vx, vy));

        if (grabbed_view)
        {
            auto wm = grabbed_view->get_wm_geometry();
            grabbed_view->move(wm.x + dx.end * output_g.width,
                wm.y + dy.end * output_g.height);

            output->focus_view(grabbed_view);

            view_change_viewport_signal data;
            data.view = grabbed_view;
            data.from = old_ws;
            data.to = output->workspace->get_current_workspace();
            output->emit_signal("view-change-viewport", &data);
        }
    }

    void stop_switch()
    {
        slide_done();
        grabbed_view = nullptr;

        for (auto view : get_ws_views())
            view->pop_transformer(vswitch_view_transformer::name);

        output->deactivate_plugin(grab_interface);
        output->render->rem_effect(&update_animation, WF_OUTPUT_EFFECT_PRE);
        output->render->auto_redraw(false);
    }

    void fini()
    {
        if (output->is_plugin_active(grab_interface->name))
            stop_switch();

        output->rem_binding(&callback_left);
        output->rem_binding(&callback_right);
        output->rem_binding(&callback_up);
        output->rem_binding(&callback_down);

        output->rem_binding(&callback_win_left);
        output->rem_binding(&callback_win_right);
        output->rem_binding(&callback_win_up);
        output->rem_binding(&callback_win_down);

        output->rem_binding(&gesture_cb);
    }
};

extern "C"
{
    wayfire_plugin_t* newInstance()
    {
        return new vswitch();
    }
}
<commit_msg>vswitch: handle set-workspace-request<commit_after>#include <output.hpp>
#include <core.hpp>
#include <debug.hpp>
#include <view.hpp>
#include <view-transform.hpp>
#include <render-manager.hpp>
#include <workspace-manager.hpp>

#include <queue>
#include <linux/input.h>
#include <utility>
#include <animation.hpp>
#include <set>
#include "view-change-viewport-signal.hpp"
#include "../wobbly/wobbly-signal.hpp"

class vswitch_view_transformer : public wf_2D_view
{
    public:
        static const std::string name;
        vswitch_view_transformer(wayfire_view view) : wf_2D_view(view) {}
        virtual uint32_t get_z_order() override { return WF_TRANSFORMER_BLUR - 1; }
};
const std::string vswitch_view_transformer::name = "vswitch-transformer";

static double clamp(double x, double s, double e)
{
    if (x < s)
        return s;
    if (x > e)
        return e;

    return x;
}

class vswitch : public wayfire_plugin_t
{
    private:
        activator_callback callback_left, callback_right, callback_up, callback_down;
        activator_callback callback_win_left, callback_win_right, callback_win_up, callback_win_down;

        gesture_callback gesture_cb;

        wf_duration duration;
        wf_transition dx, dy;
        wayfire_view grabbed_view = nullptr;

        wf_option animation_duration;

    public:
    wayfire_view get_top_view()
    {
        auto ws = output->workspace->get_current_workspace();
        auto views = output->workspace->get_views_on_workspace(ws, WF_LAYER_WORKSPACE, true);

        return views.empty() ? nullptr : views[0];
    }

    void init(wayfire_config *config)
    {
        grab_interface->name = "vswitch";
        grab_interface->abilities_mask = WF_ABILITY_CONTROL_WM;

        callback_left  = [=] () { add_direction(-1,  0); };
        callback_right = [=] () { add_direction( 1,  0); };
        callback_up    = [=] () { add_direction( 0, -1); };
        callback_down  = [=] () { add_direction( 0,  1); };

        callback_win_left  = [=] () { add_direction(-1,  0, get_top_view()); };
        callback_win_right = [=] () { add_direction( 1,  0, get_top_view()); };
        callback_win_up    = [=] () { add_direction( 0, -1, get_top_view()); };
        callback_win_down  = [=] () { add_direction( 0,  1, get_top_view()); };

        auto section   = config->get_section("vswitch");

        auto binding_left  = section->get_option("binding_left",  "<super> KEY_LEFT  | swipe right 4");
        auto binding_right = section->get_option("binding_right", "<super> KEY_RIGHT | swipe left 4");
        auto binding_up    = section->get_option("binding_up",    "<super> KEY_UP    | swipe down 4");
        auto binding_down  = section->get_option("binding_down",  "<super> KEY_DOWN  | swipe up 4");

        auto binding_win_left  = section->get_option("binding_win_left",  "<super> <shift> KEY_LEFT");
        auto binding_win_right = section->get_option("binding_win_right", "<super> <shift> KEY_RIGHT");
        auto binding_win_up    = section->get_option("binding_win_up",    "<super> <shift> KEY_UP");
        auto binding_win_down  = section->get_option("binding_win_down",  "<super> <shift> KEY_DOWN");

        output->add_activator(binding_left,  &callback_left);
        output->add_activator(binding_right, &callback_right);
        output->add_activator(binding_up,    &callback_up);
        output->add_activator(binding_down,  &callback_down);

        output->add_activator(binding_win_left,  &callback_win_left);
        output->add_activator(binding_win_right, &callback_win_right);
        output->add_activator(binding_win_up,    &callback_win_up);
        output->add_activator(binding_win_down,  &callback_win_down);

        animation_duration = section->get_option("duration", "180");
        duration = wf_duration(animation_duration);

        output->connect_signal("set-workspace-request", &on_set_workspace_request);
    }

    inline bool is_active()
    {
        return output->is_plugin_active(grab_interface->name);
    }

    void add_direction(int x, int y, wayfire_view view = nullptr)
    {
        if (!x && !y)
            return;

        if (!is_active())
            start_switch();

        if (view && view->role != WF_VIEW_ROLE_TOPLEVEL)
            view = nullptr;

        if (view && !grabbed_view)
            grabbed_view = view;

        /* Make sure that when we add this direction, we won't go outside
         * of the workspace grid */
        GetTuple(vx, vy, output->workspace->get_current_workspace());
        GetTuple(vw, vh, output->workspace->get_workspace_grid_size());
        int tvx = clamp(vx + dx.end + x, 0, vw - 1);
        int tvy = clamp(vy + dy.end + y, 0, vh - 1);

        dx = {duration.progress(dx), 1.0 * tvx - vx};
        dy = {duration.progress(dy), 1.0 * tvy - vy};

        duration.start();
    }

    signal_callback_t on_set_workspace_request = [=] (signal_data *data)
    {
        if (is_active())
            return;

        auto ev = static_cast<change_viewport_signal*> (data);

        GetTuple(ox, oy, ev->old_viewport);
        GetTuple(vx, vy, ev->new_viewport);

        ev->carried_out = true;
        add_direction(vx - ox, vy - oy);
    };

    std::vector<wayfire_view> get_ws_views()
    {
        std::vector<wayfire_view> views;
        output->workspace->for_each_view([&](wayfire_view view)
        {
            if (view != grabbed_view)
                views.push_back(view);
        }, WF_MIDDLE_LAYERS);

        return views;
    }

    bool start_switch()
    {
        if (!output->activate_plugin(grab_interface))
            return false;

        output->render->add_effect(&update_animation, WF_OUTPUT_EFFECT_PRE);
        output->render->auto_redraw(true);

        duration.start();
        dx = dy = {0, 0};

        for (auto view : get_ws_views())
        {
            if (!view->get_transformer(vswitch_view_transformer::name))
            {
                view->add_transformer(
                    nonstd::make_unique<vswitch_view_transformer>(view),
                    vswitch_view_transformer::name);
            }
        }

        return true;
    }

    effect_hook_t update_animation = [=] ()
    {
        if (!duration.running())
            return stop_switch();

        GetTuple(sw, sh, output->get_screen_size());
        for (auto view : get_ws_views())
        {
            auto tr = dynamic_cast<vswitch_view_transformer*> (
                view->get_transformer(vswitch_view_transformer::name).get());

            view->damage();
            tr->translation_x = -duration.progress(dx) * sw;
            tr->translation_y = -duration.progress(dy) * sh;
            view->damage();
        }
    };

    void slide_done()
    {
        GetTuple(vx, vy, output->workspace->get_current_workspace());
        auto old_ws = output->workspace->get_current_workspace();

        vx += dx.end;
        vy += dy.end;

        auto output_g = output->get_relative_geometry();
        output->workspace->set_workspace(std::make_tuple(vx, vy));

        if (grabbed_view)
        {
            auto wm = grabbed_view->get_wm_geometry();
            grabbed_view->move(wm.x + dx.end * output_g.width,
                wm.y + dy.end * output_g.height);

            output->focus_view(grabbed_view);

            view_change_viewport_signal data;
            data.view = grabbed_view;
            data.from = old_ws;
            data.to = output->workspace->get_current_workspace();
            output->emit_signal("view-change-viewport", &data);
        }
    }

    void stop_switch()
    {
        slide_done();
        grabbed_view = nullptr;

        for (auto view : get_ws_views())
            view->pop_transformer(vswitch_view_transformer::name);

        output->deactivate_plugin(grab_interface);
        output->render->rem_effect(&update_animation, WF_OUTPUT_EFFECT_PRE);
        output->render->auto_redraw(false);
    }

    void fini()
    {
        if (!is_active())
            stop_switch();

        output->rem_binding(&callback_left);
        output->rem_binding(&callback_right);
        output->rem_binding(&callback_up);
        output->rem_binding(&callback_down);

        output->rem_binding(&callback_win_left);
        output->rem_binding(&callback_win_right);
        output->rem_binding(&callback_win_up);
        output->rem_binding(&callback_win_down);

        output->rem_binding(&gesture_cb);
        output->disconnect_signal("set-workspace-request",
            &on_set_workspace_request);
    }
};

extern "C"
{
    wayfire_plugin_t* newInstance()
    {
        return new vswitch();
    }
}
<|endoftext|>


<commit_before>#include "dirinfotask.h"

WARNINGS_DISABLE
#include <QAtomicInt>
#include <QCoreApplication>
#include <QStandardPaths>
WARNINGS_ENABLE

#include "basetask.h"

/** Info about a directory (used recursively). */
struct dirinfo
{
    /** Sum of file sizes. */
    quint64 size;
    /** Number of files. */
    quint64 count;
};

/* Forward declaration. */
struct dirinfo getDirInfo(const QDir dir, QAtomicInt *stop_p);

DirInfoTask::DirInfoTask(QDir dir) : BaseTask(), _dir(dir)
{
}

void DirInfoTask::run()
{
    struct dirinfo dirinfo = getDirInfo(_dir, &_stopRequested);
    emit           result(dirinfo.size, dirinfo.count);

    // We're finished.
    emit dequeue();
}

void DirInfoTask::stop()
{
    _stopRequested = 1;
}

struct dirinfo getDirInfo(QDir dir, QAtomicInt *stop_p)
{
    struct dirinfo dirinfo = {0, 0};

    // Bail if requested.
    if(static_cast<int>(*stop_p) == 1)
        return dirinfo;

    if(dir.exists())
    {
        // We want to see all directories and files, no symlinks,
        // and no . and .. directories.
        dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot
                      | QDir::Hidden | QDir::NoSymLinks);

        // For each directory item...
        QFileInfoList list = dir.entryInfoList();
        for(int i = 0; i < list.size(); ++i)
        {
            QFileInfo fileInfo = list.at(i);
            if(fileInfo.isDir())
            {
                // ... if it's a dir, recursively get info about that dir.
                struct dirinfo d =
                    getDirInfo(fileInfo.absoluteFilePath(), stop_p);
                dirinfo.size += d.size;
                dirinfo.count += d.count;
            }
            else
            {
                // ... if it's a file, add its info to the total.
                dirinfo.size += static_cast<quint64>(fileInfo.size());
                dirinfo.count++;
            }
        }
    }
    return dirinfo;
}
<commit_msg>DirInfoTask: emit canceled()<commit_after>#include "dirinfotask.h"

WARNINGS_DISABLE
#include <QAtomicInt>
#include <QCoreApplication>
#include <QStandardPaths>
WARNINGS_ENABLE

#include "basetask.h"

/** Info about a directory (used recursively). */
struct dirinfo
{
    /** Sum of file sizes. */
    quint64 size;
    /** Number of files. */
    quint64 count;
};

/* Forward declaration. */
struct dirinfo getDirInfo(const QDir dir, QAtomicInt *stop_p);

DirInfoTask::DirInfoTask(QDir dir) : BaseTask(), _dir(dir)
{
}

void DirInfoTask::run()
{
    struct dirinfo dirinfo = getDirInfo(_dir, &_stopRequested);

    // Send appropriate notification.
    if(static_cast<int>(_stopRequested) == 1)
        emit canceled();
    else
        emit result(dirinfo.size, dirinfo.count);

    // We're finished.
    emit dequeue();
}

void DirInfoTask::stop()
{
    _stopRequested = 1;
}

struct dirinfo getDirInfo(QDir dir, QAtomicInt *stop_p)
{
    struct dirinfo dirinfo = {0, 0};

    // Bail if requested.
    if(static_cast<int>(*stop_p) == 1)
        return dirinfo;

    if(dir.exists())
    {
        // We want to see all directories and files, no symlinks,
        // and no . and .. directories.
        dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot
                      | QDir::Hidden | QDir::NoSymLinks);

        // For each directory item...
        QFileInfoList list = dir.entryInfoList();
        for(int i = 0; i < list.size(); ++i)
        {
            QFileInfo fileInfo = list.at(i);
            if(fileInfo.isDir())
            {
                // ... if it's a dir, recursively get info about that dir.
                struct dirinfo d =
                    getDirInfo(fileInfo.absoluteFilePath(), stop_p);
                dirinfo.size += d.size;
                dirinfo.count += d.count;
            }
            else
            {
                // ... if it's a file, add its info to the total.
                dirinfo.size += static_cast<quint64>(fileInfo.size());
                dirinfo.count++;
            }
        }
    }
    return dirinfo;
}
<|endoftext|>