<commit_before>/***************************************************************************
 *   Copyright (c) 2015 Balázs Bámer                                       *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#include <Mod/Surface/App/FeatureBSurf.h>
#include <Mod/Surface/FillType.h>
#include <Gui/ViewProvider.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/Command.h>
#include <Base/Sequencer.h>
#include <Gui/Control.h>

#include "BSurf.h"
#include "ui_BSurf.h"

using namespace SurfaceGui;
//#undef CS_FUTURE // multi-threading causes some problems

PROPERTY_SOURCE(SurfaceGui::ViewProviderBSurf, PartGui::ViewProviderPart)

namespace SurfaceGui {

bool ViewProviderBSurf::setEdit(int ModNum)
{
// When double-clicking on the item for this sketch the
// object unsets and sets its edit mode without closing
// the task panel

    Surface::BSurf* obj =  static_cast<Surface::BSurf*>(this->getObject());

    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
    TaskBSurf* tDlg = qobject_cast<TaskBSurf*>(dlg);
// start the edit dialog
    if(dlg)
    {
        tDlg->setEditedObject(obj);
        Gui::Control().showDialog(tDlg);
    }
    else
    {
        Gui::Control().showDialog(new TaskBSurf(this, obj));
    }
    return true;
}

void ViewProviderBSurf::unsetEdit(int ModNum)
{
    // nothing to do
}

BSurf::BSurf(ViewProviderBSurf* vp, Surface::BSurf* obj)
{
    ui = new Ui_DlgBSurf();
    ui->setupUi(this);
    this->vp = vp;
    setEditedObject(obj);
}

/*
 *  Destroys the object and frees any allocated resources
 */
BSurf::~BSurf()
{
    // no need to delete child widgets, Qt does it all for us
    delete ui;
}

// stores object pointer, its old fill type and adjusts radio buttons according to it.
void BSurf::setEditedObject(Surface::BSurf* obj)
{
    editedObject = obj;
    filltype_t ft = (filltype_t)(editedObject->filltype.getValue());
    switch(ft)
    {
    case StretchStyle:
        oldFillType = ft;
        ui->fillType_stretch->setChecked(true);
        break;
    case CoonsStyle:
        oldFillType = ft;
        ui->fillType_coons->setChecked(true);
        break;
    case CurvedStyle:
        oldFillType = ft;
        ui->fillType_curved->setChecked(true);
        break;
    /*default:
        printf("BSurf::setEditedObject: illegal fill type: %d\n", editedObject->filltype.getValue());
        Standard_Failure::Raise("BSurf::setEditedObject: illegal fill type.");*/
    }
    fillType = oldFillType;
}

filltype_t BSurf::getFillType() const
{
    filltype_t ret;
    if (ui->fillType_stretch->isChecked())
        ret = StretchStyle;
    else if (ui->fillType_coons->isChecked())
        ret = CoonsStyle;
    else
        ret = CurvedStyle;
    return ret;
}

void BSurf::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::LanguageChange) {
        ui->retranslateUi(this);
    }
    else {
        QWidget::changeEvent(e);
    }
}

void BSurf::accept()
{
    // applies the changes
    apply();
    Gui::Command::commitCommand();
    Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
}

void BSurf::reject()
{
    // if the object fill type was changed, reset the old one
    if(editedObject->filltype.getValue() != oldFillType)
    {
        editedObject->filltype.setValue(oldFillType);
    }
    Gui::Command::commitCommand();
    Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
    Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
}

void BSurf::apply()
{
    // apply the change only if it is a real change
    if(editedObject->filltype.getValue() != fillType)
    {
        editedObject->filltype.setValue(fillType);
        oldFillType = fillType;
        Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
    }
}

void BSurf::on_fillType_stretch_clicked()
{
    fillType = StretchStyle;
}

void BSurf::on_fillType_coons_clicked()
{
    fillType = CoonsStyle;
}

void BSurf::on_fillType_curved_clicked()
{
    fillType = CurvedStyle;
}

// ---------------------------------------

TaskBSurf::TaskBSurf(ViewProviderBSurf* vp, Surface::BSurf* obj)
{
    widget = new BSurf(vp, obj);
    Content.push_back(widget);
}

TaskBSurf::~TaskBSurf()
{
    // automatically deleted in the sub-class
}

void TaskBSurf::setEditedObject(Surface::BSurf* obj)
{
    widget->setEditedObject(obj);
}

bool TaskBSurf::accept()
{
    widget->accept();
    return true;
}

bool TaskBSurf::reject()
{
    widget->reject();
    return true;
}

// Apply clicked
void TaskBSurf::clicked(int id)
{
    if (id == QDialogButtonBox::Apply) {
        widget->apply();
    }
}

}
#include "moc_BSurf.cpp"
<commit_msg>use taskbox in taskdialog<commit_after>/***************************************************************************
 *   Copyright (c) 2015 Balázs Bámer                                       *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#include <Mod/Surface/App/FeatureBSurf.h>
#include <Mod/Surface/FillType.h>
#include <Gui/ViewProvider.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/Command.h>
#include <Base/Sequencer.h>
#include <Gui/Control.h>
#include <Gui/BitmapFactory.h>

#include "BSurf.h"
#include "ui_BSurf.h"

using namespace SurfaceGui;
//#undef CS_FUTURE // multi-threading causes some problems

PROPERTY_SOURCE(SurfaceGui::ViewProviderBSurf, PartGui::ViewProviderPart)

namespace SurfaceGui {

bool ViewProviderBSurf::setEdit(int ModNum)
{
// When double-clicking on the item for this sketch the
// object unsets and sets its edit mode without closing
// the task panel

    Surface::BSurf* obj =  static_cast<Surface::BSurf*>(this->getObject());

    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
    TaskBSurf* tDlg = qobject_cast<TaskBSurf*>(dlg);
// start the edit dialog
    if(dlg)
    {
        tDlg->setEditedObject(obj);
        Gui::Control().showDialog(tDlg);
    }
    else
    {
        Gui::Control().showDialog(new TaskBSurf(this, obj));
    }
    return true;
}

void ViewProviderBSurf::unsetEdit(int ModNum)
{
    // nothing to do
}

BSurf::BSurf(ViewProviderBSurf* vp, Surface::BSurf* obj)
{
    ui = new Ui_DlgBSurf();
    ui->setupUi(this);
    this->vp = vp;
    setEditedObject(obj);
}

/*
 *  Destroys the object and frees any allocated resources
 */
BSurf::~BSurf()
{
    // no need to delete child widgets, Qt does it all for us
    delete ui;
}

// stores object pointer, its old fill type and adjusts radio buttons according to it.
void BSurf::setEditedObject(Surface::BSurf* obj)
{
    editedObject = obj;
    filltype_t ft = (filltype_t)(editedObject->filltype.getValue());
    switch(ft)
    {
    case StretchStyle:
        oldFillType = ft;
        ui->fillType_stretch->setChecked(true);
        break;
    case CoonsStyle:
        oldFillType = ft;
        ui->fillType_coons->setChecked(true);
        break;
    case CurvedStyle:
        oldFillType = ft;
        ui->fillType_curved->setChecked(true);
        break;
    /*default:
        printf("BSurf::setEditedObject: illegal fill type: %d\n", editedObject->filltype.getValue());
        Standard_Failure::Raise("BSurf::setEditedObject: illegal fill type.");*/
    }
    fillType = oldFillType;
}

filltype_t BSurf::getFillType() const
{
    filltype_t ret;
    if (ui->fillType_stretch->isChecked())
        ret = StretchStyle;
    else if (ui->fillType_coons->isChecked())
        ret = CoonsStyle;
    else
        ret = CurvedStyle;
    return ret;
}

void BSurf::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::LanguageChange) {
        ui->retranslateUi(this);
    }
    else {
        QWidget::changeEvent(e);
    }
}

void BSurf::accept()
{
    // applies the changes
    apply();
    Gui::Command::commitCommand();
    Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
}

void BSurf::reject()
{
    // if the object fill type was changed, reset the old one
    if(editedObject->filltype.getValue() != oldFillType)
    {
        editedObject->filltype.setValue(oldFillType);
    }
    Gui::Command::commitCommand();
    Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
    Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
}

void BSurf::apply()
{
    // apply the change only if it is a real change
    if(editedObject->filltype.getValue() != fillType)
    {
        editedObject->filltype.setValue(fillType);
        oldFillType = fillType;
        Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
    }
}

void BSurf::on_fillType_stretch_clicked()
{
    fillType = StretchStyle;
}

void BSurf::on_fillType_coons_clicked()
{
    fillType = CoonsStyle;
}

void BSurf::on_fillType_curved_clicked()
{
    fillType = CurvedStyle;
}

// ---------------------------------------

TaskBSurf::TaskBSurf(ViewProviderBSurf* vp, Surface::BSurf* obj)
{
    widget = new BSurf(vp, obj);
    widget->setWindowTitle(QObject::tr("Surface"));
    taskbox = new Gui::TaskView::TaskBox(
        Gui::BitmapFactory().pixmap("BezSurf"),
        widget->windowTitle(), true, 0);
    taskbox->groupLayout()->addWidget(widget);
    Content.push_back(taskbox);
}

TaskBSurf::~TaskBSurf()
{
    // automatically deleted in the sub-class
}

void TaskBSurf::setEditedObject(Surface::BSurf* obj)
{
    widget->setEditedObject(obj);
}

bool TaskBSurf::accept()
{
    widget->accept();
    return true;
}

bool TaskBSurf::reject()
{
    widget->reject();
    return true;
}

// Apply clicked
void TaskBSurf::clicked(int id)
{
    if (id == QDialogButtonBox::Apply) {
        widget->apply();
    }
}

}
#include "moc_BSurf.cpp"
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/object.hpp"
#include "flusspferd/property_iterator.hpp"
#include "flusspferd/function.hpp"
#include "flusspferd/exception.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/root.hpp"
#include "flusspferd/arguments.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/native_object_base.hpp"
#include "flusspferd/implementation/init.hpp"
#include "flusspferd/implementation/value.hpp"
#include "flusspferd/implementation/object.hpp"
#include <cassert>
#include <js/jsapi.h>

#if JS_VERSION < 180
#include <js/jsobj.h>
#endif

using namespace flusspferd;

object::object() : Impl::object_impl(0) { }
object::~object() { }

