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

#include "string.hh"

#include "colors.h"

#include <cmath>              // for std::log, std::pow
#include <vector>             // for std::vector

class Humanize {
	long double base;
	long double div;
	std::vector<long double> scaling;
	std::vector<std::string> units;
	std::vector<std::string> colors;
	int needle;

public:
	Humanize(
		long double base_,
		std::vector<long double>&& scaling_,
		std::vector<std::string>&& units_,
		std::vector<std::string>&& colors_
	) :
		base(base_),
		div(std::log(base)),
		scaling(std::move(scaling_)),
		units(std::move(units_)),
		colors(std::move(colors_)),
		needle(std::distance(scaling.begin(), std::find(scaling.begin(), scaling.end(), 1)))
	{}

	std::string operator()(long double delta, const char* prefix, bool colored, long double rounding) const {
		long double num = delta;
		auto n = units.size();

		if (delta < 0) {
			delta = -delta;
		}
		size_t order = (delta == 0) ? n : -std::floor(std::log(delta) / div);
		order += needle;
		if (order < 0) {
			order = 0;
		} else if (order > n) {
			order = n;
		}

		num = std::round(rounding * num / scaling[order]) / rounding;
		auto& unit = units[order];

		if (colored) {
			auto& color = colors[order];
			auto& reset = colors[n + 1];
			return string::format("%s%s%s%s%s", color, prefix, string::Number(static_cast<double>(num)), unit, reset);
		}

		return string::format("%s%s%s", prefix, string::Number(static_cast<double>(num)), unit);
	}

};

// MEDIUM_SEA_GREEN  -> rgb(60, 179, 113)
// MEDIUM_SEA_GREEN  -> rgb(60, 179, 113)
// SEA_GREEN         -> rgb(46, 139, 87);
// OLIVE_DRAB        -> rgb(107, 142, 35)
// OLIVE             -> rgb(128, 128, 0)
// DARK_GOLDEN_ROD   -> rgb(184, 134, 11);
// PERU              -> rgb(205, 133, 63);
// SADDLE_BROWN      -> rgb(139, 69, 19);
// BROWN             -> rgb(165, 42, 42);

static inline std::string _from_bytes(size_t bytes, const char* prefix, bool colored) {
	static const Humanize humanize(
		1024,
		{ std::pow(1024, 8), std::pow(1024, 7), std::pow(1024, 6), std::pow(1024, 5), std::pow(1024, 4), std::pow(1024, 3), std::pow(1024, 2), std::pow(1024, 1), 1 },
		{ "YiB", "ZiB", "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" },
		{ BROWN, BROWN, BROWN, BROWN, BROWN, PERU, OLIVE, SEA_GREEN, MEDIUM_SEA_GREEN, CLEAR_COLOR }
	);
	return humanize(bytes, prefix, colored, 10.0L);
}

std::string string::from_bytes(size_t bytes, const char* prefix, bool colored) {
	return _from_bytes(bytes, prefix, colored);
}

static inline std::string _from_small_time(long double seconds, const char* prefix, bool colored) {
	static const Humanize humanize(
		1000,
		{ 1, std::pow(1000, -1), std::pow(1000, -2), std::pow(1000, -3), std::pow(1000, -4) },
		{ "s", "ms", R"(µs)", "ns", "ps" },
		{ OLIVE, OLIVE_DRAB, SEA_GREEN, MEDIUM_SEA_GREEN, MEDIUM_SEA_GREEN, CLEAR_COLOR }
	);
	return humanize(seconds, prefix, colored, 1000.0L);
}

std::string string::from_small_time(long double seconds, const char* prefix, bool colored) {
	return _from_small_time(seconds, prefix, colored);
}

static inline std::string _from_time(long double seconds, const char* prefix, bool colored) {
	static const Humanize humanize(
		60,
		{ std::pow(60, 2), std::pow(60, 1), 1 },
		{ "hrs", "min", "s" },
		{ SADDLE_BROWN, PERU, DARK_GOLDEN_ROD, CLEAR_COLOR }
	);
	return humanize(seconds, prefix, colored, 100.0L);
}

std::string string::from_time(long double seconds, const char* prefix, bool colored) {
	return _from_time(seconds, prefix, colored);
}

static inline std::string _from_delta(long double nanoseconds, const char* prefix, bool colored) {
	long double seconds = nanoseconds / 1e9;  // convert nanoseconds to seconds (as a double)
	return (seconds < 1) ? _from_small_time(seconds, prefix, colored) : _from_time(seconds, prefix, colored);
}

std::string string::from_delta(long double nanoseconds, const char* prefix, bool colored) {
	return _from_delta(nanoseconds, prefix, colored);
}

std::string string::from_delta(const std::chrono::time_point<std::chrono::system_clock>& start, const std::chrono::time_point<std::chrono::system_clock>& end, const char* prefix, bool colored) {
	return _from_delta(std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(), prefix, colored);
}
<commit_msg>Humanize: Simplify API<commit_after>/*
 * Copyright (C) 2015-2018 Dubalu LLC. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "string.hh"

#include "colors.h"

#include <cmath>              // for std::log, std::pow
#include <vector>             // for std::vector

class Humanize {
	long double base;
	long double div;
	std::vector<long double> scaling;
	std::vector<std::string> units;
	std::vector<std::string> colors;
	int needle;

public:
	Humanize(
		long double base_,
		std::vector<long double>&& scaling_,
		std::vector<std::string>&& units_,
		std::vector<std::string>&& colors_
	) :
		base(base_),
		div(std::log(base)),
		scaling(std::move(scaling_)),
		units(std::move(units_)),
		colors(std::move(colors_)),
		needle(std::distance(scaling.begin(), std::find(scaling.begin(), scaling.end(), 0)))
	{
		std::transform(scaling.begin(), scaling.end(), scaling.begin(), [&](long double s) {
			return std::pow(base, s);
		});
	}

	std::string operator()(long double delta, const char* prefix, bool colored, long double rounding) const {
		long double num = delta;
		auto n = units.size();

		if (delta < 0) {
			delta = -delta;
		}
		size_t order = (delta == 0) ? n : -std::floor(std::log(delta) / div);
		order += needle;
		if (order < 0) {
			order = 0;
		} else if (order > n) {
			order = n;
		}

		num = std::round(rounding * num / scaling[order]) / rounding;
		auto& unit = units[order];

		if (colored) {
			auto& color = colors[order];
			auto& reset = colors[n + 1];
			return string::format("%s%s%s%s%s", color, prefix, string::Number(static_cast<double>(num)), unit, reset);
		}

		return string::format("%s%s%s", prefix, string::Number(static_cast<double>(num)), unit);
	}

};

// MEDIUM_SEA_GREEN  -> rgb(60, 179, 113)
// MEDIUM_SEA_GREEN  -> rgb(60, 179, 113)
// SEA_GREEN         -> rgb(46, 139, 87);
// OLIVE_DRAB        -> rgb(107, 142, 35)
// OLIVE             -> rgb(128, 128, 0)
// DARK_GOLDEN_ROD   -> rgb(184, 134, 11);
// PERU              -> rgb(205, 133, 63);
// SADDLE_BROWN      -> rgb(139, 69, 19);
// BROWN             -> rgb(165, 42, 42);

static inline std::string _from_bytes(size_t bytes, const char* prefix, bool colored) {
	static const Humanize humanize(
		1024,
		{ 8, 7, 6, 5, 4, 3, 2, 1, 0 },
		{ "YiB", "ZiB", "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" },
		{ BROWN, BROWN, BROWN, BROWN, BROWN, PERU, OLIVE, SEA_GREEN, MEDIUM_SEA_GREEN, CLEAR_COLOR }
	);
	return humanize(bytes, prefix, colored, 10.0L);
}

std::string string::from_bytes(size_t bytes, const char* prefix, bool colored) {
	return _from_bytes(bytes, prefix, colored);
}

static inline std::string _from_small_time(long double seconds, const char* prefix, bool colored) {
	static const Humanize humanize(
		1000,
		{ 0, -1, -2, -3, -4 },
		{ "s", "ms", R"(µs)", "ns", "ps" },
		{ OLIVE, OLIVE_DRAB, SEA_GREEN, MEDIUM_SEA_GREEN, MEDIUM_SEA_GREEN, CLEAR_COLOR }
	);
	return humanize(seconds, prefix, colored, 1000.0L);
}

std::string string::from_small_time(long double seconds, const char* prefix, bool colored) {
	return _from_small_time(seconds, prefix, colored);
}

static inline std::string _from_time(long double seconds, const char* prefix, bool colored) {
	static const Humanize humanize(
		60,
		{ 2, 1, 0 },
		{ "hrs", "min", "s" },
		{ SADDLE_BROWN, PERU, DARK_GOLDEN_ROD, CLEAR_COLOR }
	);
	return humanize(seconds, prefix, colored, 100.0L);
}

std::string string::from_time(long double seconds, const char* prefix, bool colored) {
	return _from_time(seconds, prefix, colored);
}

static inline std::string _from_delta(long double nanoseconds, const char* prefix, bool colored) {
	long double seconds = nanoseconds / 1e9;  // convert nanoseconds to seconds (as a double)
	return (seconds < 1) ? _from_small_time(seconds, prefix, colored) : _from_time(seconds, prefix, colored);
}

std::string string::from_delta(long double nanoseconds, const char* prefix, bool colored) {
	return _from_delta(nanoseconds, prefix, colored);
}

std::string string::from_delta(const std::chrono::time_point<std::chrono::system_clock>& start, const std::chrono::time_point<std::chrono::system_clock>& end, const char* prefix, bool colored) {
	return _from_delta(std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(), prefix, colored);
}
<|endoftext|>


<commit_before>/*  This file is part of the Tufão project
    Copyright (C) 2012 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.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, see <http://www.gnu.org/licenses/>.
*/

#include "priv/simplesessionstore.h"
#include <QtCore/QUuid>

namespace Tufao {

SimpleSessionStore::SimpleSessionStore(const SessionSettings &settings,
                                       QObject *parent) :
    SessionStore(settings, parent),
    priv(new Priv)
{
    priv->timer.setInterval(DEFAULT_REFRESH_INTERVAL);
    connect(&priv->timer, SIGNAL(timeout()), this, SLOT(onTimer()));
    priv->timer.start();
}

SimpleSessionStore::~SimpleSessionStore()
{
    delete priv;
}

int SimpleSessionStore::refreshInterval() const
{
    return priv->timer.interval();
}

void SimpleSessionStore::setRefreshInterval(int msecs)
{
    priv->timer.setInterval(msecs);
}

bool SimpleSessionStore::hasSession(const HttpServerRequest &request) const
{
    QByteArray session(SessionStore::session(request));

    if (session.isEmpty() || !priv->lifetimeDatabase.contains(session))
        return false;

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return false;
    }

    return true;
}

void SimpleSessionStore::removeSession(const HttpServerRequest &request,
                                       HttpServerResponse &response)
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty())
        return;

    unsetSession(response);

    if (!priv->database.contains(session))
        return;

    priv->database.remove(session);
    priv->lifetimeDatabase.remove(session);
}

