<commit_before>/***********************************************************************
    filename:   CEGUIDefaultResourceProvider.cpp
    created:    8/7/2004
    author:     James '_mental_' O'Sullivan
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUIDefaultResourceProvider.h"
#include "CEGUIExceptions.h"

#if defined(__WIN32__) || defined(_WIN32)
#   include <io.h>
#   include <windows.h>
#   include <string>

//----------------------------------------------------------------------------//
std::wstring Utf8ToUtf16(const std::string& utf8text)
{
    const int textLen = MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(),
                                            utf8text.size() + 1, 0, 0);

    if (textLen == 0)
        throw CEGUI::InvalidRequestException(
            "Utf8ToUtf16 - MultiByteToWideChar failed");

    std::wstring wideStr(textLen, 0);
    MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(), utf8text.size() + 1,
                        &wideStr[0], wideStr.size());
    return wideStr;
}

//----------------------------------------------------------------------------//
CEGUI::String Utf16ToString(const wchar_t* const utf16text)
{
    const int len = WideCharToMultiByte(CP_UTF8, 0, utf16text, -1,
                                        0, 0, 0, 0);
    if (!len)
        throw CEGUI::InvalidRequestException(
            "Utf16ToUtf8 - WideCharToMultiByte failed");

    CEGUI::utf8* buff = new CEGUI::utf8[len + 1];
    WideCharToMultiByte(CP_UTF8, 0, utf16text, -1,
                        reinterpret_cast<char*>(buff), len, 0, 0);
    const CEGUI::String result(buff);
    delete[] buff;

    return result;
}

//----------------------------------------------------------------------------//
#else
#   include <sys/types.h>
#   include <sys/stat.h>
#   include <dirent.h>
#   include <fnmatch.h>
#endif

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
void DefaultResourceProvider::loadRawDataContainer(const String& filename,
                                                   RawDataContainer& output,
                                                   const String& resourceGroup)
{
    if (filename.empty())
        throw InvalidRequestException("DefaultResourceProvider::load: "
            "Filename supplied for data loading must be valid");

    const String final_filename(getFinalFilename(filename, resourceGroup));

#if defined(__WIN32__) || defined(_WIN32)
    FILE* file = _wfopen(Utf8ToUtf16(final_filename.c_str()).c_str(), L"rb");
#else
    FILE* file = fopen(final_filename.c_str(), "rb");
#endif

    if (file == 0)
        throw InvalidRequestException("DefaultResourceProvider::load: " +
            final_filename + " does not exist");

    fseek(file, 0, SEEK_END);
    const long size = ftell(file);
    fseek(file, 0, SEEK_SET);

    unsigned char* const buffer = new unsigned char[size];

    const size_t size_read = fread(buffer, sizeof(char), size, file);
    fclose(file);

    if (size_read != size)
    {
        delete[] buffer;
        throw GenericException("DefaultResourceProvider::loadRawDataContainer: "
            "A problem occurred while reading file: " + final_filename);
    }

    output.setData(buffer);
    output.setSize(size);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::unloadRawDataContainer(RawDataContainer& data)
{
    uint8* const ptr = data.getDataPtr();
    delete[] ptr;
    data.setData(0);
    data.setSize(0);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::setResourceGroupDirectory(
                                                const String& resourceGroup,
                                                const String& directory)
{
    if (directory.length() == 0)
        return;

#if defined(_WIN32) || defined(__WIN32__)
    // while we rarely use the unportable '\', the user may have
    const String separators("\\/");
#else
    const String separators("/");
#endif

    if (String::npos == separators.find(directory[directory.length() - 1]))
        d_resourceGroups[resourceGroup] = directory + '/';
    else
        d_resourceGroups[resourceGroup] = directory;
}

//----------------------------------------------------------------------------//
const String& DefaultResourceProvider::getResourceGroupDirectory(
                                                const String& resourceGroup)
{
    return d_resourceGroups[resourceGroup];
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::clearResourceGroupDirectory(
                                                const String& resourceGroup)
{
    ResourceGroupMap::iterator iter = d_resourceGroups.find(resourceGroup);

    if (iter != d_resourceGroups.end())
        d_resourceGroups.erase(iter);
}

//----------------------------------------------------------------------------//
String DefaultResourceProvider::getFinalFilename(
                                            const String& filename,
                                            const String& resourceGroup) const
{
    String final_filename;

    // look up resource group directory
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resourceGroup.empty() ?
            d_defaultResourceGroup :
            resourceGroup);

    // if there was an entry for this group, use it's directory as the
    // first part of the filename
    if (iter != d_resourceGroups.end())
        final_filename = (*iter).second;

    // append the filename part that we were passed
    final_filename += filename;

    // return result
    return final_filename;
}

//----------------------------------------------------------------------------//
size_t DefaultResourceProvider::getResourceGroupFileNames(
    std::vector<String>& out_vec,
    const String& file_pattern,
    const String& resource_group)
{
    // look-up resource group name
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resource_group.empty() ? d_defaultResourceGroup :
                              resource_group);
    // get directory that's set for the resource group
    const String dir_name(
        iter != d_resourceGroups.end() ? (*iter).second : "./");

    size_t entries = 0;

// Win32 code.
#if defined(__WIN32__) || defined(_WIN32)
    intptr_t f;
    struct _wfinddata_t fd;

    if ((f = _wfindfirst(Utf8ToUtf16((dir_name + file_pattern).c_str()).c_str(), &fd)) != -1)
    {
        do
        {
            if ((fd.attrib & _A_SUBDIR))
                continue;

            out_vec.push_back(Utf16ToString(fd.name));
            ++entries;
        }
        while (_wfindnext(f, &fd) == 0);

        _findclose(f);
    }

// Everybody else
#else
    DIR* dirp;

    if ((dirp = opendir(dir_name.c_str())))
    {
        struct dirent* dp;

        while ((dp = readdir(dirp)))
        {
            const String filename(dir_name + dp->d_name);
            struct stat s;

            if ((stat(filename.c_str(), &s) == 0) &&
                    S_ISREG(s.st_mode) &&
                    (fnmatch(file_pattern.c_str(), dp->d_name, 0) == 0))
            {
                out_vec.push_back(dp->d_name);
                ++entries;
            }
        }

        closedir(dirp);
    }
#endif

    return entries;
}

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

} // End of  CEGUI namespace section

<commit_msg>fix build issues relating to missing header in CEGUIDefaultResourceProvider.cpp<commit_after>/***********************************************************************
    filename:   CEGUIDefaultResourceProvider.cpp
    created:    8/7/2004
    author:     James '_mental_' O'Sullivan
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUIDefaultResourceProvider.h"
#include "CEGUIExceptions.h"

#include <stdio.h>

#if defined(__WIN32__) || defined(_WIN32)
#   include <io.h>
#   include <windows.h>
#   include <string>

//----------------------------------------------------------------------------//
std::wstring Utf8ToUtf16(const std::string& utf8text)
{
    const int textLen = MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(),
                                            utf8text.size() + 1, 0, 0);

    if (textLen == 0)
        throw CEGUI::InvalidRequestException(
            "Utf8ToUtf16 - MultiByteToWideChar failed");

    std::wstring wideStr(textLen, 0);
    MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(), utf8text.size() + 1,
                        &wideStr[0], wideStr.size());
    return wideStr;
}

//----------------------------------------------------------------------------//
CEGUI::String Utf16ToString(const wchar_t* const utf16text)
{
    const int len = WideCharToMultiByte(CP_UTF8, 0, utf16text, -1,
                                        0, 0, 0, 0);
    if (!len)
        throw CEGUI::InvalidRequestException(
            "Utf16ToUtf8 - WideCharToMultiByte failed");

    CEGUI::utf8* buff = new CEGUI::utf8[len + 1];
    WideCharToMultiByte(CP_UTF8, 0, utf16text, -1,
                        reinterpret_cast<char*>(buff), len, 0, 0);
    const CEGUI::String result(buff);
    delete[] buff;

    return result;
}

//----------------------------------------------------------------------------//
#else
#   include <sys/types.h>
#   include <sys/stat.h>
#   include <dirent.h>
#   include <fnmatch.h>
#endif

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
void DefaultResourceProvider::loadRawDataContainer(const String& filename,
                                                   RawDataContainer& output,
                                                   const String& resourceGroup)
{
    if (filename.empty())
        throw InvalidRequestException("DefaultResourceProvider::load: "
            "Filename supplied for data loading must be valid");

    const String final_filename(getFinalFilename(filename, resourceGroup));

#if defined(__WIN32__) || defined(_WIN32)
    FILE* file = _wfopen(Utf8ToUtf16(final_filename.c_str()).c_str(), L"rb");
#else
    FILE* file = fopen(final_filename.c_str(), "rb");
#endif

    if (file == 0)
        throw InvalidRequestException("DefaultResourceProvider::load: " +
            final_filename + " does not exist");

    fseek(file, 0, SEEK_END);
    const long size = ftell(file);
    fseek(file, 0, SEEK_SET);

    unsigned char* const buffer = new unsigned char[size];

    const size_t size_read = fread(buffer, sizeof(char), size, file);
    fclose(file);

    if (size_read != size)
    {
        delete[] buffer;
        throw GenericException("DefaultResourceProvider::loadRawDataContainer: "
            "A problem occurred while reading file: " + final_filename);
    }

    output.setData(buffer);
    output.setSize(size);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::unloadRawDataContainer(RawDataContainer& data)
{
    uint8* const ptr = data.getDataPtr();
    delete[] ptr;
    data.setData(0);
    data.setSize(0);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::setResourceGroupDirectory(
                                                const String& resourceGroup,
                                                const String& directory)
{
    if (directory.length() == 0)
        return;

#if defined(_WIN32) || defined(__WIN32__)
    // while we rarely use the unportable '\', the user may have
    const String separators("\\/");
#else
    const String separators("/");
#endif

    if (String::npos == separators.find(directory[directory.length() - 1]))
        d_resourceGroups[resourceGroup] = directory + '/';
    else
        d_resourceGroups[resourceGroup] = directory;
}

//----------------------------------------------------------------------------//
const String& DefaultResourceProvider::getResourceGroupDirectory(
                                                const String& resourceGroup)
{
    return d_resourceGroups[resourceGroup];
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::clearResourceGroupDirectory(
                                                const String& resourceGroup)
{
    ResourceGroupMap::iterator iter = d_resourceGroups.find(resourceGroup);

    if (iter != d_resourceGroups.end())
        d_resourceGroups.erase(iter);
}

//----------------------------------------------------------------------------//
String DefaultResourceProvider::getFinalFilename(
                                            const String& filename,
                                            const String& resourceGroup) const
{
    String final_filename;

    // look up resource group directory
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resourceGroup.empty() ?
            d_defaultResourceGroup :
            resourceGroup);

    // if there was an entry for this group, use it's directory as the
    // first part of the filename
    if (iter != d_resourceGroups.end())
        final_filename = (*iter).second;

    // append the filename part that we were passed
    final_filename += filename;

    // return result
    return final_filename;
}

//----------------------------------------------------------------------------//
size_t DefaultResourceProvider::getResourceGroupFileNames(
    std::vector<String>& out_vec,
    const String& file_pattern,
    const String& resource_group)
{
    // look-up resource group name
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resource_group.empty() ? d_defaultResourceGroup :
                              resource_group);
    // get directory that's set for the resource group
    const String dir_name(
        iter != d_resourceGroups.end() ? (*iter).second : "./");

    size_t entries = 0;

// Win32 code.
#if defined(__WIN32__) || defined(_WIN32)
    intptr_t f;
    struct _wfinddata_t fd;

    if ((f = _wfindfirst(Utf8ToUtf16((dir_name + file_pattern).c_str()).c_str(), &fd)) != -1)
    {
        do
        {
            if ((fd.attrib & _A_SUBDIR))
                continue;

            out_vec.push_back(Utf16ToString(fd.name));
            ++entries;
        }
        while (_wfindnext(f, &fd) == 0);

        _findclose(f);
    }

// Everybody else
#else
    DIR* dirp;

    if ((dirp = opendir(dir_name.c_str())))
    {
        struct dirent* dp;

        while ((dp = readdir(dirp)))
        {
            const String filename(dir_name + dp->d_name);
            struct stat s;

            if ((stat(filename.c_str(), &s) == 0) &&
                    S_ISREG(s.st_mode) &&
                    (fnmatch(file_pattern.c_str(), dp->d_name, 0) == 0))
            {
                out_vec.push_back(dp->d_name);
                ++entries;
            }
        }

        closedir(dirp);
    }
#endif

    return entries;
}

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

} // End of  CEGUI namespace section

<|endoftext|>


<commit_before>/*===========================================================================*\

Author: Matthias W. Smith
Email:  mwsmith2@uw.edu
Date:   2014/05/18

Detail: The program is meant to test the effects of field gradients
        on the FID frequency extraction.  The sweep parameters are
        set in a separate config file here, but the user need not rely
        on the config parameters.  All that needs to be done is the
        defining of a gradient vector.

\*===========================================================================*/