void object::seal(bool deep) {
  if (!JS_SealObject(Impl::current_context(), get(), deep))
    throw exception("Could not seal object");
}

object object::parent() {
  if (is_null())
    throw exception("Could not get object parent (object is null)");
  return Impl::wrap_object(JS_GetParent(Impl::current_context(), get()));
}

object object::prototype() {
  if (is_null())
    throw exception("Could not get object prototype (object is null)");
  return Impl::wrap_object(JS_GetPrototype(Impl::current_context(), get()));
}

void object::set_parent(object const &o) {
  if (is_null())
    throw exception("Could not set parent (object is null)");
  if (!JS_SetParent(Impl::current_context(), get(), o.get_const()))
    throw exception("Could not set object parent");
}

void object::set_prototype(object const &o) {
  if (is_null())
    throw exception("Could not set object prototype (object is null)");
  if (!JS_SetPrototype(Impl::current_context(), get(), o.get_const()))
    throw exception("Could not set object prototype");
}

void object::set_property(char const *name, value const &v_) {
  if (is_null())
    throw exception("Could not set property (object is null)");
  value v = v_;
  if (!JS_SetProperty(Impl::current_context(), get(), name,
                      Impl::get_jsvalp(v)))
    throw exception("Could not set property");
}

void object::set_property(std::string const &name, value const &v) {
  set_property(name.c_str(), v);
}

void object::set_property(value const &id, value const &v_) {
  if (is_null())
    throw exception("Could not set property (object is null)");
  local_root_scope scope;
  value v = v_;
  string name = id.to_string();
  if (!JS_SetUCProperty(Impl::current_context(), get(),
                        name.data(), name.length(),
                        Impl::get_jsvalp(v)))
    throw exception("Could not set property");
}

value object::get_property(char const *name) const {
  if (is_null())
    throw exception("Could not get property (object is null)");
  value result;
  if (!JS_GetProperty(Impl::current_context(), get_const(),
                      name, Impl::get_jsvalp(result)))
    throw exception("Could not get property");
  return result;
}

value object::get_property(std::string const &name) const {
  return get_property(name.c_str());
}

value object::get_property(value const &id) const {
  if (is_null())
    throw exception("Could not get property (object is null)");
  value result;
  local_root_scope scope;
  string name = id.to_string();
  if (!JS_GetUCProperty(Impl::current_context(), get_const(),
                        name.data(), name.length(),
                        Impl::get_jsvalp(result)))
    throw exception("Could not get property");
  return result;
}

bool object::has_property(char const *name) const {
  if (is_null())
    throw exception("Could not check property (object is null)");
  JSBool foundp;
  if (!JS_HasProperty(Impl::current_context(), get_const(), name,
                      &foundp))
    throw exception("Could not check property");
  return foundp;
}

bool object::has_property(std::string const &name) const {
  return has_property(name.c_str());
}

bool object::has_property(value const &id) const {
  if (is_null())
    throw exception("Could not check property (object is null)");
  local_root_scope scope;
  string name = id.to_string();
  JSBool foundp;
  if (!JS_HasUCProperty(Impl::current_context(), get_const(),
                        name.data(), name.length(),
                        &foundp))
    throw exception("Could not check property");
  return foundp;
}

bool object::has_own_property(char const *name_) const {
  local_root_scope scope;
  string name(name_);
  return has_own_property(name);
}

bool object::has_own_property(std::string const &name_) const {
  local_root_scope scope;
  string name(name_);
  return has_own_property(name);
}

bool object::has_own_property(value const &id) const {

  JSBool has;
#if JS_VERSION >= 180
  string name = id.to_string();
  if (!JS_AlreadyHasOwnUCProperty(Impl::current_context(), get_const(),
                                  name.data(), name.length(), &has))
#else
  JSObject *obj = get_const();
  jsval argv[] = { Impl::get_jsval(id) };
  jsval vp;
  JSBool ret = js_HasOwnPropertyHelper(Impl::current_context(), obj,
                                       obj->map->ops->lookupProperty, 1, argv,
                                       &vp);
  has = JSVAL_TO_BOOLEAN(vp);
  if (!ret)
#endif
  {
    throw exception("Unable to check for own property");
  }
  return has;
}

void object::delete_property(char const *name) {
  if (is_null())
    throw exception("Could not delete property (object is null)");
  if (!JS_DeleteProperty(Impl::current_context(), get(), name))
    throw exception("Could not delete property");
}

void object::delete_property(std::string const &name) {
  delete_property(name.c_str());
}

void object::delete_property(value const &id) {
  if (is_null())
    throw exception("Could not delete property (object is null)");
  local_root_scope scope;
  string name = id.to_string();
  jsval dummy;
  if (!JS_DeleteUCProperty2(Impl::current_context(), get(),
                            name.data(), name.length(), &dummy))
    throw exception("Could not delete property");
}

property_iterator object::begin() const {
  return property_iterator(*this);
}

property_iterator object::end() const {
  return property_iterator();
}

void object::define_property(
  string const &name, value const &init_value,
  property_attributes const attrs)
{
  if (is_null())
    throw exception("Could not define property (object is null)");

  unsigned flags = attrs.flags;
  value v;
  v = init_value;

  function getter;
  if (attrs.getter) getter = attrs.getter.get();
  function setter;
  if (attrs.setter) setter = attrs.setter.get();

  JSObject *getter_o = Impl::get_object(getter);
  JSObject *setter_o = Impl::get_object(setter);

  unsigned sm_flags = 0;

  if (~flags & dont_enumerate) sm_flags |= JSPROP_ENUMERATE;
  if (flags & read_only_property) sm_flags |= JSPROP_READONLY;
  if (flags & permanent_property) sm_flags |= JSPROP_PERMANENT;
  if (flags & shared_property) sm_flags |= JSPROP_SHARED;

  if (getter_o) sm_flags |= JSPROP_GETTER;
  if (setter_o) sm_flags |= JSPROP_SETTER;

  if(!JS_DefineUCProperty(Impl::current_context(), get_const(),
                          name.data(), name.length(),
                          Impl::get_jsval(v),
                          *(JSPropertyOp*) &getter_o,
                          *(JSPropertyOp*) &setter_o,
                          sm_flags))
    throw exception("Could not define property");
}

void object::define_property(
  std::string const &name_, value const &init_value,
  property_attributes attrs)
{
  local_root_scope scope;
  string name(name_);
  define_property(name, init_value, attrs);
}

void object::define_property(
  char const *name_, value const &init_value,
  property_attributes const attrs)
{
  local_root_scope scope;
  string name(name_);
  define_property(name, init_value,attrs);
}

bool object::is_null() const {
  return !get_const();
}

value object::apply(object const &fn, arguments const &arg_) {
  if (is_null())
    throw exception("Could not apply function (object is null)");

  value fnv(fn);
  root_value result((value()));

  arguments arg(arg_);

  JSBool status = JS_CallFunctionValue(
      Impl::current_context(),
      get(),
      Impl::get_jsval(fnv),
      arg.size(),
      Impl::get_arguments(arg),
      Impl::get_jsvalp(result));

  if (!status)
    throw exception("Could not call function");

  return result;
}

value object::call(char const *fn, arguments const &arg_) {
  if (is_null())
    throw exception("Could not call function (object is null)");

  root_value result((value()));

  arguments arg(arg_);

  JSBool status = JS_CallFunctionName(
      Impl::current_context(),
      get(),
      fn,
      arg.size(),
      Impl::get_arguments(arg),
      Impl::get_jsvalp(result));

  if (!status)
    throw exception("Could not call function");

  return result;
}

value object::call(std::string const &fn, arguments const &arg) {
  return call(fn.c_str(), arg);
}

value object::call(object o, arguments const &arg) {
  return o.apply(*this, arg);
}

value object::call(arguments const &arg) {
  return call(global(), arg);
}

bool object::is_array() const {
  return JS_IsArrayObject(Impl::current_context(), get_const());
}

bool object::get_property_attributes(
    char const *name_, property_attributes &attrs)
{
  local_root_scope scope;
  string name(name_);
  return get_property_attributes(name, attrs);
}

bool object::get_property_attributes(
    std::string name_, property_attributes &attrs)
{
  local_root_scope scope;
  string name(name_);
  return get_property_attributes(name, attrs);
}

bool object::get_property_attributes(
    string const &name, property_attributes &attrs)
{
  JSBool found;
  void *getter_op, *setter_op;
  uintN sm_flags;

  attrs.flags = 0;
  attrs.getter = boost::none;
  attrs.setter = boost::none;
  JSBool success = JS_GetUCPropertyAttrsGetterAndSetter(
          Impl::current_context(), get_const(), name.data(), name.length(),
          &sm_flags, &found,
          (JSPropertyOp*)&getter_op, (JSPropertyOp*)&setter_op);

  if (!success)
    throw exception("Could not query property attributes");

  if (!found)
    return false;

  if (~sm_flags & JSPROP_ENUMERATE) attrs.flags |= dont_enumerate;
  if (sm_flags & JSPROP_PERMANENT) attrs.flags |= permanent_property;
  if (sm_flags & JSPROP_READONLY) attrs.flags |= read_only_property;
  if (sm_flags & JSPROP_SHARED) attrs.flags |= shared_property;

  if (getter_op) {
    if (sm_flags & JSPROP_GETTER) {
      attrs.getter = Impl::wrap_object((JSObject*)getter_op);
    } else {
      // What do i set attrs.getter to here....?
    }
  }

  if (setter_op) {
    if (sm_flags & JSPROP_SETTER) {
      attrs.setter = Impl::wrap_object((JSObject*)setter_op);
    } else {
      // What do i set attrs.setter to here....?
    }
  }
  return true;
}

object::property_attributes::property_attributes()
  : flags(0u),
    getter(boost::none),
    setter(boost::none)
{}

object::property_attributes::property_attributes(
  unsigned flags,
  boost::optional<function const &> getter,
  boost::optional<function const &> setter
)
  : flags(flags),
    getter(getter),
    setter(setter)
{}
<commit_msg>core: fix bug in object::seal<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/object.hpp"
#include "flusspferd/property_iterator.hpp"
#include "flusspferd/function.hpp"
#include "flusspferd/exception.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/root.hpp"
#include "flusspferd/arguments.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/native_object_base.hpp"
#include "flusspferd/implementation/init.hpp"
#include "flusspferd/implementation/value.hpp"
#include "flusspferd/implementation/object.hpp"
#include <cassert>
#include <js/jsapi.h>

