text:
//
// Licensed to Green Energy Corp (www.greenenergycorp.com) under one or
// more contributor license agreements. See the NOTICE file distributed
// with this work for additional information regarding copyright ownership.
// Green Energy Corp licenses this file to you 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.
//
// This file was forked on 01/01/2013 by Automatak, LLC and modifications
// have been made to this file. Automatak, LLC licenses these modifications to
// you under the terms of the License.
//

#include <boost/test/unit_test.hpp>

#include "TestHelpers.h"

#include <opendnp3/ASIOExecutor.h>
#include <opendnp3/IOServiceThreadPool.h>
#include <opendnp3/Exception.h>
#include <opendnp3/Location.h>
#include <opendnp3/Log.h>
#include <opendnp3/ExecutorPause.h>

#include <map>
#include <functional>
#include <chrono>
#include <iostream>

using namespace std;
using namespace std::chrono;
using namespace opendnp3;

class TimerTestObject
{
public:
	TimerTestObject() :
		mLog(),
		mPool(mLog.GetLogger(LEV_ERROR, "thread-pool"), 1),
		mStrand(*mPool.GetIOService()),
		exe(&mStrand),
		mLast(-1),
		mNum(0),
		mMonotonic(true) {

	}

	void Receive(int aVal) {
		if(aVal <= mLast) mMonotonic = false;
		++mNum;
		mLast = aVal;
	}

	bool IsMonotonic() {
		return mMonotonic;
	}

	int Num() {
		return mNum;
	}

private:
	EventLog mLog;
	IOServiceThreadPool mPool;
	boost::asio::strand mStrand;

public:
	ASIOExecutor exe;

private:

	int mLast;
	int mNum;
	bool mMonotonic;
};

class MockTimerHandler
{
public:
	MockTimerHandler() : mCount(0)
	{}

	void OnExpiration() {
		++mCount;
	}
	size_t GetCount() {
		return mCount;
	}

private:
	size_t mCount;
};

BOOST_AUTO_TEST_SUITE(TimersTestSuite)

BOOST_AUTO_TEST_CASE(TestOrderedDispatch)
{
	const int NUM = 10000;

	TimerTestObject test;

	for(int i = 0; i < NUM; ++i) {
		test.exe.Post([&test, i]() {
			test.Receive(i);
		});
	}

	{
		ExecutorPause p(&test.exe);
	}

	BOOST_REQUIRE_EQUAL(NUM, test.Num());
	BOOST_REQUIRE(test.IsMonotonic());
}

BOOST_AUTO_TEST_CASE(ExpirationAndReuse)
{
	MockTimerHandler mth;
	boost::asio::io_service srv;
	boost::asio::strand strand(srv);
	ASIOExecutor exe(&strand);

	ITimer* pT1 = exe.Start(milliseconds(1), std::bind(&MockTimerHandler::OnExpiration, &mth));
	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(1, mth.GetCount());
	ITimer* pT2 = exe.Start(milliseconds(1), std::bind(&MockTimerHandler::OnExpiration, &mth));
	srv.reset();
	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(pT1, pT2); //The ASIO implementation should reuse timers
}

BOOST_AUTO_TEST_CASE(Cancelation)
{
	MockTimerHandler mth;
	boost::asio::io_service srv;
	boost::asio::strand strand(srv);
	ASIOExecutor exe(&strand);
	ITimer* pT1 = exe.Start(milliseconds(1), std::bind(&MockTimerHandler::OnExpiration, &mth));
	pT1->Cancel();
	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(0, mth.GetCount());
	ITimer* pT2 = exe.Start(milliseconds(1), std::bind(&MockTimerHandler::OnExpiration, &mth));
	srv.reset();
	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(pT1, pT2);
}

BOOST_AUTO_TEST_CASE(MultipleOutstanding)
{
	MockTimerHandler mth1;
	MockTimerHandler mth2;
	boost::asio::io_service srv;
	boost::asio::strand strand(srv);
	ASIOExecutor ts(&strand);
	ITimer* pT1 = ts.Start(milliseconds(0), std::bind(&MockTimerHandler::OnExpiration, &mth1));
	ITimer* pT2 = ts.Start(milliseconds(100), std::bind(&MockTimerHandler::OnExpiration, &mth2));

	BOOST_REQUIRE_NOT_EQUAL(pT1, pT2);

	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(1, mth1.GetCount());
	BOOST_REQUIRE_EQUAL(0, mth2.GetCount());

	BOOST_REQUIRE_EQUAL(1, srv.run_one());
	BOOST_REQUIRE_EQUAL(1, mth1.GetCount());
	BOOST_REQUIRE_EQUAL(1, mth2.GetCount());
}

BOOST_AUTO_TEST_SUITE_END()


text:
/*
 *                   GridGain Community Edition Licensing
 *                   Copyright 2019 GridGain Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License") modified with Commons Clause
 * Restriction; 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.
 *
 * Commons Clause Restriction
 *
 * The Software is provided to you by the Licensor under the License, as defined below, subject to
 * the following condition.
 *
 * Without limiting other conditions in the License, the grant of rights under the License will not
 * include, and the License does not grant to you, the right to Sell the Software.
 * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you
 * under the License to provide to third parties, for a fee or other consideration (including without
 * limitation fees for hosting or consulting/ support services related to the Software), a product or
 * service whose value derives, entirely or substantially, from the functionality of the Software.
 * Any license notice or attribution required by the License must also include this Commons Clause
 * License Condition notice.
 *
 * For purposes of the clause above, the “Licensor” is Copyright 2019 GridGain Systems, Inc.,
 * the “License” is the Apache License, Version 2.0, and the Software is the GridGain Community
 * Edition software provided with this notice.
 */

#ifndef _MSC_VER
#   define BOOST_TEST_DYN_LINK
#endif

#include <boost/test/unit_test.hpp>

#include "ignite/ignition.h"
#include "ignite/test_utils.h"

using namespace ignite;
using namespace cache;
using namespace boost::unit_test;

BOOST_AUTO_TEST_SUITE(InteropTestSuite)

#ifdef ENABLE_STRING_SERIALIZATION_VER_2_TESTS

BOOST_AUTO_TEST_CASE(StringUtfInvalidSequence)
{
    Ignite ignite = ignite_test::StartNode("cache-test.xml");

    Cache<std::string, std::string> cache = ignite.CreateCache<std::string, std::string>("Test");

    std::string initialValue;

    initialValue.push_back(static_cast<unsigned char>(0xD8));
    initialValue.push_back(static_cast<unsigned char>(0x00));

    try
    {
        cache.Put("key", initialValue);

        std::string cachedValue = cache.Get("key");

        BOOST_ERROR("Exception is expected due to invalid format.");
    }
    catch (const IgniteError&)
    {
        // Expected in this mode.
    }

    Ignition::StopAll(false);
}

BOOST_AUTO_TEST_CASE(StringUtfInvalidCodePoint)
{
    putenv("IGNITE_BINARY_MARSHALLER_USE_STRING_SERIALIZATION_VER_2=true");

    Ignite ignite = ignite_test::StartNode("cache-test.xml");

    Cache<std::string, std::string> cache = ignite.CreateCache<std::string, std::string>("Test");

    std::string initialValue;

    //    1110xxxx 10xxxxxx 10xxxxxx |
    // <=          11011000 00000000 | U+D8
    //  = 11101101 10100000 10000000 | ED A0 80
    initialValue.push_back(static_cast<unsigned char>(0xED));
    initialValue.push_back(static_cast<unsigned char>(0xA0));
    initialValue.push_back(static_cast<unsigned char>(0x80));

    cache.Put("key", initialValue);
    std::string cachedValue = cache.Get("key");

    // This is a valid case. Invalid code points are supported in this mode.
    BOOST_CHECK_EQUAL(initialValue, cachedValue);

    Ignition::StopAll(false);
}

#endif

BOOST_AUTO_TEST_CASE(StringUtfValid4ByteCodePoint)
{
#ifdef IGNITE_TESTS_32
    Ignite ignite = ignite_test::StartNode("cache-test-32.xml");
#else
    Ignite ignite = ignite_test::StartNode("cache-test.xml");
#endif

    Cache<std::string, std::string> cache = ignite.CreateCache<std::string, std::string>("Test");

    std::string initialValue;

    //    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
    // <=             00001 00000001 01001011 | U+1014B
    // <=      000   010000   000101   001011 | U+1014B
    //  = 11110000 10010000 10000101 10001011 | F0 90 85 8B
    initialValue.push_back(static_cast<unsigned char>(0xF0));
    initialValue.push_back(static_cast<unsigned char>(0x90));
    initialValue.push_back(static_cast<unsigned char>(0x85));
    initialValue.push_back(static_cast<unsigned char>(0x8B));

    cache.Put("key", initialValue);
    std::string cachedValue = cache.Get("key");

    // This is a valid UTF-8 code point. Should be supported in default mode.
    BOOST_CHECK_EQUAL(initialValue, cachedValue);

    Ignition::StopAll(false);
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: DirectXceriD/gridgain

max_issues_repo_name: DirectXceriD/gridgain

max_forks_repo_name: DirectXceriD/gridgain


text:
#include <mbgl/style/style_parser.hpp>
#include <mbgl/map/source.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/map/annotation.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/vec.hpp>
#include <mbgl/util/uv_detail.hpp>
#include <mbgl/platform/log.hpp>
#include <csscolorparser/csscolorparser.hpp>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/algorithm/string.hpp>
#pragma GCC diagnostic pop

#include <algorithm>

namespace mbgl {

using JSVal = const rapidjson::Value&;

StyleParser::StyleParser() {
}

void StyleParser::parse(JSVal document) {
    if (document.HasMember("constants")) {
        parseConstants(document["constants"]);
    }

    if (document.HasMember("sources")) {
        parseSources(document["sources"]);
    }

    if (document.HasMember("layers")) {
        parseLayers(document["layers"]);

        // create point annotations layer
        //
        const std::string& id = AnnotationManager::layerID;

        std::map<ClassID, ClassProperties> paints;
        util::ptr<StyleLayer> annotations = std::make_shared<StyleLayer>(id, std::move(paints));
        annotations->type = StyleLayerType::Symbol;
        layersMap.emplace(id, std::pair<JSVal, util::ptr<StyleLayer>> { JSVal(id), annotations });
        layers.emplace_back(annotations);

        util::ptr<StyleBucket> pointBucket = std::make_shared<StyleBucket>(annotations->type);
        pointBucket->name = annotations->id;
        pointBucket->source_layer = annotations->id;

        rapidjson::Document d;
        rapidjson::Value iconImage(rapidjson::kObjectType);
        iconImage.AddMember("icon-image", "{sprite}", d.GetAllocator());
        parseLayout(iconImage, pointBucket);
        rapidjson::Value iconOverlap(rapidjson::kObjectType);
        iconOverlap.AddMember("icon-allow-overlap", true, d.GetAllocator());
        parseLayout(iconOverlap, pointBucket);

        util::ptr<Source> source = std::make_shared<Source>();
        sourcesMap.emplace(id, source);
        sources.emplace_back(source);
        source->info.type = SourceType::Annotations;
        pointBucket->source = source;
        annotations->bucket = pointBucket;
        //
        // end point annotations
    }

    if (document.HasMember("sprite")) {
        parseSprite(document["sprite"]);
    }

    if (document.HasMember("glyphs")) {
        parseGlyphURL(document["glyphs"]);
    }
}

void StyleParser::parseConstants(JSVal value) {
    if (value.IsObject()) {
        rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
        for (; itr != value.MemberEnd(); ++itr) {
            std::string name { itr->name.GetString(), itr->name.GetStringLength() };
            // Discard constants that don't start with an @ sign.
            if (name.length() && name[0] == '@') {
                constants.emplace(std::move(name), &itr->value);
            }
        }
    } else {
        Log::Warning(Event::ParseStyle, "constants must be an object");
    }
}

JSVal StyleParser::replaceConstant(JSVal value) {
    if (value.IsString()) {
        auto it = constants.find({ value.GetString(), value.GetStringLength() });
        if (it != constants.end()) {
            return *it->second;
        }
    }

    return value;
}

#pragma mark - Parse Render Properties

template<> bool StyleParser::parseRenderProperty(JSVal value, bool &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsBool()) {
            target = property.GetBool();
            return true;
        } else {
            Log::Warning(Event::ParseStyle, "'%s' must be a boolean", name);
        }
    }
    return false;
}