//--- std includes ----------------------------------------------------------//
#include <fstream>

//--- other includes --------------------------------------------------------//
#include "TFile.h"
#include "TTree.h"

//--- project includes ------------------------------------------------------//
#include "fid_params.h"
#include "fid_class.h"
#include "fid_sim.h"
#include "fid_utilities.h"

using namespace fid;
using namespace fid::sweep;

int main(int argc, char **argv)
{
  // initialize the configurable parameters
  load_params(argc, argv);

  // some necessary parameters
  vec wf;
  vec tm;
  vec grads;
  vec grad_0;
  vec gradient;

  construct_time_vector(len_fids, i_time, d_time, tm);
  grads = construct_sweep_range(grad_range);

  // Make FidFactory
  GradientFidFactory gff;

  // construct a normalized, centered polynomial gradient
  char str[10];
  int npoints = 21;
  sprintf(str, "pol%d", grad::poln_order);
  TF1 f1("f1", str);

  for (auto &val : grad::poln_coefs){
    static int count = 0;
    f1.SetParameter(count++, val);
  }

  // Now set the values in the gradient
  double dx = 10.0 / (npoints - 1);
  for (double x = -5.0; x <= 5.0; x += 1.0){
    grad_0.push_back(f1.Eval(x));
  }

  // now center and normalize vector
  double avg =
    std::accumulate(grad_0.begin(), grad_0.end(), 0.0) / grad_0.size();
  for (int i = 0; i < grad_0.size(); i++){
    grad_0[i] -= avg;
  }

  // normalize by largest value
  double max = *std::max_element(grad_0.begin(), grad_0.end());
  for (int i = 0; i < grad_0.size(); i++){
    grad_0[i] /= max;
  }

  // csv output
  std::ofstream out;
  out.precision(10);
  out.setf(std::ios::fixed, std::ios::floatfield);
  out.open("data/sim_fid_quad_grad_data.csv");

  // begin sweeps
  for (auto g: grads){

    cout << "gradient strength " << g << endl;

    for (int i = 0; i < num_fids; ++i){

      gradient.resize(0);

      for (auto val : grad_0){
        gradient.push_back(val * g);
      }

      gff.ConstructFid(gradient, wf);
      FID my_fid(wf, tm);

      calc_freq_write_csv(my_fid, out);

      if (i == 0){
        static char str[60];
        sprintf(str, "data/fig/fid_quad_grad_%03dppb.pdf", (int)g);
        draw_fid(my_fid, str, string("Test FID"));
      }
    }
  } // grad

  return 0;
}

<commit_msg>Debugged the polynomial gradient analyzer.<commit_after>/*===========================================================================*\

Author: Matthias W. Smith
Email:  mwsmith2@uw.edu
Date:   2014/05/18

Detail: The program is meant to test the effects of field gradients
        on the FID frequency extraction.  The sweep parameters are
        set in a separate config file here, but the user need not rely
        on the config parameters.  All that needs to be done is the
        defining of a gradient vector.

\*===========================================================================*/

//--- std includes ----------------------------------------------------------//
#include <fstream>

//--- other includes --------------------------------------------------------//
#include "TFile.h"
#include "TTree.h"

//--- project includes ------------------------------------------------------//
#include "fid_params.h"
#include "fid_class.h"
#include "fid_sim.h"
#include "fid_utilities.h"

using namespace fid;
using namespace fid::sweep;