QList<QByteArray>
SimpleSessionStore::properties(const HttpServerRequest &request,
                               const HttpServerResponse &response) const
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->lifetimeDatabase.contains(session))
        return QList<QByteArray>();

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return QList<QByteArray>();
    }

    QList<QString> keys(priv->database[session].keys());
    QList<QByteArray> ret;

    ret.reserve(keys.size());

    for (int i = 0;i != keys.size();++i)
        ret += keys[i].toUtf8();

    return ret;
}

bool SimpleSessionStore::hasProperty(const HttpServerRequest &request,
                                     const HttpServerResponse &response,
                                     const QByteArray &key) const
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->lifetimeDatabase.contains(session))
        return false;

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return false;
    }

    return priv->database[session].contains(key);
}

QVariant SimpleSessionStore::property(const HttpServerRequest &request,
                                      HttpServerResponse &response,
                                      const QByteArray &key) const
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty())
        return QVariant();

    if (!priv->lifetimeDatabase.contains(session)) {
        // possibly avoid useless future queries
        unsetSession(response);

        return QVariant();
    }

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return QVariant();
    }

    // change session expire time
    priv->lifetimeDatabase[session]
        = QDateTime::currentDateTimeUtc().addSecs(settings.timeout * 60);

    // update cookie (expire time)
    setSession(response, session);

    const QVariantMap &sessionData(priv->database[session]);

    if (!sessionData.contains(key))
        return QVariant();

    return sessionData[key];
}

void SimpleSessionStore::setProperty(const HttpServerRequest &request,
                                     HttpServerResponse &response,
                                     const QByteArray &key,
                                     const QVariant &value)
{
    // init session variable
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->database.contains(session))
        session = createSession();

    // set property
    priv->database[session][key] = value;

    // change session expire time
    priv->lifetimeDatabase[session]
        = QDateTime::currentDateTimeUtc().addSecs(settings.timeout * 60);

    // create, if not set yet, and update cookie (expire time)
    setSession(response, session);
}

void SimpleSessionStore::removeProperty(const HttpServerRequest &request,
                                        HttpServerResponse &response,
                                        const QByteArray &key)
{
    // init session variable
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->database.contains(session))
        return;

    // remove property
    priv->database[session].remove(key);

    // change session expire time
    priv->lifetimeDatabase[session]
        = QDateTime::currentDateTimeUtc().addSecs(settings.timeout * 60);

    // update cookie (expire time)
    setSession(response, session);
}

SimpleSessionStore &SimpleSessionStore::defaultInstance()
{
    static SimpleSessionStore instance;
    return instance;
}

void SimpleSessionStore::onTimer()
{
    QHash<QByteArray, QDateTime>::iterator i(priv->lifetimeDatabase.begin());
    while (i != priv->lifetimeDatabase.end()) {
        if (i.value() <= QDateTime::currentDateTimeUtc()) {
            priv->database.remove(i.key());
            i = priv->lifetimeDatabase.erase(i);
            continue;
        }

        ++i;
    }
}

inline QByteArray SimpleSessionStore::createSession() const
{
    return QUuid::createUuid().toByteArray();
}

} // namespace Tufao
<commit_msg>restored compatibility with qt 4.7<commit_after>/*  This file is part of the Tufão project
    Copyright (C) 2012 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.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, see <http://www.gnu.org/licenses/>.
*/

#include "priv/simplesessionstore.h"
#include <QtCore/QUuid>

namespace Tufao {

SimpleSessionStore::SimpleSessionStore(const SessionSettings &settings,
                                       QObject *parent) :
    SessionStore(settings, parent),
    priv(new Priv)
{
    priv->timer.setInterval(DEFAULT_REFRESH_INTERVAL);
    connect(&priv->timer, SIGNAL(timeout()), this, SLOT(onTimer()));
    priv->timer.start();
}

SimpleSessionStore::~SimpleSessionStore()
{
    delete priv;
}

int SimpleSessionStore::refreshInterval() const
{
    return priv->timer.interval();
}

void SimpleSessionStore::setRefreshInterval(int msecs)
{
    priv->timer.setInterval(msecs);
}

bool SimpleSessionStore::hasSession(const HttpServerRequest &request) const
{
    QByteArray session(SessionStore::session(request));

    if (session.isEmpty() || !priv->lifetimeDatabase.contains(session))
        return false;

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return false;
    }

    return true;
}

void SimpleSessionStore::removeSession(const HttpServerRequest &request,
                                       HttpServerResponse &response)
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty())
        return;

    unsetSession(response);

    if (!priv->database.contains(session))
        return;

    priv->database.remove(session);
    priv->lifetimeDatabase.remove(session);
}

QList<QByteArray>
SimpleSessionStore::properties(const HttpServerRequest &request,
                               const HttpServerResponse &response) const
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->lifetimeDatabase.contains(session))
        return QList<QByteArray>();

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return QList<QByteArray>();
    }

    QList<QString> keys(priv->database[session].keys());
    QList<QByteArray> ret;

    ret.reserve(keys.size());

    for (int i = 0;i != keys.size();++i)
        ret += keys[i].toUtf8();

    return ret;
}

bool SimpleSessionStore::hasProperty(const HttpServerRequest &request,
                                     const HttpServerResponse &response,
                                     const QByteArray &key) const
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->lifetimeDatabase.contains(session))
        return false;

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return false;
    }

    return priv->database[session].contains(key);
}

QVariant SimpleSessionStore::property(const HttpServerRequest &request,
                                      HttpServerResponse &response,
                                      const QByteArray &key) const
{
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty())
        return QVariant();

    if (!priv->lifetimeDatabase.contains(session)) {
        // possibly avoid useless future queries
        unsetSession(response);

        return QVariant();
    }

    // expired session...
    if (priv->lifetimeDatabase[session] <= QDateTime::currentDateTimeUtc()) {
        priv->lifetimeDatabase.remove(session);
        priv->database.remove(session);
        return QVariant();
    }

    // change session expire time
    priv->lifetimeDatabase[session]
        = QDateTime::currentDateTimeUtc().addSecs(settings.timeout * 60);

    // update cookie (expire time)
    setSession(response, session);

    const QVariantMap &sessionData(priv->database[session]);

    if (!sessionData.contains(key))
        return QVariant();

    return sessionData[key];
}

void SimpleSessionStore::setProperty(const HttpServerRequest &request,
                                     HttpServerResponse &response,
                                     const QByteArray &key,
                                     const QVariant &value)
{
    // init session variable
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->database.contains(session))
        session = createSession();

    // set property
    priv->database[session][key] = value;

    // change session expire time
    priv->lifetimeDatabase[session]
        = QDateTime::currentDateTimeUtc().addSecs(settings.timeout * 60);

    // create, if not set yet, and update cookie (expire time)
    setSession(response, session);
}

void SimpleSessionStore::removeProperty(const HttpServerRequest &request,
                                        HttpServerResponse &response,
                                        const QByteArray &key)
{
    // init session variable
    QByteArray session(SessionStore::session(request, response));

    if (session.isEmpty() || !priv->database.contains(session))
        return;

    // remove property
    priv->database[session].remove(key);

    // change session expire time
    priv->lifetimeDatabase[session]
        = QDateTime::currentDateTimeUtc().addSecs(settings.timeout * 60);

    // update cookie (expire time)
    setSession(response, session);
}

SimpleSessionStore &SimpleSessionStore::defaultInstance()
{
    static SimpleSessionStore instance;
    return instance;
}

void SimpleSessionStore::onTimer()
{
    QHash<QByteArray, QDateTime>::iterator i(priv->lifetimeDatabase.begin());
    while (i != priv->lifetimeDatabase.end()) {
        if (i.value() <= QDateTime::currentDateTimeUtc()) {
            priv->database.remove(i.key());
            i = priv->lifetimeDatabase.erase(i);
            continue;
        }

        ++i;
    }
}

inline QByteArray SimpleSessionStore::createSession() const
{
#if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
    return static_cast<QString>(QUuid::createUuid()).toUtf8();
#else
    return QUuid::createUuid().toByteArray();
#endif
}

} // namespace Tufao
<|endoftext|>


