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

#include <mozart.hh>
#include <boostenv.hh>

#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/program_options.hpp>

using namespace mozart;
namespace fs = boost::filesystem;
namespace po = boost::program_options;

std::string envVarToOptionName(const std::string& varName) {
  if ((varName == "OZ_HOME") || (varName == "OZHOME"))
    return "home";
  else
    return "";
}

atom_t strToAtom(VM vm, const std::string& str) {
  auto mozartStr = toUTF<nchar>(makeLString(str.c_str(), str.size()));
  return vm->getAtom(mozartStr.length, mozartStr.string);
}

atom_t pathToAtom(VM vm, const fs::path& path) {
  return strToAtom(vm, path.native());
}

int main(int argc, char** argv) {
  // CONFIGURATION VARIABLES

  fs::path ozHome, initFunctorPath, baseFunctorPath;
  std::string ozSearchPath, ozSearchLoad, appURL;
  std::vector<std::string> appArgs;
  bool appGUI;

  // DEFINE OPTIONS

  po::options_description generic("Generic options");
  generic.add_options()
    ("help", "produce help message");

  po::options_description config("Configuration");
  config.add_options()
    ("home", po::value<fs::path>(&ozHome),
      "path to the home of the installation")
    ("init", po::value<fs::path>(&initFunctorPath),
      "path to the Init.ozf functor")
    ("search-path", po::value<std::string>(&ozSearchPath),
      "search path")
    ("search-load", po::value<std::string>(&ozSearchLoad),
      "search load")
    ("gui", "GUI mode");

  po::options_description hidden("Hidden options");
  hidden.add_options()
    ("base", po::value<fs::path>(&baseFunctorPath),
      "path to the Base.ozf functor")
    ("app-url", po::value<std::string>(&appURL),
      "application URL")
    ("app-args", po::value<std::vector<std::string>>(&appArgs),
      "application arguments");

  po::options_description cmdline_options;
  cmdline_options.add(generic).add(config).add(hidden);

  po::options_description environment_options;
  environment_options.add(config);

  po::options_description visible_options("Allowed options");
  visible_options.add(generic).add(config);

  po::positional_options_description positional_options;
  positional_options.add("app-url", 1);
  positional_options.add("app-args", -1);

  // PARSE OPTIONS

  po::variables_map varMap;
  po::store(po::command_line_parser(argc, argv)
              .options(cmdline_options)
              .positional(positional_options)
              .run(),
            varMap);
  po::store(po::parse_environment(environment_options, &envVarToOptionName),
            varMap);
  po::notify(varMap);

  // READ OPTIONS

  if (varMap.count("help") != 0) {
    std::cout << visible_options << "\n";
    return 0;
  }

  // Hacky way to guess if we are in a build setting
  fs::path appPath = fs::path(argv[0]).parent_path();
  bool isBuildSetting = appPath.filename() == "emulator";

  if (ozHome.empty()) {
    if (isBuildSetting)
      ozHome = appPath.parent_path().parent_path();
    else
      ozHome = appPath.parent_path();

    if (ozHome.empty())
      ozHome = ".";
  }

  if (initFunctorPath.empty()) {
    if (isBuildSetting)
      initFunctorPath = ozHome / "lib" / "cache" / "Init.ozf";
    else
      initFunctorPath = ozHome / "share" / "mozart" / "cache" / "Init.ozf";
  }

  bool useBaseFunctor = varMap.count("base") != 0;

  appGUI = varMap.count("gui") != 0;

  // SET UP THE VM AND RUN

  boostenv::BoostBasedVM boostBasedVM;
  VM vm = boostBasedVM.vm;

  // Set some properties
  {
    auto& properties = vm->getPropertyRegistry();

    atom_t ozHomeAtom = pathToAtom(vm, ozHome);
    properties.registerValueProp(
      vm, MOZART_STR("oz.home"), ozHomeAtom);
    properties.registerValueProp(
      vm, MOZART_STR("oz.emulator.home"), ozHomeAtom);
    properties.registerValueProp(
      vm, MOZART_STR("oz.configure.home"), ozHomeAtom);

    if (varMap.count("search-path") != 0)
      properties.registerValueProp(
        vm, MOZART_STR("oz.search.path"), strToAtom(vm, ozSearchPath));
    if (varMap.count("search-load") != 0)
      properties.registerValueProp(
        vm, MOZART_STR("oz.search.load"), strToAtom(vm, ozSearchLoad));

    auto decodedURL = toUTF<nchar>(makeLString(appURL.c_str()));
    auto appURLAtom = vm->getAtom(decodedURL.length, decodedURL.string);
    properties.registerValueProp(
      vm, MOZART_STR("application.url"), appURLAtom);

    OzListBuilder argsBuilder(vm);
    for (auto& arg: appArgs) {
      auto decodedArg = toUTF<nchar>(makeLString(arg.c_str()));
      argsBuilder.push_back(vm, vm->getAtom(decodedArg.length, decodedArg.string));
    }
    properties.registerValueProp(
      vm, MOZART_STR("application.args"), argsBuilder.get(vm));

    properties.registerValueProp(
      vm, MOZART_STR("application.gui"), appGUI);
  }

  // Some protected nodes
  ProtectedNode baseEnv, initFunctor;

  // Load the Base environment if required
  if (useBaseFunctor) {
    baseEnv = vm->protect(OptVar::build(vm));

    UnstableNode baseValue;
    auto& bootLoader = boostBasedVM.getBootLoader();

    if (!bootLoader(vm, baseFunctorPath.native(), baseValue)) {
      std::cerr << "panic: could not load Base functor at "
                << baseFunctorPath << std::endl;
      return 1;
    }

    // Create the thread that loads the Base environment
    if (Callable(baseValue).isProcedure(vm)) {
      ozcalls::asyncOzCall(vm, baseValue, *baseEnv);
    } else {
      // Assume it is a functor that does not import anything
      UnstableNode applyAtom = build(vm, MOZART_STR("apply"));
      UnstableNode applyProc = Dottable(baseValue).dot(vm, applyAtom);
      UnstableNode importParam = build(vm, MOZART_STR("import"));
      ozcalls::asyncOzCall(vm, applyProc, importParam, *baseEnv);
    }

    boostBasedVM.run();
  }

  // Load the Init functor
  {
    initFunctor = vm->protect(OptVar::build(vm));

    UnstableNode initValue;
    auto& bootLoader = boostBasedVM.getBootLoader();

    if (!bootLoader(vm, initFunctorPath.native(), initValue)) {
      std::cerr << "panic: could not load Init functor at "
                << initFunctorPath << std::endl;
      return 1;
    }

    // Create the thread that loads the Init functor
    if (Callable(initValue).isProcedure(vm)) {
      if (!useBaseFunctor) {
        std::cerr << "panic: Init.ozf is a procedure, "
                  << "but I have no Base to give to it" << std::endl;
        return 1;
      }

      ozcalls::asyncOzCall(vm, initValue, *baseEnv, *initFunctor);
      boostBasedVM.run();
    } else {
      // Assume it is already the Init functor
      DataflowVariable(*initFunctor).bind(vm, initValue);
    }
  }

  // Apply the Init functor
  {
    auto ApplyAtom = build(vm, MOZART_STR("apply"));
    auto ApplyProc = Dottable(*initFunctor).dot(vm, ApplyAtom);

    auto BootModule = vm->findBuiltinModule(MOZART_STR("Boot"));
    auto ImportRecord = buildRecord(
      vm, buildArity(vm, MOZART_STR("import"), MOZART_STR("Boot")),
      BootModule);

    ozcalls::asyncOzCall(vm, ApplyProc, ImportRecord, OptVar::build(vm));

    baseEnv.reset();
    initFunctor.reset();

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

#include <mozart.hh>
#include <boostenv.hh>

#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/program_options.hpp>

using namespace mozart;
namespace fs = boost::filesystem;
namespace po = boost::program_options;

std::string envVarToOptionName(const std::string& varName) {
  if (varName == "OZ_HOME")
    return "home";
  else
    return "";
}

std::string envVarToOptionNameFallback(const std::string& varName) {
  if (varName == "OZHOME")
    return "home";
  else
    return "";
}

atom_t strToAtom(VM vm, const std::string& str) {
  auto mozartStr = toUTF<nchar>(makeLString(str.c_str(), str.size()));
  return vm->getAtom(mozartStr.length, mozartStr.string);
}

atom_t pathToAtom(VM vm, const fs::path& path) {
  return strToAtom(vm, path.native());
}

int main(int argc, char** argv) {
  // CONFIGURATION VARIABLES

  fs::path ozHome, initFunctorPath, baseFunctorPath;
  std::string ozSearchPath, ozSearchLoad, appURL;
  std::vector<std::string> appArgs;
  bool appGUI;

  // DEFINE OPTIONS

  po::options_description generic("Generic options");
  generic.add_options()
    ("help", "produce help message");

  po::options_description config("Configuration");
  config.add_options()
    ("home", po::value<fs::path>(&ozHome),
      "path to the home of the installation")
    ("init", po::value<fs::path>(&initFunctorPath),
      "path to the Init.ozf functor")
    ("search-path", po::value<std::string>(&ozSearchPath),
      "search path")
    ("search-load", po::value<std::string>(&ozSearchLoad),
      "search load")
    ("gui", "GUI mode");

  po::options_description hidden("Hidden options");
  hidden.add_options()
    ("base", po::value<fs::path>(&baseFunctorPath),
      "path to the Base.ozf functor")
    ("app-url", po::value<std::string>(&appURL),
      "application URL")
    ("app-args", po::value<std::vector<std::string>>(&appArgs),
      "application arguments");

  po::options_description cmdline_options;
  cmdline_options.add(generic).add(config).add(hidden);

  po::options_description environment_options;
  environment_options.add(config);

  po::options_description visible_options("Allowed options");
  visible_options.add(generic).add(config);

  po::positional_options_description positional_options;
  positional_options.add("app-url", 1);
  positional_options.add("app-args", -1);

  // PARSE OPTIONS

  po::variables_map varMap;
  po::store(po::command_line_parser(argc, argv)
              .options(cmdline_options)
              .positional(positional_options)
              .run(),
            varMap);
  po::store(po::parse_environment(environment_options,
                                  &envVarToOptionName),
            varMap);
  po::store(po::parse_environment(environment_options,
                                  &envVarToOptionNameFallback),
            varMap);
  po::notify(varMap);

  // READ OPTIONS

  if (varMap.count("help") != 0) {
    std::cout << visible_options << "\n";
    return 0;
  }

  // Hacky way to guess if we are in a build setting
  fs::path appPath = fs::path(argv[0]).parent_path();
  bool isBuildSetting = appPath.filename() == "emulator";

  if (ozHome.empty()) {
    if (isBuildSetting)
      ozHome = appPath.parent_path().parent_path();
    else
      ozHome = appPath.parent_path();

    if (ozHome.empty())
      ozHome = ".";
  }

  if (initFunctorPath.empty()) {
    if (isBuildSetting)
      initFunctorPath = ozHome / "lib" / "cache" / "Init.ozf";
    else
      initFunctorPath = ozHome / "share" / "mozart" / "cache" / "Init.ozf";
  }

  bool useBaseFunctor = varMap.count("base") != 0;

  appGUI = varMap.count("gui") != 0;

  // SET UP THE VM AND RUN

  boostenv::BoostBasedVM boostBasedVM;
  VM vm = boostBasedVM.vm;

  // Set some properties
  {
    auto& properties = vm->getPropertyRegistry();

    atom_t ozHomeAtom = pathToAtom(vm, ozHome);
    properties.registerValueProp(
      vm, MOZART_STR("oz.home"), ozHomeAtom);
    properties.registerValueProp(
      vm, MOZART_STR("oz.emulator.home"), ozHomeAtom);
    properties.registerValueProp(
      vm, MOZART_STR("oz.configure.home"), ozHomeAtom);

    if (varMap.count("search-path") != 0)
      properties.registerValueProp(
        vm, MOZART_STR("oz.search.path"), strToAtom(vm, ozSearchPath));
    if (varMap.count("search-load") != 0)
      properties.registerValueProp(
        vm, MOZART_STR("oz.search.load"), strToAtom(vm, ozSearchLoad));

    auto decodedURL = toUTF<nchar>(makeLString(appURL.c_str()));
    auto appURLAtom = vm->getAtom(decodedURL.length, decodedURL.string);
    properties.registerValueProp(
      vm, MOZART_STR("application.url"), appURLAtom);

    OzListBuilder argsBuilder(vm);
    for (auto& arg: appArgs) {
      auto decodedArg = toUTF<nchar>(makeLString(arg.c_str()));
      argsBuilder.push_back(vm, vm->getAtom(decodedArg.length, decodedArg.string));
    }
    properties.registerValueProp(
      vm, MOZART_STR("application.args"), argsBuilder.get(vm));

    properties.registerValueProp(
      vm, MOZART_STR("application.gui"), appGUI);
  }

  // Some protected nodes
  ProtectedNode baseEnv, initFunctor;

  // Load the Base environment if required
  if (useBaseFunctor) {
    baseEnv = vm->protect(OptVar::build(vm));

    UnstableNode baseValue;
    auto& bootLoader = boostBasedVM.getBootLoader();

    if (!bootLoader(vm, baseFunctorPath.native(), baseValue)) {
      std::cerr << "panic: could not load Base functor at "
                << baseFunctorPath << std::endl;
      return 1;
    }

    // Create the thread that loads the Base environment
    if (Callable(baseValue).isProcedure(vm)) {
      ozcalls::asyncOzCall(vm, baseValue, *baseEnv);
    } else {
      // Assume it is a functor that does not import anything
      UnstableNode applyAtom = build(vm, MOZART_STR("apply"));
      UnstableNode applyProc = Dottable(baseValue).dot(vm, applyAtom);
      UnstableNode importParam = build(vm, MOZART_STR("import"));
      ozcalls::asyncOzCall(vm, applyProc, importParam, *baseEnv);
    }

    boostBasedVM.run();
  }

  // Load the Init functor
  {
    initFunctor = vm->protect(OptVar::build(vm));

    UnstableNode initValue;
    auto& bootLoader = boostBasedVM.getBootLoader();

    if (!bootLoader(vm, initFunctorPath.native(), initValue)) {
      std::cerr << "panic: could not load Init functor at "
                << initFunctorPath << std::endl;
      return 1;
    }

    // Create the thread that loads the Init functor
    if (Callable(initValue).isProcedure(vm)) {
      if (!useBaseFunctor) {
        std::cerr << "panic: Init.ozf is a procedure, "
                  << "but I have no Base to give to it" << std::endl;
        return 1;
      }

      ozcalls::asyncOzCall(vm, initValue, *baseEnv, *initFunctor);
      boostBasedVM.run();
    } else {
      // Assume it is already the Init functor
      DataflowVariable(*initFunctor).bind(vm, initValue);
    }
  }

  // Apply the Init functor
  {
    auto ApplyAtom = build(vm, MOZART_STR("apply"));
    auto ApplyProc = Dottable(*initFunctor).dot(vm, ApplyAtom);

    auto BootModule = vm->findBuiltinModule(MOZART_STR("Boot"));
    auto ImportRecord = buildRecord(
      vm, buildArity(vm, MOZART_STR("import"), MOZART_STR("Boot")),
      BootModule);

    ozcalls::asyncOzCall(vm, ApplyProc, ImportRecord, OptVar::build(vm));

    baseEnv.reset();
    initFunctor.reset();

    boostBasedVM.run();
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: line.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 14:21:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#define _LINE_CXX

#ifndef _LINK_HXX
#include <link.hxx>
#endif

#ifndef _LINE_HXX
#include <line.hxx>
#endif

#ifndef _DEBUG_HXX
#include <debug.hxx>
#endif

#include <cstdlib>
#include <cmath>

inline long FRound( double fVal )
{
    return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
}

// --------
// - Line -
// --------

double Line::GetLength() const
{
    return hypot( maStart.X() - maEnd.X(), maStart.Y() - maEnd.Y() );
}

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

BOOL Line::Intersection( const Line& rLine, Point& rIntersection ) const
{
    double  fX, fY;
    BOOL    bRet;

    if( Intersection( rLine, fX, fY ) )
    {
        rIntersection.X() = FRound( fX );
        rIntersection.Y() = FRound( fY );
        bRet = TRUE;
    }
    else
        bRet = FALSE;

    return bRet;
}

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

BOOL Line::Intersection( const Line& rLine, double& rIntersectionX, double& rIntersectionY ) const
{
    const double    fAx = maEnd.X() - maStart.X();
    const double    fAy = maEnd.Y() - maStart.Y();
    const double    fBx = rLine.maStart.X() - rLine.maEnd.X();
    const double    fBy = rLine.maStart.Y() - rLine.maEnd.Y();
    const double    fDen = fAy * fBx - fAx * fBy;
    BOOL            bOk = FALSE;

    if( fDen != 0. )
    {
        const double    fCx = maStart.X() - rLine.maStart.X();
        const double    fCy = maStart.Y() - rLine.maStart.Y();
        const double    fA = fBy * fCx - fBx * fCy;
        const BOOL      bGreater = ( fDen > 0. );

        bOk = TRUE;

        if ( bGreater )
        {
            if ( ( fA < 0. ) || ( fA > fDen ) )
                bOk = FALSE;
        }
        else if ( ( fA > 0. ) || ( fA < fDen ) )
            bOk = FALSE;

        if ( bOk )
        {
            const double fB = fAx * fCy - fAy * fCx;

            if ( bGreater )
            {
                if ( ( fB < 0. ) || ( fB > fDen ) )
                    bOk = FALSE;
            }
            else if ( ( fB > 0. ) || ( fB < fDen ) )
                bOk = FALSE;

            if( bOk )
            {
                const double fAlpha = fA / fDen;

                rIntersectionX = ( maStart.X() + fAlpha * fAx );
                rIntersectionY = ( maStart.Y() + fAlpha * fAy );
            }
        }
    }

    return bOk;
}

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

BOOL Line::Intersection( const Rectangle& rRect, Line& rIntersection ) const
{
    const BOOL  bStartInside = rRect.IsInside( maStart );
    const BOOL  bEndInside = rRect.IsInside( maEnd );
    BOOL        bRet = TRUE;

    if( bStartInside && bEndInside )
    {
        // line completely inside rect
        rIntersection.maStart = maStart;
        rIntersection.maEnd = maEnd;
    }
    else
    {
        // calculate intersections
        const Point aTL( rRect.TopLeft() ), aTR( rRect.TopRight() );
        const Point aBR( rRect.BottomRight() ), aBL( rRect.BottomLeft() );
        Point       aIntersect1, aIntersect2;
        Point*      pCurIntersection = &aIntersect1;

        if( Intersection( Line( aTL, aTR ), *pCurIntersection ) )
            pCurIntersection = &aIntersect2;

        if( Intersection( Line( aTR, aBR ), *pCurIntersection ) )
            pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;

        if( pCurIntersection && Intersection( Line( aBR, aBL ), *pCurIntersection ) )
            pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;

        if( pCurIntersection && Intersection( Line( aBL, aTL ), *pCurIntersection ) )
            pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;

        if( !pCurIntersection )
        {
            // two intersections
            rIntersection.maStart = aIntersect1;
            rIntersection.maEnd = aIntersect2;
        }
        else if( pCurIntersection == &aIntersect2 )
        {
            // one intersection
            rIntersection.maStart = aIntersect1;

            if( ( maStart != aIntersect1 ) && bStartInside )
                rIntersection.maEnd = maStart;
            else if( ( maEnd != aIntersect1 ) && bEndInside )
                rIntersection.maEnd = maEnd;
            else
                rIntersection.maEnd = rIntersection.maStart;
        }
        else
            bRet = FALSE;
    }

    return bRet;
}

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

Point Line::NearestPoint( const Point& rPoint ) const
{
    Point aRetPt;

    if ( maStart != maEnd )
    {
        const double    fDistX = maEnd.X() - maStart.X();
        const double    fDistY = maStart.Y() - maEnd.Y();
        const double    fTau = ( ( maStart.Y() - rPoint.Y() ) * fDistY -
                                 ( maStart.X() - rPoint.X() ) * fDistX ) /
                               ( fDistX * fDistX + fDistY * fDistY );

        if( fTau < 0.0 )
            aRetPt = maStart;
        else if( fTau <= 1.0 )
        {
            aRetPt.X() = FRound( maStart.X() + fTau * fDistX );
            aRetPt.Y() = FRound( maStart.Y() - fTau * fDistY );
        }
        else
            aRetPt = maEnd;
    }
    else
        aRetPt = maStart;

    return aRetPt;
}

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

double Line::GetDistance( const double& rPtX, const double& rPtY ) const
{
    double fDist;

    if( maStart != maEnd )
    {
        const double    fDistX = maEnd.X() - maStart.X();
        const double    fDistY = maEnd.Y() - maStart.Y();
        const double    fACX = maStart.X() - rPtX;
        const double    fACY = maStart.Y() - rPtY;
        const double    fL2 = fDistX * fDistX + fDistY * fDistY;
        const double    fR = ( fACY * -fDistY - fACX * fDistX ) / fL2;
        const double    fS = ( fACY * fDistX - fACX * fDistY ) / fL2;

        if( fR < 0.0 )
        {
            fDist = hypot( maStart.X() - rPtX, maStart.Y() - rPtY );

            if( fS < 0.0 )
                fDist *= -1.0;
        }
        else if( fR <= 1.0 )
            fDist = fS * sqrt( fL2 );
        else
        {
            fDist = hypot( maEnd.X() - rPtX, maEnd.Y() - rPtY );

            if( fS < 0.0 )
                fDist *= -1.0;
        }
    }
    else
        fDist = hypot( maStart.X() - rPtX, maStart.Y() - rPtY );

    return fDist;
}

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

void Line::Enum( const Link& rEnumLink )
{
    DBG_ASSERT( rEnumLink.IsSet(), "This call doesn't make any sense with !rEnumLink.IsSet()" );

    Point   aEnum;
    long    nX;
    long    nY;

    if( maStart.X() == maEnd.X() )
    {
        const long nEndY = maEnd.Y();

        nX = maStart.X();
        nY = maStart.Y();

        if( nEndY > nY )
        {
            while( nY <= nEndY )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY++;
                rEnumLink.Call( &aEnum );
            }
        }
        else
        {
            while( nY >= nEndY )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY--;
                rEnumLink.Call( &aEnum );
            }
        }
    }
    else if( maStart.Y() == maEnd.Y() )
    {
        const long nEndX = maEnd.X();

        nX = maStart.X();
        nY = maStart.Y();

        if( nEndX > nX )
        {
            while( nX <= nEndX )
            {
                aEnum.X() = nX++;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );
            }
        }
        else
        {
            while( nX >= nEndX )
            {
                aEnum.X() = nX--;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );
            }
        }
    }
    else
    {
        const long  nDX = labs( maEnd.X() - maStart.X() );
        const long  nDY = labs( maEnd.Y() - maStart.Y() );
        const long  nStartX = maStart.X();
        const long  nStartY = maStart.Y();
        const long  nEndX = maEnd.X();
        const long  nEndY = maEnd.Y();
        const long  nXInc = ( nStartX < nEndX ) ? 1L : -1L;
        const long  nYInc = ( nStartY < nEndY ) ? 1L : -1L;

        if( nDX >= nDY )
        {
            const long  nDYX = ( nDY - nDX ) << 1;
            const long  nDY2 = nDY << 1;
            long        nD = nDY2 - nDX;

            for( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );

                if( nD < 0L )
                    nD += nDY2;
                else
                    nD += nDYX, nY += nYInc;
            }
        }
        else
        {
            const long  nDYX = ( nDX - nDY ) << 1;
            const long  nDY2 = nDX << 1;
            long        nD = nDY2 - nDY;

            for( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );

                if( nD < 0L )
                    nD += nDY2;
                else
                    nD += nDYX, nX += nXInc;
            }
        }

        // last point
        aEnum.X() = nEndX;
        aEnum.Y() = nEndY;
        rEnumLink.Call( &aEnum );
    }
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.3.120); FILE MERGED 2006/09/01 17:54:52 kaib 1.3.120.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: line.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:56:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#define _LINE_CXX

