<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tempfile.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 13:42: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
 *
 ************************************************************************/

#include "tempfile.hxx"
#include "comdep.hxx"

#include <rtl/ustring.hxx>
#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif
#ifndef _TOOLS_TIME_HXX
#include <time.hxx>
#endif
#include <debug.hxx>
#include <stdio.h>

#ifdef UNX
#define _MAX_PATH 260
#endif

using namespace osl;

namespace { struct TempNameBase_Impl : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; }

struct TempFile_Impl
{
    String      aName;
    sal_Bool    bIsDirectory;
};

String GetSystemTempDir_Impl()
{
    char sBuf[_MAX_PATH];
    const char *pDir = TempDirImpl(sBuf);

    ::rtl::OString aTmpA( pDir );
    ::rtl::OUString aTmp = ::rtl::OStringToOUString( aTmpA, osl_getThreadTextEncoding() );
    rtl::OUString aRet;
    FileBase::getFileURLFromSystemPath( aTmp, aRet );
    String aName = aRet;
    if( aName.GetChar(aName.Len()-1) != '/' )
        aName += '/';
    return aName;
}

#define TMPNAME_SIZE  ( 1 + 5 + 5 + 4 + 1 )
String ConstructTempDir_Impl( const String* pParent )
{
    String aName;
    if ( pParent && pParent->Len() )
    {
        // if parent given try to use it
        rtl::OUString aTmp( *pParent );
        rtl::OUString aRet;

        // test for valid filename
        {
            ::osl::DirectoryItem aItem;
            sal_Int32 i = aRet.getLength();
            if ( aRet[i-1] == '/' )
                i--;

            if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None )
                aName = aRet;
        }
    }

    if ( !aName.Len() )
    {
        // if no parent or invalid parent : use system directory
    ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
        if ( !rTempNameBase_Impl.getLength() )
            rTempNameBase_Impl = GetSystemTempDir_Impl();
        aName = rTempNameBase_Impl;
    }

    // Make sure that directory ends with a separator
    xub_StrLen i = aName.Len();
    if( i>0 && aName.GetChar(i-1) != '/' )
        aName += '/';

    return aName;
}

void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
{
    // add a suitable tempname
    // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
    // ER 13.07.00  why not radix 36 [0-9A-Z] ?!?
    const unsigned nRadix = 26;
    String aName( rName );
    aName += String::CreateFromAscii( "sv" );

    rName.Erase();
    static unsigned long u = Time::GetSystemTicks();
    for ( unsigned long nOld = u; ++u != nOld; )
    {
        u %= (nRadix*nRadix*nRadix);
        String aTmp( aName );
        aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix );
        aTmp += String::CreateFromAscii( ".tmp" );

        if ( bDir )
        {
            FileBase::RC err = Directory::create( aTmp );
            if (  err == FileBase::E_None )
            {
                // !bKeep: only for creating a name, not a file or directory
                if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
                    rName = aTmp;
                break;
            }
            else if ( err != FileBase::E_EXIST )
            {
                // if f.e. name contains invalid chars stop trying to create dirs
                break;
            }
        }
        else
        {
            DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
            File aFile( aTmp );
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
            if (  err == FileBase::E_None )
            {
                rName = aTmp;
                aFile.close();
                break;
            }
            else if ( err != FileBase::E_EXIST )
            {
                 // if f.e. name contains invalid chars stop trying to create files
                 break;
            }
        }
    }
}

String TempFile::CreateTempName( const String* pParent )
{
    // get correct directory
    String aName = ConstructTempDir_Impl( pParent );

    // get TempFile name with default naming scheme
    CreateTempName_Impl( aName, sal_False );

    // convert to file URL
    rtl::OUString aTmp;
    if ( aName.Len() )
        aTmp = aName;
    return aTmp;
}

TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
    : pImp( new TempFile_Impl )
    , bKillingFileEnabled( sal_False )
{
    pImp->bIsDirectory = bDirectory;

    // get correct directory
    pImp->aName = ConstructTempDir_Impl( pParent );

    // get TempFile with default naming scheme
    CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
}

TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory )
    : pImp( new TempFile_Impl )
    , bKillingFileEnabled( sal_False )
{
    pImp->bIsDirectory = bDirectory;

    // get correct directory
    String aName = ConstructTempDir_Impl( pParent );

    // now use special naming scheme ( name takes leading chars and an index counting up from zero
    aName += rLeadingChars;
    for ( sal_Int32 i=0;; i++ )
    {
        String aTmp( aName );
        aTmp += String::CreateFromInt32( i );
        if ( pExtension )
            aTmp += *pExtension;
        else
            aTmp += String::CreateFromAscii( ".tmp" );
        if ( bDirectory )
        {
            FileBase::RC err = Directory::create( aTmp );
            if ( err == FileBase::E_None )
            {
                pImp->aName = aTmp;
                break;
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                break;
        }
        else
        {
            File aFile( aTmp );
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
            if ( err == FileBase::E_None )
            {
                pImp->aName = aTmp;
                aFile.close();
                break;
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                break;
        }
    }
}

TempFile::~TempFile()
{
    if ( bKillingFileEnabled )
    {
        if ( pImp->bIsDirectory )
        {
            // at the moment no recursiv algorithm present
            Directory::remove( pImp->aName );
        }
        else
        {
            File::remove( pImp->aName );
        }
    }

    delete pImp;
}

sal_Bool TempFile::IsValid() const
{
    return pImp->aName.Len() != 0;
}

String TempFile::GetName() const
{
    rtl::OUString aTmp;
    aTmp = pImp->aName;
    return aTmp;
}

String TempFile::SetTempNameBaseDirectory( const String &rBaseName )
{
    String aName( rBaseName );

    ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();

    FileBase::RC err= Directory::create( aName );
    if ( err == FileBase::E_None || err == FileBase::E_EXIST )
    {
        rTempNameBase_Impl  = aName;
        rTempNameBase_Impl += String( '/' );

        TempFile aBase( NULL, sal_True );
        if ( aBase.IsValid() )
            rTempNameBase_Impl = aBase.pImp->aName;
    }

    rtl::OUString aTmp;
    aTmp = rTempNameBase_Impl;
    return aTmp;
}

String TempFile::GetTempNameBaseDirectory()
{
    ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
    if ( !rTempNameBase_Impl.getLength() )
        rTempNameBase_Impl = GetSystemTempDir_Impl();

    rtl::OUString aTmp;
    aTmp = rTempNameBase_Impl;
    return aTmp;
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.9.44); FILE MERGED 2006/09/01 17:54:51 kaib 1.9.44.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tempfile.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:53:56 $
 *
 *  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_tools.hxx"

#include "tempfile.hxx"
#include "comdep.hxx"

#include <rtl/ustring.hxx>
#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif
#ifndef _TOOLS_TIME_HXX
#include <time.hxx>
#endif
#include <debug.hxx>
#include <stdio.h>

#ifdef UNX
#define _MAX_PATH 260
#endif

using namespace osl;

namespace { struct TempNameBase_Impl : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; }

struct TempFile_Impl
{
    String      aName;
    sal_Bool    bIsDirectory;
};

String GetSystemTempDir_Impl()
{
    char sBuf[_MAX_PATH];
    const char *pDir = TempDirImpl(sBuf);

    ::rtl::OString aTmpA( pDir );
    ::rtl::OUString aTmp = ::rtl::OStringToOUString( aTmpA, osl_getThreadTextEncoding() );
    rtl::OUString aRet;
    FileBase::getFileURLFromSystemPath( aTmp, aRet );
    String aName = aRet;
    if( aName.GetChar(aName.Len()-1) != '/' )
        aName += '/';
    return aName;
}

#define TMPNAME_SIZE  ( 1 + 5 + 5 + 4 + 1 )
String ConstructTempDir_Impl( const String* pParent )
{
    String aName;
    if ( pParent && pParent->Len() )
    {
        // if parent given try to use it
        rtl::OUString aTmp( *pParent );
        rtl::OUString aRet;

        // test for valid filename
        {
            ::osl::DirectoryItem aItem;
            sal_Int32 i = aRet.getLength();
            if ( aRet[i-1] == '/' )
                i--;

            if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None )
                aName = aRet;
        }
    }

    if ( !aName.Len() )
    {
        // if no parent or invalid parent : use system directory
    ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
        if ( !rTempNameBase_Impl.getLength() )
            rTempNameBase_Impl = GetSystemTempDir_Impl();
        aName = rTempNameBase_Impl;
    }

    // Make sure that directory ends with a separator
    xub_StrLen i = aName.Len();
    if( i>0 && aName.GetChar(i-1) != '/' )
        aName += '/';

    return aName;
}

void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
{
    // add a suitable tempname
    // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
    // ER 13.07.00  why not radix 36 [0-9A-Z] ?!?
    const unsigned nRadix = 26;
    String aName( rName );
    aName += String::CreateFromAscii( "sv" );

    rName.Erase();
    static unsigned long u = Time::GetSystemTicks();
    for ( unsigned long nOld = u; ++u != nOld; )
    {
        u %= (nRadix*nRadix*nRadix);
        String aTmp( aName );
        aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix );
        aTmp += String::CreateFromAscii( ".tmp" );

        if ( bDir )
        {
            FileBase::RC err = Directory::create( aTmp );
            if (  err == FileBase::E_None )
            {
                // !bKeep: only for creating a name, not a file or directory
                if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
                    rName = aTmp;
                break;
            }
            else if ( err != FileBase::E_EXIST )
            {
                // if f.e. name contains invalid chars stop trying to create dirs
                break;
            }
        }
        else
        {
            DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
            File aFile( aTmp );
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
            if (  err == FileBase::E_None )
            {
                rName = aTmp;
                aFile.close();
                break;
            }
            else if ( err != FileBase::E_EXIST )
            {
                 // if f.e. name contains invalid chars stop trying to create files
                 break;
            }
        }
    }
}

String TempFile::CreateTempName( const String* pParent )
{
    // get correct directory
    String aName = ConstructTempDir_Impl( pParent );

    // get TempFile name with default naming scheme
    CreateTempName_Impl( aName, sal_False );

    // convert to file URL
    rtl::OUString aTmp;
    if ( aName.Len() )
        aTmp = aName;
    return aTmp;
}

TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
    : pImp( new TempFile_Impl )
    , bKillingFileEnabled( sal_False )
{
    pImp->bIsDirectory = bDirectory;

    // get correct directory
    pImp->aName = ConstructTempDir_Impl( pParent );

    // get TempFile with default naming scheme
    CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
}

TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory )
    : pImp( new TempFile_Impl )
    , bKillingFileEnabled( sal_False )
{
    pImp->bIsDirectory = bDirectory;

    // get correct directory
    String aName = ConstructTempDir_Impl( pParent );

    // now use special naming scheme ( name takes leading chars and an index counting up from zero
    aName += rLeadingChars;
    for ( sal_Int32 i=0;; i++ )
    {
        String aTmp( aName );
        aTmp += String::CreateFromInt32( i );
        if ( pExtension )
            aTmp += *pExtension;
        else
            aTmp += String::CreateFromAscii( ".tmp" );
        if ( bDirectory )
        {
            FileBase::RC err = Directory::create( aTmp );
            if ( err == FileBase::E_None )
            {
                pImp->aName = aTmp;
                break;
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                break;
        }
        else
        {
            File aFile( aTmp );
            FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
            if ( err == FileBase::E_None )
            {
                pImp->aName = aTmp;
                aFile.close();
                break;
            }
            else if ( err != FileBase::E_EXIST )
                // if f.e. name contains invalid chars stop trying to create dirs
                break;
        }
    }
}

TempFile::~TempFile()
{
    if ( bKillingFileEnabled )
    {
        if ( pImp->bIsDirectory )
        {
            // at the moment no recursiv algorithm present
            Directory::remove( pImp->aName );
        }
        else
        {
            File::remove( pImp->aName );
        }
    }

    delete pImp;
}

sal_Bool TempFile::IsValid() const
{
    return pImp->aName.Len() != 0;
}

String TempFile::GetName() const
{
    rtl::OUString aTmp;
    aTmp = pImp->aName;
    return aTmp;
}

String TempFile::SetTempNameBaseDirectory( const String &rBaseName )
{
    String aName( rBaseName );

    ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();

    FileBase::RC err= Directory::create( aName );
    if ( err == FileBase::E_None || err == FileBase::E_EXIST )
    {
        rTempNameBase_Impl  = aName;
        rTempNameBase_Impl += String( '/' );

        TempFile aBase( NULL, sal_True );
        if ( aBase.IsValid() )
            rTempNameBase_Impl = aBase.pImp->aName;
    }

    rtl::OUString aTmp;
    aTmp = rTempNameBase_Impl;
    return aTmp;
}

String TempFile::GetTempNameBaseDirectory()
{
    ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
    if ( !rTempNameBase_Impl.getLength() )
        rTempNameBase_Impl = GetSystemTempDir_Impl();

    rtl::OUString aTmp;
    aTmp = rTempNameBase_Impl;
    return aTmp;
}

<|endoftext|>


<commit_before>/*********************************************
* Cumulative Frequency and Statistical Model
* Notes: order-1 makes pretty much no difference on BWT+MTF+RLE0 data, fast adapting order-0 is best due to the skewed distribution.
**********************************************/

#ifndef MODEL_H
#define MODEL_H

#include "rans_byte.hpp"
#include "format.hpp"

class Model
{
public:
    static const unsigned int ProbBits = 15; // Max accuracy, 16 can cause overflow in 16 bit type due to 1 << 16
    static const unsigned int ProbScale = 1 << ProbBits;

private:
	static const unsigned int UpdateStep = 32 << 10;
	static const unsigned int Order_1_States = 1;
	static const unsigned int Order_0_State = Order_1_States - 1;
	static const unsigned int AlphabetSize = 257;

	unsigned int Freqs[Order_1_States][AlphabetSize] = {{0}};
	unsigned int PreInheritedFreqs[Order_1_States][AlphabetSize] = {{0}};
	unsigned int CumFreqs[Order_1_States][AlphabetSize + 1] = {{0}};
	unsigned int Chain_1 = 0;

	unsigned short cum2sym[Order_1_States][ProbScale];
	RansEncSymbol esyms[Order_1_States][AlphabetSize];
	RansDecSymbol dsyms[Order_1_States][AlphabetSize];
	void StretchAndFitFreqs();
	void InheritStatistics();

public:
	int WriteHeader(unsigned char* outbuf, int* olen, int* clen, int* rlen);
	int ReadHeader(unsigned char* inbuf, int* olen, int* clen, int* rlen, int StackSize);
	void Build(unsigned short *buf, int len);
	void Clear();
	void SetEncodeTable();
	void SetDecodeTable();
	RansEncSymbol EncGetRange(unsigned short c);
	RansDecSymbol* DecGetNext(unsigned short c);
	int DecGetSym(int range);
};

#endif // MODEL_H <commit_msg>Delete model.hpp<commit_after><|endoftext|>


<commit_before>// Currently the O(nlogn) solution has a bug for some medium sized input.
//   But once that gets debugged, it should function for large inputs too.
// The O(n^2) solution works, but gets TLE for large inputs.

class Solution {
    const double PI = 3.14159265;

    struct Coord {
        int x=0;
        int y=0;
        bool operator==(const Coord& rhs) {
            return x == rhs.x && y == rhs.y;
        }
    };

    vector<double> slopes;
    Coord origin;

    // returns slope of the line in radians [0, 2*PI]
    double slope(Coord from, Coord to) {
        double delta_x = to.x - from.x;
        double delta_y = to.y - from.y;
        double slope = std::atan2(delta_y, delta_x);
        if (slope < 0) {slope += 2*PI;}
        return slope;
    }

    // Says whether point "check" is visible in current POV.
    // current POV is determined by the cone formed of size "angle"
    // with segment [origin, edge_point] as rightmost edge of cone
    bool isVisible(int check_index, int edge_index, double angle) {
        if (check_index == edge_index) return true;
        double slope_edge  = slopes[edge_index];
        double slope_check = slopes[check_index];
        return isVisibleSlopes(slope_edge, slope_check, angle);
    }

    // The version of isVisible that directly works with slopes
    bool isVisibleSlopes(double slope_edge, double slope_check, double angle) {
        if (slope_edge == slope_check) return true;

        double sweep_value = slope_edge + angle;
        if (sweep_value >= 2*PI) {sweep_value -= 2*PI;}

        if (sweep_value >= slope_edge) {  // sweep didn't cross x=0 pointing right
            return (slope_edge <= slope_check && slope_check <= sweep_value);
        }
        bool cond1 = (slope_edge <= slope_check && slope_check <= 2*PI);
        bool cond2 = (0 <= slope_check && slope_check <= sweep_value);
        return (cond1 || cond2);
    }

public:
    // O(n ^2) algorithm.
    int visiblePoints(vector<vector<int>>& points, int angle, vector<int>& location) {
        double angle_rads = angle * PI / 180.0;
        origin = {location[0], location[1]};

        int origin_count=0;
        for (int i=0; i<points.size(); i++) {
            Coord coord = {points[i][0], points[i][1]};
            if (coord == origin) {
                origin_count++;
                slopes.push_back(-10000); // invalid, won't be used
                continue;
            }
            slopes.push_back(slope(origin, coord));
        }

        int max=0;
        for (int i=0; i<points.size(); i++) {
            Coord edge = {points[i][0], points[i][1]};
            if (edge == origin) {continue;}
            int count_e = 0;
            for (int j=0; j<points.size(); j++) {
                Coord coord = {points[j][0], points[j][1]};
                if (coord == origin) {continue;}
                if (isVisible(j, i, angle_rads)) {count_e++;}
            }
            if (max < count_e) {max = count_e;}
        }
        return max+origin_count;
    }

    // O(n log n) time.
    int visiblePoints_nlogn(vector<vector<int>>& points, int angle, vector<int>& location) {
        double angle_rads = angle * PI / 180.0;
        origin = {location[0], location[1]};

        int origin_count=0;
        for (int i=0; i<points.size(); i++) {
            Coord coord = {points[i][0], points[i][1]};
            if (coord == origin) {
                origin_count++;
                continue;
            }
            slopes.push_back(slope(origin, coord));
        }

        std::sort(slopes.begin(), slopes.end());

        int max=0;
        int edge_ptr=0, check_ptr=0;
        int npoints=0;  // keeps track of points in current window
        unordered_map<int, int> counts;
        while (edge_ptr < slopes.size()) {
            while (check_ptr < slopes.size() &&
                   isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {
                check_ptr++;
                npoints++;
            }
            if (check_ptr == slopes.size()) {  // we may have to wrap around and check
                check_ptr=0;
                while (check_ptr < edge_ptr &&
                       isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {
                    check_ptr++;
                    npoints++;
                }
            }
            counts[edge_ptr] = npoints;
            if (npoints > max) {max = npoints;}

            // if everything is visible, just break out
            if (isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {break;}

            while (edge_ptr < slopes.size() &&
                   !isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {
                edge_ptr++;
                npoints--;
            }
        }
        return (max+origin_count);
    }
};
<commit_msg>[Fix] Fixed bug in previous nlogn solution.<commit_after>// Currently the O(nlogn) solution has a bug for some medium sized input.
//   But once that gets debugged, it should function for large inputs too.
// The O(n^2) solution works, but gets TLE for large inputs.

class Solution {
    const double PI = 3.14159265;

    struct Coord {
        int x=0;
        int y=0;
        bool operator==(const Coord& rhs) {
            return x == rhs.x && y == rhs.y;
        }
    };

    vector<double> slopes;
    Coord origin;

    // returns slope of the line in radians [0, 2*PI]
    double slope(Coord from, Coord to) {
        double delta_x = to.x - from.x;
        double delta_y = to.y - from.y;
        double slope = std::atan2(delta_y, delta_x);
        if (slope < 0) {slope += 2*PI;}
        return slope;
    }

    // Says whether point "check" is visible in current POV.
    // current POV is determined by the cone formed of size "angle"
    // with segment [origin, edge_point] as rightmost edge of cone
    bool isVisible(int check_index, int edge_index, double angle) {
        if (check_index == edge_index) return true;
        double slope_edge  = slopes[edge_index];
        double slope_check = slopes[check_index];
        return isVisibleSlopes(slope_edge, slope_check, angle);
    }

    // The version of isVisible that directly works with slopes
    bool isVisibleSlopes(double slope_edge, double slope_check, double angle) {
        if (slope_edge == slope_check) return true;

        double sweep_value = slope_edge + angle;
        if (sweep_value >= 2*PI) {sweep_value -= 2*PI;}

        if (sweep_value >= slope_edge) {  // sweep didn't cross x=0 pointing right
            return (slope_edge <= slope_check && slope_check <= sweep_value);
        }
        bool cond1 = (slope_edge <= slope_check && slope_check <= 2*PI);
        bool cond2 = (0 <= slope_check && slope_check <= sweep_value);
        return (cond1 || cond2);
    }

public:
    // O(n ^2) algorithm.
    int visiblePoints_1(vector<vector<int>>& points, int angle, vector<int>& location) {
        double angle_rads = angle * PI / 180.0;
        origin = {location[0], location[1]};

        int origin_count=0;
        for (int i=0; i<points.size(); i++) {
            Coord coord = {points[i][0], points[i][1]};
            if (coord == origin) {
                origin_count++;
                slopes.push_back(-10000); // invalid, won't be used
                continue;
            }
            slopes.push_back(slope(origin, coord));
        }

        int max=0;
        for (int i=0; i<points.size(); i++) {
            Coord edge = {points[i][0], points[i][1]};
            if (edge == origin) {continue;}
            int count_e = 0;
            for (int j=0; j<points.size(); j++) {
                Coord coord = {points[j][0], points[j][1]};
                if (coord == origin) {continue;}
                if (isVisible(j, i, angle_rads)) {count_e++;}
            }
            if (max < count_e) {max = count_e;}
        }
        return max+origin_count;
    }

     // O(n log n) time.
    int visiblePoints(vector<vector<int>>& points, int angle, vector<int>& location) {
        double angle_rads = angle * PI / 180.0;
        origin = {location[0], location[1]};

        int origin_count=0;
        for (int i=0; i<points.size(); i++) {
            Coord coord = {points[i][0], points[i][1]};
            if (coord == origin) {
                origin_count++;
                continue;
            }
            slopes.push_back(slope(origin, coord));
        }

        std::sort(slopes.begin(), slopes.end());

        int max=0;
        int edge_ptr=0, check_ptr=0;
        int npoints=0;  // keeps track of points in current window
        unordered_map<int, int> counts;
        bool wraparound =false;

        while (edge_ptr < slopes.size()) {
            int limit = wraparound ? edge_ptr : slopes.size();
            while (check_ptr < limit &&
                   isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {
                check_ptr++;
                npoints++;
            }
            if (check_ptr == slopes.size()) {  // we may have to wrap around and check
                check_ptr=0;
                wraparound = true;
                while (check_ptr < edge_ptr &&
                       isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {
                    check_ptr++;
                    npoints++;
                }
            }
            counts[edge_ptr] = npoints;
            if (npoints > max) {
                max = npoints;
            }

            // if everything is visible, just break out
            if (check_ptr == edge_ptr) {break;}

            while (edge_ptr < slopes.size() &&
                   !isVisibleSlopes(slopes[edge_ptr], slopes[check_ptr], angle_rads)) {
                edge_ptr++;
                npoints--;
            }
        }
        return (max+origin_count);
    }
};
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2018-2019 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/png/pngwriter.h>

#include <inviwo/core/datastructures/image/layer.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/datastructures/image/layerramprecision.h>

#include <png.h>

namespace inviwo {

namespace detail {

void writeToBuffer(png_structp png_ptr, png_bytep data, png_size_t length) {
    auto buffer = static_cast<std::vector<unsigned char>*>(png_get_io_ptr(png_ptr));
    for (png_size_t i = 0; i < length; i++) {
        buffer->push_back(static_cast<unsigned char>(data[i]));
    }
}

template <typename T>
void write(const LayerRAMPrecision<T>* ram, png_voidp ioPtr, png_rw_ptr writeFunc = nullptr,
           png_flush_ptr flushFunc = nullptr) {

    // TODO better exception messages
    auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    if (!png_ptr) {
        throw PNGLayerWriterException("Internal PNG Error: Failed to create write struct");
    }
    util::OnScopeExit cleanup([&]() { png_destroy_write_struct(&png_ptr, nullptr); });

    png_set_error_fn(
        png_ptr, nullptr,
        [](png_structp, png_const_charp message) {
            throw PNGLayerWriterException(std::string("Error witting PNG: ") + message);
        },
        [](png_structp, png_const_charp message) { LogWarnCustom("PNGWriter", message); });

    auto info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        throw PNGLayerWriterException("Internal PNG Error: Failed to create info struct");
    }
    cleanup.setAction([&]() { png_destroy_write_struct(&png_ptr, &info_ptr); });

    png_set_write_fn(png_ptr, ioPtr, writeFunc, flushFunc);

    const auto df = ram->getDataFormat();
    const auto color_type = [&]() {
        switch (df->getComponents()) {
            case 1:
                return PNG_COLOR_TYPE_GRAY;
            case 2:
                return PNG_COLOR_TYPE_GRAY_ALPHA;
            case 3:
                return PNG_COLOR_TYPE_RGB;
            case 4:
                return PNG_COLOR_TYPE_RGBA;
            default:
                // Should not ever reach this
                throw new PNGLayerWriterException("Unsupported number of channels");
        }
    }();

    const auto size = ram->getDimensions();
    const auto bit_depth = df->getPrecision();

    if (df->getNumericType() == NumericType::Float) {
        png_set_IHDR(png_ptr, info_ptr, static_cast<int>(size.x), static_cast<int>(size.y), 16,
                     color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                     PNG_FILTER_TYPE_BASE);

        png_write_info(png_ptr, info_ptr);
        png_set_swap(png_ptr);

        const auto pixels = ram->getDataTyped();

        using T2 = typename util::same_extent<T, glm::uint16>::type;
        std::vector<T2> newData(size.x * size.y);
        for (size_t i = 0; i < size.x * size.y; i++) {
            newData[i] = util::glm_convert_normalized<T2>(glm::clamp(pixels[i], T{0}, T{1}));
        }

        std::vector<png_bytep> rows(size.y);
        for (png_uint_32 r = 0; r < size.y; ++r) {
            rows[size.y - r - 1] = reinterpret_cast<png_bytep>(newData.data() + r * size.x);
        }

        png_write_image(png_ptr, rows.data());

    } else {
        png_set_IHDR(png_ptr, info_ptr, static_cast<int>(size.x), static_cast<int>(size.y),
                     static_cast<int>(bit_depth), color_type, PNG_INTERLACE_NONE,
                     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

        png_write_info(png_ptr, info_ptr);
        png_set_swap(png_ptr);

        auto pixels = const_cast<T*>(ram->getDataTyped());
        std::vector<png_bytep> rows(size.y);
        for (png_uint_32 r = 0; r < size.y; ++r) {
            // Inviwo images are upside down compared to how libpng expects them
            rows[size.y - r - 1] = reinterpret_cast<png_bytep>(pixels + r * size.x);
        }

        png_write_image(png_ptr, rows.data());
    }

    png_write_end(png_ptr, NULL);
}

}  // namespace detail

PNGLayerWriterException::PNGLayerWriterException(const std::string& message,
                                                 ExceptionContext context)
    : Exception(message, context) {}

PNGLayerWriter::PNGLayerWriter() : DataWriterType<Layer>() {
    addExtension(FileExtension("png", "Portable Network Graphics"));
}

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

void PNGLayerWriter::writeData(const Layer* data, const std::string filePath) const {
    data->getRepresentation<LayerRAM>()->dispatch<void>([&](auto ram) {
        FILE* fp = fopen(filePath.c_str(), "wb");
        if (!fp) throw PNGLayerWriterException("Failed to open file for writing, " + filePath);
        util::OnScopeExit closeFile([&fp]() { fclose(fp); });

        detail::write(ram, static_cast<png_voidp>(fp));
    });
}

std::unique_ptr<std::vector<unsigned char>> PNGLayerWriter::writeDataToBuffer(
    const Layer* data, const std::string&) const {

    auto buffer = std::make_unique<std::vector<unsigned char>>();
    data->getRepresentation<LayerRAM>()->dispatch<void>([&](auto ram) {
        detail::write(ram, static_cast<png_voidp>(buffer.get()), &detail::writeToBuffer);
    });

    return buffer;
}

bool PNGLayerWriter::writeDataToRepresentation(const repr*, repr*) const { return false; }

}  // namespace inviwo
<commit_msg>PNG: handling 32bit and signed data formats, closes #440 * Layers with integer formats with more than 16bit are converted to uint16 * signed integer formats are converted to unsigned<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2018-2019 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/png/pngwriter.h>

#include <inviwo/core/datastructures/image/layer.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/datastructures/image/layerramprecision.h>

#include <png.h>
#include <algorithm>

namespace inviwo {

namespace detail {

void writeToBuffer(png_structp png_ptr, png_bytep data, png_size_t length) {
    auto buffer = static_cast<std::vector<unsigned char>*>(png_get_io_ptr(png_ptr));
    for (png_size_t i = 0; i < length; i++) {
        buffer->push_back(static_cast<unsigned char>(data[i]));
    }
}

template <typename Result, typename T>
std::vector<Result> convert(const T* data, const size_t size, const T min, const T max) {
    std::vector<Result> newData(size);
    std::transform(data, data + size, newData.begin(), [min, max](const T& value) {
        return util::glm_convert_normalized<Result>(glm::clamp(value, min, max));
    });
    return newData;
}

template <typename T, typename valueType = typename util::value_type<T>::type,
          typename = typename std::enable_if<std::is_same_v<valueType, bool>>::type>
auto convertToUnsigned(const T* data, const size_t size, const T min, const T max)
    -> std::vector<typename util::same_extent<T, unsigned char>::type> {
    using T2 = typename util::same_extent<T, unsigned char>::type;
    return convert<T2>(data, size, min, max);
}

template <typename T, typename valueType = typename util::value_type<T>::type,
          typename = typename std::enable_if<!std::is_same_v<valueType, bool> &&
                                             std::is_integral_v<valueType>>::type>
auto convertToUnsigned(const T* data, const size_t size, const T min, const T max)
    -> std::vector<typename util::same_extent<T, std::make_unsigned_t<valueType>>::type> {
    using T2 = typename util::same_extent<T, std::make_unsigned_t<valueType>>::type;
    return convert<T2>(data, size, min, max);
}

template <typename T, typename valueType = typename util::value_type<T>::type,
          typename = typename std::enable_if<!std::is_integral_v<valueType>>::type>
auto convertToUnsigned(const T*, const size_t, const T, const T) -> std::vector<T> {
    return {};
}

template <typename T>
void write(const LayerRAMPrecision<T>* ram, png_voidp ioPtr, png_rw_ptr writeFunc = nullptr,
           png_flush_ptr flushFunc = nullptr) {

    // TODO better exception messages
    auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    if (!png_ptr) {
        throw PNGLayerWriterException("Internal PNG Error: Failed to create write struct");
    }
    util::OnScopeExit cleanup([&]() { png_destroy_write_struct(&png_ptr, nullptr); });

    png_set_error_fn(
        png_ptr, nullptr,
        [](png_structp, png_const_charp message) {
            throw PNGLayerWriterException(std::string("Error writing PNG: ") + message);
        },
        [](png_structp, png_const_charp message) { LogWarnCustom("PNGWriter", message); });

    auto info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        throw PNGLayerWriterException("Internal PNG Error: Failed to create info struct");
    }
    cleanup.setAction([&]() { png_destroy_write_struct(&png_ptr, &info_ptr); });

    png_set_write_fn(png_ptr, ioPtr, writeFunc, flushFunc);

    const auto df = ram->getDataFormat();
    const auto color_type = [&]() {
        switch (df->getComponents()) {
            case 1:
                return PNG_COLOR_TYPE_GRAY;
            case 2:
                return PNG_COLOR_TYPE_GRAY_ALPHA;
            case 3:
                return PNG_COLOR_TYPE_RGB;
            case 4:
                return PNG_COLOR_TYPE_RGBA;
            default:
                // Should not ever reach this
                throw new PNGLayerWriterException("Unsupported number of channels");
        }
    }();

    const auto size = ram->getDimensions();
    const auto bit_depth = df->getPrecision();

    auto writePNG = [&](auto pixels) {
        std::vector<png_bytep> rows(size.y);
        for (png_uint_32 r = 0; r < size.y; ++r) {
            // Inviwo images are upside down compared to how libpng expects them
            rows[size.y - r - 1] = reinterpret_cast<png_bytep>(pixels + r * size.x);
        }
        png_write_image(png_ptr, rows.data());
        png_write_end(png_ptr, nullptr);
    };

    const auto data = ram->getDataTyped();
    if (df->getNumericType() == NumericType::Float) {
        png_set_IHDR(png_ptr, info_ptr, static_cast<int>(size.x), static_cast<int>(size.y), 16,
                     color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                     PNG_FILTER_TYPE_BASE);

        png_write_info(png_ptr, info_ptr);
        png_set_swap(png_ptr);

        using T2 = typename util::same_extent<T, glm::uint16>::type;
        auto newData = convert<T2>(data, glm::compMul(size), T{0}, T{1});
        writePNG(newData.data());
    } else {
        png_set_IHDR(png_ptr, info_ptr, static_cast<int>(size.x), static_cast<int>(size.y),
                     static_cast<int>(std::min<size_t>(bit_depth, 16)), color_type,
                     PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

        png_write_info(png_ptr, info_ptr);
        png_set_swap(png_ptr);

        if (bit_depth > 16) {
            using T2 = typename util::same_extent<T, glm::uint16>::type;
            auto newData = convert<T2>(data, glm::compMul(size), DataFormat<T>::lowest(),
                                       DataFormat<T>::max());
            writePNG(newData.data());
        } else if (df->getNumericType() == NumericType::SignedInteger) {
            auto newData = convertToUnsigned(data, glm::compMul(size), DataFormat<T>::lowest(),
                                             DataFormat<T>::max());
            writePNG(newData.data());
        } else {
            writePNG(const_cast<T*>(ram->getDataTyped()));
        }
    }
}

}  // namespace detail

PNGLayerWriterException::PNGLayerWriterException(const std::string& message,
                                                 ExceptionContext context)
    : Exception(message, context) {}

PNGLayerWriter::PNGLayerWriter() : DataWriterType<Layer>() {
    addExtension(FileExtension("png", "Portable Network Graphics"));
}

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

void PNGLayerWriter::writeData(const Layer* data, const std::string filePath) const {
    data->getRepresentation<LayerRAM>()->dispatch<void>([&](auto ram) {
        FILE* fp = fopen(filePath.c_str(), "wb");
        if (!fp) throw PNGLayerWriterException("Failed to open file for writing, " + filePath);
        util::OnScopeExit closeFile([&fp]() { fclose(fp); });

        detail::write(ram, static_cast<png_voidp>(fp));
    });
}

std::unique_ptr<std::vector<unsigned char>> PNGLayerWriter::writeDataToBuffer(
    const Layer* data, const std::string&) const {

    auto buffer = std::make_unique<std::vector<unsigned char>>();
    data->getRepresentation<LayerRAM>()->dispatch<void>([&](auto ram) {
        detail::write(ram, static_cast<png_voidp>(buffer.get()), &detail::writeToBuffer);
    });

    return buffer;
}

bool PNGLayerWriter::writeDataToRepresentation(const repr*, repr*) const { return false; }

}  // namespace inviwo
<|endoftext|>


<commit_before>//===--- ExistentialGeneralization.cpp - Shape generalization algorithm ---===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file defines the existential type generalization algorithm,
//  which is used in the ABI for existential types.
//
//===----------------------------------------------------------------------===//

#include "GenericSignatureBuilder.h"
#include "swift/AST/Types.h"
#include "swift/AST/CanTypeVisitor.h"
#include "llvm/ADT/DenseMap.h"

using namespace swift;

namespace {

/// A helper type for performing existential type generalization.
class Generalizer : public CanTypeVisitor<Generalizer, Type> {
  friend CanTypeVisitor<Generalizer, Type>;

  ASTContext &ctx;

  llvm::DenseMap<CanType, Type> substTypes;
  llvm::DenseMap<std::pair<CanType, ProtocolDecl*>,
                 ProtocolConformanceRef> substConformances;

  Optional<GenericSignatureBuilder> sigBuilderStorage;

  GenericSignatureBuilder &sigBuilder() {
    if (!sigBuilderStorage)
      sigBuilderStorage.emplace(ctx);
    return *sigBuilderStorage;
  }

public:
  Generalizer(ASTContext &ctx) : ctx(ctx) {}

  /// Given that the given type is not itself substitutable in whatever
  /// position it appears in, generalize it.
  Type generalizeStructure(CanType type) {
    return visit(type);
  }

  SubstitutionMap getGeneralizationSubstitutions() {
    // If we never introduced a generalization parameter, we're done.
    if (!sigBuilderStorage) return SubstitutionMap();

    // Finish the signature.
    auto sig = std::move(*sigBuilderStorage).computeGenericSignature();
    sigBuilderStorage.reset();

    // TODO: minimize the signature by removing redundant generic
    // parameters.

    auto lookupParameter = [&](SubstitutableType *type) {
      auto it = substTypes.find(CanType(type));
      assert(it != substTypes.end());
      return it->second;
    };
    auto lookupConformance = [&](CanType dependentType,
                                 Type conformingReplacementType,
                                 ProtocolDecl *conformedProtocol) {
      auto it = substConformances.find({dependentType, conformedProtocol});
      assert(it != substConformances.end());
      return it->second;
    };
    return SubstitutionMap::get(sig, lookupParameter, lookupConformance);
  }

private:
  Type visitProtocolType(CanProtocolType type) {
    // Simple protocol types have no sub-structure.
    assert(!type.getParent());
    return type;
  }

  Type visitParameterizedProtocolType(CanParameterizedProtocolType origType) {
    // Generalize the argument types of parameterized protocols,
    // but don't generalize the base type.
    auto origArgs = origType.getArgs();
    SmallVector<Type, 4> newArgs;
    newArgs.reserve(origArgs.size());
    for (auto origArg: origArgs) {
      newArgs.push_back(generalizeComponentType(origArg));
    }
    return ParameterizedProtocolType::get(ctx, origType->getBaseType(),
                                          newArgs);
  }

  Type visitProtocolCompositionType(CanProtocolCompositionType origType) {
    // The member types of protocol compositions are not substitutable,
    // including class constraints.  Generalize them individually,
    // preserving structure.
    auto origMembers = origType.getMembers();
    SmallVector<Type, 4> newMembers;
    newMembers.reserve(origMembers.size());
    for (auto origMember: origMembers) {
      newMembers.push_back(generalizeStructure(origMember));
    }
    return ProtocolCompositionType::get(ctx, newMembers,
                                        origType->hasExplicitAnyObject());
  }

  // Generalize the type arguments of nominal types.
  Type visitBoundGenericType(CanBoundGenericType origType) {
    return generalizeGenericArguments(origType->getDecl(), origType);
  }
  Type visitNominalType(CanNominalType origType) {
    auto decl = origType->getDecl();
    if (decl->isGenericContext())
      return generalizeGenericArguments(decl, origType);
    return origType;
  }

  // Preserve existential structure.
  Type visitExistentialType(CanExistentialType origType) {
    return ExistentialType::get(
              generalizeStructure(origType.getConstraintType()));
  }
  Type visitExistentialMetatypeType(CanExistentialMetatypeType origType) {
    assert(!origType->hasRepresentation());
    return ExistentialMetatypeType::get(
              generalizeStructure(origType.getInstanceType()));
  }

  // These types can be generalized by a recursive transform of
  // their component types; we don't need to exclude anything or
  // handle conformances.
#define GENERALIZE_COMPONENTS(ID)                              \
  Type visit##ID##Type(Can##ID##Type origType) {               \
    return generalizeComponentTypes(origType);                 \
  }
  GENERALIZE_COMPONENTS(Function)
  GENERALIZE_COMPONENTS(Metatype)
  GENERALIZE_COMPONENTS(Tuple)
#undef GENERALIZE_COMPONENTS

  // These types can never contain component types with abstract
  // constraints, so generalizeComponentType should always substitute
  // them out.
#define NO_PRESERVABLE_STRUCTURE(ID)                           \
  Type visit##ID##Type(Can##ID##Type origType) {               \
    llvm_unreachable(#ID "Type has no structure to preserve"); \
  }
  NO_PRESERVABLE_STRUCTURE(Archetype)
  NO_PRESERVABLE_STRUCTURE(Builtin)
  NO_PRESERVABLE_STRUCTURE(DependentMember)
  NO_PRESERVABLE_STRUCTURE(GenericTypeParam)
  NO_PRESERVABLE_STRUCTURE(Module)
  NO_PRESERVABLE_STRUCTURE(Pack)
  NO_PRESERVABLE_STRUCTURE(PackExpansion)
#undef NO_PRESERVABLE_STRUCTURE

  // These types simply shouldn't appear in types that we generalize at all.
#define INVALID_TO_GENERALIZE(ID)                                       \
  Type visit##ID##Type(Can##ID##Type origType) {                        \
    llvm_unreachable(#ID "type should not be found by generalization"); \
  }
  INVALID_TO_GENERALIZE(DynamicSelf)
  INVALID_TO_GENERALIZE(Error)
  INVALID_TO_GENERALIZE(GenericFunction)
  INVALID_TO_GENERALIZE(InOut)
  INVALID_TO_GENERALIZE(LValue)
  INVALID_TO_GENERALIZE(ReferenceStorage)
  INVALID_TO_GENERALIZE(SILBlockStorage)
  INVALID_TO_GENERALIZE(SILBox)
  INVALID_TO_GENERALIZE(SILFunction)
  INVALID_TO_GENERALIZE(SILToken)
#undef INVALID_TO_GENERALIZE

  /// Generalize the generic arguments of the given generic type.s
  Type generalizeGenericArguments(NominalTypeDecl *decl, CanType type) {
    assert(decl->isGenericContext());
    auto origSubs = type->getContextSubstitutionMap(decl->getModuleContext(),
                                                    decl);

    // Generalize all of the arguments.
    auto origArgs = origSubs.getReplacementTypes();
    SmallVector<Type, 4> newArgs;
    for (auto origArg: origArgs) {
      newArgs.push_back(generalizeComponentType(CanType(origArg)));
    }

    // Generalize all of the conformances.
    // TODO: for abstract requirements, we might not generalize all
    // arguments, and we may need to leave corresponding conformances
    // concrete.
    SmallVector<ProtocolConformanceRef, 4> newConformances;
    auto origConformances = origSubs.getConformances();
    for (auto origConformance: origConformances) {
      newConformances.push_back(
        ProtocolConformanceRef(origConformance.getRequirement()));
    }

    auto origSig = origSubs.getGenericSignature();
    auto newSubs = SubstitutionMap::get(origSig, newArgs, newConformances);

    // Add any conformance requirements to the generic signature and
    // remember the conformances we generalized.
    if (!origConformances.empty()) {
      size_t i = 0;
      for (auto &origReq: origSig.getRequirements()) {
        if (origReq.getKind() != RequirementKind::Conformance) continue;
        auto origConformance = origConformances[i++];

        auto optNewReq = origReq.subst(newSubs);
        assert(optNewReq && "generalization substitution failed");
        auto &newReq = *optNewReq;

        auto source = GenericSignatureBuilder::
          FloatingRequirementSource::forInferred(SourceLoc());

        sigBuilder().addRequirement(newReq, source, nullptr);

        substConformances.insert({{newReq.getFirstType()->getCanonicalType(),
                                   newReq.getProtocolDecl()},
                                  origConformance});
      }
    }

    // Build the new type.
    return decl->getDeclaredInterfaceType().subst(newSubs);
  }

  /// Generalize the given type by preserving its top-level structure
  /// but generalizing its component types.
  Type generalizeComponentTypes(CanType type) {
    return type.transformRec([&](TypeBase *componentType) -> Optional<Type> {
      // Ignore the top level.
      if (componentType == type.getPointer())
        return None;

      return generalizeComponentType(CanType(componentType));
    });
  }

  Type generalizeComponentType(CanType origArg) {
    // TODO: Abstract constraints (some P) introduce *existential*
    // component types, which are not substitutable.  Therefore, types
    // containing them must be generalized preserving that structure
    // rather than wholly substituted.  They can appear in arbitrary
    // positions, including within tuple, function, and metatype types,
    // so we'll need to add cases for those to generalizeStructure
    // above.

    // Create a new generalization type parameter and record the
    // substitution.
    auto newParam = GenericTypeParamType::get(/*sequence*/ false,
                                              /*depth*/ 0,
                                              /*index*/ substTypes.size(),
                                              ctx);
    sigBuilder().addGenericParameter(newParam);
    substTypes.insert({CanType(newParam), origArg});
    return newParam;
  }
};

} // end anonymous namespace

ExistentialTypeGeneralization
ExistentialTypeGeneralization::get(Type rawType) {
  assert(rawType->isExistentialType());
  assert(!rawType->hasTypeParameter());

  // Canonicalize.  We need to generalize the canonical shape of the
  // type or else generalization parameters won't match up.
  CanType type = rawType->getCanonicalType();

  Generalizer generalizer(type->getASTContext());
  Type shape = generalizer.generalizeStructure(type);
  auto subs = generalizer.getGeneralizationSubstitutions();

  return {shape, subs};
}
<commit_msg>AST: Refactor existential generalization to use buildGenericSignature() instead of GenericSignatureBuilder<commit_after>//===--- ExistentialGeneralization.cpp - Shape generalization algorithm ---===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file defines the existential type generalization algorithm,
//  which is used in the ABI for existential types.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/CanTypeVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Requirement.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/DenseMap.h"

using namespace swift;

namespace {

/// A helper type for performing existential type generalization.
class Generalizer : public CanTypeVisitor<Generalizer, Type> {
  friend CanTypeVisitor<Generalizer, Type>;

  ASTContext &ctx;

  llvm::DenseMap<CanType, Type> substTypes;
  llvm::DenseMap<std::pair<CanType, ProtocolDecl*>,
                 ProtocolConformanceRef> substConformances;

  SmallVector<GenericTypeParamType *, 2> addedParameters;
  SmallVector<Requirement, 2> addedRequirements;

public:
  Generalizer(ASTContext &ctx) : ctx(ctx) {}

  /// Given that the given type is not itself substitutable in whatever
  /// position it appears in, generalize it.
  Type generalizeStructure(CanType type) {
    return visit(type);
  }

  SubstitutionMap getGeneralizationSubstitutions() {
    // If we never introduced a generalization parameter, we're done.
    if (addedParameters.empty() && addedRequirements.empty())
      return SubstitutionMap();

    // Finish the signature.
    auto sig = buildGenericSignature(ctx, GenericSignature(),
                                     addedParameters,
                                     addedRequirements);

    // TODO: minimize the signature by removing redundant generic
    // parameters.

    auto lookupParameter = [&](SubstitutableType *type) {
      auto it = substTypes.find(CanType(type));
      assert(it != substTypes.end());
      return it->second;
    };
    auto lookupConformance = [&](CanType dependentType,
                                 Type conformingReplacementType,
                                 ProtocolDecl *conformedProtocol) {
      auto it = substConformances.find({dependentType, conformedProtocol});
      assert(it != substConformances.end());
      return it->second;
    };
    return SubstitutionMap::get(sig, lookupParameter, lookupConformance);
  }

private:
  Type visitProtocolType(CanProtocolType type) {
    // Simple protocol types have no sub-structure.
    assert(!type.getParent());
    return type;
  }

  Type visitParameterizedProtocolType(CanParameterizedProtocolType origType) {
    // Generalize the argument types of parameterized protocols,
    // but don't generalize the base type.
    auto origArgs = origType.getArgs();
    SmallVector<Type, 4> newArgs;
    newArgs.reserve(origArgs.size());
    for (auto origArg: origArgs) {
      newArgs.push_back(generalizeComponentType(origArg));
    }
    return ParameterizedProtocolType::get(ctx, origType->getBaseType(),
                                          newArgs);
  }

  Type visitProtocolCompositionType(CanProtocolCompositionType origType) {
    // The member types of protocol compositions are not substitutable,
    // including class constraints.  Generalize them individually,
    // preserving structure.
    auto origMembers = origType.getMembers();
    SmallVector<Type, 4> newMembers;
    newMembers.reserve(origMembers.size());
    for (auto origMember: origMembers) {
      newMembers.push_back(generalizeStructure(origMember));
    }
    return ProtocolCompositionType::get(ctx, newMembers,
                                        origType->hasExplicitAnyObject());
  }

  // Generalize the type arguments of nominal types.
  Type visitBoundGenericType(CanBoundGenericType origType) {
    return generalizeGenericArguments(origType->getDecl(), origType);
  }
  Type visitNominalType(CanNominalType origType) {
    auto decl = origType->getDecl();
    if (decl->isGenericContext())
      return generalizeGenericArguments(decl, origType);
    return origType;
  }

  // Preserve existential structure.
  Type visitExistentialType(CanExistentialType origType) {
    return ExistentialType::get(
              generalizeStructure(origType.getConstraintType()));
  }
  Type visitExistentialMetatypeType(CanExistentialMetatypeType origType) {
    assert(!origType->hasRepresentation());
    return ExistentialMetatypeType::get(
              generalizeStructure(origType.getInstanceType()));
  }

  // These types can be generalized by a recursive transform of
  // their component types; we don't need to exclude anything or
  // handle conformances.
#define GENERALIZE_COMPONENTS(ID)                              \
  Type visit##ID##Type(Can##ID##Type origType) {               \
    return generalizeComponentTypes(origType);                 \
  }
  GENERALIZE_COMPONENTS(Function)
  GENERALIZE_COMPONENTS(Metatype)
  GENERALIZE_COMPONENTS(Tuple)
#undef GENERALIZE_COMPONENTS

  // These types can never contain component types with abstract
  // constraints, so generalizeComponentType should always substitute
  // them out.
#define NO_PRESERVABLE_STRUCTURE(ID)                           \
  Type visit##ID##Type(Can##ID##Type origType) {               \
    llvm_unreachable(#ID "Type has no structure to preserve"); \
  }
  NO_PRESERVABLE_STRUCTURE(Archetype)
  NO_PRESERVABLE_STRUCTURE(Builtin)
  NO_PRESERVABLE_STRUCTURE(DependentMember)
  NO_PRESERVABLE_STRUCTURE(GenericTypeParam)
  NO_PRESERVABLE_STRUCTURE(Module)
  NO_PRESERVABLE_STRUCTURE(Pack)
  NO_PRESERVABLE_STRUCTURE(PackExpansion)
#undef NO_PRESERVABLE_STRUCTURE

  // These types simply shouldn't appear in types that we generalize at all.
#define INVALID_TO_GENERALIZE(ID)                                       \
  Type visit##ID##Type(Can##ID##Type origType) {                        \
    llvm_unreachable(#ID "type should not be found by generalization"); \
  }
  INVALID_TO_GENERALIZE(DynamicSelf)
  INVALID_TO_GENERALIZE(Error)
  INVALID_TO_GENERALIZE(GenericFunction)
  INVALID_TO_GENERALIZE(InOut)
  INVALID_TO_GENERALIZE(LValue)
  INVALID_TO_GENERALIZE(ReferenceStorage)
  INVALID_TO_GENERALIZE(SILBlockStorage)
  INVALID_TO_GENERALIZE(SILBox)
  INVALID_TO_GENERALIZE(SILFunction)
  INVALID_TO_GENERALIZE(SILToken)
#undef INVALID_TO_GENERALIZE

  /// Generalize the generic arguments of the given generic type.s
  Type generalizeGenericArguments(NominalTypeDecl *decl, CanType type) {
    assert(decl->isGenericContext());
    auto origSubs = type->getContextSubstitutionMap(decl->getModuleContext(),
                                                    decl);

    // Generalize all of the arguments.
    auto origArgs = origSubs.getReplacementTypes();
    SmallVector<Type, 4> newArgs;
    for (auto origArg: origArgs) {
      newArgs.push_back(generalizeComponentType(CanType(origArg)));
    }

    // Generalize all of the conformances.
    // TODO: for abstract requirements, we might not generalize all
    // arguments, and we may need to leave corresponding conformances
    // concrete.
    SmallVector<ProtocolConformanceRef, 4> newConformances;
    auto origConformances = origSubs.getConformances();
    for (auto origConformance: origConformances) {
      newConformances.push_back(
        ProtocolConformanceRef(origConformance.getRequirement()));
    }

    auto origSig = origSubs.getGenericSignature();
    auto newSubs = SubstitutionMap::get(origSig, newArgs, newConformances);

    // Add any conformance requirements to the generic signature and
    // remember the conformances we generalized.
    if (!origConformances.empty()) {
      size_t i = 0;
      for (auto &origReq: origSig.getRequirements()) {
        if (origReq.getKind() != RequirementKind::Conformance) continue;
        auto origConformance = origConformances[i++];

        auto optNewReq = origReq.subst(newSubs);
        assert(optNewReq && "generalization substitution failed");
        auto &newReq = *optNewReq;

        addedRequirements.push_back(newReq);

        substConformances.insert({{newReq.getFirstType()->getCanonicalType(),
                                   newReq.getProtocolDecl()},
                                  origConformance});
      }
    }

    // Build the new type.
    return decl->getDeclaredInterfaceType().subst(newSubs);
  }

  /// Generalize the given type by preserving its top-level structure
  /// but generalizing its component types.
  Type generalizeComponentTypes(CanType type) {
    return type.transformRec([&](TypeBase *componentType) -> Optional<Type> {
      // Ignore the top level.
      if (componentType == type.getPointer())
        return None;

      return generalizeComponentType(CanType(componentType));
    });
  }

  Type generalizeComponentType(CanType origArg) {
    // TODO: Abstract constraints (some P) introduce *existential*
    // component types, which are not substitutable.  Therefore, types
    // containing them must be generalized preserving that structure
    // rather than wholly substituted.  They can appear in arbitrary
    // positions, including within tuple, function, and metatype types,
    // so we'll need to add cases for those to generalizeStructure
    // above.

    // Create a new generalization type parameter and record the
    // substitution.
    auto newParam = GenericTypeParamType::get(/*sequence*/ false,
                                              /*depth*/ 0,
                                              /*index*/ substTypes.size(),
                                              ctx);
    addedParameters.push_back(newParam);

    substTypes.insert({CanType(newParam), origArg});
    return newParam;
  }
};

} // end anonymous namespace

ExistentialTypeGeneralization
ExistentialTypeGeneralization::get(Type rawType) {
  assert(rawType->isExistentialType());
  assert(!rawType->hasTypeParameter());

  // Canonicalize.  We need to generalize the canonical shape of the
  // type or else generalization parameters won't match up.
  CanType type = rawType->getCanonicalType();

  Generalizer generalizer(type->getASTContext());
  Type shape = generalizer.generalizeStructure(type);
  auto subs = generalizer.getGeneralizationSubstitutions();

  return {shape, subs};
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: inetmimetest.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 01:09:49 $
 *
 *  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_tools.hxx"

#include "inetmime.hxx"

#include "rtl/textenc.h"
#include "rtl/ustring.hxx"

#include <cstdlib>
#include <iostream>

namespace {

bool testDecode(char const * input, char const * expected) {
    rtl::OUString result = INetMIME::decodeHeaderFieldBody(
        INetMIME::HEADER_FIELD_TEXT, input);
    bool success = result.equalsAscii(expected);
    if (!success) {
        std::cout
            << "FAILED: decodeHeaderFieldBody(\"" << input << "\"): \""
            << rtl::OUStringToOString(
                result, RTL_TEXTENCODING_ASCII_US).getStr()
            << "\" != \"" << expected << "\"\n";
    }
    return success;
}

}

int
#if defined WNT
__cdecl
#endif
main() {
    bool success = true;
    success &= testDecode("=?iso-8859-1?B?QQ==?=", "A");
    success &= testDecode("=?iso-8859-1?B?QUI=?=", "AB");
    success &= testDecode("=?iso-8859-1?B?QUJD?=", "ABC");
    return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
<commit_msg>INTEGRATION: CWS vgbugs07 (1.4.90); FILE MERGED 2007/06/04 13:32:29 vg 1.4.90.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: inetmimetest.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 22:22:10 $
 *
 *  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_tools.hxx"

#include <tools/inetmime.hxx>

#include "rtl/textenc.h"
#include "rtl/ustring.hxx"

#include <cstdlib>
#include <iostream>

namespace {

bool testDecode(char const * input, char const * expected) {
    rtl::OUString result = INetMIME::decodeHeaderFieldBody(
        INetMIME::HEADER_FIELD_TEXT, input);
    bool success = result.equalsAscii(expected);
    if (!success) {
        std::cout
            << "FAILED: decodeHeaderFieldBody(\"" << input << "\"): \""
            << rtl::OUStringToOString(
                result, RTL_TEXTENCODING_ASCII_US).getStr()
            << "\" != \"" << expected << "\"\n";
    }
    return success;
}

}

int
#if defined WNT
__cdecl
#endif
main() {
    bool success = true;
    success &= testDecode("=?iso-8859-1?B?QQ==?=", "A");
    success &= testDecode("=?iso-8859-1?B?QUI=?=", "AB");
    success &= testDecode("=?iso-8859-1?B?QUJD?=", "ABC");
    return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
<|endoftext|>


<commit_before>//
// Parser is used to invoke the clang libraries to perform actual parsing of
// the input received in the Console.
//
// Part of ccons, the interactive console for the C programming language.
//
// Copyright (c) 2009 Alexei Svitkine. This file is distributed under the
// terms of MIT Open Source License. See file LICENSE for details.
//

#include "Parser.h"

#include <iostream>
#include <stack>
#include <algorithm>

#include <llvm/Config/config.h>

#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/InitHeaderSearch.h>
#include <clang/Frontend/InitPreprocessor.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/LexDiagnostic.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/ParseAST.h>
#include <clang/Sema/SemaDiagnostic.h>

#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/Diagnostic.h>

#include "Diagnostics.h"
#include "SrcGen.h"

using std::string;

namespace ccons {

//
// ParseOperation
//

ParseOperation::ParseOperation(const clang::LangOptions& options,
                               clang::TargetInfo& target,
                               clang::Diagnostic *diag,
                               clang::PPCallbacks *callbacks) :
	_sm(new clang::SourceManager),
	_fm(new clang::FileManager),
	_hs(new clang::HeaderSearch(*_fm))
{
	clang::InitHeaderSearch ihs(*_hs);
	ihs.AddDefaultEnvVarPaths(options);
	ihs.AddDefaultSystemIncludePaths(options);
	ihs.Realize();
	_pp.reset(new clang::Preprocessor(*diag, options, target, *_sm, *_hs));
	_pp->setPPCallbacks(callbacks);
	clang::PreprocessorInitOptions ppOptions;
	InitializePreprocessor(*_pp, "", ppOptions);
	_ast.reset(new clang::ASTContext(options, *_sm, target,
		_pp->getIdentifierTable(), _pp->getSelectorTable()));
}

clang::ASTContext * ParseOperation::getASTContext() const
{
	return _ast.get();
}

clang::Preprocessor * ParseOperation::getPreprocessor() const
{
	return _pp.get();
}

clang::SourceManager * ParseOperation::getSourceManager() const
{
	return _sm.get();
}

//
// Parser
//

Parser::Parser(const clang::LangOptions& options) :
	_options(options),
	_target(clang::TargetInfo::CreateTargetInfo(LLVM_HOSTTRIPLE))
{
}

Parser::~Parser()
{
	releaseAccumulatedParseOperations();
}

void Parser::releaseAccumulatedParseOperations()
{
	for (std::vector<ParseOperation*>::iterator I = _ops.begin(), E = _ops.end();
	     I != E; ++I) {
		delete *I;
	}
	_ops.clear();
}

ParseOperation * Parser::getLastParseOperation() const
{
	return _ops.empty() ? NULL : _ops.back();
}

Parser::InputType Parser::analyzeInput(const string& contextSource,
                                       const string& buffer,
                                       int& indentLevel,
                                       std::vector<clang::FunctionDecl*> *fds)
{
	if (buffer.length() > 1 && buffer[buffer.length() - 2] == '\\') {
		indentLevel = 1;
		return Incomplete;
	}

	ProxyDiagnosticClient pdc(NULL);
	clang::Diagnostic diag(&pdc);
	llvm::OwningPtr<ParseOperation>
		parseOp(new ParseOperation(_options, *_target, &diag));
	createMemoryBuffer(buffer, "", parseOp->getSourceManager());

	clang::Token LastTok;
	bool TokWasDo = false;
	int stackSize =
		analyzeTokens(*parseOp->getPreprocessor(), LastTok, indentLevel, TokWasDo);
	if (stackSize < 0)
		return TopLevel;

	// TokWasDo is used for do { ... } while (...); loops
	if (LastTok.is(clang::tok::semi) || (LastTok.is(clang::tok::r_brace) && !TokWasDo)) {
		if (stackSize > 0) return Incomplete;
		ProxyDiagnosticClient pdc(NULL); // do not output diagnostics
		clang::Diagnostic diag(&pdc);
		// Setting this ensures "foo();" is not a valid top-level declaration.
		diag.setDiagnosticMapping(clang::diag::warn_missing_type_specifier,
	                            clang::diag::MAP_ERROR);
		diag.setSuppressSystemWarnings(true);
		string src = contextSource + buffer;
		struct : public clang::ASTConsumer {
			bool hadIncludedDecls;
			unsigned pos;
			unsigned maxPos;
			clang::SourceManager *sm;
			std::vector<clang::FunctionDecl*> fds;
			void HandleTopLevelDecl(clang::DeclGroupRef D) {
				for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
					if (clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I)) {
						clang::SourceLocation Loc = FD->getTypeSpecStartLoc();
						if (sm->isFromMainFile(Loc)) {
							unsigned offset = sm->getFileOffset(sm->getInstantiationLoc(Loc));
							if (offset >= pos) {
								fds.push_back(FD);
							}
						} else {
							while (!sm->isFromMainFile(Loc)) {
								const clang::SrcMgr::SLocEntry& Entry =
									sm->getSLocEntry(sm->getFileID(sm->getSpellingLoc(Loc)));
								Loc = Entry.getFile().getIncludeLoc();
							}
							unsigned offset = sm->getFileOffset(Loc);
							if (offset >= pos) {
								hadIncludedDecls = true;
							}
						}
					}
				}
			}
		} consumer;
		ParseOperation *parseOp = createParseOperation(&diag);
		consumer.hadIncludedDecls = false;
		consumer.pos = contextSource.length();
		consumer.maxPos = consumer.pos + buffer.length();
		consumer.sm = parseOp->getSourceManager();
		parse(src, parseOp, &consumer);
		if (pdc.hadError(clang::diag::err_unterminated_block_comment))
			return Incomplete;
		if (!pdc.hadErrors() && (!consumer.fds.empty() || consumer.hadIncludedDecls)) {
			if (!consumer.fds.empty())
				fds->swap(consumer.fds);
			return TopLevel;
		}
		return Stmt;
	}

	return Incomplete;
}

int Parser::analyzeTokens(clang::Preprocessor& PP,
                          clang::Token& LastTok,
                          int& indentLevel,
                          bool& TokWasDo)
{
	int result;
	std::stack<std::pair<clang::Token, clang::Token> > S; // Tok, PrevTok

	indentLevel = 0;
	PP.EnterMainSourceFile();

	clang::Token Tok;
	PP.Lex(Tok);
	while (Tok.isNot(clang::tok::eof)) {
		if (Tok.is(clang::tok::l_square)) {
			S.push(std::make_pair(Tok, LastTok)); // [
		} else if (Tok.is(clang::tok::l_paren)) {
			S.push(std::make_pair(Tok, LastTok)); // (
		} else if (Tok.is(clang::tok::l_brace)) {
			S.push(std::make_pair(Tok, LastTok)); // {
			indentLevel++;
		} else if (Tok.is(clang::tok::r_square)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_square)) {
				std::cout << "Unmatched [\n";
				return -1;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_paren)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_paren)) {
				std::cout << "Unmatched (\n";
				return -1;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_brace)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_brace)) {
				std::cout << "Unmatched {\n";
				return -1;
			}
			TokWasDo = S.top().second.is(clang::tok::kw_do);
			S.pop();
			indentLevel--;
		}
		LastTok = Tok;
		PP.Lex(Tok);
	}
	result = S.size();

	// TODO: We need to properly account for indent-level for blocks that do not
	//       have braces... such as:
	//
	//       if (X)
	//         Y;
	//
	// TODO: Do-while without braces doesn't work, e.g.:
	//
	//       do
	//         foo();
	//       while (bar());
	//
	// Both of the above could be solved by some kind of rewriter-pass that would
	// insert implicit braces (or simply a more involved analysis).

	// Also try to match preprocessor conditionals...
	if (result == 0) {
		clang::Lexer Lexer(PP.getSourceManager().getMainFileID(),
		                   PP.getSourceManager(),
		                   PP.getLangOptions());
		Lexer.LexFromRawLexer(Tok);
		while (Tok.isNot(clang::tok::eof)) {
			if (Tok.is(clang::tok::hash)) {
				Lexer.LexFromRawLexer(Tok);
				if (clang::IdentifierInfo *II = PP.LookUpIdentifierInfo(Tok)) {
					switch (II->getPPKeywordID()) {
						case clang::tok::pp_if:
						case clang::tok::pp_ifdef:
						case clang::tok::pp_ifndef:
							result++;
							break;
						case clang::tok::pp_endif:
							if (result == 0)
								return -1; // Nesting error.
							result--;
							break;
						default:
							break;
					}
				}
			}
			Lexer.LexFromRawLexer(Tok);
		}
	}

	return result;
}

ParseOperation * Parser::createParseOperation(clang::Diagnostic *diag,
                                              clang::PPCallbacks *callbacks)
{
	return new ParseOperation(_options, *_target, diag, callbacks);
}

void Parser::parse(const string& src,
                   ParseOperation *parseOp,
                   clang::ASTConsumer *consumer)
{
	_ops.push_back(parseOp);
	createMemoryBuffer(src, "", parseOp->getSourceManager());
	clang::ParseAST(*parseOp->getPreprocessor(), consumer,
	                *parseOp->getASTContext());
}

void Parser::parse(const string& src,
                   clang::Diagnostic *diag,
                   clang::ASTConsumer *consumer)
{
	parse(src, createParseOperation(diag), consumer);
}

llvm::MemoryBuffer * Parser::createMemoryBuffer(const string& src,
                                                const char *name,
                                                clang::SourceManager *sm)
{
	llvm::MemoryBuffer *mb =
		llvm::MemoryBuffer::getMemBufferCopy(&*src.begin(), &*src.end(), name);
	assert(mb && "Error creating MemoryBuffer!");
	sm->createMainFileIDForMemBuffer(mb);
	assert(!sm->getMainFileID().isInvalid() && "Error creating MainFileID!");
	return mb;
}

} // namespace ccons
<commit_msg>fix build<commit_after>//
// Parser is used to invoke the clang libraries to perform actual parsing of
// the input received in the Console.
//
// Part of ccons, the interactive console for the C programming language.
//
// Copyright (c) 2009 Alexei Svitkine. This file is distributed under the
// terms of MIT Open Source License. See file LICENSE for details.
//

