<commit_before>/*************************************************************************
 *
 *  $RCSfile: except.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: dbo $ $Date: 2001-10-19 13:32:39 $
 *
 *  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 <stdio.h>
#include <dlfcn.h>
#include <hash_map>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <bridges/cpp_uno/bridge.hxx>
#include <typelib/typedescription.hxx>
#include <uno/any2.h>

#include "share.hxx"

using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::__cxxabiv1;

namespace CPPU_CURRENT_NAMESPACE
{

//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW( () )
{
char const * start = p;
//      N3com3sun4star4lang24IllegalArgumentExceptionE

    OUStringBuffer buf( 64 );
    OSL_ASSERT( 'N' == *p );
    ++p; // skip N

    while ('E' != *p)
    {
        // read chars count
        long n = (*p++ - '0');
        while ('0' <= *p && '9' >= *p)
        {
            n *= 10;
            n += (*p++ - '0');
        }
        buf.appendAscii( p, n );
        p += n;
        if ('E' != *p)
            buf.append( (sal_Unicode)'.' );
    }

#ifdef DEBUG
    OUString ret( buf.makeStringAndClear() );
    OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}
//==================================================================================================
static OString toRTTIname( OUString const & unoName ) SAL_THROW( () )
{
    OStringBuffer buf( 64 );

    buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
    sal_Int32 index = 0;
    do
    {
        OUString token( unoName.getToken( 0, '.', index ) );
        buf.append( token.getLength() );
        OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
        buf.append( c_token );
    }
    while (index >= 0);
    buf.append( 'E' );

#ifdef DEBUG
    OString ret( buf.makeStringAndClear() );
    OString str( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toRTTIname(): %s => %s\n", str.getStr(), ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}

//==================================================================================================
class RTTI
{
    typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map;

    Mutex m_mutex;
    t_rtti_map m_rttis;

public:
    type_info * getRTTI( OUString const & unoName ) SAL_THROW( () );
};
//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( OUString const & unoName ) SAL_THROW( () )
{
    static void * s_hApp = dlopen( 0, RTLD_LAZY );
    type_info * rtti;

    MutexGuard guard( m_mutex );
    t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
    if (iFind == m_rttis.end())
    {
        OString rttiName( toRTTIname( unoName ) );
        rtti = (type_info *)dlsym( s_hApp, rttiName.getStr() );
        if (rtti)
        {
            pair< t_rtti_map::iterator, bool > insertion(
                m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
            OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
        }
    }
    else
    {
        rtti = iFind->second;
    }

    return rtti;
}

//--------------------------------------------------------------------------------------------------
static void deleteException( void* pExc )
{
    __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
    typelib_TypeDescription * pTD = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pTD, unoName.pData );
    OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
    if (pTD)
    {
        ::uno_destructData( pExc, pTD, cpp_release );
        ::typelib_typedescription_release( pTD );
    }
}

//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
    void * pCppExc;
    type_info * rtti;

    fprintf( stderr, ">1\n" );
    {
    // construct cpp exception object
    typelib_TypeDescription * pTypeDescr = 0;
    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
    OSL_ASSERT( pTypeDescr );
    if (! pTypeDescr)
        terminate();

    pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );

    // destruct uno exception
    ::uno_any_destruct( pUnoExc, 0 );
    // avoiding locked counts
    OUString const & unoName = *(OUString const *)&pTypeDescr->pTypeName;
    static RTTI * s_rtti = 0;
    if (! s_rtti)
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (! s_rtti)
        {
#ifdef LEAK_STATIC_DATA
            s_rtti = new RTTI();
#else
            static RTTI rtti_data;
            s_rtti = &rtti_data;
#endif
        }
    }
    rtti = (type_info *)s_rtti->getRTTI( unoName );
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
    if (! rtti)
        terminate();
    }

    __cxa_throw( pCppExc, rtti, deleteException );
}

//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno )
{
    OSL_ENSURE( header, "### no exception header!!!" );
    if (! header)
        terminate();

    typelib_TypeDescription * pExcTypeDescr = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
    OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" );
    if (! pExcTypeDescr)
        terminate();

    // construct uno exception any
    ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
    ::typelib_typedescription_release( pExcTypeDescr );
}

}

<commit_msg>#92951#<commit_after>/*************************************************************************
 *
 *  $RCSfile: except.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: dbo $ $Date: 2001-10-19 14:31:48 $
 *
 *  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 <stdio.h>
#include <dlfcn.h>
#include <hash_map>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <bridges/cpp_uno/bridge.hxx>
#include <typelib/typedescription.hxx>
#include <uno/any2.h>

#include "share.hxx"

using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::__cxxabiv1;

namespace CPPU_CURRENT_NAMESPACE
{

//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW( () )
{
char const * start = p;
//      N3com3sun4star4lang24IllegalArgumentExceptionE

    OUStringBuffer buf( 64 );
    OSL_ASSERT( 'N' == *p );
    ++p; // skip N

    while ('E' != *p)
    {
        // read chars count
        long n = (*p++ - '0');
        while ('0' <= *p && '9' >= *p)
        {
            n *= 10;
            n += (*p++ - '0');
        }
        buf.appendAscii( p, n );
        p += n;
        if ('E' != *p)
            buf.append( (sal_Unicode)'.' );
    }

#ifdef DEBUG
    OUString ret( buf.makeStringAndClear() );
    OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}
//==================================================================================================
static OString toRTTIname( OUString const & unoName ) SAL_THROW( () )
{
    OStringBuffer buf( 64 );

    buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
    sal_Int32 index = 0;
    do
    {
        OUString token( unoName.getToken( 0, '.', index ) );
        buf.append( token.getLength() );
        OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
        buf.append( c_token );
    }
    while (index >= 0);
    buf.append( 'E' );

#ifdef DEBUG
    OString ret( buf.makeStringAndClear() );
    OString str( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toRTTIname(): %s => %s\n", str.getStr(), ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}

//==================================================================================================
class RTTI
{
    typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map;

    Mutex m_mutex;
    t_rtti_map m_rttis;

public:
    type_info * getRTTI( OUString const & unoName ) SAL_THROW( () );
};
//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( OUString const & unoName ) SAL_THROW( () )
{
    static void * s_hApp = dlopen( 0, RTLD_LAZY );
    type_info * rtti;

    MutexGuard guard( m_mutex );
    t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
    if (iFind == m_rttis.end())
    {
        OString rttiName( toRTTIname( unoName ) );
        rtti = (type_info *)dlsym( s_hApp, rttiName.getStr() );
        if (rtti)
        {
            pair< t_rtti_map::iterator, bool > insertion(
                m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
            OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
        }
    }
    else
    {
        rtti = iFind->second;
    }

    return rtti;
}

//--------------------------------------------------------------------------------------------------
static void deleteException( void* pExc )
{
    __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
    typelib_TypeDescription * pTD = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pTD, unoName.pData );
    OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
    if (pTD)
    {
        ::uno_destructData( pExc, pTD, cpp_release );
        ::typelib_typedescription_release( pTD );
    }
}

//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
    void * pCppExc;
    type_info * rtti;

    {
    // construct cpp exception object
    typelib_TypeDescription * pTypeDescr = 0;
    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
    OSL_ASSERT( pTypeDescr );
    if (! pTypeDescr)
        terminate();

    pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );

    // destruct uno exception
    ::uno_any_destruct( pUnoExc, 0 );
    // avoiding locked counts
    OUString const & unoName = *(OUString const *)&pTypeDescr->pTypeName;
    static RTTI * s_rtti = 0;
    if (! s_rtti)
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (! s_rtti)
        {
#ifdef LEAK_STATIC_DATA
            s_rtti = new RTTI();
#else
            static RTTI rtti_data;
            s_rtti = &rtti_data;
#endif
        }
    }
    rtti = (type_info *)s_rtti->getRTTI( unoName );
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
    if (! rtti)
        terminate();
    }

    __cxa_throw( pCppExc, rtti, deleteException );
}

//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pExc, uno_Mapping * pCpp2Uno )
{
    OSL_ENSURE( header, "### no exception header!!!" );
    if (! header)
        terminate();

    typelib_TypeDescription * pExcTypeDescr = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
    OSL_ENSURE( pExcTypeDescr, "### can not get type description for exception!!!" );
    if (! pExcTypeDescr)
        terminate();

    // construct uno exception any
    ::uno_any_constructAndConvert( pExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
    ::typelib_typedescription_release( pExcTypeDescr );
}

}

<|endoftext|>


<commit_before>// The Art of C++ / Utility
// Copyright (c) 2016-2018 Daniel Frey

#include <tao/utility/getenv.hpp>

#include <cstdlib>
#include <stdexcept>

namespace tao
{
   namespace utility
   {
#if defined( _MSC_VER )
      std::string getenv( const std::string& name )
      {
         char* buf = nullptr;
         if( _dupenv_s( &buf, nullptr, name.c_str() ) == 0 && buf != nullptr ) {
            const std::unique_ptr< char, decltype( &std::free ) > up( buf, &std::free );
            return up.get();
         }
         throw std::runtime_error( "environment variable not found: " + name );
      }

      std::string getenv( const std::string& name, const std::string& default_value )
      {
         char* buf = nullptr;
         if( _dupenv_s( &buf, nullptr, name.c_str() ) == 0 && buf != nullptr ) {
            const std::unique_ptr< char, decltype( &std::free ) > up( buf, &std::free );
            return up.get();
         }
         return default_value;
      }
#else
      std::string getenv( const std::string& name )
      {
         const char* result = std::getenv( name.c_str() );
         return result ? result : throw std::runtime_error( "environment variable not found: " + name );
      }

      std::string getenv( const std::string& name, const std::string& default_value )
      {
         const char* result = std::getenv( name.c_str() );
         return result ? result : default_value;
      }
#endif
   }
}
<commit_msg>Add missing header<commit_after>// The Art of C++ / Utility
// Copyright (c) 2016-2018 Daniel Frey

#include <tao/utility/getenv.hpp>

#include <cstdlib>
#include <stdexcept>

#if defined( _MSC_VER )
#include <memory>
#endif

namespace tao
{
   namespace utility
   {
#if defined( _MSC_VER )
      std::string getenv( const std::string& name )
      {
         char* buf = nullptr;
         std::size_t sz = 0;
         if( _dupenv_s( &buf, &sz, name.c_str() ) == 0 && buf != nullptr ) {
            const std::unique_ptr< char, decltype( &std::free ) > up( buf, &std::free );
            return std::string( up.get(), sz );
         }
         throw std::runtime_error( "environment variable not found: " + name );
      }

      std::string getenv( const std::string& name, const std::string& default_value )
      {
         char* buf = nullptr;
         std::size_t sz = 0;
         if( _dupenv_s( &buf, &sz, name.c_str() ) == 0 && buf != nullptr ) {
            const std::unique_ptr< char, decltype( &std::free ) > up( buf, &std::free );
            return std::string( up.get(), sz );
         }
         return default_value;
      }
#else
      std::string getenv( const std::string& name )
      {
         const char* result = std::getenv( name.c_str() );
         return result ? result : throw std::runtime_error( "environment variable not found: " + name );
      }

      std::string getenv( const std::string& name, const std::string& default_value )
      {
         const char* result = std::getenv( name.c_str() );
         return result ? result : default_value;
      }
#endif
   }
}
<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    enum {start, end, height};
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        return ComputeSkylineInInterval(buildings, 0, buildings.size());
    }

    // Divide and Conquer.
    vector<vector<int>> ComputeSkylineInInterval(const vector<vector<int>>& buildings,
                                                 int left_endpoint, int right_endpoint) {
        if (right_endpoint - left_endpoint <= 1) {  // 0 or 1 skyline, just copy it.
            return {buildings.cbegin() + left_endpoint,
                buildings.cbegin() + right_endpoint};
        }
        int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
        auto left_skyline = ComputeSkylineInInterval(buildings, left_endpoint, mid);
        auto right_skyline = ComputeSkylineInInterval(buildings, mid, right_endpoint);
        return MergeSkylines(left_skyline, right_skyline);
    }

    // Merge Sort
    vector<vector<int>> MergeSkylines(vector<vector<int>>& left_skyline, vector<vector<int>>& right_skyline) {
        int i = 0, j = 0;
        vector<vector<int>> merged;

        while (i < left_skyline.size() && j < right_skyline.size()) {
            if (left_skyline[i][end] < right_skyline[j][start]) {
                merged.emplace_back(left_skyline[i++]);
            } else if (right_skyline[j][end] < left_skyline[i][start]) {
                merged.emplace_back(right_skyline[j++]);
            } else if (left_skyline[i][start] <= right_skyline[j][start]) {
                MergeIntersectSkylines(merged, left_skyline[i], i,
                                       right_skyline[j], j);
            } else {  // left_skyline[i][start] > right_skyline[j][start].
                MergeIntersectSkylines(merged, right_skyline[j], j,
                                       left_skyline[i], i);
            }
        }

        // Insert the remaining skylines.
        merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
        merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
        return merged;
    }

    // a[start] <= b[start]
    void MergeIntersectSkylines(vector<vector<int>>& merged, vector<int>& a, int& a_idx,
                                vector<int>& b, int& b_idx) {
        if (a[end] <= b[end]) {
            if (a[height] > b[height]) {  // |aaa|
                if (b[end] != a[end]) {   // |abb|b
                    merged.emplace_back(a), ++a_idx;
                    b[start] = a[end];
                } else {        // aaa
                    ++b_idx;    // abb
                }
            } else if (a[height] == b[height]) { // abb
                b[start] = a[start], ++a_idx;    // abb
            } else {  // a[height] < b[height].
                if (a[start] != b[start]) {                                           //    bb
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});  // |a|bb
                }
                ++a_idx;
            }
        } else {  // a[end] > b[end].
            if (a[height] >= b[height]) {  // aaaa
                ++b_idx;                   // abba
            } else {
                //    |bb|
                // |a||bb|a
                if (a[start] != b[start]) {
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});
                }
                a[start] = b[end];
                merged.emplace_back(b), ++b_idx;
            }
        }
    }
};

// Time:  O(nlogn)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        unordered_map<int, vector<int>> start_point_to_heights;
        unordered_map<int, vector<int>> end_point_to_heights;
        set<int> points;

        for (int i = 0; i < buildings.size(); ++i) {
            start_point_to_heights[buildings[i][0]].push_back(buildings[i][2]);
            end_point_to_heights[buildings[i][1]].push_back(buildings[i][2]);
            points.emplace(buildings[i][0]);
            points.emplace(buildings[i][1]);
        }

        vector<vector<int>> res;
        map<int, int> height_to_count;
        int curr_start = -1;
        int curr_max = 0;
        // Enumerate each point in increasing order.
        for (auto it = points.begin(); it != points.end(); ++it) {
            vector<int> start_point_heights = start_point_to_heights[*it];
            vector<int> end_point_heights = end_point_to_heights[*it];

            for (int i = 0; i < start_point_heights.size(); ++i) {
                ++height_to_count[start_point_heights[i]];
            }

            for (int i = 0; i < end_point_heights.size(); ++i) {
                --height_to_count[end_point_heights[i]];
                if (height_to_count[end_point_heights[i]] == 0) {
                    height_to_count.erase(end_point_heights[i]);
                }
            }

            if (height_to_count.empty() || curr_max != height_to_count.rbegin()->first) {
                if (curr_max > 0) {
                    res.emplace_back(move(vector<int>{curr_start, *it, curr_max}));
                }
                curr_start = *it;
                curr_max = height_to_count.empty() ? 0 : height_to_count.rbegin()->first;
            }
        }
        return res;
    }
};

<commit_msg>Update building-outline.cpp<commit_after>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    enum {start, end, height};
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        return ComputeSkylineInInterval(buildings, 0, buildings.size());
    }

    // Divide and Conquer.
    vector<vector<int>> ComputeSkylineInInterval(const vector<vector<int>>& buildings,
                                                 int left_endpoint, int right_endpoint) {
        if (right_endpoint - left_endpoint <= 1) {  // 0 or 1 skyline, just copy it.
            return {buildings.cbegin() + left_endpoint,
                    buildings.cbegin() + right_endpoint};
        }
        int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
        auto left_skyline = move(ComputeSkylineInInterval(buildings, left_endpoint, mid));
        auto right_skyline = move(ComputeSkylineInInterval(buildings, mid, right_endpoint));
        return MergeSkylines(left_skyline, right_skyline);
    }

    // Merge Sort
    vector<vector<int>> MergeSkylines(vector<vector<int>>& left_skyline, vector<vector<int>>& right_skyline) {
        int i = 0, j = 0;
        vector<vector<int>> merged;

        while (i < left_skyline.size() && j < right_skyline.size()) {
            if (left_skyline[i][end] < right_skyline[j][start]) {
                merged.emplace_back(move(left_skyline[i++]));
            } else if (right_skyline[j][end] < left_skyline[i][start]) {
                merged.emplace_back(move(right_skyline[j++]));
            } else if (left_skyline[i][start] <= right_skyline[j][start]) {
                MergeIntersectSkylines(merged, left_skyline[i], i,
                                       right_skyline[j], j);
            } else {  // left_skyline[i][start] > right_skyline[j][start].
                MergeIntersectSkylines(merged, right_skyline[j], j,
                                       left_skyline[i], i);
            }
        }

        // Insert the remaining skylines.
        merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
        merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
        return merged;
    }

    // a[start] <= b[start]
    void MergeIntersectSkylines(vector<vector<int>>& merged, vector<int>& a, int& a_idx,
                                vector<int>& b, int& b_idx) {
        if (a[end] <= b[end]) {
            if (a[height] > b[height]) {  // |aaa|
                if (b[end] != a[end]) {   // |abb|b
                    b[start] = a[end];
                    merged.emplace_back(move(a)), ++a_idx;
                } else {        // aaa
                    ++b_idx;    // abb
                }
            } else if (a[height] == b[height]) { // abb
                b[start] = a[start], ++a_idx;    // abb
            } else {  // a[height] < b[height].
                if (a[start] != b[start]) {                                           //    bb
                    merged.emplace_back(move(vector<int>{a[start], b[start], a[height]}));  // |a|bb
                }
                ++a_idx;
            }
        } else {  // a[end] > b[end].
            if (a[height] >= b[height]) {  // aaaa
                ++b_idx;                   // abba
            } else {
                //    |bb|
                // |a||bb|a
                if (a[start] != b[start]) {
                    merged.emplace_back(move(vector<int>{a[start], b[start], a[height]}));
                }
                a[start] = b[end];
                merged.emplace_back(b), ++b_idx;
            }
        }
    }
};

// Time:  O(nlogn)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        unordered_map<int, vector<int>> start_point_to_heights;
        unordered_map<int, vector<int>> end_point_to_heights;
        set<int> points;

        for (int i = 0; i < buildings.size(); ++i) {
            start_point_to_heights[buildings[i][0]].push_back(buildings[i][2]);
            end_point_to_heights[buildings[i][1]].push_back(buildings[i][2]);
            points.emplace(buildings[i][0]);
            points.emplace(buildings[i][1]);
        }

        vector<vector<int>> res;
        map<int, int> height_to_count;
        int curr_start = -1;
        int curr_max = 0;
        // Enumerate each point in increasing order.
        for (auto it = points.begin(); it != points.end(); ++it) {
            vector<int> start_point_heights = start_point_to_heights[*it];
            vector<int> end_point_heights = end_point_to_heights[*it];

            for (int i = 0; i < start_point_heights.size(); ++i) {
                ++height_to_count[start_point_heights[i]];
            }

            for (int i = 0; i < end_point_heights.size(); ++i) {
                --height_to_count[end_point_heights[i]];
                if (height_to_count[end_point_heights[i]] == 0) {
                    height_to_count.erase(end_point_heights[i]);
                }
            }

            if (height_to_count.empty() || curr_max != height_to_count.rbegin()->first) {
                if (curr_max > 0) {
                    res.emplace_back(move(vector<int>{curr_start, *it, curr_max}));
                }
                curr_start = *it;
                curr_max = height_to_count.empty() ? 0 : height_to_count.rbegin()->first;
            }
        }
        return res;
    }
};

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: except.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 15:49:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <stdio.h>
#include <dlfcn.h>
#include <cxxabi.h>
#include <hash_map>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <com/sun/star/uno/genfunc.hxx>
#include <typelib/typedescription.hxx>
#include <uno/any2.h>

#include "share.hxx"

using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::__cxxabiv1;

namespace CPPU_CURRENT_NAMESPACE
{

void dummy_can_throw_anything( char const * )
{
}

//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW( () )
{
#if defined BRIDGES_DEBUG
    char const * start = p;
#endif

    // example: N3com3sun4star4lang24IllegalArgumentExceptionE

    OUStringBuffer buf( 64 );
    OSL_ASSERT( 'N' == *p );
    ++p; // skip N

    while ('E' != *p)
    {
        // read chars count
        long n = (*p++ - '0');
        while ('0' <= *p && '9' >= *p)
        {
            n *= 10;
            n += (*p++ - '0');
        }
        buf.appendAscii( p, n );
        p += n;
        if ('E' != *p)
            buf.append( (sal_Unicode)'.' );
    }

#if defined BRIDGES_DEBUG
    OUString ret( buf.makeStringAndClear() );
    OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}

//==================================================================================================
class RTTI
{
    typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map;

    Mutex m_mutex;
    t_rtti_map m_rttis;
    t_rtti_map m_generatedRttis;

    void * m_hApp;

public:
    RTTI() SAL_THROW( () );
    ~RTTI() SAL_THROW( () );

    type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () );
};
//__________________________________________________________________________________________________
RTTI::RTTI() SAL_THROW( () )
    : m_hApp( dlopen( 0, RTLD_LAZY ) )
{
}
//__________________________________________________________________________________________________
RTTI::~RTTI() SAL_THROW( () )
{
    dlclose( m_hApp );
}

//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () )
{
    type_info * rtti;

    OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;

    MutexGuard guard( m_mutex );
    t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
    if (iFind == m_rttis.end())
    {
        // RTTI symbol
        OStringBuffer buf( 64 );
        buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
        sal_Int32 index = 0;
        do
        {
            OUString token( unoName.getToken( 0, '.', index ) );
            buf.append( token.getLength() );
            OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
            buf.append( c_token );
        }
        while (index >= 0);
        buf.append( 'E' );

        OString symName( buf.makeStringAndClear() );
        rtti = (type_info *)dlsym( m_hApp, symName.getStr() );

        if (rtti)
        {
            pair< t_rtti_map::iterator, bool > insertion(
                m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
            OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
        }
        else
        {
            // try to lookup the symbol in the generated rtti map
            t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) );
            if (iFind == m_generatedRttis.end())
            {
                // we must generate it !
                // symbol and rtti-name is nearly identical,
                // the symbol is prefixed with _ZTI
                char const * rttiName = symName.getStr() +4;
#if defined BRIDGES_DEBUG
                fprintf( stderr,"generated rtti for %s\n", rttiName );
#endif
                if (pTypeDescr->pBaseTypeDescription)
                {
                    // ensure availability of base
                    type_info * base_rtti = getRTTI(
                        (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
                    rtti = new __si_class_type_info(
                        strdup( rttiName ), (__class_type_info *)base_rtti );
                }
                else
                {
                    // this class has no base class
                    rtti = new __class_type_info( strdup( rttiName ) );
                }

                pair< t_rtti_map::iterator, bool > insertion(
                    m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
                OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" );
            }
            else // taking already generated rtti
            {
                rtti = iFind->second;
            }
        }
    }
    else
    {
        rtti = iFind->second;
    }

    return rtti;
}

//--------------------------------------------------------------------------------------------------
static void deleteException( void * pExc )
{
    __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
    typelib_TypeDescription * pTD = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pTD, unoName.pData );
    OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
    if (pTD)
    {
        ::uno_destructData( pExc, pTD, cpp_release );
        ::typelib_typedescription_release( pTD );
    }
}

//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
#if defined BRIDGES_DEBUG
    OString cstr(
        OUStringToOString(
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() );
#endif
    void * pCppExc;
    type_info * rtti;

    {
    // construct cpp exception object
    typelib_TypeDescription * pTypeDescr = 0;
    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
    OSL_ASSERT( pTypeDescr );
    if (! pTypeDescr)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }

    pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );

    // destruct uno exception
    ::uno_any_destruct( pUnoExc, 0 );
    // avoiding locked counts
    static RTTI * s_rtti = 0;
    if (! s_rtti)
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (! s_rtti)
        {
#ifdef LEAK_STATIC_DATA
            s_rtti = new RTTI();
#else
            static RTTI rtti_data;
            s_rtti = &rtti_data;
#endif
        }
    }
    rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
    if (! rtti)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }
    }

    __cxa_throw( pCppExc, rtti, deleteException );
}

//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
    if (! header)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if defined _DEBUG
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_ENSURE( 0, cstr.getStr() );
#endif
        return;
    }

    typelib_TypeDescription * pExcTypeDescr = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
#if defined BRIDGES_DEBUG
    OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> c++ exception occured: %s\n", cstr_unoName.getStr() );
#endif
    typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
    if (0 == pExcTypeDescr)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if defined _DEBUG
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_ENSURE( 0, cstr.getStr() );
#endif
    }
    else
    {
        // construct uno exception any
        uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
        typelib_typedescription_release( pExcTypeDescr );
    }
}

}

<commit_msg>INTEGRATION: CWS jw2 (1.5.18); FILE MERGED 2006/11/09 03:13:21 sparcmoz 1.5.18.1: #i71180#: remove warnings for gcc 4.1.2<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: except.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2006-11-22 11:07:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <stdio.h>
#include <dlfcn.h>
#include <cxxabi.h>
#include <hash_map>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <com/sun/star/uno/genfunc.hxx>
#include <typelib/typedescription.hxx>
#include <uno/any2.h>

#include "share.hxx"

using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::__cxxabiv1;

namespace CPPU_CURRENT_NAMESPACE
{

void dummy_can_throw_anything( char const * )
{
}

//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW( () )
{
#if defined BRIDGES_DEBUG
    char const * start = p;
#endif

    // example: N3com3sun4star4lang24IllegalArgumentExceptionE

    OUStringBuffer buf( 64 );
    OSL_ASSERT( 'N' == *p );
    ++p; // skip N

    while ('E' != *p)
    {
        // read chars count
        long n = (*p++ - '0');
        while ('0' <= *p && '9' >= *p)
        {
            n *= 10;
            n += (*p++ - '0');
        }
        buf.appendAscii( p, n );
        p += n;
        if ('E' != *p)
            buf.append( (sal_Unicode)'.' );
    }

#if defined BRIDGES_DEBUG
    OUString ret( buf.makeStringAndClear() );
    OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}

//==================================================================================================
class RTTI
{
    typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map;

    Mutex m_mutex;
    t_rtti_map m_rttis;
    t_rtti_map m_generatedRttis;

    void * m_hApp;

public:
    RTTI() SAL_THROW( () );
    ~RTTI() SAL_THROW( () );

    type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () );
};
//__________________________________________________________________________________________________
RTTI::RTTI() SAL_THROW( () )
    : m_hApp( dlopen( 0, RTLD_LAZY ) )
{
}
//__________________________________________________________________________________________________
RTTI::~RTTI() SAL_THROW( () )
{
    dlclose( m_hApp );
}

//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () )
{
    type_info * rtti;

    OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;

    MutexGuard guard( m_mutex );
    t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
    if (iFind == m_rttis.end())
    {
        // RTTI symbol
        OStringBuffer buf( 64 );
        buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
        sal_Int32 index = 0;
        do
        {
            OUString token( unoName.getToken( 0, '.', index ) );
            buf.append( token.getLength() );
            OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
            buf.append( c_token );
        }
        while (index >= 0);
        buf.append( 'E' );

        OString symName( buf.makeStringAndClear() );
        rtti = (type_info *)dlsym( m_hApp, symName.getStr() );

        if (rtti)
        {
            pair< t_rtti_map::iterator, bool > insertion(
                m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
            OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
        }
        else
        {
            // try to lookup the symbol in the generated rtti map
            t_rtti_map::const_iterator iiFind( m_generatedRttis.find( unoName ) );
            if (iiFind == m_generatedRttis.end())
            {
                // we must generate it !
                // symbol and rtti-name is nearly identical,
                // the symbol is prefixed with _ZTI
                char const * rttiName = symName.getStr() +4;
#if defined BRIDGES_DEBUG
                fprintf( stderr,"generated rtti for %s\n", rttiName );
#endif
                if (pTypeDescr->pBaseTypeDescription)
                {
                    // ensure availability of base
                    type_info * base_rtti = getRTTI(
                        (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
                    rtti = new __si_class_type_info(
                        strdup( rttiName ), (__class_type_info *)base_rtti );
                }
                else
                {
                    // this class has no base class
                    rtti = new __class_type_info( strdup( rttiName ) );
                }

                pair< t_rtti_map::iterator, bool > insertion(
                    m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
                OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" );
            }
            else // taking already generated rtti
            {
                rtti = iiFind->second;
            }
        }
    }
    else
    {
        rtti = iFind->second;
    }

    return rtti;
}

//--------------------------------------------------------------------------------------------------
static void deleteException( void * pExc )
{
    __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
    typelib_TypeDescription * pTD = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pTD, unoName.pData );
    OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
    if (pTD)
    {
        ::uno_destructData( pExc, pTD, cpp_release );
        ::typelib_typedescription_release( pTD );
    }
}

//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
#if defined BRIDGES_DEBUG
    OString cstr(
        OUStringToOString(
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() );
#endif
    void * pCppExc;
    type_info * rtti;

    {
    // construct cpp exception object
    typelib_TypeDescription * pTypeDescr = 0;
    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
    OSL_ASSERT( pTypeDescr );
    if (! pTypeDescr)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }

    pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );

    // destruct uno exception
    ::uno_any_destruct( pUnoExc, 0 );
    // avoiding locked counts
    static RTTI * s_rtti = 0;
    if (! s_rtti)
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (! s_rtti)
        {
#ifdef LEAK_STATIC_DATA
            s_rtti = new RTTI();
#else
            static RTTI rtti_data;
            s_rtti = &rtti_data;
#endif
        }
    }
    rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
    if (! rtti)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }
    }

    __cxa_throw( pCppExc, rtti, deleteException );
}

//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
    if (! header)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if defined _DEBUG
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_ENSURE( 0, cstr.getStr() );
#endif
        return;
    }

    typelib_TypeDescription * pExcTypeDescr = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
#if defined BRIDGES_DEBUG
    OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> c++ exception occured: %s\n", cstr_unoName.getStr() );
#endif
    typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
    if (0 == pExcTypeDescr)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if defined _DEBUG
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_ENSURE( 0, cstr.getStr() );
#endif
    }
    else
    {
        // construct uno exception any
        uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
        typelib_typedescription_release( pExcTypeDescr );
    }
}

}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  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
 */