<commit_before>/* Copyright 2020 Google Inc. All Rights Reserved.

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 "tensorflow_serving/servables/tensorflow/saved_model_warmup_util.h"

#include "google/protobuf/wrappers.pb.h"
#include "tensorflow/cc/saved_model/constants.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/io/record_reader.h"
#include "tensorflow/core/lib/monitoring/sampler.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow_serving/util/threadpool_executor.h"

namespace tensorflow {
namespace serving {
namespace internal {
namespace {

auto* model_warm_up_latency = monitoring::Sampler<2>::New(
    {
        "/tensorflow/serving/model_warmup_latency",
        "Distribution of wall time (in microseconds) for warming up the model.",
        "model_path",
        "status",
    },  // Scale of 10, power of 1.8 with bucket count 33 (~20 minutes).
    monitoring::Buckets::Exponential(10, 1.8, 33));

uint64_t GetLatencyMicroseconds(const uint64_t start_microseconds) {
  const uint64_t end_microseconds = EnvTime::NowMicros();
  // Avoid clock skew.
  if (end_microseconds < start_microseconds) return 0;
  return end_microseconds - start_microseconds;
}

}  // namespace

constexpr char WarmupConsts::kRequestsFileName[];
constexpr int WarmupConsts::kMaxNumRecords;

Status RunSavedModelWarmup(
    const ModelWarmupOptions& model_warmup_options, const string export_dir,
    std::function<Status(PredictionLog)> warmup_request_executor) {
  const uint64_t start_microseconds = EnvTime::NowMicros();
  const string warmup_path =
      io::JoinPath(export_dir, kSavedModelAssetsExtraDirectory,
                   WarmupConsts::kRequestsFileName);
  if (!tensorflow::Env::Default()->FilesExist({warmup_path}, nullptr)) {
    LOG(INFO) << "No warmup data file found at " << warmup_path;
    // Having warmup data is optional, return OK
    return Status::OK();
  }
  const int num_request_iterations = [&]() {
    if (model_warmup_options.has_num_request_iterations()) {
      return model_warmup_options.num_request_iterations().value();
    }
    // Default of 1.
    return 1;
  }();
  LOG(INFO) << "Starting to read warmup data for model at " << warmup_path
            << " with model-warmup-options "
            << model_warmup_options.DebugString();
  std::unique_ptr<tensorflow::RandomAccessFile> tf_record_file;
  TF_RETURN_IF_ERROR(tensorflow::Env::Default()->NewRandomAccessFile(
      warmup_path, &tf_record_file));

  int num_model_warmup_threads =
      model_warmup_options.has_num_model_warmup_threads()
          ? std::max(model_warmup_options.num_model_warmup_threads().value(), 1)
          : 1;

  struct SharedState {
    ::tensorflow::mutex mu;
    int num_thread_task_done ABSL_GUARDED_BY(mu){0};
    int num_warmup_records ABSL_GUARDED_BY(mu){0};
    ::tensorflow::Status warm_up_status ABSL_GUARDED_BY(mu);
    // Condition variable to wait until all scheduled warmup tasks are executed.
    ::tensorflow::condition_variable done ABSL_GUARDED_BY(mu);
    std::unique_ptr<tensorflow::io::SequentialRecordReader>
        tf_record_file_reader ABSL_GUARDED_BY(mu);
  };
  const auto state = std::make_shared<SharedState>();

  std::unique_ptr<Executor> executor;
  std::unique_ptr<tensorflow::io::SequentialRecordReader> tf_record_file_reader;
  Status status;
  int num_warmup_records = 0;
  if (num_model_warmup_threads <= 1) {
    tf_record_file_reader.reset(
        new tensorflow::io::SequentialRecordReader(tf_record_file.get()));
    tstring record;
    status = tf_record_file_reader->ReadRecord(&record);
    tensorflow::serving::PredictionLog prediction_log;
    while (status.ok()) {
      if (!prediction_log.ParseFromArray(record.data(), record.size())) {
        return errors::InvalidArgument(strings::StrCat(
            "Failed to parse warmup record: ", record, " from ", warmup_path));
      }

      for (int i = 0; i < num_request_iterations; ++i) {
        TF_RETURN_IF_ERROR(warmup_request_executor(prediction_log));
      }
      ++num_warmup_records;
      if (num_warmup_records > WarmupConsts::kMaxNumRecords) {
        return errors::InvalidArgument(
            "Number of warmup records exceeds the maximum (",
            WarmupConsts::kMaxNumRecords, ") at ", warmup_path);
      }
      status = tf_record_file_reader->ReadRecord(&record);
    }
  } else {
    executor.reset(new ThreadPoolExecutor(Env::Default(), "Warmup_ThreadPool",
                                          num_model_warmup_threads));
    {
      ::tensorflow::mutex_lock lock(state->mu);
      state->tf_record_file_reader.reset(
          new tensorflow::io::SequentialRecordReader(tf_record_file.get()));
    }
    for (int i = 0; i < num_model_warmup_threads; ++i) {
      executor->Schedule([state, num_request_iterations,
                          warmup_request_executor, warmup_path,
                          num_model_warmup_threads]() {
        Status status = OkStatus();
        while (status.ok()) {
          tstring record;
          Status execution_status;
          tensorflow::serving::PredictionLog prediction_log;
          {
            ::tensorflow::mutex_lock lock(state->mu);
            if (state->num_warmup_records > WarmupConsts::kMaxNumRecords) {
              state->warm_up_status = errors::InvalidArgument(
                  "Number of warmup records exceeds the maximum (",
                  WarmupConsts::kMaxNumRecords, ") at ", warmup_path);
              break;
            }
            if (!state->warm_up_status.ok()) {
              break;
            }
            execution_status =
                state->tf_record_file_reader->ReadRecord(&record);
            if (!execution_status.ok()) {
              state->warm_up_status = execution_status;
              break;
            }
            if (!prediction_log.ParseFromArray(record.data(), record.size())) {
              state->warm_up_status = errors::InvalidArgument(
                  strings::StrCat("Failed to parse warmup record: ", record,
                                  " from ", warmup_path));
              break;
            }
          }
          for (int i = 0; i < num_request_iterations; ++i) {
            execution_status = warmup_request_executor(prediction_log);
            if (!execution_status.ok()) {
              ::tensorflow::mutex_lock lock(state->mu);
              state->warm_up_status = execution_status;
              break;
            }
          }
          ::tensorflow::mutex_lock lock(state->mu);
          ++state->num_warmup_records;
          status = state->warm_up_status;
        }
        ::tensorflow::mutex_lock lock(state->mu);
        if (++state->num_thread_task_done == num_model_warmup_threads) {
          state->done.notify_one();
        }
      });
    }
    // Wait until all scheduled work are done.
    ::tensorflow::mutex_lock lock(state->mu);
    while (state->num_thread_task_done < num_model_warmup_threads) {
      state->done.wait(lock);
    }
    status = state->warm_up_status;
    num_warmup_records = state->num_warmup_records;
  }
  // OUT_OF_RANGE error means EOF was reached, re-write it to OK; in this way
  // the 'model_warm_up_latency' metric below records OK upon successful
  // warm-up.
  if (errors::IsOutOfRange(status)) {
    status = Status::OK();
  }

  const auto warmup_latency = GetLatencyMicroseconds(start_microseconds);
  model_warm_up_latency->GetCell(export_dir, status.ToString())
      ->Add(warmup_latency);

  if (errors::IsDataLoss(status)) {
    return errors::DataLoss(
        status.error_message(),
        ". Please verify your warmup data is in TFRecord format.");
  }

  TF_RETURN_IF_ERROR(status);

  LOG(INFO) << "Finished reading warmup data for model at " << warmup_path
            << ". Number of warmup records read: " << num_warmup_records
            << ". Elapsed time (microseconds): " << warmup_latency << ".";
  return Status::OK();
}

}  // namespace internal
}  // namespace serving
}  // namespace tensorflow
<commit_msg>Internal change only<commit_after>/* Copyright 2020 Google Inc. All Rights Reserved.

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 "tensorflow_serving/servables/tensorflow/saved_model_warmup_util.h"

#include "google/protobuf/wrappers.pb.h"
#include "tensorflow/cc/saved_model/constants.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/io/record_reader.h"
#include "tensorflow/core/lib/monitoring/sampler.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow_serving/util/threadpool_executor.h"

namespace tensorflow {
namespace serving {
namespace internal {
namespace {

auto* model_warm_up_latency = monitoring::Sampler<2>::New(
    {
        "/tensorflow/serving/model_warmup_latency",
        "Distribution of wall time (in microseconds) for warming up the model.",
        "model_path",
        "status",
    },  // Scale of 10, power of 1.8 with bucket count 33 (~20 minutes).
    monitoring::Buckets::Exponential(10, 1.8, 33));

uint64_t GetLatencyMicroseconds(const uint64_t start_microseconds) {
  const uint64_t end_microseconds = EnvTime::NowMicros();
  // Avoid clock skew.
  if (end_microseconds < start_microseconds) return 0;
  return end_microseconds - start_microseconds;
}

}  // namespace

constexpr char WarmupConsts::kRequestsFileName[];
constexpr int WarmupConsts::kMaxNumRecords;

Status RunSavedModelWarmup(
    const ModelWarmupOptions& model_warmup_options, const string export_dir,
    std::function<Status(PredictionLog)> warmup_request_executor) {
  const uint64_t start_microseconds = EnvTime::NowMicros();
  const string warmup_path =
      io::JoinPath(export_dir, kSavedModelAssetsExtraDirectory,
                   WarmupConsts::kRequestsFileName);
  if (!tensorflow::Env::Default()->FilesExist({warmup_path}, nullptr)) {
    LOG(INFO) << "No warmup data file found at " << warmup_path;
    // Having warmup data is optional, return OK
    return Status::OK();
  }
  const int num_request_iterations = [&]() {
    if (model_warmup_options.has_num_request_iterations()) {
      return model_warmup_options.num_request_iterations().value();
    }
    // Default of 1.
    return 1;
  }();
  LOG(INFO) << "Starting to read warmup data for model at " << warmup_path
            << " with model-warmup-options "
            << model_warmup_options.DebugString();
  std::unique_ptr<tensorflow::RandomAccessFile> tf_record_file;
  TF_RETURN_IF_ERROR(tensorflow::Env::Default()->NewRandomAccessFile(
      warmup_path, &tf_record_file));

  int num_model_warmup_threads =
      model_warmup_options.has_num_model_warmup_threads()
          ? std::max(model_warmup_options.num_model_warmup_threads().value(), 1)
          : 1;
  std::unique_ptr<tensorflow::io::SequentialRecordReader> tf_record_file_reader;
  Status status;
  int num_warmup_records = 0;
  if (num_model_warmup_threads <= 1) {
    tf_record_file_reader.reset(
        new tensorflow::io::SequentialRecordReader(tf_record_file.get()));
    tstring record;
    status = tf_record_file_reader->ReadRecord(&record);
    tensorflow::serving::PredictionLog prediction_log;
    while (status.ok()) {
      if (!prediction_log.ParseFromArray(record.data(), record.size())) {
        return errors::InvalidArgument(strings::StrCat(
            "Failed to parse warmup record: ", record, " from ", warmup_path));
      }

      for (int i = 0; i < num_request_iterations; ++i) {
        TF_RETURN_IF_ERROR(warmup_request_executor(prediction_log));
      }
      ++num_warmup_records;
      if (num_warmup_records > WarmupConsts::kMaxNumRecords) {
        return errors::InvalidArgument(
            "Number of warmup records exceeds the maximum (",
            WarmupConsts::kMaxNumRecords, ") at ", warmup_path);
      }
      status = tf_record_file_reader->ReadRecord(&record);
    }
  } else {
    struct SharedState {
      ::tensorflow::mutex mu;
      int num_thread_task_done ABSL_GUARDED_BY(mu){0};
      int num_warmup_records ABSL_GUARDED_BY(mu){0};
      ::tensorflow::Status warm_up_status ABSL_GUARDED_BY(mu);
      // Condition variable to wait until all scheduled warmup tasks are
      // executed.
      ::tensorflow::condition_variable done ABSL_GUARDED_BY(mu);
      std::unique_ptr<tensorflow::io::SequentialRecordReader>
          tf_record_file_reader ABSL_GUARDED_BY(mu);
    };
    const auto state = std::make_shared<SharedState>();

    std::unique_ptr<Executor> executor;
    executor.reset(new ThreadPoolExecutor(Env::Default(), "Warmup_ThreadPool",
                                          num_model_warmup_threads));
    {
      ::tensorflow::mutex_lock lock(state->mu);
      state->tf_record_file_reader.reset(
          new tensorflow::io::SequentialRecordReader(tf_record_file.get()));
    }
    for (int i = 0; i < num_model_warmup_threads; ++i) {
      executor->Schedule([state, num_request_iterations,
                          warmup_request_executor, warmup_path,
                          num_model_warmup_threads]() {
        Status status = OkStatus();
        while (status.ok()) {
          tstring record;
          Status execution_status;
          tensorflow::serving::PredictionLog prediction_log;
          {
            ::tensorflow::mutex_lock lock(state->mu);
            if (state->num_warmup_records > WarmupConsts::kMaxNumRecords) {
              state->warm_up_status = errors::InvalidArgument(
                  "Number of warmup records exceeds the maximum (",
                  WarmupConsts::kMaxNumRecords, ") at ", warmup_path);
              break;
            }
            if (!state->warm_up_status.ok()) {
              break;
            }
            execution_status =
                state->tf_record_file_reader->ReadRecord(&record);
            if (!execution_status.ok()) {
              state->warm_up_status = execution_status;
              break;
            }
            if (!prediction_log.ParseFromArray(record.data(), record.size())) {
              state->warm_up_status = errors::InvalidArgument(
                  strings::StrCat("Failed to parse warmup record: ", record,
                                  " from ", warmup_path));
              break;
            }
          }
          for (int i = 0; i < num_request_iterations; ++i) {
            execution_status = warmup_request_executor(prediction_log);
            if (!execution_status.ok()) {
              ::tensorflow::mutex_lock lock(state->mu);
              state->warm_up_status = execution_status;
              break;
            }
          }
          ::tensorflow::mutex_lock lock(state->mu);
          ++state->num_warmup_records;
          status = state->warm_up_status;
        }
        ::tensorflow::mutex_lock lock(state->mu);
        if (++state->num_thread_task_done == num_model_warmup_threads) {
          state->done.notify_one();
        }
      });
    }
    // Wait until all scheduled work are done.
    ::tensorflow::mutex_lock lock(state->mu);
    while (state->num_thread_task_done < num_model_warmup_threads) {
      state->done.wait(lock);
    }
    status = state->warm_up_status;
    num_warmup_records = state->num_warmup_records;
  }
  // OUT_OF_RANGE error means EOF was reached, re-write it to OK; in this way
  // the 'model_warm_up_latency' metric below records OK upon successful
  // warm-up.
  if (errors::IsOutOfRange(status)) {
    status = Status::OK();
  }

  const auto warmup_latency = GetLatencyMicroseconds(start_microseconds);
  model_warm_up_latency->GetCell(export_dir, status.ToString())
      ->Add(warmup_latency);

  if (errors::IsDataLoss(status)) {
    return errors::DataLoss(
        status.error_message(),
        ". Please verify your warmup data is in TFRecord format.");
  }

  TF_RETURN_IF_ERROR(status);

  LOG(INFO) << "Finished reading warmup data for model at " << warmup_path
            << ". Number of warmup records read: " << num_warmup_records
            << ". Elapsed time (microseconds): " << warmup_latency << ".";
  return Status::OK();
}

}  // namespace internal
}  // namespace serving
}  // namespace tensorflow
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef CONTAINERS_ITERATORS_HPP_
#define CONTAINERS_ITERATORS_HPP_

#include <algorithm>
#include <functional>
#include <queue>
#include <set>
#include <vector>
#include <utility>

#include "utils.hpp"
#include <boost/function.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>

#include "containers/scoped.hpp"

template <typename T>
struct one_way_iterator_t {
    virtual ~one_way_iterator_t() { }
    virtual typename boost::optional<T> next() = 0; // next() can block until it can read the next value
    virtual void prefetch() = 0;    // Fetch all the necessary data to be able to give the next value without blocking.
                                    // prefetch() is assumed to be asynchronous. Thus if next() is called before the data
                                    // is available, next() can still block.
};

template <class T, class U>
struct transform_iterator_t : public one_way_iterator_t<U> {
    transform_iterator_t(const boost::function<U(T&)>& _func, one_way_iterator_t<T> *_ownee) : func(_func), ownee(_ownee) { }
    virtual ~transform_iterator_t() { }

    virtual typename boost::optional<U> next() {
        boost::optional<T> value = ownee->next();
        if (!value) {
            return boost::none;
        } else {
            return boost::make_optional(func(value.get()));
        }
    }
    void prefetch() {
        ownee->prefetch();
    }

    boost::function<U(T&)> func;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

template <class T>
struct filter_iterator_t : public one_way_iterator_t<T> {
    filter_iterator_t(const boost::function<bool(T&)>& _predicate, one_way_iterator_t<T> *_ownee) : predicate(_predicate), ownee(_ownee) { }  // NOLINT
    virtual ~filter_iterator_t() { }

    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                return boost::none;
            } else {
                if (predicate(value.get())) {
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // Unfortunately we don't feel like really implementing this
        // function right now.  It would require running the filter
        // operation on return values, consuming ahead into the
        // iterator.  Also some other one_way_iterator_t
        // implementations blow this off, so why not us.
        ownee->prefetch();
    }

    boost::function<bool(T&)> predicate;  // NOLINT
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

template <typename F, typename S, typename Cmp = std::less<F> >
struct first_greater {
    typedef F first_argument_type;
    typedef S second_argument_type;
    bool operator()(std::pair<F, S> l, std::pair<F, S> r) {
        return Cmp()(r.first, l.first);
    }
};

template <typename T, typename Cmp = std::less<T> >
class merge_ordered_data_iterator_t : public one_way_iterator_t<T> {
public:
    typedef boost::shared_ptr<one_way_iterator_t<T> > mergee_t;

    merge_ordered_data_iterator_t() : mergees(), next_to_pop_from(),
        merge_heap(first_greater<T, mergee_t, Cmp>(), std::vector<std::pair<T, mergee_t> >()) { }

    virtual ~merge_ordered_data_iterator_t() {
        done();
    }

    void add_mergee(mergee_t mergee) {
        rassert(!next_to_pop_from.get());
        mergees.insert(mergee);
    }

    void add_mergee(one_way_iterator_t<T> *mergee) {
        boost::shared_ptr<one_way_iterator_t<T> > _mergee(mergee);
        add_mergee(_mergee);
    }

    typename boost::optional<T> next() {
        // if we are getting the first element, we have to request the data from all of the mergees
        if (!next_to_pop_from.get()) {
            prefetch();
            for (typename std::set<mergee_t>::iterator it = mergees.begin(); it != mergees.end();) {
                mergee_t mergee = *it;
                typename boost::optional<T> mergee_next = mergee->next();
                if (mergee_next) {
                    merge_heap.push(std::make_pair(mergee_next.get(), mergee));
                    it++;
                } else {
                    mergee.reset();          // nothing more in this iterator, delete it
                    mergees.erase(it++);    // Note: this increments the iterator, erases the element
                                            // at the old iterator position, and then updates the 'it' value
                }
            }
        } else {
            typename boost::optional<T> next_val = next_to_pop_from->next();
            if (next_val) {
                merge_heap.push(std::make_pair(next_val.get(), next_to_pop_from));
            } else {
                mergees.erase(next_to_pop_from);
                next_to_pop_from.reset();    // relinquish our hold
            }
        }
        if (merge_heap.size() == 0) {
            done();
            return boost::none;
        }

        std::pair<T, mergee_t> top = merge_heap.top();
        merge_heap.pop();
        next_to_pop_from = top.second;

        // issue the async prefetch, so that we don't need to block on next has_next/next call
        next_to_pop_from->prefetch();
        return boost::make_optional(top.first);
    }
    void prefetch() {
        typename std::set<mergee_t>::iterator it;
        for (it = mergees.begin(); it != mergees.end(); it++) {
            (*it)->prefetch();
        }
    }
private:
    void done() {
        mergees.clear();
    }
    std::set<mergee_t> mergees;
    mergee_t next_to_pop_from;
    typename std::priority_queue<std::pair<T, mergee_t>, std::vector<std::pair<T, mergee_t> >, first_greater<T, mergee_t, Cmp> > merge_heap;

};

/*
unique_iterator_t removes duplicates. It requires the input iterator to be sorted.
T has to implement operator==().

Note: Union of sets can be implemented as a unque iterator around a merge iterator.
*/
template <class T>
class unique_filter_iterator_t : public one_way_iterator_t<T> {
public:
    explicit unique_filter_iterator_t(one_way_iterator_t<T> *_ownee) : previous(boost::none), ownee(_ownee) { }
    virtual ~unique_filter_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    previous = value;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

/* repetition_filter_iterator_t produces an element whenever it was repeated
n_repetitions times in the input iterator. T has to implement operator==().
If a element is repeated more than n_repetitions times, repetition_filter_iterator_t
will output the element once per n_repetitions repetitions.

Note: Intersection of sets can be implemented as a repetition iterator around a merge iterator,
 where n_repetitions must be set to the number of input sets. This works as
 long as the input iterators are sorted and don't produce any element more than once.
 */
template <class T>
class repetition_filter_iterator_t : public one_way_iterator_t<T> {
public:
    repetition_filter_iterator_t(one_way_iterator_t<T> *_ownee, int _n_repetitions) : previous(boost::none), previous_repetitions(0), ownee(_ownee), n_repetitions(_n_repetitions) {
        rassert(n_repetitions > 0);
    }
    virtual ~repetition_filter_iterator_t() { }

    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                previous_repetitions = 0;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    // Different, start over
                    previous_repetitions = 1;
                    previous = value;
                } else {
                    // The same, increment counter
                    ++previous_repetitions;
                }

