<commit_before>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_MATCHING_IND_MATCH_DECORATOR_XY_HPP
#define OPENMVG_MATCHING_IND_MATCH_DECORATOR_XY_HPP

#include <algorithm>
#include <iostream>
#include <fstream>
#include <set>
#include <vector>

#include "openMVG/features/feature.hpp"
#include "openMVG/matching/indMatch.hpp"

namespace openMVG {
namespace matching {

/// IndMatch decorator.
/// Use sorting over x,y coordinates.
template<class T = float>
class IndMatchDecorator
{
  struct IndMatchDecoratorStruct
  {
    IndMatchDecoratorStruct
    (
      T xa, T ya,
      T xb, T yb,
      const IndMatch & ind
    )
    {
      x1 = xa; y1 = ya;
      x2 = xb; y2 = yb;
      index = ind;
    }

    /// Lexicographical ordering of matches. Used to remove duplicates.
    friend bool operator<
    (
      const IndMatchDecoratorStruct& m1,
      const IndMatchDecoratorStruct& m2
    )
    {
      if (m1 == m2) return false;

      if (m1.x1 < m2.x1)
        return m1.y1 < m2.y1;
      else
        if (m1.x1 > m2.x1)
          return m1.y1 < m2.y1;
      return m1.x1 < m2.x1;
    }

    /// Comparison Operator
    friend bool operator==
    (
      const IndMatchDecoratorStruct& m1,
      const IndMatchDecoratorStruct& m2
    )
    {

      return (m1.x1==m2.x1 && m1.y1==m2.y1 &&
        m1.x2==m2.x2 && m1.y2==m2.y2);
    }

    T x1,y1, x2,y2;
    IndMatch index;
  };
public:

  IndMatchDecorator
  (
    const std::vector<IndMatch> & vec_matches,
    const std::vector<features::SIOPointFeature> & leftFeat,
    const std::vector<features::SIOPointFeature> & rightFeat
  )
  :vec_matches_(vec_matches)
  {
    for ( const auto & cur_vec_match : vec_matches )
    {
      const size_t I = cur_vec_match.i_;
      const size_t J = cur_vec_match.j_;
      vecDecoredMatches_.push_back(
        IndMatchDecoratorStruct(leftFeat[I].x(),leftFeat[I].y(),
        rightFeat[J].x(), rightFeat[J].y(), cur_vec_match));
    }
  }

  IndMatchDecorator
  (
    const std::vector<IndMatch> & vec_matches,
    const std::vector<features::PointFeature> & leftFeat,
    const std::vector<features::PointFeature> & rightFeat
  )
  :vec_matches_(vec_matches)
  {
    for ( const auto & cur_vec_match : vec_matches )
    {
      const size_t I = cur_vec_match.i_;
      const size_t J = cur_vec_match.j_;
      vecDecoredMatches_.push_back(
        IndMatchDecoratorStruct(leftFeat[I].x(),leftFeat[I].y(),
        rightFeat[J].x(), rightFeat[J].y(), cur_vec_match));
    }
  }

  IndMatchDecorator
  (
    const std::vector<IndMatch> & vec_matches,
    const Mat & leftFeat,
    const Mat & rightFeat
  )
  :vec_matches_(vec_matches)
  {
    for ( const auto & cur_vec_match : vec_matches )
    {
      const size_t I = cur_vec_match.i_;
      const size_t J = cur_vec_match.j_;
      vecDecoredMatches_.push_back(
        IndMatchDecoratorStruct(leftFeat.col(I)(0),leftFeat.col(I)(1),
        rightFeat.col(J)(0), rightFeat.col(J)(1), cur_vec_match));
    }
  }

  /// Remove duplicates (same (x1,y1) coords that appears multiple times)
  size_t getDeduplicated(std::vector<IndMatch> & vec_matches)
  {
    const size_t sizeBefore = vecDecoredMatches_.size();
    std::set<IndMatchDecoratorStruct> set_deduplicated(
      vecDecoredMatches_.begin(),vecDecoredMatches_.end());
    vecDecoredMatches_.assign(set_deduplicated.begin(), set_deduplicated.end());

    vec_matches.resize(vecDecoredMatches_.size());
    for (size_t i = 0; i < vecDecoredMatches_.size(); ++i)  {
      const IndMatch & idxM = vecDecoredMatches_[i].index;
      vec_matches[i] = idxM;
    }

    return sizeBefore != vec_matches.size();
  }

  /**
    * Save the corresponding matches to file.
    * \param nameFile   The file where matches will be saved.
    * \param vec_match  The matches that we want to save.
    * \return bool True if everything was ok, otherwise false.
    */
    bool saveMatch(const char* nameFile) const
    {
      std::ofstream f(nameFile);
      if( f.is_open() ) {
        std::copy(vecDecoredMatches_.begin(), vecDecoredMatches_.end(),
          std::ostream_iterator<IndMatchDecoratorStruct>(f, ""));
      }
      return f.is_open();
    }

    friend std::ostream& operator<<(std::ostream& os, const IndMatchDecoratorStruct & m)
    {
      return os << m.x1 << " " << m.y1 << " " << m.x2 << " " << m.y2 << "\n";
    }

private :
  std::vector<IndMatch> vec_matches_;
  std::vector<IndMatchDecoratorStruct> vecDecoredMatches_;
};

}  // namespace matching
}  // namespace openMVG

#endif // OPENMVG_MATCHING_IND_MATCH_DECORATOR_XY_HPP
<commit_msg>cosmetic #827<commit_after>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_MATCHING_IND_MATCH_DECORATOR_XY_HPP
#define OPENMVG_MATCHING_IND_MATCH_DECORATOR_XY_HPP

#include <algorithm>
#include <iostream>
#include <fstream>
#include <set>
#include <vector>

#include "openMVG/features/feature.hpp"
#include "openMVG/matching/indMatch.hpp"

namespace openMVG {
namespace matching {

/// IndMatch decorator.
/// Use sorting over x,y coordinates.
template<class T = float>
class IndMatchDecorator
{
  struct IndMatchDecoratorStruct
  {
    IndMatchDecoratorStruct
    (
      T xa, T ya,
      T xb, T yb,
      const IndMatch & ind
    )
    {
      x1 = xa; y1 = ya;
      x2 = xb; y2 = yb;
      index = ind;
    }

    /// Lexicographical ordering of matches. Used to remove duplicates.
    friend bool operator<
    (
      const IndMatchDecoratorStruct& m1,
      const IndMatchDecoratorStruct& m2
    )
    {
      if (m1 == m2) return false;

      if (m1.x1 < m2.x1)
        return m1.y1 < m2.y1;
      else
        if (m1.x1 > m2.x1)
          return m1.y1 < m2.y1;
      return m1.x1 < m2.x1;
    }

    /// Comparison Operator
    friend bool operator==
    (
      const IndMatchDecoratorStruct& m1,
      const IndMatchDecoratorStruct& m2
    )
    {

      return (m1.x1==m2.x1 && m1.y1==m2.y1 &&
        m1.x2==m2.x2 && m1.y2==m2.y2);
    }

    T x1,y1, x2,y2;
    IndMatch index;
  };
public:

  IndMatchDecorator
  (
    const std::vector<IndMatch> & vec_matches,
    const std::vector<features::SIOPointFeature> & leftFeat,
    const std::vector<features::SIOPointFeature> & rightFeat
  )
  :vec_matches_(vec_matches)
  {
    for ( const auto & cur_vec_match : vec_matches )
    {
      const size_t I = cur_vec_match.i_;
      const size_t J = cur_vec_match.j_;
      vecDecoredMatches_.push_back(
        IndMatchDecoratorStruct(leftFeat[I].x(),leftFeat[I].y(),
        rightFeat[J].x(), rightFeat[J].y(), cur_vec_match));
    }
  }

  IndMatchDecorator
  (
    const std::vector<IndMatch> & vec_matches,
    const std::vector<features::PointFeature> & leftFeat,
    const std::vector<features::PointFeature> & rightFeat
  )
  :vec_matches_(vec_matches)
  {
    for ( const auto & cur_vec_match : vec_matches )
    {
      const size_t I = cur_vec_match.i_;
      const size_t J = cur_vec_match.j_;
      vecDecoredMatches_.push_back(
        IndMatchDecoratorStruct(leftFeat[I].x(),leftFeat[I].y(),
        rightFeat[J].x(), rightFeat[J].y(), cur_vec_match));
    }
  }

  IndMatchDecorator
  (
    const std::vector<IndMatch> & vec_matches,
    const Mat & leftFeat,
    const Mat & rightFeat
  )
  :vec_matches_(vec_matches)
  {
    for ( const auto & cur_vec_match : vec_matches )
    {
      const size_t I = cur_vec_match.i_;
      const size_t J = cur_vec_match.j_;
      vecDecoredMatches_.push_back(
        IndMatchDecoratorStruct(leftFeat.col(I)(0),leftFeat.col(I)(1),
        rightFeat.col(J)(0), rightFeat.col(J)(1), cur_vec_match));
    }
  }

  /// Remove duplicates (same (x1,y1) coords that appears multiple times)
  size_t getDeduplicated(std::vector<IndMatch> & vec_matches)
  {
    const size_t sizeBefore = vecDecoredMatches_.size();
    std::set<IndMatchDecoratorStruct> set_deduplicated(
      vecDecoredMatches_.begin(),vecDecoredMatches_.end());
    vecDecoredMatches_.assign(set_deduplicated.begin(), set_deduplicated.end());

    vec_matches.resize(vecDecoredMatches_.size());
    for (size_t i = 0; i < vecDecoredMatches_.size(); ++i)  {
      const IndMatch & idxM = vecDecoredMatches_[i].index;
      vec_matches[i] = idxM;
    }

    return sizeBefore != vec_matches.size();
  }