/*
 * @file        admin-api.cpp
 * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
 * @version     1.0
 * @brief       Implementation of external libcynara-admin API
 */

#include <map>
#include <new>
#include <string>
#include <vector>

#include <common.h>
#include <types/Policy.h>
#include <types/PolicyBucketId.h>
#include <types/PolicyKey.h>
#include <types/PolicyResult.h>
#include <types/PolicyType.h>

#include <cynara-admin.h>

#include <api/ApiInterface.h>
#include <logic/Logic.h>

struct cynara_admin {
    Cynara::ApiInterface *impl;

    cynara_admin(Cynara::ApiInterface *_impl) : impl(_impl) {
    }
    ~cynara_admin() {
        delete impl;
    }
};

CYNARA_API
int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) {
    if (!pp_cynara_admin)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    try {
        *pp_cynara_admin = new cynara_admin(new Cynara::Logic);
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_finish(struct cynara_admin *p_cynara_admin) {
    delete p_cynara_admin;

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin,
                              const cynara_admin_policy *const *policies) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!policies)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::map<Cynara::PolicyBucketId, std::vector<Cynara::Policy>> insertOrUpdate;
    std::map<Cynara::PolicyBucketId, std::vector<Cynara::PolicyKey>> remove;

    auto key = ([](const cynara_admin_policy *i)->Cynara::PolicyKey {
        std::string wildcard(CYNARA_ADMIN_WILDCARD);

        auto feature = ([&wildcard] (const char *str)->Cynara::PolicyKeyFeature {
            if (wildcard.compare(str))
                return Cynara::PolicyKeyFeature::create(str);
            else
                return Cynara::PolicyKeyFeature::createWildcard();
        });

        return Cynara::PolicyKey(feature(i->client), feature(i->user), feature(i->privilege));
    });

    try {
        for (auto i = policies; *i; i++) {
            if(!(*i)->bucket || !(*i)->client || !(*i)->user || !(*i)->privilege)
                return CYNARA_ADMIN_API_INVALID_PARAM;

            switch ((*i)->result) {
                case CYNARA_ADMIN_DELETE:
                    remove[(*i)->bucket].push_back(key(*i));
                    break;
                case CYNARA_ADMIN_DENY:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PredefinedPolicyType::DENY));
                    break;
                case CYNARA_ADMIN_ALLOW:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PredefinedPolicyType::ALLOW));
                    break;
                case CYNARA_ADMIN_BUCKET:
                    if (!(*i)->result_extra)
                        return CYNARA_ADMIN_API_INVALID_PARAM;
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PolicyResult(
                                                        Cynara::PredefinedPolicyType::BUCKET,
                                                        (*i)->result_extra)));
                    break;
                default:
                    return CYNARA_ADMIN_API_INVALID_PARAM;
            }
        }
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return p_cynara_admin->impl->setPolicies(insertOrUpdate, remove);
}

