<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2009, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreMaya/Parameter.h"
#include "IECoreMaya/NumericTraits.h"
#include "IECoreMaya/ToMayaObjectConverter.h"
#include "IECoreMaya/FromMayaObjectConverter.h"
#include "IECoreMaya/CompoundNumericParameterHandler.h"

#include "IECore/SimpleTypedData.h"
#include "IECore/NumericParameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/TypedParameter.h"

#include "maya/MFnNumericAttribute.h"
#include "maya/MFnCompoundAttribute.h"

using namespace IECoreMaya;
using namespace Imath;
using namespace boost;

static ParameterHandler::Description< CompoundNumericParameterHandler<V2i> > v2iRegistrar( IECore::V2iParameter::staticTypeId() );
static ParameterHandler::Description< CompoundNumericParameterHandler<V3i> > v3iRegistrar( IECore::V3iParameter::staticTypeId() );

static ParameterHandler::Description< CompoundNumericParameterHandler<V2f> > v2fRegistrar( IECore::V2fParameter::staticTypeId() );
static ParameterHandler::Description< CompoundNumericParameterHandler<V3f> > v3fRegistrar( IECore::V3fParameter::staticTypeId() );

static ParameterHandler::Description< CompoundNumericParameterHandler<V2d> > v2dRegistrar( IECore::V2dParameter::staticTypeId() );
static ParameterHandler::Description< CompoundNumericParameterHandler<V3d> > v3dRegistrar( IECore::V3dParameter::staticTypeId() );

static ParameterHandler::Description< CompoundNumericParameterHandler<Color3f> > color3fRegistrar( IECore::Color3fParameter::staticTypeId() );

template<typename T>
MStatus CompoundNumericParameterHandler<T>::update( IECore::ConstParameterPtr parameter, MObject &attribute ) const
{
	typename IECore::TypedParameter<T>::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	MFnNumericAttribute fnNAttr( attribute );
	if( !fnNAttr.hasObj( attribute ) )
	{
		return MS::kFailure;
	}

	if( fnNAttr.unitType()!=NumericTraits<T>::dataType() )
	{
		return MS::kFailure;
	}

	/// Set the default value one child attribute at a time. It would appear that using the variants of setDefault
	/// whicn take 2 or 3 arguments can exercise a Maya bug.
	T defValue = p->typedDefaultValue();
	for( unsigned i=0; i<T::dimensions(); i++ )
	{
		MStatus s;
		MObject childAttr = fnNAttr.child( i, &s );
		if ( !s )
		{
			return s;
		}
		MFnNumericAttribute fnChildNAttr( childAttr, &s );
		if ( !s )
		{
			return s;
		}
		s = fnChildNAttr.setDefault( defValue[i] );
		if ( !s )
		{
			return s;
		}
	}

#ifndef NDEBUG
	/// Verify that the defaults have been set correctly. Only do this in asserted builds.
	switch( T::dimensions() )
	{
		case 2 :
			{
				typename T::BaseType c0, c1 ;
				MStatus s = fnNAttr.getDefault( c0, c1 );
				assert( s );
				assert( c0 == defValue[0] );
				assert( c1 == defValue[1] );
			}
			break;
		case 3 :
			{
				typename T::BaseType c0, c1, c2;
				MStatus s = fnNAttr.getDefault( c0, c1, c2 );
				assert( s );
				assert( c0 == defValue[0] );
				assert( c1 == defValue[1] );
				assert( c2 == defValue[2] );
			}
			break;
		default :
			assert( false );
	}
#endif

	fnNAttr.setUsedAsColor( NumericTraits<T>::isColor() );

	bool keyable = true;
	bool channelBox = true;

	const IECore::ConstCompoundObjectPtr userData = parameter->userData();
	assert( userData );

	const IECore::ConstCompoundObjectPtr maya = userData->member<const IECore::CompoundObject>("maya");
	if (maya)
	{
		const IECore::ConstBoolDataPtr keyableData = maya->member<const IECore::BoolData>("keyable");
		if (keyableData)
		{
			keyable = keyableData->readable();
		}

		const IECore::ConstBoolDataPtr channelBoxData = maya->member<const IECore::BoolData>("channelBox");
		if (channelBoxData)
		{
			channelBox = channelBoxData->readable();
		}
	}

	fnNAttr.setKeyable( keyable );

	// Calling setChannelBox(true) disables keying
	if (!keyable)
	{
		fnNAttr.setChannelBox( channelBox );
	}

	return MS::kSuccess;
}

template<typename T>
MObject CompoundNumericParameterHandler<T>::create( IECore::ConstParameterPtr parameter, const MString &attributeName ) const
{
	typename IECore::TypedParameter<T>::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MObject::kNullObj;
	}

	MFnNumericAttribute fnNAttr;
	MObject result;
	switch( T::dimensions() )
	{
		case 2 :
			{
				assert( !NumericTraits<T>::isColor() );
				MObject e0 = fnNAttr.create( attributeName + "X", attributeName + "X", NumericTraits<T>::baseDataType() );
				MObject e1 = fnNAttr.create( attributeName + "Y", attributeName + "Y", NumericTraits<T>::baseDataType() );
				result = fnNAttr.create( attributeName, attributeName, e0, e1 );
			}
			break;
		case 3 :
			if( NumericTraits<T>::isColor() )
			{
				result = fnNAttr.createColor( attributeName, attributeName );
			}
			else
			{
				MObject e0 = fnNAttr.create( attributeName + "X", attributeName + "X", NumericTraits<T>::baseDataType() );
				MObject e1 = fnNAttr.create( attributeName + "Y", attributeName + "Y", NumericTraits<T>::baseDataType() );
				MObject e2 = fnNAttr.create( attributeName + "Z", attributeName + "Z", NumericTraits<T>::baseDataType() );
				result = fnNAttr.create( attributeName, attributeName, e0, e1, e2 );
			}
			break;
		default :
			assert( false );
			result = MObject::kNullObj;
	}

	update( parameter, result );
	return result;
}

