<commit_before>/*
 * colormapwidget.cpp
 *
 *  Created on: Jan 29, 2013
 *      Author: schurade
 */
#include <QtGui/QtGui>

#include "colormapwidget.h"

ColormapWidget::ColormapWidget( int width ) :
    m_colormap( FNCM_GRAY ),
    m_width( width ),
    m_lowerThreshold( 0.0 ),
    m_upperThreshold( 1.0 )
{
    QVBoxLayout* vLayout = new QVBoxLayout();

//    QHBoxLayout* hLayout = new QHBoxLayout();
//    m_nlabel = new QLabel( QString("colormap"), this );
//    hLayout->addWidget( m_nlabel );
//    hLayout->addStretch();

    QHBoxLayout* hLayout2 = new QHBoxLayout();
    m_nlabel = new QLabel( this );

    m_image = createImage( width );
    QPixmap pix( width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
    hLayout2->addWidget( m_nlabel );

    //vLayout->addLayout( hLayout );
    vLayout->addLayout( hLayout2 );
    vLayout->setContentsMargins( 1,1,1,1 );

    setLayout( vLayout );

    setFrameStyle( QFrame::Panel | QFrame::Raised );

    setStyleSheet( "QLabel { font:  bold 12px; margin-bottom: -1px }"
                     "QLineEdit { font: 12px; max-height: 14px; margin-top: -1px }"
                   );
}

ColormapWidget::~ColormapWidget()
{
}

QImage* ColormapWidget::createImage( int width )
{
    QImage* image = new QImage( width, 20, QImage::Format_RGB32 );

    for ( int i = 0; i < width; ++i )
    {
        QColor c;
        int g = 0;
        switch ( m_colormap )
        {
            case FNCM_RAINBOW1:
                c = colormap1( (float)i / (float)width );
                break;
            case FNCM_RAINBOW2:
                c = colormap2( (float)i / (float)width );
                break;
            case FNCM_BLUEWHITERED:
                c = colormap3( (float)i / (float)width );
                break;
            default:
                g = (float)i / (float)width * 255;
                c = QColor( g, g, g );
                break;
        }
        for ( int k = 0; k < 20; ++k )
        {
            image->setPixel( i, k, c.rgba() );
        }
    }

    return image;
}

QColor ColormapWidget::colormap1( float value )
{
    value = ( value - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold );

    value = qMax( 0.0f, qMin( 1.0f, value ) );
    value *= 5.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if( value < 1.0 )
    {
        g = value;
        b = 1.0f;
    }
    else if( value < 2.0 )
    {
        g = 1.0;
        b = 2.0 -value;
    }
    else if( value < 3.0 )
    {
        r = value-2.0;
        g = 1.0;
    }
    else if( value < 4.0 )
    {
        r = 1.0;
        g = 4.0-value;
    }
    else
    {
        r = 1.0;
        b = value-4.0;
    }
    return QColor( 255 * r, 255 * g, 255 * b );
}

QColor ColormapWidget::colormap2( float value )
{
    value = ( value - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold );

    value = qMax( 0.0f, qMin( 1.0f, value ) );
    value *= 6.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if( value < 2.0 )
    {
        g = value * 0.5f;
        b = 1.0f;
    }
    else if( value < 3.0 )
    {
        g = 1.0;
        b = 3.0 -value;
    }
    else if( value < 4.0 )
    {
        r = value-3.0;
        g = 1.0;
    }
    else if( value < 6.0 )
    {
        r = 1.0;
        g = 0.5f * ( 6.0-value );
    }
    else
    {
        r = 1.0;
    }
    return QColor( 255 * r, 255 * g, 255 * b );
}

QColor ColormapWidget::colormap3( float value )
{
    value = ( value - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold );

    value = qMax( 0.0f, qMin( 1.0f, value ) );
    value *= 2.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if( value < 1.0 )
    {
        r = value;
        g = value;
        b = 1.0;
    }
    else if( value <= 2.0 )
    {
        r = 1.0;
        g = 2.0-value;
        b = 2.0-value;
    }
    else
    {
        r = 1.0;
    }
    return QColor( 255 * r, 255 * g, 255 * b );
}

void ColormapWidget::setLowerThreshold( float value )
{
    value = qMax( 0.0f, qMin( 1.0f, value ) );
    m_lowerThreshold = value;
    m_image = createImage( m_width );
    QPixmap pix( m_width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
}

void ColormapWidget::setUpperThreshold( float value )
{
    value = qMax( 0.0f, qMin( 1.0f, value ) );
    m_upperThreshold = value;
    m_image = createImage( m_width );
    QPixmap pix( m_width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
}

void ColormapWidget::setColormap( int value )
{
    m_colormap = qMin( (FN_COLORMAP)value, FNCM_NOCOLORMAP );
    m_image = createImage( m_width );
    QPixmap pix( m_width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
}
<commit_msg>change colormapwidget for grayscale too<commit_after>/*
 * colormapwidget.cpp
 *
 *  Created on: Jan 29, 2013
 *      Author: schurade
 */
#include <QtGui/QtGui>

#include "colormapwidget.h"

ColormapWidget::ColormapWidget( int width ) :
    m_colormap( FNCM_GRAY ),
    m_width( width ),
    m_lowerThreshold( 0.0 ),
    m_upperThreshold( 1.0 )
{
    QVBoxLayout* vLayout = new QVBoxLayout();

//    QHBoxLayout* hLayout = new QHBoxLayout();
//    m_nlabel = new QLabel( QString("colormap"), this );
//    hLayout->addWidget( m_nlabel );
//    hLayout->addStretch();

    QHBoxLayout* hLayout2 = new QHBoxLayout();
    m_nlabel = new QLabel( this );

    m_image = createImage( width );
    QPixmap pix( width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
    hLayout2->addWidget( m_nlabel );

    //vLayout->addLayout( hLayout );
    vLayout->addLayout( hLayout2 );
    vLayout->setContentsMargins( 1,1,1,1 );

    setLayout( vLayout );

    setFrameStyle( QFrame::Panel | QFrame::Raised );

    setStyleSheet( "QLabel { font:  bold 12px; margin-bottom: -1px }"
                     "QLineEdit { font: 12px; max-height: 14px; margin-top: -1px }"
                   );
}

ColormapWidget::~ColormapWidget()
{
}

QImage* ColormapWidget::createImage( int width )
{
    QImage* image = new QImage( width, 20, QImage::Format_RGB32 );

    for ( int i = 0; i < width; ++i )
    {
        QColor c;
        int g = 0;
        switch ( m_colormap )
        {
            case FNCM_RAINBOW1:
                c = colormap1( (float)i / (float)width );
                break;
            case FNCM_RAINBOW2:
                c = colormap2( (float)i / (float)width );
                break;
            case FNCM_BLUEWHITERED:
                c = colormap3( (float)i / (float)width );
                break;
            default:
                g = qMin( 255.0f, qMax( 0.0f, ( (float)i / (float)width - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold ) * 255 ) );
                c = QColor( g, g, g );
                break;
        }
        for ( int k = 0; k < 20; ++k )
        {
            image->setPixel( i, k, c.rgba() );
        }
    }

    return image;
}

QColor ColormapWidget::colormap1( float value )
{
    value = ( value - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold );

    value = qMax( 0.0f, qMin( 1.0f, value ) );
    value *= 5.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if( value < 1.0 )
    {
        g = value;
        b = 1.0f;
    }
    else if( value < 2.0 )
    {
        g = 1.0;
        b = 2.0 -value;
    }
    else if( value < 3.0 )
    {
        r = value-2.0;
        g = 1.0;
    }
    else if( value < 4.0 )
    {
        r = 1.0;
        g = 4.0-value;
    }
    else
    {
        r = 1.0;
        b = value-4.0;
    }
    return QColor( 255 * r, 255 * g, 255 * b );
}

QColor ColormapWidget::colormap2( float value )
{
    value = ( value - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold );

    value = qMax( 0.0f, qMin( 1.0f, value ) );
    value *= 6.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if( value < 2.0 )
    {
        g = value * 0.5f;
        b = 1.0f;
    }
    else if( value < 3.0 )
    {
        g = 1.0;
        b = 3.0 -value;
    }
    else if( value < 4.0 )
    {
        r = value-3.0;
        g = 1.0;
    }
    else if( value < 6.0 )
    {
        r = 1.0;
        g = 0.5f * ( 6.0-value );
    }
    else
    {
        r = 1.0;
    }
    return QColor( 255 * r, 255 * g, 255 * b );
}

QColor ColormapWidget::colormap3( float value )
{
    value = ( value - m_lowerThreshold ) / ( m_upperThreshold - m_lowerThreshold );

    value = qMax( 0.0f, qMin( 1.0f, value ) );
    value *= 2.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if( value < 1.0 )
    {
        r = value;
        g = value;
        b = 1.0;
    }
    else if( value <= 2.0 )
    {
        r = 1.0;
        g = 2.0-value;
        b = 2.0-value;
    }
    else
    {
        r = 1.0;
    }
    return QColor( 255 * r, 255 * g, 255 * b );
}

void ColormapWidget::setLowerThreshold( float value )
{
    value = qMax( 0.0f, qMin( 1.0f, value ) );
    m_lowerThreshold = value;
    m_image = createImage( m_width );
    QPixmap pix( m_width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
}

void ColormapWidget::setUpperThreshold( float value )
{
    value = qMax( 0.0f, qMin( 1.0f, value ) );
    m_upperThreshold = value;
    m_image = createImage( m_width );
    QPixmap pix( m_width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
}

void ColormapWidget::setColormap( int value )
{
    m_colormap = qMin( (FN_COLORMAP)value, FNCM_NOCOLORMAP );
    m_image = createImage( m_width );
    QPixmap pix( m_width, 20 );
    pix.convertFromImage( *m_image );
    m_nlabel->setPixmap( pix );
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: testtdmanager.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-23 15:05:36 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
#include "com/sun/star/lang/XMain.hpp"
#include "com/sun/star/lang/XSingleComponentFactory.hpp"
#include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
#include "com/sun/star/reflection/XPublished.hpp"
#include "com/sun/star/reflection/XStructTypeDescription.hpp"
#include "com/sun/star/reflection/XTypeDescription.hpp"
#include "com/sun/star/registry/InvalidRegistryException.hpp"
#include "com/sun/star/registry/XRegistryKey.hpp"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/TypeClass.hpp"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp"
#include "cppuhelper/factory.hxx"
#include "cppuhelper/implbase1.hxx"
#include "cppuhelper/weak.hxx"
#include "rtl/textenc.h"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "uno/environment.h"
#include "uno/lbnames.h"

#include /*MSVC trouble: <cstdlib>*/ <stdlib.h>
#include <iostream>
#include <ostream>

namespace css = com::sun::star;

namespace {

class Service: public cppu::WeakImplHelper1< css::lang::XMain > {
public:
    virtual sal_Int32 SAL_CALL
    run(css::uno::Sequence< rtl::OUString > const & arguments)
        throw (css::uno::RuntimeException);

    static rtl::OUString getImplementationName();

    static css::uno::Sequence< rtl::OUString > getSupportedServiceNames();

    static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
        css::uno::Reference< css::uno::XComponentContext > const & context)
        throw (css::uno::Exception);

private:
    explicit Service(
        css::uno::Reference< css::uno::XComponentContext > const & context):
        m_context(context)
    {}

    css::uno::Reference< css::uno::XComponentContext > m_context;
};

}

namespace {

std::ostream & operator <<(std::ostream & out, rtl::OUString const & value) {
    return out << rtl::OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr();
}

void assertTrue(bool argument) {
    if (!argument) {
        std::cerr
            << "assertTrue(" << argument << ") failed" << std::endl;
        /*MSVC trouble: std::*/abort();
    }
}

void assertFalse(bool argument) {
    if (argument) {
        std::cerr
            << "assertFalse(" << argument << ") failed" << std::endl;
        /*MSVC trouble: std::*/abort();
    }
}

template< typename T > void assertEqual(T const & value, T const & argument) {
    if (argument != value) {
        std::cerr
            << "assertEqual(" << value << ", " << argument << ") failed"
            << std::endl;
        /*MSVC trouble: std::*/abort();
    }
}

}

sal_Int32 Service::run(css::uno::Sequence< rtl::OUString > const & arguments)
    throw (css::uno::RuntimeException)
{
    css::uno::Reference< css::lang::XMultiComponentFactory > factory(
        m_context->getServiceManager());
    assertTrue(factory.is());
    css::uno::Reference< css::container::XHierarchicalNameAccess > manager(
        m_context->getValueByName(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "/singletons/"
                    "com.sun.star.reflection.theTypeDescriptionManager"))),
        css::uno::UNO_QUERY_THROW);

    css::uno::Reference< css::reflection::XIndirectTypeDescription > sequence(
        manager->getByHierarchicalName(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean"))),
        css::uno::UNO_QUERY_THROW);
    assertEqual(css::uno::TypeClass_SEQUENCE, sequence->getTypeClass());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean")),
        sequence->getName());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean")),
        sequence->getReferencedType()->getName());

    css::uno::Reference< css::reflection::XStructTypeDescription > structure(
        manager->getByHierarchicalName(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "test.tdmanager.Struct<boolean,test.tdmanager.Struct<"
                    "any,com.sun.star.uno.XInterface>>"))),
        css::uno::UNO_QUERY_THROW);
    assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "test.tdmanager.Struct<boolean,test.tdmanager.Struct<"
                "any,com.sun.star.uno.XInterface>>")),
        structure->getName());
    assertEqual< bool >(false, structure->getBaseType().is());
    assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")),
        structure->getMemberTypes()[0]->getName());
    assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s")),
        structure->getMemberNames()[0]);
    assertEqual< sal_Int32 >(0, structure->getTypeParameters().getLength());
    assertEqual< sal_Int32 >(2, structure->getTypeArguments().getLength());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boolean")),
        structure->getTypeArguments()[0]->getName());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")),
        structure->getTypeArguments()[1]->getName());

    css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription >
        method(
            manager->getByHierarchicalName(
                rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM(
                        "com.sun.star.uno.XComponentContext::getValueByName"))),
            css::uno::UNO_QUERY_THROW);
    assertEqual(css::uno::TypeClass_INTERFACE_METHOD, method->getTypeClass());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "com.sun.star.uno.XComponentContext::getValueByName")),
        method->getName());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("getValueByName")),
        method->getMemberName());
    assertEqual< sal_Int32 >(3, method->getPosition());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")),
        method->getReturnType()->getName());
    assertEqual< bool >(false, method->isOneway());
    assertEqual< sal_Int32 >(1, method->getParameters().getLength());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")),
        method->getParameters()[0]->getName());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string")),
        method->getParameters()[0]->getType()->getName());
    assertEqual< bool >(true, method->getParameters()[0]->isIn());
    assertEqual< bool >(false, method->getParameters()[0]->isOut());
    assertEqual< sal_Int32 >(0, method->getParameters()[0]->getPosition());
    assertEqual< sal_Int32 >(0, method->getExceptions().getLength());

    assertFalse(
        css::uno::Reference< css::reflection::XPublished >(
            css::uno::Reference< css::reflection::XTypeDescription >(
                manager->getByHierarchicalName(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean"))),
                css::uno::UNO_QUERY_THROW),
            css::uno::UNO_QUERY).is());
    assertFalse(
        css::uno::Reference< css::reflection::XPublished >(
            css::uno::Reference< css::reflection::XTypeDescription >(
                manager->getByHierarchicalName(
                    rtl::OUString(
                        RTL_CONSTASCII_USTRINGPARAM(
                            "com.sun.star.beans.XIntroTest::ObjectName"))),
                css::uno::UNO_QUERY_THROW),
            css::uno::UNO_QUERY).is());
    assertFalse(
        css::uno::Reference< css::reflection::XPublished >(
            css::uno::Reference< css::reflection::XTypeDescription >(
                manager->getByHierarchicalName(
                    rtl::OUString(
                        RTL_CONSTASCII_USTRINGPARAM(
                            "com.sun.star.beans.XIntroTest::writeln"))),
                css::uno::UNO_QUERY_THROW),
            css::uno::UNO_QUERY).is());
    //TODO: check that the reflection of a property of an accumulation-based
    // service does not support XPublished

    return 0;
}