CYNARA_API
int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket,
                            int operation, const char *extra) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!bucket)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::string extraStr;
    try {
         extraStr = extra ? extra : "";
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }
    switch (operation) {
        case CYNARA_ADMIN_DELETE:
            return p_cynara_admin->impl->removeBucket(bucket);
        case CYNARA_ADMIN_DENY:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::DENY, extraStr));
        case CYNARA_ADMIN_ALLOW:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::ALLOW, extraStr));
        case CYNARA_ADMIN_BUCKET:
        default:
            return CYNARA_ADMIN_API_INVALID_PARAM;
    }
}
<commit_msg>Enable logs in admin library<commit_after>/*
 *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  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
 */
/*
 * @file        admin-api.cpp
 * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
 * @version     1.0
 * @brief       Implementation of external libcynara-admin API
 */

#include <map>
#include <new>
#include <string>
#include <vector>

#include <common.h>
#include <log/log.h>
#include <types/Policy.h>
#include <types/PolicyBucketId.h>
#include <types/PolicyKey.h>
#include <types/PolicyResult.h>
#include <types/PolicyType.h>

#include <cynara-admin.h>

#include <api/ApiInterface.h>
#include <logic/Logic.h>

struct cynara_admin {
    Cynara::ApiInterface *impl;

    cynara_admin(Cynara::ApiInterface *_impl) : impl(_impl) {
    }
    ~cynara_admin() {
        delete impl;
    }
};