#include "Parser.h"

#include <iostream>
#include <stack>
#include <algorithm>

#include <llvm/Config/config.h>

#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/InitHeaderSearch.h>
#include <clang/Frontend/InitPreprocessor.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/LexDiagnostic.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/ParseAST.h>
#include <clang/Sema/SemaDiagnostic.h>

#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/Diagnostic.h>

#include "Diagnostics.h"
#include "SrcGen.h"

using std::string;

namespace ccons {

//
// ParseOperation
//

ParseOperation::ParseOperation(const clang::LangOptions& options,
                               clang::TargetInfo& target,
                               clang::Diagnostic *diag,
                               clang::PPCallbacks *callbacks) :
	_sm(new clang::SourceManager),
	_fm(new clang::FileManager),
	_hs(new clang::HeaderSearch(*_fm))
{
	clang::InitHeaderSearch ihs(*_hs);
	ihs.AddDefaultEnvVarPaths(options);
	ihs.AddDefaultSystemIncludePaths(options);
	ihs.Realize();
	_pp.reset(new clang::Preprocessor(*diag, options, target, *_sm, *_hs));
	_pp->setPPCallbacks(callbacks);
	clang::PreprocessorInitOptions ppOptions;
	InitializePreprocessor(*_pp, ppOptions);
	_ast.reset(new clang::ASTContext(options, *_sm, target,
		_pp->getIdentifierTable(), _pp->getSelectorTable()));
}

clang::ASTContext * ParseOperation::getASTContext() const
{
	return _ast.get();
}

clang::Preprocessor * ParseOperation::getPreprocessor() const
{
	return _pp.get();
}

clang::SourceManager * ParseOperation::getSourceManager() const
{
	return _sm.get();
}

//
// Parser
//

Parser::Parser(const clang::LangOptions& options) :
	_options(options),
	_target(clang::TargetInfo::CreateTargetInfo(LLVM_HOSTTRIPLE))
{
}

Parser::~Parser()
{
	releaseAccumulatedParseOperations();
}

void Parser::releaseAccumulatedParseOperations()
{
	for (std::vector<ParseOperation*>::iterator I = _ops.begin(), E = _ops.end();
	     I != E; ++I) {
		delete *I;
	}
	_ops.clear();
}

ParseOperation * Parser::getLastParseOperation() const
{
	return _ops.empty() ? NULL : _ops.back();
}

Parser::InputType Parser::analyzeInput(const string& contextSource,
                                       const string& buffer,
                                       int& indentLevel,
                                       std::vector<clang::FunctionDecl*> *fds)
{
	if (buffer.length() > 1 && buffer[buffer.length() - 2] == '\\') {
		indentLevel = 1;
		return Incomplete;
	}

	ProxyDiagnosticClient pdc(NULL);
	clang::Diagnostic diag(&pdc);
	llvm::OwningPtr<ParseOperation>
		parseOp(new ParseOperation(_options, *_target, &diag));
	createMemoryBuffer(buffer, "", parseOp->getSourceManager());

	clang::Token LastTok;
	bool TokWasDo = false;
	int stackSize =
		analyzeTokens(*parseOp->getPreprocessor(), LastTok, indentLevel, TokWasDo);
	if (stackSize < 0)
		return TopLevel;

	// TokWasDo is used for do { ... } while (...); loops
	if (LastTok.is(clang::tok::semi) || (LastTok.is(clang::tok::r_brace) && !TokWasDo)) {
		if (stackSize > 0) return Incomplete;
		ProxyDiagnosticClient pdc(NULL); // do not output diagnostics
		clang::Diagnostic diag(&pdc);
		// Setting this ensures "foo();" is not a valid top-level declaration.
		diag.setDiagnosticMapping(clang::diag::warn_missing_type_specifier,
	                            clang::diag::MAP_ERROR);
		diag.setSuppressSystemWarnings(true);
		string src = contextSource + buffer;
		struct : public clang::ASTConsumer {
			bool hadIncludedDecls;
			unsigned pos;
			unsigned maxPos;
			clang::SourceManager *sm;
			std::vector<clang::FunctionDecl*> fds;
			void HandleTopLevelDecl(clang::DeclGroupRef D) {
				for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
					if (clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I)) {
						clang::SourceLocation Loc = FD->getTypeSpecStartLoc();
						if (sm->isFromMainFile(Loc)) {
							unsigned offset = sm->getFileOffset(sm->getInstantiationLoc(Loc));
							if (offset >= pos) {
								fds.push_back(FD);
							}
						} else {
							while (!sm->isFromMainFile(Loc)) {
								const clang::SrcMgr::SLocEntry& Entry =
									sm->getSLocEntry(sm->getFileID(sm->getSpellingLoc(Loc)));
								Loc = Entry.getFile().getIncludeLoc();
							}
							unsigned offset = sm->getFileOffset(Loc);
							if (offset >= pos) {
								hadIncludedDecls = true;
							}
						}
					}
				}
			}
		} consumer;
		ParseOperation *parseOp = createParseOperation(&diag);
		consumer.hadIncludedDecls = false;
		consumer.pos = contextSource.length();
		consumer.maxPos = consumer.pos + buffer.length();
		consumer.sm = parseOp->getSourceManager();
		parse(src, parseOp, &consumer);
		if (pdc.hadError(clang::diag::err_unterminated_block_comment))
			return Incomplete;
		if (!pdc.hadErrors() && (!consumer.fds.empty() || consumer.hadIncludedDecls)) {
			if (!consumer.fds.empty())
				fds->swap(consumer.fds);
			return TopLevel;
		}
		return Stmt;
	}

	return Incomplete;
}

