<commit_before>
#include "UnrealEnginePythonPrivatePCH.h"

#include "UEPySWidget.h"

static PyObject *ue_PySWidget_str(ue_PySWidget *self) {
	return PyUnicode_FromFormat("<unreal_engine.SWidget '%p' (%s)>",
		self->s_widget, TCHAR_TO_UTF8(*self->s_widget->GetTypeAsString()));
}

static PyObject *py_ue_swidget_get_children(ue_PySWidget *self, PyObject * args) {
	FChildren *children = self->s_widget->GetChildren();
	PyObject *py_list = PyList_New(0);
	for (int32 i = 0; i < children->Num(); i++) {
		TSharedRef<SWidget> widget = children->GetChildAt(i);
		PyObject *item = (PyObject *)ue_py_get_swidget(widget);
		PyList_Append(py_list, item);
		Py_DECREF(item);
	}
	return py_list;
}

static PyObject *py_ue_swidget_set_tooltip_text(ue_PySWidget *self, PyObject * args) {
	char *text;
	if (!PyArg_ParseTuple(args, "s:set_tooltip_text", &text)) {
		return NULL;
	}

	self->s_widget->SetToolTipText(FText::FromString(UTF8_TO_TCHAR(text)));

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_button_down(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_button_down", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseButtonDown(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_button_up(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_button_up", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseButtonUp(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_double_click(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_double_click", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseDoubleClick(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_move(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_move", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseMove(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_has_keyboard_focus(ue_PySWidget *self, PyObject * args) {

	if (self->s_widget->HasKeyboardFocus()) {
		Py_INCREF(Py_True);
		return Py_True;
	}

	Py_INCREF(Py_False);
	return Py_False;
}

static PyObject *py_ue_swidget_get_type(ue_PySWidget *self, PyObject * args) {
	return PyUnicode_FromString(TCHAR_TO_UTF8(*self->s_widget->GetTypeAsString()));
}

static PyMethodDef ue_PySWidget_methods[] = {
	{ "get_children", (PyCFunction)py_ue_swidget_get_children, METH_VARARGS, "" },
	{ "get_type", (PyCFunction)py_ue_swidget_get_type, METH_VARARGS, "" },
	{ "set_tooltip_text", (PyCFunction)py_ue_swidget_set_tooltip_text, METH_VARARGS, "" },
	{ "has_keyboard_focus", (PyCFunction)py_ue_swidget_has_keyboard_focus, METH_VARARGS, "" },
	{ "bind_on_mouse_button_down", (PyCFunction)py_ue_swidget_bind_on_mouse_button_down, METH_VARARGS, "" },
	{ "bind_on_mouse_button_up", (PyCFunction)py_ue_swidget_bind_on_mouse_button_down, METH_VARARGS, "" },
	{ "bind_on_mouse_double_click", (PyCFunction)py_ue_swidget_bind_on_mouse_double_click, METH_VARARGS, "" },
	{ "bind_on_mouse_move", (PyCFunction)py_ue_swidget_bind_on_mouse_move, METH_VARARGS, "" },
	{ NULL }  /* Sentinel */
};

PyTypeObject ue_PySWidgetType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"unreal_engine.SWidget", /* tp_name */
	sizeof(ue_PySWidget), /* tp_basicsize */
	0,                         /* tp_itemsize */
	0,       /* tp_dealloc */
	0,                         /* tp_print */
	0,                         /* tp_getattr */
	0,                         /* tp_setattr */
	0,                         /* tp_reserved */
	0,                         /* tp_repr */
	0,                         /* tp_as_number */
	0,                         /* tp_as_sequence */
	0,                         /* tp_as_mapping */
	0,                         /* tp_hash  */
	0,                         /* tp_call */
	(reprfunc)ue_PySWidget_str,                         /* tp_str */
	0,                         /* tp_getattro */
	0,                         /* tp_setattro */
	0,                         /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /* tp_flags */
	"Unreal Engine SWidget",           /* tp_doc */
	0,                         /* tp_traverse */
	0,                         /* tp_clear */
	0,                         /* tp_richcompare */
	0,                         /* tp_weaklistoffset */
	0,                         /* tp_iter */
	0,                         /* tp_iternext */
	ue_PySWidget_methods,             /* tp_methods */
};

void ue_python_init_swidget(PyObject *ue_module) {
	ue_PySWidgetType.tp_new = PyType_GenericNew;

	if (PyType_Ready(&ue_PySWidgetType) < 0)
		return;

	Py_INCREF(&ue_PySWidgetType);
	PyModule_AddObject(ue_module, "SWidget", (PyObject *)&ue_PySWidgetType);
}

ue_PySWidget *py_ue_is_swidget(PyObject *obj) {
	if (!PyObject_IsInstance(obj, (PyObject *)&ue_PySWidgetType))
		return nullptr;
	return (ue_PySWidget *)obj;
}

<commit_msg>added set_cursor and set_enabled to SWidget<commit_after>
#include "UnrealEnginePythonPrivatePCH.h"

#include "UEPySWidget.h"

static PyObject *ue_PySWidget_str(ue_PySWidget *self) {
	return PyUnicode_FromFormat("<unreal_engine.SWidget '%p' (%s)>",
		self->s_widget, TCHAR_TO_UTF8(*self->s_widget->GetTypeAsString()));
}

static PyObject *py_ue_swidget_get_children(ue_PySWidget *self, PyObject * args) {
	FChildren *children = self->s_widget->GetChildren();
	PyObject *py_list = PyList_New(0);
	for (int32 i = 0; i < children->Num(); i++) {
		TSharedRef<SWidget> widget = children->GetChildAt(i);
		PyObject *item = (PyObject *)ue_py_get_swidget(widget);
		PyList_Append(py_list, item);
		Py_DECREF(item);
	}
	return py_list;
}

static PyObject *py_ue_swidget_set_tooltip_text(ue_PySWidget *self, PyObject * args) {
	char *text;
	if (!PyArg_ParseTuple(args, "s:set_tooltip_text", &text)) {
		return NULL;
	}

	self->s_widget->SetToolTipText(FText::FromString(UTF8_TO_TCHAR(text)));

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_set_cursor(ue_PySWidget *self, PyObject * args) {
	int cursor;
	if (!PyArg_ParseTuple(args, "i:set_cursor", &cursor)) {
		return NULL;
	}

	self->s_widget->SetCursor((EMouseCursor::Type)cursor);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_set_enabled(ue_PySWidget *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:set_enabled", &py_bool)) {
		return NULL;
	}

	self->s_widget->SetEnabled(PyObject_IsTrue(py_bool) ? true : false);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_button_down(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_button_down", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseButtonDown(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_button_up(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_button_up", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseButtonUp(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_double_click(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_double_click", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseDoubleClick(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_bind_on_mouse_move(ue_PySWidget *self, PyObject * args) {
	PyObject *py_callable;
	if (!PyArg_ParseTuple(args, "O:bind_on_mouse_move", &py_callable)) {
		return NULL;
	}

	if (!PyCallable_Check(py_callable)) {
		return PyErr_Format(PyExc_Exception, "argument is not callable");
	}

	FPointerEventHandler handler;
	UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
	py_delegate->SetPyCallable(py_callable);
	py_delegate->AddToRoot();
	handler.BindUObject(py_delegate, &UPythonSlateDelegate::OnMouseEvent);

	self->s_widget->SetOnMouseMove(handler);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_swidget_has_keyboard_focus(ue_PySWidget *self, PyObject * args) {

	if (self->s_widget->HasKeyboardFocus()) {
		Py_INCREF(Py_True);
		return Py_True;
	}

	Py_INCREF(Py_False);
	return Py_False;
}

static PyObject *py_ue_swidget_get_type(ue_PySWidget *self, PyObject * args) {
	return PyUnicode_FromString(TCHAR_TO_UTF8(*self->s_widget->GetTypeAsString()));
}

static PyMethodDef ue_PySWidget_methods[] = {
	{ "get_children", (PyCFunction)py_ue_swidget_get_children, METH_VARARGS, "" },
	{ "get_type", (PyCFunction)py_ue_swidget_get_type, METH_VARARGS, "" },
	{ "set_tooltip_text", (PyCFunction)py_ue_swidget_set_tooltip_text, METH_VARARGS, "" },
	{ "set_cursor", (PyCFunction)py_ue_swidget_set_cursor, METH_VARARGS, "" },
	{ "set_enabled", (PyCFunction)py_ue_swidget_set_enabled, METH_VARARGS, "" },
	{ "has_keyboard_focus", (PyCFunction)py_ue_swidget_has_keyboard_focus, METH_VARARGS, "" },
	{ "bind_on_mouse_button_down", (PyCFunction)py_ue_swidget_bind_on_mouse_button_down, METH_VARARGS, "" },
	{ "bind_on_mouse_button_up", (PyCFunction)py_ue_swidget_bind_on_mouse_button_down, METH_VARARGS, "" },
	{ "bind_on_mouse_double_click", (PyCFunction)py_ue_swidget_bind_on_mouse_double_click, METH_VARARGS, "" },
	{ "bind_on_mouse_move", (PyCFunction)py_ue_swidget_bind_on_mouse_move, METH_VARARGS, "" },
	{ NULL }  /* Sentinel */
};

PyTypeObject ue_PySWidgetType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"unreal_engine.SWidget", /* tp_name */
	sizeof(ue_PySWidget), /* tp_basicsize */
	0,                         /* tp_itemsize */
	0,       /* tp_dealloc */
	0,                         /* tp_print */
	0,                         /* tp_getattr */
	0,                         /* tp_setattr */
	0,                         /* tp_reserved */
	0,                         /* tp_repr */
	0,                         /* tp_as_number */
	0,                         /* tp_as_sequence */
	0,                         /* tp_as_mapping */
	0,                         /* tp_hash  */
	0,                         /* tp_call */
	(reprfunc)ue_PySWidget_str,                         /* tp_str */
	0,                         /* tp_getattro */
	0,                         /* tp_setattro */
	0,                         /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /* tp_flags */
	"Unreal Engine SWidget",           /* tp_doc */
	0,                         /* tp_traverse */
	0,                         /* tp_clear */
	0,                         /* tp_richcompare */
	0,                         /* tp_weaklistoffset */
	0,                         /* tp_iter */
	0,                         /* tp_iternext */
	ue_PySWidget_methods,             /* tp_methods */
};

void ue_python_init_swidget(PyObject *ue_module) {
	ue_PySWidgetType.tp_new = PyType_GenericNew;

	if (PyType_Ready(&ue_PySWidgetType) < 0)
		return;

	Py_INCREF(&ue_PySWidgetType);
	PyModule_AddObject(ue_module, "SWidget", (PyObject *)&ue_PySWidgetType);
}

ue_PySWidget *py_ue_is_swidget(PyObject *obj) {
	if (!PyObject_IsInstance(obj, (PyObject *)&ue_PySWidgetType))
		return nullptr;
	return (ue_PySWidget *)obj;
}

<|endoftext|>


<commit_before>## This file is a template.  The comment below is emitted
## into the rendered file; feel free to edit this file.
// WARNING: Generated header. Do not edit!
<%
from collections import defaultdict
objects = list(settingsDict.viewkeys())
sdbusplus_namespaces = []
sdbusplus_includes = []
interfaces = []
props = defaultdict(list)

def get_setting_sdbusplus_type(setting_intf):
    setting = "sdbusplus::" + setting_intf.replace('.', '::')
    i = setting.rfind('::')
    setting = setting[:i] + '::server::' + setting[i+2:]
    return setting

def get_setting_type(setting_intf):
    setting = setting_intf.replace('.', '::')
    return setting
%>\
#pragma once

% for object in objects:
<%
    include = settingsDict[object]['Interface']
    include = include.replace('.', '/')
    include = include + "/server.hpp"
    sdbusplus_includes.append(include)
%>\
% endfor
#include <cereal/archives/json.hpp>
#include <fstream>
#include <utility>
#include <experimental/filesystem>
#include "config.h"

% for i in set(sdbusplus_includes):
#include "${i}"
% endfor

% for object in objects:
<%
    ns = get_setting_sdbusplus_type(settingsDict[object]['Interface'])
    i = ns.rfind('::')
    ns = ns[:i]
    sdbusplus_namespaces.append(ns)
%>\
% endfor

namespace phosphor
{
namespace settings
{

namespace fs = std::experimental::filesystem;

% for n in set(sdbusplus_namespaces):
using namespace ${n};
% endfor

% for object in objects:
<%
    intf = settingsDict[object]['Interface']
    interfaces.append(intf)
    if intf not in props:
        for property, value in settingsDict[object]['Defaults'].items():
            props[intf].append(property)
%>\
% endfor
% for intf in set(interfaces):
<%
    ns = intf.split(".")
    sdbusplus_type = get_setting_sdbusplus_type(intf)
%>\
% for n in ns:
namespace ${n}
{
% endfor

using Base = ${sdbusplus_type};
<% parent = "sdbusplus::server::object::object" + "<" + sdbusplus_type + ">" %>\
using Parent = ${parent};

class Impl : public Parent
{
    public:
        Impl(sdbusplus::bus::bus& bus, const char* path):
            Parent(bus, path, true),
            path(path)
        {
        }
        virtual ~Impl() = default;

% for arg in props[intf]:
<% t = arg[:1].lower() + arg[1:] %>\
        decltype(std::declval<Base>().${t}()) ${t}(decltype(std::declval<Base>().${t}()) value) override
        {
            auto result = Base::${t}();
            if (value != result)
            {
                fs::path p(SETTINGS_PERSIST_PATH);
                p /= path;
                fs::create_directories(p.parent_path());
                std::ofstream os(p.c_str(), std::ios::binary);
                cereal::JSONOutputArchive oarchive(os);
                result = Base::${t}(value);
                oarchive(*this);
            }
            return result;
        }
        using Base::${t};

    private:
        fs::path path;
% endfor
};

template<class Archive>
void save(Archive& a,
          const Impl& setting)
{
<%
    args = ["setting." + p[:1].lower() + p[1:] + "()" for p in props[intf]]
    args = ','.join(args)
%>\
    a(${args});
}

template<class Archive>
void load(Archive& a,
          Impl& setting)
{
% for arg in props[intf]:
<% t = "setting." + arg[:1].lower() + arg[1:] + "()" %>\
    decltype(${t}) ${arg}{};
% endfor
<%
    args = ','.join(props[intf])
%>\
    a(${args});
% for arg in props[intf]:
<% t = "setting." + arg[:1].lower() + arg[1:] + "(" + arg + ")" %>\
    ${t};
% endfor
}

% for n in reversed(ns):
} // namespace ${n}
% endfor
% endfor

/** @class Manager
 *
 *  @brief Compose settings objects and put them on the bus.
 */
class Manager
{
    public:
        Manager() = delete;
        Manager(const Manager&) = delete;
        Manager& operator=(const Manager&) = delete;
        Manager(Manager&&) = delete;
        Manager& operator=(Manager&&) = delete;
        virtual ~Manager() = default;

        /** @brief Constructor to put settings objects on to the bus.
         *  @param[in] bus - Bus to attach to.
         */
        Manager(sdbusplus::bus::bus& bus)
        {
            fs::path path{};
            settings =
                std::make_tuple(
% for index, object in enumerate(objects):
<% type = get_setting_type(settingsDict[object]['Interface']) + "::Impl" %>\
                    std::make_unique<${type}>(
                        bus,
  % if index < len(settingsDict) - 1:
                        "${object}"),
  % else:
                        "${object}"));
  % endif
% endfor

% for index, object in enumerate(objects):
  % for property, value in settingsDict[object]['Defaults'].items():
<% p = property[:1].lower() + property[1:] %>\
            path = fs::path(SETTINGS_PERSIST_PATH) / "${object}";
            if (fs::exists(path))
            {
                std::ifstream is(path.c_str(), std::ios::in);
                cereal::JSONInputArchive iarchive(is);
                iarchive(*std::get<${index}>(settings));
            }
            else
            {
                std::get<${index}>(settings)->
                    ${get_setting_sdbusplus_type(settingsDict[object]['Interface'])}::${p}(${value});
            }
  % endfor
            std::get<${index}>(settings)->emit_object_added();

% endfor
        }

    private:
        /* @brief Composition of settings objects. */
        std::tuple<
% for index, object in enumerate(objects):
<% type = get_setting_type(settingsDict[object]['Interface']) + "::Impl" %>\
  % if index < len(settingsDict) - 1:
            std::unique_ptr<${type}>,
  % else:
            std::unique_ptr<${type}>> settings;
  % endif
% endfor
};

} // namespace settings
} // namespace phosphor
<commit_msg>Fix to allow multiple properties per interface<commit_after>## This file is a template.  The comment below is emitted
## into the rendered file; feel free to edit this file.
// WARNING: Generated header. Do not edit!
<%
from collections import defaultdict
objects = list(settingsDict.viewkeys())
sdbusplus_namespaces = []
sdbusplus_includes = []
interfaces = []
props = defaultdict(list)

def get_setting_sdbusplus_type(setting_intf):
    setting = "sdbusplus::" + setting_intf.replace('.', '::')
    i = setting.rfind('::')
    setting = setting[:i] + '::server::' + setting[i+2:]
    return setting

def get_setting_type(setting_intf):
    setting = setting_intf.replace('.', '::')
    return setting
%>\
#pragma once

% for object in objects:
<%
    include = settingsDict[object]['Interface']
    include = include.replace('.', '/')
    include = include + "/server.hpp"
    sdbusplus_includes.append(include)
%>\
% endfor
#include <cereal/archives/json.hpp>
#include <fstream>
#include <utility>
#include <experimental/filesystem>
#include "config.h"

% for i in set(sdbusplus_includes):
#include "${i}"
% endfor

% for object in objects:
<%
    ns = get_setting_sdbusplus_type(settingsDict[object]['Interface'])
    i = ns.rfind('::')
    ns = ns[:i]
    sdbusplus_namespaces.append(ns)
%>\
% endfor

namespace phosphor
{
namespace settings
{

namespace fs = std::experimental::filesystem;

% for n in set(sdbusplus_namespaces):
using namespace ${n};
% endfor

% for object in objects:
<%
    intf = settingsDict[object]['Interface']
    interfaces.append(intf)
    if intf not in props:
        for property, value in settingsDict[object]['Defaults'].items():
            props[intf].append(property)
%>\
% endfor
% for intf in set(interfaces):
<%
    ns = intf.split(".")
    sdbusplus_type = get_setting_sdbusplus_type(intf)
%>\
% for n in ns:
namespace ${n}
{
% endfor

using Base = ${sdbusplus_type};
<% parent = "sdbusplus::server::object::object" + "<" + sdbusplus_type + ">" %>\
using Parent = ${parent};

class Impl : public Parent
{
    public:
        Impl(sdbusplus::bus::bus& bus, const char* path):
            Parent(bus, path, true),
            path(path)
        {
        }
        virtual ~Impl() = default;

% for arg in props[intf]:
<% t = arg[:1].lower() + arg[1:] %>\
        decltype(std::declval<Base>().${t}()) ${t}(decltype(std::declval<Base>().${t}()) value) override
        {
            auto result = Base::${t}();
            if (value != result)
            {
                fs::path p(SETTINGS_PERSIST_PATH);
                p /= path;
                fs::create_directories(p.parent_path());
                std::ofstream os(p.c_str(), std::ios::binary);
                cereal::JSONOutputArchive oarchive(os);
                result = Base::${t}(value);
                oarchive(*this);
            }
            return result;
        }
        using Base::${t};

% endfor
    private:
        fs::path path;
};

template<class Archive>
void save(Archive& a,
          const Impl& setting)
{
<%
    args = ["setting." + p[:1].lower() + p[1:] + "()" for p in props[intf]]
    args = ','.join(args)
%>\
    a(${args});
}

template<class Archive>
void load(Archive& a,
          Impl& setting)
{
% for arg in props[intf]:
<% t = "setting." + arg[:1].lower() + arg[1:] + "()" %>\
    decltype(${t}) ${arg}{};
% endfor
<%
    args = ','.join(props[intf])
%>\
    a(${args});
% for arg in props[intf]:
<% t = "setting." + arg[:1].lower() + arg[1:] + "(" + arg + ")" %>\
    ${t};
% endfor
}

% for n in reversed(ns):
} // namespace ${n}
% endfor
% endfor

/** @class Manager
 *
 *  @brief Compose settings objects and put them on the bus.
 */
class Manager
{
    public:
        Manager() = delete;
        Manager(const Manager&) = delete;
        Manager& operator=(const Manager&) = delete;
        Manager(Manager&&) = delete;
        Manager& operator=(Manager&&) = delete;
        virtual ~Manager() = default;

        /** @brief Constructor to put settings objects on to the bus.
         *  @param[in] bus - Bus to attach to.
         */
        Manager(sdbusplus::bus::bus& bus)
        {
            fs::path path{};
            settings =
                std::make_tuple(
% for index, object in enumerate(objects):
<% type = get_setting_type(settingsDict[object]['Interface']) + "::Impl" %>\
                    std::make_unique<${type}>(
                        bus,
  % if index < len(settingsDict) - 1:
                        "${object}"),
  % else:
                        "${object}"));
  % endif
% endfor

% for index, object in enumerate(objects):
  % for property, value in settingsDict[object]['Defaults'].items():
<% p = property[:1].lower() + property[1:] %>\
            path = fs::path(SETTINGS_PERSIST_PATH) / "${object}";
            if (fs::exists(path))
            {
                std::ifstream is(path.c_str(), std::ios::in);
                cereal::JSONInputArchive iarchive(is);
                iarchive(*std::get<${index}>(settings));
            }
            else
            {
                std::get<${index}>(settings)->
                    ${get_setting_sdbusplus_type(settingsDict[object]['Interface'])}::${p}(${value});
            }
  % endfor
            std::get<${index}>(settings)->emit_object_added();

% endfor
        }

    private:
        /* @brief Composition of settings objects. */
        std::tuple<
% for index, object in enumerate(objects):
<% type = get_setting_type(settingsDict[object]['Interface']) + "::Impl" %>\
  % if index < len(settingsDict) - 1:
            std::unique_ptr<${type}>,
  % else:
            std::unique_ptr<${type}>> settings;
  % endif
% endfor
};

} // namespace settings
} // namespace phosphor
<|endoftext|>


<commit_before>#include <microscopes/lda/kernels.hpp>

namespace microscopes {
namespace kernels {
namespace lda_crp {

std::vector<float>
calc_dish_posterior_t(microscopes::lda::state &state, size_t eid, size_t t, common::rng_t &rng) {
    std::vector<float> log_p_k(state.dishes_.size());

    auto k_old = state.dish_assignment(eid, t);
    auto n_jt_val = state.n_jt[eid][t];
    for (size_t i = 0; i < state.dishes_.size(); i++) {
        auto k = state.dishes_[i];
        float n_k_val = state.n_k.get(k); // V*beta when k == i == 0
        if (k == k_old) n_k_val -= n_jt_val;
        log_p_k[i] = distributions::fast_log(i == 0 ? state.gamma_ : state.m_k[k]);
        log_p_k[i] += distributions::fast_lgamma(n_k_val);
        log_p_k[i] -= distributions::fast_lgamma(n_k_val + n_jt_val);
    }

    for (auto &kv : state.n_jtv[eid][t]) {
        auto w = kv.first; // w is word index
        auto n_jtw = kv.second; // n_jtw is # of times word w appears at table t in doc eid.
        if (n_jtw == 0) continue; // if word w isn't at table t, continue. log_pk wouldn't change.

        for (size_t i = 0; i < state.dishes_.size(); i++) {
            float n_kw;
            n_kw = state.n_kv[state.dishes_[i]].get(w); // beta when k == i == 0
            if (state.dishes_[i] == state.dish_assignment(eid, t)) n_kw -= n_jtw;
            log_p_k[i] += distributions::fast_lgamma(n_kw + n_jtw);
            log_p_k[i] -= distributions::fast_lgamma(n_kw);
        }
    }

    std::vector<float> p_k;
    p_k.reserve(state.dishes_.size());
    float max_value = *std::max_element(log_p_k.begin(), log_p_k.end());
    for (auto log_p_k_value : log_p_k) {
        p_k.push_back(exp(log_p_k_value - max_value));
    }
    lda_util::normalize(p_k);
    return p_k;
}

std::vector<float>
calc_dish_posterior_w(microscopes::lda::state &state, const std::vector<float> &f_k, common::rng_t &rng){
    Eigen::VectorXf p_k(state.dishes_.size());
    for (size_t i = 0; i < state.dishes_.size(); ++i) {
        p_k(i) = state.m_k[state.dishes_[i]] * f_k[state.dishes_[i]];
    }
    p_k(0) = state.gamma_ / state.V;
    p_k /= p_k.sum();
    return std::vector<float>(p_k.data(), p_k.data() + p_k.size());
}

std::vector<float>
calc_f_k(microscopes::lda::state &state, size_t v, common::rng_t &rng) {
    Eigen::VectorXf f_k(state.n_kv.size());

    f_k(0) = 0;
    for (size_t k = 1; k < state.n_kv.size(); k++)
    {
        f_k(k) = state.n_kv[k].get(v) / state.n_k.get(k);
    }

    return std::vector<float>(f_k.data(), f_k.data() + f_k.size());
}

std::vector<float>
calc_table_posterior(microscopes::lda::state &state, size_t eid, std::vector<float> &f_k, common::rng_t &rng) {
    std::vector<size_t> using_table = state.using_t[eid];
    Eigen::VectorXf p_t(using_table.size());

    for (size_t i = 1; i < using_table.size(); i++) {
        auto p = using_table[i];
        p_t(i) = state.n_jt[eid][p] * f_k[state.dish_assignment(eid, p)];
    }
    Eigen::Map<Eigen::VectorXf> eigen_f_k(f_k.data(), f_k.size());
    Eigen::Map<Eigen::Matrix<size_t, Eigen::Dynamic, 1>> eigen_m_k(state.m_k.data(), state.m_k.size());
    float p_x_ji = state.gamma_ / state.V + eigen_f_k.dot(eigen_m_k.cast<float>());
    p_t(0) = p_x_ji * state.alpha_ / (state.gamma_ + state.ntables());
    p_t /= p_t.sum();
    return std::vector<float>(p_t.data(), p_t.data() + p_t.size());
}

void
sampling_t(microscopes::lda::state &state, size_t eid, size_t i, common::rng_t &rng) {
    state.remove_table(eid, i);
    size_t v = state.get_word(eid, i);
    std::vector<float> f_k = calc_f_k(state, v, rng);
    std::vector<float> p_t = calc_table_posterior(state, eid, f_k, rng);

    size_t t_new = state.using_t[eid][common::util::sample_discrete(p_t, rng)];
    if (t_new == 0)
    {
        auto p_k = calc_dish_posterior_w(state, f_k, rng);
        size_t k_new = state.dishes_[common::util::sample_discrete(p_k, rng)];
        if (k_new == 0) k_new = state.create_dish();
        t_new = state.create_table(eid, k_new);
    }
    state.add_table(eid, t_new, i);
}

void
sampling_k(microscopes::lda::state &state, size_t eid, size_t t, common::rng_t &rng) {
    state.leave_from_dish(eid, t);
    auto p_k = calc_dish_posterior_t(state, eid, t, rng);
    size_t k_new = state.dishes_[common::util::sample_discrete(p_k, rng)];
    if (k_new == 0) k_new = state.create_dish();
    state.seat_at_dish(eid, t, k_new);
}

} // namespace lda_crp

void
lda_crp_gibbs(microscopes::lda::state &state, common::rng_t &rng)
{
    for (size_t eid = 0; eid < state.nentities(); ++eid) {
        for (size_t i = 0; i < state.nterms(eid); ++i) {
            lda_crp::sampling_t(state, eid, i, rng);
        }
    }
    for (size_t eid = 0; eid < state.nentities(); ++eid) {
        for (auto t : state.using_t[eid]) {
            if (t != 0) {
                lda_crp::sampling_k(state, eid, t, rng);
            }
        }
    }
}

namespace lda_hyperparameters {

void
sample_gamma(microscopes::lda::state &state, common::rng_t &rng, float a, float b){
    float eta = distributions::sample_beta(rng, state.gamma_ + 1, state.ntables());
    float log_eta = distributions::fast_log(eta);
    float part = state.ntables() * (b - log_eta) / (a + state.ntopics() - 1);
    float pie = 1.0 / (1.0 + part);
    int u = distributions::sample_bernoulli(rng, pie);
    float shape = a + state.ntopics() - 1 + u;
    float scale = 1.0 / (b - log_eta);
    state.gamma_ = distributions::sample_gamma(rng, shape, scale);
}

void
sample_alpha(microscopes::lda::state &state, common::rng_t &rng, float a, float b){
    float qs = 0;
    float qw = 0;
    for(size_t eid=0; eid < state.nentities(); ++eid){
        float p = state.nterms(eid) / (state.nterms(eid) + state.alpha_);
        qs += distributions::sample_bernoulli(rng, p);
        qw += distributions::sample_beta(rng, state.alpha_ + 1, state.nterms(eid));
    }
    float shape = a + state.ntables() - qs;
    float scale = 1.0 / (b - qw);
    state.alpha_ = distributions::sample_gamma(rng, shape, scale);
}

} // lda_hyperparameters

} // namespace kernels
} // namespace microscopes<commit_msg>Add missing log()<commit_after>#include <microscopes/lda/kernels.hpp>

namespace microscopes {
namespace kernels {
namespace lda_crp {

std::vector<float>
calc_dish_posterior_t(microscopes::lda::state &state, size_t eid, size_t t, common::rng_t &rng) {
    std::vector<float> log_p_k(state.dishes_.size());

    auto k_old = state.dish_assignment(eid, t);
    auto n_jt_val = state.n_jt[eid][t];
    for (size_t i = 0; i < state.dishes_.size(); i++) {
        auto k = state.dishes_[i];
        float n_k_val = state.n_k.get(k); // V*beta when k == i == 0
        if (k == k_old) n_k_val -= n_jt_val;
        log_p_k[i] = distributions::fast_log(i == 0 ? state.gamma_ : state.m_k[k]);
        log_p_k[i] += distributions::fast_lgamma(n_k_val);
        log_p_k[i] -= distributions::fast_lgamma(n_k_val + n_jt_val);
    }

    for (auto &kv : state.n_jtv[eid][t]) {
        auto w = kv.first; // w is word index
        auto n_jtw = kv.second; // n_jtw is # of times word w appears at table t in doc eid.
        if (n_jtw == 0) continue; // if word w isn't at table t, continue. log_pk wouldn't change.

        for (size_t i = 0; i < state.dishes_.size(); i++) {
            float n_kw;
            n_kw = state.n_kv[state.dishes_[i]].get(w); // beta when k == i == 0
            if (state.dishes_[i] == state.dish_assignment(eid, t)) n_kw -= n_jtw;
            log_p_k[i] += distributions::fast_lgamma(n_kw + n_jtw);
            log_p_k[i] -= distributions::fast_lgamma(n_kw);
        }
    }

    std::vector<float> p_k;
    p_k.reserve(state.dishes_.size());
    float max_value = *std::max_element(log_p_k.begin(), log_p_k.end());
    for (auto log_p_k_value : log_p_k) {
        p_k.push_back(exp(log_p_k_value - max_value));
    }
    lda_util::normalize(p_k);
    return p_k;
}

std::vector<float>
calc_dish_posterior_w(microscopes::lda::state &state, const std::vector<float> &f_k, common::rng_t &rng){
    Eigen::VectorXf p_k(state.dishes_.size());
    for (size_t i = 0; i < state.dishes_.size(); ++i) {
        p_k(i) = state.m_k[state.dishes_[i]] * f_k[state.dishes_[i]];
    }
    p_k(0) = state.gamma_ / state.V;
    p_k /= p_k.sum();
    return std::vector<float>(p_k.data(), p_k.data() + p_k.size());
}

std::vector<float>
calc_f_k(microscopes::lda::state &state, size_t v, common::rng_t &rng) {
    Eigen::VectorXf f_k(state.n_kv.size());

    f_k(0) = 0;
    for (size_t k = 1; k < state.n_kv.size(); k++)
    {
        f_k(k) = state.n_kv[k].get(v) / state.n_k.get(k);
    }

    return std::vector<float>(f_k.data(), f_k.data() + f_k.size());
}

std::vector<float>
calc_table_posterior(microscopes::lda::state &state, size_t eid, std::vector<float> &f_k, common::rng_t &rng) {
    std::vector<size_t> using_table = state.using_t[eid];
    Eigen::VectorXf p_t(using_table.size());

    for (size_t i = 1; i < using_table.size(); i++) {
        auto p = using_table[i];
        p_t(i) = state.n_jt[eid][p] * f_k[state.dish_assignment(eid, p)];
    }
    Eigen::Map<Eigen::VectorXf> eigen_f_k(f_k.data(), f_k.size());
    Eigen::Map<Eigen::Matrix<size_t, Eigen::Dynamic, 1>> eigen_m_k(state.m_k.data(), state.m_k.size());
    float p_x_ji = state.gamma_ / state.V + eigen_f_k.dot(eigen_m_k.cast<float>());
    p_t(0) = p_x_ji * state.alpha_ / (state.gamma_ + state.ntables());
    p_t /= p_t.sum();
    return std::vector<float>(p_t.data(), p_t.data() + p_t.size());
}

void
sampling_t(microscopes::lda::state &state, size_t eid, size_t i, common::rng_t &rng) {
    state.remove_table(eid, i);
    size_t v = state.get_word(eid, i);
    std::vector<float> f_k = calc_f_k(state, v, rng);
    std::vector<float> p_t = calc_table_posterior(state, eid, f_k, rng);

    size_t t_new = state.using_t[eid][common::util::sample_discrete(p_t, rng)];
    if (t_new == 0)
    {
        auto p_k = calc_dish_posterior_w(state, f_k, rng);
        size_t k_new = state.dishes_[common::util::sample_discrete(p_k, rng)];
        if (k_new == 0) k_new = state.create_dish();
        t_new = state.create_table(eid, k_new);
    }
    state.add_table(eid, t_new, i);
}

void
sampling_k(microscopes::lda::state &state, size_t eid, size_t t, common::rng_t &rng) {
    state.leave_from_dish(eid, t);
    auto p_k = calc_dish_posterior_t(state, eid, t, rng);
    size_t k_new = state.dishes_[common::util::sample_discrete(p_k, rng)];
    if (k_new == 0) k_new = state.create_dish();
    state.seat_at_dish(eid, t, k_new);
}

} // namespace lda_crp

void
lda_crp_gibbs(microscopes::lda::state &state, common::rng_t &rng)
{
    for (size_t eid = 0; eid < state.nentities(); ++eid) {
        for (size_t i = 0; i < state.nterms(eid); ++i) {
            lda_crp::sampling_t(state, eid, i, rng);
        }
    }
    for (size_t eid = 0; eid < state.nentities(); ++eid) {
        for (auto t : state.using_t[eid]) {
            if (t != 0) {
                lda_crp::sampling_k(state, eid, t, rng);
            }
        }
    }
}

namespace lda_hyperparameters {

void
sample_gamma(microscopes::lda::state &state, common::rng_t &rng, float a, float b){
    float eta = distributions::sample_beta(rng, state.gamma_ + 1, state.ntables());
    float log_eta = distributions::fast_log(eta);
    float part = state.ntables() * (b - log_eta) / (a + state.ntopics() - 1);
    float pie = 1.0 / (1.0 + part);
    int u = distributions::sample_bernoulli(rng, pie);
    float shape = a + state.ntopics() - 1 + u;
    float scale = 1.0 / (b - log_eta);
    state.gamma_ = distributions::sample_gamma(rng, shape, scale);
}

void
sample_alpha(microscopes::lda::state &state, common::rng_t &rng, float a, float b){
    float qs = 0;
    float qw = 0;
    for(size_t eid=0; eid < state.nentities(); ++eid){
        float p = state.nterms(eid) / (state.nterms(eid) + state.alpha_);
        qs += distributions::sample_bernoulli(rng, p);
        qw += distributions::fast_log(distributions::sample_beta(rng, state.alpha_ + 1, state.nterms(eid)));
    }
    float shape = a + state.ntables() - qs;
    float scale = 1.0 / (b - qw);
    state.alpha_ = distributions::sample_gamma(rng, shape, scale);
}

} // lda_hyperparameters

} // namespace kernels
} // namespace microscopes<|endoftext|>


<commit_before>#include "jpeg.h"

#include <algorithm>
#include <csetjmp>  // for mozjpeg error handling
#include <iostream>

#include <mozjpeg/jpeglib.h>

const uint8_t Jpeg::header_magic[] = { 0xFF, 0xD8, 0xFF };
bool Jpeg::keep_exif_ = false;
bool Jpeg::keep_icc_profile_ = false;
bool Jpeg::keep_all_metadata_ = false;
bool Jpeg::force_arithmetic_coding_ = false;

namespace {

jmp_buf setjmp_buffer;

void mozjpeg_error_handler(j_common_ptr cinfo) {
  (*cinfo->err->output_message)(cinfo);

  longjmp(setjmp_buffer, 1);
}

}  // namespace

size_t Jpeg::Leanify(size_t size_leanified /*= 0*/) {
  struct jpeg_decompress_struct srcinfo;
  struct jpeg_compress_struct dstinfo;
  struct jpeg_error_mgr jsrcerr, jdsterr;

  srcinfo.err = jpeg_std_error(&jsrcerr);
  jsrcerr.error_exit = mozjpeg_error_handler;
  if (setjmp(setjmp_buffer)) {
    jpeg_destroy_compress(&dstinfo);
    jpeg_destroy_decompress(&srcinfo);

    return Format::Leanify(size_leanified);
  }

  jpeg_create_decompress(&srcinfo);

  dstinfo.err = jpeg_std_error(&jdsterr);
  jdsterr.error_exit = mozjpeg_error_handler;

  jpeg_create_compress(&dstinfo);

  if (is_verbose) {
    dstinfo.err->trace_level++;
  }
  if (is_fast) {
    jpeg_c_set_int_param(&dstinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST);
  }

  /* Specify data source for decompression */
  jpeg_mem_src(&srcinfo, fp_, size_);

  // Always save exif to show warning if orientation might change.
  jpeg_save_markers(&srcinfo, JPEG_APP0 + 1, 0xFFFF);
  if (keep_icc_profile_ || keep_all_metadata_) {
    jpeg_save_markers(&srcinfo, JPEG_APP0 + 2, 0xFFFF);
  }
  if (keep_all_metadata_) {
    // Save the rest APPn markers.
    for (int i = 3; i < 16; i++)
      jpeg_save_markers(&srcinfo, JPEG_APP0 + i, 0xFFFF);
    // Save comments.
    jpeg_save_markers(&srcinfo, JPEG_COM, 0xFFFF);
  }

  (void)jpeg_read_header(&srcinfo, true);

  /* Read source file as DCT coefficients */
  auto coef_arrays = jpeg_read_coefficients(&srcinfo);

  /* Initialize destination compression parameters from source values */
  jpeg_copy_critical_parameters(&srcinfo, &dstinfo);

  // use arithmetic coding if input file is arithmetic coded or if forced to
  if (srcinfo.arith_code || force_arithmetic_coding_) {
    dstinfo.arith_code = true;
    dstinfo.optimize_coding = false;
  } else {
    dstinfo.optimize_coding = true;
  }

  uint8_t* outbuffer = nullptr;
  unsigned long outsize = 0;
  /* Specify data destination for compression */
  jpeg_mem_dest(&dstinfo, &outbuffer, &outsize);

  /* Start compressor (note no image data is actually written here) */
  jpeg_write_coefficients(&dstinfo, coef_arrays);

  for (auto marker = srcinfo.marker_list; marker; marker = marker->next) {
    if (marker->marker == JPEG_APP0 + 1 && !keep_exif_ && !keep_all_metadata_) {
      // Tag number: 0x0112, data format: unsigned short(3), number of components: 1
      const uint8_t kExifOrientation[] = { 0x12, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00 };
      const uint8_t kExifOrientationMotorola[] = { 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01 };
      uint8_t* start = marker->data;
      uint8_t* end = start + marker->data_length;
      uint8_t* orientation_tag = std::search(start, end, kExifOrientation, std::end(kExifOrientation));
      bool big_endian = false;
      if (orientation_tag == end) {
        orientation_tag = std::search(start, end, kExifOrientationMotorola, std::end(kExifOrientationMotorola));
        big_endian = orientation_tag != end;
      }
      if (orientation_tag != end) {
        uint16_t orientation = *reinterpret_cast<uint16_t*>(orientation_tag + sizeof(kExifOrientation));
        if (big_endian)
          orientation = ((orientation >> 8) | (orientation << 8)) & 0xFFFF;
        // Only show warning if it's not the default upper left.
        if (orientation != 1) {
          std::cout << "Warning: The Exif being removed contains orientation data, result image might have wrong "
                       "orientation, use --keep-exif to keep Exif."
                    << std::endl;
        }
      }
      continue;
    }
    jpeg_write_marker(&dstinfo, marker->marker, marker->data, marker->data_length);
  }

  /* Finish compression and release memory */
  jpeg_finish_compress(&dstinfo);

  (void)jpeg_finish_decompress(&srcinfo);
  jpeg_destroy_decompress(&srcinfo);

  fp_ -= size_leanified;
  // use mozjpeg result if it's smaller than original
  if (outsize < size_) {
    memcpy(fp_, outbuffer, outsize);
    size_ = outsize;
  } else {
    memmove(fp_, fp_ + size_leanified, size_);
  }

  jpeg_destroy_compress(&dstinfo);

  return size_;
}<commit_msg>Try baseline too for small jpeg<commit_after>#include "jpeg.h"

#include <algorithm>
#include <csetjmp>  // for mozjpeg error handling
#include <iostream>

#include <mozjpeg/jpeglib.h>

const uint8_t Jpeg::header_magic[] = { 0xFF, 0xD8, 0xFF };
bool Jpeg::keep_exif_ = false;
bool Jpeg::keep_icc_profile_ = false;
bool Jpeg::keep_all_metadata_ = false;
bool Jpeg::force_arithmetic_coding_ = false;

namespace {

jmp_buf setjmp_buffer;

void mozjpeg_error_handler(j_common_ptr cinfo) {
  (*cinfo->err->output_message)(cinfo);

  longjmp(setjmp_buffer, 1);
}

void CompressJpeg(const j_decompress_ptr srcinfo, j_compress_ptr* compress_ptr, jvirt_barray_ptr* coef_arrays,
                  bool baseline, bool arithmetic, bool keep_exif, uint8_t** outbuffer, unsigned long* outsize) {
  jpeg_error_mgr jdsterr;
  jpeg_compress_struct dstinfo;
  *compress_ptr = &dstinfo;
  dstinfo.err = jpeg_std_error(&jdsterr);
  jdsterr.error_exit = mozjpeg_error_handler;

  jpeg_create_compress(&dstinfo);

  if (is_verbose) {
    dstinfo.err->trace_level++;
  }
  if (baseline) {
    jpeg_c_set_int_param(&dstinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST);
  }

  /* Initialize destination compression parameters from source values */
  jpeg_copy_critical_parameters(srcinfo, &dstinfo);

  // use arithmetic coding if input file is arithmetic coded or if forced to
  if (arithmetic) {
    dstinfo.arith_code = true;
    dstinfo.optimize_coding = false;
  } else {
    dstinfo.optimize_coding = true;
  }

  /* Specify data destination for compression */
  jpeg_mem_dest(&dstinfo, outbuffer, outsize);

  /* Start compressor (note no image data is actually written here) */
  jpeg_write_coefficients(&dstinfo, coef_arrays);

  for (auto marker = srcinfo->marker_list; marker; marker = marker->next) {
    if (keep_exif || marker->marker != JPEG_APP0 + 1) {
      jpeg_write_marker(&dstinfo, marker->marker, marker->data, marker->data_length);
    }
  }

  /* Finish compression and release memory */
  jpeg_finish_compress(&dstinfo);
  jpeg_destroy_compress(&dstinfo);
}

}  // namespace

size_t Jpeg::Leanify(size_t size_leanified /*= 0*/) {
  jpeg_decompress_struct srcinfo;
  j_compress_ptr dstinfo = nullptr;
  jpeg_error_mgr jsrcerr;

  srcinfo.err = jpeg_std_error(&jsrcerr);
  jsrcerr.error_exit = mozjpeg_error_handler;
  if (setjmp(setjmp_buffer)) {
    if (dstinfo)
      jpeg_destroy_compress(dstinfo);
    jpeg_destroy_decompress(&srcinfo);

    return Format::Leanify(size_leanified);
  }

  jpeg_create_decompress(&srcinfo);

  /* Specify data source for decompression */
  jpeg_mem_src(&srcinfo, fp_, size_);

  // Always save exif to show warning if orientation might change.
  jpeg_save_markers(&srcinfo, JPEG_APP0 + 1, 0xFFFF);
  if (keep_icc_profile_ || keep_all_metadata_) {
    jpeg_save_markers(&srcinfo, JPEG_APP0 + 2, 0xFFFF);
  }
  if (keep_all_metadata_) {
    // Save the rest APPn markers.
    for (int i = 3; i < 16; i++)
      jpeg_save_markers(&srcinfo, JPEG_APP0 + i, 0xFFFF);
    // Save comments.
    jpeg_save_markers(&srcinfo, JPEG_COM, 0xFFFF);
  }

  jpeg_read_header(&srcinfo, true);

  if (!keep_exif_ && !keep_all_metadata_) {
    for (auto marker = srcinfo.marker_list; marker; marker = marker->next) {
      if (marker->marker == JPEG_APP0 + 1) {
        // Tag number: 0x0112, data format: unsigned short(3), number of components: 1
        const uint8_t kExifOrientation[] = { 0x12, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00 };
        const uint8_t kExifOrientationMotorola[] = { 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01 };
        uint8_t* start = marker->data;
        uint8_t* end = start + marker->data_length;
        uint8_t* orientation_tag = std::search(start, end, kExifOrientation, std::end(kExifOrientation));
        bool big_endian = false;
        if (orientation_tag == end) {
          orientation_tag = std::search(start, end, kExifOrientationMotorola, std::end(kExifOrientationMotorola));
          big_endian = orientation_tag != end;
        }
        if (orientation_tag != end) {
          uint16_t orientation = *reinterpret_cast<uint16_t*>(orientation_tag + sizeof(kExifOrientation));
          if (big_endian)
            orientation = ((orientation >> 8) | (orientation << 8)) & 0xFFFF;
          // Only show warning if it's not the default upper left.
          if (orientation != 1) {
            std::cout << "Warning: The Exif being removed contains orientation data, result image might have wrong "
                         "orientation, use --keep-exif to keep Exif."
                      << std::endl;
          }
        }
        break;
      }
    }
  }

  /* Read source file as DCT coefficients */
  auto coef_arrays = jpeg_read_coefficients(&srcinfo);

  uint8_t* outbuffer = nullptr;
  unsigned long outsize = 0;

  // Try progressive unless fast mode.
  if (!is_fast) {
    CompressJpeg(&srcinfo, &dstinfo, coef_arrays, false, srcinfo.arith_code || force_arithmetic_coding_,
                 keep_all_metadata_ || keep_exif_, &outbuffer, &outsize);
  }

  // Try baseline if fast mode or small file.
  if (is_fast || size_ < 32768) {
    uint8_t* baseline_buffer = nullptr;
    unsigned long baseline_size = 0;

    CompressJpeg(&srcinfo, &dstinfo, coef_arrays, true, srcinfo.arith_code || force_arithmetic_coding_,
                 keep_all_metadata_ || keep_exif_, &baseline_buffer, &baseline_size);
    if (baseline_size < outsize) {
      free(outbuffer);
      outbuffer = baseline_buffer;
      outsize = baseline_size;
    } else {
      free(baseline_buffer);
    }
  }

  (void)jpeg_finish_decompress(&srcinfo);
  jpeg_destroy_decompress(&srcinfo);

  fp_ -= size_leanified;
  // use mozjpeg result if it's smaller than original
  if (outsize < size_) {
    memcpy(fp_, outbuffer, outsize);
    size_ = outsize;
  } else {
    memmove(fp_, fp_ + size_leanified, size_);
  }
  free(outbuffer);

  return size_;
}
<|endoftext|>


<commit_before>/*
 * Channel.cpp
 *
 *  Created on: Jun 13, 2012
 *      Author: cryan
 */

#include "headings.h"
#include "Channel.h"

Channel::Channel() : number{-1}, offset_{0.0}, scale_{1.0}, enabled_{false}, waveform_(0), trigDelay_{0}{}

Channel::Channel( int number) : number{number}, offset_{0.0}, scale_{1.0}, enabled_{false}, waveform_(0), trigDelay_{0}{}

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

int Channel::set_enabled(const bool & enable){
	enabled_ = enable;
	return 0;
}

bool Channel::get_enabled() const{
	return enabled_;
}

int Channel::set_offset(const float & offset){
	offset_ = (offset>1.0) ? 1.0 : offset;
	offset_ = (offset<-1.0) ? -1.0 : offset;
	return 0;
}

float Channel::get_offset() const{
	return offset_;
}

int Channel::set_scale(const float & scale){
	scale_ = scale;
	return 0;
}

float Channel::get_scale() const{
	return scale_;
}

int Channel::set_waveform(const vector<float> & data) {
	//Check whether we need to resize the waveform vector
	if (data.size() > size_t(MAX_WF_LENGTH)){
		FILE_LOG(logINFO) << "Warning: waveform too large to fit into cache. Waveform length: " << data.size();
	}

	//Copy over the waveform data
	//Waveform length must be a integer multiple of WF_MODULUS so resize to that
	waveform_.resize(size_t(WF_MODULUS*ceil(float(data.size())/WF_MODULUS)), 0);
	markers_.resize(waveform_.size());
	std::copy(data.begin(), data.end(), waveform_.begin());

	return 0;
}

int Channel::set_waveform(const vector<int16_t> & data) {
	if (data.size() > size_t(MAX_WF_LENGTH)){
		FILE_LOG(logINFO) << "Warning: waveform too large to fit into cache. Waveform length: " << data.size();
	}

	//Waveform length must be a integer multiple of WF_MODULUS so resize to that
	waveform_.resize(size_t(WF_MODULUS*ceil(float(data.size())/WF_MODULUS)), 0);
	markers_.resize(waveform_.size());
	//Copy over the waveform data and convert to scaled floats
	for(size_t ct=0; ct<data.size(); ct++){
		waveform_[ct] = float(data[ct])/MAX_WF_AMP;
	}
	return 0;
}

int Channel::set_markers(const vector<uint8_t> & data) {
	if (data.size() > markers_.size()) {
		FILE_LOG(logDEBUG) << "Marker data length does not match previously uploaded waveform data: " << data.size();
		markers_.resize(size_t(WF_MODULUS*ceil(float(data.size())/WF_MODULUS)), 0);
	}

	std::copy(data.begin(), data.end(), markers_.begin());
	return 0;
}

vector<int16_t> Channel::prep_waveform() const{
	//Apply the scale,offset and covert to integer format
	vector<int16_t> prepVec(waveform_.size());
	for(size_t ct=0; ct<prepVec.size(); ct++){
		prepVec[ct] = int16_t(MAX_WF_AMP*(scale_*waveform_[ct]+offset_));
	}

	//Clip to the max and min values allowed
	if (*max_element(prepVec.begin(), prepVec.end()) > MAX_WF_AMP){
		FILE_LOG(logWARNING) << "Waveform element too positive; clipping to max";
		for(int16_t & tmpVal : prepVec){
			if (tmpVal > MAX_WF_AMP) tmpVal = MAX_WF_AMP;
		}
	}
	if (*min_element(prepVec.begin(), prepVec.end()) < -MAX_WF_AMP){
		FILE_LOG(logWARNING) << "Waveform element too negative; clipping to max";
		for(int16_t & tmpVal : prepVec){
			if (tmpVal < -MAX_WF_AMP) tmpVal = -MAX_WF_AMP;
		}
	}
	// merge 14-bit DAC data with 2-bit marker data
	for (size_t ct=0; ct < prepVec.size(); ct++) {
		prepVec[ct] = (prepVec[ct] & 0x3FFF) | (static_cast<uint16_t>(markers_[ct]) << 14);
	}
	return prepVec;
}

int Channel::clear_data() {
	waveform_.clear();
	return 0;
}

int Channel::write_state_to_hdf5(H5::H5File & H5StateFile, const string & rootStr){

	// write waveform data
	FILE_LOG(logDEBUG) << "Writing Waveform: " << rootStr + "/waveformLib";
	vector2h5array<float>(waveform_,  &H5StateFile, rootStr + "/waveformLib", rootStr + "/waveformLib",   H5::PredType::NATIVE_FLOAT);

	// add channel state information to root group
	H5::Group tmpGroup = H5StateFile.openGroup(rootStr);

	element2h5attribute<float>("offset",  offset_,    &tmpGroup, H5::PredType::NATIVE_FLOAT);
	element2h5attribute<float>("scale",   scale_,     &tmpGroup, H5::PredType::NATIVE_FLOAT);
	element2h5attribute<bool>("enabled",  enabled_,   &tmpGroup, H5::PredType::NATIVE_UINT);
	element2h5attribute<int>("trigDelay", trigDelay_, &tmpGroup, H5::PredType::NATIVE_INT);

	tmpGroup.close();

	//Save the linklist data

	// save number of banks to rootStr + /linkListData attribute "numBanks"
//	USHORT numBanks;
//	numBanks = banks_.size();//get number of banks from channel
//
//	// set attribute
//	FILE_LOG(logDEBUG) << "Creating Group: " << rootStr + "/linkListData";
//	tmpGroup = H5StateFile.createGroup(rootStr + "/linkListData");
//	element2h5attribute<USHORT>("numBanks",  numBanks, &tmpGroup,H5::PredType::NATIVE_UINT16);
//	tmpGroup.close();
//
//	std::ostringstream tmpStream;
//	//Now loop over the number of banks found and add the bank
//	for (USHORT bankct=0; bankct<numBanks; bankct++) {
//		tmpStream.str("");
//		tmpStream << rootStr << "/linkListData/bank" << bankct+1 ;
//		FILE_LOG(logDEBUG) << "Writing State Bank: " << bankct+1 << " from hdf5";
//		banks_[bankct].write_state_to_hdf5(H5StateFile, tmpStream.str() );
//	}
	return 0;
}

int Channel::read_state_from_hdf5(H5::H5File & H5StateFile, const string & rootStr){
	clear_data();
	// read waveform data
	waveform_ = h5array2vector<float>(&H5StateFile, rootStr + "/waveformLib",   H5::PredType::NATIVE_INT16);

	// load state information
	H5::Group tmpGroup = H5StateFile.openGroup(rootStr);
	offset_    = h5element2element<float>("offset",&tmpGroup, H5::PredType::NATIVE_FLOAT);
	scale_     = h5element2element<float>("scale",&tmpGroup, H5::PredType::NATIVE_FLOAT);
	enabled_   = h5element2element<bool>("enabled",&tmpGroup, H5::PredType::NATIVE_UINT);
	trigDelay_ = h5element2element<int>("trigDelay",&tmpGroup, H5::PredType::NATIVE_INT);

	//Load the linklist data
	//TODO
	return 0;
}
<commit_msg>Default channel enabled to true.<commit_after>/*
 * Channel.cpp
 *
 *  Created on: Jun 13, 2012
 *      Author: cryan
 */

#include "headings.h"
#include "Channel.h"

Channel::Channel() : number{-1}, offset_{0.0}, scale_{1.0}, enabled_{true}, waveform_(0), trigDelay_{0}{}

Channel::Channel( int number) : number{number}, offset_{0.0}, scale_{1.0}, enabled_{true}, waveform_(0), trigDelay_{0}{}

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

int Channel::set_enabled(const bool & enable){
	enabled_ = enable;
	return 0;
}

bool Channel::get_enabled() const{
	return enabled_;
}

int Channel::set_offset(const float & offset){
	offset_ = (offset>1.0) ? 1.0 : offset;
	offset_ = (offset<-1.0) ? -1.0 : offset;
	return 0;
}

float Channel::get_offset() const{
	return offset_;
}

int Channel::set_scale(const float & scale){
	scale_ = scale;
	return 0;
}

float Channel::get_scale() const{
	return scale_;
}

int Channel::set_waveform(const vector<float> & data) {
	//Check whether we need to resize the waveform vector
	if (data.size() > size_t(MAX_WF_LENGTH)){
		FILE_LOG(logINFO) << "Warning: waveform too large to fit into cache. Waveform length: " << data.size();
	}

	//Copy over the waveform data
	//Waveform length must be a integer multiple of WF_MODULUS so resize to that
	waveform_.resize(size_t(WF_MODULUS*ceil(float(data.size())/WF_MODULUS)), 0);
	markers_.resize(waveform_.size());
	std::copy(data.begin(), data.end(), waveform_.begin());

	return 0;
}

int Channel::set_waveform(const vector<int16_t> & data) {
	if (data.size() > size_t(MAX_WF_LENGTH)){
		FILE_LOG(logINFO) << "Warning: waveform too large to fit into cache. Waveform length: " << data.size();
	}

	//Waveform length must be a integer multiple of WF_MODULUS so resize to that
	waveform_.resize(size_t(WF_MODULUS*ceil(float(data.size())/WF_MODULUS)), 0);
	markers_.resize(waveform_.size());
	//Copy over the waveform data and convert to scaled floats
	for(size_t ct=0; ct<data.size(); ct++){
		waveform_[ct] = float(data[ct])/MAX_WF_AMP;
	}
	return 0;
}

int Channel::set_markers(const vector<uint8_t> & data) {
	if (data.size() > markers_.size()) {
		FILE_LOG(logDEBUG) << "Marker data length does not match previously uploaded waveform data: " << data.size();
		markers_.resize(size_t(WF_MODULUS*ceil(float(data.size())/WF_MODULUS)), 0);
	}

	std::copy(data.begin(), data.end(), markers_.begin());
	return 0;
}

vector<int16_t> Channel::prep_waveform() const{
	//Apply the scale,offset and covert to integer format
	vector<int16_t> prepVec(waveform_.size());
	for(size_t ct=0; ct<prepVec.size(); ct++){
		prepVec[ct] = int16_t(MAX_WF_AMP*(scale_*waveform_[ct]+offset_));
	}

	//Clip to the max and min values allowed
	if (*max_element(prepVec.begin(), prepVec.end()) > MAX_WF_AMP){
		FILE_LOG(logWARNING) << "Waveform element too positive; clipping to max";
		for(int16_t & tmpVal : prepVec){
			if (tmpVal > MAX_WF_AMP) tmpVal = MAX_WF_AMP;
		}
	}
	if (*min_element(prepVec.begin(), prepVec.end()) < -MAX_WF_AMP){
		FILE_LOG(logWARNING) << "Waveform element too negative; clipping to max";
		for(int16_t & tmpVal : prepVec){
			if (tmpVal < -MAX_WF_AMP) tmpVal = -MAX_WF_AMP;
		}
	}
	// merge 14-bit DAC data with 2-bit marker data
	for (size_t ct=0; ct < prepVec.size(); ct++) {
		prepVec[ct] = (prepVec[ct] & 0x3FFF) | (static_cast<uint16_t>(markers_[ct]) << 14);
	}
	return prepVec;
}

int Channel::clear_data() {
	waveform_.clear();
	return 0;
}

int Channel::write_state_to_hdf5(H5::H5File & H5StateFile, const string & rootStr){

	// write waveform data
	FILE_LOG(logDEBUG) << "Writing Waveform: " << rootStr + "/waveformLib";
	vector2h5array<float>(waveform_,  &H5StateFile, rootStr + "/waveformLib", rootStr + "/waveformLib",   H5::PredType::NATIVE_FLOAT);

	// add channel state information to root group
	H5::Group tmpGroup = H5StateFile.openGroup(rootStr);

	element2h5attribute<float>("offset",  offset_,    &tmpGroup, H5::PredType::NATIVE_FLOAT);
	element2h5attribute<float>("scale",   scale_,     &tmpGroup, H5::PredType::NATIVE_FLOAT);
	element2h5attribute<bool>("enabled",  enabled_,   &tmpGroup, H5::PredType::NATIVE_UINT);
	element2h5attribute<int>("trigDelay", trigDelay_, &tmpGroup, H5::PredType::NATIVE_INT);

	tmpGroup.close();

	//Save the linklist data

	// save number of banks to rootStr + /linkListData attribute "numBanks"
//	USHORT numBanks;
//	numBanks = banks_.size();//get number of banks from channel
//
//	// set attribute
//	FILE_LOG(logDEBUG) << "Creating Group: " << rootStr + "/linkListData";
//	tmpGroup = H5StateFile.createGroup(rootStr + "/linkListData");
//	element2h5attribute<USHORT>("numBanks",  numBanks, &tmpGroup,H5::PredType::NATIVE_UINT16);
//	tmpGroup.close();
//
//	std::ostringstream tmpStream;
//	//Now loop over the number of banks found and add the bank
//	for (USHORT bankct=0; bankct<numBanks; bankct++) {
//		tmpStream.str("");
//		tmpStream << rootStr << "/linkListData/bank" << bankct+1 ;
//		FILE_LOG(logDEBUG) << "Writing State Bank: " << bankct+1 << " from hdf5";
//		banks_[bankct].write_state_to_hdf5(H5StateFile, tmpStream.str() );
//	}
	return 0;
}

int Channel::read_state_from_hdf5(H5::H5File & H5StateFile, const string & rootStr){
	clear_data();
	// read waveform data
	waveform_ = h5array2vector<float>(&H5StateFile, rootStr + "/waveformLib",   H5::PredType::NATIVE_INT16);

	// load state information
	H5::Group tmpGroup = H5StateFile.openGroup(rootStr);
	offset_    = h5element2element<float>("offset",&tmpGroup, H5::PredType::NATIVE_FLOAT);
	scale_     = h5element2element<float>("scale",&tmpGroup, H5::PredType::NATIVE_FLOAT);
	enabled_   = h5element2element<bool>("enabled",&tmpGroup, H5::PredType::NATIVE_UINT);
	trigDelay_ = h5element2element<int>("trigDelay",&tmpGroup, H5::PredType::NATIVE_INT);

	//Load the linklist data
	//TODO
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Nobody uses this.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "memoryleak.h"

#include <QDebug>

#include <QCoreApplication>
#include <QPluginLoader>
#include <QDir>
#include <QFileSystemWatcher>
#include <QSettings>
#include <QModelIndex>
#include <QThread>

#include "feedmanager.h"
//#include "feedplugin.h"
#include "feedplugincontainer.h"
#include "aggregatedservicemodel.h"
#include "settings.h"
#include "serviceadapter.h"
#include "searchablecontainer.h"

#include "memoryleak-defines.h"

#include "threadtest.h"

//
// Overview of McaFeedManager
//    - loads content plugins
//    - assembles aggregation of service models from all plugins
//    - passes on feed requests to the right plugin and service
//    - generates unique ids for services and stores some info in QSettings
//

const char PLUGIN_RELPATH[] = "/MeeGo/Content";

//
// static members
//

static McaFeedManager *s_manager = NULL;
static int s_refCount = 0;

McaFeedManager *McaFeedManager::takeManager()
{
    if (!s_manager)
        s_manager = new McaFeedManager;
    s_refCount++;
    return s_manager;
}

void McaFeedManager::releaseManager()
{
    if (s_manager) {
        s_refCount--;
        if (s_refCount == 0) {
            delete s_manager;
            s_manager = NULL;
        }
    }
}

//
// members
//

McaFeedManager::McaFeedManager()
{
    m_requestIdCounter = 0;
    m_destroying = false;

    qRegisterMetaType<QModelIndex>("QModelIndex");

    m_watcher = new QFileSystemWatcher;
    m_services = new McaAggregatedServiceModel;

    loadPlugins();

    // watch for new plugins getting installed and load them
    QStringList paths;
    foreach (QString path, QCoreApplication::libraryPaths())
        paths << path + PLUGIN_RELPATH;
    m_watcher->addPaths(paths);
    connect(m_watcher, SIGNAL(directoryChanged(QString)),
            this, SLOT(loadPlugins()));

    // TODO: watch for plugin updates, removals too?
}

McaFeedManager::~McaFeedManager()
{
    m_destroying = true;
    delete m_watcher;
    delete m_services;

    foreach (McaFeedPluginContainer *plugin, m_pluginToPaths.keys())
    {
        removePlugin(plugin);
    }
}

void McaFeedManager::removePlugin(McaFeedPluginContainer *plugin)
{
    disconnect(plugin, SIGNAL(loadCompleted(McaFeedPluginContainer*,QString)),
            this, SLOT(onLoadCompleted(McaFeedPluginContainer*,QString)));
    disconnect(plugin, SIGNAL(loadError(McaFeedPluginContainer*,QString)),
            this, SLOT(onLoadError(McaFeedPluginContainer*,QString)));
    disconnect(plugin, SIGNAL(feedModelCreated(QObject*,McaFeedAdapter*,int)),
            this, SIGNAL(feedCreated(QObject*,McaFeedAdapter*,int)));
    disconnect(plugin, SIGNAL(createFeedError(QString,int)),
            this, SIGNAL(createFeedError(QString,int)));

    //Allow remaining signals from threads to be dispatched
    QCoreApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents);

    qDebug() << "Terminating plugin " << m_pluginToPaths.value(plugin);
    QThread *plugin_thread = plugin->thread();
    plugin_thread->quit();
    if( !plugin_thread->wait(10000) ) {
        qWarning() << "Plugin thread is not responding";
    }

    //remove service
    foreach(const QAbstractItemModel *serviceModel, m_modelToPlugin.keys()) {
        if(m_modelToPlugin[serviceModel] == plugin) {
            const McaServiceAdapter *serviceAdapter = qobject_cast<const McaServiceAdapter*>(serviceModel);
            if(serviceAdapter) {
                //const_cast<McaServiceAdapter*>(serviceAdapter)->deleteLater();
                delete const_cast<McaServiceAdapter*>(serviceAdapter);
            } else {
                qDebug() << "NOT A SERVICE ADAPTER";
            }
            m_modelToPlugin.remove(serviceModel);
            break;
        }
    }
    //plugin->deleteLater();
    delete plugin;

    qDebug() << "Done terminating plugin " << m_pluginToPaths.value(plugin);
}

QAbstractItemModel *McaFeedManager::serviceModel()
{
    return m_services;
}

int McaFeedManager::createFeed(const QAbstractItemModel *serviceModel,
                                               const QString& name)
{
    // TODO: clean up destroyed models

    McaFeedPluginContainer *plugin = m_modelToPlugin.value(serviceModel);
    if (plugin) {
        QMetaObject::invokeMethod(plugin, "createFeedModel", Qt::QueuedConnection, Q_ARG(QString, name), Q_ARG(int, m_requestIdCounter), Q_ARG(QString, serviceId(serviceModel, name)));
        return m_requestIdCounter++;
    }

    return -1;
}

int McaFeedManager::createSearchFeed(const QAbstractItemModel *serviceModel, const QString& name, const QString& searchText)
{
    // TODO: clean up destroyed models

    McaFeedPluginContainer *plugin = m_modelToPlugin.value(serviceModel);
    if (plugin) {
        QMetaObject::invokeMethod(plugin, "createSearchModel", Qt::QueuedConnection, Q_ARG(QString, name), Q_ARG(QString, searchText), Q_ARG(int, m_requestIdCounter));
        return m_requestIdCounter++;
    }
    return -1;
}

QString McaFeedManager::getHash(QSettings *settings, const QString& path, const QString& name, int pass)
{
    QString key = path + ":" + name;
    if (pass > 0)
        key.append(QString::number(pass));

    QString hash = QString::number(qHash(key), 16);
    settings->beginGroup(hash);
    QString settingsPath = settings->value(McaSettings::KeyPluginPath).toString();
    QString settingsName = settings->value(McaSettings::KeyServiceName).toString();

    if (settingsPath.isEmpty()) {
        // no such section, so create one
        settings->setValue(McaSettings::KeyPluginPath, path);
        settings->setValue(McaSettings::KeyServiceName, name);
    }
    else if (settingsPath != path || settingsName != name) {
        // found non-matching section, return to iterate
        hash.clear();
    }

    // otherwise, hash is good so return it
    settings->endGroup();
    return hash;
}

QString McaFeedManager::serviceId(const QAbstractItemModel *serviceModel, const QString& name)
{
    // returns: empty string on error, unique hash otherwise

    McaFeedPluginContainer *plugin = m_modelToPlugin.value(serviceModel);
    if (!plugin)
        return QString();

    QString pluginPath = m_pluginToPaths.value(plugin);
    QString serviceKey = pluginPath + ":" + name;
    QString hash = m_idToHash.value(serviceKey);

    if (hash.isEmpty()) {
        // haven't seen this service yet, so check QSettings file
        QSettings settings(McaSettings::Organization, McaSettings::ApplicationCore);
        int pass = 0;
        while (true) {
            hash = getHash(&settings, pluginPath, name, pass++);
            if (!hash.isEmpty()) {
                break;
            }
        }
        m_idToHash[serviceKey] = hash;
    }

    return hash;
}

//
// protected slots
//

void McaFeedManager::loadPlugins()
{
    qDebug() << "McaFeedManager::loadPlugins()";
    // effects: checks plugin paths for any new plugins to load
    foreach (QString path, QCoreApplication::libraryPaths()) {
        QDir dir = QDir(path + PLUGIN_RELPATH);
        foreach (QString filename, dir.entryList(QStringList() << QString("*.so"))) {
            QString abspath = dir.absoluteFilePath(filename);
            if (m_pluginToPaths.values().contains(abspath))
                continue;

            McaFeedPluginContainer *pluginContainer = new McaFeedPluginContainer();
            pluginContainer->setPath(abspath);

            connect(pluginContainer, SIGNAL(loadCompleted(McaFeedPluginContainer*,QString)),
                    this, SLOT(onLoadCompleted(McaFeedPluginContainer*,QString)));
            connect(pluginContainer, SIGNAL(loadError(McaFeedPluginContainer*, QString)),
                    this, SLOT(onLoadError(McaFeedPluginContainer*,QString)));
            // Service data is accessed when the feed is created, which is why it blocks the thread.
            connect(pluginContainer, SIGNAL(feedModelCreated(QObject*,McaFeedAdapter*,int)),
                    this, SIGNAL(feedCreated(QObject*,McaFeedAdapter*,int)), Qt::BlockingQueuedConnection );
            connect(pluginContainer, SIGNAL(createFeedError(QString,int)),
                    this, SIGNAL(createFeedError(QString,int)));

#ifdef THREADING_DEBUG
            McaThreadTest *pluginThread = new McaThreadTest(this);
#else
            QThread *pluginThread = new QThread(this);
#endif
            connect(pluginThread, SIGNAL(started()), pluginContainer, SLOT(load()));

#ifdef THREADING
            pluginContainer->moveToThread(pluginThread);
#endif
            pluginThread->start();
        }
    }
}

void McaFeedManager::onLoadCompleted(McaFeedPluginContainer *plugin, const QString &absPath)
{
    if (plugin) {
        if(m_destroying) {
            removePlugin(plugin);
        } else {
            addPlugin(plugin, absPath);
        }
    } else {
        qWarning() << "Error loading plugin: received null plugin from threaded loader!";
    }
}

void McaFeedManager::onLoadError(McaFeedPluginContainer *plugin, const QString &errorString)
{
    qWarning() << "Error loading plugin: " << errorString;
    if (plugin) {
        removePlugin(plugin);
    } else {
        qWarning() << "Error deleting plugin: received null plugin from threaded loader!";
    }
}

//
// protected members
//

void McaFeedManager::addPlugin(McaFeedPluginContainer *plugin, const QString& abspath)
{
    m_pluginToPaths.insert(plugin, abspath);
    QAbstractItemModel *model = plugin->serviceModel();
    McaServiceAdapter *adapter = new McaServiceAdapter(this, 0);
    adapter->moveToThread(plugin->thread());
    m_modelToPlugin.insert(adapter, plugin);
    adapter->setSourceModel(model);
    m_services->addSourceModel(adapter);
}
<commit_msg>[lib] delete plugin within its thread before terminating thread<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "memoryleak.h"

#include <QDebug>

#include <QCoreApplication>
#include <QPluginLoader>
#include <QDir>
#include <QFileSystemWatcher>
#include <QSettings>
#include <QModelIndex>
#include <QThread>

#include "feedmanager.h"
//#include "feedplugin.h"
#include "feedplugincontainer.h"
#include "aggregatedservicemodel.h"
#include "settings.h"
#include "serviceadapter.h"
#include "searchablecontainer.h"

#include "memoryleak-defines.h"

#include "threadtest.h"

//
// Overview of McaFeedManager
//    - loads content plugins
//    - assembles aggregation of service models from all plugins
//    - passes on feed requests to the right plugin and service
//    - generates unique ids for services and stores some info in QSettings
//

const char PLUGIN_RELPATH[] = "/MeeGo/Content";

//
// static members
//

static McaFeedManager *s_manager = NULL;
static int s_refCount = 0;

McaFeedManager *McaFeedManager::takeManager()
{
    if (!s_manager)
        s_manager = new McaFeedManager;
    s_refCount++;
    return s_manager;
}

void McaFeedManager::releaseManager()
{
    if (s_manager) {
        s_refCount--;
        if (s_refCount == 0) {
            delete s_manager;
            s_manager = NULL;
        }
    }
}

//
// members
//

McaFeedManager::McaFeedManager()
{
    m_requestIdCounter = 0;
    m_destroying = false;

    qRegisterMetaType<QModelIndex>("QModelIndex");

    m_watcher = new QFileSystemWatcher;
    m_services = new McaAggregatedServiceModel;

    loadPlugins();

    // watch for new plugins getting installed and load them
    QStringList paths;
    foreach (QString path, QCoreApplication::libraryPaths())
        paths << path + PLUGIN_RELPATH;
    m_watcher->addPaths(paths);
    connect(m_watcher, SIGNAL(directoryChanged(QString)),
            this, SLOT(loadPlugins()));

    // TODO: watch for plugin updates, removals too?
}

McaFeedManager::~McaFeedManager()
{
    m_destroying = true;
    delete m_watcher;
    delete m_services;

    foreach (McaFeedPluginContainer *plugin, m_pluginToPaths.keys())
    {
        removePlugin(plugin);
    }
}

void McaFeedManager::removePlugin(McaFeedPluginContainer *plugin)
{
    disconnect(plugin, SIGNAL(loadCompleted(McaFeedPluginContainer*,QString)),
            this, SLOT(onLoadCompleted(McaFeedPluginContainer*,QString)));
    disconnect(plugin, SIGNAL(loadError(McaFeedPluginContainer*,QString)),
            this, SLOT(onLoadError(McaFeedPluginContainer*,QString)));
    disconnect(plugin, SIGNAL(feedModelCreated(QObject*,McaFeedAdapter*,int)),
            this, SIGNAL(feedCreated(QObject*,McaFeedAdapter*,int)));
    disconnect(plugin, SIGNAL(createFeedError(QString,int)),
            this, SIGNAL(createFeedError(QString,int)));

    // allow remaining signals from threads to be dispatched
    QCoreApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents);

    qDebug() << "Terminating plugin " << m_pluginToPaths.value(plugin);
    QThread *plugin_thread = plugin->thread();

    // remove service
    foreach (const QAbstractItemModel *serviceModel, m_modelToPlugin.keys()) {
        if (m_modelToPlugin[serviceModel] == plugin) {
            const McaServiceAdapter *serviceAdapter = qobject_cast<const McaServiceAdapter*>(serviceModel);
            if (serviceAdapter) {
                //const_cast<McaServiceAdapter*>(serviceAdapter)->deleteLater();
                delete const_cast<McaServiceAdapter*>(serviceAdapter);
            }
            else {
                qDebug() << "NOT A SERVICE ADAPTER";
            }
            m_modelToPlugin.remove(serviceModel);
            break;
        }
    }

    plugin->deleteLater();
    QCoreApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents);

    plugin_thread->quit();
    if (!plugin_thread->wait(3000)) {
        qWarning() << "Plugin thread is not responding";
    }

    qDebug() << "Done terminating plugin " << m_pluginToPaths.value(plugin);
    m_pluginToPaths.remove(plugin);
}

QAbstractItemModel *McaFeedManager::serviceModel()
{
    return m_services;
}

int McaFeedManager::createFeed(const QAbstractItemModel *serviceModel,
                                               const QString& name)
{
    // TODO: clean up destroyed models

    McaFeedPluginContainer *plugin = m_modelToPlugin.value(serviceModel);
    if (plugin) {
        QMetaObject::invokeMethod(plugin, "createFeedModel", Qt::QueuedConnection, Q_ARG(QString, name), Q_ARG(int, m_requestIdCounter), Q_ARG(QString, serviceId(serviceModel, name)));
        return m_requestIdCounter++;
    }

    return -1;
}

int McaFeedManager::createSearchFeed(const QAbstractItemModel *serviceModel, const QString& name, const QString& searchText)
{
    // TODO: clean up destroyed models

    McaFeedPluginContainer *plugin = m_modelToPlugin.value(serviceModel);
    if (plugin) {
        QMetaObject::invokeMethod(plugin, "createSearchModel", Qt::QueuedConnection, Q_ARG(QString, name), Q_ARG(QString, searchText), Q_ARG(int, m_requestIdCounter));
        return m_requestIdCounter++;
    }
    return -1;
}

QString McaFeedManager::getHash(QSettings *settings, const QString& path, const QString& name, int pass)
{
    QString key = path + ":" + name;
    if (pass > 0)
        key.append(QString::number(pass));

    QString hash = QString::number(qHash(key), 16);
    settings->beginGroup(hash);
    QString settingsPath = settings->value(McaSettings::KeyPluginPath).toString();
    QString settingsName = settings->value(McaSettings::KeyServiceName).toString();

    if (settingsPath.isEmpty()) {
        // no such section, so create one
        settings->setValue(McaSettings::KeyPluginPath, path);
        settings->setValue(McaSettings::KeyServiceName, name);
    }
    else if (settingsPath != path || settingsName != name) {
        // found non-matching section, return to iterate
        hash.clear();
    }

    // otherwise, hash is good so return it
    settings->endGroup();
    return hash;
}

QString McaFeedManager::serviceId(const QAbstractItemModel *serviceModel, const QString& name)
{
    // returns: empty string on error, unique hash otherwise

    McaFeedPluginContainer *plugin = m_modelToPlugin.value(serviceModel);
    if (!plugin)
        return QString();

    QString pluginPath = m_pluginToPaths.value(plugin);
    QString serviceKey = pluginPath + ":" + name;
    QString hash = m_idToHash.value(serviceKey);

    if (hash.isEmpty()) {
        // haven't seen this service yet, so check QSettings file
        QSettings settings(McaSettings::Organization, McaSettings::ApplicationCore);
        int pass = 0;
        while (true) {
            hash = getHash(&settings, pluginPath, name, pass++);
            if (!hash.isEmpty()) {
                break;
            }
        }
        m_idToHash[serviceKey] = hash;
    }

    return hash;
}

//
// protected slots
//

void McaFeedManager::loadPlugins()
{
    qDebug() << "McaFeedManager::loadPlugins()";
    // effects: checks plugin paths for any new plugins to load
    foreach (QString path, QCoreApplication::libraryPaths()) {
        QDir dir = QDir(path + PLUGIN_RELPATH);
        foreach (QString filename, dir.entryList(QStringList() << QString("*.so"))) {
            QString abspath = dir.absoluteFilePath(filename);
            if (m_pluginToPaths.values().contains(abspath))
                continue;

            McaFeedPluginContainer *pluginContainer = new McaFeedPluginContainer();
            pluginContainer->setPath(abspath);

            connect(pluginContainer, SIGNAL(loadCompleted(McaFeedPluginContainer*,QString)),
                    this, SLOT(onLoadCompleted(McaFeedPluginContainer*,QString)));
            connect(pluginContainer, SIGNAL(loadError(McaFeedPluginContainer*, QString)),
                    this, SLOT(onLoadError(McaFeedPluginContainer*,QString)));
            // Service data is accessed when the feed is created, which is why it blocks the thread.
            connect(pluginContainer, SIGNAL(feedModelCreated(QObject*,McaFeedAdapter*,int)),
                    this, SIGNAL(feedCreated(QObject*,McaFeedAdapter*,int)), Qt::BlockingQueuedConnection );
            connect(pluginContainer, SIGNAL(createFeedError(QString,int)),
                    this, SIGNAL(createFeedError(QString,int)));

#ifdef THREADING_DEBUG
            McaThreadTest *pluginThread = new McaThreadTest(this);
#else
            QThread *pluginThread = new QThread(this);
#endif
            connect(pluginThread, SIGNAL(started()), pluginContainer, SLOT(load()));

#ifdef THREADING
            pluginContainer->moveToThread(pluginThread);
#endif
            pluginThread->start();
        }
    }
}

void McaFeedManager::onLoadCompleted(McaFeedPluginContainer *plugin, const QString &absPath)
{
    if (plugin) {
        if(m_destroying) {
            removePlugin(plugin);
        } else {
            addPlugin(plugin, absPath);
        }
    } else {
        qWarning() << "Error loading plugin: received null plugin from threaded loader!";
    }
}

void McaFeedManager::onLoadError(McaFeedPluginContainer *plugin, const QString &errorString)
{
    qWarning() << "Error loading plugin: " << errorString;
    if (plugin) {
        removePlugin(plugin);
    } else {
        qWarning() << "Error deleting plugin: received null plugin from threaded loader!";
    }
}

//
// protected members
//

void McaFeedManager::addPlugin(McaFeedPluginContainer *plugin, const QString& abspath)
{
    m_pluginToPaths.insert(plugin, abspath);
    QAbstractItemModel *model = plugin->serviceModel();
    McaServiceAdapter *adapter = new McaServiceAdapter(this, 0);
    adapter->moveToThread(plugin->thread());
    m_modelToPlugin.insert(adapter, plugin);
    adapter->setSourceModel(model);
    m_services->addSourceModel(adapter);
}
<|endoftext|>


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

#pragma once

#include "initio.h"
#include <stdexcept>
#include <string>
#include <vector>

#include "aio.hpp"
#include "gpio.hpp"
#include "i2c.hpp"

#if !defined(PERIPHERALMAN)
#include "iio.hpp"
#endif

#include "pwm.hpp"
#include "spi.hpp"
#include "uart.hpp"
#include "uart_ow.hpp"

namespace mraa
{
class MraaIo
{
  private:
    mraa_io_descriptor* descs;

  public:
    MraaIo(const std::string& initStr) : descs()
    {
        if (mraa_io_init(initStr.c_str(), &descs) != MRAA_SUCCESS) {
            throw std::runtime_error("mraa_io_init error");
        }

        aios.reserve(descs->n_aio);
        for (int i = 0; i < descs->n_aio; ++i) {
            aios.emplace_back(descs->aios[i]);
        }

        gpios.reserve(descs->n_gpio);
        for (int i = 0; i < descs->n_gpio; ++i) {
            gpios.emplace_back(descs->gpios[i]);
        }

        i2cs.reserve(descs->n_i2c);
        for (int i = 0; i < descs->n_i2c; ++i) {
            i2cs.emplace_back(descs->i2cs[i]);
        }

#if !defined(PERIPHERALMAN)
        iios.reserve(descs->n_iio);
        for (int i = 0; i < descs->n_iio; ++i) {
            iios.emplace_back(descs->iios[i]);
        }
#endif

        pwms.reserve(descs->n_pwm);
        for (int i = 0; i < descs->n_pwm; ++i) {
            pwms.emplace_back(descs->pwms[i]);
        }

        spis.reserve(descs->n_spi);
        for (int i = 0; i < descs->n_spi; ++i) {
            spis.emplace_back(descs->spis[i]);
        }

        uarts.reserve(descs->n_uart);
        for (int i = 0; i < descs->n_uart; ++i) {
            uarts.emplace_back(descs->uarts[i]);
        }

        uart_ows.reserve(descs->n_uart_ow);
        for (int i = 0; i < descs->n_uart_ow; ++i) {
            uart_ows.emplace_back(descs->uart_ows[i]);
        }

        if (descs->leftover_str) {
            leftoverStr = std::string(descs->leftover_str);
        } else {
            leftoverStr = std::string("");
        }
    }

    MraaIo() : descs() {}

    ~MraaIo()
    {
        if (descs->leftover_str) {
            free(descs->leftover_str);
        }

        if (descs->n_aio) {
            free(descs->aios);
        }
        if (descs->n_gpio) {
            free(descs->gpios);
        }
        if (descs->n_i2c) {
            free(descs->i2cs);
        }
#if !defined(PERIPHERALMAN)
        if (descs->n_iio) {
            free(descs->iios);
        }
#endif
        if (descs->n_pwm) {
            free(descs->pwms);
        }
        if (descs->n_spi) {
            free(descs->spis);
        }
        if (descs->n_uart) {
            free(descs->uarts);
        }
        if (descs->n_uart_ow) {
            free(descs->uart_ows);
        }

        /* Finally free the mraa_io_descriptor structure. */
        free(descs);
    }

  public:
    std::vector<Aio> aios;
    std::vector<Gpio> gpios;
    std::vector<I2c> i2cs;
#if !defined(PERIPHERALMAN)
    std::vector<Iio> iios;
#endif
    std::vector<Pwm> pwms;
    std::vector<Spi> spis;
    std::vector<Uart> uarts;
    std::vector<UartOW> uart_ows;

  private:
    /* Used exclusively by the UPM library. */
    std::string leftoverStr;

  public:
    /* This is used mainly by sensors that use C structs/functions in C++ code. */
    mraa_io_descriptor*
    getMraaDescriptors()
    {
        return descs;
    }

    std::string
    getLeftoverStr()
    {
        return leftoverStr;
    }
};
}
<commit_msg>initio: Add safety checks inside MraaIo destructor<commit_after>/*
 * Author: Mihai Stefanescu <mihai.stefanescu@rinftech.com>
 * Copyright (c) 2018 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include "initio.h"
#include <stdexcept>
#include <string>
#include <vector>

#include "aio.hpp"
#include "gpio.hpp"
#include "i2c.hpp"

#if !defined(PERIPHERALMAN)
#include "iio.hpp"
#endif

#include "pwm.hpp"
#include "spi.hpp"
#include "uart.hpp"
#include "uart_ow.hpp"

namespace mraa
{
class MraaIo
{
  private:
    mraa_io_descriptor* descs = nullptr;

  public:
    MraaIo(const std::string& initStr) : descs()
    {
        if (mraa_io_init(initStr.c_str(), &descs) != MRAA_SUCCESS) {
            throw std::runtime_error("mraa_io_init error");
        }

        aios.reserve(descs->n_aio);
        for (int i = 0; i < descs->n_aio; ++i) {
            aios.emplace_back(descs->aios[i]);
        }

        gpios.reserve(descs->n_gpio);
        for (int i = 0; i < descs->n_gpio; ++i) {
            gpios.emplace_back(descs->gpios[i]);
        }

        i2cs.reserve(descs->n_i2c);
        for (int i = 0; i < descs->n_i2c; ++i) {
            i2cs.emplace_back(descs->i2cs[i]);
        }

#if !defined(PERIPHERALMAN)
        iios.reserve(descs->n_iio);
        for (int i = 0; i < descs->n_iio; ++i) {
            iios.emplace_back(descs->iios[i]);
        }
#endif

        pwms.reserve(descs->n_pwm);
        for (int i = 0; i < descs->n_pwm; ++i) {
            pwms.emplace_back(descs->pwms[i]);
        }

        spis.reserve(descs->n_spi);
        for (int i = 0; i < descs->n_spi; ++i) {
            spis.emplace_back(descs->spis[i]);
        }

        uarts.reserve(descs->n_uart);
        for (int i = 0; i < descs->n_uart; ++i) {
            uarts.emplace_back(descs->uarts[i]);
        }

        uart_ows.reserve(descs->n_uart_ow);
        for (int i = 0; i < descs->n_uart_ow; ++i) {
            uart_ows.emplace_back(descs->uart_ows[i]);
        }

        if (descs->leftover_str) {
            leftoverStr = std::string(descs->leftover_str);
        } else {
            leftoverStr = std::string("");
        }
    }

    MraaIo() : descs() {}

    ~MraaIo()
    {
        if (descs != nullptr) {
            if (descs->leftover_str) {
                free(descs->leftover_str);
            }
            if (descs->n_aio) {
                free(descs->aios);
            }
            if (descs->n_gpio) {
                free(descs->gpios);
            }
            if (descs->n_i2c) {
                free(descs->i2cs);
            }
#if !defined(PERIPHERALMAN)
            if (descs->n_iio) {
                free(descs->iios);
            }
#endif
            if (descs->n_pwm) {
                free(descs->pwms);
            }
            if (descs->n_spi) {
                free(descs->spis);
            }
            if (descs->n_uart) {
                free(descs->uarts);
            }
            if (descs->n_uart_ow) {
                free(descs->uart_ows);
            }

            /* Finally free the mraa_io_descriptor structure. */
            free(descs);
        }
    }

  public:
    std::vector<Aio> aios;
    std::vector<Gpio> gpios;
    std::vector<I2c> i2cs;
#if !defined(PERIPHERALMAN)
    std::vector<Iio> iios;
#endif
    std::vector<Pwm> pwms;
    std::vector<Spi> spis;
    std::vector<Uart> uarts;
    std::vector<UartOW> uart_ows;

  private:
    /* Used exclusively by the UPM library. */
    std::string leftoverStr;

  public:
    /* This is used mainly by sensors that use C structs/functions in C++ code. */
    mraa_io_descriptor*
    getMraaDescriptors()
    {
        return descs;
    }

    std::string
    getLeftoverStr()
    {
        return leftoverStr;
    }
};
}
<|endoftext|>