#if JS_VERSION < 180
#include <js/jsobj.h>
#endif

using namespace flusspferd;

object::object() : Impl::object_impl(0) { }
object::~object() { }

void object::seal(bool deep) {
  if (is_null())
    throw exception("Could not seal object (object is null)");
  if (!JS_SealObject(Impl::current_context(), get(), deep))
    throw exception("Could not seal object");
}

object object::parent() {
  if (is_null())
    throw exception("Could not get object parent (object is null)");
  return Impl::wrap_object(JS_GetParent(Impl::current_context(), get()));
}

object object::prototype() {
  if (is_null())
    throw exception("Could not get object prototype (object is null)");
  return Impl::wrap_object(JS_GetPrototype(Impl::current_context(), get()));
}

void object::set_parent(object const &o) {
  if (is_null())
    throw exception("Could not set parent (object is null)");
  if (!JS_SetParent(Impl::current_context(), get(), o.get_const()))
    throw exception("Could not set object parent");
}

void object::set_prototype(object const &o) {
  if (is_null())
    throw exception("Could not set object prototype (object is null)");
  if (!JS_SetPrototype(Impl::current_context(), get(), o.get_const()))
    throw exception("Could not set object prototype");
}

void object::set_property(char const *name, value const &v_) {
  if (is_null())
    throw exception("Could not set property (object is null)");
  value v = v_;
  if (!JS_SetProperty(Impl::current_context(), get(), name,
                      Impl::get_jsvalp(v)))
    throw exception("Could not set property");
}

void object::set_property(std::string const &name, value const &v) {
  set_property(name.c_str(), v);
}

void object::set_property(value const &id, value const &v_) {
  if (is_null())
    throw exception("Could not set property (object is null)");
  local_root_scope scope;
  value v = v_;
  string name = id.to_string();
  if (!JS_SetUCProperty(Impl::current_context(), get(),
                        name.data(), name.length(),
                        Impl::get_jsvalp(v)))
    throw exception("Could not set property");
}

value object::get_property(char const *name) const {
  if (is_null())
    throw exception("Could not get property (object is null)");
  value result;
  if (!JS_GetProperty(Impl::current_context(), get_const(),
                      name, Impl::get_jsvalp(result)))
    throw exception("Could not get property");
  return result;
}

value object::get_property(std::string const &name) const {
  return get_property(name.c_str());
}

value object::get_property(value const &id) const {
  if (is_null())
    throw exception("Could not get property (object is null)");
  value result;
  local_root_scope scope;
  string name = id.to_string();
  if (!JS_GetUCProperty(Impl::current_context(), get_const(),
                        name.data(), name.length(),
                        Impl::get_jsvalp(result)))
    throw exception("Could not get property");
  return result;
}

bool object::has_property(char const *name) const {
  if (is_null())
    throw exception("Could not check property (object is null)");
  JSBool foundp;
  if (!JS_HasProperty(Impl::current_context(), get_const(), name,
                      &foundp))
    throw exception("Could not check property");
  return foundp;
}

bool object::has_property(std::string const &name) const {
  return has_property(name.c_str());
}

bool object::has_property(value const &id) const {
  if (is_null())
    throw exception("Could not check property (object is null)");
  local_root_scope scope;
  string name = id.to_string();
  JSBool foundp;
  if (!JS_HasUCProperty(Impl::current_context(), get_const(),
                        name.data(), name.length(),
                        &foundp))
    throw exception("Could not check property");
  return foundp;
}

bool object::has_own_property(char const *name_) const {
  local_root_scope scope;
  string name(name_);
  return has_own_property(name);
}

bool object::has_own_property(std::string const &name_) const {
  local_root_scope scope;
  string name(name_);
  return has_own_property(name);
}

bool object::has_own_property(value const &id) const {

  JSBool has;
#if JS_VERSION >= 180
  string name = id.to_string();
  if (!JS_AlreadyHasOwnUCProperty(Impl::current_context(), get_const(),
                                  name.data(), name.length(), &has))
#else
  JSObject *obj = get_const();
  jsval argv[] = { Impl::get_jsval(id) };
  jsval vp;
  JSBool ret = js_HasOwnPropertyHelper(Impl::current_context(), obj,
                                       obj->map->ops->lookupProperty, 1, argv,
                                       &vp);
  has = JSVAL_TO_BOOLEAN(vp);
  if (!ret)
#endif
  {
    throw exception("Unable to check for own property");
  }
  return has;
}

void object::delete_property(char const *name) {
  if (is_null())
    throw exception("Could not delete property (object is null)");
  if (!JS_DeleteProperty(Impl::current_context(), get(), name))
    throw exception("Could not delete property");
}

void object::delete_property(std::string const &name) {
  delete_property(name.c_str());
}

void object::delete_property(value const &id) {
  if (is_null())
    throw exception("Could not delete property (object is null)");
  local_root_scope scope;
  string name = id.to_string();
  jsval dummy;
  if (!JS_DeleteUCProperty2(Impl::current_context(), get(),
                            name.data(), name.length(), &dummy))
    throw exception("Could not delete property");
}

property_iterator object::begin() const {
  return property_iterator(*this);
}

property_iterator object::end() const {
  return property_iterator();
}

void object::define_property(
  string const &name, value const &init_value,
  property_attributes const attrs)
{
  if (is_null())
    throw exception("Could not define property (object is null)");

  unsigned flags = attrs.flags;
  value v;
  v = init_value;

  function getter;
  if (attrs.getter) getter = attrs.getter.get();
  function setter;
  if (attrs.setter) setter = attrs.setter.get();

  JSObject *getter_o = Impl::get_object(getter);
  JSObject *setter_o = Impl::get_object(setter);

  unsigned sm_flags = 0;

  if (~flags & dont_enumerate) sm_flags |= JSPROP_ENUMERATE;
  if (flags & read_only_property) sm_flags |= JSPROP_READONLY;
  if (flags & permanent_property) sm_flags |= JSPROP_PERMANENT;
  if (flags & shared_property) sm_flags |= JSPROP_SHARED;

  if (getter_o) sm_flags |= JSPROP_GETTER;
  if (setter_o) sm_flags |= JSPROP_SETTER;

  if(!JS_DefineUCProperty(Impl::current_context(), get_const(),
                          name.data(), name.length(),
                          Impl::get_jsval(v),
                          *(JSPropertyOp*) &getter_o,
                          *(JSPropertyOp*) &setter_o,
                          sm_flags))
    throw exception("Could not define property");
}

void object::define_property(
  std::string const &name_, value const &init_value,
  property_attributes attrs)
{
  local_root_scope scope;
  string name(name_);
  define_property(name, init_value, attrs);
}

void object::define_property(
  char const *name_, value const &init_value,
  property_attributes const attrs)
{
  local_root_scope scope;
  string name(name_);
  define_property(name, init_value,attrs);
}

bool object::is_null() const {
  return !get_const();
}

value object::apply(object const &fn, arguments const &arg_) {
  if (is_null())
    throw exception("Could not apply function (object is null)");

  value fnv(fn);
  root_value result((value()));

  arguments arg(arg_);

  JSBool status = JS_CallFunctionValue(
      Impl::current_context(),
      get(),
      Impl::get_jsval(fnv),
      arg.size(),
      Impl::get_arguments(arg),
      Impl::get_jsvalp(result));

  if (!status)
    throw exception("Could not call function");

  return result;
}

value object::call(char const *fn, arguments const &arg_) {
  if (is_null())
    throw exception("Could not call function (object is null)");

  root_value result((value()));

  arguments arg(arg_);

  JSBool status = JS_CallFunctionName(
      Impl::current_context(),
      get(),
      fn,
      arg.size(),
      Impl::get_arguments(arg),
      Impl::get_jsvalp(result));

  if (!status)
    throw exception("Could not call function");

  return result;
}

value object::call(std::string const &fn, arguments const &arg) {
  return call(fn.c_str(), arg);
}

value object::call(object o, arguments const &arg) {
  return o.apply(*this, arg);
}

value object::call(arguments const &arg) {
  return call(global(), arg);
}

bool object::is_array() const {
  return JS_IsArrayObject(Impl::current_context(), get_const());
}

bool object::get_property_attributes(
    char const *name_, property_attributes &attrs)
{
  local_root_scope scope;
  string name(name_);
  return get_property_attributes(name, attrs);
}

bool object::get_property_attributes(
    std::string name_, property_attributes &attrs)
{
  local_root_scope scope;
  string name(name_);
  return get_property_attributes(name, attrs);
}

bool object::get_property_attributes(
    string const &name, property_attributes &attrs)
{
  JSBool found;
  void *getter_op, *setter_op;
  uintN sm_flags;

  attrs.flags = 0;
  attrs.getter = boost::none;
  attrs.setter = boost::none;
  JSBool success = JS_GetUCPropertyAttrsGetterAndSetter(
          Impl::current_context(), get_const(), name.data(), name.length(),
          &sm_flags, &found,
          (JSPropertyOp*)&getter_op, (JSPropertyOp*)&setter_op);

  if (!success)
    throw exception("Could not query property attributes");

  if (!found)
    return false;

  if (~sm_flags & JSPROP_ENUMERATE) attrs.flags |= dont_enumerate;
  if (sm_flags & JSPROP_PERMANENT) attrs.flags |= permanent_property;
  if (sm_flags & JSPROP_READONLY) attrs.flags |= read_only_property;
  if (sm_flags & JSPROP_SHARED) attrs.flags |= shared_property;

  if (getter_op) {
    if (sm_flags & JSPROP_GETTER) {
      attrs.getter = Impl::wrap_object((JSObject*)getter_op);
    } else {
      // What do i set attrs.getter to here....?
    }
  }

  if (setter_op) {
    if (sm_flags & JSPROP_SETTER) {
      attrs.setter = Impl::wrap_object((JSObject*)setter_op);
    } else {
      // What do i set attrs.setter to here....?
    }
  }
  return true;
}

object::property_attributes::property_attributes()
  : flags(0u),
    getter(boost::none),
    setter(boost::none)
{}

object::property_attributes::property_attributes(
  unsigned flags,
  boost::optional<function const &> getter,
  boost::optional<function const &> setter
)
  : flags(flags),
    getter(getter),
    setter(setter)
{}
<|endoftext|>


