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

#include "xdgbasedirs_p.h"

#include "akonadi-prefix.h" // for prefix defines

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>

#include <cstdlib>

static QStringList alternateExecPaths( const QString& path )
{
  QStringList pathList;

  pathList << path;

#if defined(Q_OS_WIN) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif

  return pathList;
}

static QStringList splitPathList( const QString &pathList )
{
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  return pathList.split( QLatin1Char( ';' ) );
#else
  return pathList.split( QLatin1Char( ':' ) );
#endif
}

namespace Akonadi {

class XdgBaseDirsPrivate
{
  public:
    XdgBaseDirsPrivate() {}

    ~XdgBaseDirsPrivate() {}
};

class XdgBaseDirsSingleton
{
public:
    QString homePath( const char *variable, const char *defaultSubDir );

    QStringList systemPathList( const char *variable, const char *defaultDirList );

  public:
    QString mConfigHome;
    QString mDataHome;

    QStringList mConfigDirs;
    QStringList mDataDirs;
    QStringList mExecutableDirs;
};

Q_GLOBAL_STATIC(XdgBaseDirsSingleton, instance)

}

using namespace Akonadi;

XdgBaseDirs::XdgBaseDirs() : d( new XdgBaseDirsPrivate() )
{
}

XdgBaseDirs::~XdgBaseDirs()
{
  delete d;
}

QString XdgBaseDirs::homePath( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataHome.isEmpty() ) {
      instance()->mDataHome = instance()->homePath( "XDG_DATA_HOME", ".local/share" );
    }
    return instance()->mDataHome;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigHome.isEmpty() ) {
      instance()->mConfigHome = instance()->homePath( "XDG_CONFIG_HOME", ".config" );
    }
    return instance()->mConfigHome;
  }

  return QString();
}

QStringList XdgBaseDirs::systemPathList( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataDirs.isEmpty() ) {
      QStringList dataDirs = instance()->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );

#ifdef Q_OS_WIN
      const QString prefixDataDir = QLatin1String( AKONADIPREFIX "/" AKONADIDATA );
#else
      const QString prefixDataDir = QLatin1String( AKONADIDATA );
#endif
      if ( !dataDirs.contains( prefixDataDir ) ) {
        dataDirs << prefixDataDir;
      }

      // fallback for users with KDE in a different prefix and not correctly set up XDG_DATA_DIRS, hi David ;-)
      QProcess proc;
      // ### should probably rather be --path xdg-something
      const QStringList args = QStringList() << QLatin1String( "--prefix" );
      proc.start( QLatin1String( "kde4-config" ), args );
      if ( proc.waitForStarted() && proc.waitForFinished() && proc.exitCode() == 0 ) {
        proc.setReadChannel( QProcess::StandardOutput );
        foreach ( const QString &basePath, splitPathList( QString::fromLocal8Bit( proc.readLine().trimmed() ) ) ) {
          const QString path = basePath + QDir::separator() + QLatin1String( "share" );
          if ( !dataDirs.contains( path ) )
            dataDirs << path;
        }
      }

      instance()->mDataDirs = dataDirs;
    }
    return instance()->mDataDirs;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigDirs.isEmpty() ) {
      QStringList configDirs = instance()->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );

#ifdef Q_OS_WIN
      const QString prefixConfigDir = QLatin1String( AKONADIPREFIX "/" AKONADICONFIG );
#else
      const QString prefixConfigDir = QLatin1String( AKONADICONFIG );
#endif
      if ( !configDirs.contains( prefixConfigDir ) ) {
        configDirs << prefixConfigDir;
      }

      instance()->mConfigDirs = configDirs;
    }
    return instance()->mConfigDirs;
  }

  return QStringList();
}

QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QString XdgBaseDirs::findExecutableFile( const QString &relPath, const QStringList &searchPath )
{
  if ( instance()->mExecutableDirs.isEmpty() ) {
    QStringList executableDirs = instance()->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );

    const QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
    if ( !executableDirs.contains( prefixExecutableDir ) ) {
      executableDirs << prefixExecutableDir;
    }

    executableDirs += searchPath;

#if defined(Q_OS_MAC) //krazy:exclude=cpp
    executableDirs += QLatin1String(AKONADIBUNDLEPATH);
#endif
    qWarning( ) << "search paths: " << executableDirs;

    instance()->mExecutableDirs = executableDirs;
  }

  QStringList::const_iterator pathIt    = instance()->mExecutableDirs.constBegin();
  QStringList::const_iterator pathEndIt = instance()->mExecutableDirs.constEnd();
  for ( ; pathIt != pathEndIt; ++pathIt ) {
    QStringList fullPathList = alternateExecPaths(*pathIt + QLatin1Char( '/' ) + relPath );

    QStringList::const_iterator it    = fullPathList.constBegin();
    QStringList::const_iterator endIt = fullPathList.constEnd();
    for ( ; it != endIt; ++it ) {
      QFileInfo fileInfo(*it);

      if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable() ) {
        return *it;
      }
    }
  }

  return QString();
}

QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath )
{
  QStringList resultList;

  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    resultList << fileInfo.absoluteFilePath();
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      resultList << fileInfo.absoluteFilePath();
    }
  }

  return resultList;
}

QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() ) {
    if ( fileInfo.isDir() ) {
      return fullPath;
    } else {
      qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
                 << "' exists but is not a directory";
    }
  } else {
    if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
      qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
                 << fileInfo.absoluteFilePath() << "'";
    } else {
      return fullPath;
    }
  }

  return QString();
}

QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}

QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}

QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode )
{
  const QString akonadiDir = QLatin1String( "akonadi" );

  QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;

  if ( openMode == WriteOnly ) return savePath;

  QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );

  if ( path.isEmpty() ) {
    return savePath;
  } else if ( openMode == ReadOnly || path == savePath ) {
    return path;
  }

  // file found in system paths and mode is ReadWrite, thus
  // we copy to the home path location and return this path
  QFile systemFile( path );

  systemFile.copy( savePath );

  return savePath;
}

QString XdgBaseDirsSingleton::homePath( const char *variable, const char *defaultSubDir )
{
  const QByteArray env = qgetenv( variable );

  QString xdgPath;
  if ( env.isEmpty() ) {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  } else if ( QDir::isAbsolutePath( QString::fromLocal8Bit( env ) ) ) {
#else
  } else if ( env.startsWith( '/' ) ) {
#endif
    xdgPath = QString::fromLocal8Bit( env );
  } else {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
  }

  return xdgPath;
}

