<commit_before>#include "ArraySort.h"
namespace NP_ARRAYSORT
{
	//-------------------------------------------------------------------------
	//    function:		strangeSort(Comparable ** array, int fromIndex, int toIndex)
	//    description:	Uses quicksort if it's more than 4 items and insertion sort
	//					otherwise.
	//
	//    Input:
	//
	//    Called By:	strangesort
	//
	//    Parameters:	Comparable ** array, int fromIndex, int toIndex
	//    Returns:      int
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	//			4/28/17	NP	Appended to version 1.0
	// ------------------------------------------------------------------------
	void strangeSort(Comparable ** array, int fromIndex, int toIndex)
	{
		if (fromIndex + 4 < toIndex) {
			int position = partition(array, fromIndex, toIndex);
			strangeSort(array, fromIndex, position - 1);
			strangeSort(array, position + 1, toIndex);
		} else if (fromIndex < toIndex) {
			insertionSort(array, fromIndex, toIndex);
		}
	}

 // ------------------------------------------------------------------------
	//    function:		partition(Comparable ** array, int fromIndex, int toIndex)
	//    description:	partitions and partially sorts things for quicksort.
	//
	//    Input:
	//
	//    Called By:	strangesort
	//
	//    Parameters:	Comparable ** array, int fromIndex, int toIndex
	//    Returns:      int
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	//			4/28/17	NP	Appended to version 1.0
	// ------------------------------------------------------------------------
	int partition(Comparable ** array, int fromIndex, int toIndex)
	{
		int pivotIndex = (fromIndex + toIndex) / 2;
		SortFirstMiddleLast(array, fromIndex, pivotIndex, toIndex);

		Comparable * pivot = array[pivotIndex];
		indexSwap(array, pivotIndex, toIndex - 1);

		int frontIndex = fromIndex + 1;
		int backIndex = pivotIndex - 1;

		while (frontIndex < backIndex) {
			while (frontIndex < backIndex && *pivot >= *array[frontIndex])
				frontIndex++;

			while (frontIndex < backIndex && *array[backIndex] >= *pivot)
				backIndex--;

			indexSwap(array, frontIndex++, pivotIndex--);
		}
		indexSwap(array, fromIndex, frontIndex);
		return frontIndex;

		// Perfectly good quick sort
		/*
		Comparable * mid = array[toIndex];
		int small = fromIndex - 1;
		for (int index = fromIndex; index < toIndex; index++) {
			if (*array[index] <= *mid) {
				small++;
				swap(array, index, small);
			}
		}
		swap(array, toIndex, small + 1);
		return small + 1;
		*/
	}

 // ------------------------------------------------------------------------
	//    function:		SortFirstMiddleLast
	//    description:	Sort the three items
	//
	//    Called By:	all sorting algs
	//
	//    Parameters:	Comparable ** array, int loIndex, int midIndex,
	//					int hiIndex
	//
	//    Returns:          void
	//
	//    History Log:
	//			4/27/17  NP  completed version 1.0
	// ------------------------------------------------------------------------
	void SortFirstMiddleLast(Comparable ** array,
							int loIndex, int midIndex,
							int hiIndex
	)
	{
		Comparable * low = array[loIndex];
		Comparable * mid = array[midIndex];
		Comparable * hi = array[hiIndex];
		while ((low > mid) || (mid > hi)) {
			if (low > mid)
				indexSwap(array, loIndex, midIndex);
			if (mid > hi)
				indexSwap(array, midIndex, hiIndex);
			if (low > hi)
				indexSwap(array, loIndex, hiIndex);
			low = array[loIndex];
			mid = array[midIndex];
			hi = array[hiIndex];
		}
	}

 // ------------------------------------------------------------------------
	//    function:		swap
	//    description:	swaps two items in an array
	//
	//    Input:		Comparable ** array, int index1, int index2
	//
	//    Called By:	all sorting algs
	//
	//    Parameters:	Comparable ** array, int index1, int index2
	//
	//    Returns:          void
	//
	//    History Log:
	//			4/27/17  NP  completed version 1.0
	// ------------------------------------------------------------------------
	void indexSwap(Comparable ** array, int index1, int index2) {
		Comparable * tmp = array[index1];
		array[index1] = array[index2];
		array[index2] = tmp;
	}

 // ------------------------------------------------------------------------
	//    function:		insertionSort(Comparable ** array, int fromIndex,
	//					int toIndex)
	//    description:	sorts a list of comparables using
	//					insertion sort algorithm
	//
	//    Input:
	//
	//    Called By:	strangesort
	//
	//    Parameters:	Comparable ** array, int fromIndex, int toInde
	//    Returns:      void
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	//			4/28/17	NP	Appended to version 1.0
	// ------------------------------------------------------------------------
	void insertionSort(Comparable ** array, int fromIndex, int toIndex)
	{
		if (fromIndex < 1)
			fromIndex = 1;

		for (int outerIndex = fromIndex; outerIndex < toIndex; outerIndex++) {
			int innerIndex = outerIndex - 1;
			Comparable * temp = array[outerIndex];

			while (innerIndex >= 0 && *temp < *array[innerIndex]) {
				array[innerIndex + 1] = array[innerIndex];
				innerIndex--;
			}

			array[innerIndex + 1] = temp;
		}
	}

 // ------------------------------------------------------------------------
	//    function:		safeRead(istream& sin, Comparable* d, const char* re)
	//    description:	safely reads in a DateTime (d) from sin.
	//				Re-prompts and re-enters if input is invalid
	//
	//    Input:		Comparable* d from sin
	//
	//    Called By:	main
	//
	//    Parameters:	istream& sin  -- the input stream
	//			Comparable* d -- pointer to the object input
	//			const char* prompt  -- prompt, if necessary
	//
	//    Returns:          void
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	// ------------------------------------------------------------------------
	void safeRead(istream& sin, Comparable* d, const char* prompt)
	{
		const int BUFFERSIZE = 256;
		d->input(sin);
		while (!sin)
		{	// read in number--enter loop if fail
			sin.clear();		// clear fail
			sin.ignore(BUFFERSIZE, '\n');	// read past newline
			cout << prompt;  // re-prompt
			d->input(sin);
		}
		// read past newline once input succeeds
		sin.ignore(BUFFERSIZE, '\n');
	}

 // ------------------------------------------------------------------------
	///    function:	void printArray(ostream & sout, Comparable **a, int size)
	///    description:	can print out an array of DateTime *
	//
	//    Output:		Comparable* d sout
	//
	//    Called By:	main
	//
	//    Parameters:	ostream& sout  -- the output stream
	//			Comparable** a -- array of pointers to the objects
	//			int size  -- number of elements in the array
	//
	//    Returns:          void
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	// ------------------------------------------------------------------------
	void printArray(ostream & sout, Comparable **array, int len)
	{
		for (int i = 0; i < len; i++)
		{
			array[i]->print(sout);
			if (i + 1 < len)
				sout << ",\n";
		}

		sout << endl;
	}
}

<commit_msg>test pure quicksort<commit_after>#include "ArraySort.h"
namespace NP_ARRAYSORT
{
	//-------------------------------------------------------------------------
	//    function:		strangeSort(Comparable ** array, int fromIndex, int toIndex)
	//    description:	Uses quicksort if it's more than 4 items and insertion sort
	//					otherwise.
	//
	//    Input:
	//
	//    Called By:	strangesort
	//
	//    Parameters:	Comparable ** array, int fromIndex, int toIndex
	//    Returns:      int
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	//			4/28/17	NP	Appended to version 1.0
	// ------------------------------------------------------------------------
	void strangeSort(Comparable ** arr, int fromIndex, int toIndex) {
		if (fromIndex < toIndex) {
			// SortFirstMiddleLast(arr, fromIndex, (fromIndex + toIndex) / 2, toIndex);
			int position = partition(arr, fromIndex, toIndex);
			strangeSort(arr, fromIndex, position - 1);
			strangeSort(arr, position + 1, toIndex);
		}
		// else if (fromIndex < toIndex) {
			// insertionSort(arr, fromIndex, toIndex);
		//}
	}

 // ------------------------------------------------------------------------
	//    function:		partition(Comparable ** array, int fromIndex, int toIndex)
	//    description:	partitions and partially sorts things for quicksort.
	//
	//    Input:
	//
	//    Called By:	strangesort
	//
	//    Parameters:	Comparable ** array, int fromIndex, int toIndex
	//    Returns:      int
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	//			4/28/17	NP	Appended to version 1.0
	// ------------------------------------------------------------------------
	int partition(Comparable ** array, int fromIndex, int toIndex) {

		int smallIndex = fromIndex - 1;

		Comparable * pivot = array[toIndex];

		for (int k = fromIndex; k < toIndex; k++) {
			if (*array[k] <= *pivot) {
				smallIndex++;
				indexSwap(array, k, smallIndex);
			}
		}

		indexSwap(array, toIndex, smallIndex + 1);
		return smallIndex + 1;
	}

 // ------------------------------------------------------------------------
	//    function:		SortFirstMiddleLast
	//    description:	Sort the three items
	//
	//    Called By:	all sorting algs
	//
	//    Parameters:	Comparable ** array, int loIndex, int midIndex,
	//					int hiIndex
	//
	//    Returns:          void
	//
	//    History Log:
	//			4/27/17  NP  completed version 1.0
	// ------------------------------------------------------------------------
	void SortFirstMiddleLast(
		Comparable ** array,
		int loIndex, int midIndex,
		int hiIndex
	)
	{
		Comparable * low = array[loIndex];
		Comparable * mid = array[midIndex];
		Comparable * hi = array[hiIndex];

		while ((*low > *mid) || (*mid > *hi)) {
			if (*low > *mid)
				indexSwap(array, loIndex, midIndex);
			else if (*mid > *hi)
				indexSwap(array, midIndex, hiIndex);
			else if (*low > *hi)
				indexSwap(array, loIndex, hiIndex);
			low = array[loIndex];
			mid = array[midIndex];
			hi = array[hiIndex];
		}
	}

 // ------------------------------------------------------------------------
	//    function:		swap
	//    description:	swaps two items in an array
	//
	//    Input:		Comparable ** array, int index1, int index2
	//
	//    Called By:	all sorting algs
	//
	//    Parameters:	Comparable ** array, int index1, int index2
	//
	//    Returns:          void
	//
	//    History Log:
	//			4/27/17  NP  completed version 1.0
	// ------------------------------------------------------------------------
	void indexSwap(Comparable ** array, int index1, int index2) {
		Comparable * tmp = array[index1];
		array[index1] = array[index2];
		array[index2] = tmp;
	}

