<commit_before>/*******************************************************************************
Copyright (c) 2012-2016 Alex Zhondin <lexxmark.dev@gmail.com>
Copyright (c) 2015-2019 Alexandra Cherdantseva <neluhus.vagus@gmail.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*******************************************************************************/

#include "PropertyDelegateQColor.h"
#include "Delegates/PropertyDelegateFactory.h"
#include "Delegates/Utils/PropertyEditorHandler.h"
#include "Delegates/Utils/PropertyEditorAux.h"
#include "PropertyDelegateAttrs.h"
#include "Utils/InplaceEditing.h"

#include <QColorDialog>

QByteArray qtnShapeAttr()
{
	return QByteArrayLiteral("shape");
}

QByteArray qtnRgbSubItemsAttr()
{
	return QByteArrayLiteral("rgbSubItems");
}

QByteArray qtnSolidDelegateName()
{
	return QByteArrayLiteral("Solid");
}

QByteArray qtnSelectColorDelegateName()
{
	return QByteArrayLiteral("SelectColor");
}

class QtnPropertyQColorLineEditBttnHandler
	: public QtnPropertyEditorBttnHandler<QtnPropertyQColorBase,
		  QtnLineEditBttn>
{
public:
	QtnPropertyQColorLineEditBttnHandler(
		QtnPropertyDelegate *delegate, QtnLineEditBttn &editor);

protected:
	virtual void onToolButtonClick() override;
	virtual void updateEditor() override;

private:
	void onToolButtonClicked(bool);
	void onEditingFinished();
};

QtnPropertyDelegateQColor::QtnPropertyDelegateQColor(
	QtnPropertyQColorBase &owner)
	: QtnPropertyDelegateTypedEx<QtnPropertyQColorBase>(owner)
	, m_shape(QtnColorDelegateShapeSquare)
{
}

void QtnPropertyDelegateQColor::Register(QtnPropertyDelegateFactory &factory)
{
	factory.registerDelegateDefault(&QtnPropertyQColorBase::staticMetaObject,
		&qtnCreateDelegate<QtnPropertyDelegateQColor, QtnPropertyQColorBase>,
		qtnSelectColorDelegateName());
}

void QtnPropertyDelegateQColor::applyAttributesImpl(
	const QtnPropertyDelegateInfo &info)
{
	info.loadAttribute(qtnShapeAttr(), m_shape);

	if (info.getAttribute(qtnRgbSubItemsAttr(), false))
	{
		addSubProperty(owner().createRedProperty());
		addSubProperty(owner().createGreenProperty());
		addSubProperty(owner().createBlueProperty());
	}
}

void QtnPropertyDelegateQColor::drawValueImpl(
	QStylePainter &painter, const QRect &rect) const
{
	if (stateProperty()->isMultiValue())
	{
		QtnPropertyDelegateTypedEx::drawValueImpl(painter, rect);
		return;
	}

	QColor value = owner().value();

	QRect textRect = rect;

	if (m_shape != QtnColorDelegateShapeNone)
	{
		QRect colorRect = rect;
		colorRect.setWidth(colorRect.height());
		colorRect.adjust(2, 2, -2, -2);

		if (m_shape == QtnColorDelegateShapeSquare)
		{
			painter.fillRect(colorRect, Qt::black);
			colorRect.adjust(1, 1, -1, -1);
			painter.fillRect(colorRect, value);
		} else if (m_shape == QtnColorDelegateShapeCircle)
		{
			bool oldAntiAliasing =
				painter.testRenderHint(QPainter::Antialiasing);
			painter.setRenderHint(QPainter::Antialiasing);

			QPainterPath path;
			path.addEllipse(colorRect);
			painter.fillPath(path, value);
			painter.drawEllipse(colorRect);

			painter.setRenderHint(QPainter::Antialiasing, oldAntiAliasing);
		}

		textRect.setLeft(colorRect.right() + 3);
	}

	if (textRect.isValid())
	{
		QtnPropertyDelegateTyped<QtnPropertyQColorBase>::drawValueImpl(
			painter, textRect);
	}
}

QWidget *QtnPropertyDelegateQColor::createValueEditorImpl(
	QWidget *parent, const QRect &rect, QtnInplaceInfo *inplaceInfo)
{
	QtnLineEditBttn *editor = new QtnLineEditBttn(parent);
	editor->setGeometry(rect);

	new QtnPropertyQColorLineEditBttnHandler(this, *editor);

	if (inplaceInfo)
	{
		editor->lineEdit->selectAll();
	}

	return editor;
}

bool QtnPropertyDelegateQColor::propertyValueToStrImpl(QString &strValue) const
{
	return owner().toStr(strValue);
}

QtnPropertyDelegateQColorSolid::QtnPropertyDelegateQColorSolid(
	QtnPropertyQColorBase &owner)
	: QtnPropertyDelegateTyped<QtnPropertyQColorBase>(owner)
{
}

void QtnPropertyDelegateQColorSolid::Register(
	QtnPropertyDelegateFactory &factory)
{
	factory.registerDelegate(&QtnPropertyQColorBase::staticMetaObject,
		&qtnCreateDelegate<QtnPropertyDelegateQColorSolid,
			QtnPropertyQColorBase>,
		qtnSolidDelegateName());
}

bool QtnPropertyDelegateQColorSolid::createSubItemValueImpl(
	QtnDrawContext &context, QtnSubItem &subItemValue)
{
	if (!QtnPropertyDelegateTyped<
			QtnPropertyQColorBase>::createSubItemValueImpl(context,
			subItemValue))
		return false;

	// correct left value rect
	subItemValue.rect.setLeft(context.splitPos);
	return true;
}

void QtnPropertyDelegateQColorSolid::drawValueImpl(
	QStylePainter &painter, const QRect &rect) const
{
	if (stateProperty()->isMultiValue())
	{
		QtnPropertyDelegateTyped::drawValueImpl(painter, rect);
		return;
	}

	painter.fillRect(rect, owner());
}

QWidget *QtnPropertyDelegateQColorSolid::createValueEditorImpl(
	QWidget *parent, const QRect &rect, QtnInplaceInfo *inplaceInfo)
{
	Q_UNUSED(rect);
	Q_UNUSED(inplaceInfo);

	QColorDialog dlg(owner(), parent);
	if (dlg.exec() == QDialog::Accepted)
	{
		owner().setValue(dlg.currentColor(), editReason());
	}

	return nullptr;
}

QtnPropertyQColorLineEditBttnHandler::QtnPropertyQColorLineEditBttnHandler(
	QtnPropertyDelegate *delegate, QtnLineEditBttn &editor)
	: QtnPropertyEditorHandlerType(delegate, editor)
{
	if (!stateProperty()->isEditableByUser())
	{
		editor.lineEdit->setReadOnly(true);
		editor.toolButton->setEnabled(false);
	}

	updateEditor();
	editor.lineEdit->installEventFilter(this);
	QObject::connect(editor.toolButton, &QToolButton::clicked, this,
		&QtnPropertyQColorLineEditBttnHandler::onToolButtonClicked);
	QObject::connect(editor.lineEdit, &QLineEdit::editingFinished, this,
		&QtnPropertyQColorLineEditBttnHandler::onEditingFinished);
}

void QtnPropertyQColorLineEditBttnHandler::onToolButtonClick()
{
	onToolButtonClicked(false);
}

void QtnPropertyQColorLineEditBttnHandler::updateEditor()
{
	QString str;
	property().toStr(str);
	editor().setTextForProperty(stateProperty(), str);
	editor().lineEdit->selectAll();
}

void QtnPropertyQColorLineEditBttnHandler::onToolButtonClicked(bool)
{
	auto property = &this->property();
	volatile bool destroyed = false;
	auto connection = QObject::connect(property, &QObject::destroyed,
		[&destroyed]() mutable { destroyed = true; });
	reverted = true;
	auto dialog = new QColorDialog(property->value(), editorBase());
	auto dialogContainer = connectDialog(dialog);

	if (dialog->exec() == QDialog::Accepted && !destroyed)
	{
		property->setValue(dialog->currentColor(), delegate()->editReason());
	}

	if (!destroyed)
		QObject::disconnect(connection);

	Q_UNUSED(dialogContainer);
}

void QtnPropertyQColorLineEditBttnHandler::onEditingFinished()
{
	if (canApply())
	{
		property().setValue(
			QColor(editor().lineEdit->text()), delegate()->editReason());
	}

	applyReset();
}
<commit_msg>fix solid color margins<commit_after>/*******************************************************************************
Copyright (c) 2012-2016 Alex Zhondin <lexxmark.dev@gmail.com>
Copyright (c) 2015-2019 Alexandra Cherdantseva <neluhus.vagus@gmail.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*******************************************************************************/

#include "PropertyDelegateQColor.h"
#include "Delegates/PropertyDelegateFactory.h"
#include "Delegates/Utils/PropertyEditorHandler.h"
#include "Delegates/Utils/PropertyEditorAux.h"
#include "PropertyDelegateAttrs.h"
#include "Utils/InplaceEditing.h"

#include <QColorDialog>

QByteArray qtnShapeAttr()
{
	return QByteArrayLiteral("shape");
}

QByteArray qtnRgbSubItemsAttr()
{
	return QByteArrayLiteral("rgbSubItems");
}

QByteArray qtnSolidDelegateName()
{
	return QByteArrayLiteral("Solid");
}

QByteArray qtnSelectColorDelegateName()
{
	return QByteArrayLiteral("SelectColor");
}

class QtnPropertyQColorLineEditBttnHandler
	: public QtnPropertyEditorBttnHandler<QtnPropertyQColorBase,
		  QtnLineEditBttn>
{
public:
	QtnPropertyQColorLineEditBttnHandler(
		QtnPropertyDelegate *delegate, QtnLineEditBttn &editor);

protected:
	virtual void onToolButtonClick() override;
	virtual void updateEditor() override;

private:
	void onToolButtonClicked(bool);
	void onEditingFinished();
};

QtnPropertyDelegateQColor::QtnPropertyDelegateQColor(
	QtnPropertyQColorBase &owner)
	: QtnPropertyDelegateTypedEx<QtnPropertyQColorBase>(owner)
	, m_shape(QtnColorDelegateShapeSquare)
{
}

void QtnPropertyDelegateQColor::Register(QtnPropertyDelegateFactory &factory)
{
	factory.registerDelegateDefault(&QtnPropertyQColorBase::staticMetaObject,
		&qtnCreateDelegate<QtnPropertyDelegateQColor, QtnPropertyQColorBase>,
		qtnSelectColorDelegateName());
}