QStringList XdgBaseDirsSingleton::systemPathList( const char *variable, const char *defaultDirList )
{
  const QByteArray env = qgetenv( variable );

  QString xdgDirList;
  if ( env.isEmpty() ) {
    xdgDirList = QLatin1String( defaultDirList );
  } else {
    xdgDirList = QString::fromLocal8Bit( env );
  }

  return splitPathList( xdgDirList );
}
<commit_msg>Resolve symlinks before checking if the file is executable. Should fix MySQL and agent launching when using maemo-optified packages.<commit_after>/***************************************************************************
 *   Copyright (C) 2007 by Kevin Krammer <kevin.krammer@gmx.at>            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "xdgbasedirs_p.h"

#include "akonadi-prefix.h" // for prefix defines

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>

#include <cstdlib>

static QStringList alternateExecPaths( const QString& path )
{
  QStringList pathList;

  pathList << path;

#if defined(Q_OS_WIN) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif

  return pathList;
}

static QStringList splitPathList( const QString &pathList )
{
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  return pathList.split( QLatin1Char( ';' ) );
#else
  return pathList.split( QLatin1Char( ':' ) );
#endif
}

namespace Akonadi {

class XdgBaseDirsPrivate
{
  public:
    XdgBaseDirsPrivate() {}

    ~XdgBaseDirsPrivate() {}
};

class XdgBaseDirsSingleton
{
public:
    QString homePath( const char *variable, const char *defaultSubDir );

    QStringList systemPathList( const char *variable, const char *defaultDirList );

  public:
    QString mConfigHome;
    QString mDataHome;

    QStringList mConfigDirs;
    QStringList mDataDirs;
    QStringList mExecutableDirs;
};

Q_GLOBAL_STATIC(XdgBaseDirsSingleton, instance)

}

using namespace Akonadi;

XdgBaseDirs::XdgBaseDirs() : d( new XdgBaseDirsPrivate() )
{
}

XdgBaseDirs::~XdgBaseDirs()
{
  delete d;
}

QString XdgBaseDirs::homePath( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataHome.isEmpty() ) {
      instance()->mDataHome = instance()->homePath( "XDG_DATA_HOME", ".local/share" );
    }
    return instance()->mDataHome;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigHome.isEmpty() ) {
      instance()->mConfigHome = instance()->homePath( "XDG_CONFIG_HOME", ".config" );
    }
    return instance()->mConfigHome;
  }

  return QString();
}

QStringList XdgBaseDirs::systemPathList( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataDirs.isEmpty() ) {
      QStringList dataDirs = instance()->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );

#ifdef Q_OS_WIN
      const QString prefixDataDir = QLatin1String( AKONADIPREFIX "/" AKONADIDATA );
#else
      const QString prefixDataDir = QLatin1String( AKONADIDATA );
#endif
      if ( !dataDirs.contains( prefixDataDir ) ) {
        dataDirs << prefixDataDir;
      }

      // fallback for users with KDE in a different prefix and not correctly set up XDG_DATA_DIRS, hi David ;-)
      QProcess proc;
      // ### should probably rather be --path xdg-something
      const QStringList args = QStringList() << QLatin1String( "--prefix" );
      proc.start( QLatin1String( "kde4-config" ), args );
      if ( proc.waitForStarted() && proc.waitForFinished() && proc.exitCode() == 0 ) {
        proc.setReadChannel( QProcess::StandardOutput );
        foreach ( const QString &basePath, splitPathList( QString::fromLocal8Bit( proc.readLine().trimmed() ) ) ) {
          const QString path = basePath + QDir::separator() + QLatin1String( "share" );
          if ( !dataDirs.contains( path ) )
            dataDirs << path;
        }
      }

      instance()->mDataDirs = dataDirs;
    }
    return instance()->mDataDirs;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigDirs.isEmpty() ) {
      QStringList configDirs = instance()->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );

#ifdef Q_OS_WIN
      const QString prefixConfigDir = QLatin1String( AKONADIPREFIX "/" AKONADICONFIG );
#else
      const QString prefixConfigDir = QLatin1String( AKONADICONFIG );
#endif
      if ( !configDirs.contains( prefixConfigDir ) ) {
        configDirs << prefixConfigDir;
      }

      instance()->mConfigDirs = configDirs;
    }
    return instance()->mConfigDirs;
  }

  return QStringList();
}

QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QString XdgBaseDirs::findExecutableFile( const QString &relPath, const QStringList &searchPath )
{
  if ( instance()->mExecutableDirs.isEmpty() ) {
    QStringList executableDirs = instance()->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );

    const QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
    if ( !executableDirs.contains( prefixExecutableDir ) ) {
      executableDirs << prefixExecutableDir;
    }

    executableDirs += searchPath;

#if defined(Q_OS_MAC) //krazy:exclude=cpp
    executableDirs += QLatin1String(AKONADIBUNDLEPATH);
#endif
    qWarning( ) << "search paths: " << executableDirs;

    instance()->mExecutableDirs = executableDirs;
  }

  QStringList::const_iterator pathIt    = instance()->mExecutableDirs.constBegin();
  QStringList::const_iterator pathEndIt = instance()->mExecutableDirs.constEnd();
  for ( ; pathIt != pathEndIt; ++pathIt ) {
    QStringList fullPathList = alternateExecPaths(*pathIt + QLatin1Char( '/' ) + relPath );

    QStringList::const_iterator it    = fullPathList.constBegin();
    QStringList::const_iterator endIt = fullPathList.constEnd();
    for ( ; it != endIt; ++it ) {
      const QFileInfo fileInfo( *it );

      // resolve symlinks, happens eg. with Maemo optify
      if ( fileInfo.canonicalFilePath().isEmpty() )
        continue;
      const QFileInfo canonicalFileInfo( fileInfo.canonicalFilePath() );

      if ( canonicalFileInfo.exists() && canonicalFileInfo.isFile() && canonicalFileInfo.isExecutable() ) {
        return *it;
      }
    }
  }

  return QString();
}

QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath )
{
  QStringList resultList;

  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    resultList << fileInfo.absoluteFilePath();
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      resultList << fileInfo.absoluteFilePath();
    }
  }

  return resultList;
}

QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() ) {
    if ( fileInfo.isDir() ) {
      return fullPath;
    } else {
      qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
                 << "' exists but is not a directory";
    }
  } else {
    if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
      qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
                 << fileInfo.absoluteFilePath() << "'";
    } else {
      return fullPath;
    }
  }

  return QString();
}

QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}

QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}

QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode )
{
  const QString akonadiDir = QLatin1String( "akonadi" );

  QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;

  if ( openMode == WriteOnly ) return savePath;

  QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );

  if ( path.isEmpty() ) {
    return savePath;
  } else if ( openMode == ReadOnly || path == savePath ) {
    return path;
  }

  // file found in system paths and mode is ReadWrite, thus
  // we copy to the home path location and return this path
  QFile systemFile( path );

  systemFile.copy( savePath );

  return savePath;
}

QString XdgBaseDirsSingleton::homePath( const char *variable, const char *defaultSubDir )
{
  const QByteArray env = qgetenv( variable );

  QString xdgPath;
  if ( env.isEmpty() ) {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  } else if ( QDir::isAbsolutePath( QString::fromLocal8Bit( env ) ) ) {
#else
  } else if ( env.startsWith( '/' ) ) {
#endif
    xdgPath = QString::fromLocal8Bit( env );
  } else {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
  }

  return xdgPath;
}

QStringList XdgBaseDirsSingleton::systemPathList( const char *variable, const char *defaultDirList )
{
  const QByteArray env = qgetenv( variable );

  QString xdgDirList;
  if ( env.isEmpty() ) {
    xdgDirList = QLatin1String( defaultDirList );
  } else {
    xdgDirList = QString::fromLocal8Bit( env );
  }

  return splitPathList( xdgDirList );
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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.txt
 *
 *  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 "selxSuperElastixFilter.h"
#include "selxBlueprint.h"
#include "selxConfigurationReader.h"
#include "selxAnyFileReader.h"
#include "selxAnyFileWriter.h"
#include "selxLogger.h"

#include <boost/algorithm/string.hpp>

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <stdexcept>

template< class T >
std::ostream &
operator<<( std::ostream & os, const std::vector< T > & v )
{
  std::copy( v.begin(), v.end(), std::ostream_iterator< T >( os, " " ) );
  return os;
}

int
main( int ac, char * av[] )
{
  try
  {
    typedef std::vector< std::string > VectorOfStringsType;

    // instantiate a SuperElastixFilter that is loaded with default components
    selx::SuperElastixFilter::Pointer superElastixFilter = selx::SuperElastixFilter::New();

    // add logger
    selx::SuperElastixFilter::LoggerPointer itkLogger = selx::SuperElastixFilter::LoggerType::New();
    itkLogger->Get()->AddConsole();
    superElastixFilter->SetLogger( itkLogger );

    fs::path            configurationPath;
    VectorOfStringsType inputPairs;
    VectorOfStringsType outputPairs;

    // Store the reader so that they will not be destroyed before the pipeline is executed.
    std::vector< selx::AnyFileReader::Pointer > fileReaders;
    // Store the writers for the update call
    //vector<ImageWriter2DType::Pointer> fileWriters;
    std::vector< selx::AnyFileWriter::Pointer > fileWriters;

    po::options_description desc( "Allowed options" );
    desc.add_options()
      ( "help", "produce help message" )
      ( "conf", po::value< fs::path >( &configurationPath )->required(), "Configuration file" )
      ( "in", po::value< VectorOfStringsType >( &inputPairs )->multitoken(), "Input data: images, labels, meshes, etc. Usage <name>=<path>" )
      ( "out", po::value< VectorOfStringsType >( &outputPairs )->multitoken(), "Output data: images, labels, meshes, etc. Usage <name>=<path>" )
      ( "graphout", po::value< fs::path >(), "Output Graphviz dot file" )
    ;

    po::variables_map vm;
    po::store( po::parse_command_line( ac, av, desc ), vm );
    po::notify( vm );

    if( vm.count( "help" ) )
    {
      std::cout << desc << "\n";
      return 0;
    }

    selx::ConfigurationReader::BlueprintPointerType blueprint = selx::ConfigurationReader::FromFile(configurationPath);

    if( vm.count( "graphout" ) )
    {
      blueprint->Write( vm[ "graphout" ].as< fs::path >().string() );
    }

    //turn the blueprint into an itkObject to connect to the superElastix itkFilter
    selx::SuperElastixFilter::BlueprintPointer itkBluePrint = selx::SuperElastixFilter::BlueprintType::New();
    itkBluePrint->Set(blueprint);
    superElastixFilter->SetBlueprint(itkBluePrint);

    if( vm.count( "in" ) )
    {
      int index = 0;
      for( const auto & inputPair : inputPairs )
      {
        VectorOfStringsType nameAndPath;
        boost::split( nameAndPath, inputPair, boost::is_any_of( "=" ) );  // NameAndPath == { "name","path" }
        const std::string & name = nameAndPath[ 0 ];
        const std::string & path = nameAndPath[ 1 ];

        // since we do not know which reader type we should instantiate for input "name",
        // we ask SuperElastix for a reader that matches the type of the source component "name"

        selx::AnyFileReader::Pointer reader = superElastixFilter->GetInputFileReader( name );
        reader->SetFileName( path );
        superElastixFilter->SetInput( name, reader->GetOutput() );
        fileReaders.push_back( reader );

        std::cout << "Input data " << index << " " << name << " : " << path << "\n";
        ++index;
      }
    }

    if( vm.count( "out" ) )
    {
      int index = 0;
      for( const auto & outputPair : outputPairs )
      {
        VectorOfStringsType nameAndPath;
        boost::split( nameAndPath, outputPair, boost::is_any_of( "=" ) );  // NameAndPath == { "name","path" }
        const std::string & name = nameAndPath[ 0 ];
        const std::string & path = nameAndPath[ 1 ];

        // since we do not know which writer type we should instantiate for output "name",
        // we ask SuperElastix for a writer that matches the type of the sink component "name"
        selx::AnyFileWriter::Pointer writer = superElastixFilter->GetOutputFileWriter( name );

        //ImageWriter2DType::Pointer writer = ImageWriter2DType::New();
        writer->SetFileName( path );
        //writer->SetInput(superElastixFilter->GetOutput<Image2DType>(name));
        writer->SetInput( superElastixFilter->GetOutput( name ) );
        fileWriters.push_back( writer );

        std::cout << "Output data " << index << " " << name << " : " << path << "\n";
        ++index;

      }
    }

    /* Execute SuperElastix by updating the writers */

    for( auto & writer : fileWriters )
    {
      writer->Update();
    }
  }
  catch( std::exception & e )
  {
    std::cerr << "error: " << e.what() << "\n";
    return 1;
  }
  catch( ... )
  {
    std::cerr << "Exception of unknown type!\n";
  }

  return 0;
}
<commit_msg>BUG: fixed #51: Crash in SuperElastix commandline application initialization of logger<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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.txt
 *
 *  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 "selxSuperElastixFilter.h"
