<commit_before>/*************************************************************************
 *
 *  $RCSfile: xmltexte.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: mib $ $Date: 2001-02-09 13:15:58 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PRECOMPILED
#include "filt_pch.hxx"
#endif

#pragma hdrstop

#ifndef _IPOBJ_HXX
#include <so3/ipobj.hxx>
#endif

#ifndef _XMLOFF_FAMILIES_HXX_
#include <xmloff/families.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef _XMLOFF_XMLKYWD_HXX
#include <xmloff/xmlkywd.hxx>
#endif

#ifndef _DOC_HXX //autogen wg. SwDoc
#include <doc.hxx>
#endif
#ifndef _NDOLE_HXX
#include <ndole.hxx>
#endif
#ifndef _UNOSTYLE_HXX
#include <unostyle.hxx>
#endif
#ifndef _UNOFRAME_HXX
#include <unoframe.hxx>
#endif
#ifndef _NDGRF_HXX
#include <ndgrf.hxx>
#endif

#ifndef _XMLEXP_HXX
#include "xmlexp.hxx"
#endif
#ifndef _XMLTEXTE_HXX
#include "xmltexte.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;

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

SwNoTxtNode *SwXMLTextParagraphExport::GetNoTxtNode(
    const Reference < XPropertySet >& rPropSet ) const
{
    Reference<XUnoTunnel> xCrsrTunnel( rPropSet, UNO_QUERY );
    ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for embedded" );
    SwXFrame *pFrame =
                (SwXFrame *)xCrsrTunnel->getSomething(
                                    SwXFrame::getUnoTunnelId() );
    ASSERT( pFrame, "SwXFrame missing" );
    SwFrmFmt *pFrmFmt = pFrame->GetFrmFmt();
    const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
    const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx();
    return  pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTxtNode();
}

void SwXMLTextParagraphExport::exportStyleContent(
        const Reference< XStyle > & rStyle )
{

    const SwXStyle* pStyle = 0;
    Reference<XUnoTunnel> xStyleTunnel( rStyle, UNO_QUERY);
    if( xStyleTunnel.is() )
    {
        pStyle = (SwXStyle*)xStyleTunnel->getSomething(
                                            SwXStyle::getUnoTunnelId() );
    }
    if( pStyle && SFX_STYLE_FAMILY_PARA == pStyle->GetFamily() )
    {
        const SwDoc *pDoc = pStyle->GetDoc();
        const SwTxtFmtColl *pColl =
            pDoc->FindTxtFmtCollByName( SwXStyleFamilies::GetUIName( pStyle->GetStyleName(), SFX_STYLE_FAMILY_PARA ) );
        ASSERT( pColl, "There is the text collection?" );
        if( pColl && RES_CONDTXTFMTCOLL == pColl->Which() )
        {
            const SwFmtCollConditions& rConditions =
                ((const SwConditionTxtFmtColl *)pColl)->GetCondColls();
            for( sal_uInt16 i=0; i < rConditions.Count(); i++ )
            {
                const SwCollCondition& rCond = *rConditions[i];

                const sal_Char *pFunc = 0;
                OUStringBuffer sBuffer( 20 );
                switch( rCond.GetCondition() )
                {
                case PARA_IN_LIST:
                    pFunc = sXML_list_level;
                    sBuffer.append( (sal_Int32)(rCond.GetSubCondition()+1) );
                    break;
                case PARA_IN_OUTLINE:
                    pFunc = sXML_outline_level;
                    sBuffer.append( (sal_Int32)(rCond.GetSubCondition()+1) );
                    break;
                case PARA_IN_FRAME:
                    pFunc = sXML_text_box;
                    break;
                case PARA_IN_TABLEHEAD:
                    pFunc = sXML_table_header;
                    break;
                case PARA_IN_TABLEBODY:
                    pFunc = sXML_table;
                    break;
                case PARA_IN_SECTION:
                    pFunc = sXML_section;
                    break;
                case PARA_IN_FOOTENOTE:
                    pFunc = sXML_footnote;
                    break;
                case PARA_IN_FOOTER:
                    pFunc = sXML_footer;
                    break;
                case PARA_IN_HEADER:
                    pFunc = sXML_header;
                    break;
                case PARA_IN_ENDNOTE:
                    pFunc = sXML_endnote;
                    break;
                }
                OUString sVal( sBuffer.makeStringAndClear() );

                DBG_ASSERT( pFunc, "SwXMLExport::ExportFmt: unknon condition" );
                if( pFunc )
                {
                    sBuffer.appendAscii( pFunc );
                    sBuffer.append( (sal_Unicode)'(' );
                    sBuffer.append( (sal_Unicode)')' );
                    if( sVal.getLength() )
                    {
                        sBuffer.append( (sal_Unicode)'=' );
                        sBuffer.append( sVal );
                    }

                    GetExport().AddAttribute( XML_NAMESPACE_STYLE,
                                sXML_condition,
                                sBuffer.makeStringAndClear() );
                    const String& rName =
                        SwXStyleFamilies::GetProgrammaticName(
                                    rCond.GetTxtFmtColl()->GetName(),
                                    SFX_STYLE_FAMILY_PARA );
                    GetExport().AddAttribute( XML_NAMESPACE_STYLE,
                                sXML_apply_style_name, rName );
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
                                              sXML_map, sal_True, sal_True );
                }
            }
        }
    }
}

void SwXMLTextParagraphExport::exportTextAutoStyles()
{
    XMLTextParagraphExport::exportTextAutoStyles();
    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_SD_GRAPHICS_ID,
                                   GetExport().GetDocHandler(),
                                   GetExport().GetMM100UnitConverter(),
                                   GetExport().GetNamespaceMap() );
}

SwXMLTextParagraphExport::SwXMLTextParagraphExport(
        SwXMLExport& rExp,
         SvXMLAutoStylePoolP& rAutoStylePool ) :
    XMLTextParagraphExport( rExp, rAutoStylePool ),
    sTextTable( RTL_CONSTASCII_USTRINGPARAM( "TextTable" ) ),
    sEmbeddedObjectProtocol( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.EmbeddedObject:" ) )
{
}

SwXMLTextParagraphExport::~SwXMLTextParagraphExport()
{
}

void SwXMLTextParagraphExport::getTextEmbeddedObjectProperties(
    const Reference < XPropertySet >& rPropSet,
    OUString& rURL,
    OUString& rClassId  ) const
{
    SwOLENode *pOLENd = GetNoTxtNode( rPropSet )->GetOLENode();
    SwOLEObj& rOLEObj = pOLENd->GetOLEObj();

    rURL = sEmbeddedObjectProtocol;
    rURL += rOLEObj.GetName();
    SvInfoObject *pInfo =
        pOLENd->GetDoc()->GetPersist()->Find( rOLEObj.GetName() );
    if( pInfo )
    {
        SvGlobalName aClassName( pInfo->GetClassName() );
        if( !SvFactory::IsIntern( aClassName ) )
            rClassId = aClassName.GetHexName();
    }
}
<commit_msg>2 parameters for IsIntern<commit_after>/*************************************************************************
 *
 *  $RCSfile: xmltexte.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2001-02-13 16:41:04 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PRECOMPILED
#include "filt_pch.hxx"
#endif

#pragma hdrstop

#ifndef _IPOBJ_HXX
#include <so3/ipobj.hxx>
#endif

#ifndef _XMLOFF_FAMILIES_HXX_
#include <xmloff/families.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef _XMLOFF_XMLKYWD_HXX
#include <xmloff/xmlkywd.hxx>
#endif

#ifndef _DOC_HXX //autogen wg. SwDoc
#include <doc.hxx>
#endif
#ifndef _NDOLE_HXX
#include <ndole.hxx>
#endif
#ifndef _UNOSTYLE_HXX
#include <unostyle.hxx>
#endif
#ifndef _UNOFRAME_HXX
#include <unoframe.hxx>
#endif
#ifndef _NDGRF_HXX
#include <ndgrf.hxx>
#endif

#ifndef _XMLEXP_HXX
#include "xmlexp.hxx"
#endif
#ifndef _XMLTEXTE_HXX
#include "xmltexte.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;

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

SwNoTxtNode *SwXMLTextParagraphExport::GetNoTxtNode(
    const Reference < XPropertySet >& rPropSet ) const
{
    Reference<XUnoTunnel> xCrsrTunnel( rPropSet, UNO_QUERY );
    ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for embedded" );
    SwXFrame *pFrame =
                (SwXFrame *)xCrsrTunnel->getSomething(
                                    SwXFrame::getUnoTunnelId() );
    ASSERT( pFrame, "SwXFrame missing" );
    SwFrmFmt *pFrmFmt = pFrame->GetFrmFmt();
    const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
    const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx();
    return  pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTxtNode();
}

void SwXMLTextParagraphExport::exportStyleContent(
        const Reference< XStyle > & rStyle )
{

    const SwXStyle* pStyle = 0;
    Reference<XUnoTunnel> xStyleTunnel( rStyle, UNO_QUERY);
    if( xStyleTunnel.is() )
    {
        pStyle = (SwXStyle*)xStyleTunnel->getSomething(
                                            SwXStyle::getUnoTunnelId() );
    }
    if( pStyle && SFX_STYLE_FAMILY_PARA == pStyle->GetFamily() )
    {
        const SwDoc *pDoc = pStyle->GetDoc();
        const SwTxtFmtColl *pColl =
            pDoc->FindTxtFmtCollByName( SwXStyleFamilies::GetUIName( pStyle->GetStyleName(), SFX_STYLE_FAMILY_PARA ) );
        ASSERT( pColl, "There is the text collection?" );
        if( pColl && RES_CONDTXTFMTCOLL == pColl->Which() )
        {
            const SwFmtCollConditions& rConditions =
                ((const SwConditionTxtFmtColl *)pColl)->GetCondColls();
            for( sal_uInt16 i=0; i < rConditions.Count(); i++ )
            {
                const SwCollCondition& rCond = *rConditions[i];

                const sal_Char *pFunc = 0;
                OUStringBuffer sBuffer( 20 );
                switch( rCond.GetCondition() )
                {
                case PARA_IN_LIST:
                    pFunc = sXML_list_level;
                    sBuffer.append( (sal_Int32)(rCond.GetSubCondition()+1) );
                    break;
                case PARA_IN_OUTLINE:
                    pFunc = sXML_outline_level;
                    sBuffer.append( (sal_Int32)(rCond.GetSubCondition()+1) );
                    break;
                case PARA_IN_FRAME:
                    pFunc = sXML_text_box;
                    break;
                case PARA_IN_TABLEHEAD:
                    pFunc = sXML_table_header;
                    break;
                case PARA_IN_TABLEBODY:
                    pFunc = sXML_table;
                    break;
                case PARA_IN_SECTION:
                    pFunc = sXML_section;
                    break;
                case PARA_IN_FOOTENOTE:
                    pFunc = sXML_footnote;
                    break;
                case PARA_IN_FOOTER:
                    pFunc = sXML_footer;
                    break;
                case PARA_IN_HEADER:
                    pFunc = sXML_header;
                    break;
                case PARA_IN_ENDNOTE:
                    pFunc = sXML_endnote;
                    break;
                }
                OUString sVal( sBuffer.makeStringAndClear() );

                DBG_ASSERT( pFunc, "SwXMLExport::ExportFmt: unknon condition" );
                if( pFunc )
                {
                    sBuffer.appendAscii( pFunc );
                    sBuffer.append( (sal_Unicode)'(' );
                    sBuffer.append( (sal_Unicode)')' );
                    if( sVal.getLength() )
                    {
                        sBuffer.append( (sal_Unicode)'=' );
                        sBuffer.append( sVal );
                    }

                    GetExport().AddAttribute( XML_NAMESPACE_STYLE,
                                sXML_condition,
                                sBuffer.makeStringAndClear() );
                    const String& rName =
                        SwXStyleFamilies::GetProgrammaticName(
                                    rCond.GetTxtFmtColl()->GetName(),
                                    SFX_STYLE_FAMILY_PARA );
                    GetExport().AddAttribute( XML_NAMESPACE_STYLE,
                                sXML_apply_style_name, rName );
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
                                              sXML_map, sal_True, sal_True );
                }
            }
        }
    }
}

void SwXMLTextParagraphExport::exportTextAutoStyles()
{
    XMLTextParagraphExport::exportTextAutoStyles();
    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_SD_GRAPHICS_ID,
                                   GetExport().GetDocHandler(),
                                   GetExport().GetMM100UnitConverter(),
                                   GetExport().GetNamespaceMap() );
}

SwXMLTextParagraphExport::SwXMLTextParagraphExport(
        SwXMLExport& rExp,
         SvXMLAutoStylePoolP& rAutoStylePool ) :
    XMLTextParagraphExport( rExp, rAutoStylePool ),
    sTextTable( RTL_CONSTASCII_USTRINGPARAM( "TextTable" ) ),
    sEmbeddedObjectProtocol( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.EmbeddedObject:" ) )
{
}

SwXMLTextParagraphExport::~SwXMLTextParagraphExport()
{
}

void SwXMLTextParagraphExport::getTextEmbeddedObjectProperties(
    const Reference < XPropertySet >& rPropSet,
    OUString& rURL,
    OUString& rClassId  ) const
{
    SwOLENode *pOLENd = GetNoTxtNode( rPropSet )->GetOLENode();
    SwOLEObj& rOLEObj = pOLENd->GetOLEObj();

    rURL = sEmbeddedObjectProtocol;
    rURL += rOLEObj.GetName();
    SvInfoObject *pInfo =
        pOLENd->GetDoc()->GetPersist()->Find( rOLEObj.GetName() );
    if( pInfo )
    {
        SvGlobalName aClassName( pInfo->GetClassName() );
        if( !SvFactory::IsIntern( aClassName, 0 ) )
            rClassId = aClassName.GetHexName();
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Michael W Powell <mwpowellhtx@gmail.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include <catch.hpp>
#include <nngcpp.h>

#include <memory>
#include <thread>

namespace constants {

    const std::string nng_addr = "inproc://nng";
    const std::string test_addr = "inproc://test";

    const std::string hello = "hello";
    const std::string again = "again";

    const nng::messaging::message_base::buffer_vector_type hello_buf = { 'h','e','l','l','o' };
    const nng::messaging::message_base::buffer_vector_type again_buf = { 'a','g','a','i','n' };
}

/* This is interesting in the event we actually need/want to separate the code under
test with a returning error number. */
#define NNG_TESTS_INIT() int errnum

