<commit_before>/*
 *  templatedlg.cpp  -  dialogue to create, edit and delete alarm templates
 *  Program:  kalarm
 *  (C) 2004 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "kalarm.h"

#include <qlayout.h>
#include <qpushbutton.h>
#include <qwhatsthis.h>

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>

#include "editdlg.h"
#include "alarmcalendar.h"
#include "functions.h"
#include "templatelistview.h"
#include "templatedlg.moc"

static const char TMPL_DIALOG_NAME[] = "TemplateDialog";

TemplateDlg* TemplateDlg::mInstance = 0;

TemplateDlg::TemplateDlg(QWidget* parent, const char* name)
	: KDialogBase(KDialogBase::Plain, i18n("Alarm Templates"), Close, Ok, parent, name, false, true)
{
	QWidget* topWidget = plainPage();
	QBoxLayout* topLayout = new QHBoxLayout(topWidget);
	topLayout->setSpacing(spacingHint());

	QBoxLayout* layout = new QVBoxLayout(topLayout);
	mTemplateList = new TemplateListView(true, i18n("The list of alarm templates"), topWidget);
	mTemplateList->setSelectionMode(QListView::Extended);
	mTemplateList->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
	connect(mTemplateList, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
	layout->addWidget(mTemplateList);

	layout = new QVBoxLayout(topLayout);
	QPushButton* button = new QPushButton(i18n("&New..."), topWidget);
	button->setFixedSize(button->sizeHint());
	connect(button, SIGNAL(clicked()), SLOT(slotNew()));
	QWhatsThis::add(button, i18n("Create a new alarm template"));
	layout->addWidget(button);

	mEditButton = new QPushButton(i18n("&Edit..."), topWidget);
	mEditButton->setFixedSize(mEditButton->sizeHint());
	connect(mEditButton, SIGNAL(clicked()), SLOT(slotEdit()));
	QWhatsThis::add(mEditButton, i18n("Edit the currently highlighted alarm template"));
	layout->addWidget(mEditButton);

	mCopyButton = new QPushButton(i18n("Co&py"), topWidget);
	mCopyButton->setFixedSize(mCopyButton->sizeHint());
	connect(mCopyButton, SIGNAL(clicked()), SLOT(slotCopy()));
	QWhatsThis::add(mCopyButton,
	      i18n("Create a new alarm template based on a copy of the currently highlighted template"));
	layout->addWidget(mCopyButton);

	mDeleteButton = new QPushButton(i18n("&Delete"), topWidget);
	mDeleteButton->setFixedSize(mDeleteButton->sizeHint());
	connect(mDeleteButton, SIGNAL(clicked()), SLOT(slotDelete()));
	QWhatsThis::add(mDeleteButton, i18n("Delete the currently highlighted alarm template"));
	layout->addWidget(mDeleteButton);

	mTemplateList->refresh();
	slotSelectionChanged();          // enable/disable buttons as appropriate

	QSize s;
	if (KAlarm::readConfigWindowSize(TMPL_DIALOG_NAME, s))
		resize(s);
}

/******************************************************************************
*  Destructor.
*/
TemplateDlg::~TemplateDlg()
{
	mInstance = 0;
}

/******************************************************************************
*  Create an instance, if none already exists.
*/
TemplateDlg* TemplateDlg::create(QWidget* parent, const char* name)
{
	if (mInstance)
		return 0;
	mInstance = new TemplateDlg(parent, name);
	return mInstance;
}

/******************************************************************************
*  Called when the New Template button is clicked to create a new template
*  based on the currently selected alarm.
*/
void TemplateDlg::slotNew()
{
	createTemplate(0, this, mTemplateList);
}

/******************************************************************************
*  Called when the Copy button is clicked to edit a copy of an existing alarm,
*  to add to the list.
*/
void TemplateDlg::slotCopy()
{
	TemplateListViewItem* item = mTemplateList->singleSelectedItem();
	if (item)
	{
		KAEvent event = item->event();
		createTemplate(&event, mTemplateList);
	}
}

/******************************************************************************
*  Create a new template.
*  If 'event' is non-zero, base the new template on an existing event or template.
*/
void TemplateDlg::createTemplate(const KAEvent* event, QWidget* parent, TemplateListView* view)
{
	EditAlarmDlg editDlg(true, i18n("New Alarm Template"), parent, "editDlg", event);
	if (editDlg.exec() == QDialog::Accepted)
	{
		KAEvent event;
		editDlg.getEvent(event);

		// Add the template to the displayed lists and to the calendar file
		AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen();
		if (cal)
		{
			cal->addEvent(event);
			cal->save();
			cal->emitEmptyStatus();
		}
		TemplateListView::addEvent(event, view);
	}
}

/******************************************************************************
*  Called when the Modify button is clicked to edit the currently highlighted
*  alarm in the list.
*/
void TemplateDlg::slotEdit()
{
	TemplateListViewItem* item = mTemplateList->singleSelectedItem();
	if (item)
	{
		KAEvent event = item->event();
		EditAlarmDlg* editDlg = new EditAlarmDlg(true, i18n("Edit Alarm Template"), this, "editDlg", &event);
		if (editDlg->exec() == QDialog::Accepted)
		{
			KAEvent newEvent;
			editDlg->getEvent(newEvent);

			// Update the event in the displays and in the calendar file
			QString id = event.id();
			newEvent.setEventID(id);
			AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen();
			if (cal)
			{
				cal->updateEvent(newEvent);
				cal->save();
			}
			TemplateListView::modifyEvent(id, newEvent, mTemplateList);
		}
	}
}