CYNARA_API
int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin) {
    if (!pp_cynara_admin)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    try {
        *pp_cynara_admin = new cynara_admin(new Cynara::Logic);
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    init_log();

    LOGD("Cynara admin initialized");

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_finish(struct cynara_admin *p_cynara_admin) {
    delete p_cynara_admin;

    return CYNARA_ADMIN_API_SUCCESS;
}

CYNARA_API
int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin,
                              const cynara_admin_policy *const *policies) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!policies)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::map<Cynara::PolicyBucketId, std::vector<Cynara::Policy>> insertOrUpdate;
    std::map<Cynara::PolicyBucketId, std::vector<Cynara::PolicyKey>> remove;

    auto key = ([](const cynara_admin_policy *i)->Cynara::PolicyKey {
        std::string wildcard(CYNARA_ADMIN_WILDCARD);

        auto feature = ([&wildcard] (const char *str)->Cynara::PolicyKeyFeature {
            if (wildcard.compare(str))
                return Cynara::PolicyKeyFeature::create(str);
            else
                return Cynara::PolicyKeyFeature::createWildcard();
        });

        return Cynara::PolicyKey(feature(i->client), feature(i->user), feature(i->privilege));
    });

    try {
        for (auto i = policies; *i; i++) {
            if(!(*i)->bucket || !(*i)->client || !(*i)->user || !(*i)->privilege)
                return CYNARA_ADMIN_API_INVALID_PARAM;

            switch ((*i)->result) {
                case CYNARA_ADMIN_DELETE:
                    remove[(*i)->bucket].push_back(key(*i));
                    break;
                case CYNARA_ADMIN_DENY:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PredefinedPolicyType::DENY));
                    break;
                case CYNARA_ADMIN_ALLOW:
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PredefinedPolicyType::ALLOW));
                    break;
                case CYNARA_ADMIN_BUCKET:
                    if (!(*i)->result_extra)
                        return CYNARA_ADMIN_API_INVALID_PARAM;
                    insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i),
                                                        Cynara::PolicyResult(
                                                        Cynara::PredefinedPolicyType::BUCKET,
                                                        (*i)->result_extra)));
                    break;
                default:
                    return CYNARA_ADMIN_API_INVALID_PARAM;
            }
        }
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }

    return p_cynara_admin->impl->setPolicies(insertOrUpdate, remove);
}