#define NNG_TESTS_REQUIRE_ERR_EQ(code, expected) errnum = code; \
    REQUIRE(errnum == expected)

/* While I despise macro code expansion, this is "better" for us because in the event
of a legit failure, we see the actual line IN-SITU where the test case ACTUALLY IS. */
#define NNG_TESTS_APPEND_STR(m, s) \
    REQUIRE(::nng_msg_append(m, s, std::strlen(s)) == 0); \
    REQUIRE(::nng_msg_len(m) == std::strlen(s)); \
    REQUIRE(std::memcmp(::nng_msg_body(m), s, std::strlen(s)) == 0)

#define NNG_TESTS_CHECK_STR(m, s) \
    REQUIRE(m != nullptr); \
    REQUIRE(::nng_msg_len(m) == std::strlen(s)); \
    REQUIRE(std::memcmp(::nng_msg_body(m), s, std::strlen(s)) == 0)

#define NNGCPP_TESTS_ALLOCATE_MSG_SZ(m, sz) \
    REQUIRE(m.has_message() == false); \
    REQUIRE(m.get_msgp() == nullptr); \
    \
    REQUIRE_NOTHROW(m.allocate(sz)); \
    REQUIRE(m.has_message() == true); \
    REQUIRE(m.get_msgp() != nullptr); \
    \
    REQUIRE(m.header() != nullptr); \
    REQUIRE(m.header()->has_message()); \
    REQUIRE(m.header()->get_msgp() == m.get_msgp()); \
    \
    REQUIRE(m.body() != nullptr); \
    REQUIRE(m.body()->has_message()); \
    REQUIRE(m.body()->get_msgp() == m.get_msgp());

#define NNGCPP_TESTS_ALLOCATE_MSG(m) NNGCPP_TESTS_ALLOCATE_MSG_SZ(m, 0)

struct c_style_fixture {

    ::nng_socket push;
    ::nng_socket pull;

    c_style_fixture() : push(0), pull(0) {

        REQUIRE(::nng_push_open(&push) == 0);
        REQUIRE(::nng_pull_open(&pull) == 0);

        REQUIRE(push > 0);
        REQUIRE(pull > 0);
    }

    virtual ~c_style_fixture() {
        ::nng_close(push);
        ::nng_close(pull);
        ::nng_fini();
    }
};

namespace nng {
    namespace messaging {

        struct message_pipe_fixture : public message_pipe {

            message_pipe_fixture(const message_base* const mbp) : message_pipe(mbp) {
            }

            ::nng_pipe get_pid() const {
                return pid;
            }
        };

        struct binary_message_fixture : public binary_message {

            binary_message_fixture() : binary_message() {
            }

            binary_message_fixture(::nng_msg* msgp) : binary_message(msgp) {
            }

            virtual void free() override {
                binary_message::free();
            }
        };

        template<>
        struct message_conversion_proxy<buffer_vector_type, binary_message_fixture> {

            virtual buffer_vector_type get(const binary_message_fixture& rhs) {
                return const_cast<binary_message_fixture&>(rhs).body()->get();
            }

            virtual void append(binary_message_fixture& lhs, const buffer_vector_type& rhs) {
                auto buf_ = gymanstic_convert<buffer_vector_type, buffer_vector_type, buffer_vector_type::value_type>(rhs);
                lhs.body()->append(buf_);
            }
        };

        template<>
        struct message_conversion_proxy<std::string, binary_message_fixture> {

            virtual std::string get(const binary_message_fixture& rhs) {
                const auto lhs_ = const_cast<binary_message_fixture&>(rhs).body()->get();
                return gymanstic_convert<buffer_vector_type, std::string, std::string::value_type>(lhs_);
            }

            virtual void append(binary_message_fixture lhs, const std::string& rhs) {
                auto buf_ = gymanstic_convert<std::string, buffer_vector_type, buffer_vector_type::value_type>(rhs);
                lhs.body()->append(buf_);
            }
        };

        buffer_vector_type& operator<<(buffer_vector_type& lhs, binary_message_fixture& rhs) {
            auto ops = message_conversion_proxy<buffer_vector_type, binary_message_fixture>();
            lhs = ops.get(rhs);
            return lhs;
        }

        std::string& operator<<(std::string& lhs, const binary_message_fixture& rhs) {
            auto ops = message_conversion_proxy<std::string, binary_message_fixture>();
            lhs = ops.get(rhs);
            return lhs;
        }

        binary_message_fixture& operator<<(binary_message_fixture& lhs, buffer_vector_type& rhs) {
            auto ops = message_conversion_proxy<buffer_vector_type, binary_message_fixture>();
            ops.append(lhs, rhs);
            return lhs;
        }

        binary_message_fixture& operator<<(binary_message_fixture& lhs, const std::string& rhs) {
            auto ops = message_conversion_proxy<std::string, binary_message_fixture>();
            ops.append(lhs, rhs);
            return lhs;
        }
    }
}

#define NNG_TESTS_VERIFY_TEST_CASE_DATA() \
    REQUIRE_THAT(constants::hello, Catch::Matchers::Equals("hello")); \
    REQUIRE_THAT(constants::again, Catch::Matchers::Equals("again")); \
    REQUIRE_THAT(constants::nng_addr, Catch::Matchers::Equals("inproc://nng")); \
    REQUIRE_THAT(constants::test_addr, Catch::Matchers::Equals("inproc://test"))