  /**
  * Save the corresponding matches to file.
  * \param nameFile   The file where matches will be saved.
  * \param vec_match  The matches that we want to save.
  * \return bool True if everything was ok, otherwise false.
  */
  bool saveMatch(const char* nameFile) const
  {
    std::ofstream f(nameFile);
    if( f.is_open() ) {
      std::copy(vecDecoredMatches_.begin(), vecDecoredMatches_.end(),
        std::ostream_iterator<IndMatchDecoratorStruct>(f, ""));
    }
    return f.is_open();
  }

  friend std::ostream& operator<<(std::ostream& os, const IndMatchDecoratorStruct & m)
  {
    return os << m.x1 << " " << m.y1 << " " << m.x2 << " " << m.y2 << "\n";
  }

private :
  std::vector<IndMatch> vec_matches_;
  std::vector<IndMatchDecoratorStruct> vecDecoredMatches_;
};

}  // namespace matching
}  // namespace openMVG

#endif // OPENMVG_MATCHING_IND_MATCH_DECORATOR_XY_HPP
<|endoftext|>


<commit_before><commit_msg>:bug: fix psfwriter<commit_after><|endoftext|>


<commit_before><commit_msg>Add optional_for support for `void`<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: namedvaluecollection.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-04 13:58:47 $
 *
 *  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
 *
 ************************************************************************/

#ifndef COMPHELPER_NAMEDVALUECOLLECTION_HXX
#include <comphelper/namedvaluecollection.hxx>
#endif

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_
#include <com/sun/star/beans/NamedValue.hpp>
#endif
/** === end UNO includes === **/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#include <hash_map>

//........................................................................
namespace comphelper
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::uno::Type;
    using ::com::sun::star::uno::cpp_acquire;
    using ::com::sun::star::uno::cpp_release;
    using ::com::sun::star::uno::cpp_queryInterface;
    /** === end UNO using === **/

    //====================================================================
    //= NamedValueCollection_Impl
    //====================================================================
    typedef ::std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash >    NamedValueRepository;

    struct NamedValueCollection_Impl
    {
        NamedValueRepository    aValues;
    };

    //====================================================================
    //= NamedValueCollection
    //====================================================================
    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection()
        :m_pImpl( new NamedValueCollection_Impl )
    {
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::~NamedValueCollection()
    {
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments )
    {
        {
            NamedValueRepository empty;
            m_pImpl->aValues.swap( empty );
        }

        PropertyValue aPropertyValue;
        NamedValue aNamedValue;

        const Any* pArgument = _rArguments.getConstArray();
        const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
        {
            if ( *pArgument >>= aPropertyValue )
                m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value;
            else if ( *pArgument >>= aNamedValue )
                m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value;
            else
                OSL_ENSURE( !pArgument->hasValue(), "NamedValueCollection::NamedValueCollection: encountered a value which I cannot handle!" );
        }
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments )
    {
        {
            NamedValueRepository empty;
            m_pImpl->aValues.swap( empty );
        }

        const PropertyValue* pArgument = _rArguments.getConstArray();
        const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
            m_pImpl->aValues[ pArgument->Name ] = pArgument->Value;
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::getIfExists_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
        {
            return uno_type_assignData(
                _pValueLocation, _rExpectedValueType.getTypeLibType(),
                const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(),
                reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
                reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
                reinterpret_cast< uno_ReleaseFunc >( cpp_release )
            );
        }
        return true;
    }

    //--------------------------------------------------------------------
    const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
            return pos->second;

        static Any aEmptyDefault;
        return aEmptyDefault;
    }

//........................................................................
} // namespace comphelper
//........................................................................

<commit_msg>INTEGRATION: CWS pchfix02 (1.3.10); FILE MERGED 2006/09/01 17:19:43 kaib 1.3.10.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: namedvaluecollection.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 17:12:43 $
 *
 *  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_comphelper.hxx"

#ifndef COMPHELPER_NAMEDVALUECOLLECTION_HXX
#include <comphelper/namedvaluecollection.hxx>
#endif

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_
#include <com/sun/star/beans/NamedValue.hpp>
#endif
/** === end UNO includes === **/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#include <hash_map>

//........................................................................
namespace comphelper
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::uno::Type;
    using ::com::sun::star::uno::cpp_acquire;
    using ::com::sun::star::uno::cpp_release;
    using ::com::sun::star::uno::cpp_queryInterface;
    /** === end UNO using === **/

    //====================================================================
    //= NamedValueCollection_Impl
    //====================================================================
    typedef ::std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash >    NamedValueRepository;

    struct NamedValueCollection_Impl
    {
        NamedValueRepository    aValues;
    };

    //====================================================================
    //= NamedValueCollection
    //====================================================================
    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection()
        :m_pImpl( new NamedValueCollection_Impl )
    {
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::~NamedValueCollection()
    {
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments )
    {
        {
            NamedValueRepository empty;
            m_pImpl->aValues.swap( empty );
        }

        PropertyValue aPropertyValue;
        NamedValue aNamedValue;

        const Any* pArgument = _rArguments.getConstArray();
        const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
        {
            if ( *pArgument >>= aPropertyValue )
                m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value;
            else if ( *pArgument >>= aNamedValue )
                m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value;
            else
                OSL_ENSURE( !pArgument->hasValue(), "NamedValueCollection::NamedValueCollection: encountered a value which I cannot handle!" );
        }
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments )
    {
        {
            NamedValueRepository empty;
            m_pImpl->aValues.swap( empty );
        }

        const PropertyValue* pArgument = _rArguments.getConstArray();
        const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
            m_pImpl->aValues[ pArgument->Name ] = pArgument->Value;
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::getIfExists_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
        {
            return uno_type_assignData(
                _pValueLocation, _rExpectedValueType.getTypeLibType(),
                const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(),
                reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
                reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
                reinterpret_cast< uno_ReleaseFunc >( cpp_release )
            );
        }
        return true;
    }

    //--------------------------------------------------------------------
    const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
            return pos->second;

        static Any aEmptyDefault;
        return aEmptyDefault;
    }

//........................................................................
} // namespace comphelper
//........................................................................

<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 1/27/2019, 9:12:45 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M;
int A[100010];
int B[100010];
set<int> V[100010];
set<int> W[100010];
int root;
int depth[100010];
int parent[100010];
typedef tuple<int, int, int> T; // v, pa, de
queue<T> Q;

void solve(int v)
{
  if (parent[v] != -2)
  {
    return;
  }
  for (auto x : W[v])
  {
    solve(x);
  }
  int maxi = 0;
  int ind = -1;
  for (auto x : W[v])
  {
    if (maxi < depth[x])
    {
      ind = x;
      maxi = depth[x];
    }
  }
  parent[v] = ind;
  depth[v] = maxi + 1;
  cerr << "parent[" << v << "] = " << parent[v] << endl;
  cerr << "depth[" << v << "] = " << depth[v] << endl;
}

int main()
{
  cin >> N >> M;
  for (auto i = 0; i < N - 1 + M; i++)
  {
    cin >> A[i] >> B[i];
    A[i]--;
    B[i]--;
  }
  for (auto i = 0; i < N - 1 + M; i++)
  {
    V[A[i]].insert(B[i]);
    W[B[i]].insert(A[i]);
  }
  fill(depth, depth + N, -1);
  fill(parent, parent + N, -2);
  int root_cnt = 0;
  for (auto i = 0; i < N; i++)
  {
    if (W[i].empty())
    {
      root_cnt++;
      root = i;
      depth[i] = 0;
      parent[i] = -1;
    }
  }
  assert(root_cnt == 1);
  for (auto i = 0; i < N; i++)
  {
    solve(i);
  }
  for (auto i = 0; i < N; i++)
  {
    cout << parent[i] + 1 << endl;
  }
}<commit_msg>submit D.cpp to 'D - Restore the Tree' (nikkei2019-qual) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 1/27/2019, 9:12:45 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M;
int A[100010];
int B[100010];
set<int> V[100010];
set<int> W[100010];
int root;
int depth[100010];
int parent[100010];
typedef tuple<int, int, int> T; // v, pa, de
queue<T> Q;

void solve(int v)
{
  if (parent[v] != -2)
  {
    return;
  }
  for (auto x : W[v])
  {
    solve(x);
  }
  int maxi = -1;
  int ind = -1;
  for (auto x : W[v])
  {
    if (maxi < depth[x])
    {
      ind = x;
      maxi = depth[x];
    }
  }
  parent[v] = ind;
  depth[v] = maxi + 1;
  // cerr << "parent[" << v << "] = " << parent[v] << endl;
  // cerr << "depth[" << v << "] = " << depth[v] << endl;
}

int main()
{
  cin >> N >> M;
  for (auto i = 0; i < N - 1 + M; i++)
  {
    cin >> A[i] >> B[i];
    A[i]--;
    B[i]--;
  }
  for (auto i = 0; i < N - 1 + M; i++)
  {
    V[A[i]].insert(B[i]);
    W[B[i]].insert(A[i]);
  }
  fill(depth, depth + N, -1);
  fill(parent, parent + N, -2);
  int root_cnt = 0;
  for (auto i = 0; i < N; i++)
  {
    if (W[i].empty())
    {
      root_cnt++;
      root = i;
      depth[i] = 0;
      parent[i] = -1;
    }
  }
  assert(root_cnt == 1);
  for (auto i = 0; i < N; i++)
  {
    solve(i);
  }
  for (auto i = 0; i < N; i++)
  {
    cout << parent[i] + 1 << endl;
  }
}<|endoftext|>


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

