<commit_before>/*
 * Copyright (C) 2012 BMW Car IT GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include "capu/os/NumericLimits.h"

TEST(NumericLimits, testLimits)
{
    EXPECT_EQ(capu::NumericLimits::Max<int64_t>(), static_cast<int64_t>(0x7fffffffffffffffLL));
    EXPECT_EQ(capu::NumericLimits::Min<int64_t>(), static_cast<int64_t>(0x8000000000000000LL));
    EXPECT_EQ(capu::NumericLimits::Max<uint64_t>(), static_cast<uint64_t>(0xffffffffffffffffULL));
    EXPECT_EQ(capu::NumericLimits::Min<uint64_t>(), static_cast<uint64_t>(0x0));
    EXPECT_EQ(capu::NumericLimits::Max<int32_t>(), static_cast<int32_t>(0x7fffffff));
    EXPECT_EQ(capu::NumericLimits::Min<int32_t>(), static_cast<int32_t>(0x80000000));
    EXPECT_EQ(capu::NumericLimits::Max<uint32_t>(), static_cast<uint32_t>(0xffffffff));
    EXPECT_EQ(capu::NumericLimits::Min<uint32_t>(), static_cast<uint32_t>(0x0));
    EXPECT_EQ(capu::NumericLimits::Max<int16_t>(), static_cast<int32_t>(32767));
    EXPECT_EQ(capu::NumericLimits::Min<int16_t>(), static_cast<int32_t>(-32768));
    EXPECT_EQ(capu::NumericLimits::Max<uint16_t>(), static_cast<int32_t>(65535));
    EXPECT_EQ(capu::NumericLimits::Min<uint16_t>(), static_cast<int32_t>(0));
    EXPECT_EQ(capu::NumericLimits::Max<int8_t>(), static_cast<int32_t>(127));
    EXPECT_EQ(capu::NumericLimits::Min<int8_t>(), static_cast<int32_t>(-128));
    EXPECT_EQ(capu::NumericLimits::Max<uint8_t>(), static_cast<int32_t>(255));
    EXPECT_EQ(capu::NumericLimits::Min<uint8_t>(), static_cast<int32_t>(0));
}
<commit_msg>Add test to confirm availability of NumericLimits for all relevant types<commit_after>/*
 * Copyright (C) 2012 BMW Car IT GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include "capu/os/NumericLimits.h"

TEST(NumericLimits, ensureAvailableForAlltypes)
{
    (void)capu::NumericLimits::Max<uint64_t>();
    (void)capu::NumericLimits::Max<int64_t>();

    (void)capu::NumericLimits::Max<uint32_t>();
    (void)capu::NumericLimits::Max<int32_t>();

    (void)capu::NumericLimits::Max<uint16_t>();
    (void)capu::NumericLimits::Max<int16_t>();

    (void)capu::NumericLimits::Max<uint8_t>();
    (void)capu::NumericLimits::Max<int8_t>();

    (void)capu::NumericLimits::Max<float>();

    (void)capu::NumericLimits::Max<capu::uint_t>();
    (void)capu::NumericLimits::Max<capu::int_t>();
}

TEST(NumericLimits, testLimits)
{
    EXPECT_EQ(capu::NumericLimits::Max<int64_t>(), static_cast<int64_t>(0x7fffffffffffffffLL));
    EXPECT_EQ(capu::NumericLimits::Min<int64_t>(), static_cast<int64_t>(0x8000000000000000LL));
    EXPECT_EQ(capu::NumericLimits::Max<uint64_t>(), static_cast<uint64_t>(0xffffffffffffffffULL));
    EXPECT_EQ(capu::NumericLimits::Min<uint64_t>(), static_cast<uint64_t>(0x0));
    EXPECT_EQ(capu::NumericLimits::Max<int32_t>(), static_cast<int32_t>(0x7fffffff));
    EXPECT_EQ(capu::NumericLimits::Min<int32_t>(), static_cast<int32_t>(0x80000000));
    EXPECT_EQ(capu::NumericLimits::Max<uint32_t>(), static_cast<uint32_t>(0xffffffff));
    EXPECT_EQ(capu::NumericLimits::Min<uint32_t>(), static_cast<uint32_t>(0x0));
    EXPECT_EQ(capu::NumericLimits::Max<int16_t>(), static_cast<int32_t>(32767));
    EXPECT_EQ(capu::NumericLimits::Min<int16_t>(), static_cast<int32_t>(-32768));
    EXPECT_EQ(capu::NumericLimits::Max<uint16_t>(), static_cast<int32_t>(65535));
    EXPECT_EQ(capu::NumericLimits::Min<uint16_t>(), static_cast<int32_t>(0));
    EXPECT_EQ(capu::NumericLimits::Max<int8_t>(), static_cast<int32_t>(127));
    EXPECT_EQ(capu::NumericLimits::Min<int8_t>(), static_cast<int32_t>(-128));
    EXPECT_EQ(capu::NumericLimits::Max<uint8_t>(), static_cast<int32_t>(255));
    EXPECT_EQ(capu::NumericLimits::Min<uint8_t>(), static_cast<int32_t>(0));
}
<|endoftext|>


<commit_before>/// @brief provides a proxy class to deal with integer below fixed-point number

#include <boost/operators.hpp>

namespace utils {
    template<typename T, size_t n, size_t f, class op, class up>
    class number;

    /// @brief proxy class for dealing with fixed-point numbers as with integers
    template<typename T, size_t n, size_t f, class op, class up>
    class as_native_proxy
        :    boost::operators<as_native_proxy<T, n, f, op, up> >,
             boost::operators2<as_native_proxy<T, n, f, op, up>, T>,
             boost::shiftable<as_native_proxy<T, n, f, op, up> >,
             boost::shiftable2<as_native_proxy<T, n, f, op, up>, T>
    {
        typedef as_native_proxy<T, n, f, op, up> this_class;
        typedef number<T, n, f, op, up> fixed_point_class;

    public:
        template<typename T>
        operator T() const
        {
            BOOST_STATIC_ASSERT((boost::is_arithmetic<T>::value));

            return T(this->value());
        }

        /// @brief copy operator
        template<typename T>
        void operator =(T val){ this->m_value = val; }

        /// @brief less operator. It is the same as one for native integral types
        /// is
        bool operator <(this_class const& x) const{ return x.value() < this->value(); }
        bool operator <(T x) const{ return x < this->value(); }

        /// @brief equality comparison operator. It is the same as one for native
        /// integral types is
        bool operator ==(this_class const& x) const{ return x.value() == this->value(); }
        bool operator ==(T x) const{ return x == this->value(); }

        /// @brief addition operator. It checks if result fits the bounds drawn
        /// from n bits of length
        this_class& operator +=(this_class const& x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_overflow(this->value() += x.value(), op()),
                up()
            );

            return *this;
        }
        this_class& operator +=(T x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_overflow(this->value() += x, op()),
                up()
            );

            return *this;
        }

        /// @brief subtraction operator. It checks if result fits the bounds drawn
        /// from n bits of length (signed/unsigned).
        this_class& operator -=(this_class const& x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_overflow(this->value() -= x.value(), op()),
                up()
            );

            return *this;
        }
        this_class& operator -=(T x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_overflow(this->value() -= x, op()),
                up()
            );

            return *this;
        }

        /// @brief multiplication operator. It checks if result fits the bounds
        /// drawn from n bits of length.
        this_class& operator *=(this_class const& x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_overflow(this->value() *= x.value(), op()),
                up()
            );

            return *this;
        }
        this_class& operator *=(T x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_overflow(this->value() *= x, op()),
                up()
            );

            return *this;
        }

        /// @brief division operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator /=(this_class const& x)
        {
            fixed_point_class::handle_underflow(
                this->value(),
                fixed_point_class::handle_underflow(this->value() /= x.value(), op()),
                up()
            );

            return *this;
        }
        this_class& operator /=(T x)
        {
            /*fixed_point_class::bounds::check*/(this->value() /= x);

            return *this;
        }
        /// @brief mod operator. It is the same as one for native types is.
        this_class& operator %=(this_class const& x)
        {
            this->value() %= x.value();

            return *this;
        }
        this_class& operator %=(T x){ this->value() %= x; return *this; }

        /// @brief xor operator. It checks if result fits the bounds drawn from
        /// n bits of length
        this_class& operator ^=(this_class const& x)
        {
            /*fixed_point_class::bounds::check*/(this->value() ^= x.value());

            return *this;
        }
        this_class& operator ^=(T x)
        {
            /*fixed_point_class::bounds::check*/(this->value() ^= x);

            return *this;
        }

        /// @brief and operator. It is the same as one for native types is.
        this_class& operator &=(this_class const& x)
        {
            this->value() &= x.value();

            return *this;
        }
        this_class& operator &=(T x){ this->value() &= x; return *this; }

        /// @brief or operator. It checks if result fits the bounds drawn from
        /// n bits of length
        this_class& operator |=(this_class const& x)
        {
            /*fixed_point_class::bounds::check*/(this->value() |= x.value());

            return *this;
        }
        this_class& operator !=(T x)
        {
            /*fixed_point_class::bounds::check*/(this->value() |= x);

            return *this;
        }

        /// @brief increment operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator ++()
        {
            /*fixed_point_class::bounds::check*/(this->value()++);

            return *this;
        }

        /// @brief decrement operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator --()
        {
            /*fixed_point_class::bounds::check*/(this->value()--);

            return *this;
        }

        /// @brief left shift operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator <<=(this_class const& x)
        {
            fixed_point_class::handle_overflow(this->value() <<= x.value(), op());

            return *this;
        }
        this_class& operator <<=(T x)
        {
            fixed_point_class::handle_overflow(this->value() <<= x, op());

            return *this;
        }

        /// @brief right shift operator. It is the same as one for native integers
        /// is.
        this_class& operator >>=(this_class const& x)
        {
            fixed_point_class::handle_underflow(this->value() >>= x.value(), op());

            return *this;
        }
        this_class& operator >>=(T x)
        {
            fixed_point_class::handle_underflow(this->value(), this->value() >>= x, up());

            return *this;
        }

    private:
        T& m_value;
        T& value(){ return this->m_value; }
        T value() const{ return this->m_value; }

        as_native_proxy(fixed_point_class& x)
            :    m_value(x.m_value){};

        template<typename T1, size_t n1, size_t f1, class op1, class up1>
        friend as_native_proxy<T1, n1, f1, op1, up1> as_native(number<T1, n1, f1, op1, up1>&);

        template<typename T1, size_t n1, size_t f1, class op1, class up1>
        friend class number;
    };
}
<commit_msg>as_native_proxy.hpp: core namespace + 'number' to 'fixed_point' + macro for checked arithmetics (common pattern in code)<commit_after>/// @brief provides a proxy class to deal with integer below fixed-point number