TEST_CASE("Catch translation of NNG C reconnect unit tests", "[nng][c][reconnect]") {

    using namespace std;
    using namespace std::chrono;
    using namespace constants;

    SECTION("Verify that we have the required data") {
        NNG_TESTS_VERIFY_TEST_CASE_DATA();
    }

    SECTION("We can create a pipeline") {

        /* When the scope rolls back, we want to destroy the fixture, which
        effectively closes the sockets, and finishes the NNG session. */
        c_style_fixture $;

        auto& pull = $.pull;
        auto& push = $.push;

        REQUIRE(::nng_setopt_usec(pull, NNG_OPT_RECONNMINT, 10000) == 0);
        REQUIRE(::nng_setopt_usec(pull, NNG_OPT_RECONNMAXT, 10000) == 0);

        SECTION("Dialing before listening works") {

            // With Reconnect Times configured, Should re-dial until Listener comes online.
            REQUIRE(::nng_dial(push, test_addr.c_str(), nullptr, NNG_FLAG_NONBLOCK) == 0);
            this_thread::sleep_for(100ms);
            REQUIRE(::nng_listen(pull, test_addr.c_str(), nullptr, 0) == 0);

            SECTION("We can send a frame") {

                ::nng_msg* msgp = nullptr;

                this_thread::sleep_for(100ms);

                REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                REQUIRE(msgp != nullptr);
                NNG_TESTS_APPEND_STR(msgp, hello.c_str());
                REQUIRE(::nng_sendmsg(push, msgp, 0) == 0);

                /* Nullifying the pointer is NOT a mistake. It is part of the zero-copy message ownership
                semantics. Once the message is "sent", the framework effectively assumes ownership. */
                msgp = nullptr;

                // Which Receiving a Message should allocate when we did not provide one.
                REQUIRE(::nng_recvmsg(pull, &msgp, 0) == 0);
                NNG_TESTS_CHECK_STR(msgp, hello.c_str());

                ::nng_msg_free(msgp);
            }
        }

        SECTION("Reconnection works") {

            ::nng_listener l;

            REQUIRE(::nng_dial(push, test_addr.c_str(), nullptr, NNG_FLAG_NONBLOCK) == 0);
            REQUIRE(::nng_listen(pull, test_addr.c_str(), &l, 0) == 0);
            this_thread::sleep_for(100ms);
            REQUIRE(::nng_listener_close(l) == 0);
            REQUIRE(::nng_listen(pull, test_addr.c_str(), nullptr, 0) == 0);

            SECTION("They still exchange frames") {
                ::nng_msg *msgp;
                ::nng_pipe p1;

                this_thread::sleep_for(100ms);
                REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                NNG_TESTS_APPEND_STR(msgp, hello.c_str());
                REQUIRE(::nng_sendmsg(push, msgp, 0) == 0);
                // Ditto message passing ownership semantics.
                msgp = nullptr;
                REQUIRE(::nng_recvmsg(pull, &msgp, 0) == 0);
                REQUIRE(msgp != nullptr);
                NNG_TESTS_CHECK_STR(msgp, hello.c_str());
                REQUIRE((p1 = ::nng_msg_get_pipe(msgp)) > 0);
                ::nng_msg_free(msgp);

                SECTION("Even after pipe close") {
                    ::nng_pipe p2;

                    REQUIRE(::nng_pipe_close(p1) == 0);
                    this_thread::sleep_for(100ms);
                    REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                    NNG_TESTS_APPEND_STR(msgp, again.c_str());
                    REQUIRE(::nng_sendmsg(push, msgp, 0) == 0);
                    msgp = nullptr;
                    REQUIRE(::nng_recvmsg(pull, &msgp, 0) == 0);
                    REQUIRE(msgp != nullptr);
                    NNG_TESTS_CHECK_STR(msgp, again.c_str());
                    REQUIRE((p2 = nng_msg_get_pipe(msgp)) > 0);
                    ::nng_msg_free(msgp);
                    REQUIRE(p2 != p1);
                }
            }
        }
    }
}

TEST_CASE("NNG C++ wrapper reconnect works", "[reconnect][cxx][wrapper]") {

    using namespace std;
    using namespace std::chrono;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using _opt_ = option_names;

    // TODO: not sure if I like having "session" part of these unit tests, per se. I almost want session to be the subject of its own set of unit tests (it should be, anyway).
    // Which "at-exit" destructor handles cleaning up the NNG resources: i.e. ::nng_fini.
    session _session_;

    SECTION("We can create a pipeline") {

        std::shared_ptr<latest_push_socket> push;
        std::shared_ptr<latest_pull_socket> pull;

        REQUIRE_NOTHROW(push = _session_.create_push_socket());
        REQUIRE_NOTHROW(pull = _session_.create_pull_socket());

        const duration<uint64_t, milli> reconnect_time = 10ms;

        // TODO: TBD: count() might be the way to go here, but I cannot say for sure.
        // http://en.cppreference.com/w/cpp/chrono/duration
        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::min_reconnect_time_usec, reconnect_time.count()));
        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::max_reconnect_time_usec, reconnect_time.count()));

        SECTION("Dialing before listening works") {

            REQUIRE_NOTHROW(push->dial(test_addr, flag_nonblock));
            this_thread::sleep_for(100ms);
            REQUIRE_NOTHROW(pull->listen(test_addr));

            /* 'Frame' in this case is loosely speaking. We do not care about exposing the NNG msg structure,
            per se. Rather, we should simply be able to "frame" buffers or strings, accordingly. */
            SECTION("We can send a frame") {

                binary_message_fixture bm;
                this_thread::sleep_for(100ms);
                NNGCPP_TESTS_ALLOCATE_MSG(bm);
                // And with a little C++ operator overloading help:
                REQUIRE_NOTHROW(bm << hello);
                REQUIRE_NOTHROW(push->send(&bm));
                /* Ditto message passing semantics. The Send() operation effectively
                nullifies the internal message. */
                REQUIRE(bm.has_message() == false);

                // TODO: TBD: message ownership semantics really deserves a unit test all its own...
                REQUIRE_NOTHROW(pull->try_receive(&bm));
                REQUIRE(bm.has_message() == true);
                // Just verify that the message matches the buffer.
                REQUIRE_THAT(bm.body()->get(), Equals(hello_buf));
            }
        }

        SECTION("Reconnection works") {

            REQUIRE_NOTHROW(push->dial(test_addr, flag_nonblock));

            {
                // We do not need to see the Listener beyond this block.
                auto lp = std::make_unique<listener>();
                REQUIRE_NOTHROW(pull->listen(test_addr, lp.get()));
                this_thread::sleep_for(100ms);
                // No need to burden "session" with this one, either.
                REQUIRE_NOTHROW(lp.reset());
            }

            // Then re-listen to the address.
            REQUIRE_NOTHROW(pull->listen(test_addr));

            // TODO: TBD: we may provide comprehension of nng_pipe from a nngcpp POV, but I'm not sure the complexity of nng_msg how that is different from a simple send/receive?
            SECTION("They still exchange frames") {

                binary_message_fixture bm;

                this_thread::sleep_for(100ms);
                NNGCPP_TESTS_ALLOCATE_MSG(bm);
                REQUIRE_NOTHROW(bm << hello);
                REQUIRE_NOTHROW(push->send(&bm));
                REQUIRE(bm.has_message() == false);

                // See notes above. Sending transfers ownership of the internal message to NNG.
                REQUIRE_NOTHROW(pull->try_receive(&bm));
                REQUIRE(bm.has_message() == true);
                // Just verify that the message matches the buffer.
                REQUIRE_THAT(bm.body()->get(), Equals(hello_buf));

                // TODO: TBD: this one deserves its own unit test as well so that we are not cluttering the integration tests
                message_pipe_fixture mp1(&bm);
                REQUIRE(mp1.is_valid() == true);
                // TODO: TBD: deserves its own unit testing...
                REQUIRE(mp1.get_pid() > 0);
                // We would not normally want to free under any circumstances, except here it is useful to fixture it.
                REQUIRE_NOTHROW(bm.free());
                REQUIRE(bm.has_message() == false);

                SECTION("Even after pipe close") {

                    // Get the fixtured PID for test purposes prior to closing.
                    auto mp1_pid = mp1.get_pid();
                    REQUIRE_NOTHROW(mp1.close());
                    REQUIRE(mp1.is_valid() == false);

                    this_thread::sleep_for(100ms);
                    NNGCPP_TESTS_ALLOCATE_MSG(bm);
                    REQUIRE_NOTHROW(bm << again);
                    // TODO: TBD: send/no-message -> receive/message is a pattern that deserves its own focused unit test...
                    REQUIRE_NOTHROW(push->send(&bm));
                    REQUIRE(bm.has_message() == false);

                    REQUIRE_NOTHROW(pull->try_receive(&bm));
                    REQUIRE(bm.has_message() == true);
                    // Just verify that the message matches the buffer.
                    REQUIRE_THAT(bm.body()->get(), Equals(again_buf));

                    message_pipe_fixture mp2(&bm);
                    REQUIRE(mp2.is_valid() == true);
                    REQUIRE_NOTHROW(bm.free());
                    REQUIRE(mp2.get_pid() != mp1_pid);
                }
            }
        }
    }
}
<commit_msg>did some re-factoring and refitting of the reconnect unit tests no need to expose free especially at the cost of introducing problematic gymnastics besides resetting the pointer is effectively the same if not stronger than simply calling free<commit_after>//
// Copyright (c) 2017 Michael W Powell <mwpowellhtx@gmail.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include <catch.hpp>
#include <nngcpp.h>

#include <memory>
#include <thread>

namespace constants {

    const std::string nng_addr = "inproc://nng";
    const std::string test_addr = "inproc://test";

    const std::string hello = "hello";
    const std::string again = "again";

    const nng::messaging::message_base::buffer_vector_type hello_buf = { 'h','e','l','l','o' };
    const nng::messaging::message_base::buffer_vector_type again_buf = { 'a','g','a','i','n' };
}

/* This is interesting in the event we actually need/want to separate the code under
test with a returning error number. */
#define NNG_TESTS_INIT() int errnum

#define NNG_TESTS_REQUIRE_ERR_EQ(code, expected) errnum = code; \
    REQUIRE(errnum == expected)

/* While I despise macro code expansion, this is "better" for us because in the event
of a legit failure, we see the actual line IN-SITU where the test case ACTUALLY IS. */
#define NNG_TESTS_APPEND_STR(m, s) \
    REQUIRE(::nng_msg_append(m, s, std::strlen(s)) == 0); \
    REQUIRE(::nng_msg_len(m) == std::strlen(s)); \
    REQUIRE(std::memcmp(::nng_msg_body(m), s, std::strlen(s)) == 0)

#define NNG_TESTS_CHECK_STR(m, s) \
    REQUIRE(m != nullptr); \
    REQUIRE(::nng_msg_len(m) == std::strlen(s)); \
    REQUIRE(std::memcmp(::nng_msg_body(m), s, std::strlen(s)) == 0)

