<commit_before>#include <QFrame>
#include <QLabel>
#include "convertertoqwidget.hpp"

namespace qtreports
{
    namespace detail
    {

        ConverterToQWidget::ConverterToQWidget( const ReportPtr & report ) :
            m_report( report ),
            m_type( WidgetType::Report )
        {}

        ConverterToQWidget::~ConverterToQWidget() {}

        bool    ConverterToQWidget::convert( WidgetType type )
        {
            m_type = type;
            return createQWidget( m_report );
        }

        bool    ConverterToQWidget::convert( const ReportPtr & report, WidgetType type )
        {
            m_type = type;
            return createQWidget( report );
        }

        QHBoxLayout * createLayout( QWidget * left, QWidget * center, QWidget * right )
        {
            auto layout = new QHBoxLayout();
            layout->setMargin( 0 );
            layout->setSpacing( 0 );

            layout->addWidget( left );
            layout->addWidget( center );
            layout->addWidget( right );

            return layout;
        }

        void    ConverterToQWidget::addVerticalBorder( QBoxLayout * parent, int height, int left, int right )
        {
            auto leftFrame = new QFrame();
            leftFrame->setFixedWidth( left );
            leftFrame->setFixedHeight( height );

            auto centerFrame = new QFrame();
            centerFrame->setFixedHeight( height );

            auto rightFrame = new QFrame();
            rightFrame->setFixedWidth( right );
            rightFrame->setFixedHeight( height );

            if( isLayout() )
            {
                QString style = "border: 1px solid gray; ";
                leftFrame->setStyleSheet( style + "border-width: 0px 1px 0px 0px; " );
                rightFrame->setStyleSheet( style + "border-width: 0px 0px 0px 1px; " );
            }

            auto layout = createLayout( leftFrame, centerFrame, rightFrame );
            parent->addLayout( layout );
        }

        void    ConverterToQWidget::addEmptySection( QBoxLayout * parent, int left, int right )
        {
            auto leftFrame = new QFrame();
            leftFrame->setFixedWidth( left );

            auto centerFrame = new QFrame();

            auto rightFrame = new QFrame();
            rightFrame->setFixedWidth( right );

            if( isLayout() )
            {
                QString style = "border: 1px solid gray; ";
                leftFrame->setStyleSheet( style + "border-width: 1px 1px 1px 0px; " );
                centerFrame->setObjectName( "frame" );
                centerFrame->setStyleSheet( "#frame{" + style + "border-width: 1px 0px 1px 0px; }" );
                rightFrame->setStyleSheet( style + "border-width: 1px 0px 1px 1px; " );
            }

            auto layout = createLayout( leftFrame, centerFrame, rightFrame );
            parent->addLayout( layout );
        }

        QFrame *    ConverterToQWidget::addSectionLayout( QBoxLayout * parent, int height, int left, int right )
        {
            auto leftFrame = new QFrame();
            leftFrame->setFixedHeight( height );
            leftFrame->setFixedWidth( left );

            auto centerFrame = new QFrame();
            centerFrame->setFixedHeight( height );

            auto rightFrame = new QFrame();
            rightFrame->setFixedHeight( height );
            rightFrame->setFixedWidth( right );

            if( isLayout() )
            {
                QString style = "border: 1px solid gray; ";
                leftFrame->setStyleSheet( style + "border-width: 1px 1px 0px 0px; " );
                centerFrame->setObjectName( "frame" );
                centerFrame->setStyleSheet( "#frame{" + style + "border-width: 1px 0px 0px 0px; }" );
                rightFrame->setStyleSheet( style + "border-width: 1px 0px 0px 1px; " );
            }

            auto layout = createLayout( leftFrame, centerFrame, rightFrame );
            parent->addLayout( layout );

            return centerFrame;
        }

        bool    ConverterToQWidget::createQWidget( const ReportPtr & report )
        {
            if( report.isNull() )
            {
                m_lastError = "Report is empty";
                return false;
            }

            auto detail = report->getDetail();
            if( detail.isNull() )
            {
                m_lastError = "Report->Detail is empty";
                return false;
            }

            m_qwidget = QWidgetPtr( new QWidget() );
            m_qwidget->setStyleSheet( "background-color: white; " );

            auto layout = new QVBoxLayout( m_qwidget.data() );
            layout->setMargin( 0 );
            layout->setSpacing( 0 );
            addVerticalBorder( layout, report->getTopMargin(), report->getLeftMargin(), report->getRightMargin() );

            auto title = report->getTitle();
            if( !title.isNull() )
            {
                auto sectionWidget = addSectionLayout( layout, title->getHeight(), report->getLeftMargin(), m_report->getRightMargin() );
                if( !createSection( sectionWidget, title ) )
                {
                    return false;
                }
            }

            if( isReport() )
            {
                for( int i = 0; i < report->getRowCount(); ++i )
                {
                    auto sectionWidget = addSectionLayout( layout, detail->getHeight(), report->getLeftMargin(), m_report->getRightMargin() );
                    if( !createSection( sectionWidget, detail ) )
                    {
                        return false;;
                    }
                }
            }
            else
            {
                auto sectionWidget = addSectionLayout( layout, detail->getHeight(), report->getLeftMargin(), m_report->getRightMargin() );
                if( !createSection( sectionWidget, detail ) )
                {
                    return false;;
                }
            }

            addEmptySection( layout, report->getLeftMargin(), report->getRightMargin() );
            addVerticalBorder( layout, report->getBottomMargin(), report->getLeftMargin(), report->getRightMargin() );

            return true;
        }

        bool    ConverterToQWidget::createSection( QWidget * parent, const SectionPtr & section )
        {
            if( isLayout() )
            {
                auto label = new QLabel( parent );
                label->setText( section->getTagName() );
                label->setStyleSheet( "font-size: 26px; color: gray" );
                label->setAlignment( Qt::AlignCenter );
                label->setAttribute( Qt::WA_TranslucentBackground );
                label->resize( parent->size() );
            }

            if( !createBands( parent, section ) )
            {
                return false;;
            }

            return true;
        }

        bool    ConverterToQWidget::createBands( QWidget * parent, const SectionPtr & section )
        {
            for( auto && band : section->getBands() )
            {
                auto frame = new QFrame( parent );
                for( auto && staticText : band->getStaticTexts() )
                {
                    auto label = new QLabel( frame );
                    QString style = "";
                    if( staticText->isBold() )
                    {
                        style += "font-weight: bold; ";
                    }
                    if( isLayout() )
                    {
                        style += "border: 1px solid gray; ";
                    }
                    label->setStyleSheet( style );
                    label->setGeometry( staticText->getRect() );
                    label->setAlignment( staticText->getAlignment() );
                    label->setText( staticText->getText() );
                }
                for( auto && textField : band->getTextFields() )
                {
                    auto label = new QLabel( frame );
                    QString style = "";
                    if( textField->isBold() )
                    {
                        style += "font-weight: bold; ";
                    }
                    if( isLayout() )
                    {
                        style += "border: 1px solid gray; ";
                    }
                    label->setStyleSheet( style );
                    label->setGeometry( textField->getRect() );
                    label->setAlignment( textField->getAlignment() );
                    label->setText( textField->getText() );
                }
            }

            return true;
        }

        const QString       ConverterToQWidget::getLastError() const
        {
            return m_lastError;
        }

        bool    ConverterToQWidget::isReport() const
        {
            return m_type == WidgetType::Report;
        }

        bool    ConverterToQWidget::isLayout() const
        {
            return m_type == WidgetType::Layout;
        }

        ConverterToQWidget::WidgetType  ConverterToQWidget::getType() const
        {
            return m_type;
        }

        const QWidgetPtr    ConverterToQWidget::getQWidget() const
        {
            return m_qwidget;
        }

    }
}
<commit_msg>Added transparent for bands and texts.<commit_after>#include <QFrame>
#include <QLabel>
#include "convertertoqwidget.hpp"

namespace qtreports
{
    namespace detail
    {

        ConverterToQWidget::ConverterToQWidget( const ReportPtr & report ) :
            m_report( report ),
            m_type( WidgetType::Report )
        {}

        ConverterToQWidget::~ConverterToQWidget() {}

        bool    ConverterToQWidget::convert( WidgetType type )
        {
            m_type = type;
            return createQWidget( m_report );
        }

        bool    ConverterToQWidget::convert( const ReportPtr & report, WidgetType type )
        {
            m_type = type;
            return createQWidget( report );
        }

        QHBoxLayout * createLayout( QWidget * left, QWidget * center, QWidget * right )
        {
            auto layout = new QHBoxLayout();
            layout->setMargin( 0 );
            layout->setSpacing( 0 );

            layout->addWidget( left );
            layout->addWidget( center );
            layout->addWidget( right );

            return layout;
        }

        void    ConverterToQWidget::addVerticalBorder( QBoxLayout * parent, int height, int left, int right )
        {
            auto leftFrame = new QFrame();
            leftFrame->setFixedWidth( left );
            leftFrame->setFixedHeight( height );

            auto centerFrame = new QFrame();
            centerFrame->setFixedHeight( height );

            auto rightFrame = new QFrame();
            rightFrame->setFixedWidth( right );
            rightFrame->setFixedHeight( height );

            if( isLayout() )
            {
                QString style = "border: 1px solid gray; ";
                leftFrame->setStyleSheet( style + "border-width: 0px 1px 0px 0px; " );
                rightFrame->setStyleSheet( style + "border-width: 0px 0px 0px 1px; " );
            }

            auto layout = createLayout( leftFrame, centerFrame, rightFrame );
            parent->addLayout( layout );
        }

        void    ConverterToQWidget::addEmptySection( QBoxLayout * parent, int left, int right )
        {
            auto leftFrame = new QFrame();
            leftFrame->setFixedWidth( left );

            auto centerFrame = new QFrame();

            auto rightFrame = new QFrame();
            rightFrame->setFixedWidth( right );

            if( isLayout() )
            {
                QString style = "border: 1px solid gray; ";
                leftFrame->setStyleSheet( style + "border-width: 1px 1px 1px 0px; " );
                centerFrame->setObjectName( "frame" );
                centerFrame->setStyleSheet( "#frame{" + style + "border-width: 1px 0px 1px 0px; }" );
                rightFrame->setStyleSheet( style + "border-width: 1px 0px 1px 1px; " );
            }

            auto layout = createLayout( leftFrame, centerFrame, rightFrame );
            parent->addLayout( layout );
        }

        QFrame *    ConverterToQWidget::addSectionLayout( QBoxLayout * parent, int height, int left, int right )
        {
            auto leftFrame = new QFrame();
            leftFrame->setFixedHeight( height );
            leftFrame->setFixedWidth( left );

            auto centerFrame = new QFrame();
            centerFrame->setFixedHeight( height );

            auto rightFrame = new QFrame();
            rightFrame->setFixedHeight( height );
            rightFrame->setFixedWidth( right );

            if( isLayout() )
            {
                QString style = "border: 1px solid gray; ";
                leftFrame->setStyleSheet( style + "border-width: 1px 1px 0px 0px; " );
                centerFrame->setObjectName( "frame" );
                centerFrame->setStyleSheet( "#frame{" + style + "border-width: 1px 0px 0px 0px; }" );
                rightFrame->setStyleSheet( style + "border-width: 1px 0px 0px 1px; " );
            }

            auto layout = createLayout( leftFrame, centerFrame, rightFrame );
            parent->addLayout( layout );

            return centerFrame;
        }

