<commit_before>/*
    Copyright (C) <2010>  <Frank Scheffold (fscheffold@googlemail.com)>

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

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

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*/

/**
  @author: Frank Scheffold
*/

#include "kremotecontroldaemon.h"
#include "krcdadaptor.h"

#include <kdelirc/libkremotecontrol/dbusinterface.h>
#include <kdelirc/libkremotecontrol/mode.h>
#include <kdelirc/libkremotecontrol/action.h>
#include <kdelirc/libkremotecontrol/executionengine.h>
#include <kdelirc/libkremotecontrol/remotelist.h>

#include <KCModuleInfo>
#include <KDebug>
#include <KNotification>
#include <KAboutData>
#include <KIconLoader>
#include <KToolInvocation>

#include<QPixmap>
// #include <QErrorMessage>

using namespace Solid::Control;

K_PLUGIN_FACTORY(KRemoteControlDaemonFactory, registerPlugin<KRemoteControlDaemon>();)
K_EXPORT_PLUGIN(KRemoteControlDaemonFactory("kremotecontroldaemon"))

class KRemoteControlDaemonPrivate
{
  private:
      KRemoteControlDaemon *m_parent;
      RemoteList m_remoteList;
      QStringList m_ignoreNextButtonList;

  public:

      KComponentData applicationData;

      KRemoteControlDaemonPrivate(KRemoteControlDaemon *parent) {
          m_parent = parent;
      };

      ~KRemoteControlDaemonPrivate() {
      };

      RemoteList remoteList(){
          return m_remoteList;
      };

      void reload(){
          m_remoteList.loadFromConfig("kremotecontrolrc");
          KConfig config("kremotecontrolrc");
          KConfigGroup globalGroup(&config, "Global");
          if(globalGroup.readEntry("ShowTrayIcon", true)){
              kDebug() << "starting notifier item" <<
              KToolInvocation::kdeinitExec("krcdnotifieritem");
          } else {
              emit m_parent->unloadTray();
          }
      };

      Remote* getRemote(const QString& remoteName) {
          return m_remoteList.getRemote(remoteName);
      };

      bool isButtonEventIgnored(const QString &remote){
          return m_ignoreNextButtonList.contains(remote);
      };

      void ignoreButtonEvents(const QString& remote){
          kDebug() << "muting remote" << remote;
          m_ignoreNextButtonList.append(remote);
          m_ignoreNextButtonList.removeDuplicates();
      }

      void considerButtonEvents(const QString& remote){
          kDebug() << "unmuting remote" << remote;
          m_ignoreNextButtonList.removeAll(remote);
      }

      void clearIgnore(){
          m_remoteList.clear();
      }
};

KRemoteControlDaemon::KRemoteControlDaemon(QObject* parent, const QVariantList& ): KDEDModule(parent), d_ptr(new KRemoteControlDaemonPrivate(this)) {
    Q_D(KRemoteControlDaemon);
  //   QErrorMessage::qtHandler ()  ;
    //qInstallMsgHandler();
    new KrcdAdaptor(this);
    KAboutData aboutData("krcd", "krcd", ki18n("K Remote Control Daemon"),
                          "0.1", ki18n("Remote Control Daemon for KDE4"),
                          KAboutData::License_GPL, ki18n("(c) 2010 Frank Scheffold"),
                          KLocalizedString(), "http://www.kde.org");

    aboutData.addAuthor(ki18n("Michael Zanetti"), ki18n("Maintainer"), "michal_zanetti@gmx.net");
    aboutData.addAuthor(ki18n("Frank Scheffold"), ki18n("Developer"), "fscheffold@googlemail.com");
    aboutData.addAuthor(ki18n("Gav Wood"), ki18n("Original KDELirc Developer"), "gav.wood@kde.org");

    d->applicationData = KComponentData(aboutData);
    connect(RemoteControlManager::notifier(), SIGNAL(statusChanged(bool)), this, SLOT(slotStatusChanged(bool)));
    connect(RemoteControlManager::notifier(), SIGNAL(remoteControlAdded(const QString&)), this, SLOT(slotRemoteControlAdded(const QString&)));
    connect(RemoteControlManager::notifier(), SIGNAL(remoteControlRemoved(const QString&)), this, SLOT(slotRemoteControlRemoved(const QString&)));
    d_ptr->reload();
    foreach(const QString &remote, RemoteControl::allRemoteNames()){
        RemoteControl *rc = new RemoteControl(remote);
        kDebug() << "connecting to remote" << remote;
        connect(rc, SIGNAL(buttonPressed(const Solid::Control::RemoteControlButton &)),
                this,  SLOT(gotMessage(const Solid::Control::RemoteControlButton &)));
    }
}

KRemoteControlDaemon::~KRemoteControlDaemon() {
    emit unloadTray();
}

void KRemoteControlDaemon::slotStatusChanged(bool connected) {
    if(connected){
        foreach(const QString &remote, RemoteControl::allRemoteNames()){
            RemoteControl *rc = new RemoteControl(remote);
            kDebug() << "connecting to remote" << remote;
            connect(rc,
                    SIGNAL(buttonPressed(const Solid::Control::RemoteControlButton &)),
                    this,
                    SLOT(gotMessage(const Solid::Control::RemoteControlButton &)));
        }
    }
    emit connectionChanged(connected);
}

void KRemoteControlDaemon::gotMessage(const Solid::Control::RemoteControlButton& button) {
    kDebug()<< "Got message from remote " << button.remoteName() << " button " << button.name();
    Remote *remote=   d_ptr->getRemote(button.remoteName());
    if(! remote){
        kDebug()<< "No remote found for remote" << button.remoteName();;
        return;
    }
    if(d_ptr->isButtonEventIgnored(remote->name())){
        kDebug() << "Events for  "<< remote->name() <<    " are currently ignored";
        return;
    }
    emit(buttonPressed());
    //This is for debugging purposes, till we got our tray icon back
//    notifyEvent("" + remote->name() + ":
" + i18n("Button %1 pressed" , button.name()));
    if(remote->currentMode()){
        QList<Action*> actionList = remote->currentMode()->actionsForButton(button.name());
        if(remote->nextMode(button.name())){
            Mode *mode = remote->currentMode();
	    notifyModeChanged(remote);
            if(remote->currentMode()-> doAfter()){
                actionList.append(remote->currentMode()->actionsForButton(button.name()));
            }
            emit(modeChanged(remote->name(), mode->name()));
        }
        foreach(Action *action, actionList){
            ExecutionEngine::executeAction(action);
        }
    }
}

void KRemoteControlDaemon::reloadConfiguration() {
    d_ptr->reload();
    notifyEvent(i18n("Configuration reloaded."));
    foreach(const Remote *remote, d_ptr->remoteList()){
        emit modeChanged(remote->name(), remote->masterMode()->name());
    }
}

void KRemoteControlDaemon::changeMode(const QString& remoteName, Mode* mode) {
    Remote *remote=   d_ptr->getRemote(remoteName);
    if(remote && remote->allModes().contains(mode)){
        remote->setCurrentMode(mode);
    }
}

void KRemoteControlDaemon::ignoreButtonEvents(const QString& remoteName) {
  if(remoteName.isEmpty()){
        foreach(const Remote *remote, d_ptr->remoteList()){
            d_ptr->ignoreButtonEvents(remote->name());
        }
    }else{
    d_ptr->ignoreButtonEvents(remoteName);
    }
}

void KRemoteControlDaemon::considerButtonEvents(const QString& remoteName) {
  if(remoteName.isEmpty()){
        d_ptr->clearIgnore();
    }else{
        foreach(const Remote *remote, d_ptr->remoteList()){
            d_ptr->considerButtonEvents(remote->name());
        }
    }
}

void KRemoteControlDaemon::slotRemoteControlAdded(const QString& name) {
    if(d_ptr->getRemote(name)){
        kDebug() << "remote found";
        notifyEvent(i18n("The remote control %1 is now available.", name));
    }else{
        kDebug() << "remote not found";
        KNotification *notification = KNotification::event("global_event", i18n("An unconfigured remote control %1 is now available.", name),
                  DesktopIcon("infrared-remote"), 0, KNotification::Persistant, d_ptr->applicationData);
        notification->setActions(QStringList() << i18nc("Configure the remote", "Configure remote"));
        connect(notification, SIGNAL(activated(unsigned int)), SLOT(lauchKcmShell()));
    }
    emit remoteControlAdded(name);
}

void KRemoteControlDaemon::lauchKcmShell() {
  kDebug() << "Launch kcmshell";
   KToolInvocation::startServiceByDesktopName("kcm_lirc");
}

void KRemoteControlDaemon::slotRemoteControlRemoved(const QString& name) {
    notifyEvent(i18n("The remote %1 was removed from system.", name));
    emit remoteControlRemoved(name);
}

bool KRemoteControlDaemon::changeMode(const QString& remoteName, const QString& modeName) {
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
      foreach(Mode *mode, remote-> allModes()){
	if(mode->name() == modeName){
	  remote->setCurrentMode(mode);
	  notifyModeChanged(remote);
	  return true;
	}
      }
    }
    return false;
}

QStringList KRemoteControlDaemon::getModesForRemote(const QString& remoteName) {
    QStringList list;
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
        foreach(const Mode *mode, remote->allModes()){
            list << mode->name();
        }
    }
    return list;
}

QStringList KRemoteControlDaemon::getConfiguredRemotes() {
  QStringList list;
  foreach(Remote *remote, d_ptr->remoteList()){
    list << remote->name();
  }
  return list;
}

 void KRemoteControlDaemon::notifyModeChanged(Remote* remote) {
  KNotification::event("mode_event",
  "" + remote->name() + ":
" + i18n("Mode switched to %1" , remote->currentMode()->name()),
  DesktopIcon(remote->currentMode()->iconName().isEmpty() ? "infrared-remote" : remote->currentMode()->iconName()),
  0, KNotification::CloseOnTimeout, d_ptr->applicationData);
}

QString KRemoteControlDaemon::getCurrentMode(const QString& remoteName) {
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
      return remote->currentMode()->name();
    }
    return "modeNotFound";
}

QString KRemoteControlDaemon::getModeIcon(const QString &remoteName, const QString& modeName) {
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
        Mode *mode = remote->modeByName(modeName);
        if(mode){
            return mode->iconName();
        }
    }
    return "";
}

void KRemoteControlDaemon::notifyEvent(const QString& message, const QString& iconName, const QString& event) {
    KNotification::event(event, message, DesktopIcon(iconName), 0, KNotification::CloseOnTimeout, d_ptr->applicationData);
}

bool KRemoteControlDaemon::eventsIgnored(const QString& remoteName) {
  return d_ptr->isButtonEventIgnored(remoteName);
}
<commit_msg>always execute actions in Master mode<commit_after>/*
    Copyright (C) <2010>  <Frank Scheffold (fscheffold@googlemail.com)>

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

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

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*/

/**
  @author: Frank Scheffold
*/

#include "kremotecontroldaemon.h"
#include "krcdadaptor.h"

#include <kdelirc/libkremotecontrol/dbusinterface.h>
#include <kdelirc/libkremotecontrol/mode.h>
#include <kdelirc/libkremotecontrol/action.h>
#include <kdelirc/libkremotecontrol/executionengine.h>
#include <kdelirc/libkremotecontrol/remotelist.h>

#include <KCModuleInfo>
#include <KDebug>
#include <KNotification>
#include <KAboutData>
#include <KIconLoader>
#include <KToolInvocation>

#include<QPixmap>
// #include <QErrorMessage>

using namespace Solid::Control;