int Parser::analyzeTokens(clang::Preprocessor& PP,
                          clang::Token& LastTok,
                          int& indentLevel,
                          bool& TokWasDo)
{
	int result;
	std::stack<std::pair<clang::Token, clang::Token> > S; // Tok, PrevTok

	indentLevel = 0;
	PP.EnterMainSourceFile();

	clang::Token Tok;
	PP.Lex(Tok);
	while (Tok.isNot(clang::tok::eof)) {
		if (Tok.is(clang::tok::l_square)) {
			S.push(std::make_pair(Tok, LastTok)); // [
		} else if (Tok.is(clang::tok::l_paren)) {
			S.push(std::make_pair(Tok, LastTok)); // (
		} else if (Tok.is(clang::tok::l_brace)) {
			S.push(std::make_pair(Tok, LastTok)); // {
			indentLevel++;
		} else if (Tok.is(clang::tok::r_square)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_square)) {
				std::cout << "Unmatched [\n";
				return -1;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_paren)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_paren)) {
				std::cout << "Unmatched (\n";
				return -1;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_brace)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_brace)) {
				std::cout << "Unmatched {\n";
				return -1;
			}
			TokWasDo = S.top().second.is(clang::tok::kw_do);
			S.pop();
			indentLevel--;
		}
		LastTok = Tok;
		PP.Lex(Tok);
	}
	result = S.size();

	// TODO: We need to properly account for indent-level for blocks that do not
	//       have braces... such as:
	//
	//       if (X)
	//         Y;
	//
	// TODO: Do-while without braces doesn't work, e.g.:
	//
	//       do
	//         foo();
	//       while (bar());
	//
	// Both of the above could be solved by some kind of rewriter-pass that would
	// insert implicit braces (or simply a more involved analysis).

	// Also try to match preprocessor conditionals...
	if (result == 0) {
		clang::Lexer Lexer(PP.getSourceManager().getMainFileID(),
		                   PP.getSourceManager(),
		                   PP.getLangOptions());
		Lexer.LexFromRawLexer(Tok);
		while (Tok.isNot(clang::tok::eof)) {
			if (Tok.is(clang::tok::hash)) {
				Lexer.LexFromRawLexer(Tok);
				if (clang::IdentifierInfo *II = PP.LookUpIdentifierInfo(Tok)) {
					switch (II->getPPKeywordID()) {
						case clang::tok::pp_if:
						case clang::tok::pp_ifdef:
						case clang::tok::pp_ifndef:
							result++;
							break;
						case clang::tok::pp_endif:
							if (result == 0)
								return -1; // Nesting error.
							result--;
							break;
						default:
							break;
					}
				}
			}
			Lexer.LexFromRawLexer(Tok);
		}
	}

	return result;
}