        bool    ConverterToQWidget::createQWidget( const ReportPtr & report )
        {
            if( report.isNull() )
            {
                m_lastError = "Report is empty";
                return false;
            }

            auto detail = report->getDetail();
            if( detail.isNull() )
            {
                m_lastError = "Report->Detail is empty";
                return false;
            }

            m_qwidget = QWidgetPtr( new QWidget() );
            m_qwidget->setStyleSheet( "background-color: white; " );

            auto layout = new QVBoxLayout( m_qwidget.data() );
            layout->setMargin( 0 );
            layout->setSpacing( 0 );
            addVerticalBorder( layout, report->getTopMargin(), report->getLeftMargin(), report->getRightMargin() );

            auto title = report->getTitle();
            if( !title.isNull() )
            {
                auto sectionWidget = addSectionLayout( layout, title->getHeight(), report->getLeftMargin(), m_report->getRightMargin() );
                if( !createSection( sectionWidget, title ) )
                {
                    return false;
                }
            }

            if( isReport() )
            {
                for( int i = 0; i < report->getRowCount(); ++i )
                {
                    auto sectionWidget = addSectionLayout( layout, detail->getHeight(), report->getLeftMargin(), m_report->getRightMargin() );
                    if( !createSection( sectionWidget, detail ) )
                    {
                        return false;;
                    }
                }
            }
            else
            {
                auto sectionWidget = addSectionLayout( layout, detail->getHeight(), report->getLeftMargin(), m_report->getRightMargin() );
                if( !createSection( sectionWidget, detail ) )
                {
                    return false;;
                }
            }

            addEmptySection( layout, report->getLeftMargin(), report->getRightMargin() );
            addVerticalBorder( layout, report->getBottomMargin(), report->getLeftMargin(), report->getRightMargin() );

            return true;
        }

        bool    ConverterToQWidget::createSection( QWidget * parent, const SectionPtr & section )
        {
            if( isLayout() )
            {
                auto label = new QLabel( parent );
                label->setText( section->getTagName() );
                label->setStyleSheet( "font-size: 26px; color: gray" );
                label->setAlignment( Qt::AlignCenter );
                label->setAttribute( Qt::WA_TranslucentBackground );
                label->resize( parent->size() );
            }

            if( !createBands( parent, section ) )
            {
                return false;;
            }

            return true;
        }

        bool    ConverterToQWidget::createBands( QWidget * parent, const SectionPtr & section )
        {
            for( auto && band : section->getBands() )
            {
                auto frame = new QFrame( parent );
                frame->setStyleSheet( "background-color: transparent; " );
                for( auto && staticText : band->getStaticTexts() )
                {
                    auto label = new QLabel( frame );
                    QString style = "";
                    if( staticText->isBold() )
                    {
                        style += "font-weight: bold; ";
                    }
                    if( isLayout() )
                    {
                        style += "border: 1px solid gray; ";
                    }
                    label->setStyleSheet( "background-color: transparent; " + style );
                    label->setGeometry( staticText->getRect() );
                    label->setAlignment( staticText->getAlignment() );
                    label->setText( staticText->getText() );
                }
                for( auto && textField : band->getTextFields() )
                {
                    auto label = new QLabel( frame );
                    QString style = "";
                    if( textField->isBold() )
                    {
                        style += "font-weight: bold; ";
                    }
                    if( isLayout() )
                    {
                        style += "border: 1px solid gray; ";
                    }
                    label->setStyleSheet( "background-color: transparent; " + style );
                    label->setGeometry( textField->getRect() );
                    label->setAlignment( textField->getAlignment() );
                    label->setText( textField->getText() );
                }
            }

            return true;
        }

        const QString       ConverterToQWidget::getLastError() const
        {
            return m_lastError;
        }

        bool    ConverterToQWidget::isReport() const
        {
            return m_type == WidgetType::Report;
        }

        bool    ConverterToQWidget::isLayout() const
        {
            return m_type == WidgetType::Layout;
        }

        ConverterToQWidget::WidgetType  ConverterToQWidget::getType() const
        {
            return m_type;
        }

        const QWidgetPtr    ConverterToQWidget::getQWidget() const
        {
            return m_qwidget;
        }

    }
}
<|endoftext|>


<commit_before>// Copyright 2008 Google Inc.
//
// 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 <cassert>
#include <iostream>
#include "pca_estimator.h"

namespace Torch {

PcaEstimator::PcaEstimator(int n_dim_, int n_eigen_, int minibatch_size_, real gamma_) : Object()
{
  n_dim = n_dim_;
  n_eigen = n_eigen_;
  minibatch_size = minibatch_size_;
  gamma = gamma_;
  lambda = 1e-3;

  n_observations = 0;
  minibatch_index = 0;

  Initialize();
}

void PcaEstimator::Initialize()
{
  Xt = new(allocator) Mat(n_eigen + minibatch_size, n_dim);
  Xt->zero();

  x_sum = new(allocator) Vec(n_dim);
  for (int i=0; i<x_sum->n; i++)
    x_sum->ptr[i] = 0.0;

  G = new(allocator) Mat(n_eigen + minibatch_size, n_eigen + minibatch_size);
  G->zero();
  for (int i=0; i<n_eigen; i++)
    G->ptr[i][i] = lambda;

  d = new(allocator) Vec(n_eigen + minibatch_size);
  for (int i=0; i<n_eigen+minibatch_size; i++)
    d->ptr[i] = 0.0;

  V = new(allocator)  Mat(n_eigen + minibatch_size, n_eigen + minibatch_size);
  V->zero();

  Ut = new(allocator)  Mat(n_eigen, n_dim);
  Ut->zero();
}

void PcaEstimator::Observe(Vec *x)
{
  assert(x->n == n_dim);

  n_observations++;

  // Add the *non-centered* observation to Xt.
  int row = n_eigen + minibatch_index;
  Xt->setRow(row, x);

  // Update the discounted sum of the observations.
  for (int i=0; i<x_sum->n; i++)
    x_sum->ptr[i] = x_sum->ptr[i] * gamma + x->ptr[i];

  // To get the mean, we must normalize the sum by:
  // /gamma^(n_observations-1) + /gamma^(n_observations-2) + ... + 1
  real normalizer = (1 - pow(gamma, (real)n_observations)) /(1 - gamma);
  real inv_normalizer = 1.0 / normalizer;

  // Now center the observation.
  // We will lose the first observation as it is the only one in the mean.
  Vec new_x(Xt->ptr[row], n_dim);
  for (int i=0; i<new_x.n; i++)
    new_x.ptr[i] -= x_sum->ptr[i] * inv_normalizer;

  // Multiply the centered observation by the discount compensator. Basically
  // we make this observation look "younger" than the previous ones. The actual
  // discount is applied in the reevaluation (and when solving the equations in
  // the case of TONGA) by multiplying every direction with the same aging factor.
  real rn = pow(gamma, -0.5*(minibatch_index+1));
  for (int i=0; i<n_dim; i++)
    Xt->ptr[row][i] *= rn;

  // Update the Gram Matrix. Xkt represents the currently used portion
  // of Xt (first rows).
  Vec new_g(G->ptr[row], row + 1);
  Mat *Xkt =  Xt->subMat(0,0,row,n_dim-1);
  mxMatMulVec(Xkt, x, &new_g);
  delete Xkt;

  // Now copy G(row,:) to G(:,row).
  // There are row+1 values, but the diag doesn't need to get copied.
  for (int i=0; i<row; i++)
    G->ptr[i][row] =  G->ptr[row][i];

  minibatch_index++;

  if(minibatch_index==minibatch_size)
    Reevaluate();

}

void PcaEstimator::Reevaluate()
{
  // TODO do the modifications to handle when this is not true.
  assert(minibatch_index==minibatch_size);

  // Regularize - not necessary but in case
  //for (int i=0; i<n_eigen+minibatch_size; i++)
  //  G->ptr[i][i] += lambda;

  // The Gram matrix is up to date. Get its low rank eigendecomposition.
  // TODO How to get only #n_eigen# elements?
  mxSymEig(G, V, d);

  // The eigen values and vectors are *NOT SORTED*. Furthermore, the vectors
  // are on the columns.
  // Find and sort the n_eigen first values and vectors using Dumb Sort
  for (int i=0; i<n_eigen; i++) {
    // Initialize the max search
    int max_index = i;
    real max_value = d->ptr[i];

    // Compare with remaining possibilities
    for (int j=i+1; j<n_eigen+minibatch_size; j++) {
      if (max_value < d->ptr[j])  {
        max_value = d->ptr[j];
        max_index = j;
      }
    }

    // Swap!
    d->ptr[max_index] = d->ptr[i];
    d->ptr[i] = max_value;
    mxSwapColsMat(V, i, max_index, -1, -1);
  }

  // Convert the n_eigen first eigenvectors of the Gram matrix contained in V
  // into *unnormalized* eigenvectors U of the covariance.
  Mat *Vk = V->subMat(0, 0, n_eigen+minibatch_index-1, n_eigen-1);
  mxTrMatMulMat(Vk, Xt, Ut);
  delete Vk;

  // Take into account the discount factor.
  // Here, minibatch index is minibacth_size. We age everyone. Because of the
  // previous multiplications to make some observations "younger" we multiply
  // everyone by the same factor.
  // TODO VERIFY THIS!
  real rn = pow(gamma, -0.5*(minibatch_index+1));
  real inv_rn2 = 1.0/(rn*rn);

  mxRealMulMat(1.0/rn, Ut, Ut);
  for (int i=0; i<d->n; i++)
    d->ptr[i] *= inv_rn2;

  //---------------------
  /*
  std::cout << "*** Reevaluate! ***" << std::endl;
  real normalizer = (1.0 - pow(gamma, (real)n_observations)) /(1.0 - gamma);
  real inv_normalizer = 1.0 / normalizer;
  std::cout << "inv_normalizer: " << inv_normalizer << std::endl;
  for (int i=0; i<n_eigen; i++)
    std::cout << d->ptr[i] * inv_normalizer << std::endl;
  */
  //---------------------

  // Update Xt, G and minibatch_index
  Mat *Xkt =  Xt->subMat(0,0,n_eigen-1,n_dim-1);
  Xkt->copy(Ut);
  delete Xkt;

  for (int i=0; i<n_eigen; i++)
    G->ptr[i][i] = d->ptr[i];

  minibatch_index=0;
}

void PcaEstimator::GetLeadingEigen(Vec *the_d, Mat *the_Vt)
{

  // Copy the eigen values and normalize them by (1 - pow(gamma,real(t+1)))/(1 - gamma);
  the_d->copy(d);

  real normalizer = (1.0 - pow(gamma, (real)n_observations)) /(1.0 - gamma);
  real inv_normalizer = 1.0 / normalizer;

  for (int i=0; i<the_d->n; i++)
    the_d->ptr[i] *= inv_normalizer;

  // Copy the unnormalized eigen vectors and normalize them
  the_Vt->copy(Ut);

  warning("I haven't normalized the eigen vectors");

}

PcaEstimator::~PcaEstimator()
{
}

}
<commit_msg>GetLeadingEigen now returns normalized eigenvectors.<commit_after>// Copyright 2008 Google Inc.
//
// 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 <cassert>
#include <iostream>
#include "pca_estimator.h"