<commit_before>#include "yael/NetworkSocketListener.h"
#include "yael/EventLoop.h"

using namespace yael;

NetworkSocketListener::NetworkSocketListener()
    : EventListener(EventListener::Mode::ReadOnly), m_socket(nullptr), m_fileno(-1)
{
}

NetworkSocketListener::NetworkSocketListener(std::unique_ptr<network::Socket> &&socket, SocketType type)
    : EventListener(EventListener::Mode::ReadOnly), m_socket(nullptr), m_socket_type(SocketType::None), m_fileno(-1)
{
    if(socket)
    {
        NetworkSocketListener::set_socket(std::forward<std::unique_ptr<network::Socket>>(socket), type);

        m_socket->wait_connection_established();
    }
}

std::unique_ptr<network::Socket> NetworkSocketListener::release_socket()
{
    std::unique_lock lock(m_mutex);

    // Move socket before we unregistered so socket doesn't get closed
    auto sock = std::move(m_socket);

    ///FIXME we should tell event listener to remap the socket
    // the current approach can cause race conditions...
    auto &el = EventLoop::get_instance();
    el.unregister_event_listener(std::dynamic_pointer_cast<EventListener>(shared_from_this()));

    return sock;
}

void NetworkSocketListener::set_socket(std::unique_ptr<network::Socket> &&socket, SocketType type)
{
    std::unique_lock lock(m_mutex);

    if(m_socket)
    {
        throw std::runtime_error("There is already a socket assigned to this listener!");
    }

    if(!socket->is_valid())
    {
        throw std::runtime_error("Not a valid socket!");
    }

    m_socket = std::move(socket);
    m_socket_type = type;
    m_fileno = m_socket->get_fileno();
}

bool NetworkSocketListener::is_valid()
{
    std::unique_lock lock(m_mutex);

    if(!m_socket)
    {
        return false;
    }

    return m_socket->is_valid();
}

bool NetworkSocketListener::is_connected()
{
    std::unique_lock lock(m_mutex);

    if(!m_socket)
    {
        return false;
    }

    return m_socket->is_connected();
}

void NetworkSocketListener::on_write_ready()
{
    std::unique_lock lock(m_send_mutex);

    bool has_more;

    try {
        has_more = m_socket->do_send();
    } catch(const network::socket_error &e) {
        LOG(WARNING) << "Failed to send data to " << m_socket->get_remote_address() << e.what();

        has_more = false;

        lock.unlock();
        close_socket();
    }

    if(!has_more && is_valid())
    {
        this->set_mode(EventListener::Mode::ReadOnly);
    }
}

void NetworkSocketListener::send(std::unique_ptr<uint8_t[]> &&data, size_t length, bool blocking)
{
    std::unique_lock lock(m_send_mutex);

    bool has_more;

    while(true) {
        try {
            has_more = m_socket->send(std::move(data), length);
            break;
        } catch(const network::socket_error &e) {
            LOG(ERROR) << e.what();
            has_more = false;
            break;
        } catch(const network::send_queue_full&) {
            if(blocking)
            {
                LOG(WARNING) << "Send queue to " << m_socket->get_remote_address() << " is full. Thread is blocking...";
                m_socket->wait_send_queue_empty();
            }
            else
            {
                LOG(ERROR) << "Failed to send data to " << m_socket->get_remote_address() << ": send queue is full";
                has_more = false;
                close_socket();
                break;
            }
        }
    }

    if(is_valid())
    {
        if(has_more)
        {
            set_mode(Mode::ReadWrite);
        }
        else
        {
            set_mode(Mode::ReadOnly);
        }
    }
    else
    {
        // Tell event loop connection was lost or terminated
        auto &el = EventLoop::get_instance();
        el.unregister_event_listener(shared_from_this());
    }
}

void NetworkSocketListener::send(const uint8_t *data, size_t length, bool blocking)
{
    std::unique_lock lock(m_send_mutex);

    bool has_more;

    while(true) {
        try {
            has_more = m_socket->send(data, length);
            break;
        } catch(const network::socket_error &e) {
            LOG(ERROR) << e.what();
            has_more = false;
            break;
        } catch(const network::send_queue_full&) {
            if(blocking)
            {
                LOG(WARNING) << "Send queue to " << m_socket->get_remote_address() << " is full. Thread is blocking...";
                m_socket->wait_send_queue_empty();
            }
            else
            {
                LOG(ERROR) << "Failed to send data to " << m_socket->get_remote_address() << ": send queue is full";
                has_more = false;
                close_socket();
                break;
            }
        }
    }

    if(is_valid())
    {
        if(has_more)
        {
            set_mode(Mode::ReadWrite);
        }
        else
        {
            set_mode(Mode::ReadOnly);
        }
    }
    else
    {
        // Tell event loop connection was lost or terminated
        auto &el = EventLoop::get_instance();
        el.unregister_event_listener(shared_from_this());
    }
}

void NetworkSocketListener::wait_for_connection()
{
    while(!is_connected())
    {
        if(!m_socket)
        {
            // busy wait while socket doesn't exist
            continue;
        }

        if(m_socket->is_listening())
        {
            throw std::runtime_error("Cannot wait for connection. Is listening.");
        }

        m_socket->wait_connection_established();
    }
}

void NetworkSocketListener::on_error()
{
    LOG(WARNING) << "Got error; closing socket";
    close_socket();
}

void NetworkSocketListener::on_read_ready()
{
    std::unique_lock lock(m_mutex);

    switch(m_socket_type)
    {
    case SocketType::Acceptor:
    {
        auto result = m_socket->accept();
        lock.unlock();

        for(auto &s: result)
        {
            this->on_new_connection(std::move(s));
        }

        break;
    }
    case SocketType::Connection:
    {
        try
        {
            while(m_socket)
            {
                auto message = m_socket->receive();

                if(message)
                {
                    lock.unlock();
                    this->on_network_message(*message);
                    lock.lock();
                }
                else
                {
                    // no more data
                    break;
                }
            }
        }
        catch (const network::socket_error &e)
        {
            LOG(WARNING) << e.what();
        }

        // After processing the last message we will notify the user that the socket is closed
        if(m_socket && !m_socket->is_valid())
        {
            close_socket_internal(lock);
        }

        break;
    }
    default:
        throw std::runtime_error("Unknown socket type!");
    }

}

void NetworkSocketListener::close_socket_internal(std::unique_lock<std::mutex> &lock)
{
    // make sure we invoke the callback at most once
    if(m_has_disconnected)
    {
        //ignore
        return;
    }

    m_has_disconnected = true;

    if(m_socket)
    {
        bool done = m_socket->close();
        lock.unlock();

        if(done)
        {
            if(m_socket_type == SocketType::Connection)
            {
                this->on_disconnect();
            }
            else if(EventLoop::is_initialized())
            {
                try {
                    auto &el = EventLoop::get_instance();
                    el.unregister_event_listener(shared_from_this());
                } catch(const std::runtime_error&) {
                    // can happen during shutdown
                    // ignore...
                }
            }
        }
    }
}

int32_t NetworkSocketListener::get_fileno() const
{
    return m_fileno;
}
<commit_msg>Fix deadlock<commit_after>#include "yael/NetworkSocketListener.h"
#include "yael/EventLoop.h"

using namespace yael;

NetworkSocketListener::NetworkSocketListener()
    : EventListener(EventListener::Mode::ReadOnly), m_socket(nullptr), m_fileno(-1)
{
}

NetworkSocketListener::NetworkSocketListener(std::unique_ptr<network::Socket> &&socket, SocketType type)
    : EventListener(EventListener::Mode::ReadOnly), m_socket(nullptr), m_socket_type(SocketType::None), m_fileno(-1)
{
    if(socket)
    {
        NetworkSocketListener::set_socket(std::forward<std::unique_ptr<network::Socket>>(socket), type);

        m_socket->wait_connection_established();
    }
}

std::unique_ptr<network::Socket> NetworkSocketListener::release_socket()
{
    std::unique_lock lock(m_mutex);

    // Move socket before we unregistered so socket doesn't get closed
    auto sock = std::move(m_socket);

    ///FIXME we should tell event listener to remap the socket
    // the current approach can cause race conditions...
    auto &el = EventLoop::get_instance();
    el.unregister_event_listener(std::dynamic_pointer_cast<EventListener>(shared_from_this()));

    return sock;
}

void NetworkSocketListener::set_socket(std::unique_ptr<network::Socket> &&socket, SocketType type)
{
    std::unique_lock lock(m_mutex);

    if(m_socket)
    {
        throw std::runtime_error("There is already a socket assigned to this listener!");
    }

    if(!socket->is_valid())
    {
        throw std::runtime_error("Not a valid socket!");
    }

    m_socket = std::move(socket);
    m_socket_type = type;
    m_fileno = m_socket->get_fileno();
}

bool NetworkSocketListener::is_valid()
{
    std::unique_lock lock(m_mutex);

    if(!m_socket)
    {
        return false;
    }

    return m_socket->is_valid();
}

bool NetworkSocketListener::is_connected()
{
    std::unique_lock lock(m_mutex);

    if(!m_socket)
    {
        return false;
    }

    return m_socket->is_connected();
}

void NetworkSocketListener::on_write_ready()
{
    std::unique_lock lock(m_send_mutex);

    bool has_more;

    try {
        has_more = m_socket->do_send();
    } catch(const network::socket_error &e) {
        LOG(WARNING) << "Failed to send data to " << m_socket->get_remote_address() << e.what();

        has_more = false;

        lock.unlock();
        close_socket();
    }

    if(!has_more && is_valid())
    {
        this->set_mode(EventListener::Mode::ReadOnly);
    }
}

void NetworkSocketListener::send(std::unique_ptr<uint8_t[]> &&data, size_t length, bool blocking)
{
    std::unique_lock lock(m_send_mutex);

    bool has_more;

    while(true) {
        try {
            has_more = m_socket->send(std::move(data), length);
            break;
        } catch(const network::socket_error &e) {
            LOG(ERROR) << e.what();
            has_more = false;
            break;
        } catch(const network::send_queue_full&) {
            if(blocking)
            {
                LOG(WARNING) << "Send queue to " << m_socket->get_remote_address() << " is full. Thread is blocking...";
                m_socket->wait_send_queue_empty();
            }
            else
            {
                LOG(ERROR) << "Failed to send data to " << m_socket->get_remote_address() << ": send queue is full";
                has_more = false;
                close_socket();
                break;
            }
        }
    }

    if(is_valid())
    {
        if(has_more)
        {
            set_mode(Mode::ReadWrite);
        }
        else
        {
            set_mode(Mode::ReadOnly);
        }
    }
    else
    {
        // Tell event loop connection was lost or terminated
        auto &el = EventLoop::get_instance();
        el.unregister_event_listener(shared_from_this());
    }
}