#ifndef _LINK_HXX
#include <link.hxx>
#endif

#ifndef _LINE_HXX
#include <line.hxx>
#endif

#ifndef _DEBUG_HXX
#include <debug.hxx>
#endif

#include <cstdlib>
#include <cmath>

inline long FRound( double fVal )
{
    return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
}

// --------
// - Line -
// --------

double Line::GetLength() const
{
    return hypot( maStart.X() - maEnd.X(), maStart.Y() - maEnd.Y() );
}

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

BOOL Line::Intersection( const Line& rLine, Point& rIntersection ) const
{
    double  fX, fY;
    BOOL    bRet;

    if( Intersection( rLine, fX, fY ) )
    {
        rIntersection.X() = FRound( fX );
        rIntersection.Y() = FRound( fY );
        bRet = TRUE;
    }
    else
        bRet = FALSE;

    return bRet;
}

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

BOOL Line::Intersection( const Line& rLine, double& rIntersectionX, double& rIntersectionY ) const
{
    const double    fAx = maEnd.X() - maStart.X();
    const double    fAy = maEnd.Y() - maStart.Y();
    const double    fBx = rLine.maStart.X() - rLine.maEnd.X();
    const double    fBy = rLine.maStart.Y() - rLine.maEnd.Y();
    const double    fDen = fAy * fBx - fAx * fBy;
    BOOL            bOk = FALSE;

    if( fDen != 0. )
    {
        const double    fCx = maStart.X() - rLine.maStart.X();
        const double    fCy = maStart.Y() - rLine.maStart.Y();
        const double    fA = fBy * fCx - fBx * fCy;
        const BOOL      bGreater = ( fDen > 0. );

        bOk = TRUE;

        if ( bGreater )
        {
            if ( ( fA < 0. ) || ( fA > fDen ) )
                bOk = FALSE;
        }
        else if ( ( fA > 0. ) || ( fA < fDen ) )
            bOk = FALSE;

        if ( bOk )
        {
            const double fB = fAx * fCy - fAy * fCx;

            if ( bGreater )
            {
                if ( ( fB < 0. ) || ( fB > fDen ) )
                    bOk = FALSE;
            }
            else if ( ( fB > 0. ) || ( fB < fDen ) )
                bOk = FALSE;

            if( bOk )
            {
                const double fAlpha = fA / fDen;

                rIntersectionX = ( maStart.X() + fAlpha * fAx );
                rIntersectionY = ( maStart.Y() + fAlpha * fAy );
            }
        }
    }

    return bOk;
}

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