#include "stdafx.h"
#include "starbuck.h"
#include "BuildServerManager.h"
#include <QGLWidget>
#include "ScrollHandler.h"

using namespace BlackBerry::Starbuck;

const int Starbuck::PROGRESS_BAR_HEIGHT = 23;

Starbuck::Starbuck(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags)
{
    init();
}

Starbuck::~Starbuck()
{
    if (_config != NULL)
    delete _config;

    if ( progressBar != NULL )
    delete progressBar;

    if ( webViewInternal != NULL )
    delete webViewInternal;
}

void Starbuck::enableHardwareAcceleration()
{
    if (!_hwToggleMenuItem->isChecked())
    {
        _config->hardwareAccelerationEnabled(0);
        _hwToggleMenuItem->setChecked(false);
    }
    else
    {
        _config->hardwareAccelerationEnabled(1);
        _hwToggleMenuItem->setChecked(true);
    }

    QMessageBox::information(this, "Restart Ripple", "Please restart Ripple for changes to take effect");
}

void Starbuck::enableWebGL()
{
    if (!_webGLToggleMenuItem->isChecked())
    {
        _config->webGLEnabled(0);
        _webGLToggleMenuItem->setChecked(false);
        webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::WebGLEnabled, false);
    }
    else
    {
        _config->webGLEnabled(1);
        _webGLToggleMenuItem->setChecked(true);
        webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::WebGLEnabled, true);
    }
}

void Starbuck::init(void)
{

    // create menu items
    _optionsMenu = menuBar()->addMenu("Options");
    _hwToggleMenuItem = _optionsMenu->addAction("Enable Hardware Acceleration", this, SLOT(enableHardwareAcceleration()));
    _hwToggleMenuItem->setCheckable(true);
    _webGLToggleMenuItem = _optionsMenu->addAction("Enable WebGL", this, SLOT(enableWebGL()));
    _webGLToggleMenuItem->setCheckable(true);

    _config = ConfigData::getInstance();
    setAttribute(Qt::WA_DeleteOnClose);

    webViewInternal = new QtGraphicsStageWebView(this);
	webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
	webViewInternal->qtStageWebView()->settings()->enablePersistentStorage(_config->localStoragePath());
    webViewInternal->qtStageWebView()->settings()->setOfflineStorageDefaultQuota(512000000);
    webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
    webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true);
#if QT_VERSION >= 0x040800
    webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true);
#endif
    webViewInternal->qtStageWebView()->settings()->setWebSecurityEnabled(false);

    if (_config->webGLEnabled() == 1)
    {
        _webGLToggleMenuItem->setChecked(true);
        webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::WebGLEnabled, true);
    }

    if (_config->hardwareAccelerationEnabled() == 1)
    {
        _hwToggleMenuItem->setChecked(true);
        _GLWidget = new QGLWidget;
        QGLFormat format;
        format.setSampleBuffers(2);
        format.setRgba(true);
        format.setDoubleBuffer(true);
        _GLWidget->setFormat(format);
        webViewInternal->setViewport(_GLWidget);
        webViewInternal->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
        _GLWidget->makeCurrent();

        // init scroll handler
        _scrollHandler = new ScrollHandler(webViewInternal->qtStageWebView());
        _GLWidget->installEventFilter(_scrollHandler);

    }

    //Progress bar-------------------------
    progressBar = new QProgressBar(this);
    progressBar->setObjectName(QString::fromUtf8("progressBar"));
    //When the loading of a new page has started, show and reset the progress bar
    connect(webViewInternal, SIGNAL(loadStarted()), progressBar, SLOT( show() ));
    connect(webViewInternal, SIGNAL(loadStarted()), progressBar, SLOT( reset()));
    //Increment the progress bar as the page loads
    connect(webViewInternal, SIGNAL(loadProgress(int)), progressBar, SLOT(setValue(int)));
    //When page is finished loading, hide the progress bar
    connect(webViewInternal, SIGNAL(loadFinished(bool)), progressBar, SLOT( hide() ));
    //--------------------------------------
    // init window

    QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
    QSize size = _config->windowSize();
    resize(size);

    if (_config->windowState() == 1)
        setWindowState(Qt::WindowMaximized);

    //Set geometry for progressbar
    progressBar->setGeometry(QRect(0, (size.height() - PROGRESS_BAR_HEIGHT), size.width(), PROGRESS_BAR_HEIGHT));

    move(_config->windowPosition());

    webViewInternal->qtStageWebView()->load(QUrl(_config->toolingContent()));

    setCentralWidget(webViewInternal);

    //register webview
    connect(webViewInternal->qtStageWebView()->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(registerAPIs()));

    //stagewebview interfaces
    m_pStageViewHandler = new StageViewMsgHandler(this);
    m_pStageViewHandler->Register(webViewInternal->qtStageWebView());

    //start build server
    connect(BuildServerManager::getInstance(), SIGNAL(findUsablePort(int)), m_pStageViewHandler, SLOT(setServerPort(int)));

    QFile cmd(_config->buildServiceCommand());
    if (cmd.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QTextStream in(&cmd);
        m_pStageViewHandler->setServerPort(BuildServerManager::getInstance()->start(in.readLine(), _config->buildServicePort()));
        cmd.close();
    }
    else
    {
        qDebug() << "Can not open file:" << cmd.fileName() << "Error:" << cmd.error();
        cmd.close();
    }

}

void Starbuck::closeEvent(QCloseEvent *event)
{
    _config->windowPosition(pos());
    if (this->windowState() != Qt::WindowMaximized)
        _config->windowSize(size());
    _config->windowState((this->windowState() == Qt::WindowMaximized) ? 1 : 0);
    _config->writeSettings();
    event->accept();
    BuildServerManager::getInstance()->stop();
}

void Starbuck::registerAPIs()
{
    //register StageWebViewMsgHandler as JS object named stagewebview
    QWebFrame* frame = webViewInternal->qtStageWebView()->page()->mainFrame();
    frame->addToJavaScriptWindowObject(QString("stagewebview"), m_pStageViewHandler);
}

void Starbuck::resizeEvent(QResizeEvent * e )
{
    webViewInternal->qtStageWebView()->setGeometry(this->geometry());
	progressBar->setGeometry(QRect(0, (e->size().height() - PROGRESS_BAR_HEIGHT), e->size().width(), PROGRESS_BAR_HEIGHT));
    e->accept();
}
<commit_msg>Another small fix to resizing window code, issue #58<commit_after>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "stdafx.h"
#include "starbuck.h"
#include "BuildServerManager.h"
#include <QGLWidget>
#include "ScrollHandler.h"

using namespace BlackBerry::Starbuck;

const int Starbuck::PROGRESS_BAR_HEIGHT = 23;

Starbuck::Starbuck(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags)
{
    init();
}

Starbuck::~Starbuck()
{
    if (_config != NULL)
    delete _config;

    if ( progressBar != NULL )
    delete progressBar;

    if ( webViewInternal != NULL )
    delete webViewInternal;
}

void Starbuck::enableHardwareAcceleration()
{
    if (!_hwToggleMenuItem->isChecked())
    {
        _config->hardwareAccelerationEnabled(0);
        _hwToggleMenuItem->setChecked(false);
    }
    else
    {
        _config->hardwareAccelerationEnabled(1);
        _hwToggleMenuItem->setChecked(true);
    }

    QMessageBox::information(this, "Restart Ripple", "Please restart Ripple for changes to take effect");
}

void Starbuck::enableWebGL()
{
    if (!_webGLToggleMenuItem->isChecked())
    {
        _config->webGLEnabled(0);
        _webGLToggleMenuItem->setChecked(false);
        webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::WebGLEnabled, false);
    }
    else
    {
        _config->webGLEnabled(1);
        _webGLToggleMenuItem->setChecked(true);
        webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::WebGLEnabled, true);
    }
}

void Starbuck::init(void)
{

    // create menu items
    _optionsMenu = menuBar()->addMenu("Options");
    _hwToggleMenuItem = _optionsMenu->addAction("Enable Hardware Acceleration", this, SLOT(enableHardwareAcceleration()));
    _hwToggleMenuItem->setCheckable(true);
    _webGLToggleMenuItem = _optionsMenu->addAction("Enable WebGL", this, SLOT(enableWebGL()));
    _webGLToggleMenuItem->setCheckable(true);

    _config = ConfigData::getInstance();
    setAttribute(Qt::WA_DeleteOnClose);

    webViewInternal = new QtGraphicsStageWebView(this);
	webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
	webViewInternal->qtStageWebView()->settings()->enablePersistentStorage(_config->localStoragePath());
    webViewInternal->qtStageWebView()->settings()->setOfflineStorageDefaultQuota(512000000);
    webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
    webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true);
#if QT_VERSION >= 0x040800
    webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true);