void NetworkSocketListener::send(const uint8_t *data, size_t length, bool blocking)
{
    std::unique_lock lock(m_send_mutex);

    bool has_more;

    while(true) {
        try {
            has_more = m_socket->send(data, length);
            break;
        }
        catch(const network::socket_error &e)
        {
            LOG(ERROR) << e.what();
            has_more = false;
            break;
        }
        catch(const network::send_queue_full&)
        {
            if(blocking)
            {
                LOG(WARNING) << "Send queue to " << m_socket->get_remote_address() << " is full. Thread is blocking...";

                lock.unlock();
                m_socket->wait_send_queue_empty();
                lock.lock();
            }
            else
            {
                LOG(ERROR) << "Failed to send data to " << m_socket->get_remote_address() << ": send queue is full";
                has_more = false;
                close_socket();
                break;
            }
        }
    }

    if(is_valid())
    {
        if(has_more)
        {
            set_mode(Mode::ReadWrite);
        }
        else
        {
            set_mode(Mode::ReadOnly);
        }
    }
    else
    {
        // Tell event loop connection was lost or terminated
        auto &el = EventLoop::get_instance();
        el.unregister_event_listener(shared_from_this());
    }
}

void NetworkSocketListener::wait_for_connection()
{
    while(!is_connected())
    {
        if(!m_socket)
        {
            // busy wait while socket doesn't exist
            continue;
        }

        if(m_socket->is_listening())
        {
            throw std::runtime_error("Cannot wait for connection. Is listening.");
        }

        m_socket->wait_connection_established();
    }
}

void NetworkSocketListener::on_error()
{
    LOG(WARNING) << "Got error; closing socket";
    close_socket();
}

void NetworkSocketListener::on_read_ready()
{
    std::unique_lock lock(m_mutex);

    switch(m_socket_type)
    {
    case SocketType::Acceptor:
    {
        auto result = m_socket->accept();
        lock.unlock();

        for(auto &s: result)
        {
            this->on_new_connection(std::move(s));
        }

        break;
    }
    case SocketType::Connection:
    {
        try
        {
            while(m_socket)
            {
                auto message = m_socket->receive();

                if(message)
                {
                    lock.unlock();
                    this->on_network_message(*message);
                    lock.lock();
                }
                else
                {
                    // no more data
                    break;
                }
            }
        }
        catch (const network::socket_error &e)
        {
            LOG(WARNING) << e.what();
        }

        // After processing the last message we will notify the user that the socket is closed
        if(m_socket && !m_socket->is_valid())
        {
            close_socket_internal(lock);
        }

        break;
    }
    default:
        throw std::runtime_error("Unknown socket type!");
    }

}

void NetworkSocketListener::close_socket_internal(std::unique_lock<std::mutex> &lock)
{
    // make sure we invoke the callback at most once
    if(m_has_disconnected)
    {
        //ignore
        return;
    }

    m_has_disconnected = true;

    if(m_socket)
    {
        bool done = m_socket->close();
        lock.unlock();

        if(done)
        {
            if(m_socket_type == SocketType::Connection)
            {
                this->on_disconnect();
            }
            else if(EventLoop::is_initialized())
            {
                try {
                    auto &el = EventLoop::get_instance();
                    el.unregister_event_listener(shared_from_this());
                } catch(const std::runtime_error&) {
                    // can happen during shutdown
                    // ignore...
                }
            }
        }
    }
}

int32_t NetworkSocketListener::get_fileno() const
{
    return m_fileno;
}
<|endoftext|>


<commit_before>//===-- SparcJITInfo.cpp - Implement the Sparc JIT Interface --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the JIT interfaces for the Sparc target.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "jit"
#include "SparcJITInfo.h"
#include "SparcRelocations.h"

#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/Support/Memory.h"

using namespace llvm;

/// JITCompilerFunction - This contains the address of the JIT function used to
/// compile a function lazily.
static TargetJITInfo::JITCompilerFn JITCompilerFunction;

extern "C" void SparcCompilationCallback();

extern "C" {
#if defined (__sparc__)
  asm(
      ".text\n"
      "\t.align 4\n"
      "\t.global SparcCompilationCallback\n"
      "\t.type SparcCompilationCallback, #function\n"
      "SparcCompilationCallback:\n"
      // Save current register window.
      "\tsave %sp, -192, %sp\n"
      // stubaddr+4 is in %g1.
      "\tcall SparcCompilationCallbackC\n"
      "\t  sub %g1, 4, %o0\n"
      // restore original register window and
      // copy %o0 to %g1
      "\t  restore %o0, 0, %g1\n"
      // call the new stub
      "\tjmp %g1\n"
      "\t  nop\n"
      "\t.size   SparcCompilationCallback, .-SparcCompilationCallback"
      );

#else
  void SparcCompilationCallback() {
    llvm_unreachable(
      "Cannot call SparcCompilationCallback() on a non-sparc arch!");
  }
#endif
}

#define HI(Val) (((unsigned)(Val)) >> 10)
#define LO(Val) (((unsigned)(Val)) & 0x3FF)

#define SETHI_INST(imm, rd)    (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF))
#define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \
                                | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
#define NOP_INST               SETHI_INST(0, 0)

extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) {
  // Get the address of the compiled code for this function.
  intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);

  // Rewrite the function stub so that we don't end up here every time we
  // execute the call. We're replacing the first three instructions of the
  // stub with code that jumps to the compiled function:
  //   sethi %hi(NewVal), %g1
  //   jmp %g1+%lo(NewVal)
  //   nop

  *(intptr_t *)(StubAddr)      = SETHI_INST(HI(NewVal), 1);
  *(intptr_t *)(StubAddr + 4)  = JMP_INST(1, LO(NewVal), 0);
  *(intptr_t *)(StubAddr + 8)  = NOP_INST;

  sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12);
  return (void*)StubAddr;
}

void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
  assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction");
}

TargetJITInfo::StubLayout SparcJITInfo::getStubLayout() {
  // The stub contains 3 4-byte instructions, aligned at 4 bytes. See
  // emitFunctionStub for details.

  StubLayout Result = { 3*4, 4 };
  return Result;
}

void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn,
                                     JITCodeEmitter &JCE)
{
  JCE.emitAlignment(4);
  void *Addr = (void*) (JCE.getCurrentPCValue());
  if (!sys::Memory::setRangeWritable(Addr, 12))
    llvm_unreachable("ERROR: Unable to mark stub writable.");

  intptr_t EmittedAddr;
  if (Fn != (void*)(intptr_t)SparcCompilationCallback)
    EmittedAddr = (intptr_t)Fn;
  else
    EmittedAddr = (intptr_t)SparcCompilationCallback;

  // sethi %hi(EmittedAddr), %g1
  // jmp   %g1+%lo(EmittedAddr), %g1
  // nop

  JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1));
  JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1));
  JCE.emitWordBE(NOP_INST);

  sys::Memory::InvalidateInstructionCache(Addr, 12);
  if (!sys::Memory::setRangeExecutable(Addr, 12))
    llvm_unreachable("ERROR: Unable to mark stub executable.");

  return Addr;
}

TargetJITInfo::LazyResolverFn
SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) {
  JITCompilerFunction = F;
  return SparcCompilationCallback;
}

/// relocate - Before the JIT can run a block of code that has been emitted,
/// it must rewrite the code to contain the actual addresses of any
/// referenced global symbols.
void SparcJITInfo::relocate(void *Function, MachineRelocation *MR,
                            unsigned NumRelocs, unsigned char *GOTBase) {
  for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
    void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
    intptr_t ResultPtr = (intptr_t) MR->getResultPointer();

    switch ((SP::RelocationType) MR->getRelocationType()) {
    default: llvm_unreachable("Unknown reloc!");
    case SP::reloc_sparc_hi:
      ResultPtr = (ResultPtr >> 10) & 0x3fffff;
      break;

    case SP::reloc_sparc_lo:
      ResultPtr = (ResultPtr & 0x3ff);
      break;

    case SP::reloc_sparc_pc30:
      ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffffff;
      break;

    case SP::reloc_sparc_pc22:
      ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffff;
      break;

    case SP::reloc_sparc_pc19:
      ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff;
      break;
    }
    *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
  }
}

<commit_msg>Prune trailing linefeeds.<commit_after>//===-- SparcJITInfo.cpp - Implement the Sparc JIT Interface --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the JIT interfaces for the Sparc target.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "jit"
#include "SparcJITInfo.h"
#include "SparcRelocations.h"

#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/Support/Memory.h"

using namespace llvm;

/// JITCompilerFunction - This contains the address of the JIT function used to
/// compile a function lazily.
static TargetJITInfo::JITCompilerFn JITCompilerFunction;

extern "C" void SparcCompilationCallback();

extern "C" {
#if defined (__sparc__)
  asm(
      ".text\n"
      "\t.align 4\n"
      "\t.global SparcCompilationCallback\n"
      "\t.type SparcCompilationCallback, #function\n"
      "SparcCompilationCallback:\n"
      // Save current register window.
      "\tsave %sp, -192, %sp\n"
      // stubaddr+4 is in %g1.
      "\tcall SparcCompilationCallbackC\n"
      "\t  sub %g1, 4, %o0\n"
      // restore original register window and
      // copy %o0 to %g1
      "\t  restore %o0, 0, %g1\n"
      // call the new stub
      "\tjmp %g1\n"
      "\t  nop\n"
      "\t.size   SparcCompilationCallback, .-SparcCompilationCallback"
      );

#else
  void SparcCompilationCallback() {
    llvm_unreachable(
      "Cannot call SparcCompilationCallback() on a non-sparc arch!");
  }
#endif
}

#define HI(Val) (((unsigned)(Val)) >> 10)
#define LO(Val) (((unsigned)(Val)) & 0x3FF)

#define SETHI_INST(imm, rd)    (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF))
#define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \
                                | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