int main(int argc, char **argv)
{
  // initialize the configurable parameters
  load_params(argc, argv);

  // some necessary parameters
  vec wf;
  vec tm;
  vec grads;
  vec grad_0;
  vec gradient;

  construct_time_vector(len_fids, i_time, d_time, tm);
  grads = construct_sweep_range(grad_range);

  // Make FidFactory
  GradientFidFactory gff;

  // construct a normalized, centered polynomial gradient
  char str[60];
  int npoints = 21;
  sprintf(str, "pol%d", grad::poln_order);
  TF1 f1("f1", str);

  for (auto &val : grad::poln_coefs){
    static int count = 0;
    f1.SetParameter(count++, val);
  }

  // Now set the values in the gradient
  double dx = 10.0 / (npoints - 1);
  for (double x = -5.0; x <= 5.0; x += 1.0){
    grad_0.push_back(f1.Eval(x));
  }

  // now center and normalize vector
  double avg =
    std::accumulate(grad_0.begin(), grad_0.end(), 0.0) / grad_0.size();
  for (int i = 0; i < grad_0.size(); i++){
    grad_0[i] -= avg;
  }

  // normalize by largest value
  double max = *std::max_element(grad_0.begin(), grad_0.end());
  for (int i = 0; i < grad_0.size(); i++){
    grad_0[i] /= max;
  }

  // csv output
  std::ofstream out;
  out.precision(10);
  out.setf(std::ios::fixed, std::ios::floatfield);
  sprintf(str, "data/sim_fid_pol%d_grad_data.csv", grad::poln_order);
  out.open(str);

  // begin sweeps
  for (auto g: grads){

    cout << "gradient strength " << g << endl;

    for (int i = 0; i < num_fids; ++i){

      gradient.resize(0);

      for (auto val : grad_0){
        gradient.push_back(val * g);
      }

      gff.ConstructFid(gradient, wf);
      FID my_fid(wf, tm);

      calc_freq_write_csv(my_fid, out);

      if (i == 0){
        sprintf(str, "data/fig/fid_pol%d_grad_%03dppb.pdf", grad::poln_order, (int)g);
        draw_fid(my_fid, str, string("Test FID"));
      }
    }
  } // grad

  return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.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.

=========================================================================*/

// Qt includes
#include <QApplication>
#include <QString>
#include <QTimer>

// CTK includes
#include "ctkConfig.h"
#include "ctkConsole.h"
#include "ctkTest.h"

// ----------------------------------------------------------------------------
class ctkConsoleTester: public QObject
{
  Q_OBJECT
private slots:
  void testShow();

  void testRunFile();
  void testRunFile_data();
};

// ----------------------------------------------------------------------------
void ctkConsoleTester::testShow()
{
  ctkConsole console;
  console.show();
  QTest::qWaitForWindowShown(&console);
}

// ----------------------------------------------------------------------------
void ctkConsoleTester::testRunFile()
{
  ctkConsole console;
  QFETCH(QString, file);
  console.runFile(file);
}

// ----------------------------------------------------------------------------
void ctkConsoleTester::testRunFile_data()
{
  QTest::addColumn<QString>("file");
  QTest::newRow("null") << QString();
  QTest::newRow("empty") << "";
  QTest::newRow("invalid") << " ";
  QTest::newRow(".") << ".";
  QTest::newRow("file")
    << QFileInfo(QDir(CTK_SOURCE_DIR), "README").absoluteFilePath();
}

// ----------------------------------------------------------------------------
CTK_TEST_MAIN(ctkConsoleTest)
#include "moc_ctkConsoleTest.cpp"
<commit_msg>Fix ctkConsoleTest for Qt5.<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.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.

=========================================================================*/

// Qt includes
#include <QApplication>
#include <QString>
#include <QTimer>

// CTK includes
#include "ctkConfig.h"
#include "ctkConsole.h"
#include "ctkTest.h"

// ----------------------------------------------------------------------------
class ctkConsoleTester: public QObject
{
  Q_OBJECT
private slots:
  void testShow();

  void testRunFile();
  void testRunFile_data();
};

// ----------------------------------------------------------------------------
void ctkConsoleTester::testShow()
{
  ctkConsole console;
  console.show();
#if (QT_VERSION >= 0x50000)
  QTest::qWaitForWindowActive(&console);
#else
  QTest::qWaitForWindowShown(&console);
#endif
}

// ----------------------------------------------------------------------------
void ctkConsoleTester::testRunFile()
{
  ctkConsole console;
  QFETCH(QString, file);
  console.runFile(file);
}

// ----------------------------------------------------------------------------
void ctkConsoleTester::testRunFile_data()
{
  QTest::addColumn<QString>("file");
  QTest::newRow("null") << QString();
  QTest::newRow("empty") << "";
  QTest::newRow("invalid") << " ";
  QTest::newRow(".") << ".";
  QTest::newRow("file")
    << QFileInfo(QDir(CTK_SOURCE_DIR), "README").absoluteFilePath();
}

// ----------------------------------------------------------------------------
CTK_TEST_MAIN(ctkConsoleTest)
#include "moc_ctkConsoleTest.cpp"
<|endoftext|>


<commit_before>// Copyright (c) 2015, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: yanshiguang02@baidu.com

#include "bfs_wrapper.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <bfs.h>
#include "common/logging.h"
#include "common/timer.h"

namespace bfs {

int32_t BfsFile::Write(const char* buf, int32_t len) {
    common::timer::AutoTimer ac(0.1, "BfsFile::Write", _name.c_str());
    int ret = _file->Write(buf, len);
    LOG(INFO, "Write(%s, len: %d) return %d", _name.c_str(), len, ret);
    if (ret != len) {
        LOG(INFO, "Write(%s, len: %d) return %d",
            _name.c_str(), len, ret);
    }
    return ret;
}

int32_t BfsFile::Flush() {
    common::timer::AutoTimer ac(1, "Flush", _name.c_str());
    int ret = -1;
    if (_file->Flush()) {
        ret = 0;
    }
    LOG(INFO, "Flush(%s) return %d", _name.c_str(), ret);
    return ret;
}
int32_t BfsFile::Sync() {
    LOG(INFO, "Sync(%s) start", _name.c_str());
    common::timer::AutoTimer ac(10, "Sync", _name.c_str());
    int ret = -1;
    if (_file->Sync()) {
        ret = 0;
    }
    LOG(INFO, "Sync(%s) return %d", _name.c_str(), ret);
    return ret;
}
int32_t BfsFile::Read(char* buf, int32_t len) {
    common::timer::AutoTimer ac(1, "Read", _name.c_str());
    int32_t ret = _file->Read(buf, len);
    LOG(INFO, "Read(%s, len: %d) return %d", _name.c_str(), len, ret);
    if (ret != len) {
        LOG(INFO, "Read(%s, len: %d) return %d",
            _name.c_str(), len, ret);
    }
    return ret;
}
int32_t BfsFile::Pread(int64_t offset, char* buf, int32_t len) {
    common::timer::AutoTimer ac(1, "Pread", _name.c_str());
    int32_t ret = _file->Pread(buf, len, offset, true);
    LOG(INFO, "Pread(%s, offset: %ld, len: %d) return %d",
        _name.c_str(), offset, len, ret);
    return ret;
}
int64_t BfsFile::Tell() {
    common::timer::AutoTimer ac(1, "Tell", _name.c_str());
    int64_t ret = _file->Seek(0, SEEK_CUR);
    LOG(INFO, "Tell(%s) return %ld", _name.c_str(), ret);
    return ret;
}
int32_t BfsFile::Seek(int64_t offset) {
    common::timer::AutoTimer ac(1, "Seek", _name.c_str());
    int64_t ret = _file->Seek(offset, SEEK_SET);
    if (ret >= 0) {
        ret = 0;
    }
    LOG(INFO, "Seek(%s, %ld) return %ld", _name.c_str(), offset, ret);
    return ret;
}
int32_t BfsFile::CloseFile() {
    LOG(INFO, "CloseFile(%s)", _name.c_str());
    common::timer::AutoTimer ac(1, "CloseFile", _name.c_str());
    bool ret = _file->Close();
    delete _file;
    _file = NULL;
    if (!ret) {
        LOG(INFO, "CloseFile(%s) fail", _name.c_str());
        return -1;
    }
    LOG(INFO, "CloseFile(%s) succeed", _name.c_str());
    return 0;
}

BfsImpl::BfsImpl(const std::string& conf) {
    if (!FS::OpenFileSystem(conf.c_str(), &_fs)) {
        assert(0);
    }
}

int32_t BfsImpl::CreateDirectory(const std::string& path) {
    LOG(INFO, "CreateDirectory(%s)", path.c_str());
    _fs->CreateDirectory(path.c_str());
    return 0;
}
int32_t BfsImpl::DeleteDirectory(const std::string& path) {
    LOG(INFO, "DeleteDirectory(%s)", path.c_str());
    if (!_fs->DeleteDirectory(path.c_str(), true)) {
        LOG(INFO, "DeleteDirectory(%s) fail", path.c_str());
        return -1;
    }
    LOG(INFO, "DeleteDirectory(%s) succeed", path.c_str());
    return 0;
}
int32_t BfsImpl::Exists(const std::string& filename) {
    LOG(INFO, "Exists(%s)", filename.c_str());
    if (!_fs->Access(filename.c_str(), 0)) {
        LOG(INFO, "Exists(%s) return false", filename.c_str());
        return -1;
    }
    LOG(INFO, "Exists(%s) return true", filename.c_str());
    return 0;
}
int32_t BfsImpl::Delete(const std::string& filename) {
    common::timer::AutoTimer ac(1, "Delete", filename.c_str());
    if (!_fs->DeleteFile(filename.c_str())) {
        LOG(INFO, "Delete(%s) fail", filename.c_str());
        return -1;
    }
    LOG(INFO, "Delete(%s) succeed", filename.c_str());
    return 0;
}
int32_t BfsImpl::GetFileSize(const std::string& filename, uint64_t* size) {
    int64_t file_size = 0;
    if (!_fs->GetFileSize(filename.c_str(), &file_size)) {
        LOG(INFO, "GetFileSize(%s) fail", filename.c_str());
        return -1;
    }
    *size = file_size;
    LOG(INFO, "GetFileSize(%s) return %lu", filename.c_str(), *size);
    return 0;
}
int32_t BfsImpl::Rename(const std::string& from, const std::string& to) {
    int ret = Delete(to);
    if (ret) {
        return ret;
    }
    if (!_fs->Rename(from.c_str(), to.c_str())) {
        LOG(INFO, "Rename(%s, %s) fail", from.c_str(), to.c_str());
        return -1;
    }
    LOG(INFO, "Rename(%s, %s) succeed", from.c_str(), to.c_str());
    return 0;
}
int32_t BfsImpl::Copy(const std::string& from, const std::string& to) {
    LOG(INFO, "Copy(%s, %s)", from.c_str(), to.c_str());
    abort();
    return 0;
}

int32_t BfsImpl::ListDirectory(const std::string& path, std::vector<std::string>* result) {
    common::timer::AutoTimer ac(1, "ListDirectory", path.c_str());
    LOG(INFO, "ListDirectory(%s)", path.c_str());
    if (result == NULL) {
        return -1;
    }
    bfs::BfsFileInfo* files = NULL;
    int num = 0;
    if (!_fs->ListDirectory(path.c_str(), &files, &num)) {
        return -1;
    }
    for (int i = 0; i < num; i++) {
        char* pathname = files[i].name;
        char* filename = rindex(pathname, '/');
        if (filename != NULL && filename[0] != '\0') {
            result->push_back(filename + 1);
        }
    }
    delete[] files;
    LOG(INFO, "ListDirectory(%s) return %lu items", path.c_str(), result->size());
    return 0;
}

leveldb::DfsFile* BfsImpl::OpenFile(const std::string& filename, int32_t flags) {
    common::timer::AutoTimer ac(0, "OpenFile", filename.c_str());
    LOG(INFO, "OpenFile(%s,%d)", filename.c_str(), flags);
    int openflag = O_WRONLY;
    if (leveldb::WRONLY != flags) {
        openflag = O_RDONLY;
    }
    bfs::File* file = NULL;
    if (!_fs->OpenFile(filename.c_str(), openflag, &file)) {
        return NULL;
    }
    LOG(INFO, "OpenFile(%s,%d) succeed", filename.c_str(), flags);
    return new BfsFile(filename, file);
}

} // namespace

extern "C" {

leveldb::Dfs* NewDfs(const char* conf) {
    common::SetLogFile("./bfslog");
    common::SetWarningFile("./bfswf");
    return new bfs::BfsImpl(conf);
}

}
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<commit_msg>Fix tera wrapper rename<commit_after>// Copyright (c) 2015, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: yanshiguang02@baidu.com

#include "bfs_wrapper.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <bfs.h>
#include "common/logging.h"
#include "common/timer.h"

namespace bfs {

int32_t BfsFile::Write(const char* buf, int32_t len) {
    common::timer::AutoTimer ac(0.1, "BfsFile::Write", _name.c_str());
    int ret = _file->Write(buf, len);
    LOG(INFO, "Write(%s, len: %d) return %d", _name.c_str(), len, ret);
    if (ret != len) {
        LOG(INFO, "Write(%s, len: %d) return %d",
            _name.c_str(), len, ret);
    }
    return ret;
}

int32_t BfsFile::Flush() {
    common::timer::AutoTimer ac(1, "Flush", _name.c_str());
    int ret = -1;
    if (_file->Flush()) {
        ret = 0;
    }
    LOG(INFO, "Flush(%s) return %d", _name.c_str(), ret);
    return ret;
}
int32_t BfsFile::Sync() {
    LOG(INFO, "Sync(%s) start", _name.c_str());
    common::timer::AutoTimer ac(10, "Sync", _name.c_str());
    int ret = -1;
    if (_file->Sync()) {
        ret = 0;
    }
    LOG(INFO, "Sync(%s) return %d", _name.c_str(), ret);
    return ret;
}
int32_t BfsFile::Read(char* buf, int32_t len) {
    common::timer::AutoTimer ac(1, "Read", _name.c_str());
    int32_t ret = _file->Read(buf, len);
    LOG(INFO, "Read(%s, len: %d) return %d", _name.c_str(), len, ret);
    if (ret != len) {
        LOG(INFO, "Read(%s, len: %d) return %d",
            _name.c_str(), len, ret);
    }
    return ret;
}
int32_t BfsFile::Pread(int64_t offset, char* buf, int32_t len) {
    common::timer::AutoTimer ac(1, "Pread", _name.c_str());
    int32_t ret = _file->Pread(buf, len, offset, true);
    LOG(INFO, "Pread(%s, offset: %ld, len: %d) return %d",
        _name.c_str(), offset, len, ret);
    return ret;
}
int64_t BfsFile::Tell() {
    common::timer::AutoTimer ac(1, "Tell", _name.c_str());
    int64_t ret = _file->Seek(0, SEEK_CUR);
    LOG(INFO, "Tell(%s) return %ld", _name.c_str(), ret);
    return ret;
}
int32_t BfsFile::Seek(int64_t offset) {
    common::timer::AutoTimer ac(1, "Seek", _name.c_str());
    int64_t ret = _file->Seek(offset, SEEK_SET);
    if (ret >= 0) {
        ret = 0;
    }
    LOG(INFO, "Seek(%s, %ld) return %ld", _name.c_str(), offset, ret);
    return ret;
}
int32_t BfsFile::CloseFile() {
    LOG(INFO, "CloseFile(%s)", _name.c_str());
    common::timer::AutoTimer ac(1, "CloseFile", _name.c_str());
    bool ret = _file->Close();
    delete _file;
    _file = NULL;
    if (!ret) {
        LOG(INFO, "CloseFile(%s) fail", _name.c_str());
        return -1;
    }
    LOG(INFO, "CloseFile(%s) succeed", _name.c_str());
    return 0;
}

BfsImpl::BfsImpl(const std::string& conf) {
    if (!FS::OpenFileSystem(conf.c_str(), &_fs)) {
        assert(0);
    }
}

int32_t BfsImpl::CreateDirectory(const std::string& path) {
    LOG(INFO, "CreateDirectory(%s)", path.c_str());
    _fs->CreateDirectory(path.c_str());
    return 0;
}
int32_t BfsImpl::DeleteDirectory(const std::string& path) {
    LOG(INFO, "DeleteDirectory(%s)", path.c_str());
    if (!_fs->DeleteDirectory(path.c_str(), true)) {
        LOG(INFO, "DeleteDirectory(%s) fail", path.c_str());
        return -1;
    }
    LOG(INFO, "DeleteDirectory(%s) succeed", path.c_str());
    return 0;
}
int32_t BfsImpl::Exists(const std::string& filename) {
    LOG(INFO, "Exists(%s)", filename.c_str());
    if (!_fs->Access(filename.c_str(), 0)) {
        LOG(INFO, "Exists(%s) return false", filename.c_str());
        return -1;
    }
    LOG(INFO, "Exists(%s) return true", filename.c_str());
    return 0;
}
int32_t BfsImpl::Delete(const std::string& filename) {
    common::timer::AutoTimer ac(1, "Delete", filename.c_str());
    if (!_fs->DeleteFile(filename.c_str())) {
        LOG(INFO, "Delete(%s) fail", filename.c_str());
        return -1;
    }
    LOG(INFO, "Delete(%s) succeed", filename.c_str());
    return 0;
}
int32_t BfsImpl::GetFileSize(const std::string& filename, uint64_t* size) {
    int64_t file_size = 0;
    if (!_fs->GetFileSize(filename.c_str(), &file_size)) {
        LOG(INFO, "GetFileSize(%s) fail", filename.c_str());
        return -1;
    }
    *size = file_size;
    LOG(INFO, "GetFileSize(%s) return %lu", filename.c_str(), *size);
    return 0;
}
int32_t BfsImpl::Rename(const std::string& from, const std::string& to) {
    Delete(to);
    if (!_fs->Rename(from.c_str(), to.c_str())) {
        LOG(INFO, "Rename(%s, %s) fail", from.c_str(), to.c_str());
        return -1;
    }
    LOG(INFO, "Rename(%s, %s) succeed", from.c_str(), to.c_str());
    return 0;
}
int32_t BfsImpl::Copy(const std::string& from, const std::string& to) {
    LOG(INFO, "Copy(%s, %s)", from.c_str(), to.c_str());
    abort();
    return 0;
}

int32_t BfsImpl::ListDirectory(const std::string& path, std::vector<std::string>* result) {
    common::timer::AutoTimer ac(1, "ListDirectory", path.c_str());
    LOG(INFO, "ListDirectory(%s)", path.c_str());
    if (result == NULL) {
        return -1;
    }
    bfs::BfsFileInfo* files = NULL;
    int num = 0;
    if (!_fs->ListDirectory(path.c_str(), &files, &num)) {
        return -1;
    }
    for (int i = 0; i < num; i++) {
        char* pathname = files[i].name;
        char* filename = rindex(pathname, '/');
        if (filename != NULL && filename[0] != '\0') {
            result->push_back(filename + 1);
        }
    }
    delete[] files;
    LOG(INFO, "ListDirectory(%s) return %lu items", path.c_str(), result->size());
    return 0;
}

leveldb::DfsFile* BfsImpl::OpenFile(const std::string& filename, int32_t flags) {
    common::timer::AutoTimer ac(0, "OpenFile", filename.c_str());
    LOG(INFO, "OpenFile(%s,%d)", filename.c_str(), flags);
    int openflag = O_WRONLY;
    if (leveldb::WRONLY != flags) {
        openflag = O_RDONLY;
    }
    bfs::File* file = NULL;
    if (!_fs->OpenFile(filename.c_str(), openflag, &file)) {
        return NULL;
    }
    LOG(INFO, "OpenFile(%s,%d) succeed", filename.c_str(), flags);
    return new BfsFile(filename, file);
}

} // namespace

extern "C" {

leveldb::Dfs* NewDfs(const char* conf) {
    common::SetLogFile("./bfslog");
    common::SetWarningFile("./bfswf");
    return new bfs::BfsImpl(conf);
}

}
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<|endoftext|>


<commit_before>#ifndef MJOLNIR_UTIL_RANGE_HPP
#define MJOLNIR_UTIL_RANGE_HPP
#include <iterator>

namespace mjolnir
{

template<typename Iterator>
struct range
{
    using iterator = Iterator;
    using reverse_iterator = std::reverse_iterator<iterator>;

    range(iterator b, iterator e) noexcept
        : begin_(b), end_(e), sz_(std::distance(b, e))
    {}

    range() noexcept : sz_(0){}
    ~range() = default;
    range(const range&) = default;
    range(range&&)      = default;
    range& operator=(const range&) = default;
    range& operator=(range&&)      = default;

    iterator begin() const noexcept {return begin_;}
    iterator end()   const noexcept {return end_;}
    reverse_iterator rbegin() const noexcept {return reverse_iterator(begin_);}
    reverse_iterator rend()   const noexcept {return reverse_iterator(end_);}

    std::size_t size() const noexcept {return sz_;}

    iterator begin_;
    iterator end_;
    std::size_t sz_;
};

template<typename Iterator>
inline range<Iterator> make_range(Iterator b, Iterator e)
{
    return range<Iterator>(b, e);
}

} // mjolnir
#endif// MJOLNIR_UTIL_RANGE_HPP
<commit_msg>test: check range::iterator is randomly accessible<commit_after>#ifndef MJOLNIR_UTIL_RANGE_HPP
#define MJOLNIR_UTIL_RANGE_HPP
#include <iterator>

namespace mjolnir
{

template<typename Iterator>
struct range
{
    using iterator         = Iterator;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using value_type       = typename std::iterator_traits<iterator>::value_type;
    using reference        = typename std::iterator_traits<iterator>::reference;

    static_assert(std::is_same<std::random_access_iterator_tag,
        typename std::iterator_traits<iterator>::iterator_category
        >::value, "mjolnir::range assumes iterator to be randomly accessible");

    range(iterator b, iterator e) noexcept
        : begin_(b), end_(e), sz_(std::distance(b, e))
    {}

    range() noexcept : sz_(0){}
    ~range() = default;
    range(const range&) = default;
    range(range&&)      = default;
    range& operator=(const range&) = default;
    range& operator=(range&&)      = default;

    iterator begin() const noexcept {return begin_;}
    iterator end()   const noexcept {return end_;}
    reverse_iterator rbegin() const noexcept {return reverse_iterator(begin_);}
    reverse_iterator rend()   const noexcept {return reverse_iterator(end_);}

    std::size_t size() const noexcept {return sz_;}

    iterator begin_;
    iterator end_;
    std::size_t sz_;
};

template<typename Iterator>
inline range<Iterator> make_range(Iterator b, Iterator e)
{
    return range<Iterator>(b, e);
}

} // mjolnir
#endif// MJOLNIR_UTIL_RANGE_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2011-2015 Branimir Karadzic. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include "common.h"
#include "bgfx_utils.h"
#include "camera.h"

#define CUBES_DIM 10

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	};

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