CYNARA_API
int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket,
                            int operation, const char *extra) {
    if (!p_cynara_admin || !p_cynara_admin->impl)
        return CYNARA_ADMIN_API_INVALID_PARAM;
    if (!bucket)
        return CYNARA_ADMIN_API_INVALID_PARAM;

    std::string extraStr;
    try {
         extraStr = extra ? extra : "";
    } catch (const std::bad_alloc &ex) {
        return CYNARA_ADMIN_API_OUT_OF_MEMORY;
    }
    switch (operation) {
        case CYNARA_ADMIN_DELETE:
            return p_cynara_admin->impl->removeBucket(bucket);
        case CYNARA_ADMIN_DENY:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::DENY, extraStr));
        case CYNARA_ADMIN_ALLOW:
            return p_cynara_admin->impl->insertOrUpdateBucket(bucket,
                Cynara::PolicyResult(Cynara::PredefinedPolicyType::ALLOW, extraStr));
        case CYNARA_ADMIN_BUCKET:
        default:
            return CYNARA_ADMIN_API_INVALID_PARAM;
    }
}
<|endoftext|>


<commit_before>#include <cstdint>
#include <cstring>
#include <algorithm>
#include <array>
#include <functional>
#include <istream>
#include <iterator>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <insertionfinder/algorithm.hpp>
#include <insertionfinder/cube.hpp>
#include "utils.hpp"
using namespace std;
using namespace InsertionFinder;
using namespace Details;

namespace {
    constexpr const char* twist_string[24] = {
        "", "U", "U2", "U'",
        "", "D", "D2", "D'",
        "", "R", "R2", "R'",
        "", "L", "L2", "L'",
        "", "F", "F2", "F'",
        "", "B", "B2", "B'"
    };

    struct Transform {
        int transform[3];
        int additional_twist;
    };

    const unordered_map<string, Transform> pattern_table({
        {"x", {{4, 2, 1}, -1}},
        {"[r]", {{4, 2, 1}, -1}},
        {"[l']", {{4, 2, 1}, -1}},
        {"x2", {{1, 2, 5}, -1}},
        {"[r2]", {{1, 2, 5}, -1}},
        {"[l2]", {{1, 2, 5}, -1}},
        {"x'", {{5, 2, 0}, -1}},
        {"[r']", {{5, 2, 0}, -1}},
        {"[l]", {{5, 2, 0}, -1}},
        {"y", {{0, 5, 2}, -1}},
        {"[u]", {{0, 5, 2}, -1}},
        {"[d']", {{0, 5, 2}, -1}},
        {"y2", {{0, 3, 5}, -1}},
        {"[u2]", {{0, 3, 5}, -1}},
        {"[d2]", {{0, 3, 5}, -1}},
        {"y'", {{0, 4, 3}, -1}},
        {"[u']", {{0, 4, 3}, -1}},
        {"[d]", {{0, 4, 3}, -1}},
        {"z", {{3, 0, 4}, -1}},
        {"[f]", {{3, 0, 4}, -1}},
        {"[b']", {{3, 0, 4}, -1}},
        {"z2", {{1, 3, 4}, -1}},
        {"[f2]", {{1, 3, 4}, -1}},
        {"[b2]", {{1, 3, 4}, -1}},
        {"z'", {{2, 1, 4}, -1}},
        {"[f']", {{2, 1, 4}, -1}},
        {"[b]", {{2, 1, 4}, -1}},
        {"Uw", {{0, 5, 2}, 5}},
        {"2Uw", {{0, 5, 2}, 5}},
        {"Uw2", {{0, 3, 5}, 6}},
        {"2Uw2", {{0, 3, 5}, 6}},
        {"Uw'", {{0, 4, 3}, 7}},
        {"2Uw'", {{0, 4, 3}, 7}},
        {"Dw", {{0, 4, 3}, 1}},
        {"2Dw", {{0, 4, 3}, 1}},
        {"Dw2", {{0, 3, 5}, 2}},
        {"2Dw2", {{0, 3, 5}, 2}},
        {"Dw'", {{0, 5, 2}, 3}},
        {"2Dw'", {{0, 5, 2}, 3}},
        {"Rw", {{4, 2, 1}, 13}},
        {"2Rw", {{4, 2, 1}, 13}},
        {"Rw2", {{1, 2, 5}, 14}},
        {"2Rw2", {{1, 2, 5}, 14}},
        {"Rw'", {{5, 2, 0}, 15}},
        {"2Rw'", {{5, 2, 0}, 15}},
        {"Lw", {{5, 2, 0}, 9}},
        {"2Lw", {{5, 2, 0}, 9}},
        {"Lw2", {{1, 2, 5}, 10}},
        {"2Lw2", {{1, 2, 5}, 10}},
        {"Lw'", {{4, 2, 1}, 11}},
        {"2Lw'", {{4, 2, 1}, 11}},
        {"Fw", {{3, 0, 4}, 21}},
        {"2Fw", {{3, 0, 4}, 21}},
        {"Fw2", {{1, 3, 4}, 22}},
        {"2Fw2", {{1, 3, 4}, 22}},
        {"Fw'", {{2, 1, 4}, 23}},
        {"2Fw'", {{2, 1, 4}, 23}},
        {"Bw", {{2, 1, 4}, 17}},
        {"2Bw", {{2, 1, 4}, 17}},
        {"Bw2", {{1, 3, 4}, 18}},
        {"2Bw2", {{1, 3, 4}, 18}},
        {"Bw'", {{3, 0, 4}, 19}},
        {"2Bw'", {{3, 0, 4}, 19}}
    });
};

Algorithm::Algorithm(const string& algorithm_string) {
    static const regex twists_regex(
        R"(\s*((?:2?[UDRLFB]w|[UDRLFB])[2']?|[xyz][2']?|\[[udrlfb][2']?\])\s*)",
        regex_constants::ECMAScript | regex_constants::optimize
    );
    int transform[3] = {0, 2, 4};
    smatch match_result;
    string temp_string = algorithm_string;
    while (regex_search(temp_string, match_result, twists_regex)) {
        if (match_result.position()) {
            throw AlgorithmError(algorithm_string);
        }
        if (auto find_result = pattern_table.find(match_result[1]); find_result != pattern_table.cend()) {
            const auto& [pattern_transform, twist] = find_result->second;
            if (twist != -1) {
                this->twists.push_back(transform_twist(transform, twist));
            }
            int new_transform[3];
            for (size_t i = 0; i < 3; ++i) {
                int temp = pattern_transform[i];
                new_transform[i] = transform[temp >> 1] ^ (temp & 1);
            }
            memcpy(transform, new_transform, 3 * sizeof(int));
        } else {
            int twist = find(twist_string, twist_string + 24, string(match_result[1])) - twist_string;
            this->twists.push_back(transform_twist(transform, twist));
        }
        temp_string = match_result.suffix();
    }
    if (!temp_string.empty()) {
        throw AlgorithmError(algorithm_string);
    }
    for (int i = 0; i < 24; ++i) {
        const int* permutation = rotation_permutation[Cube::inverse_center[i]];
        if (permutation[0] == transform[0] && permutation[1] == transform[1]) {
            this->rotation = i;
            break;
        }
    }
}

int Algorithm::compare(const Algorithm& lhs, const Algorithm& rhs) noexcept {
    const auto& t1 = lhs.twists;
    const auto& t2 = rhs.twists;
    if (int x = static_cast<int>(t1.size()) - static_cast<int>(t2.size())) {
        return x;
    }
    for (size_t i = 0, l = t1.size(); i < l; ++i) {
        if (t1[i] != t2[i]) {
            return t1[i] - t2[i];
        }
    }
    if (lhs.rotation != rhs.rotation) {
        return lhs.rotation - rhs.rotation;
    }
    return 0;
}