/******************************************************************************
*  Called when the Delete button is clicked to delete the currently highlighted
*  alarms in the list.
*/
void TemplateDlg::slotDelete()
{
	QValueList<EventListViewItemBase*> items = mTemplateList->selectedItems();
	int n = items.count();
	if (KMessageBox::warningContinueCancel(this, i18n("Do you really want to delete the selected alarm template?",
	                                                  "Do you really want to delete the %n selected alarm templates?", n),
	                                       i18n("Delete Alarm Template", "Delete Alarm Templates", n), KGuiItem(i18n("&Delete"), "editdelete"))
		    != KMessageBox::Continue)
		return;
	AlarmCalendar::templateCalendar()->startUpdate();    // prevent multiple saves of the calendar until we're finished
	for (QValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
	{
		TemplateListViewItem* item = (TemplateListViewItem*)(*it);
		KAEvent event = item->event();

		// Delete the event from the displays
		QString id = event.id();
		AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen();
		if (cal)
		{
			cal->deleteEvent(id);
			cal->save();
			cal->emitEmptyStatus();
		}
		mTemplateList->deleteEvent(id);
	}
	AlarmCalendar::templateCalendar()->endUpdate();    // save the calendar now
}

/******************************************************************************
* Called when the group of items selected changes.
* Enable/disable the buttons depending on whether/how many templates are
* currently highlighted.
*/
void TemplateDlg::slotSelectionChanged()
{
	int count = mTemplateList->selectedCount();
	mEditButton->setEnabled(count == 1);
	mCopyButton->setEnabled(count == 1);
	mDeleteButton->setEnabled(count);
}

/******************************************************************************
*  Called when the dialog's size has changed.
*  Records the new size in the config file.
*/
void TemplateDlg::resizeEvent(QResizeEvent* re)
{
	if (isVisible())
		KAlarm::writeConfigWindowSize(TMPL_DIALOG_NAME, re->size());
	KDialog::resizeEvent(re);
}
<commit_msg>Fix compile error<commit_after>/*
 *  templatedlg.cpp  -  dialogue to create, edit and delete alarm templates
 *  Program:  kalarm
 *  (C) 2004 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "kalarm.h"

#include <qlayout.h>
#include <qpushbutton.h>
#include <qwhatsthis.h>

#include <klocale.h>
#include <kguiitem.h>
#include <kmessagebox.h>
#include <kdebug.h>

#include "editdlg.h"
#include "alarmcalendar.h"
#include "functions.h"
#include "templatelistview.h"
#include "templatedlg.moc"

static const char TMPL_DIALOG_NAME[] = "TemplateDialog";

TemplateDlg* TemplateDlg::mInstance = 0;

TemplateDlg::TemplateDlg(QWidget* parent, const char* name)
	: KDialogBase(KDialogBase::Plain, i18n("Alarm Templates"), Close, Ok, parent, name, false, true)
{
	QWidget* topWidget = plainPage();
	QBoxLayout* topLayout = new QHBoxLayout(topWidget);
	topLayout->setSpacing(spacingHint());

	QBoxLayout* layout = new QVBoxLayout(topLayout);
	mTemplateList = new TemplateListView(true, i18n("The list of alarm templates"), topWidget);
	mTemplateList->setSelectionMode(QListView::Extended);
	mTemplateList->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
	connect(mTemplateList, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
	layout->addWidget(mTemplateList);

	layout = new QVBoxLayout(topLayout);
	QPushButton* button = new QPushButton(i18n("&New..."), topWidget);
	button->setFixedSize(button->sizeHint());
	connect(button, SIGNAL(clicked()), SLOT(slotNew()));
	QWhatsThis::add(button, i18n("Create a new alarm template"));
	layout->addWidget(button);

	mEditButton = new QPushButton(i18n("&Edit..."), topWidget);
	mEditButton->setFixedSize(mEditButton->sizeHint());
	connect(mEditButton, SIGNAL(clicked()), SLOT(slotEdit()));
	QWhatsThis::add(mEditButton, i18n("Edit the currently highlighted alarm template"));
	layout->addWidget(mEditButton);

	mCopyButton = new QPushButton(i18n("Co&py"), topWidget);
	mCopyButton->setFixedSize(mCopyButton->sizeHint());
	connect(mCopyButton, SIGNAL(clicked()), SLOT(slotCopy()));
	QWhatsThis::add(mCopyButton,
	      i18n("Create a new alarm template based on a copy of the currently highlighted template"));
	layout->addWidget(mCopyButton);

	mDeleteButton = new QPushButton(i18n("&Delete"), topWidget);
	mDeleteButton->setFixedSize(mDeleteButton->sizeHint());
	connect(mDeleteButton, SIGNAL(clicked()), SLOT(slotDelete()));
	QWhatsThis::add(mDeleteButton, i18n("Delete the currently highlighted alarm template"));
	layout->addWidget(mDeleteButton);

	mTemplateList->refresh();
	slotSelectionChanged();          // enable/disable buttons as appropriate

	QSize s;
	if (KAlarm::readConfigWindowSize(TMPL_DIALOG_NAME, s))
		resize(s);
}

/******************************************************************************
*  Destructor.
*/
TemplateDlg::~TemplateDlg()
{
	mInstance = 0;
}

/******************************************************************************
*  Create an instance, if none already exists.
*/
TemplateDlg* TemplateDlg::create(QWidget* parent, const char* name)
{
	if (mInstance)
		return 0;
	mInstance = new TemplateDlg(parent, name);
	return mInstance;
}

/******************************************************************************
*  Called when the New Template button is clicked to create a new template
*  based on the currently selected alarm.
*/
void TemplateDlg::slotNew()
{
	createTemplate(0, this, mTemplateList);
}

/******************************************************************************
*  Called when the Copy button is clicked to edit a copy of an existing alarm,
*  to add to the list.
*/
void TemplateDlg::slotCopy()
{
	TemplateListViewItem* item = mTemplateList->singleSelectedItem();
	if (item)
	{
		KAEvent event = item->event();
		createTemplate(&event, mTemplateList);
	}
}

/******************************************************************************
*  Create a new template.
*  If 'event' is non-zero, base the new template on an existing event or template.
*/
void TemplateDlg::createTemplate(const KAEvent* event, QWidget* parent, TemplateListView* view)
{
	EditAlarmDlg editDlg(true, i18n("New Alarm Template"), parent, "editDlg", event);
	if (editDlg.exec() == QDialog::Accepted)
	{
		KAEvent event;
		editDlg.getEvent(event);

		// Add the template to the displayed lists and to the calendar file
		AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen();
		if (cal)
		{
			cal->addEvent(event);
			cal->save();
			cal->emitEmptyStatus();
		}
		TemplateListView::addEvent(event, view);
	}
}

/******************************************************************************
*  Called when the Modify button is clicked to edit the currently highlighted
*  alarm in the list.
*/
void TemplateDlg::slotEdit()
{
	TemplateListViewItem* item = mTemplateList->singleSelectedItem();
	if (item)
	{
		KAEvent event = item->event();
		EditAlarmDlg* editDlg = new EditAlarmDlg(true, i18n("Edit Alarm Template"), this, "editDlg", &event);
		if (editDlg->exec() == QDialog::Accepted)
		{
			KAEvent newEvent;
			editDlg->getEvent(newEvent);

			// Update the event in the displays and in the calendar file
			QString id = event.id();
			newEvent.setEventID(id);
			AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen();
			if (cal)
			{
				cal->updateEvent(newEvent);
				cal->save();
			}
			TemplateListView::modifyEvent(id, newEvent, mTemplateList);
		}
	}
}

/******************************************************************************
*  Called when the Delete button is clicked to delete the currently highlighted
*  alarms in the list.
*/
void TemplateDlg::slotDelete()
{
	QValueList<EventListViewItemBase*> items = mTemplateList->selectedItems();
	int n = items.count();
	if (KMessageBox::warningContinueCancel(this, i18n("Do you really want to delete the selected alarm template?",
	                                                  "Do you really want to delete the %n selected alarm templates?", n),
	                                       i18n("Delete Alarm Template", "Delete Alarm Templates", n), KGuiItem(i18n("&Delete"), "editdelete"))
		    != KMessageBox::Continue)
		return;
	AlarmCalendar::templateCalendar()->startUpdate();    // prevent multiple saves of the calendar until we're finished
	for (QValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
	{
		TemplateListViewItem* item = (TemplateListViewItem*)(*it);
		KAEvent event = item->event();

		// Delete the event from the displays
		QString id = event.id();
		AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen();
		if (cal)
		{
			cal->deleteEvent(id);
			cal->save();
			cal->emitEmptyStatus();
		}
		mTemplateList->deleteEvent(id);
	}
	AlarmCalendar::templateCalendar()->endUpdate();    // save the calendar now
}

/******************************************************************************
* Called when the group of items selected changes.
* Enable/disable the buttons depending on whether/how many templates are
* currently highlighted.
*/
void TemplateDlg::slotSelectionChanged()
{
	int count = mTemplateList->selectedCount();
	mEditButton->setEnabled(count == 1);
	mCopyButton->setEnabled(count == 1);
	mDeleteButton->setEnabled(count);
}

/******************************************************************************
*  Called when the dialog's size has changed.
*  Records the new size in the config file.
*/
void TemplateDlg::resizeEvent(QResizeEvent* re)
{
	if (isVisible())
		KAlarm::writeConfigWindowSize(TMPL_DIALOG_NAME, re->size());
	KDialog::resizeEvent(re);
}
<|endoftext|>


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

/**
 * @file
 *   This file implements the OpenThread CoAP API.
 */

#include <openthread/coap.h>

#include "openthread-instance.h"
#include "coap/coap_header.hpp"

#if OPENTHREAD_ENABLE_APPLICATION_COAP

using namespace ot;

void otCoapHeaderInit(otCoapHeader *aHeader, otCoapType aType, otCoapCode aCode)
{
    Coap::Header *header = static_cast<Coap::Header *>(aHeader);
    header->Init(aType, aCode);
}

void otCoapHeaderSetToken(otCoapHeader *aHeader, const uint8_t *aToken, uint8_t aTokenLength)
{
    static_cast<Coap::Header *>(aHeader)->SetToken(aToken, aTokenLength);
}

void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength)
{
    static_cast<Coap::Header *>(aHeader)->SetToken(aTokenLength);
}

ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption)
{
    return static_cast<Coap::Header *>(aHeader)->AppendOption(*static_cast<const Coap::Header::Option *>(aOption));
}

ThreadError otCoapHeaderAppendUintOption(otCoapHeader *aHeader, uint16_t aNumber, uint32_t aValue)
{
    return static_cast<Coap::Header *>(aHeader)->AppendUintOption(aNumber, aValue);
}

ThreadError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve)
{
    return static_cast<Coap::Header *>(aHeader)->AppendObserveOption(aObserve);
}

ThreadError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath)
{
    return static_cast<Coap::Header *>(aHeader)->AppendUriPathOptions(aUriPath);
}

ThreadError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge)
{
    return static_cast<Coap::Header *>(aHeader)->AppendMaxAgeOption(aMaxAge);
}

ThreadError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery)
{
    return static_cast<Coap::Header *>(aHeader)->AppendUriQueryOption(aUriQuery);
}

void otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader)
{
    static_cast<Coap::Header *>(aHeader)->SetPayloadMarker();
}

void otCoapHeaderSetMessageId(otCoapHeader *aHeader, uint16_t aMessageId)
{
    return static_cast<Coap::Header *>(aHeader)->SetMessageId(aMessageId);
}

otCoapType otCoapHeaderGetType(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetType();
}

otCoapCode otCoapHeaderGetCode(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetCode();
}

uint16_t otCoapHeaderGetMessageId(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetMessageId();
}

uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetTokenLength();
}

const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetToken();
}

const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader)
{
    return static_cast<const otCoapOption *>(static_cast<Coap::Header *>(aHeader)->GetFirstOption());
}

const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader)
{
    return static_cast<const otCoapOption *>(static_cast<Coap::Header *>(aHeader)->GetNextOption());
}

otMessage *otCoapNewMessage(otInstance *aInstance, const otCoapHeader *aHeader)
{
    Message *message;
    VerifyOrExit(aHeader != NULL, message = NULL);
    message = aInstance->mThreadNetif.GetCoap().NewMessage(*(static_cast<const Coap::Header *>(aHeader)));
exit:
    return message;
}

ThreadError otCoapSendRequest(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo,
                              otCoapResponseHandler aHandler, void *aContext)
{
    return aInstance->mThreadNetif.GetCoap().SendMessage(
               *static_cast<Message *>(aMessage),
               *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
               aHandler, aContext);
}

ThreadError otCoapStart(otInstance *aInstance, uint16_t aPort)
{
    return aInstance->mApplicationCoap.Start(aPort);
}

ThreadError otCoapStop(otInstance *aInstance)
{
    return aInstance->mApplicationCoap.Stop();
}

ThreadError otCoapAddResource(otInstance *aInstance, otCoapResource *aResource)
{
    return aInstance->mApplicationCoap.AddResource(*static_cast<Coap::Resource *>(aResource));
}

void otCoapRemoveResource(otInstance *aInstance, otCoapResource *aResource)
{
    aInstance->mApplicationCoap.RemoveResource(*static_cast<Coap::Resource *>(aResource));
}

ThreadError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    return aInstance->mApplicationCoap.SendMessage(
               *static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

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

/**
 * @file
 *   This file implements the OpenThread CoAP API.
 */

#include <openthread/coap.h>

#include "openthread-instance.h"
#include "coap/coap_header.hpp"

#if OPENTHREAD_ENABLE_APPLICATION_COAP

using namespace ot;

void otCoapHeaderInit(otCoapHeader *aHeader, otCoapType aType, otCoapCode aCode)
{
    Coap::Header *header = static_cast<Coap::Header *>(aHeader);
    header->Init(aType, aCode);
}

void otCoapHeaderSetToken(otCoapHeader *aHeader, const uint8_t *aToken, uint8_t aTokenLength)
{
    static_cast<Coap::Header *>(aHeader)->SetToken(aToken, aTokenLength);
}

void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength)
{
    static_cast<Coap::Header *>(aHeader)->SetToken(aTokenLength);
}

ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption)
{
    return static_cast<Coap::Header *>(aHeader)->AppendOption(*static_cast<const Coap::Header::Option *>(aOption));
}

ThreadError otCoapHeaderAppendUintOption(otCoapHeader *aHeader, uint16_t aNumber, uint32_t aValue)
{
    return static_cast<Coap::Header *>(aHeader)->AppendUintOption(aNumber, aValue);
}

ThreadError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve)
{
    return static_cast<Coap::Header *>(aHeader)->AppendObserveOption(aObserve);
}

ThreadError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath)
{
    return static_cast<Coap::Header *>(aHeader)->AppendUriPathOptions(aUriPath);
}

ThreadError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge)
{
    return static_cast<Coap::Header *>(aHeader)->AppendMaxAgeOption(aMaxAge);
}

ThreadError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery)
{
    return static_cast<Coap::Header *>(aHeader)->AppendUriQueryOption(aUriQuery);
}

void otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader)
{
    static_cast<Coap::Header *>(aHeader)->SetPayloadMarker();
}

void otCoapHeaderSetMessageId(otCoapHeader *aHeader, uint16_t aMessageId)
{
    return static_cast<Coap::Header *>(aHeader)->SetMessageId(aMessageId);
}