ParseOperation * Parser::createParseOperation(clang::Diagnostic *diag,
                                              clang::PPCallbacks *callbacks)
{
	return new ParseOperation(_options, *_target, diag, callbacks);
}

void Parser::parse(const string& src,
                   ParseOperation *parseOp,
                   clang::ASTConsumer *consumer)
{
	_ops.push_back(parseOp);
	createMemoryBuffer(src, "", parseOp->getSourceManager());
	clang::ParseAST(*parseOp->getPreprocessor(), consumer,
	                *parseOp->getASTContext());
}

void Parser::parse(const string& src,
                   clang::Diagnostic *diag,
                   clang::ASTConsumer *consumer)
{
	parse(src, createParseOperation(diag), consumer);
}

llvm::MemoryBuffer * Parser::createMemoryBuffer(const string& src,
                                                const char *name,
                                                clang::SourceManager *sm)
{
	llvm::MemoryBuffer *mb =
		llvm::MemoryBuffer::getMemBufferCopy(&*src.begin(), &*src.end(), name);
	assert(mb && "Error creating MemoryBuffer!");
	sm->createMainFileIDForMemBuffer(mb);
	assert(!sm->getMainFileID().isInvalid() && "Error creating MainFileID!");
	return mb;
}

} // namespace ccons
<|endoftext|>