#endif
    webViewInternal->qtStageWebView()->settings()->setWebSecurityEnabled(false);

    if (_config->webGLEnabled() == 1)
    {
        _webGLToggleMenuItem->setChecked(true);
        webViewInternal->qtStageWebView()->settings()->setAttribute(QWebSettings::WebGLEnabled, true);
    }

    if (_config->hardwareAccelerationEnabled() == 1)
    {
        _hwToggleMenuItem->setChecked(true);
        _GLWidget = new QGLWidget;
        QGLFormat format;
        format.setSampleBuffers(2);
        format.setRgba(true);
        format.setDoubleBuffer(true);
        _GLWidget->setFormat(format);
        webViewInternal->setViewport(_GLWidget);
        webViewInternal->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
        _GLWidget->makeCurrent();

        // init scroll handler
        _scrollHandler = new ScrollHandler(webViewInternal->qtStageWebView());
        _GLWidget->installEventFilter(_scrollHandler);

    }

    //Progress bar-------------------------
    progressBar = new QProgressBar(this);
    progressBar->setObjectName(QString::fromUtf8("progressBar"));
    //When the loading of a new page has started, show and reset the progress bar
    connect(webViewInternal, SIGNAL(loadStarted()), progressBar, SLOT( show() ));
    connect(webViewInternal, SIGNAL(loadStarted()), progressBar, SLOT( reset()));
    //Increment the progress bar as the page loads
    connect(webViewInternal, SIGNAL(loadProgress(int)), progressBar, SLOT(setValue(int)));
    //When page is finished loading, hide the progress bar
    connect(webViewInternal, SIGNAL(loadFinished(bool)), progressBar, SLOT( hide() ));
    //--------------------------------------
    // init window

    QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
    QSize size = _config->windowSize();
    resize(size);

    if (_config->windowState() == 1)
        setWindowState(Qt::WindowMaximized);

    //Set geometry for progressbar
    progressBar->setGeometry(QRect(0, (size.height() - PROGRESS_BAR_HEIGHT), size.width(), PROGRESS_BAR_HEIGHT));

    move(_config->windowPosition());

    webViewInternal->qtStageWebView()->load(QUrl(_config->toolingContent()));

    setCentralWidget(webViewInternal);

    //register webview
    connect(webViewInternal->qtStageWebView()->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(registerAPIs()));

    //stagewebview interfaces
    m_pStageViewHandler = new StageViewMsgHandler(this);
    m_pStageViewHandler->Register(webViewInternal->qtStageWebView());

    //start build server
    connect(BuildServerManager::getInstance(), SIGNAL(findUsablePort(int)), m_pStageViewHandler, SLOT(setServerPort(int)));

    QFile cmd(_config->buildServiceCommand());
    if (cmd.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QTextStream in(&cmd);
        m_pStageViewHandler->setServerPort(BuildServerManager::getInstance()->start(in.readLine(), _config->buildServicePort()));
        cmd.close();
    }
    else
    {
        qDebug() << "Can not open file:" << cmd.fileName() << "Error:" << cmd.error();
        cmd.close();
    }

}

void Starbuck::closeEvent(QCloseEvent *event)
{
    _config->windowPosition(pos());
    if (this->windowState() != Qt::WindowMaximized)
        _config->windowSize(size());
    _config->windowState((this->windowState() == Qt::WindowMaximized) ? 1 : 0);
    _config->writeSettings();
    event->accept();
    BuildServerManager::getInstance()->stop();
}

void Starbuck::registerAPIs()
{
    //register StageWebViewMsgHandler as JS object named stagewebview
    QWebFrame* frame = webViewInternal->qtStageWebView()->page()->mainFrame();
    frame->addToJavaScriptWindowObject(QString("stagewebview"), m_pStageViewHandler);
}

void Starbuck::resizeEvent(QResizeEvent * e )
{
    QRect geo = this->geometry();
    geo.setX(0);
    geo.setY(0);
    webViewInternal->qtStageWebView()->setGeometry(geo);
	progressBar->setGeometry(QRect(0, (e->size().height() - PROGRESS_BAR_HEIGHT), e->size().width(), PROGRESS_BAR_HEIGHT));
    e->accept();
}
<|endoftext|>


<commit_before>//
//  CAS.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 25/11/2017.
//  Copyright 2017 Thomas Harte. All rights reserved.
//

#include "CAS.hpp"

#include <cassert>
#include <cstring>

using namespace Storage::Tape;

/*
	CAS files are a raw byte capture of tape content, with all solid tones transmuted to
	the placeholder 1F A6 DE BA CC 13 7D 74 and gaps omitted.

	Since that byte stream may also occur within files, and gaps and tone lengths need to be
	reconstructed, knowledge of the MSX tape byte format is also required. Specifically:

	Each tone followed by ten bytes that determine the file type:

		ten bytes of value 0xD0 => a binary file;
		ten bytes of value 0xD3 => it's a basic file;
		ten bytes of value 0xEA => it's an ASCII file; and
		any other pattern implies a raw data block.

	Raw data blocks contain their two-byte length, then data.

	Binary, Basic and ASCII files then have a six-byte file name, followed by a short tone, followed
	by the file contents.

	ASCII files:

		... are a sequence of short tone/256-byte chunk pairs. For CAS purposes, these continue until
		you hit another 1F A6 DE BA CC 13 7D 74 sequence.

	Binary files:

		... begin with three 16-bit values, the starting, ending and execution addresses. Then there is
		the correct amount of data to fill memory from the starting to the ending address, inclusive.

	BASIC files:

		... are in Microsoft-standard BASIC form of (two bytes link to next line), (two bytes line number), [tokens],
		starting from address 0x8001. These files continue until a next line address of 0x0000 is found, then
		are usually padded by 0s for a period that I haven't yet determined a pattern for. The code below treats
		everything to the next 0x1f as padding.
*/

namespace  {
	const uint8_t header_signature[8] = {0x1f, 0xa6, 0xde, 0xba, 0xcc, 0x13, 0x7d, 0x74};

	#define TenX(x) {x, x, x, x, x, x, x, x, x, x}
	const uint8_t binary_signature[] = TenX(0xd0);
	const uint8_t basic_signature[] = TenX(0xd3);
	const uint8_t ascii_signature[] = TenX(0xea);
}

CAS::CAS(const std::string &file_name) {
	Storage::FileHolder file(file_name);

	enum class Mode {
		Seeking,
		ASCII,
		Binary,
		BASIC
	} parsing_mode_ = Mode::Seeking;

	while(true) {
		// Churn through the file until the next header signature is found.
		const auto header_position = file.tell();
		const auto signature = file.read(8);
		if(signature.size() != 8) break;
		if(std::memcmp(signature.data(), header_signature, 8)) {
			// Check for other 1fs in this stream, and repeat from there if any.
			for(size_t c = 0; c < 8; ++c) {
				if(signature[c] == 0x1f) {
					file.seek(header_position + long(c), SEEK_SET);
					break;
				} else {
					// Attach any unexpected bytes to the back of the most recent chunk.
					// In effect this creates a linear search for the next explicit tone.
					if(!chunks_.empty()) {
						chunks_.back().data.push_back(signature[c]);
					}
				}
			}
			continue;
		}

		// A header has definitely been found. Require from here at least 16 further bytes,
		// being the type and a name.
		const auto type = file.read(10);
		if(type.size() != 10) break;

		const bool is_binary	= !std::memcmp(type.data(), binary_signature, type.size());
		const bool is_basic		= !std::memcmp(type.data(), basic_signature, type.size());
		const bool is_ascii		= !std::memcmp(type.data(), ascii_signature, type.size());

		switch(parsing_mode_) {
			case Mode::Seeking: {
				if(is_ascii || is_binary || is_basic) {
					file.seek(header_position + 8, SEEK_SET);
					chunks_.emplace_back(!chunks_.empty(), true, file.read(10 + 6));

					if(is_ascii)	parsing_mode_ = Mode::ASCII;
					if(is_binary)	parsing_mode_ = Mode::Binary;
					if(is_basic)	parsing_mode_ = Mode::BASIC;
				} else {
					// Raw data appears now. Grab its length and keep going.
					file.seek(header_position + 8, SEEK_SET);
					const uint16_t length = file.get16le();

					file.seek(header_position, SEEK_SET);
					chunks_.emplace_back(false, false, file.read(size_t(length) + 2 + 8));
				}
			} break;

			case Mode::ASCII:
				// Keep reading ASCII in 256-byte segments until a non-ASCII chunk arrives.
				if(is_binary || is_basic || is_ascii) {
					file.seek(header_position, SEEK_SET);
					parsing_mode_ = Mode::Seeking;
				} else {
					file.seek(header_position + 8, SEEK_SET);
					chunks_.emplace_back(false, false, file.read(256));
				}
			break;

			case Mode::Binary: {
				// Get the start and end addresses in order to figure out how much data
				// is here.
				file.seek(header_position + 8, SEEK_SET);
				const uint16_t start_address = file.get16le();
				const uint16_t end_address = file.get16le();

				file.seek(header_position + 8, SEEK_SET);
				const auto length = end_address - start_address + 1;
				chunks_.emplace_back(false, false, file.read(size_t(length) + 6));

				parsing_mode_ = Mode::Seeking;
			} break;

			case Mode::BASIC: {
				// Horror of horrors, this will mean actually following the BASIC
				// linked list of line contents.
				file.seek(header_position + 8, SEEK_SET);
				uint16_t address = 0x8001;	// the BASIC start address.
				while(true) {
					const uint16_t next_line_address = file.get16le();
					if(!next_line_address || file.eof()) break;
					file.seek(next_line_address - address - 2, SEEK_CUR);
					address = next_line_address;
				}
				const auto length = (file.tell() - 1) - (header_position + 8);

				// Create the chunk and return to regular parsing.
				file.seek(header_position + 8, SEEK_SET);
				chunks_.emplace_back(false, false, file.read(size_t(length)));
				parsing_mode_ = Mode::Seeking;
			} break;
		}
	}
}

bool CAS::is_at_end() {
	return phase_ == Phase::EndOfFile;
}

void CAS::virtual_reset() {
	phase_ = Phase::Header;
	chunk_pointer_ = 0;
	distance_into_phase_ = 0;
	distance_into_bit_ = 0;
}