#define NNGCPP_TESTS_ALLOCATE_MSG_SZ(m, sz) \
    REQUIRE((m).has_message() == false); \
    REQUIRE((m).get_msgp() == nullptr); \
    \
    REQUIRE_NOTHROW((m).allocate(sz)); \
    REQUIRE((m).has_message() == true); \
    REQUIRE((m).get_msgp() != nullptr); \
    \
    REQUIRE((m).header() != nullptr); \
    REQUIRE((m).header()->has_message()); \
    REQUIRE((m).header()->get_msgp() == (m).get_msgp()); \
    \
    REQUIRE((m).body() != nullptr); \
    REQUIRE((m).body()->has_message()); \
    REQUIRE((m).body()->get_msgp() == (m).get_msgp());

#define NNGCPP_TESTS_ALLOCATE_MSG(m) NNGCPP_TESTS_ALLOCATE_MSG_SZ(m, 0)

struct c_style_fixture {

    ::nng_socket push;
    ::nng_socket pull;

    c_style_fixture() : push(0), pull(0) {

        REQUIRE(::nng_push_open(&push) == 0);
        REQUIRE(::nng_pull_open(&pull) == 0);

        REQUIRE(push > 0);
        REQUIRE(pull > 0);
    }

    virtual ~c_style_fixture() {
        ::nng_close(push);
        ::nng_close(pull);
        ::nng_fini();
    }
};

namespace nng {
    namespace messaging {

        struct message_pipe_fixture : public message_pipe {

            message_pipe_fixture(const message_base* const mbp) : message_pipe(mbp) {
            }

            ::nng_pipe get_pid() const {
                return pid;
            }
        };
    }
}

#define NNG_TESTS_VERIFY_TEST_CASE_DATA() \
    REQUIRE_THAT(constants::hello, Catch::Matchers::Equals("hello")); \
    REQUIRE_THAT(constants::again, Catch::Matchers::Equals("again")); \
    REQUIRE_THAT(constants::nng_addr, Catch::Matchers::Equals("inproc://nng")); \
    REQUIRE_THAT(constants::test_addr, Catch::Matchers::Equals("inproc://test"))

TEST_CASE("Catch translation of NNG C reconnect unit tests", "[nng][c][reconnect]") {

    using namespace std;
    using namespace std::chrono;
    using namespace constants;

    SECTION("Verify that we have the required data") {
        NNG_TESTS_VERIFY_TEST_CASE_DATA();
    }

    SECTION("We can create a pipeline") {

        /* When the scope rolls back, we want to destroy the fixture, which
        effectively closes the sockets, and finishes the NNG session. */
        c_style_fixture $;

        auto& pull = $.pull;
        auto& push = $.push;

        REQUIRE(::nng_setopt_usec(pull, NNG_OPT_RECONNMINT, 10000) == 0);
        REQUIRE(::nng_setopt_usec(pull, NNG_OPT_RECONNMAXT, 10000) == 0);

        SECTION("Dialing before listening works") {

            // With Reconnect Times configured, Should re-dial until Listener comes online.
            REQUIRE(::nng_dial(push, test_addr.c_str(), nullptr, NNG_FLAG_NONBLOCK) == 0);
            this_thread::sleep_for(100ms);
            REQUIRE(::nng_listen(pull, test_addr.c_str(), nullptr, 0) == 0);

            SECTION("We can send a frame") {

                ::nng_msg* msgp = nullptr;

                this_thread::sleep_for(100ms);

                REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                REQUIRE(msgp != nullptr);
                NNG_TESTS_APPEND_STR(msgp, hello.c_str());
                REQUIRE(::nng_sendmsg(push, msgp, 0) == 0);

                /* Nullifying the pointer is NOT a mistake. It is part of the zero-copy message ownership
                semantics. Once the message is "sent", the framework effectively assumes ownership. */
                msgp = nullptr;

                // Which Receiving a Message should allocate when we did not provide one.
                REQUIRE(::nng_recvmsg(pull, &msgp, 0) == 0);
                NNG_TESTS_CHECK_STR(msgp, hello.c_str());

                ::nng_msg_free(msgp);
            }
        }

        SECTION("Reconnection works") {

            ::nng_listener l;

            REQUIRE(::nng_dial(push, test_addr.c_str(), nullptr, NNG_FLAG_NONBLOCK) == 0);
            REQUIRE(::nng_listen(pull, test_addr.c_str(), &l, 0) == 0);
            this_thread::sleep_for(100ms);
            REQUIRE(::nng_listener_close(l) == 0);
            REQUIRE(::nng_listen(pull, test_addr.c_str(), nullptr, 0) == 0);

            SECTION("They still exchange frames") {
                ::nng_msg *msgp;
                ::nng_pipe p1;

                this_thread::sleep_for(100ms);
                REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                NNG_TESTS_APPEND_STR(msgp, hello.c_str());
                REQUIRE(::nng_sendmsg(push, msgp, 0) == 0);
                // Ditto message passing ownership semantics.
                msgp = nullptr;
                REQUIRE(::nng_recvmsg(pull, &msgp, 0) == 0);
                REQUIRE(msgp != nullptr);
                NNG_TESTS_CHECK_STR(msgp, hello.c_str());
                REQUIRE((p1 = ::nng_msg_get_pipe(msgp)) > 0);
                ::nng_msg_free(msgp);

                SECTION("Even after pipe close") {
                    ::nng_pipe p2;

                    REQUIRE(::nng_pipe_close(p1) == 0);
                    this_thread::sleep_for(100ms);
                    REQUIRE(::nng_msg_alloc(&msgp, 0) == 0);
                    NNG_TESTS_APPEND_STR(msgp, again.c_str());
                    REQUIRE(::nng_sendmsg(push, msgp, 0) == 0);
                    msgp = nullptr;
                    REQUIRE(::nng_recvmsg(pull, &msgp, 0) == 0);
                    REQUIRE(msgp != nullptr);
                    NNG_TESTS_CHECK_STR(msgp, again.c_str());
                    REQUIRE((p2 = nng_msg_get_pipe(msgp)) > 0);
                    ::nng_msg_free(msgp);
                    REQUIRE(p2 != p1);
                }
            }
        }
    }
}

TEST_CASE("NNG C++ wrapper reconnect works", "[reconnect][cxx][wrapper]") {

    using namespace std;
    using namespace std::chrono;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using _opt_ = option_names;

    // TODO: not sure if I like having "session" part of these unit tests, per se. I almost want session to be the subject of its own set of unit tests (it should be, anyway).
    // Which "at-exit" destructor handles cleaning up the NNG resources: i.e. ::nng_fini.
    session _session_;

    SECTION("We can create a pipeline") {

        std::shared_ptr<latest_push_socket> push;
        std::shared_ptr<latest_pull_socket> pull;

        REQUIRE_NOTHROW(push = _session_.create_push_socket());
        REQUIRE_NOTHROW(pull = _session_.create_pull_socket());

        const duration<uint64_t, milli> reconnect_time = 10ms;

        // TODO: TBD: count() might be the way to go here, but I cannot say for sure.
        // http://en.cppreference.com/w/cpp/chrono/duration
        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::min_reconnect_time_usec, reconnect_time.count()));
        REQUIRE_NOTHROW(pull->set_option_usec(_opt_::max_reconnect_time_usec, reconnect_time.count()));

        SECTION("Dialing before listening works") {

            REQUIRE_NOTHROW(push->dial(test_addr, flag_nonblock));
            this_thread::sleep_for(100ms);
            REQUIRE_NOTHROW(pull->listen(test_addr));

            /* 'Frame' in this case is loosely speaking. We do not care about exposing the NNG msg structure,
            per se. Rather, we should simply be able to "frame" buffers or strings, accordingly. */
            SECTION("We can send a frame") {

                auto bmp = std::make_unique<binary_message>();
                this_thread::sleep_for(100ms);
                NNGCPP_TESTS_ALLOCATE_MSG(*bmp);
                // And with a little C++ operator overloading help:
                REQUIRE_NOTHROW(*bmp << hello);
                REQUIRE_NOTHROW(push->send(bmp.get()));
                /* Ditto message passing semantics. The Send() operation effectively
                nullifies the internal message. */
                REQUIRE(bmp->has_message() == false);

                REQUIRE_NOTHROW(pull->try_receive(bmp.get()));
                REQUIRE(bmp->has_message() == true);
                // Just verify that the message matches the buffer.
                REQUIRE_THAT(bmp->body()->get(), Equals(hello_buf));
            }
        }

        SECTION("Reconnection works") {

            REQUIRE_NOTHROW(push->dial(test_addr, flag_nonblock));

            {
                // We do not need to see the Listener beyond this block.
                auto lp = std::make_unique<listener>();
                REQUIRE_NOTHROW(pull->listen(test_addr, lp.get()));
                this_thread::sleep_for(100ms);
                // No need to burden "session" with this one, either.
                REQUIRE_NOTHROW(lp.reset());
            }

            // Then re-listen to the address.
            REQUIRE_NOTHROW(pull->listen(test_addr));

            // TODO: TBD: we may provide comprehension of nng_pipe from a nngcpp POV, but I'm not sure the complexity of nng_msg how that is different from a simple send/receive?
            SECTION("They still exchange frames") {

                auto bmp = std::make_unique<binary_message>();

                this_thread::sleep_for(100ms);
                NNGCPP_TESTS_ALLOCATE_MSG(*bmp);
                REQUIRE_NOTHROW(*bmp << hello);
                REQUIRE_NOTHROW(push->send(bmp.get()));
                REQUIRE(bmp->has_message() == false);

                // See notes above. Sending transfers ownership of the internal message to NNG.
                REQUIRE_NOTHROW(pull->try_receive(bmp.get()));
                REQUIRE(bmp->has_message() == true);
                // Just verify that the message matches the buffer.
                REQUIRE_THAT(bmp->body()->get(), Equals(hello_buf));

                // TODO: TBD: this one deserves its own unit test as well so that we are not cluttering the integration tests
                message_pipe_fixture mp1(bmp.get());
                REQUIRE(mp1.is_valid() == true);
                // TODO: TBD: deserves its own unit testing...
                REQUIRE(mp1.get_pid() > 0);
                /* Resetting the message pointer is effectively the same, if stronger, for purposes
                of this unit test, without necessarily needing to expose the free method. */
                REQUIRE_NOTHROW(bmp.reset());
                REQUIRE(bmp.get() == nullptr);

                SECTION("Even after pipe close") {

                    // Get the fixtured PID for test purposes prior to closing.
                    auto mp1_pid = mp1.get_pid();
                    REQUIRE_NOTHROW(mp1.close());
                    REQUIRE(mp1.is_valid() == false);

                    this_thread::sleep_for(100ms);
                    auto bmp2 = std::make_unique<binary_message>();
                    NNGCPP_TESTS_ALLOCATE_MSG(*bmp2);
                    REQUIRE_NOTHROW(*bmp2 << again);
                    // TODO: TBD: send/no-message -> receive/message is a pattern that deserves its own focused unit test...
                    REQUIRE_NOTHROW(push->send(bmp2.get()));
                    REQUIRE(bmp2->has_message() == false);

                    REQUIRE_NOTHROW(pull->try_receive(bmp2.get()));
                    REQUIRE(bmp2->has_message() == true);
                    // Just verify that the message matches the buffer.
                    REQUIRE_THAT(bmp2->body()->get(), Equals(again_buf));

                    message_pipe_fixture mp2(bmp2.get());
                    REQUIRE(mp2.is_valid() == true);
                    // Ditto resetting the pointer versus exposing the free method.
                    REQUIRE_NOTHROW(bmp2.reset());
                    REQUIRE(bmp2.get() == nullptr);
                    REQUIRE(mp2.get_pid() != mp1_pid);
                }
            }
        }
    }
}
<|endoftext|>


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