namespace Torch {

PcaEstimator::PcaEstimator(int n_dim_, int n_eigen_, int minibatch_size_, real gamma_) : Object()
{
  n_dim = n_dim_;
  n_eigen = n_eigen_;
  minibatch_size = minibatch_size_;
  gamma = gamma_;
  lambda = 1e-3;

  n_observations = 0;
  minibatch_index = 0;

  Initialize();
}

void PcaEstimator::Initialize()
{
  Xt = new(allocator) Mat(n_eigen + minibatch_size, n_dim);
  Xt->zero();

  x_sum = new(allocator) Vec(n_dim);
  for (int i=0; i<x_sum->n; i++)
    x_sum->ptr[i] = 0.0;

  G = new(allocator) Mat(n_eigen + minibatch_size, n_eigen + minibatch_size);
  G->zero();
  for (int i=0; i<n_eigen; i++)
    G->ptr[i][i] = lambda;

  d = new(allocator) Vec(n_eigen + minibatch_size);
  for (int i=0; i<n_eigen+minibatch_size; i++)
    d->ptr[i] = 0.0;

  V = new(allocator)  Mat(n_eigen + minibatch_size, n_eigen + minibatch_size);
  V->zero();

  Ut = new(allocator)  Mat(n_eigen, n_dim);
  Ut->zero();
}

void PcaEstimator::Observe(Vec *x)
{
  assert(x->n == n_dim);

  n_observations++;

  // Add the *non-centered* observation to Xt.
  int row = n_eigen + minibatch_index;
  Xt->setRow(row, x);

  // Update the discounted sum of the observations.
  for (int i=0; i<x_sum->n; i++)
    x_sum->ptr[i] = x_sum->ptr[i] * gamma + x->ptr[i];

  // To get the mean, we must normalize the sum by:
  // /gamma^(n_observations-1) + /gamma^(n_observations-2) + ... + 1
  real normalizer = (1 - pow(gamma, (real)n_observations)) /(1 - gamma);
  real inv_normalizer = 1.0 / normalizer;

  // Now center the observation.
  // We will lose the first observation as it is the only one in the mean.
  Vec new_x(Xt->ptr[row], n_dim);
  for (int i=0; i<new_x.n; i++)
    new_x.ptr[i] -= x_sum->ptr[i] * inv_normalizer;

  // Multiply the centered observation by the discount compensator. Basically
  // we make this observation look "younger" than the previous ones. The actual
  // discount is applied in the reevaluation (and when solving the equations in
  // the case of TONGA) by multiplying every direction with the same aging factor.
  real rn = pow(gamma, -0.5*(minibatch_index+1));
  for (int i=0; i<n_dim; i++)
    Xt->ptr[row][i] *= rn;

  // Update the Gram Matrix. Xkt represents the currently used portion
  // of Xt (first rows).
  Vec new_g(G->ptr[row], row + 1);
  Mat *Xkt =  Xt->subMat(0,0,row,n_dim-1);
  mxMatMulVec(Xkt, x, &new_g);
  delete Xkt;

  // Now copy G(row,:) to G(:,row).
  // There are row+1 values, but the diag doesn't need to get copied.
  for (int i=0; i<row; i++)
    G->ptr[i][row] =  G->ptr[row][i];

  minibatch_index++;

  if(minibatch_index==minibatch_size)
    Reevaluate();

}

void PcaEstimator::Reevaluate()
{
  // TODO do the modifications to handle when this is not true.
  assert(minibatch_index==minibatch_size);

  // Regularize - not necessary but in case
  //for (int i=0; i<n_eigen+minibatch_size; i++)
  //  G->ptr[i][i] += lambda;

  // The Gram matrix is up to date. Get its low rank eigendecomposition.
  // TODO How to get only #n_eigen# elements?
  mxSymEig(G, V, d);

  // The eigen values and vectors are *NOT SORTED*. Furthermore, the vectors
  // are on the columns.
  // Find and sort the n_eigen first values and vectors using Dumb Sort
  for (int i=0; i<n_eigen; i++) {
    // Initialize the max search
    int max_index = i;
    real max_value = d->ptr[i];

    // Compare with remaining possibilities
    for (int j=i+1; j<n_eigen+minibatch_size; j++) {
      if (max_value < d->ptr[j])  {
        max_value = d->ptr[j];
        max_index = j;
      }
    }

    // Swap!
    d->ptr[max_index] = d->ptr[i];
    d->ptr[i] = max_value;
    mxSwapColsMat(V, i, max_index, -1, -1);
  }

  // Convert the n_eigen first eigenvectors of the Gram matrix contained in V
  // into *unnormalized* eigenvectors U of the covariance.
  Mat *Vk = V->subMat(0, 0, n_eigen+minibatch_index-1, n_eigen-1);
  mxTrMatMulMat(Vk, Xt, Ut);
  delete Vk;

  // Take into account the discount factor.
  // Here, minibatch index is minibacth_size. We age everyone. Because of the
  // previous multiplications to make some observations "younger" we multiply
  // everyone by the same factor.
  // TODO VERIFY THIS!
  real rn = pow(gamma, -0.5*(minibatch_index+1));
  real inv_rn2 = 1.0/(rn*rn);

  mxRealMulMat(1.0/rn, Ut, Ut);
  for (int i=0; i<d->n; i++)
    d->ptr[i] *= inv_rn2;

  //---------------------
  /*
  std::cout << "*** Reevaluate! ***" << std::endl;
  real normalizer = (1.0 - pow(gamma, (real)n_observations)) /(1.0 - gamma);
  real inv_normalizer = 1.0 / normalizer;
  std::cout << "inv_normalizer: " << inv_normalizer << std::endl;
  for (int i=0; i<n_eigen; i++)
    std::cout << d->ptr[i] * inv_normalizer << std::endl;
  */
  //---------------------

  // Update Xt, G and minibatch_index
  Mat *Xkt =  Xt->subMat(0,0,n_eigen-1,n_dim-1);
  Xkt->copy(Ut);
  delete Xkt;

  for (int i=0; i<n_eigen; i++)
    G->ptr[i][i] = d->ptr[i];

  minibatch_index=0;
}

void PcaEstimator::GetLeadingEigen(Vec *the_d, Mat *the_Vt)
{

  // Copy the eigen values and normalize them by (1 - pow(gamma,real(t+1)))/(1 - gamma);
  the_d->copy(d);

  real normalizer = (1.0 - pow(gamma, (real)n_observations)) /(1.0 - gamma);
  real inv_normalizer = 1.0 / normalizer;

  for (int i=0; i<the_d->n; i++)
    the_d->ptr[i] *= inv_normalizer;

  // Copy the unnormalized eigen vectors and normalize them
  the_Vt->copy(Ut);

  // Normalize
  Vec a_eigenvec(NULL, n_dim);
  for (int i=0; i<the_Vt->m; i++) {
    a_eigenvec.ptr = the_Vt->ptr[i];
    real inv_norm2 = 1.0 / a_eigenvec.norm2();
    for (int j=0; j<the_Vt->n; j++)
      the_Vt->ptr[i][j] *= inv_norm2;
    assert( fabs(a_eigenvec.norm2() - 1.0) < 1e-6 );
  }

}

PcaEstimator::~PcaEstimator()
{
}

}
<|endoftext|>


<commit_before>// Copyright 2017 Netherlands Institute for Radio Astronomy (ASTRON)
// Copyright 2017 Netherlands eScience Center
//
// 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 <fstream>

#include <SynthesizedBeams.hpp>

namespace AstroData {

void generateBeamMapping(const AstroData::Observation & observation, std::vector<unsigned int & beamMapping, const unsigned int padding, const bool subbanding) {
  for ( unsigned int beam = 0; beam < observation.getNrSynthesizedBeams(); beam++ ) {
    if ( subbanding) {
      for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ ) {
        beamMapping[(beam * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband] = beam % observation.getNrBeams();
      }
    } else {
      for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
        beamMapping[(beam * observation.getNrChannels(padding / sizeof(unsigned int))) + channel] = beam % observation.getNrBeams();
      }
    }
  }
}

void readBeamMapping(const AstroData::Observation & observation, const std::string & inputFilename, std::vector<unsigned int> & beamMapping, const unsigned int padding, const bool subbanding) {
  std::ifstream inputFile;

  inputFile.open(inputFilename);
  if ( !inputFile ) {i
    throw FileError("Impossible to open " + inputFilename);
  }
  for ( unsigned int sBeam = 0; sBeam < observation.getNrSynthesizedBeams(); sBeam++ ) {
    if ( subbanding ) {
      for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ ) {
        inputFile >> beamMapping[(sBeam * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband];
      }
    } else {
      for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
        inputFile >> beamMapping[(sBeam * observation.getNrChannels(padding / sizeof(unsigned int))) + channel];
      }
    }
  }
  inputFile.close();
}

} // AstroData

<commit_msg>Typo.<commit_after>// Copyright 2017 Netherlands Institute for Radio Astronomy (ASTRON)
// Copyright 2017 Netherlands eScience Center
//
// 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 <fstream>

#include <SynthesizedBeams.hpp>

namespace AstroData {

void generateBeamMapping(const AstroData::Observation & observation, std::vector<unsigned int & beamMapping, const unsigned int padding, const bool subbanding) {
  for ( unsigned int beam = 0; beam < observation.getNrSynthesizedBeams(); beam++ ) {
    if ( subbanding) {
      for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ ) {
        beamMapping[(beam * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband] = beam % observation.getNrBeams();
      }
    } else {
      for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
        beamMapping[(beam * observation.getNrChannels(padding / sizeof(unsigned int))) + channel] = beam % observation.getNrBeams();
      }
    }
  }
}

void readBeamMapping(const AstroData::Observation & observation, const std::string & inputFilename, std::vector<unsigned int> & beamMapping, const unsigned int padding, const bool subbanding) {
  std::ifstream inputFile;

  inputFile.open(inputFilename);
  if ( !inputFile ) {
    throw FileError("Impossible to open " + inputFilename);
  }
  for ( unsigned int sBeam = 0; sBeam < observation.getNrSynthesizedBeams(); sBeam++ ) {
    if ( subbanding ) {
      for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ ) {
        inputFile >> beamMapping[(sBeam * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband];
      }
    } else {
      for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
        inputFile >> beamMapping[(sBeam * observation.getNrChannels(padding / sizeof(unsigned int))) + channel];
      }
    }
  }
  inputFile.close();
}

} // AstroData

<|endoftext|>


<commit_before>#include <stdexcept>
#include <memory>
#include <cmath>
#include <cassert>
#include <iostream>

#include "gamestates/playstate.hh"
#include "gamestates/endstate.hh"
#include "settings.hh"
#include "map_reader.hh"
#include "player.hh"
#include "mouse.hh"
#include "map.hh"
#include "text_drawer.hh"
#include "turrets/basic.hh"
#include "turrets/sniper.hh"
#include "turrets/super.hh"
#include "mobs/foot_soldier.hh"
#include "mobs/horse_soldier.hh"
#include "mobs/tank_soldier.hh"
#include "pathfinding.hh"

PlayState::PlayState(std::string map)
    : turret_{nullptr}
{
    if (!MapReader::set_size(map))
        throw std::logic_error("Could not load map '" + map + "'.");
    Map::init();
    if (!MapReader::read_map(map))
        throw std::logic_error("Error reading map '" + map + "'.");
    Map::init_draw(0, 50);
    Player::init(150, 10, std::chrono::system_clock::now());
    this->levels.push_back(Level("resources/levels/1.td42"));
    this->levels.push_back(Level("resources/levels/2.td42"));
    this->levels.push_back(Level("resources/levels/3.td42"));
    this->levels.push_back(Level("resources/levels/4.td42"));
    this->levels.push_back(Level("resources/levels/5.td42"));
    ms_before_next_level = 100;
    ms_before_next_mob = TIME_BETWEEN_MOBS;
    if (!toogy_content_.loadFromFile("resources/towerselection.png"))
        throw std::logic_error("Could not load logo.");
    sf::Sprite t(toogy_content_);
    toogy_tres_content_ = t;
    toogy_tres_content_.setPosition(5, Settings::screen_height
                                       - toogy_content_.getSize().y / 2 - 50);
    toogy_tres_content_.setScale(0.5, 0.5);
}