#define NOP_INST               SETHI_INST(0, 0)

extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) {
  // Get the address of the compiled code for this function.
  intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);

  // Rewrite the function stub so that we don't end up here every time we
  // execute the call. We're replacing the first three instructions of the
  // stub with code that jumps to the compiled function:
  //   sethi %hi(NewVal), %g1
  //   jmp %g1+%lo(NewVal)
  //   nop

  *(intptr_t *)(StubAddr)      = SETHI_INST(HI(NewVal), 1);
  *(intptr_t *)(StubAddr + 4)  = JMP_INST(1, LO(NewVal), 0);
  *(intptr_t *)(StubAddr + 8)  = NOP_INST;

  sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12);
  return (void*)StubAddr;
}

void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
  assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction");
}

TargetJITInfo::StubLayout SparcJITInfo::getStubLayout() {
  // The stub contains 3 4-byte instructions, aligned at 4 bytes. See
  // emitFunctionStub for details.

  StubLayout Result = { 3*4, 4 };
  return Result;
}

void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn,
                                     JITCodeEmitter &JCE)
{
  JCE.emitAlignment(4);
  void *Addr = (void*) (JCE.getCurrentPCValue());
  if (!sys::Memory::setRangeWritable(Addr, 12))
    llvm_unreachable("ERROR: Unable to mark stub writable.");

  intptr_t EmittedAddr;
  if (Fn != (void*)(intptr_t)SparcCompilationCallback)
    EmittedAddr = (intptr_t)Fn;
  else
    EmittedAddr = (intptr_t)SparcCompilationCallback;

  // sethi %hi(EmittedAddr), %g1
  // jmp   %g1+%lo(EmittedAddr), %g1
  // nop

  JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1));
  JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1));
  JCE.emitWordBE(NOP_INST);

  sys::Memory::InvalidateInstructionCache(Addr, 12);
  if (!sys::Memory::setRangeExecutable(Addr, 12))
    llvm_unreachable("ERROR: Unable to mark stub executable.");

  return Addr;
}

TargetJITInfo::LazyResolverFn
SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) {
  JITCompilerFunction = F;
  return SparcCompilationCallback;
}

/// relocate - Before the JIT can run a block of code that has been emitted,
/// it must rewrite the code to contain the actual addresses of any
/// referenced global symbols.
void SparcJITInfo::relocate(void *Function, MachineRelocation *MR,
                            unsigned NumRelocs, unsigned char *GOTBase) {
  for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
    void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
    intptr_t ResultPtr = (intptr_t) MR->getResultPointer();

    switch ((SP::RelocationType) MR->getRelocationType()) {
    default: llvm_unreachable("Unknown reloc!");
    case SP::reloc_sparc_hi:
      ResultPtr = (ResultPtr >> 10) & 0x3fffff;
      break;

    case SP::reloc_sparc_lo:
      ResultPtr = (ResultPtr & 0x3ff);
      break;

    case SP::reloc_sparc_pc30:
      ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffffff;
      break;

    case SP::reloc_sparc_pc22:
      ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffff;
      break;

    case SP::reloc_sparc_pc19:
      ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff;
      break;
    }
    *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
  }
}
<|endoftext|>


<commit_before>//===- TargetRegisterInfo.cpp - Target Register Information Implementation ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TargetRegisterInfo interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/ADT/BitVector.h"

using namespace llvm;

TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR,
                             regclass_iterator RCB, regclass_iterator RCE,
                             const char *const *subregindexnames,
                             int CFSO, int CFDO,
                             const unsigned* subregs, const unsigned subregsize,
                         const unsigned* aliases, const unsigned aliasessize)
  : SubregHash(subregs), SubregHashSize(subregsize),
    AliasesHash(aliases), AliasesHashSize(aliasessize),
    Desc(D), SubRegIndexNames(subregindexnames), NumRegs(NR),
    RegClassBegin(RCB), RegClassEnd(RCE) {
  assert(NumRegs < FirstVirtualRegister &&
         "Target has too many physical registers!");

  CallFrameSetupOpcode   = CFSO;
  CallFrameDestroyOpcode = CFDO;
}

TargetRegisterInfo::~TargetRegisterInfo() {}

/// getMinimalPhysRegClass - Returns the Register Class of a physical
/// register of the given type, picking the most sub register class of
/// the right type that contains this physreg.
const TargetRegisterClass *
TargetRegisterInfo::getMinimalPhysRegClass(unsigned reg, EVT VT) const {
  assert(isPhysicalRegister(reg) && "reg must be a physical register");

  // Pick the most sub register class of the right type that contains
  // this physreg.
  const TargetRegisterClass* BestRC = 0;
  for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; ++I){
    const TargetRegisterClass* RC = *I;
    if ((VT == MVT::Other || RC->hasType(VT)) && RC->contains(reg) &&
        (!BestRC || BestRC->hasSubClass(RC)))
      BestRC = RC;
  }

  assert(BestRC && "Couldn't find the register class");
  return BestRC;
}

/// getAllocatableSetForRC - Toggle the bits that represent allocatable
/// registers for the specific register class.
static void getAllocatableSetForRC(const MachineFunction &MF,
                                   const TargetRegisterClass *RC, BitVector &R){
  for (TargetRegisterClass::iterator I = RC->allocation_order_begin(MF),
         E = RC->allocation_order_end(MF); I != E; ++I)
    R.set(*I);
}

BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF,
                                          const TargetRegisterClass *RC) const {
  BitVector Allocatable(NumRegs);
  if (RC) {
    getAllocatableSetForRC(MF, RC, Allocatable);
  } else {
    for (TargetRegisterInfo::regclass_iterator I = regclass_begin(),
         E = regclass_end(); I != E; ++I)
      getAllocatableSetForRC(MF, *I, Allocatable);
  }

  // Mask out the reserved registers
  BitVector Reserved = getReservedRegs(MF);
  Allocatable ^= Reserved & Allocatable;

  return Allocatable;
}

/// getFrameIndexOffset - Returns the displacement from the frame register to
/// the stack frame of the specified index. This is the default implementation
/// which is overridden for some targets.
int TargetRegisterInfo::getFrameIndexOffset(const MachineFunction &MF,
                                            int FI) const {
  const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  return MFI->getObjectOffset(FI) + MFI->getStackSize() -
    TFI.getOffsetOfLocalArea() + MFI->getOffsetAdjustment();
}

/// getInitialFrameState - Returns a list of machine moves that are assumed
/// on entry to a function.
void
TargetRegisterInfo::getInitialFrameState(std::vector<MachineMove> &Moves) const{
  // Default is to do nothing.
}

const TargetRegisterClass *
llvm::getCommonSubClass(const TargetRegisterClass *A,
                        const TargetRegisterClass *B) {
  // First take care of the trivial cases
  if (A == B)
    return A;
  if (!A || !B)
    return 0;

  // If B is a subclass of A, it will be handled in the loop below
  if (B->hasSubClass(A))
    return A;

  const TargetRegisterClass *Best = 0;
  for (TargetRegisterClass::sc_iterator I = A->subclasses_begin();
       const TargetRegisterClass *X = *I; ++I) {
    if (X == B)
      return B;                 // B is a subclass of A

    // X must be a common subclass of A and B
    if (!B->hasSubClass(X))
      continue;

    // A superclass is definitely better.
    if (!Best || Best->hasSuperClass(X)) {
      Best = X;
      continue;
    }

    // A subclass is definitely worse
    if (Best->hasSubClass(X))
      continue;

    // Best and *I have no super/sub class relation - pick the larger class, or
    // the smaller spill size.
    int nb = std::distance(Best->begin(), Best->end());
    int ni = std::distance(X->begin(), X->end());
    if (ni>nb || (ni==nb && X->getSize() < Best->getSize()))
      Best = X;
  }
  return Best;
}
<commit_msg>remove trailing whitespace<commit_after>//===- TargetRegisterInfo.cpp - Target Register Information Implementation ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TargetRegisterInfo interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/ADT/BitVector.h"

using namespace llvm;

TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR,
                             regclass_iterator RCB, regclass_iterator RCE,
                             const char *const *subregindexnames,
                             int CFSO, int CFDO,
                             const unsigned* subregs, const unsigned subregsize,
                         const unsigned* aliases, const unsigned aliasessize)
  : SubregHash(subregs), SubregHashSize(subregsize),
    AliasesHash(aliases), AliasesHashSize(aliasessize),
    Desc(D), SubRegIndexNames(subregindexnames), NumRegs(NR),
    RegClassBegin(RCB), RegClassEnd(RCE) {
  assert(NumRegs < FirstVirtualRegister &&
         "Target has too many physical registers!");

  CallFrameSetupOpcode   = CFSO;
  CallFrameDestroyOpcode = CFDO;
}

TargetRegisterInfo::~TargetRegisterInfo() {}

/// getMinimalPhysRegClass - Returns the Register Class of a physical
/// register of the given type, picking the most sub register class of
/// the right type that contains this physreg.
const TargetRegisterClass *
TargetRegisterInfo::getMinimalPhysRegClass(unsigned reg, EVT VT) const {
  assert(isPhysicalRegister(reg) && "reg must be a physical register");

  // Pick the most sub register class of the right type that contains
  // this physreg.
  const TargetRegisterClass* BestRC = 0;
  for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; ++I){
    const TargetRegisterClass* RC = *I;
    if ((VT == MVT::Other || RC->hasType(VT)) && RC->contains(reg) &&
        (!BestRC || BestRC->hasSubClass(RC)))
      BestRC = RC;
  }

  assert(BestRC && "Couldn't find the register class");
  return BestRC;
}

/// getAllocatableSetForRC - Toggle the bits that represent allocatable
/// registers for the specific register class.
static void getAllocatableSetForRC(const MachineFunction &MF,
                                   const TargetRegisterClass *RC, BitVector &R){
  for (TargetRegisterClass::iterator I = RC->allocation_order_begin(MF),
         E = RC->allocation_order_end(MF); I != E; ++I)
    R.set(*I);
}

BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF,
                                          const TargetRegisterClass *RC) const {
  BitVector Allocatable(NumRegs);
  if (RC) {
    getAllocatableSetForRC(MF, RC, Allocatable);
  } else {
    for (TargetRegisterInfo::regclass_iterator I = regclass_begin(),
         E = regclass_end(); I != E; ++I)
      getAllocatableSetForRC(MF, *I, Allocatable);
  }

  // Mask out the reserved registers
  BitVector Reserved = getReservedRegs(MF);
  Allocatable ^= Reserved & Allocatable;

  return Allocatable;
}