otCoapType otCoapHeaderGetType(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetType();
}

otCoapCode otCoapHeaderGetCode(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetCode();
}

uint16_t otCoapHeaderGetMessageId(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetMessageId();
}

uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetTokenLength();
}

const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader)
{
    return static_cast<const Coap::Header *>(aHeader)->GetToken();
}

const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader)
{
    return static_cast<const otCoapOption *>(static_cast<Coap::Header *>(aHeader)->GetFirstOption());
}

const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader)
{
    return static_cast<const otCoapOption *>(static_cast<Coap::Header *>(aHeader)->GetNextOption());
}

otMessage *otCoapNewMessage(otInstance *aInstance, const otCoapHeader *aHeader)
{
    Message *message;
    VerifyOrExit(aHeader != NULL, message = NULL);
    message = aInstance->mApplicationCoap.NewMessage(*(static_cast<const Coap::Header *>(aHeader)));
exit:
    return message;
}

ThreadError otCoapSendRequest(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo,
                              otCoapResponseHandler aHandler, void *aContext)
{
    return aInstance->mApplicationCoap.SendMessage(
               *static_cast<Message *>(aMessage),
               *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
               aHandler, aContext);
}

ThreadError otCoapStart(otInstance *aInstance, uint16_t aPort)
{
    return aInstance->mApplicationCoap.Start(aPort);
}

ThreadError otCoapStop(otInstance *aInstance)
{
    return aInstance->mApplicationCoap.Stop();
}

ThreadError otCoapAddResource(otInstance *aInstance, otCoapResource *aResource)
{
    return aInstance->mApplicationCoap.AddResource(*static_cast<Coap::Resource *>(aResource));
}

void otCoapRemoveResource(otInstance *aInstance, otCoapResource *aResource)
{
    aInstance->mApplicationCoap.RemoveResource(*static_cast<Coap::Resource *>(aResource));
}

ThreadError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    return aInstance->mApplicationCoap.SendMessage(
               *static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef UTILS_HASH_HH_
#define UTILS_HASH_HH_

#include <functional>
#include "core/apply.hh"

namespace utils {

// public for unit testing etc
inline size_t hash_combine(size_t left, size_t right) {
    return left + 0x9e3779b9 + (right << 6) + (right >> 2);
}

struct tuple_hash {
private:
    // CMH. Add specializations here to handle recursive tuples
    template<typename T>
    static size_t hash(const T& t) {
        return std::hash<T>()(t);
    }
    template<size_t index, typename...Types>
    struct hash_impl {
        size_t operator()(const std::tuple<Types...>& t, size_t a) const {
            return hash_impl<index-1, Types...>()(t, hash_combine(hash(std::get<index>(t)), a));
        }
        size_t operator()(const std::tuple<Types...>& t) const {
            return hash_impl<index-1, Types...>()(t, hash(std::get<index>(t)));
        }
    };
    template<class...Types>
    struct hash_impl<0, Types...> {
        size_t operator()(const std::tuple<Types...>& t, size_t a) const {
            return hash_combine(hash(std::get<0>(t)), a);
        }
        size_t operator()(const std::tuple<Types...>& t) const {
            return hash(std::get<0>(t));
        }
    };
public:
    template<typename T1, typename T2>
    size_t operator()(const std::pair<T1, T2>& p) const {
        return hash_combine(hash(p.first), hash(p.second));
    }
    template<typename... Args>
    size_t operator()(const std::tuple<Args...>& v) const;
};

template<typename... Args>
inline size_t tuple_hash::operator()(const std::tuple<Args...>& v) const {
    return hash_impl<std::tuple_size<std::tuple<Args...>>::value - 1, Args...>()(v);
}
template<>
inline size_t tuple_hash::operator()(const std::tuple<>& v) const {
    return 0;
}

}

#endif /* UTILS_HASH_HH_ */
<commit_msg>tuple_hash: Add convinence operator for two arguments (non-pair)<commit_after>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef UTILS_HASH_HH_
#define UTILS_HASH_HH_

#include <functional>
#include "core/apply.hh"

namespace utils {

// public for unit testing etc
inline size_t hash_combine(size_t left, size_t right) {
    return left + 0x9e3779b9 + (right << 6) + (right >> 2);
}

struct tuple_hash {
private:
    // CMH. Add specializations here to handle recursive tuples
    template<typename T>
    static size_t hash(const T& t) {
        return std::hash<T>()(t);
    }
    template<size_t index, typename...Types>
    struct hash_impl {
        size_t operator()(const std::tuple<Types...>& t, size_t a) const {
            return hash_impl<index-1, Types...>()(t, hash_combine(hash(std::get<index>(t)), a));
        }
        size_t operator()(const std::tuple<Types...>& t) const {
            return hash_impl<index-1, Types...>()(t, hash(std::get<index>(t)));
        }
    };
    template<class...Types>
    struct hash_impl<0, Types...> {
        size_t operator()(const std::tuple<Types...>& t, size_t a) const {
            return hash_combine(hash(std::get<0>(t)), a);
        }
        size_t operator()(const std::tuple<Types...>& t) const {
            return hash(std::get<0>(t));
        }
    };
public:
    template<typename T1, typename T2>
    size_t operator()(const std::pair<T1, T2>& p) const {
        return hash_combine(hash(p.first), hash(p.second));
    }
    template<typename T1, typename T2>
    size_t operator()(const T1& t1, const T2& t2) const {
        return hash_combine(hash(t1), hash(t2));
    }
    template<typename... Args>
    size_t operator()(const std::tuple<Args...>& v) const;
};

template<typename... Args>
inline size_t tuple_hash::operator()(const std::tuple<Args...>& v) const {
    return hash_impl<std::tuple_size<std::tuple<Args...>>::value - 1, Args...>()(v);
}
template<>
inline size_t tuple_hash::operator()(const std::tuple<>& v) const {
    return 0;
}

}

#endif /* UTILS_HASH_HH_ */
<|endoftext|>


<commit_before>#ifndef ASSERT_HPP
#define ASSERT_HPP
#include <iostream>
#include "core/debug/break.hpp"

namespace tz
{

	namespace debug
	{
		static bool assert_failure = false;
	}

#ifdef topaz_assert
#undef topaz_assert
#endif
/**
 * Evaluate the expression. This should be used to guarantee that expressions are true at runtime.
 * If an assertion failure is catastrophic for the machine (such as a GPU/BSOD), use a hard-assert instead.
 * If the expression can be evaluated at compile-time, use a static_assert -- Guaranteed by the C++ standard since C++11.
 * If TOPAZ_DEBUG == 1 and the expression evaluates to false, send an error message to cerr and send a breakpoint signal to the debugger. If no debugger is attached, the OS will likely kill the program.
 * Note: To guarantee termination on failure without a debugger, use a hard-assert.
 */
#define topaz_assert(EXPRESSION, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_message(std::cerr, false, \
"Assertion failure: ", #EXPRESSION, "\nIn file: ", __FILE__, \
" on line ", __LINE__, ":\n\t", __VA_ARGS__))

	template<typename... Args>
	inline void assert_message([[maybe_unused]] std::ostream &out, [[maybe_unused]] bool hard, [[maybe_unused]] Args &&... args)
	{
#if TOPAZ_DEBUG
		std::flush(out);
		#if TOPAZ_UNIT_TEST
			bool unit_test = true;
		#else
			bool unit_test = false;
		#endif
		if(unit_test)
		{
			// Note: We don't print out the assertion message as a unit-test. It's expected that the expectation failure sort this out instead.
			debug::assert_failure = true;
		}
		else
		{
			// Use the given ostream.
			(out << ... << args) << std::endl;
			tz::debugbreak();
			if(hard)
			{
				out << "[HARD ASSERT DETECTED. ABORTING.]\n" << std::endl;
				std::abort();
			}
		}
#endif
	}

#ifdef topaz_assertf
#undef topaz_assertf
#endif
#define topaz_assertf(EXPRESSION, fmt, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_messagef(stderr, \
"Assertion failure: %s\nIn file: %s on line %d:\n\t" fmt, #EXPRESSION, __FILE__, __LINE__, __VA_ARGS__))

    template<typename... Args>
    inline void assert_messagef(FILE* output_stream, const char* fmt, Args&&... args)
    {
        #if TOPAZ_DEBUG
            fflush(output_stream);
            fprintf(output_stream, fmt, std::forward<Args>(args)...);
            std::abort();
		#endif
    }

	namespace debug::test
	{
		inline bool assert_failure()
		{
			return tz::debug::assert_failure;
		}

		inline void clear_assert_failure()
		{
			tz::debug::assert_failure = false;
		}
	}

#ifdef topaz_hard_assert
#undef topaz_hard_assert
#endif
/**
 * Evaluate the expression in a stricter manner than a normal assert.
 * If TOPAZ_DEBUG == 1 and the expression evaluates to false, send an error message to cerr and send a breakpoint signal to the debugger. After that, invoke abort() to guarantee program termination.
 */
#define topaz_hard_assert(EXPRESSION, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_message(std::cerr, true, \
"[FATAL ERROR] Hard Assertion failure: ", #EXPRESSION, "\nIn file: ", __FILE__, \
" on line ", __LINE__, ":\n\t", __VA_ARGS__))
#ifdef topaz_assert_clear
#undef topaz_assert_clear
#endif
#define topaz_assert_clear() tz::debug::test::clear_assert_failure()
}

#endif // ASSERT_HPP<commit_msg>+ Added topaz_hard_assertf and fixed an issue where topaz_assertf did not match the behaviour of topaz_assert<commit_after>#ifndef ASSERT_HPP
#define ASSERT_HPP
#include <iostream>
#include "core/debug/break.hpp"

namespace tz
{