class Occlusion : public entry::AppI
{
	void init(int _argc, char** _argv) BX_OVERRIDE
	{
		Args args(_argc, _argv);

		uint32_t width  = 1280;
		uint32_t height = 720;
		m_debug  = BGFX_DEBUG_TEXT;
		m_reset  = BGFX_RESET_VSYNC;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(width, height, m_reset);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x303030ff
				, 1.0f
				, 0
				);

		bgfx::setViewClear(2
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x202020ff
				, 1.0f
				, 0
				);

		// Create vertex stream declaration.
		PosColorVertex::init();

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
				, PosColorVertex::ms_decl
				);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) )
				);

		// Create program from shaders.
		m_program = loadProgram("vs_cubes", "fs_cubes");

		for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii)
		{
			m_occlusionQueries[ii] = bgfx::createOcclusionQuery();
		}

		cameraCreate();

		const float initialPos[3] = { 15.5f, 0.0f, -15.5f };
		cameraSetPosition(initialPos);
		cameraSetHorizontalAngle(bx::toRad(-45.0f) );

		m_timeOffset = bx::getHPCounter();
	}

	virtual int shutdown() BX_OVERRIDE
	{
		// Cleanup.
		cameraDestroy();

		for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii)
		{
			bgfx::destroyOcclusionQuery(m_occlusionQueries[ii]);
		}

		bgfx::destroyIndexBuffer(m_ibh);
		bgfx::destroyVertexBuffer(m_vbh);
		bgfx::destroyProgram(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() BX_OVERRIDE
	{
		if (!entry::processWindowEvents(m_state, m_debug, m_reset) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(bx::getHPFrequency() );
			const double toMs = 1000.0/freq;
			const float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) );
			const float deltaTime = float(frameTime/freq);

			// Use debug font to print information about this example.
			bgfx::dbgTextClear();
			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/26-occlusion");
			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Using occlusion query to do conditional rendering.");
			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);

			uint32_t width  = m_state.m_width;
			uint32_t height = m_state.m_height;

			// Update camera.
			float view[16];
			cameraUpdate(deltaTime, m_state.m_mouse);
			cameraGetViewMtx(view);

			// Set view and projection matrix for view 0.
			const bgfx::HMD* hmd = bgfx::getHMD();
			if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) )
			{
				float viewHead[16];
				float eye[3] = {};
				bx::mtxQuatTranslationHMD(viewHead, hmd->eye[0].rotation, eye);

				float tmp[16];
				bx::mtxMul(tmp, view, viewHead);

				float proj[16];
				bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);

				bgfx::setViewTransform(0, tmp, proj);
				bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);

				bgfx::setViewTransform(1, tmp, proj);
				bgfx::setViewRect(1, 0, 0, hmd->width, hmd->height);
			}
			else
			{
				float proj[16];
				bx::mtxProj(proj, 90.0f, float(width)/float(height), 0.1f, 10000.0f);

				bgfx::setViewTransform(0, view, proj);
				bgfx::setViewRect(0, 0, 0, width, height);

				bgfx::setViewTransform(1, view, proj);
				bgfx::setViewRect(1, 0, 0, width, height);

				float at[3]  = {  0.0f,  0.0f,   0.0f };
				float eye[3] = { 17.5f, 10.0f, -17.5f };
				bx::mtxLookAt(view, eye, at);

				bgfx::setViewTransform(2, view, proj);
				bgfx::setViewRect(2, 10, height - height/4 - 10, width/4, height/4);
			}

			bgfx::touch(0);
			bgfx::touch(2);

			for (uint32_t yy = 0; yy < CUBES_DIM; ++yy)
			{
				for (uint32_t xx = 0; xx < CUBES_DIM; ++xx)
				{
					float mtx[16];
					bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f);
					mtx[12] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(xx)*3.0f;
					mtx[13] = 0.0f;
					mtx[14] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(yy)*3.0f;

					bgfx::OcclusionQueryHandle occlusionQuery = m_occlusionQueries[yy*CUBES_DIM+xx];

					bgfx::setTransform(mtx);
					bgfx::setVertexBuffer(m_vbh);
					bgfx::setIndexBuffer(m_ibh);
					bgfx::setCondition(occlusionQuery, true);
					bgfx::setState(BGFX_STATE_DEFAULT);
					bgfx::submit(0, m_program);

					bgfx::setTransform(mtx);
					bgfx::setVertexBuffer(m_vbh);
					bgfx::setIndexBuffer(m_ibh);
					bgfx::setState(0
						| BGFX_STATE_DEPTH_TEST_LEQUAL
						| BGFX_STATE_CULL_CW
						);
					bgfx::submit(1, m_program, occlusionQuery);

					bgfx::setTransform(mtx);
					bgfx::setVertexBuffer(m_vbh);
					bgfx::setIndexBuffer(m_ibh);
					bgfx::setCondition(occlusionQuery, true);
					bgfx::setState(BGFX_STATE_DEFAULT);
					bgfx::submit(2, m_program);
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	uint32_t m_reset;
	uint32_t m_debug;

	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle m_ibh;
	bgfx::ProgramHandle m_program;
	int64_t m_timeOffset;

	bgfx::OcclusionQueryHandle m_occlusionQueries[CUBES_DIM*CUBES_DIM];

	entry::WindowState m_state;
};