 // ------------------------------------------------------------------------
	//    function:		insertionSort(Comparable ** array, int fromIndex,
	//					int toIndex)
	//    description:	sorts a list of comparables using
	//					insertion sort algorithm
	//
	//    Input:
	//
	//    Called By:	strangesort
	//
	//    Parameters:	Comparable ** array, int fromIndex, int toInde
	//    Returns:      void
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	//			4/28/17	NP	Appended to version 1.0
	// ------------------------------------------------------------------------
	void insertionSort(Comparable ** array, int fromIndex, int toIndex)
	{
		for (int cursor = fromIndex; cursor < toIndex; cursor++) {
			int secondCursor = cursor - 1;
			Comparable * temp = array[cursor];

			while (secondCursor >= 0 && *temp < *array[secondCursor]) {
				*array[secondCursor + 1] = *array[secondCursor];
				secondCursor--;
			}

			*array[secondCursor + 1] = *temp;
		}
	}

 // ------------------------------------------------------------------------
	//    function:		safeRead(istream& sin, Comparable* d, const char* re)
	//    description:	safely reads in a DateTime (d) from sin.
	//				Re-prompts and re-enters if input is invalid
	//
	//    Input:		Comparable* d from sin
	//
	//    Called By:	main
	//
	//    Parameters:	istream& sin  -- the input stream
	//			Comparable* d -- pointer to the object input
	//			const char* prompt  -- prompt, if necessary
	//
	//    Returns:          void
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	// ------------------------------------------------------------------------
	void safeRead(istream& sin, Comparable* d, const char* prompt)
	{
		const int BUFFERSIZE = 256;
		d->input(sin);
		while (!sin)
		{	// read in number--enter loop if fail
			sin.clear();		// clear fail
			sin.ignore(BUFFERSIZE, '\n');	// read past newline
			cout << prompt;  // re-prompt
			d->input(sin);
		}
		// read past newline once input succeeds
		sin.ignore(BUFFERSIZE, '\n');
	}

 // ------------------------------------------------------------------------
	///    function:	void printArray(ostream & sout, Comparable **a, int size)
	///    description:	can print out an array of DateTime *
	//
	//    Output:		Comparable* d sout
	//
	//    Called By:	main
	//
	//    Parameters:	ostream& sout  -- the output stream
	//			Comparable** a -- array of pointers to the objects
	//			int size  -- number of elements in the array
	//
	//    Returns:          void
	//
	//    History Log:
	//			2/9/08  PB  completed version 1.0
	// ------------------------------------------------------------------------
	void printArray(ostream & sout, Comparable **array, int len)
	{
		for (int i = 0; i < len; i++)
		{
			array[i]->print(sout);
			if (i + 1 < len)
				sout << ",\n";
		}

		sout << endl;
	}
}

<|endoftext|>


<commit_before>#include "auth/http-auth.h"
#include <utility>

HttpAuth::HttpAuth(QString type, QString url, QList<AuthField*> fields, QString cookie, QString redirectUrl, QString csrfUrl, QStringList csrfFields)
	: FieldAuth(std::move(type), std::move(fields)), m_url(std::move(url)), m_cookie(std::move(cookie)), m_redirectUrl(std::move(redirectUrl)), m_csrfUrl(std::move(csrfUrl)), m_csrfFields(std::move(csrfFields))
{}

QString HttpAuth::url() const
{
	return m_url;
}

QString HttpAuth::cookie() const
{
	return m_cookie;
}

QString HttpAuth::redirectUrl() const
{
	return m_redirectUrl;
}

QString HttpAuth::csrfUrl() const
{
	return m_csrfUrl;
}

QStringList HttpAuth::csrfFields() const
{
	return m_csrfFields;
}

<commit_msg>Fix linting issues<commit_after>#include "auth/http-auth.h"
#include <utility>

HttpAuth::HttpAuth(QString type, QString url, QList<AuthField*> fields, QString cookie, QString redirectUrl, QString csrfUrl, QStringList csrfFields)
	: FieldAuth(std::move(type), std::move(fields)), m_url(std::move(url)), m_cookie(std::move(cookie)), m_redirectUrl(std::move(redirectUrl)), m_csrfUrl(std::move(csrfUrl)), m_csrfFields(std::move(csrfFields))
{}

QString HttpAuth::url() const
{
	return m_url;
}

QString HttpAuth::cookie() const
{
	return m_cookie;
}

QString HttpAuth::redirectUrl() const
{
	return m_redirectUrl;
}

QString HttpAuth::csrfUrl() const
{
	return m_csrfUrl;
}

QStringList HttpAuth::csrfFields() const
{
	return m_csrfFields;
}
<|endoftext|>


<commit_before>#include "response.h"
#include "config.h"
#include "string_stream.h"

const std::string rs::httpserver::Response::keepAliveHeaderValue_ = std::string("timeout=") + boost::lexical_cast<std::string>(Config::KeepAliveTimeoutTotal);

void rs::httpserver::Response::Send(const std::string& data) {
    StringStream stream(data);
    setContentLength(data.length()).Send(stream);
}

void rs::httpserver::Response::Send(Stream& stream) {
    std::stringstream headers;
    SerializeHeaders(headers);

    socket_->Send(headers.str());

    if (!request_->IsHead()) {
        Stream::byte buffer[2048];

        int bytesRead = 0;
        while ((bytesRead = stream.Read(buffer, 0, sizeof(buffer))) > 0) {
            responseStream_.Write(buffer, 0, bytesRead);
        }
    }

    responseStream_.Flush();
}

void rs::httpserver::Response::SerializeHeaders(std::stringstream& sout) {
    const auto isHttp10 = request_->IsHttp10();

    if (isHttp10) {
        version_ = Headers::Http10;
        headers_[Headers::Connection] = "close";
        headers_.erase(Headers::KeepAlive);
        headers_.erase(Headers::TransferEncoding);
    } else if (request_->IsKeepAlive()) {
        headers_[Headers::Connection] = "keep-alive";
        headers_[Headers::KeepAlive] = keepAliveHeaderValue_;
    } else {
        headers_[Headers::Connection] = "close";
        headers_.erase(Headers::KeepAlive);
    }

    // TODO: enable when chunked encoding is ready
    /*if (!isHttp10 && !HasContentLength()) {
        headers_[Headers::TransferEncoding] = "chunked";
    }*/

    if (statusCode_ == 200) {
        statusDescription_ = "OK";
    }

    sout << version_ << " " << statusCode_;
    if (statusDescription_.length() > 0) {
        sout << " " << statusDescription_;
    }
    sout << "\r\n";

    for (auto i : headers_) {
        sout << i.first << ": " << i.second << "\r\n";
    }

    sout << "\r\n";
}<commit_msg>Use the correct keep-alive timeout in the response<commit_after>#include "response.h"
#include "config.h"
#include "string_stream.h"

const std::string rs::httpserver::Response::keepAliveHeaderValue_ = std::string("timeout=") + boost::lexical_cast<std::string>(Config::KeepAliveTimeout);

void rs::httpserver::Response::Send(const std::string& data) {
    StringStream stream(data);
    setContentLength(data.length()).Send(stream);
}

void rs::httpserver::Response::Send(Stream& stream) {
    std::stringstream headers;
    SerializeHeaders(headers);

    socket_->Send(headers.str());

    if (!request_->IsHead()) {
        Stream::byte buffer[2048];

        int bytesRead = 0;
        while ((bytesRead = stream.Read(buffer, 0, sizeof(buffer))) > 0) {
            responseStream_.Write(buffer, 0, bytesRead);
        }
    }

    responseStream_.Flush();
}

void rs::httpserver::Response::SerializeHeaders(std::stringstream& sout) {
    const auto isHttp10 = request_->IsHttp10();

    if (isHttp10) {
        version_ = Headers::Http10;
        headers_[Headers::Connection] = "close";
        headers_.erase(Headers::KeepAlive);
        headers_.erase(Headers::TransferEncoding);
    } else if (request_->IsKeepAlive()) {
        headers_[Headers::Connection] = "keep-alive";
        headers_[Headers::KeepAlive] = keepAliveHeaderValue_;
    } else {
        headers_[Headers::Connection] = "close";
        headers_.erase(Headers::KeepAlive);
    }

    // TODO: enable when chunked encoding is ready
    /*if (!isHttp10 && !HasContentLength()) {
        headers_[Headers::TransferEncoding] = "chunked";
    }*/

    if (statusCode_ == 200) {
        statusDescription_ = "OK";
    }

    sout << version_ << " " << statusCode_;
    if (statusDescription_.length() > 0) {
        sout << " " << statusDescription_;
    }
    sout << "\r\n";

    for (auto i : headers_) {
        sout << i.first << ": " << i.second << "\r\n";
    }

    sout << "\r\n";
}<|endoftext|>


<commit_before>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "pathchooser.h"

#include "basevalidatinglineedit.h"
#include "qtcassert.h"

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QSettings>

#include <QtGui/QDesktopServices>
#include <QtGui/QFileDialog>
#include <QtGui/QHBoxLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QToolButton>

namespace Core {
namespace Utils {

#ifdef Q_OS_OSX
/*static*/ const char * const PathChooser::browseButtonLabel = "Choose...";
#else
/*static*/ const char * const PathChooser::browseButtonLabel = "Browse...";
#endif

// ------------------ PathValidatingLineEdit
class PathValidatingLineEdit : public BaseValidatingLineEdit
{
public:
    explicit PathValidatingLineEdit(PathChooser *chooser, QWidget *parent = 0);

protected:
    virtual bool validate(const QString &value, QString *errorMessage) const;

private:
    PathChooser *m_chooser;
};

PathValidatingLineEdit::PathValidatingLineEdit(PathChooser *chooser, QWidget *parent) :
    BaseValidatingLineEdit(parent),
    m_chooser(chooser)
{
    QTC_ASSERT(chooser, return);
}

bool PathValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
    return m_chooser->validatePath(value, errorMessage);
}

// ------------------ PathChooserPrivate
struct PathChooserPrivate
{
    PathChooserPrivate(PathChooser *chooser);