#include "selxBlueprint.h"
#include "selxConfigurationReader.h"
#include "selxAnyFileReader.h"
#include "selxAnyFileWriter.h"
#include "selxLogger.h"

#include <boost/algorithm/string.hpp>

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <stdexcept>

template< class T >
std::ostream &
operator<<( std::ostream & os, const std::vector< T > & v )
{
  std::copy( v.begin(), v.end(), std::ostream_iterator< T >( os, " " ) );
  return os;
}

int
main( int ac, char * av[] )
{
  try
  {
    typedef std::vector< std::string > VectorOfStringsType;

    // instantiate a SuperElastixFilter that is loaded with default components
    selx::SuperElastixFilter::Pointer superElastixFilter = selx::SuperElastixFilter::New();

    // add logger
    selx::SuperElastixFilter::LoggerPointer itkLogger = selx::SuperElastixFilter::LoggerType::New();
	std::unique_ptr<selx::Logger> selxLogger(new selx::Logger());
	selxLogger->AddConsole();
	itkLogger->Set( selxLogger);

	superElastixFilter->SetLogger(itkLogger);

    fs::path            configurationPath;
    VectorOfStringsType inputPairs;
    VectorOfStringsType outputPairs;

    // Store the reader so that they will not be destroyed before the pipeline is executed.
    std::vector< selx::AnyFileReader::Pointer > fileReaders;
    // Store the writers for the update call
    //vector<ImageWriter2DType::Pointer> fileWriters;
    std::vector< selx::AnyFileWriter::Pointer > fileWriters;

    po::options_description desc( "Allowed options" );
    desc.add_options()
      ( "help", "produce help message" )
      ( "conf", po::value< fs::path >( &configurationPath )->required(), "Configuration file" )
      ( "in", po::value< VectorOfStringsType >( &inputPairs )->multitoken(), "Input data: images, labels, meshes, etc. Usage <name>=<path>" )
      ( "out", po::value< VectorOfStringsType >( &outputPairs )->multitoken(), "Output data: images, labels, meshes, etc. Usage <name>=<path>" )
      ( "graphout", po::value< fs::path >(), "Output Graphviz dot file" )
    ;

    po::variables_map vm;
    po::store( po::parse_command_line( ac, av, desc ), vm );
    po::notify( vm );

    if( vm.count( "help" ) )
    {
      std::cout << desc << "\n";
      return 0;
    }

    selx::ConfigurationReader::BlueprintPointerType blueprint = selx::ConfigurationReader::FromFile(configurationPath);

    if( vm.count( "graphout" ) )
    {
      blueprint->Write( vm[ "graphout" ].as< fs::path >().string() );
    }

    //turn the blueprint into an itkObject to connect to the superElastix itkFilter
    selx::SuperElastixFilter::BlueprintPointer itkBluePrint = selx::SuperElastixFilter::BlueprintType::New();
    itkBluePrint->Set(blueprint);
    superElastixFilter->SetBlueprint(itkBluePrint);

    if( vm.count( "in" ) )
    {
      int index = 0;
      for( const auto & inputPair : inputPairs )
      {
        VectorOfStringsType nameAndPath;
        boost::split( nameAndPath, inputPair, boost::is_any_of( "=" ) );  // NameAndPath == { "name","path" }
        const std::string & name = nameAndPath[ 0 ];
        const std::string & path = nameAndPath[ 1 ];

        // since we do not know which reader type we should instantiate for input "name",
        // we ask SuperElastix for a reader that matches the type of the source component "name"

        selx::AnyFileReader::Pointer reader = superElastixFilter->GetInputFileReader( name );
        reader->SetFileName( path );
        superElastixFilter->SetInput( name, reader->GetOutput() );
        fileReaders.push_back( reader );

        std::cout << "Input data " << index << " " << name << " : " << path << "\n";
        ++index;
      }
    }

    if( vm.count( "out" ) )
    {
      int index = 0;
      for( const auto & outputPair : outputPairs )
      {
        VectorOfStringsType nameAndPath;
        boost::split( nameAndPath, outputPair, boost::is_any_of( "=" ) );  // NameAndPath == { "name","path" }
        const std::string & name = nameAndPath[ 0 ];
        const std::string & path = nameAndPath[ 1 ];

        // since we do not know which writer type we should instantiate for output "name",
        // we ask SuperElastix for a writer that matches the type of the sink component "name"
        selx::AnyFileWriter::Pointer writer = superElastixFilter->GetOutputFileWriter( name );

        //ImageWriter2DType::Pointer writer = ImageWriter2DType::New();
        writer->SetFileName( path );
        //writer->SetInput(superElastixFilter->GetOutput<Image2DType>(name));
        writer->SetInput( superElastixFilter->GetOutput( name ) );
        fileWriters.push_back( writer );

        std::cout << "Output data " << index << " " << name << " : " << path << "\n";
        ++index;

      }
    }

    /* Execute SuperElastix by updating the writers */

    for( auto & writer : fileWriters )
    {
      writer->Update();
    }
  }
  catch( std::exception & e )
  {
    std::cerr << "error: " << e.what() << "\n";
    return 1;
  }
  catch( ... )
  {
    std::cerr << "Exception of unknown type!\n";
  }

  return 0;
}
<|endoftext|>