ENTRY_IMPLEMENT_MAIN(Occlusion);
<commit_msg>Cleanup.<commit_after>/*
 * Copyright 2011-2015 Branimir Karadzic. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include "common.h"
#include "bgfx_utils.h"
#include "camera.h"

#define CUBES_DIM 10

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	};

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

class Occlusion : public entry::AppI
{
	void init(int _argc, char** _argv) BX_OVERRIDE
	{
		Args args(_argc, _argv);

		uint32_t width  = 1280;
		uint32_t height = 720;
		m_debug  = BGFX_DEBUG_TEXT;
		m_reset  = BGFX_RESET_VSYNC;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(width, height, m_reset);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x303030ff
				, 1.0f
				, 0
				);

		bgfx::setViewClear(2
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x202020ff
				, 1.0f
				, 0
				);

		// Create vertex stream declaration.
		PosColorVertex::init();

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
				, PosColorVertex::ms_decl
				);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) )
				);

		// Create program from shaders.
		m_program = loadProgram("vs_cubes", "fs_cubes");

		for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii)
		{
			m_occlusionQueries[ii] = bgfx::createOcclusionQuery();
		}

		cameraCreate();

		const float initialPos[3] = { 15.5f, 0.0f, -15.5f };
		cameraSetPosition(initialPos);
		cameraSetHorizontalAngle(bx::toRad(-45.0f) );

		m_timeOffset = bx::getHPCounter();
	}

	virtual int shutdown() BX_OVERRIDE
	{
		// Cleanup.
		cameraDestroy();

		for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii)
		{
			bgfx::destroyOcclusionQuery(m_occlusionQueries[ii]);
		}

		bgfx::destroyIndexBuffer(m_ibh);
		bgfx::destroyVertexBuffer(m_vbh);
		bgfx::destroyProgram(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() BX_OVERRIDE
	{
		if (!entry::processWindowEvents(m_state, m_debug, m_reset) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(bx::getHPFrequency() );
			const double toMs = 1000.0/freq;
			const float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) );
			const float deltaTime = float(frameTime/freq);

			// Use debug font to print information about this example.
			bgfx::dbgTextClear();
			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/26-occlusion");
			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Using occlusion query for conditional rendering.");
			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);

			uint32_t width  = m_state.m_width;
			uint32_t height = m_state.m_height;

			// Update camera.
			float view[16];
			cameraUpdate(deltaTime, m_state.m_mouse);
			cameraGetViewMtx(view);

			// Set view and projection matrix for view 0.
			const bgfx::HMD* hmd = bgfx::getHMD();
			if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) )
			{
				float viewHead[16];
				float eye[3] = {};
				bx::mtxQuatTranslationHMD(viewHead, hmd->eye[0].rotation, eye);

				float tmp[16];
				bx::mtxMul(tmp, view, viewHead);

				float proj[16];
				bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);

				bgfx::setViewTransform(0, tmp, proj);
				bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);

				bgfx::setViewTransform(1, tmp, proj);
				bgfx::setViewRect(1, 0, 0, hmd->width, hmd->height);
			}
			else
			{
				float proj[16];
				bx::mtxProj(proj, 90.0f, float(width)/float(height), 0.1f, 10000.0f);

				bgfx::setViewTransform(0, view, proj);
				bgfx::setViewRect(0, 0, 0, width, height);

				bgfx::setViewTransform(1, view, proj);
				bgfx::setViewRect(1, 0, 0, width, height);

				float at[3]  = {  0.0f,  0.0f,   0.0f };
				float eye[3] = { 17.5f, 10.0f, -17.5f };
				bx::mtxLookAt(view, eye, at);

				bgfx::setViewTransform(2, view, proj);
				bgfx::setViewRect(2, 10, height - height/4 - 10, width/4, height/4);
			}

			bgfx::touch(0);
			bgfx::touch(2);

			for (uint32_t yy = 0; yy < CUBES_DIM; ++yy)
			{
				for (uint32_t xx = 0; xx < CUBES_DIM; ++xx)
				{
					float mtx[16];
					bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f);
					mtx[12] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(xx)*3.0f;
					mtx[13] = 0.0f;
					mtx[14] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(yy)*3.0f;

					bgfx::OcclusionQueryHandle occlusionQuery = m_occlusionQueries[yy*CUBES_DIM+xx];

					bgfx::setTransform(mtx);
					bgfx::setVertexBuffer(m_vbh);
					bgfx::setIndexBuffer(m_ibh);
					bgfx::setCondition(occlusionQuery, true);
					bgfx::setState(BGFX_STATE_DEFAULT);
					bgfx::submit(0, m_program);

					bgfx::setTransform(mtx);
					bgfx::setVertexBuffer(m_vbh);
					bgfx::setIndexBuffer(m_ibh);
					bgfx::setState(0
						| BGFX_STATE_DEPTH_TEST_LEQUAL
						| BGFX_STATE_CULL_CW
						);
					bgfx::submit(1, m_program, occlusionQuery);

					bgfx::setTransform(mtx);
					bgfx::setVertexBuffer(m_vbh);
					bgfx::setIndexBuffer(m_ibh);
					bgfx::setCondition(occlusionQuery, true);
					bgfx::setState(BGFX_STATE_DEFAULT);
					bgfx::submit(2, m_program);
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	uint32_t m_reset;
	uint32_t m_debug;

	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle m_ibh;
	bgfx::ProgramHandle m_program;
	int64_t m_timeOffset;

	bgfx::OcclusionQueryHandle m_occlusionQueries[CUBES_DIM*CUBES_DIM];

	entry::WindowState m_state;
};

ENTRY_IMPLEMENT_MAIN(Occlusion);
<|endoftext|>


<commit_before>#ifndef _BUFFERED_READER_HPP
#define _BUFFERED_READER_HPP

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdio>
#include <exception>
#include <iostream>
#include <list>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <utility>
#include <vector>

#include "MaeParserConfig.hpp"

namespace schrodinger
{

/**
 * A simple data class to hold unchanging character buffer data. Copies are
 * reference counted.
 */
class EXPORT_MAEPARSER BufferData
{
  private:
    std::vector<char> m_data;
    size_t m_size;

  public:
    explicit BufferData(size_t size = 0);

    /**
     * Return access to the beginning of the data buffer for loading.
     */
    char* begin() { return m_data.data(); }

    /**
     * Return a pointer to the beginning of the character buffer.
     */
    const char* begin() const { return m_data.data(); }

    /**
     * Return the logical size of the buffer.
     */
    size_t size() const { return m_size; }

    /**
     * Reduce (but not increase) logical size of the buffer (to keep track of
     * size).
     *
     * Specifying a size larger than the current one throws a runtime_error.
     *
     * This doesn't actually free up any memory or modify the underlying
     * character buffer.
     */
    void resize(size_t size);
};

/**
 * Base class for loading BufferData objects from some source.
 */
class BufferLoader
{
  private:
    size_t m_default_size;

  public:
    static const size_t DEFAULT_SIZE = 131072;

    explicit BufferLoader(size_t default_size = DEFAULT_SIZE)
        : m_default_size(default_size)
    {
    }

    virtual ~BufferLoader() = default;

    /**
     * Return the default buffer size for this BufferLoader. This should be
     * used to construct the BufferData object if no other size is preferred.
     */
    virtual size_t getDefaultSize() const { return m_default_size; }

    /**
     * Load the next chunk of data into the BufferData object.
     *
     * The amount of data loaded will be a maximum of the current size of
     * BufferData.
     *
     * Returns true if new characters were loaded.
     */
    bool load(BufferData& data) const
    {
        char* begin = nullptr;
        char* end = nullptr;
        return load(data, begin, end);
    }

    /**
     * Copy everything from 'begin' through 'end' to the beginning of the
     * BufferData object (to deal with tokens that span buffer boundaries) and
     * then load the next chunk of data into the remainder of the BufferData.
     *
     * Returns true if new characters were loaded.
     */
    virtual bool load(BufferData& data, const char* begin,
                      const char* end) const;

  protected:
    /**
     * Read 'size' bytes and dump them into 'ptr'. Return the number of bytes
     * loaded.
     */
    virtual size_t readData(char* ptr, size_t size) const = 0;
};

/**
 * A BufferLoader that reads from an input stream.
 *
 * Note that the input stream is not owned by the StreamLoader (and so
 * ifstreams must be closed by the caller).
 */
class StreamLoader : public BufferLoader
{
  private:
    std::istream& m_stream;

  public:
    StreamLoader(std::istream& stream) : m_stream(stream) {}

    StreamLoader() = delete;
    StreamLoader(const StreamLoader&) = delete;
    StreamLoader& operator=(const StreamLoader&) = delete;

    size_t readData(char* ptr, size_t size) const override;
};

/**
 * A BufferLoader that reads from a FILE pointer.
 *
 * Experiments on OS X show this to be measurably faster than input stream
 * reading. While it seems this isn't expected in theory, no way to make them
 * equivalent has yet been found in practice.
 *
 * Note that the FILE pointer is not owned by the FileLoader and must be closed
 * by the caller.
 */
class FileLoader : public BufferLoader
{
  private:
    FILE* m_file;

  public:
    FileLoader(FILE* file) : m_file(file) {}

    size_t readData(char* ptr, size_t size) const override;
};

/**
 * Character buffer.
 *
 * This is a shared resource manager for an allocated character buffer along
 * with iterator location information.
 *
 * The character buffer is stored in a BufferData object, which is reference
 * counted and can be retrieved by the data() method.
 */