BOOL Line::Intersection( const Rectangle& rRect, Line& rIntersection ) const
{
    const BOOL  bStartInside = rRect.IsInside( maStart );
    const BOOL  bEndInside = rRect.IsInside( maEnd );
    BOOL        bRet = TRUE;

    if( bStartInside && bEndInside )
    {
        // line completely inside rect
        rIntersection.maStart = maStart;
        rIntersection.maEnd = maEnd;
    }
    else
    {
        // calculate intersections
        const Point aTL( rRect.TopLeft() ), aTR( rRect.TopRight() );
        const Point aBR( rRect.BottomRight() ), aBL( rRect.BottomLeft() );
        Point       aIntersect1, aIntersect2;
        Point*      pCurIntersection = &aIntersect1;

        if( Intersection( Line( aTL, aTR ), *pCurIntersection ) )
            pCurIntersection = &aIntersect2;

        if( Intersection( Line( aTR, aBR ), *pCurIntersection ) )
            pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;

        if( pCurIntersection && Intersection( Line( aBR, aBL ), *pCurIntersection ) )
            pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;

        if( pCurIntersection && Intersection( Line( aBL, aTL ), *pCurIntersection ) )
            pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;

        if( !pCurIntersection )
        {
            // two intersections
            rIntersection.maStart = aIntersect1;
            rIntersection.maEnd = aIntersect2;
        }
        else if( pCurIntersection == &aIntersect2 )
        {
            // one intersection
            rIntersection.maStart = aIntersect1;

            if( ( maStart != aIntersect1 ) && bStartInside )
                rIntersection.maEnd = maStart;
            else if( ( maEnd != aIntersect1 ) && bEndInside )
                rIntersection.maEnd = maEnd;
            else
                rIntersection.maEnd = rIntersection.maStart;
        }
        else
            bRet = FALSE;
    }

    return bRet;
}

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