rtl::OUString Service::getImplementationName() {
    return rtl::OUString::createFromAscii("test.tdmanager.impl");
}

css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames() {
    return css::uno::Sequence< rtl::OUString >();
}

css::uno::Reference< css::uno::XInterface > Service::createInstance(
    css::uno::Reference< css::uno::XComponentContext > const & context)
    throw (css::uno::Exception)
{
    return static_cast< cppu::OWeakObject * >(new Service(context));
}

extern "C" void SAL_CALL component_getImplementationEnvironment(
    char const ** envTypeName, uno_Environment **)
{
    if (envTypeName != 0) {
        *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
    }
}

extern "C" void * SAL_CALL component_getFactory(char const * implName,
                                                void * serviceManager, void *) {
    void * p = 0;
    if (serviceManager != 0) {
        css::uno::Reference< css::lang::XSingleComponentFactory > f;
        if (Service::getImplementationName().equalsAscii(implName)) {
            f = cppu::createSingleComponentFactory(
                &Service::createInstance, Service::getImplementationName(),
                Service::getSupportedServiceNames());
        }
        if (f.is()) {
            f->acquire();
            p = f.get();
        }
    }
    return p;
}

namespace {

bool writeInfo(void * registryKey, rtl::OUString const & implementationName,
               css::uno::Sequence< rtl::OUString > const & serviceNames) {
    rtl::OUString keyName(rtl::OUString::createFromAscii("/"));
    keyName += implementationName;
    keyName += rtl::OUString::createFromAscii("/UNO/SERVICES");
    css::uno::Reference< css::registry::XRegistryKey > key;
    try {
        key = static_cast< css::registry::XRegistryKey * >(registryKey)->
            createKey(keyName);
    } catch (css::registry::InvalidRegistryException &) {}
    if (!key.is()) {
        return false;
    }
    bool success = true;
    for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
        try {
            key->createKey(serviceNames[i]);
        } catch (css::registry::InvalidRegistryException &) {
            success = false;
            break;
        }
    }
    return success;
}

}

extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * registryKey) {
    return registryKey
        && writeInfo(registryKey, Service::getImplementationName(),
                     Service::getSupportedServiceNames());
}
<commit_msg>INTEGRATION: CWS unotlc (1.2.16); FILE MERGED 2004/08/03 15:04:37 dbo 1.2.16.2: RESYNC: (1.2-1.3); FILE MERGED 2004/07/12 13:37:25 dbo 1.2.16.1: #i20303# tests for compatibility type checks Issue number: Submitted by: Reviewed by:<commit_after>/*************************************************************************
 *
 *  $RCSfile: testtdmanager.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2004-08-12 12:20:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
#include "com/sun/star/container/XSet.hpp"
#include "com/sun/star/lang/XMain.hpp"
#include "com/sun/star/lang/XSingleComponentFactory.hpp"
#include "com/sun/star/lang/IllegalArgumentException.hpp"
#include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
#include "com/sun/star/reflection/XPublished.hpp"
#include "com/sun/star/reflection/XStructTypeDescription.hpp"
#include "com/sun/star/reflection/XTypeDescription.hpp"
#include "com/sun/star/registry/InvalidRegistryException.hpp"
#include "com/sun/star/registry/XRegistryKey.hpp"
#include "com/sun/star/registry/XSimpleRegistry.hpp"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/TypeClass.hpp"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp"
#include "cppuhelper/factory.hxx"
#include "cppuhelper/implbase1.hxx"
#include "cppuhelper/weak.hxx"
#include "osl/file.h"
#include "osl/thread.h"
#include "rtl/textenc.h"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "uno/environment.h"
#include "uno/lbnames.h"