K_PLUGIN_FACTORY(KRemoteControlDaemonFactory, registerPlugin<KRemoteControlDaemon>();)
K_EXPORT_PLUGIN(KRemoteControlDaemonFactory("kremotecontroldaemon"))

class KRemoteControlDaemonPrivate
{
  private:
      KRemoteControlDaemon *m_parent;
      RemoteList m_remoteList;
      QStringList m_ignoreNextButtonList;

  public:

      KComponentData applicationData;

      KRemoteControlDaemonPrivate(KRemoteControlDaemon *parent) {
          m_parent = parent;
      };

      ~KRemoteControlDaemonPrivate() {
      };

      RemoteList remoteList(){
          return m_remoteList;
      };

      void reload(){
          m_remoteList.loadFromConfig("kremotecontrolrc");
          KConfig config("kremotecontrolrc");
          KConfigGroup globalGroup(&config, "Global");
          if(globalGroup.readEntry("ShowTrayIcon", true)){
              kDebug() << "starting notifier item" <<
              KToolInvocation::kdeinitExec("krcdnotifieritem");
          } else {
              emit m_parent->unloadTray();
          }
      };

      Remote* getRemote(const QString& remoteName) {
          return m_remoteList.getRemote(remoteName);
      };

      bool isButtonEventIgnored(const QString &remote){
          return m_ignoreNextButtonList.contains(remote);
      };

      void ignoreButtonEvents(const QString& remote){
          kDebug() << "muting remote" << remote;
          m_ignoreNextButtonList.append(remote);
          m_ignoreNextButtonList.removeDuplicates();
      }

      void considerButtonEvents(const QString& remote){
          kDebug() << "unmuting remote" << remote;
          m_ignoreNextButtonList.removeAll(remote);
      }

      void clearIgnore(){
          m_remoteList.clear();
      }
};

KRemoteControlDaemon::KRemoteControlDaemon(QObject* parent, const QVariantList& ): KDEDModule(parent), d_ptr(new KRemoteControlDaemonPrivate(this)) {
    Q_D(KRemoteControlDaemon);
  //   QErrorMessage::qtHandler ()  ;
    //qInstallMsgHandler();
    new KrcdAdaptor(this);
    KAboutData aboutData("krcd", "krcd", ki18n("K Remote Control Daemon"),
                          "0.1", ki18n("Remote Control Daemon for KDE4"),
                          KAboutData::License_GPL, ki18n("(c) 2010 Frank Scheffold"),
                          KLocalizedString(), "http://www.kde.org");

    aboutData.addAuthor(ki18n("Michael Zanetti"), ki18n("Maintainer"), "michal_zanetti@gmx.net");
    aboutData.addAuthor(ki18n("Frank Scheffold"), ki18n("Developer"), "fscheffold@googlemail.com");
    aboutData.addAuthor(ki18n("Gav Wood"), ki18n("Original KDELirc Developer"), "gav.wood@kde.org");

    d->applicationData = KComponentData(aboutData);
    connect(RemoteControlManager::notifier(), SIGNAL(statusChanged(bool)), this, SLOT(slotStatusChanged(bool)));
    connect(RemoteControlManager::notifier(), SIGNAL(remoteControlAdded(const QString&)), this, SLOT(slotRemoteControlAdded(const QString&)));
    connect(RemoteControlManager::notifier(), SIGNAL(remoteControlRemoved(const QString&)), this, SLOT(slotRemoteControlRemoved(const QString&)));
    d_ptr->reload();
    foreach(const QString &remote, RemoteControl::allRemoteNames()){
        RemoteControl *rc = new RemoteControl(remote);
        kDebug() << "connecting to remote" << remote;
        connect(rc, SIGNAL(buttonPressed(const Solid::Control::RemoteControlButton &)),
                this,  SLOT(gotMessage(const Solid::Control::RemoteControlButton &)));
    }
}

KRemoteControlDaemon::~KRemoteControlDaemon() {
    emit unloadTray();
}

void KRemoteControlDaemon::slotStatusChanged(bool connected) {
    if(connected){
        foreach(const QString &remote, RemoteControl::allRemoteNames()){
            RemoteControl *rc = new RemoteControl(remote);
            kDebug() << "connecting to remote" << remote;
            connect(rc,
                    SIGNAL(buttonPressed(const Solid::Control::RemoteControlButton &)),
                    this,
                    SLOT(gotMessage(const Solid::Control::RemoteControlButton &)));
        }
    }
    emit connectionChanged(connected);
}

void KRemoteControlDaemon::gotMessage(const Solid::Control::RemoteControlButton& button) {
    kDebug()<< "Got message from remote " << button.remoteName() << " button " << button.name();
    Remote *remote=   d_ptr->getRemote(button.remoteName());
    if(! remote){
        kDebug()<< "No remote found for remote" << button.remoteName();;
        return;
    }
    if(d_ptr->isButtonEventIgnored(remote->name())){
        kDebug() << "Events for  "<< remote->name() <<    " are currently ignored";
        return;
    }

    emit(buttonPressed());

    if(remote->currentMode()){
        QList<Action*> actionList = remote->masterMode()->actionsForButton(button.name());
        actionList.append(remote->currentMode()->actionsForButton(button.name()));
        if(remote->nextMode(button.name())){
            Mode *mode = remote->currentMode();
	    notifyModeChanged(remote);
            if(remote->currentMode()-> doAfter()){
                actionList.append(remote->currentMode()->actionsForButton(button.name()));
            }
            emit(modeChanged(remote->name(), mode->name()));
        }
        foreach(Action *action, actionList){
            ExecutionEngine::executeAction(action);
        }
    }
}

void KRemoteControlDaemon::reloadConfiguration() {
    d_ptr->reload();
    notifyEvent(i18n("Configuration reloaded."));
    foreach(const Remote *remote, d_ptr->remoteList()){
        emit modeChanged(remote->name(), remote->masterMode()->name());
    }
}

void KRemoteControlDaemon::changeMode(const QString& remoteName, Mode* mode) {
    Remote *remote=   d_ptr->getRemote(remoteName);
    if(remote && remote->allModes().contains(mode)){
        remote->setCurrentMode(mode);
    }
}

void KRemoteControlDaemon::ignoreButtonEvents(const QString& remoteName) {
  if(remoteName.isEmpty()){
        foreach(const Remote *remote, d_ptr->remoteList()){
            d_ptr->ignoreButtonEvents(remote->name());
        }
    }else{
    d_ptr->ignoreButtonEvents(remoteName);
    }
}

void KRemoteControlDaemon::considerButtonEvents(const QString& remoteName) {
  if(remoteName.isEmpty()){
        d_ptr->clearIgnore();
    }else{
        foreach(const Remote *remote, d_ptr->remoteList()){
            d_ptr->considerButtonEvents(remote->name());
        }
    }
}

void KRemoteControlDaemon::slotRemoteControlAdded(const QString& name) {
    if(d_ptr->getRemote(name)){
        kDebug() << "remote found";
        notifyEvent(i18n("The remote control %1 is now available.", name));
    }else{
        kDebug() << "remote not found";
        KNotification *notification = KNotification::event("global_event", i18n("An unconfigured remote control %1 is now available.", name),
                  DesktopIcon("infrared-remote"), 0, KNotification::Persistant, d_ptr->applicationData);
        notification->setActions(QStringList() << i18nc("Configure the remote", "Configure remote"));
        connect(notification, SIGNAL(activated(unsigned int)), SLOT(lauchKcmShell()));
    }
    emit remoteControlAdded(name);
}

void KRemoteControlDaemon::lauchKcmShell() {
  kDebug() << "Launch kcmshell";
   KToolInvocation::startServiceByDesktopName("kcm_lirc");
}

void KRemoteControlDaemon::slotRemoteControlRemoved(const QString& name) {
    notifyEvent(i18n("The remote %1 was removed from system.", name));
    emit remoteControlRemoved(name);
}

bool KRemoteControlDaemon::changeMode(const QString& remoteName, const QString& modeName) {
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
      foreach(Mode *mode, remote-> allModes()){
	if(mode->name() == modeName){
	  remote->setCurrentMode(mode);
	  notifyModeChanged(remote);
	  return true;
	}
      }
    }
    return false;
}

QStringList KRemoteControlDaemon::getModesForRemote(const QString& remoteName) {
    QStringList list;
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
        foreach(const Mode *mode, remote->allModes()){
            list << mode->name();
        }
    }
    return list;
}

QStringList KRemoteControlDaemon::getConfiguredRemotes() {
  QStringList list;
  foreach(Remote *remote, d_ptr->remoteList()){
    list << remote->name();
  }
  return list;
}

 void KRemoteControlDaemon::notifyModeChanged(Remote* remote) {
  KNotification::event("mode_event",
  "" + remote->name() + ":
" + i18n("Mode switched to %1" , remote->currentMode()->name()),
  DesktopIcon(remote->currentMode()->iconName().isEmpty() ? "infrared-remote" : remote->currentMode()->iconName()),
  0, KNotification::CloseOnTimeout, d_ptr->applicationData);
}

QString KRemoteControlDaemon::getCurrentMode(const QString& remoteName) {
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
      return remote->currentMode()->name();
    }
    return "modeNotFound";
}

QString KRemoteControlDaemon::getModeIcon(const QString &remoteName, const QString& modeName) {
    Remote *remote = d_ptr->remoteList().getRemote(remoteName);
    if(remote){
        Mode *mode = remote->modeByName(modeName);
        if(mode){
            return mode->iconName();
        }
    }
    return "";
}

void KRemoteControlDaemon::notifyEvent(const QString& message, const QString& iconName, const QString& event) {
    KNotification::event(event, message, DesktopIcon(iconName), 0, KNotification::CloseOnTimeout, d_ptr->applicationData);
}