#include <boost/operators.hpp>
#include <boost/numeric/conversion/cast.hpp>

namespace core {
    template<typename T, size_t n, size_t f, class op, class up>
    class fixed_point;

    /// @brief proxy class for dealing with fixed-point numbers as with integers
    template<typename T, size_t n, size_t f, class op, class up>
    class as_native_proxy
        :    boost::operators<as_native_proxy<T, n, f, op, up> >,
             boost::operators2<as_native_proxy<T, n, f, op, up>, T>,
             boost::shiftable<as_native_proxy<T, n, f, op, up> >,
             boost::shiftable2<as_native_proxy<T, n, f, op, up>, T>
    {
        typedef as_native_proxy<T, n, f, op, up> this_class;
        typedef fixed_point<T, n, f, op, up> fixed_point_class;

    public:
        template<typename T>
        operator T() const
        {
            BOOST_STATIC_ASSERT((boost::is_arithmetic<T>::value));

            return T(this->value());
        }

        /// @brief copy operator
        template<typename T>
        void operator =(T val){ this->m_value = val; }

        /// @brief less operator. It is the same as one for native integral types
        /// is
        bool operator <(this_class const& x) const{ return x.value() < this->value(); }
        bool operator <(T x) const{ return x < this->value(); }

        /// @brief equality comparison operator. It is the same as one for native
        /// integral types is
        bool operator ==(this_class const& x) const{ return x.value() == this->value(); }
        bool operator ==(T x) const{ return x == this->value(); }

#define checked_arithmetics(f, val) \
    fixed_point_class::handle_underflow( \
        this->value(), \
        fixed_point_class::handle_overflow(this->value() f val, op()), \
        up() \
    )

        /// @brief addition operator. It checks if result fits the bounds drawn
        /// from n bits of length
        this_class& operator +=(this_class const& x)
        {
            checked_arithmetics(+=, x.value());

            return *this;
        }
        this_class& operator +=(T x)
        {
            checked_arithmetics(+=, x);

            return *this;
        }

        /// @brief subtraction operator. It checks if result fits the bounds drawn
        /// from n bits of length (signed/unsigned).
        this_class& operator -=(this_class const& x)
        {
            checked_arithmetics(-=, x.value());

            return *this;
        }
        this_class& operator -=(T x)
        {
            checked_arithmetics(-=, x);

            return *this;
        }

        /// @brief multiplication operator. It checks if result fits the bounds
        /// drawn from n bits of length.
        this_class& operator *=(this_class const& x)
        {
            checked_arithmetics(*=, x.value());

            return *this;
        }
        this_class& operator *=(T x)
        {
            checked_arithmetics(*=, x);

            return *this;
        }

        /// @brief division operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator /=(this_class const& x)
        {
            checked_arithmetics(/=, x.value());

            return *this;
        }
        this_class& operator /=(T x)
        {
            checked_arithmetics(/=, x);

            return *this;
        }
#undef checked_arithmetics

        /// @brief mod operator. It is the same as one for native types is.
        this_class& operator %=(this_class const& x)
        {
            this->value() %= x.value();

            return *this;
        }
        this_class& operator %=(T x){ this->value() %= x; return *this; }

        /// @brief xor operator. It checks if result fits the bounds drawn from
        /// n bits of length
        this_class& operator ^=(this_class const& x)
        {
            this->value() ^= x.value();

            return *this;
        }
        this_class& operator ^=(T x)
        {
            this->value() ^= boost::numeric_cast<fixed_point_class::word_type>(x);

            return *this;
        }

        /// @brief and operator. It is the same as one for native types is.
        this_class& operator &=(this_class const& x)
        {
            this->value() &= x.value();

            return *this;
        }
        this_class& operator &=(T x){ this->value() &= x; return *this; }

        /// @brief or operator. It checks if result fits the bounds drawn from
        /// n bits of length
        this_class& operator |=(this_class const& x)
        {
            this->value() |= x.value();

            return *this;
        }
        this_class& operator |=(T x)
        {
            this->value() |= boost::numeric_cast<fixed_point_class::word_type>(x);

            return *this;
        }

        /// @brief increment operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator ++()
        {
            fixed_point_class::handle_overflow(this->value()++, op());

            return *this;
        }

        /// @brief decrement operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator --()
        {
            fixed_point_class::handle_overflow(this->value()--, op());

            return *this;
        }

        /// @brief left shift operator. It checks if result fits the bounds drawn
        /// from n bits of length.
        this_class& operator <<=(this_class const& x)
        {
            fixed_point_class::handle_overflow(this->value() <<= x.value(), op());

            return *this;
        }
        this_class& operator <<=(T x)
        {
            fixed_point_class::handle_overflow(this->value() <<= x, op());

            return *this;
        }

        /// @brief right shift operator. It is the same as one for native integers
        /// is.
        this_class& operator >>=(this_class const& x)
        {
            this->value() >>= x.value();

            return *this;
        }
        this_class& operator >>=(T x)
        {
            this->value() >>= x;

            return *this;
        }

    private:
        T& m_value;
        T& value(){ return this->m_value; }
        T value() const{ return this->m_value; }

        as_native_proxy(fixed_point_class& x)
            :    m_value(x.m_value){};

        template<typename T1, size_t n1, size_t f1, class op1, class up1>
        friend as_native_proxy<T1, n1, f1, op1, up1> as_native(fixed_point<T1, n1, f1, op1, up1>&);

        template<typename T1, size_t n1, size_t f1, class op1, class up1>
        friend class fixed_point;
    };
}
<|endoftext|>


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

#include "CppExporter.h"

#include "OOModel/src/declarations/Project.h"
#include "OOModel/src/expressions/MetaCallExpression.h"
#include "OOModel/src/declarations/TypeAlias.h"

#include "Export/src/writer/Exporter.h"
#include "Export/src/writer/FragmentLayouter.h"
#include "Export/src/tree/CompositeFragment.h"
#include "ModelBase/src/model/TreeManager.h"
#include "OOModel/src/declarations/NameImport.h"
#include "OOModel/src/declarations/ExplicitTemplateInstantiation.h"
#include "OOInteraction/src/string_offset_providers/StringComponents.h"

#include "../CodeUnit.h"
#include "../CodeComposite.h"
#include "../Config.h"