<commit_before>// Time:  ctor:   O(n),
//        query:  O(logn)
// Space: O(n)

/**
 * Definition of Interval:
 * classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this->start = start;
 *         this->end = end;
 *     }
 */

// Segment Tree solution.
class SegmentTreeSumNode {
public:
    int start, end;
    long long sum;
    SegmentTreeSumNode *left, *right;
    SegmentTreeSumNode(int start, int end, long long sum) {
        this->start = start;
        this->end = end;
        this->sum = sum;
        this->left = this->right = NULL;
    }
};

class Solution {
public:
    /**
     *@param A, queries: Given an integer array and an query list
     *@return: The result list
     */
    vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
        vector<long long> res;

        // Build segment tree.
        SegmentTreeSumNode *root = build(A, 0, A.size() - 1);

        // Do each query.
        for (const auto& q : queries) {
            res.emplace_back(query(root, q.start, q.end));
        }

        return res;
    }

    // Build segment tree.
    SegmentTreeSumNode *build(vector<int> &A, int start, int end) {
        if (start > end) {
            return nullptr;
        }

        // The root's start and end is given by build method.
        SegmentTreeSumNode *root = new SegmentTreeSumNode(start, end, 0);

        // If start equals to end, there will be no children for this node.
        if (start == end) {
            root->sum = A[start];
            return root;
        }

        // Left child: start=A.left, end=(A.left + A.right) / 2.
        root->left = build(A, start, (start + end) / 2);

        // Right child: start=(A.left + A.right) / 2 + 1, end=A.right.
        root->right = build(A, (start + end) / 2 + 1, end);

        long long left_sum = root->left != nullptr? root->left->sum : 0;
        long long right_sum = root->right != nullptr? root->right->sum : 0;

        // Update sum.
        root->sum = left_sum + right_sum;
        return root;
    }

    // Query sum in given range.
    long long query(SegmentTreeSumNode *root, int start, int end) {
        // Out of range.
        if (root == nullptr || root->start > end || root->end <  start) {
            return 0;
        }

        // Current segment is totally within range [start, end]
        if (root->start >= start && root->end <= end) {
            return root->sum;
        }

        long long left = query(root->left, start, end);
        long long right = query(root->right, start, end);

        // Find sum in the children.
        return left + right;
    }
};
<commit_msg>Update interval-sum.cpp<commit_after>// Time:  ctor:   O(n),
//        query:  O(logn)
// Space: O(n)