Point Line::NearestPoint( const Point& rPoint ) const
{
    Point aRetPt;

    if ( maStart != maEnd )
    {
        const double    fDistX = maEnd.X() - maStart.X();
        const double    fDistY = maStart.Y() - maEnd.Y();
        const double    fTau = ( ( maStart.Y() - rPoint.Y() ) * fDistY -
                                 ( maStart.X() - rPoint.X() ) * fDistX ) /
                               ( fDistX * fDistX + fDistY * fDistY );

        if( fTau < 0.0 )
            aRetPt = maStart;
        else if( fTau <= 1.0 )
        {
            aRetPt.X() = FRound( maStart.X() + fTau * fDistX );
            aRetPt.Y() = FRound( maStart.Y() - fTau * fDistY );
        }
        else
            aRetPt = maEnd;
    }
    else
        aRetPt = maStart;

    return aRetPt;
}

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

double Line::GetDistance( const double& rPtX, const double& rPtY ) const
{
    double fDist;

    if( maStart != maEnd )
    {
        const double    fDistX = maEnd.X() - maStart.X();
        const double    fDistY = maEnd.Y() - maStart.Y();
        const double    fACX = maStart.X() - rPtX;
        const double    fACY = maStart.Y() - rPtY;
        const double    fL2 = fDistX * fDistX + fDistY * fDistY;
        const double    fR = ( fACY * -fDistY - fACX * fDistX ) / fL2;
        const double    fS = ( fACY * fDistX - fACX * fDistY ) / fL2;

        if( fR < 0.0 )
        {
            fDist = hypot( maStart.X() - rPtX, maStart.Y() - rPtY );

            if( fS < 0.0 )
                fDist *= -1.0;
        }
        else if( fR <= 1.0 )
            fDist = fS * sqrt( fL2 );
        else
        {
            fDist = hypot( maEnd.X() - rPtX, maEnd.Y() - rPtY );

            if( fS < 0.0 )
                fDist *= -1.0;
        }
    }
    else
        fDist = hypot( maStart.X() - rPtX, maStart.Y() - rPtY );

    return fDist;
}

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

void Line::Enum( const Link& rEnumLink )
{
    DBG_ASSERT( rEnumLink.IsSet(), "This call doesn't make any sense with !rEnumLink.IsSet()" );

    Point   aEnum;
    long    nX;
    long    nY;

    if( maStart.X() == maEnd.X() )
    {
        const long nEndY = maEnd.Y();

        nX = maStart.X();
        nY = maStart.Y();

        if( nEndY > nY )
        {
            while( nY <= nEndY )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY++;
                rEnumLink.Call( &aEnum );
            }
        }
        else
        {
            while( nY >= nEndY )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY--;
                rEnumLink.Call( &aEnum );
            }
        }
    }
    else if( maStart.Y() == maEnd.Y() )
    {
        const long nEndX = maEnd.X();

        nX = maStart.X();
        nY = maStart.Y();

        if( nEndX > nX )
        {
            while( nX <= nEndX )
            {
                aEnum.X() = nX++;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );
            }
        }
        else
        {
            while( nX >= nEndX )
            {
                aEnum.X() = nX--;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );
            }
        }
    }
    else
    {
        const long  nDX = labs( maEnd.X() - maStart.X() );
        const long  nDY = labs( maEnd.Y() - maStart.Y() );
        const long  nStartX = maStart.X();
        const long  nStartY = maStart.Y();
        const long  nEndX = maEnd.X();
        const long  nEndY = maEnd.Y();
        const long  nXInc = ( nStartX < nEndX ) ? 1L : -1L;
        const long  nYInc = ( nStartY < nEndY ) ? 1L : -1L;

        if( nDX >= nDY )
        {
            const long  nDYX = ( nDY - nDX ) << 1;
            const long  nDY2 = nDY << 1;
            long        nD = nDY2 - nDX;

            for( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );

                if( nD < 0L )
                    nD += nDY2;
                else
                    nD += nDYX, nY += nYInc;
            }
        }
        else
        {
            const long  nDYX = ( nDX - nDY ) << 1;
            const long  nDY2 = nDX << 1;
            long        nD = nDY2 - nDY;

            for( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
            {
                aEnum.X() = nX;
                aEnum.Y() = nY;
                rEnumLink.Call( &aEnum );

                if( nD < 0L )
                    nD += nDY2;
                else
                    nD += nDYX, nX += nXInc;
            }
        }

        // last point
        aEnum.X() = nEndX;
        aEnum.Y() = nEndY;
        rEnumLink.Call( &aEnum );
    }
}
<|endoftext|>


<commit_before>/* * Copyright (c) 2016 Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* 3. The names of its contributors may not be used to endorse or promote
*    products derived from this software without specific prior written
*    permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* *********************************************************************************************** *
* CARLsim
* created by: (MDR) Micah Richert, (JN) Jayram M. Nageswaran
* maintained by:
* (MA) Mike Avery <averym@uci.edu>
* (MB) Michael Beyeler <mbeyeler@uci.edu>,
* (KDC) Kristofor Carlson <kdcarlso@uci.edu>
* (TSC) Ting-Shuo Chou <tingshuc@uci.edu>
* (HK) Hirak J Kashyap <kashyaph@uci.edu>
*
* CARLsim v1.0: JM, MDR
* CARLsim v2.0/v2.1/v2.2: JM, MDR, MA, MB, KDC
* CARLsim3: MB, KDC, TSC
* CARLsim4: TSC, HK
*
* CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
* Ver 12/31/2016
*/
#include "stopwatch.h"

#include <stdio.h>
#include <algorithm>		// std::find
#include <assert.h>			// assert

#include <carlsim_log_definitions.h>	// CARLSIM_ERROR, CARLSIM_WARN, CARLSIM_INFO

// ****************************************************************************************************************** //
// STOPWATCH UTILITY PRIVATE IMPLEMENTATION
// ****************************************************************************************************************** //

/*!
 * \brief Private implementation of the Stopwatch Utility
 *
 * This class provides a timer with milliseconds resolution.
 * \see http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c/1861337#1861337
 * \since v3.1
 */
class Stopwatch::Impl {
public:
	// +++++ PUBLIC METHODS: CONSTRUCTOR / DESTRUCTOR +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //

	Impl(bool startTimer) {
		reset();
		if (startTimer) {
			start("start");
		}
	}

	~Impl() {
		// nothing to see here
	}

	// resets the timer
	void reset() {
		if (_isTimerOn) {
			CARLSIM_WARN("Stopwatch::reset", "Cannot reset timer when timer is on.");
			return;
		}

		_isTimerOn = false;
		_startTimeMs.clear();
		_stopTimeMs.clear();
		_lapTimeMs.clear();
		_accumTimeMs = 0;
		_tags.clear();
	}

	// starts/continues the timer
	void start(const std::string& tag) {
		if (_isTimerOn) {
			CARLSIM_WARN("Stopwatch::start", "Cannot start timer when timer is already on.");
			return;
		}

		// start/continue timer
		_isTimerOn = true;
		_tags.push_back(tag);
		_startTimeMs.push_back( getCurrentTime() );
	}