void QtnPropertyDelegateQColor::applyAttributesImpl(
	const QtnPropertyDelegateInfo &info)
{
	info.loadAttribute(qtnShapeAttr(), m_shape);

	if (info.getAttribute(qtnRgbSubItemsAttr(), false))
	{
		addSubProperty(owner().createRedProperty());
		addSubProperty(owner().createGreenProperty());
		addSubProperty(owner().createBlueProperty());
	}
}

void QtnPropertyDelegateQColor::drawValueImpl(
	QStylePainter &painter, const QRect &rect) const
{
	if (stateProperty()->isMultiValue())
	{
		QtnPropertyDelegateTypedEx::drawValueImpl(painter, rect);
		return;
	}

	QColor value = owner().value();

	QRect textRect = rect;

	if (m_shape != QtnColorDelegateShapeNone)
	{
		QRect colorRect = rect;
		colorRect.setWidth(colorRect.height());
		colorRect.adjust(2, 2, -2, -2);

		if (m_shape == QtnColorDelegateShapeSquare)
		{
			painter.fillRect(colorRect, Qt::black);
			colorRect.adjust(1, 1, -1, -1);
			painter.fillRect(colorRect, value);
		} else if (m_shape == QtnColorDelegateShapeCircle)
		{
			bool oldAntiAliasing =
				painter.testRenderHint(QPainter::Antialiasing);
			painter.setRenderHint(QPainter::Antialiasing);

			QPainterPath path;
			path.addEllipse(colorRect);
			painter.fillPath(path, value);
			painter.drawEllipse(colorRect);

			painter.setRenderHint(QPainter::Antialiasing, oldAntiAliasing);
		}

		textRect.setLeft(colorRect.right() + 3);
	}

	if (textRect.isValid())
	{
		QtnPropertyDelegateTyped<QtnPropertyQColorBase>::drawValueImpl(
			painter, textRect);
	}
}

QWidget *QtnPropertyDelegateQColor::createValueEditorImpl(
	QWidget *parent, const QRect &rect, QtnInplaceInfo *inplaceInfo)
{
	QtnLineEditBttn *editor = new QtnLineEditBttn(parent);
	editor->setGeometry(rect);

	new QtnPropertyQColorLineEditBttnHandler(this, *editor);

	if (inplaceInfo)
	{
		editor->lineEdit->selectAll();
	}

	return editor;
}

bool QtnPropertyDelegateQColor::propertyValueToStrImpl(QString &strValue) const
{
	return owner().toStr(strValue);
}

QtnPropertyDelegateQColorSolid::QtnPropertyDelegateQColorSolid(
	QtnPropertyQColorBase &owner)
	: QtnPropertyDelegateTyped<QtnPropertyQColorBase>(owner)
{
}

void QtnPropertyDelegateQColorSolid::Register(
	QtnPropertyDelegateFactory &factory)
{
	factory.registerDelegate(&QtnPropertyQColorBase::staticMetaObject,
		&qtnCreateDelegate<QtnPropertyDelegateQColorSolid,
			QtnPropertyQColorBase>,
		qtnSolidDelegateName());
}

bool QtnPropertyDelegateQColorSolid::createSubItemValueImpl(
	QtnDrawContext &context, QtnSubItem &subItemValue)
{
	if (!QtnPropertyDelegateTyped<
			QtnPropertyQColorBase>::createSubItemValueImpl(context,
			subItemValue))
		return false;

	// correct left value rect
	subItemValue.rect.setLeft(context.splitPos);
	return true;
}

void QtnPropertyDelegateQColorSolid::drawValueImpl(
	QStylePainter &painter, const QRect &rect) const
{
	if (stateProperty()->isMultiValue())
	{
		QtnPropertyDelegateTyped::drawValueImpl(painter, rect);
		return;
	}

	auto boxRect = rect;
	boxRect.adjust(2, 2, -2, -2);
	painter.fillRect(boxRect, owner());
}

QWidget *QtnPropertyDelegateQColorSolid::createValueEditorImpl(
	QWidget *parent, const QRect &rect, QtnInplaceInfo *inplaceInfo)
{
	Q_UNUSED(rect);
	Q_UNUSED(inplaceInfo);

	QColorDialog dlg(owner(), parent);
	if (dlg.exec() == QDialog::Accepted)
	{
		owner().setValue(dlg.currentColor(), editReason());
	}

	return nullptr;
}

QtnPropertyQColorLineEditBttnHandler::QtnPropertyQColorLineEditBttnHandler(
	QtnPropertyDelegate *delegate, QtnLineEditBttn &editor)
	: QtnPropertyEditorHandlerType(delegate, editor)
{
	if (!stateProperty()->isEditableByUser())
	{
		editor.lineEdit->setReadOnly(true);
		editor.toolButton->setEnabled(false);
	}

	updateEditor();
	editor.lineEdit->installEventFilter(this);
	QObject::connect(editor.toolButton, &QToolButton::clicked, this,
		&QtnPropertyQColorLineEditBttnHandler::onToolButtonClicked);
	QObject::connect(editor.lineEdit, &QLineEdit::editingFinished, this,
		&QtnPropertyQColorLineEditBttnHandler::onEditingFinished);
}

void QtnPropertyQColorLineEditBttnHandler::onToolButtonClick()
{
	onToolButtonClicked(false);
}

void QtnPropertyQColorLineEditBttnHandler::updateEditor()
{
	QString str;
	property().toStr(str);
	editor().setTextForProperty(stateProperty(), str);
	editor().lineEdit->selectAll();
}

void QtnPropertyQColorLineEditBttnHandler::onToolButtonClicked(bool)
{
	auto property = &this->property();
	volatile bool destroyed = false;
	auto connection = QObject::connect(property, &QObject::destroyed,
		[&destroyed]() mutable { destroyed = true; });
	reverted = true;
	auto dialog = new QColorDialog(property->value(), editorBase());
	auto dialogContainer = connectDialog(dialog);

	if (dialog->exec() == QDialog::Accepted && !destroyed)
	{
		property->setValue(dialog->currentColor(), delegate()->editReason());
	}

	if (!destroyed)
		QObject::disconnect(connection);

	Q_UNUSED(dialogContainer);
}

void QtnPropertyQColorLineEditBttnHandler::onEditingFinished()
{
	if (canApply())
	{
		property().setValue(
			QColor(editor().lineEdit->text()), delegate()->editReason());
	}

	applyReset();
}
<|endoftext|>


<commit_before>/*  Copyright (C) 2009  Adenilson Cavalcanti <savagobr@yahoo.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; by version 2 of the License or (at your
 *  choice) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

/* TODO:
 * - test edit event
 * - query-by-update implement and test
 * - support for recurrent events (it will require changes on libgcal)
 * - Some duplicated code must be moved to a common function (setting
 * KCal::Event data in gcal_event_t).
 */

#include "gcalresource.h"
#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <kcal/event.h>
#include <kdatetime.h>
#include <qstring.h>
#include <KWindowSystem>
#include <akonadi/changerecorder.h>
#include <akonadi/itemfetchscope.h>
#include <KUrl>
#include <kdatetime.h>
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<KCal::Incidence> IncidencePtr;

extern "C" {
#include <gcalendar.h>
#include <gcal_status.h>
}

using namespace Akonadi;

GCalResource::GCalResource( const QString &id )
	: ResourceBase(id)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject(
		QLatin1String( "/Settings" ), Settings::self(),
		QDBusConnection::ExportAdaptors );

	changeRecorder()->itemFetchScope().fetchFullPayload();

	if (!(gcal = gcal_new(GCALENDAR)))
		exit(1);
	gcal_set_store_xml(gcal, 1);
	all_events.length = 0;
	all_events.entries = NULL;
}

GCalResource::~GCalResource()
{
	gcal_cleanup_events(&all_events);
	pending.clear();
	deleted.clear();
}

void GCalResource::retrieveTimestamp(QString &timestamp)
{
	timestamp = Settings::self()->timestamp();
}

void GCalResource::saveTimestamp(QString &timestamp)
{
	Settings::self()->setTimestamp(timestamp);
	Settings::self()->writeConfig();
}

void GCalResource::retrieveCollections()
{
    if (!authenticated) {
	    kError() << "No authentication for Google Calendar available";
	    const QString message = i18nc("@info: status",
					  "Not yet authenticated for "
					  "use of Google Calendar");

	    emit error(message);

	    emit status(Broken, message);
	    return;
    }

    Collection c;
    c.setParent(Collection::root());
    c.setRemoteId("google-calendar");
    c.setName(name());

    QStringList mimeTypes;
    mimeTypes << "text/calendar";
    c.setContentMimeTypes(mimeTypes);

    Collection::List list;
    list << c;
    collectionsRetrieved(list);
}

void GCalResource::retrieveItems( const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);
	Item::List items;
	int result;
	gcal_event_t event;
	QString timestamp;
	QByteArray t_byte;

	kError() << "\n............. retrieveItems ...........\n";
	if (!authenticated) {
		kError() << "No authentication for Google calendar available";
		const QString message = i18nc("@info:status",
					      "Not yet authenticated for"
					      " use of Google calendar");
		emit error(message);
		emit status(Broken, message);
		return;
	}

	/* Query by updated */
// 	retrieveTimestamp(timestamp);
// 	t_byte = timestamp.toLocal8Bit();
// 	if (t_byte.length() > TIMESTAMP_SIZE) {
// 		//TODO: implement getUpdated
// 		//result = getUpdated(t_byte.data());
// 		return;
// 	}
	kError() << "First retrieve";

	if ((result = gcal_get_events(gcal, &all_events)))
		exit(1);

	/* GCalendar returns last updated entry as first element */
	event = gcal_event_element(&all_events, 0);
	if (!event) {
		kError() << "Failed to retrieve last updated event.";
		const QString message = i18nc("@info:status",
					      "Failed getting last updated"
					      " event");
		emit error(message);
		emit status(Broken, message);
		return;

	}

	timestamp = gcal_event_get_updated(event);
	saveTimestamp(timestamp);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_events.length; ++i) {
		Item item(QLatin1String("text/calendar"));
		KCal::Event *kevent;
		kevent = new KCal::Event;
		QString temp;
		event = gcal_event_element(&all_events, i);

		temp = gcal_event_get_title(event);
		kevent->setSummary(temp);

		temp = gcal_event_get_where(event);
		kevent->setLocation(temp);

		KCal::Incidence::Status status;
		if (gcal_event_is_deleted(event))
			status = KCal::Incidence::StatusCanceled;
		else
			status = KCal::Incidence::StatusConfirmed;
		kevent->setStatus(status);

		temp = gcal_event_get_content(event);
		kevent->setDescription(temp);

		KDateTime start, end;
		temp = gcal_event_get_start(event);
		start = start.fromString(temp, KDateTime::ISODate);
		temp = gcal_event_get_end(event);
		end = end.fromString(temp, KDateTime::ISODate);
		kevent->setDtStart(start);
		kevent->setDtEnd(end);

		qDebug() << "start: " << start.dateTime()
			 << "\tend: " << end.dateTime();

		/* remoteID: edit_url */
		KUrl urlEtag(gcal_event_get_url(event));
		item.setRemoteId(urlEtag.url());
		item.setPayload(IncidencePtr(kevent));

		items << item;
	}

	itemsRetrieved(items);
	kError() << "\n............. done retrieveItems! ...........\n";
}