template<typename T>
MStatus CompoundNumericParameterHandler<T>::setValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	typename IECore::TypedParameter<T>::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	if( plug.numChildren() != T::dimensions() )
	{
		return MS::kFailure;
	}

	T v = p->getTypedValue();
	for( unsigned i=0; i<plug.numChildren(); i++ )
	{
		MStatus s = plug.child( i ).setValue( v[i] );
		if( !s )
		{
			return s;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus CompoundNumericParameterHandler<T>::setValue( const MPlug &plug, IECore::ParameterPtr parameter ) const
{
	typename IECore::TypedParameter<T>::Ptr p = IECore::runTimeCast<IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	if( plug.numChildren() != T::dimensions() )
	{
		return MS::kFailure;
	}

	T v;
	for( unsigned i=0; i<plug.numChildren(); i++ )
	{
		MStatus s = plug.child( i ).getValue( v[i] );
		if( !s )
		{
			return s;
		}
	}

	p->setTypedValue( v );
	return MS::kSuccess;
}
<commit_msg>Fixed typo.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2010, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreMaya/Parameter.h"
#include "IECoreMaya/NumericTraits.h"
#include "IECoreMaya/ToMayaObjectConverter.h"
#include "IECoreMaya/FromMayaObjectConverter.h"
#include "IECoreMaya/CompoundNumericParameterHandler.h"

#include "IECore/SimpleTypedData.h"
#include "IECore/NumericParameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/TypedParameter.h"

#include "maya/MFnNumericAttribute.h"
#include "maya/MFnCompoundAttribute.h"

using namespace IECoreMaya;
using namespace Imath;
using namespace boost;

static ParameterHandler::Description< CompoundNumericParameterHandler<V2i> > v2iRegistrar( IECore::V2iParameter::staticTypeId() );
static ParameterHandler::Description< CompoundNumericParameterHandler<V3i> > v3iRegistrar( IECore::V3iParameter::staticTypeId() );

static ParameterHandler::Description< CompoundNumericParameterHandler<V2f> > v2fRegistrar( IECore::V2fParameter::staticTypeId() );
static ParameterHandler::Description< CompoundNumericParameterHandler<V3f> > v3fRegistrar( IECore::V3fParameter::staticTypeId() );

static ParameterHandler::Description< CompoundNumericParameterHandler<V2d> > v2dRegistrar( IECore::V2dParameter::staticTypeId() );
static ParameterHandler::Description< CompoundNumericParameterHandler<V3d> > v3dRegistrar( IECore::V3dParameter::staticTypeId() );

static ParameterHandler::Description< CompoundNumericParameterHandler<Color3f> > color3fRegistrar( IECore::Color3fParameter::staticTypeId() );

template<typename T>
MStatus CompoundNumericParameterHandler<T>::update( IECore::ConstParameterPtr parameter, MObject &attribute ) const
{
	typename IECore::TypedParameter<T>::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	MFnNumericAttribute fnNAttr( attribute );
	if( !fnNAttr.hasObj( attribute ) )
	{
		return MS::kFailure;
	}

	if( fnNAttr.unitType()!=NumericTraits<T>::dataType() )
	{
		return MS::kFailure;
	}

	/// Set the default value one child attribute at a time. It would appear that using the variants of setDefault
	/// which take 2 or 3 arguments can exercise a Maya bug.
	T defValue = p->typedDefaultValue();
	for( unsigned i=0; i<T::dimensions(); i++ )
	{
		MStatus s;
		MObject childAttr = fnNAttr.child( i, &s );
		if ( !s )
		{
			return s;
		}
		MFnNumericAttribute fnChildNAttr( childAttr, &s );
		if ( !s )
		{
			return s;
		}
		s = fnChildNAttr.setDefault( defValue[i] );
		if ( !s )
		{
			return s;
		}
	}

#ifndef NDEBUG
	/// Verify that the defaults have been set correctly. Only do this in asserted builds.
	switch( T::dimensions() )
	{
		case 2 :
			{
				typename T::BaseType c0, c1 ;
				MStatus s = fnNAttr.getDefault( c0, c1 );
				assert( s );
				assert( c0 == defValue[0] );
				assert( c1 == defValue[1] );
			}
			break;
		case 3 :
			{
				typename T::BaseType c0, c1, c2;
				MStatus s = fnNAttr.getDefault( c0, c1, c2 );
				assert( s );
				assert( c0 == defValue[0] );
				assert( c1 == defValue[1] );
				assert( c2 == defValue[2] );
			}
			break;
		default :
			assert( false );
	}
#endif

	fnNAttr.setUsedAsColor( NumericTraits<T>::isColor() );

	bool keyable = true;
	bool channelBox = true;

	const IECore::ConstCompoundObjectPtr userData = parameter->userData();
	assert( userData );

	const IECore::ConstCompoundObjectPtr maya = userData->member<const IECore::CompoundObject>("maya");
	if (maya)
	{
		const IECore::ConstBoolDataPtr keyableData = maya->member<const IECore::BoolData>("keyable");
		if (keyableData)
		{
			keyable = keyableData->readable();
		}

		const IECore::ConstBoolDataPtr channelBoxData = maya->member<const IECore::BoolData>("channelBox");
		if (channelBoxData)
		{
			channelBox = channelBoxData->readable();
		}
	}

	fnNAttr.setKeyable( keyable );

	// Calling setChannelBox(true) disables keying
	if (!keyable)
	{
		fnNAttr.setChannelBox( channelBox );
	}

	return MS::kSuccess;
}

template<typename T>
MObject CompoundNumericParameterHandler<T>::create( IECore::ConstParameterPtr parameter, const MString &attributeName ) const
{
	typename IECore::TypedParameter<T>::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MObject::kNullObj;
	}

	MFnNumericAttribute fnNAttr;
	MObject result;
	switch( T::dimensions() )
	{
		case 2 :
			{
				assert( !NumericTraits<T>::isColor() );
				MObject e0 = fnNAttr.create( attributeName + "X", attributeName + "X", NumericTraits<T>::baseDataType() );
				MObject e1 = fnNAttr.create( attributeName + "Y", attributeName + "Y", NumericTraits<T>::baseDataType() );
				result = fnNAttr.create( attributeName, attributeName, e0, e1 );
			}
			break;
		case 3 :
			if( NumericTraits<T>::isColor() )
			{
				result = fnNAttr.createColor( attributeName, attributeName );
			}
			else
			{
				MObject e0 = fnNAttr.create( attributeName + "X", attributeName + "X", NumericTraits<T>::baseDataType() );
				MObject e1 = fnNAttr.create( attributeName + "Y", attributeName + "Y", NumericTraits<T>::baseDataType() );
				MObject e2 = fnNAttr.create( attributeName + "Z", attributeName + "Z", NumericTraits<T>::baseDataType() );
				result = fnNAttr.create( attributeName, attributeName, e0, e1, e2 );
			}
			break;
		default :
			assert( false );
			result = MObject::kNullObj;
	}

	update( parameter, result );
	return result;
}

template<typename T>
MStatus CompoundNumericParameterHandler<T>::setValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	typename IECore::TypedParameter<T>::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	if( plug.numChildren() != T::dimensions() )
	{
		return MS::kFailure;
	}

	T v = p->getTypedValue();
	for( unsigned i=0; i<plug.numChildren(); i++ )
	{
		MStatus s = plug.child( i ).setValue( v[i] );
		if( !s )
		{
			return s;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus CompoundNumericParameterHandler<T>::setValue( const MPlug &plug, IECore::ParameterPtr parameter ) const
{
	typename IECore::TypedParameter<T>::Ptr p = IECore::runTimeCast<IECore::TypedParameter<T> >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	if( plug.numChildren() != T::dimensions() )
	{
		return MS::kFailure;
	}

	T v;
	for( unsigned i=0; i<plug.numChildren(); i++ )
	{
		MStatus s = plug.child( i ).getValue( v[i] );
		if( !s )
		{
			return s;
		}
	}

	p->setTypedValue( v );
	return MS::kSuccess;
}
<|endoftext|>


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

#include <QHostAddress>
#include <QMap>
#include <QObject>
#include <QTest>

#include <qmdnsengine/dns.h>
#include <qmdnsengine/record.h>

#define PARSE_RECORD(r) \
    quint16 offset = 0; \
    QMdnsEngine::Record record; \
    bool result = QMdnsEngine::parseRecord( \
        QByteArray(r, sizeof(r)), \
        offset, \
        record \
    )

#define WRITE_RECORD() \
    QByteArray packet; \
    quint16 offset; \
    NameMap nameMap; \
    QMdnsEngine::writeRecord(packet, offset, record, nameMap)

typedef QMap<QByteArray, quint16> NameMap;

const char NameSimple[] = {
    '\x04', '_', 't', 'c', 'p',
    '\x05', 'l', 'o', 'c', 'a', 'l',
    '\0'
};

const char NamePointer[] = {
    '\x04', '_', 't', 'c', 'p',
    '\x05', 'l', 'o', 'c', 'a', 'l',
    '\0',
    '\x04', 't', 'e', 's', 't',
    '\xc0', '\0'
};

const char NameCorrupt[] = {
    '\x03', '1', '2'
};

const char RecordA[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x01',
    '\x80', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x04',
    '\x7f', '\x00', '\x00', '\x01'
};

const char RecordAAAA[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x1c',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x10',
    '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
    '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x01'
};

const char RecordPTR[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x0c',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x07',
    '\x05', 't', 'e', 's', 't', '2', '\0',
};

const char RecordSRV[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x21',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x0d',
    '\x00', '\x01', '\x00', '\x02', '\x00', '\x03',
    '\x05', 't', 'e', 's', 't', '2', '\0',
};

const char RecordTXT[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x10',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x06',
    '\x03', 'a', '=', 'a',
    '\x01', 'b'
};

const QByteArray Name("test.");
const quint32 Ttl = 3600;
const QHostAddress Ipv4Address("127.0.0.1");
const QHostAddress Ipv6Address("::1");
const QByteArray Target("test2.");
const quint16 Priority = 1;
const quint16 Weight = 2;
const quint16 Port = 3;
const QMap<QByteArray, QByteArray> Attributes{
    {"a", "a"},
    {"b", QByteArray()}
};

class TestDns : public QObject
{
    Q_OBJECT

private Q_SLOTS:

    void testParseName_data();
    void testParseName();

    void testWriteName_data();
    void testWriteName();

    void testParseRecordA();
    void testParseRecordAAAA();
    void testParseRecordPTR();
    void testParseRecordSRV();
    void testParseRecordTXT();

    void testWriteRecordA();
    void testWriteRecordAAAA();
    void testWriteRecordPTR();
    void testWriteRecordSRV();
    void testWriteRecordTXT();
};

void TestDns::testParseName_data()
{
    QTest::addColumn<QByteArray>("packet");
    QTest::addColumn<quint16>("initialOffset");
    QTest::addColumn<quint16>("correctOffset");
    QTest::addColumn<QByteArray>("correctName");
    QTest::addColumn<bool>("correctResult");

    QTest::newRow("simple")
            << QByteArray(NameSimple, sizeof(NameSimple))
            << static_cast<quint16>(0)
            << static_cast<quint16>(12)
            << QByteArray("_tcp.local.")
            << true;

    QTest::newRow("pointer")
            << QByteArray(NamePointer, sizeof(NamePointer))
            << static_cast<quint16>(12)
            << static_cast<quint16>(19)
            << QByteArray("test._tcp.local.")
            << true;

    QTest::newRow("corrupt data")
            << QByteArray(NameCorrupt, sizeof(NameCorrupt))
            << static_cast<quint16>(0)
            << static_cast<quint16>(0)
            << QByteArray()
            << false;
}

void TestDns::testParseName()
{
    QFETCH(QByteArray, packet);
    QFETCH(quint16, initialOffset);
    QFETCH(quint16, correctOffset);
    QFETCH(QByteArray, correctName);
    QFETCH(bool, correctResult);

    quint16 offset = initialOffset;
    QByteArray name;
    bool result = QMdnsEngine::parseName(packet, offset, name);

    QCOMPARE(result, correctResult);
    if (result) {
        QCOMPARE(offset, correctOffset);
        QCOMPARE(name, correctName);
    }
}

void TestDns::testWriteName_data()
{
    QTest::addColumn<QByteArray>("initialPacket");
    QTest::addColumn<quint16>("initialOffset");
    QTest::addColumn<quint16>("correctOffset");
    QTest::addColumn<QByteArray>("name");
    QTest::addColumn<NameMap>("nameMap");
    QTest::addColumn<QByteArray>("correctPacket");

    QTest::newRow("simple")
            << QByteArray()
            << static_cast<quint16>(0)
            << static_cast<quint16>(12)
            << QByteArray("_tcp.local.")
            << NameMap()
            << QByteArray(NameSimple, sizeof(NameSimple));

    QTest::newRow("pointer")
            << QByteArray(NameSimple, sizeof(NameSimple))
            << static_cast<quint16>(sizeof(NameSimple))
            << static_cast<quint16>(19)
            << QByteArray("test._tcp.local.")
            << NameMap{{"_tcp.local", 0}}
            << QByteArray(NamePointer, sizeof(NamePointer));
}

void TestDns::testWriteName()
{
    QFETCH(QByteArray, initialPacket);
    QFETCH(quint16, initialOffset);
    QFETCH(QByteArray, name);
    QFETCH(NameMap, nameMap);
    QFETCH(QByteArray, correctPacket);

    QByteArray packet = initialPacket;
    quint16 offset = initialOffset;
    QMdnsEngine::writeName(packet, offset, name, nameMap);

    QCOMPARE(packet, correctPacket);
    QCOMPARE(offset, correctOffset);
}

void TestDns::testParseRecordA()
{
    PARSE_RECORD(RecordA);

    QCOMPARE(result, true);
    QCOMPARE(record.name(), Name);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::A));
    QCOMPARE(record.flushCache(), true);
    QCOMPARE(record.ttl(), Ttl);
    QCOMPARE(record.address(), Ipv4Address);
}

void TestDns::testParseRecordAAAA()
{
    PARSE_RECORD(RecordAAAA);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::AAAA));
    QCOMPARE(record.address(), Ipv6Address);
}