Tape::Pulse CAS::virtual_get_next_pulse() {
	Pulse pulse;
	pulse.length.clock_rate = 9600;
	// Clock rate is four times the baud rate (of 2400), because the quickest thing that might need
	// to be communicated is a '1', which is two cycles at the baud rate, i.e. four events:
	// high, low, high, low.

	// If this is a gap, then that terminates a file. If this is already the end
	// of the file then perpetual gaps await.
	if(phase_ == Phase::Gap || phase_ == Phase::EndOfFile) {
		pulse.length.length = pulse.length.clock_rate;
		pulse.type = Pulse::Type::Zero;

		if(phase_ == Phase::Gap) {
			phase_ = Phase::Header;
			distance_into_phase_ = 0;
		}

		return pulse;
	}

	// Determine which bit is now forthcoming.
	int bit = 1;

	switch(phase_) {
		default: break;

		case Phase::Header: {
			// In the header, all bits are 1s, so let the default value stand. Just check whether the
			// header is ended and, if so, move on to bytes.
			distance_into_bit_++;
			if(distance_into_bit_ == 2) {
				distance_into_phase_++;
				distance_into_bit_ = 0;

				// This code always produces a 2400 baud signal; so use the appropriate Red Book-supplied
				// constants to check whether the header has come to an end.
				if(distance_into_phase_ == (chunks_[chunk_pointer_].long_header ? 31744 : 7936)) {
					phase_ = Phase::Bytes;
					distance_into_phase_ = 0;
					distance_into_bit_ = 0;
				}
			}
		} break;

		case Phase::Bytes: {
			// Provide bits with a single '0' start bit and two '1' stop bits.
			uint8_t byte_value = chunks_[chunk_pointer_].data[distance_into_phase_ / 11];
			int bit_offset = distance_into_phase_ % 11;
			switch(bit_offset) {
				case 0:		bit = 0;									break;
				default:	bit = (byte_value >> (bit_offset - 1)) & 1;	break;
				case 9:
				case 10:	bit = 1;									break;
			}

			// If bit is finished, and if all bytes in chunk have been posted then:
			//	- if this is the final chunk then note end of file.
			//	- otherwise, roll onto the next header or gap, depending on whether the next chunk has a gap.
			distance_into_bit_++;
			if(distance_into_bit_ == (bit ? 4 : 2)) {
				distance_into_bit_ = 0;
				distance_into_phase_++;
				if(distance_into_phase_ == chunks_[chunk_pointer_].data.size() * 11) {
					distance_into_phase_ = 0;
					chunk_pointer_++;
					if(chunk_pointer_ == chunks_.size()) {
						phase_ = Phase::EndOfFile;
					} else {
						phase_ = chunks_[chunk_pointer_].has_gap ? Phase::Gap : Phase::Header;
					}
				}
			}
		} break;
	}

	// A '1' is encoded with twice the frequency of a '0'.
	pulse.length.length = static_cast<unsigned int>(2 - bit);
	pulse.type = (distance_into_bit_ & 1) ? Pulse::Type::High : Pulse::Type::Low;

	return pulse;
}
<commit_msg>Corrects arithmetic on raw data blocks.<commit_after>//
//  CAS.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 25/11/2017.
//  Copyright 2017 Thomas Harte. All rights reserved.
//

#include "CAS.hpp"

#include <cassert>
#include <cstring>

using namespace Storage::Tape;

/*
	CAS files are a raw byte capture of tape content, with all solid tones transmuted to
	the placeholder 1F A6 DE BA CC 13 7D 74 and gaps omitted.

	Since that byte stream may also occur within files, and gaps and tone lengths need to be
	reconstructed, knowledge of the MSX tape byte format is also required. Specifically:

	Each tone followed by ten bytes that determine the file type:

		ten bytes of value 0xD0 => a binary file;
		ten bytes of value 0xD3 => it's a basic file;
		ten bytes of value 0xEA => it's an ASCII file; and
		any other pattern implies a raw data block.

	Raw data blocks contain their two-byte length, then data.

	Binary, Basic and ASCII files then have a six-byte file name, followed by a short tone, followed
	by the file contents.

	ASCII files:

		... are a sequence of short tone/256-byte chunk pairs. For CAS purposes, these continue until
		you hit another 1F A6 DE BA CC 13 7D 74 sequence.

	Binary files:

		... begin with three 16-bit values, the starting, ending and execution addresses. Then there is
		the correct amount of data to fill memory from the starting to the ending address, inclusive.

	BASIC files:

		... are in Microsoft-standard BASIC form of (two bytes link to next line), (two bytes line number), [tokens],
		starting from address 0x8001. These files continue until a next line address of 0x0000 is found, then
		are usually padded by 0s for a period that I haven't yet determined a pattern for. The code below treats
		everything to the next 0x1f as padding.
*/

namespace  {
	const uint8_t header_signature[8] = {0x1f, 0xa6, 0xde, 0xba, 0xcc, 0x13, 0x7d, 0x74};

	#define TenX(x) {x, x, x, x, x, x, x, x, x, x}
	const uint8_t binary_signature[] = TenX(0xd0);
	const uint8_t basic_signature[] = TenX(0xd3);
	const uint8_t ascii_signature[] = TenX(0xea);
}

CAS::CAS(const std::string &file_name) {
	Storage::FileHolder file(file_name);

	enum class Mode {
		Seeking,
		ASCII,
		Binary,
		BASIC
	} parsing_mode_ = Mode::Seeking;

	while(true) {
		// Churn through the file until the next header signature is found.
		const auto header_position = file.tell();
		const auto signature = file.read(8);
		if(signature.size() != 8) break;
		if(std::memcmp(signature.data(), header_signature, 8)) {
			// Check for other 1fs in this stream, and repeat from there if any.
			for(size_t c = 0; c < 8; ++c) {
				if(signature[c] == 0x1f) {
					file.seek(header_position + long(c), SEEK_SET);
					break;
				} else {
					// Attach any unexpected bytes to the back of the most recent chunk.
					// In effect this creates a linear search for the next explicit tone.
					if(!chunks_.empty()) {
						chunks_.back().data.push_back(signature[c]);
					}
				}
			}
			continue;
		}

		// A header has definitely been found. Require from here at least 16 further bytes,
		// being the type and a name.
		const auto type = file.read(10);
		if(type.size() != 10) break;

		const bool is_binary	= !std::memcmp(type.data(), binary_signature, type.size());
		const bool is_basic		= !std::memcmp(type.data(), basic_signature, type.size());
		const bool is_ascii		= !std::memcmp(type.data(), ascii_signature, type.size());

		switch(parsing_mode_) {
			case Mode::Seeking: {
				if(is_ascii || is_binary || is_basic) {
					file.seek(header_position + 8, SEEK_SET);
					chunks_.emplace_back(!chunks_.empty(), true, file.read(10 + 6));

					if(is_ascii)	parsing_mode_ = Mode::ASCII;
					if(is_binary)	parsing_mode_ = Mode::Binary;
					if(is_basic)	parsing_mode_ = Mode::BASIC;
				} else {
					// Raw data appears now. Grab its length and keep going.
					file.seek(header_position + 8, SEEK_SET);
					const uint16_t length = file.get16le();

					file.seek(header_position + 8, SEEK_SET);
					chunks_.emplace_back(false, false, file.read(size_t(length) + 2));
				}
			} break;

			case Mode::ASCII:
				// Keep reading ASCII in 256-byte segments until a non-ASCII chunk arrives.
				if(is_binary || is_basic || is_ascii) {
					file.seek(header_position, SEEK_SET);
					parsing_mode_ = Mode::Seeking;
				} else {
					file.seek(header_position + 8, SEEK_SET);
					chunks_.emplace_back(false, false, file.read(256));
				}
			break;

			case Mode::Binary: {
				// Get the start and end addresses in order to figure out how much data
				// is here.
				file.seek(header_position + 8, SEEK_SET);
				const uint16_t start_address = file.get16le();
				const uint16_t end_address = file.get16le();

				file.seek(header_position + 8, SEEK_SET);
				const auto length = end_address - start_address + 1;
				chunks_.emplace_back(false, false, file.read(size_t(length) + 6));

				parsing_mode_ = Mode::Seeking;
			} break;

			case Mode::BASIC: {
				// Horror of horrors, this will mean actually following the BASIC
				// linked list of line contents.
				file.seek(header_position + 8, SEEK_SET);
				uint16_t address = 0x8001;	// the BASIC start address.
				while(true) {
					const uint16_t next_line_address = file.get16le();
					if(!next_line_address || file.eof()) break;
					file.seek(next_line_address - address - 2, SEEK_CUR);
					address = next_line_address;
				}
				const auto length = (file.tell() - 1) - (header_position + 8);

				// Create the chunk and return to regular parsing.
				file.seek(header_position + 8, SEEK_SET);
				chunks_.emplace_back(false, false, file.read(size_t(length)));
				parsing_mode_ = Mode::Seeking;
			} break;
		}
	}
}

bool CAS::is_at_end() {
	return phase_ == Phase::EndOfFile;
}

void CAS::virtual_reset() {
	phase_ = Phase::Header;
	chunk_pointer_ = 0;
	distance_into_phase_ = 0;
	distance_into_bit_ = 0;
}