    PathValidatingLineEdit *m_lineEdit;
    PathChooser::Kind m_acceptingKind;
    QString m_dialogTitleOverride;
};

PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) :
    m_lineEdit(new PathValidatingLineEdit(chooser)),
    m_acceptingKind(PathChooser::Directory)
{
}

PathChooser::PathChooser(QWidget *parent) :
    QWidget(parent),
    m_d(new PathChooserPrivate(this))
{
    QHBoxLayout *hLayout = new QHBoxLayout;
    hLayout->setContentsMargins(0, 0, 0, 0);

    connect(m_d->m_lineEdit, SIGNAL(validReturnPressed()), this, SIGNAL(returnPressed()));
    connect(m_d->m_lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
    connect(m_d->m_lineEdit, SIGNAL(validChanged()), this, SIGNAL(validChanged()));

    m_d->m_lineEdit->setMinimumWidth(260);
    hLayout->addWidget(m_d->m_lineEdit);
    hLayout->setSizeConstraint(QLayout::SetMinimumSize);

    QToolButton *browseButton = new QToolButton;
    browseButton->setText(tr(browseButtonLabel));
    connect(browseButton, SIGNAL(clicked()), this, SLOT(slotBrowse()));

    hLayout->addWidget(browseButton);
    setLayout(hLayout);
    setFocusProxy(m_d->m_lineEdit);
}

PathChooser::~PathChooser()
{
    delete m_d;
}

QString PathChooser::path() const
{
    return m_d->m_lineEdit->text();
}

void PathChooser::setPath(const QString &path)
{
    const QString defaultPath = path.isEmpty() ? homePath() : path;
    m_d->m_lineEdit->setText(QDir::toNativeSeparators(defaultPath));
}

void PathChooser::slotBrowse()
{
    QString predefined = path();
    if (!predefined.isEmpty() && !QFileInfo(predefined).isDir())
        predefined.clear();

    // Prompt for a file/dir
    QString dialogTitle;
    QString newPath;
    switch (m_d->m_acceptingKind) {
    case PathChooser::Directory:
        newPath = QFileDialog::getExistingDirectory(this,
                makeDialogTitle(tr("Choose a directory")), predefined);
        break;

    case PathChooser::File: // fall through
    case PathChooser::Command:
        newPath = QFileDialog::getOpenFileName(this,
                makeDialogTitle(tr("Choose a file")), predefined);
        break;

    default:
        ;
    }

    // TODO make cross-platform
    // Delete trailing slashes unless it is "/", only
    if (!newPath.isEmpty()) {
        if (newPath.size() > 1 && newPath.endsWith(QDir::separator()))
            newPath.truncate(newPath.size() - 1);
        setPath(newPath);
    }
}

bool PathChooser::isValid() const
{
    return m_d->m_lineEdit->isValid();
}

QString PathChooser::errorMessage() const
{
    return m_d->m_lineEdit->errorMessage();
}

bool PathChooser::validatePath(const QString &path, QString *errorMessage)
{
    if (path.isEmpty()) {
        if (errorMessage)
            *errorMessage = tr("The path must not be empty.");
        return false;
    }

    const QFileInfo fi(path);
    const bool isDir = fi.isDir();

    // Check if existing
    switch (m_d->m_acceptingKind) {
    case PathChooser::Directory: // fall through
    case PathChooser::File:
        if (!fi.exists()) {
            if (errorMessage)
                *errorMessage = tr("The path '%1' does not exist.").arg(path);
            return false;
        }
        break;

    case PathChooser::Command: // fall through
    default:
        ;
    }

    // Check expected kind
    switch (m_d->m_acceptingKind) {
    case PathChooser::Directory:
        if (!isDir) {
            if (errorMessage)
                *errorMessage = tr("The path '%1' is not a directory.").arg(path);
            return false;
        }
        break;

    case PathChooser::File:
        if (isDir) {
            if (errorMessage)
                *errorMessage = tr("The path '%1' is not a file.").arg(path);
            return false;
        }
        break;

    case PathChooser::Command:
        // TODO do proper command validation
        // i.e. search $PATH for a matching file
        break;

    default:
        ;
    }

    return true;
}

QString PathChooser::label()
{
    return tr("Path:");
}

QString PathChooser::homePath()
{
#ifdef Q_OS_WIN
    // Return 'users/<name>/Documents' on Windows, since Windows explorer
    // does not let people actually display the contents of their home
    // directory. Alternatively, create a QtCreator-specific directory?
    return QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
#else
    return QDir::homePath();
#endif
}

void PathChooser::setExpectedKind(Kind expected)
{
    m_d->m_acceptingKind = expected;
}

void PathChooser::setPromptDialogTitle(const QString &title)
{
    m_d->m_dialogTitleOverride = title;
}

QString PathChooser::makeDialogTitle(const QString &title)
{
    if (m_d->m_dialogTitleOverride.isNull())
        return title;
    else
        return m_d->m_dialogTitleOverride;
}

} // namespace Utils
} // namespace Core
<commit_msg>Fixes:    - Choose... buttons are push buttons on mac<commit_after>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "pathchooser.h"

#include "basevalidatinglineedit.h"
#include "qtcassert.h"

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QSettings>

#include <QtGui/QDesktopServices>
#include <QtGui/QFileDialog>
#include <QtGui/QHBoxLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QToolButton>
#include <QtGui/QPushButton>

namespace Core {
namespace Utils {

#ifdef Q_OS_MAC
/*static*/ const char * const PathChooser::browseButtonLabel = "Choose...";
#else
/*static*/ const char * const PathChooser::browseButtonLabel = "Browse...";
#endif

// ------------------ PathValidatingLineEdit
class PathValidatingLineEdit : public BaseValidatingLineEdit
{
public:
    explicit PathValidatingLineEdit(PathChooser *chooser, QWidget *parent = 0);

protected:
    virtual bool validate(const QString &value, QString *errorMessage) const;

private:
    PathChooser *m_chooser;
};

PathValidatingLineEdit::PathValidatingLineEdit(PathChooser *chooser, QWidget *parent) :
    BaseValidatingLineEdit(parent),
    m_chooser(chooser)
{
    QTC_ASSERT(chooser, return);
}

bool PathValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
    return m_chooser->validatePath(value, errorMessage);
}

// ------------------ PathChooserPrivate
struct PathChooserPrivate
{
    PathChooserPrivate(PathChooser *chooser);

    PathValidatingLineEdit *m_lineEdit;
    PathChooser::Kind m_acceptingKind;
    QString m_dialogTitleOverride;
};

PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) :
    m_lineEdit(new PathValidatingLineEdit(chooser)),
    m_acceptingKind(PathChooser::Directory)
{
}

PathChooser::PathChooser(QWidget *parent) :
    QWidget(parent),
    m_d(new PathChooserPrivate(this))
{
    QHBoxLayout *hLayout = new QHBoxLayout;
    hLayout->setContentsMargins(0, 0, 0, 0);

    connect(m_d->m_lineEdit, SIGNAL(validReturnPressed()), this, SIGNAL(returnPressed()));
    connect(m_d->m_lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
    connect(m_d->m_lineEdit, SIGNAL(validChanged()), this, SIGNAL(validChanged()));

    m_d->m_lineEdit->setMinimumWidth(260);
    hLayout->addWidget(m_d->m_lineEdit);
    hLayout->setSizeConstraint(QLayout::SetMinimumSize);

#ifdef Q_OS_MAC
    QPushButton *browseButton = new QPushButton;
#else
    QToolButton *browseButton = new QToolButton;
#endif
    browseButton->setText(tr(browseButtonLabel));
    connect(browseButton, SIGNAL(clicked()), this, SLOT(slotBrowse()));

    hLayout->addWidget(browseButton);
    setLayout(hLayout);
    setFocusProxy(m_d->m_lineEdit);
}

PathChooser::~PathChooser()
{
    delete m_d;
}

QString PathChooser::path() const
{
    return m_d->m_lineEdit->text();
}

void PathChooser::setPath(const QString &path)
{
    const QString defaultPath = path.isEmpty() ? homePath() : path;
    m_d->m_lineEdit->setText(QDir::toNativeSeparators(defaultPath));
}

void PathChooser::slotBrowse()
{
    QString predefined = path();
    if (!predefined.isEmpty() && !QFileInfo(predefined).isDir())
        predefined.clear();

    // Prompt for a file/dir
    QString dialogTitle;
    QString newPath;
    switch (m_d->m_acceptingKind) {
    case PathChooser::Directory:
        newPath = QFileDialog::getExistingDirectory(this,
                makeDialogTitle(tr("Choose a directory")), predefined);
        break;

    case PathChooser::File: // fall through
    case PathChooser::Command:
        newPath = QFileDialog::getOpenFileName(this,
                makeDialogTitle(tr("Choose a file")), predefined);
        break;

    default:
        ;
    }

    // TODO make cross-platform
    // Delete trailing slashes unless it is "/", only
    if (!newPath.isEmpty()) {
        if (newPath.size() > 1 && newPath.endsWith(QDir::separator()))
            newPath.truncate(newPath.size() - 1);
        setPath(newPath);
    }
}

bool PathChooser::isValid() const
{
    return m_d->m_lineEdit->isValid();
}

QString PathChooser::errorMessage() const
{
    return m_d->m_lineEdit->errorMessage();
}

bool PathChooser::validatePath(const QString &path, QString *errorMessage)
{
    if (path.isEmpty()) {
        if (errorMessage)
            *errorMessage = tr("The path must not be empty.");
        return false;
    }

    const QFileInfo fi(path);
    const bool isDir = fi.isDir();

    // Check if existing
    switch (m_d->m_acceptingKind) {
    case PathChooser::Directory: // fall through
    case PathChooser::File:
        if (!fi.exists()) {
            if (errorMessage)
                *errorMessage = tr("The path '%1' does not exist.").arg(path);
            return false;
        }
        break;

    case PathChooser::Command: // fall through
    default:
        ;
    }

    // Check expected kind
    switch (m_d->m_acceptingKind) {
    case PathChooser::Directory:
        if (!isDir) {
            if (errorMessage)
                *errorMessage = tr("The path '%1' is not a directory.").arg(path);
            return false;
        }
        break;

    case PathChooser::File:
        if (isDir) {
            if (errorMessage)
                *errorMessage = tr("The path '%1' is not a file.").arg(path);
            return false;
        }
        break;

    case PathChooser::Command:
        // TODO do proper command validation
        // i.e. search $PATH for a matching file
        break;

    default:
        ;
    }

    return true;
}

QString PathChooser::label()
{
    return tr("Path:");
}

QString PathChooser::homePath()
{
#ifdef Q_OS_WIN
    // Return 'users/<name>/Documents' on Windows, since Windows explorer
    // does not let people actually display the contents of their home
    // directory. Alternatively, create a QtCreator-specific directory?
    return QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
#else
    return QDir::homePath();
#endif
}

void PathChooser::setExpectedKind(Kind expected)
{
    m_d->m_acceptingKind = expected;
}

void PathChooser::setPromptDialogTitle(const QString &title)
{
    m_d->m_dialogTitleOverride = title;
}

QString PathChooser::makeDialogTitle(const QString &title)
{
    if (m_d->m_dialogTitleOverride.isNull())
        return title;
    else
        return m_d->m_dialogTitleOverride;
}

} // namespace Utils
} // namespace Core
<|endoftext|>