#include /*MSVC trouble: <cstdlib>*/ <stdlib.h>
#include <iostream>
#include <ostream>

namespace css = com::sun::star;

namespace {

class Service: public cppu::WeakImplHelper1< css::lang::XMain > {
public:
    virtual sal_Int32 SAL_CALL
    run(css::uno::Sequence< rtl::OUString > const & arguments)
        throw (css::uno::RuntimeException);

    static rtl::OUString getImplementationName();

    static css::uno::Sequence< rtl::OUString > getSupportedServiceNames();

    static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
        css::uno::Reference< css::uno::XComponentContext > const & context)
        throw (css::uno::Exception);

private:
    explicit Service(
        css::uno::Reference< css::uno::XComponentContext > const & context):
        m_context(context)
    {}

    css::uno::Reference< css::uno::XComponentContext > m_context;
};

}

namespace {

std::ostream & operator <<(std::ostream & out, rtl::OUString const & value) {
    return out << rtl::OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr();
}

void assertTrue(bool argument) {
    if (!argument) {
        std::cerr
            << "assertTrue(" << argument << ") failed" << std::endl;
        /*MSVC trouble: std::*/abort();
    }
}

void assertFalse(bool argument) {
    if (argument) {
        std::cerr
            << "assertFalse(" << argument << ") failed" << std::endl;
        /*MSVC trouble: std::*/abort();
    }
}

template< typename T > void assertEqual(T const & value, T const & argument) {
    if (argument != value) {
        std::cerr
            << "assertEqual(" << value << ", " << argument << ") failed"
            << std::endl;
        /*MSVC trouble: std::*/abort();
    }
}

}

sal_Int32 Service::run(css::uno::Sequence< rtl::OUString > const & arguments)
    throw (css::uno::RuntimeException)
{
    css::uno::Reference< css::lang::XMultiComponentFactory > factory(
        m_context->getServiceManager());
    assertTrue(factory.is());
    css::uno::Reference< css::container::XHierarchicalNameAccess > manager(
        m_context->getValueByName(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "/singletons/"
                    "com.sun.star.reflection.theTypeDescriptionManager"))),
        css::uno::UNO_QUERY_THROW);

    ////////////////////////////////////////
    // test: add cmd line rdbs to manager
    ////////////////////////////////////////

    OSL_ASSERT( arguments.getLength() > 0 );
    css::uno::Reference<css::container::XSet> xSet(
        manager, css::uno::UNO_QUERY_THROW );
    for ( sal_Int32 argPos = 0; argPos < arguments.getLength(); ++argPos ) {
        rtl::OUString url;
        OSL_VERIFY( osl_File_E_None == osl_getFileURLFromSystemPath(
                        arguments[argPos].pData, &url.pData ) );
        bool supposedToBeCompatible = ! url.endsWithIgnoreAsciiCaseAsciiL(
            RTL_CONSTASCII_STRINGPARAM("_incomp.rdb") );

        css::uno::Reference<css::registry::XSimpleRegistry> xReg(
            m_context->getServiceManager()->createInstanceWithContext(
                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                   "com.sun.star.registry.SimpleRegistry") ),
                m_context ), css::uno::UNO_QUERY_THROW );
        xReg->open( url, true /* read-only */, false /* ! create */ );
        css::uno::Any arg( makeAny(xReg) );
        css::uno::Reference<css::container::XHierarchicalNameAccess> xTDprov(
            m_context->getServiceManager()->
            createInstanceWithArgumentsAndContext(
                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                   "com.sun.star.comp.stoc."
                                   "RegistryTypeDescriptionProvider") ),
                css::uno::Sequence<css::uno::Any>( &arg, 1 ), m_context ),
            css::uno::UNO_QUERY_THROW );
        try {
            xSet->insert( makeAny(xTDprov) );
            if (! supposedToBeCompatible)
                std::cerr << "current rdb file: " <<
                    rtl::OUStringToOString(
                        url, osl_getThreadTextEncoding()).getStr() << std::endl;
            assertTrue(supposedToBeCompatible);
        } catch (css::lang::IllegalArgumentException &) {
            if (supposedToBeCompatible)
                throw;
            assertFalse(supposedToBeCompatible);
        }
    }

    ///////

    css::uno::Reference< css::reflection::XIndirectTypeDescription > sequence(
        manager->getByHierarchicalName(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean"))),
        css::uno::UNO_QUERY_THROW);
    assertEqual(css::uno::TypeClass_SEQUENCE, sequence->getTypeClass());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean")),
        sequence->getName());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean")),
        sequence->getReferencedType()->getName());

    css::uno::Reference< css::reflection::XStructTypeDescription > structure(
        manager->getByHierarchicalName(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "test.tdmanager.Struct<boolean,test.tdmanager.Struct<"
                    "any,com.sun.star.uno.XInterface>>"))),
        css::uno::UNO_QUERY_THROW);
    assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "test.tdmanager.Struct<boolean,test.tdmanager.Struct<"
                "any,com.sun.star.uno.XInterface>>")),
        structure->getName());
    assertEqual< bool >(false, structure->getBaseType().is());
    assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")),
        structure->getMemberTypes()[0]->getName());
    assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s")),
        structure->getMemberNames()[0]);
    assertEqual< sal_Int32 >(0, structure->getTypeParameters().getLength());
    assertEqual< sal_Int32 >(2, structure->getTypeArguments().getLength());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boolean")),
        structure->getTypeArguments()[0]->getName());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")),
        structure->getTypeArguments()[1]->getName());

    css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription >
        method(
            manager->getByHierarchicalName(
                rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM(
                        "com.sun.star.uno.XComponentContext::getValueByName"))),
            css::uno::UNO_QUERY_THROW);
    assertEqual(css::uno::TypeClass_INTERFACE_METHOD, method->getTypeClass());
    assertEqual(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "com.sun.star.uno.XComponentContext::getValueByName")),
        method->getName());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("getValueByName")),
        method->getMemberName());
    assertEqual< sal_Int32 >(3, method->getPosition());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")),
        method->getReturnType()->getName());
    assertEqual< bool >(false, method->isOneway());
    assertEqual< sal_Int32 >(1, method->getParameters().getLength());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")),
        method->getParameters()[0]->getName());
    assertEqual(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string")),
        method->getParameters()[0]->getType()->getName());
    assertEqual< bool >(true, method->getParameters()[0]->isIn());
    assertEqual< bool >(false, method->getParameters()[0]->isOut());
    assertEqual< sal_Int32 >(0, method->getParameters()[0]->getPosition());
    assertEqual< sal_Int32 >(0, method->getExceptions().getLength());

    assertFalse(
        css::uno::Reference< css::reflection::XPublished >(
            css::uno::Reference< css::reflection::XTypeDescription >(
                manager->getByHierarchicalName(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean"))),
                css::uno::UNO_QUERY_THROW),
            css::uno::UNO_QUERY).is());
    assertFalse(
        css::uno::Reference< css::reflection::XPublished >(
            css::uno::Reference< css::reflection::XTypeDescription >(
                manager->getByHierarchicalName(
                    rtl::OUString(
                        RTL_CONSTASCII_USTRINGPARAM(
                            "com.sun.star.beans.XIntroTest::ObjectName"))),
                css::uno::UNO_QUERY_THROW),
            css::uno::UNO_QUERY).is());
    assertFalse(
        css::uno::Reference< css::reflection::XPublished >(
            css::uno::Reference< css::reflection::XTypeDescription >(
                manager->getByHierarchicalName(
                    rtl::OUString(
                        RTL_CONSTASCII_USTRINGPARAM(
                            "com.sun.star.beans.XIntroTest::writeln"))),
                css::uno::UNO_QUERY_THROW),
            css::uno::UNO_QUERY).is());
    //TODO: check that the reflection of a property of an accumulation-based
    // service does not support XPublished

    return 0;
}

rtl::OUString Service::getImplementationName() {
    return rtl::OUString::createFromAscii("test.tdmanager.impl");
}

css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames() {
    return css::uno::Sequence< rtl::OUString >();
}

css::uno::Reference< css::uno::XInterface > Service::createInstance(
    css::uno::Reference< css::uno::XComponentContext > const & context)
    throw (css::uno::Exception)
{
    return static_cast< cppu::OWeakObject * >(new Service(context));
}

extern "C" void SAL_CALL component_getImplementationEnvironment(
    char const ** envTypeName, uno_Environment **)
{
    if (envTypeName != 0) {
        *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
    }
}

extern "C" void * SAL_CALL component_getFactory(char const * implName,
                                                void * serviceManager, void *) {
    void * p = 0;
    if (serviceManager != 0) {
        css::uno::Reference< css::lang::XSingleComponentFactory > f;
        if (Service::getImplementationName().equalsAscii(implName)) {
            f = cppu::createSingleComponentFactory(
                &Service::createInstance, Service::getImplementationName(),
                Service::getSupportedServiceNames());
        }
        if (f.is()) {
            f->acquire();
            p = f.get();
        }
    }
    return p;
}

namespace {

bool writeInfo(void * registryKey, rtl::OUString const & implementationName,
               css::uno::Sequence< rtl::OUString > const & serviceNames) {
    rtl::OUString keyName(rtl::OUString::createFromAscii("/"));
    keyName += implementationName;
    keyName += rtl::OUString::createFromAscii("/UNO/SERVICES");
    css::uno::Reference< css::registry::XRegistryKey > key;
    try {
        key = static_cast< css::registry::XRegistryKey * >(registryKey)->
            createKey(keyName);
    } catch (css::registry::InvalidRegistryException &) {}
    if (!key.is()) {
        return false;
    }
    bool success = true;
    for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
        try {
            key->createKey(serviceNames[i]);
        } catch (css::registry::InvalidRegistryException &) {
            success = false;
            break;
        }
    }
    return success;
}

}

extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * registryKey) {
    return registryKey
        && writeInfo(registryKey, Service::getImplementationName(),
                     Service::getSupportedServiceNames());
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/c_str.H $                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file c_str.H
/// @brief Function to return the C-string name of a thing
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#ifndef _MSS_C_STR_H_
#define _MSS_C_STR_H_

#include <fapi2.H>
#include <generic/memory/lib/utils/index.H>

namespace mss
{

// Thread local storage for the string we're going to create.
//TODO RTC:153924 Remove the else case when issue is resolved
#ifndef PLAT_NO_THREAD_LOCAL_STORAGE
    extern thread_local char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#else
    extern char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#endif

///
/// @brief non-target c_str general declaration
/// @tparam T - type you want the const char * for
/// @param[in] i_input - input you want the const char * for
/// @return const char *
///
template< typename T >
const char* c_str( const T& i_input );

///
/// @brief fapi2::Target c_str general declaration
/// @tparam T - fapi2::TargetType you want the name for
/// @param[in] i_target - target you want the name for
/// @return const char *
///
template< fapi2::TargetType T >
inline const char* c_str( const fapi2::template Target<T>& i_target )
{
    fapi2::toString( i_target, c_str_storage, fapi2::MAX_ECMD_STRING_LEN );
    return c_str_storage;
}

template<>
inline const char* c_str( const fapi2::template Target<fapi2::TARGET_TYPE_DIMM>& i_target )
{
    const auto l_mca = i_target.getParent<fapi2::TARGET_TYPE_MCA>();
    const auto l_mcs = l_mca.getParent<fapi2::TARGET_TYPE_MCS>();

    constexpr auto l_max_gen = 3;
    constexpr auto l_max_type = 4;
    const char* const l_map_gen_to_string[l_max_gen] = {"empty", "DDR3", "DDR4"};
    const char* const l_map_type_to_string[l_max_type] = {"empty", "RDIMM", "UDIMM", "LRDIMM"};

    uint8_t l_type = 0;
    uint8_t l_gen = 0;
    char l_buffer[fapi2::MAX_ECMD_STRING_LEN] = {};

    fapi2::toString( i_target, c_str_storage, fapi2::MAX_ECMD_STRING_LEN );

    // Had to unroll FAPI_TRY so that fapi2::current_err doesn't get overwritten, causes errors
    // when calling c_str inside of a function that returns fapi2::ReturnCode
    constexpr size_t PORTS_PER_MCS = 2;
    constexpr size_t MAX_DIMM_PER_PORT = 2;
    uint8_t l_value[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {};

    if (FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_value) != fapi2::FAPI2_RC_SUCCESS)
    {
        goto fapi_try_exit;
    }

    l_type = l_value[mss::index(l_mca)][mss::index(i_target)];

    if (l_type >= l_max_type)
    {
        goto fapi_try_exit;
    }

    // Had to unroll FAPI_TRY so that fapi2::current_err doesn't get overwritten, causes errors
    // when calling c_str inside of a function that returns fapi2::ReturnCode
    if (FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_value) != fapi2::FAPI2_RC_SUCCESS)
    {
        goto fapi_try_exit;
    }

    l_gen = l_value[mss::index(l_mca)][mss::index(i_target)];

    if (l_gen >= l_max_gen)
    {
        goto fapi_try_exit;
    }

    snprintf(l_buffer, fapi2::MAX_ECMD_STRING_LEN, " %s (%s)", l_map_type_to_string[l_type], l_map_gen_to_string[l_gen]);
    return strncat( c_str_storage, l_buffer, fapi2::MAX_ECMD_STRING_LEN - strlen(c_str_storage) );

fapi_try_exit:
    // Probably the best we're going to do ...
    return c_str_storage;
}

}
#endif
<commit_msg>L3 work for mss xmls<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/c_str.H $                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file c_str.H
/// @brief Function to return the C-string name of a thing
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_C_STR_H_
#define _MSS_C_STR_H_

#include <fapi2.H>
#include <generic/memory/lib/utils/index.H>

namespace mss
{

// Thread local storage for the string we're going to create.
//TODO RTC:153924 Remove the else case when issue is resolved
#ifndef PLAT_NO_THREAD_LOCAL_STORAGE
    extern thread_local char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#else
    extern char c_str_storage[fapi2::MAX_ECMD_STRING_LEN];
#endif

///
/// @brief non-target c_str general declaration
/// @tparam T - type you want the const char * for
/// @param[in] i_input - input you want the const char * for
/// @return const char *
///
template< typename T >
const char* c_str( const T& i_input );

///
/// @brief fapi2::Target c_str general declaration
/// @tparam T - fapi2::TargetType you want the name for
/// @param[in] i_target - target you want the name for
/// @return const char *
///
template< fapi2::TargetType T >
inline const char* c_str( const fapi2::template Target<T>& i_target )
{
    fapi2::toString( i_target, c_str_storage, fapi2::MAX_ECMD_STRING_LEN );
    return c_str_storage;
}

template<>
inline const char* c_str( const fapi2::template Target<fapi2::TARGET_TYPE_DIMM>& i_target )
{
    const auto l_mca = i_target.getParent<fapi2::TARGET_TYPE_MCA>();
    const auto l_mcs = l_mca.getParent<fapi2::TARGET_TYPE_MCS>();

    constexpr auto l_max_gen = 3;
    constexpr auto l_max_type = 4;
    const char* const l_map_gen_to_string[l_max_gen] = {"empty", "DDR3", "DDR4"};
    const char* const l_map_type_to_string[l_max_type] = {"empty", "RDIMM", "UDIMM", "LRDIMM"};

    uint8_t l_type = 0;
    uint8_t l_gen = 0;
    char l_buffer[fapi2::MAX_ECMD_STRING_LEN] = {};

    fapi2::toString( i_target, c_str_storage, fapi2::MAX_ECMD_STRING_LEN );

    // Had to unroll FAPI_TRY so that fapi2::current_err doesn't get overwritten, causes errors
    // when calling c_str inside of a function that returns fapi2::ReturnCode
    constexpr size_t PORTS_PER_MCS = 2;
    constexpr size_t MAX_DIMM_PER_PORT = 2;
    uint8_t l_value[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {};

    if (FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_value) != fapi2::FAPI2_RC_SUCCESS)
    {
        goto fapi_try_exit;
    }

    l_type = l_value[mss::index(l_mca)][mss::index(i_target)];

    if (l_type >= l_max_type)
    {
        goto fapi_try_exit;
    }

    // Had to unroll FAPI_TRY so that fapi2::current_err doesn't get overwritten, causes errors
    // when calling c_str inside of a function that returns fapi2::ReturnCode
    if (FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_value) != fapi2::FAPI2_RC_SUCCESS)
    {
        goto fapi_try_exit;
    }

    l_gen = l_value[mss::index(l_mca)][mss::index(i_target)];

    if (l_gen >= l_max_gen)
    {
        goto fapi_try_exit;
    }

    snprintf(l_buffer, fapi2::MAX_ECMD_STRING_LEN, " %s (%s)", l_map_type_to_string[l_type], l_map_gen_to_string[l_gen]);
    return strncat( c_str_storage, l_buffer, fapi2::MAX_ECMD_STRING_LEN - strlen(c_str_storage) );

fapi_try_exit:
    // Probably the best we're going to do ...
    return c_str_storage;
}

}
#endif
<|endoftext|>


<commit_before><commit_msg>gui: remove obsolete stub<commit_after><|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"

#include "MyString.h"

//------------------------------------------------------------------------

static void displayJobShort(ClassAd *ad);
static void short_header(void);
static void short_print(int,int,const char*,int,int,int,int,int,int,const char *);
static void short_header (void);
static void displayJobShort (ClassAd *);
static void shorten (char *, int);
static char* format_date( time_t date );
static char* format_time( int tot_secs );
static char encode_status( int status );
static bool EvalBool(ClassAd *ad, const char *constraint);

//------------------------------------------------------------------------

static void Usage(char* name)
{
  printf("Usage: %s [-l] [-f history-filename] [ cluster_id | cluster_id.proc_id | owner]\n",name);
  exit(1);
}

//------------------------------------------------------------------------

main(int argc, char* argv[])
{
  char* JobHistoryFileName=NULL;
  int LongFormat=FALSE;
  char* constraint=NULL;
  int cluster, proc;
  char tmp[512];
  int i;

  for(i=1; i<argc; i++) {
    if (strcmp(argv[i],"-l")==0) {
      LongFormat=TRUE;
    }
    else if (strcmp(argv[i],"-f")==0) {
      if (i+1==argc || JobHistoryFileName) break;
      i++;
	  JobHistoryFileName=argv[i];
    }
    else if (strcmp(argv[i],"-help")==0) {
	  Usage(argv[0]);
    }
    else if (sscanf (argv[i], "%d.%d", &cluster, &proc) == 2) {
      if (constraint) break;
      sprintf (tmp, "((%s == %d) && (%s == %d))",
               ATTR_CLUSTER_ID, cluster,ATTR_PROC_ID, proc);
      constraint=tmp;
    }
    else if (sscanf (argv[i], "%d", &cluster) == 1) {
      if (constraint) break;
      sprintf (tmp, "(%s == %d)", ATTR_CLUSTER_ID, cluster);
      constraint=tmp;
    }
    else {
      if (constraint) break;
      sprintf(tmp, "(%s == \"%s\")", ATTR_OWNER, argv[i]);
      constraint=tmp;
    }
  }
  if (i<argc) Usage(argv[0]);

  config( 0 );
  if (!JobHistoryFileName) {
    JobHistoryFileName=param("HISTORY");
  }

  FILE* LogFile=fopen(JobHistoryFileName,"r");
  if (!LogFile) {
    fprintf(stderr,"History file not found or empty.\n");
    exit(1);
  }

  // printf("HistroyFile=%s\nLongFormat=%d\n",JobHistoryFileName,LongFormat);
  // if (constraint) printf("constraint=%s\n",constraint);

  int EndFlag=0;
  if (!LongFormat) short_header();
  while(!EndFlag) {
    ClassAd* ad=new ClassAd(LogFile,"***",EndFlag);
    if (!constraint || EvalBool(ad, constraint)) {
      if (LongFormat) { ad->fPrint(stdout); printf("\n"); }
      else displayJobShort(ad);
    }
  }

  fclose(LogFile);
  exit(0);
}