bool KRemoteControlDaemon::eventsIgnored(const QString& remoteName) {
  return d_ptr->isButtonEventIgnored(remoteName);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 MIPS Technologies, Inc.
 * 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: Korey Sewell
 *
 */

#ifndef __CPU_INORDER_COMM_HH__
#define __CPU_INORDER_COMM_HH__

#include <vector>

#include "arch/faults.hh"
#include "arch/isa_traits.hh"
#include "base/types.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
#include "cpu/inorder/pipeline_traits.hh"
#include "cpu/inst_seq.hh"

/** Struct that defines the information passed from in between stages */
/** This information mainly goes forward through the pipeline. */
struct InterStageStruct {
    std::vector<ThePipeline::DynInstPtr> insts;
    bool squash;
    bool branchMispredict;
    bool branchTaken;
    uint64_t mispredPC;
    uint64_t nextPC;
    InstSeqNum squashedSeqNum;
    bool includeSquashInst;

    InterStageStruct()
        : squash(false),
          branchMispredict(false), branchTaken(false),
          mispredPC(0), nextPC(0),
          squashedSeqNum(0), includeSquashInst(false)
    { }

};

/** Turn This into a Class */
/** Struct that defines all backwards communication. */
struct TimeStruct {
    struct stageComm {
        bool squash;
        bool predIncorrect;
        uint64_t branchAddr;

        // @todo: Might want to package this kind of branch stuff into a single
        // struct as it is used pretty frequently.
        bool branchMispredict;
        bool branchTaken;
        Addr mispredPC;
        TheISA::PCState nextPC;

        unsigned branchCount;

        // Represents the instruction that has either been retired or
        // squashed.  Similar to having a single bus that broadcasts the
        // retired or squashed sequence number.
        InstSeqNum doneSeqNum;
        InstSeqNum bdelayDoneSeqNum;
        bool squashDelaySlot;

        //Just in case we want to do a commit/squash on a cycle
        //(necessary for multiple ROBs?)
        bool commitInsts;
        InstSeqNum squashSeqNum;

        // Communication specifically to the IQ to tell the IQ that it can
        // schedule a non-speculative instruction.
        InstSeqNum nonSpecSeqNum;

        bool uncached;
        ThePipeline::DynInstPtr uncachedLoad;

        bool interruptPending;
        bool clearInterrupt;
    };

    stageComm stageInfo[ThePipeline::NumStages][ThePipeline::MaxThreads];

    bool stageBlock[ThePipeline::NumStages][ThePipeline::MaxThreads];
    bool stageUnblock[ThePipeline::NumStages][ThePipeline::MaxThreads];
};

#endif //__CPU_INORDER_COMM_HH__
<commit_msg>inorder: cleanup intercomm. structs/squash info<commit_after>/*
 * Copyright (c) 2007 MIPS Technologies, Inc.
 * 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: Korey Sewell
 *
 */

#ifndef __CPU_INORDER_COMM_HH__
#define __CPU_INORDER_COMM_HH__

#include <vector>

#include "arch/faults.hh"
#include "arch/isa_traits.hh"
#include "base/types.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
#include "cpu/inorder/pipeline_traits.hh"
#include "cpu/inst_seq.hh"

/** Struct that defines the information passed from in between stages */
/** This information mainly goes forward through the pipeline. */
struct InterStageStruct {
    //@todo: probably should make this a list since the amount of
    //       instructions that get passed forward per cycle is
    //       really dependent on issue width, CPI, etc.
    std::vector<ThePipeline::DynInstPtr> insts;

    // Add any information that needs to be passed forward to stages
    // below ...
};

/** Struct that defines all backwards communication. */
struct TimeStruct {
    struct stageComm {
        bool squash;
        InstSeqNum doneSeqNum;

        bool uncached;
        ThePipeline::DynInstPtr uncachedLoad;
    };

    stageComm stageInfo[ThePipeline::NumStages][ThePipeline::MaxThreads];

    bool stageBlock[ThePipeline::NumStages][ThePipeline::MaxThreads];
    bool stageUnblock[ThePipeline::NumStages][ThePipeline::MaxThreads];
};

#endif //__CPU_INORDER_COMM_HH__
<|endoftext|>


<commit_before>#include "rdb_protocol/op.hpp"
#include "rdb_protocol/term.hpp"
#include "rdb_protocol/terms/terms.hpp"

namespace ql {

class sample_term_t : public op_term_t {
public:
    sample_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
    counted_t<val_t> eval_impl() {
        int num_int = arg(1)->as_int();
        rcheck(num_int >= 0,
               strprintf("Number of items to sample must be non-negative, got `%d`.", num_int));
        size_t num = num_int;
        counted_t<table_t> t;
        counted_t<datum_stream_t> seq;
        counted_t<val_t> v = arg(0);

        if (v->get_type().is_convertible(val_t::type_t::SELECTION)) {
            std::pair<counted_t<table_t>, counted_t<datum_stream_t> > t_seq
                = v->as_selection();
            t = t_seq.first;
            seq = t_seq.second;
        } else {
            seq = v->as_seq();
        }

        std::vector<counted_t<const datum_t> > result;
        int element_number = 0;
        while (counted_t<const datum_t> row = seq->next()) {
            element_number++;
            if (result.size() < num) {
                result.push_back(row);
            } else {
                /* We have a limitation on the size of arrays that makes
                 * sure they are less than the size of an integer. */
                size_t new_index = randint(element_number);
                if (new_index < num) {
                    result[new_index] = row;
                }
            }
        }

        rcheck(result.size() == num,
                strprintf("Trying to sample `%zu` elements from" \
                          "a sequence of size `%zu`.", num, result.size()));
        counted_t<datum_stream_t> new_ds(
                new array_datum_stream_t(env, make_counted<const datum_t>(result),
                                         backtrace()));

        return t.has() ? new_val(new_ds, t) : new_val(new_ds);
    }
    bool is_deterministic_impl() const {
        return false;
    }
    virtual const char *name() const { return "sample"; }
};

counted_t<term_t> make_sample_term(env_t *env, protob_t<const Term> term) {
    return counted_t<sample_term_t>(new sample_term_t(env, term));
}

} //namespace ql
<commit_msg>Adds shuffling to sample output.<commit_after>#include <algorithm>

#include "rdb_protocol/op.hpp"
#include "rdb_protocol/term.hpp"
#include "rdb_protocol/terms/terms.hpp"

namespace ql {

class sample_term_t : public op_term_t {
public:
    sample_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
    counted_t<val_t> eval_impl() {
        int num_int = arg(1)->as_int();
        rcheck(num_int >= 0,
               strprintf("Number of items to sample must be non-negative, got `%d`.", num_int));
        size_t num = num_int;
        counted_t<table_t> t;
        counted_t<datum_stream_t> seq;
        counted_t<val_t> v = arg(0);

        if (v->get_type().is_convertible(val_t::type_t::SELECTION)) {
            std::pair<counted_t<table_t>, counted_t<datum_stream_t> > t_seq
                = v->as_selection();
            t = t_seq.first;
            seq = t_seq.second;
        } else {
            seq = v->as_seq();
        }

        std::vector<counted_t<const datum_t> > result;
        int element_number = 0;
        while (counted_t<const datum_t> row = seq->next()) {
            element_number++;
            if (result.size() < num) {
                result.push_back(row);
            } else {
                /* We have a limitation on the size of arrays that makes
                 * sure they are less than the size of an integer. */
                size_t new_index = randint(element_number);
                if (new_index < num) {
                    result[new_index] = row;
                }
            }
        }

        std::random_shuffle(result.begin(), result.end());

        counted_t<datum_stream_t> new_ds(
                new array_datum_stream_t(env, make_counted<const datum_t>(result),
                                         backtrace()));

        return t.has() ? new_val(new_ds, t) : new_val(new_ds);
    }
    bool is_deterministic_impl() const {
        return false;
    }
    virtual const char *name() const { return "sample"; }
};

counted_t<term_t> make_sample_term(env_t *env, protob_t<const Term> term) {
    return counted_t<sample_term_t>(new sample_term_t(env, term));
}

} //namespace ql
<|endoftext|>


<commit_before>#ifndef _internal_hpp_INCLUDED
#define _internal_hpp_INCLUDED

#include <cassert>
#include <climits>
#include <cstdio>
#include <vector>

/*------------------------------------------------------------------------*/

using namespace std;

/*------------------------------------------------------------------------*/

#include "arena.hpp"
#include "avg.hpp"
#include "ema.hpp"
#include "flags.hpp"
#include "format.hpp"
#include "level.hpp"
#include "link.hpp"
#include "logging.hpp"
#include "options.hpp"
#include "profile.hpp"
#include "queue.hpp"
#include "stats.hpp"
#include "timer.hpp"
#include "watch.hpp"
#include "var.hpp"
#include "util.hpp"
#include "limit.hpp"
#include "inc.hpp"
#include "clause.hpp"

/*------------------------------------------------------------------------*/

namespace CaDiCaL {

class Proof;
class File;

class Internal {

  friend class Solver;

  friend class Arena;
  friend struct Logger;
  friend struct Message;
  friend class Parser;
  friend class Proof;
  friend struct Stats;

  friend struct bumped_earlier;
  friend struct trail_bumped_smaller;
  friend struct trail_smaller;

  /*----------------------------------------------------------------------*/

  // The actual state of the solver is in this section.

  bool unsat;                   // empty clause found or learned
  bool iterating;               // report learned unit (iteration)
  bool clashing;                // found clashing units in 'parse_dimacs'
  size_t vsize;                 // actually allocated variable data size
  int max_var;                  // maximum variable index
  int level;                    // decision level ('control.size () - 1')
  signed char * vals;           // assignment       [-max_var,max_var]
  signed char * solution;       // for debugging    [-max_var,max_var]
  signed char * marks;          // signed marks     [1,max_var]
  signed char * phases;         // saved assignment [1,max_var]
  Var * vtab;                   // variable table
  Link * ltab;                  // table of links for decision queue
  Flags * ftab;                 // seen, poison, minimized flags table
  long * btab;                  // enqueue time stamps for queue
  Queue queue;                  // variable move to front decision queue
  Watches * wtab;               // table of watches for all literals
  Clause * conflict;            // set in 'propagation', reset in 'analyze'
  size_t propagated;            // next trail position to propagate
  vector<int> trail;            // assigned literals
  vector<int> clause;           // temporary in parsing & learning
  vector<int> levels;           // decision levels in learned clause
  vector<int> analyzed;         // analyzed literals in 'analyze'
  vector<int> minimized;        // removable or poison in 'minimize'
  vector<Level> control;        // 'level + 1 == control.size ()'
  vector<Clause*> clauses;      // ordered collection of all clauses
  vector<Clause*> resolved;     // large clauses in 'analyze'
  EMA fast_glue_avg;            // fast glue average
  EMA slow_glue_avg;            // slow glue average
  EMA restartint;               // actual restart interval average
  EMA restarteff;               // restart effectiveness average
  EMA size_avg;                 // learned clause size average
  EMA jump_avg;                 // jump average
  Limit lim;                    // limits for various phases
  Inc inc;                      // limit increments
  Proof * proof;                // trace clausal proof if non zero
  Options opts;                 // run-time options
  Stats stats;                  // statistics
  vector<int> original;         // original CNF for debugging
  vector<Timer> timers;         // active timers for profiling functions
  Profiles profiles;            // global profiled time for functions
  Arena arena;                  // memory arena for moving garbage collector
  Format error;                 // last (persistent) error message
  Internal * internal;          // proxy to 'this' in macros (redundant)

  /*----------------------------------------------------------------------*/

  // Internal delegates and helpers for corresponding functions in 'Solver'.
  //
  void resize_queue (int new_max_var);
  void resize (int new_max_var);
  void add_original_lit (int lit);

  // Enlarge tables.
  //
  void enlarge_vals (int new_vsize);
  void enlarge (int new_max_var);

  // Functions for monitoring resources.
  //
  size_t vector_bytes ();
  void inc_bytes (size_t);
  void dec_bytes (size_t);

  double seconds ();
  size_t max_bytes ();
  size_t current_bytes ();

  int active_variables () const { return max_var - stats.fixed; }

  // Regularly reports what is going on in 'report.cpp'.
  //
  void report (char type, bool verbose = false);

  // Unsigned literals (abs) with checks.
  //
  int vidx (int lit) const {
    int idx;
    assert (lit), assert (lit != INT_MIN);
    idx = abs (lit);
    assert (idx <= max_var);
    return idx;
  }

  // Unsigned version with LSB denoting sign.  This is used in indexing arrays
  // by literals.  The idea is to keep the elements in such an array for both
  // the positive and negated version of a literal close together.
  //
  unsigned vlit (int lit) { return (lit < 0) + 2u * (unsigned) vidx (lit); }

  // Helper functions to access variable and literal data.
  //
  Var & var (int lit)         { return vtab[vidx (lit)]; }
  Link & link (int lit)       { return ltab[vidx (lit)]; }
  Flags & flags (int lit)     { return ftab[vidx (lit)]; }

  const Flags & flags (int lit) const { return ftab[vidx (lit)]; }

  Watches & watches (int lit) { return wtab[vlit (lit)]; }

  // Marking variables with a sign (positive or negative).
  //
  signed char marked (int lit) const {
    signed char res = marks [ vidx (lit) ];
    if (lit < 0) res = -res;
    return res;
  }
  void mark (int lit) {
    assert (!marked (lit));
    marks[vidx (lit)] = sign (lit);
  }
  void unmark (int lit) { marks [ vidx (lit) ] = 0; }

  void mark_clause ();          // mark 'this->clause'
  void unmark_clause ();        // unmark 'this->clause'

  void mark (Clause *);
  void unmark (Clause *);

  // Watch literal 'lit' in clause with blocking literal 'blit'.
  // Inlined here, since it occurs in the tight inner loop of 'propagate'.
  //
  inline void watch_literal (int lit, int blit, Clause * c, int size) {
    Watches & ws = watches (lit);
    ws.push_back (Watch (blit, c, size));
    LOG (c, "watch %d blit %d in", lit, blit);
  }

  void unwatch_literal (int lit, Clause * c);
  void update_size_watch (int lit, Clause * c, int new_size);

  // Update queue to point to last potentially still unassigned variable.
  // All variables after 'queue.unassigned' in bump order are assumed to be
  // assigned.  Then update the 'queue.bumped' field and log it.  This is
  // inlined here since it occurs in several inner loops.
  //
  inline void update_queue_unassigned (int idx) {
    assert (0 < idx), assert (idx <= max_var);
    queue.unassigned = idx;
    queue.bumped = btab[idx];
    LOG ("queue unassigned now %d bumped %ld", idx, btab[idx]);
  }

  // Managing clauses in 'clause.cpp'.  Without explicit 'Clause' argument
  // these functions work on the global temporary 'clause'.
  //
  void watch_clause (Clause *);
  size_t bytes_clause (int size);
  Clause * new_clause (bool red, int glue = 0);
  void deallocate_clause (Clause *);
  void delete_clause (Clause *);
  bool tautological_clause ();
  void add_new_original_clause ();
  Clause * new_learned_clause (int glue);

  // We want to eagerly update statistics as soon clauses are marked
  // garbage.  Otherwise 'report' for instance gives wrong numbers after
  // 'subsume' before the next 'reduce'.  Thus we factored out marking and
  // accounting for garbage clauses.  Note that we do not update allocated
  // bytes statistics at this point, but wait until the next 'collect'.
  //
  void mark_garbage (Clause * c) {
    assert (!c->garbage);
    if (c->redundant) assert (stats.redundant), stats.redundant--;
    else assert (stats.irredundant), stats.irredundant--;
    c->garbage = true;
  }

  // Forward reasoning through propagation in 'propagate.cpp'.
  //
  void assign (int lit);                 // unit or decision
  void assign (int lit, Clause *);       // driving learned clause
  void assign (int lit, Clause *, int);  // inlined in 'propagate.cpp'
  bool propagate ();

  // Undo and restart in 'backtrack.cpp'.
  //
  void unassign (int lit);
  void backtrack (int target_level = 0);

  // Learning from conflicts in 'analyze.cc'.
  //
  void learn_empty_clause ();
  void learn_unit_clause (int lit);
  bool minimize_literal (int lit, int depth = 0);
  void minimize_clause ();
  bool shrink_literal (int lit, int depth = 0);
  void shrink_clause ();
  void bump_variable (int lit);
  void bump_variables ();
  void bump_resolved_clauses ();
  void resolve_clause (Clause *);
  void clear_seen ();
  void clear_levels ();
  void clear_minimized ();
  void analyze_literal (int lit, int & open);
  void analyze_reason (int lit, Clause *, int & open);
  void analyze ();
  void iterate ();       // for reporting learned unit clause

  // Restarting policy in 'restart.cc'.
  //
  bool restarting ();
  int reuse_trail ();
  void restart ();

  // Asynchronous terminating check.
  //
  bool terminating ();
  void terminate ();            // TODO: not implemented yet.

  // Reducing means determining useless clauses with 'reduce' in
  // 'reduce.cpp' as well as root level satisfied clause and then collecting
  // them with 'garbage_collection' in 'collect.cpp'.
  //
  bool reducing ();
  void protect_reasons ();
  void unprotect_reasons ();
  int clause_contains_fixed_literal (Clause *);
  void flush_falsified_literals (Clause *);
  void mark_satisfied_clauses_as_garbage ();
  void mark_useless_redundant_clauses_as_garbage ();
  void move_clause (Clause *);
  void move_non_garbage_clauses ();
  void delete_garbage_clauses ();
  void flush_watches ();
  void setup_watches ();
  void check_clause_stats ();
  void garbage_collection ();
  void reduce ();

  // Eager backward subsumption checking of learned clauses.
  //
  bool eagerly_subsume_last_learned (Clause *);
  void eagerly_subsume_last_learned ();

  // Regular forward subsumption checking.
  //
  bool subsuming ();
  void strengthen_clause (Clause *, int);
  void subsume_clause (Clause * subsuming, Clause * subsumed);
  int subsume_check (Clause * subsuming, Clause * subsumed);
  int subsume (Clause *, vector<Clause*> * occs);
  void subsume ();

  // Part on picking the next decision in 'decide.cpp'.
  //
  bool satisfied () const { return trail.size () == (size_t) max_var; }
  int next_decision_variable ();
  void decide ();

  // Main search functions in 'internal.cpp'.
  //
  int search ();                // CDCL loop
  void init_solving ();
  int solve ();

  // Built in profiling in 'profile.cpp'.
  //
  void start_profiling (Profile * p, double);
  void stop_profiling (Profile * p, double);

  void start_profiling (Profile * p) { start_profiling (p, seconds ()); }
  void stop_profiling (Profile * p) { stop_profiling (p, seconds ()); }

  void update_all_timers (double now);
  void print_profile (double now);

  // Checking solutions (see 'solution.cpp').
  //
  int sol (int lit) const;
  void check_clause ();

  void check (int (Internal::*assignment) (int) const);

  Internal ();
  ~Internal ();

  // Get the value of a literal: -1 = false, 0 = unassigned, 1 = true.
  //
  int val (int lit) const {
    assert (lit), assert (abs (lit) <= max_var);
    return vals[lit];
  }

  long & bumped (int lit) { return btab[vidx (lit)]; }

  // As 'val' but restricted to the root-level value of a literal.
  //
  int fixed (int lit) {
    int idx = vidx (lit), res = vals[idx];
    if (res && vtab[idx].level) res = 0;
    if (lit < 0) res = -res;
    return res;
  }

  // Parsing functions (handed over to 'parse.cpp').
  //
  const char * parse_dimacs (FILE *);
  const char * parse_dimacs (const char *);
  const char * parse_solution (const char *);

  // Enable and disable proof logging.
  void close_proof ();
  void new_proof (File *, bool owned = false);
};

struct trail_smaller {
  Internal * internal;
  trail_smaller (Internal * s) : internal (s) { }
  bool operator () (int a, int b) {
    return internal->var (a).trail < internal->var (b).trail;
  }
};

};

#endif
<commit_msg>another comment<commit_after>#ifndef _internal_hpp_INCLUDED
#define _internal_hpp_INCLUDED

#include <cassert>
#include <climits>
#include <cstdio>
#include <vector>

/*------------------------------------------------------------------------*/

using namespace std;

/*------------------------------------------------------------------------*/

#include "arena.hpp"
#include "avg.hpp"
#include "ema.hpp"
#include "flags.hpp"
#include "format.hpp"
#include "level.hpp"
#include "link.hpp"
#include "logging.hpp"
#include "options.hpp"
#include "profile.hpp"
#include "queue.hpp"
#include "stats.hpp"
#include "timer.hpp"
#include "watch.hpp"
#include "var.hpp"
#include "util.hpp"
#include "limit.hpp"
#include "inc.hpp"
#include "clause.hpp"

/*------------------------------------------------------------------------*/

namespace CaDiCaL {

class Proof;
class File;

class Internal {

  friend class Solver;

  friend class Arena;
  friend struct Logger;
  friend struct Message;
  friend class Parser;
  friend class Proof;
  friend struct Stats;

  friend struct bumped_earlier;
  friend struct trail_bumped_smaller;
  friend struct trail_smaller;

  /*----------------------------------------------------------------------*/

  // The actual state of the solver is in this section.

  bool unsat;                   // empty clause found or learned
  bool iterating;               // report learned unit (iteration)
  bool clashing;                // found clashing units in 'parse_dimacs'
  size_t vsize;                 // actually allocated variable data size
  int max_var;                  // maximum variable index
  int level;                    // decision level ('control.size () - 1')
  signed char * vals;           // assignment       [-max_var,max_var]
  signed char * solution;       // for debugging    [-max_var,max_var]
  signed char * marks;          // signed marks     [1,max_var]
  signed char * phases;         // saved assignment [1,max_var]
  Var * vtab;                   // variable table
  Link * ltab;                  // table of links for decision queue
  Flags * ftab;                 // seen, poison, minimized flags table
  long * btab;                  // enqueue time stamps for queue
  Queue queue;                  // variable move to front decision queue
  Watches * wtab;               // table of watches for all literals
  Clause * conflict;            // set in 'propagation', reset in 'analyze'
  size_t propagated;            // next trail position to propagate
  vector<int> trail;            // assigned literals
  vector<int> clause;           // temporary in parsing & learning
  vector<int> levels;           // decision levels in learned clause
  vector<int> analyzed;         // analyzed literals in 'analyze'
  vector<int> minimized;        // removable or poison in 'minimize'
  vector<Level> control;        // 'level + 1 == control.size ()'
  vector<Clause*> clauses;      // ordered collection of all clauses
  vector<Clause*> resolved;     // large clauses in 'analyze'
  EMA fast_glue_avg;            // fast glue average
  EMA slow_glue_avg;            // slow glue average
  EMA restartint;               // actual restart interval average
  EMA restarteff;               // restart effectiveness average
  EMA size_avg;                 // learned clause size average
  EMA jump_avg;                 // jump average
  Limit lim;                    // limits for various phases
  Inc inc;                      // limit increments
  Proof * proof;                // trace clausal proof if non zero
  Options opts;                 // run-time options
  Stats stats;                  // statistics
  vector<int> original;         // original CNF for debugging
  vector<Timer> timers;         // active timers for profiling functions
  Profiles profiles;            // global profiled time for functions
  Arena arena;                  // memory arena for moving garbage collector
  Format error;                 // last (persistent) error message
  Internal * internal;          // proxy to 'this' in macros (redundant)

  /*----------------------------------------------------------------------*/

  // Internal delegates and helpers for corresponding functions in 'Solver'.
  //
  void resize_queue (int new_max_var);
  void resize (int new_max_var);
  void add_original_lit (int lit);

  // Enlarge tables.
  //
  void enlarge_vals (int new_vsize);
  void enlarge (int new_max_var);

  // Functions for monitoring resources.
  //
  size_t vector_bytes ();
  void inc_bytes (size_t);
  void dec_bytes (size_t);

  double seconds ();
  size_t max_bytes ();
  size_t current_bytes ();

  int active_variables () const { return max_var - stats.fixed; }

  // Regularly reports what is going on in 'report.cpp'.
  //
  void report (char type, bool verbose = false);

  // Unsigned literals (abs) with checks.
  //
  int vidx (int lit) const {
    int idx;
    assert (lit), assert (lit != INT_MIN);
    idx = abs (lit);
    assert (idx <= max_var);
    return idx;
  }

  // Unsigned version with LSB denoting sign.  This is used in indexing arrays
  // by literals.  The idea is to keep the elements in such an array for both
  // the positive and negated version of a literal close together.
  //
  unsigned vlit (int lit) { return (lit < 0) + 2u * (unsigned) vidx (lit); }

  // Helper functions to access variable and literal data.
  //
  Var & var (int lit)         { return vtab[vidx (lit)]; }
  Link & link (int lit)       { return ltab[vidx (lit)]; }
  Flags & flags (int lit)     { return ftab[vidx (lit)]; }

  const Flags & flags (int lit) const { return ftab[vidx (lit)]; }

  Watches & watches (int lit) { return wtab[vlit (lit)]; }

  // Marking variables with a sign (positive or negative).
  //
  signed char marked (int lit) const {
    signed char res = marks [ vidx (lit) ];
    if (lit < 0) res = -res;
    return res;
  }
  void mark (int lit) {
    assert (!marked (lit));
    marks[vidx (lit)] = sign (lit);
  }
  void unmark (int lit) { marks [ vidx (lit) ] = 0; }

  void mark_clause ();          // mark 'this->clause'
  void unmark_clause ();        // unmark 'this->clause'

  void mark (Clause *);
  void unmark (Clause *);

  // Watch literal 'lit' in clause with blocking literal 'blit'.
  // Inlined here, since it occurs in the tight inner loop of 'propagate'.
  //
  inline void watch_literal (int lit, int blit, Clause * c, int size) {
    Watches & ws = watches (lit);
    ws.push_back (Watch (blit, c, size));
    LOG (c, "watch %d blit %d in", lit, blit);
  }

  void unwatch_literal (int lit, Clause * c);
  void update_size_watch (int lit, Clause * c, int new_size);

  // Update queue to point to last potentially still unassigned variable.
  // All variables after 'queue.unassigned' in bump order are assumed to be
  // assigned.  Then update the 'queue.bumped' field and log it.  This is
  // inlined here since it occurs in several inner loops.
  //
  inline void update_queue_unassigned (int idx) {
    assert (0 < idx), assert (idx <= max_var);
    queue.unassigned = idx;
    queue.bumped = btab[idx];
    LOG ("queue unassigned now %d bumped %ld", idx, btab[idx]);
  }

  // Managing clauses in 'clause.cpp'.  Without explicit 'Clause' argument
  // these functions work on the global temporary 'clause'.
  //
  void watch_clause (Clause *);
  size_t bytes_clause (int size);
  Clause * new_clause (bool red, int glue = 0);
  void deallocate_clause (Clause *);
  void delete_clause (Clause *);
  bool tautological_clause ();
  void add_new_original_clause ();
  Clause * new_learned_clause (int glue);

  // We want to eagerly update statistics as soon clauses are marked
  // garbage.  Otherwise 'report' for instance gives wrong numbers after
  // 'subsume' before the next 'reduce'.  Thus we factored out marking and
  // accounting for garbage clauses.  Note that we do not update allocated
  // bytes statistics at this point, but wait until the next 'collect'.
  // In order not to miss any update to those statistics we call
  // 'check_clause_stats' after garbage collection in debugging mode.
  //
  void mark_garbage (Clause * c) {
    assert (!c->garbage);
    if (c->redundant) assert (stats.redundant), stats.redundant--;
    else assert (stats.irredundant), stats.irredundant--;
    c->garbage = true;
  }

  // Forward reasoning through propagation in 'propagate.cpp'.
  //
  void assign (int lit);                 // unit or decision
  void assign (int lit, Clause *);       // driving learned clause
  void assign (int lit, Clause *, int);  // inlined in 'propagate.cpp'
  bool propagate ();

  // Undo and restart in 'backtrack.cpp'.
  //
  void unassign (int lit);
  void backtrack (int target_level = 0);

  // Learning from conflicts in 'analyze.cc'.
  //
  void learn_empty_clause ();
  void learn_unit_clause (int lit);
  bool minimize_literal (int lit, int depth = 0);
  void minimize_clause ();
  bool shrink_literal (int lit, int depth = 0);
  void shrink_clause ();
  void bump_variable (int lit);
  void bump_variables ();
  void bump_resolved_clauses ();
  void resolve_clause (Clause *);
  void clear_seen ();
  void clear_levels ();
  void clear_minimized ();
  void analyze_literal (int lit, int & open);
  void analyze_reason (int lit, Clause *, int & open);
  void analyze ();
  void iterate ();       // for reporting learned unit clause

  // Restarting policy in 'restart.cc'.
  //
  bool restarting ();
  int reuse_trail ();
  void restart ();

  // Asynchronous terminating check.
  //
  bool terminating ();
  void terminate ();            // TODO: not implemented yet.

  // Reducing means determining useless clauses with 'reduce' in
  // 'reduce.cpp' as well as root level satisfied clause and then collecting
  // them with 'garbage_collection' in 'collect.cpp'.
  //
  bool reducing ();
  void protect_reasons ();
  void unprotect_reasons ();
  int clause_contains_fixed_literal (Clause *);
  void flush_falsified_literals (Clause *);
  void mark_satisfied_clauses_as_garbage ();
  void mark_useless_redundant_clauses_as_garbage ();
  void move_clause (Clause *);
  void move_non_garbage_clauses ();
  void delete_garbage_clauses ();
  void flush_watches ();
  void setup_watches ();
  void check_clause_stats ();
  void garbage_collection ();
  void reduce ();

  // Eager backward subsumption checking of learned clauses.
  //
  bool eagerly_subsume_last_learned (Clause *);
  void eagerly_subsume_last_learned ();

  // Regular forward subsumption checking.
  //
  bool subsuming ();
  void strengthen_clause (Clause *, int);
  void subsume_clause (Clause * subsuming, Clause * subsumed);
  int subsume_check (Clause * subsuming, Clause * subsumed);
  int subsume (Clause *, vector<Clause*> * occs);
  void subsume ();

  // Part on picking the next decision in 'decide.cpp'.
  //
  bool satisfied () const { return trail.size () == (size_t) max_var; }
  int next_decision_variable ();
  void decide ();

  // Main search functions in 'internal.cpp'.
  //
  int search ();                // CDCL loop
  void init_solving ();
  int solve ();

  // Built in profiling in 'profile.cpp'.
  //
  void start_profiling (Profile * p, double);
  void stop_profiling (Profile * p, double);

  void start_profiling (Profile * p) { start_profiling (p, seconds ()); }
  void stop_profiling (Profile * p) { stop_profiling (p, seconds ()); }

  void update_all_timers (double now);
  void print_profile (double now);

  // Checking solutions (see 'solution.cpp').
  //
  int sol (int lit) const;
  void check_clause ();

  void check (int (Internal::*assignment) (int) const);

  Internal ();
  ~Internal ();

  // Get the value of a literal: -1 = false, 0 = unassigned, 1 = true.
  //
  int val (int lit) const {
    assert (lit), assert (abs (lit) <= max_var);
    return vals[lit];
  }

  long & bumped (int lit) { return btab[vidx (lit)]; }

  // As 'val' but restricted to the root-level value of a literal.
  //
  int fixed (int lit) {
    int idx = vidx (lit), res = vals[idx];
    if (res && vtab[idx].level) res = 0;
    if (lit < 0) res = -res;
    return res;
  }

  // Parsing functions (handed over to 'parse.cpp').
  //
  const char * parse_dimacs (FILE *);
  const char * parse_dimacs (const char *);
  const char * parse_solution (const char *);

  // Enable and disable proof logging.
  void close_proof ();
  void new_proof (File *, bool owned = false);
};

struct trail_smaller {
  Internal * internal;
  trail_smaller (Internal * s) : internal (s) { }
  bool operator () (int a, int b) {
    return internal->var (a).trail < internal->var (b).trail;
  }
};

};

#endif
<|endoftext|>


<commit_before><commit_msg>dom_operations to use WebAnimationController<commit_after><|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Razer Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "DriverLoader.h"
#include "InterfaceTraits.h"
#include "SearchPathExtender.h"

// Library/third-party includes
#include <osvr/Util/PlatformConfig.h>

// Standard includes
#include <iostream>

#if defined(OSVR_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#define NO_MINMAX
#include <windows.h>
#elif defined(OSVR_LINUX) || defined(OSVR_MACOSX)
#include <dlfcn.h>
#endif

namespace osvr {
namespace vive {

    static const auto ENTRY_POINT_FUNCTION_NAME = "HmdDriverFactory";

    struct DriverLoader::Impl {
/// Platform-specific handle to dynamic library
#if defined(OSVR_WINDOWS)
        HMODULE driver_ = nullptr;
#elif defined(OSVR_MACOSX) || defined(OSVR_LINUX)
        void *driver_ = nullptr;
#endif

        /// Destructor: should contain platform-specific code to unload dynamic
        /// library.
        ~Impl() {
#if defined(OSVR_WINDOWS)
            if (driver_) {
                FreeLibrary(driver_);
            }
#elif defined(OSVR_MACOSX) || defined(OSVR_LINUX)
            if (driver_) {
                dlclose(driver_);
            }
#endif
        }
    };

    /// Constructor should contain platform-specific code to load dynamic
    /// library to populate handle in pimpl struct and extract the entry point
    /// function pointer.
    DriverLoader::DriverLoader(std::string const &driverRoot,
                               std::string const &driverFile)
        : impl_(new Impl) {
        /// Set the PATH to include the driver directory so it can
        /// find its deps.
        SearchPathExtender extender(driverRoot);
#if defined(OSVR_WINDOWS)
        impl_->driver_ = LoadLibraryA(driverFile.c_str());
        if (!impl_->driver_) {
            reset();
            throw CouldNotLoadDriverModule();
        }

        auto proc = GetProcAddress(impl_->driver_, ENTRY_POINT_FUNCTION_NAME);
        if (!proc) {
            reset();
            throw CouldNotLoadEntryPoint();
        }
        factory_ = reinterpret_cast<DriverFactory>(proc);
#elif defined(OSVR_LINUX) || defined(OSVR_MACOSX)
        impl_->driver_ = dlopen(driverFile.c_str());
        if (!impl_->driver_) {
            reset();
            throw CouldNotLoadDriverModule(dlerror());
        }

        auto proc = dlsym(impl_->driver_, ENTRY_POINT_FUNCTION_NAME);
        if (!proc) {
            reset();
            throw CouldNotLoadEntryPoint(dlerror());
        }
        factory_ = reinterpret_cast<DriverFactory>(proc);                                                                       \
#endif
    }

    std::unique_ptr<DriverLoader>
    DriverLoader::make(std::string const &driverRoot,
                       std::string const &driverFile) {
        std::unique_ptr<DriverLoader> ret(
            new DriverLoader(driverRoot, driverFile));
        return ret;
    }

    DriverLoader::~DriverLoader() { reset(); }

    DriverLoader::operator bool() const {
        /// Presence of a valid private impl object is equivalent to validity of
        /// the object overall.
        return static_cast<bool>(impl_);
    }

    bool DriverLoader::isHMDPresent(std::string const &userConfigDir) const {
        auto ret = getInterface<vr::IClientTrackedDeviceProvider>();
        if (ret.first) {
            // std::cout << "Successfully got the
            // IClientTrackedDeviceProvider!";
            auto clientProvider = ret.first;
            auto isPresent =
                clientProvider->BIsHmdPresent(userConfigDir.c_str());
            // std::cout << " is present? " << std::boolalpha << isPresent
            //          << std::endl;
            return isPresent;
        }
        // std::cout << "Couldn't get it, error code " << ret.second <<
        // std::endl;
        return false;
    }

    void DriverLoader::reset() {
        if (cleanup_) {
#if 0
            std::cout << "osvr::vive::DriverLoader::reset() - cleaning "
                         "up main provider"
                      << std::endl;
#endif
            cleanup_();
            cleanup_ = std::function<void()>{};
        }
        if (impl_) {
#if 0
            std::cout << "osvr::vive::DriverLoader::reset() - unloading driver"
                      << std::endl;
#endif
            impl_.reset();
        }
    }
} // namespace vive
} // namespace osvr
<commit_msg>Fix invalid dlopen() call. Use RTLD_NOW, so it will return error on opening, if there is unresolved symbols. Use RTLD_GLOBAL, so other libraries can access the driver, if it need<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Razer Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "DriverLoader.h"
#include "InterfaceTraits.h"
#include "SearchPathExtender.h"

// Library/third-party includes
#include <osvr/Util/PlatformConfig.h>

// Standard includes
#include <iostream>

#if defined(OSVR_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#define NO_MINMAX
#include <windows.h>
#elif defined(OSVR_LINUX) || defined(OSVR_MACOSX)
#include <dlfcn.h>
#endif

namespace osvr {
namespace vive {

    static const auto ENTRY_POINT_FUNCTION_NAME = "HmdDriverFactory";

    struct DriverLoader::Impl {
/// Platform-specific handle to dynamic library
#if defined(OSVR_WINDOWS)
        HMODULE driver_ = nullptr;
#elif defined(OSVR_MACOSX) || defined(OSVR_LINUX)
        void *driver_ = nullptr;
#endif

        /// Destructor: should contain platform-specific code to unload dynamic
        /// library.
        ~Impl() {
#if defined(OSVR_WINDOWS)
            if (driver_) {
                FreeLibrary(driver_);
            }
#elif defined(OSVR_MACOSX) || defined(OSVR_LINUX)
            if (driver_) {
                dlclose(driver_);
            }
#endif
        }
    };

    /// Constructor should contain platform-specific code to load dynamic
    /// library to populate handle in pimpl struct and extract the entry point
    /// function pointer.
    DriverLoader::DriverLoader(std::string const &driverRoot,
                               std::string const &driverFile)
        : impl_(new Impl) {
        /// Set the PATH to include the driver directory so it can
        /// find its deps.
        SearchPathExtender extender(driverRoot);
#if defined(OSVR_WINDOWS)
        impl_->driver_ = LoadLibraryA(driverFile.c_str());
        if (!impl_->driver_) {
            reset();
            throw CouldNotLoadDriverModule();
        }

        auto proc = GetProcAddress(impl_->driver_, ENTRY_POINT_FUNCTION_NAME);
        if (!proc) {
            reset();
            throw CouldNotLoadEntryPoint();
        }
        factory_ = reinterpret_cast<DriverFactory>(proc);
#elif defined(OSVR_LINUX) || defined(OSVR_MACOSX)
        impl_->driver_ = dlopen(driverFile.c_str(), RTLD_NOW | RTLD_GLOBAL);
        if (!impl_->driver_) {
            reset();
            throw CouldNotLoadDriverModule(dlerror());
        }

        auto proc = dlsym(impl_->driver_, ENTRY_POINT_FUNCTION_NAME);
        if (!proc) {
            reset();
            throw CouldNotLoadEntryPoint(dlerror());
        }
        factory_ = reinterpret_cast<DriverFactory>(proc);                                                                       \
#endif
    }

    std::unique_ptr<DriverLoader>
    DriverLoader::make(std::string const &driverRoot,
                       std::string const &driverFile) {
        std::unique_ptr<DriverLoader> ret(
            new DriverLoader(driverRoot, driverFile));
        return ret;
    }

    DriverLoader::~DriverLoader() { reset(); }

    DriverLoader::operator bool() const {
        /// Presence of a valid private impl object is equivalent to validity of
        /// the object overall.
        return static_cast<bool>(impl_);
    }

    bool DriverLoader::isHMDPresent(std::string const &userConfigDir) const {
        auto ret = getInterface<vr::IClientTrackedDeviceProvider>();
        if (ret.first) {
            // std::cout << "Successfully got the
            // IClientTrackedDeviceProvider!";
            auto clientProvider = ret.first;
            auto isPresent =
                clientProvider->BIsHmdPresent(userConfigDir.c_str());
            // std::cout << " is present? " << std::boolalpha << isPresent
            //          << std::endl;
            return isPresent;
        }
        // std::cout << "Couldn't get it, error code " << ret.second <<
        // std::endl;
        return false;
    }

    void DriverLoader::reset() {
        if (cleanup_) {
#if 0
            std::cout << "osvr::vive::DriverLoader::reset() - cleaning "
                         "up main provider"
                      << std::endl;
#endif
            cleanup_();
            cleanup_ = std::function<void()>{};
        }
        if (impl_) {
#if 0
            std::cout << "osvr::vive::DriverLoader::reset() - unloading driver"
                      << std::endl;
#endif
            impl_.reset();
        }
    }
} // namespace vive
} // namespace osvr
<|endoftext|>


<commit_before>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
   Copyright (C) 2007 Mirko Stocker <me@misto.ch>
   Copyright (C) 2009 Dominik Haumann <dhaumann kde org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

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

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

//BEGIN Includes
#include "katefilebrowser.h"
#include "katefilebrowser.moc"

#include "katebookmarkhandler.h"

#include <ktexteditor/document.h>
#include <ktexteditor/view.h>

#include <KActionCollection>
#include <KActionMenu>
#include <KConfigGroup>
#include <KDebug>
#include <KDirOperator>
#include <KFilePlacesModel>
#include <KHistoryComboBox>
#include <KLocale>
#include <KToolBar>
#include <KUrlNavigator>
#include <QAbstractItemView>
#include <QDir>
#include <QLabel>
#include <QLineEdit>
#include <QToolButton>
#include <KMessageBox>

#include <kdeversion.h>

//END Includes

KateFileBrowser::KateFileBrowser(Kate::MainWindow *mainWindow,
                                 QWidget * parent, const char * name)
  : KVBox (parent)
  , m_mainWindow(mainWindow)
{
  setObjectName(name);

  m_toolbar = new KToolBar(this);
  m_toolbar->setMovable(false);
  m_toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
  m_toolbar->setContextMenuPolicy(Qt::NoContextMenu);

  // includes some actions, but not hooked into the shortcut dialog atm
  m_actionCollection = new KActionCollection(this);
  m_actionCollection->addAssociatedWidget(this);

  KFilePlacesModel* model = new KFilePlacesModel(this);
  m_urlNavigator = new KUrlNavigator(model, KUrl(QDir::homePath()), this);
  connect(m_urlNavigator, SIGNAL(urlChanged(KUrl)), SLOT(updateDirOperator(KUrl)));

  m_dirOperator = new KDirOperator(KUrl(), this);
  m_dirOperator->setView(KFile::/* Simple */Detail);
  m_dirOperator->view()->setSelectionMode(QAbstractItemView::ExtendedSelection);
  m_dirOperator->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));