Tape::Pulse CAS::virtual_get_next_pulse() {
	Pulse pulse;
	pulse.length.clock_rate = 9600;
	// Clock rate is four times the baud rate (of 2400), because the quickest thing that might need
	// to be communicated is a '1', which is two cycles at the baud rate, i.e. four events:
	// high, low, high, low.

	// If this is a gap, then that terminates a file. If this is already the end
	// of the file then perpetual gaps await.
	if(phase_ == Phase::Gap || phase_ == Phase::EndOfFile) {
		pulse.length.length = pulse.length.clock_rate;
		pulse.type = Pulse::Type::Zero;

		if(phase_ == Phase::Gap) {
			phase_ = Phase::Header;
			distance_into_phase_ = 0;
		}

		return pulse;
	}

	// Determine which bit is now forthcoming.
	int bit = 1;

	switch(phase_) {
		default: break;

		case Phase::Header: {
			// In the header, all bits are 1s, so let the default value stand. Just check whether the
			// header is ended and, if so, move on to bytes.
			distance_into_bit_++;
			if(distance_into_bit_ == 2) {
				distance_into_phase_++;
				distance_into_bit_ = 0;

				// This code always produces a 2400 baud signal; so use the appropriate Red Book-supplied
				// constants to check whether the header has come to an end.
				if(distance_into_phase_ == (chunks_[chunk_pointer_].long_header ? 31744 : 7936)) {
					phase_ = Phase::Bytes;
					distance_into_phase_ = 0;
					distance_into_bit_ = 0;
				}
			}
		} break;

		case Phase::Bytes: {
			// Provide bits with a single '0' start bit and two '1' stop bits.
			uint8_t byte_value = chunks_[chunk_pointer_].data[distance_into_phase_ / 11];
			int bit_offset = distance_into_phase_ % 11;
			switch(bit_offset) {
				case 0:		bit = 0;									break;
				default:	bit = (byte_value >> (bit_offset - 1)) & 1;	break;
				case 9:
				case 10:	bit = 1;									break;
			}

			// If bit is finished, and if all bytes in chunk have been posted then:
			//	- if this is the final chunk then note end of file.
			//	- otherwise, roll onto the next header or gap, depending on whether the next chunk has a gap.
			distance_into_bit_++;
			if(distance_into_bit_ == (bit ? 4 : 2)) {
				distance_into_bit_ = 0;
				distance_into_phase_++;
				if(distance_into_phase_ == chunks_[chunk_pointer_].data.size() * 11) {
					distance_into_phase_ = 0;
					chunk_pointer_++;
					if(chunk_pointer_ == chunks_.size()) {
						phase_ = Phase::EndOfFile;
					} else {
						phase_ = chunks_[chunk_pointer_].has_gap ? Phase::Gap : Phase::Header;
					}
				}
			}
		} break;
	}

	// A '1' is encoded with twice the frequency of a '0'.
	pulse.length.length = static_cast<unsigned int>(2 - bit);
	pulse.type = (distance_into_bit_ & 1) ? Pulse::Type::High : Pulse::Type::Low;

	return pulse;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: precompiled_basctl.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:30.436716

#ifdef PRECOMPILED_HEADERS
#include <tools/debug.hxx>
#endif

<commit_msg>INTEGRATION: CWS obo30 (1.4.16); FILE MERGED 2008/06/06 05:29:20 obo 1.4.16.1: #i90100# enable PCH<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: precompiled_basctl.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:30.436716

#ifdef PRECOMPILED_HEADERS
#include "com/sun/star/accessibility/AccessibleEventId.hpp"
#include "com/sun/star/accessibility/AccessibleRole.hpp"
#include "com/sun/star/accessibility/AccessibleStateType.hpp"
#include "com/sun/star/awt/XDialog.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/beans/XPropertySet.hpp"
#include "com/sun/star/beans/Property.hpp"
#include "com/sun/star/container/XNameContainer.hpp"
#include "com/sun/star/document/MacroExecMode.hpp"
#include "com/sun/star/frame/XDispatchProvider.hpp"
#include "com/sun/star/frame/XLayoutManager.hpp"
#include "com/sun/star/resource/XStringResourcePersistence.hpp"
#include "com/sun/star/script/XLibraryContainer.hpp"
#include "com/sun/star/script/XLibraryContainerPassword.hpp"
#ifndef _COM_SUN_STAR_SCRIPT_XLIBRYARYCONTAINER2_HPP_
#include "com/sun/star/script/XLibraryContainer2.hpp"
#endif
#include "com/sun/star/task/XStatusIndicator.hpp"
#include "com/sun/star/task/XStatusIndicatorFactory.hpp"
#include "com/sun/star/ui/dialogs/XFilePicker.hpp"
#include "com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp"
#include "com/sun/star/ui/dialogs/XFilterManager.hpp"
#include "com/sun/star/ui/dialogs/TemplateDescription.hpp"
#include "com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp"
#include "com/sun/star/util/XCloneable.hpp"

#include "comphelper/types.hxx"
#include "comphelper/processfactory.hxx"

#include "toolkit/awt/vclxfont.hxx"
#include "toolkit/helper/externallock.hxx"
#include "toolkit/helper/convert.hxx"
#include "toolkit/helper/vclunohelper.hxx"

#include "tools/debug.hxx"
#include "tools/diagnose_ex.h"
#include "tools/urlobj.hxx"

#include "vcl/wrkwin.hxx"
#include "vcl/msgbox.hxx"
#include "vcl/menu.hxx"
#include "vcl/status.hxx"
#include "vcl/sound.hxx"
#include "vcl/svapp.hxx"
#include "vcl/scrbar.hxx"

#include "svtools/svarray.hxx"
#include "svtools/itempool.hxx"
#include "svtools/itemset.hxx"
#include "svtools/aeitem.hxx"
#include "svtools/stritem.hxx"
#include "svtools/whiter.hxx"
#include "svtools/langtab.hxx"
#include "svtools/texteng.hxx"
#include "svtools/textview.hxx"
#include "svtools/xtextedt.hxx"
#include "svtools/txtattr.hxx"
#include "svtools/textwindowpeer.hxx"
#include "svtools/urihelper.hxx"

#define _BASIC_TEXTPORTIONS
#include "basic/sbdef.hxx"
#include "basic/sbstar.hxx"
#include "basic/sbmeth.hxx"
#include "basic/sbmod.hxx"
#include "basic/basmgr.hxx"
#include "basic/sbuno.hxx"
#include "basic/basrdll.hxx"
#include "basic/sbx.hxx"

#include "sfx2/app.hxx"
#include "sfx2/objface.hxx"
#include "sfx2/printer.hxx"
#include "sfx2/viewsh.hxx"
#include "sfx2/event.hxx"
#include "sfx2/bindings.hxx"
#include "sfx2/request.hxx"
#include "sfx2/childwin.hxx"
#include "sfx2/viewfrm.hxx"
#include "sfx2/dispatch.hxx"
#include "sfx2/objsh.hxx"
#include "sfx2/genlink.hxx"
#include "sfx2/dispatch.hxx"
#include "sfx2/minfitem.hxx"
#include "sfx2/dinfdlg.hxx"
#include "sfx2/docfac.hxx"
#include "sfx2/progress.hxx"
#include "sfx2/docfile.hxx"
#include "sfx2/docfac.hxx"

#define ITEMID_FONT             0
#define ITEMID_POSTURE          0
#define ITEMID_WEIGHT           0
#define ITEMID_SHADOWED         0
#define ITEMID_CONTOUR          0
#define ITEMID_CROSSEDOUT       0
#define ITEMID_UNDERLINE        0
#define ITEMID_FONTHEIGHT       0
#define ITEMID_COLOR            0
#define ITEMID_ADJUST           0
#define ITEMID_LINESPACING      0
#define ITEMID_TABSTOP          0
#define ITEMID_LRSPACE          0
#define ITEMID_ULSPACE          0
#define ITEMID_SEARCH           0
#define ITEMID_SEARCH           0
#define ITEMID_SIZE             0
#define ITEMID_FONTLIST     0
#define ITEMID_AUTOKERN     0
#define ITEMID_WORDLINEMODE 0
#define ITEMID_PROPSIZE     0
#define ITEMID_CHARSETCOLOR 0
#define ITEMID_KERNING      0
#define ITEMID_CASEMAP      0
#define ITEMID_ESCAPEMENT   0
#define ITEMID_LANGUAGE     0
#define ITEMID_NOLINEBREAK  0
#define ITEMID_NOHYPHENHERE 0
#define ITEMID_BLINK        0
#define ITEMID_PAPERBIN     0
#define ITEMID_PRINT        0
#define ITEMID_OPAQUE       0
#define ITEMID_PROTECT      0
#define ITEMID_SHADOW       0
#define ITEMID_BOX          0
#define ITEMID_BOXINFO      0
#define ITEMID_FMTBREAK     0
#define ITEMID_FMTKEEP      0
#define ITEMID_LINE         0
#define ITEMID_BRUSH        0

#include "svx/srchitem.hxx"
#include "svx/flstitem.hxx"
#include "svx/fontitem.hxx"
#include "svx/postitem.hxx"
#include "svx/wghtitem.hxx"
#include "svx/fhgtitem.hxx"
#include "svx/fwdtitem.hxx"
#include "svx/udlnitem.hxx"
#include "svx/crsditem.hxx"
#include "svx/shdditem.hxx"
#include "svx/akrnitem.hxx"
#include "svx/wrlmitem.hxx"
#include "svx/cntritem.hxx"
#include "svx/prszitem.hxx"
#include "svx/colritem.hxx"
#include "svx/cscoitem.hxx"
#include "svx/kernitem.hxx"

#include "svx/cmapitem.hxx"
#include "svx/escpitem.hxx"
#include "svx/langitem.hxx"
#include "svx/nlbkitem.hxx"
#include "svx/nhypitem.hxx"
#include "svx/lcolitem.hxx"
#include "svx/blnkitem.hxx"

#include "svx/pbinitem.hxx"
#include "svx/sizeitem.hxx"
#include "svx/lrspitem.hxx"
#include "svx/ulspitem.hxx"
#include "svx/prntitem.hxx"
#include "svx/opaqitem.hxx"
#include "svx/protitem.hxx"
#include "svx/shaditem.hxx"
#include "svx/boxitem.hxx"
#include "svx/brkitem.hxx"
#include "svx/keepitem.hxx"
#include "svx/bolnitem.hxx"
#include "svx/brshitem.hxx"
#include "svx/xmlsecctrl.hxx"
#include "svx/unolingu.hxx"

#include "xmlscript/xmldlg_imexp.hxx"

#include "unotools/charclass.hxx"
#include "unotools/accessiblestatesethelper.hxx"
#include "unotools/accessiblerelationsethelper.hxx"
#endif

<|endoftext|>


<commit_before><commit_msg>[Windows] Add exports for dll_host test broken by r252071 and r251071<commit_after><|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "qmljshighlighter.h"

#include <QtCore/QSet>
#include <QtCore/QtAlgorithms>
#include <QtCore/QDebug>

#include <utils/qtcassert.h>

using namespace QmlJSEditor;
using namespace QmlJS;

Highlighter::Highlighter(QTextDocument *parent)
    : TextEditor::SyntaxHighlighter(parent),
      m_qmlEnabled(true),
      m_inMultilineComment(false)
{
    m_currentBlockParentheses.reserve(20);
    m_braceDepth = 0;
    m_foldingIndent = 0;
}

Highlighter::~Highlighter()
{
}

bool Highlighter::isQmlEnabled() const
{
    return m_qmlEnabled;
}

void Highlighter::setQmlEnabled(bool qmlEnabled)
{
    m_qmlEnabled = qmlEnabled;
}

void Highlighter::setFormats(const QVector<QTextCharFormat> &formats)
{
    QTC_ASSERT(formats.size() == NumFormats, return);
    qCopy(formats.begin(), formats.end(), m_formats);
}

void Highlighter::highlightBlock(const QString &text)
{
    const QList<Token> tokens = m_scanner(text, onBlockStart());

    int index = 0;
    while (index < tokens.size()) {
        const Token &token = tokens.at(index);

        switch (token.kind) {
            case Token::Keyword:
                setFormat(token.offset, token.length, m_formats[KeywordFormat]);
                break;

            case Token::String:
                setFormat(token.offset, token.length, m_formats[StringFormat]);
                break;

            case Token::Comment:
                if (m_inMultilineComment && text.midRef(token.end() - 2, 2) == QLatin1String("*/")) {
                    onClosingParenthesis('-', token.end() - 1, index == tokens.size()-1);
                    m_inMultilineComment = false;
                } else if (!m_inMultilineComment
                           && (m_scanner.state() & Scanner::MultiLineMask) == Scanner::MultiLineComment
                           && index == tokens.size() - 1) {
                    onOpeningParenthesis('+', token.offset, index == 0);
                    m_inMultilineComment = true;
                }
                setFormat(token.offset, token.length, m_formats[CommentFormat]);
                break;

            case Token::RegExp:
                setFormat(token.offset, token.length, m_formats[StringFormat]);
                break;

            case Token::LeftParenthesis:
                onOpeningParenthesis('(', token.offset, index == 0);
                break;

            case Token::RightParenthesis:
                onClosingParenthesis(')', token.offset, index == tokens.size()-1);
                break;

            case Token::LeftBrace:
                onOpeningParenthesis('{', token.offset, index == 0);
                break;

            case Token::RightBrace:
                onClosingParenthesis('}', token.offset, index == tokens.size()-1);
                break;

            case Token::LeftBracket:
                onOpeningParenthesis('[', token.offset, index == 0);
                break;

            case Token::RightBracket:
                onClosingParenthesis(']', token.offset, index == tokens.size()-1);
                break;

            case Token::Identifier: {
                if (!m_qmlEnabled)
                    break;

                const QStringRef spell = text.midRef(token.offset, token.length);

                if (maybeQmlKeyword(spell)) {
                    // check the previous token
                    if (index == 0 || tokens.at(index - 1).isNot(Token::Dot)) {
                        if (index + 1 == tokens.size() || tokens.at(index + 1).isNot(Token::Colon)) {
                            setFormat(token.offset, token.length, m_formats[KeywordFormat]);
                            break;
                        }
                    }
                } else if (index > 0 && maybeQmlBuiltinType(spell)) {
                    const Token &previousToken = tokens.at(index - 1);
                    if (previousToken.is(Token::Identifier) && text.at(previousToken.offset) == QLatin1Char('p')
                        && text.midRef(previousToken.offset, previousToken.length) == QLatin1String("property")) {
                        setFormat(token.offset, token.length, m_formats[KeywordFormat]);
                        break;
                    }
                }
            }   break;

            case Token::Delimiter:
                break;

            default:
                break;
        } // end swtich

        ++index;
    }

    int previousTokenEnd = 0;
    for (int index = 0; index < tokens.size(); ++index) {
        const Token &token = tokens.at(index);
        setFormat(previousTokenEnd, token.begin() - previousTokenEnd, m_formats[VisualWhitespace]);

        switch (token.kind) {
        case Token::Comment:
        case Token::String:
        case Token::RegExp: {
            int i = token.begin(), e = token.end();
            while (i < e) {
                const QChar ch = text.at(i);
                if (ch.isSpace()) {
                    const int start = i;
                    do {
                        ++i;
                    } while (i < e && text.at(i).isSpace());
                    setFormat(start, i - start, m_formats[VisualWhitespace]);
                } else {
                    ++i;
                }
            }
        } break;

        default:
            break;
        } // end of switch

        previousTokenEnd = token.end();
    }

    setFormat(previousTokenEnd, text.length() - previousTokenEnd, m_formats[VisualWhitespace]);

    setCurrentBlockState(m_scanner.state());
    onBlockEnd(m_scanner.state());
}

bool Highlighter::maybeQmlKeyword(const QStringRef &text) const
{
    if (text.isEmpty())
        return false;

    const QChar ch = text.at(0);
    if (ch == QLatin1Char('p') && text == QLatin1String("property")) {
        return true;
    } else if (ch == QLatin1Char('a') && text == QLatin1String("alias")) {
        return true;
    } else if (ch == QLatin1Char('s') && text == QLatin1String("signal")) {
        return true;
    } else if (ch == QLatin1Char('p') && text == QLatin1String("property")) {
        return true;
    } else if (ch == QLatin1Char('r') && text == QLatin1String("readonly")) {
        return true;
    } else if (ch == QLatin1Char('i') && text == QLatin1String("import")) {
        return true;
    } else if (ch == QLatin1Char('o') && text == QLatin1String("on")) {
        return true;
    } else {
        return false;
    }
}

bool Highlighter::maybeQmlBuiltinType(const QStringRef &text) const
{
    if (text.isEmpty())
        return false;

    const QChar ch = text.at(0);

    if (ch == QLatin1Char('i') && text == QLatin1String("int")) {
        return true;
    } else if (ch == QLatin1Char('b') && text == QLatin1String("bool")) {
        return true;
    } else if (ch == QLatin1Char('d') && text == QLatin1String("double")) {
        return true;
    } else if (ch == QLatin1Char('r') && text == QLatin1String("real")) {
        return true;
    } else if (ch == QLatin1Char('s') && text == QLatin1String("string")) {
        return true;
    } else if (ch == QLatin1Char('u') && text == QLatin1String("url")) {
        return true;
    } else if (ch == QLatin1Char('c') && text == QLatin1String("color")) {
        return true;
    } else if (ch == QLatin1Char('d') && text == QLatin1String("date")) {
        return true;
    } else if (ch == QLatin1Char('v') && text == QLatin1String("var")) {
        return true;
    } else if (ch == QLatin1Char('v') && text == QLatin1String("variant")) {
        return true;
    } else {
        return false;
    }
}

int Highlighter::onBlockStart()
{
    m_currentBlockParentheses.clear();
    m_braceDepth = 0;
    m_foldingIndent = 0;
    m_inMultilineComment = false;
    if (TextEditor::TextBlockUserData *userData = TextEditor::BaseTextDocumentLayout::testUserData(currentBlock())) {
        userData->setFoldingIndent(0);
        userData->setFoldingStartIncluded(false);
        userData->setFoldingEndIncluded(false);
    }

    int state = 0;
    int previousState = previousBlockState();
    if (previousState != -1) {
        state = previousState & 0xff;
        m_braceDepth = (previousState >> 8);
        m_inMultilineComment = ((state & Scanner::MultiLineMask) == Scanner::MultiLineComment);
    }
    m_foldingIndent = m_braceDepth;

    return state;
}

void Highlighter::onBlockEnd(int state)
{
    typedef TextEditor::TextBlockUserData TextEditorBlockData;

    setCurrentBlockState((m_braceDepth << 8) | state);
    TextEditor::BaseTextDocumentLayout::setParentheses(currentBlock(), m_currentBlockParentheses);
    TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), m_foldingIndent);
}