<commit_before>/************************************************************************************
 *   Copyright (C) 2014-2015 by Savoir-Faire Linux                                       *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
 *                                                                                *
 *   This library is free software; you can redistribute it and/or                  *
 *   modify it under the terms of the GNU Lesser General Public                     *
 *   License as published by the Free Software Foundation; either                   *
 *   version 2.1 of the License, or (at your option) any later version.             *
 *                                                                                *
 *   This library is distributed in the hope that it will be useful,                *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of                 *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU              *
 *   Lesser General Public License for more details.                                *
 *                                                                                *
 *   You should have received a copy of the GNU Lesser General Public               *
 *   License along with this library; if not, write to the Free Software            *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA *
 ***********************************************************************************/
#include "localhistorycollection.h"

//Qt
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QHash>
#include <QtCore/QStandardPaths>
#include <QtCore/QStandardPaths>
#include <QtCore/QUrl>

//Ring
#include "call.h"
#include "media/media.h"
#include "media/recording.h"
#include "media/avrecording.h"
#include "account.h"
#include "person.h"
#include "certificate.h"
#include "contactmethod.h"
#include "categorizedhistorymodel.h"
#include "globalinstances.h"
#include "interfaces/pixmapmanipulatori.h"

class LocalHistoryEditor final : public CollectionEditor<Call>
{
public:
   LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent);
   virtual bool save       ( const Call* item ) override;
   virtual bool remove     ( const Call* item ) override;
   virtual bool edit       ( Call*       item ) override;
   virtual bool addNew     ( Call*       item ) override;
   virtual bool addExisting( const Call* item ) override;

private:
   virtual QVector<Call*> items() const override;

   //Helpers
   void saveCall(QTextStream& stream, const Call* call);
   bool regenFile(const Call* toIgnore);

   //Attributes
   QVector<Call*> m_lItems;
   LocalHistoryCollection* m_pCollection;
};

LocalHistoryEditor::LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent) :
CollectionEditor<Call>(m),m_pCollection(parent)
{

}

LocalHistoryCollection::LocalHistoryCollection(CollectionMediator<Call>* mediator) :
CollectionInterface(new LocalHistoryEditor(mediator,this)),m_pMediator(mediator)
{
//    setObjectName("LocalHistoryCollection");
}

LocalHistoryCollection::~LocalHistoryCollection()
{

}

void LocalHistoryEditor::saveCall(QTextStream& stream, const Call* call)
{
   const QString direction = (call->direction()==Call::Direction::INCOMING)?
      Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING;

   const Account* a = call->account();
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID          ).arg(call->historyId()                     );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START ).arg(call->startTimeStamp()         );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP  ).arg(call->stopTimeStamp()          );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID      ).arg(a?QString(a->id()):""          );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME    ).arg(call->peerName()               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER     ).arg(call->peerContactMethod()->uri() );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION       ).arg(direction                      );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::MISSED          ).arg(call->isMissed()               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_USED    ).arg(false                          );//TODO

   //TODO handle more than one recording
   if (call->hasRecording(Media::Media::Type::AUDIO,Media::Media::Direction::IN)) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::RECORDING_PATH  ).arg(((Media::AVRecording*)call->recordings(Media::Media::Type::AUDIO,Media::Media::Direction::IN)[0])->path().path());
   }

   if (call->peerContactMethod()->contact()) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_UID  ).arg(
         QString(call->peerContactMethod()->contact()->uid())
      );
   }
   if (call->certificate())
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CERT_PATH).arg(call->certificate()->path());
   stream << "\n";
   stream.flush();
}

bool LocalHistoryEditor::regenFile(const Call* toIgnore)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      QTextStream stream(&file);
      for (const Call* c : CategorizedHistoryModel::instance().getHistoryCalls()) {
         if (c != toIgnore)
            saveCall(stream, c);
      }
      file.close();
      return true;
   }
   return false;
}

bool LocalHistoryEditor::save(const Call* call)
{
   if (call->collection()->editor<Call>() != this)
      return addNew(const_cast<Call*>(call));

   return regenFile(nullptr);
}

bool LocalHistoryEditor::remove(const Call* item)
{
   if (regenFile(item)) {
      mediator()->removeItem(item);
      return true;
   }
   return false;
}

bool LocalHistoryEditor::edit( Call* item)
{
   Q_UNUSED(item)
   return false;
}

bool LocalHistoryEditor::addNew( Call* call)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   if ((call->collection() && call->collection()->editor<Call>() == this)  || call->historyId().isEmpty()) return false;
   //TODO support \r and \n\r end of line
   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/')+"history.ini");

   if ( file.open(QIODevice::Append | QIODevice::Text) ) {
      QTextStream streamFileOut(&file);
      saveCall(streamFileOut, call);
      file.close();

      const_cast<Call*>(call)->setCollection(m_pCollection);
      addExisting(call);
      return true;
   }
   else
      qWarning() << "Unable to save history";
   return false;
}

bool LocalHistoryEditor::addExisting(const Call* item)
{
   m_lItems << const_cast<Call*>(item);
   mediator()->addItem(item);
   return true;
}

QVector<Call*> LocalHistoryEditor::items() const
{
   return m_lItems;
}

QString LocalHistoryCollection::name () const
{
   return QObject::tr("Local history");
}

QString LocalHistoryCollection::category () const
{
   return QObject::tr("History");
}

QVariant LocalHistoryCollection::icon() const
{
   return GlobalInstances::pixmapManipulator().collectionIcon(this,Interfaces::PixmapManipulatorI::CollectionIconHint::HISTORY);
}

bool LocalHistoryCollection::isEnabled() const
{
   return true;
}

bool LocalHistoryCollection::load()
{
   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
      QMap<QString,QString> hc;
      QStringList lines;

      while (!file.atEnd())
         lines << file.readLine().trimmed();
      file.close();

      for (const QString& line : lines) {
         //The item is complete
         if ((line.isEmpty() || !line.size()) && hc.size()) {
            Call* pastCall = Call::buildHistoryCall(hc);

            pastCall->setCollection(this);

            editor<Call>()->addExisting(pastCall);
            hc.clear();
         }
         // Add to the current set
         else {
            const int idx = line.indexOf("=");
            if (idx >= 0)
               hc[line.left(idx)] = line.right(line.size()-idx-1);
         }
      }
      return true;
   }
   else
      qWarning() << "History doesn't exist or is not readable";
   return false;
}

bool LocalHistoryCollection::reload()
{
   return false;
}

FlagPack<CollectionInterface::SupportedFeatures> LocalHistoryCollection::supportedFeatures() const
{
   return
      CollectionInterface::SupportedFeatures::NONE       |
      CollectionInterface::SupportedFeatures::LOAD       |
      CollectionInterface::SupportedFeatures::CLEAR      |
      CollectionInterface::SupportedFeatures::REMOVE     |
      CollectionInterface::SupportedFeatures::MANAGEABLE |
      CollectionInterface::SupportedFeatures::ADD        ;
}

bool LocalHistoryCollection::clear()
{
   QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   return true;
}

QByteArray LocalHistoryCollection::id() const
{
   return "mhb";
}
<commit_msg>history: fix encoding of history file<commit_after>/************************************************************************************
 *   Copyright (C) 2014-2015 by Savoir-Faire Linux                                       *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
 *                                                                                *
 *   This library is free software; you can redistribute it and/or                  *
 *   modify it under the terms of the GNU Lesser General Public                     *
 *   License as published by the Free Software Foundation; either                   *
 *   version 2.1 of the License, or (at your option) any later version.             *
 *                                                                                *
 *   This library is distributed in the hope that it will be useful,                *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of                 *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU              *
 *   Lesser General Public License for more details.                                *
 *                                                                                *
 *   You should have received a copy of the GNU Lesser General Public               *
 *   License along with this library; if not, write to the Free Software            *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA *
 ***********************************************************************************/
#include "localhistorycollection.h"

//Qt
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QHash>
#include <QtCore/QStandardPaths>
#include <QtCore/QStandardPaths>
#include <QtCore/QUrl>

//Ring
#include "call.h"
#include "media/media.h"
#include "media/recording.h"
#include "media/avrecording.h"
#include "account.h"
#include "person.h"
#include "certificate.h"
#include "contactmethod.h"
#include "categorizedhistorymodel.h"
#include "globalinstances.h"
#include "interfaces/pixmapmanipulatori.h"

class LocalHistoryEditor final : public CollectionEditor<Call>
{
public:
   LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent);
   virtual bool save       ( const Call* item ) override;
   virtual bool remove     ( const Call* item ) override;
   virtual bool edit       ( Call*       item ) override;
   virtual bool addNew     ( Call*       item ) override;
   virtual bool addExisting( const Call* item ) override;

private:
   virtual QVector<Call*> items() const override;

   //Helpers
   void saveCall(QTextStream& stream, const Call* call);
   bool regenFile(const Call* toIgnore);

   //Attributes
   QVector<Call*> m_lItems;
   LocalHistoryCollection* m_pCollection;
};

LocalHistoryEditor::LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent) :
CollectionEditor<Call>(m),m_pCollection(parent)
{

}

LocalHistoryCollection::LocalHistoryCollection(CollectionMediator<Call>* mediator) :
CollectionInterface(new LocalHistoryEditor(mediator,this)),m_pMediator(mediator)
{
//    setObjectName("LocalHistoryCollection");
}