#if KDE_IS_VERSION(4, 4, 60)
  // Mime filter for the KDirOperator
  QStringList filter;
  filter << "text/plain" << "text/html" << "inode/directory";
  m_dirOperator->setNewFileMenuSupportedMimeTypes(filter);
#endif

  setFocusProxy(m_dirOperator);
  connect(m_dirOperator, SIGNAL(viewChanged(QAbstractItemView*)),
          this, SLOT(selectorViewChanged(QAbstractItemView*)));
  connect(m_urlNavigator, SIGNAL(returnPressed()),
          m_dirOperator, SLOT(setFocus()));
  // now all actions exist in dir operator and we can use them in the toolbar
  setupActions();
  setupToolbar();

  KHBox* filterBox = new KHBox(this);

  QLabel* filterLabel = new QLabel(i18n("Filter:"), filterBox);
  m_filter = new KHistoryComboBox(true, filterBox);
  filterLabel->setBuddy(m_filter);
  m_filter->setMaxCount(10);
  m_filter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));

  connect(m_filter, SIGNAL(editTextChanged(QString)),
          SLOT(slotFilterChange(QString)));
  connect(m_filter, SIGNAL(returnPressed(QString)),
          m_filter, SLOT(addToHistory(QString)));
  connect(m_filter, SIGNAL(returnPressed(QString)),
          m_dirOperator, SLOT(setFocus()));

  connect(m_dirOperator, SIGNAL(urlEntered(KUrl)),
          this, SLOT(updateUrlNavigator(KUrl)));

  // Connect the bookmark handler
  connect(m_bookmarkHandler, SIGNAL(openUrl(QString)),
          this, SLOT(setDir(QString)));

  m_filter->setWhatsThis(i18n("Enter a name filter to limit which files are displayed."));

  connect(m_dirOperator, SIGNAL(fileSelected(KFileItem)), this, SLOT(fileSelected(KFileItem)));
  connect(m_mainWindow, SIGNAL(viewChanged()), this, SLOT(autoSyncFolder()));
}