namespace CppExport {

QList<Export::ExportError> CppExporter::exportTree(Model::TreeManager* treeManager,
																	const QString& pathToProjectContainerDirectory)
{
	QHash<QString, QString> mergeMap = Config::instance().dependencyUnitMergeMap();

	QList<CodeUnit*> codeUnits;
	units(treeManager->root(), "", codeUnits, mergeMap);

	for (auto unit : codeUnits) unit->calculateSourceFragments();
	for (auto unit : codeUnits) unit->calculateDependencies(codeUnits);

	auto directory = new Export::SourceDir{nullptr, pathToProjectContainerDirectory};
	for (auto codeComposite : mergeUnits(codeUnits, mergeMap))
		createFilesFromComposite(directory, codeComposite);

	auto layout = layouter();
	Export::Exporter::exportToFileSystem("", directory, &layout, Export::Exporter::ExportSpan::AllFiles);

	return {};

}

void CppExporter::createFilesFromComposite(Export::SourceDir* directory, CodeComposite* codeComposite)
{
	Export::SourceFragment* headerFragment{};
	Export::SourceFragment* sourceFragment{};
	codeComposite->fragments(headerFragment, sourceFragment);

	if (headerFragment)
		directory->file(codeComposite->name() + codeComposite->headerPartExtension()).append(headerFragment);
	if (sourceFragment)
		directory->file(codeComposite->name() + codeComposite->sourcePartExtension()).append(sourceFragment);
}

QString CppExporter::codeUnitNameQualifier(Model::Node* node)
{
	Q_ASSERT(node);

	QStringList result;
	if (auto parentModule = node->firstAncestorOfType<OOModel::Module>())
		do
		{
			if (parentModule->kind() == OOModel::Module::ModuleKind::Folder)
				result.prepend(parentModule->name());
			parentModule = parentModule->firstAncestorOfType<OOModel::Module>();
		} while (parentModule);

	if (auto parentProject = node->firstAncestorOfType<OOModel::Project>())
		result.prepend(parentProject->name());

	return result.join('/') + "/";
}

void CppExporter::units(Model::Node* current, QString namespaceName, QList<CodeUnit*>& result,
								QHash<QString, QString>& mergeMap)
{
	if (!DCast<OOModel::Project>(current))
	{
		if (auto ooModule = DCast<OOModel::Module>(current))
		{
			// ignore the "ExternalMacro" module
			if (ooModule->name() == "ExternalMacro") return;

			namespaceName = ooModule->name();
		}
		else if (auto ooNameImport = DCast<OOModel::NameImport>(current))
		{
			auto referenceExpression = DCast<OOModel::ReferenceExpression>(ooNameImport->importedName());
			Q_ASSERT(referenceExpression);

			if (!referenceExpression->target() || !DCast<OOModel::Project>(referenceExpression->target()))
				result.append(new CodeUnit{codeUnitNameQualifier(referenceExpression) +
														referenceExpression->name(),
													current});
			return;
		}
		else if (auto ooExplicitTemplateInstantiation = DCast<OOModel::ExplicitTemplateInstantiation>(current))
		{
			result.append(new CodeUnit{
					codeUnitNameQualifier(ooExplicitTemplateInstantiation) +
						OOInteraction::StringComponents::stringForNode(ooExplicitTemplateInstantiation->instantiatedClass()),
					current});
			return;
		}
		else if (auto ooDeclaration = DCast<OOModel::Declaration>(current))
		{
			auto codeUnitName = codeUnitNameQualifier(ooDeclaration) + ooDeclaration->name();
			if (auto method = DCast<OOModel::Method>(ooDeclaration))
				for (auto argument : *method->arguments())
					codeUnitName += OOInteraction::StringComponents::stringForNode(argument->typeExpression());

			result.append(new CodeUnit{codeUnitName, current});

			for (auto subDeclaration : *ooDeclaration->subDeclarations())
				if (auto explicitTemplateInstantiation = DCast<OOModel::ExplicitTemplateInstantiation>(subDeclaration))
				{
					auto typedListCodeUnitName = codeUnitName + "|ExplicitTemplateInstantiationInClass";

					auto it = mergeMap.find(codeUnitName);
					if (it != mergeMap.end())
						mergeMap.insert(typedListCodeUnitName, *it);
					else
						mergeMap.insert(typedListCodeUnitName, codeUnitName);

					result.append(new CodeUnit{typedListCodeUnitName, explicitTemplateInstantiation});
				}
			return;
		}
		else if (auto ooMetaCall = DCast<OOModel::MetaCallExpression>(current))
		{
			auto ooCalleeReference = DCast<OOModel::ReferenceExpression>(ooMetaCall->callee());
			Q_ASSERT(ooCalleeReference);

			QStringList arguments;
			for (auto argument : *ooMetaCall->arguments())
				arguments.append(OOInteraction::StringComponents::stringForNode(argument));

			result.append(new CodeUnit{codeUnitNameQualifier(ooCalleeReference) + ooCalleeReference->name() +
												"(" + arguments.join(",") + ")", current});
			return;
		}
	}

	for (auto child : current->children())
		units(child, namespaceName, result, mergeMap);
}

QList<CodeComposite*> CppExporter::mergeUnits(QList<CodeUnit*>& units, QHash<QString, QString>& mergeMap)
{
	QHash<QString, CodeComposite*> nameToCompositeMap;
	for (auto unit : units)
	{
		auto it = mergeMap.find(unit->name());
		auto compositeName = it != mergeMap.end() ? *it : unit->name();

		auto cIt = nameToCompositeMap.find(compositeName);
		if (cIt != nameToCompositeMap.end())
			// case A: the composite that unit is a part of already exists => merge
			(*cIt)->addUnit(unit);
		else
		{
			// case B: the composite that unit is a part of does not yet exist
			auto composite = new CodeComposite{compositeName};
			composite->addUnit(unit);
			nameToCompositeMap.insert(composite->name(), composite);
		}
	}

	return nameToCompositeMap.values();
}

Export::FragmentLayouter CppExporter::layouter()
{
	auto result = Export::FragmentLayouter{"\t"};
	result.addRule("enumerators", Export::FragmentLayouter::IndentChildFragments, "", ",\n", "");
	result.addRule("vertical", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("sections", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("declarationComment", Export::FragmentLayouter::NoIndentation
							| Export::FragmentLayouter::NewLineAfterPostfix, "", "\n", "");
	result.addRule("spacedSections", Export::FragmentLayouter::NoIndentation, "", "\n\n", "");
	result.addRule("accessorSections", Export::FragmentLayouter::IndentChildFragments, "", "\n", "");
	result.addRule("bodySections", Export::FragmentLayouter::NewLineBefore
						  | Export::FragmentLayouter::IndentChildFragments | Export::FragmentLayouter::NewLineAfterPrefix
						  | Export::FragmentLayouter::NewLineBeforePostfix, "{", "\n", "}");
	result.addRule("space", Export::FragmentLayouter::SpaceAtEnd, "", " ", "");
	result.addRule("comma", Export::FragmentLayouter::SpaceAfterSeparator, "", ",", "");
	result.addRule("initializerList", Export::FragmentLayouter::SpaceAfterSeparator, "{", ",", "}");
	result.addRule("argsList", Export::FragmentLayouter::SpaceAfterSeparator, "(", ",", ")");
	result.addRule("typeArgsList", Export::FragmentLayouter::SpaceAfterSeparator, "<", ",", ">");
	result.addRule("templateArgsList", Export::FragmentLayouter::SpaceAfterSeparator
							| Export::FragmentLayouter::NewLineAfterPostfix, "template<", ",", ">");

	result.addRule("body", Export::FragmentLayouter::NewLineBefore | Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"{", "\n", "}");
	result.addRule("bodyNoBraces", Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"", "\n", "");
	result.addRule("sameLineIf", Export::FragmentLayouter::NewLineBeforePostfix, " ", "\n", "");
	result.addRule("macroBody", Export::FragmentLayouter::NewLineBefore | Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"", "\n", "");
	result.addRule("macro", Export::FragmentLayouter::BackslashAfterLines
						| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix);
	result.addRule("emptyLineAtEnd", Export::FragmentLayouter::EmptyLineAtEnd);
	result.addRule("namespace", Export::FragmentLayouter::NoIndentation | Export::FragmentLayouter::SpaceAfterPrefix,
						"namespace", "", "");

	return result;
}

Export::ExportMapContainer& CppExporter::exportMaps()
{
	static Export::ExportMapContainer* container = new Export::ExportMapContainer{};
	return *container;
}

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

#include "CppExporter.h"

#include "OOModel/src/declarations/Project.h"
#include "OOModel/src/expressions/MetaCallExpression.h"
#include "OOModel/src/declarations/TypeAlias.h"

#include "Export/src/writer/Exporter.h"
#include "Export/src/writer/FragmentLayouter.h"
#include "Export/src/tree/CompositeFragment.h"
#include "ModelBase/src/model/TreeManager.h"
#include "OOModel/src/declarations/NameImport.h"
#include "OOModel/src/declarations/ExplicitTemplateInstantiation.h"
#include "OOInteraction/src/string_offset_providers/StringComponents.h"

#include "../CodeUnit.h"
#include "../CodeComposite.h"
#include "../Config.h"

namespace CppExport {

QList<Export::ExportError> CppExporter::exportTree(Model::TreeManager* treeManager,
																	const QString& pathToProjectContainerDirectory)
{
	QHash<QString, QString> mergeMap = Config::instance().dependencyUnitMergeMap();

	QList<CodeUnit*> codeUnits;
	units(treeManager->root(), "", codeUnits, mergeMap);

	for (auto unit : codeUnits) unit->calculateSourceFragments();
	for (auto unit : codeUnits) unit->calculateDependencies(codeUnits);

	auto directory = new Export::SourceDir{nullptr, pathToProjectContainerDirectory};
	for (auto codeComposite : mergeUnits(codeUnits, mergeMap))
		createFilesFromComposite(directory, codeComposite);

	auto layout = layouter();
	Export::Exporter::exportToFileSystem("", directory, &layout, Export::Exporter::ExportSpan::AllFiles);

	return {};

}

void CppExporter::createFilesFromComposite(Export::SourceDir* directory, CodeComposite* codeComposite)
{
	Export::SourceFragment* headerFragment{};
	Export::SourceFragment* sourceFragment{};
	codeComposite->fragments(headerFragment, sourceFragment);

	if (headerFragment)
		directory->file(codeComposite->name() + codeComposite->headerPartExtension()).append(headerFragment);
	if (sourceFragment)
		directory->file(codeComposite->name() + codeComposite->sourcePartExtension()).append(sourceFragment);
}

QString CppExporter::codeUnitNameQualifier(Model::Node* node)
{
	Q_ASSERT(node);

	QStringList result;
	if (auto parentModule = node->firstAncestorOfType<OOModel::Module>())
		do
		{
			if (parentModule->kind() == OOModel::Module::ModuleKind::Folder)
				result.prepend(parentModule->name());
			parentModule = parentModule->firstAncestorOfType<OOModel::Module>();
		} while (parentModule);

	if (auto parentProject = node->firstAncestorOfType<OOModel::Project>())
		result.prepend(parentProject->name());

	return result.join('/') + "/";
}

void CppExporter::units(Model::Node* current, QString namespaceName, QList<CodeUnit*>& result,
								QHash<QString, QString>& mergeMap)
{
	if (!DCast<OOModel::Project>(current))
	{
		if (auto ooModule = DCast<OOModel::Module>(current))
		{
			// ignore the "ExternalMacro" module
			if (ooModule->name() == "ExternalMacro") return;

			namespaceName = ooModule->name();
		}
		else if (auto ooNameImport = DCast<OOModel::NameImport>(current))
		{
			auto referenceExpression = DCast<OOModel::ReferenceExpression>(ooNameImport->importedName());
			Q_ASSERT(referenceExpression);

			if (!referenceExpression->target() || !DCast<OOModel::Project>(referenceExpression->target()))
				result.append(new CodeUnit{codeUnitNameQualifier(referenceExpression) +
														referenceExpression->name(),
													current});
			return;
		}
		else if (auto ooExplicitTemplateInstantiation = DCast<OOModel::ExplicitTemplateInstantiation>(current))
		{
			result.append(new CodeUnit{
					codeUnitNameQualifier(ooExplicitTemplateInstantiation) +
						OOInteraction::StringComponents::stringForNode(ooExplicitTemplateInstantiation->instantiatedClass()),
					current});
			return;
		}
		else if (auto ooDeclaration = DCast<OOModel::Declaration>(current))
		{
			auto codeUnitName = codeUnitNameQualifier(ooDeclaration) + ooDeclaration->name();
			if (auto method = DCast<OOModel::Method>(ooDeclaration))
				for (auto argument : *method->arguments())
					codeUnitName += OOInteraction::StringComponents::stringForNode(argument->typeExpression());

			result.append(new CodeUnit{codeUnitName, current});

			for (auto subDeclaration : *ooDeclaration->subDeclarations())
				if (auto explicitTemplateInstantiation = DCast<OOModel::ExplicitTemplateInstantiation>(subDeclaration))
				{
					auto typedListCodeUnitName = codeUnitName + "|ExplicitTemplateInstantiationInClass";

					auto it = mergeMap.find(codeUnitName);
					if (it != mergeMap.end())
						mergeMap.insert(typedListCodeUnitName, *it);
					else
						mergeMap.insert(typedListCodeUnitName, codeUnitName);

					result.append(new CodeUnit{typedListCodeUnitName, explicitTemplateInstantiation});
				}
				else if (auto nameImport = DCast<OOModel::NameImport>(subDeclaration))
				{
					auto nameImportCodeUnitName = codeUnitName + "|NameImportInClass";

					auto it = mergeMap.find(codeUnitName);
					if (it != mergeMap.end())
						mergeMap.insert(nameImportCodeUnitName, *it);
					else
						mergeMap.insert(nameImportCodeUnitName, codeUnitName);

					result.append(new CodeUnit{nameImportCodeUnitName, nameImport});
				}
			return;
		}
		else if (auto ooMetaCall = DCast<OOModel::MetaCallExpression>(current))
		{
			auto ooCalleeReference = DCast<OOModel::ReferenceExpression>(ooMetaCall->callee());
			Q_ASSERT(ooCalleeReference);

			QStringList arguments;
			for (auto argument : *ooMetaCall->arguments())
				arguments.append(OOInteraction::StringComponents::stringForNode(argument));

			result.append(new CodeUnit{codeUnitNameQualifier(ooCalleeReference) + ooCalleeReference->name() +
												"(" + arguments.join(",") + ")", current});
			return;
		}
	}

	for (auto child : current->children())
		units(child, namespaceName, result, mergeMap);
}

QList<CodeComposite*> CppExporter::mergeUnits(QList<CodeUnit*>& units, QHash<QString, QString>& mergeMap)
{
	QHash<QString, CodeComposite*> nameToCompositeMap;
	for (auto unit : units)
	{
		auto it = mergeMap.find(unit->name());
		auto compositeName = it != mergeMap.end() ? *it : unit->name();

		auto cIt = nameToCompositeMap.find(compositeName);
		if (cIt != nameToCompositeMap.end())
			// case A: the composite that unit is a part of already exists => merge
			(*cIt)->addUnit(unit);
		else
		{
			// case B: the composite that unit is a part of does not yet exist
			auto composite = new CodeComposite{compositeName};
			composite->addUnit(unit);
			nameToCompositeMap.insert(composite->name(), composite);
		}
	}

	return nameToCompositeMap.values();
}

Export::FragmentLayouter CppExporter::layouter()
{
	auto result = Export::FragmentLayouter{"\t"};
	result.addRule("enumerators", Export::FragmentLayouter::IndentChildFragments, "", ",\n", "");
	result.addRule("vertical", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("sections", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("declarationComment", Export::FragmentLayouter::NoIndentation
							| Export::FragmentLayouter::NewLineAfterPostfix, "", "\n", "");
	result.addRule("spacedSections", Export::FragmentLayouter::NoIndentation, "", "\n\n", "");
	result.addRule("accessorSections", Export::FragmentLayouter::IndentChildFragments, "", "\n", "");
	result.addRule("bodySections", Export::FragmentLayouter::NewLineBefore
						  | Export::FragmentLayouter::IndentChildFragments | Export::FragmentLayouter::NewLineAfterPrefix
						  | Export::FragmentLayouter::NewLineBeforePostfix, "{", "\n", "}");
	result.addRule("space", Export::FragmentLayouter::SpaceAtEnd, "", " ", "");
	result.addRule("comma", Export::FragmentLayouter::SpaceAfterSeparator, "", ",", "");
	result.addRule("initializerList", Export::FragmentLayouter::SpaceAfterSeparator, "{", ",", "}");
	result.addRule("argsList", Export::FragmentLayouter::SpaceAfterSeparator, "(", ",", ")");
	result.addRule("typeArgsList", Export::FragmentLayouter::SpaceAfterSeparator, "<", ",", ">");
	result.addRule("templateArgsList", Export::FragmentLayouter::SpaceAfterSeparator
							| Export::FragmentLayouter::NewLineAfterPostfix, "template<", ",", ">");

	result.addRule("body", Export::FragmentLayouter::NewLineBefore | Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"{", "\n", "}");
	result.addRule("bodyNoBraces", Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"", "\n", "");
	result.addRule("sameLineIf", Export::FragmentLayouter::NewLineBeforePostfix, " ", "\n", "");
	result.addRule("macroBody", Export::FragmentLayouter::NewLineBefore | Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"", "\n", "");
	result.addRule("macro", Export::FragmentLayouter::BackslashAfterLines
						| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix);
	result.addRule("emptyLineAtEnd", Export::FragmentLayouter::EmptyLineAtEnd);
	result.addRule("namespace", Export::FragmentLayouter::NoIndentation | Export::FragmentLayouter::SpaceAfterPrefix,
						"namespace", "", "");

	return result;
}

Export::ExportMapContainer& CppExporter::exportMaps()
{
	static Export::ExportMapContainer* container = new Export::ExportMapContainer{};
	return *container;
}

}
<|endoftext|>


<commit_before><commit_msg>DS1, week 7, tree and forest,  problem 1<commit_after><|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <string.h>
#if defined(_WIN32) || defined(_MSC_VER)
    #define __PRETTY_FUNCTION__ __FUNCSIG__
    #if _MSC_VER < 1900
        #define snprintf sprintf_s
    #endif
    #define STATIC_ static
    #define __AF_FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#else
    //#ifndef __PRETTY_FUNCTION__
    //    #define __PRETTY_FUNCTION__ __func__ // __PRETTY_FUNCTION__ Fallback
    //#endif
    #define STATIC_ inline
    #define __AF_FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#endif

<commit_msg>__AF_FILENAME__ returns path from src<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <string>

inline std::string
clipFilePath(std::string path, std::string str)
{
    std::string::size_type pos = path.rfind(str);
    if(pos == std::string::npos) {
        return path;
    } else {
        return path.substr(pos);
    }
}

#if defined(_WIN32) || defined(_MSC_VER)
    #define __PRETTY_FUNCTION__ __FUNCSIG__
    #if _MSC_VER < 1900
        #define snprintf sprintf_s
    #endif
    #define STATIC_ static
    #define __AF_FILENAME__ (clipFilePath(__FILE__, "src\\").c_str())
#else
    //#ifndef __PRETTY_FUNCTION__
    //    #define __PRETTY_FUNCTION__ __func__ // __PRETTY_FUNCTION__ Fallback
    //#endif
    #define STATIC_ inline
    #define __AF_FILENAME__ (clipFilePath(__FILE__, "src/").c_str())
#endif

<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS visibility02 (1.3.50); FILE MERGED 2005/01/27 17:58:27 mhu 1.3.50.1: #i38608# More classes / symbols need to be exported.<commit_after><|endoftext|>


<commit_before>//
// Created by lz on 1/24/17.
//

#include "connection.hpp"
#include <functional>
#include <system_error>
#include <stdexcept>

//TODO: monitor POLLIN/POLLOUT individually
namespace c10k
{
    void Connection::register_event()
    {
        std::lock_guard<std::recursive_mutex> lk(mutex);
        using namespace std::placeholders;
        if (!registered.exchange(true)) {
            logger->trace("Event registered");
            el.add_event(fd, EventType {EventCategory::POLLRDHUP},
                         std::bind(&Connection::event_handler, shared_from_this(), _1));
            event_listen.set(EventCategory::POLLRDHUP);
        }
    }

    void Connection::remove_event()
    {
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (registered.exchange(false)) {
            logger->trace("Event removed");
            el.remove_event(fd);
        }
    }

    void Connection::enable_event(EventCategory ec)
    {
        using namespace std::placeholders;
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (!event_listen.is(ec) && !is_closed())
        {
            event_listen.set(ec);
            logger->trace("Enable event listen: cur={}", event_listen);
            el.modify_event(fd, event_listen, std::bind(&Connection::event_handler, shared_from_this(), _1));
        }
    }

    void Connection::disable_event(EventCategory ec)
    {
        using namespace std::placeholders;
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (event_listen.is(ec) && !is_closed())
        {
            event_listen.unset(ec);
            logger->trace("Disable event listen: cur={}", event_listen);
            el.modify_event(fd, event_listen, std::bind(&Connection::event_handler, shared_from_this(), _1));
        }
    }

    void Connection::handle_read()
    {
        logger->trace("Handling read, there are {} items in r_buffer", r_buffer.size());
        if (is_closed())
            throw std::runtime_error("Read when socket is closed");
        while (!r_buffer.empty()) // can read
        {
            detail::ConnRReq &req = r_buffer.front();
            logger->trace("Read the first request: {} / {}", req.buf.size(), req.requested_len);
            for (;req.buf.size() < req.requested_len;)
            {
                int read_len = std::min(1024, req.requested_len - (int)req.buf.size());
                req.buf.resize(req.buf.size() + read_len);
                int read_result = ::read(fd, &*req.buf.end() - read_len, read_len);
                req.buf.resize(read_result > 0 ? req.buf.size() - (read_len - read_result) : req.buf.size() - read_len);
                logger->trace("Performing read {} bytes, result={}", read_len, read_result);
                if (read_result < 0)
                    if (errno != EAGAIN && errno != EWOULDBLOCK)
                        throw std::system_error(read_result, std::system_category());
                    else
                        break;
            }

            if (req.buf.size() == req.requested_len) // read OK
            {
                logger->trace("Req read OK, executing callback");
                req.exec_callback(shared_from_this(), &*req.buf.begin(), &*req.buf.end());
                r_buffer.pop();
            } else // wait for next time
            {
                break;
            }
        }
        if (r_buffer.empty())
            disable_event(EventCategory::POLLIN);
    }

    void Connection::handle_write()
    {
        logger->trace("Handling write, there are {} items in w_buffer", w_buffer.size());
        if (is_closed())
            throw std::runtime_error("Write when socket is closed");
        while (!w_buffer.empty()) // can write
        {
            detail::ConnWReq &req = w_buffer.front();
            logger->trace("Write the first request: {} / {}", req.offset, req.buf.size());
            int write_result;
            for(;req.offset < req.buf.size();)
            {
                int write_len = std::min(1024, (int)req.buf.size() - req.offset);
                logger->trace("Performing write {} bytes from off={}", write_len, req.offset);
                int write_result = ::write(fd, &*req.buf.begin() + req.offset, write_len);
                logger->trace("Write result={}", write_result);
                if (write_result < 0)
                    if (errno != EAGAIN && errno != EWOULDBLOCK)
                        throw std::system_error(write_result, std::system_category());
                    else
                        break;
                req.offset += write_result;
            }
            if (req.offset == req.buf.size()) // write OK
            {
                logger->trace("Req write OK, executing callback");
                auto this_ptr = shared_from_this();
                logger->trace("Current ptr use_count={}", this_ptr.use_count());
                req.exec_callback(shared_from_this());
                logger->trace("Current ptr after use use_count={}", this_ptr.use_count());
                w_buffer.pop();
            } else
            {
                break; // wait for next time
            }
        }
        if (w_buffer.empty())
            disable_event(EventCategory::POLLOUT);
    }

    void Connection::event_handler(const Event &e)
    {
        auto self = shared_from_this();
        logger->debug("Handling event {}", e);
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (!is_closed()) {
            try {
                if (e.event_type.is(EventCategory::POLLIN))
                    handle_read();
                if (e.event_type.is(EventCategory::POLLOUT))
                    handle_write();
                if (e.event_type.is_err())
                    close();
            } catch (std::exception &e) {
                logger->warn("Socket closed when processing event, closing connection:", e.what());
                close();
            }
        }
    }

}<commit_msg>Connection: Read result == 0 <=> socket close<commit_after>//
// Created by lz on 1/24/17.
//

#include "connection.hpp"
#include <functional>
#include <system_error>
#include <stdexcept>

//TODO: monitor POLLIN/POLLOUT individually
namespace c10k
{
    void Connection::register_event()
    {
        std::lock_guard<std::recursive_mutex> lk(mutex);
        using namespace std::placeholders;
        if (!registered.exchange(true)) {
            logger->trace("Event registered");
            el.add_event(fd, EventType {EventCategory::POLLRDHUP},
                         std::bind(&Connection::event_handler, shared_from_this(), _1));
            event_listen.set(EventCategory::POLLRDHUP);
        }
    }

    void Connection::remove_event()
    {
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (registered.exchange(false)) {
            logger->trace("Event removed");
            el.remove_event(fd);
        }
    }

    void Connection::enable_event(EventCategory ec)
    {
        using namespace std::placeholders;
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (!event_listen.is(ec) && !is_closed())
        {
            event_listen.set(ec);
            logger->trace("Enable event listen: cur={}", event_listen);
            el.modify_event(fd, event_listen, std::bind(&Connection::event_handler, shared_from_this(), _1));
        }
    }

    void Connection::disable_event(EventCategory ec)
    {
        using namespace std::placeholders;
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (event_listen.is(ec) && !is_closed())
        {
            event_listen.unset(ec);
            logger->trace("Disable event listen: cur={}", event_listen);
            el.modify_event(fd, event_listen, std::bind(&Connection::event_handler, shared_from_this(), _1));
        }
    }

    void Connection::handle_read()
    {
        logger->trace("Handling read, there are {} items in r_buffer", r_buffer.size());
        if (is_closed())
            throw std::runtime_error("Read when socket is closed");
        while (!r_buffer.empty()) // can read
        {
            detail::ConnRReq &req = r_buffer.front();
            logger->trace("Read the first request: {} / {}", req.buf.size(), req.requested_len);
            for (;req.buf.size() < req.requested_len;)
            {
                int read_len = std::min(1024, req.requested_len - (int)req.buf.size());
                req.buf.resize(req.buf.size() + read_len);
                int read_result = ::read(fd, &*req.buf.end() - read_len, read_len);
                req.buf.resize(read_result > 0 ? req.buf.size() - (read_len - read_result) : req.buf.size() - read_len);
                logger->trace("Performing read {} bytes, result={}", read_len, read_result);
                if (read_result <= 0)
                    if (errno != EAGAIN && errno != EWOULDBLOCK || read_result == 0)
                        throw std::system_error(errno, std::system_category());
                    else
                        break;
            }

            if (req.buf.size() == req.requested_len) // read OK
            {
                logger->trace("Req read OK, executing callback");
                req.exec_callback(shared_from_this(), &*req.buf.begin(), &*req.buf.end());
                r_buffer.pop();
            } else // wait for next time
            {
                break;
            }
        }
        if (r_buffer.empty())
            disable_event(EventCategory::POLLIN);
    }

    void Connection::handle_write()
    {
        logger->trace("Handling write, there are {} items in w_buffer", w_buffer.size());
        if (is_closed())
            throw std::runtime_error("Write when socket is closed");
        while (!w_buffer.empty()) // can write
        {
            detail::ConnWReq &req = w_buffer.front();
            logger->trace("Write the first request: {} / {}", req.offset, req.buf.size());
            int write_result;
            for(;req.offset < req.buf.size();)
            {
                int write_len = std::min(1024, (int)req.buf.size() - req.offset);
                logger->trace("Performing write {} bytes from off={}", write_len, req.offset);
                int write_result = ::write(fd, &*req.buf.begin() + req.offset, write_len);
                logger->trace("Write result={}", write_result);
                if (write_result < 0)
                    if (errno != EAGAIN && errno != EWOULDBLOCK)
                        throw std::system_error(errno, std::system_category());
                    else
                        break;
                req.offset += write_result;
            }
            if (req.offset == req.buf.size()) // write OK
            {
                logger->trace("Req write OK, executing callback");
                auto this_ptr = shared_from_this();
                logger->trace("Current ptr use_count={}", this_ptr.use_count());
                req.exec_callback(shared_from_this());
                logger->trace("Current ptr after use use_count={}", this_ptr.use_count());
                w_buffer.pop();
            } else
            {
                break; // wait for next time
            }
        }
        if (w_buffer.empty())
            disable_event(EventCategory::POLLOUT);
    }

    void Connection::event_handler(const Event &e)
    {
        auto self = shared_from_this();
        logger->debug("Handling event {}", e);
        std::lock_guard<std::recursive_mutex> lk(mutex);
        if (!is_closed()) {
            try {
                if (e.event_type.is(EventCategory::POLLIN))
                    handle_read();
                if (e.event_type.is(EventCategory::POLLOUT))
                    handle_write();
                if (e.event_type.is_err())
                    close();
            } catch (std::exception &e) {
                logger->warn("Socket closed when processing event, closing connection:", e.what());
                close();
            }
        }
    }

}<|endoftext|>


<commit_before>/*
 * TI Voxel Lib component.
 *
 * Copyright (c) 2014 Texas Instruments Inc.
 */

#include "CameraSystem.h"

#include "SimpleOpt.h"
#include "Common.h"
#include "Logger.h"
#include "UVCStreamer.h"
#include <iomanip>
#include <fstream>

using namespace Voxel;

enum Options
{
  VENDOR_ID = 0,
  PRODUCT_ID = 1,
  SERIAL_NUMBER = 2,
  CREATE_PROFILE = 3,
  PARENT_PROFILE_ID = 4,
  PROFILE_ID = 5,
  SECTION = 6,
  PARAM_NAME = 7,
  PARAM_VALUE = 8,
  LIST_PROFILES = 9,
  REMOVE_PROFILE = 10,
  WRITE_TO_EEPROM = 11,
  SAVE_FILE_TO_HOST = 12,
  SET_DEFAULT_PROFILE = 13,
};

Vector<CSimpleOpt::SOption> argumentSpecifications =
{
  { VENDOR_ID,            "-v", SO_REQ_SEP, "Vendor ID of the USB device (hexadecimal)"}, // Only worker count is needed here
  { PRODUCT_ID,           "-p", SO_REQ_SEP, "Comma separated list of Product IDs of the USB devices (hexadecimal)"},
  { SERIAL_NUMBER,        "-s", SO_REQ_SEP, "Serial number of the USB device (string)"},
  { CREATE_PROFILE,       "-c", SO_REQ_SEP, "Should create a new profile? If given, then name is to specified"},
  { PARENT_PROFILE_ID,    "-d", SO_REQ_SEP, "Parent profile ID used while creating a new profile [default = -1]."},
  { PROFILE_ID,           "-i", SO_REQ_SEP, "ID of the camera profile"},
  { SECTION,              "-t", SO_REQ_SEP, "Name of the configuration section"},
  { PARAM_NAME,           "-n", SO_REQ_SEP, "Name of the parameter to read/write"},
  { PARAM_VALUE,          "-u", SO_REQ_SEP, "Value for the parameter. This will be written. If not given, then the parameter will be read."},
  { LIST_PROFILES,        "-l", SO_NONE,    "List all profiles for this camera"},
  { REMOVE_PROFILE,       "-r", SO_NONE,    "Remove profile selected with -i option"},
  { WRITE_TO_EEPROM,      "-w", SO_NONE,    "Write to EEPROM, the profile selected with -i option"},
  { SAVE_FILE_TO_HOST,    "-z", SO_NONE,    "Save selected profile (present in EEPROM) to host"},
  { SET_DEFAULT_PROFILE,  "-e", SO_NONE,    "Set the default profile to the value given with -i. If a value of 0   is given, the hardware will have no default profile."},
  SO_END_OF_OPTIONS
};

void help()
{
  std::cout << "CameraSystemConfigTest v1.0" << std::endl;

  CSimpleOpt::SOption *option = argumentSpecifications.data();

  while(option->nId >= 0)
  {
    std::cout << option->pszArg << " " << option->helpInfo << std::endl;
    option++;
  }
}

int main(int argc, char *argv[])
{
  CSimpleOpt s(argc, argv, argumentSpecifications);

  logger.setDefaultLogLevel(LOG_ERROR);

  uint16_t vid = 0;

  Vector<uint16_t> pids;
  String serialNumber;

  bool listProfiles = false;

  bool createProfile = false, removeProfile = false, writeToEEPROM = false, saveToHost = false;
  String profileName;
  int profileID = -1, parentProfileID = -1;

  bool readParam = true;
  String section, paramName, paramValue;
  bool changeDefault = false;

  char *endptr;
  Vector<String> splits;

  while (s.Next())
  {
    if (s.LastError() != SO_SUCCESS)
    {
      std::cout << s.GetLastErrorText(s.LastError()) << ": '" << s.OptionText() << "' (use -h to get command line help)" << std::endl;
      help();
      return -1;
    }

    //std::cout << s.OptionId() << ": " << s.OptionArg() << std::endl;

    Vector<String> splits;
    switch (s.OptionId())
    {
      case VENDOR_ID:
        vid = (uint16_t)strtol(s.OptionArg(), &endptr, 16);
        break;

      case PRODUCT_ID:
        split(s.OptionArg(), ',', splits);

        for(auto &s1: splits)
          pids.push_back((uint16_t)strtol(s1.c_str(), &endptr, 16));

        break;

      case SERIAL_NUMBER:
        serialNumber = s.OptionArg();
        break;

      case CREATE_PROFILE:
        createProfile = true;
        profileName = s.OptionArg();
        break;

      case PARENT_PROFILE_ID:
        parentProfileID = atoi(s.OptionArg());
        break;

      case PROFILE_ID:
        profileID = atoi(s.OptionArg());
        break;

      case SECTION:
        section = s.OptionArg();
        break;

      case PARAM_NAME:
        paramName = s.OptionArg();
        break;

      case PARAM_VALUE:
        readParam = false;
        paramValue = s.OptionArg();

        if(paramValue.size() > 0 &&
            ((paramValue[0] == '\'' && paramValue[paramValue.size() - 1] == '\'') ||
            (paramValue[0] == '"' && paramValue[paramValue.size() - 1] == '"')))
          paramValue = paramValue.substr(1, paramValue.size() - 2);

        break;

      case LIST_PROFILES:
        listProfiles = true;
        break;

      case REMOVE_PROFILE:
        removeProfile = true;
        break;

      case WRITE_TO_EEPROM:
        writeToEEPROM = true;
        break;

      case SAVE_FILE_TO_HOST:
        saveToHost = true;
        break;

      case SET_DEFAULT_PROFILE:
        changeDefault = true;
        break;

      default:
        help();
        break;
    };
  }

  if(vid == 0 || pids.size() == 0 || pids[0] == 0)
  {
    logger(LOG_ERROR) << "Required argument missing." << std::endl;
    help();
    return -1;
  }

  CameraSystem sys;

  // Get all valid detected devices
  const Vector<DevicePtr> &devices = sys.scan();

  DevicePtr toConnect;

  std::cout << "Detected devices: " << std::endl;
  for(auto &d: devices)
  {
    std::cout << d->id() << std::endl;

    if(d->interfaceID() == Device::USB)
    {
      USBDevice &usb = (USBDevice &)*d;

      if(usb.vendorID() == vid && (serialNumber.size() == 0 || usb.serialNumber() == serialNumber))
      {
        for(auto pid: pids)
          if(usb.productID() == pid)
            toConnect = d;
      }
    }
  }

  if(!toConnect)
  {
    logger(LOG_ERROR) << "No valid device found for the specified VID:PID:serialnumber" << std::endl;
    return -1;
  }

  DepthCameraPtr depthCamera = sys.connect(toConnect);

  if(!depthCamera)
  {
    logger(LOG_ERROR) << "Could not load depth camera for device " << toConnect->id() << std::endl;
    return -1;
  }

  if(!depthCamera->isInitialized())
  {
    logger(LOG_ERROR) << "Depth camera not initialized for device " << toConnect->id() << std::endl;
    return -1;
  }

  std::cout << "Successfully loaded depth camera for device " << toConnect->id() << std::endl;

  if(listProfiles)
  {
    const Map<int, String> &profiles = depthCamera->getCameraProfileNames();

    for(auto &p: profiles)
    {
      std::cout << p.first << ", " << p.second;

      ConfigurationFile *c = depthCamera->configFile.getCameraProfile(p.first);

      if(c && c->getLocation() == ConfigurationFile::IN_CAMERA)
        std::cout << " (HW)";

      std::cout << std::endl;
    }

    return 0;
  }

  if(changeDefault)
  {
    if (profileID == 0)
    {
      if(!depthCamera->configFile.removeDefaultCameraProfileIDInCamera())
      {
        logger(LOG_ERROR) << "Cannot reset the default profile in camera." << std::endl;
        return -1;
      }
      std::cout << "Successfully reset the default camera profile in hardware." << std::endl;
      return 0;
    }

    else
    {
      if(!depthCamera->configFile.setDefaultCameraProfile(profileID))
      {
        logger(LOG_ERROR) << "Failed to set default profile to: " << profileID << ". Check if the profile is available" << std::endl;
        return -1;
      }
      std::cout << "Successfully changed the default camera profile to: " << profileID << std::endl;
      return 0;
    }
  }

  int id;

  if(createProfile)
  {
    id = depthCamera->addCameraProfile(profileName, parentProfileID);
    if(id < 0)
    {
      logger(LOG_ERROR) << "Failed to create new camera profile with name '" << profileName << "' and parent = " << parentProfileID << std::endl;
      return -1;
    }

    std::cout << "Created profile with id = " << id << std::endl;
  }
  else
  {
    id = profileID;
  }

  ConfigurationFile *configFile = depthCamera->configFile.getCameraProfile(id);

  if(!configFile)
  {
    logger(LOG_ERROR) << "Could not find config file for id = " << id << std::endl;
    return -1;
  }

  bool needToWrite = false;
  if(section.size() == 0 || paramName.size() == 0 || (!readParam && paramValue.size() == 0))
  {
    logger(LOG_INFO) << "One of the requirement parameter to read/write parameter is missing." << std::endl;
  }
  else
  {
    if(readParam)
    {
      if(configFile->isPresent(section, paramName))
        std::cout << "Param value for section = " << section << ", name = " << paramName
          << ", value = " << configFile->get(section, paramName) << std::endl;
      else
        logger(LOG_ERROR) << "Param not found, section = " << section << ", name = " << paramName << std::endl;
    }
    else
    {
      if(!configFile->set(section, paramName, paramValue))
      {
        std::cout << "Failed to set parameter, section = " << section << ", name = " << paramName
        << ", value = " << paramValue << std::endl;
      }
      else
      {
        std::cout << "Successfully set parameter, section = " << section << ", name = " << paramName
        << ", value = " << paramValue << std::endl;
        needToWrite = true;
      }
    }
  }

  if(needToWrite)
  {
    if(configFile->getLocation() == ConfigurationFile::IN_CAMERA)
    {
      if(!depthCamera->configFile.writeToHardware())
      {
        logger(LOG_ERROR) << "Failed to save configuration for id = " << id << std::endl;
        return -1;
      }
    }
    else if(!configFile->write())
    {
      logger(LOG_ERROR) << "Failed to save configuration for id = " << id << std::endl;
      return -1;
    }
    return 0;
  }

  if(writeToEEPROM)
  {
    if(!depthCamera->saveCameraProfileToHardware(id))
    {
      logger(LOG_ERROR) << "Failed to save configuration for id = " << id << " to EEPROM." << std::endl;
      return -1;
    }

    std::cout << "Profile saved to hardware with id = " << id << std::endl;
    return 0;
  }

  if(saveToHost)
  {
    ConfigurationFile *config = depthCamera->configFile.getCameraProfile(id);

    if(!config)
    {
      logger(LOG_ERROR) << "Failed to get configuration for id = " << id << "." << std::endl;
      return -1;
    }

    if(!config->write())
    {
      logger(LOG_ERROR) << "Failed to save configuration with id = " << id << " on host." << std::endl;
      return -1;
    }

    std::cout << "Profile saved to host with id = " << id << " to file '" << config->getConfigFileName() << "'" << std::endl;
    return 0;
  }

  if(removeProfile)
  {
    char ch;
    std::cout << "Are you sure you want to remove profile with id '" << id << "' [y/n]? ";
    std::cin >> ch;

    if(ch == 'y' || ch == 'Y')
    {
      if(!depthCamera->configFile.removeCameraProfile(id))
      {
        std::cout << "Failed to remove camera profile '" << id << "'" << std::endl;
        return -1;
      }
      else
        std::cout << "Successfully removed camera profile '" << id << "'" << std::endl;
    }
    return 0;
  }

  return 0;
}<commit_msg>Added an option to remove parameter from a profile.<commit_after>/*
 * TI Voxel Lib component.
 *
 * Copyright (c) 2014 Texas Instruments Inc.
 */

#include "CameraSystem.h"

#include "SimpleOpt.h"
#include "Common.h"
#include "Logger.h"
#include "UVCStreamer.h"
#include <iomanip>
#include <fstream>

using namespace Voxel;

enum Options
{
  VENDOR_ID = 0,
  PRODUCT_ID = 1,
  SERIAL_NUMBER = 2,
  CREATE_PROFILE = 3,
  PARENT_PROFILE_ID = 4,
  PROFILE_ID = 5,
  SECTION = 6,
  PARAM_NAME = 7,
  PARAM_VALUE = 8,
  LIST_PROFILES = 9,
  REMOVE_PROFILE = 10,
  WRITE_TO_EEPROM = 11,
  SAVE_FILE_TO_HOST = 12,
  SET_DEFAULT_PROFILE = 13,
  PARAM_REMOVE = 14,
};

Vector<CSimpleOpt::SOption> argumentSpecifications =
{
  { VENDOR_ID,            "-v", SO_REQ_SEP, "Vendor ID of the USB device (hexadecimal)"}, // Only worker count is needed here
  { PRODUCT_ID,           "-p", SO_REQ_SEP, "Comma separated list of Product IDs of the USB devices (hexadecimal)"},
  { SERIAL_NUMBER,        "-s", SO_REQ_SEP, "Serial number of the USB device (string)"},
  { CREATE_PROFILE,       "-c", SO_REQ_SEP, "Should create a new profile? If given, then name is to specified"},
  { PARENT_PROFILE_ID,    "-d", SO_REQ_SEP, "Parent profile ID used while creating a new profile [default = -1]."},
  { PROFILE_ID,           "-i", SO_REQ_SEP, "ID of the camera profile"},
  { SECTION,              "-t", SO_REQ_SEP, "Name of the configuration section"},
  { PARAM_NAME,           "-n", SO_REQ_SEP, "Name of the parameter to read/write"},
  { PARAM_VALUE,          "-u", SO_REQ_SEP, "Value for the parameter. This will be written. If not given, then the parameter will be read."},
  { LIST_PROFILES,        "-l", SO_NONE,    "List all profiles for this camera"},
  { REMOVE_PROFILE,       "-r", SO_NONE,    "Remove profile selected with -i option"},
  { WRITE_TO_EEPROM,      "-w", SO_NONE,    "Write to EEPROM, the profile selected with -i option"},
  { SAVE_FILE_TO_HOST,    "-z", SO_NONE,    "Save selected profile (present in EEPROM) to host"},
  { SET_DEFAULT_PROFILE,  "-e", SO_NONE,    "Set the default profile to the value given with -i. If a value of 0   is given, the hardware will have no default profile."},
  { PARAM_REMOVE,         "-a", SO_NONE,    "Remove the parameter given by -n."},
  SO_END_OF_OPTIONS
};

void help()
{
  std::cout << "CameraSystemConfigTest v1.0" << std::endl;

  CSimpleOpt::SOption *option = argumentSpecifications.data();

  while(option->nId >= 0)
  {
    std::cout << option->pszArg << " " << option->helpInfo << std::endl;
    option++;
  }
}

int main(int argc, char *argv[])
{
  CSimpleOpt s(argc, argv, argumentSpecifications);

  logger.setDefaultLogLevel(LOG_ERROR);

  uint16_t vid = 0;

  Vector<uint16_t> pids;
  String serialNumber;

  bool listProfiles = false;

  bool createProfile = false, removeProfile = false, writeToEEPROM = false, saveToHost = false;
  String profileName;
  int profileID = -1, parentProfileID = -1;

  bool readParam = true;
  String section, paramName, paramValue;
  bool changeDefault = false;
  bool removeParameter = false;

  char *endptr;
  Vector<String> splits;

  while (s.Next())
  {
    if (s.LastError() != SO_SUCCESS)
    {
      std::cout << s.GetLastErrorText(s.LastError()) << ": '" << s.OptionText() << "' (use -h to get command line help)" << std::endl;
      help();
      return -1;
    }

    //std::cout << s.OptionId() << ": " << s.OptionArg() << std::endl;

    Vector<String> splits;
    switch (s.OptionId())
    {
      case VENDOR_ID:
        vid = (uint16_t)strtol(s.OptionArg(), &endptr, 16);
        break;

      case PRODUCT_ID:
        split(s.OptionArg(), ',', splits);

        for(auto &s1: splits)
          pids.push_back((uint16_t)strtol(s1.c_str(), &endptr, 16));

        break;

      case SERIAL_NUMBER:
        serialNumber = s.OptionArg();
        break;

      case CREATE_PROFILE:
        createProfile = true;
        profileName = s.OptionArg();
        break;

      case PARENT_PROFILE_ID:
        parentProfileID = atoi(s.OptionArg());
        break;

      case PROFILE_ID:
        profileID = atoi(s.OptionArg());
        break;

      case SECTION:
        section = s.OptionArg();
        break;

      case PARAM_NAME:
        paramName = s.OptionArg();
        break;

      case PARAM_VALUE:
        readParam = false;
        paramValue = s.OptionArg();

        if(paramValue.size() > 0 &&
            ((paramValue[0] == '\'' && paramValue[paramValue.size() - 1] == '\'') ||
            (paramValue[0] == '"' && paramValue[paramValue.size() - 1] == '"')))
          paramValue = paramValue.substr(1, paramValue.size() - 2);

        break;

      case LIST_PROFILES:
        listProfiles = true;
        break;

      case REMOVE_PROFILE:
        removeProfile = true;
        break;

      case WRITE_TO_EEPROM:
        writeToEEPROM = true;
        break;

      case SAVE_FILE_TO_HOST:
        saveToHost = true;
        break;

      case SET_DEFAULT_PROFILE:
        changeDefault = true;
        break;

      case PARAM_REMOVE:
        removeParameter = true;
        break;

      default:
        help();
        break;
    };
  }

  if(vid == 0 || pids.size() == 0 || pids[0] == 0)
  {
    logger(LOG_ERROR) << "Required argument missing." << std::endl;
    help();
    return -1;
  }

  CameraSystem sys;

  // Get all valid detected devices
  const Vector<DevicePtr> &devices = sys.scan();

  DevicePtr toConnect;

  std::cout << "Detected devices: " << std::endl;
  for(auto &d: devices)
  {
    std::cout << d->id() << std::endl;

    if(d->interfaceID() == Device::USB)
    {
      USBDevice &usb = (USBDevice &)*d;

      if(usb.vendorID() == vid && (serialNumber.size() == 0 || usb.serialNumber() == serialNumber))
      {
        for(auto pid: pids)
          if(usb.productID() == pid)
            toConnect = d;
      }
    }
  }

  if(!toConnect)
  {
    logger(LOG_ERROR) << "No valid device found for the specified VID:PID:serialnumber" << std::endl;
    return -1;
  }

  DepthCameraPtr depthCamera = sys.connect(toConnect);

  if(!depthCamera)
  {
    logger(LOG_ERROR) << "Could not load depth camera for device " << toConnect->id() << std::endl;
    return -1;
  }

  if(!depthCamera->isInitialized())
  {
    logger(LOG_ERROR) << "Depth camera not initialized for device " << toConnect->id() << std::endl;
    return -1;
  }

  std::cout << "Successfully loaded depth camera for device " << toConnect->id() << std::endl;

  if(listProfiles)
  {
    const Map<int, String> &profiles = depthCamera->getCameraProfileNames();

    for(auto &p: profiles)
    {
      std::cout << p.first << ", " << p.second;

      ConfigurationFile *c = depthCamera->configFile.getCameraProfile(p.first);

      if(c && c->getLocation() == ConfigurationFile::IN_CAMERA)
        std::cout << " (HW)";

      std::cout << std::endl;
    }

    return 0;
  }

  if(changeDefault)
  {
    if (profileID == 0)
    {
      if(!depthCamera->configFile.removeDefaultCameraProfileIDInCamera())
      {
        logger(LOG_ERROR) << "Cannot reset the default profile in camera." << std::endl;
        return -1;
      }
      std::cout << "Successfully reset the default camera profile in hardware." << std::endl;
      return 0;
    }

    else
    {
      if(!depthCamera->configFile.setDefaultCameraProfile(profileID))
      {
        logger(LOG_ERROR) << "Failed to set default profile to: " << profileID << ". Check if the profile is available" << std::endl;
        return -1;
      }
      std::cout << "Successfully changed the default camera profile to: " << profileID << std::endl;
      return 0;
    }
  }

  int id;

  if(createProfile)
  {
    id = depthCamera->addCameraProfile(profileName, parentProfileID);
    if(id < 0)
    {
      logger(LOG_ERROR) << "Failed to create new camera profile with name '" << profileName << "' and parent = " << parentProfileID << std::endl;
      return -1;
    }

    std::cout << "Created profile with id = " << id << std::endl;
  }
  else
  {
    id = profileID;
  }

  ConfigurationFile *configFile = depthCamera->configFile.getCameraProfile(id);

  if(!configFile)
  {
    logger(LOG_ERROR) << "Could not find config file for id = " << id << std::endl;
    return -1;
  }

  bool needToWrite = false;
  if(section.size() == 0 || paramName.size() == 0 || (!readParam && paramValue.size() == 0))
  {
    logger(LOG_INFO) << "One of the requirement parameter to read/write parameter is missing." << std::endl;
  }
  else
  {
    if(readParam && removeParameter == false)
    {
      if(configFile->isPresent(section, paramName))
        std::cout << "Param value for section = " << section << ", name = " << paramName
          << ", value = " << configFile->get(section, paramName) << std::endl;
      else
        logger(LOG_ERROR) << "Param not found, section = " << section << ", name = " << paramName << std::endl;
    }
    else if (readParam && removeParameter == true)
    {
      if(configFile->isPresent(section,paramName))
      {
        auto val = configFile->get(section, paramName);
        configFile->remove(section, paramName);
        needToWrite = true;
        std::cout << "Successfully removed the parameter: " << paramName << " for id: " << id << std::endl;
        std::cout << "Previous Value of the parameter = " << val << std::endl;
      }
      else
      {
        logger(LOG_ERROR) << "Param not found, section = " << section << ", name = " << paramName << std::endl;
      }
    }
    else
    {
      if(!configFile->set(section, paramName, paramValue))
      {
        std::cout << "Failed to set parameter, section = " << section << ", name = " << paramName
        << ", value = " << paramValue << std::endl;
      }
      else
      {
        std::cout << "Successfully set parameter, section = " << section << ", name = " << paramName
        << ", value = " << paramValue << std::endl;
        needToWrite = true;
      }
    }
  }

  if(needToWrite)
  {
    if(configFile->getLocation() == ConfigurationFile::IN_CAMERA)
    {
      if(!depthCamera->configFile.writeToHardware())
      {
        logger(LOG_ERROR) << "Failed to save configuration for id = " << id << std::endl;
        return -1;
      }
    }
    else if(!configFile->write())
    {
      logger(LOG_ERROR) << "Failed to save configuration for id = " << id << std::endl;
      return -1;
    }
    return 0;
  }

  if(writeToEEPROM)
  {
    if(!depthCamera->saveCameraProfileToHardware(id))
    {
      logger(LOG_ERROR) << "Failed to save configuration for id = " << id << " to EEPROM." << std::endl;
      return -1;
    }

    std::cout << "Profile saved to hardware with id = " << id << std::endl;
    return 0;
  }

  if(saveToHost)
  {
    ConfigurationFile *config = depthCamera->configFile.getCameraProfile(id);

    if(!config)
    {
      logger(LOG_ERROR) << "Failed to get configuration for id = " << id << "." << std::endl;
      return -1;
    }

    if(!config->write())
    {
      logger(LOG_ERROR) << "Failed to save configuration with id = " << id << " on host." << std::endl;
      return -1;
    }

    std::cout << "Profile saved to host with id = " << id << " to file '" << config->getConfigFileName() << "'" << std::endl;
    return 0;
  }

  if(removeProfile)
  {
    char ch;
    std::cout << "Are you sure you want to remove profile with id '" << id << "' [y/n]? ";
    std::cin >> ch;

    if(ch == 'y' || ch == 'Y')
    {
      if(!depthCamera->configFile.removeCameraProfile(id))
      {
        std::cout << "Failed to remove camera profile '" << id << "'" << std::endl;
        return -1;
      }
      else
        std::cout << "Successfully removed camera profile '" << id << "'" << std::endl;
    }
    return 0;
  }

  return 0;
}<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright (C) 2007-2009 David Robillard <http://drobilla.net>
 *
 * Ingen 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.
 *
 * Ingen 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 details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "raul/log.hpp"

#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/event/event.h"
#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h"

#include "shared/LV2Atom.hpp"
#include "shared/LV2URIMap.hpp"

#include "NodeModel.hpp"
#include "PluginUI.hpp"
#include "PortModel.hpp"

using namespace std;
using namespace Raul;

namespace Ingen {
namespace Client {

static void
lv2_ui_write(LV2UI_Controller controller,
             uint32_t         port_index,
             uint32_t         buffer_size,
             uint32_t         format,
             const void*      buffer)
{
	PluginUI* const ui = (PluginUI*)controller;

	const NodeModel::Ports& ports = ui->node()->ports();
	if (port_index >= ports.size()) {
		error << "UI for " << ui->node()->plugin()->uri()
		      << " tried to write to non-existent port " << port_index << endl;
		return;
	}

	SharedPtr<PortModel> port = ports[port_index];

	const Shared::LV2URIMap& uris = *ui->world()->uris().get();

	// float (special case, always 0)
	if (format == 0) {
		assert(buffer_size == 4);
		if (*(float*)buffer == port->value().get_float())
			return; // do nothing (handle stupid plugin UIs that feed back)

		ui->world()->engine()->set_property(port->path(),
		                                    uris.ingen_value,
		                                    Atom(*(float*)buffer));

	} else if (format == uris.ui_Events.id) {
		LV2_Event_Buffer*  buf = (LV2_Event_Buffer*)buffer;
		LV2_Event_Iterator iter;
		uint8_t*           data;
		lv2_event_begin(&iter, buf);
		while (lv2_event_is_valid(&iter)) {
			LV2_Event* const ev = lv2_event_get(&iter, &data);
			if (ev->type == uris.midi_MidiEvent.id) {
				// FIXME: bundle multiple events by writing an entire buffer here
				ui->world()->engine()->set_property(
					port->path(),
					uris.ingen_value,
					Atom("http://lv2plug.in/ns/ext/midi#MidiEvent", ev->size, data));
			} else {
				warn << "Unable to serialise UI event type " << ev->type
				     << ", event lost" << endl;
			}

			lv2_event_increment(&iter);
		}

	} else if (format == uris.atom_AtomTransfer.id) {
		LV2_Atom* buf = (LV2_Atom*)buffer;
		Raul::Atom val;
		Shared::LV2Atom::to_atom(uris, buf, val);
		ui->world()->engine()->set_property(port->path(), uris.ingen_value, val);

	} else {
		warn << "Unknown value format " << format
		     << " from LV2 UI " << ui->node()->plugin()->uri() << endl;
	}
}

PluginUI::PluginUI(Ingen::Shared::World* world,
                   SharedPtr<NodeModel>  node)
	: _world(world)
	, _node(node)
	, _instance(NULL)
{
}

PluginUI::~PluginUI()
{
	slv2_ui_instance_free(_instance);
}

SharedPtr<PluginUI>
PluginUI::create(Ingen::Shared::World* world,
                 SharedPtr<NodeModel>  node,
                 SLV2Plugin            plugin)
{
	SharedPtr<PluginUI> ret(new PluginUI(world, node));
	ret->_features = world->lv2_features()->lv2_features(world, node.get());

	SLV2Value gtk_ui = slv2_value_new_uri(
		world->slv2_world(), "http://lv2plug.in/ns/extensions/ui#GtkUI");

	SLV2UI ui = slv2_plugin_get_default_ui(plugin, gtk_ui);

	SLV2UIInstance instance = slv2_ui_instance_new(
		plugin,
		ui,
		gtk_ui,
		lv2_ui_write,
		ret.get(),
		ret->_features->array());

	if (instance) {
		ret->_instance = instance;
	} else {
		error << "Failed to instantiate LV2 UI" << endl;
		ret.reset();
	}

	return ret;
}

LV2UI_Widget
PluginUI::get_widget()
{
	return (LV2UI_Widget*)slv2_ui_instance_get_widget(_instance);
}

void
PluginUI::port_event(uint32_t    port_index,
                     uint32_t    buffer_size,
                     uint32_t    format,
                     const void* buffer)
{
	slv2_ui_instance_port_event(
		_instance, port_index, buffer_size, format, buffer);
}

} // namespace Client
} // namespace Ingen
<commit_msg>Update for new SLV2 UI API.<commit_after>/* This file is part of Ingen.
 * Copyright (C) 2007-2009 David Robillard <http://drobilla.net>
 *
 * Ingen 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.
 *
 * Ingen 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 details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "raul/log.hpp"

#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/event/event.h"
#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h"

#include "shared/LV2Atom.hpp"
#include "shared/LV2URIMap.hpp"

#include "NodeModel.hpp"
#include "PluginUI.hpp"
#include "PortModel.hpp"

using namespace std;
using namespace Raul;

namespace Ingen {
namespace Client {

static void
lv2_ui_write(LV2UI_Controller controller,
             uint32_t         port_index,
             uint32_t         buffer_size,
             uint32_t         format,
             const void*      buffer)
{
	PluginUI* const ui = (PluginUI*)controller;

	const NodeModel::Ports& ports = ui->node()->ports();
	if (port_index >= ports.size()) {
		error << "UI for " << ui->node()->plugin()->uri()
		      << " tried to write to non-existent port " << port_index << endl;
		return;
	}

	SharedPtr<PortModel> port = ports[port_index];

	const Shared::LV2URIMap& uris = *ui->world()->uris().get();

	// float (special case, always 0)
	if (format == 0) {
		assert(buffer_size == 4);
		if (*(float*)buffer == port->value().get_float())
			return; // do nothing (handle stupid plugin UIs that feed back)

		ui->world()->engine()->set_property(port->path(),
		                                    uris.ingen_value,
		                                    Atom(*(float*)buffer));

	} else if (format == uris.ui_Events.id) {
		LV2_Event_Buffer*  buf = (LV2_Event_Buffer*)buffer;
		LV2_Event_Iterator iter;
		uint8_t*           data;
		lv2_event_begin(&iter, buf);
		while (lv2_event_is_valid(&iter)) {
			LV2_Event* const ev = lv2_event_get(&iter, &data);
			if (ev->type == uris.midi_MidiEvent.id) {
				// FIXME: bundle multiple events by writing an entire buffer here
				ui->world()->engine()->set_property(
					port->path(),
					uris.ingen_value,
					Atom("http://lv2plug.in/ns/ext/midi#MidiEvent", ev->size, data));
			} else {
				warn << "Unable to serialise UI event type " << ev->type
				     << ", event lost" << endl;
			}

			lv2_event_increment(&iter);
		}

	} else if (format == uris.atom_AtomTransfer.id) {
		LV2_Atom* buf = (LV2_Atom*)buffer;
		Raul::Atom val;
		Shared::LV2Atom::to_atom(uris, buf, val);
		ui->world()->engine()->set_property(port->path(), uris.ingen_value, val);

	} else {
		warn << "Unknown value format " << format
		     << " from LV2 UI " << ui->node()->plugin()->uri() << endl;
	}
}

PluginUI::PluginUI(Ingen::Shared::World* world,
                   SharedPtr<NodeModel>  node)
	: _world(world)
	, _node(node)
	, _instance(NULL)
{
}

PluginUI::~PluginUI()
{
	slv2_ui_instance_free(_instance);
}

SharedPtr<PluginUI>
PluginUI::create(Ingen::Shared::World* world,
                 SharedPtr<NodeModel>  node,
                 SLV2Plugin            plugin)
{
	SharedPtr<PluginUI> ret(new PluginUI(world, node));
	ret->_features = world->lv2_features()->lv2_features(world, node.get());

	SLV2Value gtk_ui = slv2_value_new_uri(
		world->slv2_world(), "http://lv2plug.in/ns/extensions/ui#GtkUI");

	SLV2UI ui = slv2_plugin_get_default_ui(plugin, gtk_ui);

	SLV2UIHost ui_host = slv2_ui_host_new(
		ret.get(), lv2_ui_write, NULL, NULL, NULL);

	SLV2UIInstance instance = slv2_ui_instance_new(
		plugin,
		ui,
		gtk_ui,
		ui_host,
		ret->_features->array());

	slv2_ui_host_free(ui_host);

	if (instance) {
		ret->_instance = instance;
	} else {
		error << "Failed to instantiate LV2 UI" << endl;
		ret.reset();
	}

	return ret;
}

LV2UI_Widget
PluginUI::get_widget()
{
	return (LV2UI_Widget*)slv2_ui_instance_get_widget(_instance);
}

void
PluginUI::port_event(uint32_t    port_index,
                     uint32_t    buffer_size,
                     uint32_t    format,
                     const void* buffer)
{
	slv2_ui_instance_port_event(
		_instance, port_index, buffer_size, format, buffer);
}

} // namespace Client
} // namespace Ingen
<|endoftext|>