bool GCalResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
	return true;
}

void GCalResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GCalResource::doSetOnline(bool online)
{
	Q_UNUSED(online);
}

int GCalResource::getUpdated(char *timestamp)
{
	Q_UNUSED(timestamp);

	return -1;
}

void GCalResource::configure( WId windowId )
{
	int result = 0;
	if (windowId && dlgConf)
		KWindowSystem::setMainWindow(dlgConf, windowId);

	dlgConf->exec();
	if (!(result = authenticate(dlgConf->eAccount->text(),
				    dlgConf->ePass->text()))) {
		result = saveToWallet(dlgConf->eAccount->text(),
				      dlgConf->ePass->text(),
				      windowId);

		synchronize();
	}

	if (result) {
		kError() << "Failed configuring resource.";
		const QString message = i18nc("@info:status",
					      "Invalid password.");
		emit error(message);
		emit status(Broken, message);
		return;
	}
}

void GCalResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);

    gcal_event_t event;
    KCal::Event *kevent;
    IncidencePtr ptrEvent;
    QByteArray t_byte;
    QString temp;
    KDateTime time;
    //TODO: test for recurrence (and ignore creation for while)

    if (!authenticated) {
        kError() << "No authentication for Google calendar available";
        const QString message = i18nc("@info:status",
                          "Not yet authenticated for"
                          " use of Google calendar");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (item.hasPayload<IncidencePtr>()) {
	    ptrEvent = item.payload<IncidencePtr>();
	    kevent = dynamic_cast<KCal::Event *>(ptrEvent.get());
    } else {
        kError() << "Add without payload!";
        const QString message = i18nc("@info:status",
                          "No payload to add event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (!(event = gcal_event_new(NULL))) {
        kError() << "Memory allocation error!";
        const QString message = i18nc("@info:status",
                      "Failed to create gcal_event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    temp = kevent->summary();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_title(event, t_byte);
    }

    temp = kevent->description();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_content(event, t_byte);
    }

    temp = kevent->location();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_where(event, t_byte);
    }

    /* Only this fields are being successfuly extracted */
    time = kevent->dtStart();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_start(event, t_byte.data());

    time = kevent->dtEnd();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_end(event, t_byte.data());

    if ((gcal_add_event(gcal, event))) {
        kError() << "Failed adding new calendar"
                << "title:" << kevent->summary();
        const QString message = i18nc("@info:status",
                            "failed adding new calendar");
        emit error(message);
        emit status(Broken, message);
    }

    KUrl url(gcal_event_get_url(event));
    Item newItem(item);
    newItem.setPayload(IncidencePtr(kevent->clone()));
    newItem.setRemoteId(url.url());
    changeCommitted(newItem);

    gcal_event_delete(event);
}

void GCalResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
    gcal_event_t event;
    KCal::Event *kevent;
    IncidencePtr ptrEvent;
    QByteArray t_byte;
    QString temp;
    KDateTime time;
    //TODO: test for recurrence (and ignore creation for while)

    if (!authenticated) {
        kError() << "No authentication for Google calendar available";
        const QString message = i18nc("@info:status",
                          "Not yet authenticated for"
                          " use of Google calendar");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (item.hasPayload<IncidencePtr>()) {
	    ptrEvent = item.payload<IncidencePtr>();
	    kevent = dynamic_cast<KCal::Event *>(ptrEvent.get());
    } else {
        kError() << "Add without payload!";
        const QString message = i18nc("@info:status",
                          "No payload to add event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (!(event = gcal_event_new(NULL))) {
        kError() << "Memory allocation error!";
        const QString message = i18nc("@info:status",
                      "Failed to create gcal_event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    temp = kevent->summary();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_title(event, t_byte);
    }

    temp = kevent->description();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_content(event, t_byte);
    }

    temp = kevent->location();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_where(event, t_byte);
    }

    /* Only this fields are being successfuly extracted */
    time = kevent->dtStart();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_start(event, t_byte.data());

    time = kevent->dtEnd();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_end(event, t_byte.data());

    KUrl url(item.remoteId());
    temp = url.url();
    t_byte = temp.toAscii();
    gcal_event_set_url(event, t_byte.data());

    if ((gcal_update_event(gcal, event))) {
        kError() << "Failed adding new calendar"
                << "title:" << kevent->summary();
        const QString message = i18nc("@info:status",
                            "failed adding new calendar");
        emit error(message);
        emit status(Broken, message);
    }

    temp = gcal_event_get_url(event);
    url = temp;
    Item newItem(item);
    newItem.setPayload(IncidencePtr(kevent->clone()));
    newItem.setRemoteId(url.url());
    changeCommitted(newItem);

    gcal_event_delete(event);

}

void GCalResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED(item);

    gcal_event_t event;
    QString temp;
    QByteArray t_byte;

    kDebug() << "Deleting one item ... ";

    if(!authenticated) {
        kError() << "No authentication for Google calendar";
        const QString message = i18nc("@info:status",
                                "Not yet authenticated for "
                                "use of Google calendar");
        emit error(message);
        emit status(Broken, message);
    }

    if (!(event = gcal_event_new(NULL))) {
        kError() << "Memory allocation error!";
        const QString message = i18nc("@info:status",
                                "Failed to create gcal_event");
        emit error(message);
        emit status(Broken, message);
    }

    KUrl url(item.remoteId());
    temp = url.url();
    t_byte = temp.toAscii();
    gcal_event_set_url(event, t_byte.data());

    if (gcal_erase_event(gcal, event)) {
        kError() << "Failed deleting calendar";
        const QString message = i18nc("@info:status",
                                "Failed deleting new calendar");
        emit error(message);
        emit status(Broken, message);
    }

    gcal_event_delete(event);

    changeProcessed();
    kDebug() << "done deleting!!";
}

AKONADI_RESOURCE_MAIN( GCalResource )

#include "gcalresource.moc"
<commit_msg>Updating comments.<commit_after>/*  Copyright (C) 2009  Adenilson Cavalcanti <savagobr@yahoo.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; by version 2 of the License or (at your
 *  choice) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

/* TODO:
 * - query-by-update implement and test
 * - support for recurrent events (it will require changes on libgcal)
 * - Some duplicated code must be moved to a common function (setting
 * KCal::Event data in gcal_event_t).
 */

#include "gcalresource.h"
#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <kcal/event.h>
#include <kdatetime.h>
#include <qstring.h>
#include <KWindowSystem>
#include <akonadi/changerecorder.h>
#include <akonadi/itemfetchscope.h>
#include <KUrl>
#include <kdatetime.h>
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<KCal::Incidence> IncidencePtr;

extern "C" {
#include <gcalendar.h>
#include <gcal_status.h>
}

using namespace Akonadi;

GCalResource::GCalResource( const QString &id )
	: ResourceBase(id)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject(
		QLatin1String( "/Settings" ), Settings::self(),
		QDBusConnection::ExportAdaptors );

	changeRecorder()->itemFetchScope().fetchFullPayload();

	if (!(gcal = gcal_new(GCALENDAR)))
		exit(1);
	gcal_set_store_xml(gcal, 1);
	all_events.length = 0;
	all_events.entries = NULL;
}

GCalResource::~GCalResource()
{
	gcal_cleanup_events(&all_events);
	pending.clear();
	deleted.clear();
}

void GCalResource::retrieveTimestamp(QString &timestamp)
{
	timestamp = Settings::self()->timestamp();
}

void GCalResource::saveTimestamp(QString &timestamp)
{
	Settings::self()->setTimestamp(timestamp);
	Settings::self()->writeConfig();
}

void GCalResource::retrieveCollections()
{
    if (!authenticated) {
	    kError() << "No authentication for Google Calendar available";
	    const QString message = i18nc("@info: status",
					  "Not yet authenticated for "
					  "use of Google Calendar");

	    emit error(message);

	    emit status(Broken, message);
	    return;
    }

    Collection c;
    c.setParent(Collection::root());
    c.setRemoteId("google-calendar");
    c.setName(name());

    QStringList mimeTypes;
    mimeTypes << "text/calendar";
    c.setContentMimeTypes(mimeTypes);

    Collection::List list;
    list << c;
    collectionsRetrieved(list);
}

void GCalResource::retrieveItems( const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);
	Item::List items;
	int result;
	gcal_event_t event;
	QString timestamp;
	QByteArray t_byte;

	kError() << "\n............. retrieveItems ...........\n";
	if (!authenticated) {
		kError() << "No authentication for Google calendar available";
		const QString message = i18nc("@info:status",
					      "Not yet authenticated for"
					      " use of Google calendar");
		emit error(message);
		emit status(Broken, message);
		return;
	}

	/* Query by updated */