void PlayState::insert_mode(std::shared_ptr<Turret> t)
{
    turret_ = t;
    t->set_opacity(100);
}

void PlayState::exit_insert_mode()
{
    turret_ = nullptr;
    ms_before_next_level = 100;
}

void PlayState::exit_insert_mode_and_create()
{
    if (turret_ != nullptr)
    {
        if (!Player::remove_money(turret_->get_cost()))
        {
            turret_ = nullptr;
            return;
        }
        auto pos = turret_->get_pos();
        if (pos.first < 0 || pos.first >= Map::width || pos.second < 0
            || pos.second >= Map::height
            || (Map::cells[pos.first][pos.second].type != CellType::Empty
           && Map::cells[pos.first][pos.second].type != Obstacle))
        {
            turret_ = nullptr;
            return;
        }
        auto t = Map::cells[pos.first][pos.second].type;
        Map::cells[pos.first][pos.second].type = CellType::Tower;
        auto list = pathfind(Map::start_mobs, Map::finish_mobs);
        if (list.size() == 0)
        {
            Map::cells[pos.first][pos.second].type = t;
            turret_ = nullptr;
            return;
        }
        turret_->set_opacity(255);
        Map::turrets.push_front(turret_);
        turret_ = nullptr;
        for (auto& enemy : Map::ennemies)
            enemy->update_pathfinding();
    }
}

void PlayState::draw(sf::RenderWindow& w)
{
    if (turret_ != nullptr)
    {
        auto pos = Mouse::get_mouse_pos(w);
        unsigned px;
        unsigned py;
        Map::screen_to_map(pos.first, pos.second, px, py);
        turret_->set_pos(px, py);
    }
    Map::draw(w, turret_);
    TextDrawer::display_time(w);
    TextDrawer::display_lifes(w);
    TextDrawer::display_money(w);
    TextDrawer::display_mouse_coords(w);
    TextDrawer::display_mouse_coords_on_map(w);
    w.draw(toogy_tres_content_);
}

bool is_arrived(float x1, float x2, float y1, float y2)
{
    int ix1 = x1;
    int ix2 = x2;
    int iy1 = y1;
    int iy2 = y2;
    if (ix1 == ix2 && iy1 == iy2)
        return true;
    float dx = fabs(x1 - x2);
    float dy = fabs(y1 - y2);
    return dx < 0.2f && dy < 0.2f;
}

void PlayState::update(unsigned elapsed_ms)
{
    //static std::chrono::time_point<std::chrono::system_clock> time;
    //std::chrono::duration<double> elapsed =
    //std::chrono::system_clock::now() - time;
    //time = std::chrono::system_clock::now();
    //std::cout << std::to_string(elapsed.count()) << std::endl;
    if (this->levels.size() == 0 && Map::ennemies.empty())
    {
        GameState::stack.pop_back();
        auto ptr = std::make_shared<EndState>();
        GameState::stack.push_back(ptr);
    }
    else if (ms_before_next_level <= 0)
    {
        if (ms_before_next_mob <= 0)
        {
            if (!this->levels.front().make_mob())
            {
                std::cout << "NEW LEVEL" << std::endl;
                this->levels.pop_front();
                ms_before_next_level = TIME_BETWEEN_LEVELS;
            }
            else
                ms_before_next_mob = TIME_BETWEEN_MOBS;
        }
        else
            ms_before_next_mob -= elapsed_ms;
    }
    else
        ms_before_next_level -= elapsed_ms;
    for (std::list<std::shared_ptr<Mob>>::iterator i = Map::ennemies.begin();
            i != Map::ennemies.end();)
    {
        if ((*i)->dead())
            i = Map::ennemies.erase(i);
        else
        {
            (*i)->move();
            auto pos = (*i)->get_pos();
            if (is_arrived(pos.first, Map::finish_mobs.first,
                        pos.second, Map::finish_mobs.second))
            {
                (*i)->harakiri();
                if (!Player::remove_a_life())
                {
                    GameState::stack.pop_back();
                    auto ptr = std::make_shared<EndState>();
                    GameState::stack.push_back(ptr);
                }
                i = Map::ennemies.erase(i);
            }
            else
                ++i;
        }
    }
    for (std::shared_ptr<Turret> turret : Map::turrets)
        turret->attack(elapsed_ms);
    ++elapsed_ms;
}
<commit_msg>Coding style<commit_after>#include <stdexcept>
#include <memory>
#include <cmath>
#include <cassert>
#include <iostream>

#include "gamestates/playstate.hh"
#include "gamestates/endstate.hh"
#include "settings.hh"
#include "map_reader.hh"
#include "player.hh"
#include "mouse.hh"
#include "map.hh"
#include "text_drawer.hh"
#include "turrets/basic.hh"
#include "turrets/sniper.hh"
#include "turrets/super.hh"
#include "mobs/foot_soldier.hh"
#include "mobs/horse_soldier.hh"
#include "mobs/tank_soldier.hh"
#include "pathfinding.hh"

PlayState::PlayState(std::string map)
         : turret_{nullptr}
{
    if (!MapReader::set_size(map))
        throw std::logic_error("Could not load map '" + map + "'.");
    Map::init();
    if (!MapReader::read_map(map))
        throw std::logic_error("Error reading map '" + map + "'.");
    Map::init_draw(0, 50);
    Player::init(150, 10, std::chrono::system_clock::now());
    this->levels.push_back(Level("resources/levels/1.td42"));
    this->levels.push_back(Level("resources/levels/2.td42"));
    this->levels.push_back(Level("resources/levels/3.td42"));
    this->levels.push_back(Level("resources/levels/4.td42"));
    this->levels.push_back(Level("resources/levels/5.td42"));
    ms_before_next_level = 100;
    ms_before_next_mob = TIME_BETWEEN_MOBS;
    if (!toogy_content_.loadFromFile("resources/towerselection.png"))
        throw std::logic_error("Could not load logo.");
    sf::Sprite t(toogy_content_);
    toogy_tres_content_ = t;
    toogy_tres_content_.setPosition(5, Settings::screen_height
                                       - toogy_content_.getSize().y / 2 - 50);
    toogy_tres_content_.setScale(0.5, 0.5);
}

void PlayState::insert_mode(std::shared_ptr<Turret> t)
{
    turret_ = t;
    t->set_opacity(100);
}

void PlayState::exit_insert_mode()
{
    turret_ = nullptr;
    ms_before_next_level = 100;
}

void PlayState::exit_insert_mode_and_create()
{
    if (turret_ != nullptr)
    {
        if (!Player::remove_money(turret_->get_cost()))
        {
            turret_ = nullptr;
            return;
        }
        auto pos = turret_->get_pos();
        if (pos.first < 0 || pos.first >= Map::width || pos.second < 0
            || pos.second >= Map::height
            || (Map::cells[pos.first][pos.second].type != CellType::Empty
           && Map::cells[pos.first][pos.second].type != Obstacle))
        {
            turret_ = nullptr;
            return;
        }
        auto t = Map::cells[pos.first][pos.second].type;
        Map::cells[pos.first][pos.second].type = CellType::Tower;
        auto list = pathfind(Map::start_mobs, Map::finish_mobs);
        if (list.size() == 0)
        {
            Map::cells[pos.first][pos.second].type = t;
            turret_ = nullptr;
            return;
        }
        turret_->set_opacity(255);
        Map::turrets.push_front(turret_);
        turret_ = nullptr;
        for (auto& enemy : Map::ennemies)
            enemy->update_pathfinding();
    }
}

void PlayState::draw(sf::RenderWindow& w)
{
    if (turret_ != nullptr)
    {
        auto pos = Mouse::get_mouse_pos(w);
        unsigned px;
        unsigned py;
        Map::screen_to_map(pos.first, pos.second, px, py);
        turret_->set_pos(px, py);
    }
    Map::draw(w, turret_);
    TextDrawer::display_time(w);
    TextDrawer::display_lifes(w);
    TextDrawer::display_money(w);
    TextDrawer::display_mouse_coords(w);
    TextDrawer::display_mouse_coords_on_map(w);
    w.draw(toogy_tres_content_);
}

bool is_arrived(float x1, float x2, float y1, float y2)
{
    int ix1 = x1;
    int ix2 = x2;
    int iy1 = y1;
    int iy2 = y2;
    if (ix1 == ix2 && iy1 == iy2)
        return true;
    float dx = fabs(x1 - x2);
    float dy = fabs(y1 - y2);
    return dx < 0.2f && dy < 0.2f;
}

void PlayState::update(unsigned elapsed_ms)
{
    if (this->levels.size() == 0 && Map::ennemies.empty())
    {
        GameState::stack.pop_back();
        auto ptr = std::make_shared<EndState>();
        GameState::stack.push_back(ptr);
    }
    else if (ms_before_next_level <= 0)
    {
        if (ms_before_next_mob <= 0)
        {
            if (!this->levels.front().make_mob())
            {
                std::cout << "NEW LEVEL" << std::endl;
                this->levels.pop_front();
                ms_before_next_level = TIME_BETWEEN_LEVELS;
            }
            else
                ms_before_next_mob = TIME_BETWEEN_MOBS;
        }
        else
            ms_before_next_mob -= elapsed_ms;
    }
    else
        ms_before_next_level -= elapsed_ms;
    for (std::list<std::shared_ptr<Mob>>::iterator i = Map::ennemies.begin();
            i != Map::ennemies.end();)
    {
        if ((*i)->dead())
            i = Map::ennemies.erase(i);
        else
        {
            (*i)->move();
            auto pos = (*i)->get_pos();
            if (is_arrived(pos.first, Map::finish_mobs.first,
                        pos.second, Map::finish_mobs.second))
            {
                (*i)->harakiri();
                if (!Player::remove_a_life())
                {
                    GameState::stack.pop_back();
                    auto ptr = std::make_shared<EndState>();
                    GameState::stack.push_back(ptr);
                }
                i = Map::ennemies.erase(i);
            }
            else
                ++i;
        }
    }
    for (std::shared_ptr<Turret> turret : Map::turrets)
        turret->attack(elapsed_ms);
    ++elapsed_ms;
}
<|endoftext|>


<commit_before>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// 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 "rclcpp/utilities.hpp"

#include <atomic>
#include <condition_variable>
#include <csignal>
#include <cstdio>
#include <cstring>
#include <map>
#include <mutex>
#include <string>
#include <vector>

#include "rcl/error_handling.h"
#include "rcl/rcl.h"

#include "rmw/error_handling.h"
#include "rmw/rmw.h"

// Determine if sigaction is available
#if __APPLE__ || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
#define HAS_SIGACTION
#endif

/// Represent the status of the global interrupt signal.
static volatile sig_atomic_t g_signal_status = 0;
/// Guard conditions for interrupting the rmw implementation when the global interrupt signal fired.
static std::map<rcl_wait_set_t *, rcl_guard_condition_t> g_sigint_guard_cond_handles;
/// Mutex to protect g_sigint_guard_cond_handles
static std::mutex g_sigint_guard_cond_handles_mutex;
/// Condition variable for timed sleep (see sleep_for).
static std::condition_variable g_interrupt_condition_variable;
static std::atomic<bool> g_is_interrupted(false);
/// Mutex for protecting the global condition variable.
static std::mutex g_interrupt_mutex;

#ifdef HAS_SIGACTION
static struct sigaction old_action;
#else
typedef void (* signal_handler_t)(int);
static signal_handler_t old_signal_handler = 0;
#endif