/**
 * Definition of Interval:
 * classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this->start = start;
 *         this->end = end;
 *     }
 */

// Segment Tree solution.
class SegmentTreeSumNode {
public:
    int start, end;
    long long sum;
    SegmentTreeSumNode *left, *right;
    SegmentTreeSumNode(int start, int end, long long sum) {
        this->start = start;
        this->end = end;
        this->sum = sum;
        this->left = this->right = NULL;
    }
};

class Solution {
public:
    /**
     *@param A, queries: Given an integer array and an query list
     *@return: The result list
     */
    vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
        vector<long long> res;

        // Build segment tree.
        SegmentTreeSumNode *root = build(A, 0, A.size() - 1);

        // Do each query.
        for (const auto& q : queries) {
            res.emplace_back(query(root, q.start, q.end));
        }

        return res;
    }

    // Build segment tree.
    SegmentTreeSumNode *build(vector<int> &A, int start, int end) {
        if (start > end) {
            return nullptr;
        }

        // The root's start and end is given by build method.
        SegmentTreeSumNode *root = new SegmentTreeSumNode(start, end, 0);

        // If start equals to end, there will be no children for this node.
        if (start == end) {
            root->sum = A[start];
            return root;
        }

        // Left child: start=A.left, end=(A.left + A.right) / 2.
        root->left = build(A, start, (start + end) / 2);

        // Right child: start=(A.left + A.right) / 2 + 1, end=A.right.
        root->right = build(A, (start + end) / 2 + 1, end);

        long long left_sum = root->left != nullptr? root->left->sum : 0;
        long long right_sum = root->right != nullptr? root->right->sum : 0;

        // Update sum.
        root->sum = left_sum + right_sum;
        return root;
    }

    // Query sum in given range.
    long long query(SegmentTreeSumNode *root, int start, int end) {
        // Out of range.
        if (root == nullptr || root->start > end || root->end <  start) {
            return 0;
        }

        // Current segment is totally within range [start, end]
        if (root->start >= start && root->end <= end) {
            return root->sum;
        }

        long long left = query(root->left, start, end);
        long long right = query(root->right, start, end);

        // Find sum in the children.
        return left + right;
    }
};

// Time:  ctor:   O(nlogn),
//        query:  O(logn)
// Space: O(n)
// Binary Indexed Tree (BIT) solution.
class Solution2 {
public:
    /**
     *@param A, queries: Given an integer array and an query list
     *@return: The result list
     */
    vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
        nums_ = A;

        vector<long long> res;

        bit_ = vector<long long>(nums_.size() + 1);
        for (int i = 0; i < nums_.size(); ++i) {
            add(i, nums_[i]);
        }
        for (const auto& q : queries) {
            res.emplace_back(query(q.start, q.end));
        }

        return res;
    }

private:
    vector<int> nums_;
    vector<long long> bit_;

    long long query(int start, int end) {
        long long sum = sumRegion_bit(end);
        if (start > 0) {
            sum -= sumRegion_bit(start - 1);
        }
        return sum;
    }

    long long sumRegion_bit(long long i) {
        ++i;
        long long sum = 0;
        for (; i > 0; i -= lower_bit(i)) {
            sum += bit_[i];
        }
        return sum;
    }

    void add(int i, int val) {
        ++i;
        for (; i <= nums_.size(); i += lower_bit(i)) {
            bit_[i] += val;
        }
    }

    int lower_bit(int i) {
        return i & -i;
    }
};
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: clang -shared %S/call_lib.c -o%p/libcall_lib%shlibext && ls %p/libcall_lib%shlibext && cat %s | %cling -L%p | FileCheck %s

.L libcall_lib
extern "C" int cling_testlibrary_function();
int i = cling_testlibrary_function();
extern "C" int printf(const char* fmt, ...);
printf("got i=%d\n", i); // CHECK: got i=66
.q
<commit_msg>Fix writing files to source directory, write to build directory instead.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: clang -shared %S/call_lib.c -o%T/libcall_lib%shlibext && ls %T/libcall_lib%shlibext && cat %s | %cling -L%T | FileCheck %s

.L libcall_lib
extern "C" int cling_testlibrary_function();
int i = cling_testlibrary_function();
extern "C" int printf(const char* fmt, ...);
printf("got i=%d\n", i); // CHECK: got i=66
.q
<|endoftext|>


<commit_before>// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "dxsubfilter_uuids.h"
#include "dxsubfilter.h"

//------------------------------------------------------------------------------
/* List of class IDs and creator functions for the class factory. This
   provides the link between the OLE entry point in the DLL and an object
   being created. The class factory will call the static CreateInstance
   function when it is asked to create a CLSID_SystemClock object */