// 	retrieveTimestamp(timestamp);
// 	t_byte = timestamp.toLocal8Bit();
// 	if (t_byte.length() > TIMESTAMP_SIZE) {
// 		//TODO: implement getUpdated
// 		//result = getUpdated(t_byte.data());
// 		return;
// 	}
	kError() << "First retrieve";

	if ((result = gcal_get_events(gcal, &all_events)))
		exit(1);

	/* GCalendar returns last updated entry as first element */
	event = gcal_event_element(&all_events, 0);
	if (!event) {
		kError() << "Failed to retrieve last updated event.";
		const QString message = i18nc("@info:status",
					      "Failed getting last updated"
					      " event");
		emit error(message);
		emit status(Broken, message);
		return;

	}

	timestamp = gcal_event_get_updated(event);
	saveTimestamp(timestamp);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_events.length; ++i) {
		Item item(QLatin1String("text/calendar"));
		KCal::Event *kevent;
		kevent = new KCal::Event;
		QString temp;
		event = gcal_event_element(&all_events, i);

		temp = gcal_event_get_title(event);
		kevent->setSummary(temp);

		temp = gcal_event_get_where(event);
		kevent->setLocation(temp);

		KCal::Incidence::Status status;
		if (gcal_event_is_deleted(event))
			status = KCal::Incidence::StatusCanceled;
		else
			status = KCal::Incidence::StatusConfirmed;
		kevent->setStatus(status);

		temp = gcal_event_get_content(event);
		kevent->setDescription(temp);

		KDateTime start, end;
		temp = gcal_event_get_start(event);
		start = start.fromString(temp, KDateTime::ISODate);
		temp = gcal_event_get_end(event);
		end = end.fromString(temp, KDateTime::ISODate);
		kevent->setDtStart(start);
		kevent->setDtEnd(end);

		qDebug() << "start: " << start.dateTime()
			 << "\tend: " << end.dateTime();

		/* remoteID: edit_url */
		KUrl urlEtag(gcal_event_get_url(event));
		item.setRemoteId(urlEtag.url());
		item.setPayload(IncidencePtr(kevent));

		items << item;
	}

	itemsRetrieved(items);
	kError() << "\n............. done retrieveItems! ...........\n";
}

bool GCalResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
	return true;
}

void GCalResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GCalResource::doSetOnline(bool online)
{
	Q_UNUSED(online);
}

int GCalResource::getUpdated(char *timestamp)
{
	Q_UNUSED(timestamp);

	return -1;
}

void GCalResource::configure( WId windowId )
{
	int result = 0;
	if (windowId && dlgConf)
		KWindowSystem::setMainWindow(dlgConf, windowId);

	dlgConf->exec();
	if (!(result = authenticate(dlgConf->eAccount->text(),
				    dlgConf->ePass->text()))) {
		result = saveToWallet(dlgConf->eAccount->text(),
				      dlgConf->ePass->text(),
				      windowId);

		synchronize();
	}

	if (result) {
		kError() << "Failed configuring resource.";
		const QString message = i18nc("@info:status",
					      "Invalid password.");
		emit error(message);
		emit status(Broken, message);
		return;
	}
}

void GCalResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);

    gcal_event_t event;
    KCal::Event *kevent;
    IncidencePtr ptrEvent;
    QByteArray t_byte;
    QString temp;
    KDateTime time;
    //TODO: test for recurrence (and ignore creation for while)

    if (!authenticated) {
        kError() << "No authentication for Google calendar available";
        const QString message = i18nc("@info:status",
                          "Not yet authenticated for"
                          " use of Google calendar");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (item.hasPayload<IncidencePtr>()) {
	    ptrEvent = item.payload<IncidencePtr>();
	    kevent = dynamic_cast<KCal::Event *>(ptrEvent.get());
    } else {
        kError() << "Add without payload!";
        const QString message = i18nc("@info:status",
                          "No payload to add event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (!(event = gcal_event_new(NULL))) {
        kError() << "Memory allocation error!";
        const QString message = i18nc("@info:status",
                      "Failed to create gcal_event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    temp = kevent->summary();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_title(event, t_byte);
    }

    temp = kevent->description();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_content(event, t_byte);
    }

    temp = kevent->location();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_where(event, t_byte);
    }

    time = kevent->dtStart();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_start(event, t_byte.data());

    time = kevent->dtEnd();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_end(event, t_byte.data());

    if ((gcal_add_event(gcal, event))) {
        kError() << "Failed adding new calendar"
                << "title:" << kevent->summary();
        const QString message = i18nc("@info:status",
                            "failed adding new calendar");
        emit error(message);
        emit status(Broken, message);
    }

    KUrl url(gcal_event_get_url(event));
    Item newItem(item);
    newItem.setPayload(IncidencePtr(kevent->clone()));
    newItem.setRemoteId(url.url());
    changeCommitted(newItem);

    gcal_event_delete(event);
}

void GCalResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
    gcal_event_t event;
    KCal::Event *kevent;
    IncidencePtr ptrEvent;
    QByteArray t_byte;
    QString temp;
    KDateTime time;
    //TODO: test for recurrence (and ignore creation for while)

    if (!authenticated) {
        kError() << "No authentication for Google calendar available";
        const QString message = i18nc("@info:status",
                          "Not yet authenticated for"
                          " use of Google calendar");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (item.hasPayload<IncidencePtr>()) {
	    ptrEvent = item.payload<IncidencePtr>();
	    kevent = dynamic_cast<KCal::Event *>(ptrEvent.get());
    } else {
        kError() << "Add without payload!";
        const QString message = i18nc("@info:status",
                          "No payload to add event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    if (!(event = gcal_event_new(NULL))) {
        kError() << "Memory allocation error!";
        const QString message = i18nc("@info:status",
                      "Failed to create gcal_event");
        emit error(message);
        emit status(Broken, message);
        return;
    }

    temp = kevent->summary();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_title(event, t_byte);
    }

    temp = kevent->description();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_content(event, t_byte);
    }

    temp = kevent->location();
    if (!temp.isEmpty()) {
        t_byte = temp.toLocal8Bit();
        gcal_event_set_where(event, t_byte);
    }

    /* Only this fields are being successfuly extracted */
    time = kevent->dtStart();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_start(event, t_byte.data());

    time = kevent->dtEnd();
    temp = time.toString(KDateTime::ISODate);
    t_byte = temp.toLocal8Bit();
    gcal_event_set_end(event, t_byte.data());

    KUrl url(item.remoteId());
    temp = url.url();
    t_byte = temp.toAscii();
    gcal_event_set_url(event, t_byte.data());

    if ((gcal_update_event(gcal, event))) {
        kError() << "Failed adding new calendar"
                << "title:" << kevent->summary();
        const QString message = i18nc("@info:status",
                            "failed adding new calendar");
        emit error(message);
        emit status(Broken, message);
    }

    temp = gcal_event_get_url(event);
    url = temp;
    Item newItem(item);
    newItem.setPayload(IncidencePtr(kevent->clone()));
    newItem.setRemoteId(url.url());
    changeCommitted(newItem);

    gcal_event_delete(event);

}

void GCalResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED(item);

    gcal_event_t event;
    QString temp;
    QByteArray t_byte;

    kDebug() << "Deleting one item ... ";

    if(!authenticated) {
        kError() << "No authentication for Google calendar";
        const QString message = i18nc("@info:status",
                                "Not yet authenticated for "
                                "use of Google calendar");
        emit error(message);
        emit status(Broken, message);
    }

    if (!(event = gcal_event_new(NULL))) {
        kError() << "Memory allocation error!";
        const QString message = i18nc("@info:status",
                                "Failed to create gcal_event");
        emit error(message);
        emit status(Broken, message);
    }

    KUrl url(item.remoteId());
    temp = url.url();
    t_byte = temp.toAscii();
    gcal_event_set_url(event, t_byte.data());

    if (gcal_erase_event(gcal, event)) {
        kError() << "Failed deleting calendar";
        const QString message = i18nc("@info:status",
                                "Failed deleting new calendar");
        emit error(message);
        emit status(Broken, message);
    }

    gcal_event_delete(event);

    changeProcessed();
    kDebug() << "done deleting!!";
}

AKONADI_RESOURCE_MAIN( GCalResource )

#include "gcalresource.moc"
<|endoftext|>


<commit_before>#include "ffoption.h"

#if defined(CC_PF_LINUX) || defined(CC_PF_MINGW32)
#   include <getopt.h>
#endif

#include <cstdio>
#include <iostream>
#include <cstdlib>

using namespace ff;

FFOption::FFOption()
    :ignore_name_(false)
    ,ignore_ret_type_(false)
    ,regex_(false)
    ,recursion_(false)
    ,find_declare_(false)
    ,print_filename_(true)
    ,print_line_num_(false)
    ,print_match_count_(false)
    ,start_time_(0)
    ,end_time_(0)
    ,function_signature_()
    ,clang_args_cnt_(0)
    ,clang_args_()
    ,files_()
{

}

//#ifdef FF_DEBUG
void
FFOption::debugPrintStatus() const
{
    std::printf("FFOption{\n");
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->ignore_name_), this->ignore_name_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->ignore_ret_type_), this->ignore_ret_type_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->regex_), this->regex_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->recursion_), this->recursion_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->find_declare_), this->find_declare_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->print_filename_), this->print_filename_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->print_line_num_), this->print_line_num_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->print_match_count_), this->print_match_count_);
    std::printf("\t%s: %ld\n", FF_TO_SRTING(this->start_time_), this->start_time_);
    std::printf("\t%s: %ld\n", FF_TO_SRTING(this->end_time_), this->end_time_);
    //std::printf("\t%s: %s\n", FF_TO_SRTING(this->clang_args_), this->clang_args_.c_str());
    std::printf("\t%s: [", FF_TO_SRTING(this->files_));
    for (std::vector<std::string>::const_iterator cit = this->files_.begin();   \
            cit != this->files_.end();cit ++) {
        std::printf (" %s ", cit->c_str());
    }
    std::printf("]\n");
    std::printf("\t%s:{\n", FF_TO_SRTING(this->function_signature_));
    std::printf("\t\treturn type -> %s\n", this->function_signature_.returnType().c_str());
    std::printf("\t\tfunction name -> %s\n", this->function_signature_.functionName().c_str());
    std::printf("\t\targment list -> %lu[", this->function_signature_.argsType().size());
    for (std::vector<std::string>::const_iterator sit = this->function_signature_.argsType().begin();  \
         sit != this->function_signature_.argsType().end();sit ++) {
        std::printf(" %s ", sit->c_str());
    }
    std::printf("]\n\t}\n}\n");
}
//#endif

