<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTracker/ontologies/nco.h>
#include <QDebug>

#include "trackerchangelistener.h"
#include "qcontact.h"

using namespace SopranoLive;

TrackerChangeListener::TrackerChangeListener(QObject* parent)
:QObject(parent)
{
    SopranoLive::BackEnds::Tracker::ClassUpdateSignaler *signaler =
            SopranoLive::BackEnds::Tracker::ClassUpdateSignaler::get(
                    nco::Contact::iri());
    // Note here that we are not using
    // QAbstractItemModel signals from LiveNodes::model() because
    // node list for which notification comes is fixed. Those are used for
    // async implementation
    if (signaler)
    {
        connect(signaler, SIGNAL(subjectsAdded(const QStringList &)),
                SLOT(subjectsAdded(const QStringList &)));
        connect(signaler,
                SIGNAL(baseRemoveSubjectsd(const QStringList &)),
                SLOT(subjectsRemoved(const QStringList &)));
        connect(signaler,
                SIGNAL(subjectsChanged(const QStringList &)),
                SLOT(subjectsChanged(const QStringList &)));
    }
    //this corresponds with telepathysupport/ TrackerSink::onSimplePresenceChanged
       signaler = SopranoLive::BackEnds::Tracker::ClassUpdateSignaler::get(
                    nfo::IMAccount::iri());
        connect(signaler,
                SIGNAL(subjectsChanged(const QStringList &)),
                SLOT(imAccountChanged(const QStringList &)));

}

TrackerChangeListener::~TrackerChangeListener()
{
}
// TEMPORARY here we'll for now extract ids from tracker contact URI.
// In future need nonblocking async way to get contact ids from tracker contact urls
// let's see which signals will be used from libqttracker
QContactLocalId url2UniqueId(const QString &contactUrl)
{
    QRegExp rx("(\\d+)");
    bool conversion = false;
    QContactLocalId id = 0;
    if( rx.indexIn(contactUrl) != -1 )
    {
        id = rx.cap(1).toUInt(&conversion, 10);
    }
    if( !conversion )
        qWarning() << Q_FUNC_INFO << "unparsed uri to uniqueI:" << contactUrl;
    return id;

}

void TrackerChangeListener::subjectsAdded(const QStringList &subjects)
{
    QList<QContactLocalId> added;
    foreach(const QString &uri, subjects)
    {
        added << url2UniqueId(uri);
    }
    qDebug() << Q_FUNC_INFO << "added contactids:" << added;
    emit contactsAdded(added);
}

void TrackerChangeListener::subjectsRemoved(const QStringList &subjects)
{
    QList<QContactLocalId> added;
    foreach(const QString &uri, subjects)
    {
        added << url2UniqueId(uri);
    }
    qDebug() << Q_FUNC_INFO << "removed contactids:" << added;
    emit contactsRemoved(added);
}

// TODO data changed for full query
void TrackerChangeListener::subjectsChanged(const QStringList &subjects)
{
    QList<QContactLocalId> added;
    foreach(const QString &uri, subjects)
    {
        added << url2UniqueId(uri);
    }
    qDebug() << Q_FUNC_INFO << "changed contactids:" << added;
    emit contactsChanged(added);
}

void TrackerChangeListener::imAccountChanged(const QStringList& subjects) {
    // leave the debug output for few days as TODO remainder to fix writing to tracker
    qDebug() << Q_FUNC_INFO << subjects;

    RDFVariable RDFContact = RDFVariable::fromType<nco::PersonContact>();
    // fetch all changed contacts at once
    QSet<QUrl> urls;
    foreach(const QString &str, subjects)
        urls << QUrl(str);
    RDFContact.property<nco::hasIMAccount>().isMemberOf(urls.toList());
    RDFSelect query;
    query.addColumn("contactId", RDFContact.property<nco::contactUID>());

    QSharedPointer<AsyncQuery> request = QSharedPointer<AsyncQuery> (new AsyncQuery(query),
                       &QObject::deleteLater);
    connect(request.data(), SIGNAL(queryReady(AsyncQuery*)), SLOT(imQueryReady(AsyncQuery*)));
    pendingQueries[request.data()] = request;
}

AsyncQuery::AsyncQuery(RDFSelect selectQuery)
{
    nodes = ::tracker()->modelQuery(selectQuery);
    QObject::connect(nodes.model(), SIGNAL(modelUpdated()), this,
            SLOT(queryReady()));
}

void AsyncQuery::queryReady()
{
    emit queryReady(this);
}

void TrackerChangeListener::imQueryReady(AsyncQuery* req)
{
    if( pendingQueries.contains(req))
    {
        QSharedPointer<AsyncQuery> query = pendingQueries.take(req);
        QSet<QContactLocalId> contactsChangedPresence;
        for(int i=0; i<query->nodes->rowCount(); i++) {
            contactsChangedPresence << query->nodes->index(i, 0).data().toUInt();
        }
        if( !contactsChangedPresence.isEmpty() )
            emit contactsChanged(contactsChangedPresence.toList());
    }
}
<commit_msg>Remove duplicate ids from contactsChanged signal.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTracker/ontologies/nco.h>
#include <QDebug>

#include "trackerchangelistener.h"
#include "qcontact.h"

using namespace SopranoLive;

TrackerChangeListener::TrackerChangeListener(QObject* parent)
:QObject(parent)
{
    SopranoLive::BackEnds::Tracker::ClassUpdateSignaler *signaler =
            SopranoLive::BackEnds::Tracker::ClassUpdateSignaler::get(
                    nco::Contact::iri());
    // Note here that we are not using
    // QAbstractItemModel signals from LiveNodes::model() because
    // node list for which notification comes is fixed. Those are used for
    // async implementation
    if (signaler)
    {
        connect(signaler, SIGNAL(subjectsAdded(const QStringList &)),
                SLOT(subjectsAdded(const QStringList &)));
        connect(signaler,
                SIGNAL(baseRemoveSubjectsd(const QStringList &)),
                SLOT(subjectsRemoved(const QStringList &)));
        connect(signaler,
                SIGNAL(subjectsChanged(const QStringList &)),
                SLOT(subjectsChanged(const QStringList &)));
    }
    //this corresponds with telepathysupport/ TrackerSink::onSimplePresenceChanged
       signaler = SopranoLive::BackEnds::Tracker::ClassUpdateSignaler::get(
                    nfo::IMAccount::iri());
        connect(signaler,
                SIGNAL(subjectsChanged(const QStringList &)),
                SLOT(imAccountChanged(const QStringList &)));

}

TrackerChangeListener::~TrackerChangeListener()
{
}
// TEMPORARY here we'll for now extract ids from tracker contact URI.
// In future need nonblocking async way to get contact ids from tracker contact urls
// let's see which signals will be used from libqttracker
QContactLocalId url2UniqueId(const QString &contactUrl)
{
    QRegExp rx("(\\d+)");
    bool conversion = false;
    QContactLocalId id = 0;
    if( rx.indexIn(contactUrl) != -1 )
    {
        id = rx.cap(1).toUInt(&conversion, 10);
    }
    if( !conversion )
        qWarning() << Q_FUNC_INFO << "unparsed uri to uniqueI:" << contactUrl;
    return id;

}

void TrackerChangeListener::subjectsAdded(const QStringList &subjects)
{
    QList<QContactLocalId> added;
    foreach(const QString &uri, subjects)
    {
        added << url2UniqueId(uri);
    }
    qDebug() << Q_FUNC_INFO << "added contactids:" << added;
    emit contactsAdded(added);
}

void TrackerChangeListener::subjectsRemoved(const QStringList &subjects)
{
    QList<QContactLocalId> added;
    foreach(const QString &uri, subjects)
    {
        added << url2UniqueId(uri);
    }
    qDebug() << Q_FUNC_INFO << "removed contactids:" << added;
    emit contactsRemoved(added);
}

// TODO data changed for full query
void TrackerChangeListener::subjectsChanged(const QStringList &subjects)
{
    QList<QContactLocalId> changed;
    foreach(const QString &uri, subjects) {
        QContactLocalId id = url2UniqueId(uri);
        if (changed.contains(id) == false) {
            changed << id;
        }
    }
    qDebug() << Q_FUNC_INFO << "changed contactids:" << changed;
    emit contactsChanged(changed);
}

void TrackerChangeListener::imAccountChanged(const QStringList& subjects) {
    // leave the debug output for few days as TODO remainder to fix writing to tracker
    qDebug() << Q_FUNC_INFO << subjects;

    RDFVariable RDFContact = RDFVariable::fromType<nco::PersonContact>();
    // fetch all changed contacts at once
    QSet<QUrl> urls;
    foreach(const QString &str, subjects)
        urls << QUrl(str);
    RDFContact.property<nco::hasIMAccount>().isMemberOf(urls.toList());
    RDFSelect query;
    query.addColumn("contactId", RDFContact.property<nco::contactUID>());

    QSharedPointer<AsyncQuery> request = QSharedPointer<AsyncQuery> (new AsyncQuery(query),
                       &QObject::deleteLater);
    connect(request.data(), SIGNAL(queryReady(AsyncQuery*)), SLOT(imQueryReady(AsyncQuery*)));
    pendingQueries[request.data()] = request;
}

AsyncQuery::AsyncQuery(RDFSelect selectQuery)
{
    nodes = ::tracker()->modelQuery(selectQuery);
    QObject::connect(nodes.model(), SIGNAL(modelUpdated()), this,
            SLOT(queryReady()));
}

void AsyncQuery::queryReady()
{
    emit queryReady(this);
}