CFactoryTemplate g_Templates[1] = {
    {L"CDXSubFilter", &CLSID_DXSubFilter, CDXSubFilter::CreateInstance}
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/*		DLL Entry Point			*/
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// To be self registering, OLE servers must export functions named
// DllRegisterServer and DllUnregisterServer. These are the functions that are
// called when RegSrv32.exe is run.

STDAPI DllRegisterServer()
{
	return AMovieDllRegisterServer();
}

STDAPI DllRegisterServer2(BOOL b)
{
	return AMovieDllRegisterServer2(b);
}

STDAPI DllUnregisterServer()
{
	return AMovieDllUnregisterServer();
}

<commit_msg>Apparently AMovieDllRegisterServer is obsolete.<commit_after>// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "dxsubfilter_uuids.h"
#include "dxsubfilter.h"

//------------------------------------------------------------------------------
/* List of class IDs and creator functions for the class factory. This
   provides the link between the OLE entry point in the DLL and an object
   being created. The class factory will call the static CreateInstance
   function when it is asked to create a CLSID_SystemClock object */

CFactoryTemplate g_Templates[1] = {
    {L"CDXSubFilter", &CLSID_DXSubFilter, CDXSubFilter::CreateInstance}
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/*		DLL Entry Point			*/
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// To be self registering, OLE servers must export functions named
// DllRegisterServer and DllUnregisterServer. These are the functions that are
// called when RegSrv32.exe is run.

STDAPI DllRegisterServer()
{
	return AMovieDllRegisterServer2(TRUE);
}

STDAPI DllRegisterServer2(BOOL b)
{
	return AMovieDllRegisterServer2(b);
}

STDAPI DllUnregisterServer()
{
	return AMovieDllRegisterServer2(FALSE);
}

<|endoftext|>


<commit_before>#include "webcam.hpp"

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));

// this mask filters out areas with too many edges
// removed for now; it didn't generalize well
/*
  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 200, 1, THRESH_BINARY);
  blur(canny*255, canny, Size(width/10, height/10));
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny mask", gray.mul(canny));
*/

// this mask filters out areas which have not changed much
// background needs to be updated when person is not in frame
// use OVR SDK to do this later
  Mat flow_gray, flow;
  absdiff(blurred_img, background, flow_gray);
  cvtColor(flow_gray, flow_gray, CV_RGB2GRAY);
  flow = flow_gray.clone();//inefficient but convenient
  morphFast(flow);
  threshold(flow, flow, 60, 1, THRESH_BINARY);
//  imshow("flow mask", gray.mul(flow));

// this mask gets anything kind of dark (DK2) and dilates
  Mat kindofdark;
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
//  imshow("dark mask", gray.mul(kindofdark));

  Mat mask = flow.mul(kindofdark);
  imshow("premask", gray.mul(mask));
  waitKey(1);
// open the mask
  Mat smallMask;
  resize(mask, smallMask, Size(150,150));
  Mat erodeKernel = ellipticKernel(41,81);
  erode(smallMask, smallMask, erodeKernel);
  Mat dilateKernel = ellipticKernel(41,81);
  dilate(smallMask, smallMask, dilateKernel);
  resize(smallMask, smallMask, Size(width, height));
  bitwise_and(smallMask,mask,mask);
  imshow("morph mask", gray.mul(mask));

// update background with new morph mask
// average what we know is background with prior background
// erode it first since we really want to be sure it's bg

//  Mat erodeKernel = ellipticKernel(21);
  erode(mask, mask, erodeKernel);
  Mat mask_;
  subtract(1,mask,mask_);
  Mat mask3, mask3_;
  channel[0] = mask;
  channel[1] = mask;
  channel[2] = mask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_) + blurred_img.mul(mask3_))/2;

  imshow("background", background);

  Moments lol = moments(flow_gray, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);

/*
  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  Mat classifyThis;
  blur(gray, classifyThis, Size(10,10));
//  bilateralFilter(gray, classifyThis, 15, 10, 1);
  equalizeHist(classifyThis, classifyThis);
  classifyThis = classifyThis.mul(mask);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 5, CV_HAAR_SCALE_IMAGE);
  for (size_t i=0; i<mouths.size(); i++) {
   Point center( mouths[i].x + mouths[i].width*0.5, mouths[i].y + mouths[i].height*0.5 );
   ellipse( image, center, Size( mouths[i].width*0.5, mouths[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
  }
  imshow("MOUTH", image);
*/

  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));

// this mask filters out areas with too many edges
// removed for now; it didn't generalize well
/*
  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 200, 1, THRESH_BINARY);
  blur(canny*255, canny, Size(width/10, height/10));
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny mask", gray.mul(canny));
*/

// this mask filters out areas which have not changed much
// background needs to be updated when person is not in frame
// use OVR SDK to do this later
  Mat flow_gray, flow;
  absdiff(blurred_img, background, flow_gray);
  cvtColor(flow_gray, flow_gray, CV_RGB2GRAY);
  flow = flow_gray.clone();//inefficient but convenient
  morphFast(flow);
  threshold(flow, flow, 60, 1, THRESH_BINARY);
//  imshow("flow mask", gray.mul(flow));

// this mask gets anything kind of dark (DK2) and dilates
  Mat kindofdark;
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
//  imshow("dark mask", gray.mul(kindofdark));

  Mat mask = flow.mul(kindofdark);
  imshow("premask", gray.mul(mask));
  waitKey(1);
// open the mask
  Mat smallMask;
  resize(mask, smallMask, Size(150,150));
  Mat erodeKernel = ellipticKernel(41,81);
  erode(smallMask, smallMask, erodeKernel);
  Mat dilateKernel = ellipticKernel(41,81);
  dilate(smallMask, smallMask, dilateKernel);
  resize(smallMask, smallMask, Size(width, height));
  bitwise_and(smallMask,mask,mask);
  imshow("morph mask", gray.mul(mask));

// update background with new morph mask
// average what we know is background with prior background
// erode it first since we really want to be sure it's bg

//  Mat erodeKernel = ellipticKernel(21);
  erode(mask, mask, erodeKernel);
  Mat mask_;
  subtract(1,mask,mask_);
  Mat mask3, mask3_;
  channel[0] = mask;
  channel[1] = mask;
  channel[2] = mask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_) + blurred_img.mul(mask3_))/2;

  imshow("background", background);

  Mat xkcd;
  pow(flow_gray, 4, xkcd);
  Moments lol = moments(xkcd, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);