                // Have we got enough repetitions?
                rassert(previous_repetitions <= n_repetitions);
                if (previous_repetitions == n_repetitions) {
                    previous_repetitions = 0;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    int previous_repetitions;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
    int n_repetitions;
};

#endif /* CONTAINERS_ITERATORS_HPP_ */
<commit_msg>Made merge_ordered_data_iterator_t use std::shared_ptr instead of boost::shared_ptr.<commit_after>// Copyright 2010-2013 RethinkDB, all rights reserved.
#ifndef CONTAINERS_ITERATORS_HPP_
#define CONTAINERS_ITERATORS_HPP_

#include <algorithm>
#include <functional>
#include <memory>
#include <queue>
#include <set>
#include <vector>
#include <utility>

#include "utils.hpp"
#include <boost/function.hpp>
#include <boost/optional.hpp>

#include "containers/scoped.hpp"

template <typename T>
struct one_way_iterator_t {
    virtual ~one_way_iterator_t() { }
    virtual typename boost::optional<T> next() = 0; // next() can block until it can read the next value
    virtual void prefetch() = 0;    // Fetch all the necessary data to be able to give the next value without blocking.
                                    // prefetch() is assumed to be asynchronous. Thus if next() is called before the data
                                    // is available, next() can still block.
};

template <class T, class U>
struct transform_iterator_t : public one_way_iterator_t<U> {
    transform_iterator_t(const boost::function<U(T&)>& _func, one_way_iterator_t<T> *_ownee) : func(_func), ownee(_ownee) { }
    virtual ~transform_iterator_t() { }

    virtual typename boost::optional<U> next() {
        boost::optional<T> value = ownee->next();
        if (!value) {
            return boost::none;
        } else {
            return boost::make_optional(func(value.get()));
        }
    }
    void prefetch() {
        ownee->prefetch();
    }