	namespace debug
	{
		static bool assert_failure = false;
	}

#ifdef topaz_assert
#undef topaz_assert
#endif
/**
 * Evaluate the expression. This should be used to guarantee that expressions are true at runtime.
 * If an assertion failure is catastrophic for the machine (such as a GPU/BSOD), use a hard-assert instead.
 * If the expression can be evaluated at compile-time, use a static_assert -- Guaranteed by the C++ standard since C++11.
 * If TOPAZ_DEBUG == 1 and the expression evaluates to false, send an error message to cerr and send a breakpoint signal to the debugger. If no debugger is attached, the OS will likely kill the program.
 * Note: To guarantee termination on failure without a debugger, use a hard-assert.
 */
#define topaz_assert(EXPRESSION, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_message(std::cerr, false, \
"Assertion failure: ", #EXPRESSION, "\nIn file: ", __FILE__, \
" on line ", __LINE__, ":\n\t", __VA_ARGS__))

	template<typename... Args>
	inline void assert_message([[maybe_unused]] std::ostream &out, [[maybe_unused]] bool hard, [[maybe_unused]] Args &&... args)
	{
#if TOPAZ_DEBUG
		std::flush(out);
		#if TOPAZ_UNIT_TEST
			bool unit_test = true;
		#else
			bool unit_test = false;
		#endif
		if(unit_test)
		{
			// Note: We don't print out the assertion message as a unit-test. It's expected that the expectation failure sort this out instead.
			debug::assert_failure = true;
		}
		else
		{
			// Use the given ostream.
			(out << ... << args) << std::endl;
			tz::debugbreak();
			if(hard)
			{
				out << "[HARD ASSERT DETECTED. ABORTING.]\n" << std::endl;
				std::abort();
			}
		}
#endif
	}

#ifdef topaz_assertf
#undef topaz_assertf
#endif
#define topaz_assertf(EXPRESSION, fmt, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_messagef(stderr, false, \
"Assertion failure: %s\nIn file: %s on line %d:\n\t" fmt, #EXPRESSION, __FILE__, __LINE__, __VA_ARGS__))

    template<typename... Args>
    inline void assert_messagef([[maybe_unused]] FILE* output_stream, [[maybe_unused]] bool hard, [[maybe_unused]] const char* fmt, [[maybe_unused]] Args&&... args)
    {
#if TOPAZ_DEBUG
		#if TOPAZ_UNIT_TEST
			bool unit_test = true;
		#else
			bool unit_test = false;
		#endif
		if(unit_test)
		{
			// Note: We don't print out the assertion message as a unit-test. It's expected that the expectation failure sort this out instead.
			debug::assert_failure = true;
		}
		else
		{
			// Use the given ostream.
			fflush(output_stream);
			fprintf(output_stream, fmt, std::forward<Args>(args)...);
			tz::debugbreak();
			if(hard)
			{
				fprintf(output_stream, "%s", "[HARD ASSERT DETECTED. ABORTING.]\n");
				std::abort();
			}
		}
#endif
    }

	namespace debug::test
	{
		inline bool assert_failure()
		{
			return tz::debug::assert_failure;
		}

		inline void clear_assert_failure()
		{
			tz::debug::assert_failure = false;
		}
	}

#ifdef topaz_hard_assert
#undef topaz_hard_assert
#endif
/**
 * Evaluate the expression in a stricter manner than a normal assert.
 * If TOPAZ_DEBUG == 1 and the expression evaluates to false, send an error message to cerr and send a breakpoint signal to the debugger. After that, invoke abort() to guarantee program termination.
 */
#define topaz_hard_assert(EXPRESSION, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_message(std::cerr, true, \
"[FATAL ERROR] Hard Assertion failure: ", #EXPRESSION, "\nIn file: ", __FILE__, \
" on line ", __LINE__, ":\n\t", __VA_ARGS__))

#ifdef topaz_hard_assertf
#undef topaz_hard_assertf
#endif
#define topaz_hard_assertf(EXPRESSION, fmt, ...) ((EXPRESSION) ? \
(void)0 : tz::assert_messagef(stderr, true, \
"[FATAL ERROR] Hard Assertion failure: %s\nIn file: %s on line %d:\n\t" fmt, #EXPRESSION, __FILE__, __LINE__, __VA_ARGS__))

#ifdef topaz_assert_clear
#undef topaz_assert_clear
#endif
#define topaz_assert_clear() tz::debug::test::clear_assert_failure()
}

#endif // ASSERT_HPP<|endoftext|>


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

/** @file
@brief Implementation of the ACI transport layer module
*/

#include <SPI.h>
#include "hal_platform.h"
#include "hal_aci_tl.h"
#include <avr/sleep.h>

static void           m_print_aci_data(hal_aci_data_t *p_data);
static uint8_t        spi_readwrite(uint8_t aci_byte);

static hal_aci_data_t received_data;
static bool           aci_debug_print;

aci_queue_t    aci_tx_q;
aci_queue_t    aci_rx_q;

static aci_pins_t	 *a_pins_local_ptr;

static void m_aci_q_init(aci_queue_t *aci_q)
{
  uint8_t loop;

  aci_debug_print = false;
  aci_q->head = 0;
  aci_q->tail = 0;
  for(loop=0; loop<ACI_QUEUE_SIZE; loop++)
  {
    aci_q->aci_data[loop].buffer[0] = 0x00;
    aci_q->aci_data[loop].buffer[1] = 0x00;
  }
}

void hal_aci_debug_print(bool enable)
{
	aci_debug_print = enable;
}

bool m_aci_q_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
{
  const uint8_t next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
  const uint8_t length = p_data->buffer[0];

  if (next == aci_q->head)
  {
    /* full queue */
    return false;
  }
  aci_q->aci_data[aci_q->tail].status_byte = 0;

  memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1);
  aci_q->tail = next;

  return true;
}

//@comment after a port to a new mcu have test for the queue states, esp. the full and the empty states
static bool m_aci_q_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
{
  if (aci_q->head == aci_q->tail)
  {
    /* empty queue */
    return false;
  }

  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
  aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE;

  return true;
}

bool m_aci_q_is_empty(aci_queue_t *aci_q)
{
  return (aci_q->head == aci_q->tail);
}

bool m_aci_q_is_full(aci_queue_t *aci_q)
{
  uint8_t next;
  bool state;

  //This should be done in a critical section
  noInterrupts();
  next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;

  if (next == aci_q->head)
  {
    state = true;
  }
  else
  {
    state = false;
  }

  interrupts();
  //end

  return state;
}

void m_print_aci_data(hal_aci_data_t *p_data)
{
  const uint8_t length = p_data->buffer[0];
  uint8_t i;
  Serial.print(length, DEC);
  Serial.print(" :");
  for (i=0; i<=length; i++)
  {
    Serial.print(p_data->buffer[i], HEX);
    Serial.print(F(", "));
  }
  Serial.println(F(""));
}

void m_rdy_line_handle(void)
{
  hal_aci_data_t *p_aci_data;

  sleep_disable();
  detachInterrupt(1);

  // Receive or transmit data
  p_aci_data = hal_aci_tl_poll_get();

  // Check if we received data
  if (p_aci_data->buffer[0] > 0)
  {
    if (!m_aci_q_enqueue(&aci_rx_q, p_aci_data))
    {
      /* Receive Buffer full.
         Should never happen.
         Spin in a while loop.
         */
       while(1);
    }
    if (m_aci_q_is_full(&aci_rx_q))
    {
      /* Disable RDY line interrupt.
         Will latch any pending RDY lines, so when enabled it again this
         routine should be taken again */
	  if (true == a_pins_local_ptr->interface_is_interrupt)
	  {
		EIMSK &= ~(0x2);
	  }
    }
  }
}

bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data)
{
  bool was_full = m_aci_q_is_full(&aci_rx_q);

  if (m_aci_q_dequeue(&aci_rx_q, p_aci_data))
  {
    if (true == aci_debug_print)
    {
      Serial.print(" E");
      m_print_aci_data(p_aci_data);
    }

    if (was_full)
    {
	  if (true == a_pins_local_ptr->interface_is_interrupt)
	  {
		/* Enable RDY line interrupt again */
		EIMSK |= (0x2);
	  }
    }
    return true;
  }
  else
  {
    return false;
  }
}

void hal_aci_tl_init(aci_pins_t *a_pins)
{
  received_data.buffer[0] = 0;

  m_aci_pins_set(a_pins);

  /*
  The SPI lines used are mapped directly to the hardware SPI
  MISO MOSI and SCK
  Change here if the pins are mapped differently

  The SPI library assumes that the hardware pins are used
  */
  SPI.begin();
  SPI.setBitOrder(LSBFIRST);
  SPI.setClockDivider(a_pins->spi_clock_divider);
  SPI.setDataMode(SPI_MODE0);

  /* initialize aci cmd queue */
  m_aci_q_init(&aci_tx_q);
  m_aci_q_init(&aci_rx_q);

  //Configure the IO lines
  pinMode(a_pins->rdyn_pin,		INPUT_PULLUP);
  pinMode(a_pins->reqn_pin,		OUTPUT);

  if (UNUSED != a_pins->active_pin)
  {
	pinMode(a_pins->active_pin,	INPUT);
  }

  if (UNUSED != a_pins->reset_pin)
  {
	pinMode(a_pins->reset_pin,	OUTPUT);

	if (REDBEARLAB_SHIELD_V1_1 == a_pins->board_name)
	{
		//The reset for this board is inverted and has a Power On Reset
		//circuit that takes about 100ms to trigger the reset
		digitalWrite(a_pins->reset_pin, 1);
		delay(100);
		digitalWrite(a_pins->reset_pin, 0);
	}
	else
	{
		digitalWrite(a_pins->reset_pin, 1);
		digitalWrite(a_pins->reset_pin, 0);
		digitalWrite(a_pins->reset_pin, 1);
	}

  }

  digitalWrite(a_pins->miso_pin, 0);
  digitalWrite(a_pins->mosi_pin, 0);
  digitalWrite(a_pins->reqn_pin, 1);
  digitalWrite(a_pins->sck_pin,  0);

  delay(30); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset

  //Attach the interrupt to the RDYN line as requested by the caller
  if (a_pins->interface_is_interrupt)
  {
	attachInterrupt(a_pins->interrupt_number, m_rdy_line_handle, LOW); // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW
  }
}

bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd)
{
  const uint8_t length = p_aci_cmd->buffer[0];
  bool ret_val = false;

  if (length > HAL_ACI_MAX_LENGTH)
  {
    return false;
  }
  else
  {
    if (m_aci_q_enqueue(&aci_tx_q, p_aci_cmd))
    {
      ret_val = true;
    }
  }

  if (true == aci_debug_print)
  {
    Serial.print("C");
    m_print_aci_data(p_aci_cmd);
  }

  digitalWrite(a_pins_local_ptr->reqn_pin, 0);
  return ret_val;
}