KateFileBrowser::~KateFileBrowser()
{
}
//END Constroctor/Destrctor

//BEGIN Public Methods
void KateFileBrowser::setupToolbar()
{
  KConfigGroup config(KGlobal::config(), "filebrowser");
  QStringList actions = config.readEntry( "toolbar actions", QStringList() );
  if ( actions.isEmpty() ) // default toolbar
    actions << "back" << "forward" << "bookmarks" << "sync_dir" << "configure";

  // remove all actions from the toolbar (there should be none)
  m_toolbar->clear();

  // now add all actions to the toolbar
  foreach (const QString& it, actions)
  {
    QAction *ac = 0;
    if (it.isEmpty()) continue;
    if (it == "bookmarks" || it == "sync_dir" || it == "configure")
      ac = actionCollection()->action(it);
    else
      ac = m_dirOperator->actionCollection()->action(it);

    if (ac)
      m_toolbar->addAction(ac);
  }
}

void KateFileBrowser::readSessionConfig(KConfigBase *config, const QString & name)
{
  KConfigGroup cgDir(config, name + ":dir");
  m_dirOperator->readConfig(cgDir);
  m_dirOperator->setView(KFile::Default);

  KConfigGroup cg(config, name);
  m_urlNavigator->setLocationUrl(cg.readPathEntry("location", QDir::homePath()));
  setDir(cg.readPathEntry("location", QDir::homePath()));
  m_autoSyncFolder->setChecked(cg.readEntry("auto sync folder", false));
  m_filter->setHistoryItems(cg.readEntry("filter history", QStringList()), true);
}