#include "raspboop/Raspboop.h"

namespace raspboop
{
namespace sensors
{

HCSR04::HCSR04()
{
	EchoPin = -1;
	TriggerPin = -1;
	EchoStart = 0;
	EchoEnd = 0;
	Distance = 0;
}

HCSR04* HCSR04::Create(int ECHO, int TRIG)
{

	// Using the same pins. Should notify user
	if(ECHO == TRIG)
		return NULL;

	HCSR04* H = (HCSR04*)malloc(sizeof(HCSR04));

	// Not enough memory. Should notify user
	if(H == NULL)
		return NULL;

	new(H) HCSR04;

	H->EchoPin = ECHO;
	H->TriggerPin = TRIG;

	H->SetInputPin(ECHO);
	H->SetOutputPin(TRIG);

	digitalWrite(TRIG, LOW);

	return H;
}

void HCSR04::Sense()
{
	// Pins are not set, should notify user
	if(EchoPin == -1 || TriggerPin == -1)
		return;

	EchoStart = EchoEnd = 0;

	digitalWrite(TriggerPin, HIGH);
	// HCSR04 manual states to wait 10 micros when triggered
	delayMicroseconds(10);
	digitalWrite(TRIG, LOW);

	while(digitalRead(EchoPin) == 0)
		EchoStart = (float)micros();

	while(digitalRead(EchoPin))
		EchoEnd = (float)micros();

	Distance = (EchoEnd - EchoStart) * .017f;
}

void HCSR04::ReleasePins()
{
	digitalWrite(TriggerPin, LOW);
}

HCSR04::~HCSR04()
{
}

} /* sensors */
} /* raspboop */
<commit_msg>HCSR04: change TRIG to TriggerPin<commit_after>/* *
* Copyright (c) 2013 Julio Gutierrez
*
* Permission is hereby granted, free of charge, to any person obtaining a co$
* this software and associated documentation files (the "Software"), to deal$
* the Software without restriction, including without limitation the rights $
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell cop$
* the Software, and to permit persons to whom the Software is furnished to d$
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in$
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, F$
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR$
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHE$
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* */

#include "raspboop/Raspboop.h"

namespace raspboop
{
namespace sensors
{

HCSR04::HCSR04()
{
	EchoPin = -1;
	TriggerPin = -1;
	EchoStart = 0;
	EchoEnd = 0;
	Distance = 0;
}

HCSR04* HCSR04::Create(int ECHO, int TRIG)
{

	// Using the same pins. Should notify user
	if(ECHO == TRIG)
		return NULL;

	HCSR04* H = (HCSR04*)malloc(sizeof(HCSR04));

	// Not enough memory. Should notify user
	if(H == NULL)
		return NULL;

	new(H) HCSR04;

	H->EchoPin = ECHO;
	H->TriggerPin = TRIG;

	H->SetInputPin(ECHO);
	H->SetOutputPin(TRIG);

	digitalWrite(TRIG, LOW);

	return H;
}

void HCSR04::Sense()
{
	// Pins are not set, should notify user
	if(EchoPin == -1 || TriggerPin == -1)
		return;

	EchoStart = EchoEnd = 0;

	digitalWrite(TriggerPin, HIGH);
	// HCSR04 manual states to wait 10 micros when triggered
	delayMicroseconds(10);
	digitalWrite(TriggerPin, LOW);

	while(digitalRead(EchoPin) == 0)
		EchoStart = (float)micros();

	while(digitalRead(EchoPin))
		EchoEnd = (float)micros();

	Distance = (EchoEnd - EchoStart) * .017f;
}

void HCSR04::ReleasePins()
{
	digitalWrite(TriggerPin, LOW);
}

HCSR04::~HCSR04()
{
}

} /* sensors */
} /* raspboop */
<|endoftext|>


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

#include "perfetto/profiling/memory/heap_profile.h"

#include <inttypes.h>

__attribute__((visibility("default"))) uint64_t
AHeapProfileEnableCallbackInfo_getSamplingInterval(
    const AHeapProfileEnableCallbackInfo*) {
  return 0;
}

__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_create(
    const char*) {
  return nullptr;
}

__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setEnabledCallback(
    AHeapInfo*,
    void (*)(void*, const AHeapProfileEnableCallbackInfo*),
    void*) {
  return nullptr;
}

__attribute__((visibility("default"))) AHeapInfo*
AHeapInfo_setDisabledCallback(AHeapInfo*, void (*)(void*), void*) {
  return nullptr;
}

__attribute__((visibility("default"))) uint32_t AHeapProfile_registerHeap(
    AHeapInfo*) {
  return 0;
}

__attribute__((visibility("default"))) bool
AHeapProfile_reportAllocation(uint32_t, uint64_t, uint64_t) {
  return false;
}

__attribute__((visibility("default"))) bool
AHeapProfile_reportSample(uint32_t, uint64_t, uint64_t) {
  return false;
}

__attribute__((visibility("default"))) void AHeapProfile_reportFree(uint32_t,
                                                                    uint64_t) {}

__attribute__((visibility("default"))) bool AHeapProfile_initSession(
    void* (*)(size_t),
    void (*)(void*)) {
  return false;
}
<commit_msg>Fix parameters to HeapInfo_setDisabledCallback. am: 61cbb8911d am: ea20c986c2 am: d0545f1837<commit_after>/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "perfetto/profiling/memory/heap_profile.h"

#include <inttypes.h>

__attribute__((visibility("default"))) uint64_t
AHeapProfileEnableCallbackInfo_getSamplingInterval(
    const AHeapProfileEnableCallbackInfo*) {
  return 0;
}

__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_create(
    const char*) {
  return nullptr;
}

__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setEnabledCallback(
    AHeapInfo*,
    void (*)(void*, const AHeapProfileEnableCallbackInfo*),
    void*) {
  return nullptr;
}

__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setDisabledCallback(
    AHeapInfo*,
    void (*)(void*, const AHeapProfileDisableCallbackInfo*),
    void*) {
  return nullptr;
}

__attribute__((visibility("default"))) uint32_t AHeapProfile_registerHeap(
    AHeapInfo*) {
  return 0;
}

__attribute__((visibility("default"))) bool
AHeapProfile_reportAllocation(uint32_t, uint64_t, uint64_t) {
  return false;
}

__attribute__((visibility("default"))) bool
AHeapProfile_reportSample(uint32_t, uint64_t, uint64_t) {
  return false;
}

__attribute__((visibility("default"))) void AHeapProfile_reportFree(uint32_t,
                                                                    uint64_t) {}