hal_aci_data_t * hal_aci_tl_poll_get(void)
{
  uint8_t byte_cnt;
  uint8_t byte_sent_cnt;
  uint8_t max_bytes;
  hal_aci_data_t data_to_send;

  digitalWrite(a_pins_local_ptr->reqn_pin, 0);

  // Receive from queue
  if (m_aci_q_dequeue(&aci_tx_q, &data_to_send) == false)
  {
    /* queue was empty, nothing to send */
    data_to_send.status_byte = 0;
    data_to_send.buffer[0] = 0;
  }

  //Change this if your mcu has DMA for the master SPI

  // Send length, receive header
  byte_sent_cnt = 0;
  received_data.status_byte = spi_readwrite(data_to_send.buffer[byte_sent_cnt++]);
  // Send first byte, receive length from slave
  received_data.buffer[0] = spi_readwrite(data_to_send.buffer[byte_sent_cnt++]);
  if (0 == data_to_send.buffer[0])
  {
    max_bytes = received_data.buffer[0];
  }
  else
  {
    // Set the maximum to the biggest size. One command byte is already sent
    max_bytes = (received_data.buffer[0] > (data_to_send.buffer[0] - 1))
      ? received_data.buffer[0] : (data_to_send.buffer[0] - 1);
  }

  if (max_bytes > HAL_ACI_MAX_LENGTH)
  {
    max_bytes = HAL_ACI_MAX_LENGTH;
  }

  // Transmit/receive the rest of the packet
  for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++)
  {
    received_data.buffer[byte_cnt+1] =  spi_readwrite(data_to_send.buffer[byte_sent_cnt++]);
  }

  digitalWrite(a_pins_local_ptr->reqn_pin, 1);

  //RDYN should follow the REQN line in approx 100ns

  sleep_enable();
  if (a_pins_local_ptr->interface_is_interrupt)
  {
	attachInterrupt(a_pins_local_ptr->interrupt_number, m_rdy_line_handle, LOW);
  }

  if (false == m_aci_q_is_empty(&aci_tx_q))
  {
    //Lower the REQN line to start a new ACI transaction
    digitalWrite(a_pins_local_ptr->reqn_pin, 0);
  }

  /* valid Rx available or transmit finished*/
  return (&received_data);
}

static uint8_t spi_readwrite(const uint8_t aci_byte)
{
	return SPI.transfer(aci_byte);
}

void m_aci_q_flush(void)
{
  noInterrupts();
  /* re-initialize aci cmd queue and aci event queue to flush them*/
  m_aci_q_init(&aci_tx_q);
  m_aci_q_init(&aci_rx_q);
  interrupts();
}

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

/** @file
@brief Implementation of the ACI transport layer module
*/

#include <SPI.h>
#include "hal_platform.h"
#include "hal_aci_tl.h"
#include <avr/sleep.h>

static void           m_print_aci_data(hal_aci_data_t *p_data);
static uint8_t        spi_readwrite(uint8_t aci_byte);

static hal_aci_data_t received_data;
static bool           aci_debug_print;

aci_queue_t    aci_tx_q;
aci_queue_t    aci_rx_q;

static aci_pins_t	 *a_pins_local_ptr;

static void m_aci_q_init(aci_queue_t *aci_q)
{
  uint8_t loop;

  aci_debug_print = false;
  aci_q->head = 0;
  aci_q->tail = 0;
  for(loop=0; loop<ACI_QUEUE_SIZE; loop++)
  {
    aci_q->aci_data[loop].buffer[0] = 0x00;
    aci_q->aci_data[loop].buffer[1] = 0x00;
  }
}

void hal_aci_debug_print(bool enable)
{
	aci_debug_print = enable;
}

bool m_aci_q_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
{
  const uint8_t next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
  const uint8_t length = p_data->buffer[0];

  if (next == aci_q->head)
  {
    /* full queue */
    return false;
  }
  aci_q->aci_data[aci_q->tail].status_byte = 0;

  memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1);
  aci_q->tail = next;

  return true;
}

//@comment after a port to a new mcu have test for the queue states, esp. the full and the empty states
static bool m_aci_q_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
{
  if (aci_q->head == aci_q->tail)
  {
    /* empty queue */
    return false;
  }

  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
  aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE;

  return true;
}

bool m_aci_q_is_empty(aci_queue_t *aci_q)
{
  return (aci_q->head == aci_q->tail);
}

bool m_aci_q_is_full(aci_queue_t *aci_q)
{
  uint8_t next;
  bool state;

  //This should be done in a critical section
  noInterrupts();
  next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;

  if (next == aci_q->head)
  {
    state = true;
  }
  else
  {
    state = false;
  }

  interrupts();
  //end

  return state;
}

void m_print_aci_data(hal_aci_data_t *p_data)
{
  const uint8_t length = p_data->buffer[0];
  uint8_t i;
  Serial.print(length, DEC);
  Serial.print(" :");
  for (i=0; i<=length; i++)
  {
    Serial.print(p_data->buffer[i], HEX);
    Serial.print(F(", "));
  }
  Serial.println(F(""));
}

void m_rdy_line_handle(void)
{
  hal_aci_data_t *p_aci_data;

  sleep_disable();
  detachInterrupt(1);

  // Receive or transmit data
  p_aci_data = hal_aci_tl_poll_get();

  // Check if we received data
  if (p_aci_data->buffer[0] > 0)
  {
    if (!m_aci_q_enqueue(&aci_rx_q, p_aci_data))
    {
      /* Receive Buffer full.
         Should never happen.
         Spin in a while loop.
         */
       while(1);
    }
    if (m_aci_q_is_full(&aci_rx_q))
    {
      /* Disable RDY line interrupt.
         Will latch any pending RDY lines, so when enabled it again this
         routine should be taken again */
	  if (true == a_pins_local_ptr->interface_is_interrupt)
	  {
		EIMSK &= ~(0x2);
	  }
    }
  }
}

bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data)
{
  bool was_full = m_aci_q_is_full(&aci_rx_q);

  if (m_aci_q_dequeue(&aci_rx_q, p_aci_data))
  {
    if (true == aci_debug_print)
    {
      Serial.print(" E");
      m_print_aci_data(p_aci_data);
    }

    if (was_full)
    {
	  if (true == a_pins_local_ptr->interface_is_interrupt)
	  {
		/* Enable RDY line interrupt again */
		EIMSK |= (0x2);
	  }
    }
    return true;
  }
  else
  {
    return false;
  }
}

void hal_aci_tl_init(aci_pins_t *a_pins)
{
  received_data.buffer[0] = 0;

  m_aci_pins_set(a_pins);

  /*
  The SPI lines used are mapped directly to the hardware SPI
  MISO MOSI and SCK
  Change here if the pins are mapped differently

  The SPI library assumes that the hardware pins are used
  */
  SPI.begin();
  SPI.setBitOrder(LSBFIRST);
  SPI.setClockDivider(a_pins->spi_clock_divider);
  SPI.setDataMode(SPI_MODE0);

  /* initialize aci cmd queue */
  m_aci_q_init(&aci_tx_q);
  m_aci_q_init(&aci_rx_q);

  //Configure the IO lines
  pinMode(a_pins->rdyn_pin,		INPUT_PULLUP);
  pinMode(a_pins->reqn_pin,		OUTPUT);

  if (UNUSED != a_pins->active_pin)
  {
	pinMode(a_pins->active_pin,	INPUT);
  }

  if (UNUSED != a_pins->reset_pin)
  {
	pinMode(a_pins->reset_pin,	OUTPUT);

	if (REDBEARLAB_SHIELD_V1_1 == a_pins->board_name)
	{
		//The reset for this board is inverted and has a Power On Reset
		//circuit that takes about 100ms to trigger the reset
		digitalWrite(a_pins->reset_pin, 1);
		delay(100);
		digitalWrite(a_pins->reset_pin, 0);
	}
	else
	{
		digitalWrite(a_pins->reset_pin, 1);
		digitalWrite(a_pins->reset_pin, 0);
		digitalWrite(a_pins->reset_pin, 1);
	}

  }

  digitalWrite(a_pins->miso_pin, 0);
  digitalWrite(a_pins->mosi_pin, 0);
  digitalWrite(a_pins->reqn_pin, 1);
  digitalWrite(a_pins->sck_pin,  0);

  delay(30); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset

  //Attach the interrupt to the RDYN line as requested by the caller
  if (a_pins->interface_is_interrupt)
  {
	attachInterrupt(a_pins->interrupt_number, m_rdy_line_handle, LOW); // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW
  }
}

bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd)
{
  const uint8_t length = p_aci_cmd->buffer[0];
  bool ret_val = false;

  if (length > HAL_ACI_MAX_LENGTH)
  {
    return false;
  }
  else
  {
    if (m_aci_q_enqueue(&aci_tx_q, p_aci_cmd))
    {
      ret_val = true;
      digitalWrite(a_pins_local_ptr->reqn_pin, 0); //Place request line low only if enqueued
    }
  }

  if ((true == aci_debug_print) && (true == ret_val))
  {
    Serial.print("C");
    m_print_aci_data(p_aci_cmd);
  }

  return ret_val;
}

hal_aci_data_t * hal_aci_tl_poll_get(void)
{
  uint8_t byte_cnt;
  uint8_t byte_sent_cnt;
  uint8_t max_bytes;
  hal_aci_data_t data_to_send;

  digitalWrite(a_pins_local_ptr->reqn_pin, 0);

  // Receive from queue
  if (m_aci_q_dequeue(&aci_tx_q, &data_to_send) == false)
  {
    /* queue was empty, nothing to send */
    data_to_send.status_byte = 0;
    data_to_send.buffer[0] = 0;
  }

  //Change this if your mcu has DMA for the master SPI

  // Send length, receive header
  byte_sent_cnt = 0;
  received_data.status_byte = spi_readwrite(data_to_send.buffer[byte_sent_cnt++]);
  // Send first byte, receive length from slave
  received_data.buffer[0] = spi_readwrite(data_to_send.buffer[byte_sent_cnt++]);
  if (0 == data_to_send.buffer[0])
  {
    max_bytes = received_data.buffer[0];
  }
  else
  {
    // Set the maximum to the biggest size. One command byte is already sent
    max_bytes = (received_data.buffer[0] > (data_to_send.buffer[0] - 1))
      ? received_data.buffer[0] : (data_to_send.buffer[0] - 1);
  }

  if (max_bytes > HAL_ACI_MAX_LENGTH)
  {
    max_bytes = HAL_ACI_MAX_LENGTH;
  }

  // Transmit/receive the rest of the packet
  for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++)
  {
    received_data.buffer[byte_cnt+1] =  spi_readwrite(data_to_send.buffer[byte_sent_cnt++]);
  }

  digitalWrite(a_pins_local_ptr->reqn_pin, 1);

  //RDYN should follow the REQN line in approx 100ns

  sleep_enable();
  if (a_pins_local_ptr->interface_is_interrupt)
  {
	attachInterrupt(a_pins_local_ptr->interrupt_number, m_rdy_line_handle, LOW);
  }

  if (false == m_aci_q_is_empty(&aci_tx_q))
  {
    //Lower the REQN line to start a new ACI transaction
    digitalWrite(a_pins_local_ptr->reqn_pin, 0);
  }

  /* valid Rx available or transmit finished*/
  return (&received_data);
}