LocalHistoryCollection::~LocalHistoryCollection()
{

}

void LocalHistoryEditor::saveCall(QTextStream& stream, const Call* call)
{
   stream.setCodec("UTF-8");
   const QString direction = (call->direction()==Call::Direction::INCOMING)?
      Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING;

   const Account* a = call->account();
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID          ).arg(call->historyId()                     );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START ).arg(call->startTimeStamp()         );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP  ).arg(call->stopTimeStamp()          );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID      ).arg(a?QString(a->id()):""          );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME    ).arg(call->peerName()               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER     ).arg(call->peerContactMethod()->uri() );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION       ).arg(direction                      );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::MISSED          ).arg(call->isMissed()               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_USED    ).arg(false                          );//TODO

   //TODO handle more than one recording
   if (call->hasRecording(Media::Media::Type::AUDIO,Media::Media::Direction::IN)) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::RECORDING_PATH  ).arg(((Media::AVRecording*)call->recordings(Media::Media::Type::AUDIO,Media::Media::Direction::IN)[0])->path().path());
   }

   if (call->peerContactMethod()->contact()) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_UID  ).arg(
         QString(call->peerContactMethod()->contact()->uid())
      );
   }
   if (call->certificate())
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CERT_PATH).arg(call->certificate()->path());
   stream << "\n";
   stream.flush();
}

bool LocalHistoryEditor::regenFile(const Call* toIgnore)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      QTextStream stream(&file);
      for (const Call* c : CategorizedHistoryModel::instance().getHistoryCalls()) {
         if (c != toIgnore)
            saveCall(stream, c);
      }
      file.close();
      return true;
   }
   return false;
}

bool LocalHistoryEditor::save(const Call* call)
{
   if (call->collection()->editor<Call>() != this)
      return addNew(const_cast<Call*>(call));

   return regenFile(nullptr);
}

bool LocalHistoryEditor::remove(const Call* item)
{
   if (regenFile(item)) {
      mediator()->removeItem(item);
      return true;
   }
   return false;
}

bool LocalHistoryEditor::edit( Call* item)
{
   Q_UNUSED(item)
   return false;
}

bool LocalHistoryEditor::addNew( Call* call)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   if ((call->collection() && call->collection()->editor<Call>() == this)  || call->historyId().isEmpty()) return false;
   //TODO support \r and \n\r end of line
   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/')+"history.ini");

   if ( file.open(QIODevice::Append | QIODevice::Text) ) {
      QTextStream streamFileOut(&file);
      saveCall(streamFileOut, call);
      file.close();

      const_cast<Call*>(call)->setCollection(m_pCollection);
      addExisting(call);
      return true;
   }
   else
      qWarning() << "Unable to save history";
   return false;
}

bool LocalHistoryEditor::addExisting(const Call* item)
{
   m_lItems << const_cast<Call*>(item);
   mediator()->addItem(item);
   return true;
}

QVector<Call*> LocalHistoryEditor::items() const
{
   return m_lItems;
}

QString LocalHistoryCollection::name () const
{
   return QObject::tr("Local history");
}

QString LocalHistoryCollection::category () const
{
   return QObject::tr("History");
}

QVariant LocalHistoryCollection::icon() const
{
   return GlobalInstances::pixmapManipulator().collectionIcon(this,Interfaces::PixmapManipulatorI::CollectionIconHint::HISTORY);
}

bool LocalHistoryCollection::isEnabled() const
{
   return true;
}

bool LocalHistoryCollection::load()
{
   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
      QMap<QString,QString> hc;
      QStringList lines;

      while (!file.atEnd())
         lines << file.readLine().trimmed();
      file.close();

      for (const QString& line : lines) {
         //The item is complete
         if ((line.isEmpty() || !line.size()) && hc.size()) {
            Call* pastCall = Call::buildHistoryCall(hc);

            pastCall->setCollection(this);

            editor<Call>()->addExisting(pastCall);
            hc.clear();
         }
         // Add to the current set
         else {
            const int idx = line.indexOf("=");
            if (idx >= 0)
               hc[line.left(idx)] = line.right(line.size()-idx-1);
         }
      }
      return true;
   }
   else
      qWarning() << "History doesn't exist or is not readable";
   return false;
}

bool LocalHistoryCollection::reload()
{
   return false;
}

FlagPack<CollectionInterface::SupportedFeatures> LocalHistoryCollection::supportedFeatures() const
{
   return
      CollectionInterface::SupportedFeatures::NONE       |
      CollectionInterface::SupportedFeatures::LOAD       |
      CollectionInterface::SupportedFeatures::CLEAR      |
      CollectionInterface::SupportedFeatures::REMOVE     |
      CollectionInterface::SupportedFeatures::MANAGEABLE |
      CollectionInterface::SupportedFeatures::ADD        ;
}

bool LocalHistoryCollection::clear()
{
   QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   return true;
}

QByteArray LocalHistoryCollection::id() const
{
   return "mhb";
}
<|endoftext|>


<commit_before>#include "MeshLoader.hpp"

#include "File.hpp"
#include "Mesh.hpp"

bool MeshLoader::LoadMesh(const char* filePath, Mesh& mesh)
{
	using uint = unsigned int;
	using ushort = unsigned short;

	Buffer<unsigned char> file = File::Read(filePath);
	size_t fileSize = file.Count();

	const uint headerSize = 16;
	const uint boundsSize = 6 * sizeof(float);

	if (file.IsValid() && fileSize >= headerSize)
	{
		unsigned char* d = file.Data();
		uint* headerData = reinterpret_cast<uint*>(d);
		uint fileMagic = headerData[0];

		if (fileMagic == 0x91191010)
		{
			// Get header data

			uint vertComps = headerData[1];
			uint vertCount = headerData[2];
			uint indexCount = headerData[3];

			// Get vertex data components count and size

			uint posCount = (vertComps & 0x01) >> 0;
			uint posSize = posCount * 3 * sizeof(float);

			uint normCount = (vertComps & 0x02) >> 1;
			uint normSize = normCount * 3 * sizeof(float);

			uint colCount = (vertComps & 0x04) >> 2;
			uint colSize = colCount * 3 * sizeof(float);

			uint texCount = (vertComps & 0x08) >> 3;
			uint texSize = texCount * 2 * sizeof(float);

			uint vertSize = posSize + normSize + colSize + texSize;
			uint vertexDataSize = vertCount * vertSize;

			uint indexSize = indexCount > (1 << 16) ? 4 : 2;
			uint indexDataSize = indexCount * indexSize;

			uint expectedSize = headerSize + boundsSize + vertexDataSize + indexDataSize;

			// Check that the file size matches the header description
			if (expectedSize == fileSize)
			{
				float* boundsData = reinterpret_cast<float*>(d + headerSize);
				float* vertData = reinterpret_cast<float*>(d + headerSize + boundsSize);
				ushort* indexData = reinterpret_cast<ushort*>(d + headerSize + boundsSize + vertexDataSize);

				mesh.bounds.center.x = boundsData[0];
				mesh.bounds.center.y = boundsData[1];
				mesh.bounds.center.z = boundsData[2];

				mesh.bounds.extents.x = boundsData[3];
				mesh.bounds.extents.y = boundsData[4];
				mesh.bounds.extents.z = boundsData[5];

				if (normCount == 1 && colCount == 0 && texCount == 0)
					mesh.Upload_PosNor(vertData, vertCount, indexData, indexCount);

				else if (normCount == 0 && colCount == 1 && texCount == 0)
					mesh.Upload_PosCol(vertData, vertCount, indexData, indexCount);

				else if (normCount == 1 && colCount == 1 && texCount == 0)
					mesh.Upload_PosNorCol(vertData, vertCount, indexData, indexCount);

				return true;
			}
		}
	}

	return false;
}
<commit_msg>Add an assert for mesh file expected size<commit_after>#include "MeshLoader.hpp"

#include <cassert>

#include "File.hpp"
#include "Mesh.hpp"

bool MeshLoader::LoadMesh(const char* filePath, Mesh& mesh)
{
	using uint = unsigned int;
	using ushort = unsigned short;

	Buffer<unsigned char> file = File::Read(filePath);
	size_t fileSize = file.Count();

	const uint headerSize = 16;
	const uint boundsSize = 6 * sizeof(float);

	if (file.IsValid() && fileSize >= headerSize)
	{
		unsigned char* d = file.Data();
		uint* headerData = reinterpret_cast<uint*>(d);
		uint fileMagic = headerData[0];

		if (fileMagic == 0x91191010)
		{
			// Get header data

			uint vertComps = headerData[1];
			uint vertCount = headerData[2];
			uint indexCount = headerData[3];

			// Get vertex data components count and size

			uint posCount = (vertComps & 0x01) >> 0;
			uint posSize = posCount * 3 * sizeof(float);

			uint normCount = (vertComps & 0x02) >> 1;
			uint normSize = normCount * 3 * sizeof(float);

			uint colCount = (vertComps & 0x04) >> 2;
			uint colSize = colCount * 3 * sizeof(float);

			uint texCount = (vertComps & 0x08) >> 3;
			uint texSize = texCount * 2 * sizeof(float);

			uint vertSize = posSize + normSize + colSize + texSize;
			uint vertexDataSize = vertCount * vertSize;

			uint indexSize = indexCount > (1 << 16) ? 4 : 2;
			uint indexDataSize = indexCount * indexSize;

			uint expectedSize = headerSize + boundsSize + vertexDataSize + indexDataSize;

			assert(expectedSize == fileSize);

			// Check that the file size matches the header description
			if (expectedSize == fileSize)
			{
				float* boundsData = reinterpret_cast<float*>(d + headerSize);
				float* vertData = reinterpret_cast<float*>(d + headerSize + boundsSize);
				ushort* indexData = reinterpret_cast<ushort*>(d + headerSize + boundsSize + vertexDataSize);

				mesh.bounds.center.x = boundsData[0];
				mesh.bounds.center.y = boundsData[1];
				mesh.bounds.center.z = boundsData[2];

				mesh.bounds.extents.x = boundsData[3];
				mesh.bounds.extents.y = boundsData[4];
				mesh.bounds.extents.z = boundsData[5];

				if (normCount == 1 && colCount == 0 && texCount == 0)
					mesh.Upload_PosNor(vertData, vertCount, indexData, indexCount);

				else if (normCount == 0 && colCount == 1 && texCount == 0)
					mesh.Upload_PosCol(vertData, vertCount, indexData, indexCount);

				else if (normCount == 1 && colCount == 1 && texCount == 0)
					mesh.Upload_PosNorCol(vertData, vertCount, indexData, indexCount);

				return true;
			}
		}
	}

	return false;
}
<|endoftext|>