void TestDns::testParseRecordPTR()
{
    PARSE_RECORD(RecordPTR);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::PTR));
    QCOMPARE(record.target(), QByteArray("test2."));
}

void TestDns::testParseRecordSRV()
{
    PARSE_RECORD(RecordSRV);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::SRV));
    QCOMPARE(record.priority(), Priority);
    QCOMPARE(record.weight(), Weight);
    QCOMPARE(record.port(), Port);
    QCOMPARE(record.target(), Target);
}

void TestDns::testParseRecordTXT()
{
    PARSE_RECORD(RecordTXT);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::TXT));
    QCOMPARE(record.attributes(), Attributes);
}

void TestDns::testWriteRecordA()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::A);
    record.setFlushCache(true);
    record.setTtl(Ttl);
    record.setAddress(Ipv4Address);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordA, sizeof(RecordA)));
}

void TestDns::testWriteRecordAAAA()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::AAAA);
    record.setTtl(Ttl);
    record.setAddress(Ipv6Address);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordAAAA, sizeof(RecordAAAA)));
}

void TestDns::testWriteRecordPTR()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::PTR);
    record.setTtl(Ttl);
    record.setTarget(Target);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordPTR, sizeof(RecordPTR)));
}

void TestDns::testWriteRecordSRV()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::SRV);
    record.setTtl(Ttl);
    record.setPriority(Priority);
    record.setWeight(Weight);
    record.setPort(Port);
    record.setTarget(Target);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordSRV, sizeof(RecordSRV)));
}

void TestDns::testWriteRecordTXT()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::TXT);
    record.setTtl(Ttl);
    for (auto i = Attributes.constBegin(); i != Attributes.constEnd(); ++i) {
        record.addAttribute(i.key(), i.value());
    }

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordTXT, sizeof(RecordTXT)));
}

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

#include <QHostAddress>
#include <QMap>
#include <QObject>
#include <QTest>

#include <qmdnsengine/dns.h>
#include <qmdnsengine/record.h>

#define PARSE_RECORD(r) \
    quint16 offset = 0; \
    QMdnsEngine::Record record; \
    bool result = QMdnsEngine::parseRecord( \
        QByteArray(r, sizeof(r)), \
        offset, \
        record \
    )

#define WRITE_RECORD() \
    QByteArray packet; \
    quint16 offset; \
    NameMap nameMap; \
    QMdnsEngine::writeRecord(packet, offset, record, nameMap)

typedef QMap<QByteArray, quint16> NameMap;

const char NameSimple[] = {
    '\x04', '_', 't', 'c', 'p',
    '\x05', 'l', 'o', 'c', 'a', 'l',
    '\0'
};

const char NamePointer[] = {
    '\x04', '_', 't', 'c', 'p',
    '\x05', 'l', 'o', 'c', 'a', 'l',
    '\0',
    '\x04', 't', 'e', 's', 't',
    '\xc0', '\0'
};

const char NameCorrupt[] = {
    '\x03', '1', '2'
};

const char RecordA[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x01',
    '\x80', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x04',
    '\x7f', '\x00', '\x00', '\x01'
};

const char RecordAAAA[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x1c',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x10',
    '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
    '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x01'
};

const char RecordPTR[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x0c',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x07',
    '\x05', 't', 'e', 's', 't', '2', '\0',
};

const char RecordSRV[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x21',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x0d',
    '\x00', '\x01', '\x00', '\x02', '\x00', '\x03',
    '\x05', 't', 'e', 's', 't', '2', '\0',
};

const char RecordTXT[] = {
    '\x04', 't', 'e', 's', 't', '\0',
    '\x00', '\x10',
    '\x00', '\x01',
    '\x00', '\x00', '\x0e', '\x10',
    '\x00', '\x06',
    '\x03', 'a', '=', 'a',
    '\x01', 'b'
};

const QByteArray Name("test.");
const quint32 Ttl = 3600;
const QHostAddress Ipv4Address("127.0.0.1");
const QHostAddress Ipv6Address("::1");
const QByteArray Target("test2.");
const quint16 Priority = 1;
const quint16 Weight = 2;
const quint16 Port = 3;
const QMap<QByteArray, QByteArray> Attributes{
    {"a", "a"},
    {"b", QByteArray()}
};

class TestDns : public QObject
{
    Q_OBJECT

private Q_SLOTS:

    void testParseName_data();
    void testParseName();

    void testWriteName_data();
    void testWriteName();

    void testParseRecordA();
    void testParseRecordAAAA();
    void testParseRecordPTR();
    void testParseRecordSRV();
    void testParseRecordTXT();

    void testWriteRecordA();
    void testWriteRecordAAAA();
    void testWriteRecordPTR();
    void testWriteRecordSRV();
    void testWriteRecordTXT();
};

void TestDns::testParseName_data()
{
    QTest::addColumn<QByteArray>("packet");
    QTest::addColumn<quint16>("initialOffset");
    QTest::addColumn<quint16>("correctOffset");
    QTest::addColumn<QByteArray>("correctName");
    QTest::addColumn<bool>("correctResult");

    QTest::newRow("simple")
            << QByteArray(NameSimple, sizeof(NameSimple))
            << static_cast<quint16>(0)
            << static_cast<quint16>(12)
            << QByteArray("_tcp.local.")
            << true;

    QTest::newRow("pointer")
            << QByteArray(NamePointer, sizeof(NamePointer))
            << static_cast<quint16>(12)
            << static_cast<quint16>(19)
            << QByteArray("test._tcp.local.")
            << true;

    QTest::newRow("corrupt data")
            << QByteArray(NameCorrupt, sizeof(NameCorrupt))
            << static_cast<quint16>(0)
            << static_cast<quint16>(0)
            << QByteArray()
            << false;
}

void TestDns::testParseName()
{
    QFETCH(QByteArray, packet);
    QFETCH(quint16, initialOffset);
    QFETCH(quint16, correctOffset);
    QFETCH(QByteArray, correctName);
    QFETCH(bool, correctResult);

    quint16 offset = initialOffset;
    QByteArray name;
    bool result = QMdnsEngine::parseName(packet, offset, name);

    QCOMPARE(result, correctResult);
    if (result) {
        QCOMPARE(offset, correctOffset);
        QCOMPARE(name, correctName);
    }
}