	// stops the timer
	uint64_t stop(bool printMessage=true, FILE* fileStream=NULL) {
		if (!_isTimerOn) {
			CARLSIM_WARN("Stopwatch::stop", "Cannot stop timer when timer is already off.");
			return _accumTimeMs;
		}

		// pause/stop timer and update exe time
		_isTimerOn = false;
		_stopTimeMs.push_back( getCurrentTime() );
		uint64_t lapMs = _stopTimeMs.back() - _startTimeMs.back();
		_lapTimeMs.push_back(lapMs);

		// keep track of accumulated record time
		// check for arithmetic overflow
		assert(_accumTimeMs + lapMs >= _accumTimeMs);
		_accumTimeMs += lapMs;

		if (printMessage) {
			print(fileStream);
		}

		return _accumTimeMs;
	}

	// prints a summary to a file
	void print(FILE* fileStream=NULL) const {
		if (_isTimerOn) {
			CARLSIM_WARN("Stopwatch::print", "Cannot print when timer is on.");
			return;
		}

		if (fileStream == NULL) {
			fileStream = stdout; // default
		}

		fprintf(fileStream, "\n--------------------------------------------------------------------------------\n");
		fprintf(fileStream, "| Stopwatch                                                                    |\n");
		fprintf(fileStream, "|------------------------------------------------------------------------------|\n");
		fprintf(fileStream, "|                  Tag         Start          Stop           Lap         Total |\n");

		uint64_t totalMsSoFar = 0;
		for (unsigned int i=0; i<_lapTimeMs.size(); i++) {
			totalMsSoFar += _lapTimeMs[i];
			uint64_t startMs = _startTimeMs[i] - _startTimeMs[0];
			uint64_t stopMs = _stopTimeMs[i] - _startTimeMs[0];
			uint64_t lapMs = _lapTimeMs[i];

			fprintf(fileStream, "| %20.20s  %02lu:%02lu:%02lu.%03lu  %02lu:%02lu:%02lu.%03lu "
				" %02lu:%02lu:%02lu.%03lu  %02lu:%02lu:%02lu.%03lu |\n",
				_tags[i].c_str(),
				startMs/3600000, (startMs/1000/60)%60, (startMs/1000)%60, startMs%1000,
				stopMs/3600000, (stopMs/1000/60)%60, (stopMs/1000)%60, stopMs%1000,
				lapMs/3600000, (lapMs/1000/60)%60, (lapMs/1000)%60, lapMs%1000,
				totalMsSoFar/3600000, (totalMsSoFar/1000/60)%60, (totalMsSoFar/1000)%60, totalMsSoFar%1000);
		}
		fprintf(fileStream, "--------------------------------------------------------------------------------\n");
	}

	// lap is equivalent to stop-start
	// returns current lap time
	uint64_t lap(const std::string& tag) {
		if (!_isTimerOn) {
			CARLSIM_WARN("Stopwatch::lap", "Cannot use lap when timer is off.");
			return 0;
		}

		stop(false);
		start(tag);
		return _lapTimeMs.back();
	}

	// returns lap time, look-up by tag
	uint64_t getLapTime(const std::string& tag) const {
		unsigned int pos = std::find(_tags.begin(), _tags.end(), tag) - _tags.begin();
		if (pos >=0 && pos < _tags.size()) {
			if (pos >= _lapTimeMs.size()) {
				CARLSIM_WARN("Stopwatch::getLapTime(tag)", "Cannot look up current lap time until timer stopped.");
				return 0;
			}
			printf("pos = %u, time = %lu\n",pos,_lapTimeMs[pos]);
			return _lapTimeMs[pos];
		} else {
			CARLSIM_WARN("Stopwatch::getLapTime(tag)", "Invalid tag specified.");
			return 0;
		}
	}

	// returns lap time, look-up by index
	uint64_t getLapTime(unsigned int index) const {
		if (index < _lapTimeMs.size()) {
			return _lapTimeMs[index];
		} else {
			CARLSIM_WARN("Stopwatch::getLapTime(index)", "Invalid index specified.");
			return 0;
		}
	}

private:
	// +++++ PRIVATE METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //

	uint64_t getCurrentTime() const {
	#if defined(WIN32) || defined(WIN64)
		// Windows
		FILETIME ft;
		LARGE_INTEGER li;

		// Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
		// to a LARGE_INTEGER structure.
		GetSystemTimeAsFileTime(&ft);
		li.LowPart = ft.dwLowDateTime;
		li.HighPart = ft.dwHighDateTime;

		uint64_t ret = li.QuadPart;
		ret -= 116444736000000000LL; // Convert from file time to UNIX epoch time.
		ret /= 10000; // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals

		return ret;
	#else
		// Unix
		struct timeval tv;

		gettimeofday(&tv, NULL);

		uint64_t ret = tv.tv_usec;
		// Convert from micro seconds (10^-6) to milliseconds (10^-3)
		ret /= 1000;

		// Adds the seconds (10^0) after converting them to milliseconds (10^-3)
		ret += (tv.tv_sec * 1000);

		return ret;
	#endif
	}

	// +++++ PRIVATE STATIC PROPERTIES ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //

	// +++++ PRIVATE PROPERTIES +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
	std::vector<uint64_t> _startTimeMs;		// vector of start times (Unix/Windows timestamps)
	std::vector<uint64_t> _stopTimeMs;		// vector of end times (Unix/Windows timestamps)
	std::vector<uint64_t> _lapTimeMs;		// vector lap times (stop-start for every lap)
	uint64_t _accumTimeMs;					// acumulated record time (sum of all laps)
	std::vector<std::string> _tags;			// string tag for every lap
	bool _isTimerOn;						// flag to indicate whether stopwatch is running (true) or not (false)

};

// ****************************************************************************************************************** //
// STOPWATCH API IMPLEMENTATION
// ****************************************************************************************************************** //

// create and destroy a pImpl instance
Stopwatch::Stopwatch(bool startTimer) : _impl( new Impl(startTimer) ) {}
Stopwatch::~Stopwatch() { delete _impl; }

void Stopwatch::start(const std::string& tag) { _impl->start(tag); }
uint64_t Stopwatch::stop(bool printMessage, FILE* printFile) { return _impl->stop(printMessage, printFile); }
uint64_t Stopwatch::lap(const std::string& tag) { return _impl->lap(tag); }
void Stopwatch::reset() { _impl->reset(); }

uint64_t Stopwatch::getLapTime(const std::string& tag) const { return _impl->getLapTime(tag); }
uint64_t Stopwatch::getLapTime(int index) const { return _impl->getLapTime(index); }

void Stopwatch::print(FILE* fileStream) const { _impl->print(fileStream); }<commit_msg>Quick fix initialization bug in stopwatch.cpp<commit_after>/* * Copyright (c) 2016 Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* 3. The names of its contributors may not be used to endorse or promote
*    products derived from this software without specific prior written
*    permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* *********************************************************************************************** *
* CARLsim
* created by: (MDR) Micah Richert, (JN) Jayram M. Nageswaran
* maintained by:
* (MA) Mike Avery <averym@uci.edu>
* (MB) Michael Beyeler <mbeyeler@uci.edu>,
* (KDC) Kristofor Carlson <kdcarlso@uci.edu>
* (TSC) Ting-Shuo Chou <tingshuc@uci.edu>
* (HK) Hirak J Kashyap <kashyaph@uci.edu>
*
* CARLsim v1.0: JM, MDR
* CARLsim v2.0/v2.1/v2.2: JM, MDR, MA, MB, KDC
* CARLsim3: MB, KDC, TSC
* CARLsim4: TSC, HK
*
* CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
* Ver 12/31/2016
*/
#include "stopwatch.h"

#include <stdio.h>
#include <algorithm>		// std::find
#include <assert.h>			// assert

#include <carlsim_log_definitions.h>	// CARLSIM_ERROR, CARLSIM_WARN, CARLSIM_INFO

// ****************************************************************************************************************** //
// STOPWATCH UTILITY PRIVATE IMPLEMENTATION
// ****************************************************************************************************************** //

/*!
 * \brief Private implementation of the Stopwatch Utility
 *
 * This class provides a timer with milliseconds resolution.
 * \see http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c/1861337#1861337
 * \since v3.1
 */
class Stopwatch::Impl {
public:
	// +++++ PUBLIC METHODS: CONSTRUCTOR / DESTRUCTOR +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //

	Impl(bool startTimer) {
		_isTimerOn = false;
		reset();
		if (startTimer) {
			start("start");
		}
	}

	~Impl() {
		// nothing to see here
	}

	// resets the timer
	void reset() {
		if (_isTimerOn) {
			CARLSIM_WARN("Stopwatch::reset", "Cannot reset timer when timer is on.");
			return;
		}

		_isTimerOn = false;
		_startTimeMs.clear();
		_stopTimeMs.clear();
		_lapTimeMs.clear();
		_accumTimeMs = 0;
		_tags.clear();
	}