<commit_before>// MS WARNINGS MACRO
#define _SCL_SECURE_NO_WARNINGS
#include <boost/network/protocol/http/server.hpp>

#include <iostream>
#include <string>
#include <fstream>

#include "server.hpp"
#include "tools.hpp"
#include "problem.hpp"
#include "answer.hpp"

namespace http = boost::network::http;

/*<< Defines the server. >>*/
struct submit_form;
typedef http::server<submit_form> server;

struct submit_form {
    std::string problem_set = "default";
    void operator() (server::request const &request, server::response &response)
    {
        std::string p = (std::string)destination(request);
        std::string b = (std::string)body(request);
        if(p == "/SubmitForm") {
            std::ifstream ifs("res/SubmitForm.html");
            std::stringstream buf;
            buf << ifs.rdbuf();
            response = server::response::stock_reply(server::response::ok, buf.str());
        } else if(p == "/SubmitAnswer") {
            std::cerr << b << std::endl;
            auto req = post_req_to_map(b);
            percent_decode(req["answer"]);
            std::cerr << "playerid: " << req["playerid"] << std::endl;
            std::cerr << "problemid: " << req["problemid"] << std::endl;
            std::cerr << "options: " << req["options"] << std::endl;
            std::cerr << "answer:\n" << req["answer"] << std::endl;
            pcserver pcs;
            problem pro(problem_set);
            pro.load(req["problemid"]);
            answer ans(req["answer"]);
            if(pro.valid() && ans.valid())
                pcs.parse(pro.get(), ans.get());
            std::string s_res;
            if(pcs.ok()) {
                if(req["options"].find("quiet") != std::string::npos) { // 見つかった場合
                    s_res = pcs.get_output();
                } else {
                    s_res = pro.get_error() + ans.get_error() + pcs.get_output();
                }
            } else {
                s_res = pro.get_error() + ans.get_error() + pcs.get_error();
            }
            response = server::response::stock_reply(server::response::ok, s_res);
        } else if(p.substr(0, 9) == "/problem/") {
            std::ifstream ifs("problem_set/" + problem_set + "/problem/" + p.substr(9)); // insecure
            if(ifs.fail()) {
                response = server::response::stock_reply(server::response::not_found, "Not found");
            } else {
                response = server::response::stock_reply(server::response::ok, "data");
//                response << boost::network::header("Content-Type", "image/x-portable-pixmap");
//                response << boost::network::header("Connection", "close");
            }
        } else {
            response = server::response::stock_reply((boost::network::http::basic_response<boost::network::http::tags::http_server>::status_type)418, "I'm a tea pot");
        }
    }
    void log(...){}
};

void http_run()
{
    try {
        /*<< Creates the request handler. >>*/
        submit_form handler;
        /*<< Creates the server. >>*/
        server::options options(handler);
        server server_(options.address("127.0.0.1").port("80"));
        /*<< Runs the server. >>*/
        server_.run();
    }
    catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
}

int main()
{
    http_run();
    return 0;
}

<commit_msg>serverでcpp-netlibを使うコードを削除<commit_after><|endoftext|>


<commit_before>#include "changecreditsdialog.h"
#include "ui_changecreditsdialog.h"

#include <QMessageBox>

#include "src/structures.hpp"
#include "src/uvmanager.hpp"
#include "src/exceptions.hpp"

#define CUM CategorieUVManager::getInstance()
#define UVM UvManager::getInstance()

//! Ouverture du Pop up de changement de crédits pour l'UV selectionnée
ChangeCreditsDialog::ChangeCreditsDialog(QWidget *parent, QString u) :
    QDialog(parent),
    ui(new Ui::ChangeCreditsDialog)
{
    ui->setupUi(this);
    uv = u;

    try {
        UVM->getItem(uv);

    } catch(const Exception &e) {
        QMessageBox error(this);
        error.setText("UV inconnue");
        error.exec();
    }

    ui->credits->setMinimum(0);
    ui->categories->addItems(CUM->getItemNameList());

    QStringList header;
    header << "Crédits" << "Catégorie";
    ui->tableWidget->setColumnCount(2);
    ui->tableWidget->setHorizontalHeaderLabels(header);
    ui->tableWidget->setRowCount(0);
    ui->tableWidget->setColumnCount(2);
    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    connect(this, SIGNAL(accepted()), this, SLOT(closing()));
}

//! Ajout de crédits dans une catégorie pour une UV
void ChangeCreditsDialog::ajouter() {
    QString credits = QString::number(ui->credits->value());
    QString categorie =  ui->categories->currentText();
    ui->credits->clear();

    //Si des crédits ont déjà été rajoutés pour cette catégorie,
    //On ignore l’ajout
    for(int i=0; i<ui->tableWidget->rowCount(); i++) {
        if(ui->tableWidget->item(i, 1)->text() == categorie) {
            return;
        }
    }

    ui->tableWidget->setRowCount(ui->tableWidget->rowCount() + 1);
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 0, new QTableWidgetItem(credits));
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 1, new QTableWidgetItem(categorie));
}

//! fermeture du pop up et sauvegarde des nouveaux crédits
void ChangeCreditsDialog::closing() {
    Uv& concerned = UVM->getItem(uv);
    concerned.resetCredits();
    for(int i=0; i<ui->tableWidget->rowCount(); i++) {
        unsigned int credits;
        credits = ui->tableWidget->item(i, 0)->text().toUInt();
        concerned.setCredits(ui->tableWidget->item(i, 1)->text(), credits);
    }
}

ChangeCreditsDialog::~ChangeCreditsDialog() {
    delete ui;
}
<commit_msg>Fix doublon<commit_after>#include "changecreditsdialog.h"
#include "ui_changecreditsdialog.h"

#include <QMessageBox>

#include "src/structures.hpp"
#include "src/uvmanager.hpp"
#include "src/exceptions.hpp"

#define CUM CategorieUVManager::getInstance()
#define UVM UvManager::getInstance()

//! Ouverture du Pop up de changement de crédits pour l'UV selectionnée
ChangeCreditsDialog::ChangeCreditsDialog(QWidget *parent, QString u) :
    QDialog(parent),
    ui(new Ui::ChangeCreditsDialog)
{
    ui->setupUi(this);
    uv = u;

    try {
        UVM->getItem(uv);

    } catch(const Exception &e) {
        QMessageBox error(this);
        error.setText("UV inconnue");
        error.exec();
    }

    ui->credits->setMinimum(0);
    ui->categories->addItems(CUM->getItemNameList());

    QStringList header;
    header << "Crédits" << "Catégorie";
    ui->tableWidget->setColumnCount(2);
    ui->tableWidget->setHorizontalHeaderLabels(header);
    ui->tableWidget->setRowCount(0);
    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    connect(this, SIGNAL(accepted()), this, SLOT(closing()));
}

//! Ajout de crédits dans une catégorie pour une UV
void ChangeCreditsDialog::ajouter() {
    QString credits = QString::number(ui->credits->value());
    QString categorie =  ui->categories->currentText();
    ui->credits->clear();

    //Si des crédits ont déjà été rajoutés pour cette catégorie,
    //On ignore l’ajout
    for(int i=0; i<ui->tableWidget->rowCount(); i++) {
        if(ui->tableWidget->item(i, 1)->text() == categorie) {
            return;
        }
    }

    ui->tableWidget->setRowCount(ui->tableWidget->rowCount() + 1);
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 0, new QTableWidgetItem(credits));
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 1, new QTableWidgetItem(categorie));
}

//! fermeture du pop up et sauvegarde des nouveaux crédits
void ChangeCreditsDialog::closing() {
    Uv& concerned = UVM->getItem(uv);
    concerned.resetCredits();
    for(int i=0; i<ui->tableWidget->rowCount(); i++) {
        unsigned int credits;
        credits = ui->tableWidget->item(i, 0)->text().toUInt();
        concerned.setCredits(ui->tableWidget->item(i, 1)->text(), credits);
    }
}