ostream& operator<<(ostream& out, const Algorithm& algorithm) {
    static const char* rotation_string[24] = {
        "", "y", "y2", "y'",
        "x", "x y", "x y2", "x y'",
        "x2", "x2 y", "z2", "x2 y'",
        "x'", "x' y", "x' y2", "x' y'",
        "z", "z y", "z y2", "z y'",
        "z'", "z' y", "z' y2", "z' y'"
    };
    algorithm.print(out, 0, algorithm.twists.size());
    if (algorithm.rotation && !algorithm.twists.empty()) {
        out << ' ';
    }
    out << rotation_string[algorithm.rotation];
    return out;
}

void Algorithm::print(ostream& out, size_t begin, size_t end) const {
    using namespace placeholders;
    if (begin >= end) {
        return;
    }
    transform(
        this->twists.cbegin() + begin, this->twists.cbegin() + end,
        ostream_iterator<const char*>(out, " "),
        [](int twist) {return twist_string[twist];}
    );
}

string Algorithm::str() const {
    stringstream stream;
    stream << *this;
    return stream.str();
}

void Algorithm::save_to(ostream& out) const {
    size_t length = this->twists.size();
    out.write(reinterpret_cast<char*>(&length), sizeof(size_t));
    auto data = make_unique<char[]>(length);
    for (size_t i = 0; i < length; ++i) {
        data[i] = this->twists[i];
    }
    out.write(data.get(), length);
    char rotation_data = this->rotation;
    out.write(&rotation_data, 1);
}

void Algorithm::read_from(istream& in) {
    size_t length;
    in.read(reinterpret_cast<char*>(&length), sizeof(size_t));
    if (in.gcount() != sizeof(size_t)) {
        throw AlgorithmStreamError();
    }
    auto data = make_unique<char[]>(length);
    in.read(data.get(), length);
    if (static_cast<size_t>(in.gcount()) != length) {
        throw AlgorithmStreamError();
    }
    this->twists = vector<int>(data.get(), data.get() + length);
    char rotation_data;
    in.read(&rotation_data, 1);
    if (static_cast<size_t>(in.gcount()) != 1) {
        throw AlgorithmStreamError();
    }
    this->rotation = rotation_data;

    const int* transform = rotation_permutation[this->rotation];
    auto& twists = this->twists;
    this->begin_mask = twist_mask(Algorithm::inverse_twist[twists[0]]);
    if (length > 1 && twists[0] >> 3 == twists[1] >> 3) {
        this->begin_mask |= twist_mask(Algorithm::inverse_twist[twists[1]]);
    }
    this->end_mask = twist_mask(Algorithm::inverse_twist[
        transform_twist(transform, twists[length - 1])
    ]);
    if (length > 1 && twists[length - 1] >> 3 == twists[length - 2] >> 3) {
        this->end_mask |= twist_mask(Algorithm::inverse_twist[
            transform_twist(transform, twists[length - 2])
        ]);
    }
    if (length > 2 && this->begin_mask & this->end_mask) {
        this->set_up_mask = 0;
        uint32_t set_up_mask = (this->begin_mask & this->end_mask) >> 24;
        for (size_t i = 0; i < 6; ++i) {
            if (set_up_mask & 1 << i) {
                this->set_up_mask |= 0xe << (i << 2) | 1 << (i + 24);
            }
        }
        this->set_up_mask &= this->end_mask;
    } else {
        this->set_up_mask = 0;
    }
}

Algorithm Algorithm::operator+(const Algorithm& rhs) const {
    using namespace placeholders;
    Algorithm result;
    result.twists.reserve(this->twists.size() + rhs.twists.size());
    result.twists.assign(this->twists.cbegin(), this->twists.cend());
    transform(
        rhs.twists.cbegin(), rhs.twists.cend(),
        back_inserter(result.twists),
        bind(transform_twist, rotation_permutation[Cube::inverse_center[this->rotation]], _1)
    );
    result.rotation = Cube::center_transform[this->rotation][rhs.rotation];
    return result;
}

Algorithm& Algorithm::operator+=(const Algorithm& rhs) {
    using namespace placeholders;
    this->twists.reserve(this->twists.size() + rhs.twists.size());
    transform(
        rhs.twists.cbegin(), rhs.twists.cend(),
        back_inserter(this->twists),
        bind(transform_twist, rotation_permutation[Cube::inverse_center[this->rotation]], _1)
    );
    this->rotation = Cube::center_transform[this->rotation][rhs.rotation];
    return *this;
}

size_t hash<Algorithm>::operator()(const Algorithm& algorithm) const noexcept {
    size_t result = algorithm.rotation;
    for (int twist: algorithm.twists) {
        result = result * 31 + twist;
    }
    return result;
}

void Algorithm::detect_rotation() noexcept {
    Cube cube;
    cube.twist(*this);
    this->rotation = cube.best_placement().placement();
}

void Algorithm::inverse() {
    reverse(this->twists.begin(), this->twists.end());
    this->rotate(this->rotation);
    this->rotation = Cube::inverse_center[this->rotation];
}

Algorithm Algorithm::inverse(const Algorithm& algorithm) {
    using namespace placeholders;
    Algorithm result;
    result.twists.reserve(algorithm.twists.size());
    transform(
        algorithm.twists.crbegin(), algorithm.twists.crend(),
        back_inserter(result.twists),
        bind(transform_twist, rotation_permutation[algorithm.rotation], _1)
    );
    result.rotation = Cube::inverse_center[algorithm.rotation];
    return result;
}
<commit_msg>fix Algorithm::print<commit_after>#include <cstdint>
#include <cstring>
#include <algorithm>
#include <array>
#include <functional>
#include <istream>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <insertionfinder/algorithm.hpp>
#include <insertionfinder/cube.hpp>
#include "utils.hpp"
using namespace std;
using namespace InsertionFinder;
using namespace Details;

namespace {
    constexpr const char* twist_string[24] = {
        "", "U", "U2", "U'",
        "", "D", "D2", "D'",
        "", "R", "R2", "R'",
        "", "L", "L2", "L'",
        "", "F", "F2", "F'",
        "", "B", "B2", "B'"
    };

    struct Transform {
        int transform[3];
        int additional_twist;
    };

    const unordered_map<string, Transform> pattern_table({
        {"x", {{4, 2, 1}, -1}},
        {"[r]", {{4, 2, 1}, -1}},
        {"[l']", {{4, 2, 1}, -1}},
        {"x2", {{1, 2, 5}, -1}},
        {"[r2]", {{1, 2, 5}, -1}},
        {"[l2]", {{1, 2, 5}, -1}},
        {"x'", {{5, 2, 0}, -1}},
        {"[r']", {{5, 2, 0}, -1}},
        {"[l]", {{5, 2, 0}, -1}},
        {"y", {{0, 5, 2}, -1}},
        {"[u]", {{0, 5, 2}, -1}},
        {"[d']", {{0, 5, 2}, -1}},
        {"y2", {{0, 3, 5}, -1}},
        {"[u2]", {{0, 3, 5}, -1}},
        {"[d2]", {{0, 3, 5}, -1}},
        {"y'", {{0, 4, 3}, -1}},
        {"[u']", {{0, 4, 3}, -1}},
        {"[d]", {{0, 4, 3}, -1}},
        {"z", {{3, 0, 4}, -1}},
        {"[f]", {{3, 0, 4}, -1}},
        {"[b']", {{3, 0, 4}, -1}},
        {"z2", {{1, 3, 4}, -1}},
        {"[f2]", {{1, 3, 4}, -1}},
        {"[b2]", {{1, 3, 4}, -1}},
        {"z'", {{2, 1, 4}, -1}},
        {"[f']", {{2, 1, 4}, -1}},
        {"[b]", {{2, 1, 4}, -1}},
        {"Uw", {{0, 5, 2}, 5}},
        {"2Uw", {{0, 5, 2}, 5}},
        {"Uw2", {{0, 3, 5}, 6}},
        {"2Uw2", {{0, 3, 5}, 6}},
        {"Uw'", {{0, 4, 3}, 7}},
        {"2Uw'", {{0, 4, 3}, 7}},
        {"Dw", {{0, 4, 3}, 1}},
        {"2Dw", {{0, 4, 3}, 1}},
        {"Dw2", {{0, 3, 5}, 2}},
        {"2Dw2", {{0, 3, 5}, 2}},
        {"Dw'", {{0, 5, 2}, 3}},
        {"2Dw'", {{0, 5, 2}, 3}},
        {"Rw", {{4, 2, 1}, 13}},
        {"2Rw", {{4, 2, 1}, 13}},
        {"Rw2", {{1, 2, 5}, 14}},
        {"2Rw2", {{1, 2, 5}, 14}},
        {"Rw'", {{5, 2, 0}, 15}},
        {"2Rw'", {{5, 2, 0}, 15}},
        {"Lw", {{5, 2, 0}, 9}},
        {"2Lw", {{5, 2, 0}, 9}},
        {"Lw2", {{1, 2, 5}, 10}},
        {"2Lw2", {{1, 2, 5}, 10}},
        {"Lw'", {{4, 2, 1}, 11}},
        {"2Lw'", {{4, 2, 1}, 11}},
        {"Fw", {{3, 0, 4}, 21}},
        {"2Fw", {{3, 0, 4}, 21}},
        {"Fw2", {{1, 3, 4}, 22}},
        {"2Fw2", {{1, 3, 4}, 22}},
        {"Fw'", {{2, 1, 4}, 23}},
        {"2Fw'", {{2, 1, 4}, 23}},
        {"Bw", {{2, 1, 4}, 17}},
        {"2Bw", {{2, 1, 4}, 17}},
        {"Bw2", {{1, 3, 4}, 18}},
        {"2Bw2", {{1, 3, 4}, 18}},
        {"Bw'", {{3, 0, 4}, 19}},
        {"2Bw'", {{3, 0, 4}, 19}}
    });
};