//------------------------------------------------------------------------

static void
displayJobShort (ClassAd *ad)
{
        int cluster, proc, date, status, prio, image_size, CompDate;
        float utime;
        char owner[64], cmd[2048], args[2048];

        if (!ad->EvalInteger (ATTR_CLUSTER_ID, NULL, cluster)           ||
                !ad->EvalInteger (ATTR_PROC_ID, NULL, proc)                             ||
                !ad->EvalInteger (ATTR_Q_DATE, NULL, date)                              ||
                !ad->EvalInteger (ATTR_COMPLETION_DATE, NULL, CompDate)	 ||
                !ad->EvalFloat   (ATTR_JOB_REMOTE_USER_CPU, NULL, utime)||
                !ad->EvalInteger (ATTR_JOB_STATUS, NULL, status)                ||
                !ad->EvalInteger (ATTR_JOB_PRIO, NULL, prio)                    ||
                !ad->EvalInteger (ATTR_IMAGE_SIZE, NULL, image_size)    ||
                !ad->EvalString  (ATTR_OWNER, NULL, owner)                              ||
                !ad->EvalString  (ATTR_JOB_CMD, NULL, cmd) )
        {
                printf (" --- ???? --- \n");
                return;
        }

        shorten (owner, 14);
        if (ad->EvalString ("Args", NULL, args)) strcat (cmd, args);
        shorten (cmd, 18);
        short_print (cluster, proc, owner, date, CompDate, (int)utime, status, prio,
                                        image_size, cmd);

}

//------------------------------------------------------------------------

static void
short_header (void)
{
    printf( " %-7s %-14s %11s %12s %-2s %11s %-3s %-4s %-18s\n",
        "ID",
        "OWNER",
        "SUBMITTED",
        "CPU_USAGE",
        "ST",
		"COMPLETED",
        "PRI",
        "SIZE",
        "CMD"
    );
}

//------------------------------------------------------------------------

static void
shorten (char *buff, int len)
{
    if ((unsigned int)strlen (buff) > (unsigned int)len) buff[len] = '\0';
}

//------------------------------------------------------------------------

/*
  Print a line of data for the "short" display of a PROC structure.  The
  "short" display is the one used by "condor_q".  N.B. the columns used
  by this routine must match those defined by the short_header routine
  defined above.
*/

static void
short_print(
        int cluster,
        int proc,
        const char *owner,
        int date,
		int CompDate,
        int time,
        int status,
        int prio,
        int image_size,
        const char *cmd
        ) {
		MyString SubmitDateStr=format_date(date);
		MyString CompDateStr=format_date(CompDate);
        printf( "%4d.%-3d %-14s %-11s %-12s %-2c %-11s %-3d %-4.1f %-18s\n",
                cluster,
                proc,
                owner,
                (const char*) SubmitDateStr,
                format_time(time),
                encode_status(status),
                (const char*) CompDateStr,
                prio,
                image_size/1024.0,
                cmd
        );
}

//------------------------------------------------------------------------

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/