    boost::function<U(T&)> func;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

template <class T>
struct filter_iterator_t : public one_way_iterator_t<T> {
    filter_iterator_t(const boost::function<bool(T&)>& _predicate, one_way_iterator_t<T> *_ownee) : predicate(_predicate), ownee(_ownee) { }  // NOLINT
    virtual ~filter_iterator_t() { }

    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                return boost::none;
            } else {
                if (predicate(value.get())) {
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // Unfortunately we don't feel like really implementing this
        // function right now.  It would require running the filter
        // operation on return values, consuming ahead into the
        // iterator.  Also some other one_way_iterator_t
        // implementations blow this off, so why not us.
        ownee->prefetch();
    }

    boost::function<bool(T&)> predicate;  // NOLINT
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

template <typename F, typename S, typename Cmp = std::less<F> >
struct first_greater {
    typedef F first_argument_type;
    typedef S second_argument_type;
    bool operator()(std::pair<F, S> l, std::pair<F, S> r) {
        return Cmp()(r.first, l.first);
    }
};

template <typename T, typename Cmp = std::less<T> >
class merge_ordered_data_iterator_t : public one_way_iterator_t<T> {
public:
    typedef std::shared_ptr<one_way_iterator_t<T> > mergee_t;

    merge_ordered_data_iterator_t() : mergees(), next_to_pop_from(),
        merge_heap(first_greater<T, mergee_t, Cmp>(), std::vector<std::pair<T, mergee_t> >()) { }

    virtual ~merge_ordered_data_iterator_t() {
        done();
    }

    void add_mergee(mergee_t mergee) {
        rassert(!next_to_pop_from.get());
        mergees.insert(mergee);
    }

    void add_mergee(one_way_iterator_t<T> *mergee) {
        std::shared_ptr<one_way_iterator_t<T> > _mergee(mergee);
        add_mergee(_mergee);
    }

    typename boost::optional<T> next() {
        // if we are getting the first element, we have to request the data from all of the mergees
        if (!next_to_pop_from.get()) {
            prefetch();
            for (typename std::set<mergee_t>::iterator it = mergees.begin(); it != mergees.end();) {
                mergee_t mergee = *it;
                typename boost::optional<T> mergee_next = mergee->next();
                if (mergee_next) {
                    merge_heap.push(std::make_pair(mergee_next.get(), mergee));
                    it++;
                } else {
                    mergee.reset();          // nothing more in this iterator, delete it
                    mergees.erase(it++);    // Note: this increments the iterator, erases the element
                                            // at the old iterator position, and then updates the 'it' value
                }
            }
        } else {
            typename boost::optional<T> next_val = next_to_pop_from->next();
            if (next_val) {
                merge_heap.push(std::make_pair(next_val.get(), next_to_pop_from));
            } else {
                mergees.erase(next_to_pop_from);
                next_to_pop_from.reset();    // relinquish our hold
            }
        }
        if (merge_heap.size() == 0) {
            done();
            return boost::none;
        }

        std::pair<T, mergee_t> top = merge_heap.top();
        merge_heap.pop();
        next_to_pop_from = top.second;

        // issue the async prefetch, so that we don't need to block on next has_next/next call
        next_to_pop_from->prefetch();
        return boost::make_optional(top.first);
    }
    void prefetch() {
        typename std::set<mergee_t>::iterator it;
        for (it = mergees.begin(); it != mergees.end(); it++) {
            (*it)->prefetch();
        }
    }
private:
    void done() {
        mergees.clear();
    }
    std::set<mergee_t> mergees;
    mergee_t next_to_pop_from;
    typename std::priority_queue<std::pair<T, mergee_t>, std::vector<std::pair<T, mergee_t> >, first_greater<T, mergee_t, Cmp> > merge_heap;

};

/*
unique_iterator_t removes duplicates. It requires the input iterator to be sorted.
T has to implement operator==().

Note: Union of sets can be implemented as a unque iterator around a merge iterator.
*/
template <class T>
class unique_filter_iterator_t : public one_way_iterator_t<T> {
public:
    explicit unique_filter_iterator_t(one_way_iterator_t<T> *_ownee) : previous(boost::none), ownee(_ownee) { }
    virtual ~unique_filter_iterator_t() {
        delete ownee;
    }
    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    previous = value;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
};

/* repetition_filter_iterator_t produces an element whenever it was repeated
n_repetitions times in the input iterator. T has to implement operator==().
If a element is repeated more than n_repetitions times, repetition_filter_iterator_t
will output the element once per n_repetitions repetitions.

Note: Intersection of sets can be implemented as a repetition iterator around a merge iterator,
 where n_repetitions must be set to the number of input sets. This works as
 long as the input iterators are sorted and don't produce any element more than once.
 */
template <class T>
class repetition_filter_iterator_t : public one_way_iterator_t<T> {
public:
    repetition_filter_iterator_t(one_way_iterator_t<T> *_ownee, int _n_repetitions) : previous(boost::none), previous_repetitions(0), ownee(_ownee), n_repetitions(_n_repetitions) {
        rassert(n_repetitions > 0);
    }
    virtual ~repetition_filter_iterator_t() { }

    virtual typename boost::optional<T> next() {
        for (;;) {
            boost::optional<T> value = ownee->next();
            if (!value) {
                previous = value;
                previous_repetitions = 0;
                return boost::none;
            } else {
                // Is this element different from what we had before?
                if (!previous || !(previous.get() == value.get())) {
                    // Different, start over
                    previous_repetitions = 1;
                    previous = value;
                } else {
                    // The same, increment counter
                    ++previous_repetitions;
                }

                // Have we got enough repetitions?
                rassert(previous_repetitions <= n_repetitions);
                if (previous_repetitions == n_repetitions) {
                    previous_repetitions = 0;
                    return value;
                }
                // otherwise, continue.
            }
        }
    }
    void prefetch() {
        // TODO: Should we implement this?
        ownee->prefetch();
    }

private:
    boost::optional<T> previous;
    int previous_repetitions;
    scoped_ptr_t<one_way_iterator_t<T> > ownee;
    int n_repetitions;
};

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


<commit_before>/*
* SHA-3
* (C) 2010,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/sha3.h>
#include <botan/exceptn.h>

namespace Botan {

//static
void SHA_3::permute(uint64_t A[25])
   {
   static const uint64_t RC[24] = {
      0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
      0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
      0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
      0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
      0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
      0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
      0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
      0x8000000000008080, 0x0000000080000001, 0x8000000080008008
   };

   for(size_t i = 0; i != 24; ++i)
      {
      const uint64_t C0 = A[0] ^ A[5] ^ A[10] ^ A[15] ^ A[20];
      const uint64_t C1 = A[1] ^ A[6] ^ A[11] ^ A[16] ^ A[21];
      const uint64_t C2 = A[2] ^ A[7] ^ A[12] ^ A[17] ^ A[22];
      const uint64_t C3 = A[3] ^ A[8] ^ A[13] ^ A[18] ^ A[23];
      const uint64_t C4 = A[4] ^ A[9] ^ A[14] ^ A[19] ^ A[24];

      const uint64_t D0 = rotl<1>(C0) ^ C3;
      const uint64_t D1 = rotl<1>(C1) ^ C4;
      const uint64_t D2 = rotl<1>(C2) ^ C0;
      const uint64_t D3 = rotl<1>(C3) ^ C1;
      const uint64_t D4 = rotl<1>(C4) ^ C2;

      const uint64_t B00 = A[ 0] ^ D1;
      const uint64_t B10 = rotl<1>(A[ 1] ^ D2);
      const uint64_t B20 = rotl<62>(A[ 2] ^ D3);
      const uint64_t B05 = rotl<28>(A[ 3] ^ D4);
      const uint64_t B15 = rotl<27>(A[ 4] ^ D0);
      const uint64_t B16 = rotl<36>(A[ 5] ^ D1);
      const uint64_t B01 = rotl<44>(A[ 6] ^ D2);
      const uint64_t B11 = rotl<6>(A[ 7] ^ D3);
      const uint64_t B21 = rotl<55>(A[ 8] ^ D4);
      const uint64_t B06 = rotl<20>(A[ 9] ^ D0);
      const uint64_t B07 = rotl<3>(A[10] ^ D1);
      const uint64_t B17 = rotl<10>(A[11] ^ D2);
      const uint64_t B02 = rotl<43>(A[12] ^ D3);
      const uint64_t B12 = rotl<25>(A[13] ^ D4);
      const uint64_t B22 = rotl<39>(A[14] ^ D0);
      const uint64_t B23 = rotl<41>(A[15] ^ D1);
      const uint64_t B08 = rotl<45>(A[16] ^ D2);
      const uint64_t B18 = rotl<15>(A[17] ^ D3);
      const uint64_t B03 = rotl<21>(A[18] ^ D4);
      const uint64_t B13 = rotl<8>(A[19] ^ D0);
      const uint64_t B14 = rotl<18>(A[20] ^ D1);
      const uint64_t B24 = rotl<2>(A[21] ^ D2);
      const uint64_t B09 = rotl<61>(A[22] ^ D3);
      const uint64_t B19 = rotl<56>(A[23] ^ D4);
      const uint64_t B04 = rotl<14>(A[24] ^ D0);

      A[ 0] = B00 ^ (~B01 & B02);
      A[ 1] = B01 ^ (~B02 & B03);
      A[ 2] = B02 ^ (~B03 & B04);
      A[ 3] = B03 ^ (~B04 & B00);
      A[ 4] = B04 ^ (~B00 & B01);
      A[ 5] = B05 ^ (~B06 & B07);
      A[ 6] = B06 ^ (~B07 & B08);
      A[ 7] = B07 ^ (~B08 & B09);
      A[ 8] = B08 ^ (~B09 & B05);
      A[ 9] = B09 ^ (~B05 & B06);
      A[10] = B10 ^ (~B11 & B12);
      A[11] = B11 ^ (~B12 & B13);
      A[12] = B12 ^ (~B13 & B14);
      A[13] = B13 ^ (~B14 & B10);
      A[14] = B14 ^ (~B10 & B11);
      A[15] = B15 ^ (~B16 & B17);
      A[16] = B16 ^ (~B17 & B18);
      A[17] = B17 ^ (~B18 & B19);
      A[18] = B18 ^ (~B19 & B15);
      A[19] = B19 ^ (~B15 & B16);
      A[20] = B20 ^ (~B21 & B22);
      A[21] = B21 ^ (~B22 & B23);
      A[22] = B22 ^ (~B23 & B24);
      A[23] = B23 ^ (~B24 & B20);
      A[24] = B24 ^ (~B20 & B21);

      A[0] ^= RC[i];
      }
   }

//static
size_t SHA_3::absorb(size_t bitrate,
                     secure_vector<uint64_t>& S, size_t S_pos,
                     const uint8_t input[], size_t length)
   {
   while(length > 0)
      {
      size_t to_take = std::min(length, bitrate / 8 - S_pos);

      length -= to_take;

      while(to_take && S_pos % 8)
         {
         S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));

         ++S_pos;
         ++input;
         --to_take;
         }

      while(to_take && to_take % 8 == 0)
         {
         S[S_pos / 8] ^= load_le<uint64_t>(input, 0);
         S_pos += 8;
         input += 8;
         to_take -= 8;
         }

      while(to_take)
         {
         S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));

         ++S_pos;
         ++input;
         --to_take;
         }

      if(S_pos == bitrate / 8)
         {
         SHA_3::permute(S.data());
         S_pos = 0;
         }
      }

   return S_pos;
   }

//static
void SHA_3::finish(size_t bitrate,
                   secure_vector<uint64_t>& S, size_t S_pos,
                   uint8_t init_pad, uint8_t fini_pad)
   {
   S[S_pos / 8] ^= static_cast<uint64_t>(init_pad) << (8 * (S_pos % 8));
   S[(bitrate / 64) - 1] ^= static_cast<uint64_t>(fini_pad) << 56;
   SHA_3::permute(S.data());
   }

//static
void SHA_3::expand(size_t bitrate,
                   secure_vector<uint64_t>& S,
                   uint8_t output[], size_t output_length)
   {
   BOTAN_ARG_CHECK(bitrate % 8 == 0);

   size_t Si = 0;

   for(size_t i = 0; i != output_length; ++i)
      {
      if(i > 0)
         {
         if(i % (bitrate / 8) == 0)
            {
            SHA_3::permute(S.data());
            Si = 0;
            }
         else if(i % 8 == 0)
            {
            Si += 1;
            }
         }

      output[i] = get_byte(7 - (i % 8), S[Si]);
      }
   }

SHA_3::SHA_3(size_t output_bits) :
   m_output_bits(output_bits),
   m_bitrate(1600 - 2*output_bits),
   m_S(25),
   m_S_pos(0)
   {
   // We only support the parameters for SHA-3 in this constructor

   if(output_bits != 224 && output_bits != 256 &&
      output_bits != 384 && output_bits != 512)
      throw Invalid_Argument("SHA_3: Invalid output length " +
                             std::to_string(output_bits));
   }

std::string SHA_3::name() const
   {
   return "SHA-3(" + std::to_string(m_output_bits) + ")";
   }

std::unique_ptr<HashFunction> SHA_3::copy_state() const
   {
   return std::unique_ptr<HashFunction>(new SHA_3(*this));
   }

HashFunction* SHA_3::clone() const
   {
   return new SHA_3(m_output_bits);
   }

void SHA_3::clear()
   {
   zeroise(m_S);
   m_S_pos = 0;
   }

void SHA_3::add_data(const uint8_t input[], size_t length)
   {
   m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length);
   }

void SHA_3::final_result(uint8_t output[])
   {
   SHA_3::finish(m_bitrate, m_S, m_S_pos, 0x06, 0x80);

   /*
   * We never have to run the permutation again because we only support
   * limited output lengths
   */
   copy_out_vec_le(output, m_output_bits/8, m_S);

   clear();
   }

}
<commit_msg>Whitespace<commit_after>/*
* SHA-3
* (C) 2010,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/sha3.h>
#include <botan/exceptn.h>

namespace Botan {

//static
void SHA_3::permute(uint64_t A[25])
   {
   static const uint64_t RC[24] = {
      0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
      0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
      0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
      0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
      0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
      0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
      0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
      0x8000000000008080, 0x0000000080000001, 0x8000000080008008
   };

   for(size_t i = 0; i != 24; ++i)
      {
      const uint64_t C0 = A[0] ^ A[5] ^ A[10] ^ A[15] ^ A[20];
      const uint64_t C1 = A[1] ^ A[6] ^ A[11] ^ A[16] ^ A[21];
      const uint64_t C2 = A[2] ^ A[7] ^ A[12] ^ A[17] ^ A[22];
      const uint64_t C3 = A[3] ^ A[8] ^ A[13] ^ A[18] ^ A[23];
      const uint64_t C4 = A[4] ^ A[9] ^ A[14] ^ A[19] ^ A[24];

      const uint64_t D0 = rotl<1>(C0) ^ C3;
      const uint64_t D1 = rotl<1>(C1) ^ C4;
      const uint64_t D2 = rotl<1>(C2) ^ C0;
      const uint64_t D3 = rotl<1>(C3) ^ C1;
      const uint64_t D4 = rotl<1>(C4) ^ C2;

      const uint64_t B00 = A[ 0] ^ D1;
      const uint64_t B10 = rotl< 1>(A[ 1] ^ D2);
      const uint64_t B20 = rotl<62>(A[ 2] ^ D3);
      const uint64_t B05 = rotl<28>(A[ 3] ^ D4);
      const uint64_t B15 = rotl<27>(A[ 4] ^ D0);
      const uint64_t B16 = rotl<36>(A[ 5] ^ D1);
      const uint64_t B01 = rotl<44>(A[ 6] ^ D2);
      const uint64_t B11 = rotl< 6>(A[ 7] ^ D3);
      const uint64_t B21 = rotl<55>(A[ 8] ^ D4);
      const uint64_t B06 = rotl<20>(A[ 9] ^ D0);
      const uint64_t B07 = rotl< 3>(A[10] ^ D1);
      const uint64_t B17 = rotl<10>(A[11] ^ D2);
      const uint64_t B02 = rotl<43>(A[12] ^ D3);
      const uint64_t B12 = rotl<25>(A[13] ^ D4);
      const uint64_t B22 = rotl<39>(A[14] ^ D0);
      const uint64_t B23 = rotl<41>(A[15] ^ D1);
      const uint64_t B08 = rotl<45>(A[16] ^ D2);
      const uint64_t B18 = rotl<15>(A[17] ^ D3);
      const uint64_t B03 = rotl<21>(A[18] ^ D4);
      const uint64_t B13 = rotl< 8>(A[19] ^ D0);
      const uint64_t B14 = rotl<18>(A[20] ^ D1);
      const uint64_t B24 = rotl< 2>(A[21] ^ D2);
      const uint64_t B09 = rotl<61>(A[22] ^ D3);
      const uint64_t B19 = rotl<56>(A[23] ^ D4);
      const uint64_t B04 = rotl<14>(A[24] ^ D0);

      A[ 0] = B00 ^ (~B01 & B02);
      A[ 1] = B01 ^ (~B02 & B03);
      A[ 2] = B02 ^ (~B03 & B04);
      A[ 3] = B03 ^ (~B04 & B00);
      A[ 4] = B04 ^ (~B00 & B01);
      A[ 5] = B05 ^ (~B06 & B07);
      A[ 6] = B06 ^ (~B07 & B08);
      A[ 7] = B07 ^ (~B08 & B09);
      A[ 8] = B08 ^ (~B09 & B05);
      A[ 9] = B09 ^ (~B05 & B06);
      A[10] = B10 ^ (~B11 & B12);
      A[11] = B11 ^ (~B12 & B13);
      A[12] = B12 ^ (~B13 & B14);
      A[13] = B13 ^ (~B14 & B10);
      A[14] = B14 ^ (~B10 & B11);
      A[15] = B15 ^ (~B16 & B17);
      A[16] = B16 ^ (~B17 & B18);
      A[17] = B17 ^ (~B18 & B19);
      A[18] = B18 ^ (~B19 & B15);
      A[19] = B19 ^ (~B15 & B16);
      A[20] = B20 ^ (~B21 & B22);
      A[21] = B21 ^ (~B22 & B23);
      A[22] = B22 ^ (~B23 & B24);
      A[23] = B23 ^ (~B24 & B20);
      A[24] = B24 ^ (~B20 & B21);

      A[0] ^= RC[i];
      }
   }

//static
size_t SHA_3::absorb(size_t bitrate,
                     secure_vector<uint64_t>& S, size_t S_pos,
                     const uint8_t input[], size_t length)
   {
   while(length > 0)
      {
      size_t to_take = std::min(length, bitrate / 8 - S_pos);

      length -= to_take;

      while(to_take && S_pos % 8)
         {
         S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));

         ++S_pos;
         ++input;
         --to_take;
         }

      while(to_take && to_take % 8 == 0)
         {
         S[S_pos / 8] ^= load_le<uint64_t>(input, 0);
         S_pos += 8;
         input += 8;
         to_take -= 8;
         }

      while(to_take)
         {
         S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));

         ++S_pos;
         ++input;
         --to_take;
         }

      if(S_pos == bitrate / 8)
         {
         SHA_3::permute(S.data());
         S_pos = 0;
         }
      }

   return S_pos;
   }

//static
void SHA_3::finish(size_t bitrate,
                   secure_vector<uint64_t>& S, size_t S_pos,
                   uint8_t init_pad, uint8_t fini_pad)
   {
   S[S_pos / 8] ^= static_cast<uint64_t>(init_pad) << (8 * (S_pos % 8));
   S[(bitrate / 64) - 1] ^= static_cast<uint64_t>(fini_pad) << 56;
   SHA_3::permute(S.data());
   }

//static
void SHA_3::expand(size_t bitrate,
                   secure_vector<uint64_t>& S,
                   uint8_t output[], size_t output_length)
   {
   BOTAN_ARG_CHECK(bitrate % 8 == 0);

   size_t Si = 0;

   for(size_t i = 0; i != output_length; ++i)
      {
      if(i > 0)
         {
         if(i % (bitrate / 8) == 0)
            {
            SHA_3::permute(S.data());
            Si = 0;
            }
         else if(i % 8 == 0)
            {
            Si += 1;
            }
         }

      output[i] = get_byte(7 - (i % 8), S[Si]);
      }
   }

SHA_3::SHA_3(size_t output_bits) :
   m_output_bits(output_bits),
   m_bitrate(1600 - 2*output_bits),
   m_S(25),
   m_S_pos(0)
   {
   // We only support the parameters for SHA-3 in this constructor

   if(output_bits != 224 && output_bits != 256 &&
      output_bits != 384 && output_bits != 512)
      throw Invalid_Argument("SHA_3: Invalid output length " +
                             std::to_string(output_bits));
   }

std::string SHA_3::name() const
   {
   return "SHA-3(" + std::to_string(m_output_bits) + ")";
   }

std::unique_ptr<HashFunction> SHA_3::copy_state() const
   {
   return std::unique_ptr<HashFunction>(new SHA_3(*this));
   }

HashFunction* SHA_3::clone() const
   {
   return new SHA_3(m_output_bits);
   }

void SHA_3::clear()
   {
   zeroise(m_S);
   m_S_pos = 0;
   }

void SHA_3::add_data(const uint8_t input[], size_t length)
   {
   m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length);
   }

void SHA_3::final_result(uint8_t output[])
   {
   SHA_3::finish(m_bitrate, m_S, m_S_pos, 0x06, 0x80);

   /*
   * We never have to run the permutation again because we only support
   * limited output lengths
   */
   copy_out_vec_le(output, m_output_bits/8, m_S);