void TestDns::testWriteName_data()
{
    QTest::addColumn<QByteArray>("initialPacket");
    QTest::addColumn<quint16>("initialOffset");
    QTest::addColumn<quint16>("correctOffset");
    QTest::addColumn<QByteArray>("name");
    QTest::addColumn<NameMap>("nameMap");
    QTest::addColumn<QByteArray>("correctPacket");

    QTest::newRow("simple")
            << QByteArray()
            << static_cast<quint16>(0)
            << static_cast<quint16>(12)
            << QByteArray("_tcp.local.")
            << NameMap()
            << QByteArray(NameSimple, sizeof(NameSimple));

    QTest::newRow("pointer")
            << QByteArray(NameSimple, sizeof(NameSimple))
            << static_cast<quint16>(sizeof(NameSimple))
            << static_cast<quint16>(19)
            << QByteArray("test._tcp.local.")
            << NameMap{{"_tcp.local", 0}}
            << QByteArray(NamePointer, sizeof(NamePointer));
}

void TestDns::testWriteName()
{
    QFETCH(QByteArray, initialPacket);
    QFETCH(quint16, initialOffset);
    QFETCH(quint16, correctOffset);
    QFETCH(QByteArray, name);
    QFETCH(NameMap, nameMap);
    QFETCH(QByteArray, correctPacket);

    QByteArray packet = initialPacket;
    quint16 offset = initialOffset;
    QMdnsEngine::writeName(packet, offset, name, nameMap);

    QCOMPARE(packet, correctPacket);
    QCOMPARE(offset, correctOffset);
}

void TestDns::testParseRecordA()
{
    PARSE_RECORD(RecordA);

    QCOMPARE(result, true);
    QCOMPARE(record.name(), Name);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::A));
    QCOMPARE(record.flushCache(), true);
    QCOMPARE(record.ttl(), Ttl);
    QCOMPARE(record.address(), Ipv4Address);
}

void TestDns::testParseRecordAAAA()
{
    PARSE_RECORD(RecordAAAA);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::AAAA));
    QCOMPARE(record.address(), Ipv6Address);
}

void TestDns::testParseRecordPTR()
{
    PARSE_RECORD(RecordPTR);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::PTR));
    QCOMPARE(record.target(), QByteArray("test2."));
}

void TestDns::testParseRecordSRV()
{
    PARSE_RECORD(RecordSRV);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::SRV));
    QCOMPARE(record.priority(), Priority);
    QCOMPARE(record.weight(), Weight);
    QCOMPARE(record.port(), Port);
    QCOMPARE(record.target(), Target);
}

void TestDns::testParseRecordTXT()
{
    PARSE_RECORD(RecordTXT);

    QCOMPARE(result, true);
    QCOMPARE(record.type(), static_cast<quint16>(QMdnsEngine::TXT));
    QCOMPARE(record.attributes(), Attributes);
}

void TestDns::testWriteRecordA()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::A);
    record.setFlushCache(true);
    record.setTtl(Ttl);
    record.setAddress(Ipv4Address);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordA, sizeof(RecordA)));
}

void TestDns::testWriteRecordAAAA()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::AAAA);
    record.setTtl(Ttl);
    record.setAddress(Ipv6Address);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordAAAA, sizeof(RecordAAAA)));
}

void TestDns::testWriteRecordPTR()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::PTR);
    record.setTtl(Ttl);
    record.setTarget(Target);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordPTR, sizeof(RecordPTR)));
}

void TestDns::testWriteRecordSRV()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::SRV);
    record.setTtl(Ttl);
    record.setPriority(Priority);
    record.setWeight(Weight);
    record.setPort(Port);
    record.setTarget(Target);

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordSRV, sizeof(RecordSRV)));
}

void TestDns::testWriteRecordTXT()
{
    QMdnsEngine::Record record;
    record.setName(Name);
    record.setType(QMdnsEngine::TXT);
    record.setTtl(Ttl);
    for (auto i = Attributes.constBegin(); i != Attributes.constEnd(); ++i) {
        record.addAttribute(i.key(), i.value());
    }

    WRITE_RECORD();

    QCOMPARE(packet, QByteArray(RecordTXT, sizeof(RecordTXT)));
}

QTEST_MAIN(TestDns)
#include "TestDns.moc"
<|endoftext|>


<commit_before>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "\n*Unknown command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
//  std::string input;

//  struct timeval timeout;
  fd_set read_set;
//  int file_desc = 0;
  int result;
  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

  char stdin_buffer[kBufferSize];
  memset(&stdin_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  std::cout << ">" << std::flush;

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        std::cout << "entering if STDIN" << std::endl;

        int read_stdin_size = read(STDIN_FILENO, stdin_buffer, kBufferSize);

        std::cout << "after read STDIN" << std::endl;

        if (read_stdin_size != 0) {
          if (stdin_buffer[0] == '/') {
            ProcessInput(stdin_buffer);
          } else {
            // Send chat messages
            StripChar(stdin_buffer, '\n');
            RequestSay(stdin_buffer);
          }
        }

        memset(&stdin_buffer, 0, kBufferSize);
      } // end of if STDIN_FILENO

      if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data
        int read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          // TODO capture user input, store, clean input, then print buffer, afterward replace input
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              struct text_say say;
              memcpy(&say, receive_buffer, sizeof(struct text_say));
              std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
              std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
              std::cout << ">" << std::flush;
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<commit_msg>use can to capture input before deleting<commit_after>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *channel;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

// Connects to the server at a the given port.
void Connect(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Try each address until we successfully connect().
  // If socket() (or connect()) fails, close the socket and try the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int RequestSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int RequestLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int RequestLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int RequestJoin(char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  return 0;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);
  bool result = true;

  if (inputs[0] == "/exit") {
    RequestLogout();
    result = false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join") {

  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch") {

  } else {
    std::cout << "\n*Unknown command" << std::endl;
  }

  return result;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  char *input;

//  struct timeval timeout;
  fd_set read_set;
//  int file_desc = 0;
  int result;
  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

  char stdin_buffer[kBufferSize];
  memset(&stdin_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  Connect(domain, port_str);

  RequestLogin(username);

  channel = (char *) "Common";
  RequestJoin(channel);

  // TODO handle response from send

  std::cout << ">" << std::flush;

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        int read_stdin_size = read(STDIN_FILENO, stdin_buffer, kBufferSize);

        if (read_stdin_size != 0) {
          if (stdin_buffer[0] == '/') {
            ProcessInput(stdin_buffer);
          } else {
            // Send chat messages
            StripChar(stdin_buffer, '\n');
            RequestSay(stdin_buffer);
          }
        }

        memset(&stdin_buffer, 0, kBufferSize);
      } // end of if STDIN_FILENO

      if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data
        int read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          // TODO capture user input, store, clean input, then print buffer, afterward replace input
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              struct text_say say;
              memcpy(&say, receive_buffer, sizeof(struct text_say));
              std::cin >> input;
              std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
              std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
              std::cout << ">" << input << std::flush;
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<|endoftext|>


<commit_before>#ifndef _UNTOOLS_UCBSTREAMHELPER_HXX
#define _UNTOOLS_UCBSTREAMHELPER_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

#include <tools/stream.hxx>

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace task
            {
                class XInteractionHandler;
            }
            namespace io
            {
                class XStream;
                class XInputStream;
            }
        }
    }
};

#define NS_UNO ::com::sun::star::uno
#define NS_IO ::com::sun::star::io
#define NS_TASK ::com::sun::star::task

class String;
namespace utl
{
    class UcbLockBytesHandler;

    class UcbStreamHelper : public SvStream
    {
    public:
        static SvStream*    CreateStream( const String& rFileName, StreamMode eOpenMode,
                                UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True );
        static SvStream*    CreateStream( const String& rFileName, StreamMode eOpenMode,
                                NS_UNO::Reference < NS_TASK::XInteractionHandler >,
                                UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True );
        static SvStream*    CreateStream( const String& rFileName, StreamMode eOpenMode,
                                sal_Bool bFileExists,
                                UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True );
        static SvStream*    CreateStream( NS_UNO::Reference < NS_IO::XInputStream > xStream );
        static SvStream*    CreateStream( NS_UNO::Reference < NS_IO::XStream > xStream );
    };
};

#endif
<commit_msg>INTEGRATION: CWS mav09 (1.3.140); FILE MERGED 2004/07/08 08:28:40 mav 1.3.140.4: RESYNC: (1.4-1.5); FILE MERGED 2004/04/29 16:49:45 mav 1.3.140.3: RESYNC: (1.3-1.4); FILE MERGED 2004/04/15 14:36:31 mba 1.3.140.2: #ii27773#: create Stream from XStream 2004/04/15 14:34:57 mba 1.3.140.1: #ii27773#: create Stream from XStream<commit_after>#ifndef _UNTOOLS_UCBSTREAMHELPER_HXX
#define _UNTOOLS_UCBSTREAMHELPER_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XSTREAM_HPP_
#include <com/sun/star/io/XStream.hpp>
#endif

#include <tools/stream.hxx>

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace task
            {
                class XInteractionHandler;
            }
            namespace io
            {
                class XStream;
                class XInputStream;
            }
        }
    }
};

#define NS_UNO ::com::sun::star::uno
#define NS_IO ::com::sun::star::io
#define NS_TASK ::com::sun::star::task