class EXPORT_MAEPARSER Buffer
{
  private:
    BufferData m_data;
    BufferLoader* m_loader{nullptr};
    size_t m_starting_column{1};

  public:
    char* begin{nullptr};
    char* end{nullptr};
    char* current{nullptr};
    size_t line_number{1};

    explicit Buffer(size_t buffer_size = 0);

    /**
     * Construct an empty buffer that can be loaded from the provided input
     * stream.
     */
    explicit Buffer(std::istream& stream, size_t buffer_size = 0);

    /**
     * Construct an empty buffer that can be loaded from the provided FILE
     * pointer.
     */
    explicit Buffer(FILE* file, size_t buffer_size = 0);

    /**
     * Create a buffer from a string.
     *
     * This makes a copy of the string data. Calls to load() always return
     * false.
     */
    explicit Buffer(const std::string& str);

    ~Buffer();

    Buffer(const Buffer&) = delete;
    Buffer& operator=(const Buffer&) = delete;

  public:
    void setBufferLoader(BufferLoader* loader) { m_loader = loader; }

    BufferLoader* getBufferLoader() { return m_loader; }

    /**
     * Load new BufferData from the BufferLoader. Update Buffer pointers.
     */
    bool load()
    {
        char* save = nullptr;
        return load(save);
    }

    /**
     * Save data from the 'save' pointer to the end of the current BufferData
     * into a new BufferData instance, then load the remainder of the
     * BufferData instance with data from the BufferLoader.
     *
     * This allows us to deal with tokens that cross buffer boundaries.
     *
     * Update Buffer pointers.
     */
    bool load(char*& save);

    inline size_t size() const { return m_data.size(); }

    BufferData data() const { return m_data; }

    inline bool operator==(const Buffer& other) const
    {
        return this->m_data.begin() == other.m_data.begin();
    }

    inline bool operator!=(const Buffer& other) const
    {
        return !(*this == other);
    }

    friend std::ostream& operator<<(std::ostream& os, const Buffer& b);

    /**
     * Return the column number of the last character read.
     */
    size_t getColumn() const { return getColumn(current); }

    /**
     * Return the column number of the provided character.
     */
    size_t getColumn(const char* ptr) const;
};

/**
 * Allow Buffer objects to be written to a stream.
 *
 * This purpose of this is only to allow Boost testing assertions to work. It
 * doesn't do anything terribly useful.
 */
std::ostream& operator<<(std::ostream& os, const Buffer& b);

/**
 * A class to collect tokens with minimal copying by saving the buffer and
 * token start and end indices.
 */
class EXPORT_MAEPARSER TokenBufferList
{
  public:
    /// A simple data class to keep the info about the buffers and tokens
    // straight.
    class EXPORT_MAEPARSER TokenBuffer
    {
      public:
        BufferData buffer_data;
        /// The index of the first token stored in this buffer.
        size_t first_value;
        /// One greater than the index of the last token stored in this buffer.
        size_t last_value;

        TokenBuffer(BufferData data, size_t next_index)
            : buffer_data(std::move(data)), first_value(next_index),
              last_value(next_index)
        {
        }
    };

  private:
    /// List of TokenBuffer objects.
    std::list<TokenBuffer> m_token_buffer_list;

    /// Buffer indices for the beginnings of collected tokens.
    std::vector<size_t> m_begin;

    /// Buffer indices for one past the end of collected tokens.
    std::vector<size_t> m_end;

  public:
    TokenBufferList() : m_token_buffer_list(), m_begin(), m_end() {}

    ///
    //  Create a TokenBufferList from an initial Buffer and the number of
    //  values you expect to be collected. The number of collected tokens
    //  isn't limited to this value, it's just used to reserve space for
    //  storage.
    //
    explicit TokenBufferList(const BufferData& buffer_data, size_t values = 0)
        : TokenBufferList()
    {
        reserve(values);
        if (buffer_data.size() != 0) {
            m_token_buffer_list.emplace_back(buffer_data, 0);
        }
    }

    void reserve(size_t size)
    {
        m_begin.reserve(size);
        m_end.reserve(size);
    }

    inline void setTokenIndices(size_t begin, size_t end)
    {
        m_begin.push_back(begin);
        m_end.push_back(end);
        m_token_buffer_list.back().last_value = m_end.size();
    }

    void appendBufferData(const BufferData& buffer_data);

    /**
     * Return token data as char pointer and length.
     *
     * Data is owned by the TokenBufferList and does not need to be freed.
     *
     * No trailing '\0' is present; data length must be observed.
     */
    void getData(size_t index, const char** const data,
                 size_t* const length) const;
};

/**
 * A class to modify a Buffer's loading behavior through RAII.
 *
 * It collects all loaded BufferData instances and stores them in a
 * TokenBufferList for parsing later.
 */
class BufferDataCollector : public BufferLoader
{
  private:
    Buffer* m_buffer;
    BufferLoader* m_loader;
    TokenBufferList* m_tokens_list;

  public:
    BufferDataCollector(Buffer* buffer, TokenBufferList* tokens_list)
        : m_loader(nullptr), m_tokens_list(tokens_list)
    {
        m_buffer = buffer;
        m_loader = m_buffer->getBufferLoader();
        m_buffer->setBufferLoader(this);
    }

    ~BufferDataCollector() override { m_buffer->setBufferLoader(m_loader); }

    bool load(BufferData& data, const char* begin,
              const char* end) const override;

    size_t readData(char* ptr, size_t size) const override;
};

} // end namespace schrodinger

#endif
<commit_msg>remove TokenBufferList constructor<commit_after>#ifndef _BUFFERED_READER_HPP
#define _BUFFERED_READER_HPP

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdio>
#include <exception>
#include <iostream>
#include <list>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <utility>
#include <vector>

#include "MaeParserConfig.hpp"

namespace schrodinger
{

/**
 * A simple data class to hold unchanging character buffer data. Copies are
 * reference counted.
 */
class EXPORT_MAEPARSER BufferData
{
  private:
    std::vector<char> m_data;
    size_t m_size;

  public:
    explicit BufferData(size_t size = 0);

    /**
     * Return access to the beginning of the data buffer for loading.
     */
    char* begin() { return m_data.data(); }

    /**
     * Return a pointer to the beginning of the character buffer.
     */
    const char* begin() const { return m_data.data(); }

    /**
     * Return the logical size of the buffer.
     */
    size_t size() const { return m_size; }

    /**
     * Reduce (but not increase) logical size of the buffer (to keep track of
     * size).
     *
     * Specifying a size larger than the current one throws a runtime_error.
     *
     * This doesn't actually free up any memory or modify the underlying
     * character buffer.
     */
    void resize(size_t size);
};

/**
 * Base class for loading BufferData objects from some source.
 */
class BufferLoader
{
  private:
    size_t m_default_size;

  public:
    static const size_t DEFAULT_SIZE = 131072;

    explicit BufferLoader(size_t default_size = DEFAULT_SIZE)
        : m_default_size(default_size)
    {
    }

    virtual ~BufferLoader() = default;

    /**
     * Return the default buffer size for this BufferLoader. This should be
     * used to construct the BufferData object if no other size is preferred.
     */
    virtual size_t getDefaultSize() const { return m_default_size; }

    /**
     * Load the next chunk of data into the BufferData object.
     *
     * The amount of data loaded will be a maximum of the current size of
     * BufferData.
     *
     * Returns true if new characters were loaded.
     */
    bool load(BufferData& data) const
    {
        char* begin = nullptr;
        char* end = nullptr;
        return load(data, begin, end);
    }

    /**
     * Copy everything from 'begin' through 'end' to the beginning of the
     * BufferData object (to deal with tokens that span buffer boundaries) and
     * then load the next chunk of data into the remainder of the BufferData.
     *
     * Returns true if new characters were loaded.
     */
    virtual bool load(BufferData& data, const char* begin,
                      const char* end) const;

  protected:
    /**
     * Read 'size' bytes and dump them into 'ptr'. Return the number of bytes
     * loaded.
     */
    virtual size_t readData(char* ptr, size_t size) const = 0;
};

/**
 * A BufferLoader that reads from an input stream.
 *
 * Note that the input stream is not owned by the StreamLoader (and so
 * ifstreams must be closed by the caller).
 */
class StreamLoader : public BufferLoader
{
  private:
    std::istream& m_stream;

  public:
    StreamLoader(std::istream& stream) : m_stream(stream) {}

    StreamLoader() = delete;
    StreamLoader(const StreamLoader&) = delete;
    StreamLoader& operator=(const StreamLoader&) = delete;

    size_t readData(char* ptr, size_t size) const override;
};

/**
 * A BufferLoader that reads from a FILE pointer.
 *
 * Experiments on OS X show this to be measurably faster than input stream
 * reading. While it seems this isn't expected in theory, no way to make them
 * equivalent has yet been found in practice.
 *
 * Note that the FILE pointer is not owned by the FileLoader and must be closed
 * by the caller.
 */
class FileLoader : public BufferLoader
{
  private:
    FILE* m_file;

  public:
    FileLoader(FILE* file) : m_file(file) {}

    size_t readData(char* ptr, size_t size) const override;
};

/**
 * Character buffer.
 *
 * This is a shared resource manager for an allocated character buffer along
 * with iterator location information.
 *
 * The character buffer is stored in a BufferData object, which is reference
 * counted and can be retrieved by the data() method.
 */
class EXPORT_MAEPARSER Buffer
{
  private:
    BufferData m_data;
    BufferLoader* m_loader{nullptr};
    size_t m_starting_column{1};

  public:
    char* begin{nullptr};
    char* end{nullptr};
    char* current{nullptr};
    size_t line_number{1};

    explicit Buffer(size_t buffer_size = 0);

    /**
     * Construct an empty buffer that can be loaded from the provided input
     * stream.
     */
    explicit Buffer(std::istream& stream, size_t buffer_size = 0);

    /**
     * Construct an empty buffer that can be loaded from the provided FILE
     * pointer.
     */
    explicit Buffer(FILE* file, size_t buffer_size = 0);

    /**
     * Create a buffer from a string.
     *
     * This makes a copy of the string data. Calls to load() always return
     * false.
     */
    explicit Buffer(const std::string& str);

    ~Buffer();

    Buffer(const Buffer&) = delete;
    Buffer& operator=(const Buffer&) = delete;

  public:
    void setBufferLoader(BufferLoader* loader) { m_loader = loader; }

    BufferLoader* getBufferLoader() { return m_loader; }

    /**
     * Load new BufferData from the BufferLoader. Update Buffer pointers.
     */
    bool load()
    {
        char* save = nullptr;
        return load(save);
    }

    /**
     * Save data from the 'save' pointer to the end of the current BufferData
     * into a new BufferData instance, then load the remainder of the
     * BufferData instance with data from the BufferLoader.
     *
     * This allows us to deal with tokens that cross buffer boundaries.
     *
     * Update Buffer pointers.
     */
    bool load(char*& save);