template<> bool StyleParser::parseRenderProperty(JSVal value, std::string &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsString()) {
            target = { property.GetString(), property.GetStringLength() };
            return true;
        } else {
            Log::Warning(Event::ParseStyle, "'%s' must be a string", name);
        }
    }
    return false;
}

template<> bool StyleParser::parseRenderProperty(JSVal value, float &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsNumber()) {
            target = property.GetDouble();
            return true;
        } else {
            Log::Warning(Event::ParseStyle, "'%s' must be a number", name);
        }
    }
    return false;
}

template<> bool StyleParser::parseRenderProperty(JSVal value, uint16_t &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsUint()) {
            unsigned int int_value = property.GetUint();
            if (int_value > std::numeric_limits<uint16_t>::max()) {
                Log::Warning(Event::ParseStyle, "values for %s that are larger than %d are not supported", name, std::numeric_limits<uint16_t>::max());
                return false;
            }

            target = int_value;
            return true;
        } else {
            Log::Warning(Event::ParseStyle, "%s must be an unsigned integer", name);
        }
    }
    return false;
}

template<> bool StyleParser::parseRenderProperty(JSVal value, int32_t &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsInt()) {
            target = property.GetInt();
            return true;
        } else {
            Log::Warning(Event::ParseStyle, "%s must be an integer", name);
        }
    }
    return false;
}

template<> bool StyleParser::parseRenderProperty(JSVal value, vec2<float> &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsArray()) {
            if (property.Size() >= 2) {
                target.x = property[(rapidjson::SizeType)0].GetDouble();
                target.y = property[(rapidjson::SizeType)1].GetDouble();
                return true;
            } else {
                Log::Warning(Event::ParseStyle, "%s must have at least two members", name);
            }
        } else {
            Log::Warning(Event::ParseStyle, "%s must be an array of numbers", name);
        }
    }
    return false;
}

template<typename Parser, typename T>
bool StyleParser::parseRenderProperty(JSVal value, T &target, const char *name) {
    if (value.HasMember(name)) {
        JSVal property = replaceConstant(value[name]);
        if (property.IsString()) {
            target = Parser({ property.GetString(), property.GetStringLength() });
            return true;
        } else {
            Log::Warning(Event::ParseStyle, "%s must have one of the enum values", name);
        }
    }
    return false;
}

#pragma mark - Parse Sources

void StyleParser::parseSources(JSVal value) {
    if (value.IsObject()) {
        rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
        for (; itr != value.MemberEnd(); ++itr) {
            std::string name { itr->name.GetString(), itr->name.GetStringLength() };
            util::ptr<Source> source = std::make_shared<Source>();
            parseRenderProperty<SourceTypeClass>(itr->value, source->info.type, "type");
            parseRenderProperty(itr->value, source->info.url, "url");
            parseRenderProperty(itr->value, source->info.tile_size, "tileSize");
            source->info.parseTileJSONProperties(itr->value);
            sources.emplace_back(source);
            sourcesMap.emplace(name, source);
        }
    } else {
        Log::Warning(Event::ParseStyle, "sources must be an object");
    }
}

#pragma mark - Parse Style Properties

Color parseColor(JSVal value) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "color value must be a string");
        return Color{{ 0, 0, 0, 0 }};
    }

    CSSColorParser::Color css_color = CSSColorParser::parse({ value.GetString(), value.GetStringLength() });

    // Premultiply the color.
    const float factor = css_color.a / 255;

    return Color{{(float)css_color.r * factor,
                  (float)css_color.g * factor,
                  (float)css_color.b * factor,
                  css_color.a}};
}

std::tuple<bool,std::vector<float>> StyleParser::parseFloatArray(JSVal value) {
    if (!value.IsArray()) {
        Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
        return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
    }

    std::vector<float> vec;
    for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
        JSVal part = replaceConstant(value[i]);
        if (!part.IsNumber()) {
            Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
            return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
        }
        vec.push_back(part.GetDouble());
    }
    return std::tuple<bool, std::vector<float>> { true, vec };
}

template <>
std::tuple<bool, std::array<float, 2>> StyleParser::parseProperty(JSVal value, const char*) {
    if (value.IsArray() && value.Size() == 2 &&
            value[rapidjson::SizeType(0)].IsNumber() &&
            value[rapidjson::SizeType(1)].IsNumber()) {

        float first = value[rapidjson::SizeType(0)].GetDouble();
        float second = value[rapidjson::SizeType(1)].GetDouble();
        return std::tuple<bool, std::array<float, 2>> { false, {{ first, second }} };
    } else {
        Log::Warning(Event::ParseStyle, "value must be array of two numbers");
        return std::tuple<bool, std::array<float, 2>> { false, {{ 0.0f, 0.0f }} };
    }
}

template <>
std::tuple<bool, float> StyleParser::parseProperty(JSVal value, const char* property_name) {
    JSVal rvalue = replaceConstant(value);
    if (rvalue.IsNumber()) {
        return std::tuple<bool, float> { true, rvalue.GetDouble() };
    } else {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", property_name);
        return std::tuple<bool, float> { false, 0.0f };
    }
}

template <>
std::tuple<bool, Color> StyleParser::parseProperty(JSVal value, const char*) {
    JSVal rvalue = replaceConstant(value);
    return std::tuple<bool, Color> { true, parseColor(rvalue) };
}

template <>
std::tuple<bool, Faded<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char*) {
    Faded<std::vector<float>> parsed;
    JSVal rvalue = replaceConstant(value);
    parsed.to = std::get<1>(parseFloatArray(rvalue));
    return std::tuple<bool, Faded<std::vector<float>>> { true, parsed };
}

template <>
std::tuple<bool, Faded<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    JSVal rvalue = replaceConstant(value);
    Faded<std::string> parsed;
    if (rvalue.IsString()) {
        parsed.to = { value.GetString(), value.GetStringLength() };
        return std::tuple<bool, Faded<std::string>> { true, parsed };
    } else {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string, or a string function", property_name);
        return std::tuple<bool, Faded<std::string>> { false, parsed };
    }
}

template <typename T>
std::tuple<bool, std::vector<std::pair<float, T>>> StyleParser::parseStops(JSVal value_stops, const char *property_name) {

    if (!value_stops.IsArray()) {
        Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
        return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
    }

    std::vector<std::pair<float, T>> stops;

    for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
        JSVal stop = value_stops[i];
        if (stop.IsArray()) {
            if (stop.Size() != 2) {
                Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
                return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
            }

            JSVal z = stop[rapidjson::SizeType(0)];
            if (!z.IsNumber()) {
                Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
                return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
            }

            stops.emplace_back(z.GetDouble(), std::get<1>(parseProperty<T>(replaceConstant(stop[rapidjson::SizeType(1)]), property_name)));
        } else {
            Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
            return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
        }
    }
    return std::tuple<bool, std::vector<std::pair<float, T>>>(true, stops);
}

template <typename T>
std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value, const char *property_name) {
    if (!value.IsObject()) {
        return std::tuple<bool, Function<T>> { true, ConstantFunction<T>(std::get<1>(parseProperty<T>(value, property_name))) };
    }

    if (!value.HasMember("stops")) {
        Log::Warning(Event::ParseStyle, "function must specify a function type");
        return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
    }

    float base = 1.0f;

    if (value.HasMember("base")) {
        JSVal value_base = value["base"];
        if (value_base.IsNumber()) {
            base = value_base.GetDouble();
        } else {
            Log::Warning(Event::ParseStyle, "base must be numeric");
        }
    }

    auto stops = parseStops<T>(value["stops"], property_name);

    if (!std::get<0>(stops)) {
        return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
    }

    return std::tuple<bool, Function<T>> { true, StopsFunction<T>(std::get<1>(stops), base) };
}