class String;
namespace utl
{
    class UcbLockBytesHandler;

    class UcbStreamHelper : public SvStream
    {
    public:
        static SvStream*    CreateStream( const String& rFileName, StreamMode eOpenMode,
                                UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True );
        static SvStream*    CreateStream( const String& rFileName, StreamMode eOpenMode,
                                NS_UNO::Reference < NS_TASK::XInteractionHandler >,
                                UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True );
        static SvStream*    CreateStream( const String& rFileName, StreamMode eOpenMode,
                                sal_Bool bFileExists,
                                UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True );
        static SvStream*    CreateStream( NS_UNO::Reference < NS_IO::XInputStream > xStream );
        static SvStream*    CreateStream( NS_UNO::Reference < NS_IO::XStream > xStream );
    };
};

#endif
<|endoftext|>


<commit_before>#include "include/Node.hpp"
#include "include/Tree.hpp"
#include <cstddef>
#include <iostream>

int main() {
    Node< std::string >* node = new Node< std::string >( 1, "Lorhan", nullptr, nullptr );
    std::cout << node->getValue() << std::endl;
    std::cout << node->left << std::endl;
    std::cout << node->right << std::endl;
    delete node;

    Tree< std::string > tree = Tree< std::string >();
    tree.insert( 10, "!" );
    tree.insert( 1, "Lorhan" );
    tree.insert( 2, "Sohaky" );
    tree.insert( 3, "top" );
    tree.insert( 4, "da" );
    tree.insert( 5, "balada" );
    std::cout << tree << std::endl;

    std::cout << tree.searchByValue( "top" ) << std::endl;
    std::cout << tree.searchByKey( 3 ) << std::endl;

    std::cout << "\n\n";
    Tree< char > tree2 = Tree< char >();

    tree2.insert( 2, '2' );
    tree2.insert( 1, '1' );
    tree2.insert( 4, '4' );
    tree2.insert( 3, '3' );
    tree2.insert( 5, '5' );
    std::cout << tree2 << std::endl;

    return 0;
}
<commit_msg>Teste da função de remoção<commit_after>#include "include/Node.hpp"
#include "include/Tree.hpp"
#include <cstddef>
#include <iostream>

int main() {
    Node< std::string >* node = new Node< std::string >( 1, "Lorhan", nullptr, nullptr );
    std::cout << node->getValue() << std::endl;
    std::cout << node->left << std::endl;
    std::cout << node->right << std::endl;
    delete node;

    Tree< std::string > tree = Tree< std::string >();
    tree.insert( 10, "!" );
    tree.insert( 1, "Lorhan" );
    tree.insert( 2, "Sohaky" );
    tree.insert( 3, "top" );
    tree.insert( 4, "da" );
    tree.insert( 5, "balada" );
    std::cout << tree << std::endl;

    std::cout << tree.searchByValue( "top" ) << std::endl;
    std::cout << tree.searchByKey( 3 ) << std::endl;

    std::cout << "\n\n";
    Tree< char > tree2 = Tree< char >();

    tree2.insert( 2, '2' );
    tree2.insert( 1, '1' );
    tree2.insert( 4, '4' );
    tree2.insert( 3, '3' );
    tree2.insert( 5, '5' );
    std::cout << tree2 << std::endl;

    tree2.remove( 4 );
    std::cout << tree2 << std::endl;
    tree2.remove( 2 );
    std::cout << tree2 << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int MDC(int n, int m);

int MDC(int n, int m){
	int a;
	int b;
	int resultado;

	temp_bool_1 = n > m;
	temp_bool_1= !temp_bool_1;
	if( temp_bool_1 ) goto L_if_end_1;
		a = n;

	b = m;

	L_if_end_1:
		a = m;

	b = n;

	L_if_chain_end_1:

	temp_bool_2 = b == 0;
	temp_bool_2= !temp_bool_2;
	if( temp_bool_2 ) goto L_if_end_2;
		resultado = m;

	L_if_end_2:
		resultado = MDC(a,b);
;

	L_if_chain_end_2:

	return resultado;
}

int main() {
	int temp_bool_1;
	int temp_bool_2;

	int a;
	int b;
	int res;

	printf( "%s" , "Digite dois inteiros, por favor: \n" );

	scanf( "%d" , &a );

	scanf( "%d" , &b );

	res = MDC(a,b);
;

	printf( "%s" , "MDC entre os dois: " );
	printf( "%d" , res );
	printf( "%s" , "\n" );

	return 0;
}

<commit_msg>Useless file<commit_after><|endoftext|>


<commit_before><commit_msg>pass first AXI communication in multi-thread simulation<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/aw_browser_main_parts.h"

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_dev_tools_discovery_provider.h"
#include "android_webview/browser/aw_media_client_android.h"
#include "android_webview/browser/aw_result_codes.h"
#include "android_webview/browser/deferred_gpu_command_service.h"
#include "android_webview/common/aw_resource.h"
#include "android_webview/common/aw_switches.h"
#include "base/android/apk_assets.h"
#include "base/android/build_info.h"
#include "base/android/locale_utils.h"
#include "base/android/memory_pressure_listener_android.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_utils.h"
#include "media/base/android/media_client_android.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/resource_bundle_android.h"
#include "ui/base/ui_base_paths.h"
#include "ui/gl/gl_surface.h"

namespace android_webview {

AwBrowserMainParts::AwBrowserMainParts(AwBrowserContext* browser_context)
    : browser_context_(browser_context) {
}

AwBrowserMainParts::~AwBrowserMainParts() {
}

void AwBrowserMainParts::PreEarlyInitialization() {
  net::NetworkChangeNotifier::SetFactory(
      new net::NetworkChangeNotifierFactoryAndroid());

  // Android WebView does not use default MessageLoop. It has its own
  // Android specific MessageLoop. Also see MainMessageLoopRun.
  DCHECK(!main_message_loop_.get());
  main_message_loop_.reset(new base::MessageLoopForUI);
  base::MessageLoopForUI::current()->Start();
}

int AwBrowserMainParts::PreCreateThreads() {
  base::MemoryMappedFile::Region pak_region =
      base::MemoryMappedFile::Region::kWholeFile;

  // TODO(primiano, mkosiba): GetApplicationLocale requires a ResourceBundle
  // instance to be present to work correctly so we call this (knowing it will
  // fail) just to create the ResourceBundle instance. We should refactor
  // ResourceBundle/GetApplicationLocale to not require an instance to be
  // initialized.
  ui::SetLocalePaksStoredInApk(true);
  ui::ResourceBundle::InitSharedInstanceWithLocale(
      base::android::GetDefaultLocale(),
      NULL,
      ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
  std::string locale = l10n_util::GetApplicationLocale(std::string());
  std::string pak_path = ui::GetPathForAndroidLocalePakWithinApk(locale);
  int pak_fd = base::android::OpenApkAsset(pak_path, &pak_region);
  if (pak_fd != -1) {
    ui::ResourceBundle::CleanupSharedInstance();
    ui::ResourceBundle::InitSharedInstanceWithPakFileRegion(
        base::File(pak_fd), pak_region);
  } else {
    LOG(WARNING) << "Failed to load " << locale << ".pak from the apk. "
                    "Bringing up WebView without any locale";
  }

  // Try to directly mmap the webviewchromium.pak from the apk. Fall back to
  // load from file, using PATH_SERVICE, otherwise.
  pak_fd = base::android::OpenApkAsset("assets/webviewchromium.pak",
                                       &pak_region);
  if (pak_fd != -1) {
    ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
        base::File(pak_fd), pak_region, ui::SCALE_FACTOR_NONE);
  } else {
    base::FilePath pak_path;
    PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &pak_path);
    LOG(WARNING) << "Cannot load webviewchromium.pak assets from the apk. "
                    "Falling back loading it from " << pak_path.MaybeAsASCII();
    ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
        pak_path.AppendASCII("webviewchromium.pak"), ui::SCALE_FACTOR_NONE);
  }

  base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(
      base::android::AttachCurrentThread());
  DeferredGpuCommandService::SetInstance();

  return content::RESULT_CODE_NORMAL_EXIT;
}

void AwBrowserMainParts::PreMainMessageLoopRun() {
  browser_context_->PreMainMessageLoopRun();

  AwDevToolsDiscoveryProvider::Install();

  media::SetMediaClientAndroid(
      new AwMediaClientAndroid(AwResource::GetConfigKeySystemUuidMapping()));

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kUseInProcCommandBuffer)) {
    gfx::GLSurface::InitializeOneOff();
  } else {
    content::SynchronousCompositor::SetUseIpcCommandBuffer();
  }

  content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView();

  // This is needed for WebView Classic backwards compatibility
  // See crbug.com/298495
  content::SetMaxURLChars(20 * 1024 * 1024);
}

bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
  // Android WebView does not use default MessageLoop. It has its own
  // Android specific MessageLoop.
  return true;
}

}  // namespace android_webview
<commit_msg>[Android WebView] Clean up resources loading logic<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/aw_browser_main_parts.h"

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_dev_tools_discovery_provider.h"
#include "android_webview/browser/aw_media_client_android.h"
#include "android_webview/browser/aw_result_codes.h"
#include "android_webview/browser/deferred_gpu_command_service.h"
#include "android_webview/common/aw_resource.h"
#include "android_webview/common/aw_switches.h"
#include "base/android/apk_assets.h"
#include "base/android/build_info.h"
#include "base/android/locale_utils.h"
#include "base/android/memory_pressure_listener_android.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_utils.h"
#include "media/base/android/media_client_android.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/resource_bundle_android.h"
#include "ui/base/ui_base_paths.h"
#include "ui/gl/gl_surface.h"

namespace android_webview {

AwBrowserMainParts::AwBrowserMainParts(AwBrowserContext* browser_context)
    : browser_context_(browser_context) {
}

AwBrowserMainParts::~AwBrowserMainParts() {
}

void AwBrowserMainParts::PreEarlyInitialization() {
  net::NetworkChangeNotifier::SetFactory(
      new net::NetworkChangeNotifierFactoryAndroid());

  // Android WebView does not use default MessageLoop. It has its own
  // Android specific MessageLoop. Also see MainMessageLoopRun.
  DCHECK(!main_message_loop_.get());
  main_message_loop_.reset(new base::MessageLoopForUI);
  base::MessageLoopForUI::current()->Start();
}

int AwBrowserMainParts::PreCreateThreads() {
  ui::SetLocalePaksStoredInApk(true);
  std::string locale = ui::ResourceBundle::InitSharedInstanceWithLocale(
      base::android::GetDefaultLocale(),
      NULL,
      ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
  if (locale.empty()) {
    LOG(WARNING) << "Failed to load locale .pak from the apk. "
        "Bringing up WebView without any locale";
  }

  // Try to directly mmap the webviewchromium.pak from the apk. Fall back to
  // load from file, using PATH_SERVICE, otherwise.
  base::FilePath pak_file_path;
  PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &pak_file_path);
  pak_file_path = pak_file_path.AppendASCII("webviewchromium.pak");
  ui::LoadMainAndroidPackFile("assets/webviewchromium.pak", pak_file_path);

  base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(
      base::android::AttachCurrentThread());
  DeferredGpuCommandService::SetInstance();

  return content::RESULT_CODE_NORMAL_EXIT;
}

void AwBrowserMainParts::PreMainMessageLoopRun() {
  browser_context_->PreMainMessageLoopRun();

  AwDevToolsDiscoveryProvider::Install();

  media::SetMediaClientAndroid(
      new AwMediaClientAndroid(AwResource::GetConfigKeySystemUuidMapping()));

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kUseInProcCommandBuffer)) {
    gfx::GLSurface::InitializeOneOff();
  } else {
    content::SynchronousCompositor::SetUseIpcCommandBuffer();
  }

  content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView();

  // This is needed for WebView Classic backwards compatibility
  // See crbug.com/298495
  content::SetMaxURLChars(20 * 1024 * 1024);
}

bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
  // Android WebView does not use default MessageLoop. It has its own
  // Android specific MessageLoop.
  return true;
}

}  // namespace android_webview
<|endoftext|>


<commit_before>#include <stdio.h>
#include <inttypes.h>
#include <lcm/lcm.h>
#include <iostream>
#include <limits>

#include "joints2frames.hpp"
#include <ConciseArgs>

using namespace std;
using namespace boost;
using namespace boost::assign;

// false usually, set true to disable the limiting:
#define DONT_LIMIT_FREQUENCY FALSE

joints2frames::joints2frames(boost::shared_ptr<lcm::LCM> &lcm_, bool show_labels_, bool show_triads_,
  bool standalone_head_, bool multisense_sim_):
          lcm_(lcm_), show_labels_(show_labels_), show_triads_(show_triads_),
          standalone_head_(standalone_head_),
          multisense_sim_(multisense_sim_){

  botparam_ = bot_param_new_from_server(lcm_->getUnderlyingLCM(), 0);

  model_ = boost::shared_ptr<ModelClient>(new ModelClient(lcm_->getUnderlyingLCM(), 0));
  KDL::Tree tree;
  if (!kdl_parser::treeFromString( model_->getURDFString() ,tree)){
    cerr << "ERROR: Failed to extract kdl tree from xml robot description" << endl;
    exit(-1);
  }
  fksolver_ = boost::shared_ptr<KDL::TreeFkSolverPosFull_recursive>(new KDL::TreeFkSolverPosFull_recursive(tree));

  // Vis Config:
  pc_vis_ = new pronto_vis( lcm_->getUnderlyingLCM());
  // obj: id name type reset
  pc_vis_->obj_cfg_list.push_back( obj_cfg(6001,"Frames",5,1) );
  lcm_->subscribe("EST_ROBOT_STATE",&joints2frames::robot_state_handler,this);

  #if DONT_LIMIT_FREQUENCY
    std::cout << "Output signals will not limited in rate\n";
  #else
    std::cout << "Output signals will be limited to these rates:\n";
    pub_frequency_["BODY_TO_HEAD"] = FrequencyLimit(0, 1E6/getMaxFrequency( "head") );
    pub_frequency_["BODY_TO_RHAND_FORCE_TORQUE"] = FrequencyLimit(0, 1E6/getMaxFrequency( "r_hand_force_torque" ) );
    pub_frequency_["BODY_TO_LHAND_FORCE_TORQUE"] = FrequencyLimit(0, 1E6/getMaxFrequency( "l_hand_force_torque" ) );
  #endif
}

double joints2frames::getMaxFrequency(std::string query_root){
  double max_frequency=1.0;

  string query = "coordinate_frames." + query_root+ ".max_frequency";

  if ( bot_param_get_double(botparam_, query.c_str() , &max_frequency) == 0){
    std::cout << max_frequency << "Hz \t| " << query_root  << "\n";
  }else{
    max_frequency =1.0;
    std::cout << max_frequency << "Hz \t| " << query_root << " ###### not found. using default ######\n";
  }
  return max_frequency;
}

Eigen::Isometry3d KDLToEigen(KDL::Frame tf){
  Eigen::Isometry3d tf_out;
  tf_out.setIdentity();
  tf_out.translation()  << tf.p[0], tf.p[1], tf.p[2];
  Eigen::Quaterniond q;
  tf.M.GetQuaternion( q.x() , q.y(), q.z(), q.w());
  tf_out.rotate(q);
  return tf_out;
}

void joints2frames::publishPose(Eigen::Isometry3d pose, int64_t utime, std::string channel){
  if (!shouldPublish(utime, channel) )
    return;

  bot_core::pose_t pose_msg;
  pose_msg.utime =   utime;
  pose_msg.pos[0] = pose.translation().x();
  pose_msg.pos[1] = pose.translation().y();
  pose_msg.pos[2] = pose.translation().z();
  Eigen::Quaterniond r_x(pose.rotation());
  pose_msg.orientation[0] =  r_x.w();
  pose_msg.orientation[1] =  r_x.x();
  pose_msg.orientation[2] =  r_x.y();
  pose_msg.orientation[3] =  r_x.z();
  lcm_->publish( channel, &pose_msg);
}

void joints2frames::publishRigidTransform(Eigen::Isometry3d pose, int64_t utime, std::string channel){
  if (!shouldPublish(utime, channel) )
    return;

  bot_core::rigid_transform_t tf;
  tf.utime = utime;
  tf.trans[0] = pose.translation().x();
  tf.trans[1] = pose.translation().y();
  tf.trans[2] = pose.translation().z();
  Eigen::Quaterniond quat(pose.rotation());
  tf.quat[0] = quat.w();
  tf.quat[1] = quat.x();
  tf.quat[2] = quat.y();
  tf.quat[3] = quat.z();
  lcm_->publish(channel, &tf);
}

// find the channel and check to see if it should be published
// true: publish | false: dont publish
// then update the utime that it was last published at
bool joints2frames::shouldPublish(int64_t utime, std::string channel){
  #if DONT_LIMIT_FREQUENCY
    return true;
  #endif

  std::map<string,FrequencyLimit>::iterator it;
  it = pub_frequency_.find( channel );

  if(it == pub_frequency_.end()){
    std::cout << channel << " was not found in the pub_frequency list - not publishing\n";
    return false;
  }

  if (utime <  it->second.last_utime ){
    it->second.last_utime  = 0;
    std::cout << utime << " detected negative time change for " << channel << " resetting last_utime\n";
  }

  if (utime >  it->second.min_period + it->second.last_utime ){
    it->second.last_utime = utime;
    return true;
  }

  // if published recently - then dont publish again
  return false;
}