void Highlighter::onOpeningParenthesis(QChar parenthesis, int pos, bool atStart)
{
    if (parenthesis == QLatin1Char('{') || parenthesis == QLatin1Char('[') || parenthesis == QLatin1Char('+')) {
        ++m_braceDepth;
        // if a folding block opens at the beginning of a line, treat the entire line
        // as if it were inside the folding block
        if (atStart)
            TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
    }
    m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Opened, parenthesis, pos));
}

void Highlighter::onClosingParenthesis(QChar parenthesis, int pos, bool atEnd)
{
    if (parenthesis == QLatin1Char('}') || parenthesis == QLatin1Char(']') || parenthesis == QLatin1Char('-')) {
        --m_braceDepth;
        if (atEnd)
            TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
        else
            m_foldingIndent = qMin(m_braceDepth, m_foldingIndent); // folding indent is the minimum brace depth of a block
    }
    m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Closed, parenthesis, pos));
}

<commit_msg>QmlJS: Fix highlighting of property types.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "qmljshighlighter.h"

#include <QtCore/QSet>
#include <QtCore/QtAlgorithms>
#include <QtCore/QDebug>

#include <utils/qtcassert.h>

using namespace QmlJSEditor;
using namespace QmlJS;

Highlighter::Highlighter(QTextDocument *parent)
    : TextEditor::SyntaxHighlighter(parent),
      m_qmlEnabled(true),
      m_inMultilineComment(false)
{
    m_currentBlockParentheses.reserve(20);
    m_braceDepth = 0;
    m_foldingIndent = 0;
}