<commit_before>#include "Player.h"
#include "Renderer.h"

void Player::SetDirection(Position direction)
{
	if (!Cornering)
	{
		NextDir = direction;
	}
}

bool Player::CanGo(const Field *f, Position delta)
{
	Position sum = CurrentPos + delta;
	Position newPos(
			(sum.X + (FIELD_WIDTH * TILE_SIZE))
			% (FIELD_WIDTH * TILE_SIZE),
			(sum.Y + (FIELD_HEIGHT * TILE_SIZE))
			% (FIELD_HEIGHT * TILE_SIZE));
	Field::TileType new_tile = f->InterpolateAtPos(newPos);

	Field::TileType move_flag = MoveFlag();
	return (new_tile & move_flag) == move_flag;
}

Player::Event Player::Move(const Field *f, Field::PelletStatus &p)
{
	if (Paused == 0)
	{
		int corner_range = CornerRange();
		for (int i = 0, distance = Speed(); i < distance; i++)
		{
			if (CanGo(f, NextDir))
			{
				CurrentPos += NextDir;
				CurrentDir = NextDir;
				Cornering = false;
			}
			else if (Cornering
					|| corner_range > 0
					&& CanGo(
						f,
						CurrentDir * CornerRange() + NextDir * CornerRange()))
			{
				CurrentPos += CurrentDir + NextDir;
				Cornering = true;
			}
			else if (CanGo(f, CurrentDir))
			{
				CurrentPos += CurrentDir;
			}
			CurrentPos = Position(
					(CurrentPos.X + (FIELD_WIDTH * TILE_SIZE))
					% (FIELD_WIDTH * TILE_SIZE),
					(CurrentPos.Y + (FIELD_HEIGHT * TILE_SIZE))
					% (FIELD_HEIGHT * TILE_SIZE));
		}
	}
	else
	{
		Paused--;
	}
	AnimFrame++;
	return None;
}
<commit_msg>Players don't animate when paused<commit_after>#include "Player.h"
#include "Renderer.h"