void joints2frames::robot_state_handler(const lcm::ReceiveBuffer* rbuf, const std::string& channel, const  drc::robot_state_t* msg){

  // 0. Extract World Pose of body:
  Eigen::Isometry3d world_to_body;
  world_to_body.setIdentity();
  world_to_body.translation()  << msg->pose.translation.x, msg->pose.translation.y, msg->pose.translation.z;
  Eigen::Quaterniond quat = Eigen::Quaterniond(msg->pose.rotation.w, msg->pose.rotation.x,
                                               msg->pose.rotation.y, msg->pose.rotation.z);
  world_to_body.rotate(quat);

  // 1. Solve for Forward Kinematics:
  // call a routine that calculates the transforms the joint_state_t* msg.
  map<string, double> jointpos_in;
  map<string, KDL::Frame > cartpos_out;
  for (uint i=0; i< (uint) msg->num_joints; i++) //cast to uint to suppress compiler warning
    jointpos_in.insert(make_pair(msg->joint_name[i], msg->joint_position[i]));

  // Calculate forward position kinematics
  bool kinematics_status;
  bool flatten_tree=true; // determines absolute transforms to robot origin, otherwise relative transforms between joints.
  kinematics_status = fksolver_->JntToCart(jointpos_in,cartpos_out,flatten_tree);
  if(kinematics_status>=0){
    // cout << "Success!" <<endl;
  }else{
    cerr << "Error: could not calculate forward kinematics!" <<endl;
    return;
  }

  if (multisense_sim_){
    vector<string>::iterator it;
    vector<string> vec;
    vec = msg->joint_name;
    it=find(vec.begin(),vec.end(),"hokuyo_joint");

    if(it != vec.end()){
      int hokuyo_idx = (it-vec.begin());

      double angle = msg->joint_position[hokuyo_idx];
      // publish message for bot_frames
      bot_core::rigid_transform_t preToPostFrame;
      preToPostFrame.utime = msg->utime;
      preToPostFrame.trans[0] = 0;
      preToPostFrame.trans[1] = 0;
      preToPostFrame.trans[2] = 0;
      preToPostFrame.quat[0] = std::cos(angle/2);
      preToPostFrame.quat[1] = 0;
      preToPostFrame.quat[2] = 0;
      preToPostFrame.quat[3] = std::sin(angle/2);
      lcm_->publish("PRE_SPINDLE_TO_POST_SPINDLE",
                                 &preToPostFrame);
    }
  }

  // 2a. Determine the required BOT_FRAMES transforms:
  Eigen::Isometry3d body_to_head, body_to_hokuyo_link;
  bool body_to_head_found =false;
  bool body_to_hokuyo_link_found = false;
  for( map<string, KDL::Frame >::iterator ii=cartpos_out.begin(); ii!=cartpos_out.end(); ++ii){
    std::string link = (*ii).first;
    if (   (*ii).first.compare( "head" ) == 0 ){
      body_to_head = KDLToEigen( (*ii).second );
      body_to_head_found=true;
    }else if(  (*ii).first.compare( "hokuyo_link" ) == 0 ){
      body_to_hokuyo_link = KDLToEigen( (*ii).second );
      body_to_hokuyo_link_found=true;
    }else if(  (*ii).first.compare( "r_hand_force_torque" ) == 0 ){ // ft sensor
      publishRigidTransform( KDLToEigen( (*ii).second ) , msg->utime, "BODY_TO_RHAND_FORCE_TORQUE" );
    }else if(  (*ii).first.compare( "l_hand_force_torque" ) == 0 ){ // ft sensor
      publishRigidTransform( KDLToEigen( (*ii).second ) , msg->utime, "BODY_TO_LHAND_FORCE_TORQUE" );
    }
  }

  // 2b. Republish the required BOT_FRAMES transforms:
  if (body_to_head_found){
    publishRigidTransform(body_to_head, msg->utime, "BODY_TO_HEAD");
  }
  if (standalone_head_){
    // If publishing from the head alone, then the head is also the body link:
    publishRigidTransform(body_to_hokuyo_link, msg->utime, "HEAD_TO_HOKUYO_LINK" );
  }

  // 3. Loop through joints and extract world positions:
  if (show_triads_){
    int counter =msg->utime;
    std::vector<Isometry3dTime> body_to_jointTs, world_to_jointsT;
    std::vector< int64_t > body_to_joint_utimes;
    std::vector< std::string > joint_names;
    for( map<string, KDL::Frame >::iterator ii=cartpos_out.begin(); ii!=cartpos_out.end(); ++ii){
      std::string joint = (*ii).first;
      //cout << joint  << ": \n";
      joint_names.push_back( joint  );
      body_to_joint_utimes.push_back( counter);

      Eigen::Isometry3d body_to_joint = KDLToEigen( (*ii).second );
      Isometry3dTime body_to_jointT(counter, body_to_joint);
      body_to_jointTs.push_back(body_to_jointT);
      // convert to world positions
      Isometry3dTime world_to_jointT(counter, world_to_body*body_to_joint);
      world_to_jointsT.push_back(world_to_jointT);
      counter++;
    }

    pc_vis_->pose_collection_to_lcm_from_list(6001, world_to_jointsT); // all joints in world frame
    if (show_labels_)
      pc_vis_->text_collection_to_lcm(6002, 6001, "Frames [Labels]", joint_names, body_to_joint_utimes );
  }
}

int
main(int argc, char ** argv){
  bool labels = false;
  bool triads = false;
  bool standalone_head = false;
  bool multisense_sim = false;
  ConciseArgs opt(argc, (char**)argv);
  opt.add(triads, "t", "triads","Frame Triads - show no not");
  opt.add(labels, "l", "labels","Frame Labels - show no not");
  opt.add(standalone_head, "s", "standalone_head","Standalone Sensor Head");
  opt.add(multisense_sim, "m", "multisense_sim","In sim, publish PRE_SPINDLE_TO_POST_SPINDLE");
  opt.parse();
  if (labels){ // require triads if labels is to be published
    triads=true;
  }

  std::cout << "triads: " << triads << "\n";
  std::cout << "labels: " << labels << "\n";

  boost::shared_ptr<lcm::LCM> lcm(new lcm::LCM("") );
  if(!lcm->good())
    return 1;

  joints2frames app(lcm,labels,triads, standalone_head, multisense_sim);
  while(0 == lcm->handle());
  return 0;
}
<commit_msg>minor typo fix<commit_after>#include <stdio.h>
#include <inttypes.h>
#include <lcm/lcm.h>
#include <iostream>
#include <limits>

#include "joints2frames.hpp"
#include <ConciseArgs>

using namespace std;
using namespace boost;
using namespace boost::assign;

// false usually, set true to disable the limiting:
#define DONT_LIMIT_FREQUENCY FALSE

joints2frames::joints2frames(boost::shared_ptr<lcm::LCM> &lcm_, bool show_labels_, bool show_triads_,
  bool standalone_head_, bool multisense_sim_):
          lcm_(lcm_), show_labels_(show_labels_), show_triads_(show_triads_),
          standalone_head_(standalone_head_),
          multisense_sim_(multisense_sim_){

  botparam_ = bot_param_new_from_server(lcm_->getUnderlyingLCM(), 0);

  model_ = boost::shared_ptr<ModelClient>(new ModelClient(lcm_->getUnderlyingLCM(), 0));
  KDL::Tree tree;
  if (!kdl_parser::treeFromString( model_->getURDFString() ,tree)){
    cerr << "ERROR: Failed to extract kdl tree from xml robot description" << endl;
    exit(-1);
  }
  fksolver_ = boost::shared_ptr<KDL::TreeFkSolverPosFull_recursive>(new KDL::TreeFkSolverPosFull_recursive(tree));

  // Vis Config:
  pc_vis_ = new pronto_vis( lcm_->getUnderlyingLCM());
  // obj: id name type reset
  pc_vis_->obj_cfg_list.push_back( obj_cfg(6001,"Frames",5,1) );
  lcm_->subscribe("EST_ROBOT_STATE",&joints2frames::robot_state_handler,this);

  #if DONT_LIMIT_FREQUENCY
    std::cout << "Output signals will not limited in rate\n";
  #else
    std::cout << "Output signals will be limited to these rates:\n";
    pub_frequency_["BODY_TO_HEAD"] = FrequencyLimit(0, 1E6/getMaxFrequency( "head") );
    pub_frequency_["BODY_TO_RHAND_FORCE_TORQUE"] = FrequencyLimit(0, 1E6/getMaxFrequency( "r_hand_force_torque" ) );
    pub_frequency_["BODY_TO_LHAND_FORCE_TORQUE"] = FrequencyLimit(0, 1E6/getMaxFrequency( "l_hand_force_torque" ) );
  #endif
}

double joints2frames::getMaxFrequency(std::string query_root){
  double max_frequency=1.0;

  string query = "coordinate_frames." + query_root+ ".max_frequency";

  if ( bot_param_get_double(botparam_, query.c_str() , &max_frequency) == 0){
    std::cout << max_frequency << "Hz \t| " << query_root  << "\n";
  }else{
    max_frequency =1.0;
    std::cout << max_frequency << "Hz \t| " << query_root << " ###### not found. using default ######\n";
  }
  return max_frequency;
}