void KateFileBrowser::writeSessionConfig(KConfigBase *config, const QString & name)
{
  KConfigGroup cgDir(config, name + ":dir");
  m_dirOperator->writeConfig(cgDir);

  KConfigGroup cg = KConfigGroup(config, name);
  cg.writePathEntry("location", m_urlNavigator->locationUrl().url());
  cg.writeEntry("auto sync folder", m_autoSyncFolder->isChecked());
  cg.writeEntry("filter history", m_filter->historyItems());
}

//END Public Methods

//BEGIN Public Slots

void KateFileBrowser::slotFilterChange(const QString & nf)
{
  QString f = nf.trimmed();
  const bool empty = f.isEmpty() || f == "*";

  if (empty) {
    m_dirOperator->clearFilter();
  } else {
    m_dirOperator->setNameFilter(f);
  }

  m_dirOperator->updateDir();
}

bool kateFileSelectorIsReadable (const KUrl& url)
{
  if (!url.isLocalFile())
    return true; // what else can we say?

  QDir dir(url.toLocalFile());
  return dir.exists ();
}

void KateFileBrowser::setDir(KUrl u)
{
  KUrl newurl;

  if (!u.isValid())
    newurl.setPath(QDir::homePath());
  else
    newurl = u;

  QString pathstr = newurl.path(KUrl::AddTrailingSlash);
  newurl.setPath(pathstr);

  if (!kateFileSelectorIsReadable (newurl))
    newurl.cd(QString::fromLatin1(".."));

  if (!kateFileSelectorIsReadable (newurl))
    newurl.setPath(QDir::homePath());

  m_dirOperator->setUrl(newurl, true);
}