/// getFrameIndexOffset - Returns the displacement from the frame register to
/// the stack frame of the specified index. This is the default implementation
/// which is overridden for some targets.
int TargetRegisterInfo::getFrameIndexOffset(const MachineFunction &MF,
                                            int FI) const {
  const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  return MFI->getObjectOffset(FI) + MFI->getStackSize() -
    TFI.getOffsetOfLocalArea() + MFI->getOffsetAdjustment();
}

/// getInitialFrameState - Returns a list of machine moves that are assumed
/// on entry to a function.
void
TargetRegisterInfo::getInitialFrameState(std::vector<MachineMove> &Moves) const{
  // Default is to do nothing.
}

const TargetRegisterClass *
llvm::getCommonSubClass(const TargetRegisterClass *A,
                        const TargetRegisterClass *B) {
  // First take care of the trivial cases
  if (A == B)
    return A;
  if (!A || !B)
    return 0;

  // If B is a subclass of A, it will be handled in the loop below
  if (B->hasSubClass(A))
    return A;

  const TargetRegisterClass *Best = 0;
  for (TargetRegisterClass::sc_iterator I = A->subclasses_begin();
       const TargetRegisterClass *X = *I; ++I) {
    if (X == B)
      return B;                 // B is a subclass of A

    // X must be a common subclass of A and B
    if (!B->hasSubClass(X))
      continue;

    // A superclass is definitely better.
    if (!Best || Best->hasSuperClass(X)) {
      Best = X;
      continue;
    }

    // A subclass is definitely worse
    if (Best->hasSubClass(X))
      continue;

    // Best and *I have no super/sub class relation - pick the larger class, or
    // the smaller spill size.
    int nb = std::distance(Best->begin(), Best->end());
    int ni = std::distance(X->begin(), X->end());
    if (ni>nb || (ni==nb && X->getSize() < Best->getSize()))
      Best = X;
  }
  return Best;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Lukasz Janyst <ljanyst@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Utils/SourceNormalization.h"

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"

#include <utility>

using namespace clang;

namespace {
///\brief A Lexer that exposes preprocessor directives.
class MinimalPPLexer: public Lexer {
public:
  ///\brief Construct a Lexer from LangOpts and source.
  MinimalPPLexer(const LangOptions &LangOpts, llvm::StringRef source):
    Lexer(SourceLocation(), LangOpts,
          source.begin(), source.begin(), source.end()) {}

  bool inPPDirective() const { return ParsingPreprocessorDirective; }

  ///\brief Lex, forwarding to Lexer::LexFromRawLexer, and keeping track of
  /// preprocessor directives to provide a tok::eod corresponding to a
  /// tok::hash.
  bool Lex(Token& Tok) {
    bool ret = LexFromRawLexer(Tok);
    if (inPPDirective()) {
      // Saw a PP directive; probe for eod to end PP parsing mode.
      if (Tok.is(tok::eod))
        ParsingPreprocessorDirective = false;
    } else {
      if (Tok.is(tok::hash)) {
        // Found a PP directive, request tok::eod to be generated.
        ParsingPreprocessorDirective = true;
      }
    }
    return ret;
  }

  ///\brief Advance to token with given token kind.
  ///
  /// \param Tok - Token to advance.
  /// \param kind - Token kind where to stop lexing.
  /// \return - Result of most recent call to Lex().
  bool AdvanceTo(Token& Tok, tok::TokenKind kind) {
    while (!Lex(Tok)) {
      if (Tok.is(kind))
        return false;
    }
    return true;
  }
};

size_t getFileOffset(const Token& Tok) {
  return Tok.getLocation().getRawEncoding();
}

}

size_t
cling::utils::isUnnamedMacro(llvm::StringRef source,
                             clang::LangOptions& LangOpts) {
  // Find the first token that is not a non-cpp directive nor a comment.
  // If that token is a '{' we have an unnamed macro.

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;
  bool AfterHash = false;
  while (true) {
    bool atEOF = Lex.Lex(Tok);

    if (atEOF)
      return std::string::npos;

    if (Lex.inPPDirective() || Tok.is(tok::eod)) {
      if (AfterHash) {
        if (Tok.is(tok::raw_identifier)) {
          StringRef keyword(Tok.getRawIdentifier());
          if (keyword.startswith("if")) {
            // This could well be
            //   #if FOO
            //   {
            // where we would determine this to be an unnamed macro and replace
            // '{' by ' ', whether FOO is #defined or not. Instead, assume that
            // this is not an unnamed macro and we need to parse it as is.
            return std::string::npos;
          }
        }
        AfterHash = false;
      } else
        AfterHash = Tok.is(tok::hash);

      continue; // Skip PP directives.
    }

    if (Tok.is(tok::l_brace))
      return getFileOffset(Tok);

    if (Tok.is(tok::comment))
      continue; // ignore comments

    return std::string::npos;
  }

  // Empty file?

  return std::string::npos;
}

size_t cling::utils::getWrapPoint(std::string& source,
                                  const clang::LangOptions& LangOpts) {
  // TODO: For future reference.
  // Parser* P = const_cast<clang::Parser*>(m_IncrParser->getParser());
  // Parser::TentativeParsingAction TA(P);
  // TPResult result = P->isCXXDeclarationSpecifier();
  // TA.Revert();
  // return result == TPResult::True();

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;

  //size_t wrapPoint = 0;

  while (true) {
    bool atEOF = Lex.Lex(Tok);
    if (Lex.inPPDirective() || Tok.is(tok::eod)) {
      //wrapPoint = getFileOffset(Tok);
      if (atEOF)
        break;
      continue; // Skip PP directives; they just move the wrap point.
    }

    const tok::TokenKind kind = Tok.getKind();

    if (kind == tok::raw_identifier && !Tok.needsCleaning()) {
      StringRef keyword(Tok.getRawIdentifier());
      if (keyword.equals("using")) {
        // FIXME: Using definitions and declarations should be decl extracted.
        // Until we have that, don't wrap them if they are the only input.
        if (Lex.AdvanceTo(Tok, tok::semi)) {
          // EOF while looking for semi. Don't wrap.
          return std::string::npos;
        }
        // There is "more" - let's assume this input consists of a using
        // declaration or definition plus some code that should be wrapped.
        return getFileOffset(Tok);
      }
      if (keyword.equals("extern"))
        return std::string::npos;
      if (keyword.equals("namespace"))
        return std::string::npos;
      if (keyword.equals("template"))
        return std::string::npos;

      // There is something else here that needs to be wrapped.
      return getFileOffset(Tok);
    }

    // FIXME: in the future, continue lexing to extract relevant PP directives;
    // return wrapPoint
    // There is something else here that needs to be wrapped.
    return getFileOffset(Tok);
  }

  // We have only had PP directives; no need to wrap.
  return std::string::npos;
}
<commit_msg>No need to wrap if EOF, possibly after preproc (ROOT-8325).<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Lukasz Janyst <ljanyst@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Utils/SourceNormalization.h"

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"

#include <utility>

using namespace clang;

namespace {
///\brief A Lexer that exposes preprocessor directives.
class MinimalPPLexer: public Lexer {
public:
  ///\brief Construct a Lexer from LangOpts and source.
  MinimalPPLexer(const LangOptions &LangOpts, llvm::StringRef source):
    Lexer(SourceLocation(), LangOpts,
          source.begin(), source.begin(), source.end()) {}

  bool inPPDirective() const { return ParsingPreprocessorDirective; }

  ///\brief Lex, forwarding to Lexer::LexFromRawLexer, and keeping track of
  /// preprocessor directives to provide a tok::eod corresponding to a
  /// tok::hash.
  bool Lex(Token& Tok) {
    bool ret = LexFromRawLexer(Tok);
    if (inPPDirective()) {
      // Saw a PP directive; probe for eod to end PP parsing mode.
      if (Tok.is(tok::eod))
        ParsingPreprocessorDirective = false;
    } else {
      if (Tok.is(tok::hash)) {
        // Found a PP directive, request tok::eod to be generated.
        ParsingPreprocessorDirective = true;
      }
    }
    return ret;
  }

  ///\brief Advance to token with given token kind.
  ///
  /// \param Tok - Token to advance.
  /// \param kind - Token kind where to stop lexing.
  /// \return - Result of most recent call to Lex().
  bool AdvanceTo(Token& Tok, tok::TokenKind kind) {
    while (!Lex(Tok)) {
      if (Tok.is(kind))
        return false;
    }
    return true;
  }
};

size_t getFileOffset(const Token& Tok) {
  return Tok.getLocation().getRawEncoding();
}

}

size_t
cling::utils::isUnnamedMacro(llvm::StringRef source,
                             clang::LangOptions& LangOpts) {
  // Find the first token that is not a non-cpp directive nor a comment.
  // If that token is a '{' we have an unnamed macro.

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;
  bool AfterHash = false;
  while (true) {
    bool atEOF = Lex.Lex(Tok);

    if (atEOF)
      return std::string::npos;

    if (Lex.inPPDirective() || Tok.is(tok::eod)) {
      if (AfterHash) {
        if (Tok.is(tok::raw_identifier)) {
          StringRef keyword(Tok.getRawIdentifier());
          if (keyword.startswith("if")) {
            // This could well be
            //   #if FOO
            //   {
            // where we would determine this to be an unnamed macro and replace
            // '{' by ' ', whether FOO is #defined or not. Instead, assume that
            // this is not an unnamed macro and we need to parse it as is.
            return std::string::npos;
          }
        }
        AfterHash = false;
      } else
        AfterHash = Tok.is(tok::hash);

      continue; // Skip PP directives.
    }

    if (Tok.is(tok::l_brace))
      return getFileOffset(Tok);

    if (Tok.is(tok::comment))
      continue; // ignore comments

    return std::string::npos;
  }

  // Empty file?

  return std::string::npos;
}

size_t cling::utils::getWrapPoint(std::string& source,
                                  const clang::LangOptions& LangOpts) {
  // TODO: For future reference.
  // Parser* P = const_cast<clang::Parser*>(m_IncrParser->getParser());
  // Parser::TentativeParsingAction TA(P);
  // TPResult result = P->isCXXDeclarationSpecifier();
  // TA.Revert();
  // return result == TPResult::True();

  MinimalPPLexer Lex(LangOpts, source);
  Token Tok;

  //size_t wrapPoint = 0;

  while (true) {
    bool atEOF = Lex.Lex(Tok);
    if (Lex.inPPDirective() || Tok.is(tok::eod)) {
      //wrapPoint = getFileOffset(Tok);
      if (atEOF)
        break;
      continue; // Skip PP directives; they just move the wrap point.
    }

    if (Tok.is(tok::eof)) {
      // Reached EOF before seeing a non-preproc token.
      // Nothing to wrap.
      return std::string::npos;
    }

    const tok::TokenKind kind = Tok.getKind();

    if (kind == tok::raw_identifier && !Tok.needsCleaning()) {
      StringRef keyword(Tok.getRawIdentifier());
      if (keyword.equals("using")) {
        // FIXME: Using definitions and declarations should be decl extracted.
        // Until we have that, don't wrap them if they are the only input.
        if (Lex.AdvanceTo(Tok, tok::semi)) {
          // EOF while looking for semi. Don't wrap.
          return std::string::npos;
        }
        // There is "more" - let's assume this input consists of a using
        // declaration or definition plus some code that should be wrapped.
        return getFileOffset(Tok);
      }
      if (keyword.equals("extern"))
        return std::string::npos;
      if (keyword.equals("namespace"))
        return std::string::npos;
      if (keyword.equals("template"))
        return std::string::npos;

      // There is something else here that needs to be wrapped.
      return getFileOffset(Tok);
    }

    // FIXME: in the future, continue lexing to extract relevant PP directives;
    // return wrapPoint
    // There is something else here that needs to be wrapped.
    return getFileOffset(Tok);
  }

  // We have only had PP directives; no need to wrap.
  return std::string::npos;
}
<|endoftext|>


<commit_before>#ifndef DICE_IOPERATION_H
#define DICE_IOPERATION_H

#include "../stdafx.hpp"

//Base for a Decorator Pattern
class IOperation
{
protected:
    std::vector<int> _elements;
    int _count;
    IOperation *_componentOp;

    // Execute operation. All heavy lifting for object.
    virtual void execute() = 0;

public:
    // Executes all operations.
    virtual inline void evaluate()
    {
	_componentOp->evaluate();
	execute();
    }
    virtual std::string toString() const
    {
        std::string result = "";
        for (auto& element : _elements)
            result += std::to_string(element) + " ";
        return result;
    }
    inline int getCount() const { return _count; }
    inline const std::vector<int> &getElements() const { return _elements; }
};

#endif //DICE_IOPERATION_H
<commit_msg>Integrated RollResult into IOperation.<commit_after>#ifndef DICE_IOPERATION_H
#define DICE_IOPERATION_H

#include "../stdafx.hpp"
#include "DiceRoll/Operations/RollResult.h"

//Base for a Decorator Pattern
class IOperation
{
protected:
    std::vector<int> _elements;
    int _count;
    IOperation *_componentOp;

    // Execute operation. All heavy lifting for object.
    virtual std::shared_ptr<RollResult> execute() = 0;

public:
    // Executes all operations.
    // By default, merges _componentOp's RollResult with its.
    virtual inline std::shared_ptr<RollResult> evaluate()
    {
	std::shared_ptr<RollResult> result = _componentOp->evaluate();
	result->append(result.get());
	return result;
    }
    virtual std::string toString() const
    {
        std::string result = "";
        for (auto& element : _elements)
            result += std::to_string(element) + " ";
        return result;
    }
    inline int getCount() const { return _count; }
    inline const std::vector<int> &getElements() const { return _elements; }
};

#endif //DICE_IOPERATION_H
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  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.
 *
 *=========================================================================*/

#include "PercentileGridSampler.h"

#include <cassert> // assert
#include <cmath> // std::exp
#include <algorithm> // std::count

namespace madai {

PercentileGridSampler
::PercentileGridSampler() :
  Sampler(),
  m_NumberOfSamplesInEachDimension(4)
{
}

PercentileGridSampler
::~PercentileGridSampler()
{
}

Sample
PercentileGridSampler
::NextSample()
{
  const std::vector< Parameter > & parameters = m_Model->GetParameters();
  assert (this->GetNumberOfActiveParameters() > 0);
  unsigned int p = m_Model->GetNumberOfParameters();

  assert(m_CurrentParameters.size() == m_Model->GetNumberOfParameters());
  std::vector< double > x(m_CurrentParameters); // copy constructor

  // do something
  double rangeOverN = 1.0 / static_cast< double >( m_NumberOfSamplesInEachDimension );
  double start = 0.5 * rangeOverN;
  for ( unsigned int dim = 0; dim < p; ++dim ) {
    if (this->IsParameterActive(dim)) {
      x[dim] =
        parameters[dim].GetPriorDistribution()->GetPercentile(
            start + (m_StateVector[dim] * rangeOverN));
    }
  }

  unsigned int dim = 0;
  while ((! this->IsParameterActive(dim)) ||
         (m_StateVector[dim] == m_NumberOfSamplesInEachDimension - 1)) {
    m_StateVector[dim] = 0;
    dim = (dim + 1) % p;
  }
  m_StateVector[dim] ++;

  std::vector< double > y( m_Model->GetNumberOfScalarOutputs(), 0.0 );
  double ll; // ll is new_log_likelihood
  Model * m = const_cast< Model * >(m_Model);
  m->GetScalarOutputsAndLogLikelihood(x,y,ll);
  return Sample( x, y, ll );

}

void PercentileGridSampler
::SetNumberOfSamples( unsigned int N )
{
  if (m_Model == NULL)
    return;
  // call this function *after* Deactivating Parameters!
  unsigned int p = this->GetNumberOfActiveParameters();
  assert((p <= m_Model->GetNumberOfParameters()) && (p > 0));
  unsigned int n = static_cast< unsigned int >(
      std::ceil(std::pow(N,1.0 / static_cast< double >(p))));
  if (n < 2)
    n = 2;
  m_NumberOfSamplesInEachDimension = n;
}

unsigned int
PercentileGridSampler
::GetNumberOfSamples()
{
  float floatResult = std::pow(static_cast<float>(m_NumberOfSamplesInEachDimension),
                               static_cast<int>(this->GetNumberOfActiveParameters()));
  return static_cast<unsigned int>( floatResult + 0.5 );
}

void
PercentileGridSampler
::Reset()
{
  this->Initialize( m_Model );
}

void
PercentileGridSampler
::Initialize( const Model * model )
{
  assert(model != NULL);
  if ((model == NULL) || (m_Model == model))
    return;
  m_Model = model;

  Sampler::Initialize( model );
  unsigned int p = m_Model->GetNumberOfParameters();
  this->SetNumberOfSamples(this->GetNumberOfSamples());
  m_StateVector.clear();
  m_StateVector.resize(p,0);
}

} // end namespace madai
<commit_msg>If no parameters are active, GetNumberOfSamples() returns 0<commit_after>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  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.
 *
 *=========================================================================*/

#include "PercentileGridSampler.h"

#include <cassert> // assert
#include <cmath> // std::exp
#include <algorithm> // std::count

namespace madai {

PercentileGridSampler
::PercentileGridSampler() :
  Sampler(),
  m_NumberOfSamplesInEachDimension(4)
{
}

PercentileGridSampler
::~PercentileGridSampler()
{
}

Sample
PercentileGridSampler
::NextSample()
{
  const std::vector< Parameter > & parameters = m_Model->GetParameters();
  assert (this->GetNumberOfActiveParameters() > 0);
  unsigned int p = m_Model->GetNumberOfParameters();

  assert(m_CurrentParameters.size() == m_Model->GetNumberOfParameters());
  std::vector< double > x(m_CurrentParameters); // copy constructor

  // do something
  double rangeOverN = 1.0 / static_cast< double >( m_NumberOfSamplesInEachDimension );
  double start = 0.5 * rangeOverN;
  for ( unsigned int dim = 0; dim < p; ++dim ) {
    if (this->IsParameterActive(dim)) {
      x[dim] =
        parameters[dim].GetPriorDistribution()->GetPercentile(
            start + (m_StateVector[dim] * rangeOverN));
    }
  }

  unsigned int dim = 0;
  while ((! this->IsParameterActive(dim)) ||
         (m_StateVector[dim] == m_NumberOfSamplesInEachDimension - 1)) {
    m_StateVector[dim] = 0;
    dim = (dim + 1) % p;
  }
  m_StateVector[dim] ++;

  std::vector< double > y( m_Model->GetNumberOfScalarOutputs(), 0.0 );
  double ll; // ll is new_log_likelihood
  Model * m = const_cast< Model * >(m_Model);
  m->GetScalarOutputsAndLogLikelihood(x,y,ll);
  return Sample( x, y, ll );

}

void PercentileGridSampler
::SetNumberOfSamples( unsigned int N )
{
  if (m_Model == NULL)
    return;
  // call this function *after* Deactivating Parameters!
  unsigned int p = this->GetNumberOfActiveParameters();
  assert((p <= m_Model->GetNumberOfParameters()) && (p > 0));
  unsigned int n = static_cast< unsigned int >(
      std::ceil(std::pow(N,1.0 / static_cast< double >(p))));
  if (n < 2)
    n = 2;
  m_NumberOfSamplesInEachDimension = n;
}

unsigned int
PercentileGridSampler
::GetNumberOfSamples()
{
  if ( this->GetNumberOfActiveParameters() == 0 ) {
    return 0;
  }

  float floatResult = std::pow(static_cast<float>(m_NumberOfSamplesInEachDimension),
                               static_cast<int>(this->GetNumberOfActiveParameters()));
  return static_cast<unsigned int>( floatResult + 0.5 );
}

void
PercentileGridSampler
::Reset()
{
  this->Initialize( m_Model );
}

void
PercentileGridSampler
::Initialize( const Model * model )
{
  assert(model != NULL);
  if ((model == NULL) || (m_Model == model))
    return;
  m_Model = model;

  Sampler::Initialize( model );
  unsigned int p = m_Model->GetNumberOfParameters();
  this->SetNumberOfSamples(this->GetNumberOfSamples());
  m_StateVector.clear();
  m_StateVector.resize(p,0);
}

} // end namespace madai
<|endoftext|>