static uint8_t spi_readwrite(const uint8_t aci_byte)
{
	return SPI.transfer(aci_byte);
}

void m_aci_q_flush(void)
{
  noInterrupts();
  /* re-initialize aci cmd queue and aci event queue to flush them*/
  m_aci_q_init(&aci_tx_q);
  m_aci_q_init(&aci_rx_q);
  interrupts();
}

void m_aci_pins_set(aci_pins_t *a_pins_ptr)
{
  a_pins_local_ptr = a_pins_ptr;
}<|endoftext|>


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

#include <exotica/Problems/UnconstrainedTimeIndexedProblem.h>
#include <exotica/Setup.h>

REGISTER_PROBLEM_TYPE("UnconstrainedTimeIndexedProblem", exotica::UnconstrainedTimeIndexedProblem)

namespace exotica
{

  UnconstrainedTimeIndexedProblem::UnconstrainedTimeIndexedProblem()
      : T(0), tau(0), Q_rate(0), W_rate(0), H_rate(0)
  {
    Flags = KIN_FK | KIN_J;
  }

  UnconstrainedTimeIndexedProblem::~UnconstrainedTimeIndexedProblem()
  {

  }

  void UnconstrainedTimeIndexedProblem::Instantiate(UnconstrainedTimeIndexedProblemInitializer& init)
  {
      T = init.T;
      if (T <= 2)
      {
        throw_named("Invalid number of timesteps: "<<T);
      }
      tau = init.Tau;
      Q_rate = init.Qrate;
      H_rate = init.Hrate;
      W_rate = init.Wrate;

      NumTasks = Tasks.size();
      PhiN = 0;
      JN = 0;
      TaskSpaceVector yref;
      for(int i=0;i<NumTasks;i++)
      {
          appendVector(yref.map, Tasks[i]->getLieGroupIndices());
          PhiN += Tasks[i]->Length;
          JN += Tasks[i]->LengthJ;
      }

      N = scene_->getSolver().getNumJoints();

      W = Eigen::MatrixXd::Identity(N, N)*W_rate;
      if(init.W.rows()>0)
      {
          if(init.W.rows()==N)
          {
              W.diagonal() = init.W*W_rate;
          }
          else
          {
              throw_named("W dimension mismatch! Expected "<<N<<", got "<<init.W.rows());
          }
      }
      H = Eigen::MatrixXd::Identity(N, N)*Q_rate;
      Q = Eigen::MatrixXd::Identity(N, N)*H_rate;

      if(init.Rho.rows()==0)
      {
          Rho.assign(T, Eigen::VectorXd::Ones(NumTasks));
      }
      else if(init.Rho.rows()==NumTasks)
      {
          Rho.assign(T, init.Rho);
      }
      else if(init.Rho.rows()==NumTasks*T)
      {
          Rho.resize(T);
          for(int i=0;i<T;i++)
          {
              Rho[i] = init.Rho.segment(i*NumTasks,NumTasks);
          }
      }
      else
      {
          throw_named("Invalid task weights rho! "<<init.Rho.rows());
      }
      yref.setZero(PhiN);
      y.assign(T, yref);
      Phi = y;
      ydiff.assign(T, Eigen::VectorXd::Zero(JN));
      J.assign(T, Eigen::MatrixXd(JN, N));
  }

    double UnconstrainedTimeIndexedProblem::getDuration()
    {
        return tau * (double) T;
    }

    void UnconstrainedTimeIndexedProblem::Update(Eigen::VectorXdRefConst x, int t)
    {
        scene_->Update(x);
        for(int i=0;i<NumTasks;i++)
        {
            Tasks[i]->update(x, Phi[t].data.segment(Tasks[i]->Start, Tasks[i]->Length), J[t].middleRows(Tasks[i]->StartJ, Tasks[i]->LengthJ));
        }
        ydiff[t] = y[t] - Phi[t];
    }

    void UnconstrainedTimeIndexedProblem::setGoal(const std::string & task_name, Eigen::VectorXdRefConst goal, int t)
    {
      try
      {
        TaskMap_ptr task = TaskMaps.at(task_name);
        y[t].data.segment(task->Start, task->Length) = goal;
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot set Goal. Task map '"<<task_name<<"' Does not exist.");
      }
    }

    void UnconstrainedTimeIndexedProblem::setRho(const std::string & task_name, const double rho, int t)
    {
      try
      {
        TaskMap_ptr task = TaskMaps.at(task_name);
        Rho[t](task->Id) = rho;
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot set Rho. Task map '"<<task_name<<"' Does not exist.");
      }
    }

    Eigen::VectorXd UnconstrainedTimeIndexedProblem::getGoal(const std::string & task_name, int t)
    {
      try
      {
        TaskMap_ptr task = TaskMaps.at(task_name);
        return y[t].data.segment(task->Start, task->Length);
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot get Goal. Task map '"<<task_name<<"' Does not exist.");
      }
    }