Eigen::Isometry3d KDLToEigen(KDL::Frame tf){
  Eigen::Isometry3d tf_out;
  tf_out.setIdentity();
  tf_out.translation()  << tf.p[0], tf.p[1], tf.p[2];
  Eigen::Quaterniond q;
  tf.M.GetQuaternion( q.x() , q.y(), q.z(), q.w());
  tf_out.rotate(q);
  return tf_out;
}

void joints2frames::publishPose(Eigen::Isometry3d pose, int64_t utime, std::string channel){
  if (!shouldPublish(utime, channel) )
    return;

  bot_core::pose_t pose_msg;
  pose_msg.utime =   utime;
  pose_msg.pos[0] = pose.translation().x();
  pose_msg.pos[1] = pose.translation().y();
  pose_msg.pos[2] = pose.translation().z();
  Eigen::Quaterniond r_x(pose.rotation());
  pose_msg.orientation[0] =  r_x.w();
  pose_msg.orientation[1] =  r_x.x();
  pose_msg.orientation[2] =  r_x.y();
  pose_msg.orientation[3] =  r_x.z();
  lcm_->publish( channel, &pose_msg);
}

void joints2frames::publishRigidTransform(Eigen::Isometry3d pose, int64_t utime, std::string channel){
  if (!shouldPublish(utime, channel) )
    return;

  bot_core::rigid_transform_t tf;
  tf.utime = utime;
  tf.trans[0] = pose.translation().x();
  tf.trans[1] = pose.translation().y();
  tf.trans[2] = pose.translation().z();
  Eigen::Quaterniond quat(pose.rotation());
  tf.quat[0] = quat.w();
  tf.quat[1] = quat.x();
  tf.quat[2] = quat.y();
  tf.quat[3] = quat.z();
  lcm_->publish(channel, &tf);
}

// find the channel and check to see if it should be published
// true: publish | false: dont publish
// then update the utime that it was last published at
bool joints2frames::shouldPublish(int64_t utime, std::string channel){
  #if DONT_LIMIT_FREQUENCY
    return true;
  #endif

  std::map<string,FrequencyLimit>::iterator it;
  it = pub_frequency_.find( channel );

  if(it == pub_frequency_.end()){
    std::cout << channel << " was not found in the pub_frequency list - not publishing\n";
    return false;
  }

  if (utime <  it->second.last_utime ){
    it->second.last_utime  = 0;
    std::cout << utime << " detected negative time change for " << channel << " resetting last_utime\n";
  }

  if (utime >  it->second.min_period + it->second.last_utime ){
    it->second.last_utime = utime;
    return true;
  }

  // if published recently - then dont publish again
  return false;
}

void joints2frames::robot_state_handler(const lcm::ReceiveBuffer* rbuf, const std::string& channel, const  drc::robot_state_t* msg){

  // 0. Extract World Pose of body:
  Eigen::Isometry3d world_to_body;
  world_to_body.setIdentity();
  world_to_body.translation()  << msg->pose.translation.x, msg->pose.translation.y, msg->pose.translation.z;
  Eigen::Quaterniond quat = Eigen::Quaterniond(msg->pose.rotation.w, msg->pose.rotation.x,
                                               msg->pose.rotation.y, msg->pose.rotation.z);
  world_to_body.rotate(quat);

  // 1. Solve for Forward Kinematics:
  // call a routine that calculates the transforms the joint_state_t* msg.
  map<string, double> jointpos_in;
  map<string, KDL::Frame > cartpos_out;
  for (uint i=0; i< (uint) msg->num_joints; i++) //cast to uint to suppress compiler warning
    jointpos_in.insert(make_pair(msg->joint_name[i], msg->joint_position[i]));

  // Calculate forward position kinematics
  bool kinematics_status;
  bool flatten_tree=true; // determines absolute transforms to robot origin, otherwise relative transforms between joints.
  kinematics_status = fksolver_->JntToCart(jointpos_in,cartpos_out,flatten_tree);
  if(kinematics_status>=0){
    // cout << "Success!" <<endl;
  }else{
    cerr << "Error: could not calculate forward kinematics!" <<endl;
    return;
  }

  if (multisense_sim_){
    vector<string>::iterator it;
    vector<string> vec;
    vec = msg->joint_name;
    it=find(vec.begin(),vec.end(),"hokuyo_joint");

    if(it != vec.end()){
      int hokuyo_idx = (it-vec.begin());

      double angle = msg->joint_position[hokuyo_idx];
      // publish message for bot_frames
      bot_core::rigid_transform_t preToPostFrame;
      preToPostFrame.utime = msg->utime;
      preToPostFrame.trans[0] = 0;
      preToPostFrame.trans[1] = 0;
      preToPostFrame.trans[2] = 0;
      preToPostFrame.quat[0] = std::cos(angle/2);
      preToPostFrame.quat[1] = 0;
      preToPostFrame.quat[2] = 0;
      preToPostFrame.quat[3] = std::sin(angle/2);
      lcm_->publish("PRE_SPINDLE_TO_POST_SPINDLE",
                                 &preToPostFrame);
    }
  }

  // 2a. Determine the required BOT_FRAMES transforms:
  Eigen::Isometry3d body_to_head, body_to_hokuyo_link;
  bool body_to_head_found =false;
  bool body_to_hokuyo_link_found = false;
  for( map<string, KDL::Frame >::iterator ii=cartpos_out.begin(); ii!=cartpos_out.end(); ++ii){
    std::string link = (*ii).first;
    if (   (*ii).first.compare( "head" ) == 0 ){
      body_to_head = KDLToEigen( (*ii).second );
      body_to_head_found=true;
    }else if(  (*ii).first.compare( "hokuyo_link" ) == 0 ){
      body_to_hokuyo_link = KDLToEigen( (*ii).second );
      body_to_hokuyo_link_found=true;
    }else if(  (*ii).first.compare( "r_hand_force_torque" ) == 0 ){ // ft sensor
      publishRigidTransform( KDLToEigen( (*ii).second ) , msg->utime, "BODY_TO_RHAND_FORCE_TORQUE" );
    }else if(  (*ii).first.compare( "l_hand_force_torque" ) == 0 ){ // ft sensor
      publishRigidTransform( KDLToEigen( (*ii).second ) , msg->utime, "BODY_TO_LHAND_FORCE_TORQUE" );
    }
  }

  // 2b. Republish the required BOT_FRAMES transforms:
  if (body_to_head_found){
    publishRigidTransform(body_to_head, msg->utime, "BODY_TO_HEAD");
  }
  if (standalone_head_){
    // If publishing from the head alone, then the head is also the body link:
    publishRigidTransform(body_to_hokuyo_link, msg->utime, "HEAD_TO_HOKUYO_LINK" );
  }

  // 3. Loop through joints and extract world positions:
  if (show_triads_){
    int counter =msg->utime;
    std::vector<Isometry3dTime> body_to_jointTs, world_to_jointsT;
    std::vector< int64_t > body_to_joint_utimes;
    std::vector< std::string > joint_names;
    for( map<string, KDL::Frame >::iterator ii=cartpos_out.begin(); ii!=cartpos_out.end(); ++ii){
      std::string joint = (*ii).first;
      //cout << joint  << ": \n";
      joint_names.push_back( joint  );
      body_to_joint_utimes.push_back( counter);

      Eigen::Isometry3d body_to_joint = KDLToEigen( (*ii).second );
      Isometry3dTime body_to_jointT(counter, body_to_joint);
      body_to_jointTs.push_back(body_to_jointT);
      // convert to world positions
      Isometry3dTime world_to_jointT(counter, world_to_body*body_to_joint);
      world_to_jointsT.push_back(world_to_jointT);
      counter++;
    }

    pc_vis_->pose_collection_to_lcm_from_list(6001, world_to_jointsT); // all joints in world frame
    if (show_labels_)
      pc_vis_->text_collection_to_lcm(6002, 6001, "Frames [Labels]", joint_names, body_to_joint_utimes );
  }
}

int
main(int argc, char ** argv){
  bool labels = false;
  bool triads = false;
  bool standalone_head = false;
  bool multisense_sim = false;
  ConciseArgs opt(argc, (char**)argv);
  opt.add(triads, "t", "triads","Publish Frame Triads");
  opt.add(labels, "l", "labels","Publish Frame Labels");
  opt.add(standalone_head, "s", "standalone_head","Standalone Sensor Head");
  opt.add(multisense_sim, "m", "multisense_sim","In sim, publish PRE_SPINDLE_TO_POST_SPINDLE");
  opt.parse();
  if (labels){ // require triads if labels is to be published
    triads=true;
  }

  std::cout << "triads: " << triads << "\n";
  std::cout << "labels: " << labels << "\n";

  boost::shared_ptr<lcm::LCM> lcm(new lcm::LCM("") );
  if(!lcm->good())
    return 1;

  joints2frames app(lcm,labels,triads, standalone_head, multisense_sim);
  while(0 == lcm->handle());
  return 0;
}
<|endoftext|>