<commit_before>// zlib input file stream wrapper.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998  Bernie Bright - bbright@c031.aone.net.au
//
// 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; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA  02111-1307, USA.
//
// $Id$

#include <ctype.h> // isspace()

#ifdef SG_HAVE_STD_INCLUDES
# include <cerrno>
# include <string>
#else
# include <errno.h>
#endif

#include "sgstream.hxx"

sg_gzifstream::sg_gzifstream()
    : istream(&gzbuf)
{
}

//-----------------------------------------------------------------------------
//
// Open a possibly gzipped file for reading.
//
sg_gzifstream::sg_gzifstream( const string& name, ios_openmode io_mode )
    : istream(&gzbuf)
{
    this->open( name, io_mode );
}

//-----------------------------------------------------------------------------
//
// Attach a stream to an already opened file descriptor.
//
sg_gzifstream::sg_gzifstream( int fd, ios_openmode io_mode )
    : istream(&gzbuf)
{
    gzbuf.attach( fd, io_mode );
}

//-----------------------------------------------------------------------------
//
// Open a possibly gzipped file for reading.
// If the initial open fails and the filename has a ".gz" extension then
// remove the extension and try again.
// If the initial open fails and the filename doesn't have a ".gz" extension
// then append ".gz" and try again.
//
void
sg_gzifstream::open( const string& name, ios_openmode io_mode )
{
    gzbuf.open( name.c_str(), io_mode );
    if ( ! gzbuf.is_open() )
    {
	string s = name;
	if ( s.substr( s.length() - 3, 3 ) == ".gz" )
	{
	    // remove ".gz" suffix
	    s.replace( s.length() - 3, 3, "" );
// 	    s.erase( s.length() - 3, 3 );
	}
	else
	{
	    // Append ".gz" suffix
	    s += ".gz";
	}

	// Try again.
	gzbuf.open( s.c_str(), io_mode );
    }
}