    inline size_t size() const { return m_data.size(); }

    BufferData data() const { return m_data; }

    inline bool operator==(const Buffer& other) const
    {
        return this->m_data.begin() == other.m_data.begin();
    }

    inline bool operator!=(const Buffer& other) const
    {
        return !(*this == other);
    }

    friend std::ostream& operator<<(std::ostream& os, const Buffer& b);

    /**
     * Return the column number of the last character read.
     */
    size_t getColumn() const { return getColumn(current); }

    /**
     * Return the column number of the provided character.
     */
    size_t getColumn(const char* ptr) const;
};

/**
 * Allow Buffer objects to be written to a stream.
 *
 * This purpose of this is only to allow Boost testing assertions to work. It
 * doesn't do anything terribly useful.
 */
std::ostream& operator<<(std::ostream& os, const Buffer& b);

/**
 * A class to collect tokens with minimal copying by saving the buffer and
 * token start and end indices.
 */
class EXPORT_MAEPARSER TokenBufferList
{
  public:
    /// A simple data class to keep the info about the buffers and tokens
    // straight.
    class EXPORT_MAEPARSER TokenBuffer
    {
      public:
        BufferData buffer_data;
        /// The index of the first token stored in this buffer.
        size_t first_value;
        /// One greater than the index of the last token stored in this buffer.
        size_t last_value;

        TokenBuffer(BufferData data, size_t next_index)
            : buffer_data(std::move(data)), first_value(next_index),
              last_value(next_index)
        {
        }
    };

  private:
    /// List of TokenBuffer objects.
    std::list<TokenBuffer> m_token_buffer_list;

    /// Buffer indices for the beginnings of collected tokens.
    std::vector<size_t> m_begin;

    /// Buffer indices for one past the end of collected tokens.
    std::vector<size_t> m_end;

  public:
    TokenBufferList() : m_token_buffer_list(), m_begin(), m_end() {}

    void reserve(size_t size)
    {
        m_begin.reserve(size);
        m_end.reserve(size);
    }

    inline void setTokenIndices(size_t begin, size_t end)
    {
        m_begin.push_back(begin);
        m_end.push_back(end);
        m_token_buffer_list.back().last_value = m_end.size();
    }

    void appendBufferData(const BufferData& buffer_data);

    /**
     * Return token data as char pointer and length.
     *
     * Data is owned by the TokenBufferList and does not need to be freed.
     *
     * No trailing '\0' is present; data length must be observed.
     */
    void getData(size_t index, const char** const data,
                 size_t* const length) const;
};

/**
 * A class to modify a Buffer's loading behavior through RAII.
 *
 * It collects all loaded BufferData instances and stores them in a
 * TokenBufferList for parsing later.
 */
class BufferDataCollector : public BufferLoader
{
  private:
    Buffer* m_buffer;
    BufferLoader* m_loader;
    TokenBufferList* m_tokens_list;

  public:
    BufferDataCollector(Buffer* buffer, TokenBufferList* tokens_list)
        : m_loader(nullptr), m_tokens_list(tokens_list)
    {
        m_buffer = buffer;
        m_loader = m_buffer->getBufferLoader();
        m_buffer->setBufferLoader(this);
    }

    ~BufferDataCollector() override { m_buffer->setBufferLoader(m_loader); }

    bool load(BufferData& data, const char* begin,
              const char* end) const override;

    size_t readData(char* ptr, size_t size) const override;
};

} // end namespace schrodinger

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *	Manjeet Dahiya
 *
 * Source:
 *	http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "statusWidget.h"
#include <QMenu>
#include <QFileDialog>
#include <QMessageBox>

statusWidget::statusWidget(QWidget* parent)
{
    setupUi(this);
    QMenu* menu = new QMenu(this);
    menu->addAction(actionAvailable);
    menu->addAction(actionBusy);
    menu->addAction(actionAway);
//    menu->addAction(actionInvisible);
    menu->addSeparator();
    menu->addAction(actionSign_out);
    toolButton_userName->setMenu(menu);

    bool check = connect(statusTextWidgetObject, SIGNAL(statusTextChanged(const QString&)), SIGNAL(statusTextChanged(const QString&)));
    Q_ASSERT(check);

    check = connect(actionAvailable, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionBusy, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionAway, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionInvisible, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionSign_out, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);

    check = connect(pushButton_avatar, SIGNAL(clicked()), SLOT(avatarSelection()));
    Q_ASSERT(check);
}

void statusWidget::setStatusText(const QString& statusText)
{
    statusTextWidgetObject->setStatusText(statusText);
}

void statusWidget::presenceMenuTriggered()
{
    QString icon = "green";
    QAction* action = qobject_cast<QAction*>(sender());
    if(action == actionAvailable)
    {
        emit presenceTypeChanged(QXmppPresence::Available);
        icon = "green";
    }
    else if(action == actionBusy)
    {
        emit presenceStatusTypeChanged(QXmppPresence::Status::DND);
        icon = "red";
    }
    else if(action == actionAway)
    {
        emit presenceStatusTypeChanged(QXmppPresence::Status::Away);
        icon = "orange";
    }
    else if(action == actionInvisible)
    {
        emit presenceStatusTypeChanged(QXmppPresence::Status::Invisible);
        icon = "gray";
    }
    else if(action == actionSign_out)
    {
        emit presenceTypeChanged(QXmppPresence::Unavailable);
        icon = "gray";
    }
    label->setPixmap(QPixmap(":/icons/resource/"+icon+".png"));
}

void statusWidget::setPresenceAndStatusType(QXmppPresence::Type presenceType,
                                  QXmppPresence::Status::Type statusType)
{
    if(presenceType == QXmppPresence::Available)
    {
        QString icon = "green";
        switch(statusType)
        {
        case QXmppPresence::Status::Online:
        case QXmppPresence::Status::Chat:
            icon = "green";
            break;
        case QXmppPresence::Status::Away:
        case QXmppPresence::Status::XA:
            icon = "orange";
            break;
        case QXmppPresence::Status::DND:
            icon = "red";
            break;
        case QXmppPresence::Status::Invisible:
        case QXmppPresence::Status::Offline:
            icon = "gray";
            break;
        }
        label->setPixmap(QPixmap(":/icons/resource/"+icon+".png"));
    }
    else if(presenceType == QXmppPresence::Unavailable)
    {
        label->setPixmap(QPixmap(":/icons/resource/gray.png"));
    }
}

void statusWidget::avatarSelection()
{
    QString file = QFileDialog::getOpenFileName(this, "Select your avatar", QString(),
                                                QString("Images (*.png *.jpeg *.jpg)"));
    if(file.isEmpty())
        return;

    QImage image;
    if(image.load(file))
    {
        QImage scaled = image.scaled(QSize(96, 96), Qt::KeepAspectRatio,
                                     Qt::SmoothTransformation);
        emit avatarChanged(scaled);
    }
    else
        QMessageBox::information(this, "Avatar selection", "Invalid image file");
}

void statusWidget::setDisplayName(const QString& name)
{
    toolButton_userName->setText(name);
}

void statusWidget::setAvatar(const QImage& image)
{
    pushButton_avatar->setIcon(QIcon(QPixmap::fromImage(image)));
}
<commit_msg>add more filters<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *	Manjeet Dahiya
 *
 * Source:
 *	http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "statusWidget.h"
#include <QMenu>
#include <QFileDialog>
#include <QMessageBox>