__attribute__((visibility("default"))) bool AHeapProfile_initSession(
    void* (*)(size_t),
    void (*)(void*)) {
  return false;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

#include "Game.h"
#include "Dog.h"
#include "Cat.h"
#include "Hawk.h"
#include "Bat.h"
#include "Turtle.h"
#include "Shark.h"
#include "ArmyAnt.h"
#include "ArmyAntQueen.h"
#include "Dragon.h"

/*
 * Remember to include the header file of the animal classes here
 */

using namespace std;

Game::Game(std::string file) {
  load(file);
}

Game::~Game() {
  for(int i = 0; i < 10; i++)
    delete animals[i/5][i%5];
}

/**
 * You should instantiate the animal objects here
 * Please refer to the example of "Dog"
 */
void Game::load(std::string file)
{
  ifstream in(file.c_str());
  int c = 0;
  int id;
  while(in >> id)
    {
      switch(id)
	{
	case DOG:
	  animals[c/5][c%5] = new Dog(this, c/5, c%5);
	  break;
	case CAT:
	  animals[c/5][c%5] = new Cat(this, c/5, c%5);
	  break;
	case HAWK:
	  animals[c/5][c%5] = new Hawk(this, c/5, c%5);
	  break;
	case BAT:
	  animals[c/5][c%5] = new Bat(this, c/5, c%5);
	  break;
	case TURTLE:
	  animals[c/5][c%5] = new Turtle(this, c/5, c%5);
	  break;
	case SHARK:
	  animals[c/5][c%5] = new Shark(this, c/5, c%5);
	  break;
	case ARMY_ANT:
	  animals[c/5][c%5] = new ArmyAnt(this, c/5, c%5);
	  break;
	case ARMY_ANT_QUEEN:
	  animals[c/5][c%5] = new ArmyAntQueen(this, c/5, c%5);
	  break;
	case DRAGON:
	  animals[c/5][c%5] = new Dragon(this, c/5, c%5);
	  break;
	}

      c++;
    }

}

/**
 * Do NOT modify this function
 */
bool Game::isEnd()
{
  int deadCount1 = 0;
  int deadCount2 = 0;
  for(int i = 0; i < 5; i++)
    {
      deadCount1 += animals[P1][i]->isDead();
      deadCount2 += animals[P2][i]->isDead();
    }

  if(deadCount1 == 5 && deadCount2 == 5)
    {
      cout << "Draws!" << endl;
    }else if (deadCount1 == 5)
    {
      cout << "Player " << P2+1 << " Wins!" << endl;
    } else if (deadCount2 == 5)
    {
      cout << "Player " << P1+1 << " Wins!" << endl;
    } else {
    return false;
  }
  return true;

}

void Game::start()
{
  Player currentPlayer = P1;
  int turnCount = 1;
  while(!isEnd())
    {
      for(int i = 0; i < 5; i++)
	{
	  if(!animals[currentPlayer][i]->isDead())
	    animals[currentPlayer][i]->attack();
	}

      /**
       * To-Do 2: Codes for Special moves (if any) should be written here
       * Hint: You should use dynamic binding, you may add data members/ functions in the Game class to help you implement this part
       */

      if (countFlying(currentPlayer) > 2)
	std::cout << "Player " << currentPlayer+1 << " has harassed the other player." << std::endl;
	for (int i = 0; i < 5; ++i)
	  animals[currentPlayer][i]->harass();

      if (countSwimming(currentPlayer) > 2)
	std::cout << "Player " << currentPlayer+1 << " has summoned a Tsunami." << std::endl;
	for (int i = 0; i < 5; ++i)
	  animals[currentPlayer][i]->summonTsunami();

      if (countArmyAnt(currentPlayer) >= 5)
	std::cout << "Player " << currentPlayer+1 << "'s Ant Army has marched and conquered." << std::endl;
	for (int i = 0; i < 5; ++i)
	  animals[currentPlayer][i]->marchAndConquer();

      //Output turn info
      cout << "Turn " << turnCount++ << " Player " << currentPlayer+1 << " attacks:" << endl;
      cout << "Player 1" << endl;
      for(int i = 0; i < 5; i++)
	{
	  if(!animals[P1][i]->isDead())
	    cout << animals[P1][i]->getName() << ":"
		 << animals[P1][i]->getCurrentHP() << " ";
	  else
	    cout << animals[P1][i]->getName() << ":"
		 << "DEAD" << " ";
	}
      cout << endl;
      cout << "Player 2" << endl;
      for(int i = 0; i < 5; i++)
	{
	  if(!animals[P2][i]->isDead())
	    cout << animals[P2][i]->getName() << ":"
		 << animals[P2][i]->getCurrentHP() << " ";
	  else
	    cout << animals[P2][i]->getName() << ":"
		 << "DEAD" << " ";
	}
      cout << endl;

      //Switch player turn
      if(currentPlayer == P1)
	currentPlayer = P2;
      else
	currentPlayer = P1;
    }
}

int Game::countFlying(int player) {
  int count = 0;
  for (int i = 0; i < 5; ++i) {
    if (animals[player][i]->getType() == Type::FLYING)
      count++;
  }
  return count;
}

int Game::countSwimming(int player) {
  int count = 0;
  for (int i = 0; i < 5; ++i) {
    if (animals[player][i]->getType() == Type::SWIMMING)
      count++;
  }
  return count;
}

int Game::countArmyAnt(int player) {
  int count = 0;
  for (int i = 0; i < 5; ++i) {
    if (animals[player][i]->getType() == Type::ANT)
      count++;
  }
  return count;
}
<commit_msg>PA5: fixed error in special moves<commit_after>#include <iostream>
#include <fstream>

#include "Game.h"
#include "Dog.h"
#include "Cat.h"
#include "Hawk.h"
#include "Bat.h"
#include "Turtle.h"
#include "Shark.h"
#include "ArmyAnt.h"
#include "ArmyAntQueen.h"
#include "Dragon.h"

/*
 * Remember to include the header file of the animal classes here
 */

using namespace std;

Game::Game(std::string file) {
  load(file);
}

Game::~Game() {
  for(int i = 0; i < 10; i++)
    delete animals[i/5][i%5];
}

/**
 * You should instantiate the animal objects here
 * Please refer to the example of "Dog"
 */
void Game::load(std::string file)
{
  ifstream in(file.c_str());
  int c = 0;
  int id;
  while(in >> id)
    {
      switch(id)
	{
	case DOG:
	  animals[c/5][c%5] = new Dog(this, c/5, c%5);
	  break;
	case CAT:
	  animals[c/5][c%5] = new Cat(this, c/5, c%5);
	  break;
	case HAWK:
	  animals[c/5][c%5] = new Hawk(this, c/5, c%5);
	  break;
	case BAT:
	  animals[c/5][c%5] = new Bat(this, c/5, c%5);
	  break;
	case TURTLE:
	  animals[c/5][c%5] = new Turtle(this, c/5, c%5);
	  break;
	case SHARK:
	  animals[c/5][c%5] = new Shark(this, c/5, c%5);
	  break;
	case ARMY_ANT:
	  animals[c/5][c%5] = new ArmyAnt(this, c/5, c%5);
	  break;
	case ARMY_ANT_QUEEN:
	  animals[c/5][c%5] = new ArmyAntQueen(this, c/5, c%5);
	  break;
	case DRAGON:
	  animals[c/5][c%5] = new Dragon(this, c/5, c%5);
	  break;
	}

      c++;
    }

}

/**
 * Do NOT modify this function
 */
bool Game::isEnd()
{
  int deadCount1 = 0;
  int deadCount2 = 0;
  for(int i = 0; i < 5; i++)
    {
      deadCount1 += animals[P1][i]->isDead();
      deadCount2 += animals[P2][i]->isDead();
    }

  if(deadCount1 == 5 && deadCount2 == 5)
    {
      cout << "Draws!" << endl;
    }else if (deadCount1 == 5)
    {
      cout << "Player " << P2+1 << " Wins!" << endl;
    } else if (deadCount2 == 5)
    {
      cout << "Player " << P1+1 << " Wins!" << endl;
    } else {
    return false;
  }
  return true;

}

void Game::start()
{
  Player currentPlayer = P1;
  int turnCount = 1;
  while(!isEnd())
    {
      for(int i = 0; i < 5; i++)
	{
	  if(!animals[currentPlayer][i]->isDead())
	    animals[currentPlayer][i]->attack();
	}

      /**
       * To-Do 2: Codes for Special moves (if any) should be written here
       * Hint: You should use dynamic binding, you may add data members/ functions in the Game class to help you implement this part
       */

      if (countFlying(currentPlayer) > 2) {
	std::cout << "Player " << currentPlayer+1 << " has harassed the other player." << std::endl;
	for (int i = 0; i < 5; ++i)
	  animals[currentPlayer][i]->harass();
      }

      if (countSwimming(currentPlayer) > 2) {
	std::cout << "Player " << currentPlayer+1 << " has summoned a Tsunami." << std::endl;
	for (int i = 0; i < 5; ++i)
	  animals[currentPlayer][i]->summonTsunami();
      }

      if (countArmyAnt(currentPlayer) >= 5) {
	std::cout << "Player " << currentPlayer+1 << "'s Ant Army has marched and conquered." << std::endl;
	for (int i = 0; i < 5; ++i)
	  animals[currentPlayer][i]->marchAndConquer();
      }

      //Output turn info
      cout << "Turn " << turnCount++ << " Player " << currentPlayer+1 << " attacks:" << endl;
      cout << "Player 1" << endl;
      for(int i = 0; i < 5; i++)
	{
	  if(!animals[P1][i]->isDead())
	    cout << animals[P1][i]->getName() << ":"
		 << animals[P1][i]->getCurrentHP() << " ";
	  else
	    cout << animals[P1][i]->getName() << ":"
		 << "DEAD" << " ";
	}
      cout << endl;
      cout << "Player 2" << endl;
      for(int i = 0; i < 5; i++)
	{
	  if(!animals[P2][i]->isDead())
	    cout << animals[P2][i]->getName() << ":"
		 << animals[P2][i]->getCurrentHP() << " ";
	  else
	    cout << animals[P2][i]->getName() << ":"
		 << "DEAD" << " ";
	}
      cout << endl;

      //Switch player turn
      if(currentPlayer == P1)
	currentPlayer = P2;
      else
	currentPlayer = P1;
    }
}

int Game::countFlying(int player) {
  int count = 0;
  for (int i = 0; i < 5; ++i) {
    if (animals[player][i]->getType() == Type::FLYING)
      count++;
  }
  return count;
}

int Game::countSwimming(int player) {
  int count = 0;
  for (int i = 0; i < 5; ++i) {
    if (animals[player][i]->getType() == Type::SWIMMING)
      count++;
  }
  return count;
}

int Game::countArmyAnt(int player) {
  int count = 0;
  for (int i = 0; i < 5; ++i) {
    if (animals[player][i]->getType() == Type::ANT)
      count++;
  }
  return count;
}
<|endoftext|>


<commit_before>#include "resolver.hpp"
#include "decl.hpp"
#include "action.hpp"
#include "expr.hpp"

#include <sstream>

namespace pip
{

  void
  resolver::resolve_decl(decl* d)
  {
    switch (get_kind(d)) {
      dk_program:
        return resolve_decl(cast<program_decl>(d));
      dk_table:
        return resolve_decl(cast<table_decl>(d));
      default:
        break;
    }
    throw std::logic_error("invalid declaration");
  }

  void
  resolver::resolve_decl(program_decl* p)
  {
    // 1st pass: generate the lookup table for devices in the program.
    for (decl* d : p->decls) {
      assert(d->id);
      decls[d->id] = d;
    }

    // 2nd pass: resolve references to declarations.
    for (decl* d : p->decls)
      resolve_decl(d);
  }

  void
  resolver::resolve_decl(table_decl* t)
  {
    resolve_actions(t->prep);

    for (match* m : t->rules) {
      resolve_expr(m->key);
      resolve_actions(m->acts);
    }
  }

  void
  resolver::resolve_actions(action_seq& as)
  {
    for (action* a : as)
      resolve_action(a);
  }

  void
  resolver::resolve_action(action* a)
  {
    switch (get_kind(a)) {
      case ak_advance:
        return resolve_action(cast<advance_action>(a));
      case ak_copy:
        return resolve_action(cast<copy_action>(a));
      case ak_set:
        return resolve_action(cast<set_action>(a));
      case ak_write:
        return resolve_action(cast<write_action>(a));
      case ak_clear:
        return resolve_action(cast<clear_action>(a));
      case ak_drop:
        return resolve_action(cast<drop_action>(a));
      case ak_match:
        return resolve_action(cast<match_action>(a));
      case ak_goto:
        return resolve_action(cast<goto_action>(a));
      case ak_output:
        return resolve_action(cast<output_action>(a));
    }
  }

  void
  resolver::resolve_action(advance_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(copy_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(set_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(write_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(clear_action* a)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_action(drop_action* a)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_action(match_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(goto_action* a)
  {
    resolve_expr(a->dest);
  }

  void
  resolver::resolve_action(output_action* a)
  {
    resolve_expr(a->port);
  }

  void
  resolver::resolve_expr(expr* e)
  {
    switch (get_kind(e)) {
      case ek_int:
        return resolve_expr(cast<int_expr>(e));
      case ek_range:
        return resolve_expr(cast<range_expr>(e));
      case ek_wild:
        return resolve_expr(cast<wild_expr>(e));
      case ek_miss:
        return resolve_expr(cast<miss_expr>(e));
      case ek_ref:
        return resolve_expr(cast<ref_expr>(e));
      case ek_field:
        return resolve_expr(cast<field_expr>(e));
    }
  }

  void
  resolver::resolve_expr(int_expr* e)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_expr(wild_expr* e)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_expr(range_expr* e)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_expr(ref_expr* e)
  {
    auto iter = decls.find(e->id);
    if (iter == decls.end()) {
      std::stringstream ss;
      ss << "no table named '" << e->id << '\'';
      throw lookup_error(get_location(e), ss.str());
    }
    e->ref = iter->second;
  }

  void
  resolver::resolve_expr(field_expr* e)
  {
    // FIXME: Match field expressions to internal definitions of protocol
    // information and functionality. For example, the field "eth.type"
    // should map to an object that yields the offset and length of that
    // field -- possibly also a function to actually fetch the value and
    // applying a byte order transformation.
    throw std::logic_error("not implemented");
  }

} // namespace pip
<commit_msg>Apparently, you can have non-case labeled statements in a switch.<commit_after>#include "resolver.hpp"
#include "decl.hpp"
#include "action.hpp"
#include "expr.hpp"

#include <sstream>

namespace pip
{

  void
  resolver::resolve_decl(decl* d)
  {
    switch (get_kind(d)) {
      case dk_program:
        return resolve_decl(cast<program_decl>(d));
      case dk_table:
        return resolve_decl(cast<table_decl>(d));
      default:
        break;
    }
    throw std::logic_error("invalid declaration");
  }

  void
  resolver::resolve_decl(program_decl* p)
  {
    // 1st pass: generate the lookup table for devices in the program.
    for (decl* d : p->decls) {
      assert(d->id);
      decls[d->id] = d;
    }

    // 2nd pass: resolve references to declarations.
    for (decl* d : p->decls)
      resolve_decl(d);
  }

  void
  resolver::resolve_decl(table_decl* t)
  {
    resolve_actions(t->prep);

    for (match* m : t->rules) {
      resolve_expr(m->key);
      resolve_actions(m->acts);
    }
  }

  void
  resolver::resolve_actions(action_seq& as)
  {
    for (action* a : as)
      resolve_action(a);
  }

  void
  resolver::resolve_action(action* a)
  {
    switch (get_kind(a)) {
      case ak_advance:
        return resolve_action(cast<advance_action>(a));
      case ak_copy:
        return resolve_action(cast<copy_action>(a));
      case ak_set:
        return resolve_action(cast<set_action>(a));
      case ak_write:
        return resolve_action(cast<write_action>(a));
      case ak_clear:
        return resolve_action(cast<clear_action>(a));
      case ak_drop:
        return resolve_action(cast<drop_action>(a));
      case ak_match:
        return resolve_action(cast<match_action>(a));
      case ak_goto:
        return resolve_action(cast<goto_action>(a));
      case ak_output:
        return resolve_action(cast<output_action>(a));
    }
  }

  void
  resolver::resolve_action(advance_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(copy_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(set_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(write_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(clear_action* a)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_action(drop_action* a)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_action(match_action* a)
  {
    throw std::logic_error("not implemented");
  }

  void
  resolver::resolve_action(goto_action* a)
  {
    resolve_expr(a->dest);
  }

  void
  resolver::resolve_action(output_action* a)
  {
    resolve_expr(a->port);
  }

  void
  resolver::resolve_expr(expr* e)
  {
    switch (get_kind(e)) {
      case ek_int:
        return resolve_expr(cast<int_expr>(e));
      case ek_range:
        return resolve_expr(cast<range_expr>(e));
      case ek_wild:
        return resolve_expr(cast<wild_expr>(e));
      case ek_miss:
        return resolve_expr(cast<miss_expr>(e));
      case ek_ref:
        return resolve_expr(cast<ref_expr>(e));
      case ek_field:
        return resolve_expr(cast<field_expr>(e));
    }
  }

  void
  resolver::resolve_expr(int_expr* e)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_expr(wild_expr* e)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_expr(range_expr* e)
  {
    // Nothing to do.
  }

  void
  resolver::resolve_expr(ref_expr* e)
  {
    auto iter = decls.find(e->id);
    if (iter == decls.end()) {
      std::stringstream ss;
      ss << "no table named '" << e->id << '\'';
      throw lookup_error(get_location(e), ss.str());
    }
    e->ref = iter->second;
  }

  void
  resolver::resolve_expr(field_expr* e)
  {
    // FIXME: Match field expressions to internal definitions of protocol
    // information and functionality. For example, the field "eth.type"
    // should map to an object that yields the offset and length of that
    // field -- possibly also a function to actually fetch the value and
    // applying a byte order transformation.
    throw std::logic_error("not implemented");
  }

} // namespace pip
<|endoftext|>


<commit_before>#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>

#include "arch/io/disk.hpp"
#include "clustering/administration/main/directory_lock.hpp"

bool check_existence(const base_path_t& base_path) {
    return 0 == access(base_path.path().c_str(), F_OK);
}

bool check_dir_emptiness(const base_path_t& base_path) {
    DIR *dp;
    struct dirent *ep;

    dp = opendir(base_path.path().c_str());
    if (dp == NULL) {
        return false;
    }
    while ((ep = readdir(dp)) != NULL) {
        if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
            closedir(dp);
            return false;
        }
    }
    closedir(dp);
    return true;
}

directory_lock_t::directory_lock_t(const base_path_t &path, bool create, bool *created_out) :
    directory_path(path),
    created(false),
    initialize_done(false) {

    *created_out = false;
    bool dir_exists = check_existence(directory_path);

    if (!dir_exists) {
        if (!create) {
            throw directory_missing_exc_t(directory_path);
        }
        int mkdir_res;
        do {
            mkdir_res = mkdir(directory_path.path().c_str(), 0755);
        } while (mkdir_res == -1 && get_errno() == EINTR);
        if (mkdir_res != 0) {
            throw directory_create_failed_exc_t(get_errno(), directory_path);
        }
        created = true;
        *created_out = true;

        // Call fsync() on the parent directory to guarantee that the newly
        // created directory's directory entry is persisted to disk.
        warn_fsync_parent_directory(directory_path.path().c_str());
    } else if (create && check_dir_emptiness(directory_path)) {
        created = true;
        *created_out = true;
    }

    directory_fd.reset(::open(directory_path.path().c_str(), O_RDONLY));
    if (directory_fd.get() == INVALID_FD) {
        throw directory_open_failed_exc_t(get_errno(), directory_path);
    }

    if (flock(directory_fd.get(), LOCK_EX | LOCK_NB) != 0) {
        throw directory_locked_exc_t(directory_path);
    }
}

directory_lock_t::~directory_lock_t() {
    // Only delete the directory if we created it and haven't finished initialization
    if (created && !initialize_done) {
        remove_directory_recursive(directory_path.path().c_str());
    }
}

void directory_lock_t::directory_initialized() {
    guarantee(directory_fd.get() != INVALID_FD);
    initialize_done = true;
}

void directory_lock_t::change_ownership(gid_t group_id, const std::string &group_name,
                                        uid_t user_id, const std::string &user_name) {
    if (group_id != INVALID_GID || user_id != INVALID_UID) {
        if (fchown(directory_fd.get(), user_id, group_id) != 0) {
            throw std::runtime_error(strprintf("Failed to change ownership of data "
                                               "directory '%s' to '%s:%s': %s",
                                               directory_path.path().c_str(),
                                               user_name.c_str(),
                                               group_name.c_str(),
                                               errno_string(get_errno()).c_str()));
        }
    }
}
<commit_msg>More improvements for #2359<commit_after>#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>

#include "arch/io/disk.hpp"
#include "clustering/administration/main/directory_lock.hpp"

bool check_existence(const base_path_t& base_path) {
    return 0 == access(base_path.path().c_str(), F_OK);
}

bool check_dir_emptiness(const base_path_t& base_path) {
    DIR *dp;
    struct dirent *ep;

    set_errno(0);
    dp = opendir(base_path.path().c_str());
    if (dp == NULL) {
        return false;
    }
    guarantee_err(get_errno() == 0, "Error while reading directory");
    while ((ep = readdir(dp)) != NULL) {
        if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
            closedir(dp);
            return false;
        }
    }
    closedir(dp);
    return true;
}

directory_lock_t::directory_lock_t(const base_path_t &path, bool create, bool *created_out) :
    directory_path(path),
    created(false),
    initialize_done(false) {

    *created_out = false;
    bool dir_exists = check_existence(directory_path);

    if (!dir_exists) {
        if (!create) {
            throw directory_missing_exc_t(directory_path);
        }
        int mkdir_res;
        do {
            mkdir_res = mkdir(directory_path.path().c_str(), 0755);
        } while (mkdir_res == -1 && get_errno() == EINTR);
        if (mkdir_res != 0) {
            throw directory_create_failed_exc_t(get_errno(), directory_path);
        }
        created = true;
        *created_out = true;

        // Call fsync() on the parent directory to guarantee that the newly
        // created directory's directory entry is persisted to disk.
        warn_fsync_parent_directory(directory_path.path().c_str());
    } else if (create && check_dir_emptiness(directory_path)) {
        created = true;
        *created_out = true;
    }

    directory_fd.reset(::open(directory_path.path().c_str(), O_RDONLY));
    if (directory_fd.get() == INVALID_FD) {
        throw directory_open_failed_exc_t(get_errno(), directory_path);
    }

    if (flock(directory_fd.get(), LOCK_EX | LOCK_NB) != 0) {
        throw directory_locked_exc_t(directory_path);
    }
}

directory_lock_t::~directory_lock_t() {
    // Only delete the directory if we created it and haven't finished initialization
    if (created && !initialize_done) {
        remove_directory_recursive(directory_path.path().c_str());
    }
}

void directory_lock_t::directory_initialized() {
    guarantee(directory_fd.get() != INVALID_FD);
    initialize_done = true;
}

void directory_lock_t::change_ownership(gid_t group_id, const std::string &group_name,
                                        uid_t user_id, const std::string &user_name) {
    if (group_id != INVALID_GID || user_id != INVALID_UID) {
        if (fchown(directory_fd.get(), user_id, group_id) != 0) {
            throw std::runtime_error(strprintf("Failed to change ownership of data "
                                               "directory '%s' to '%s:%s': %s",
                                               directory_path.path().c_str(),
                                               user_name.c_str(),
                                               group_name.c_str(),
                                               errno_string(get_errno()).c_str()));
        }
    }
}
<|endoftext|>


<commit_before>#include "setupHeadmount.h"

#include <fstream>

using namespace Setup;

static const char* preloadPosition = "../../../res/headmount_pos.txt";
static std::vector<cv::Point> userPoints;

void mouseHandler(int event, int x, int y, int flags, void* param) {
	switch(event) {
		case CV_EVENT_LBUTTONUP:
			userPoints.push_back(cv::Point(x,y));
			break;
	}
}

cv::Rect arrangePoints(cv::Point a, cv::Point b) {
	cv::Rect r( fmin(a.x, b.x), fmin(a.y, b.y), 0, 0 );
	r.width = fmax(a.x, b.x) - r.x;
	r.height = fmax(a.y, b.y) - r.y;
	return r;
}

RectPair Headmount::askUserForInput(cv::VideoCapture cam, cv::String window) {
	cv::Mat frame;

	FILE *file = fopen(preloadPosition, "r");
	bool shouldWriteToFile = true;
	cv::Point ltl, lbr, rtl, rbr;
	if ( file && fscanf(file, "[%d %d] [%d %d] - [%d %d] [%d %d]\n", &ltl.x, &ltl.y, &lbr.x, &lbr.y, &rtl.x, &rtl.y, &rbr.x, &rbr.y) ) {
		userPoints.push_back(ltl);
		userPoints.push_back(lbr);
		userPoints.push_back(rtl);
		userPoints.push_back(rbr);
		userPoints.push_back(ltl); // because 5 points are needed for manual setup
		shouldWriteToFile = false;
	}
	fclose(file);

	setMouseCallback(window, mouseHandler, NULL);

	while (userPoints.size() < 5) { // + 1 to allow redo with esc key

		cam.read(frame);
		if (frame.empty())
			continue;

		cv::flip(frame, frame, 1);

		// User instructions
		cv::String infoText = "Mouse click to select eye regions (ESC undo)";
		if (userPoints.size() == 4)
			infoText = "Confirm selection with another click.";
		cv::putText(frame, infoText, cv::Point(10, frame.rows - 10), cv::FONT_HERSHEY_PLAIN, 2.0f, cv::Scalar(255,255,255));

		// Draw current selection
		for (int i = 0; i < userPoints.size(); i++) {
			circle(frame, userPoints[i], 3, 1234);

			if ((i % 2) == 0 && (i+1) < userPoints.size())
				rectangle(frame, userPoints[i], userPoints[i+1], 200);
		}
		imshow(window, frame);

		// Undo selection
		if( cv::waitKey(300) == 27 ) { // escape key
			if (userPoints.size() == 0)
				exit(EXIT_FAILURE);
			userPoints.pop_back();
		}
	}

	setMouseCallback(window, nullptr, NULL);

	if (shouldWriteToFile) {
		std::ofstream outputStream(preloadPosition);
		outputStream
		<< "[" << userPoints[0].x << " " << userPoints[0].y << "] "
		<< "[" << userPoints[1].x << " " << userPoints[1].y << "] - "
		<< "[" << userPoints[2].x << " " << userPoints[2].y << "] "
		<< "[" << userPoints[3].x << " " << userPoints[3].y << "]\n";
		outputStream.close();
	}

	cv::Rect l = arrangePoints(userPoints[0], userPoints[1]);
	cv::Rect r = arrangePoints(userPoints[2], userPoints[3]);
	if (l.x < r.x) {
		return std::make_pair(l, r);
	} else {
		return std::make_pair(r, l);
	}
}
<commit_msg>Headmount setup refactor<commit_after>#include "setupHeadmount.h"

#include <fstream>

using namespace Setup;

static const char* preloadPosition = "../../../res/headmount_pos.txt";
static std::vector<cv::Point> userPoints;

void mouseHandler(int event, int x, int y, int flags, void* param) {
	switch(event) {
		case CV_EVENT_LBUTTONUP:
			if (userPoints.size() < 4)
				userPoints.push_back(cv::Point(x,y));
			break;
	}
}

cv::Rect arrangePoints(cv::Point a, cv::Point b) {
	cv::Rect r( fmin(a.x, b.x), fmin(a.y, b.y), 0, 0 );
	r.width = fmax(a.x, b.x) - r.x;
	r.height = fmax(a.y, b.y) - r.y;
	return r;
}

void loadFromFile(const char* path) {
	FILE *file = fopen(path, "r");
	cv::Point ltl, lbr, rtl, rbr;
	if ( file && fscanf(file, "[%d %d] [%d %d] - [%d %d] [%d %d]\n", &ltl.x, &ltl.y, &lbr.x, &lbr.y, &rtl.x, &rtl.y, &rbr.x, &rbr.y) ) {
		userPoints.push_back(ltl);
		userPoints.push_back(lbr);
		userPoints.push_back(rtl);
		userPoints.push_back(rbr);
	}
	fclose(file);
}

void saveToFile(const char* path) {
	std::ofstream outputStream(path);
	outputStream
	<< "[" << userPoints[0].x << " " << userPoints[0].y << "] "
	<< "[" << userPoints[1].x << " " << userPoints[1].y << "] - "
	<< "[" << userPoints[2].x << " " << userPoints[2].y << "] "
	<< "[" << userPoints[3].x << " " << userPoints[3].y << "]\n";
	outputStream.close();
}

RectPair Headmount::askUserForInput(cv::VideoCapture cam, cv::String window) {
	cv::Mat frame;

	setMouseCallback(window, mouseHandler, NULL);

	while (true) {

		cam.read(frame);
		if (frame.empty())
			continue;

		cv::flip(frame, frame, 1);

		// User instructions
		cv::String infoText = "Mouse click to select eye regions (ESC undo)";
		if (userPoints.size() == 4)
			infoText = "Confirm selection with spacebar.";
		cv::putText(frame, infoText, cv::Point(10, frame.rows - 10), cv::FONT_HERSHEY_PLAIN, 2.0f, cv::Scalar(255,255,255));

		// Draw current selection
		for (int i = 0; i < userPoints.size(); i++) {
			circle(frame, userPoints[i], 3, 1234);

			if ((i % 2) == 0 && (i+1) < userPoints.size())
				rectangle(frame, userPoints[i], userPoints[i+1], 200);
		}
		imshow(window, frame);

		int key = cv::waitKey(300);
		if( key == 27 ) // escape key, undo selection
		{
			if (userPoints.size() == 0)
				exit(EXIT_FAILURE);
			// Undo selection
			userPoints.pop_back();
		}
		else if ( key == 'l' )  // L, load file
		{
			loadFromFile(preloadPosition);
		}
		else if ( key == ' ' ) // spacebar, confirm selection
		{
			if (userPoints.size() == 4)
				break;
		}
	}

	saveToFile(preloadPosition);

	setMouseCallback(window, nullptr, NULL);

	cv::Rect l = arrangePoints(userPoints[0], userPoints[1]);
	cv::Rect r = arrangePoints(userPoints[2], userPoints[3]);
	if (l.x < r.x) {
		return std::make_pair(l, r);
	} else {
		return std::make_pair(r, l);
	}
}
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>

#include "rana.hpp"

void benchmark()
{

    std::fstream file("sample.json");
    std::stringstream ss;
    ss << file.rdbuf();
    std::string file_string = ss.str();
    rana::parser parser;
    rana::value result;

    std::chrono::high_resolution_clock clock;
    auto start = clock.now();

    for(int i = 0; i < 1000; i++)
    {
        parser.set_buffer(file_string.data(), file_string.length());
        parser.parse_next(result);
    }

    auto elapsed = clock.now() - start;
    std::cout << elapsed.count() / 10000000.0 << std::endl;
}

int main()
{
    benchmark();
    return 0;
}
<commit_msg>fix unused variable warning and pause when done benchmarking<commit_after>#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>

#include "rana.hpp"

void benchmark()
{

    std::fstream file("sample.json");
    std::stringstream ss;
    ss << file.rdbuf();
    std::string file_string = ss.str();

    auto start = std::chrono::high_resolution_clock::now();

	rana::parser parser;
	rana::value result;

    for(int i = 0; i < 1000; i++)
    {
        parser.set_buffer(file_string.data(), file_string.length());
        parser.parse_next(result);
    }

	auto elapsed = std::chrono::high_resolution_clock::now() - start;
    std::cout << elapsed.count() * 1.0 / std::chrono::high_resolution_clock::period::den << std::endl;
}

int main()
{
    benchmark();
	int a = 0;
	std::cin >> a;
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>initialize variable<commit_after><|endoftext|>


<commit_before>
#include <gmock/gmock.h>

#include <liblocate/utils.h>

class utils_test : public testing::Test
{
public:
    utils_test()
    {
    }
};
<commit_msg>Start tests<commit_after>
#include <gmock/gmock.h>

#include <liblocate/utils.h>

class utils_test : public testing::Test
{
public:
    utils_test()
    {
    }
};

TEST_F(utils_test, unifiedPath_NoPath)
{
    char * str1 = "A-string";

    unifiedPath(str1, strlen(str1));

    EXPECT_STREQ(str1, "A-string");
}

TEST_F(utils_test, unifiedPath_UnixPath)
{
    char * str1 = "/usr/include/c++/v1/tuple";

    unifiedPath(str1, strlen(str1));

    EXPECT_STREQ(str1, "/usr/include/c++/v1/tuple");
}

TEST_F(utils_test, unifiedPath_WindowsPath)
{
    char * str1 = "C:\\dev\\include\\c++\\v1\\tuple";

    unifiedPath(str1, strlen(str1));

    EXPECT_STREQ(str1, "C:/dev/include/c++/v1/tuple");
}
<|endoftext|>