template <typename T>
std::tuple<bool, PiecewiseConstantFunction<T>> StyleParser::parsePiecewiseConstantFunction(JSVal value, Duration duration) {
    if (!value.HasMember("stops")) {
        Log::Warning(Event::ParseStyle, "function must specify a function type");
        return std::tuple<bool, PiecewiseConstantFunction<T>> { false, {} };
    }

    auto stops = parseStops<T>(value["stops"], "");

    if (!std::get<0>(stops)) {
        return std::tuple<bool, PiecewiseConstantFunction<T>> { false, {} };
    }

    return std::tuple<bool, PiecewiseConstantFunction<T>> { true, { std::get<1>(stops), duration } };
}

template <typename T>
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass) {
    auto res = parseProperty<T>(value, property_name);
    if (std::get<0>(res)) {
        klass.set(key, std::get<1>(res));
    }
    return std::get<0>(res);
}

template <typename T>
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass, JSVal transition) {
    auto res = parseProperty<T>(value, property_name, transition);
    if (std::get<0>(res)) {
        klass.set(key, std::get<1>(res));
    }
    return std::get<0>(res);
}

template<typename T>
void StyleParser::parseVisibility(StyleBucket &bucket, JSVal value) {
    if (!value.HasMember("visibility")) {
        return;
    } else if (!value["visibility"].IsString()) {
        Log::Warning(Event::ParseStyle, "value of 'visibility' must be a string");
        bucket.visibility = VisibilityType::Visible;
        return;
    }
    bucket.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() });
}

template<typename T>
bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value) {
    if (!value.HasMember(property_name)) {
        return false;
    } else {
        return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass);
    }
}

template<typename T>
bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value, const char *transition_name) {
    if (!value.HasMember(property_name)) {
        return false;
    } else {
        if (value.HasMember(transition_name)) {
            return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass, value[transition_name]);
        } else {
            JSVal val = JSVal(rapidjson::kObjectType);
            return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass, val);
        }
    }
}

std::string normalizeFontStack(const std::string &name) {
    namespace algo = boost::algorithm;
    std::vector<std::string> parts;
    algo::split(parts, name, algo::is_any_of(","), algo::token_compress_on);
    std::for_each(parts.begin(), parts.end(), [](std::string& str) { algo::trim(str); });
    return algo::join(parts, ", ");
}

template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, std::string> { false, std::string() };
    }

    if (std::string { "text-font" } == property_name) {
        return std::tuple<bool, std::string> {
            true, normalizeFontStack({ value.GetString(), value.GetStringLength() })
        };
    } else {
        return std::tuple<bool, std::string> { true, { value.GetString(), value.GetStringLength() } };
    }
}

template<> std::tuple<bool, bool> StyleParser::parseProperty(JSVal value, const char *property_name) {
    if (!value.IsBool()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a boolean", property_name);
        return std::tuple<bool, bool> { false, true };
    }

    return std::tuple<bool, bool> { true, value.GetBool() };
}

template<> std::tuple<bool, TranslateAnchorType> StyleParser::parseProperty(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, TranslateAnchorType> { false, TranslateAnchorType::Map };
    }

    return std::tuple<bool, TranslateAnchorType> { true, TranslateAnchorTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, RotateAnchorType> StyleParser::parseProperty<RotateAnchorType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, RotateAnchorType> { false, RotateAnchorType::Map };
    }

    return std::tuple<bool, RotateAnchorType> { true, RotateAnchorTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, CapType> StyleParser::parseProperty<CapType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, CapType> { false, CapType::Butt };
    }

    return std::tuple<bool, CapType> { true, CapTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, JoinType> StyleParser::parseProperty<JoinType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, JoinType> { false, JoinType::Miter };
    }

    return std::tuple<bool, JoinType> { true, JoinTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, PlacementType> StyleParser::parseProperty<PlacementType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, PlacementType> { false, PlacementType::Point };
    }

    return std::tuple<bool, PlacementType> { true, PlacementTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, TextAnchorType> StyleParser::parseProperty<TextAnchorType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, TextAnchorType> { false, TextAnchorType::Center };
    }

    return std::tuple<bool, TextAnchorType> { true, TextAnchorTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, TextJustifyType> StyleParser::parseProperty<TextJustifyType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, TextJustifyType> { false, TextJustifyType::Center };
    }

    return std::tuple<bool, TextJustifyType> { true, TextJustifyTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, TextTransformType> StyleParser::parseProperty<TextTransformType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, TextTransformType> { false, TextTransformType::None };
    }

    return std::tuple<bool, TextTransformType> { true, TextTransformTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, RotationAlignmentType> StyleParser::parseProperty<RotationAlignmentType>(JSVal value, const char *property_name) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
        return std::tuple<bool, RotationAlignmentType> { false, RotationAlignmentType::Map };
    }

    return std::tuple<bool, RotationAlignmentType> { true, RotationAlignmentTypeClass({ value.GetString(), value.GetStringLength() }) };
}

template<> std::tuple<bool, PropertyTransition> StyleParser::parseProperty(JSVal value, const char */*property_name*/) {
    PropertyTransition transition;
    if (value.IsObject()) {
        if (value.HasMember("duration") && value["duration"].IsNumber()) {
            transition.duration = std::chrono::milliseconds(value["duration"].GetUint());
        }
        if (value.HasMember("delay") && value["delay"].IsNumber()) {
            transition.delay = std::chrono::milliseconds(value["delay"].GetUint());
        }
    }

    if (transition.duration == Duration::zero() && transition.delay == Duration::zero()) {
        return std::tuple<bool, PropertyTransition> { false, std::move(transition) };
    }

    return std::tuple<bool, PropertyTransition> { true, std::move(transition) };
}

template<> std::tuple<bool, Function<std::array<float, 2>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<std::array<float, 2>>(value, property_name);
}

template<> std::tuple<bool, Function<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<std::string>(value, property_name);
}

template<> std::tuple<bool, Function<TranslateAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<TranslateAnchorType>(value, property_name);
}

template<> std::tuple<bool, Function<RotateAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<RotateAnchorType>(value, property_name);
}

template<> std::tuple<bool, Function<CapType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<CapType>(value, property_name);
}

template<> std::tuple<bool, Function<JoinType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<JoinType>(value, property_name);
}

template<> std::tuple<bool, Function<PlacementType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<PlacementType>(value, property_name);
}

template<> std::tuple<bool, Function<TextAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<TextAnchorType>(value, property_name);
}

template<> std::tuple<bool, Function<TextJustifyType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<TextJustifyType>(value, property_name);
}

template<> std::tuple<bool, Function<TextTransformType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<TextTransformType>(value, property_name);
}

template<> std::tuple<bool, Function<RotationAlignmentType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<RotationAlignmentType>(value, property_name);
}

template<> std::tuple<bool, Function<bool>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<bool>(value, property_name);
}

template<> std::tuple<bool, Function<float>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<float>(value, property_name);
}

template<> std::tuple<bool, Function<Color>> StyleParser::parseProperty(JSVal value, const char *property_name) {
    return parseFunction<Color>(value, property_name);
}

template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) {
    Duration duration = std::chrono::milliseconds(300);
    if (transition.HasMember("duration")) {
        duration = std::chrono::milliseconds(transition["duration"].GetUint());
    }

    if (value.IsObject()) {
        return parsePiecewiseConstantFunction<Faded<std::vector<float>>>(value, duration);
    } else if (value.IsArray()) {
        Faded<std::vector<float>> parsed;
        std::tuple<bool, std::vector<float>> floatarray = parseFloatArray(value);
        parsed.to = std::get<1>(floatarray);
        return std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> { std::get<0>(floatarray),  { parsed, duration } };
    } else {
        Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name);
        return std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> { false, {} };
    }
}

template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) {

    Duration duration = std::chrono::milliseconds(300);
    if (transition.HasMember("duration")) {
        duration = std::chrono::milliseconds(transition["duration"].GetUint());
    }

    if (value.IsObject()) {
        return parsePiecewiseConstantFunction<Faded<std::string>>(value, duration);
    } else if (value.IsString()) {
        Faded<std::string> parsed;
        parsed.to = { value.GetString(), value.GetStringLength() };
        return std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> { true,  { parsed, duration } };
    } else {
        Log::Warning(Event::ParseStyle, "value of '%s' must be string or a string function", property_name);
        return std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> { false, {} };
    }
}

#pragma mark - Parse Layers

void StyleParser::parseLayers(JSVal value) {
    if (!value.IsArray()) {
        Log::Warning(Event::ParseStyle, "layers must be an array");
        return;
    }

    for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
        JSVal layerValue = value[i];

        if (!layerValue.IsObject()) {
            Log::Warning(Event::ParseStyle, "layer must be an object");
            continue;
        }

        if (!layerValue.HasMember("id")) {
            Log::Warning(Event::ParseStyle, "layer must have an id");
            continue;
        }

        JSVal id = layerValue["id"];
        if (!id.IsString()) {
            Log::Warning(Event::ParseStyle, "layer id must be a string");
            continue;
        }

        const std::string layerID = { id.GetString(), id.GetStringLength() };
        if (layersMap.find(layerID) != layersMap.end()) {
            Log::Warning(Event::ParseStyle, "duplicate layer id %s", layerID.c_str());
            continue;
        }

        // Parse paints already, as they can't be inherited anyway.
        std::map<ClassID, ClassProperties> paints;
        parsePaints(layerValue, paints);

        util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>(layerID, std::move(paints));

        layers.emplace_back(layer);
        layersMap.emplace(layerID, std::pair<JSVal, util::ptr<StyleLayer>> { layerValue, layer });
    }

    for (auto& pair : layersMap) {
        parseLayer(pair.second);
    }
}

void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) {
    JSVal value = pair.first;
    util::ptr<StyleLayer> &layer = pair.second;

    if (value.HasMember("type")) {
        JSVal type = value["type"];
        if (!type.IsString()) {
            Log::Warning(Event::ParseStyle, "layer type of '%s' must be a string", layer->id.c_str());
        } else {
            layer->type = StyleLayerTypeClass(std::string { type.GetString(), type.GetStringLength() });
        }
    }

    if (layer->bucket) {
        // Skip parsing this again. We already have a valid layer definition.
        return;
    }

    // Make sure we have not previously attempted to parse this layer.
    if (std::find(stack.begin(), stack.end(), layer.get()) != stack.end()) {
        Log::Warning(Event::ParseStyle, "layer reference of '%s' is circular", layer->id.c_str());
        return;
    }

    if (value.HasMember("ref")) {
        // This layer is referencing another layer. Inherit the bucket from that layer, if we
        // already parsed it.
        parseReference(replaceConstant(value["ref"]), layer);
    } else {
        // Otherwise, parse the source/source-layer/filter/render keys to form the bucket.
        parseBucket(value, layer);
    }
}