bool
FFOption::parseCommandArgs(int argc, char **argv)
{
    static const char* cmd_short_options = "R";

    static struct option cmd_long_options[] = {
        /*switch*/
		{"ignore-name",     no_argument,        0, 'N'},//0
		{"ignore-ret-type", no_argument,        0, 'Y'},//1
		{"regex",           no_argument,        0, 'G'},//2
        {"recursion",       no_argument,        0, 'R'},
        {"find-declare",    no_argument,        0, 'd'},
        {"filename",        no_argument,        0, 'f'},
        {"line-number",     no_argument,        0, 'n'},
        {"match-count",     no_argument,        0, 'c'},
        /*option*/
        {"signature",       required_argument,  0, 's'},
        {"ret-type",        required_argument,  0, 'r'},
        {"args-type",       required_argument,  0, 'a'},
        {"start-time",      required_argument,  0, 'S'},
        {"end-time",        required_argument,  0, 'E'},
        {"threads-count",   required_argument,  0, 't'},
        {"clang",           required_argument,  0,  'C'},
        /**/
        {"help",            no_argument,        0, 'h'},
        {"version",         no_argument,        0, 'v'},
        {0,                 0,                  0, 0}
    };

    std::string ret_type, args_type;

    int opt = 0;

    int option_index = 0;

    while((opt = getopt_long(argc, argv, cmd_short_options, cmd_long_options, &option_index)) != -1){
        if (opt == -1) {
            this->printOptionHelp();
            break;
        }
        switch (opt) {
        case 'N':{ this->ignore_name_ = true; } break;
        case 'Y':{ this->ignore_ret_type_ = true; } break;
		case 'G':{ this->regex_ = true; } break;
        case 'R':{ this->recursion_ = true; } break;
        case 'D':{ this->find_declare_ = true; } break;
        case 'f':{ this->print_filename_ = true; } break;
        case 'n':{ this->print_line_num_ = true; } break;
            //when we set print_match_count_ true
            //we need check print_filename_
        case 'c':{ this->print_match_count_ = true; } break;
        /**************************************************/
        case 's':{ this->function_signature_.parseSignature(optarg); } break;
        case 'r':{ ret_type = optarg; } break;
        case 'a':{ args_type = optarg; } break;
        case 'S':{ this->setStartTime(std::atol(optarg)); } break;
        case 'E':{ this->setEndTime(std::atol(optarg)); } break;
        case 't':{ this->setThreadCount(std::atoi(optarg)); } break;
        case 'C':{ this->setClangArgs(optarg); } break;
        /*************************************************/
        case 'h':
        case 'v':
        default:{ this->printOptionHelp(); exit(0);} break;
        }
    }

    if (this->function_signature_ == FunctionSignature()) {
        if (!ret_type.empty()) {
            this->function_signature_.parseRetType(ret_type);
        }
        if (!args_type.empty()) {
            this->function_signature_.parseArgsType(args_type);
        }
    }

    if (optind >= argc) {
        return false;
    }

    while (optind < argc) {
        this->pushFiles(std::string(argv[optind ++]));
    }

    this->checkClangOptions(std::string("-x,c++,-std=c++11"));

    return true;
}

void
FFOption::printOptionHelp() const
{
    static const char* s_help = FF_OPTION_HELP;

    std::printf(s_help);
}

<commit_msg>fix error<commit_after>#include "ffoption.h"

#if defined(CC_PF_LINUX) || defined(CC_PF_MINGW32)
#   include <getopt.h>
#endif

#include <cstdio>
#include <iostream>
#include <cstdlib>

using namespace ff;

FFOption::FFOption()
    :ignore_name_(false)
    ,ignore_ret_type_(false)
    ,regex_(false)
    ,recursion_(false)
    ,find_declare_(false)
    ,print_filename_(true)
    ,print_line_num_(false)
    ,print_match_count_(false)
    ,start_time_(0)
    ,end_time_(0)
    ,function_signature_()
    ,clang_args_cnt_(0)
    ,clang_args_()
    ,files_()
{

}

//#ifdef FF_DEBUG
void
FFOption::debugPrintStatus() const
{
    std::printf("FFOption{\n");
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->ignore_name_), this->ignore_name_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->ignore_ret_type_), this->ignore_ret_type_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->regex_), this->regex_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->recursion_), this->recursion_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->find_declare_), this->find_declare_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->print_filename_), this->print_filename_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->print_line_num_), this->print_line_num_);
    std::printf("\t%s: %d\n", FF_TO_SRTING(this->print_match_count_), this->print_match_count_);
    std::printf("\t%s: %ld\n", FF_TO_SRTING(this->start_time_), this->start_time_);
    std::printf("\t%s: %ld\n", FF_TO_SRTING(this->end_time_), this->end_time_);
    //std::printf("\t%s: %s\n", FF_TO_SRTING(this->clang_args_), this->clang_args_.c_str());
    std::printf("\t%s: [", FF_TO_SRTING(this->files_));
    for (std::vector<std::string>::const_iterator cit = this->files_.begin();   \
            cit != this->files_.end();cit ++) {
        std::printf (" %s ", cit->c_str());
    }
    std::printf("]\n");
    std::printf("\t%s:{\n", FF_TO_SRTING(this->function_signature_));
    std::printf("\t\treturn type -> %s\n", this->function_signature_.returnType().c_str());
    std::printf("\t\tfunction name -> %s\n", this->function_signature_.functionName().c_str());
    std::printf("\t\targment list -> %lu[", this->function_signature_.argsType().size());
    for (std::vector<std::string>::const_iterator sit = this->function_signature_.argsType().begin();  \
         sit != this->function_signature_.argsType().end();sit ++) {
        std::printf(" %s ", sit->c_str());
    }
    std::printf("]\n\t}\n}\n");
}
//#endif

bool
FFOption::parseCommandArgs(int argc, char **argv)
{
    static const char* cmd_short_options = "R";

    static struct option cmd_long_options[] = {
        /*switch*/
		{"ignore-name",     no_argument,        0, 'N'},//0
		{"ignore-ret-type", no_argument,        0, 'Y'},//1
		{"regex",           no_argument,        0, 'G'},//2
        {"recursion",       no_argument,        0, 'R'},
        {"find-declare",    no_argument,        0, 'd'},
        {"filename",        no_argument,        0, 'f'},
        {"line-number",     no_argument,        0, 'n'},
        {"match-count",     no_argument,        0, 'c'},
        /*option*/
        {"signature",       required_argument,  0, 's'},
        {"ret-type",        required_argument,  0, 'r'},
        {"args-type",       required_argument,  0, 'a'},
        {"start-time",      required_argument,  0, 'S'},
        {"end-time",        required_argument,  0, 'E'},
        {"threads-count",   required_argument,  0, 't'},
        {"clang",           required_argument,  0,  'C'},
        /**/
        {"help",            no_argument,        0, 'h'},
        {"version",         no_argument,        0, 'v'},
        {0,                 0,                  0, 0}
    };

    std::string ret_type, args_type;

    int opt = 0;

    int option_index = 0;

    while((opt = getopt_long(argc, argv, cmd_short_options, cmd_long_options, &option_index)) != -1){
        if (opt == -1) {
            this->printOptionHelp();
            break;
        }
        switch (opt) {
        case 'N':{ this->ignore_name_ = true; } break;
        case 'Y':{ this->ignore_ret_type_ = true; } break;
		case 'G':{ this->regex_ = true; } break;
        case 'R':{ this->recursion_ = true; } break;
        case 'D':{ this->find_declare_ = true; } break;
        case 'f':{ this->print_filename_ = true; } break;
        case 'n':{ this->print_line_num_ = true; } break;
            //when we set print_match_count_ true
            //we need check print_filename_
        case 'c':{ this->print_match_count_ = true; } break;
        /**************************************************/
        case 's':{ this->function_signature_.parseSignature(optarg); } break;
        case 'r':{ ret_type = optarg; } break;
        case 'a':{ args_type = optarg; } break;
        case 'S':{ this->setStartTime(std::atol(optarg)); } break;
        case 'E':{ this->setEndTime(std::atol(optarg)); } break;
        case 't':{ this->setThreadCount(std::atoi(optarg)); } break;
        case 'C':{ this->setClangArgs(optarg); } break;
        /*************************************************/
        case 'h':
        case 'v':
        default:{ this->printOptionHelp(); exit(0);} break;
        }
    }

    if (this->function_signature_ == FunctionSignature()) {
        if (!ret_type.empty()) {
            this->function_signature_.parseRetType(ret_type);
        }
        if (!args_type.empty()) {
            this->function_signature_.parseArgsType(args_type);
        }
    }

    if (optind >= argc) {
        return false;
    }

    while (optind < argc) {
        this->pushFiles(std::string(argv[optind ++]));
    }

    this->checkClangOptions(std::string("-x,c++,-std=c++11"));

    return true;
}

void
FFOption::printOptionHelp() const
{
    static const char* s_help = FF_OPTION_HELP;

    std::printf("%s", s_help);
}

<|endoftext|>


<commit_before>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008-2020 <http://www.ArcEmu.org/>
 *
 * This program 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
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "../Util.h"
#include "../../testing/testmacros.h"
#include <iostream>

class UtilTest
{
public:
	bool testArcemuToLower();
	bool testArcemuToLowerWithLowerCase();

	bool testArcemuToUpper();
	bool testArcemuToUpperWithUpperCase();

	bool testFloatRoundUp();
	bool testFloatRoundDown();
	bool testFloatRoundWhole();

	bool testDoubleRoundUp();
	bool testDoubleRoundDown();
	bool testDoubleRoundWhole();

	bool testLongDoubleRoundUp();
	bool testLongDoubleRoundDown();
	bool testLongDoubleRoundWhole();

	bool testStrSplitWhenEmpty();
	bool testStrSplitWhenEmptySeparator();
	bool testStrSplitWhenWrongSeparator();
	bool testStrSplit();

	bool testCapitalizeStringEmpty();
	bool testCapitalizeStringUpper();
	bool testCapitalizeStringLower();
	bool testCapitalizeStringCapitalized();

	bool run();
};