	// starts/continues the timer
	void start(const std::string& tag) {
		if (_isTimerOn) {
			CARLSIM_WARN("Stopwatch::start", "Cannot start timer when timer is already on.");
			return;
		}

		// start/continue timer
		_isTimerOn = true;
		_tags.push_back(tag);
		_startTimeMs.push_back( getCurrentTime() );
	}

	// stops the timer
	uint64_t stop(bool printMessage=true, FILE* fileStream=NULL) {
		if (!_isTimerOn) {
			CARLSIM_WARN("Stopwatch::stop", "Cannot stop timer when timer is already off.");
			return _accumTimeMs;
		}

		// pause/stop timer and update exe time
		_isTimerOn = false;
		_stopTimeMs.push_back( getCurrentTime() );
		uint64_t lapMs = _stopTimeMs.back() - _startTimeMs.back();
		_lapTimeMs.push_back(lapMs);

		// keep track of accumulated record time
		// check for arithmetic overflow
		assert(_accumTimeMs + lapMs >= _accumTimeMs);
		_accumTimeMs += lapMs;

		if (printMessage) {
			print(fileStream);
		}

		return _accumTimeMs;
	}

	// prints a summary to a file
	void print(FILE* fileStream=NULL) const {
		if (_isTimerOn) {
			CARLSIM_WARN("Stopwatch::print", "Cannot print when timer is on.");
			return;
		}

		if (fileStream == NULL) {
			fileStream = stdout; // default
		}

		fprintf(fileStream, "\n--------------------------------------------------------------------------------\n");
		fprintf(fileStream, "| Stopwatch                                                                    |\n");
		fprintf(fileStream, "|------------------------------------------------------------------------------|\n");
		fprintf(fileStream, "|                  Tag         Start          Stop           Lap         Total |\n");

		uint64_t totalMsSoFar = 0;
		for (unsigned int i=0; i<_lapTimeMs.size(); i++) {
			totalMsSoFar += _lapTimeMs[i];
			uint64_t startMs = _startTimeMs[i] - _startTimeMs[0];
			uint64_t stopMs = _stopTimeMs[i] - _startTimeMs[0];
			uint64_t lapMs = _lapTimeMs[i];

			fprintf(fileStream, "| %20.20s  %02lu:%02lu:%02lu.%03lu  %02lu:%02lu:%02lu.%03lu "
				" %02lu:%02lu:%02lu.%03lu  %02lu:%02lu:%02lu.%03lu |\n",
				_tags[i].c_str(),
				startMs/3600000, (startMs/1000/60)%60, (startMs/1000)%60, startMs%1000,
				stopMs/3600000, (stopMs/1000/60)%60, (stopMs/1000)%60, stopMs%1000,
				lapMs/3600000, (lapMs/1000/60)%60, (lapMs/1000)%60, lapMs%1000,
				totalMsSoFar/3600000, (totalMsSoFar/1000/60)%60, (totalMsSoFar/1000)%60, totalMsSoFar%1000);
		}
		fprintf(fileStream, "--------------------------------------------------------------------------------\n");
	}

	// lap is equivalent to stop-start
	// returns current lap time
	uint64_t lap(const std::string& tag) {
		if (!_isTimerOn) {
			CARLSIM_WARN("Stopwatch::lap", "Cannot use lap when timer is off.");
			return 0;
		}

		stop(false);
		start(tag);
		return _lapTimeMs.back();
	}

	// returns lap time, look-up by tag
	uint64_t getLapTime(const std::string& tag) const {
		unsigned int pos = std::find(_tags.begin(), _tags.end(), tag) - _tags.begin();
		if (pos >=0 && pos < _tags.size()) {
			if (pos >= _lapTimeMs.size()) {
				CARLSIM_WARN("Stopwatch::getLapTime(tag)", "Cannot look up current lap time until timer stopped.");
				return 0;
			}
			printf("pos = %u, time = %lu\n",pos,_lapTimeMs[pos]);
			return _lapTimeMs[pos];
		} else {
			CARLSIM_WARN("Stopwatch::getLapTime(tag)", "Invalid tag specified.");
			return 0;
		}
	}

	// returns lap time, look-up by index
	uint64_t getLapTime(unsigned int index) const {
		if (index < _lapTimeMs.size()) {
			return _lapTimeMs[index];
		} else {
			CARLSIM_WARN("Stopwatch::getLapTime(index)", "Invalid index specified.");
			return 0;
		}
	}

private:
	// +++++ PRIVATE METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //

	uint64_t getCurrentTime() const {
	#if defined(WIN32) || defined(WIN64)
		// Windows
		FILETIME ft;
		LARGE_INTEGER li;

		// Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
		// to a LARGE_INTEGER structure.
		GetSystemTimeAsFileTime(&ft);
		li.LowPart = ft.dwLowDateTime;
		li.HighPart = ft.dwHighDateTime;

		uint64_t ret = li.QuadPart;
		ret -= 116444736000000000LL; // Convert from file time to UNIX epoch time.
		ret /= 10000; // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals

		return ret;
	#else
		// Unix
		struct timeval tv;

		gettimeofday(&tv, NULL);

		uint64_t ret = tv.tv_usec;
		// Convert from micro seconds (10^-6) to milliseconds (10^-3)
		ret /= 1000;

		// Adds the seconds (10^0) after converting them to milliseconds (10^-3)
		ret += (tv.tv_sec * 1000);

		return ret;
	#endif
	}

	// +++++ PRIVATE STATIC PROPERTIES ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //

	// +++++ PRIVATE PROPERTIES +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
	std::vector<uint64_t> _startTimeMs;		// vector of start times (Unix/Windows timestamps)
	std::vector<uint64_t> _stopTimeMs;		// vector of end times (Unix/Windows timestamps)
	std::vector<uint64_t> _lapTimeMs;		// vector lap times (stop-start for every lap)
	uint64_t _accumTimeMs;					// acumulated record time (sum of all laps)
	std::vector<std::string> _tags;			// string tag for every lap
	bool _isTimerOn;						// flag to indicate whether stopwatch is running (true) or not (false)

};

// ****************************************************************************************************************** //
// STOPWATCH API IMPLEMENTATION
// ****************************************************************************************************************** //

// create and destroy a pImpl instance
Stopwatch::Stopwatch(bool startTimer) : _impl( new Impl(startTimer) ) {}
Stopwatch::~Stopwatch() { delete _impl; }

void Stopwatch::start(const std::string& tag) { _impl->start(tag); }
uint64_t Stopwatch::stop(bool printMessage, FILE* printFile) { return _impl->stop(printMessage, printFile); }
uint64_t Stopwatch::lap(const std::string& tag) { return _impl->lap(tag); }
void Stopwatch::reset() { _impl->reset(); }

uint64_t Stopwatch::getLapTime(const std::string& tag) const { return _impl->getLapTime(tag); }
uint64_t Stopwatch::getLapTime(int index) const { return _impl->getLapTime(index); }

void Stopwatch::print(FILE* fileStream) const { _impl->print(fileStream); }<|endoftext|>


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

#include "builder.h"
#include "dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "utils/arena_allocator.h"

#include "gtest/gtest.h"

namespace art {

static void TestCode(const uint16_t* data, const int* blocks, size_t blocks_length) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);
  HGraphBuilder builder(&allocator);
  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
  HGraph* graph = builder.BuildGraph(*item);
  ASSERT_NE(graph, nullptr);
  graph->BuildDominatorTree();
  ASSERT_EQ(graph->blocks()->Size(), blocks_length);
  for (size_t i = 0; i < blocks_length; i++) {
    if (blocks[i] == -1) {
      ASSERT_EQ(nullptr, graph->blocks()->Get(i)->dominator());
    } else {
      ASSERT_NE(nullptr, graph->blocks()->Get(i)->dominator());
      ASSERT_EQ(blocks[i], graph->blocks()->Get(i)->dominator()->block_id());
    }
  }
}