static char* format_date( time_t date )
{
        static char     buf[ 12 ];
        struct tm       *tm;

		if (date==0) return " ??? ";

        tm = localtime( &date );
        sprintf( buf, "%2d/%-2d %02d:%02d",
                (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
        );
        return buf;
}

//------------------------------------------------------------------------

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/

static char     *
format_time( int tot_secs )
{
        int             days;
        int             hours;
        int             min;
        int             secs;
        static char     answer[25];

        days = tot_secs / DAY;
        tot_secs %= DAY;
        hours = tot_secs / HOUR;
        tot_secs %= HOUR;
        min = tot_secs / MINUTE;
        secs = tot_secs % MINUTE;

        (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
        return answer;
}

//------------------------------------------------------------------------

/*
  Encode a status from a PROC structure as a single letter suited for
  printing.
*/

static char
encode_status( int status )
{
        switch( status ) {
          case UNEXPANDED:
                return 'U';
          case IDLE:
                return 'I';
          case RUNNING:
                return 'R';
          case COMPLETED:
                return 'C';
          case REMOVED:
                return 'X';
          default:
                return ' ';
        }
}

//------------------------------------------------------------------------

static bool EvalBool(ClassAd *ad, const char *constraint)
{
    ExprTree *tree;
    EvalResult result;

    if (Parse(constraint, tree) != 0) {
        // dprintf(D_ALWAYS, "can't parse constraint: %s\n", constraint);
        return false;
    }

    // Evaluate constraint with ad in the target scope so that constraints
    // have the same semantics as the collector queries.  --RR
    if (!tree->EvalTree(NULL, ad, &result)) {
        // dprintf(D_ALWAYS, "can't evaluate constraint: %s\n", constraint);
        delete tree;
        return false;
    }
    delete tree;
    if (result.type == LX_INTEGER) {
        return (bool)result.i;
    }
    // dprintf(D_ALWAYS, "contraint (%s) does not evaluate to bool\n", constraint);
    return false;
}

<commit_msg>Fixed Rank=0 Req=True bug, by treating it as a AttrList instead of ClassAd<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"

#include "MyString.h"

//------------------------------------------------------------------------

static void displayJobShort(AttrList* ad);
static void short_header(void);
static void short_print(int,int,const char*,int,int,int,int,int,int,const char *);
static void short_header (void);
static void shorten (char *, int);
static char* format_date( time_t date );
static char* format_time( int tot_secs );
static char encode_status( int status );
static bool EvalBool(AttrList *ad, const char *constraint);

//------------------------------------------------------------------------

static void Usage(char* name)
{
  printf("Usage: %s [-l] [-f history-filename] [ cluster_id | cluster_id.proc_id | owner]\n",name);
  exit(1);
}

//------------------------------------------------------------------------

main(int argc, char* argv[])
{
  char* JobHistoryFileName=NULL;
  int LongFormat=FALSE;
  char* constraint=NULL;
  int cluster, proc;
  char tmp[512];
  int i;

  for(i=1; i<argc; i++) {
    if (strcmp(argv[i],"-l")==0) {
      LongFormat=TRUE;
    }
    else if (strcmp(argv[i],"-f")==0) {
      if (i+1==argc || JobHistoryFileName) break;
      i++;
	  JobHistoryFileName=argv[i];
    }
    else if (strcmp(argv[i],"-help")==0) {
	  Usage(argv[0]);
    }
    else if (sscanf (argv[i], "%d.%d", &cluster, &proc) == 2) {
      if (constraint) break;
      sprintf (tmp, "((%s == %d) && (%s == %d))",
               ATTR_CLUSTER_ID, cluster,ATTR_PROC_ID, proc);
      constraint=tmp;
    }
    else if (sscanf (argv[i], "%d", &cluster) == 1) {
      if (constraint) break;
      sprintf (tmp, "(%s == %d)", ATTR_CLUSTER_ID, cluster);
      constraint=tmp;
    }
    else {
      if (constraint) break;
      sprintf(tmp, "(%s == \"%s\")", ATTR_OWNER, argv[i]);
      constraint=tmp;
    }
  }
  if (i<argc) Usage(argv[0]);

  config( 0 );
  if (!JobHistoryFileName) {
    JobHistoryFileName=param("HISTORY");
  }

  FILE* LogFile=fopen(JobHistoryFileName,"r");
  if (!LogFile) {
    fprintf(stderr,"History file not found or empty.\n");
    exit(1);
  }

  // printf("HistroyFile=%s\nLongFormat=%d\n",JobHistoryFileName,LongFormat);
  // if (constraint) printf("constraint=%s\n",constraint);

  int EndFlag=0;
  if (!LongFormat) short_header();
  while(!EndFlag) {
    AttrList* ad=new AttrList(LogFile,"***",EndFlag);
    if (!constraint || EvalBool(ad, constraint)) {
      if (LongFormat) { ad->fPrint(stdout); printf("\n"); }
      else displayJobShort(ad);
    }
  }

  fclose(LogFile);
  exit(0);
}

//------------------------------------------------------------------------

static void
displayJobShort(AttrList* ad)
{
        int cluster, proc, date, status, prio, image_size, CompDate;
        float utime;
        char owner[64], cmd[2048], args[2048];

        if (!ad->EvalInteger (ATTR_CLUSTER_ID, NULL, cluster)           ||
                !ad->EvalInteger (ATTR_PROC_ID, NULL, proc)                             ||
                !ad->EvalInteger (ATTR_Q_DATE, NULL, date)                              ||
                !ad->EvalInteger (ATTR_COMPLETION_DATE, NULL, CompDate)	 ||
                !ad->EvalFloat   (ATTR_JOB_REMOTE_USER_CPU, NULL, utime)||
                !ad->EvalInteger (ATTR_JOB_STATUS, NULL, status)                ||
                !ad->EvalInteger (ATTR_JOB_PRIO, NULL, prio)                    ||
                !ad->EvalInteger (ATTR_IMAGE_SIZE, NULL, image_size)    ||
                !ad->EvalString  (ATTR_OWNER, NULL, owner)                              ||
                !ad->EvalString  (ATTR_JOB_CMD, NULL, cmd) )
        {
                printf (" --- ???? --- \n");
                return;
        }

        shorten (owner, 14);
        if (ad->EvalString ("Args", NULL, args)) strcat (cmd, args);
        shorten (cmd, 18);
        short_print (cluster, proc, owner, date, CompDate, (int)utime, status, prio,
                                        image_size, cmd);

}

//------------------------------------------------------------------------

static void
short_header (void)
{
    printf( " %-7s %-14s %11s %12s %-2s %11s %-3s %-4s %-18s\n",
        "ID",
        "OWNER",
        "SUBMITTED",
        "CPU_USAGE",
        "ST",
		"COMPLETED",
        "PRI",
        "SIZE",
        "CMD"
    );
}

//------------------------------------------------------------------------

static void
shorten (char *buff, int len)
{
    if ((unsigned int)strlen (buff) > (unsigned int)len) buff[len] = '\0';
}

//------------------------------------------------------------------------

/*
  Print a line of data for the "short" display of a PROC structure.  The
  "short" display is the one used by "condor_q".  N.B. the columns used
  by this routine must match those defined by the short_header routine
  defined above.
*/

static void
short_print(
        int cluster,
        int proc,
        const char *owner,
        int date,
		int CompDate,
        int time,
        int status,
        int prio,
        int image_size,
        const char *cmd
        ) {
		MyString SubmitDateStr=format_date(date);
		MyString CompDateStr=format_date(CompDate);
        printf( "%4d.%-3d %-14s %-11s %-12s %-2c %-11s %-3d %-4.1f %-18s\n",
                cluster,
                proc,
                owner,
                SubmitDateStr.Value(),
                format_time(time),
                encode_status(status),
                CompDateStr.Value(),
                prio,
                image_size/1024.0,
                cmd
        );
}

//------------------------------------------------------------------------

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/

static char* format_date( time_t date )
{
        static char     buf[ 12 ];
        struct tm       *tm;

		if (date==0) return " ??? ";

        tm = localtime( &date );
        sprintf( buf, "%2d/%-2d %02d:%02d",
                (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
        );
        return buf;
}

//------------------------------------------------------------------------

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/

static char     *
format_time( int tot_secs )
{
        int             days;
        int             hours;
        int             min;
        int             secs;
        static char     answer[25];

        days = tot_secs / DAY;
        tot_secs %= DAY;
        hours = tot_secs / HOUR;
        tot_secs %= HOUR;
        min = tot_secs / MINUTE;
        secs = tot_secs % MINUTE;

        (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
        return answer;
}

//------------------------------------------------------------------------

/*
  Encode a status from a PROC structure as a single letter suited for
  printing.
*/

static char
encode_status( int status )
{
        switch( status ) {
          case UNEXPANDED:
                return 'U';
          case IDLE:
                return 'I';
          case RUNNING:
                return 'R';
          case COMPLETED:
                return 'C';
          case REMOVED:
                return 'X';
          default:
                return ' ';
        }
}

//------------------------------------------------------------------------

static bool EvalBool(AttrList* ad, const char *constraint)
{
    ExprTree *tree;
    EvalResult result;

    if (Parse(constraint, tree) != 0) {
        // dprintf(D_ALWAYS, "can't parse constraint: %s\n", constraint);
        return false;
    }

    // Evaluate constraint with ad in the target scope so that constraints
    // have the same semantics as the collector queries.  --RR
    if (!tree->EvalTree(NULL, ad, &result)) {
        // dprintf(D_ALWAYS, "can't evaluate constraint: %s\n", constraint);
        delete tree;
        return false;
    }
    delete tree;
    if (result.type == LX_INTEGER) {
        return (bool)result.i;
    }
    // dprintf(D_ALWAYS, "contraint (%s) does not evaluate to bool\n", constraint);
    return false;
}

<|endoftext|>


<commit_before>#include "constraints.h"
#include <algorithm>
#include <boost/asio/ip/address.hpp>
using namespace std;

bool is_not_invalid_doid(const doid_t& c)
{
	return c != INVALID_DO_ID;
}
bool is_not_reserved_doid(const doid_t& c)
{
	return (c < 1) || (c > 999);
}
bool is_not_invalid_channel(const channel_t& c)
{
	return c != INVALID_CHANNEL;
}
bool is_not_reserved_channel(const channel_t& c)
{
	return (c < 1)
	    || ((c > 999) && (c < (channel_t(1) << ZONE_BITS)))
	    || (c > channel_t(999) << ZONE_BITS);
}
bool is_boolean_keyword(const string& str)
{
	string lower = str;
	transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
	return (lower == "false") || (lower == "true");
}
bool is_valid_ip_address(const string& host)
{
	using namespace boost::asio;
	using namespace boost::system;

	// Parse out port from address string
	string addr;
    int col_index = host.find_last_of(":");
    int sqr_index = host.find_last_of("]");
	if(col_index != (int)string::npos && col_index > sqr_index)
	{
		addr = host.substr(0, col_index);
	}
	else
	{
		addr = host;
	}

	error_code ec;
	ip::address::from_string(addr, ec);
	if(ec.value() != 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}
<commit_msg>changed namespacing to fix clang bug<commit_after>#include "constraints.h"
#include <algorithm>
#include <boost/asio/ip/address.hpp>
using namespace std;

bool is_not_invalid_doid(const doid_t& c)
{
	return c != INVALID_DO_ID;
}
bool is_not_reserved_doid(const doid_t& c)
{
	return (c < 1) || (c > 999);
}
bool is_not_invalid_channel(const channel_t& c)
{
	return c != INVALID_CHANNEL;
}
bool is_not_reserved_channel(const channel_t& c)
{
	return (c < 1)
	    || ((c > 999) && (c < (channel_t(1) << ZONE_BITS)))
	    || (c > channel_t(999) << ZONE_BITS);
}
bool is_boolean_keyword(const string& str)
{
	string lower = str;
	transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
	return (lower == "false") || (lower == "true");
}
bool is_valid_ip_address(const string& host)
{
	using namespace boost::asio;
	//using namespace boost::system;

	// Parse out port from address string
	string addr;
    int col_index = host.find_last_of(":");
    int sqr_index = host.find_last_of("]");
	if(col_index != (int)string::npos && col_index > sqr_index)
	{
		addr = host.substr(0, col_index);
	}
	else
	{
		addr = host;
	}

	boost::system::error_code ec;
	ip::address::from_string(addr, ec);
	if(ec.value() != 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}
<|endoftext|>


<commit_before>#pragma once

#include <type_traits>
#include <algorithm>
#include <iterator>
#include <utility>
#include <cstddef>
#include <memory>
#include <string>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "handle.hpp"
#include "util.hpp"

namespace uvw {

/**
 * @brief SendEvent event.
 *
 * It will be emitted by UDPHandle according with its functionalities.
 */
struct SendEvent: Event<SendEvent> {};

/**
 * @brief UDPDataEvent event.
 *
 * It will be emitted by UDPHandle according with its functionalities.
 */
struct UDPDataEvent: Event<UDPDataEvent> {
    explicit UDPDataEvent(Addr sender, std::unique_ptr<const char[]> data, std::size_t length, bool partial) noexcept
        : data{std::move(data)}, length{length}, sender{std::move(sender)}, partial{partial}
    {}

    std::unique_ptr<const char[]> data; /*!< A bunch of data read on the stream. */
    std::size_t length;  /*!< The amount of data read on the stream. */
    Addr sender; /*!< A valid instance of Addr. */
    bool partial; /*!< True if the message was truncated, false otherwise. */
};

namespace details {

enum class UVUdpFlags: std::underlying_type_t<uv_udp_flags> {
    IPV6ONLY = UV_UDP_IPV6ONLY,
    REUSEADDR = UV_UDP_REUSEADDR
};

enum class UVMembership: std::underlying_type_t<uv_membership> {
    LEAVE_GROUP = UV_LEAVE_GROUP,
    JOIN_GROUP = UV_JOIN_GROUP
};

class SendReq final: public Request<SendReq, uv_udp_send_t> {
public:
    using Deleter = void(*)(uv_buf_t *);

    SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<uv_buf_t[], Deleter> bufs, std::size_t nbufs)
        : Request<SendReq, uv_udp_send_t>{std::move(ca), std::move(loop)},
          bufs{std::move(bufs)},
          nbufs{nbufs}
    {}

    void send(uv_udp_t *handle, const struct sockaddr* addr) {
        invoke(&uv_udp_send, get(), handle, bufs.get(), nbufs, addr, &defaultCallback<SendEvent>);
    }

private:
    std::unique_ptr<uv_buf_t[], Deleter> bufs;
    std::size_t nbufs;
};

}

/**
 * @brief The UDPHandle handle.
 *
 * UDP handles encapsulate UDP communication for both clients and servers.

 * By default, _IPv4_ is used as a template parameter. The handle already
 * supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
 *
 * To create an `UDPHandle` through a `Loop`, arguments follow:
 *
 * * An optional integer value that indicates optional flags used to initialize
 * the socket.
 *
 * See the official
 * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex)
 * for further details.
 */
class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
    template<typename I>
    static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
        typename details::IpTraits::Type *aptr = reinterpret_cast<const typename details::IpTraits::Type *>(addr);

        UDPHandle &udp = *(static_cast<UDPHandle*>(handle->data));
        // data will be destroyed no matter of what the value of nread is
        std::unique_ptr<const char[]> data{buf->base};

        if(nread > 0) {
            // data available (can be truncated)
            udp.publish(UDPDataEvent{details::address(aptr), std::move(data), static_cast<size_t>(nread), static_cast<bool>(flags & UV_UDP_PARTIAL)});
        } else if(nread == 0 && addr == nullptr) {
            // no more data to be read, doing nothing is fine
        } else if(nread == 0 && addr != nullptr) {
            // empty udp packet
            udp.publish(UDPDataEvent{details::address(aptr), std::move(data), static_cast<size_t>(nread), false});
        } else {
            // transmission error
            udp.publish(ErrorEvent(nread));
        }
    }

public:
    using Membership = details::UVMembership;
    using Bind = details::UVUdpFlags;
    using IPv4 = uvw::IPv4;
    using IPv6 = uvw::IPv6;

    using Handle::Handle;

    explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f)
        : Handle{std::move(ca), std::move(ref)}, tag{FLAGS}, flags{f}
    {}

    /**
     * @brief Initializes the handle. The actual socket is created lazily.
     * @return True in case of success, false otherwise.
     */
    bool init() {
        return (tag == FLAGS)
                ? initialize(&uv_udp_init_ex, flags)
                : initialize(&uv_udp_init);
    }

    /**
     * @brief Opens an existing file descriptor or SOCKET as a UDP handle.
     *
     * The passed file descriptor or SOCKET is not checked for its type, but
     * it’s required that it represents a valid datagram socket.
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_open)
     * for further details.
     *
     * @param sock A valid socket handle (either a file descriptor or a SOCKET).
     */
    void open(OSSocketHandle sock) {
        invoke(&uv_udp_open, get(), sock);
    }

    /**
     * @brief Binds the UDP handle to an IP address and port.
     *
     * Available flags are:
     *
     * * `UDPHandle::Bind::IPV6ONLY`
     * * `UDPHandle::Bind::REUSEADDR`
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_flags)
     * for further details.
     *
     * @param ip The IP address to which to bind.
     * @param port The port to which to bind.
     * @param flags Optional additional flags.
     */
    template<typename I = IPv4>
    void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);
        invoke(&uv_udp_bind, get(), reinterpret_cast<const sockaddr *>(&addr), flags);
    }

    /**
     * @brief Binds the UDP handle to an IP address and port.
     *
     * Available flags are:
     *
     * * `UDPHandle::Bind::IPV6ONLY`
     * * `UDPHandle::Bind::REUSEADDR`
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_flags)
     * for further details.
     *
     * @param addr A valid instance of Addr.
     * @param flags Optional additional flags.
     */
    template<typename I = IPv4>
    void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
        bind(addr.ip, addr.port, flags);
    }

    /**
     * @brief Get the local IP and port of the UDP handle.
     * @return A valid instance of Addr, an empty one in case of errors.
     */
    template<typename I = IPv4>
    Addr sock() const noexcept {
        return details::address(&uv_udp_getsockname, get());
    }

    /**
     * @brief Sets membership for a multicast address.
     *
     * Available values for `membership` are:
     *
     * * `UDPHandle::Membership::LEAVE_GROUP`
     * * `UDPHandle::Membership::JOIN_GROUP`
     *
     * @param multicast Multicast address to set membership for.
     * @param iface Interface address.
     * @param membership Action to be performed.
     * @return True in case of success, false otherwise.
     */
    template<typename I = IPv4>
    bool multicastMembership(std::string multicast, std::string iface, Membership membership) {
        return (0 == uv_udp_set_membership(get(), multicast.data(), iface.data(), static_cast<uv_membership>(membership)));
    }

    /**
     * @brief Sets IP multicast loop flag.
     *
     * This makes multicast packets loop back to local sockets.
     *
     * @param enable True to enable multicast loop, false otherwise.
     * @return True in case of success, false otherwise.
     */
    bool multicastLoop(bool enable = true) {
        return (0 == uv_udp_set_multicast_loop(get(), enable));
    }

    /**
     * @brief Sets the multicast ttl.
     * @param val A value in the range `[1, 255]`.
     * @return True in case of success, false otherwise.
     */
    bool multicastTtl(int val) {
        return (0 == uv_udp_set_multicast_ttl(get(), val > 255 ? 255 : val));
    }

    /**
     * @brief Sets the multicast interface to send or receive data on.
     * @param iface Interface address.
     * @return True in case of success, false otherwise.
     */
    template<typename I = IPv4>
    bool multicastInterface(std::string iface) {
        return (0 == uv_udp_set_multicast_interface(get(), iface.data()));
    }

    /**
     * @brief Sets broadcast on or off.
     * @param enable True to set broadcast on, false otherwise.
     * @return True in case of success, false otherwise.
     */
    bool broadcast(bool enable = false) {
        return (0 == uv_udp_set_broadcast(get(), enable));
    }

    /**
     * @brief Sets the time to live.
     * @param val A value in the range `[1, 255]`.
     * @return True in case of success, false otherwise.
     */
    bool ttl(int val) {
        return (0 == uv_udp_set_ttl(get(), val > 255 ? 255 : val));
    }

    /**
     * @brief Sends data over the UDP socket.
     *
     * Note that if the socket has not previously been bound with `bind()`, it
     * will be bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a
     * random port number.
     *
     * The handle takes the ownership of the data and it is in charge of delete
     * them.
     *
     * A SendEvent event will be emitted when the data have been sent.

     * An ErrorEvent event will be emitted in case of errors.
     *
     * @param ip The address to which to send data.
     * @param port The port to which to send data.
     * @param data The data to be sent.
     * @param len The lenght of the submitted data.
     */
    template<typename I = IPv4>
    void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, std::size_t len) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);

        auto send = loop().resource(
                    std::unique_ptr<uv_buf_t[], details::SendReq::Deleter>{
                        new uv_buf_t[1]{ uv_buf_init(data.release(), len) },
                        [](uv_buf_t *bufs) { delete[] bufs->base; delete[] bufs; }
                    }, 1);

        auto listener = [ptr = shared_from_this()](const auto &event, details::SendReq &) {
            ptr->publish(event);
        };

        send->once<ErrorEvent>(listener);
        send->once<SendEvent>(listener);
        send->send(get(), reinterpret_cast<const sockaddr *>(&addr));
    }

    /**
     * @brief Sends data over the UDP socket.
     *
     * Note that if the socket has not previously been bound with `bind()`, it
     * will be bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a
     * random port number.
     *
     * The handle doesn't take the ownership of the data. Be sure that their
     * lifetime overcome the one of the request.
     *
     * A SendEvent event will be emitted when the data have been sent.

     * An ErrorEvent event will be emitted in case of errors.
     *
     * @param ip The address to which to send data.
     * @param port The port to which to send data.
     * @param data The data to be sent.
     * @param len The lenght of the submitted data.
     */
    template<typename I = IPv4>
    void send(std::string ip, unsigned int port, char *data, std::size_t len) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);

        auto send = loop().resource(
                    std::unique_ptr<uv_buf_t[], details::SendReq::Deleter>{
                        new uv_buf_t[1]{ uv_buf_init(data, len) },
                        [](uv_buf_t *bufs) { delete[] bufs; }
                    }, 1);

        auto listener = [ptr = shared_from_this()](const auto &event, details::SendReq &) {
            ptr->publish(event);
        };

        send->once<ErrorEvent>(listener);
        send->once<SendEvent>(listener);
        send->send(get(), reinterpret_cast<const sockaddr *>(&addr));
    }

    /**
     * @brief Sends data over the UDP socket.
     *
     * Same as `send()`, but it won’t queue a send request if it can’t be
     * completed immediately.
     *
     * @param ip The address to which to send data.
     * @param port The port to which to send data.
     * @param data The data to be sent.
     * @param len The lenght of the submitted data.
     * @return Number of bytes written.
     */
    template<typename I = IPv4>
    int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, std::size_t len) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);

        uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
        auto bw = uv_udp_try_send(get(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));

        if(bw < 0) {
            publish(ErrorEvent{bw});
            bw = 0;
        }

        return bw;
    }

    /**
     * @brief Prepares for receiving data.
     *
     * Note that if the socket has not previously been bound with `bind()`, it
     * is bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a random
     * port number.
     *
     * An UDPDataEvent event will be emitted when the handle receives data.

     * An ErrorEvent event will be emitted in case of errors.
     */
    template<typename I = IPv4>
    void recv() {
        invoke(&uv_udp_recv_start, get(), &allocCallback, &recvCallback);
    }

    /**
     * @brief Stops listening for incoming datagrams.
     */
    void stop() {
        invoke(&uv_udp_recv_stop, get());
    }