void TrackerChangeListener::imQueryReady(AsyncQuery* req)
{
    if( pendingQueries.contains(req))
    {
        QSharedPointer<AsyncQuery> query = pendingQueries.take(req);
        QSet<QContactLocalId> contactsChangedPresence;
        for(int i=0; i<query->nodes->rowCount(); i++) {
            contactsChangedPresence << query->nodes->index(i, 0).data().toUInt();
        }
        if( !contactsChangedPresence.isEmpty() )
            emit contactsChanged(contactsChangedPresence.toList());
    }
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include <sox.h>
#include <time.h>
#include "deepspeech.h"

#define N_CEP 26
#define N_CONTEXT 9

struct ds_result {
  char* string;
  double cpu_time_overall;
  double cpu_time_mfcc;
  double cpu_time_infer;
};

// DsSTT() instrumented
struct ds_result*
LocalDsSTT(DeepSpeechContext* aCtx, const short* aBuffer, size_t aBufferSize,
           int aSampleRate)
{
  float** mfcc;
  struct ds_result* res = (struct ds_result*)malloc(sizeof(struct ds_result));
  if (!res) {
    return NULL;
  }

  clock_t ds_start_time = clock();
  clock_t ds_end_mfcc = 0, ds_end_infer = 0;

  int n_frames =
    DsGetMfccFrames(aCtx, aBuffer, aBufferSize, aSampleRate, &mfcc);
  ds_end_mfcc = clock();

  res->string = DsInfer(aCtx, mfcc, n_frames);
  ds_end_infer = clock();

  DsFreeMfccFrames(mfcc, n_frames);

  res->cpu_time_overall =
    ((double) (ds_end_infer - ds_start_time)) / CLOCKS_PER_SEC;
  res->cpu_time_mfcc =
    ((double) (ds_end_mfcc  - ds_start_time)) / CLOCKS_PER_SEC;
  res->cpu_time_infer =
    ((double) (ds_end_infer - ds_end_mfcc))   / CLOCKS_PER_SEC;

  return res;
}

int
main(int argc, char **argv)
{
  if (argc < 3 || argc > 4) {
    printf("Usage: deepspeech MODEL_PATH AUDIO_PATH [-t]\n");
    printf("  MODEL_PATH\tPath to the model (protocol buffer binary file)\n");
    printf("  AUDIO_PATH\tPath to the audio file to run"
           " (any file format supported by libsox)\n");
    printf("  -t\t\tRun in benchmark mode, output mfcc & inference time\n");
    return 1;
  }

  // Initialise DeepSpeech
  DeepSpeechContext* ctx = DsInit(argv[1], N_CEP, N_CONTEXT);
  assert(ctx);

  // Initialise SOX
  assert(sox_init() == SOX_SUCCESS);

  sox_format_t* input = sox_open_read(argv[2], NULL, NULL, NULL);
  assert(input);

  int sampleRate = (int)input->signal.rate;

  // Resample/reformat the audio so we can pass it through the MFCC functions
  sox_signalinfo_t target_signal = {
      SOX_UNSPEC, // Rate
      1, // Channels
      16, // Precision
      SOX_UNSPEC, // Length
      NULL // Effects headroom multiplier
  };

  sox_encodinginfo_t target_encoding = {
    SOX_ENCODING_SIGN2, // Sample format
    16, // Bits per sample
    0.0, // Compression factor
    sox_option_default, // Should bytes be reversed
    sox_option_default, // Should nibbles be reversed
    sox_option_default, // Should bits be reversed (pairs of bits?)
    sox_false // Reverse endianness
  };

  char *buffer;
  size_t buffer_size;
  sox_format_t* output = sox_open_memstream_write(&buffer, &buffer_size,
                                                  &target_signal,
                                                  &target_encoding,
                                                  "raw", NULL);
  assert(output);

  // Setup the effects chain to decode/resample
  char* sox_args[10];
  sox_effects_chain_t* chain =
    sox_create_effects_chain(&input->encoding, &output->encoding);

  sox_effect_t* e = sox_create_effect(sox_find_effect("input"));
  sox_args[0] = (char*)input;
  assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
  assert(sox_add_effect(chain, e, &input->signal, &input->signal) ==
         SOX_SUCCESS);
  free(e);

  e = sox_create_effect(sox_find_effect("channels"));
  assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
  assert(sox_add_effect(chain, e, &input->signal, &output->signal) ==
         SOX_SUCCESS);
  free(e);

  e = sox_create_effect(sox_find_effect("output"));
  sox_args[0] = (char*)output;
  assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
  assert(sox_add_effect(chain, e, &input->signal, &output->signal) ==
         SOX_SUCCESS);
  free(e);

  // Finally run the effects chain
  sox_flow_effects(chain, NULL, NULL);
  sox_delete_effects_chain(chain);
  sox_close(output);
  sox_close(input);

  // Pass audio to DeepSpeech
  struct ds_result* result = LocalDsSTT(ctx, (const short*)buffer, buffer_size / 2, sampleRate);
  if (result) {
    if (result->string) {
      printf("%s\n", result->string);
      free(result->string);
    }

    if ((argc == 4) && (strncmp(argv[3], "-t", 3) == 0)) {
      printf("cpu_time_overall=%.05f cpu_time_mfcc=%.05f cpu_time_infer=%.05f\n",
             result->cpu_time_overall,
             result->cpu_time_mfcc,
             result->cpu_time_infer);
    }

    free(result);
  }

  // Deinitialise and quit
  DsClose(ctx);
  sox_quit();

  return 0;
}
<commit_msg>Replace sox_open_memstream_write() for OS-X. Fixes issue #461<commit_after>#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include <sox.h>
#include <time.h>
#include "deepspeech.h"
#ifdef __APPLE__
#include <unistd.h>
#endif

#define N_CEP 26
#define N_CONTEXT 9

struct ds_result {
  char* string;
  double cpu_time_overall;
  double cpu_time_mfcc;
  double cpu_time_infer;
};

// DsSTT() instrumented
struct ds_result*
LocalDsSTT(DeepSpeechContext* aCtx, const short* aBuffer, size_t aBufferSize,
           int aSampleRate)
{
  float** mfcc;
  struct ds_result* res = (struct ds_result*)malloc(sizeof(struct ds_result));
  if (!res) {
    return NULL;
  }

  clock_t ds_start_time = clock();
  clock_t ds_end_mfcc = 0, ds_end_infer = 0;

  int n_frames =
    DsGetMfccFrames(aCtx, aBuffer, aBufferSize, aSampleRate, &mfcc);
  ds_end_mfcc = clock();

  res->string = DsInfer(aCtx, mfcc, n_frames);
  ds_end_infer = clock();

  DsFreeMfccFrames(mfcc, n_frames);

  res->cpu_time_overall =
    ((double) (ds_end_infer - ds_start_time)) / CLOCKS_PER_SEC;
  res->cpu_time_mfcc =
    ((double) (ds_end_mfcc  - ds_start_time)) / CLOCKS_PER_SEC;
  res->cpu_time_infer =
    ((double) (ds_end_infer - ds_end_mfcc))   / CLOCKS_PER_SEC;

  return res;
}

int
main(int argc, char **argv)
{
  if (argc < 3 || argc > 4) {
    printf("Usage: deepspeech MODEL_PATH AUDIO_PATH [-t]\n");
    printf("  MODEL_PATH\tPath to the model (protocol buffer binary file)\n");
    printf("  AUDIO_PATH\tPath to the audio file to run"
           " (any file format supported by libsox)\n");
    printf("  -t\t\tRun in benchmark mode, output mfcc & inference time\n");
    return 1;
  }

  // Initialise DeepSpeech
  DeepSpeechContext* ctx = DsInit(argv[1], N_CEP, N_CONTEXT);
  assert(ctx);

  // Initialise SOX
  assert(sox_init() == SOX_SUCCESS);

  sox_format_t* input = sox_open_read(argv[2], NULL, NULL, NULL);
  assert(input);

  int sampleRate = (int)input->signal.rate;

  // Resample/reformat the audio so we can pass it through the MFCC functions
  sox_signalinfo_t target_signal = {
      SOX_UNSPEC, // Rate
      1, // Channels
      16, // Precision
      SOX_UNSPEC, // Length
      NULL // Effects headroom multiplier
  };

  sox_encodinginfo_t target_encoding = {
    SOX_ENCODING_SIGN2, // Sample format
    16, // Bits per sample
    0.0, // Compression factor
    sox_option_default, // Should bytes be reversed
    sox_option_default, // Should nibbles be reversed
    sox_option_default, // Should bits be reversed (pairs of bits?)
    sox_false // Reverse endianness
  };

#ifdef __APPLE__
  // It would be preferable to use sox_open_memstream_write here, but OS-X
  // doesn't support POSIX 2008, which it requires. See Issue #461.
  // Instead, we write to a temporary file.
  char* output_name = tmpnam(NULL);
  assert(output_name);
  sox_format_t* output = sox_open_write(output_name, &target_signal,
                                        &target_encoding, "raw", NULL, NULL);
#else
  char* buffer;
  size_t buffer_size;
  sox_format_t* output = sox_open_memstream_write(&buffer, &buffer_size,
                                                  &target_signal,
                                                  &target_encoding,
                                                  "raw", NULL);
#endif

  assert(output);

  // Setup the effects chain to decode/resample
  char* sox_args[10];
  sox_effects_chain_t* chain =
    sox_create_effects_chain(&input->encoding, &output->encoding);

  sox_effect_t* e = sox_create_effect(sox_find_effect("input"));
  sox_args[0] = (char*)input;
  assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
  assert(sox_add_effect(chain, e, &input->signal, &input->signal) ==
         SOX_SUCCESS);
  free(e);

  e = sox_create_effect(sox_find_effect("channels"));
  assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
  assert(sox_add_effect(chain, e, &input->signal, &output->signal) ==
         SOX_SUCCESS);
  free(e);

  e = sox_create_effect(sox_find_effect("output"));
  sox_args[0] = (char*)output;
  assert(sox_effect_options(e, 1, sox_args) == SOX_SUCCESS);
  assert(sox_add_effect(chain, e, &input->signal, &output->signal) ==
         SOX_SUCCESS);
  free(e);

  // Finally run the effects chain
  sox_flow_effects(chain, NULL, NULL);
  sox_delete_effects_chain(chain);

  // Close sox handles
  sox_close(output);
  sox_close(input);

#ifdef __APPLE__
  size_t buffer_size = (size_t)(output->olength * 2);
  char* buffer = (char*)malloc(sizeof(char) * buffer_size);
  FILE* output_file = fopen(output_name, "rb");
  assert(fread(buffer, sizeof(char), buffer_size, output_file) == buffer_size);
  fclose(output_file);
  unlink(output_name);
#endif

  // Pass audio to DeepSpeech
  struct ds_result* result = LocalDsSTT(ctx, (const short*)buffer, buffer_size / 2, sampleRate);
  free(buffer);

  if (result) {
    if (result->string) {
      printf("%s\n", result->string);
      free(result->string);
    }

    if ((argc == 4) && (strncmp(argv[3], "-t", 3) == 0)) {
      printf("cpu_time_overall=%.05f cpu_time_mfcc=%.05f cpu_time_infer=%.05f\n",
             result->cpu_time_overall,
             result->cpu_time_mfcc,
             result->cpu_time_infer);
    }

    free(result);
  }

  // Deinitialise and quit
  DsClose(ctx);
  sox_quit();

  return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.
 *
 *=========================================================================*/
// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif

#include "itkImage.h"
#include "itkDiscreteGaussianDerivativeImageFilter.h"
#include "itkMultiplyByConstantImageFilter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkImageRegionIterator.h"

namespace
{

bool NormalizeSineWave( double frequencyPerImage, unsigned int order, double pixelSpacing = 1.0 )
{
  // for an image f(x) = sin ( w*x ), where w is a measure of
  // frequency, this method verifies that the normalized scale-scale
  // is with in reasonable tolerance of the theoretical value.

  const unsigned int ImageDimension = 1;
  const unsigned int imageSize = 1024;
  const double       tol = vcl_pow( .001, 1.0 / order ); // this is
                                                         // still
                                                         // larger
                                                         // then it
                                                         // should be!

  double frequency = frequencyPerImage * 2.0 * vnl_math::pi / ( imageSize * pixelSpacing );

  // The theoretical maximal value should occour at this sigma
  double sigma_max = vcl_sqrt( double( order ) ) / frequency;

  // the theoreical maximal value of the derivative, obtained at sigma_max
  double expected_max = vcl_pow( double(order), order *0.5 ) * vcl_exp( -0.5 * order );

  typedef itk::Image< double, ImageDimension > ImageType;
  ImageType::Pointer image = ImageType::New();

  ImageType::SizeType size;
  size.Fill( imageSize );

  image->SetRegions( ImageType::RegionType( size ) );
  image->Allocate();

  ImageType::SpacingType spacing;
  spacing.Fill( pixelSpacing );

  image->SetSpacing( spacing );

  itk::ImageRegionIterator< ImageType > iter( image, image->GetBufferedRegion() );

  // create sine wave image
  while( !iter.IsAtEnd() )
    {
    ImageType::PointType p;
    image->TransformIndexToPhysicalPoint( iter.GetIndex(), p );
    const double x = p[0];
    double       value = vcl_sin( x * frequency );

    iter.Set( value );
    ++iter;
    }

  std::cout << "variance: " << vnl_math_sqr( sigma_max ) << std::endl;

  typedef itk::DiscreteGaussianDerivativeImageFilter<ImageType, ImageType> GaussianFilterType;
  GaussianFilterType::Pointer filter = GaussianFilterType::New();
  filter->SetInput( image );
  filter->SetVariance( vnl_math_sqr( sigma_max ) );
  filter->SetOrder( order );
  filter->SetUseImageSpacing( true );
  filter->SetMaximumError( .0005 );
  filter->SetMaximumKernelWidth( 500 );
  filter->SetNormalizeAcrossScale( true );

  ImageType::Pointer outputImage = filter->GetOutput();
  outputImage->Update();

  // maximal value of the first derivative
  double maxLx = itk::NumericTraits<double>::NonpositiveMin();

  itk::ImageRegionConstIterator< ImageType > oiter( outputImage, outputImage->GetBufferedRegion() );

  while ( !oiter.IsAtEnd() )
    {
    maxLx = std::max( maxLx, oiter.Get() );
    ++oiter;
    }

  // check if the maximal is obtained with a little bit smaller Gaussian
  filter->SetVariance( vnl_math_sqr( sigma_max*0.95 ) );
  outputImage->Update();
  oiter.GoToBegin();

  while ( !oiter.IsAtEnd() )
    {
    if ( maxLx < oiter.Get() &&
         vcl_abs( maxLx - oiter.Get() ) > tol )
      {
      std::cout << "FAIL: For period: " << 1.0/frequency
                << " maxLx: " << maxLx
                << " tolerance exceeded by: "
                << vcl_abs( maxLx - oiter.Get() ) << std::endl;
      return false;
      }
    ++oiter;
    }

  // check if the maximal is obtained with a little bit bigger Gaussian
  filter->SetVariance( vnl_math_sqr( sigma_max*1.05 ) );
  outputImage->Update();
  oiter.GoToBegin();

  while ( !oiter.IsAtEnd() )
    {
    if ( maxLx < oiter.Get() &&
         vcl_abs( maxLx - oiter.Get() ) > tol )
      {
      std::cout << "FAIL:  For period: " << 1.0/frequency
                << " maxLx: " << maxLx
                << " tolerance exceeded by: "
                << vcl_abs( maxLx - oiter.Get() ) << std::endl;
      return false;
      }
    ++oiter;
    }

  std::cout << "f: " << frequencyPerImage << " max: " << maxLx
            << " expected max: " << expected_max << std::endl;

  if (  vcl_abs( maxLx - expected_max ) > .01 )
    {
    std::cout << "FAIL: tolerance of expected max exceeded!" << std::endl;
    }

  return true;

}

}

int itkDiscreteGaussianDerivativeImageFilterScaleSpaceTest(int, char* [] )
{
  int pass = true;

  std::cout << " Testing First Order Gaussian" << std::endl;
  pass  &= NormalizeSineWave( 16, 1 );
  pass  &= NormalizeSineWave( 32, 1 );
  pass  &= NormalizeSineWave( 64, 1 );

  std::cout << " Testing Second Order Gaussian" << std::endl;
  pass  &= NormalizeSineWave( 16, 2 );
  pass  &= NormalizeSineWave( 32, 2 );
  pass  &= NormalizeSineWave( 64, 2 );

  std::cout << " Testing Spacing Invariance" << std::endl;
  pass  &= NormalizeSineWave( 16, 2, 0.01 );
  pass  &= NormalizeSineWave( 16, 2, 100 );

  if ( !pass )
    {
    std::cout << "Test Failed!" << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<commit_msg>COMP: fix int &= bool unsafe warning<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.
 *
 *=========================================================================*/
// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif

#include "itkImage.h"
#include "itkDiscreteGaussianDerivativeImageFilter.h"
#include "itkMultiplyByConstantImageFilter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkImageRegionIterator.h"

namespace
{

bool NormalizeSineWave( double frequencyPerImage, unsigned int order, double pixelSpacing = 1.0 )
{
  // for an image f(x) = sin ( w*x ), where w is a measure of
  // frequency, this method verifies that the normalized scale-scale
  // is with in reasonable tolerance of the theoretical value.

  const unsigned int ImageDimension = 1;
  const unsigned int imageSize = 1024;
  const double       tol = vcl_pow( .001, 1.0 / order ); // this is
                                                         // still
                                                         // larger
                                                         // then it
                                                         // should be!

  double frequency = frequencyPerImage * 2.0 * vnl_math::pi / ( imageSize * pixelSpacing );

  // The theoretical maximal value should occour at this sigma
  double sigma_max = vcl_sqrt( double( order ) ) / frequency;

  // the theoreical maximal value of the derivative, obtained at sigma_max
  double expected_max = vcl_pow( double(order), order *0.5 ) * vcl_exp( -0.5 * order );

  typedef itk::Image< double, ImageDimension > ImageType;
  ImageType::Pointer image = ImageType::New();

  ImageType::SizeType size;
  size.Fill( imageSize );

  image->SetRegions( ImageType::RegionType( size ) );
  image->Allocate();

  ImageType::SpacingType spacing;
  spacing.Fill( pixelSpacing );

  image->SetSpacing( spacing );

  itk::ImageRegionIterator< ImageType > iter( image, image->GetBufferedRegion() );

  // create sine wave image
  while( !iter.IsAtEnd() )
    {
    ImageType::PointType p;
    image->TransformIndexToPhysicalPoint( iter.GetIndex(), p );
    const double x = p[0];
    double       value = vcl_sin( x * frequency );

    iter.Set( value );
    ++iter;
    }

  std::cout << "variance: " << vnl_math_sqr( sigma_max ) << std::endl;

  typedef itk::DiscreteGaussianDerivativeImageFilter<ImageType, ImageType> GaussianFilterType;
  GaussianFilterType::Pointer filter = GaussianFilterType::New();
  filter->SetInput( image );
  filter->SetVariance( vnl_math_sqr( sigma_max ) );
  filter->SetOrder( order );
  filter->SetUseImageSpacing( true );
  filter->SetMaximumError( .0005 );
  filter->SetMaximumKernelWidth( 500 );
  filter->SetNormalizeAcrossScale( true );

  ImageType::Pointer outputImage = filter->GetOutput();
  outputImage->Update();

  // maximal value of the first derivative
  double maxLx = itk::NumericTraits<double>::NonpositiveMin();

  itk::ImageRegionConstIterator< ImageType > oiter( outputImage, outputImage->GetBufferedRegion() );

  while ( !oiter.IsAtEnd() )
    {
    maxLx = std::max( maxLx, oiter.Get() );
    ++oiter;
    }

  // check if the maximal is obtained with a little bit smaller Gaussian
  filter->SetVariance( vnl_math_sqr( sigma_max*0.95 ) );
  outputImage->Update();
  oiter.GoToBegin();

  while ( !oiter.IsAtEnd() )
    {
    if ( maxLx < oiter.Get() &&
         vcl_abs( maxLx - oiter.Get() ) > tol )
      {
      std::cout << "FAIL: For period: " << 1.0/frequency
                << " maxLx: " << maxLx
                << " tolerance exceeded by: "
                << vcl_abs( maxLx - oiter.Get() ) << std::endl;
      return false;
      }
    ++oiter;
    }

  // check if the maximal is obtained with a little bit bigger Gaussian
  filter->SetVariance( vnl_math_sqr( sigma_max*1.05 ) );
  outputImage->Update();
  oiter.GoToBegin();

  while ( !oiter.IsAtEnd() )
    {
    if ( maxLx < oiter.Get() &&
         vcl_abs( maxLx - oiter.Get() ) > tol )
      {
      std::cout << "FAIL:  For period: " << 1.0/frequency
                << " maxLx: " << maxLx
                << " tolerance exceeded by: "
                << vcl_abs( maxLx - oiter.Get() ) << std::endl;
      return false;
      }
    ++oiter;
    }

  std::cout << "f: " << frequencyPerImage << " max: " << maxLx
            << " expected max: " << expected_max << std::endl;

  if (  vcl_abs( maxLx - expected_max ) > .01 )
    {
    std::cout << "FAIL: tolerance of expected max exceeded!" << std::endl;
    }

  return true;

}

}

int itkDiscreteGaussianDerivativeImageFilterScaleSpaceTest(int, char* [] )
{
  bool pass = true;

  std::cout << " Testing First Order Gaussian" << std::endl;
  pass  &= NormalizeSineWave( 16, 1 );
  pass  &= NormalizeSineWave( 32, 1 );
  pass  &= NormalizeSineWave( 64, 1 );

  std::cout << " Testing Second Order Gaussian" << std::endl;
  pass  &= NormalizeSineWave( 16, 2 );
  pass  &= NormalizeSineWave( 32, 2 );
  pass  &= NormalizeSineWave( 64, 2 );

  std::cout << " Testing Spacing Invariance" << std::endl;
  pass  &= NormalizeSineWave( 16, 2, 0.01 );
  pass  &= NormalizeSineWave( 16, 2, 100 );

  if ( !pass )
    {
    std::cout << "Test Failed!" << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//
// Urho3D Engine
// Copyright (c) 2008-2011 Lasse rni
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "Precompiled.h"
#include "Context.h"
#include "File.h"
#include "FileSystem.h"
#include "Log.h"
#include "SharedArrayPtr.h"

#include <cstdio>

#ifdef _WIN32
#include <Windows.h>
#include <Shellapi.h>
#include <direct.h>
#include <process.h>
// Enable SHGetSpecialFolderPath on MinGW
#ifndef _MSC_VER
#define _WIN32_IE 0x0400
#endif
#include <Shlobj.h>
#else
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#define MAX_PATH 256
#endif

#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif

#include "DebugNew.h"

OBJECTTYPESTATIC(FileSystem);

FileSystem::FileSystem(Context* context) :
    Object(context)
{
}

FileSystem::~FileSystem()
{
}

bool FileSystem::SetCurrentDir(const String& pathName)
{
    if (!CheckAccess(pathName))
    {
        LOGERROR("Access denied to " + pathName);
        return false;
    }
    #ifdef _WIN32
    if (SetCurrentDirectory(GetNativePath(pathName).CString()) == FALSE)
    {
        LOGERROR("Failed to change directory to " + pathName);
        return false;
    }
    #else
    if (chdir(GetNativePath(pathName).CString()) != 0)
    {
        LOGERROR("Failed to change directory to " + pathName);
        return false;
    }
    #endif
    return true;
}

bool FileSystem::CreateDir(const String& pathName)
{
    if (!CheckAccess(pathName))
    {
        LOGERROR("Access denied to " + pathName);
        return false;
    }

    #ifdef _WIN32
    bool success = (CreateDirectory(GetNativePath(RemoveTrailingSlash(pathName)).CString(), 0) == TRUE) ||
        (GetLastError() == ERROR_ALREADY_EXISTS);
    #else
    bool success = (mkdir(GetNativePath(RemoveTrailingSlash(pathName)).CString(), S_IRWXU) == 0) || (errno == EEXIST);
    #endif

    if (success)
        LOGDEBUG("Created directory " + pathName);
    else
        LOGERROR("Failed to create directory " + pathName);

    return success;
}

int FileSystem::SystemCommand(const String& commandLine)
{
    if (allowedPaths_.Empty())
        return system(commandLine.CString());
    else
    {
        LOGERROR("Executing an external command is not allowed");
        return -1;
    }
}

int FileSystem::SystemRun(const String& fileName, const Vector<String>& arguments)
{
    #ifdef _WIN32
    if (allowedPaths_.Empty())
    {
        String fixedFileName = GetNativePath(fileName);

        PODVector<const char*> argPtrs;
        argPtrs.Push(fixedFileName.CString());
        for (unsigned i = 0; i < arguments.Size(); ++i)
            argPtrs.Push(arguments[i].CString());
        argPtrs.Push(0);

        return _spawnv(_P_WAIT, fixedFileName.CString(), &argPtrs[0]);
    }
    else
    {
        LOGERROR("Executing an external command is not allowed");
        return -1;
    }
    #else
    /// \todo Implement on Unix-like systems
    LOGERROR("SystemRun not implemented");
    return false;
    #endif
}

bool FileSystem::SystemOpen(const String& fileName, const String& mode)
{
    #ifdef _WIN32
    if (allowedPaths_.Empty())
    {
        if ((!FileExists(fileName)) && (!DirExists(fileName)))
        {
            LOGERROR("File or directory " + fileName + " not found");
            return false;
        }

        bool success = (int)ShellExecute(0, !mode.Empty() ? (char*)mode.CString() : 0,
            (char*)GetNativePath(fileName).CString(), 0, 0, SW_SHOW) > 32;
        if (!success)
            LOGERROR("Failed to open " + fileName + " externally");
        return success;
    }
    else
    {
        LOGERROR("Opening a file externally is not allowed");
        return false;
    }
    #else
    /// \todo Implement on Unix-like systems
    LOGERROR("SystemOpen not implemented");
    return false;
    #endif
}

bool FileSystem::Copy(const String& srcFileName, const String& destFileName)
{
    if (!CheckAccess(GetPath(srcFileName)))
    {
        LOGERROR("Access denied to " + srcFileName);
        return false;
    }
    if (!CheckAccess(GetPath(destFileName)))
    {
        LOGERROR("Access denied to " + destFileName);
        return false;
    }

    SharedPtr<File> srcFile(new File(context_, srcFileName, FILE_READ));
    SharedPtr<File> destFile(new File(context_, destFileName, FILE_WRITE));
    if ((!srcFile->IsOpen()) || (!destFile->IsOpen()))
        return false;

    unsigned fileSize = srcFile->GetSize();

    SharedArrayPtr<unsigned char> buffer(new unsigned char[fileSize]);
    unsigned bytesRead = srcFile->Read(buffer.GetPtr(), fileSize);
    unsigned bytesWritten = destFile->Write(buffer.GetPtr(), fileSize);

    return (bytesRead == fileSize) && (bytesWritten == fileSize);
}

bool FileSystem::Rename(const String& srcFileName, const String& destFileName)
{
    if (!CheckAccess(GetPath(srcFileName)))
    {
        LOGERROR("Access denied to " + srcFileName);
        return false;
    }
    if (!CheckAccess(GetPath(destFileName)))
    {
        LOGERROR("Access denied to " + destFileName);
        return false;
    }

    return rename(GetNativePath(srcFileName).CString(), GetNativePath(destFileName).CString()) == 0;
}

bool FileSystem::Delete(const String& fileName)
{
    if (!CheckAccess(GetPath(fileName)))
    {
        LOGERROR("Access denied to " + fileName);
        return false;
    }

    return remove(GetNativePath(fileName).CString()) == 0;
}

String FileSystem::GetCurrentDir()
{
    char path[MAX_PATH];
    path[0] = 0;

    #ifdef _WIN32
    GetCurrentDirectory(MAX_PATH, path);
    #else
    getcwd(path, MAX_PATH);
    #endif

    return AddTrailingSlash(String(path));
}

bool FileSystem::CheckAccess(const String& pathName)
{
    String fixedPath = AddTrailingSlash(pathName);

    // If no allowed directories defined, succeed always
    if (allowedPaths_.Empty())
        return true;

    // If there is any attempt to go to a parent directory, disallow
    if (fixedPath.Find("..") != String::NPOS)
        return false;

    // Check if the path is a partial match of any of the allowed directories
    for (Set<String>::ConstIterator i = allowedPaths_.Begin(); i != allowedPaths_.End(); ++i)
    {
        if (fixedPath.Find(*i) == 0)
            return true;
    }

    // Not found, so disallow
    return false;
}

bool FileSystem::FileExists(const String& fileName)
{
    if (!CheckAccess(GetPath(fileName)))
        return false;

    String fixedName = GetNativePath(RemoveTrailingSlash(fileName));
    #ifdef _WIN32
    DWORD attributes = GetFileAttributes(fixedName.CString());
    if ((attributes == INVALID_FILE_ATTRIBUTES) || (attributes & FILE_ATTRIBUTE_DIRECTORY))
        return false;
    #else
    struct stat st;
    if ((stat(fixedName.CString(), &st)) || (st.st_mode & S_IFDIR))
        return false;
    #endif

    return true;
}

bool FileSystem::DirExists(const String& pathName)
{
    if (!CheckAccess(pathName))
        return false;

    String fixedName = GetNativePath(RemoveTrailingSlash(pathName));
    #ifdef _WIN32
    DWORD attributes = GetFileAttributes(fixedName.CString());
    if ((attributes == INVALID_FILE_ATTRIBUTES) || (!(attributes & FILE_ATTRIBUTE_DIRECTORY)))
        return false;
    #else
    struct stat st;
    if ((stat(fixedName.CString(), &st)) || (!(st.st_mode & S_IFDIR)))
        return false;
    #endif

    return true;
}

void FileSystem::ScanDir(Vector<String>& result, const String& pathName, const String& filter, unsigned flags, bool recursive)
{
    result.Clear();

    if (CheckAccess(pathName))
    {
        String initialPath = AddTrailingSlash(pathName);
        ScanDirInternal(result, initialPath, initialPath, filter, flags, recursive);
    }
}

String FileSystem::GetProgramDir()
{
    char exeName[MAX_PATH];
    exeName[0] = 0;

    #ifdef _WIN32
    GetModuleFileName(0, exeName, MAX_PATH);
    #endif
    #ifdef __APPLE__
    unsigned size = MAX_PATH;
    _NSGetExecutablePath(exeName, &size);
    #endif
    #ifdef __linux__
    unsigned pid = getpid();
    String link = "/proc/" + String(pid) + "/exe";
    readlink(link.CString(), exeName, MAX_PATH);
    #endif

    return GetPath(String(exeName));
}

String FileSystem::GetUserDocumentsDir()
{
    char pathName[MAX_PATH];
    pathName[0] = 0;
    #ifdef _WIN32
    SHGetSpecialFolderPath(0, pathName, CSIDL_PERSONAL, 0);
    #else
    strcpy(pathName, getenv("HOME"));
    #endif
    return AddTrailingSlash(String(pathName));
}

void FileSystem::RegisterPath(const String& pathName)
{
    if (pathName.Empty())
        return;

    allowedPaths_.Insert(AddTrailingSlash(pathName));
}

void FileSystem::ScanDirInternal(Vector<String>& result, String path, const String& startPath,
    const String& filter, unsigned flags, bool recursive)
{
    path = AddTrailingSlash(path);
    String pathAndFilter = GetNativePath(path + filter);
    String deltaPath;
    if (path.Length() > startPath.Length())
        deltaPath = path.Substring(startPath.Length());

    #ifdef _WIN32
    WIN32_FIND_DATA info;
    HANDLE handle = FindFirstFile(pathAndFilter.CString(), &info);
    if (handle != INVALID_HANDLE_VALUE)
    {
        do
        {
            String fileName((const char*)&info.cFileName[0]);
            if (!fileName.Empty())
            {
                if ((info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) && (!(flags & SCAN_HIDDEN)))
                    continue;
                if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    if (flags & SCAN_DIRS)
                        result.Push(deltaPath + fileName);
                    if ((recursive) && (fileName != ".") && (fileName != ".."))
                        ScanDirInternal(result, path + fileName, startPath, filter, flags, recursive);
                }
                else if (flags & SCAN_FILES)
                    result.Push(deltaPath + fileName);
            }
        }
        while (FindNextFile(handle, &info));

        FindClose(handle);
    }
    #else
    DIR *dir;
    struct dirent *de;
    struct stat st;
    dir = opendir(GetNativePath(path).CString());
    if (dir)
    {
        while (de = readdir(dir))
        {
            String fileName(de->d_name);
            String pathAndName = path + fileName;
            if (!stat(pathAndName.CString(), &st))
            {
                if (st.st_mode & S_IFDIR)
                {
                    if (flags & SCAN_DIRS)
                        result.Push(deltaPath + fileName);
                    if ((recursive) && (fileName != ".") && (fileName != ".."))
                        ScanDirInternal(result, path + fileName, startPath, filter, flags, recursive);
                }
                else if (flags & SCAN_FILES)
                    result.Push(deltaPath + fileName);
            }
        }
        closedir(dir);
    }
    #endif
}

void SplitPath(const String& fullPath, String& pathName, String& fileName, String& extension)
{
    String fullPathCopy = GetInternalPath(fullPath);

    unsigned extPos = fullPathCopy.FindLast('.');
    if (extPos != String::NPOS)
    {
        extension = fullPathCopy.Substring(extPos).ToLower();
        fullPathCopy = fullPathCopy.Substring(0, extPos);
    }
    else
        extension.Clear();

    unsigned pathPos = fullPathCopy.FindLast('/');
    if (pathPos != String::NPOS)
    {
        fileName = fullPathCopy.Substring(pathPos + 1);
        pathName = fullPathCopy.Substring(0, pathPos + 1);
    }
    else
    {
        fileName = fullPathCopy;
        pathName.Clear();
    }
}

String GetPath(const String& fullPath)
{
    String path, file, extension;
    SplitPath(fullPath, path, file, extension);
    return path;
}

String GetFileName(const String& fullPath)
{
    String path, file, extension;
    SplitPath(fullPath, path, file, extension);
    return file;
}

String GetExtension(const String& fullPath)
{
    String path, file, extension;
    SplitPath(fullPath, path, file, extension);
    return extension;
}

String GetFileNameAndExtension(const String& fileName)
{
    String path, file, extension;
    SplitPath(fileName, path, file, extension);
    return file + extension;
}

String AddTrailingSlash(const String& pathName)
{
    String ret = pathName;
    ret.Replace('\\', '/');
    if ((!ret.Empty()) && (ret.Back() != '/'))
        ret += '/';

    return ret;
}

String RemoveTrailingSlash(const String& pathName)
{
    String ret = pathName;
    ret.Replace('\\', '/');
    if ((!ret.Empty()) && (ret.Back() == '/'))
        ret.Resize(ret.Length() - 1);

    return ret;
}

String GetParentPath(const String& path)
{
    unsigned pos = RemoveTrailingSlash(path).FindLast('/');
    if (pos != String::NPOS)
        return path.Substring(0, pos + 1);
    else
        return String();
}

String GetInternalPath(const String& pathName)
{
    String ret = pathName;
    ret.Replace('\\', '/');

    return ret;
}

String GetNativePath(const String& pathName)
{
#ifdef _WIN32
    String ret = pathName;
    ret.Replace('/', '\\');
    return ret;
#else
    return pathName;
#endif
}
<commit_msg>Fixed GetProgramDir() to clear the whole buffer. Implemented SystemRun() on Unix.<commit_after>//
// Urho3D Engine
// Copyright (c) 2008-2011 Lasse rni
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "Precompiled.h"
#include "Context.h"
#include "File.h"
#include "FileSystem.h"
#include "Log.h"
#include "SharedArrayPtr.h"

#include <cstdio>
#include <cstring>

#ifdef _WIN32
#include <Windows.h>
#include <Shellapi.h>
#include <direct.h>
#include <process.h>
// Enable SHGetSpecialFolderPath on MinGW
#ifndef _MSC_VER
#define _WIN32_IE 0x0400
#endif
#include <Shlobj.h>
#else
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define MAX_PATH 256
#endif

#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif

#include "DebugNew.h"

OBJECTTYPESTATIC(FileSystem);

FileSystem::FileSystem(Context* context) :
    Object(context)
{
}

FileSystem::~FileSystem()
{
}

bool FileSystem::SetCurrentDir(const String& pathName)
{
    if (!CheckAccess(pathName))
    {
        LOGERROR("Access denied to " + pathName);
        return false;
    }
    #ifdef _WIN32
    if (SetCurrentDirectory(GetNativePath(pathName).CString()) == FALSE)
    {
        LOGERROR("Failed to change directory to " + pathName);
        return false;
    }
    #else
    if (chdir(GetNativePath(pathName).CString()) != 0)
    {
        LOGERROR("Failed to change directory to " + pathName);
        return false;
    }
    #endif
    return true;
}

bool FileSystem::CreateDir(const String& pathName)
{
    if (!CheckAccess(pathName))
    {
        LOGERROR("Access denied to " + pathName);
        return false;
    }

    #ifdef _WIN32
    bool success = (CreateDirectory(GetNativePath(RemoveTrailingSlash(pathName)).CString(), 0) == TRUE) ||
        (GetLastError() == ERROR_ALREADY_EXISTS);
    #else
    bool success = (mkdir(GetNativePath(RemoveTrailingSlash(pathName)).CString(), S_IRWXU) == 0) || (errno == EEXIST);
    #endif

    if (success)
        LOGDEBUG("Created directory " + pathName);
    else
        LOGERROR("Failed to create directory " + pathName);

    return success;
}

int FileSystem::SystemCommand(const String& commandLine)
{
    if (allowedPaths_.Empty())
        return system(commandLine.CString());
    else
    {
        LOGERROR("Executing an external command is not allowed");
        return -1;
    }
}

int FileSystem::SystemRun(const String& fileName, const Vector<String>& arguments)
{
    if (allowedPaths_.Empty())
    {
        String fixedFileName = GetNativePath(fileName);

        #ifdef _WIN32
        PODVector<const char*> argPtrs;
        argPtrs.Push(fixedFileName.CString());
        for (unsigned i = 0; i < arguments.Size(); ++i)
            argPtrs.Push(arguments[i].CString());
        argPtrs.Push(0);

        return _spawnv(_P_WAIT, fixedFileName.CString(), &argPtrs[0]);
        #else
        pid_t pid = fork();
        if (!pid)
        {
            PODVector<const char*> argPtrs;
            argPtrs.Push(fixedFileName.CString());
            for (unsigned i = 0; i < arguments.Size(); ++i)
                argPtrs.Push(arguments[i].CString());
            argPtrs.Push(0);

            execvp(argPtrs[0], (char**)&argPtrs[0]);
            return -1; // Return -1 if we could not spawn the process
        }
        else if (pid > 0)
        {
            int exitCode;
            wait(&exitCode);
            return exitCode ? 1 : 0;
        }
        else
        {
            LOGERROR("Failed to fork");
            return -1;
        }
        #endif
    }
    else
    {
        LOGERROR("Executing an external command is not allowed");
        return -1;
    }
}

bool FileSystem::SystemOpen(const String& fileName, const String& mode)
{
    #ifdef _WIN32
    if (allowedPaths_.Empty())
    {
        if ((!FileExists(fileName)) && (!DirExists(fileName)))
        {
            LOGERROR("File or directory " + fileName + " not found");
            return false;
        }

        bool success = (int)ShellExecute(0, !mode.Empty() ? (char*)mode.CString() : 0,
            (char*)GetNativePath(fileName).CString(), 0, 0, SW_SHOW) > 32;
        if (!success)
            LOGERROR("Failed to open " + fileName + " externally");
        return success;
    }
    else
    {
        LOGERROR("Opening a file externally is not allowed");
        return false;
    }
    #else
    /// \todo Implement on Unix-like systems
    LOGERROR("SystemOpen not implemented");
    return false;
    #endif
}

bool FileSystem::Copy(const String& srcFileName, const String& destFileName)
{
    if (!CheckAccess(GetPath(srcFileName)))
    {
        LOGERROR("Access denied to " + srcFileName);
        return false;
    }
    if (!CheckAccess(GetPath(destFileName)))
    {
        LOGERROR("Access denied to " + destFileName);
        return false;
    }

    SharedPtr<File> srcFile(new File(context_, srcFileName, FILE_READ));
    SharedPtr<File> destFile(new File(context_, destFileName, FILE_WRITE));
    if ((!srcFile->IsOpen()) || (!destFile->IsOpen()))
        return false;

    unsigned fileSize = srcFile->GetSize();

    SharedArrayPtr<unsigned char> buffer(new unsigned char[fileSize]);
    unsigned bytesRead = srcFile->Read(buffer.GetPtr(), fileSize);
    unsigned bytesWritten = destFile->Write(buffer.GetPtr(), fileSize);

    return (bytesRead == fileSize) && (bytesWritten == fileSize);
}

bool FileSystem::Rename(const String& srcFileName, const String& destFileName)
{
    if (!CheckAccess(GetPath(srcFileName)))
    {
        LOGERROR("Access denied to " + srcFileName);
        return false;
    }
    if (!CheckAccess(GetPath(destFileName)))
    {
        LOGERROR("Access denied to " + destFileName);
        return false;
    }

    return rename(GetNativePath(srcFileName).CString(), GetNativePath(destFileName).CString()) == 0;
}

bool FileSystem::Delete(const String& fileName)
{
    if (!CheckAccess(GetPath(fileName)))
    {
        LOGERROR("Access denied to " + fileName);
        return false;
    }

    return remove(GetNativePath(fileName).CString()) == 0;
}

String FileSystem::GetCurrentDir()
{
    char path[MAX_PATH];
    path[0] = 0;

    #ifdef _WIN32
    GetCurrentDirectory(MAX_PATH, path);
    #else
    getcwd(path, MAX_PATH);
    #endif

    return AddTrailingSlash(String(path));
}

bool FileSystem::CheckAccess(const String& pathName)
{
    String fixedPath = AddTrailingSlash(pathName);

    // If no allowed directories defined, succeed always
    if (allowedPaths_.Empty())
        return true;

    // If there is any attempt to go to a parent directory, disallow
    if (fixedPath.Find("..") != String::NPOS)
        return false;

    // Check if the path is a partial match of any of the allowed directories
    for (Set<String>::ConstIterator i = allowedPaths_.Begin(); i != allowedPaths_.End(); ++i)
    {
        if (fixedPath.Find(*i) == 0)

            return true;
    }

    // Not found, so disallow
    return false;
}

bool FileSystem::FileExists(const String& fileName)
{
    if (!CheckAccess(GetPath(fileName)))
        return false;

    String fixedName = GetNativePath(RemoveTrailingSlash(fileName));
    #ifdef _WIN32
    DWORD attributes = GetFileAttributes(fixedName.CString());
    if ((attributes == INVALID_FILE_ATTRIBUTES) || (attributes & FILE_ATTRIBUTE_DIRECTORY))
        return false;
    #else
    struct stat st;
    if ((stat(fixedName.CString(), &st)) || (st.st_mode & S_IFDIR))
        return false;
    #endif

    return true;
}

bool FileSystem::DirExists(const String& pathName)
{
    if (!CheckAccess(pathName))
        return false;

    String fixedName = GetNativePath(RemoveTrailingSlash(pathName));
    #ifdef _WIN32
    DWORD attributes = GetFileAttributes(fixedName.CString());
    if ((attributes == INVALID_FILE_ATTRIBUTES) || (!(attributes & FILE_ATTRIBUTE_DIRECTORY)))
        return false;
    #else
    struct stat st;
    if ((stat(fixedName.CString(), &st)) || (!(st.st_mode & S_IFDIR)))
        return false;
    #endif

    return true;
}

void FileSystem::ScanDir(Vector<String>& result, const String& pathName, const String& filter, unsigned flags, bool recursive)
{
    result.Clear();

    if (CheckAccess(pathName))
    {
        String initialPath = AddTrailingSlash(pathName);
        ScanDirInternal(result, initialPath, initialPath, filter, flags, recursive);
    }
}

String FileSystem::GetProgramDir()
{
    char exeName[MAX_PATH];
    memset(exeName, 0, MAX_PATH);

    #ifdef _WIN32
    GetModuleFileName(0, exeName, MAX_PATH);
    #endif
    #ifdef __APPLE__
    unsigned size = MAX_PATH;
    _NSGetExecutablePath(exeName, &size);
    #endif
    #ifdef __linux__
    pid_t pid = getpid();
    String link = "/proc/" + String(pid) + "/exe";
    readlink(link.CString(), exeName, MAX_PATH);
    #endif

    return GetPath(String(exeName));
}

String FileSystem::GetUserDocumentsDir()
{
    char pathName[MAX_PATH];
    pathName[0] = 0;
    #ifdef _WIN32
    SHGetSpecialFolderPath(0, pathName, CSIDL_PERSONAL, 0);
    #else
    strcpy(pathName, getenv("HOME"));
    #endif
    return AddTrailingSlash(String(pathName));
}

void FileSystem::RegisterPath(const String& pathName)
{
    if (pathName.Empty())
        return;

    allowedPaths_.Insert(AddTrailingSlash(pathName));
}

void FileSystem::ScanDirInternal(Vector<String>& result, String path, const String& startPath,
    const String& filter, unsigned flags, bool recursive)
{
    path = AddTrailingSlash(path);
    String pathAndFilter = GetNativePath(path + filter);
    String deltaPath;
    if (path.Length() > startPath.Length())
        deltaPath = path.Substring(startPath.Length());

    #ifdef _WIN32
    WIN32_FIND_DATA info;
    HANDLE handle = FindFirstFile(pathAndFilter.CString(), &info);
    if (handle != INVALID_HANDLE_VALUE)
    {
        do
        {
            String fileName((const char*)&info.cFileName[0]);
            if (!fileName.Empty())
            {
                if ((info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) && (!(flags & SCAN_HIDDEN)))
                    continue;
                if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    if (flags & SCAN_DIRS)
                        result.Push(deltaPath + fileName);
                    if ((recursive) && (fileName != ".") && (fileName != ".."))
                        ScanDirInternal(result, path + fileName, startPath, filter, flags, recursive);
                }
                else if (flags & SCAN_FILES)
                    result.Push(deltaPath + fileName);
            }
        }
        while (FindNextFile(handle, &info));

        FindClose(handle);
    }
    #else
    DIR *dir;
    struct dirent *de;
    struct stat st;
    dir = opendir(GetNativePath(path).CString());
    if (dir)
    {
        while (de = readdir(dir))
        {
            String fileName(de->d_name);
            String pathAndName = path + fileName;
            if (!stat(pathAndName.CString(), &st))
            {
                if (st.st_mode & S_IFDIR)
                {
                    if (flags & SCAN_DIRS)
                        result.Push(deltaPath + fileName);
                    if ((recursive) && (fileName != ".") && (fileName != ".."))
                        ScanDirInternal(result, path + fileName, startPath, filter, flags, recursive);
                }
                else if (flags & SCAN_FILES)
                    result.Push(deltaPath + fileName);
            }
        }
        closedir(dir);
    }
    #endif
}

void SplitPath(const String& fullPath, String& pathName, String& fileName, String& extension)
{
    String fullPathCopy = GetInternalPath(fullPath);

    unsigned extPos = fullPathCopy.FindLast('.');
    if (extPos != String::NPOS)
    {
        extension = fullPathCopy.Substring(extPos).ToLower();
        fullPathCopy = fullPathCopy.Substring(0, extPos);
    }
    else
        extension.Clear();

    unsigned pathPos = fullPathCopy.FindLast('/');
    if (pathPos != String::NPOS)
    {
        fileName = fullPathCopy.Substring(pathPos + 1);
        pathName = fullPathCopy.Substring(0, pathPos + 1);
    }
    else
    {
        fileName = fullPathCopy;
        pathName.Clear();
    }
}

String GetPath(const String& fullPath)
{
    String path, file, extension;
    SplitPath(fullPath, path, file, extension);
    return path;
}

String GetFileName(const String& fullPath)
{
    String path, file, extension;
    SplitPath(fullPath, path, file, extension);
    return file;
}

String GetExtension(const String& fullPath)
{
    String path, file, extension;
    SplitPath(fullPath, path, file, extension);
    return extension;
}

String GetFileNameAndExtension(const String& fileName)
{
    String path, file, extension;
    SplitPath(fileName, path, file, extension);
    return file + extension;
}

String AddTrailingSlash(const String& pathName)
{
    String ret = pathName;
    ret.Replace('\\', '/');
    if ((!ret.Empty()) && (ret.Back() != '/'))
        ret += '/';

    return ret;
}

String RemoveTrailingSlash(const String& pathName)
{
    String ret = pathName;
    ret.Replace('\\', '/');
    if ((!ret.Empty()) && (ret.Back() == '/'))
        ret.Resize(ret.Length() - 1);

    return ret;
}

String GetParentPath(const String& path)
{
    unsigned pos = RemoveTrailingSlash(path).FindLast('/');
    if (pos != String::NPOS)
        return path.Substring(0, pos + 1);
    else
        return String();
}

String GetInternalPath(const String& pathName)
{
    String ret = pathName;
    ret.Replace('\\', '/');

    return ret;
}

String GetNativePath(const String& pathName)
{
#ifdef _WIN32
    String ret = pathName;
    ret.Replace('/', '\\');
    return ret;
#else
    return pathName;
#endif
}
<|endoftext|>


<commit_before>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2020 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
***********************************************************************************************************************
* @file  GfxRegHandler.cpp
* @brief LLPC source file: Implementation of LLPC utility class GfxRegHandler
***********************************************************************************************************************
*/
#include "lgc/util/GfxRegHandler.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"

using namespace lgc;
using namespace llvm;

// =====================================================================================================================
//
// @param builder : The builder handle
// @param reg : The registered target vec <n x i32>
GfxRegHandler::GfxRegHandler(IRBuilder<> *builder, Value *reg) : GfxRegHandlerBase(builder, reg) {
  m_one = builder->getInt32(1);
}

// =====================================================================================================================
// Common function for getting the current value for the hardware register
//
// @param regId : The register ID, which is the index of BitsInfo and BitsState
Value *GfxRegHandler::getRegCommon(unsigned regId) {
  // Under two condition, we need to fetch the range of bits
  //  - The register has not being initialized
  //  - The register is being modified
  if (!m_bitsState[regId].value || m_bitsState[regId].isModified) {
    // Fetch bits according to BitsInfo
    m_bitsState[regId].value = getBits(m_bitsInfo[regId]);
  }

  // Since the specified range of bits is cached, set it unmodified
  m_bitsState[regId].isModified = 0;

  // Return the cached value
  return m_bitsState[regId].value;
}

// =====================================================================================================================
// Get combined data from two seperate dwords
// Note: The return type is one dword, it doesn't support two dwords for now.
// TODO: Expand to support 2-dwords combination result.
//
// @param regIdLo : The ID of low part register
// @param regIdHi : Reg ID of high part register
Value *GfxRegHandler::getRegCombine(unsigned regIdLo, unsigned regIdHi) {
  Value *regValueLo = getRegCommon(regIdLo);
  Value *regValueHi = getRegCommon(regIdHi);
  return m_builder->CreateOr(m_builder->CreateShl(regValueHi, m_bitsInfo[regIdLo].count), regValueLo);
}

// =====================================================================================================================
// Set register value into two seperate dwords
// Note: The input pRegValue only supports one dword
//
// @param regIdLo : The ID of low part register
// @param regIdHi : Reg ID of high part register
// @param regValue : Data used for setting
void GfxRegHandler::setRegCombine(unsigned regIdLo, unsigned regIdHi, Value *regValue) {
  Value *regValueLo =
      m_builder->CreateIntrinsic(Intrinsic::amdgcn_ubfe, m_builder->getInt32Ty(),
                                 {regValue, m_builder->getInt32(0), m_builder->getInt32(m_bitsInfo[regIdLo].count)});

  Value *regValueHi = m_builder->CreateLShr(regValue, m_builder->getInt32(m_bitsInfo[regIdLo].count));

  setRegCommon(regIdLo, regValueLo);
  setRegCommon(regIdHi, regValueHi);
}

// =====================================================================================================================
// SqImgSampReg Bits infomation look up table (Gfx9-10)
// Refer to imported/chip/gfx9/gfx9_plus_merged_registers.h : SQ_IMG_SAMP_WORD
static constexpr BitsInfo SqImgSampRegBitsGfx9[static_cast<unsigned>(SqSampRegs::Count)] = {
    {0, 30, 2}, // FilterMode
    {2, 20, 2}, // XyMagFilter
    {2, 22, 2}, // XyMinFilter
};

// =====================================================================================================================
// Helper class for handling Registers defined in SQ_IMG_SAMP_WORD
//
// @param builder : Bound builder context
// @param reg : Bound register vec <n x i32>
// @param gfxIpVersion : Target GFX IP version
SqImgSampRegHandler::SqImgSampRegHandler(IRBuilder<> *builder, Value *reg, GfxIpVersion *gfxIpVersion)
    : GfxRegHandler(builder, reg) {
  m_gfxIpVersion = gfxIpVersion;

  switch (gfxIpVersion->major) {
  case 6:
  case 7:
  case 8:
  case 9:
  case 10:
    m_bitsInfo = SqImgSampRegBitsGfx9;
    break;
  default:
    llvm_unreachable("GFX IP is not supported!");
    break;
  }
  setBitsState(m_bitsState);
}

// =====================================================================================================================
// Get the current value for the hardware register
//
// @param regId : Register ID
Value *SqImgSampRegHandler::getReg(SqSampRegs regId) {
  switch (regId) {
  case SqSampRegs::FilterMode:
  case SqSampRegs::xyMagFilter:
  case SqSampRegs::xyMinFilter:
    return getRegCommon(static_cast<unsigned>(regId));
  default:
    // TODO: More will be implemented.
    llvm_unreachable("Not implemented!");
    break;
  }
  return nullptr;
}

// =====================================================================================================================
// Set the current value for the hardware register
//
// @param regId : Register ID
// @param regValue : Value to set to this register
void SqImgSampRegHandler::setReg(SqSampRegs regId, Value *regValue) {
  switch (regId) {
  case SqSampRegs::FilterMode:
  case SqSampRegs::xyMagFilter:
  case SqSampRegs::xyMinFilter:
    setRegCommon(static_cast<unsigned>(regId), regValue);
    break;
  default:
    llvm_unreachable("Bad SqImgSampRegHandler::SetReg!");
    break;
  }
}

// =====================================================================================================================
// SqImgSampReg Bits information look up table (Gfx6,7,8)
// Refer to imported/chip/gfx6/si_ci_merged_registers.h : SQ_IMG_RSRC_WORD
static constexpr BitsInfo SqImgRsrcRegBitsGfx6[static_cast<unsigned>(SqRsrcRegs::Count)] = {
    {0, 0, 32},  // BaseAddress
    {1, 0, 8},   // BaseAddressHi
    {1, 20, 6},  // Format
    {2, 0, 14},  // Width
    {2, 14, 14}, // Height
    {3, 0, 12},  // DstSelXYZW
    {},          // SwizzleMode
    {4, 0, 13},  // Depth
    {4, 13, 14}, // Pitch
    {},          // BcSwizzle
    {3, 12, 4},  // BaseLevel
    {3, 16, 4},  // LastLevel
    {5, 0, 13},  // BaseArray
    {5, 13, 13}, // LastArray
    {},          // WidthLo
    {},          // WidthHi
};

// =====================================================================================================================
// SqImgSampReg Bits information look up table (Gfx9)
// Refer to imported/chip/gfx9/gfx9_plus_merged_registers.h : SQ_IMG_RSRC_WORD
static constexpr BitsInfo SqImgRsrcRegBitsGfx9[static_cast<unsigned>(SqRsrcRegs::Count)] = {
    {0, 0, 32},  // BaseAddress
    {1, 0, 8},   // BaseAddressHi
    {1, 20, 9},  // Format
    {2, 0, 14},  // Width
    {2, 14, 14}, // Height
    {3, 0, 12},  // DstSelXYZW
    {3, 20, 5},  // SwizzleMode
    {4, 0, 13},  // Depth
    {4, 13, 12}, // Pitch
    {4, 29, 3},  // BcSwizzle
    {3, 12, 4},  // BaseLevel
    {3, 16, 4},  // LastLevel
    {5, 0, 13},  // BaseArray
    {},          // LastArray
    {},          // WidthLo
    {},          // WidthHi
};

// =====================================================================================================================
// SqImgSampReg Bits information look up table (Gfx10)
// TODO: update comment when the registers file is available
static constexpr BitsInfo SqImgRsrcRegBitsGfx10[static_cast<unsigned>(SqRsrcRegs::Count)] = {
    {0, 0, 32},  // BaseAddress
    {1, 0, 8},   // BaseAddressHi
    {1, 20, 9},  // Format
    {},          // Width
    {2, 14, 16}, // Height
    {3, 0, 12},  // DstSelXYZW
    {3, 20, 5},  // SwizzleMode
    {4, 0, 16},  // Depth
    {},          // Pitch
    {3, 25, 3},  // BcSwizzle
    {3, 12, 4},  // BaseLevel
    {3, 16, 4},  // LastLevel
    {4, 16, 16}, // BaseArray
    {},          // LastArray
    {1, 30, 2},  // WidthLo
    {2, 0, 14},  // WidthHi
};

// =====================================================================================================================
// Helper class for handling Registers defined in SQ_IMG_RSRC_WORD
//
// @param builder : Bound builder context
// @param reg : Bound register vec <n x i32>
// @param gfxIpVersion : Current GFX IP version
SqImgRsrcRegHandler::SqImgRsrcRegHandler(IRBuilder<> *builder, Value *reg, GfxIpVersion *gfxIpVersion)
    : GfxRegHandler(builder, reg) {
  m_gfxIpVersion = gfxIpVersion;

  switch (gfxIpVersion->major) {
  case 6:
  case 7:
  case 8:
    m_bitsInfo = SqImgRsrcRegBitsGfx6;
    break;
  case 9:
    m_bitsInfo = SqImgRsrcRegBitsGfx9;
    break;
  case 10:
    m_bitsInfo = SqImgRsrcRegBitsGfx10;
    break;
  default:
    llvm_unreachable("GFX IP is not supported!");
    break;
  }
  setBitsState(m_bitsState);
}

// =====================================================================================================================
// Get the current value for the hardware register
//
// @param regId : Register ID
Value *SqImgRsrcRegHandler::getReg(SqRsrcRegs regId) {
  switch (regId) {
  case SqRsrcRegs::BaseAddress:
  case SqRsrcRegs::Format:
  case SqRsrcRegs::DstSelXYZW:
  case SqRsrcRegs::SwizzleMode:
  case SqRsrcRegs::BcSwizzle:
  case SqRsrcRegs::BaseLevel:
  case SqRsrcRegs::LastLevel:
  case SqRsrcRegs::BaseArray:
    return getRegCommon(static_cast<unsigned>(regId));
  case SqRsrcRegs::Depth:
  case SqRsrcRegs::Height:
  case SqRsrcRegs::Pitch:
    return m_builder->CreateAdd(getRegCommon(static_cast<unsigned>(regId)), m_one);
  case SqRsrcRegs::Width:
    switch (m_gfxIpVersion->major) {
    case 6:
    case 7:
    case 8:
    case 9:
      return m_builder->CreateAdd(getRegCommon(static_cast<unsigned>(regId)), m_one);
    case 10:
      return m_builder->CreateAdd(
          getRegCombine(static_cast<unsigned>(SqRsrcRegs::WidthLo), static_cast<unsigned>(SqRsrcRegs::WidthHi)), m_one);
    default:
      llvm_unreachable("GFX IP is not supported!");
      break;
    }
  case SqRsrcRegs::LastArray:
    switch (m_gfxIpVersion->major) {
    case 6:
    case 7:
    case 8:
      return getRegCommon(static_cast<unsigned>(regId));
    default:
      llvm_unreachable("GFX IP is not supported!");
      break;
    }
  default:
    // TODO: More will be implemented.
    llvm_unreachable("Not implemented!");
  }
  return nullptr;
}

// =====================================================================================================================
// Set the current value for the hardware register
//
// @param regId : Register ID
// @param regValue : Value to set to this register
void SqImgRsrcRegHandler::setReg(SqRsrcRegs regId, Value *regValue) {
  switch (regId) {
  case SqRsrcRegs::BaseAddress:
  case SqRsrcRegs::BaseAddressHi:
  case SqRsrcRegs::Format:
  case SqRsrcRegs::DstSelXYZW:
  case SqRsrcRegs::SwizzleMode:
  case SqRsrcRegs::Depth:
  case SqRsrcRegs::BcSwizzle:
    setRegCommon(static_cast<unsigned>(regId), regValue);
    break;
  case SqRsrcRegs::Height:
  case SqRsrcRegs::Pitch:
    setRegCommon(static_cast<unsigned>(regId), m_builder->CreateSub(regValue, m_one));
    break;
  case SqRsrcRegs::Width:
    switch (m_gfxIpVersion->major) {
    case 6:
    case 7:
    case 8:
    case 9:
      setRegCommon(static_cast<unsigned>(regId), m_builder->CreateSub(regValue, m_one));
      break;
    case 10:
      setRegCombine(static_cast<unsigned>(SqRsrcRegs::WidthLo), static_cast<unsigned>(SqRsrcRegs::WidthHi),
                    m_builder->CreateSub(regValue, m_one));
      break;
    default:
      llvm_unreachable("GFX IP is not supported!");
      break;
    }
    break;
  case SqRsrcRegs::WidthLo:
  case SqRsrcRegs::WidthHi:
  case SqRsrcRegs::Count:
    llvm_unreachable("Bad SqImgRsrcRegHandler::SetReg!");
    break;
  }
}
<commit_msg>Fix the width of some GFX10 image resource fields<commit_after>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2020 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
***********************************************************************************************************************
* @file  GfxRegHandler.cpp
* @brief LLPC source file: Implementation of LLPC utility class GfxRegHandler
***********************************************************************************************************************
*/
#include "lgc/util/GfxRegHandler.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"

using namespace lgc;
using namespace llvm;

// =====================================================================================================================
//
// @param builder : The builder handle
// @param reg : The registered target vec <n x i32>
GfxRegHandler::GfxRegHandler(IRBuilder<> *builder, Value *reg) : GfxRegHandlerBase(builder, reg) {
  m_one = builder->getInt32(1);
}

// =====================================================================================================================
// Common function for getting the current value for the hardware register
//
// @param regId : The register ID, which is the index of BitsInfo and BitsState
Value *GfxRegHandler::getRegCommon(unsigned regId) {
  // Under two condition, we need to fetch the range of bits
  //  - The register has not being initialized
  //  - The register is being modified
  if (!m_bitsState[regId].value || m_bitsState[regId].isModified) {
    // Fetch bits according to BitsInfo
    m_bitsState[regId].value = getBits(m_bitsInfo[regId]);
  }

  // Since the specified range of bits is cached, set it unmodified
  m_bitsState[regId].isModified = 0;

  // Return the cached value
  return m_bitsState[regId].value;
}

// =====================================================================================================================
// Get combined data from two seperate dwords
// Note: The return type is one dword, it doesn't support two dwords for now.
// TODO: Expand to support 2-dwords combination result.
//
// @param regIdLo : The ID of low part register
// @param regIdHi : Reg ID of high part register
Value *GfxRegHandler::getRegCombine(unsigned regIdLo, unsigned regIdHi) {
  Value *regValueLo = getRegCommon(regIdLo);
  Value *regValueHi = getRegCommon(regIdHi);
  return m_builder->CreateOr(m_builder->CreateShl(regValueHi, m_bitsInfo[regIdLo].count), regValueLo);
}

// =====================================================================================================================
// Set register value into two seperate dwords
// Note: The input pRegValue only supports one dword
//
// @param regIdLo : The ID of low part register
// @param regIdHi : Reg ID of high part register
// @param regValue : Data used for setting
void GfxRegHandler::setRegCombine(unsigned regIdLo, unsigned regIdHi, Value *regValue) {
  Value *regValueLo =
      m_builder->CreateIntrinsic(Intrinsic::amdgcn_ubfe, m_builder->getInt32Ty(),
                                 {regValue, m_builder->getInt32(0), m_builder->getInt32(m_bitsInfo[regIdLo].count)});

  Value *regValueHi = m_builder->CreateLShr(regValue, m_builder->getInt32(m_bitsInfo[regIdLo].count));

  setRegCommon(regIdLo, regValueLo);
  setRegCommon(regIdHi, regValueHi);
}

// =====================================================================================================================
// SqImgSampReg Bits infomation look up table (Gfx9-10)
// Refer to imported/chip/gfx9/gfx9_plus_merged_registers.h : SQ_IMG_SAMP_WORD
static constexpr BitsInfo SqImgSampRegBitsGfx9[static_cast<unsigned>(SqSampRegs::Count)] = {
    {0, 30, 2}, // FilterMode
    {2, 20, 2}, // XyMagFilter
    {2, 22, 2}, // XyMinFilter
};

// =====================================================================================================================
// Helper class for handling Registers defined in SQ_IMG_SAMP_WORD
//
// @param builder : Bound builder context
// @param reg : Bound register vec <n x i32>
// @param gfxIpVersion : Target GFX IP version
SqImgSampRegHandler::SqImgSampRegHandler(IRBuilder<> *builder, Value *reg, GfxIpVersion *gfxIpVersion)
    : GfxRegHandler(builder, reg) {
  m_gfxIpVersion = gfxIpVersion;

  switch (gfxIpVersion->major) {
  case 6:
  case 7:
  case 8:
  case 9:
  case 10:
    m_bitsInfo = SqImgSampRegBitsGfx9;
    break;
  default:
    llvm_unreachable("GFX IP is not supported!");
    break;
  }
  setBitsState(m_bitsState);
}

// =====================================================================================================================
// Get the current value for the hardware register
//
// @param regId : Register ID
Value *SqImgSampRegHandler::getReg(SqSampRegs regId) {
  switch (regId) {
  case SqSampRegs::FilterMode:
  case SqSampRegs::xyMagFilter:
  case SqSampRegs::xyMinFilter:
    return getRegCommon(static_cast<unsigned>(regId));
  default:
    // TODO: More will be implemented.
    llvm_unreachable("Not implemented!");
    break;
  }
  return nullptr;
}

// =====================================================================================================================
// Set the current value for the hardware register
//
// @param regId : Register ID
// @param regValue : Value to set to this register
void SqImgSampRegHandler::setReg(SqSampRegs regId, Value *regValue) {
  switch (regId) {
  case SqSampRegs::FilterMode:
  case SqSampRegs::xyMagFilter:
  case SqSampRegs::xyMinFilter:
    setRegCommon(static_cast<unsigned>(regId), regValue);
    break;
  default:
    llvm_unreachable("Bad SqImgSampRegHandler::SetReg!");
    break;
  }
}

// =====================================================================================================================
// SqImgSampReg Bits information look up table (Gfx6,7,8)
// Refer to imported/chip/gfx6/si_ci_merged_registers.h : SQ_IMG_RSRC_WORD
static constexpr BitsInfo SqImgRsrcRegBitsGfx6[static_cast<unsigned>(SqRsrcRegs::Count)] = {
    {0, 0, 32},  // BaseAddress
    {1, 0, 8},   // BaseAddressHi
    {1, 20, 6},  // Format
    {2, 0, 14},  // Width
    {2, 14, 14}, // Height
    {3, 0, 12},  // DstSelXYZW
    {},          // SwizzleMode
    {4, 0, 13},  // Depth
    {4, 13, 14}, // Pitch
    {},          // BcSwizzle
    {3, 12, 4},  // BaseLevel
    {3, 16, 4},  // LastLevel
    {5, 0, 13},  // BaseArray
    {5, 13, 13}, // LastArray
    {},          // WidthLo
    {},          // WidthHi
};

// =====================================================================================================================
// SqImgSampReg Bits information look up table (Gfx9)
// Refer to imported/chip/gfx9/gfx9_plus_merged_registers.h : SQ_IMG_RSRC_WORD
static constexpr BitsInfo SqImgRsrcRegBitsGfx9[static_cast<unsigned>(SqRsrcRegs::Count)] = {
    {0, 0, 32},  // BaseAddress
    {1, 0, 8},   // BaseAddressHi
    {1, 20, 9},  // Format
    {2, 0, 14},  // Width
    {2, 14, 14}, // Height
    {3, 0, 12},  // DstSelXYZW
    {3, 20, 5},  // SwizzleMode
    {4, 0, 13},  // Depth
    {4, 13, 12}, // Pitch
    {4, 29, 3},  // BcSwizzle
    {3, 12, 4},  // BaseLevel
    {3, 16, 4},  // LastLevel
    {5, 0, 13},  // BaseArray
    {},          // LastArray
    {},          // WidthLo
    {},          // WidthHi
};

// =====================================================================================================================
// SqImgSampReg Bits information look up table (Gfx10)
// TODO: update comment when the registers file is available
static constexpr BitsInfo SqImgRsrcRegBitsGfx10[static_cast<unsigned>(SqRsrcRegs::Count)] = {
    {0, 0, 32},  // BaseAddress
    {1, 0, 8},   // BaseAddressHi
    {1, 20, 9},  // Format
    {},          // Width
    {2, 14, 14}, // Height
    {3, 0, 12},  // DstSelXYZW
    {3, 20, 5},  // SwizzleMode
    {4, 0, 13},  // Depth
    {},          // Pitch
    {3, 25, 3},  // BcSwizzle
    {3, 12, 4},  // BaseLevel
    {3, 16, 4},  // LastLevel
    {4, 16, 13}, // BaseArray
    {},          // LastArray
    {1, 30, 2},  // WidthLo
    {2, 0, 12},  // WidthHi
};

// =====================================================================================================================
// Helper class for handling Registers defined in SQ_IMG_RSRC_WORD
//
// @param builder : Bound builder context
// @param reg : Bound register vec <n x i32>
// @param gfxIpVersion : Current GFX IP version
SqImgRsrcRegHandler::SqImgRsrcRegHandler(IRBuilder<> *builder, Value *reg, GfxIpVersion *gfxIpVersion)
    : GfxRegHandler(builder, reg) {
  m_gfxIpVersion = gfxIpVersion;

  switch (gfxIpVersion->major) {
  case 6:
  case 7:
  case 8:
    m_bitsInfo = SqImgRsrcRegBitsGfx6;
    break;
  case 9:
    m_bitsInfo = SqImgRsrcRegBitsGfx9;
    break;
  case 10:
    m_bitsInfo = SqImgRsrcRegBitsGfx10;
    break;
  default:
    llvm_unreachable("GFX IP is not supported!");
    break;
  }
  setBitsState(m_bitsState);
}

// =====================================================================================================================
// Get the current value for the hardware register
//
// @param regId : Register ID
Value *SqImgRsrcRegHandler::getReg(SqRsrcRegs regId) {
  switch (regId) {
  case SqRsrcRegs::BaseAddress:
  case SqRsrcRegs::Format:
  case SqRsrcRegs::DstSelXYZW:
  case SqRsrcRegs::SwizzleMode:
  case SqRsrcRegs::BcSwizzle:
  case SqRsrcRegs::BaseLevel:
  case SqRsrcRegs::LastLevel:
  case SqRsrcRegs::BaseArray:
    return getRegCommon(static_cast<unsigned>(regId));
  case SqRsrcRegs::Depth:
  case SqRsrcRegs::Height:
  case SqRsrcRegs::Pitch:
    return m_builder->CreateAdd(getRegCommon(static_cast<unsigned>(regId)), m_one);
  case SqRsrcRegs::Width:
    switch (m_gfxIpVersion->major) {
    case 6:
    case 7:
    case 8:
    case 9:
      return m_builder->CreateAdd(getRegCommon(static_cast<unsigned>(regId)), m_one);
    case 10:
      return m_builder->CreateAdd(
          getRegCombine(static_cast<unsigned>(SqRsrcRegs::WidthLo), static_cast<unsigned>(SqRsrcRegs::WidthHi)), m_one);
    default:
      llvm_unreachable("GFX IP is not supported!");
      break;
    }
  case SqRsrcRegs::LastArray:
    switch (m_gfxIpVersion->major) {
    case 6:
    case 7:
    case 8:
      return getRegCommon(static_cast<unsigned>(regId));
    default:
      llvm_unreachable("GFX IP is not supported!");
      break;
    }
  default:
    // TODO: More will be implemented.
    llvm_unreachable("Not implemented!");
  }
  return nullptr;
}

// =====================================================================================================================
// Set the current value for the hardware register
//
// @param regId : Register ID
// @param regValue : Value to set to this register
void SqImgRsrcRegHandler::setReg(SqRsrcRegs regId, Value *regValue) {
  switch (regId) {
  case SqRsrcRegs::BaseAddress:
  case SqRsrcRegs::BaseAddressHi:
  case SqRsrcRegs::Format:
  case SqRsrcRegs::DstSelXYZW:
  case SqRsrcRegs::SwizzleMode:
  case SqRsrcRegs::Depth:
  case SqRsrcRegs::BcSwizzle:
    setRegCommon(static_cast<unsigned>(regId), regValue);
    break;
  case SqRsrcRegs::Height:
  case SqRsrcRegs::Pitch:
    setRegCommon(static_cast<unsigned>(regId), m_builder->CreateSub(regValue, m_one));
    break;
  case SqRsrcRegs::Width:
    switch (m_gfxIpVersion->major) {
    case 6:
    case 7:
    case 8:
    case 9:
      setRegCommon(static_cast<unsigned>(regId), m_builder->CreateSub(regValue, m_one));
      break;
    case 10:
      setRegCombine(static_cast<unsigned>(SqRsrcRegs::WidthLo), static_cast<unsigned>(SqRsrcRegs::WidthHi),
                    m_builder->CreateSub(regValue, m_one));
      break;
    default:
      llvm_unreachable("GFX IP is not supported!");
      break;
    }
    break;
  case SqRsrcRegs::WidthLo:
  case SqRsrcRegs::WidthHi:
  case SqRsrcRegs::Count:
    llvm_unreachable("Bad SqImgRsrcRegHandler::SetReg!");
    break;
  }
}
<|endoftext|>