TEST(OptimizerTest, ReturnVoid) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
      Instruction::RETURN_VOID);  // Block number 1

  const int dominators[] = {
    -1,
    0,
    1
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG1) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO | 0x100,  // Block number 1
    Instruction::RETURN_VOID);  // Block number 2

  const int dominators[] = {
    -1,
    0,
    1,
    2
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG2) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO | 0x100,  // Block number 1
    Instruction::GOTO | 0x100,  // Block number 2
    Instruction::RETURN_VOID);  // Block number 3

  const int dominators[] = {
    -1,
    0,
    1,
    2,
    3
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG3) {
  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO | 0x200,    // Block number 1
    Instruction::RETURN_VOID,     // Block number 2
    Instruction::GOTO | 0xFF00);  // Block number 3

  const int dominators[] = {
    -1,
    0,
    3,
    1,
    2
  };

  TestCode(data1, dominators, sizeof(dominators) / sizeof(int));

  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO_16, 3,
    Instruction::RETURN_VOID,
    Instruction::GOTO_16, 0xFFFF);

  TestCode(data2, dominators, sizeof(dominators) / sizeof(int));

  const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO_32, 4, 0,
    Instruction::RETURN_VOID,
    Instruction::GOTO_32, 0xFFFF, 0xFFFF);

  TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG4) {
  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::NOP,
    Instruction::GOTO | 0xFF00);

  const int dominators[] = {
    -1,
    0,
    -1
  };

  TestCode(data1, dominators, sizeof(dominators) / sizeof(int));

  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO_32, 0, 0);

  TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG5) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::RETURN_VOID,     // Block number 1
    Instruction::GOTO | 0x100,    // Dead block
    Instruction::GOTO | 0xFE00);  // Block number 2

  const int dominators[] = {
    -1,
    0,
    -1,
    1
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG6) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,
    Instruction::GOTO | 0x100,
    Instruction::RETURN_VOID);

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    3
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG7) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,        // Block number 1
    Instruction::GOTO | 0x100,    // Block number 2
    Instruction::GOTO | 0xFF00);  // Block number 3

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    -1  // exit block is not dominated by any block due to the spin loop.
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG8) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,        // Block number 1
    Instruction::GOTO | 0x200,    // Block number 2
    Instruction::GOTO | 0x100,    // Block number 3
    Instruction::GOTO | 0xFF00);  // Block number 4

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    1,
    -1  // exit block is not dominated by any block due to the spin loop.
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG9) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,        // Block number 1
    Instruction::GOTO | 0x200,    // Block number 2
    Instruction::GOTO | 0x100,    // Block number 3
    Instruction::GOTO | 0xFE00);  // Block number 4

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    1,
    -1  // exit block is not dominated by any block due to the spin loop.
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG10) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 6,  // Block number 1
    Instruction::IF_EQ, 3,  // Block number 2
    Instruction::GOTO | 0x100,  // Block number 3
    Instruction::GOTO | 0x100,  // Block number 4
    Instruction::RETURN_VOID);  // Block number 5

  const int dominators[] = {
    -1,
    0,
    1,
    2,
    2,
    1,
    5  // Block number 5 dominates exit block
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

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

#include "builder.h"
#include "dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "utils/arena_allocator.h"

#include "gtest/gtest.h"

namespace art {

static void TestCode(const uint16_t* data, const int* blocks, size_t blocks_length) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);
  HGraphBuilder builder(&allocator);
  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
  HGraph* graph = builder.BuildGraph(*item);
  ASSERT_NE(graph, nullptr);
  graph->BuildDominatorTree();
  ASSERT_EQ(graph->blocks()->Size(), blocks_length);
  for (size_t i = 0; i < blocks_length; i++) {
    if (blocks[i] == -1) {
      ASSERT_EQ(nullptr, graph->blocks()->Get(i)->dominator());
    } else {
      ASSERT_NE(nullptr, graph->blocks()->Get(i)->dominator());
      ASSERT_EQ(blocks[i], graph->blocks()->Get(i)->dominator()->block_id());
    }
  }
}

TEST(OptimizerTest, ReturnVoid) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
      Instruction::RETURN_VOID);  // Block number 1

  const int dominators[] = {
    -1,
    0,
    1
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG1) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO | 0x100,  // Block number 1
    Instruction::RETURN_VOID);  // Block number 2

  const int dominators[] = {
    -1,
    0,
    1,
    2
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG2) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO | 0x100,  // Block number 1
    Instruction::GOTO | 0x100,  // Block number 2
    Instruction::RETURN_VOID);  // Block number 3

  const int dominators[] = {
    -1,
    0,
    1,
    2,
    3
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG3) {
  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO | 0x200,    // Block number 1
    Instruction::RETURN_VOID,     // Block number 2
    Instruction::GOTO | 0xFF00);  // Block number 3

  const int dominators[] = {
    -1,
    0,
    3,
    1,
    2
  };

  TestCode(data1, dominators, sizeof(dominators) / sizeof(int));

  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO_16, 3,
    Instruction::RETURN_VOID,
    Instruction::GOTO_16, 0xFFFF);

  TestCode(data2, dominators, sizeof(dominators) / sizeof(int));

  const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO_32, 4, 0,
    Instruction::RETURN_VOID,
    Instruction::GOTO_32, 0xFFFF, 0xFFFF);

  TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG4) {
  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::NOP,
    Instruction::GOTO | 0xFF00);

  const int dominators[] = {
    -1,
    0,
    -1
  };

  TestCode(data1, dominators, sizeof(dominators) / sizeof(int));

  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::GOTO_32, 0, 0);

  TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG5) {
  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
    Instruction::RETURN_VOID,     // Block number 1
    Instruction::GOTO | 0x100,    // Dead block
    Instruction::GOTO | 0xFE00);  // Block number 2

  const int dominators[] = {
    -1,
    0,
    -1,
    1
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG6) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,
    Instruction::GOTO | 0x100,
    Instruction::RETURN_VOID);

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    3
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG7) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,        // Block number 1
    Instruction::GOTO | 0x100,    // Block number 2
    Instruction::GOTO | 0xFF00);  // Block number 3

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    -1  // exit block is not dominated by any block due to the spin loop.
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG8) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,        // Block number 1
    Instruction::GOTO | 0x200,    // Block number 2
    Instruction::GOTO | 0x100,    // Block number 3
    Instruction::GOTO | 0xFF00);  // Block number 4

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    1,
    -1  // exit block is not dominated by any block due to the spin loop.
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG9) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 3,        // Block number 1
    Instruction::GOTO | 0x200,    // Block number 2
    Instruction::GOTO | 0x100,    // Block number 3
    Instruction::GOTO | 0xFE00);  // Block number 4

  const int dominators[] = {
    -1,
    0,
    1,
    1,
    1,
    -1  // exit block is not dominated by any block due to the spin loop.
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

TEST(OptimizerTest, CFG10) {
  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 6,  // Block number 1
    Instruction::IF_EQ, 3,  // Block number 2
    Instruction::GOTO | 0x100,  // Block number 3
    Instruction::GOTO | 0x100,  // Block number 4
    Instruction::RETURN_VOID);  // Block number 5

  const int dominators[] = {
    -1,
    0,
    1,
    2,
    2,
    1,
    5  // Block number 5 dominates exit block
  };

  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}

}  // namespace art
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: localstratumbase.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-07 10:10:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_LOCALBE_LOCALSTRATUMBASE_HXX_
#define CONFIGMGR_LOCALBE_LOCALSTRATUMBASE_HXX_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XBACKENDENTITIES_HPP_
#include <com/sun/star/configuration/backend/XBackendEntities.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XUPDATABLELAYER_HPP_
#include <com/sun/star/configuration/backend/XUpdatableLayer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_INVALIDBOOTSTRAPFILEEXCEPTION_HPP_
#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_CANNOTCONNECTEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/CannotConnectException.hpp>
#endif

#ifndef _CPPUHELPER_COMPBASE3_HXX_
#include <cppuhelper/compbase3.hxx>
#endif

namespace configmgr
{
    struct ServiceImplementationInfo;

    namespace localbe
    {
//------------------------------------------------------------------------------

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace backend = css::configuration::backend ;
//------------------------------------------------------------------------------

typedef cppu::WeakComponentImplHelper3<lang::XInitialization,
                                       backend::XBackendEntities,
                                       lang::XServiceInfo> LocalStratumImplBase ;

struct LocalStratumMutexHolder { osl::Mutex mMutex; };
//------------------------------------------------------------------------------
static const char kLocalDataSuffix[] = ".xcu";
//------------------------------------------------------------------------------

/**
  Helper for implementing the [Single|Multi]LayerStratum service for local file access.
  */
class LocalStratumBase : protected LocalStratumMutexHolder, public LocalStratumImplBase
{
protected :
    /**
      Service constructor from a service factory.

      @param xContext   component context
      */
    LocalStratumBase(const uno::Reference<uno::XComponentContext>& xContext) ;

    /** Destructor */
    ~LocalStratumBase() ;

public:
    // XInitialize
    virtual void SAL_CALL
        initialize( const uno::Sequence<uno::Any>& aParameters)
            throw (uno::RuntimeException, uno::Exception,
                   css::configuration::InvalidBootstrapFileException,
                   backend::CannotConnectException,
                   backend::BackendSetupException);

    // XBackendEntities
    virtual rtl::OUString SAL_CALL
        getOwnerEntity(  )
            throw (uno::RuntimeException);

    virtual rtl::OUString SAL_CALL
        getAdminEntity(  )
            throw (uno::RuntimeException);

    virtual sal_Bool SAL_CALL
        supportsEntity( const rtl::OUString& aEntity )
            throw (backend::BackendAccessException, uno::RuntimeException);

    virtual sal_Bool SAL_CALL
        isEqualEntity( const rtl::OUString& aEntity, const rtl::OUString& aOtherEntity )
            throw (backend::BackendAccessException, lang::IllegalArgumentException, uno::RuntimeException);

    // XServiceInfo
    virtual rtl::OUString SAL_CALL
        getImplementationName(  )
            throw (uno::RuntimeException);

    virtual sal_Bool SAL_CALL
        supportsService( const rtl::OUString& aServiceName )
            throw (uno::RuntimeException) ;