private:
    enum { DEFAULT, FLAGS } tag{DEFAULT};
    unsigned int flags{};
};

}
<commit_msg>Use std::size_t<commit_after>#pragma once

#include <type_traits>
#include <algorithm>
#include <iterator>
#include <utility>
#include <cstddef>
#include <memory>
#include <string>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "handle.hpp"
#include "util.hpp"

namespace uvw {

/**
 * @brief SendEvent event.
 *
 * It will be emitted by UDPHandle according with its functionalities.
 */
struct SendEvent: Event<SendEvent> {};

/**
 * @brief UDPDataEvent event.
 *
 * It will be emitted by UDPHandle according with its functionalities.
 */
struct UDPDataEvent: Event<UDPDataEvent> {
    explicit UDPDataEvent(Addr sender, std::unique_ptr<const char[]> data, std::size_t length, bool partial) noexcept
        : data{std::move(data)}, length{length}, sender{std::move(sender)}, partial{partial}
    {}

    std::unique_ptr<const char[]> data; /*!< A bunch of data read on the stream. */
    std::size_t length;  /*!< The amount of data read on the stream. */
    Addr sender; /*!< A valid instance of Addr. */
    bool partial; /*!< True if the message was truncated, false otherwise. */
};

namespace details {

enum class UVUdpFlags: std::underlying_type_t<uv_udp_flags> {
    IPV6ONLY = UV_UDP_IPV6ONLY,
    REUSEADDR = UV_UDP_REUSEADDR
};

enum class UVMembership: std::underlying_type_t<uv_membership> {
    LEAVE_GROUP = UV_LEAVE_GROUP,
    JOIN_GROUP = UV_JOIN_GROUP
};

class SendReq final: public Request<SendReq, uv_udp_send_t> {
public:
    using Deleter = void(*)(uv_buf_t *);

    SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<uv_buf_t[], Deleter> bufs, std::size_t nbufs)
        : Request<SendReq, uv_udp_send_t>{std::move(ca), std::move(loop)},
          bufs{std::move(bufs)},
          nbufs{nbufs}
    {}