    double UnconstrainedTimeIndexedProblem::getRho(const std::string & task_name, int t)
    {
      try
      {
        TaskMap_ptr task = TaskMaps.at(task_name);
        return Rho[t](task->Id);
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot get Rho. Task map '"<<task_name<<"' Does not exist.");
      }
    }
}
<commit_msg>UnconstrainedTimeIndexedProblem: Avoid segfault for out of range t values in getter/setters - Checks whether chosen timestep is valid - Adds support for -1 = last element<commit_after>/*
 *  Created on: 19 Apr 2014
 *      Author: Vladimir Ivan
 *
 * Copyright (c) 2016, University Of Edinburgh
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of  nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <exotica/Problems/UnconstrainedTimeIndexedProblem.h>
#include <exotica/Setup.h>

REGISTER_PROBLEM_TYPE("UnconstrainedTimeIndexedProblem", exotica::UnconstrainedTimeIndexedProblem)

namespace exotica
{

  UnconstrainedTimeIndexedProblem::UnconstrainedTimeIndexedProblem()
      : T(0), tau(0), Q_rate(0), W_rate(0), H_rate(0)
  {
    Flags = KIN_FK | KIN_J;
  }

  UnconstrainedTimeIndexedProblem::~UnconstrainedTimeIndexedProblem()
  {

  }

  void UnconstrainedTimeIndexedProblem::Instantiate(UnconstrainedTimeIndexedProblemInitializer& init)
  {
      T = init.T;
      if (T <= 2)
      {
        throw_named("Invalid number of timesteps: "<<T);
      }
      tau = init.Tau;
      Q_rate = init.Qrate;
      H_rate = init.Hrate;
      W_rate = init.Wrate;

      NumTasks = Tasks.size();
      PhiN = 0;
      JN = 0;
      TaskSpaceVector yref;
      for(int i=0;i<NumTasks;i++)
      {
          appendVector(yref.map, Tasks[i]->getLieGroupIndices());
          PhiN += Tasks[i]->Length;
          JN += Tasks[i]->LengthJ;
      }

      N = scene_->getSolver().getNumJoints();

      W = Eigen::MatrixXd::Identity(N, N)*W_rate;
      if(init.W.rows()>0)
      {
          if(init.W.rows()==N)
          {
              W.diagonal() = init.W*W_rate;
          }
          else
          {
              throw_named("W dimension mismatch! Expected "<<N<<", got "<<init.W.rows());
          }
      }
      H = Eigen::MatrixXd::Identity(N, N)*Q_rate;
      Q = Eigen::MatrixXd::Identity(N, N)*H_rate;

      if(init.Rho.rows()==0)
      {
          Rho.assign(T, Eigen::VectorXd::Ones(NumTasks));
      }
      else if(init.Rho.rows()==NumTasks)
      {
          Rho.assign(T, init.Rho);
      }
      else if(init.Rho.rows()==NumTasks*T)
      {
          Rho.resize(T);
          for(int i=0;i<T;i++)
          {
              Rho[i] = init.Rho.segment(i*NumTasks,NumTasks);
          }
      }
      else
      {
          throw_named("Invalid task weights rho! "<<init.Rho.rows());
      }
      yref.setZero(PhiN);
      y.assign(T, yref);
      Phi = y;
      ydiff.assign(T, Eigen::VectorXd::Zero(JN));
      J.assign(T, Eigen::MatrixXd(JN, N));
  }

    double UnconstrainedTimeIndexedProblem::getDuration()
    {
        return tau * (double) T;
    }

    void UnconstrainedTimeIndexedProblem::Update(Eigen::VectorXdRefConst x, int t)
    {
        scene_->Update(x);
        for(int i=0;i<NumTasks;i++)
        {
            Tasks[i]->update(x, Phi[t].data.segment(Tasks[i]->Start, Tasks[i]->Length), J[t].middleRows(Tasks[i]->StartJ, Tasks[i]->LengthJ));
        }
        ydiff[t] = y[t] - Phi[t];
    }

    void UnconstrainedTimeIndexedProblem::setGoal(const std::string & task_name, Eigen::VectorXdRefConst goal, int t)
    {
      try
      {
        if (t >= T || t < -1) {
          throw_pretty("Requested t="
                       << t
                       << " out of range, needs to be 0 =< t < " << T);
        } else if (t == -1) {
          t = T - 1;
        }

        TaskMap_ptr task = TaskMaps.at(task_name);
        y[t].data.segment(task->Start, task->Length) = goal;
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot set Goal. Task map '"<<task_name<<"' Does not exist.");
      }
    }

    void UnconstrainedTimeIndexedProblem::setRho(const std::string & task_name, const double rho, int t)
    {
      try
      {
        if (t >= T || t < -1) {
          throw_pretty("Requested t="
                       << t
                       << " out of range, needs to be 0 =< t < " << T);
        } else if (t == -1) {
          t = T - 1;
        }

        TaskMap_ptr task = TaskMaps.at(task_name);
        Rho[t](task->Id) = rho;
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot set Rho. Task map '"<<task_name<<"' Does not exist.");
      }
    }

    Eigen::VectorXd UnconstrainedTimeIndexedProblem::getGoal(const std::string & task_name, int t)
    {
      try
      {
        if (t >= T || t < -1) {
          throw_pretty("Requested t="
                       << t
                       << " out of range, needs to be 0 =< t < " << T);
        } else if (t == -1) {
          t = T - 1;
        }

        TaskMap_ptr task = TaskMaps.at(task_name);
        return y[t].data.segment(task->Start, task->Length);
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot get Goal. Task map '"<<task_name<<"' Does not exist.");
      }
    }

    double UnconstrainedTimeIndexedProblem::getRho(const std::string & task_name, int t)
    {
      try
      {
        if (t >= T || t < -1) {
          throw_pretty("Requested t="
                       << t
                       << " out of range, needs to be 0 =< t < " << T);
        } else if (t == -1) {
          t = T - 1;
        }

        TaskMap_ptr task = TaskMaps.at(task_name);
        return Rho[t](task->Id);
      }
      catch(std::out_of_range& e)
      {
          throw_pretty("Cannot get Rho. Task map '"<<task_name<<"' Does not exist.");
      }
    }
}
<|endoftext|>


<commit_before>#include <bts/kid/kid_server.hpp>
#include <bts/blockchain/difficulty.hpp>
#include <bts/db/level_map.hpp>
#include <fc/filesystem.hpp>
#include <fc/network/http/server.hpp>
#include <fc/exception/exception.hpp>
#include <fc/thread/thread.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/io/raw.hpp>

namespace bts { namespace kid {
   uint64_t   name_record::difficulty()const
   {
      return 1000 * bts::blockchain::difficulty( digest512() );
   }

   fc::ecc::public_key signed_name_record::get_signee()const
   {
      return fc::ecc::public_key( master_signature, digest() );
   }
   fc::ecc::public_key stored_key::get_signee()const
   {
      FC_ASSERT( encrypted_key.size() > 0 );
      auto digest = fc::sha256::hash( encrypted_key.data(), encrypted_key.size() );
      return fc::ecc::public_key( signature, digest );
   }
   fc::sha256 name_record::digest()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }
   fc::sha256 name_record::digest512()const
   {
      fc::sha512::encoder enc;
      fc::raw::pack( enc, *this );
      auto h512 = enc.result();
      return fc::sha256::hash( (char*)&h512, sizeof(h512) );
   }

   fc::sha256 signed_name_record::id()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }

   fc::sha256 block::digest()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }

   fc::sha256 signed_block::id()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }

   void signed_block::sign( const fc::ecc::private_key& trustee_priv_key )
   {
      trustee_signature = trustee_priv_key.sign_compact( id() );
   }

   void signed_block::verify( const fc::ecc::public_key& trustee_pub_key )
   {
      FC_ASSERT( fc::ecc::public_key( trustee_signature, id() ) == trustee_pub_key )
   }

   namespace detail
   {
       class server_impl
       {
          public:
             server*                                                   _self;
             bts::db::level_map<std::string, history >                 _name_index;
             bts::db::level_map<uint32_t, signed_block>                _block_database;
             bts::db::level_map<std::string,stored_key >               _key_data;
             bts::db::level_map<fc::ripemd160, std::string>            _key_to_name;

             std::unordered_map<std::string, signed_name_record>       _pending;

             fc::future<void>                                          _block_gen_loop_complete;

             signed_block                                              _current_block;
             fc::sha256                                                _current_block_id;
             fc::ecc::private_key                                      _trustee_key;

             void block_generation_loop()
             {
                while( !_block_gen_loop_complete.canceled() )
                {
                   if( _pending.size() && (fc::time_point::now() - _current_block.timestamp) > fc::seconds(60) )
                   {
                      signed_block next_block;
                      next_block.number     = _current_block.number + 1;
                      auto next_diff        = _current_block.difficulty * 500 / _pending.size();
                      next_diff             = (_current_block.difficulty * 99 + next_diff) / 100;
                      next_block.difficulty = std::max<uint64_t>(next_diff, 1000 );
                      next_block.timestamp  = fc::time_point::now();

                      for( auto rec : _pending )
                      {
                         next_block.records.push_back( rec.second );
                      }

                      next_block.sign( _trustee_key );
                      _block_database.store(next_block.number,next_block);

                      for( uint32_t rec = 0; rec < next_block.records.size(); ++rec )
                      {
                         auto hist = _self->fetch_history( next_block.records[rec].name );
                         hist.updates.push_back( name_index( next_block.number, rec ) );
                         _name_index.store( next_block.records[rec].name, hist );
                      }

                      _current_block = next_block;
                      _current_block_id = _current_block.id();
                   }
                   fc::usleep( fc::seconds( 1 ) );
                }
             }
       };
   } // namespace detail

   server::server()
   :my( new detail::server_impl() )
   {
      my->_self = this;
      my->_block_gen_loop_complete = fc::async( [=](){ my->block_generation_loop(); } );
   }
   server::~server()
   {
      ilog( "waiting for block generation loop to exit" );
      try {
         my->_block_gen_loop_complete.cancel();
         my->_block_gen_loop_complete.wait();
      }
      catch ( const fc::canceled_exception& e ){}
      catch ( const fc::exception& e )
      {
         wlog( "${e}", ("e",e.to_detail_string()) );
      }
   }

   void server::set_data_directory( const fc::path& dir )
   {
      my->_name_index.open( dir / "name_index" );
      my->_block_database.open( dir / "block_database" );
      my->_key_data.open( dir / "key_data" );
      my->_key_to_name.open( dir / "key_to_name" );
   }

   void server::listen( const fc::ip::endpoint& ep )
   {
   }

   bool server::update_record( const signed_name_record& r )
   {
      FC_ASSERT( my->_pending.size() < 20000 );
      FC_ASSERT( fc::trim_and_normalize_spaces( r.name ) == r.name );
      FC_ASSERT( fc::to_lower( r.name ) == r.name );
      FC_ASSERT( r.difficulty() >= my->_current_block.difficulty );
      FC_ASSERT( my->_current_block_id == r.prev_block_id     );

      auto pending_itr = my->_pending.find( r.name );
      FC_ASSERT( pending_itr == my->_pending.end()         );
      auto hist = fetch_history( r.name );
      if( hist.updates.size() == 0 )
      {
         my->_pending[r.name] = r;
         return true;
      }

      auto old_record  = fetch_record( hist.updates.back() );
      FC_ASSERT( old_record.master_key == r.get_signee() )
      my->_pending[r.name] = r;
      return true;
   }

   signed_name_record      server::fetch_record( const std::string& name )
   {
      auto pending_itr = my->_pending.find( name );
      if( pending_itr != my->_pending.end() )
         return pending_itr->second;
      auto hist= fetch_history( name );
      FC_ASSERT( hist.updates.size() > 0 );

      auto old_block   = fetch_block( hist.updates.back().block_num );
      return fetch_record( hist.updates.back() );
      FC_ASSERT( old_block.records.size() > hist.updates.back().record_num );
      return old_block.records[hist.updates.back().record_num];
   }

   signed_name_record      server::fetch_record( const name_index& index )
   {
      auto old_block   = fetch_block( index.block_num );
      FC_ASSERT( old_block.records.size() > index.record_num );
      return old_block.records[index.record_num];
   }

   history server::fetch_history( const std::string& name )
   {
      history hist;
      auto itr = my->_name_index.find(name);
      if( itr.valid() )
         hist = itr.value();
      return hist;
   }

   void                    server::store_key( const std::string& name, const stored_key& k )
   {
      auto cur_rec = fetch_record( name );
      FC_ASSERT( k.encrypted_key.size() < 1024*16 );
      FC_ASSERT( cur_rec.master_key == k.get_signee()  );
      my->_key_data.store( name, k );
   }

   stored_key       server::fetch_key( const std::string& name )
   {
      return my->_key_data.fetch( name );
   }

   signed_block            server::fetch_block( uint32_t block_num )
   {
      return my->_block_database.fetch( block_num );
   }

} } // namespace bts::kid
<commit_msg>started http interface<commit_after>#include <bts/kid/kid_server.hpp>
#include <bts/blockchain/difficulty.hpp>
#include <bts/db/level_map.hpp>
#include <fc/filesystem.hpp>
#include <fc/network/http/server.hpp>
#include <fc/exception/exception.hpp>
#include <fc/thread/thread.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/io/raw.hpp>

namespace bts { namespace kid {
   uint64_t   name_record::difficulty()const
   {
      return 1000 * bts::blockchain::difficulty( digest512() );
   }

   fc::ecc::public_key signed_name_record::get_signee()const
   {
      return fc::ecc::public_key( master_signature, digest() );
   }
   fc::ecc::public_key stored_key::get_signee()const
   {
      FC_ASSERT( encrypted_key.size() > 0 );
      auto digest = fc::sha256::hash( encrypted_key.data(), encrypted_key.size() );
      return fc::ecc::public_key( signature, digest );
   }
   fc::sha256 name_record::digest()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }
   fc::sha256 name_record::digest512()const
   {
      fc::sha512::encoder enc;
      fc::raw::pack( enc, *this );
      auto h512 = enc.result();
      return fc::sha256::hash( (char*)&h512, sizeof(h512) );
   }

   fc::sha256 signed_name_record::id()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }

   fc::sha256 block::digest()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }

   fc::sha256 signed_block::id()const
   {
      fc::sha256::encoder enc;
      fc::raw::pack( enc, *this );
      return enc.result();
   }

   void signed_block::sign( const fc::ecc::private_key& trustee_priv_key )
   {
      trustee_signature = trustee_priv_key.sign_compact( id() );
   }

   void signed_block::verify( const fc::ecc::public_key& trustee_pub_key )
   {
      FC_ASSERT( fc::ecc::public_key( trustee_signature, id() ) == trustee_pub_key )
   }

   namespace detail
   {
       class server_impl
       {
          public:
             server*                                                   _self;
             fc::http::server                                          _httpd;
             bts::db::level_map<std::string, history >                 _name_index;
             bts::db::level_map<uint32_t, signed_block>                _block_database;
             bts::db::level_map<std::string,stored_key >               _key_data;
             bts::db::level_map<fc::ripemd160, std::string>            _key_to_name;

             std::unordered_map<std::string, signed_name_record>       _pending;

             fc::future<void>                                          _block_gen_loop_complete;

             signed_block                                              _current_block;
             fc::sha256                                                _current_block_id;
             fc::ecc::private_key                                      _trustee_key;

             void block_generation_loop()
             {
                while( !_block_gen_loop_complete.canceled() )
                {
                   if( _pending.size() && (fc::time_point::now() - _current_block.timestamp) > fc::seconds(60) )
                   {
                      signed_block next_block;
                      next_block.number     = _current_block.number + 1;
                      auto next_diff        = _current_block.difficulty * 500 / _pending.size();
                      next_diff             = (_current_block.difficulty * 99 + next_diff) / 100;
                      next_block.difficulty = std::max<uint64_t>(next_diff, 1000 );
                      next_block.timestamp  = fc::time_point::now();

                      for( auto rec : _pending )
                      {
                         next_block.records.push_back( rec.second );
                      }

                      next_block.sign( _trustee_key );
                      _block_database.store(next_block.number,next_block);

                      for( uint32_t rec = 0; rec < next_block.records.size(); ++rec )
                      {
                         auto hist = _self->fetch_history( next_block.records[rec].name );
                         hist.updates.push_back( name_index( next_block.number, rec ) );
                         _name_index.store( next_block.records[rec].name, hist );
                      }

                      _current_block = next_block;
                      _current_block_id = _current_block.id();
                   }
                   fc::usleep( fc::seconds( 1 ) );
                }
             }

             void handle_request( const fc::http::request& r, const fc::http::server::response& s )
             {
                 auto pos = r.path.find( "/" );
                 auto first_dir = r.path.substr(0,pos);
                 if( first_dir == "update_record" )
                 {
                    s.set_status( fc::http::reply::RecordCreated );
                 }
                 else if( first_dir == "fetch_by_name" )
                 {
                    s.set_status( fc::http::reply::Found );
                 }
                 else if( first_dir == "fetch_by_key" )
                 {
                    s.set_status( fc::http::reply::Found );
                 }
                 else if( first_dir == "store_key" )
                 {
                    s.set_status( fc::http::reply::RecordCreated );
                 }
                 else if( first_dir == "fetch_key" )
                 {
                    s.set_status( fc::http::reply::Found );
                 }
                 else
                 {
                    s.set_status( fc::http::reply::NotFound );
                 }
             }
       };
   } // namespace detail

   server::server()
   :my( new detail::server_impl() )
   {
      my->_self = this;
      my->_block_gen_loop_complete = fc::async( [=](){ my->block_generation_loop(); } );
   }
   server::~server()
   {
      ilog( "waiting for block generation loop to exit" );
      try {
         my->_block_gen_loop_complete.cancel();
         my->_block_gen_loop_complete.wait();
      }
      catch ( const fc::canceled_exception& e ){}
      catch ( const fc::exception& e )
      {
         wlog( "${e}", ("e",e.to_detail_string()) );
      }
   }

   void server::set_data_directory( const fc::path& dir )
   {
      my->_name_index.open( dir / "name_index" );
      my->_block_database.open( dir / "block_database" );
      my->_key_data.open( dir / "key_data" );
      my->_key_to_name.open( dir / "key_to_name" );
   }

   void server::listen( const fc::ip::endpoint& ep )
   {
      my->_httpd.on_request( [=]( const fc::http::request& r, const fc::http::server::response& s ){ my->handle_request( r, s ); } );
      my->_httpd.listen(ep);
   }

   bool server::update_record( const signed_name_record& r )
   {
      FC_ASSERT( my->_pending.size() < 20000 );
      FC_ASSERT( fc::trim_and_normalize_spaces( r.name ) == r.name );
      FC_ASSERT( fc::to_lower( r.name ) == r.name );
      FC_ASSERT( r.difficulty() >= my->_current_block.difficulty );
      FC_ASSERT( my->_current_block_id == r.prev_block_id     );

      auto pending_itr = my->_pending.find( r.name );
      FC_ASSERT( pending_itr == my->_pending.end()         );
      auto hist = fetch_history( r.name );
      if( hist.updates.size() == 0 )
      {
         my->_pending[r.name] = r;
         return true;
      }

      auto old_record  = fetch_record( hist.updates.back() );
      FC_ASSERT( old_record.master_key == r.get_signee() )
      my->_pending[r.name] = r;
      return true;
   }

   signed_name_record      server::fetch_record( const std::string& name )
   {
      auto pending_itr = my->_pending.find( name );
      if( pending_itr != my->_pending.end() )
         return pending_itr->second;
      auto hist= fetch_history( name );
      FC_ASSERT( hist.updates.size() > 0 );

      auto old_block   = fetch_block( hist.updates.back().block_num );
      return fetch_record( hist.updates.back() );
      FC_ASSERT( old_block.records.size() > hist.updates.back().record_num );
      return old_block.records[hist.updates.back().record_num];
   }

   signed_name_record      server::fetch_record( const name_index& index )
   {
      auto old_block   = fetch_block( index.block_num );
      FC_ASSERT( old_block.records.size() > index.record_num );
      return old_block.records[index.record_num];
   }

   history server::fetch_history( const std::string& name )
   {
      history hist;
      auto itr = my->_name_index.find(name);
      if( itr.valid() )
         hist = itr.value();
      return hist;
   }

   void                    server::store_key( const std::string& name, const stored_key& k )
   {
      auto cur_rec = fetch_record( name );
      FC_ASSERT( k.encrypted_key.size() < 1024*16 );
      FC_ASSERT( cur_rec.master_key == k.get_signee()  );
      my->_key_data.store( name, k );
   }

   stored_key       server::fetch_key( const std::string& name )
   {
      return my->_key_data.fetch( name );
   }

   signed_block            server::fetch_block( uint32_t block_num )
   {
      return my->_block_database.fetch( block_num );
   }

} } // namespace bts::kid
<|endoftext|>


<commit_before>/*
   eXokernel Development Kit (XDK)

   Based on code by Samsung Research America Copyright (C) 2013

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

   The GNU C 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.

   As a special exception, if you link the code in this file with
   files compiled with a GNU compiler to produce an executable,
   that does not cause the resulting executable to be covered by
   the GNU Lesser General Public License.  This exception does not
   however invalidate any other reasons why the executable file
   might be covered by the GNU Lesser General Public License.
   This exception applies to code released by its copyright holders
   in files containing the exception.
*/