   clear();
   }

}
<|endoftext|>


<commit_before>/*
    This file is part of Kontact
    Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org>
    Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org>

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <qhbox.h>
#include <qcombobox.h>
#include <qwhatsthis.h>
#include <qsplitter.h>

#include <kapplication.h>
#include <kconfig.h>
#include <ktrader.h>
#include <klibloader.h>
#include <kdebug.h>
#include <kstdaction.h>
#include <klistbox.h>
#include <kiconloader.h>
#include <kstandarddirs.h>
#include <kshortcut.h>
#include <kparts/componentfactory.h>
#include <klocale.h>
#include <kstatusbar.h>
#include <kcmultidialog.h>

#include <dcopclient.h>

#include "kpplugin.h"

#include "mainwindow.h"
#include "sidepane.h"

using namespace Kontact;

MainWindow::MainWindow()
  : Kontact::Core()
{
  // create the GUI
  QHBox *box = new QHBox(this);
  box->setFrameStyle(  QFrame::Panel | QFrame::Sunken );

  QSplitter *splitter = new QSplitter(box);

  m_sidePane = new SidePane(splitter);
  m_sidePane->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
  connect(m_sidePane, SIGNAL(showPart(KParts::Part*)), SLOT(showPart(KParts::Part*)));

  m_stack = new QWidgetStack(splitter);

  setCentralWidget(box);

  statusBar()->show();

  // prepare the part manager
  m_partManager = new KParts::PartManager(this);
  connect(m_partManager, SIGNAL(activePartChanged(KParts::Part *)), this, SLOT(activePartChanged(KParts::Part *)));

  setupActions();

  loadSettings();

  loadPlugins();

  setXMLFile("kontactui.rc");

  createGUI(0);

  m_sidePane->invokeFirstEntry();

  resize(600, 400); // initial size
  setAutoSaveSettings();
}

MainWindow::~MainWindow()
{
    QPtrList<KParts::Part> parts = *m_partManager->parts();
    parts.setAutoDelete(true);
    parts.clear();
}

void MainWindow::loadSettings()
{
}

void MainWindow::saveSettings()
{
}

void MainWindow::setupActions()
{
  (void) KStdAction::quit(this, SLOT(slotQuit()), actionCollection(), "file_quit");
  (void) KStdAction::preferences(this, SLOT(slotPreferences()), actionCollection(), "settings_preferences");
  m_newActions = new KActionMenu( i18n("New"), BarIcon("mail_generic"), actionCollection(), "action_new" );
}

void MainWindow::insertNewAction(KAction *action)
{
  m_newActions->insert(action);
}

void MainWindow::loadPlugins()
{
  KTrader::OfferList offers = KTrader::self()->query(QString::fromLatin1("Kontact/Plugin"), QString::null);

  for (KTrader::OfferList::ConstIterator it = offers.begin(); it != offers.end(); ++it)
  {
    kdDebug(5600) << "Loading Plugin: " << (*it)->name() << endl;
    Kontact::Plugin *plugin = KParts::ComponentFactory
      ::createInstanceFromService<Kontact::Plugin>(*it, this);
    if (!plugin)
      continue;

    addPlugin(plugin);
  }
}

void MainWindow::addPlugin(Kontact::Plugin *plugin)
{
  kdDebug(5600) << "Added plugin" << endl;

  // merge the plugins GUI into the main window
  insertChildClient(plugin);
  m_plugins.append(plugin);
  m_sidePane->addEntry(plugin);
}

void MainWindow::addPart(KParts::Part *part)
{
  m_partManager->addPart(part, false);

  if (part->widget())
    m_stack->addWidget(part->widget(), 0);
}

void MainWindow::activePartChanged(KParts::Part *part)
{
  kdDebug(5600) << "Part activated: " << part << endl;
  createGUI(part);
}

void MainWindow::showPart(KParts::Part* part)
{

  QPtrList<KParts::Part> parts = *m_partManager->parts();
//  if (!parts.find(part))
      addPart(part);

  m_partManager->setActivePart( part );
  QWidget* view = part->widget();
  Q_ASSERT(view);
  if ( view )
  {
    m_stack->raiseWidget( view );
    view->show();
    view->setFocus();
  }
}

void MainWindow::slotQuit()
{
  close();
}

void MainWindow::slotPreferences()
{
  KCMultiDialog* dialog = new KCMultiDialog("PIM", this, "KontactPreferences");

  QStringList modules;

  // find all all modules for all plugins
  QPtrListIterator<Kontact::Plugin> pit(m_plugins);
  for(; pit.current(); ++pit)
  {
     QStringList tmp = pit.current()->configModules();
     if(!tmp.isEmpty())
         modules += tmp;
  }

  // add them all
  QStringList::iterator mit;
  for (mit = modules.begin(); mit != modules.end(); ++mit)
    dialog->addModule((*mit));

  dialog->show();
  dialog->raise();
}

int MainWindow::startServiceFor( const QString& serviceType,
                           const QString& constraint,
                           const QString& preferences,
                           QString *error, QCString* dcopService, int flags )
{
  QPtrListIterator<Kontact::Plugin> it( m_plugins );
  for ( ; it.current() ; ++it )
  {
    if ( it.current()->createDCOPInterface( serviceType ) ) {
      kdDebug(5600) << "found interface for " << serviceType << endl;
      if ( dcopService )
        *dcopService = it.current()->dcopClient()->appId();
      kdDebug(5600) << "appId=" << it.current()->dcopClient()->appId() << endl;
      return 0; // success
    }
  }
  kdDebug(5600) << "Didn't find dcop interface, falling back to external process" << endl;
  return KDCOPServiceStarter::startServiceFor( serviceType, constraint, preferences, error, dcopService, flags );
}

#include "mainwindow.moc"

// vim: ts=4 sw=4 et
<commit_msg>Brown Paperbag #1, add Parts only once<commit_after>/*
    This file is part of Kontact
    Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org>
    Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org>

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <qhbox.h>
#include <qcombobox.h>
#include <qwhatsthis.h>
#include <qsplitter.h>

#include <kapplication.h>
#include <kconfig.h>
#include <ktrader.h>
#include <klibloader.h>
#include <kdebug.h>
#include <kstdaction.h>
#include <klistbox.h>
#include <kiconloader.h>
#include <kstandarddirs.h>
#include <kshortcut.h>
#include <kparts/componentfactory.h>
#include <klocale.h>
#include <kstatusbar.h>
#include <kcmultidialog.h>

#include <dcopclient.h>

#include "kpplugin.h"

#include "mainwindow.h"
#include "sidepane.h"

using namespace Kontact;

MainWindow::MainWindow()
  : Kontact::Core()
{
  // create the GUI
  QHBox *box = new QHBox(this);
  box->setFrameStyle(  QFrame::Panel | QFrame::Sunken );

  QSplitter *splitter = new QSplitter(box);

  m_sidePane = new SidePane(splitter);
  m_sidePane->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
  connect(m_sidePane, SIGNAL(showPart(KParts::Part*)), SLOT(showPart(KParts::Part*)));

  m_stack = new QWidgetStack(splitter);

  setCentralWidget(box);

  statusBar()->show();

  // prepare the part manager
  m_partManager = new KParts::PartManager(this);
  connect(m_partManager, SIGNAL(activePartChanged(KParts::Part *)), this, SLOT(activePartChanged(KParts::Part *)));

  setupActions();

  loadSettings();

  loadPlugins();

  setXMLFile("kontactui.rc");

  createGUI(0);

  m_sidePane->invokeFirstEntry();

  resize(600, 400); // initial size
  setAutoSaveSettings();
}

MainWindow::~MainWindow()
{
    QPtrList<KParts::Part> parts = *m_partManager->parts();
    parts.setAutoDelete(true);
    parts.clear();
}

void MainWindow::loadSettings()
{
}

void MainWindow::saveSettings()
{
}

void MainWindow::setupActions()
{
  (void) KStdAction::quit(this, SLOT(slotQuit()), actionCollection(), "file_quit");
  (void) KStdAction::preferences(this, SLOT(slotPreferences()), actionCollection(), "settings_preferences");
  m_newActions = new KActionMenu( i18n("New"), BarIcon("mail_generic"), actionCollection(), "action_new" );
}

void MainWindow::insertNewAction(KAction *action)
{
  m_newActions->insert(action);
}

void MainWindow::loadPlugins()
{
  KTrader::OfferList offers = KTrader::self()->query(QString::fromLatin1("Kontact/Plugin"), QString::null);

  for (KTrader::OfferList::ConstIterator it = offers.begin(); it != offers.end(); ++it)
  {
    kdDebug(5600) << "Loading Plugin: " << (*it)->name() << endl;
    Kontact::Plugin *plugin = KParts::ComponentFactory
      ::createInstanceFromService<Kontact::Plugin>(*it, this);
    if (!plugin)
      continue;

    addPlugin(plugin);
  }
}

void MainWindow::addPlugin(Kontact::Plugin *plugin)
{
  kdDebug(5600) << "Added plugin" << endl;

  // merge the plugins GUI into the main window
  insertChildClient(plugin);
  m_plugins.append(plugin);
  m_sidePane->addEntry(plugin);
}

void MainWindow::addPart(KParts::Part *part)
{
  m_partManager->addPart(part, false);

  if (part->widget())
    m_stack->addWidget(part->widget(), 0);
}

void MainWindow::activePartChanged(KParts::Part *part)
{
  kdDebug(5600) << "Part activated: " << part << " with stack id. "
      << m_stack->id(part->widget())<< endl;
  createGUI(part);
}

void MainWindow::showPart(KParts::Part* part)
{
  QPtrList<KParts::Part> *partList = const_cast< QPtrList<KParts::Part>* >(m_partManager->parts());
  if (partList->find(part) == -1)
      addPart(part);

  m_partManager->setActivePart( part );
  QWidget* view = part->widget();
  Q_ASSERT(view);
  if ( view )
  {
    m_stack->raiseWidget( view );
    view->show();
    view->setFocus();
  }
}

void MainWindow::slotQuit()
{
  close();
}

void MainWindow::slotPreferences()
{
  KCMultiDialog* dialog = new KCMultiDialog("PIM", this, "KontactPreferences");

  QStringList modules;

  // find all all modules for all plugins
  QPtrListIterator<Kontact::Plugin> pit(m_plugins);
  for(; pit.current(); ++pit)
  {
     QStringList tmp = pit.current()->configModules();
     if(!tmp.isEmpty())
         modules += tmp;
  }

  // add them all
  QStringList::iterator mit;
  for (mit = modules.begin(); mit != modules.end(); ++mit)
    dialog->addModule((*mit));

  dialog->show();
  dialog->raise();
}

int MainWindow::startServiceFor( const QString& serviceType,
                           const QString& constraint,
                           const QString& preferences,
                           QString *error, QCString* dcopService, int flags )
{
  QPtrListIterator<Kontact::Plugin> it( m_plugins );
  for ( ; it.current() ; ++it )
  {
    if ( it.current()->createDCOPInterface( serviceType ) ) {
      kdDebug(5600) << "found interface for " << serviceType << endl;
      if ( dcopService )
        *dcopService = it.current()->dcopClient()->appId();
      kdDebug(5600) << "appId=" << it.current()->dcopClient()->appId() << endl;
      return 0; // success
    }
  }
  kdDebug(5600) << "Didn't find dcop interface, falling back to external process" << endl;
  return KDCOPServiceStarter::startServiceFor( serviceType, constraint, preferences, error, dcopService, flags );
}

#include "mainwindow.moc"

// vim: ts=4 sw=4 et
<|endoftext|>


<commit_before>// timer.cpp
// 30. April 2017
// Created by:
// 		Bryan Burkhardt (bmburkhardt@alaska.edu)
// 		Alexander Eckert (aeckert@alaska.edu)
// 		Jeremiah Jacobson (jjacobson2@alaska.edu)
// 		Jarye Murphy (jmurphy11@alaska.edu)
// 		Cameron Showalter (cjshowalter@alaska.edu)
//
// Source file for timer

#include <iomanip>

#include "../include/timer.hpp"

/****** Timer Functions ******/