ChangeCreditsDialog::~ChangeCreditsDialog() {
    delete ui;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	スケーリング（拡大、縮小）
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "common/vtx.hpp"
#include <unordered_map>

namespace img {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	スケーリング・クラス
		@param[in]	RENDER	レンダー・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RENDER>
	class scaling {

		RENDER&		render_;

		struct xy_pad {
			uint32_t	r;
			uint32_t	g;
			uint32_t	b;
			uint32_t	cnt;
		};

		typedef std::unordered_map<uint32_t, xy_pad> MAP;
		MAP			map_;

#if 0
		static float sinc_(float l)
		{
			return std::sin(vtx::get_pi<float>() * l) / (vtx::get_pi<float>() * l);
		}

		static float lanczos_(float d, float n)
		{
			if(d == 0.0f) {
				return 1.0f;
			} else if(std::abs(d) >= n) {
				return 0.0f;
			} else {
				return sinc_(d) * sinc_(d / n);
			}
		}

		float lanczos_tbl_[(12 + 1) * (12 + 1)];
		float lanczos_n_;
		// -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0
		void init_lanczos_(float n)
		{
			if(lanczos_n_ == n) return;

			float y = -3.0f;
			for(int i = 0; i < (12 + 1); ++i) {
				float yl = lanczos_(y, n);
				float x = -3.0f;
				for(int j = 0; j < (12 + 1); ++j) {
					float xl = lanczos_(x, n);
					lanczos_tbl_[i * (12 + 1) + j] = xl * yl;
					x += 0.5f;
				}
				y += 0.5f;
			}
			lanczos_n_ = n;
		}

		float lanczos_t_(float x, float y, float n)
		{
			int i = static_cast<int>(y * 2.0f);
			i += 6;
			int j = static_cast<int>(x * 2.0f);
			j += 6;
			if(i >= 0 && i < (12 + 1) && j >= 0 && j < (12 + 1)) {
				return lanczos_tbl_[i * (12 + 1) + j];
			} else {
				return lanczos_(x, n) * lanczos_(y, n);
			}
		}
#endif

#if 0
	static void color_div_(const rgbaf& col, float total, rgba8& c)
	{
		rgbaf cc;
		if(total != 0.0f) {
			float sf = 1.0f / total;
			cc.r = col.r * sf;
			cc.g = col.g * sf;
			cc.b = col.b * sf;
			cc.a = col.a * sf;
		} else {
			cc = col;
		}

		if(cc.r < 0.0f) {
			c.r = 0;
		} else if(cc.r > 255.0f) {
			c.r = 255;
		} else {
			c.r = static_cast<unsigned char>(cc.r);
		}

		if(cc.g < 0.0f) {
			c.g = 0;
		} else if(cc.g > 255.0f) {
			c.g = 255;
		} else {
			c.g = static_cast<unsigned char>(cc.g);
		}

		if(cc.b < 0.0f) {
			c.b = 0;
		} else if(cc.b > 255.0f) {
			c.b = 255;
		} else {
			c.b = static_cast<unsigned char>(cc.b);
		}

		if(cc.a < 0.0f) {
			c.a = 0;
		} else if(cc.a > 255.0f) {
			c.a = 255;
		} else {
			c.a = static_cast<unsigned char>(cc.a);
		}
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	画像をリサイズする（lanczos-3 アルゴリズム）
		@param[in]	src	ソースのイメージ
		@param[out]	dst	リサイズイメージ
		@param[in]	scale	スケール・ファクター
	*/
	//-----------------------------------------------------------------//
	void resize_image(const i_img* src, img_rgba8& dst, float scale)
	{
		if(scale <= 0.0f) return;

		int sw = src->get_size().x;
		int sh = src->get_size().y;
		int dw = static_cast<int>(static_cast<float>(sw) * scale);
		int dh = static_cast<int>(static_cast<float>(sh) * scale);
		dst.create(vtx::spos(dw, dh), src->test_alpha());

		float n = 3.0f;
		init_lanczos_(n);

		float scn = 1.0f / scale;
		if(scale > 1.0f) {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = (static_cast<float>(out.y) + 0.5f) * scn;
				int ys = static_cast<int>(yy - n);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>(yy + n);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = (static_cast<float>(out.x) + 0.5f) * scn;
					int xs = static_cast<int>(xx - n);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>(xx + n);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = fabs((pos.y + 0.5f) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs((static_cast<float>(pos.x) + 0.5f) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += c.r * weight;
							col.g += c.g * weight;
							col.b += c.b * weight;
							col.a += c.a * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		} else {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = static_cast<float>(out.y) + 0.5f;
				int ys = static_cast<int>((yy - n) * scn);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>((yy + n) * scn);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = static_cast<float>(out.x) + 0.5f;
					int xs = static_cast<int>((xx - n) * scn);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>((xx + n) * scn);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = std::abs(((static_cast<float>(pos.y) + 0.5f) * scale) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs(((static_cast<float>(pos.x) + 0.5f) * scale) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += static_cast<float>(c.r) * weight;
							col.g += static_cast<float>(c.g) * weight;
							col.b += static_cast<float>(c.b) * weight;
							col.a += static_cast<float>(c.a) * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		}
	}
#endif

		vtx::spos	ofs_;
		struct step_t {
			int32_t	up;
			int32_t	dn;
			step_t(uint32_t u = 0, uint32_t d = 1) noexcept : up(u), dn(d) { }
		};
		step_t		scale_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクタ
			@param[in]	render	レンダークラス（参照）
		*/
		//-----------------------------------------------------------------//
		scaling(RENDER& render) noexcept : render_(render),
//			lanczos_n_(0.0f),
			ofs_(0), scale_()
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	オフセットを設定
			@param[in]	ofs	オフセット
		*/
		//-----------------------------------------------------------------//
		void set_offset(const vtx::spos& ofs = vtx::spos(0)) noexcept { ofs_ = ofs; }

		//-----------------------------------------------------------------//
		/*!
			@brief	スケールを設定
			@param[in]	up		分子
			@param[in]	dn		分母
		*/
		//-----------------------------------------------------------------//
		void set_scale(uint32_t up = 1, uint32_t dn = 1) noexcept { scale_ = step_t(up, dn); }

		void cleanup()
		{
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	描画ファンクタ
			@param[in]	x	X 座標
			@param[in]	y	Y 座標
			@param[in]	r	R カラー
			@param[in]	g	G カラー
			@param[in]	b	B カラー
		*/
		//-----------------------------------------------------------------//
		void operator() (int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b) noexcept
		{
			auto c = RENDER::COLOR::rgb(r, g, b);
			if(scale_.up < scale_.dn) {
				if(c == 0) c = 1;
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				auto rc = render_.get_plot(xx + ofs_.x, yy + ofs_.y);
				if(rc == 0) {
					render_.plot(xx + ofs_.x, yy + ofs_.y, c);
				} else {
					auto nc = render_.color_sum(c, rc);
					render_.plot(xx + ofs_.x, yy + ofs_.y, nc);
				}
			} else if(scale_.up > scale_.dn) {
				auto d  = scale_.up * 2 / scale_.dn;
				if(d & 1) { d >>= 1; ++d; } else { d >>= 1; }
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				render_.fill_box(xx + ofs_.x, yy + ofs_.y, d, d, c);
			} else {
				render_.plot(x + ofs_.x, y + ofs_.y, c);
			}
#if 0
			uint32_t key = static_cast<uint16_t>(xx) | (static_cast<uint16_t>(yy) << 16);
			auto it = map_.find(key);
			if(it != map_.end()) {
//				it->first.r += r;
//				it->first.g += g;
//				it->first.b += b;
//				++it->first.cnt;
//				if(it->first.cnt >= 4) {
//					auto c = RENDER::COLOR::rgb(r, g, b);
//					render_.plot(xx + ofs_.x, yy + ofs_.y, c);
//				}
			} else {
				map_.emplace(r, g, b, 1);
			}
#endif
		}
	};
}
<commit_msg>update: scale for antialias<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	スケーリング（拡大、縮小）
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "common/vtx.hpp"
// #include <unordered_map>

namespace img {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	スケーリング・クラス
		@param[in]	RENDER	レンダー・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RENDER>
	class scaling {

		RENDER&		render_;

		struct xy_pad {
			uint32_t	r;
			uint32_t	g;
			uint32_t	b;
			uint32_t	cnt;
		};

//		typedef std::unordered_map<uint32_t, xy_pad> MAP;
//		MAP			map_;

#if 0
		static float sinc_(float l)
		{
			return std::sin(vtx::get_pi<float>() * l) / (vtx::get_pi<float>() * l);
		}

		static float lanczos_(float d, float n)
		{
			if(d == 0.0f) {
				return 1.0f;
			} else if(std::abs(d) >= n) {
				return 0.0f;
			} else {
				return sinc_(d) * sinc_(d / n);
			}
		}

		float lanczos_tbl_[(12 + 1) * (12 + 1)];
		float lanczos_n_;
		// -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0
		void init_lanczos_(float n)
		{
			if(lanczos_n_ == n) return;

			float y = -3.0f;
			for(int i = 0; i < (12 + 1); ++i) {
				float yl = lanczos_(y, n);
				float x = -3.0f;
				for(int j = 0; j < (12 + 1); ++j) {
					float xl = lanczos_(x, n);
					lanczos_tbl_[i * (12 + 1) + j] = xl * yl;
					x += 0.5f;
				}
				y += 0.5f;
			}
			lanczos_n_ = n;
		}

		float lanczos_t_(float x, float y, float n)
		{
			int i = static_cast<int>(y * 2.0f);
			i += 6;
			int j = static_cast<int>(x * 2.0f);
			j += 6;
			if(i >= 0 && i < (12 + 1) && j >= 0 && j < (12 + 1)) {
				return lanczos_tbl_[i * (12 + 1) + j];
			} else {
				return lanczos_(x, n) * lanczos_(y, n);
			}
		}
#endif

#if 0
	static void color_div_(const rgbaf& col, float total, rgba8& c)
	{
		rgbaf cc;
		if(total != 0.0f) {
			float sf = 1.0f / total;
			cc.r = col.r * sf;
			cc.g = col.g * sf;
			cc.b = col.b * sf;
			cc.a = col.a * sf;
		} else {
			cc = col;
		}

		if(cc.r < 0.0f) {
			c.r = 0;
		} else if(cc.r > 255.0f) {
			c.r = 255;
		} else {
			c.r = static_cast<unsigned char>(cc.r);
		}

		if(cc.g < 0.0f) {
			c.g = 0;
		} else if(cc.g > 255.0f) {
			c.g = 255;
		} else {
			c.g = static_cast<unsigned char>(cc.g);
		}

		if(cc.b < 0.0f) {
			c.b = 0;
		} else if(cc.b > 255.0f) {
			c.b = 255;
		} else {
			c.b = static_cast<unsigned char>(cc.b);
		}

		if(cc.a < 0.0f) {
			c.a = 0;
		} else if(cc.a > 255.0f) {
			c.a = 255;
		} else {
			c.a = static_cast<unsigned char>(cc.a);
		}
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	画像をリサイズする（lanczos-3 アルゴリズム）
		@param[in]	src	ソースのイメージ
		@param[out]	dst	リサイズイメージ
		@param[in]	scale	スケール・ファクター
	*/
	//-----------------------------------------------------------------//
	void resize_image(const i_img* src, img_rgba8& dst, float scale)
	{
		if(scale <= 0.0f) return;

		int sw = src->get_size().x;
		int sh = src->get_size().y;
		int dw = static_cast<int>(static_cast<float>(sw) * scale);
		int dh = static_cast<int>(static_cast<float>(sh) * scale);
		dst.create(vtx::spos(dw, dh), src->test_alpha());

		float n = 3.0f;
		init_lanczos_(n);

		float scn = 1.0f / scale;
		if(scale > 1.0f) {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = (static_cast<float>(out.y) + 0.5f) * scn;
				int ys = static_cast<int>(yy - n);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>(yy + n);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = (static_cast<float>(out.x) + 0.5f) * scn;
					int xs = static_cast<int>(xx - n);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>(xx + n);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = fabs((pos.y + 0.5f) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs((static_cast<float>(pos.x) + 0.5f) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += c.r * weight;
							col.g += c.g * weight;
							col.b += c.b * weight;
							col.a += c.a * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		} else {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = static_cast<float>(out.y) + 0.5f;
				int ys = static_cast<int>((yy - n) * scn);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>((yy + n) * scn);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = static_cast<float>(out.x) + 0.5f;
					int xs = static_cast<int>((xx - n) * scn);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>((xx + n) * scn);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = std::abs(((static_cast<float>(pos.y) + 0.5f) * scale) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs(((static_cast<float>(pos.x) + 0.5f) * scale) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += static_cast<float>(c.r) * weight;
							col.g += static_cast<float>(c.g) * weight;
							col.b += static_cast<float>(c.b) * weight;
							col.a += static_cast<float>(c.a) * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		}
	}
#endif

		vtx::spos	ofs_;
		struct step_t {
			int32_t	up;
			int32_t	dn;
			step_t(uint32_t u = 0, uint32_t d = 1) noexcept : up(u), dn(d) { }
		};
		step_t		scale_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクタ
			@param[in]	render	レンダークラス（参照）
		*/
		//-----------------------------------------------------------------//
		scaling(RENDER& render) noexcept : render_(render),
//			lanczos_n_(0.0f),
			ofs_(0), scale_()
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	オフセットを設定
			@param[in]	ofs	オフセット
		*/
		//-----------------------------------------------------------------//
		void set_offset(const vtx::spos& ofs = vtx::spos(0)) noexcept { ofs_ = ofs; }

		//-----------------------------------------------------------------//
		/*!
			@brief	スケールを設定
			@param[in]	up		分子
			@param[in]	dn		分母
		*/
		//-----------------------------------------------------------------//
		void set_scale(uint32_t up = 1, uint32_t dn = 1) noexcept { scale_ = step_t(up, dn); }

		void cleanup()
		{
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	描画ファンクタ
			@param[in]	x	X 座標
			@param[in]	y	Y 座標
			@param[in]	r	R カラー
			@param[in]	g	G カラー
			@param[in]	b	B カラー
		*/
		//-----------------------------------------------------------------//
		void operator() (int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b) noexcept
		{
			auto c = RENDER::COLOR::rgb(r, g, b);
			if(scale_.up < scale_.dn) {
				if(c == 0) c = 1;
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				auto rc = render_.get_plot(xx + ofs_.x, yy + ofs_.y);
				if(rc == 0) {
					render_.plot(xx + ofs_.x, yy + ofs_.y, c);
				} else {
					auto nc = render_.color_sum(c, rc);
					render_.plot(xx + ofs_.x, yy + ofs_.y, nc);
				}
			} else if(scale_.up > scale_.dn) {
				auto d  = scale_.up * 2 / scale_.dn;
				if(d & 1) { d >>= 1; ++d; } else { d >>= 1; }
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				render_.fill_box(xx + ofs_.x, yy + ofs_.y, d, d, c);
			} else {
				render_.plot(x + ofs_.x, y + ofs_.y, c);
			}
#if 0
			uint32_t key = static_cast<uint16_t>(xx) | (static_cast<uint16_t>(yy) << 16);
			auto it = map_.find(key);
			if(it != map_.end()) {
//				it->first.r += r;
//				it->first.g += g;
//				it->first.b += b;
//				++it->first.cnt;
//				if(it->first.cnt >= 4) {
//					auto c = RENDER::COLOR::rgb(r, g, b);
//					render_.plot(xx + ofs_.x, yy + ofs_.y, c);
//				}
			} else {
				map_.emplace(r, g, b, 1);
			}
#endif
		}
	};
}
<|endoftext|>


<commit_before>#pragma once

#include <entwine/util/pool.hpp>

#include <greyhound/defs.hpp>
#include <greyhound/manager.hpp>

namespace greyhound
{

template<typename S>
class Router
{
    using Req = typename S::Request;
    using Res = typename S::Response;
    using ReqPtr = std::shared_ptr<typename S::Request>;
    using ResPtr = std::shared_ptr<typename S::Response>;

public:
    template<typename... Args>
    Router(Manager& manager, unsigned int port, Args&&... args)
        : m_manager(manager)
        , m_server(std::forward<Args>(args)...)
        , m_pool(m_manager.threads())
    {
        m_server.config.port = port;
        m_server.config.timeout_request = 0;
        m_server.config.timeout_content = 0;

        m_server.default_resource["GET"] = [](ResPtr res, ReqPtr req)
        {
            res->write(HttpStatusCode::client_error_not_found);
        };

        m_server.on_error = [](ReqPtr req, const SimpleWeb::error_code& ec)
        {
            if (
                    ec &&
                    ec != SimpleWeb::errc::operation_canceled &&
                    ec != SimpleWeb::errc::broken_pipe &&
                    ec != SimpleWeb::asio::error::eof)
            {
                std::cout << "Error " << ec << ": " << ec.message() <<
                    std::endl;
            }
        };
    }

    template<typename F>
    void get(std::string match, F f) { route("GET", match, f); }

    template<typename F>
    void put(std::string match, F f) { route("PUT", match, f); }

    template<typename F>
    void route(std::string method, std::string match, F f)
    {
        m_server.resource[match][method] = [this, &f](ResPtr res, ReqPtr req)
        {
            // res->close_connection_after_response = true;
            m_pool.add([this, &f, req, res]()
            {
                auto error(
                        [this, &res](HttpStatusCode code, std::string message)
                {
                    // Don't cache errors.  This is a multi-map, so remove any
                    // existing Cache-Control setting.
                    Headers h(m_manager.headers());
                    for (auto it(h.begin()); it != h.end(); )
                    {
                        if (it->first == "Cache-Control") it = h.erase(it);
                        else ++it;
                    }

                    h.emplace("Cache-Control", "public, max-age=0");
                    res->write(code, message, h);
                });

                try
                {
                    const std::string name(req->path_match[1]);
                    if (auto resource = m_manager.get(name, *req))
                    {
                        f(*resource, *req, *res);
                    }
                    else
                    {
                        throw HttpError(
                                HttpStatusCode::client_error_not_found,
                                name + " could not be created");
                    }
                }
                catch (HttpError& e)
                {
                    std::cout << "HTTP error: " << e.what() << std::endl;
                    error(e.code(), e.what());
                }
                catch (std::exception& e)
                {
                    std::cout << "Caught: " << e.what() << std::endl;
                    error(HttpStatusCode::client_error_bad_request, e.what());
                }
                catch (...)
                {
                    std::cout << "Caught unknown error" << std::endl;
                    error(
                            HttpStatusCode::server_error_internal_server_error,
                            "Internal server error");
                }
            });
        };
    }

    void start() { m_server.start(); }
    void stop() { m_server.stop(); m_pool.join(); }
    unsigned int port() const { return m_server.config.port; }

private:
    Manager& m_manager;
    S m_server;

    entwine::Pool m_pool;
};

} // namespace greyhound

<commit_msg>Add query timeouts and some logging.<commit_after>#pragma once

#include <entwine/util/pool.hpp>

#include <greyhound/defs.hpp>
#include <greyhound/manager.hpp>

namespace greyhound
{

template<typename S>
class Router
{
    using Req = typename S::Request;
    using Res = typename S::Response;
    using ReqPtr = std::shared_ptr<typename S::Request>;
    using ResPtr = std::shared_ptr<typename S::Response>;

public:
    template<typename... Args>
    Router(Manager& manager, unsigned int port, Args&&... args)
        : m_manager(manager)
        , m_server(std::forward<Args>(args)...)
        , m_pool(m_manager.threads())
    {
        m_server.config.port = port;
        m_server.config.timeout_request = 30;
        m_server.config.timeout_content = 120;

        m_server.default_resource["GET"] = [](ResPtr res, ReqPtr req)
        {
            res->write(HttpStatusCode::client_error_not_found);
        };

        m_server.on_error = [](ReqPtr req, const SimpleWeb::error_code& ec)
        {
            if (
                    ec &&
                    ec != SimpleWeb::errc::operation_canceled &&
                    ec != SimpleWeb::errc::broken_pipe &&
                    ec != SimpleWeb::asio::error::eof)
            {
                std::cout << "Error " << ec << ": " << ec.message() <<
                    std::endl;
            }
        };
    }

    template<typename F>
    void get(std::string match, F f) { route("GET", match, f); }

    template<typename F>
    void put(std::string match, F f) { route("PUT", match, f); }

    template<typename F>
    void route(std::string method, std::string match, F f)
    {
        m_server.resource[match][method] = [this, &f](ResPtr res, ReqPtr req)
        {
            // res->close_connection_after_response = true;
            m_pool.add([this, &f, req, res]() mutable
            {
                auto error(
                        [this, &res](HttpStatusCode code, std::string message)
                {
                    // Don't cache errors.  This is a multi-map, so remove any
                    // existing Cache-Control setting.
                    Headers h(m_manager.headers());
                    for (auto it(h.begin()); it != h.end(); )
                    {
                        if (it->first == "Cache-Control") it = h.erase(it);
                        else ++it;
                    }

                    h.emplace("Cache-Control", "public, max-age=0");
                    res->write(code, message, h);
                });

                try
                {
                    const std::string name(req->path_match[1]);
                    if (auto resource = m_manager.get(name, *req))
                    {
                        f(*resource, *req, *res);
                    }
                    else
                    {
                        throw HttpError(
                                HttpStatusCode::client_error_not_found,
                                name + " could not be created");
                    }
                }
                catch (HttpError& e)
                {
                    std::cout << "HTTP error: " << e.what() << std::endl;
                    error(e.code(), e.what());
                }
                catch (std::exception& e)
                {
                    std::cout << "Caught: " << e.what() << std::endl;
                    error(HttpStatusCode::client_error_bad_request, e.what());
                }
                catch (...)
                {
                    std::cout << "Caught unknown error" << std::endl;
                    error(
                            HttpStatusCode::server_error_internal_server_error,
                            "Internal server error");
                }

                res.reset();
                req.reset();
                if (res) std::cout << "Nonzero res" << std::endl;
                if (req) std::cout << "Nonzero req" << std::endl;
            });
        };
    }

    void start() { m_server.start(); }
    void stop() { m_server.stop(); m_pool.join(); }
    unsigned int port() const { return m_server.config.port; }

private:
    Manager& m_manager;
    S m_server;

    entwine::Pool m_pool;
};

} // namespace greyhound

<|endoftext|>