/*
  Authors:
  Copyright (C) 2014, Daniel G. Waddington <daniel.waddington@acm.org>
*/

#include <stdint.h>
#include <dlfcn.h>
#include <assert.h>
#include <stdio.h>

#include <component/base.h>
#include <common/errors.h>

namespace Component
{

  bool operator==(const Component::uuid_t& lhs, const Component::uuid_t& rhs) {
    return memcmp(&lhs, &rhs, sizeof(Component::uuid_t))==0;
  }

  /**
    * Called by the client to load the component from a DLL file
    *
    */
  IBase * load_component(const char * dllname, Component::uuid_t component_id) {

    void * (*factory_createInstance)(Component::uuid_t&);
    char * error;
    void * dll = dlopen(dllname,RTLD_NOW);

    if(!dll) {
      PERR("unable to load library (%s) - check dependencies with ldd tool.",dllname);
      return NULL;
    }

    dlerror();
    *(void **) (&factory_createInstance) = dlsym(dll,"factory_createInstance");

    if ((error = dlerror()) != NULL)  {
      PERR("Error: %s\n", error);
      return NULL;
    }

    IBase* comp = (IBase*) factory_createInstance(component_id);

    if(!comp) {
      PERR("Error: factory create instance returned null.");
      return NULL;
    }

    assert(comp);
    comp->set_dll_handle(dll); /* record so we can call dlclose() */
    comp->add_ref();

    return comp;
  }

  /**
   * Perform pairwise binding of components
   *
   * @param components List of components to bind
   *
   * @return S_OK on success.
   */
  status_t bind(std::vector<IBase *> components) {

    for(int i=0;i<components.size();i++) {
      assert(components[i]);
      for(int j=0;j<components.size();j++) {
        assert(components[j]);
        if(i==j) continue;
        if(components[i]->bind(components[j]) == -1) {
          PDBG("connect call in pairwise bind failed.");
          return E_FAIL;
        }
      }
    }

    return S_OK;
  }
}
<commit_msg>looks nicer<commit_after>/*
   eXokernel Development Kit (XDK)

   Based on code by Samsung Research America Copyright (C) 2013

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

   The GNU C 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.

   As a special exception, if you link the code in this file with
   files compiled with a GNU compiler to produce an executable,
   that does not cause the resulting executable to be covered by
   the GNU Lesser General Public License.  This exception does not
   however invalidate any other reasons why the executable file
   might be covered by the GNU Lesser General Public License.
   This exception applies to code released by its copyright holders
   in files containing the exception.
*/

/*
  Authors:
  Copyright (C) 2014, Daniel G. Waddington <daniel.waddington@acm.org>
*/

#include <stdint.h>
#include <dlfcn.h>
#include <assert.h>
#include <stdio.h>

#include <component/base.h>
#include <common/errors.h>

namespace Component
{

  bool operator==(const Component::uuid_t& lhs, const Component::uuid_t& rhs) {
    return memcmp(&lhs, &rhs, sizeof(Component::uuid_t))==0;
  }

  /**
    * Called by the client to load the component from a DLL file
    *
    */
  IBase * load_component(const char * dllname, Component::uuid_t component_id) {

    void * (*factory_createInstance)(Component::uuid_t&);
    char * error;
    void * dll = dlopen(dllname,RTLD_NOW);

    if(!dll) {
      PERR("unable to load library (%s) - check dependencies with ldd tool.",dllname);
      return NULL;
    }

    dlerror();
    *(void **) (&factory_createInstance) = dlsym(dll,"factory_createInstance");

    if ((error = dlerror()) != NULL)  {
      PERR("Error: %s\n", error);
      return NULL;
    }

    IBase* comp = (IBase*) factory_createInstance(component_id);

    if(comp==NULL) {
      PERR("Error: factory create instance returned null.");
      return NULL;
    }

    comp->set_dll_handle(dll); /* record so we can call dlclose() */
    comp->add_ref();

    return comp;
  }

  /**
   * Perform pairwise binding of components
   *
   * @param components List of components to bind
   *
   * @return S_OK on success.
   */
  status_t bind(std::vector<IBase *> components) {

    for(int i=0;i<components.size();i++) {
      assert(components[i]);
      for(int j=0;j<components.size();j++) {
        assert(components[j]);
        if(i==j) continue;
        if(components[i]->bind(components[j]) == -1) {
          PDBG("connect call in pairwise bind failed.");
          return E_FAIL;
        }
      }
    }

    return S_OK;
  }
}
<|endoftext|>