/*
  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  Mat classifyThis;
  blur(gray, classifyThis, Size(10,10));
//  bilateralFilter(gray, classifyThis, 15, 10, 1);
  equalizeHist(classifyThis, classifyThis);
  classifyThis = classifyThis.mul(mask);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 5, CV_HAAR_SCALE_IMAGE);
  for (size_t i=0; i<mouths.size(); i++) {
   Point center( mouths[i].x + mouths[i].width*0.5, mouths[i].y + mouths[i].height*0.5 );
   ellipse( image, center, Size( mouths[i].width*0.5, mouths[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
  }
  imshow("MOUTH", image);
*/

  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));
 imshow("background", background);

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  //imshow("webcam", image);

  Mat gray;
  cvtColor(image, gray, CV_RGB2GRAY);

  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny1", canny*255);
  waitKey(1);

  int kwidth, kheight;
  if (width/2 > height) {
   kwidth = height/8;
   kheight = height/16;
  } else {
   int kwidth = width/16;
   int kheight = width/32;
  }

  kwidth += (1-(kwidth%2));//round up to nearest odd
  kheight += (1-(kheight%2));//round up to nearest odd
  Size kernelSize;
  kernelSize = Size(kwidth, kheight);
  Mat kernel = getStructuringElement(MORPH_ELLIPSE, kernelSize);

  morphologyEx(canny, canny, MORPH_OPEN, kernel);
  imshow("canny2", canny*255);
  waitKey(1);
  morphologyEx(canny, canny, MORPH_CLOSE, kernel);
  imshow("canny3", canny*255);
  waitKey(1);
  erode(canny, canny, kernel);
  imshow("canny4", canny*255);
  waitKey(1);

  Mat flow;
  blur(image, flow, Size(50,50));
  absdiff(flow, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  blur(flow, flow, Size(50,50));
  equalizeHist(flow, flow);
  Mat mask;
  threshold(flow, mask, 170, 1, THRESH_BINARY);
  mask = mask.mul(canny);
  dilate(mask, mask, kernel); // maybe repeat some more
  imshow("FLOW", gray.mul(mask));

//  Moments lol = moments(mask, 1);
//  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
//  imshow("leimage", image);

/*
  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  Mat classifyThis;
  bilateralFilter(gray, classifyThis, 15, 10, 1);
  equalizeHist(classifyThis, classifyThis);
  classifyThis = classifyThis.mul(mask);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 2, CV_HAAR_SCALE_IMAGE);
  for (size_t i=0; i<mouths.size(); i++) {
   Point center( mouths[i].x + mouths[i].width*0.5, mouths[i].y + mouths[i].height*0.5 );
   ellipse( image, center, Size( mouths[i].width*0.5, mouths[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
  }
  imshow("MOUTH", image);
*/
  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));
 imshow("background", background);

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  //imshow("webcam", image);

  Mat gray;
  cvtColor(image, gray, CV_RGB2GRAY);

  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny1", canny*255);
  waitKey(1);

  int kwidth, kheight;
  if (width/2 > height) {
   kwidth = height/4;
   kheight = height/8;
  } else {
   int kwidth = width/8;
   int kheight = width/16;
  }

  kwidth += (1-(kwidth%2));//round up to nearest odd
  kheight += (1-(kheight%2));//round up to nearest odd
  Size kernelSize;
  kernelSize = Size(kwidth, kheight);
  Mat kernel = getStructuringElement(MORPH_ELLIPSE, kernelSize);

  morphologyEx(canny, canny, MORPH_OPEN, kernel);
  imshow("canny2", canny*255);
  waitKey(1);
  morphologyEx(canny, canny, MORPH_CLOSE, kernel);
  imshow("canny3", canny*255);
  waitKey(1);
  erode(canny, canny, kernel);
  imshow("canny4", canny*255);
  waitKey(1);

  Mat flow;
  blur(image, flow, Size(50,50));
  absdiff(flow, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  blur(flow, flow, Size(50,50));
  equalizeHist(flow, flow);
  Mat mask;
  threshold(flow, mask, 170, 1, THRESH_BINARY);
  mask = mask.mul(canny);
  dilate(mask, mask, kernel); // maybe repeat some more
  imshow("FLOW", gray.mul(mask));

//  Moments lol = moments(mask, 1);
//  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
//  imshow("leimage", image);

/*
  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  Mat classifyThis;
  bilateralFilter(gray, classifyThis, 15, 10, 1);
  equalizeHist(classifyThis, classifyThis);
  classifyThis = classifyThis.mul(mask);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 2, CV_HAAR_SCALE_IMAGE);
  for (size_t i=0; i<mouths.size(); i++) {
   Point center( mouths[i].x + mouths[i].width*0.5, mouths[i].y + mouths[i].height*0.5 );
   ellipse( image, center, Size( mouths[i].width*0.5, mouths[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
  }
  imshow("MOUTH", image);
*/
  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2012 Daniel Lundin
//

#include "medida/timer_context.h"

#include "medida/timer.h"
#include "medida/types.h"

namespace medida {

class TimerContext::Impl {
 public:
  Impl(Timer& timer);
  ~Impl();
  void Reset();
  std::chrono::nanoseconds Stop();
 private:
  Clock::time_point start_time_;
  Timer& timer_;
  bool active_;
};

TimerContext::TimerContext(TimerContext&& timer)
    : impl_ {std::move(timer.impl_)} {
}

TimerContext::TimerContext(Timer& timer)
    : impl_ {new TimerContext::Impl {timer}} {
}

TimerContext::~TimerContext() {
}

void TimerContext::checkImpl() const
{
  if (!impl_)
  {
    throw std::runtime_error("Access to moved TimerContext::impl_");
  }
}

void TimerContext::Reset() {
  checkImpl();
  impl_->Reset();
}

std::chrono::nanoseconds TimerContext::Stop() {
  checkImpl();
  return std::chrono::nanoseconds(0);
}

// === Implementation ===

TimerContext::Impl::Impl(Timer& timer)
    : timer_ (timer) {  // FIXME: GCC Bug 50025 - Uniform initialization of reference members broken
  Reset();
}

TimerContext::Impl::~Impl() {
  Stop();
}

void TimerContext::Impl::Reset() {
  start_time_ = Clock::now();
  active_ = true;
}

std::chrono::nanoseconds TimerContext::Impl::Stop() {
  if (active_) {
    auto dur = Clock::now() - start_time_;
    timer_.Update(dur);
    active_ = false;
    return dur;
  }
  return std::chrono::nanoseconds(0);
}

} // namespace medida
<commit_msg>Fix TimerContext::Stop to call impl_->Stop()<commit_after>//
// Copyright (c) 2012 Daniel Lundin
//

#include "medida/timer_context.h"

#include "medida/timer.h"
#include "medida/types.h"

namespace medida {

class TimerContext::Impl {
 public:
  Impl(Timer& timer);
  ~Impl();
  void Reset();
  std::chrono::nanoseconds Stop();
 private:
  Clock::time_point start_time_;
  Timer& timer_;
  bool active_;
};

TimerContext::TimerContext(TimerContext&& timer)
    : impl_ {std::move(timer.impl_)} {
}

TimerContext::TimerContext(Timer& timer)
    : impl_ {new TimerContext::Impl {timer}} {
}

TimerContext::~TimerContext() {
}

void TimerContext::checkImpl() const
{
  if (!impl_)
  {
    throw std::runtime_error("Access to moved TimerContext::impl_");
  }
}

void TimerContext::Reset() {
  checkImpl();
  impl_->Reset();
}

std::chrono::nanoseconds TimerContext::Stop() {
  checkImpl();
  return impl_->Stop();
}

// === Implementation ===

TimerContext::Impl::Impl(Timer& timer)
    : timer_ (timer) {  // FIXME: GCC Bug 50025 - Uniform initialization of reference members broken
  Reset();
}

TimerContext::Impl::~Impl() {
  Stop();
}

void TimerContext::Impl::Reset() {
  start_time_ = Clock::now();
  active_ = true;
}

std::chrono::nanoseconds TimerContext::Impl::Stop() {
  if (active_) {
    auto dur = Clock::now() - start_time_;
    timer_.Update(dur);
    active_ = false;
    return dur;
  }
  return std::chrono::nanoseconds(0);
}

} // namespace medida
<|endoftext|>


<commit_before>#include "mem/cache/tags/splru.hh"
#include "base/intmath.hh"
#include "debug/CacheRepl.hh"
#include "mem/cache/tags/cacheset.hh"
#include "mem/cache/tags/lru.hh"
#include "mem/cache/base.hh"
#include "sim/core.hh"
#include <typeinfo>

SPLRU::SPLRU( unsigned _numSets,
        unsigned _blkSize,
        unsigned _assoc,
        unsigned _hit_latency )
    : LRU(_numSets/2, _blkSize, _assoc, _hit_latency )
{
    init_sets();
    assert( ( numSets % num_sds ) == 0 );
    warmupBound = numSets * num_sds * assoc;
}

CacheSet
SPLRU::get_set( int setnum, uint64_t tid ){
    return LRU::get_set( setnum, tid );
    assert(sets[setnum][tid]);
    return sets[setnum][tid];
}

void
SPLRU::init_sets(){
    sets = new CacheSet*[numSets];
    for( int i=0; i< numSets; ++i ) sets[i] = new CacheSet[num_sds];
    blks = new BlkType[numSets * num_sds * assoc];
    // allocate data storage in one big chunk
    numBlocks = numSets * num_sds * assoc;
    dataBlks = new uint8_t[numBlocks * blkSize];

    unsigned blkIndex = 0;       // index into blks array
    for (unsigned i = 0; i < numSets; ++i) {
        for( unsigned k=0; k < num_sds; k++ ){
            sets[i][k].assoc = assoc;

            sets[i][k].blks = new BlkType*[assoc];

            // link in the data blocks
            for (unsigned j = 0; j < assoc; ++j) {
                // locate next cache block
                BlkType *blk = &blks[blkIndex];
                blk->data = &dataBlks[blkSize*blkIndex];
                ++blkIndex;

                // invalidate new cache block
                blk->status = 0;

                //EGH Fix Me : do we need to initialize blk?

                // Setting the tag to j is just to prevent long chains in the hash
                // table; won't matter because the block is invalid
                blk->tag = j;
                blk->whenReady = 0;
                blk->isTouched = false;
                blk->size = blkSize;
                sets[i][k].blks[j]=blk;
                blk->set = i;
            }
        }
    }
}

void
SPLRU::cleanupRefs()
{
    for (unsigned i = 0; i < numSets*num_sds*assoc; ++i) {
        if (blks[i].isValid()) {
            totalRefs += blks[i].refCount;
            ++sampledRefs;
        }
    }
}
<commit_msg>SPLRU actually uses its own cache sets instead of invoking the LRU method<commit_after>#include "mem/cache/tags/splru.hh"
#include "base/intmath.hh"
#include "debug/CacheRepl.hh"
#include "mem/cache/tags/cacheset.hh"
#include "mem/cache/tags/lru.hh"
#include "mem/cache/base.hh"
#include "sim/core.hh"
#include <typeinfo>

SPLRU::SPLRU( unsigned _numSets,
        unsigned _blkSize,
        unsigned _assoc,
        unsigned _hit_latency )
    : LRU(_numSets/2, _blkSize, _assoc, _hit_latency )
{
    init_sets();
    assert( ( numSets % num_sds ) == 0 );
    warmupBound = numSets * num_sds * assoc;
}

CacheSet
SPLRU::get_set( int setnum, uint64_t tid ){
    assert(sets[setnum][tid]);
    return sets[setnum][tid];
}

void
SPLRU::init_sets(){
    sets = new CacheSet*[numSets];
    for( int i=0; i< numSets; ++i ) sets[i] = new CacheSet[num_sds];
    blks = new BlkType[numSets * num_sds * assoc];
    // allocate data storage in one big chunk
    numBlocks = numSets * num_sds * assoc;
    dataBlks = new uint8_t[numBlocks * blkSize];

    unsigned blkIndex = 0;       // index into blks array
    for (unsigned i = 0; i < numSets; ++i) {
        for( unsigned k=0; k < num_sds; k++ ){
            sets[i][k].assoc = assoc;

            sets[i][k].blks = new BlkType*[assoc];

            // link in the data blocks
            for (unsigned j = 0; j < assoc; ++j) {
                // locate next cache block
                BlkType *blk = &blks[blkIndex];
                blk->data = &dataBlks[blkSize*blkIndex];
                ++blkIndex;

                // invalidate new cache block
                blk->status = 0;

                //EGH Fix Me : do we need to initialize blk?

                // Setting the tag to j is just to prevent long chains in the hash
                // table; won't matter because the block is invalid
                blk->tag = j;
                blk->whenReady = 0;
                blk->isTouched = false;
                blk->size = blkSize;
                sets[i][k].blks[j]=blk;
                blk->set = i;
            }
        }
    }
}

void
SPLRU::cleanupRefs()
{
    for (unsigned i = 0; i < numSets*num_sds*assoc; ++i) {
        if (blks[i].isValid()) {
            totalRefs += blks[i].refCount;
            ++sampledRefs;
        }
    }
}
<|endoftext|>