void Timer::updateCurrentTimer() {
	currentTimer = music->_music.getPlayingOffset();
	currentTimeSeconds = (int)currentTimer.asSeconds();
	currentTimeMinutes = convertToMinutes((int)currentTimer.asSeconds());
	currentTimeHours = convertToHours((int) currentTimeSeconds);
	currentTimerStreamSeconds.str("");
	currentTimerStreamMinutes.str("");
	currentTimerStreamHours.str("");
	currentTimerStreamSeconds << std::fixed << std::setprecision(0) << (int) currentTimeSeconds % 60;
	currentTimerStreamMinutes << std::fixed << std::setprecision(0) << ((int)currentTimeMinutes%60);
	currentTimerStreamHours << std::fixed << std::setprecision(0) << (currentTimeHours);

	// Seconds
	if ((int)currentTimeSeconds%60 < 10) {
		currentSec = "0" + currentTimerStreamSeconds.str() + "/";
	}
	else {
		currentSec = currentTimerStreamSeconds.str() + "/";
	}
	// Minutes
	if((int)currentTimeMinutes%60 < 10) {
		currentMin = "0" + currentTimerStreamMinutes.str() + ":";
	}
	else {
		currentMin = currentTimerStreamMinutes.str() + ":";
	}
	// Hours
	if((int)currentTimeHours < 10) {
		currentHour = "0" + currentTimerStreamHours.str() + ":";
	}
	else {
		currentHour = currentTimerStreamHours.str() + ":";
	}
}