//END Public Slots

//BEGIN Private Slots

void KateFileBrowser::fileSelected(const KFileItem & /*file*/)
{
  openSelectedFiles();
}

void KateFileBrowser::openSelectedFiles()
{
  const KFileItemList list = m_dirOperator->selectedItems();

  if (list.count()>20) {
    if (KMessageBox::questionYesNo(this,i18n("You are trying to open %1 files, are your sure?").arg(list.count()))
      == KMessageBox::No) return;
  }

  foreach (const KFileItem& item, list)
  {
    m_mainWindow->openUrl(item.url());
  }

  m_dirOperator->view()->selectionModel()->clear();
}

void KateFileBrowser::updateDirOperator(const KUrl& u)
{
  m_dirOperator->setUrl(u, true);
}

void KateFileBrowser::updateUrlNavigator(const KUrl& u)
{
  m_urlNavigator->setLocationUrl(u);
}

void KateFileBrowser::setActiveDocumentDir()
{
//   kDebug(13001)<<"KateFileBrowser::setActiveDocumentDir()";
  KUrl u = activeDocumentUrl();
//   kDebug(13001)<<"URL: "<<u.pathOrUrl();
  if (!u.isEmpty())
    setDir(u.upUrl());
//   kDebug(13001)<<"... setActiveDocumentDir() DONE!";
}

void KateFileBrowser::autoSyncFolder()
{
  if (m_autoSyncFolder->isChecked()) {
    setActiveDocumentDir();
  }
}

void KateFileBrowser::selectorViewChanged(QAbstractItemView * newView)
{
  newView->setSelectionMode(QAbstractItemView::ExtendedSelection);
}

//END Private Slots

//BEGIN Protected

KUrl KateFileBrowser::activeDocumentUrl()
{
  KTextEditor::View *v = m_mainWindow->activeView();
  if (v)
    return v->document()->url();
  return KUrl();
}

void KateFileBrowser::setupActions()
{
  // bookmarks action!
  KActionMenu *acmBookmarks = new KActionMenu(KIcon("bookmarks"), i18n("Bookmarks"), this);
  acmBookmarks->setDelayed(false);
  m_bookmarkHandler = new KateBookmarkHandler(this, acmBookmarks->menu());
  acmBookmarks->setShortcutContext(Qt::WidgetWithChildrenShortcut);

  // action for synchronizing the dir operator with the current document path
  KAction* syncFolder = new KAction(this);
  syncFolder->setShortcutContext(Qt::WidgetWithChildrenShortcut);
  syncFolder->setText(i18n("Current Document Folder"));
  syncFolder->setIcon(KIcon("system-switch-user"));
  connect(syncFolder, SIGNAL(triggered()), this, SLOT(setActiveDocumentDir()));

  m_actionCollection->addAction("sync_dir", syncFolder);
  m_actionCollection->addAction("bookmarks", acmBookmarks);

  // section for settings menu
  KActionMenu *optionsMenu = new KActionMenu(KIcon("configure"), i18n("Options"), this);
  optionsMenu->setDelayed(false);
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("short view"));
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("detailed view"));
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("tree view"));
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("detailed tree view"));
  optionsMenu->addSeparator();
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("show hidden"));

  // action for synchronising the dir operator with the current document path
  m_autoSyncFolder = new KAction(this);
  m_autoSyncFolder->setCheckable(true);
  m_autoSyncFolder->setText(i18n("Automatically synchronize with current document"));
  m_autoSyncFolder->setIcon(KIcon("system-switch-user"));
  connect(m_autoSyncFolder, SIGNAL(triggered()), this, SLOT(autoSyncFolder()));
  optionsMenu->addAction(m_autoSyncFolder);

  m_actionCollection->addAction("configure", optionsMenu);

  //
  // Remove all shortcuts due to shortcut clashes (e.g. F5: reload, Ctrl+B: bookmark)
  // BUGS: #188954, #236368
  //
  foreach (QAction* a, m_actionCollection->actions()) {
    a->setShortcut(QKeySequence());
  }
  foreach (QAction* a, m_dirOperator->actionCollection()->actions()) {
    a->setShortcut(QKeySequence());
  }
}
//END Protected

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>i18n: properly use plural form and pass arguments to i18n*()<commit_after>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
   Copyright (C) 2007 Mirko Stocker <me@misto.ch>
   Copyright (C) 2009 Dominik Haumann <dhaumann kde org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

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

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

//BEGIN Includes
#include "katefilebrowser.h"
#include "katefilebrowser.moc"

#include "katebookmarkhandler.h"

#include <ktexteditor/document.h>
#include <ktexteditor/view.h>

#include <KActionCollection>
#include <KActionMenu>
#include <KConfigGroup>
#include <KDebug>
#include <KDirOperator>
#include <KFilePlacesModel>
#include <KHistoryComboBox>
#include <KLocale>
#include <KToolBar>
#include <KUrlNavigator>
#include <QAbstractItemView>
#include <QDir>
#include <QLabel>
#include <QLineEdit>
#include <QToolButton>
#include <KMessageBox>

#include <kdeversion.h>

//END Includes

KateFileBrowser::KateFileBrowser(Kate::MainWindow *mainWindow,
                                 QWidget * parent, const char * name)
  : KVBox (parent)
  , m_mainWindow(mainWindow)
{
  setObjectName(name);

  m_toolbar = new KToolBar(this);
  m_toolbar->setMovable(false);
  m_toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
  m_toolbar->setContextMenuPolicy(Qt::NoContextMenu);

  // includes some actions, but not hooked into the shortcut dialog atm
  m_actionCollection = new KActionCollection(this);
  m_actionCollection->addAssociatedWidget(this);

  KFilePlacesModel* model = new KFilePlacesModel(this);
  m_urlNavigator = new KUrlNavigator(model, KUrl(QDir::homePath()), this);
  connect(m_urlNavigator, SIGNAL(urlChanged(KUrl)), SLOT(updateDirOperator(KUrl)));

  m_dirOperator = new KDirOperator(KUrl(), this);
  m_dirOperator->setView(KFile::/* Simple */Detail);
  m_dirOperator->view()->setSelectionMode(QAbstractItemView::ExtendedSelection);
  m_dirOperator->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));

#if KDE_IS_VERSION(4, 4, 60)
  // Mime filter for the KDirOperator
  QStringList filter;
  filter << "text/plain" << "text/html" << "inode/directory";
  m_dirOperator->setNewFileMenuSupportedMimeTypes(filter);
#endif

  setFocusProxy(m_dirOperator);
  connect(m_dirOperator, SIGNAL(viewChanged(QAbstractItemView*)),
          this, SLOT(selectorViewChanged(QAbstractItemView*)));
  connect(m_urlNavigator, SIGNAL(returnPressed()),
          m_dirOperator, SLOT(setFocus()));
  // now all actions exist in dir operator and we can use them in the toolbar
  setupActions();
  setupToolbar();

  KHBox* filterBox = new KHBox(this);

  QLabel* filterLabel = new QLabel(i18n("Filter:"), filterBox);
  m_filter = new KHistoryComboBox(true, filterBox);
  filterLabel->setBuddy(m_filter);
  m_filter->setMaxCount(10);
  m_filter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));

  connect(m_filter, SIGNAL(editTextChanged(QString)),
          SLOT(slotFilterChange(QString)));
  connect(m_filter, SIGNAL(returnPressed(QString)),
          m_filter, SLOT(addToHistory(QString)));
  connect(m_filter, SIGNAL(returnPressed(QString)),
          m_dirOperator, SLOT(setFocus()));

  connect(m_dirOperator, SIGNAL(urlEntered(KUrl)),
          this, SLOT(updateUrlNavigator(KUrl)));

  // Connect the bookmark handler
  connect(m_bookmarkHandler, SIGNAL(openUrl(QString)),
          this, SLOT(setDir(QString)));

  m_filter->setWhatsThis(i18n("Enter a name filter to limit which files are displayed."));

  connect(m_dirOperator, SIGNAL(fileSelected(KFileItem)), this, SLOT(fileSelected(KFileItem)));
  connect(m_mainWindow, SIGNAL(viewChanged()), this, SLOT(autoSyncFolder()));
}

KateFileBrowser::~KateFileBrowser()
{
}
//END Constroctor/Destrctor

//BEGIN Public Methods
void KateFileBrowser::setupToolbar()
{
  KConfigGroup config(KGlobal::config(), "filebrowser");
  QStringList actions = config.readEntry( "toolbar actions", QStringList() );
  if ( actions.isEmpty() ) // default toolbar
    actions << "back" << "forward" << "bookmarks" << "sync_dir" << "configure";

  // remove all actions from the toolbar (there should be none)
  m_toolbar->clear();

  // now add all actions to the toolbar
  foreach (const QString& it, actions)
  {
    QAction *ac = 0;
    if (it.isEmpty()) continue;
    if (it == "bookmarks" || it == "sync_dir" || it == "configure")
      ac = actionCollection()->action(it);
    else
      ac = m_dirOperator->actionCollection()->action(it);

    if (ac)
      m_toolbar->addAction(ac);
  }
}

void KateFileBrowser::readSessionConfig(KConfigBase *config, const QString & name)
{
  KConfigGroup cgDir(config, name + ":dir");
  m_dirOperator->readConfig(cgDir);
  m_dirOperator->setView(KFile::Default);

  KConfigGroup cg(config, name);
  m_urlNavigator->setLocationUrl(cg.readPathEntry("location", QDir::homePath()));
  setDir(cg.readPathEntry("location", QDir::homePath()));
  m_autoSyncFolder->setChecked(cg.readEntry("auto sync folder", false));
  m_filter->setHistoryItems(cg.readEntry("filter history", QStringList()), true);
}

void KateFileBrowser::writeSessionConfig(KConfigBase *config, const QString & name)
{
  KConfigGroup cgDir(config, name + ":dir");
  m_dirOperator->writeConfig(cgDir);

  KConfigGroup cg = KConfigGroup(config, name);
  cg.writePathEntry("location", m_urlNavigator->locationUrl().url());
  cg.writeEntry("auto sync folder", m_autoSyncFolder->isChecked());
  cg.writeEntry("filter history", m_filter->historyItems());
}

//END Public Methods

//BEGIN Public Slots

void KateFileBrowser::slotFilterChange(const QString & nf)
{
  QString f = nf.trimmed();
  const bool empty = f.isEmpty() || f == "*";

  if (empty) {
    m_dirOperator->clearFilter();
  } else {
    m_dirOperator->setNameFilter(f);
  }

  m_dirOperator->updateDir();
}

bool kateFileSelectorIsReadable (const KUrl& url)
{
  if (!url.isLocalFile())
    return true; // what else can we say?

  QDir dir(url.toLocalFile());
  return dir.exists ();
}

void KateFileBrowser::setDir(KUrl u)
{
  KUrl newurl;

  if (!u.isValid())
    newurl.setPath(QDir::homePath());
  else
    newurl = u;

  QString pathstr = newurl.path(KUrl::AddTrailingSlash);
  newurl.setPath(pathstr);

  if (!kateFileSelectorIsReadable (newurl))
    newurl.cd(QString::fromLatin1(".."));

  if (!kateFileSelectorIsReadable (newurl))
    newurl.setPath(QDir::homePath());

  m_dirOperator->setUrl(newurl, true);
}