TESTCASE_REGISTRY_FOR( UtilTest )
	TESTCASE( UtilTest, testArcemuToLower, "arcemu_TOLOWER converts uppercase to lowercase." )
	TESTCASE( UtilTest, testArcemuToLowerWithLowerCase, "arcemu_TOLOWER converts leaves lowercase." )

	TESTCASE( UtilTest, testArcemuToUpper, "arcemu_TOUPPER converts lowercase to uppercase." )
	TESTCASE( UtilTest, testArcemuToUpperWithUpperCase, "arcemu_TOUPPER leaves uppercase as is" )

	TESTCASE( UtilTest, testFloatRoundUp, "round( float ) rounds up when appropriate" )
	TESTCASE( UtilTest, testFloatRoundDown, "round( float ) rounds down when appropriate" )
	TESTCASE( UtilTest, testFloatRoundWhole, "round( float ) doesn't round a whole number" )

	TESTCASE( UtilTest, testDoubleRoundUp, "round( double ) rounds up when appropriate" )
	TESTCASE( UtilTest, testDoubleRoundDown, "round( double ) rounds down when appropriate" )
	TESTCASE( UtilTest, testDoubleRoundWhole, "round( double ) doesn't round a whole number" )

	TESTCASE( UtilTest, testLongDoubleRoundUp, "round( long double ) rounds up when appropriate" )
	TESTCASE( UtilTest, testLongDoubleRoundDown, "round( long double ) rounds down when appropriate" )
	TESTCASE( UtilTest, testLongDoubleRoundWhole, "round( long double ) doesn't round a whole number" )

	TESTCASE( UtilTest, testStrSplitWhenEmpty, "StrSplit returns an empty vector when given an empty string" )
	TESTCASE( UtilTest, testStrSplitWhenEmptySeparator, "StrSplit returns the original string in a 1 length vector, when given an empty separator" )
	TESTCASE( UtilTest, testStrSplitWhenWrongSeparator, "StrSplit returns the original string in a 1 length vector, when given a wrong separator" )
	TESTCASE( UtilTest, testStrSplit, "StrSplit splits the string into a vector of string" )

	TESTCASE( UtilTest, testCapitalizeStringEmpty, "CapitalizeString leaves an empty string empty" )
	TESTCASE( UtilTest, testCapitalizeStringUpper, "CapitalizeString transforms uppercase string correctly" )
	TESTCASE( UtilTest, testCapitalizeStringLower, "CapitalizeString transforms lowercase string correctly" )
	TESTCASE( UtilTest, testCapitalizeStringCapitalized, "CapitalizeString leaves capitalized string capitalized" )
TESTCASE_REGISTRY_END()