    virtual uno::Sequence<rtl::OUString> SAL_CALL
        getSupportedServiceNames(  )
            throw (uno::RuntimeException) ;

protected:
    rtl::OUString const & getBaseUrl() const
    { return mStrataDataUrl; }

    static rtl::OUString getDataSuffix()
    { return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(kLocalDataSuffix)); }
//------------------------------------------------------------------------------
    /// raise a NoSupportException for an attempt to update this layer
    void failReadonly();

    // helper for implementing the stratum getLayer[s] function[s]
    uno::Reference<backend::XLayer> SAL_CALL
        getLayer( const rtl::OUString& aLayerId, const rtl::OUString& aTimestamp )
            throw (backend::BackendAccessException, lang::IllegalArgumentException, uno::RuntimeException);

    /**
      Builds a LocalFileLayer object given a subpath
      Since the LocalFileLayer implements the various
      interfaces a layer can be accessed as, a few methods
      need one.

      @param aSubpath   Subpath
      @return   local file layer
      @throws com::sun::star::lang::IllegalArgumentException
              if the subpath is invalid.
      */
    uno::Reference<backend::XLayer> createReadonlyFileLayer(const rtl::OUString& aSubpath)
        throw (lang::IllegalArgumentException) ;

    /**
      Builds a LocalFileLayer object given a subpath.
      Since the LocalFileLayer implements the various
      interfaces a layer can be accessed as, a few methods
      need one.

      @param aSubpath   subpath
      @return   local file layer
      @throws com::sun::star::lang::IllegalArgumentException
              if the subpath is invalid.
      */
    uno::Reference<backend::XUpdatableLayer> createUpdatableFileLayer(const rtl::OUString& aSubpath)
        throw (lang::IllegalArgumentException) ;

    /**
      Tells if a file is more recent than a given date.
      The date is formatted YYYYMMDDhhmmssZ.

      @param aSubpath       relative URL of the component to check
      @param aTimestamp     timestamp to check against
      @return   sal_True if the file is more recent, sal_False otherwise
      */
    sal_Bool isMoreRecent(const rtl::OUString& aSubpath,
                          const rtl::OUString& aTimestamp) ;

protected:
    /// Parses and adjusts the passed base URL
    virtual void adjustBaseURL(rtl::OUString& aBaseURL);

private:
    /**
      Retrieves the appropriate layer and sublayers base directories.

      @param aLayerUrl      layer base URL, filled on return
      @param aSubLayerUrl   sublayer base URL, filled on return
      */
    virtual void getLayerDirectories(rtl::OUString& aLayerUrl,
                                     rtl::OUString& aSubLayerUrl) const = 0;
    virtual const ServiceImplementationInfo * getServiceInfoData() const = 0;

private :
    /** Service factory */
    uno::Reference<lang::XMultiServiceFactory> mFactory ;
    /**
      Base of the strata data.
      */
    rtl::OUString mStrataDataUrl ;

} ;

} } // configmgr.localbe

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.46); FILE MERGED 2005/09/05 17:04:52 rt 1.2.46.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: localstratumbase.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 04:07:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef CONFIGMGR_LOCALBE_LOCALSTRATUMBASE_HXX_
#define CONFIGMGR_LOCALBE_LOCALSTRATUMBASE_HXX_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XBACKENDENTITIES_HPP_
#include <com/sun/star/configuration/backend/XBackendEntities.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XUPDATABLELAYER_HPP_
#include <com/sun/star/configuration/backend/XUpdatableLayer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_INVALIDBOOTSTRAPFILEEXCEPTION_HPP_
#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_CANNOTCONNECTEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/CannotConnectException.hpp>
#endif

#ifndef _CPPUHELPER_COMPBASE3_HXX_
#include <cppuhelper/compbase3.hxx>
#endif

namespace configmgr
{
    struct ServiceImplementationInfo;

    namespace localbe
    {
//------------------------------------------------------------------------------

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace backend = css::configuration::backend ;
//------------------------------------------------------------------------------

typedef cppu::WeakComponentImplHelper3<lang::XInitialization,
                                       backend::XBackendEntities,
                                       lang::XServiceInfo> LocalStratumImplBase ;

struct LocalStratumMutexHolder { osl::Mutex mMutex; };
//------------------------------------------------------------------------------
static const char kLocalDataSuffix[] = ".xcu";
//------------------------------------------------------------------------------

/**
  Helper for implementing the [Single|Multi]LayerStratum service for local file access.
  */
class LocalStratumBase : protected LocalStratumMutexHolder, public LocalStratumImplBase
{
protected :
    /**
      Service constructor from a service factory.

      @param xContext   component context
      */
    LocalStratumBase(const uno::Reference<uno::XComponentContext>& xContext) ;

    /** Destructor */
    ~LocalStratumBase() ;

public:
    // XInitialize
    virtual void SAL_CALL
        initialize( const uno::Sequence<uno::Any>& aParameters)
            throw (uno::RuntimeException, uno::Exception,
                   css::configuration::InvalidBootstrapFileException,
                   backend::CannotConnectException,
                   backend::BackendSetupException);

    // XBackendEntities
    virtual rtl::OUString SAL_CALL
        getOwnerEntity(  )
            throw (uno::RuntimeException);

    virtual rtl::OUString SAL_CALL
        getAdminEntity(  )
            throw (uno::RuntimeException);

    virtual sal_Bool SAL_CALL
        supportsEntity( const rtl::OUString& aEntity )
            throw (backend::BackendAccessException, uno::RuntimeException);

    virtual sal_Bool SAL_CALL
        isEqualEntity( const rtl::OUString& aEntity, const rtl::OUString& aOtherEntity )
            throw (backend::BackendAccessException, lang::IllegalArgumentException, uno::RuntimeException);

    // XServiceInfo
    virtual rtl::OUString SAL_CALL
        getImplementationName(  )
            throw (uno::RuntimeException);

    virtual sal_Bool SAL_CALL
        supportsService( const rtl::OUString& aServiceName )
            throw (uno::RuntimeException) ;

    virtual uno::Sequence<rtl::OUString> SAL_CALL
        getSupportedServiceNames(  )
            throw (uno::RuntimeException) ;

protected:
    rtl::OUString const & getBaseUrl() const
    { return mStrataDataUrl; }

    static rtl::OUString getDataSuffix()
    { return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(kLocalDataSuffix)); }
//------------------------------------------------------------------------------
    /// raise a NoSupportException for an attempt to update this layer
    void failReadonly();

    // helper for implementing the stratum getLayer[s] function[s]
    uno::Reference<backend::XLayer> SAL_CALL
        getLayer( const rtl::OUString& aLayerId, const rtl::OUString& aTimestamp )
            throw (backend::BackendAccessException, lang::IllegalArgumentException, uno::RuntimeException);

    /**
      Builds a LocalFileLayer object given a subpath
      Since the LocalFileLayer implements the various
      interfaces a layer can be accessed as, a few methods
      need one.

      @param aSubpath   Subpath
      @return   local file layer
      @throws com::sun::star::lang::IllegalArgumentException
              if the subpath is invalid.
      */
    uno::Reference<backend::XLayer> createReadonlyFileLayer(const rtl::OUString& aSubpath)
        throw (lang::IllegalArgumentException) ;

    /**
      Builds a LocalFileLayer object given a subpath.
      Since the LocalFileLayer implements the various
      interfaces a layer can be accessed as, a few methods
      need one.

      @param aSubpath   subpath
      @return   local file layer
      @throws com::sun::star::lang::IllegalArgumentException
              if the subpath is invalid.
      */
    uno::Reference<backend::XUpdatableLayer> createUpdatableFileLayer(const rtl::OUString& aSubpath)
        throw (lang::IllegalArgumentException) ;

    /**
      Tells if a file is more recent than a given date.
      The date is formatted YYYYMMDDhhmmssZ.

      @param aSubpath       relative URL of the component to check
      @param aTimestamp     timestamp to check against
      @return   sal_True if the file is more recent, sal_False otherwise
      */
    sal_Bool isMoreRecent(const rtl::OUString& aSubpath,
                          const rtl::OUString& aTimestamp) ;

protected:
    /// Parses and adjusts the passed base URL
    virtual void adjustBaseURL(rtl::OUString& aBaseURL);

private:
    /**
      Retrieves the appropriate layer and sublayers base directories.

      @param aLayerUrl      layer base URL, filled on return
      @param aSubLayerUrl   sublayer base URL, filled on return
      */
    virtual void getLayerDirectories(rtl::OUString& aLayerUrl,
                                     rtl::OUString& aSubLayerUrl) const = 0;
    virtual const ServiceImplementationInfo * getServiceInfoData() const = 0;

private :
    /** Service factory */
    uno::Reference<lang::XMultiServiceFactory> mFactory ;
    /**
      Base of the strata data.
      */
    rtl::OUString mStrataDataUrl ;

} ;

} } // configmgr.localbe

#endif
<|endoftext|>