Algorithm::Algorithm(const string& algorithm_string) {
    static const regex twists_regex(
        R"(\s*((?:2?[UDRLFB]w|[UDRLFB])[2']?|[xyz][2']?|\[[udrlfb][2']?\])\s*)",
        regex_constants::ECMAScript | regex_constants::optimize
    );
    int transform[3] = {0, 2, 4};
    smatch match_result;
    string temp_string = algorithm_string;
    while (regex_search(temp_string, match_result, twists_regex)) {
        if (match_result.position()) {
            throw AlgorithmError(algorithm_string);
        }
        if (auto find_result = pattern_table.find(match_result[1]); find_result != pattern_table.cend()) {
            const auto& [pattern_transform, twist] = find_result->second;
            if (twist != -1) {
                this->twists.push_back(transform_twist(transform, twist));
            }
            int new_transform[3];
            for (size_t i = 0; i < 3; ++i) {
                int temp = pattern_transform[i];
                new_transform[i] = transform[temp >> 1] ^ (temp & 1);
            }
            memcpy(transform, new_transform, 3 * sizeof(int));
        } else {
            int twist = find(twist_string, twist_string + 24, string(match_result[1])) - twist_string;
            this->twists.push_back(transform_twist(transform, twist));
        }
        temp_string = match_result.suffix();
    }
    if (!temp_string.empty()) {
        throw AlgorithmError(algorithm_string);
    }
    for (int i = 0; i < 24; ++i) {
        const int* permutation = rotation_permutation[Cube::inverse_center[i]];
        if (permutation[0] == transform[0] && permutation[1] == transform[1]) {
            this->rotation = i;
            break;
        }
    }
}

int Algorithm::compare(const Algorithm& lhs, const Algorithm& rhs) noexcept {
    const auto& t1 = lhs.twists;
    const auto& t2 = rhs.twists;
    if (int x = static_cast<int>(t1.size()) - static_cast<int>(t2.size())) {
        return x;
    }
    for (size_t i = 0, l = t1.size(); i < l; ++i) {
        if (t1[i] != t2[i]) {
            return t1[i] - t2[i];
        }
    }
    if (lhs.rotation != rhs.rotation) {
        return lhs.rotation - rhs.rotation;
    }
    return 0;
}

ostream& operator<<(ostream& out, const Algorithm& algorithm) {
    static const char* rotation_string[24] = {
        "", "y", "y2", "y'",
        "x", "x y", "x y2", "x y'",
        "x2", "x2 y", "z2", "x2 y'",
        "x'", "x' y", "x' y2", "x' y'",
        "z", "z y", "z y2", "z y'",
        "z'", "z' y", "z' y2", "z' y'"
    };
    algorithm.print(out, 0, algorithm.twists.size());
    if (algorithm.rotation && !algorithm.twists.empty()) {
        out << ' ';
    }
    out << rotation_string[algorithm.rotation];
    return out;
}

void Algorithm::print(ostream& out, size_t begin, size_t end) const {
    using namespace placeholders;
    if (begin >= end) {
        return;
    }
    out << twist_string[this->twists[begin]];
    for (size_t i = begin; ++i < end;) {
        out << ' ' << twist_string[this->twists[i]];
    }
}

string Algorithm::str() const {
    stringstream stream;
    stream << *this;
    return stream.str();
}

void Algorithm::save_to(ostream& out) const {
    size_t length = this->twists.size();
    out.write(reinterpret_cast<char*>(&length), sizeof(size_t));
    auto data = make_unique<char[]>(length);
    for (size_t i = 0; i < length; ++i) {
        data[i] = this->twists[i];
    }
    out.write(data.get(), length);
    char rotation_data = this->rotation;
    out.write(&rotation_data, 1);
}

void Algorithm::read_from(istream& in) {
    size_t length;
    in.read(reinterpret_cast<char*>(&length), sizeof(size_t));
    if (in.gcount() != sizeof(size_t)) {
        throw AlgorithmStreamError();
    }
    auto data = make_unique<char[]>(length);
    in.read(data.get(), length);
    if (static_cast<size_t>(in.gcount()) != length) {
        throw AlgorithmStreamError();
    }
    this->twists = vector<int>(data.get(), data.get() + length);
    char rotation_data;
    in.read(&rotation_data, 1);
    if (static_cast<size_t>(in.gcount()) != 1) {
        throw AlgorithmStreamError();
    }
    this->rotation = rotation_data;

    const int* transform = rotation_permutation[this->rotation];
    auto& twists = this->twists;
    this->begin_mask = twist_mask(Algorithm::inverse_twist[twists[0]]);
    if (length > 1 && twists[0] >> 3 == twists[1] >> 3) {
        this->begin_mask |= twist_mask(Algorithm::inverse_twist[twists[1]]);
    }
    this->end_mask = twist_mask(Algorithm::inverse_twist[
        transform_twist(transform, twists[length - 1])
    ]);
    if (length > 1 && twists[length - 1] >> 3 == twists[length - 2] >> 3) {
        this->end_mask |= twist_mask(Algorithm::inverse_twist[
            transform_twist(transform, twists[length - 2])
        ]);
    }
    if (length > 2 && this->begin_mask & this->end_mask) {
        this->set_up_mask = 0;
        uint32_t set_up_mask = (this->begin_mask & this->end_mask) >> 24;
        for (size_t i = 0; i < 6; ++i) {
            if (set_up_mask & 1 << i) {
                this->set_up_mask |= 0xe << (i << 2) | 1 << (i + 24);
            }
        }
        this->set_up_mask &= this->end_mask;
    } else {
        this->set_up_mask = 0;
    }
}

Algorithm Algorithm::operator+(const Algorithm& rhs) const {
    using namespace placeholders;
    Algorithm result;
    result.twists.reserve(this->twists.size() + rhs.twists.size());
    result.twists.assign(this->twists.cbegin(), this->twists.cend());
    transform(
        rhs.twists.cbegin(), rhs.twists.cend(),
        back_inserter(result.twists),
        bind(transform_twist, rotation_permutation[Cube::inverse_center[this->rotation]], _1)
    );
    result.rotation = Cube::center_transform[this->rotation][rhs.rotation];
    return result;
}

Algorithm& Algorithm::operator+=(const Algorithm& rhs) {
    using namespace placeholders;
    this->twists.reserve(this->twists.size() + rhs.twists.size());
    transform(
        rhs.twists.cbegin(), rhs.twists.cend(),
        back_inserter(this->twists),
        bind(transform_twist, rotation_permutation[Cube::inverse_center[this->rotation]], _1)
    );
    this->rotation = Cube::center_transform[this->rotation][rhs.rotation];
    return *this;
}

size_t hash<Algorithm>::operator()(const Algorithm& algorithm) const noexcept {
    size_t result = algorithm.rotation;
    for (int twist: algorithm.twists) {
        result = result * 31 + twist;
    }
    return result;
}

void Algorithm::detect_rotation() noexcept {
    Cube cube;
    cube.twist(*this);
    this->rotation = cube.best_placement().placement();
}

void Algorithm::inverse() {
    reverse(this->twists.begin(), this->twists.end());
    this->rotate(this->rotation);
    this->rotation = Cube::inverse_center[this->rotation];
}

Algorithm Algorithm::inverse(const Algorithm& algorithm) {
    using namespace placeholders;
    Algorithm result;
    result.twists.reserve(algorithm.twists.size());
    transform(
        algorithm.twists.crbegin(), algorithm.twists.crend(),
        back_inserter(result.twists),
        bind(transform_twist, rotation_permutation[algorithm.rotation], _1)
    );
    result.rotation = Cube::inverse_center[algorithm.rotation];
    return result;
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>

#include <string>
#include <vector>

#include "netbase.h"

using namespace std;

BOOST_AUTO_TEST_SUITE(netbase_tests)

BOOST_AUTO_TEST_CASE(netbase_networks)
{
    BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork()                              == NET_UNROUTABLE);
    BOOST_CHECK(CNetAddr("::1").GetNetwork()                                    == NET_UNROUTABLE);
    BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork()                                == NET_IPV4);
    BOOST_CHECK(CNetAddr("2001::8888").GetNetwork()                             == NET_IPV6);
    BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
}

BOOST_AUTO_TEST_CASE(netbase_properties)
{
    BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
    BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4());
    BOOST_CHECK(CNetAddr("::1").IsIPv6());
    BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918());
    BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918());
    BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918());
    BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849());
    BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927());
    BOOST_CHECK(CNetAddr("2002::1").IsRFC3964());
    BOOST_CHECK(CNetAddr("FC00::").IsRFC4193());
    BOOST_CHECK(CNetAddr("2001::2").IsRFC4380());
    BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843());
    BOOST_CHECK(CNetAddr("FE80::").IsRFC4862());
    BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052());
    BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
    BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
    BOOST_CHECK(CNetAddr("::1").IsLocal());
    BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
    BOOST_CHECK(CNetAddr("2001::1").IsRoutable());
    BOOST_CHECK(CNetAddr("127.0.0.1").IsValid());
}