#ifdef HAS_SIGACTION
struct sigaction
set_sigaction(int signal_value, const struct sigaction & action)
#else
signal_handler_t
set_signal_handler(int signal_value, signal_handler_t signal_handler)
#endif
{
#ifdef HAS_SIGACTION
  struct sigaction old_action;
  ssize_t ret = sigaction(signal_value, &action, &old_action);
  if (ret == -1)
#else
  signal_handler_t old_signal_handler = std::signal(signal_value, signal_handler);
  // NOLINTNEXTLINE(readability/braces)
  if (old_signal_handler == SIG_ERR)
#endif
  {
    const size_t error_length = 1024;
    // NOLINTNEXTLINE(runtime/arrays)
    char error_string[error_length];
#ifndef _WIN32
#if (defined(_GNU_SOURCE) && !defined(ANDROID))
    char * msg = strerror_r(errno, error_string, error_length);
    if (msg != error_string) {
      strncpy(error_string, msg, error_length);
      msg[error_length - 1] = '\0';
    }
#else
    int error_status = strerror_r(errno, error_string, error_length);
    if (error_status != 0) {
      throw std::runtime_error("Failed to get error string for errno: " + std::to_string(errno));
    }
#endif
#else
    strerror_s(error_string, error_length, errno);
#endif
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(
      std::string("Failed to set SIGINT signal handler: (" + std::to_string(errno) + ")") +
      error_string);
    // *INDENT-ON*
  }

#ifdef HAS_SIGACTION
  return old_action;
#else
  return old_signal_handler;
#endif
}

void
trigger_interrupt_guard_condition(int signal_value)
{
  g_signal_status = signal_value;
  {
    std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
    for (auto & kv : g_sigint_guard_cond_handles) {
      rcl_ret_t status = rcl_trigger_guard_condition(&(kv.second));
      if (status != RCL_RET_OK) {
        fprintf(stderr,
          "[rclcpp::error] failed to trigger guard condition: %s\n", rcl_get_error_string_safe());
      }
    }
  }
  g_is_interrupted.store(true);
  g_interrupt_condition_variable.notify_all();
}

void
#ifdef HAS_SIGACTION
signal_handler(int signal_value, siginfo_t * siginfo, void * context)
#else
signal_handler(int signal_value)
#endif
{
  // TODO(wjwwood): remove? move to console logging at some point?
  printf("signal_handler(%d)\n", signal_value);

#ifdef HAS_SIGACTION
  if (old_action.sa_flags & SA_SIGINFO) {
    if (old_action.sa_sigaction != NULL) {
      old_action.sa_sigaction(signal_value, siginfo, context);
    }
  } else {
    // *INDENT-OFF*
    if (
      old_action.sa_handler != NULL &&  // Is set
      old_action.sa_handler != SIG_DFL &&  // Is not default
      old_action.sa_handler != SIG_IGN)  // Is not ignored
    // *INDENT-ON*
    {
      old_action.sa_handler(signal_value);
    }
  }
#else
  if (old_signal_handler) {
    old_signal_handler(signal_value);
  }
#endif

  trigger_interrupt_guard_condition(signal_value);
}

void
rclcpp::utilities::init(int argc, char * argv[])
{
  g_is_interrupted.store(false);
  if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(
      std::string("failed to initialize rmw implementation: ") + rcl_get_error_string_safe());
    // *INDENT-ON*
  }
#ifdef HAS_SIGACTION
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigemptyset(&action.sa_mask);
  action.sa_sigaction = ::signal_handler;
  action.sa_flags = SA_SIGINFO;
  ::old_action = set_sigaction(SIGINT, action);
  // Register an on_shutdown hook to restore the old action.
  rclcpp::utilities::on_shutdown([]() {
    set_sigaction(SIGINT, ::old_action);
  });
#else
  ::old_signal_handler = set_signal_handler(SIGINT, ::signal_handler);
  // Register an on_shutdown hook to restore the old signal handler.
  rclcpp::utilities::on_shutdown([]() {
    set_signal_handler(SIGINT, ::old_signal_handler);
  });
#endif
}

bool
rclcpp::utilities::ok()
{
  return ::g_signal_status == 0;
}

static std::mutex on_shutdown_mutex_;
static std::vector<std::function<void(void)>> on_shutdown_callbacks_;

void
rclcpp::utilities::shutdown()
{
  trigger_interrupt_guard_condition(SIGINT);

  {
    std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
    for (auto & on_shutdown_callback : on_shutdown_callbacks_) {
      on_shutdown_callback();
    }
  }
}

void
rclcpp::utilities::on_shutdown(std::function<void(void)> callback)
{
  std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
  on_shutdown_callbacks_.push_back(callback);
}

rcl_guard_condition_t *
rclcpp::utilities::get_sigint_guard_condition(rcl_wait_set_t * waitset)
{
  std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
  auto kv = g_sigint_guard_cond_handles.find(waitset);
  if (kv != g_sigint_guard_cond_handles.end()) {
    return &kv->second;
  } else {
    rcl_guard_condition_t handle =
      rcl_get_zero_initialized_guard_condition();
    rcl_guard_condition_options_t options = rcl_guard_condition_get_default_options();
    if (rcl_guard_condition_init(&handle, options) != RCL_RET_OK) {
      // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
      throw std::runtime_error(std::string(
        "Couldn't initialize guard condition: ") + rcl_get_error_string_safe());
      // *INDENT-ON*
    }
    g_sigint_guard_cond_handles[waitset] = handle;
    return &g_sigint_guard_cond_handles[waitset];
  }
}

void
rclcpp::utilities::release_sigint_guard_condition(rcl_wait_set_t * waitset)
{
  std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
  auto kv = g_sigint_guard_cond_handles.find(waitset);
  if (kv != g_sigint_guard_cond_handles.end()) {
    if (rcl_guard_condition_fini(&kv->second) != RCL_RET_OK) {
      // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
      throw std::runtime_error(std::string(
        "Failed to destroy sigint guard condition: ") +
        rcl_get_error_string_safe());
      // *INDENT-ON*
    }
    g_sigint_guard_cond_handles.erase(kv);
  } else {
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(std::string(
      "Tried to release sigint guard condition for nonexistent waitset"));
    // *INDENT-ON*
  }
}

bool
rclcpp::utilities::sleep_for(const std::chrono::nanoseconds & nanoseconds)
{
  std::chrono::nanoseconds time_left = nanoseconds;
  {
    std::unique_lock<std::mutex> lock(::g_interrupt_mutex);
    auto start = std::chrono::steady_clock::now();
    ::g_interrupt_condition_variable.wait_for(lock, nanoseconds);
    time_left -= std::chrono::steady_clock::now() - start;
  }
  if (time_left > std::chrono::nanoseconds::zero() && !g_is_interrupted) {
    return sleep_for(time_left);
  }
  // Return true if the timeout elapsed successfully, otherwise false.
  return !g_is_interrupted;
}
<commit_msg>reset error code before throwing in rclcpp::utilities::init<commit_after>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// 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 "rclcpp/utilities.hpp"

#include <atomic>
#include <condition_variable>
#include <csignal>
#include <cstdio>
#include <cstring>
#include <map>
#include <mutex>
#include <string>
#include <vector>

#include "rcl/error_handling.h"
#include "rcl/rcl.h"

#include "rmw/error_handling.h"
#include "rmw/rmw.h"

// Determine if sigaction is available
#if __APPLE__ || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
#define HAS_SIGACTION
#endif

/// Represent the status of the global interrupt signal.
static volatile sig_atomic_t g_signal_status = 0;
/// Guard conditions for interrupting the rmw implementation when the global interrupt signal fired.
static std::map<rcl_wait_set_t *, rcl_guard_condition_t> g_sigint_guard_cond_handles;
/// Mutex to protect g_sigint_guard_cond_handles
static std::mutex g_sigint_guard_cond_handles_mutex;
/// Condition variable for timed sleep (see sleep_for).
static std::condition_variable g_interrupt_condition_variable;
static std::atomic<bool> g_is_interrupted(false);
/// Mutex for protecting the global condition variable.
static std::mutex g_interrupt_mutex;

#ifdef HAS_SIGACTION
static struct sigaction old_action;
#else
typedef void (* signal_handler_t)(int);
static signal_handler_t old_signal_handler = 0;
#endif

#ifdef HAS_SIGACTION
struct sigaction
set_sigaction(int signal_value, const struct sigaction & action)
#else
signal_handler_t
set_signal_handler(int signal_value, signal_handler_t signal_handler)
#endif
{
#ifdef HAS_SIGACTION
  struct sigaction old_action;
  ssize_t ret = sigaction(signal_value, &action, &old_action);
  if (ret == -1)
#else
  signal_handler_t old_signal_handler = std::signal(signal_value, signal_handler);
  // NOLINTNEXTLINE(readability/braces)
  if (old_signal_handler == SIG_ERR)
#endif
  {
    const size_t error_length = 1024;
    // NOLINTNEXTLINE(runtime/arrays)
    char error_string[error_length];
#ifndef _WIN32
#if (defined(_GNU_SOURCE) && !defined(ANDROID))
    char * msg = strerror_r(errno, error_string, error_length);
    if (msg != error_string) {
      strncpy(error_string, msg, error_length);
      msg[error_length - 1] = '\0';
    }
#else
    int error_status = strerror_r(errno, error_string, error_length);
    if (error_status != 0) {
      throw std::runtime_error("Failed to get error string for errno: " + std::to_string(errno));
    }
#endif
#else
    strerror_s(error_string, error_length, errno);
#endif
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(
      std::string("Failed to set SIGINT signal handler: (" + std::to_string(errno) + ")") +
      error_string);
    // *INDENT-ON*
  }

#ifdef HAS_SIGACTION
  return old_action;
#else
  return old_signal_handler;
#endif
}

void
trigger_interrupt_guard_condition(int signal_value)
{
  g_signal_status = signal_value;
  {
    std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
    for (auto & kv : g_sigint_guard_cond_handles) {
      rcl_ret_t status = rcl_trigger_guard_condition(&(kv.second));
      if (status != RCL_RET_OK) {
        fprintf(stderr,
          "[rclcpp::error] failed to trigger guard condition: %s\n", rcl_get_error_string_safe());
      }
    }
  }
  g_is_interrupted.store(true);
  g_interrupt_condition_variable.notify_all();
}

void
#ifdef HAS_SIGACTION
signal_handler(int signal_value, siginfo_t * siginfo, void * context)
#else
signal_handler(int signal_value)
#endif
{
  // TODO(wjwwood): remove? move to console logging at some point?
  printf("signal_handler(%d)\n", signal_value);

#ifdef HAS_SIGACTION
  if (old_action.sa_flags & SA_SIGINFO) {
    if (old_action.sa_sigaction != NULL) {
      old_action.sa_sigaction(signal_value, siginfo, context);
    }
  } else {
    // *INDENT-OFF*
    if (
      old_action.sa_handler != NULL &&  // Is set
      old_action.sa_handler != SIG_DFL &&  // Is not default
      old_action.sa_handler != SIG_IGN)  // Is not ignored
    // *INDENT-ON*
    {
      old_action.sa_handler(signal_value);
    }
  }
#else
  if (old_signal_handler) {
    old_signal_handler(signal_value);
  }
#endif

  trigger_interrupt_guard_condition(signal_value);
}

void
rclcpp::utilities::init(int argc, char * argv[])
{
  g_is_interrupted.store(false);
  if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
    std::string msg = "failed to initialize rmw implementation: ";
    msg += rcl_get_error_string_safe();
    rcl_reset_error();
    throw std::runtime_error(msg);
  }
#ifdef HAS_SIGACTION
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigemptyset(&action.sa_mask);
  action.sa_sigaction = ::signal_handler;
  action.sa_flags = SA_SIGINFO;
  ::old_action = set_sigaction(SIGINT, action);
  // Register an on_shutdown hook to restore the old action.
  rclcpp::utilities::on_shutdown([]() {
    set_sigaction(SIGINT, ::old_action);
  });