bool UtilTest::testArcemuToLower()
{
	std::string actual = "UPPERCASE STRING";
	std::string original = actual;
	std::string expected = "uppercase string";

	Arcemu::Shared::Util::arcemu_TOLOWER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testArcemuToLowerWithLowerCase()
{
	std::string actual = "lowercase string";
	std::string original = actual;
	std::string expected = original;

	Arcemu::Shared::Util::arcemu_TOLOWER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testArcemuToUpper()
{
	std::string actual = "lowercase string";
	std::string original = actual;
	std::string expected = "LOWERCASE STRING";

	Arcemu::Shared::Util::arcemu_TOUPPER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testArcemuToUpperWithUpperCase()
{
	std::string actual = "UPPERCASE STRING";
	std::string original = actual;
	std::string expected = original;

	Arcemu::Shared::Util::arcemu_TOUPPER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testFloatRoundUp()
{
	float input = 2.6f;
	float expected = 3.0f;
	float actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testFloatRoundDown()
{
	float input = 2.2f;
	float expected = 2.0f;
	float actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testFloatRoundWhole()
{
	float input = 2.0f;
	float expected = 2.0f;
	float actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testDoubleRoundUp()
{
	double input = 2.6;
	double expected = 3.0;
	double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testDoubleRoundDown()
{
	double input = 2.2;
	double expected = 2.0;
	double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testDoubleRoundWhole()
{
	double input = 2.0;
	double expected = 2.0;
	double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testLongDoubleRoundUp()
{
	long double input = 2.6;
	long double expected = 3.0;
	long double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testLongDoubleRoundDown()
{
	long double input = 2.2;
	long double expected = 2.0;
	long double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testLongDoubleRoundWhole()
{
	long double input = 2.0;
	long double expected = 2.0;
	long double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testStrSplitWhenEmpty()
{
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( "", ";" );
	TEST_EQ( 0, strings.size() );

	TESTCASE_END();
}

bool UtilTest::testStrSplitWhenEmptySeparator()
{
	std::string string = "one;two;three";
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( string, "" );
	TEST_EQ( 1, strings.size() );
	TEST_EQ( strings[ 0 ], string );

	TESTCASE_END();
}

bool UtilTest::testStrSplitWhenWrongSeparator()
{
	std::string string = "one;two;three";
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( string, "|" );
	TEST_EQ( 1, strings.size() );
	TEST_EQ( strings[ 0 ], string );

	TESTCASE_END();
}

bool UtilTest::testStrSplit()
{
	std::string string = "one;two;three";
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( string, ";" );
	TEST_EQ( 3, strings.size() );
	TEST_EQ( "one", strings[ 0 ] );
	TEST_EQ( "two", strings[ 1 ] );
	TEST_EQ( "three", strings[ 2 ] );

	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringEmpty()
{
	std::string string = "";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( string.size(), 0 );
	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringUpper()
{
	std::string string = "UPPER";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( "Upper", string );
	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringLower()
{
	std::string string = "lower";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( "Lower", string );
	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringCapitalized()
{
	std::string string = "Capitalized";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( "Capitalized", string );
	TESTCASE_END();
}

bool UtilTest::run()
{
	RUN_TESTS();
}

int main( int argc, char *argv[] )
{
	RUN_TESTCLASS( UtilTest );
}
<commit_msg>Missed this one<commit_after>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2008-2020 <http://www.ArcEmu.org/>
 *
 * This program 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
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Util/Util.h"
#include "../../testing/testmacros.h"
#include <iostream>

class UtilTest
{
public:
	bool testArcemuToLower();
	bool testArcemuToLowerWithLowerCase();

	bool testArcemuToUpper();
	bool testArcemuToUpperWithUpperCase();

	bool testFloatRoundUp();
	bool testFloatRoundDown();
	bool testFloatRoundWhole();

	bool testDoubleRoundUp();
	bool testDoubleRoundDown();
	bool testDoubleRoundWhole();

	bool testLongDoubleRoundUp();
	bool testLongDoubleRoundDown();
	bool testLongDoubleRoundWhole();

	bool testStrSplitWhenEmpty();
	bool testStrSplitWhenEmptySeparator();
	bool testStrSplitWhenWrongSeparator();
	bool testStrSplit();

	bool testCapitalizeStringEmpty();
	bool testCapitalizeStringUpper();
	bool testCapitalizeStringLower();
	bool testCapitalizeStringCapitalized();

	bool run();
};

TESTCASE_REGISTRY_FOR( UtilTest )
	TESTCASE( UtilTest, testArcemuToLower, "arcemu_TOLOWER converts uppercase to lowercase." )
	TESTCASE( UtilTest, testArcemuToLowerWithLowerCase, "arcemu_TOLOWER converts leaves lowercase." )

	TESTCASE( UtilTest, testArcemuToUpper, "arcemu_TOUPPER converts lowercase to uppercase." )
	TESTCASE( UtilTest, testArcemuToUpperWithUpperCase, "arcemu_TOUPPER leaves uppercase as is" )

	TESTCASE( UtilTest, testFloatRoundUp, "round( float ) rounds up when appropriate" )
	TESTCASE( UtilTest, testFloatRoundDown, "round( float ) rounds down when appropriate" )
	TESTCASE( UtilTest, testFloatRoundWhole, "round( float ) doesn't round a whole number" )

	TESTCASE( UtilTest, testDoubleRoundUp, "round( double ) rounds up when appropriate" )
	TESTCASE( UtilTest, testDoubleRoundDown, "round( double ) rounds down when appropriate" )
	TESTCASE( UtilTest, testDoubleRoundWhole, "round( double ) doesn't round a whole number" )

	TESTCASE( UtilTest, testLongDoubleRoundUp, "round( long double ) rounds up when appropriate" )
	TESTCASE( UtilTest, testLongDoubleRoundDown, "round( long double ) rounds down when appropriate" )
	TESTCASE( UtilTest, testLongDoubleRoundWhole, "round( long double ) doesn't round a whole number" )

	TESTCASE( UtilTest, testStrSplitWhenEmpty, "StrSplit returns an empty vector when given an empty string" )
	TESTCASE( UtilTest, testStrSplitWhenEmptySeparator, "StrSplit returns the original string in a 1 length vector, when given an empty separator" )
	TESTCASE( UtilTest, testStrSplitWhenWrongSeparator, "StrSplit returns the original string in a 1 length vector, when given a wrong separator" )
	TESTCASE( UtilTest, testStrSplit, "StrSplit splits the string into a vector of string" )

	TESTCASE( UtilTest, testCapitalizeStringEmpty, "CapitalizeString leaves an empty string empty" )
	TESTCASE( UtilTest, testCapitalizeStringUpper, "CapitalizeString transforms uppercase string correctly" )
	TESTCASE( UtilTest, testCapitalizeStringLower, "CapitalizeString transforms lowercase string correctly" )
	TESTCASE( UtilTest, testCapitalizeStringCapitalized, "CapitalizeString leaves capitalized string capitalized" )
TESTCASE_REGISTRY_END()

bool UtilTest::testArcemuToLower()
{
	std::string actual = "UPPERCASE STRING";
	std::string original = actual;
	std::string expected = "uppercase string";

	Arcemu::Shared::Util::arcemu_TOLOWER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testArcemuToLowerWithLowerCase()
{
	std::string actual = "lowercase string";
	std::string original = actual;
	std::string expected = original;

	Arcemu::Shared::Util::arcemu_TOLOWER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testArcemuToUpper()
{
	std::string actual = "lowercase string";
	std::string original = actual;
	std::string expected = "LOWERCASE STRING";

	Arcemu::Shared::Util::arcemu_TOUPPER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testArcemuToUpperWithUpperCase()
{
	std::string actual = "UPPERCASE STRING";
	std::string original = actual;
	std::string expected = original;

	Arcemu::Shared::Util::arcemu_TOUPPER( actual );

	std::cout << "Original: " << original << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected.compare( actual ), 0 );

	TESTCASE_END();
}

bool UtilTest::testFloatRoundUp()
{
	float input = 2.6f;
	float expected = 3.0f;
	float actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testFloatRoundDown()
{
	float input = 2.2f;
	float expected = 2.0f;
	float actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testFloatRoundWhole()
{
	float input = 2.0f;
	float expected = 2.0f;
	float actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testDoubleRoundUp()
{
	double input = 2.6;
	double expected = 3.0;
	double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testDoubleRoundDown()
{
	double input = 2.2;
	double expected = 2.0;
	double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testDoubleRoundWhole()
{
	double input = 2.0;
	double expected = 2.0;
	double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testLongDoubleRoundUp()
{
	long double input = 2.6;
	long double expected = 3.0;
	long double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testLongDoubleRoundDown()
{
	long double input = 2.2;
	long double expected = 2.0;
	long double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testLongDoubleRoundWhole()
{
	long double input = 2.0;
	long double expected = 2.0;
	long double actual = Arcemu::Shared::Util::round( input );

	std::cout << "Input: " << input << std::endl;
	std::cout << "Expected: " << expected << std::endl;
	std::cout << "Actual: " << actual << std::endl;

	TEST_EQ( expected, actual );

	TESTCASE_END();
}

bool UtilTest::testStrSplitWhenEmpty()
{
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( "", ";" );
	TEST_EQ( 0, strings.size() );

	TESTCASE_END();
}

bool UtilTest::testStrSplitWhenEmptySeparator()
{
	std::string string = "one;two;three";
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( string, "" );
	TEST_EQ( 1, strings.size() );
	TEST_EQ( strings[ 0 ], string );

	TESTCASE_END();
}

bool UtilTest::testStrSplitWhenWrongSeparator()
{
	std::string string = "one;two;three";
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( string, "|" );
	TEST_EQ( 1, strings.size() );
	TEST_EQ( strings[ 0 ], string );

	TESTCASE_END();
}

bool UtilTest::testStrSplit()
{
	std::string string = "one;two;three";
	std::vector< std::string > strings = Arcemu::Shared::Util::StrSplit( string, ";" );
	TEST_EQ( 3, strings.size() );
	TEST_EQ( "one", strings[ 0 ] );
	TEST_EQ( "two", strings[ 1 ] );
	TEST_EQ( "three", strings[ 2 ] );

	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringEmpty()
{
	std::string string = "";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( string.size(), 0 );
	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringUpper()
{
	std::string string = "UPPER";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( "Upper", string );
	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringLower()
{
	std::string string = "lower";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( "Lower", string );
	TESTCASE_END();
}

bool UtilTest::testCapitalizeStringCapitalized()
{
	std::string string = "Capitalized";
	Arcemu::Shared::Util::CapitalizeString( string );
	TEST_EQ( "Capitalized", string );
	TESTCASE_END();
}

bool UtilTest::run()
{
	RUN_TESTS();
}

int main( int argc, char *argv[] )
{
	RUN_TESTCLASS( UtilTest );
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Magnus Jonsson & Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author 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 "libtorrent/file.hpp"
#include <sstream>

#include <windows.h>

#define DWORD_MAX 0xffffffffu

namespace
{
	// must be used to not leak memory in case something would throw
	class auto_LocalFree
	{
	public:
		auto_LocalFree(HLOCAL memory)
			: m_memory(memory)
		{
		}
		~auto_LocalFree()
		{
			if(m_memory)
				LocalFree(m_memory);
		}
	private:
		HLOCAL m_memory;
	};

	void throw_exception(const char* thrower)
	{
		char *buffer=0;
		int err = GetLastError();
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, err, 0, (LPSTR)&buffer, 0, 0);

		auto_LocalFree auto_free(buffer); // needed for exception safety
		std::stringstream s;
		s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");

		throw libtorrent::file_error(s.str());
	}
}

namespace libtorrent
{

	struct file::impl : boost::noncopyable
	{
		enum open_flags
		{
			read_flag = 1,
			write_flag = 2
		};

		enum seek_mode
		{
			seek_begin = FILE_BEGIN,
			seek_from_here = FILE_CURRENT,
			seek_end = FILE_END
		};

		impl()
		{
			m_file_handle = INVALID_HANDLE_VALUE;
		}

		void open(const char *file_name, open_flags flags)
		{
			assert(file_name);
			assert(flags & (read_flag | write_flag));

			DWORD access_mask = 0;
			if (flags & read_flag)
				access_mask |= GENERIC_READ;
			if (flags & write_flag)
				access_mask |= GENERIC_WRITE;

			assert(access_mask & (GENERIC_READ | GENERIC_WRITE));

			HANDLE new_handle = CreateFile(
				file_name
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & read_flag)?OPEN_EXISTING:OPEN_ALWAYS
				, FILE_ATTRIBUTE_NORMAL
				, 0);

			if (new_handle == INVALID_HANDLE_VALUE)
			{
				std::stringstream s;
				s << "couldn't open file '" << file_name << "'";
				throw file_error(s.str());
			}
			// will only close old file if the open succeeded
			close();
			m_file_handle = new_handle;
		}

		void close()
		{
			if (m_file_handle != INVALID_HANDLE_VALUE)
			{
				CloseHandle(m_file_handle);
				m_file_handle = INVALID_HANDLE_VALUE;
			}
		}

		~impl()
		{
			close();
		}

		size_type write(const char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);
			DWORD bytes_written = 0;
			if (num_bytes != 0)
			{
				if (FALSE == WriteFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_written
					, 0))
				{
					throw_exception("file::write");
				}
			}
			return bytes_written;
		}

		size_type read(char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);

			DWORD bytes_read = 0;
			if (num_bytes != 0)
			{
				if (FALSE == ReadFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_read
					, 0))
				{
					throw_exception("file::read");
				}
			}
			return bytes_read;
		}

		void seek(size_type pos, seek_mode from_where)
		{
			assert(pos >= 0 || from_where != seek_begin);
			assert(pos <= 0 || from_where != seek_end);
			LARGE_INTEGER offs;
			offs.QuadPart = pos;
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, from_where))
			{
					throw_exception("file::seek");
			}
		}

		size_type tell()
		{
			LARGE_INTEGER offs;
			offs.QuadPart = 0;

			// is there any other way to get offset?
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, FILE_CURRENT))
			{
				throw_exception("file::tell");
			}

			size_type pos=offs.QuadPart;
			assert(pos>=0);
			return pos;
		}
/*
		size_type size()
		{
			LARGE_INTEGER s;
			if (FALSE == GetFileSizeEx(m_file_handle, &s))
			{
				throw_exception("file::size");
			}

			size_type size = s.QuadPart;
			assert(size >= 0);
			return size;
		}
*/
	private:

		HANDLE m_file_handle;

	};
}

namespace libtorrent
{

	const file::seek_mode file::begin(file::impl::seek_begin);
	const file::seek_mode file::end(file::impl::seek_end);

	const file::open_mode file::in(file::impl::read_flag);
	const file::open_mode file::out(file::impl::write_flag);

	file::file()
		: m_impl(new libtorrent::file::impl())
	{
	}
	file::file(boost::filesystem::path const& p, open_mode m)
		: m_impl(new libtorrent::file::impl())
	{
		open(p,m);
	}

	file::~file()
	{
	}

	void file::open(boost::filesystem::path const& p, open_mode m)
	{
		m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buffer, size_type num_bytes)
	{
		return m_impl->write(buffer, num_bytes);
	}

	size_type file::read(char* buffer, size_type num_bytes)
	{
		return m_impl->read(buffer, num_bytes);
	}

	void file::seek(size_type pos, seek_mode m)
	{
		m_impl->seek(pos,impl::seek_mode(m.m_val));
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}
}
<commit_msg>support unicode compiling<commit_after>/*

Copyright (c) 2003, Magnus Jonsson & Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author 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 "libtorrent/file.hpp"
#include <sstream>

#include <windows.h>

#define DWORD_MAX 0xffffffffu

namespace
{
	// must be used to not leak memory in case something would throw
	class auto_LocalFree
	{
	public:
		auto_LocalFree(HLOCAL memory)
			: m_memory(memory)
		{
		}
		~auto_LocalFree()
		{
			if(m_memory)
				LocalFree(m_memory);
		}
	private:
		HLOCAL m_memory;
	};

	void throw_exception(const char* thrower)
	{
		char *buffer=0;
		int err = GetLastError();
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, err, 0, (LPWSTR)(LPCSTR)&buffer, 0, 0);

		auto_LocalFree auto_free(buffer); // needed for exception safety
		std::stringstream s;
		s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");

		throw libtorrent::file_error(s.str());
	}
}

namespace libtorrent
{

	struct file::impl : boost::noncopyable
	{
		enum open_flags
		{
			read_flag = 1,
			write_flag = 2
		};

		enum seek_mode
		{
			seek_begin = FILE_BEGIN,
			seek_from_here = FILE_CURRENT,
			seek_end = FILE_END
		};

		impl()
		{
			m_file_handle = INVALID_HANDLE_VALUE;
		}

		void open(const char *file_name, open_flags flags)
		{
			assert(file_name);
			assert(flags & (read_flag | write_flag));

			DWORD access_mask = 0;
			if (flags & read_flag)
				access_mask |= GENERIC_READ;
			if (flags & write_flag)
				access_mask |= GENERIC_WRITE;

			assert(access_mask & (GENERIC_READ | GENERIC_WRITE));

			HANDLE new_handle = CreateFile(
				(LPCWSTR)file_name
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & read_flag)?OPEN_EXISTING:OPEN_ALWAYS
				, FILE_ATTRIBUTE_NORMAL
				, 0);

			if (new_handle == INVALID_HANDLE_VALUE)
			{
				std::stringstream s;
				s << "couldn't open file '" << file_name << "'";
				throw file_error(s.str());
			}
			// will only close old file if the open succeeded
			close();
			m_file_handle = new_handle;
		}

		void close()
		{
			if (m_file_handle != INVALID_HANDLE_VALUE)
			{
				CloseHandle(m_file_handle);
				m_file_handle = INVALID_HANDLE_VALUE;
			}
		}

		~impl()
		{
			close();
		}

		size_type write(const char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);
			DWORD bytes_written = 0;
			if (num_bytes != 0)
			{
				if (FALSE == WriteFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_written
					, 0))
				{
					throw_exception("file::write");
				}
			}
			return bytes_written;
		}

		size_type read(char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);

			DWORD bytes_read = 0;
			if (num_bytes != 0)
			{
				if (FALSE == ReadFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_read
					, 0))
				{
					throw_exception("file::read");
				}
			}
			return bytes_read;
		}

		void seek(size_type pos, seek_mode from_where)
		{
			assert(pos >= 0 || from_where != seek_begin);
			assert(pos <= 0 || from_where != seek_end);
			LARGE_INTEGER offs;
			offs.QuadPart = pos;
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, from_where))
			{
					throw_exception("file::seek");
			}
		}

		size_type tell()
		{
			LARGE_INTEGER offs;
			offs.QuadPart = 0;

			// is there any other way to get offset?
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, FILE_CURRENT))
			{
				throw_exception("file::tell");
			}

			size_type pos=offs.QuadPart;
			assert(pos>=0);
			return pos;
		}
/*
		size_type size()
		{
			LARGE_INTEGER s;
			if (FALSE == GetFileSizeEx(m_file_handle, &s))
			{
				throw_exception("file::size");
			}

			size_type size = s.QuadPart;
			assert(size >= 0);
			return size;
		}
*/
	private:

		HANDLE m_file_handle;

	};
}

namespace libtorrent
{

	const file::seek_mode file::begin(file::impl::seek_begin);
	const file::seek_mode file::end(file::impl::seek_end);

	const file::open_mode file::in(file::impl::read_flag);
	const file::open_mode file::out(file::impl::write_flag);

	file::file()
		: m_impl(new libtorrent::file::impl())
	{
	}
	file::file(boost::filesystem::path const& p, open_mode m)
		: m_impl(new libtorrent::file::impl())
	{
		open(p,m);
	}

	file::~file()
	{
	}

	void file::open(boost::filesystem::path const& p, open_mode m)
	{
		m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buffer, size_type num_bytes)
	{
		return m_impl->write(buffer, num_bytes);
	}

	size_type file::read(char* buffer, size_type num_bytes)
	{
		return m_impl->read(buffer, num_bytes);
	}

	void file::seek(size_type pos, seek_mode m)
	{
		m_impl->seek(pos,impl::seek_mode(m.m_val));
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}
}
<|endoftext|>


<commit_before>#include <sorted.hpp>

#include <set>
#include <unordered_set>
#include <vector>
#include <array>
#include <string>
#include <utility>

#include "helpers.hpp"
#include "catch.hpp"

using iter::sorted;

using Vec = const std::vector<int>;

TEST_CASE("sorted: iterates through a vector in sorted order", "[sorted]" ){
    Vec ns = {4, 0, 5, 1, 6, 7, 9, 3, 2, 8};
    auto s = sorted(ns);
    Vec v(std::begin(s), std::end(s));
    Vec vc = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    REQUIRE( v == vc );
}

TEST_CASE("sorted: can modify elements through sorted", "[sorted]") {
    std::vector<int> ns(3, 9);
    for (auto&& n : sorted(ns)) {
        n = -1;
    }
    Vec vc(3, -1);
    REQUIRE( ns == vc );
}

TEST_CASE("sorted: can iterate over unordered container", "[sorted]") {
    std::unordered_set<int> ns = {1, 3, 2, 0, 4};
    auto s = sorted(ns);

    Vec v(std::begin(s), std::end(s));
    Vec vc = {0, 1, 2, 3, 4};
    REQUIRE( v == vc );
}

TEST_CASE("sorted: empty when iterable is empty", "[sorted]") {
    Vec ns{};
    auto s = sorted(ns);
    REQUIRE( std::begin(s) == std::end(s) );
}

namespace {
    bool int_greater_than(int lhs, int rhs) {
        return lhs > rhs;
    }

    struct IntGreaterThan {
        bool operator() (int lhs, int rhs) const {
            return lhs > rhs;
        }
    };
}

TEST_CASE("sorted: works with different functor types", "[sorted]") {
    Vec ns = {4, 1, 3, 2, 0};
    std::vector<int> v;
    SECTION("with function pointer") {
        auto s = sorted(ns, int_greater_than);
        v.insert(v.begin(), std::begin(s), std::end(s));
    }

    SECTION("with callable object") {
        auto s = sorted(ns, IntGreaterThan{});
        v.insert(v.begin(), std::begin(s), std::end(s));
    }

    SECTION("with lambda") {
        auto s = sorted(ns, [](int lhs, int rhs){return lhs > rhs;});
        v.insert(v.begin(), std::begin(s), std::end(s));
    }

    Vec vc = {4, 3, 2, 1, 0};
    REQUIRE( v == vc );
}
<commit_msg>tests sorted moves and binds correctly<commit_after>#include <sorted.hpp>

#include <set>
#include <unordered_set>
#include <vector>
#include <array>
#include <string>
#include <utility>

#include "helpers.hpp"
#include "catch.hpp"

using iter::sorted;

using Vec = const std::vector<int>;

TEST_CASE("sorted: iterates through a vector in sorted order", "[sorted]" ){
    Vec ns = {4, 0, 5, 1, 6, 7, 9, 3, 2, 8};
    auto s = sorted(ns);
    Vec v(std::begin(s), std::end(s));
    Vec vc = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    REQUIRE( v == vc );
}

TEST_CASE("sorted: can modify elements through sorted", "[sorted]") {
    std::vector<int> ns(3, 9);
    for (auto&& n : sorted(ns)) {
        n = -1;
    }
    Vec vc(3, -1);
    REQUIRE( ns == vc );
}

TEST_CASE("sorted: can iterate over unordered container", "[sorted]") {
    std::unordered_set<int> ns = {1, 3, 2, 0, 4};
    auto s = sorted(ns);

    Vec v(std::begin(s), std::end(s));
    Vec vc = {0, 1, 2, 3, 4};
    REQUIRE( v == vc );
}

TEST_CASE("sorted: empty when iterable is empty", "[sorted]") {
    Vec ns{};
    auto s = sorted(ns);
    REQUIRE( std::begin(s) == std::end(s) );
}

namespace {
    bool int_greater_than(int lhs, int rhs) {
        return lhs > rhs;
    }

    struct IntGreaterThan {
        bool operator() (int lhs, int rhs) const {
            return lhs > rhs;
        }
    };
}

TEST_CASE("sorted: works with different functor types", "[sorted]") {
    Vec ns = {4, 1, 3, 2, 0};
    std::vector<int> v;
    SECTION("with function pointer") {
        auto s = sorted(ns, int_greater_than);
        v.insert(v.begin(), std::begin(s), std::end(s));
    }

    SECTION("with callable object") {
        auto s = sorted(ns, IntGreaterThan{});
        v.insert(v.begin(), std::begin(s), std::end(s));
    }

    SECTION("with lambda") {
        auto s = sorted(ns, [](int lhs, int rhs){return lhs > rhs;});
        v.insert(v.begin(), std::begin(s), std::end(s));
    }

    Vec vc = {4, 3, 2, 1, 0};
    REQUIRE( v == vc );
}

namespace {
template <typename T>
class BasicIterableWithConstDeref {
    private:
        T *data;
        std::size_t size;
        bool was_moved_from_ = false;
    public:
        BasicIterableWithConstDeref(std::initializer_list<T> il)
            : data{new T[il.size()]},
            size{il.size()}
        {
            // would like to use enumerate, can't because it's for unit
            // testing enumerate
            std::size_t i = 0;
            for (auto&& e : il) {
                data[i] = e;
                ++i;
            }
        }

        BasicIterableWithConstDeref& operator=(BasicIterableWithConstDeref&&) = delete;
        BasicIterableWithConstDeref& operator=(const BasicIterableWithConstDeref&) = delete;
        BasicIterableWithConstDeref(const BasicIterableWithConstDeref&) = delete;

        BasicIterableWithConstDeref(BasicIterableWithConstDeref&& other)
            : data{other.data},
            size{other.size}
        {
            other.data = nullptr;
            other.was_moved_from_ = true;
        }

        bool was_moved_from() const {
            return this->was_moved_from_;
        }

        ~BasicIterableWithConstDeref() {
            delete [] this->data;
        }

        class Iterator {
            private:
                T *p;
            public:
                Iterator(T *b) : p{b} { }
                bool operator!=(const Iterator& other) const {
                    return this->p != other.p;
                }

                Iterator& operator++() {
                    ++this->p;
                    return *this;
                }

                T& operator*() {
                    return *this->p;
                }

                const T& operator*() const {
                    return *this->p;
                }
        };

        Iterator begin() {
            return {this->data};
        }

        Iterator end() {
            return {this->data + this->size};
        }
};
}

TEST_CASE("sorted: moves rvalues and binds to lvalues", "[sorted]") {
    BasicIterableWithConstDeref<int> bi{1, 2};
    sorted(bi);
    REQUIRE_FALSE( bi.was_moved_from() );

    sorted(std::move(bi));
    REQUIRE( bi.was_moved_from() );
}
<|endoftext|>


<commit_before>#include <string>

#include "acmacs-base/argv.hh"
#include "acmacs-base/enumerate.hh"
#include "acmacs-chart-2/chart.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "hidb-5/hidb.hh"

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

using namespace acmacs::argv;

struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    argument<str> chart{*this, mandatory};
};

int main(int argc, const char* argv[])
{
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        auto chart = acmacs::chart::import_from_file(opt.chart, acmacs::chart::Verify::None, report_time::no);
        const auto& hidb = hidb::get(chart->info()->virus_type(acmacs::chart::Info::Compute::Yes), report_time::no);
        auto sera = chart->sera();
        const auto hidb_sera = hidb.sera()->find(*sera);
        auto hidb_tables = hidb.tables();
        for (auto [sr_no, serum] : acmacs::enumerate(*sera)) {
            std::cout << std::setw(3) << std::right << sr_no << ' ' << serum->full_name_with_passage() << '\n';
            if (auto hidb_serum = hidb_sera[sr_no]; hidb_serum)
                std::cout << "  tables:" << hidb_serum->number_of_tables() << '\n';
            else
                std::cerr << "WARNING: not in hidb\n";
        }
    }
    catch (std::exception& err) {
        std::cerr << err.what() << std::endl;
        exit_code = 1;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>whocc-sera-of-chart<commit_after>#include <string>

#include "acmacs-base/argv.hh"
#include "acmacs-base/enumerate.hh"
#include "acmacs-chart-2/chart.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "hidb-5/hidb.hh"

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

using namespace acmacs::argv;

struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    argument<str> chart{*this, mandatory};
};

int main(int argc, const char* argv[])
{
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        auto chart = acmacs::chart::import_from_file(opt.chart, acmacs::chart::Verify::None, report_time::no);
        const auto& hidb = hidb::get(chart->info()->virus_type(acmacs::chart::Info::Compute::Yes), report_time::no);
        auto sera = chart->sera();
        const auto hidb_sera = hidb.sera()->find(*sera);
        auto hidb_tables = hidb.tables();
        for (auto [sr_no, serum] : acmacs::enumerate(*sera)) {
            std::cout << std::setw(3) << std::right << sr_no << ' ' << serum->full_name_with_passage() << '\n';
            if (auto hidb_serum = hidb_sera[sr_no]; hidb_serum) {
                const auto stat = hidb_tables->stat(hidb_serum->tables());
                for (const auto& entry : stat)
                    std::cout << "  " << entry.title() << "  tables:" << std::setw(3) << std::right << entry.number << " newest: " << std::setw(30) << std::left << entry.most_recent->name() << " oldest: " << entry.oldest->name() << '\n';
            }
            else
                std::cerr << "WARNING: not in hidb\n";
        }
    }
    catch (std::exception& err) {
        std::cerr << err.what() << std::endl;
        exit_code = 1;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>