statusWidget::statusWidget(QWidget* parent)
{
    setupUi(this);
    QMenu* menu = new QMenu(this);
    menu->addAction(actionAvailable);
    menu->addAction(actionBusy);
    menu->addAction(actionAway);
//    menu->addAction(actionInvisible);
    menu->addSeparator();
    menu->addAction(actionSign_out);
    toolButton_userName->setMenu(menu);

    bool check = connect(statusTextWidgetObject, SIGNAL(statusTextChanged(const QString&)), SIGNAL(statusTextChanged(const QString&)));
    Q_ASSERT(check);

    check = connect(actionAvailable, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionBusy, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionAway, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionInvisible, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);
    check = connect(actionSign_out, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
    Q_ASSERT(check);

    check = connect(pushButton_avatar, SIGNAL(clicked()), SLOT(avatarSelection()));
    Q_ASSERT(check);
}

void statusWidget::setStatusText(const QString& statusText)
{
    statusTextWidgetObject->setStatusText(statusText);
}

void statusWidget::presenceMenuTriggered()
{
    QString icon = "green";
    QAction* action = qobject_cast<QAction*>(sender());
    if(action == actionAvailable)
    {
        emit presenceTypeChanged(QXmppPresence::Available);
        icon = "green";
    }
    else if(action == actionBusy)
    {
        emit presenceStatusTypeChanged(QXmppPresence::Status::DND);
        icon = "red";
    }
    else if(action == actionAway)
    {
        emit presenceStatusTypeChanged(QXmppPresence::Status::Away);
        icon = "orange";
    }
    else if(action == actionInvisible)
    {
        emit presenceStatusTypeChanged(QXmppPresence::Status::Invisible);
        icon = "gray";
    }
    else if(action == actionSign_out)
    {
        emit presenceTypeChanged(QXmppPresence::Unavailable);
        icon = "gray";
    }
    label->setPixmap(QPixmap(":/icons/resource/"+icon+".png"));
}

void statusWidget::setPresenceAndStatusType(QXmppPresence::Type presenceType,
                                  QXmppPresence::Status::Type statusType)
{
    if(presenceType == QXmppPresence::Available)
    {
        QString icon = "green";
        switch(statusType)
        {
        case QXmppPresence::Status::Online:
        case QXmppPresence::Status::Chat:
            icon = "green";
            break;
        case QXmppPresence::Status::Away:
        case QXmppPresence::Status::XA:
            icon = "orange";
            break;
        case QXmppPresence::Status::DND:
            icon = "red";
            break;
        case QXmppPresence::Status::Invisible:
        case QXmppPresence::Status::Offline:
            icon = "gray";
            break;
        }
        label->setPixmap(QPixmap(":/icons/resource/"+icon+".png"));
    }
    else if(presenceType == QXmppPresence::Unavailable)
    {
        label->setPixmap(QPixmap(":/icons/resource/gray.png"));
    }
}

void statusWidget::avatarSelection()
{
    QString fileFilters = QString("Images (*.png *.jpeg *.jpg *.gif *.bmp);;All Files (*.*)");
    QString file = QFileDialog::getOpenFileName(this, "Select your avatar",
                                                QString(), fileFilters);
    if(file.isEmpty())
        return;

    QImage image;
    if(image.load(file))
    {
        QImage scaled = image.scaled(QSize(96, 96), Qt::KeepAspectRatio,
                                     Qt::SmoothTransformation);
        emit avatarChanged(scaled);
    }
    else
        QMessageBox::information(this, "Avatar selection", "Invalid image file");
}

void statusWidget::setDisplayName(const QString& name)
{
    toolButton_userName->setText(name);
}

void statusWidget::setAvatar(const QImage& image)
{
    pushButton_avatar->setIcon(QIcon(QPixmap::fromImage(image)));
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "Verifier.h"

#include <algorithm>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "ConfigFiles.h"
#include "DexClass.h"
#include "DexUtil.h"
#include "IRInstruction.h"
#include "ReachableClasses.h"
#include "Trace.h"
#include "Walkers.h"

namespace {

const std::string CLASS_DEPENDENCY_FILENAME = "redex-class-dependencies.txt";

using refs_t = std::unordered_map<const DexClass*,
                                  std::set<DexClass*, dexclasses_comparator>>;
using class_to_store_map_t = std::unordered_map<const DexClass*, DexStore*>;
using allowed_store_map_t =
    std::unordered_map<std::string, std::set<std::string>>;

/**
 * Helper function that scans all the opcodes in the application and produces a
 * map of references from the class containing the opcode to the class
 * referenced by the opcode.
 *
 * @param scope all classes we're processing
 * @param dmethod_refs [out] all refs to dmethods in the application
 * @param class_refs [out] all refs to classes in the application
 *
 */
void build_refs(const Scope& scope, refs_t& class_refs) {
  // TODO: walk through annotations
  walk::opcodes(
      scope,
      [](const DexMethod*) { return true; },
      [&](const DexMethod* meth, IRInstruction* insn) {
        if (insn->has_type()) {
          const auto tref = type_class(insn->get_type());
          if (tref) class_refs[tref].emplace(type_class(meth->get_class()));
          return;
        }
        if (insn->has_field()) {
          const auto tref = type_class(insn->get_field()->get_class());
          if (tref) class_refs[tref].emplace(type_class(meth->get_class()));
          return;
        }
        if (insn->has_method()) {
          // log methods class type, for virtual methods, this may not actually
          // exist and true verification would require that the binding refers
          // to a class that is valid.
          const auto mref = type_class(insn->get_method()->get_class());
          if (mref) class_refs[mref].emplace(type_class(meth->get_class()));

          // don't log return type or types of parameters for now, but this is
          // how you might do it.
          // const auto proto = insn->get_method()->get_proto();
          // const auto rref = type_class(proto->get_rtype());
          // if (rref) class_refs[rref].emplace(type_class(meth->get_class()));
          // for (const auto arg : proto->get_args()->get_type_list()) {
          //   const auto aref = type_class(arg);
          //   if (aref)
          //   class_refs[aref].emplace(type_class(meth->get_class()));
          // }

          return;
        }
      });
}

DexStore& findStore(std::string& name, DexStoresVector& stores) {
  for (auto& store : stores) {
    if (name == store.get_name()) {
      return store;
    }
  }
  return stores[0];
}

std::set<std::string> getAllowedStores(DexStoresVector& stores,
                                       DexStore& store,
                                       allowed_store_map_t store_map) {
  auto search = store_map.find(store.get_name());
  if (search != store_map.end()) {
    return search->second;
  }
  store_map[store.get_name()].emplace(store.get_name());
  store_map[store.get_name()].emplace(stores[0].get_name());
  for (auto parent : store.get_dependencies()) {
    store_map[store.get_name()].emplace(parent);
    for (const auto& grandparent :
         getAllowedStores(stores, findStore(parent, stores), store_map)) {
      store_map[store.get_name()].emplace(grandparent);
    }
  }
  return store_map[store.get_name()];
}

void verifyStore(DexStoresVector& stores,
                 DexStore& store,
                 class_to_store_map_t map,
                 const allowed_store_map_t& store_map,
                 FILE* fd) {
  refs_t class_refs;
  auto scope = build_class_scope(store.get_dexen());
  build_refs(scope, class_refs);
  for (auto& ref : class_refs) {
    const auto target = ref.first;
    for (const auto& source : ref.second) {
      std::string target_store_name;
      auto find = map.find(target);
      if (find != map.end()) {
        target_store_name = find->second->get_name();
      } else {
        target_store_name = "external";
      }
      std::set<std::string> allowed_stores =
          getAllowedStores(stores, store, store_map);
      if (allowed_stores.find(target_store_name) == allowed_stores.end()) {
        TRACE(VERIFY, 5, "BAD REFERENCE from %s %s to %s %s",
              store.get_name().c_str(), source->get_deobfuscated_name().c_str(),
              target_store_name.c_str(),
              target->get_deobfuscated_name().c_str());
      }
      if (fd != nullptr) {
        fprintf(fd, "%s:%s->%s:%s\n", store.get_name().c_str(),
                source->get_deobfuscated_name().c_str(),
                target_store_name.c_str(),
                target->get_deobfuscated_name().c_str());
      }
    }
  }
}

} // namespace

void VerifierPass::run_pass(DexStoresVector& stores,
                            ConfigFiles& conf,
                            PassManager& mgr) {
  auto class_dep_out = conf.metafile(CLASS_DEPENDENCY_FILENAME);
  FILE* fd = fopen(class_dep_out.c_str(), "w");

  if (fd == nullptr) {
    perror("Error opening class dependencies output file");
    return;
  }

  allowed_store_map_t store_map;
  class_to_store_map_t map;
  for (auto& store : stores) {
    auto scope = build_class_scope(store.get_dexen());
    for (const auto& cls : scope) {
      map[cls] = &store;
    }
  }
  for (auto& store : stores) {
    verifyStore(stores, store, map, store_map, fd);
  }

  if (fd != nullptr) {
    fclose(fd);
  }
}

static VerifierPass s_pass;
<commit_msg>Use show_deobfuscated in VerifierPass<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "Verifier.h"

#include <algorithm>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "ConfigFiles.h"
#include "DexClass.h"
#include "DexUtil.h"
#include "IRInstruction.h"
#include "ReachableClasses.h"
#include "Show.h"
#include "Trace.h"
#include "Walkers.h"

namespace {

const std::string CLASS_DEPENDENCY_FILENAME = "redex-class-dependencies.txt";

using refs_t = std::unordered_map<const DexClass*,
                                  std::set<DexClass*, dexclasses_comparator>>;
using class_to_store_map_t = std::unordered_map<const DexClass*, DexStore*>;
using allowed_store_map_t =
    std::unordered_map<std::string, std::set<std::string>>;

/**
 * Helper function that scans all the opcodes in the application and produces a
 * map of references from the class containing the opcode to the class
 * referenced by the opcode.
 *
 * @param scope all classes we're processing
 * @param dmethod_refs [out] all refs to dmethods in the application
 * @param class_refs [out] all refs to classes in the application
 *
 */
void build_refs(const Scope& scope, refs_t& class_refs) {
  // TODO: walk through annotations
  walk::opcodes(
      scope,
      [](const DexMethod*) { return true; },
      [&](const DexMethod* meth, IRInstruction* insn) {
        if (insn->has_type()) {
          const auto tref = type_class(insn->get_type());
          if (tref) class_refs[tref].emplace(type_class(meth->get_class()));
          return;
        }
        if (insn->has_field()) {
          const auto tref = type_class(insn->get_field()->get_class());
          if (tref) class_refs[tref].emplace(type_class(meth->get_class()));
          return;
        }
        if (insn->has_method()) {
          // log methods class type, for virtual methods, this may not actually
          // exist and true verification would require that the binding refers
          // to a class that is valid.
          const auto mref = type_class(insn->get_method()->get_class());
          if (mref) class_refs[mref].emplace(type_class(meth->get_class()));

          // don't log return type or types of parameters for now, but this is
          // how you might do it.
          // const auto proto = insn->get_method()->get_proto();
          // const auto rref = type_class(proto->get_rtype());
          // if (rref) class_refs[rref].emplace(type_class(meth->get_class()));
          // for (const auto arg : proto->get_args()->get_type_list()) {
          //   const auto aref = type_class(arg);
          //   if (aref)
          //   class_refs[aref].emplace(type_class(meth->get_class()));
          // }

          return;
        }
      });
}

DexStore& findStore(std::string& name, DexStoresVector& stores) {
  for (auto& store : stores) {
    if (name == store.get_name()) {
      return store;
    }
  }
  return stores[0];
}

std::set<std::string> getAllowedStores(DexStoresVector& stores,
                                       DexStore& store,
                                       allowed_store_map_t store_map) {
  auto search = store_map.find(store.get_name());
  if (search != store_map.end()) {
    return search->second;
  }
  store_map[store.get_name()].emplace(store.get_name());
  store_map[store.get_name()].emplace(stores[0].get_name());
  for (auto parent : store.get_dependencies()) {
    store_map[store.get_name()].emplace(parent);
    for (const auto& grandparent :
         getAllowedStores(stores, findStore(parent, stores), store_map)) {
      store_map[store.get_name()].emplace(grandparent);
    }
  }
  return store_map[store.get_name()];
}

void verifyStore(DexStoresVector& stores,
                 DexStore& store,
                 class_to_store_map_t map,
                 const allowed_store_map_t& store_map,
                 FILE* fd) {
  refs_t class_refs;
  auto scope = build_class_scope(store.get_dexen());
  build_refs(scope, class_refs);
  for (auto& ref : class_refs) {
    const auto target = ref.first;
    for (const auto& source : ref.second) {
      std::string target_store_name;
      auto find = map.find(target);
      if (find != map.end()) {
        target_store_name = find->second->get_name();
      } else {
        target_store_name = "external";
      }
      std::set<std::string> allowed_stores =
          getAllowedStores(stores, store, store_map);
      if (allowed_stores.find(target_store_name) == allowed_stores.end()) {
        TRACE(VERIFY, 5, "BAD REFERENCE from %s %s to %s %s",
              store.get_name().c_str(), show_deobfuscated(source).c_str(),
              target_store_name.c_str(), show_deobfuscated(target).c_str());
      }
      if (fd != nullptr) {
        fprintf(fd, "%s:%s->%s:%s\n", store.get_name().c_str(),
                show_deobfuscated(source).c_str(), target_store_name.c_str(),
                show_deobfuscated(target).c_str());
      }
    }
  }
}

} // namespace

void VerifierPass::run_pass(DexStoresVector& stores,
                            ConfigFiles& conf,
                            PassManager& mgr) {
  auto class_dep_out = conf.metafile(CLASS_DEPENDENCY_FILENAME);
  FILE* fd = fopen(class_dep_out.c_str(), "w");

  if (fd == nullptr) {
    perror("Error opening class dependencies output file");
    return;
  }

  allowed_store_map_t store_map;
  class_to_store_map_t map;
  for (auto& store : stores) {
    auto scope = build_class_scope(store.get_dexen());
    for (const auto& cls : scope) {
      map[cls] = &store;
    }
  }
  for (auto& store : stores) {
    verifyStore(stores, store, map, store_map, fd);
  }

  if (fd != nullptr) {
    fclose(fd);
  }
}

static VerifierPass s_pass;
<|endoftext|>