void Player::SetDirection(Position direction)
{
	if (!Cornering)
	{
		NextDir = direction;
	}
}

bool Player::CanGo(const Field *f, Position delta)
{
	Position sum = CurrentPos + delta;
	Position newPos(
			(sum.X + (FIELD_WIDTH * TILE_SIZE))
			% (FIELD_WIDTH * TILE_SIZE),
			(sum.Y + (FIELD_HEIGHT * TILE_SIZE))
			% (FIELD_HEIGHT * TILE_SIZE));
	Field::TileType new_tile = f->InterpolateAtPos(newPos);

	Field::TileType move_flag = MoveFlag();
	return (new_tile & move_flag) == move_flag;
}

Player::Event Player::Move(const Field *f, Field::PelletStatus &p)
{
	if (Paused == 0)
	{
		int corner_range = CornerRange();
		for (int i = 0, distance = Speed(); i < distance; i++)
		{
			if (CanGo(f, NextDir))
			{
				CurrentPos += NextDir;
				CurrentDir = NextDir;
				Cornering = false;
			}
			else if (Cornering
					|| corner_range > 0
					&& CanGo(
						f,
						CurrentDir * CornerRange() + NextDir * CornerRange()))
			{
				CurrentPos += CurrentDir + NextDir;
				Cornering = true;
			}
			else if (CanGo(f, CurrentDir))
			{
				CurrentPos += CurrentDir;
			}
			CurrentPos = Position(
					(CurrentPos.X + (FIELD_WIDTH * TILE_SIZE))
					% (FIELD_WIDTH * TILE_SIZE),
					(CurrentPos.Y + (FIELD_HEIGHT * TILE_SIZE))
					% (FIELD_HEIGHT * TILE_SIZE));
		}
		AnimFrame++;
	}
	else
	{
		Paused--;
	}
	return None;
}
<|endoftext|>