Highlighter::~Highlighter()
{
}

bool Highlighter::isQmlEnabled() const
{
    return m_qmlEnabled;
}

void Highlighter::setQmlEnabled(bool qmlEnabled)
{
    m_qmlEnabled = qmlEnabled;
}

void Highlighter::setFormats(const QVector<QTextCharFormat> &formats)
{
    QTC_ASSERT(formats.size() == NumFormats, return);
    qCopy(formats.begin(), formats.end(), m_formats);
}

void Highlighter::highlightBlock(const QString &text)
{
    const QList<Token> tokens = m_scanner(text, onBlockStart());

    int index = 0;
    while (index < tokens.size()) {
        const Token &token = tokens.at(index);

        switch (token.kind) {
            case Token::Keyword:
                setFormat(token.offset, token.length, m_formats[KeywordFormat]);
                break;

            case Token::String:
                setFormat(token.offset, token.length, m_formats[StringFormat]);
                break;

            case Token::Comment:
                if (m_inMultilineComment && text.midRef(token.end() - 2, 2) == QLatin1String("*/")) {
                    onClosingParenthesis('-', token.end() - 1, index == tokens.size()-1);
                    m_inMultilineComment = false;
                } else if (!m_inMultilineComment
                           && (m_scanner.state() & Scanner::MultiLineMask) == Scanner::MultiLineComment
                           && index == tokens.size() - 1) {
                    onOpeningParenthesis('+', token.offset, index == 0);
                    m_inMultilineComment = true;
                }
                setFormat(token.offset, token.length, m_formats[CommentFormat]);
                break;

            case Token::RegExp:
                setFormat(token.offset, token.length, m_formats[StringFormat]);
                break;

            case Token::LeftParenthesis:
                onOpeningParenthesis('(', token.offset, index == 0);
                break;

            case Token::RightParenthesis:
                onClosingParenthesis(')', token.offset, index == tokens.size()-1);
                break;

            case Token::LeftBrace:
                onOpeningParenthesis('{', token.offset, index == 0);
                break;

            case Token::RightBrace:
                onClosingParenthesis('}', token.offset, index == tokens.size()-1);
                break;

            case Token::LeftBracket:
                onOpeningParenthesis('[', token.offset, index == 0);
                break;

            case Token::RightBracket:
                onClosingParenthesis(']', token.offset, index == tokens.size()-1);
                break;

            case Token::Identifier: {
                if (!m_qmlEnabled)
                    break;

                const QStringRef spell = text.midRef(token.offset, token.length);

                if (maybeQmlKeyword(spell)) {
                    // check the previous token
                    if (index == 0 || tokens.at(index - 1).isNot(Token::Dot)) {
                        if (index + 1 == tokens.size() || tokens.at(index + 1).isNot(Token::Colon)) {
                            setFormat(token.offset, token.length, m_formats[KeywordFormat]);
                            break;
                        }
                    }
                } else if (index > 0 && maybeQmlBuiltinType(spell)) {
                    const Token &previousToken = tokens.at(index - 1);
                    if (previousToken.is(Token::Identifier) && text.at(previousToken.offset) == QLatin1Char('p')
                        && text.midRef(previousToken.offset, previousToken.length) == QLatin1String("property")) {
                        setFormat(token.offset, token.length, m_formats[KeywordFormat]);
                        break;
                    }
                }
            }   break;

            case Token::Delimiter:
                break;

            default:
                break;
        } // end swtich

        ++index;
    }

    int previousTokenEnd = 0;
    for (int index = 0; index < tokens.size(); ++index) {
        const Token &token = tokens.at(index);
        setFormat(previousTokenEnd, token.begin() - previousTokenEnd, m_formats[VisualWhitespace]);

        switch (token.kind) {
        case Token::Comment:
        case Token::String:
        case Token::RegExp: {
            int i = token.begin(), e = token.end();
            while (i < e) {
                const QChar ch = text.at(i);
                if (ch.isSpace()) {
                    const int start = i;
                    do {
                        ++i;
                    } while (i < e && text.at(i).isSpace());
                    setFormat(start, i - start, m_formats[VisualWhitespace]);
                } else {
                    ++i;
                }
            }
        } break;

        default:
            break;
        } // end of switch

        previousTokenEnd = token.end();
    }

    setFormat(previousTokenEnd, text.length() - previousTokenEnd, m_formats[VisualWhitespace]);

    setCurrentBlockState(m_scanner.state());
    onBlockEnd(m_scanner.state());
}

bool Highlighter::maybeQmlKeyword(const QStringRef &text) const
{
    if (text.isEmpty())
        return false;

    const QChar ch = text.at(0);
    if (ch == QLatin1Char('p') && text == QLatin1String("property")) {
        return true;
    } else if (ch == QLatin1Char('a') && text == QLatin1String("alias")) {
        return true;
    } else if (ch == QLatin1Char('s') && text == QLatin1String("signal")) {
        return true;
    } else if (ch == QLatin1Char('p') && text == QLatin1String("property")) {
        return true;
    } else if (ch == QLatin1Char('r') && text == QLatin1String("readonly")) {
        return true;
    } else if (ch == QLatin1Char('i') && text == QLatin1String("import")) {
        return true;
    } else if (ch == QLatin1Char('o') && text == QLatin1String("on")) {
        return true;
    } else {
        return false;
    }
}

bool Highlighter::maybeQmlBuiltinType(const QStringRef &text) const
{
    if (text.isEmpty())
        return false;

    const QChar ch = text.at(0);

    if (ch == QLatin1Char('a') && text == QLatin1String("action")) {
            return true;
    } else if (ch == QLatin1Char('b') && text == QLatin1String("bool")) {
        return true;
    } else if (ch == QLatin1Char('c') && text == QLatin1String("color")) {
        return true;
    } else if (ch == QLatin1Char('d') && text == QLatin1String("date")) {
        return true;
    } else if (ch == QLatin1Char('d') && text == QLatin1String("double")) {
        return true;
    } else if (ch == QLatin1Char('e') && text == QLatin1String("enumeration")) {
        return true;
    } else if (ch == QLatin1Char('f') && text == QLatin1String("font")) {
        return true;
    } else if (ch == QLatin1Char('i') && text == QLatin1String("int")) {
        return true;
    } else if (ch == QLatin1Char('l') && text == QLatin1String("list")) {
        return true;
    } else if (ch == QLatin1Char('p') && text == QLatin1String("point")) {
        return true;
    } else if (ch == QLatin1Char('r') && text == QLatin1String("real")) {
        return true;
    } else if (ch == QLatin1Char('r') && text == QLatin1String("rect")) {
        return true;
    } else if (ch == QLatin1Char('s') && text == QLatin1String("size")) {
        return true;
    } else if (ch == QLatin1Char('s') && text == QLatin1String("string")) {
        return true;
    } else if (ch == QLatin1Char('t') && text == QLatin1String("time")) {
        return true;
    } else if (ch == QLatin1Char('u') && text == QLatin1String("url")) {
        return true;
    } else if (ch == QLatin1Char('v') && text == QLatin1String("variant")) {
        return true;
    } else if (ch == QLatin1Char('v') && text == QLatin1String("vector3d")) {
        return true;
    } else {
        return false;
    }
}

int Highlighter::onBlockStart()
{
    m_currentBlockParentheses.clear();
    m_braceDepth = 0;
    m_foldingIndent = 0;
    m_inMultilineComment = false;
    if (TextEditor::TextBlockUserData *userData = TextEditor::BaseTextDocumentLayout::testUserData(currentBlock())) {
        userData->setFoldingIndent(0);
        userData->setFoldingStartIncluded(false);
        userData->setFoldingEndIncluded(false);
    }

    int state = 0;
    int previousState = previousBlockState();
    if (previousState != -1) {
        state = previousState & 0xff;
        m_braceDepth = (previousState >> 8);
        m_inMultilineComment = ((state & Scanner::MultiLineMask) == Scanner::MultiLineComment);
    }
    m_foldingIndent = m_braceDepth;

    return state;
}

void Highlighter::onBlockEnd(int state)
{
    typedef TextEditor::TextBlockUserData TextEditorBlockData;

    setCurrentBlockState((m_braceDepth << 8) | state);
    TextEditor::BaseTextDocumentLayout::setParentheses(currentBlock(), m_currentBlockParentheses);
    TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), m_foldingIndent);
}

void Highlighter::onOpeningParenthesis(QChar parenthesis, int pos, bool atStart)
{
    if (parenthesis == QLatin1Char('{') || parenthesis == QLatin1Char('[') || parenthesis == QLatin1Char('+')) {
        ++m_braceDepth;
        // if a folding block opens at the beginning of a line, treat the entire line
        // as if it were inside the folding block
        if (atStart)
            TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
    }
    m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Opened, parenthesis, pos));
}

void Highlighter::onClosingParenthesis(QChar parenthesis, int pos, bool atEnd)
{
    if (parenthesis == QLatin1Char('}') || parenthesis == QLatin1Char(']') || parenthesis == QLatin1Char('-')) {
        --m_braceDepth;
        if (atEnd)
            TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
        else
            m_foldingIndent = qMin(m_braceDepth, m_foldingIndent); // folding indent is the minimum brace depth of a block
    }
    m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Closed, parenthesis, pos));
}

<|endoftext|>