void
sg_gzifstream::attach( int fd, ios_openmode io_mode )
{
    gzbuf.attach( fd, io_mode );
}

//
// Manipulators
//

istream&
skipeol( istream& in )
{
    char c = '\0';
    // skip to end of line.

#ifdef __MWERKS__
    while ( in.get(c) && c != '\0' ) {
#else
    while ( in.get(c) ) {
#endif
    	if ( (c == '\n') || (c == '\r') ) {
	    break;
	}
    }

    return in;
}

istream&
skipws( istream& in ) {
    char c;
#ifdef __MWERKS__
    while ( in.get(c) && c != '\0' ) {
#else
    while ( in.get(c) ) {
#endif

#ifdef __MWERKS__
	if ( ! isspace( c ) && c != '\n' ) {
#else
	if ( ! isspace( c ) ) {
#endif
	    // put pack the non-space character
	    in.putback(c);
	    break;
	}
    }
    return in;
}

istream&
skipcomment( istream& in )
{
    while ( in )
    {
	// skip whitespace
#ifdef __MWERKS__
	in >> ::skipws;
#else
	in >> skipws;
#endif

	char c;
	if ( in.get( c ) && c != '#' )
	{
	    // not a comment
	    in.putback(c);
	    break;
	}
	in >> skipeol;
    }
    return in;
}

<commit_msg>Use the SimGear default notation.<commit_after>// zlib input file stream wrapper.
//
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998  Bernie Bright - bbright@c031.aone.net.au
//
// 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; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA  02111-1307, USA.
//
// $Id$

#include <simgear/compiler.h>
#include STL_STRING

#include <ctype.h> // isspace()

#ifdef SG_HAVE_STD_INCLUDES
# include <cerrno>
#else
# include <errno.h>
#endif

#include "sgstream.hxx"

sg_gzifstream::sg_gzifstream()
    : istream(&gzbuf)
{
}

//-----------------------------------------------------------------------------
//
// Open a possibly gzipped file for reading.
//
sg_gzifstream::sg_gzifstream( const string& name, ios_openmode io_mode )
    : istream(&gzbuf)
{
    this->open( name, io_mode );
}

//-----------------------------------------------------------------------------
//
// Attach a stream to an already opened file descriptor.
//
sg_gzifstream::sg_gzifstream( int fd, ios_openmode io_mode )
    : istream(&gzbuf)
{
    gzbuf.attach( fd, io_mode );
}

//-----------------------------------------------------------------------------
//
// Open a possibly gzipped file for reading.
// If the initial open fails and the filename has a ".gz" extension then
// remove the extension and try again.
// If the initial open fails and the filename doesn't have a ".gz" extension
// then append ".gz" and try again.
//
void
sg_gzifstream::open( const string& name, ios_openmode io_mode )
{
    gzbuf.open( name.c_str(), io_mode );
    if ( ! gzbuf.is_open() )
    {
	string s = name;
	if ( s.substr( s.length() - 3, 3 ) == ".gz" )
	{
	    // remove ".gz" suffix
	    s.replace( s.length() - 3, 3, "" );
// 	    s.erase( s.length() - 3, 3 );
	}
	else
	{
	    // Append ".gz" suffix
	    s += ".gz";
	}

	// Try again.
	gzbuf.open( s.c_str(), io_mode );
    }
}

void
sg_gzifstream::attach( int fd, ios_openmode io_mode )
{
    gzbuf.attach( fd, io_mode );
}

//
// Manipulators
//

istream&
skipeol( istream& in )
{
    char c = '\0';
    // skip to end of line.

#ifdef __MWERKS__
    while ( in.get(c) && c != '\0' ) {
#else
    while ( in.get(c) ) {
#endif
    	if ( (c == '\n') || (c == '\r') ) {
	    break;
	}
    }

    return in;
}

istream&
skipws( istream& in ) {
    char c;
#ifdef __MWERKS__
    while ( in.get(c) && c != '\0' ) {
#else
    while ( in.get(c) ) {
#endif

#ifdef __MWERKS__
	if ( ! isspace( c ) && c != '\n' ) {
#else
	if ( ! isspace( c ) ) {
#endif
	    // put pack the non-space character
	    in.putback(c);
	    break;
	}
    }
    return in;
}

istream&
skipcomment( istream& in )
{
    while ( in )
    {
	// skip whitespace
#ifdef __MWERKS__
	in >> ::skipws;
#else
	in >> skipws;
#endif

	char c;
	if ( in.get( c ) && c != '#' )
	{
	    // not a comment
	    in.putback(c);
	    break;
	}
	in >> skipeol;
    }
    return in;
}

<|endoftext|>