#else
  ::old_signal_handler = set_signal_handler(SIGINT, ::signal_handler);
  // Register an on_shutdown hook to restore the old signal handler.
  rclcpp::utilities::on_shutdown([]() {
    set_signal_handler(SIGINT, ::old_signal_handler);
  });
#endif
}

bool
rclcpp::utilities::ok()
{
  return ::g_signal_status == 0;
}

static std::mutex on_shutdown_mutex_;
static std::vector<std::function<void(void)>> on_shutdown_callbacks_;

void
rclcpp::utilities::shutdown()
{
  trigger_interrupt_guard_condition(SIGINT);

  {
    std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
    for (auto & on_shutdown_callback : on_shutdown_callbacks_) {
      on_shutdown_callback();
    }
  }
}

void
rclcpp::utilities::on_shutdown(std::function<void(void)> callback)
{
  std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
  on_shutdown_callbacks_.push_back(callback);
}

rcl_guard_condition_t *
rclcpp::utilities::get_sigint_guard_condition(rcl_wait_set_t * waitset)
{
  std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
  auto kv = g_sigint_guard_cond_handles.find(waitset);
  if (kv != g_sigint_guard_cond_handles.end()) {
    return &kv->second;
  } else {
    rcl_guard_condition_t handle =
      rcl_get_zero_initialized_guard_condition();
    rcl_guard_condition_options_t options = rcl_guard_condition_get_default_options();
    if (rcl_guard_condition_init(&handle, options) != RCL_RET_OK) {
      // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
      throw std::runtime_error(std::string(
        "Couldn't initialize guard condition: ") + rcl_get_error_string_safe());
      // *INDENT-ON*
    }
    g_sigint_guard_cond_handles[waitset] = handle;
    return &g_sigint_guard_cond_handles[waitset];
  }
}

void
rclcpp::utilities::release_sigint_guard_condition(rcl_wait_set_t * waitset)
{
  std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
  auto kv = g_sigint_guard_cond_handles.find(waitset);
  if (kv != g_sigint_guard_cond_handles.end()) {
    if (rcl_guard_condition_fini(&kv->second) != RCL_RET_OK) {
      // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
      throw std::runtime_error(std::string(
        "Failed to destroy sigint guard condition: ") +
        rcl_get_error_string_safe());
      // *INDENT-ON*
    }
    g_sigint_guard_cond_handles.erase(kv);
  } else {
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(std::string(
      "Tried to release sigint guard condition for nonexistent waitset"));
    // *INDENT-ON*
  }
}

bool
rclcpp::utilities::sleep_for(const std::chrono::nanoseconds & nanoseconds)
{
  std::chrono::nanoseconds time_left = nanoseconds;
  {
    std::unique_lock<std::mutex> lock(::g_interrupt_mutex);
    auto start = std::chrono::steady_clock::now();
    ::g_interrupt_condition_variable.wait_for(lock, nanoseconds);
    time_left -= std::chrono::steady_clock::now() - start;
  }
  if (time_left > std::chrono::nanoseconds::zero() && !g_is_interrupted) {
    return sleep_for(time_left);
  }
  // Return true if the timeout elapsed successfully, otherwise false.
  return !g_is_interrupted;
}
<|endoftext|>


<commit_before>// Copyright (c) 1999-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.

#include <Xw_Extension.h>

/* ifdef then trace on */
#ifdef TRACE
#define TRACE_OPEN_IMAGE
#endif

/*
   XW_EXT_IMAGEDATA Xw_open_image (awindow,aimageinfo,width,height):
   XW_EXT_WINDOW *awindow ;
   XW_USERDATA *aimageinfo ;		Image identifier
   int width,height		Image size in pixels

	Open an Image in the same Window visual as defined
	NOTE than this image can be filled with Xw_put_pixel

	Returns The image extension address if Successful
	returns  NULL if BadAllocation

   XW_STATUS Xw_close_image (aimage):
   XW_EXT_IMAGEDATA *aimage     Extended Image address

        Close an Image

        returns  SUCCESS always

   XW_EXT_IMAGEDATA* Xw_get_image_handle (awindow,aimageinfo):
   XW_EXT_WINDOW *awindow ;
   XW_USERDATA	aimageinfo     Image identifier

	returns the Image handle associated to the image ID
		or NULL if no image exist.

*/

#ifdef XW_PROTOTYPE
void* Xw_open_image (void *awindow,void *aimageinfo,int width,int height)
#else
void* Xw_open_image (awindow,aimageinfo,width,height)
void *awindow ;
void *aimageinfo ;
int width,height ;
#endif /*XW_PROTOTYPE*/
{
XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow;
XW_EXT_IMAGEDATA *pimage ;
XW_EXT_COLORMAP *pcolormap ;
//int i,pad ;
int pad ;
char *cdata ;

    if( !Xw_isdefine_window(pwindow) ) {
        /*ERROR*Bad EXT_WINDOW Address*/
        Xw_set_error(24,"Xw_open_image",pwindow) ;
        return (NULL) ;
    }

    switch (_DEPTH) {
    	case 8 :
	    pad = 1 ;
	    break ;
	case 12 :
	case 16 :
	    pad = 2 ;
	    break ;
	case 24 :
	    pad = 4 ;
	    break ;
	case 48 :
	case 64 :
	    pad = 8 ;
	    break ;
	default :
	    /*ERROR*Unimplemented Image Visual depth*/
	    Xw_set_error(64,"Xw_open_image",&_DEPTH) ;
	    return (NULL) ;
    }

    if( !(cdata = (char*) Xw_calloc(width*height,pad)) ) {
	/*ERROR*XImage Allocation failed*/
	Xw_set_error(60,"Xw_open_image",0) ;
        return (NULL) ;
    }

    if( !(pimage = Xw_add_imagedata_structure(sizeof(XW_EXT_IMAGEDATA))) )
								return (NULL) ;

    pimage->pimageinfo = aimageinfo ;
    pimage->pcolormap = pcolormap = _COLORMAP ;
    _IIMAGE = XCreateImage(_CDISPLAY,_CVISUAL,_DEPTH,
			ZPixmap,0,cdata,width,height,pad*8,width*pad) ;
    if( !_IIMAGE ) {
	/*ERROR*XImage Creation failed*/
	Xw_set_error(62,"Xw_open_image",0) ;
	Xw_del_imagedata_structure(pimage) ;
    }

#ifdef  TRACE_OPEN_IMAGE
if( Xw_get_trace() ) {
    printf (" %lx = Xw_open_image(%lx,%lx,%d,%d)\n",(long ) pimage,(long ) pwindow,(long ) aimageinfo,
							width,height);
}
#endif

    return (pimage);
}

static XW_EXT_IMAGEDATA *PimageList =NULL ;

#ifdef XW_PROTOTYPE
XW_EXT_IMAGEDATA* Xw_add_imagedata_structure(int size)
#else
XW_EXT_IMAGEDATA* Xw_add_imagedata_structure(size)
int size ;
#endif /*XW_PROTOTYPE*/
/*
        Create and Insert one Extended image structure in the
        EXtended image List

        returns Extended image address if successful
                or NULL if Bad Allocation
*/
{
XW_EXT_IMAGEDATA *pimage ;
//int i ;

	pimage = (XW_EXT_IMAGEDATA*) Xw_malloc(size) ;

        if( pimage ) {
	    pimage->type = IMAGE_TYPE ;
	    pimage->link = PimageList ;
	    PimageList = pimage ;
	    pimage->pcolormap = NULL ;
	    pimage->zoom = 1.;
            pimage->pximage = NULL ;
            pimage->zximage = NULL ;
	    pimage->maxwindow = 0 ;
        } else {
	    /*ERROR*EXT_IMAGE allocation failed*/
	    Xw_set_error(27,"Xw_open_image",0) ;
        }

        return (pimage) ;
}

#ifdef XW_PROTOTYPE
XW_STATUS Xw_close_image (void* aimage)
#else
XW_STATUS Xw_close_image (aimage)
void *aimage;
#endif /*XW_PROTOTYPE*/
{
XW_EXT_IMAGEDATA *pimage = (XW_EXT_IMAGEDATA*) aimage ;

        Xw_del_imagedata_structure(pimage) ;

#ifdef  TRACE_CLOSE_IMAGE
if( Xw_get_trace() ) {
        printf (" Xw_close_image(%x)\n",pimage);
}
#endif

        return (XW_SUCCESS);
}

#ifdef XW_PROTOTYPE
void* Xw_get_image_handle (void* awindow,void *aimageinfo)
#else
void* Xw_get_image_handle (awindow,aimageinfo)
void *awindow ;
void *aimageinfo ;
#endif /*XW_PROTOTYPE*/
{
#ifdef  TRACE_OPEN_IMAGE
XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ;
#endif
XW_EXT_IMAGEDATA *pimage ;

	for( pimage = PimageList ; pimage ;
			pimage = (XW_EXT_IMAGEDATA*) pimage->link ) {
            if( pimage->pimageinfo == aimageinfo ) break ;
        }

#ifdef  TRACE_OPEN_IMAGE
if( Xw_get_trace() ) {
    printf (" %lx = Xw_get_image_handle(%lx,%lx)\n",(long ) pimage,(long ) pwindow,(long ) aimageinfo);
}
#endif

	return (pimage) ;
}

#ifdef XW_PROTOTYPE
XW_STATUS Xw_del_imagedata_structure(XW_EXT_IMAGEDATA *aimage)
#else
XW_STATUS Xw_del_imagedata_structure(aimage)
XW_EXT_IMAGEDATA *aimage;
#endif /*XW_PROTOTYPE*/
/*
        Remove the Extended image address from the Extended List and
        Free the Extended Image

        returns ERROR if the image address is not Found in the list
        returns XW_SUCCESS if successful
*/
{
XW_EXT_IMAGEDATA *pimage = aimage ;
//int i ;

    if( !pimage ) return (XW_ERROR) ;

    if( pimage->maxwindow ) --pimage->maxwindow ;

    if( pimage->maxwindow ) {
	return (XW_ERROR) ;
    } else {
	if( _IIMAGE ) XDestroyImage(_IIMAGE) ;
	if( _ZIMAGE ) XDestroyImage(_ZIMAGE) ;
        if( pimage == PimageList ) {
            PimageList = (XW_EXT_IMAGEDATA*) pimage->link ;
        } else {
            for( pimage = PimageList ; pimage ;
			pimage = (XW_EXT_IMAGEDATA*) pimage->link ) {
                if( pimage->link == aimage ) {
                    pimage->link = aimage->link ;
                    break ;
                }
            }
        }
        Xw_free(aimage) ;
    }
    return (XW_SUCCESS) ;
}
<commit_msg>[cppcheck-fix][memory-leak]<commit_after>// Copyright (c) 1999-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.

#include <Xw_Extension.h>

/* ifdef then trace on */
#ifdef TRACE
#define TRACE_OPEN_IMAGE
#endif

/*
   XW_EXT_IMAGEDATA Xw_open_image (awindow,aimageinfo,width,height):
   XW_EXT_WINDOW *awindow ;
   XW_USERDATA *aimageinfo ;		Image identifier
   int width,height		Image size in pixels

	Open an Image in the same Window visual as defined
	NOTE than this image can be filled with Xw_put_pixel

	Returns The image extension address if Successful
	returns  NULL if BadAllocation

   XW_STATUS Xw_close_image (aimage):
   XW_EXT_IMAGEDATA *aimage     Extended Image address

        Close an Image

        returns  SUCCESS always

   XW_EXT_IMAGEDATA* Xw_get_image_handle (awindow,aimageinfo):
   XW_EXT_WINDOW *awindow ;
   XW_USERDATA	aimageinfo     Image identifier

	returns the Image handle associated to the image ID
		or NULL if no image exist.

*/