//END Public Slots

//BEGIN Private Slots

void KateFileBrowser::fileSelected(const KFileItem & /*file*/)
{
  openSelectedFiles();
}

void KateFileBrowser::openSelectedFiles()
{
  const KFileItemList list = m_dirOperator->selectedItems();

  if (list.count()>20) {
    if (KMessageBox::questionYesNo(this,i18np("You are trying to open 1 file, are your sure?", "You are trying to open %1 files, are your sure?", list.count()))
      == KMessageBox::No) return;
  }

  foreach (const KFileItem& item, list)
  {
    m_mainWindow->openUrl(item.url());
  }

  m_dirOperator->view()->selectionModel()->clear();
}

void KateFileBrowser::updateDirOperator(const KUrl& u)
{
  m_dirOperator->setUrl(u, true);
}

void KateFileBrowser::updateUrlNavigator(const KUrl& u)
{
  m_urlNavigator->setLocationUrl(u);
}

void KateFileBrowser::setActiveDocumentDir()
{
//   kDebug(13001)<<"KateFileBrowser::setActiveDocumentDir()";
  KUrl u = activeDocumentUrl();
//   kDebug(13001)<<"URL: "<<u.pathOrUrl();
  if (!u.isEmpty())
    setDir(u.upUrl());
//   kDebug(13001)<<"... setActiveDocumentDir() DONE!";
}

void KateFileBrowser::autoSyncFolder()
{
  if (m_autoSyncFolder->isChecked()) {
    setActiveDocumentDir();
  }
}

void KateFileBrowser::selectorViewChanged(QAbstractItemView * newView)
{
  newView->setSelectionMode(QAbstractItemView::ExtendedSelection);
}

//END Private Slots

//BEGIN Protected

KUrl KateFileBrowser::activeDocumentUrl()
{
  KTextEditor::View *v = m_mainWindow->activeView();
  if (v)
    return v->document()->url();
  return KUrl();
}

void KateFileBrowser::setupActions()
{
  // bookmarks action!
  KActionMenu *acmBookmarks = new KActionMenu(KIcon("bookmarks"), i18n("Bookmarks"), this);
  acmBookmarks->setDelayed(false);
  m_bookmarkHandler = new KateBookmarkHandler(this, acmBookmarks->menu());
  acmBookmarks->setShortcutContext(Qt::WidgetWithChildrenShortcut);

  // action for synchronizing the dir operator with the current document path
  KAction* syncFolder = new KAction(this);
  syncFolder->setShortcutContext(Qt::WidgetWithChildrenShortcut);
  syncFolder->setText(i18n("Current Document Folder"));
  syncFolder->setIcon(KIcon("system-switch-user"));
  connect(syncFolder, SIGNAL(triggered()), this, SLOT(setActiveDocumentDir()));

  m_actionCollection->addAction("sync_dir", syncFolder);
  m_actionCollection->addAction("bookmarks", acmBookmarks);

  // section for settings menu
  KActionMenu *optionsMenu = new KActionMenu(KIcon("configure"), i18n("Options"), this);
  optionsMenu->setDelayed(false);
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("short view"));
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("detailed view"));
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("tree view"));
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("detailed tree view"));
  optionsMenu->addSeparator();
  optionsMenu->addAction(m_dirOperator->actionCollection()->action("show hidden"));

  // action for synchronising the dir operator with the current document path
  m_autoSyncFolder = new KAction(this);
  m_autoSyncFolder->setCheckable(true);
  m_autoSyncFolder->setText(i18n("Automatically synchronize with current document"));
  m_autoSyncFolder->setIcon(KIcon("system-switch-user"));
  connect(m_autoSyncFolder, SIGNAL(triggered()), this, SLOT(autoSyncFolder()));
  optionsMenu->addAction(m_autoSyncFolder);

  m_actionCollection->addAction("configure", optionsMenu);

  //
  // Remove all shortcuts due to shortcut clashes (e.g. F5: reload, Ctrl+B: bookmark)
  // BUGS: #188954, #236368
  //
  foreach (QAction* a, m_actionCollection->actions()) {
    a->setShortcut(QKeySequence());
  }
  foreach (QAction* a, m_dirOperator->actionCollection()->actions()) {
    a->setShortcut(QKeySequence());
  }
}
//END Protected

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector.hpp>
#include <string.hpp>

#include "ethernet_layer.hpp"
#include "logging.hpp"
#include "kernel_utils.hpp"
#include "arp_layer.hpp"

namespace {

network::ethernet::ether_type decode_ether_type(network::ethernet::header* header){
    auto type = switch_endian_16(header->type);

    if(type == 0x800){
        return network::ethernet::ether_type::IPV4;
    } else if(type == 0x86DD){
        return network::ethernet::ether_type::IPV6;
    } else if(type == 0x806){
        return network::ethernet::ether_type::ARP;
    } else {
        return network::ethernet::ether_type::UNKNOWN;
    }
}

uint16_t type_to_code(network::ethernet::ether_type type){
    switch(type){
        case network::ethernet::ether_type::IPV4:
            return 0x800;
        case network::ethernet::ether_type::IPV6:
            return 0x86DD;
        case network::ethernet::ether_type::ARP:
            return 0x806;
        case network::ethernet::ether_type::UNKNOWN:
            logging::logf(logging::log_level::ERROR, "ethernet: Decoding UNKOWN code\n");
            return 0x0;
    }
}

} //end of anonymous namespace

void network::ethernet::decode(network::interface_descriptor& interface, packet& packet){
    header* ether_header = reinterpret_cast<header*>(packet.payload);

    // Filter out non-ethernet II frames
    if(switch_endian_16(ether_header->type) < 1536){
        logging::logf(logging::log_level::ERROR, "ethernet: error only ethernet frame type II is supported\n");
        return;
    }

    size_t source_mac = 0;
    size_t target_mac = 0;

    for(size_t i = 0; i < 6; ++i){
        source_mac |= uint64_t(ether_header->source.mac[i]) << ((5 - i) * 8);
        target_mac |= uint64_t(ether_header->target.mac[i]) << ((5 - i) * 8);
    }

    logging::logf(logging::log_level::TRACE, "ethernet: Source MAC Address %h \n", source_mac);
    logging::logf(logging::log_level::TRACE, "ethernet: Destination MAC Address %h \n", target_mac);

    packet.type = decode_ether_type(ether_header);
    packet.index += sizeof(header);

    switch(packet.type){
        case ether_type::IPV4:
            logging::logf(logging::log_level::TRACE, "ethernet: IPV4 Packet (unsupported)\n");
            break;
        case ether_type::IPV6:
            logging::logf(logging::log_level::TRACE, "ethernet: IPV6 Packet (unsupported)\n");
            break;
        case ether_type::ARP:
            network::arp::decode(interface, packet);
            break;
        case ether_type::UNKNOWN:
            logging::logf(logging::log_level::TRACE, "ethernet: Unhandled Packet Type: %u\n", uint64_t(switch_endian_16(ether_header->type)));
            break;
    }
}

network::ethernet::packet network::ethernet::prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){
    auto total_size = size + sizeof(header);

    network::ethernet::packet p(new char[total_size], total_size);
    p.type = type;
    p.index = sizeof(header);

    auto source_mac = interface.mac_address;

    auto* ether_header = reinterpret_cast<header*>(p.payload);
    ether_header->type = switch_endian_16(type_to_code(type));

    for(size_t i = 0; i < 6; ++i){
        ether_header->source.mac[i] = (source_mac >> ((5 - i) * 8));
        ether_header->target.mac[i] = (destination >> ((5 - i) * 8));
    }

    return p;
}

void network::ethernet::finalize_packet(network::interface_descriptor& interface, packet& p){
    interface.send(p);
}
<commit_msg>Safety net<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector.hpp>
#include <string.hpp>

#include "ethernet_layer.hpp"
#include "logging.hpp"
#include "kernel_utils.hpp"
#include "arp_layer.hpp"

namespace {

network::ethernet::ether_type decode_ether_type(network::ethernet::header* header){
    auto type = switch_endian_16(header->type);

    if(type == 0x800){
        return network::ethernet::ether_type::IPV4;
    } else if(type == 0x86DD){
        return network::ethernet::ether_type::IPV6;
    } else if(type == 0x806){
        return network::ethernet::ether_type::ARP;
    } else {
        return network::ethernet::ether_type::UNKNOWN;
    }
}

uint16_t type_to_code(network::ethernet::ether_type type){
    switch(type){
        case network::ethernet::ether_type::IPV4:
            return 0x800;
        case network::ethernet::ether_type::IPV6:
            return 0x86DD;
        case network::ethernet::ether_type::ARP:
            return 0x806;
        case network::ethernet::ether_type::UNKNOWN:
            logging::logf(logging::log_level::ERROR, "ethernet: Decoding UNKOWN code\n");
            return 0x0;
    }
}

} //end of anonymous namespace

void network::ethernet::decode(network::interface_descriptor& interface, packet& packet){
    header* ether_header = reinterpret_cast<header*>(packet.payload);

    // Filter out non-ethernet II frames
    if(switch_endian_16(ether_header->type) < 1536){
        logging::logf(logging::log_level::ERROR, "ethernet: error only ethernet frame type II is supported\n");
        return;
    }

    size_t source_mac = 0;
    size_t target_mac = 0;

    for(size_t i = 0; i < 6; ++i){
        source_mac |= uint64_t(ether_header->source.mac[i]) << ((5 - i) * 8);
        target_mac |= uint64_t(ether_header->target.mac[i]) << ((5 - i) * 8);
    }

    logging::logf(logging::log_level::TRACE, "ethernet: Source MAC Address %h \n", source_mac);
    logging::logf(logging::log_level::TRACE, "ethernet: Destination MAC Address %h \n", target_mac);

    packet.type = decode_ether_type(ether_header);
    packet.index += sizeof(header);

    switch(packet.type){
        case ether_type::IPV4:
            logging::logf(logging::log_level::TRACE, "ethernet: IPV4 Packet (unsupported)\n");
            break;
        case ether_type::IPV6:
            logging::logf(logging::log_level::TRACE, "ethernet: IPV6 Packet (unsupported)\n");
            break;
        case ether_type::ARP:
            network::arp::decode(interface, packet);
            break;
        case ether_type::UNKNOWN:
            logging::logf(logging::log_level::TRACE, "ethernet: Unhandled Packet Type: %u\n", uint64_t(switch_endian_16(ether_header->type)));
            break;
        default:
            logging::logf(logging::log_level::ERROR, "ethernet: Unhandled Packet Type in switch: %u\n", uint64_t(switch_endian_16(ether_header->type)));
            break;
    }
}

network::ethernet::packet network::ethernet::prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){
    auto total_size = size + sizeof(header);

    network::ethernet::packet p(new char[total_size], total_size);
    p.type = type;
    p.index = sizeof(header);

    auto source_mac = interface.mac_address;

    auto* ether_header = reinterpret_cast<header*>(p.payload);
    ether_header->type = switch_endian_16(type_to_code(type));

    for(size_t i = 0; i < 6; ++i){
        ether_header->source.mac[i] = (source_mac >> ((5 - i) * 8));
        ether_header->target.mac[i] = (destination >> ((5 - i) * 8));
    }

    return p;
}

void network::ethernet::finalize_packet(network::interface_descriptor& interface, packet& p){
    interface.send(p);
}
<|endoftext|>