    void send(uv_udp_t *handle, const struct sockaddr* addr) {
        invoke(&uv_udp_send, get(), handle, bufs.get(), nbufs, addr, &defaultCallback<SendEvent>);
    }

private:
    std::unique_ptr<uv_buf_t[], Deleter> bufs;
    std::size_t nbufs;
};

}

/**
 * @brief The UDPHandle handle.
 *
 * UDP handles encapsulate UDP communication for both clients and servers.

 * By default, _IPv4_ is used as a template parameter. The handle already
 * supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
 *
 * To create an `UDPHandle` through a `Loop`, arguments follow:
 *
 * * An optional integer value that indicates optional flags used to initialize
 * the socket.
 *
 * See the official
 * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex)
 * for further details.
 */
class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
    template<typename I>
    static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
        typename details::IpTraits::Type *aptr = reinterpret_cast<const typename details::IpTraits::Type *>(addr);

        UDPHandle &udp = *(static_cast<UDPHandle*>(handle->data));
        // data will be destroyed no matter of what the value of nread is
        std::unique_ptr<const char[]> data{buf->base};

        if(nread > 0) {
            // data available (can be truncated)
            udp.publish(UDPDataEvent{details::address(aptr), std::move(data), static_cast<std::size_t>(nread), static_cast<bool>(flags & UV_UDP_PARTIAL)});
        } else if(nread == 0 && addr == nullptr) {
            // no more data to be read, doing nothing is fine
        } else if(nread == 0 && addr != nullptr) {
            // empty udp packet
            udp.publish(UDPDataEvent{details::address(aptr), std::move(data), static_cast<std::size_t>(nread), false});
        } else {
            // transmission error
            udp.publish(ErrorEvent(nread));
        }
    }

public:
    using Membership = details::UVMembership;
    using Bind = details::UVUdpFlags;
    using IPv4 = uvw::IPv4;
    using IPv6 = uvw::IPv6;

    using Handle::Handle;

    explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f)
        : Handle{std::move(ca), std::move(ref)}, tag{FLAGS}, flags{f}
    {}

    /**
     * @brief Initializes the handle. The actual socket is created lazily.
     * @return True in case of success, false otherwise.
     */
    bool init() {
        return (tag == FLAGS)
                ? initialize(&uv_udp_init_ex, flags)
                : initialize(&uv_udp_init);
    }

    /**
     * @brief Opens an existing file descriptor or SOCKET as a UDP handle.
     *
     * The passed file descriptor or SOCKET is not checked for its type, but
     * it’s required that it represents a valid datagram socket.
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_open)
     * for further details.
     *
     * @param sock A valid socket handle (either a file descriptor or a SOCKET).
     */
    void open(OSSocketHandle sock) {
        invoke(&uv_udp_open, get(), sock);
    }

    /**
     * @brief Binds the UDP handle to an IP address and port.
     *
     * Available flags are:
     *
     * * `UDPHandle::Bind::IPV6ONLY`
     * * `UDPHandle::Bind::REUSEADDR`
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_flags)
     * for further details.
     *
     * @param ip The IP address to which to bind.
     * @param port The port to which to bind.
     * @param flags Optional additional flags.
     */
    template<typename I = IPv4>
    void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);
        invoke(&uv_udp_bind, get(), reinterpret_cast<const sockaddr *>(&addr), flags);
    }

    /**
     * @brief Binds the UDP handle to an IP address and port.
     *
     * Available flags are:
     *
     * * `UDPHandle::Bind::IPV6ONLY`
     * * `UDPHandle::Bind::REUSEADDR`
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_flags)
     * for further details.
     *
     * @param addr A valid instance of Addr.
     * @param flags Optional additional flags.
     */
    template<typename I = IPv4>
    void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
        bind(addr.ip, addr.port, flags);
    }

    /**
     * @brief Get the local IP and port of the UDP handle.
     * @return A valid instance of Addr, an empty one in case of errors.
     */
    template<typename I = IPv4>
    Addr sock() const noexcept {
        return details::address(&uv_udp_getsockname, get());
    }

    /**
     * @brief Sets membership for a multicast address.
     *
     * Available values for `membership` are:
     *
     * * `UDPHandle::Membership::LEAVE_GROUP`
     * * `UDPHandle::Membership::JOIN_GROUP`
     *
     * @param multicast Multicast address to set membership for.
     * @param iface Interface address.
     * @param membership Action to be performed.
     * @return True in case of success, false otherwise.
     */
    template<typename I = IPv4>
    bool multicastMembership(std::string multicast, std::string iface, Membership membership) {
        return (0 == uv_udp_set_membership(get(), multicast.data(), iface.data(), static_cast<uv_membership>(membership)));
    }

    /**
     * @brief Sets IP multicast loop flag.
     *
     * This makes multicast packets loop back to local sockets.
     *
     * @param enable True to enable multicast loop, false otherwise.
     * @return True in case of success, false otherwise.
     */
    bool multicastLoop(bool enable = true) {
        return (0 == uv_udp_set_multicast_loop(get(), enable));
    }

    /**
     * @brief Sets the multicast ttl.
     * @param val A value in the range `[1, 255]`.
     * @return True in case of success, false otherwise.
     */
    bool multicastTtl(int val) {
        return (0 == uv_udp_set_multicast_ttl(get(), val > 255 ? 255 : val));
    }

    /**
     * @brief Sets the multicast interface to send or receive data on.
     * @param iface Interface address.
     * @return True in case of success, false otherwise.
     */
    template<typename I = IPv4>
    bool multicastInterface(std::string iface) {
        return (0 == uv_udp_set_multicast_interface(get(), iface.data()));
    }

    /**
     * @brief Sets broadcast on or off.
     * @param enable True to set broadcast on, false otherwise.
     * @return True in case of success, false otherwise.
     */
    bool broadcast(bool enable = false) {
        return (0 == uv_udp_set_broadcast(get(), enable));
    }

    /**
     * @brief Sets the time to live.
     * @param val A value in the range `[1, 255]`.
     * @return True in case of success, false otherwise.
     */
    bool ttl(int val) {
        return (0 == uv_udp_set_ttl(get(), val > 255 ? 255 : val));
    }

    /**
     * @brief Sends data over the UDP socket.
     *
     * Note that if the socket has not previously been bound with `bind()`, it
     * will be bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a
     * random port number.
     *
     * The handle takes the ownership of the data and it is in charge of delete
     * them.
     *
     * A SendEvent event will be emitted when the data have been sent.

     * An ErrorEvent event will be emitted in case of errors.
     *
     * @param ip The address to which to send data.
     * @param port The port to which to send data.
     * @param data The data to be sent.
     * @param len The lenght of the submitted data.
     */
    template<typename I = IPv4>
    void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, std::size_t len) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);

        auto send = loop().resource(
                    std::unique_ptr<uv_buf_t[], details::SendReq::Deleter>{
                        new uv_buf_t[1]{ uv_buf_init(data.release(), len) },
                        [](uv_buf_t *bufs) { delete[] bufs->base; delete[] bufs; }
                    }, 1);

        auto listener = [ptr = shared_from_this()](const auto &event, details::SendReq &) {
            ptr->publish(event);
        };

        send->once<ErrorEvent>(listener);
        send->once<SendEvent>(listener);
        send->send(get(), reinterpret_cast<const sockaddr *>(&addr));
    }

    /**
     * @brief Sends data over the UDP socket.
     *
     * Note that if the socket has not previously been bound with `bind()`, it
     * will be bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a
     * random port number.
     *
     * The handle doesn't take the ownership of the data. Be sure that their
     * lifetime overcome the one of the request.
     *
     * A SendEvent event will be emitted when the data have been sent.

     * An ErrorEvent event will be emitted in case of errors.
     *
     * @param ip The address to which to send data.
     * @param port The port to which to send data.
     * @param data The data to be sent.
     * @param len The lenght of the submitted data.
     */
    template<typename I = IPv4>
    void send(std::string ip, unsigned int port, char *data, std::size_t len) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);

        auto send = loop().resource(
                    std::unique_ptr<uv_buf_t[], details::SendReq::Deleter>{
                        new uv_buf_t[1]{ uv_buf_init(data, len) },
                        [](uv_buf_t *bufs) { delete[] bufs; }
                    }, 1);

        auto listener = [ptr = shared_from_this()](const auto &event, details::SendReq &) {
            ptr->publish(event);
        };

        send->once<ErrorEvent>(listener);
        send->once<SendEvent>(listener);
        send->send(get(), reinterpret_cast<const sockaddr *>(&addr));
    }

    /**
     * @brief Sends data over the UDP socket.
     *
     * Same as `send()`, but it won’t queue a send request if it can’t be
     * completed immediately.
     *
     * @param ip The address to which to send data.
     * @param port The port to which to send data.
     * @param data The data to be sent.
     * @param len The lenght of the submitted data.
     * @return Number of bytes written.
     */
    template<typename I = IPv4>
    int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, std::size_t len) {
        typename details::IpTraits::Type addr;
        details::IpTraits::addrFunc(ip.data(), port, &addr);

        uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
        auto bw = uv_udp_try_send(get(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));

        if(bw < 0) {
            publish(ErrorEvent{bw});
            bw = 0;
        }

        return bw;
    }

    /**
     * @brief Prepares for receiving data.
     *
     * Note that if the socket has not previously been bound with `bind()`, it
     * is bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a random
     * port number.
     *
     * An UDPDataEvent event will be emitted when the handle receives data.

     * An ErrorEvent event will be emitted in case of errors.
     */
    template<typename I = IPv4>
    void recv() {
        invoke(&uv_udp_recv_start, get(), &allocCallback, &recvCallback);
    }

    /**
     * @brief Stops listening for incoming datagrams.
     */
    void stop() {
        invoke(&uv_udp_recv_stop, get());
    }

private:
    enum { DEFAULT, FLAGS } tag{DEFAULT};
    unsigned int flags{};
};

}
<|endoftext|>