void Timer::updateTotalTimer() {
	totalTimer = music->_music.getDuration();
	totalTimeSeconds = (int)totalTimer.asSeconds();
	totalTimeMinutes = convertToMinutes((int) totalTimeSeconds);
	totalTimeHours = convertToHours((int) totalTimeSeconds);
	totalTimerStreamSeconds.str("");
	totalTimerStreamMinutes.str("");
	totalTimerStreamHours.str("");
	totalTimerStreamSeconds << std::fixed << std::setprecision(0) << (int) totalTimeSeconds % 60;
	totalTimerStreamMinutes << std::fixed << std::setprecision(0) << ((int)totalTimeMinutes%60);
	totalTimerStreamHours << std::fixed << std::setprecision(0) << (totalTimeHours);

	// Seconds
	if ((int)totalTimeSeconds%60 < 10) {
		totalSec = "0" + totalTimerStreamSeconds.str();
	}
	else {
		totalSec = totalTimerStreamSeconds.str();
	}
	// Minutes
	if((int)totalTimeMinutes%60 < 10) {
		totalMin = "0" + totalTimerStreamMinutes.str() + ":";
	}
	else {
		totalMin = totalTimerStreamMinutes.str() + ":";
	}
	// Hours
	if((int)totalTimeHours < 10) {
		totalHour = "0" + totalTimerStreamHours.str() + ":";
	}
	else {
		totalHour = totalTimerStreamHours.str() + ":";
	}
}

std::string Timer::selectDisplayTimer() {
	// 0:xx
	std::string rv = "";
	if(totalTimeMinutes < 1) {
		rv = "0:";
		rv += currentSec + "0:";
		rv += totalSec;
		return rv;
	}
		// xx:xx
	else if(currentTimeHours < 1 && totalTimeHours < 1 && totalTimeMinutes > 0) {
		return currentMin + currentSec + totalMin + totalSec;
	}
		// xx:xx:xx
	else {
		return currentHour + currentMin + currentSec + totalHour + totalMin + totalSec;
	}

	if(music->_music.getStatus() == 0) {
		music->callNextSong();
	}
}

void Timer::displayTimer() {
	updateCurrentTimer();
	updateTotalTimer();
	selectDisplayTimer();
}

int Timer::convertToMinutes(int seconds) {
	return seconds/60;
}

int Timer::convertToHours(int seconds) {
	return (seconds/(60*60));
}

// void Timer::setStyleTimer(sf::Font font) {
// 	displayTimerText.setFont(font);
// 	displayTimerText.setCharacterSize(24);
// 	displayTimerText.setColor(sf::Color::Red);
// 	displayTimerText.setPosition(40,75);
// }

Timer::Timer(std::shared_ptr<Music> music) : music(music) {
}<commit_msg>Fixed auto start next song<commit_after>// timer.cpp
// 30. April 2017
// Created by:
// 		Bryan Burkhardt (bmburkhardt@alaska.edu)
// 		Alexander Eckert (aeckert@alaska.edu)
// 		Jeremiah Jacobson (jjacobson2@alaska.edu)
// 		Jarye Murphy (jmurphy11@alaska.edu)
// 		Cameron Showalter (cjshowalter@alaska.edu)
//
// Source file for timer

#include <iomanip>

#include "../include/timer.hpp"

/****** Timer Functions ******/

void Timer::updateCurrentTimer() {
	currentTimer = music->_music.getPlayingOffset();
	currentTimeSeconds = (int)currentTimer.asSeconds();
	currentTimeMinutes = convertToMinutes((int)currentTimer.asSeconds());
	currentTimeHours = convertToHours((int) currentTimeSeconds);
	currentTimerStreamSeconds.str("");
	currentTimerStreamMinutes.str("");
	currentTimerStreamHours.str("");
	currentTimerStreamSeconds << std::fixed << std::setprecision(0) << (int) currentTimeSeconds % 60;
	currentTimerStreamMinutes << std::fixed << std::setprecision(0) << ((int)currentTimeMinutes%60);
	currentTimerStreamHours << std::fixed << std::setprecision(0) << (currentTimeHours);

	// Seconds
	if ((int)currentTimeSeconds%60 < 10) {
		currentSec = "0" + currentTimerStreamSeconds.str() + "/";
	}
	else {
		currentSec = currentTimerStreamSeconds.str() + "/";
	}
	// Minutes
	if((int)currentTimeMinutes%60 < 10) {
		currentMin = "0" + currentTimerStreamMinutes.str() + ":";
	}
	else {
		currentMin = currentTimerStreamMinutes.str() + ":";
	}
	// Hours
	if((int)currentTimeHours < 10) {
		currentHour = "0" + currentTimerStreamHours.str() + ":";
	}
	else {
		currentHour = currentTimerStreamHours.str() + ":";
	}
}

void Timer::updateTotalTimer() {
	totalTimer = music->_music.getDuration();
	totalTimeSeconds = (int)totalTimer.asSeconds();
	totalTimeMinutes = convertToMinutes((int) totalTimeSeconds);
	totalTimeHours = convertToHours((int) totalTimeSeconds);
	totalTimerStreamSeconds.str("");
	totalTimerStreamMinutes.str("");
	totalTimerStreamHours.str("");
	totalTimerStreamSeconds << std::fixed << std::setprecision(0) << (int) totalTimeSeconds % 60;
	totalTimerStreamMinutes << std::fixed << std::setprecision(0) << ((int)totalTimeMinutes%60);
	totalTimerStreamHours << std::fixed << std::setprecision(0) << (totalTimeHours);

	// Seconds
	if ((int)totalTimeSeconds%60 < 10) {
		totalSec = "0" + totalTimerStreamSeconds.str();
	}
	else {
		totalSec = totalTimerStreamSeconds.str();
	}
	// Minutes
	if((int)totalTimeMinutes%60 < 10) {
		totalMin = "0" + totalTimerStreamMinutes.str() + ":";
	}
	else {
		totalMin = totalTimerStreamMinutes.str() + ":";
	}
	// Hours
	if((int)totalTimeHours < 10) {
		totalHour = "0" + totalTimerStreamHours.str() + ":";
	}
	else {
		totalHour = totalTimerStreamHours.str() + ":";
	}
}

std::string Timer::selectDisplayTimer() {
	// 0:xx
	std::string rv = "";

	if(music->_music.getStatus() == 0) {
		music->callNextSong();
	}
	if(totalTimeMinutes < 1) {
		rv = "0:";
		rv += currentSec + "0:";
		rv += totalSec;
		return rv;
	}
		// xx:xx
	else if(currentTimeHours < 1 && totalTimeHours < 1 && totalTimeMinutes > 0) {
		return currentMin + currentSec + totalMin + totalSec;
	}
		// xx:xx:xx
	else {
		return currentHour + currentMin + currentSec + totalHour + totalMin + totalSec;
	}

}

void Timer::displayTimer() {
	updateCurrentTimer();
	updateTotalTimer();
	selectDisplayTimer();
}

int Timer::convertToMinutes(int seconds) {
	return seconds/60;
}

int Timer::convertToHours(int seconds) {
	return (seconds/(60*60));
}

// void Timer::setStyleTimer(sf::Font font) {
// 	displayTimerText.setFont(font);
// 	displayTimerText.setCharacterSize(24);
// 	displayTimerText.setColor(sf::Color::Red);
// 	displayTimerText.setPosition(40,75);
// }

Timer::Timer(std::shared_ptr<Music> music) : music(music) {
}<|endoftext|>


<commit_before>#include <iostream>
#include <TLSClient.h>

int main (void)
{
  try
  {
    // A very basic TLS client, with X.509 authentication.
    TLSClient client;
    client.debug (0);
    //client.trust (true)
    client.limit (1024);
    client.init ("../../pki/ca.cert.pem",
                 "../../pki/client.cert.pem",
                 "../../pki/client.key.pem");
    client.connect ("127.0.0.1", "5556");

    client.send ("This is a test.");

    std::string response;
    client.recv (response);
    std::cout << "c: '" << response << "'\n";
    client.bye ();
  }

  catch (std::string& e)
  {
    std::cout << "ERROR " << e << "\n";
  }

  catch (...)
  {
    std::cout << "ERROR\n";
  }

  return 0;
}

<commit_msg>tls/c<commit_after>#include <iostream>
#include <TLSClient.h>

int main (void)
{
  try
  {
    // A very basic TLS client, with X.509 authentication.
    TLSClient client;
    client.debug (0);
    client.trust (TLSClient::strict);
    client.limit (1024);
    client.init ("../../pki/ca.cert.pem",
                 "../../pki/client.cert.pem",
                 "../../pki/client.key.pem");
    client.connect ("127.0.0.1", "5556");

    client.send ("This is a test.");

    std::string response;
    client.recv (response);
    std::cout << "c: '" << response << "'\n";
    client.bye ();
  }

  catch (std::string& e)
  {
    std::cout << "ERROR " << e << "\n";
  }

  catch (...)
  {
    std::cout << "ERROR\n";
  }

  return 0;
}

<|endoftext|>