#ifdef XW_PROTOTYPE
void* Xw_open_image (void *awindow,void *aimageinfo,int width,int height)
#else
void* Xw_open_image (awindow,aimageinfo,width,height)
void *awindow ;
void *aimageinfo ;
int width,height ;
#endif /*XW_PROTOTYPE*/
{
XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow;
XW_EXT_IMAGEDATA *pimage ;
XW_EXT_COLORMAP *pcolormap ;
//int i,pad ;
int pad ;
char *cdata ;

    if( !Xw_isdefine_window(pwindow) ) {
        /*ERROR*Bad EXT_WINDOW Address*/
        Xw_set_error(24,"Xw_open_image",pwindow) ;
        return (NULL) ;
    }

    switch (_DEPTH) {
    	case 8 :
	    pad = 1 ;
	    break ;
	case 12 :
	case 16 :
	    pad = 2 ;
	    break ;
	case 24 :
	    pad = 4 ;
	    break ;
	case 48 :
	case 64 :
	    pad = 8 ;
	    break ;
	default :
	    /*ERROR*Unimplemented Image Visual depth*/
	    Xw_set_error(64,"Xw_open_image",&_DEPTH) ;
	    return (NULL) ;
    }

    if( !(cdata = (char*) Xw_calloc(width*height,pad)) ) {
	/*ERROR*XImage Allocation failed*/
	Xw_set_error(60,"Xw_open_image",0) ;
    Xw_free(cdata);
        return (NULL) ;
    }

    if( !(pimage = Xw_add_imagedata_structure(sizeof(XW_EXT_IMAGEDATA))) )
								return (NULL) ;

    pimage->pimageinfo = aimageinfo ;
    pimage->pcolormap = pcolormap = _COLORMAP ;
    _IIMAGE = XCreateImage(_CDISPLAY,_CVISUAL,_DEPTH,
			ZPixmap,0,cdata,width,height,pad*8,width*pad) ;
    if( !_IIMAGE ) {
	/*ERROR*XImage Creation failed*/
	Xw_set_error(62,"Xw_open_image",0) ;
	Xw_del_imagedata_structure(pimage) ;
    }

#ifdef  TRACE_OPEN_IMAGE
if( Xw_get_trace() ) {
    printf (" %lx = Xw_open_image(%lx,%lx,%d,%d)\n",(long ) pimage,(long ) pwindow,(long ) aimageinfo,
							width,height);
}
#endif

    return (pimage);
}

static XW_EXT_IMAGEDATA *PimageList =NULL ;

#ifdef XW_PROTOTYPE
XW_EXT_IMAGEDATA* Xw_add_imagedata_structure(int size)
#else
XW_EXT_IMAGEDATA* Xw_add_imagedata_structure(size)
int size ;
#endif /*XW_PROTOTYPE*/
/*
        Create and Insert one Extended image structure in the
        EXtended image List

        returns Extended image address if successful
                or NULL if Bad Allocation
*/
{
XW_EXT_IMAGEDATA *pimage ;
//int i ;

	pimage = (XW_EXT_IMAGEDATA*) Xw_malloc(size) ;

        if( pimage ) {
	    pimage->type = IMAGE_TYPE ;
	    pimage->link = PimageList ;
	    PimageList = pimage ;
	    pimage->pcolormap = NULL ;
	    pimage->zoom = 1.;
            pimage->pximage = NULL ;
            pimage->zximage = NULL ;
	    pimage->maxwindow = 0 ;
        } else {
	    /*ERROR*EXT_IMAGE allocation failed*/
	    Xw_set_error(27,"Xw_open_image",0) ;
        }

        return (pimage) ;
}

#ifdef XW_PROTOTYPE
XW_STATUS Xw_close_image (void* aimage)
#else
XW_STATUS Xw_close_image (aimage)
void *aimage;
#endif /*XW_PROTOTYPE*/
{
XW_EXT_IMAGEDATA *pimage = (XW_EXT_IMAGEDATA*) aimage ;

        Xw_del_imagedata_structure(pimage) ;

#ifdef  TRACE_CLOSE_IMAGE
if( Xw_get_trace() ) {
        printf (" Xw_close_image(%x)\n",pimage);
}
#endif

        return (XW_SUCCESS);
}

#ifdef XW_PROTOTYPE
void* Xw_get_image_handle (void* awindow,void *aimageinfo)
#else
void* Xw_get_image_handle (awindow,aimageinfo)
void *awindow ;
void *aimageinfo ;
#endif /*XW_PROTOTYPE*/
{
#ifdef  TRACE_OPEN_IMAGE
XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ;
#endif
XW_EXT_IMAGEDATA *pimage ;

	for( pimage = PimageList ; pimage ;
			pimage = (XW_EXT_IMAGEDATA*) pimage->link ) {
            if( pimage->pimageinfo == aimageinfo ) break ;
        }

#ifdef  TRACE_OPEN_IMAGE
if( Xw_get_trace() ) {
    printf (" %lx = Xw_get_image_handle(%lx,%lx)\n",(long ) pimage,(long ) pwindow,(long ) aimageinfo);
}
#endif

	return (pimage) ;
}

#ifdef XW_PROTOTYPE
XW_STATUS Xw_del_imagedata_structure(XW_EXT_IMAGEDATA *aimage)
#else
XW_STATUS Xw_del_imagedata_structure(aimage)
XW_EXT_IMAGEDATA *aimage;
#endif /*XW_PROTOTYPE*/
/*
        Remove the Extended image address from the Extended List and
        Free the Extended Image

        returns ERROR if the image address is not Found in the list
        returns XW_SUCCESS if successful
*/
{
XW_EXT_IMAGEDATA *pimage = aimage ;
//int i ;

    if( !pimage ) return (XW_ERROR) ;

    if( pimage->maxwindow ) --pimage->maxwindow ;

    if( pimage->maxwindow ) {
	return (XW_ERROR) ;
    } else {
	if( _IIMAGE ) XDestroyImage(_IIMAGE) ;
	if( _ZIMAGE ) XDestroyImage(_ZIMAGE) ;
        if( pimage == PimageList ) {
            PimageList = (XW_EXT_IMAGEDATA*) pimage->link ;
        } else {
            for( pimage = PimageList ; pimage ;
			pimage = (XW_EXT_IMAGEDATA*) pimage->link ) {
                if( pimage->link == aimage ) {
                    pimage->link = aimage->link ;
                    break ;
                }
            }
        }
        Xw_free(aimage) ;
    }
    return (XW_SUCCESS) ;
}
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gin/v8_initializer.h"

#include "base/basictypes.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/sys_string_conversions.h"
#include "crypto/sha2.h"

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#endif  // OS_MACOSX
#include "base/path_service.h"
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

namespace gin {

namespace {

base::MemoryMappedFile* g_mapped_natives = nullptr;
base::MemoryMappedFile* g_mapped_snapshot = nullptr;

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if !defined(OS_MACOSX)
const int kV8SnapshotBasePathKey =
#if defined(OS_ANDROID)
    base::DIR_ANDROID_APP_DATA;
#elif defined(OS_POSIX)
    base::DIR_EXE;
#elif defined(OS_WIN)
    base::DIR_MODULE;
#endif  // OS_ANDROID
#endif  // !OS_MACOSX

const char kNativesFileName[] = "natives_blob.bin";
const char kSnapshotFileName[] = "snapshot_blob.bin";

void GetV8FilePaths(base::FilePath* natives_path_out,
                    base::FilePath* snapshot_path_out) {
#if !defined(OS_MACOSX)
  base::FilePath data_path;
  PathService::Get(kV8SnapshotBasePathKey, &data_path);
  DCHECK(!data_path.empty());

  *natives_path_out = data_path.AppendASCII(kNativesFileName);
  *snapshot_path_out = data_path.AppendASCII(kSnapshotFileName);
#else   // !defined(OS_MACOSX)
  base::ScopedCFTypeRef<CFStringRef> natives_file_name(
      base::SysUTF8ToCFStringRef(kNativesFileName));
  *natives_path_out =
      base::mac::PathForFrameworkBundleResource(natives_file_name);
  base::ScopedCFTypeRef<CFStringRef> snapshot_file_name(
      base::SysUTF8ToCFStringRef(kSnapshotFileName));
  *snapshot_path_out =
      base::mac::PathForFrameworkBundleResource(snapshot_file_name);
  DCHECK(!natives_path_out->empty());
  DCHECK(!snapshot_path_out->empty());
#endif  // !defined(OS_MACOSX)
}

bool MapV8Files(base::File natives_file,
                base::File snapshot_file,
                base::MemoryMappedFile::Region natives_region =
                    base::MemoryMappedFile::Region::kWholeFile,
                base::MemoryMappedFile::Region snapshot_region =
                    base::MemoryMappedFile::Region::kWholeFile) {
  g_mapped_natives = new base::MemoryMappedFile;
  if (!g_mapped_natives->IsValid()) {
    if (!g_mapped_natives->Initialize(natives_file.Pass(), natives_region)) {
      delete g_mapped_natives;
      g_mapped_natives = NULL;
      LOG(FATAL) << "Couldn't mmap v8 natives data file";
      return false;
    }
  }

  g_mapped_snapshot = new base::MemoryMappedFile;
  if (!g_mapped_snapshot->IsValid()) {
    if (!g_mapped_snapshot->Initialize(snapshot_file.Pass(), snapshot_region)) {
      delete g_mapped_snapshot;
      g_mapped_snapshot = NULL;
      LOG(ERROR) << "Couldn't mmap v8 snapshot data file";
      return false;
    }
  }

  return true;
}

#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
bool VerifyV8SnapshotFile(base::MemoryMappedFile* snapshot_file,
                          const unsigned char* fingerprint) {
  unsigned char output[crypto::kSHA256Length];
  crypto::SHA256HashString(
      base::StringPiece(reinterpret_cast<const char*>(snapshot_file->data()),
                        snapshot_file->length()),
      output, sizeof(output));
  return !memcmp(fingerprint, output, sizeof(output));
}
#endif  // V8_VERIFY_EXTERNAL_STARTUP_DATA
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

bool GenerateEntropy(unsigned char* buffer, size_t amount) {
  base::RandBytes(buffer, amount);
  return true;
}

}  // namespace

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
// Defined in gen/gin/v8_snapshot_fingerprint.cc
extern const unsigned char g_natives_fingerprint[];
extern const unsigned char g_snapshot_fingerprint[];
#endif  // V8_VERIFY_EXTERNAL_STARTUP_DATA

// static
bool V8Initializer::LoadV8Snapshot() {
  if (g_mapped_natives && g_mapped_snapshot)
    return true;

  base::FilePath natives_data_path;
  base::FilePath snapshot_data_path;
  GetV8FilePaths(&natives_data_path, &snapshot_data_path);

  int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
  if (!MapV8Files(base::File(natives_data_path, flags),
                  base::File(snapshot_data_path, flags)))
    return false;

#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
  return VerifyV8SnapshotFile(g_mapped_natives, g_natives_fingerprint) &&
         VerifyV8SnapshotFile(g_mapped_snapshot, g_snapshot_fingerprint);
#else
  return true;
#endif  // V8_VERIFY_EXTERNAL_STARTUP_DATA
}

// static
bool V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile natives_pf,
                                         int64 natives_offset,
                                         int64 natives_size,
                                         base::PlatformFile snapshot_pf,
                                         int64 snapshot_offset,
                                         int64 snapshot_size) {
  if (g_mapped_natives && g_mapped_snapshot)
    return true;

  base::MemoryMappedFile::Region natives_region =
      base::MemoryMappedFile::Region::kWholeFile;
  if (natives_size != 0 || natives_offset != 0) {
    natives_region =
        base::MemoryMappedFile::Region(natives_offset, natives_size);
  }

  base::MemoryMappedFile::Region snapshot_region =
      base::MemoryMappedFile::Region::kWholeFile;
  if (natives_size != 0 || natives_offset != 0) {
    snapshot_region =
        base::MemoryMappedFile::Region(snapshot_offset, snapshot_size);
  }

  return MapV8Files(base::File(natives_pf), base::File(snapshot_pf),
                    natives_region, snapshot_region);
}