#pragma mark - Parse Styles

void StyleParser::parsePaints(JSVal value, std::map<ClassID, ClassProperties> &paints) {
    rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
    for (; itr != value.MemberEnd(); ++itr) {
        const std::string name { itr->name.GetString(), itr->name.GetStringLength() };

        if (name == "paint") {
            parsePaint(replaceConstant(itr->value), paints[ClassID::Default]);
        } else if (name.compare(0, 6, "paint.") == 0 && name.length() > 6) {
            const ClassID class_id = ClassDictionary::Get().lookup(name.substr(6));
            parsePaint(replaceConstant(itr->value), paints[class_id]);
        }
    }
}

void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
    using Key = PropertyKey;

    parseOptionalProperty<Function<bool>>("fill-antialias", Key::FillAntialias, klass, value);
    parseOptionalProperty<Function<float>>("fill-opacity", Key::FillOpacity, klass, value);
    parseOptionalProperty<PropertyTransition>("fill-opacity-transition", Key::FillOpacity, klass, value);
    parseOptionalProperty<Function<Color>>("fill-color", Key::FillColor, klass, value);
    parseOptionalProperty<PropertyTransition>("fill-color-transition", Key::FillColor, klass, value);
    parseOptionalProperty<Function<Color>>("fill-outline-color", Key::FillOutlineColor, klass, value);
    parseOptionalProperty<PropertyTransition>("fill-outline-color-transition", Key::FillOutlineColor, klass, value);
    parseOptionalProperty<Function<std::array<float, 2>>>("fill-translate", Key::FillTranslate, klass, value);
    parseOptionalProperty<PropertyTransition>("fill-translate-transition", Key::FillTranslate, klass, value);
    parseOptionalProperty<Function<TranslateAnchorType>>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
    parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("fill-image", Key::FillImage, klass, value, "fill-image-transition");

    parseOptionalProperty<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
    parseOptionalProperty<PropertyTransition>("line-opacity-transition", Key::LineOpacity, klass, value);
    parseOptionalProperty<Function<Color>>("line-color", Key::LineColor, klass, value);
    parseOptionalProperty<PropertyTransition>("line-color-transition", Key::LineColor, klass, value);
    parseOptionalProperty<Function<std::array<float,2>>>("line-translate", Key::LineTranslate, klass, value);
    parseOptionalProperty<PropertyTransition>("line-translate-transition", Key::LineTranslate, klass, value);
    parseOptionalProperty<Function<TranslateAnchorType>>("line-translate-anchor", Key::LineTranslateAnchor, klass, value);
    parseOptionalProperty<Function<float>>("line-width", Key::LineWidth, klass, value);
    parseOptionalProperty<PropertyTransition>("line-width-transition", Key::LineWidth, klass, value);
    parseOptionalProperty<Function<float>>("line-gap-width", Key::LineGapWidth, klass, value);
    parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value);
    parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
    parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
    parseOptionalProperty<PiecewiseConstantFunction<Faded<std::vector<float>>>>("line-dasharray", Key::LineDashArray, klass, value, "line-dasharray-transition");
    parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("line-image", Key::LineImage, klass, value, "line-image-transition");

    parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-opacity-transition", Key::IconOpacity, klass, value);
    parseOptionalProperty<Function<float>>("icon-size", Key::IconSize, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-size-transition", Key::IconSize, klass, value);
    parseOptionalProperty<Function<Color>>("icon-color", Key::IconColor, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-color-transition", Key::IconColor, klass, value);
    parseOptionalProperty<Function<Color>>("icon-halo-color", Key::IconHaloColor, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-halo-color-transition", Key::IconHaloColor, klass, value);
    parseOptionalProperty<Function<float>>("icon-halo-width", Key::IconHaloWidth, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-halo-width-transition", Key::IconHaloWidth, klass, value);
    parseOptionalProperty<Function<float>>("icon-halo-blur", Key::IconHaloBlur, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-halo-blur-transition", Key::IconHaloBlur, klass, value);
    parseOptionalProperty<Function<std::array<float, 2>>>("icon-translate", Key::IconTranslate, klass, value);
    parseOptionalProperty<PropertyTransition>("icon-translate-transition", Key::IconTranslate, klass, value);
    parseOptionalProperty<Function<TranslateAnchorType>>("icon-translate-anchor", Key::IconTranslateAnchor, klass, value);

    parseOptionalProperty<Function<float>>("text-opacity", Key::TextOpacity, klass, value);
    parseOptionalProperty<PropertyTransition>("text-opacity-transition", Key::TextOpacity, klass, value);
    parseOptionalProperty<Function<float>>("text-size", Key::TextSize, klass, value);
    parseOptionalProperty<PropertyTransition>("text-size-transition", Key::TextSize, klass, value);
    parseOptionalProperty<Function<Color>>("text-color", Key::TextColor, klass, value);
    parseOptionalProperty<PropertyTransition>("text-color-transition", Key::TextColor, klass, value);
    parseOptionalProperty<Function<Color>>("text-halo-color", Key::TextHaloColor, klass, value);
    parseOptionalProperty<PropertyTransition>("text-halo-color-transition", Key::TextHaloColor, klass, value);
    parseOptionalProperty<Function<float>>("text-halo-width", Key::TextHaloWidth, klass, value);
    parseOptionalProperty<PropertyTransition>("text-halo-width-transition", Key::TextHaloWidth, klass, value);
    parseOptionalProperty<Function<float>>("text-halo-blur", Key::TextHaloBlur, klass, value);
    parseOptionalProperty<PropertyTransition>("text-halo-blur-transition", Key::TextHaloBlur, klass, value);
    parseOptionalProperty<Function<std::array<float, 2>>>("text-translate", Key::TextTranslate, klass, value);
    parseOptionalProperty<PropertyTransition>("text-translate-transition", Key::TextTranslate, klass, value);
    parseOptionalProperty<Function<TranslateAnchorType>>("text-translate-anchor", Key::TextTranslateAnchor, klass, value);

    parseOptionalProperty<Function<float>>("raster-opacity", Key::RasterOpacity, klass, value);
    parseOptionalProperty<PropertyTransition>("raster-opacity-transition", Key::RasterOpacity, klass, value);
    parseOptionalProperty<Function<float>>("raster-hue-rotate", Key::RasterHueRotate, klass, value);
    parseOptionalProperty<PropertyTransition>("raster-hue-rotate-transition", Key::RasterHueRotate, klass, value);
    parseOptionalProperty<Function<float>>("raster-brightness-min", Key::RasterBrightnessLow, klass, value);
    parseOptionalProperty<Function<float>>("raster-brightness-max", Key::RasterBrightnessHigh, klass, value);
    parseOptionalProperty<PropertyTransition>("raster-brightness-transition", Key::RasterBrightness, klass, value);
    parseOptionalProperty<Function<float>>("raster-saturation", Key::RasterSaturation, klass, value);
    parseOptionalProperty<PropertyTransition>("raster-saturation-transition", Key::RasterSaturation, klass, value);
    parseOptionalProperty<Function<float>>("raster-contrast", Key::RasterContrast, klass, value);
    parseOptionalProperty<PropertyTransition>("raster-contrast-transition", Key::RasterContrast, klass, value);
    parseOptionalProperty<Function<float>>("raster-fade-duration", Key::RasterFade, klass, value);
    parseOptionalProperty<PropertyTransition>("raster-fade-duration-transition", Key::RasterFade, klass, value);

    parseOptionalProperty<Function<float>>("background-opacity", Key::BackgroundOpacity, klass, value);
    parseOptionalProperty<Function<Color>>("background-color", Key::BackgroundColor, klass, value);
    parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("background-image", Key::BackgroundImage, klass, value, "background-image-transition");
}

void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
    using Key = PropertyKey;

    parseVisibility<VisibilityType>(*bucket, value);

    parseOptionalProperty<Function<CapType>>("line-cap", Key::LineCap, bucket->layout, value);
    parseOptionalProperty<Function<JoinType>>("line-join", Key::LineJoin, bucket->layout, value);
    parseOptionalProperty<Function<float>>("line-miter-limit", Key::LineMiterLimit, bucket->layout, value);
    parseOptionalProperty<Function<float>>("line-round-limit", Key::LineRoundLimit, bucket->layout, value);

    parseOptionalProperty<Function<PlacementType>>("symbol-placement", Key::SymbolPlacement, bucket->layout, value);
    parseOptionalProperty<Function<float>>("symbol-min-distance", Key::SymbolMinDistance, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("symbol-avoid-edges", Key::SymbolAvoidEdges, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("icon-allow-overlap", Key::IconAllowOverlap, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("icon-ignore-placement", Key::IconIgnorePlacement, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("icon-optional", Key::IconOptional, bucket->layout, value);
    parseOptionalProperty<Function<RotationAlignmentType>>("icon-rotation-alignment", Key::IconRotationAlignment, bucket->layout, value);
    parseOptionalProperty<Function<float>>("icon-max-size", Key::IconMaxSize, bucket->layout, value);
    parseOptionalProperty<Function<std::string>>("icon-image", Key::IconImage, bucket->layout, value);
    parseOptionalProperty<Function<float>>("icon-rotate", Key::IconRotate, bucket->layout, value);
    parseOptionalProperty<Function<float>>("icon-padding", Key::IconPadding, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("icon-keep-upright", Key::IconKeepUpright, bucket->layout, value);
    parseOptionalProperty<Function<std::array<float, 2>>>("icon-offset", Key::IconOffset, bucket->layout, value);
    parseOptionalProperty<Function<RotationAlignmentType>>("text-rotation-alignment", Key::TextRotationAlignment, bucket->layout, value);
    parseOptionalProperty<Function<std::string>>("text-field", Key::TextField, bucket->layout, value);
    parseOptionalProperty<Function<std::string>>("text-font", Key::TextFont, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-max-size", Key::TextMaxSize, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-max-width", Key::TextMaxWidth, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-line-height", Key::TextLineHeight, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-letter-spacing", Key::TextLetterSpacing, bucket->layout, value);
    parseOptionalProperty<Function<TextJustifyType>>("text-justify", Key::TextJustify, bucket->layout, value);
    parseOptionalProperty<Function<TextAnchorType>>("text-anchor", Key::TextAnchor, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-max-angle", Key::TextMaxAngle, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-rotate", Key::TextRotate, bucket->layout, value);
    parseOptionalProperty<Function<float>>("text-padding", Key::TextPadding, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("text-keep-upright", Key::TextKeepUpright, bucket->layout, value);
    parseOptionalProperty<Function<TextTransformType>>("text-transform", Key::TextTransform, bucket->layout, value);
    parseOptionalProperty<Function<std::array<float, 2>>>("text-offset", Key::TextOffset, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("text-allow-overlap", Key::TextAllowOverlap, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("text-ignore-placement", Key::TextIgnorePlacement, bucket->layout, value);
    parseOptionalProperty<Function<bool>>("text-optional", Key::TextOptional, bucket->layout, value);

}

void StyleParser::parseReference(JSVal value, util::ptr<StyleLayer> &layer) {
    if (!value.IsString()) {
        Log::Warning(Event::ParseStyle, "layer ref of '%s' must be a string", layer->id.c_str());
        return;
    }
    const std::string ref { value.GetString(), value.GetStringLength() };
    auto it = layersMap.find(ref);
    if (it == layersMap.end()) {
        Log::Warning(Event::ParseStyle, "layer '%s' references unknown layer %s", layer->id.c_str(), ref.c_str());
        // We cannot parse this layer further.
        return;
    }

    // Recursively parse the referenced layer.
    stack.push_front(layer.get());
    parseLayer(it->second);
    stack.pop_front();

    util::ptr<StyleLayer> reference = it->second.second;
    layer->type = reference->type;
    layer->bucket = reference->bucket;
}

#pragma mark - Parse Bucket

void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
    util::ptr<StyleBucket> bucket = std::make_shared<StyleBucket>(layer->type);

    // We name the buckets according to the layer that defined it.
    bucket->name = layer->id;

    if (value.HasMember("source")) {
        JSVal value_source = replaceConstant(value["source"]);
        if (value_source.IsString()) {
            const std::string source_name = { value_source.GetString(), value_source.GetStringLength() };
            auto source_it = sourcesMap.find(source_name);
            if (source_it != sourcesMap.end()) {
                bucket->source = source_it->second;
            } else {
                Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", source_name.c_str(), layer->id.c_str());
            }
        } else {
            Log::Warning(Event::ParseStyle, "source of layer '%s' must be a string", layer->id.c_str());
        }
    }

    if (value.HasMember("source-layer")) {
        JSVal value_source_layer = replaceConstant(value["source-layer"]);
        if (value_source_layer.IsString()) {
            bucket->source_layer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
        } else {
            Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", layer->id.c_str());
        }
    }

    if (value.HasMember("filter")) {
        JSVal value_filter = replaceConstant(value["filter"]);
        bucket->filter = parseFilterExpression(value_filter);
    }

    if (value.HasMember("layout")) {
        JSVal value_render = replaceConstant(value["layout"]);
        parseLayout(value_render, bucket);
    }

    if (value.HasMember("minzoom")) {
        JSVal min_zoom = value["minzoom"];
        if (min_zoom.IsNumber()) {
            bucket->min_zoom = min_zoom.GetDouble();
        } else {
            Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", layer->id.c_str());
        }
    }

    if (value.HasMember("maxzoom")) {
        JSVal max_zoom = value["maxzoom"];
        if (max_zoom.IsNumber()) {
            bucket->max_zoom = max_zoom.GetDouble();
        } else {
            Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", layer->id.c_str());
        }
    }

    layer->bucket = bucket;
}

void StyleParser::parseSprite(JSVal value) {
    if (value.IsString()) {
        sprite = { value.GetString(), value.GetStringLength() };
    }
}

void StyleParser::parseGlyphURL(JSVal value) {
    if (value.IsString()) {
        glyph_url = { value.GetString(), value.GetStringLength() };
    }
}

}

max_stars_repo_name: tamaskenez/mapbox-gl-native-cmake

max_issues_repo_name: tamaskenez/mapbox-gl-native-cmake

max_forks_repo_name: tamaskenez/mapbox-gl-native-cmake


text:
// Software License for MTL
//
// Copyright (c) 2007 The Trustees of Indiana University.
//               2008 Dresden University of Technology and the Trustees of Indiana University.
//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
// All rights reserved.
// Authors: Peter Gottschling and Andrew Lumsdaine
//
// This file is part of the Matrix Template Library
//
// See also license.mtl.txt in the distribution.

#include <iostream>
#include <complex>
#include <boost/numeric/mtl/mtl.hpp>

using namespace std;

#if defined(MTL_WITH_INITLIST) && defined(MTL_WITH_AUTO) && defined(MTL_WITH_RANGEDFOR)
#include <initializer_list>

template <typename Matrix>
void test(const char* name)
{
    const Matrix A={{3, 4},
		    {5, 6}};

    cout << "Test " << name << ", A(initialization):\n" << A << "\n";
    MTL_THROW_IF(A[1][0] != 5.0, mtl::runtime_error("wrong value or position"));

    Matrix B;
    B= {{3, 4},
	{5, 6}};
    cout << "B(assignment):\n" << B << "\n";
    MTL_THROW_IF(B[1][0] != 5.0, mtl::runtime_error("wrong value or position"));
}
#else
template <typename Matrix>
void test(const char* ) {}
#endif

int main(int , char**)
{
    using mtl::mat::parameters;
    using namespace mtl;

    test<dense2D<double> >("dense2D<double>");
    test<dense2D<float> >("dense2D<float>");
    test<dense2D<complex<double> > >("dense2D<complex<double>>");
    test<dense2D<float, mat::parameters<col_major> > >("dense2D<float> col_major");

    test<compressed2D<float> >("compressed2D<float>");
    test<compressed2D<float, mat::parameters<col_major> > >("compressed2D<float> col_major");

    test<morton_dense<double, recursion::morton_z_mask> >("Morton Z-order");

    return 0;
}


text:
/**
 * Canary - A free and open-source MMORPG server emulator
 * Copyright (C) 2021 OpenTibiaBR <opentibiabr@outlook.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include <boost/range/adaptor/reversed.hpp>

#include "game/game.h"
#include "items/item.h"
#include "items/weapons/weapons.h"
#include "lua/functions/items/weapon_functions.hpp"
#include "lua/scripts/scripts.h"
#include "utils/tools.h"

int WeaponFunctions::luaCreateWeapon(lua_State* L) {
	// Weapon(type)
	if (getScriptEnv()->getScriptInterface() != &g_scripts().getScriptInterface()) {
		reportErrorFunc("Weapons can only be registered in the Scripts interface.");
		lua_pushnil(L);
		return 1;
	}

	WeaponType_t type = getNumber<WeaponType_t>(L, 2);
	switch (type) {
		case WEAPON_SWORD:
		case WEAPON_AXE:
		case WEAPON_CLUB: {
			WeaponMelee* weapon = new WeaponMelee(getScriptEnv()->getScriptInterface());
			if (weapon) {
				pushUserdata<WeaponMelee>(L, weapon);
				setMetatable(L, -1, "Weapon");
				weapon->weaponType = type;
				weapon->fromLua = true;
			} else {
				lua_pushnil(L);
			}
			break;
		}
		case WEAPON_DISTANCE:
		case WEAPON_AMMO: {
			WeaponDistance* weapon = new WeaponDistance(getScriptEnv()->getScriptInterface());
			if (weapon) {
				pushUserdata<WeaponDistance>(L, weapon);
				setMetatable(L, -1, "Weapon");
				weapon->weaponType = type;
				weapon->fromLua = true;
			} else {
				lua_pushnil(L);
			}
			break;
		}
		case WEAPON_WAND: {
			WeaponWand* weapon = new WeaponWand(getScriptEnv()->getScriptInterface());
			if (weapon) {
				pushUserdata<WeaponWand>(L, weapon);
				setMetatable(L, -1, "Weapon");
				weapon->weaponType = type;
				weapon->fromLua = true;
			} else {
				lua_pushnil(L);
			}
			break;
		}
		default: {
			lua_pushnil(L);
			break;
		}
	}
	return 1;
}

int WeaponFunctions::luaWeaponAction(lua_State* L) {
	// weapon:action(callback)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		std::string typeName = getString(L, 2);
		std::string tmpStr = asLowerCaseString(typeName);
		if (tmpStr == "removecount") {
			weapon->action = WEAPONACTION_REMOVECOUNT;
		} else if (tmpStr == "removecharge") {
			weapon->action = WEAPONACTION_REMOVECHARGE;
		} else if (tmpStr == "move") {
			weapon->action = WEAPONACTION_MOVE;
		} else {
			SPDLOG_ERROR("[WeaponFunctions::luaWeaponAction] - "
                         "No valid action {}", typeName);
			pushBoolean(L, false);
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponRegister(lua_State* L) {
	// weapon:register()
	Weapon** weaponPtr = getRawUserdata<Weapon>(L, 1);
	if (weaponPtr && *weaponPtr) {
		Weapon* weapon = *weaponPtr;
		if (weapon->weaponType == WEAPON_DISTANCE || weapon->weaponType == WEAPON_AMMO) {
			weapon = getUserdata<WeaponDistance>(L, 1);
		} else if (weapon->weaponType == WEAPON_WAND) {
			weapon = getUserdata<WeaponWand>(L, 1);
		} else {
			weapon = getUserdata<WeaponMelee>(L, 1);
		}

		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.weaponType = weapon->weaponType;

		if (weapon->getWieldInfo() != 0) {
			it.wieldInfo = weapon->getWieldInfo();
			it.vocationString = weapon->getVocationString();
			it.minReqLevel = weapon->getReqLevel();
			it.minReqMagicLevel = weapon->getReqMagLv();
		}

		weapon->configureWeapon(it);
		pushBoolean(L, g_weapons().registerLuaEvent(weapon));
		weapon = nullptr; // Releases weapon, removing the luascript reference
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponOnUseWeapon(lua_State* L) {
	// weapon:onUseWeapon(callback)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		if (!weapon->loadCallback()) {
			pushBoolean(L, false);
			return 1;
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponUnproperly(lua_State* L) {
	// weapon:wieldedUnproperly(bool)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setWieldUnproperly(getBoolean(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponLevel(lua_State* L) {
	// weapon:level(lvl)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setRequiredLevel(getNumber<uint32_t>(L, 2));
		weapon->setWieldInfo(WIELDINFO_LEVEL);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponMagicLevel(lua_State* L) {
	// weapon:magicLevel(lvl)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setRequiredMagLevel(getNumber<uint32_t>(L, 2));
		weapon->setWieldInfo(WIELDINFO_MAGLV);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponMana(lua_State* L) {
	// weapon:mana(mana)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setMana(getNumber<uint32_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponManaPercent(lua_State* L) {
	// weapon:manaPercent(percent)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setManaPercent(getNumber<uint32_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponHealth(lua_State* L) {
	// weapon:health(health)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setHealth(getNumber<int32_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponHealthPercent(lua_State* L) {
	// weapon:healthPercent(percent)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setHealthPercent(getNumber<uint32_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponSoul(lua_State* L) {
	// weapon:soul(soul)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setSoul(getNumber<uint32_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponBreakChance(lua_State* L) {
	// weapon:breakChance(percent)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setBreakChance(getNumber<uint32_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponWandDamage(lua_State* L) {
	// weapon:damage(damage[min, max]) only use this if the weapon is a wand!
	WeaponWand* weapon = getUserdata<WeaponWand>(L, 1);
	if (weapon) {
		weapon->setMinChange(getNumber<uint32_t>(L, 2));
		if (lua_gettop(L) > 2) {
			weapon->setMaxChange(getNumber<uint32_t>(L, 3));
		} else {
			weapon->setMaxChange(getNumber<uint32_t>(L, 2));
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponElement(lua_State* L) {
	// weapon:element(combatType)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		if (!getNumber<CombatType_t>(L, 2)) {
			std::string element = getString(L, 2);
			std::string tmpStrValue = asLowerCaseString(element);
			if (tmpStrValue == "earth") {
				weapon->params.combatType = COMBAT_EARTHDAMAGE;
			} else if (tmpStrValue == "ice") {
				weapon->params.combatType = COMBAT_ICEDAMAGE;
			} else if (tmpStrValue == "energy") {
				weapon->params.combatType = COMBAT_ENERGYDAMAGE;
			} else if (tmpStrValue == "fire") {
				weapon->params.combatType = COMBAT_FIREDAMAGE;
			} else if (tmpStrValue == "death") {
				weapon->params.combatType = COMBAT_DEATHDAMAGE;
			} else if (tmpStrValue == "holy") {
				weapon->params.combatType = COMBAT_HOLYDAMAGE;
			} else {
				SPDLOG_WARN("[WeaponFunctions:luaWeaponElement] - "
							"Type {} does not exist", element);
			}
		} else {
			weapon->params.combatType = getNumber<CombatType_t>(L, 2);
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponPremium(lua_State* L) {
	// weapon:premium(bool)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setNeedPremium(getBoolean(L, 2));
		weapon->setWieldInfo(WIELDINFO_PREMIUM);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponVocation(lua_State* L) {
	// weapon:vocation(vocName[, showInDescription = false, lastVoc = false])
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->addVocWeaponMap(getString(L, 2));
		weapon->setWieldInfo(WIELDINFO_VOCREQ);
		std::string tmp;
		bool showInDescription = false;
		bool lastVoc = false;
		if (getBoolean(L, 3)) {
			showInDescription = getBoolean(L, 3);
		}
		if (getBoolean(L, 4)) {
			lastVoc = getBoolean(L, 4);
		}
		if (showInDescription) {
			if (weapon->getVocationString().empty()) {
				tmp = asLowerCaseString(getString(L, 2));
				tmp += "s";
				weapon->setVocationString(tmp);
			} else {
				tmp = weapon->getVocationString();
				if (lastVoc) {
					tmp += " and ";
				} else {
					tmp += ", ";
				}
				tmp += asLowerCaseString(getString(L, 2));
				tmp += "s";
				weapon->setVocationString(tmp);
			}
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponId(lua_State* L) {
	// weapon:id(id)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		weapon->setID(getNumber<uint16_t>(L, 2));
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponAttack(lua_State* L) {
	// weapon:attack(atk)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.attack = getNumber<int32_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponDefense(lua_State* L) {
	// weapon:defense(defense[, extraDefense])
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.defense = getNumber<int32_t>(L, 2);
		if (lua_gettop(L) > 2) {
			it.extraDefense = getNumber<int32_t>(L, 3);
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponRange(lua_State* L) {
	// weapon:range(range)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.shootRange = getNumber<uint8_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponCharges(lua_State* L) {
	// weapon:charges(charges[, showCharges = true])
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		bool showCharges = true;
		if (lua_gettop(L) > 2) {
			showCharges = getBoolean(L, 3);
		}
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.charges = getNumber<uint8_t>(L, 2);
		it.showCharges = showCharges;
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponDuration(lua_State* L) {
	// weapon:duration(duration[, showDuration = true])
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		bool showDuration = true;
		if (lua_gettop(L) > 2) {
			showDuration = getBoolean(L, 3);
		}
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.decayTime = getNumber<uint8_t>(L, 2);
		it.showDuration = showDuration;
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponDecayTo(lua_State* L) {
	// weapon:decayTo([itemid = 0]
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t itemid = 0;
		if (lua_gettop(L) > 1) {
			itemid = getNumber<uint16_t>(L, 2);
		}
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.decayTo = itemid;
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponTransformEquipTo(lua_State* L) {
	// weapon:transformEquipTo(itemid)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.transformEquipTo = getNumber<uint16_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponTransformDeEquipTo(lua_State* L) {
	// weapon:transformDeEquipTo(itemid)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.transformDeEquipTo = getNumber<uint16_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponShootType(lua_State* L) {
	// weapon:shootType(type)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.shootType = getNumber<ShootType_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponSlotType(lua_State* L) {
	// weapon:slotType(slot)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		std::string slot = getString(L, 2);

		if (slot == "two-handed") {
			it.slotPosition = SLOTP_TWO_HAND;
		} else {
			it.slotPosition = SLOTP_HAND;
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponAmmoType(lua_State* L) {
	// weapon:ammoType(type)
	WeaponDistance* weapon = getUserdata<WeaponDistance>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		std::string type = getString(L, 2);

		if (type == "arrow") {
			it.ammoType = AMMO_ARROW;
		} else if (type == "bolt"){
			it.ammoType = AMMO_BOLT;
		} else {
			SPDLOG_WARN("[WeaponFunctions:luaWeaponAmmoType] - "
						"Type {} does not exist", type);
			lua_pushnil(L);
			return 1;
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponHitChance(lua_State* L) {
	// weapon:hitChance(chance)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.hitChance = getNumber<int8_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponMaxHitChance(lua_State* L) {
	// weapon:maxHitChance(max)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.maxHitChance = getNumber<int32_t>(L, 2);
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

int WeaponFunctions::luaWeaponExtraElement(lua_State* L) {
	// weapon:extraElement(atk, combatType)
	Weapon* weapon = getUserdata<Weapon>(L, 1);
	if (weapon) {
		uint16_t id = weapon->getID();
		ItemType& it = Item::items.getItemType(id);
		it.abilities.get()->elementDamage = getNumber<uint16_t>(L, 2);

		if (!getNumber<CombatType_t>(L, 3)) {
			std::string element = getString(L, 3);
			std::string tmpStrValue = asLowerCaseString(element);
			if (tmpStrValue == "earth") {
				it.abilities.get()->elementType = COMBAT_EARTHDAMAGE;
			} else if (tmpStrValue == "ice") {
				it.abilities.get()->elementType = COMBAT_ICEDAMAGE;
			} else if (tmpStrValue == "energy") {
				it.abilities.get()->elementType = COMBAT_ENERGYDAMAGE;
			} else if (tmpStrValue == "fire") {
				it.abilities.get()->elementType = COMBAT_FIREDAMAGE;
			} else if (tmpStrValue == "death") {
				it.abilities.get()->elementType = COMBAT_DEATHDAMAGE;
			} else if (tmpStrValue == "holy") {
				it.abilities.get()->elementType = COMBAT_HOLYDAMAGE;
			} else {
				SPDLOG_WARN("[WeaponFunctions:luaWeaponExtraElement] - "
							"Type {} does not exist", element);
			}
		} else {
			it.abilities.get()->elementType = getNumber<CombatType_t>(L, 3);
		}
		pushBoolean(L, true);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

max_stars_repo_name: Waclaw-I/BagnoOTS

max_issues_repo_name: Waclaw-I/BagnoOTS

max_forks_repo_name: Waclaw-I/BagnoOTS


text:
#include <edba/conn_info.hpp>

#include <edba/detail/utils.hpp>

#include <boost/foreach.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/algorithm/string/find_iterator.hpp>

#include <map>

using namespace std;

namespace edba {

struct conn_info::data
{
    struct string_ref_icmp
    {
        bool operator()(const string_ref& f, const string_ref& s) const
        {
            return boost::algorithm::ilexicographical_compare(f, s);
        }
    };

    typedef map<string_ref, string_ref, string_ref_icmp> rng_map;
    rng_map pairs_;
    string driver_name_;
    string clean_conn_string_;
};

conn_info::conn_info(const string_ref& conn_string) : data_(new data)
{
    using namespace boost;
    using namespace boost::algorithm;

    // First get driver name
    BOOST_AUTO(colon_iter, (find(conn_string.begin(), conn_string.end(), ':')));
    if (colon_iter == conn_string.end())
        throw invalid_connection_string("invalid_connection_string: " + to_string(conn_string) + " - driver name was not specified");

    BOOST_AUTO(driver_name_rng, (make_iterator_range(conn_string.begin(), colon_iter)));
    trim(driver_name_rng);
    data_->driver_name_.assign(driver_name_rng.begin(), driver_name_rng.end());

    // Iterate over all properties in connection string
    BOOST_AUTO(props, (make_iterator_range(++colon_iter, conn_string.end())));
    BOOST_AUTO(si, (make_split_iterator(props, first_finder(";"))));
    BOOST_TYPEOF(si) end_si;

    for(;si != end_si; ++si)
    {
        string_ref trimmed_pair = trim(*si);

        // split by '=' on key and value
        const char* eq_sign = find(trimmed_pair.begin(), trimmed_pair.end(), '=');
        string_ref key(trimmed_pair.begin(), eq_sign);
        string_ref val;
        if (eq_sign != trimmed_pair.end())
            val = string_ref(eq_sign + 1, trimmed_pair.end());

        // trim key and value
        trim(key);
        trim(val);

        if (key.empty())
            continue;

        // insert pair to map
        data_->pairs_.insert(make_pair(key, val));

        // prepare clean connection string without edba specific tags
        if('@' == key.front())
            continue;

        data_->clean_conn_string_.append(key.begin(), key.end());
        data_->clean_conn_string_.append("=");
        data_->clean_conn_string_.append(val.begin(), val.end());
        data_->clean_conn_string_.append("; ");
    }
}

bool conn_info::has(const char* key) const
{
    using namespace boost;
    return data_->pairs_.find(as_literal(key)) != data_->pairs_.end();
}

string_ref conn_info::get(const char* key, const char* def) const
{
    using namespace boost;

    BOOST_AUTO(res, data_->pairs_.find(as_literal(key)));
    return data_->pairs_.end() == res ? as_literal(def) : res->second;
}

string conn_info::get_copy(const char* key, const char* def) const
{
    return boost::copy_range<string>(get(key, def));
}

int conn_info::get(const char* key, int def) const
{
    using namespace boost;

    BOOST_AUTO(res, data_->pairs_.find(as_literal(key)));
    if (data_->pairs_.end() == res || res->second.empty())
        return def;

    char buf[20] = {0};
    EDBA_MEMCPY(buf, 20, res->second.begin(), res->second.size());

    return atoi(buf);
}

const string& conn_info::conn_string() const
{
    return data_->clean_conn_string_;
}

string conn_info::pgsql_conn_string() const
{
    string pq_str;

    BOOST_FOREACH(data::rng_map::const_reference p, data_->pairs_)
    {
        if(p.first[0]=='@')
            continue;

        pq_str.append(p.first.begin(), p.first.end());
        pq_str += "='";
        append_escaped(p.second, pq_str);
        pq_str += "' ";
    }

    return pq_str;
}

void conn_info::append_escaped(const string_ref& rng, string& dst)
{
    for(string_ref::difference_type i=0; i < rng.size(); ++i)
    {
        if(rng[i]=='\\')
            dst+="\\\\";
        else if(rng[i]=='\'')
            dst+="\\\'";
        else
            dst+=rng[i];
    }
}

string_ref conn_info::driver_name() const
{
    return data_->driver_name_;
}

}


text:
#include "hspice.h"
#include <boost/lexical_cast.hpp>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <stdio.h>
#include <string>
#include <strstream>

Hspice::Hspice(Settings *s) {
  config = s;
  templateFile = config->lookupString("simulation.template");
  netlistFile = config->lookupString("simulation.netlist");
  dt = config->lookupFloat("simulation.time");
  parameterSize = config->lookupInt("parameter.size");
  objectiveSize = config->lookupInt("objective.size");
}

Hspice::~Hspice() {}

void Hspice::generateNetlist(vector<string> parameterName,
                             vector<string> parameterUnit, double *parameters,
                             vector<string> setting) {
  icfilename = setting[0];
  bool dcSimulation = false;
  if (setting[2].compare("dc") == 0) {
    dcSimulation = true;
  }
  stringstream sed;
  sed << "cat " << templateFile << "  | sed ";
  for (int i = 0; i < parameterName.size(); i++) {
    sed << "-e s/" << parameterName[i] << "/" << parameters[i]
        << parameterUnit[i] << "/ ";
  }
  /*if (dcSimulation){
          sed << "-e s/$tran/" << "\".tran " << dt / 10 << " " << dt << "\"/ ";
          sed << "-e s/$save/" << "\".save type=ic file=" << setting[0] << "
  level=all time=" << dt << "\"/ "; }else{ sed << "-e s/$tran/" << "\".tran " <<
  dt / 10 << " " << dt << " uic" << "\"/ "; sed << "-e s/$save/" << "\".save
  type=ic file=" << setting[0] << " level=all time=" << dt << "\"/ "; sed << "-e
  s/$load/" << "\".load file=" << setting[1] << "\"/";
  }*/
  sed << " > " << netlistFile << endl;
  system(sed.str().c_str());
}

void Hspice::runSimulation(string simulationLogFilename) {
  string hspiceCommand =
      "hspice " + netlistFile + " > " + simulationLogFilename;
  cout << hspiceCommand << endl;
  system(hspiceCommand.c_str());
}

double *Hspice::parseSimulationLog(string filename, vector<string> objectives) {
  double *result = new double[objectiveSize];
  for (int i = 0; i < objectiveSize; i++) {
    result[i] = -1;
  }

  // generate the regex for each objective
  vector<regex> regs;
  for (int i = 0; i < objectives.size(); i++) {
    const string floating_point_regex =
        "([-+]?[0-9]*\\.?[0-9]+)[eE]([-+]?[0-9]+)?";
    const string whitespace_regex = "^[ \t]*";
    const string extraspace_regex = "[ ]*";
    string regexString = whitespace_regex + objectives[i] + "=" +
                         extraspace_regex + floating_point_regex;
    regex reg(regexString);
    regs.push_back(reg);
  }

  // parse the logfile, for each line, check it against all the
  // regular-expressions
  ifstream logfile(filename);
  int lineno = 0;
  string s;
  if (logfile.is_open()) {
    while (getline(logfile, s)) {
      lineno++;
      for (int i = 0; i < regs.size(); i++) {
        auto res = cmatch{};
        if (regex_search(s.c_str(), res, regs[i])) {
          double significand = boost::lexical_cast<double>(res[1]);
          double exponent = boost::lexical_cast<double>(res[2]);
          double value = significand * pow(10, exponent);
          result[i] = value;
          cout << lineno << ": " << objectives[i] << " " << value << endl;
        }
      }
    }
    logfile.close();
  }
  return result;
}

vector<double> Hspice::getFinalState() {
  vector<double> result;
  int d = config->lookupInt("dimensions");
  result.push_back(dt);
  double *tmp = parseICFile(icfilename + "0");
  for (int i = 0; i < d; i++) {
    result.push_back(tmp[i]);
  }
  return result;
}

// The input is something like this:
// 5.0000000000n   226.6820055575m   71.3468319456m  -71.3468319456m
// The first number is transient simulation time, the rest are variables that
// need to be converted to double
vector<double> Hspice::parse(string s) {
  vector<double> result;
  string word;
  string str = s;
  if (s.c_str()[s.length() - 1] == unluckyThirteen) { // guess what this does!
    str = s.substr(0, s.length() - 1);
  }
  stringstream stream(str);
  while (getline(stream, word, ' ')) {
    if (!is_only_ascii_whitespace(word)) {
      double d;
      stringstream ss(word);
      ss >> d;
      char c = word.c_str()[word.length() - 1];
      d = d * unit(c);
      result.push_back(d);
    }
  }
  return result;
}

bool Hspice::is_only_ascii_whitespace(const std::string &str) {
  // bool isOnlyWhiteSpace = false;
  // return str.find_first_not_of (' ') == str.npos)
  std::string::const_iterator it = str.begin();
  do {
    if (it == str.end())
      return true;
  } while (*it >= 0 && *it <= 0x7f && std::isspace(*(it++)));
  // one of these conditions will be optimized away by the compiler,
  // which one depends on whether char is signed or not
  return false;
}

double Hspice::unit(char u) {
  switch (u) {
  case 'f':
  case 'F':
    return 1e-15;
    break;
  case 'p':
  case 'P':
    return 1e-12;
    break;
  case 'n':
  case 'N':
    return 1e-9;
    break;
  case 'u':
  case 'U':
    return 1e-6;
    break;
  case 'm':
  case 'M':
    return 1e-3;
    break;
  case 'k':
  case 'K':
    return 1e3;
    break;

  default:
    return 1;
  }
}

double *Hspice::parseICFile(string fileName) {
  int d = config->lookupInt("dimensions");
  double *result = new double[d];
  string line;
  ifstream simResult(fileName);

  if (simResult.good()) {
    do {
      getline(simResult, line); // skip the headers (usually 12 lines)
    } while (line.compare(".ic") != 0);

    for (int i = 0; i < d; i++) {
      getline(simResult, line);
      line = line.substr(line.find_first_of("=") + 1, line.length());
      double value;
      stringstream ss(line);
      ss >> value;
      line.erase(line.find_last_not_of(" \n\r\t") + 1);
      char c = line.c_str()[line.length() - 1];
      value = value * unit(c);
      result[i] = value;
    }
  }
  simResult.close();
  return result;
}

max_stars_repo_name: ahmadyan/Duplex

max_issues_repo_name: ahmadyan/Duplex

max_forks_repo_name: ahmadyan/Duplex


text:
/******************************************************************************
 * Author(s): Christopher J. Havlicek
 *
 * See LICENSE and CONTACTS.
 ******************************************************************************/
#include "../../kmap.hpp"
#include "../master.hpp"

#include <boost/test/unit_test.hpp>

namespace utf = boost::unit_test;

namespace kmap::test {

BOOST_AUTO_TEST_SUITE( kmap_iface )
BOOST_AUTO_TEST_SUITE( create_alias ) // TODO: This suite should rather be named "alias" alone, as it includes deletion, movement, etc. checks as well.

BOOST_AUTO_TEST_CASE( leaf
                    ,
                    * utf::depends_on( "kmap_iface/create_node" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/2" ] ) );
    BOOST_TEST( kmap.exists( "/2.1" ) );
    BOOST_TEST( kmap.fetch_children( nodes[ "/2.1" ] ).empty() );
    BOOST_TEST( kmap.resolve( nodes[ "/2.1" ] ) == nodes[ "/1" ] );

    BOOST_TEST( kmap.select_node( nodes[ "/2.1" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/2.1" ] );
}

BOOST_AUTO_TEST_CASE( delete_alias
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/leaf" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/2" ] ) );
    BOOST_TEST( kmap.delete_node( nodes[ "/2.1" ] ) );
    BOOST_TEST( !kmap.exists( "/2.1" ) );
    BOOST_TEST( kmap.fetch_children( nodes[ "/2" ] ).empty() );
    BOOST_TEST( kmap.exists( "/1" ) );

    BOOST_TEST( kmap.select_node( nodes[ "/2" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/2" ] );
}

BOOST_AUTO_TEST_CASE( alias_from_alias
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/leaf" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1.2"
                   , "3"
                   , "4" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/3" ] ) );
    BOOST_TEST( kmap.create_alias( nodes[ "/3.1" ]
                                 , nodes[ "/4" ] ) );
    BOOST_TEST( kmap.resolve( nodes[ "/4.1" ] ) == nodes[ "/1" ] );
    BOOST_TEST( kmap.resolve( nodes[ "/4.1.2" ] ) == nodes[ "/1.2" ] );
}

BOOST_AUTO_TEST_CASE( alias_has_alias_child
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/leaf" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1.2"
                   , "3"
                   , "4" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/3" ] ) );
    BOOST_TEST( kmap.create_alias( nodes[ "/3" ]
                                 , nodes[ "/4" ] ) );
    BOOST_TEST( kmap.resolve( nodes[ "/4.3.1" ] ) == nodes[ "/1" ] );

    BOOST_TEST( kmap.select_node( nodes[ "/4" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/4" ] );
    BOOST_TEST( kmap.select_node( nodes[ "/4.3" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/4.3" ] );
    BOOST_TEST( kmap.select_node( nodes[ "/4.3.1.2" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/4.3.1.2" ] );
}

BOOST_AUTO_TEST_CASE( has_child
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/leaf" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1.2"
                   , "3"
                   , "4" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/3" ] ) );
    BOOST_TEST( kmap.exists( "/3.1.2" ) );
    BOOST_TEST( kmap.fetch_children( nodes[ "/3.1" ] ).size() == 1 );
    BOOST_TEST( kmap.resolve( nodes[ "/3.1" ] ) == nodes[ "/1" ] );
    BOOST_TEST( kmap.select_node( nodes[ "/3.1" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/3.1" ] );
}

BOOST_AUTO_TEST_CASE( update_alias_create_child
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/has_child" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/2" ] ) );
    create_lineages( "1.3" );
    BOOST_TEST( kmap.exists( "/2.1.3" ) );
    BOOST_TEST( kmap.select_node( nodes[ "/2.1.3" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/2.1.3" ] );
}

BOOST_AUTO_TEST_CASE( update_alias_delete_child
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/has_child" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1.2"
                   , "3" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/3" ] ) );
    BOOST_TEST( kmap.delete_node( nodes[ "/1.2" ] ) );
    BOOST_TEST( !kmap.exists( "/3.1.2" ) );
    BOOST_TEST( kmap.select_node( nodes[ "/3.1" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/3.1" ] );
}

BOOST_AUTO_TEST_CASE( update_alias_delete_source
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/has_child" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2" );

    BOOST_TEST( kmap.create_alias( nodes[ "/1" ]
                                 , nodes[ "/2" ] ) );
    BOOST_TEST( kmap.delete_node( nodes[ "/1" ] ) );
    BOOST_TEST( !kmap.exists( "/1" ) );
    BOOST_TEST( !kmap.exists( "/2.1" ) );
    BOOST_TEST( kmap.select_node( nodes[ "/2" ] ) );
    BOOST_TEST( kmap.selected_node() == nodes[ "/2" ] );
}

BOOST_AUTO_TEST_CASE( create_alias_nested_outside_in
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/has_child" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2"
                   , "3" );

    BOOST_TEST( kmap.create_alias( nodes[ "/3" ]
                                 , nodes[ "/2" ] ) );
    BOOST_TEST( kmap.create_alias( nodes[ "/2" ]
                                 , nodes[ "/1" ] ) );
    BOOST_TEST( kmap.select_node( nodes[ "/1" ] ) );
    BOOST_TEST( kmap.travel_right() );
    BOOST_TEST( kmap.travel_right() );
    BOOST_TEST( kmap.selected_node() == nodes[ "/1.2.3" ] );
}

BOOST_AUTO_TEST_CASE( create_alias_nested_inside_out
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/has_child" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2"
                   , "3" );

    BOOST_TEST( kmap.create_alias( nodes[ "/2" ]
                                 , nodes[ "/1" ] ) );
    BOOST_TEST( kmap.create_alias( nodes[ "/3" ]
                                 , nodes[ "/2" ] ) );
    BOOST_TEST( kmap.select_node( nodes[ "/1" ] ) );
    BOOST_TEST( kmap.travel_right() );
    BOOST_TEST( kmap.travel_right() );
    BOOST_TEST( kmap.selected_node() == nodes[ "/1.2.3" ] );
}

BOOST_AUTO_TEST_CASE( create_alias_from_alias
                    ,
                    * utf::depends_on( "kmap_iface/create_alias/has_child" )
                    * utf::fixture< ClearMapFixture >() )
{
    auto& kmap = Singleton::instance();
    auto const nodes = kmap.node_fetcher();

    create_lineages( "1"
                   , "2"
                   , "3" );

    BOOST_TEST( kmap.create_alias( nodes[ "/2" ]
                                 , nodes[ "/1" ] ) ); // Alias 2 to 1
    BOOST_TEST( kmap.create_alias( nodes[ "/3" ]
                                 , nodes[ "/1.2" ] ) ); // Alias 3 to the alias 2 (1.2).
}

BOOST_AUTO_TEST_SUITE_END( /*create_alias*/ )
BOOST_AUTO_TEST_SUITE_END( /* kmap_iface */ )

} // namespace kmap::test

max_stars_repo_name: moralismercatus/kmap

max_issues_repo_name: moralismercatus/kmap

max_forks_repo_name: moralismercatus/kmap


text:
//
// Created by Yohsuke Murase on 2020/05/16.
//

#ifndef CARAVAN_SCHEDULER__SPAWNERHANDLER_HPP_
#define CARAVAN_SCHEDULER__SPAWNERHANDLER_HPP_

#include <iostream>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

#ifndef USE_BOOST_FS
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#endif

typedef std::vector<std::pair<std::string, std::string>> env_t;

class SpawnerHandler {
 public:
  SpawnerHandler(int read_fd, int write_fd, int child_pid)
      : r_fd(read_fd), w_fd(write_fd), pid(child_pid), terminated(false) {};
  ~SpawnerHandler() {
    if (!terminated) { Terminate(); }
  }
  SpawnerHandler(SpawnerHandler &&) = default;
  int System(const std::string &cmd, const fs::path &work_dir = fs::current_path(),
             const env_t &envs = {}) {
    json j = {
        {"command", cmd},
        {"work_dir", work_dir.string()},
        {"envs", envs}
    };
    SendBytes(json::to_msgpack(j));
    int rc = ReceiveInt();
    return rc;
  }
  void Terminate() {
    close(r_fd);
    close(w_fd);
    waitpid(pid, nullptr, 0);
    terminated = true;
  };
 private:
  void SendBytes(const std::vector<uint8_t> &bytes) {
    uint64_t n = bytes.size();
    write(w_fd, &n, sizeof(uint64_t)); // send size
    write(w_fd, bytes.data(), bytes.size()); // send bytes
  }
  int ReceiveInt() {
    int n = 0;
    size_t s = read(r_fd, &n, sizeof(int));
    assert(s == sizeof(int));
    return n;
  }

  const int r_fd, w_fd, pid;
  bool terminated;
};

#endif //CARAVAN_SCHEDULER__SPAWNERHANDLER_HPP_

ext: hpp

max_stars_repo_name: crest-cassia/caravan

max_issues_repo_name: crest-cassia/caravan

max_forks_repo_name: crest-cassia/caravan


text:
//------------------------------------------------------------------------------
/*
    This file is part of rippled: https://github.com/ripple/rippled
    Copyright (c) 2012 - 2017 Ripple Labs Inc.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose  with  or without fee is hereby granted, provided that the above
    copyright notice and this permission notice appear in all copies.

    THE  SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF
    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    ANY  SPECIAL ,  DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN
    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#include <BeastConfig.h>
#include <ripple/core/TerminateHandler.h>
#include <ripple/basics/Log.h>
#include <ripple/beast/core/CurrentThreadName.h>

#include <boost/coroutine/exceptions.hpp>
#include <exception>
#include <iostream>
#include <typeinfo>

namespace ripple {

void terminateHandler()
{
    if (std::current_exception())
    {
        auto const thName =
            beast::getCurrentThreadName().value_or("Unknown");
        try
        {
            throw;
        }
        catch (const std::exception& e)
        {
            auto exName = typeid (e).name();
            std::cerr
                << "Terminating thread " << thName << ": unhandled "
                << exName << " '" << e.what () << "'\n";
            JLOG(debugLog().fatal())
                << "Terminating thread " << thName << ": unhandled "
                << exName << " '" << e.what () << "'\n";
        }
        catch (boost::coroutines::detail::forced_unwind const&)
        {
            std::cerr
                << "Terminating thread " << thName << ": forced_unwind\n";
            JLOG(debugLog().fatal())
                << "Terminating thread " << thName << ": forced_unwind\n";
        }
        catch (...)
        {
            std::cerr
                << "Terminating thread " << thName << ": unknown exception\n";
            JLOG (debugLog().fatal())
                << "Terminating thread " << thName << ": unknown exception\n";
        }
    }
}

}