bool static TestSplitHost(string test, string host, int port)
{
    string hostOut;
    int portOut = -1;
    SplitHostPort(test, portOut, hostOut);
    return hostOut == host && port == portOut;
}

BOOST_AUTO_TEST_CASE(netbase_splithost)
{
    BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1));
    BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1));
    BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80));
    BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80));
    BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
    BOOST_CHECK(TestSplitHost("127.0.0.1:1968", "127.0.0.1", 1968));
    BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
    BOOST_CHECK(TestSplitHost("[127.0.0.1]:1968", "127.0.0.1", 1968));
    BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
    BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:1968", "::ffff:127.0.0.1", 1968));
    BOOST_CHECK(TestSplitHost("[::]:1968", "::", 1968));
    BOOST_CHECK(TestSplitHost("::1968", "::1968", -1));
    BOOST_CHECK(TestSplitHost(":1968", "", 1968));
    BOOST_CHECK(TestSplitHost("[]:1968", "", 1968));
    BOOST_CHECK(TestSplitHost("", "", -1));
}

bool static TestParse(string src, string canon)
{
    CService addr;
    if (!LookupNumeric(src.c_str(), addr, 65535))
        return canon == "";
    return canon == addr.ToString();
}

BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
{
    BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535"));
    BOOST_CHECK(TestParse("127.0.0.1:1968", "127.0.0.1:1968"));
    BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535"));
    BOOST_CHECK(TestParse("::", "[::]:65535"));
    BOOST_CHECK(TestParse("[::]:1968", "[::]:1968"));
    BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
    BOOST_CHECK(TestParse(":::", ""));
}

BOOST_AUTO_TEST_CASE(onioncat_test)
{
    // values from http://www.cypherpunk.at/onioncat/wiki/OnionCat
    CNetAddr addr1("5wyqrzbvrdsumnok.onion");
    CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
    BOOST_CHECK(addr1 == addr2);
    BOOST_CHECK(addr1.IsTor());
    BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
    BOOST_CHECK(addr1.IsRoutable());
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Update to v3<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Copyright (c) 2013-2014 Memorycoin Dev Team

#include <boost/test/unit_test.hpp>

#include <string>
#include <vector>

#include "netbase.h"

using namespace std;

BOOST_AUTO_TEST_SUITE(netbase_tests)

BOOST_AUTO_TEST_CASE(netbase_networks)
{
    BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork()                              == NET_UNROUTABLE);
    BOOST_CHECK(CNetAddr("::1").GetNetwork()                                    == NET_UNROUTABLE);
    BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork()                                == NET_IPV4);
    BOOST_CHECK(CNetAddr("2001::8888").GetNetwork()                             == NET_IPV6);
    BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
}

BOOST_AUTO_TEST_CASE(netbase_properties)
{
    BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
    BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4());
    BOOST_CHECK(CNetAddr("::1").IsIPv6());
    BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918());
    BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918());
    BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918());
    BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849());
    BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927());
    BOOST_CHECK(CNetAddr("2002::1").IsRFC3964());
    BOOST_CHECK(CNetAddr("FC00::").IsRFC4193());
    BOOST_CHECK(CNetAddr("2001::2").IsRFC4380());
    BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843());
    BOOST_CHECK(CNetAddr("FE80::").IsRFC4862());
    BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052());
    BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
    BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
    BOOST_CHECK(CNetAddr("::1").IsLocal());
    BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
    BOOST_CHECK(CNetAddr("2001::1").IsRoutable());
    BOOST_CHECK(CNetAddr("127.0.0.1").IsValid());
}

bool static TestSplitHost(string test, string host, int port)
{
    string hostOut;
    int portOut = -1;
    SplitHostPort(test, portOut, hostOut);
    return hostOut == host && port == portOut;
}

BOOST_AUTO_TEST_CASE(netbase_splithost)
{
    BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1));
    BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1));
    BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80));
    BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80));
    BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
    BOOST_CHECK(TestSplitHost("127.0.0.1:1968", "127.0.0.1", 1968));
    BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
    BOOST_CHECK(TestSplitHost("[127.0.0.1]:1968", "127.0.0.1", 1968));
    BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
    BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:1968", "::ffff:127.0.0.1", 1968));
    BOOST_CHECK(TestSplitHost("[::]:1968", "::", 1968));
    BOOST_CHECK(TestSplitHost("::1968", "::1968", -1));
    BOOST_CHECK(TestSplitHost(":1968", "", 1968));
    BOOST_CHECK(TestSplitHost("[]:1968", "", 1968));
    BOOST_CHECK(TestSplitHost("", "", -1));
}

bool static TestParse(string src, string canon)
{
    CService addr;
    if (!LookupNumeric(src.c_str(), addr, 65535))
        return canon == "";
    return canon == addr.ToString();
}

BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
{
    BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535"));
    BOOST_CHECK(TestParse("127.0.0.1:1968", "127.0.0.1:1968"));
    BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535"));
    BOOST_CHECK(TestParse("::", "[::]:65535"));
    BOOST_CHECK(TestParse("[::]:1968", "[::]:1968"));
    BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
    BOOST_CHECK(TestParse(":::", ""));
}

BOOST_AUTO_TEST_CASE(onioncat_test)
{
    // values from http://www.cypherpunk.at/onioncat/wiki/OnionCat
    CNetAddr addr1("5wyqrzbvrdsumnok.onion");
    CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
    BOOST_CHECK(addr1 == addr2);
    BOOST_CHECK(addr1.IsTor());
    BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
    BOOST_CHECK(addr1.IsRoutable());
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>// Copyright (C) 2008  Timothy Moore timoore@redhat.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#ifdef HAVE_CONFIG_H
#  include <simgear_config.h>
#endif

#include <osg/StateSet>

#include "EffectCullVisitor.hxx"

#include "EffectGeode.hxx"
#include "Effect.hxx"
#include "Technique.hxx"

namespace simgear
{

using osgUtil::CullVisitor;

EffectCullVisitor::EffectCullVisitor()
{
}

EffectCullVisitor::EffectCullVisitor(const EffectCullVisitor& rhs) :
    CullVisitor(rhs)
{
}

CullVisitor* EffectCullVisitor::clone() const
{
    return new EffectCullVisitor(*this);
}

void EffectCullVisitor::apply(osg::Geode& node)
{
    if (isCulled(node))
        return;
    EffectGeode *eg = dynamic_cast<EffectGeode*>(&node);
    if (!eg) {
        CullVisitor::apply(node);
        return;
    }
    Technique* technique = eg->getEffect()->chooseTechnique(&getRenderInfo());
    if (!technique) {
        CullVisitor::apply(node);
        return;
    }
    // push the node's state.
    osg::StateSet* node_state = node.getStateSet();
    if (node_state)
        pushStateSet(node_state);
    for (EffectGeode::DrawablesIterator beginItr = eg->drawablesBegin(),
             e = eg->drawablesEnd();
         beginItr != e;
         beginItr = technique->processDrawables(beginItr, e, this,
                                                eg->isCullingActive()))
        ;
    // pop the node's state off the geostate stack.
    if (node_state)
        popStateSet();

}
}
<commit_msg>check for null effect in EffectCullVisitor<commit_after>// Copyright (C) 2008  Timothy Moore timoore@redhat.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#ifdef HAVE_CONFIG_H
#  include <simgear_config.h>
#endif

#include <osg/StateSet>

#include "EffectCullVisitor.hxx"

#include "EffectGeode.hxx"
#include "Effect.hxx"
#include "Technique.hxx"

namespace simgear
{

using osgUtil::CullVisitor;

EffectCullVisitor::EffectCullVisitor()
{
}

EffectCullVisitor::EffectCullVisitor(const EffectCullVisitor& rhs) :
    CullVisitor(rhs)
{
}

CullVisitor* EffectCullVisitor::clone() const
{
    return new EffectCullVisitor(*this);
}

void EffectCullVisitor::apply(osg::Geode& node)
{
    if (isCulled(node))
        return;
    EffectGeode *eg = dynamic_cast<EffectGeode*>(&node);
    if (!eg) {
        CullVisitor::apply(node);
        return;
    }
    Effect* effect = eg->getEffect();
    Technique* technique = 0;
    if (!(effect && (technique = effect->chooseTechnique(&getRenderInfo())))) {
        CullVisitor::apply(node);
        return;
    }
    // push the node's state.
    osg::StateSet* node_state = node.getStateSet();
    if (node_state)
        pushStateSet(node_state);
    for (EffectGeode::DrawablesIterator beginItr = eg->drawablesBegin(),
             e = eg->drawablesEnd();
         beginItr != e;
         beginItr = technique->processDrawables(beginItr, e, this,
                                                eg->isCullingActive()))
        ;
    // pop the node's state off the geostate stack.
    if (node_state)
        popStateSet();

}
}
<|endoftext|>