// static
bool V8Initializer::OpenV8FilesForChildProcesses(
    base::PlatformFile* natives_fd_out,
    base::PlatformFile* snapshot_fd_out) {
  base::FilePath natives_data_path;
  base::FilePath snapshot_data_path;
  GetV8FilePaths(&natives_data_path, &snapshot_data_path);

  int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
  base::File natives_data_file(natives_data_path, file_flags);
  base::File snapshot_data_file(snapshot_data_path, file_flags);

  if (!natives_data_file.IsValid() || !snapshot_data_file.IsValid())
    return false;

  *natives_fd_out = natives_data_file.TakePlatformFile();
  *snapshot_fd_out = snapshot_data_file.TakePlatformFile();
  return true;
}

#endif  // V8_USE_EXTERNAL_STARTUP_DATA

// static
void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode,
                               v8::ArrayBuffer::Allocator* allocator) {
  CHECK(allocator);

  static bool v8_is_initialized = false;
  if (v8_is_initialized)
    return;

  v8::V8::InitializePlatform(V8Platform::Get());
  v8::V8::SetArrayBufferAllocator(allocator);

  if (gin::IsolateHolder::kStrictMode == mode) {
    static const char use_strict[] = "--use_strict";
    v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1);
  }

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
  v8::StartupData natives;
  natives.data = reinterpret_cast<const char*>(g_mapped_natives->data());
  natives.raw_size = static_cast<int>(g_mapped_natives->length());
  v8::V8::SetNativesDataBlob(&natives);

  v8::StartupData snapshot;
  snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data());
  snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length());
  v8::V8::SetSnapshotDataBlob(&snapshot);
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

  v8::V8::SetEntropySource(&GenerateEntropy);
  v8::V8::Initialize();

  v8_is_initialized = true;
}

// static
void V8Initializer::GetV8ExternalSnapshotData(const char** natives_data_out,
                                              int* natives_size_out,
                                              const char** snapshot_data_out,
                                              int* snapshot_size_out) {
  if (!g_mapped_natives || !g_mapped_snapshot) {
    *natives_data_out = *snapshot_data_out = NULL;
    *natives_size_out = *snapshot_size_out = 0;
    return;
  }
  *natives_data_out = reinterpret_cast<const char*>(g_mapped_natives->data());
  *snapshot_data_out = reinterpret_cast<const char*>(g_mapped_snapshot->data());
  *natives_size_out = static_cast<int>(g_mapped_natives->length());
  *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length());
}

}  // namespace gin
<commit_msg>Add additional checks to help diagnose issue 479537.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gin/v8_initializer.h"

#include "base/basictypes.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/sys_string_conversions.h"
#include "crypto/sha2.h"

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#endif  // OS_MACOSX
#include "base/path_service.h"
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

namespace gin {

namespace {

base::MemoryMappedFile* g_mapped_natives = nullptr;
base::MemoryMappedFile* g_mapped_snapshot = nullptr;

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if !defined(OS_MACOSX)
const int kV8SnapshotBasePathKey =
#if defined(OS_ANDROID)
    base::DIR_ANDROID_APP_DATA;
#elif defined(OS_POSIX)
    base::DIR_EXE;
#elif defined(OS_WIN)
    base::DIR_MODULE;
#endif  // OS_ANDROID
#endif  // !OS_MACOSX

const char kNativesFileName[] = "natives_blob.bin";
const char kSnapshotFileName[] = "snapshot_blob.bin";

void GetV8FilePaths(base::FilePath* natives_path_out,
                    base::FilePath* snapshot_path_out) {
#if !defined(OS_MACOSX)
  base::FilePath data_path;
  PathService::Get(kV8SnapshotBasePathKey, &data_path);
  DCHECK(!data_path.empty());

  *natives_path_out = data_path.AppendASCII(kNativesFileName);
  *snapshot_path_out = data_path.AppendASCII(kSnapshotFileName);
#else   // !defined(OS_MACOSX)
  base::ScopedCFTypeRef<CFStringRef> natives_file_name(
      base::SysUTF8ToCFStringRef(kNativesFileName));
  *natives_path_out =
      base::mac::PathForFrameworkBundleResource(natives_file_name);
  base::ScopedCFTypeRef<CFStringRef> snapshot_file_name(
      base::SysUTF8ToCFStringRef(kSnapshotFileName));
  *snapshot_path_out =
      base::mac::PathForFrameworkBundleResource(snapshot_file_name);
  DCHECK(!natives_path_out->empty());
  DCHECK(!snapshot_path_out->empty());
#endif  // !defined(OS_MACOSX)
}

bool MapV8Files(base::File natives_file,
                base::File snapshot_file,
                base::MemoryMappedFile::Region natives_region =
                    base::MemoryMappedFile::Region::kWholeFile,
                base::MemoryMappedFile::Region snapshot_region =
                    base::MemoryMappedFile::Region::kWholeFile) {
  g_mapped_natives = new base::MemoryMappedFile;
  if (!g_mapped_natives->IsValid()) {
    if (!g_mapped_natives->Initialize(natives_file.Pass(), natives_region)) {
      delete g_mapped_natives;
      g_mapped_natives = NULL;
      LOG(FATAL) << "Couldn't mmap v8 natives data file";
      return false;
    }
  }

  g_mapped_snapshot = new base::MemoryMappedFile;
  if (!g_mapped_snapshot->IsValid()) {
    if (!g_mapped_snapshot->Initialize(snapshot_file.Pass(), snapshot_region)) {
      delete g_mapped_snapshot;
      g_mapped_snapshot = NULL;
      LOG(ERROR) << "Couldn't mmap v8 snapshot data file";
      return false;
    }
  }

  return true;
}

#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
bool VerifyV8SnapshotFile(base::MemoryMappedFile* snapshot_file,
                          const unsigned char* fingerprint) {
  unsigned char output[crypto::kSHA256Length];
  crypto::SHA256HashString(
      base::StringPiece(reinterpret_cast<const char*>(snapshot_file->data()),
                        snapshot_file->length()),
      output, sizeof(output));
  return !memcmp(fingerprint, output, sizeof(output));
}
#endif  // V8_VERIFY_EXTERNAL_STARTUP_DATA
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

bool GenerateEntropy(unsigned char* buffer, size_t amount) {
  base::RandBytes(buffer, amount);
  return true;
}

}  // namespace

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
// Defined in gen/gin/v8_snapshot_fingerprint.cc
extern const unsigned char g_natives_fingerprint[];
extern const unsigned char g_snapshot_fingerprint[];
#endif  // V8_VERIFY_EXTERNAL_STARTUP_DATA

// static
bool V8Initializer::LoadV8Snapshot() {
  if (g_mapped_natives && g_mapped_snapshot)
    return true;

  base::FilePath natives_data_path;
  base::FilePath snapshot_data_path;
  GetV8FilePaths(&natives_data_path, &snapshot_data_path);

  int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
  if (!MapV8Files(base::File(natives_data_path, flags),
                  base::File(snapshot_data_path, flags)))
    return false;

#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
  // TODO(oth) Remove these temporary CHECKs once http://crbug.com/479537 is
  // fixed. These are just here to identify whether canary failures are
  // due to verification or file/vm failures.
  bool natives_ok =
      VerifyV8SnapshotFile(g_mapped_natives, g_natives_fingerprint);
  CHECK(natives_ok);
  bool snapshot_ok =
      VerifyV8SnapshotFile(g_mapped_snapshot, g_snapshot_fingerprint);
  CHECK(snapshot_ok);
  return natives_ok && snapshot_ok;
#else
  return true;
#endif  // V8_VERIFY_EXTERNAL_STARTUP_DATA
}

// static
bool V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile natives_pf,
                                         int64 natives_offset,
                                         int64 natives_size,
                                         base::PlatformFile snapshot_pf,
                                         int64 snapshot_offset,
                                         int64 snapshot_size) {
  if (g_mapped_natives && g_mapped_snapshot)
    return true;

  base::MemoryMappedFile::Region natives_region =
      base::MemoryMappedFile::Region::kWholeFile;
  if (natives_size != 0 || natives_offset != 0) {
    natives_region =
        base::MemoryMappedFile::Region(natives_offset, natives_size);
  }

  base::MemoryMappedFile::Region snapshot_region =
      base::MemoryMappedFile::Region::kWholeFile;
  if (natives_size != 0 || natives_offset != 0) {
    snapshot_region =
        base::MemoryMappedFile::Region(snapshot_offset, snapshot_size);
  }

  return MapV8Files(base::File(natives_pf), base::File(snapshot_pf),
                    natives_region, snapshot_region);
}

// static
bool V8Initializer::OpenV8FilesForChildProcesses(
    base::PlatformFile* natives_fd_out,
    base::PlatformFile* snapshot_fd_out) {
  base::FilePath natives_data_path;
  base::FilePath snapshot_data_path;
  GetV8FilePaths(&natives_data_path, &snapshot_data_path);

  int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
  base::File natives_data_file(natives_data_path, file_flags);
  base::File snapshot_data_file(snapshot_data_path, file_flags);

  if (!natives_data_file.IsValid() || !snapshot_data_file.IsValid())
    return false;

  *natives_fd_out = natives_data_file.TakePlatformFile();
  *snapshot_fd_out = snapshot_data_file.TakePlatformFile();
  return true;
}

#endif  // V8_USE_EXTERNAL_STARTUP_DATA

// static
void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode,
                               v8::ArrayBuffer::Allocator* allocator) {
  CHECK(allocator);

  static bool v8_is_initialized = false;
  if (v8_is_initialized)
    return;

  v8::V8::InitializePlatform(V8Platform::Get());
  v8::V8::SetArrayBufferAllocator(allocator);

  if (gin::IsolateHolder::kStrictMode == mode) {
    static const char use_strict[] = "--use_strict";
    v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1);
  }

#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
  v8::StartupData natives;
  natives.data = reinterpret_cast<const char*>(g_mapped_natives->data());
  natives.raw_size = static_cast<int>(g_mapped_natives->length());
  v8::V8::SetNativesDataBlob(&natives);

  v8::StartupData snapshot;
  snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data());
  snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length());
  v8::V8::SetSnapshotDataBlob(&snapshot);
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

  v8::V8::SetEntropySource(&GenerateEntropy);
  v8::V8::Initialize();

  v8_is_initialized = true;
}

// static
void V8Initializer::GetV8ExternalSnapshotData(const char** natives_data_out,
                                              int* natives_size_out,
                                              const char** snapshot_data_out,
                                              int* snapshot_size_out) {
  if (!g_mapped_natives || !g_mapped_snapshot) {
    *natives_data_out = *snapshot_data_out = NULL;
    *natives_size_out = *snapshot_size_out = 0;
    return;
  }
  *natives_data_out = reinterpret_cast<const char*>(g_mapped_natives->data());
  *snapshot_data_out = reinterpret_cast<const char*>(g_mapped_snapshot->data());
  *natives_size_out = static_cast<int>(g_mapped_natives->length());
  *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length());
}

}  // namespace gin
<|endoftext|>