<commit_before>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "progressbar.h"
#include "algo/loop.h"

#include "image.h"

#include "fixel_format/helpers.h"
#include "fixel_format/keys.h"

using namespace MR;
using namespace App;

void usage ()
{
  AUTHOR = "David Raffelt (david.raffelt@florey.edu.au)";

  DESCRIPTION
  + "Crop a fixel index image along with corresponding fixel data images";

  ARGUMENTS
  + Argument ("dir_in", "the input fixel folder").type_text ()
  + Argument ("dir_out", "the output fixel folder").type_text ();

  OPTIONS
  + Option ("mask", "the threshold mask").required ()
  + Argument ("image").type_image_in ()
  + Option ("data", "specify a fixel data image filename (relative to the input fixel folder) to "
                    "be cropped.").allow_multiple ()
  + Argument ("image").type_image_in ();
}

void run ()
{
  const auto fixel_folder = argument[0];
  FixelFormat::check_fixel_folder (fixel_folder);

  const auto out_fixel_folder = argument[1];
  auto index_image = FixelFormat::find_index_header (fixel_folder).get_image <uint32_t> ();

  auto opt = get_options ("mask");
  auto mask_image = Image<bool>::open (std::string (opt[0][0]));

  FixelFormat::check_fixel_size (index_image, mask_image);
  FixelFormat::check_fixel_folder (out_fixel_folder, true);

  Header out_header = Header (index_image);
  size_t total_nfixels = std::stoul (out_header.keyval ()[FixelFormat::n_fixels_key]);

  // We need to do a first pass fo the mask image to determine the cropped num. of fixels
  for (auto l = Loop (0) (mask_image); l; ++l) {
    if (!mask_image.value ())
      total_nfixels --;
  }

  out_header.keyval ()[FixelFormat::n_fixels_key] = str (total_nfixels);
  const auto index_image_basename = Path::basename (index_image.name ());
  auto out_index_image = Image<uint32_t>::create (Path::join (out_fixel_folder, index_image_basename), out_header);

  // Crop index image
  mask_image.index (1) = 0;
  for (auto l = Loop ("cropping index image: " + index_image_basename, 0, 3) (index_image, out_index_image); l; ++l) {
    index_image.index (3) = 0;
    size_t nfixels = index_image.value ();

    index_image.index (3) = 1;
    size_t offset = index_image.value ();

    for (size_t i = 0, N = nfixels; i < N; ++i) {
      mask_image.index (0) = offset + i;
      if (!mask_image.value ())
        nfixels--;
    }

    out_index_image.index (3) = 0;
    out_index_image.value () = nfixels;

    out_index_image.index (3) = 1;
    out_index_image.value () = offset;
  }

  // Crop data images
  opt = get_options ("data");

  for (size_t n = 0, N = opt.size (); n < N; n++) {
    const auto data_file = opt[n][0];
    const auto data_file_path = Path::join (fixel_folder, data_file);

    Header header = Header::open (data_file_path);
    auto in_data = header.get_image <float> ();

    check_dimensions (in_data, mask_image, {0, 2});

    header.size (0) = total_nfixels;
    auto out_data = Image<float>::create (Path::join (out_fixel_folder, data_file), header);

    size_t offset(0);

    for (auto l = Loop ("cropping data: " + data_file, 0) (mask_image, in_data); l; ++l) {
      if (mask_image.value ()) {
        out_data.index (1) = offset;
        out_data.row (1) = in_data.row (1);
        offset++;
      }
    }

  }

}

<commit_msg>fixelcrop: Fixing comment typo<commit_after>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "progressbar.h"
#include "algo/loop.h"

#include "image.h"

#include "fixel_format/helpers.h"
#include "fixel_format/keys.h"

using namespace MR;
using namespace App;

void usage ()
{
  AUTHOR = "David Raffelt (david.raffelt@florey.edu.au)";

  DESCRIPTION
  + "Crop a fixel index image along with corresponding fixel data images";

  ARGUMENTS
  + Argument ("dir_in", "the input fixel folder").type_text ()
  + Argument ("dir_out", "the output fixel folder").type_text ();

  OPTIONS
  + Option ("mask", "the threshold mask").required ()
  + Argument ("image").type_image_in ()
  + Option ("data", "specify a fixel data image filename (relative to the input fixel folder) to "
                    "be cropped.").allow_multiple ()
  + Argument ("image").type_image_in ();
}

void run ()
{
  const auto fixel_folder = argument[0];
  FixelFormat::check_fixel_folder (fixel_folder);

  const auto out_fixel_folder = argument[1];
  auto index_image = FixelFormat::find_index_header (fixel_folder).get_image <uint32_t> ();

  auto opt = get_options ("mask");
  auto mask_image = Image<bool>::open (std::string (opt[0][0]));

  FixelFormat::check_fixel_size (index_image, mask_image);
  FixelFormat::check_fixel_folder (out_fixel_folder, true);

  Header out_header = Header (index_image);
  size_t total_nfixels = std::stoul (out_header.keyval ()[FixelFormat::n_fixels_key]);

  // We need to do a first pass of the mask image to determine the cropped num. of fixels
  for (auto l = Loop (0) (mask_image); l; ++l) {
    if (!mask_image.value ())
      total_nfixels --;
  }

  out_header.keyval ()[FixelFormat::n_fixels_key] = str (total_nfixels);
  const auto index_image_basename = Path::basename (index_image.name ());
  auto out_index_image = Image<uint32_t>::create (Path::join (out_fixel_folder, index_image_basename), out_header);

  // Crop index image
  mask_image.index (1) = 0;
  for (auto l = Loop ("cropping index image: " + index_image_basename, 0, 3) (index_image, out_index_image); l; ++l) {
    index_image.index (3) = 0;
    size_t nfixels = index_image.value ();

    index_image.index (3) = 1;
    size_t offset = index_image.value ();

    for (size_t i = 0, N = nfixels; i < N; ++i) {
      mask_image.index (0) = offset + i;
      if (!mask_image.value ())
        nfixels--;
    }

    out_index_image.index (3) = 0;
    out_index_image.value () = nfixels;

    out_index_image.index (3) = 1;
    out_index_image.value () = offset;
  }

  // Crop data images
  opt = get_options ("data");

  for (size_t n = 0, N = opt.size (); n < N; n++) {
    const auto data_file = opt[n][0];
    const auto data_file_path = Path::join (fixel_folder, data_file);

    Header header = Header::open (data_file_path);
    auto in_data = header.get_image <float> ();

    check_dimensions (in_data, mask_image, {0, 2});

    header.size (0) = total_nfixels;
    auto out_data = Image<float>::create (Path::join (out_fixel_folder, data_file), header);

    size_t offset(0);

    for (auto l = Loop ("cropping data: " + data_file, 0) (mask_image, in_data); l; ++l) {
      if (mask_image.value ()) {
        out_data.index (1) = offset;
        out_data.row (1) = in_data.row (1);
        offset++;
      }
    }

  }

}

<|endoftext|>


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

#include <wx/utils.h>
#include <wx/log.h>
#include <wx/process.h>
#include <wx/txtstrm.h>
#include <wx/string.h>
#include <wx/intl.h>
#include <wx/stdpaths.h>
#include <wx/translation.h>
#include <wx/filename.h>

#include <boost/throw_exception.hpp>

#include "gexecute.h"
#include "errors.h"

// GCC's libstdc++ didn't have functional std::regex implementation until 4.9
#if (defined(__GNUC__) && !defined(__clang__) && !wxCHECK_GCC_VERSION(4,9))
    #include <boost/regex.hpp>
    using boost::wregex;
    using boost::wsmatch;
    using boost::regex_match;
#else
    #include <regex>
    using std::wregex;
    using std::wsmatch;
    using std::regex_match;
#endif

namespace
{

#ifdef __WXOSX__
wxString GetGettextPluginPath()
{
    return wxStandardPaths::Get().GetPluginsDir() + "/GettextTools.bundle";
}
#endif // __WXOSX__

#if defined(__WXOSX__) || defined(__WXMSW__)

inline wxString GetAuxBinariesDir()
{
    return GetGettextPackagePath() + "/bin";
}

wxString GetPathToAuxBinary(const wxString& program)
{
    wxFileName path;
    path.SetPath(GetAuxBinariesDir());
    path.SetName(program);
#ifdef __WXMSW__
    path.SetExt("exe");
#endif
    if ( path.IsFileExecutable() )
    {
        return wxString::Format(_T("\"%s\""), path.GetFullPath().c_str());
    }
    else
    {
        wxLogTrace("poedit.execute",
                   L"%s doesn’t exist, falling back to %s",
                   path.GetFullPath().c_str(),
                   program.c_str());
        return program;
    }
}
#endif // __WXOSX__ || __WXMSW__

bool ReadOutput(wxInputStream& s, wxArrayString& out)
{
    // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
    s.Reset();
    wxTextInputStream tis(s, " ", wxConvAuto() /* UTF-8, fallback if impossible */);

    while (true)
    {
        wxString line = tis.ReadLine();
        if ( !line.empty() )
            out.push_back(line);
        if (s.Eof())
            break;
        if ( !s )
            return false;
    }

    return true;
}

long DoExecuteGettext(const wxString& cmdline_, wxArrayString& gstderr)
{
    wxExecuteEnv env;
    wxString cmdline(cmdline_);

#if defined(__WXOSX__) || defined(__WXMSW__)
    wxString binary = cmdline.BeforeFirst(_T(' '));
    cmdline = GetPathToAuxBinary(binary) + cmdline.Mid(binary.length());
    wxGetEnvMap(&env.env);
    env.env["GETTEXTIOENCODING"] = "UTF-8";

    wxString lang = wxTranslations::Get()->GetBestTranslation("gettext-tools");
	if ( !lang.empty() )
        env.env["LANG"] = lang;
#endif // __WXOSX__ || __WXMSW__

#ifdef __WXOSX__
    // Hack alert! On Windows, relocation works, but building with it is too
    // messy/broken on macOS, so just use some custom hacks instead:
    auto sharedir = GetGettextPackagePath() + "/share";
    env.env["POEDIT_LOCALEDIR"] = sharedir + "/locale";
    env.env["GETTEXTDATADIR"] = sharedir + "/gettext";
#endif

    wxLogTrace("poedit.execute", "executing: %s", cmdline.c_str());

    wxScopedPtr<wxProcess> process(new wxProcess);
    process->Redirect();

    long retcode = wxExecute(cmdline, wxEXEC_BLOCK | wxEXEC_NODISABLE | wxEXEC_NOEVENTS, process.get(), &env);

	wxInputStream *std_err = process->GetErrorStream();
    if ( std_err && !ReadOutput(*std_err, gstderr) )
        retcode = -1;

    if ( retcode == -1 )
    {
        BOOST_THROW_EXCEPTION(Exception(wxString::Format(_("Cannot execute program: %s"), cmdline.c_str())));
    }

    return retcode;
}

} // anonymous namespace

bool ExecuteGettext(const wxString& cmdline)
{
    wxArrayString gstderr;
    long retcode = DoExecuteGettext(cmdline, gstderr);

    wxString pending;
    for (auto& ln: gstderr)
    {
        if (ln.empty())
            continue;

        // special handling of multiline errors
        if (ln[0] == ' ' || ln[0] == '\t')
        {
            pending += "\n\t" + ln.Strip(wxString::both);
        }
        else
        {
            if (!pending.empty())
                wxLogError("%s", pending);

            pending = ln;
        }
    }

    if (!pending.empty())
        wxLogError("%s", pending);

    return retcode == 0;
}

bool ExecuteGettextAndParseOutput(const wxString& cmdline, GettextErrors& errors)
{
    wxArrayString gstderr;
    long retcode = DoExecuteGettext(cmdline, gstderr);

    static const wregex RE_ERROR(L".*\\.po:([0-9]+)(:[0-9]+)?: (.*)");

    for (const auto& ewx: gstderr)
    {
        const auto e = ewx.ToStdWstring();
        wxLogTrace("poedit", "  stderr: %s", e.c_str());
        if ( e.empty() )
            continue;

        GettextError rec;

        wsmatch match;
        if (regex_match(e, match, RE_ERROR))
        {
            rec.line = std::stoi(match.str(1));
            rec.text = match.str(3);
            errors.push_back(rec);
            wxLogTrace("poedit.execute",
                       _T("        => parsed error = \"%s\" at %d"),
                       rec.text.c_str(), rec.line);
        }
        else
        {
            wxLogTrace("poedit.execute", "        (unrecognized line!)");
            // FIXME: handle the rest of output gracefully too
        }
    }

    return retcode == 0;
}

wxString QuoteCmdlineArg(const wxString& s)
{
    wxString s2(s);
#ifdef __UNIX__
    s2.Replace("\"", "\\\"");
#endif
    return "\"" + s2 + "\"";
}

#if defined(__WXOSX__) || defined(__WXMSW__)
wxString GetGettextPackagePath()
{
#if defined(__WXOSX__)
    return GetGettextPluginPath() + "/Contents/MacOS";
#elif defined(__WXMSW__)
    return wxStandardPaths::Get().GetDataDir() + wxFILE_SEP_PATH + "GettextTools";
#endif
}
#endif // __WXOSX__ || __WXMSW__

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

#include <wx/utils.h>
#include <wx/log.h>
#include <wx/process.h>
#include <wx/txtstrm.h>
#include <wx/string.h>
#include <wx/intl.h>
#include <wx/stdpaths.h>
#include <wx/translation.h>
#include <wx/filename.h>

#include <boost/throw_exception.hpp>

#include "gexecute.h"
#include "errors.h"

// GCC's libstdc++ didn't have functional std::regex implementation until 4.9
#if (defined(__GNUC__) && !defined(__clang__) && !wxCHECK_GCC_VERSION(4,9))
    #include <boost/regex.hpp>
    using boost::wregex;
    using boost::wsmatch;
    using boost::regex_match;
#else
    #include <regex>
    using std::wregex;
    using std::wsmatch;
    using std::regex_match;
#endif

namespace
{

#ifdef __WXOSX__
wxString GetGettextPluginPath()
{
    return wxStandardPaths::Get().GetPluginsDir() + "/GettextTools.bundle";
}
#endif // __WXOSX__

#if defined(__WXOSX__) || defined(__WXMSW__)

inline wxString GetAuxBinariesDir()
{
    return GetGettextPackagePath() + "/bin";
}

wxString GetPathToAuxBinary(const wxString& program)
{
    wxFileName path;
    path.SetPath(GetAuxBinariesDir());
    path.SetName(program);
#ifdef __WXMSW__
    path.SetExt("exe");
#endif
    if ( path.IsFileExecutable() )
    {
        return wxString::Format(_T("\"%s\""), path.GetFullPath().c_str());
    }
    else
    {
        wxLogTrace("poedit.execute",
                   L"%s doesn’t exist, falling back to %s",
                   path.GetFullPath().c_str(),
                   program.c_str());
        return program;
    }
}
#endif // __WXOSX__ || __WXMSW__

bool ReadOutput(wxInputStream& s, wxArrayString& out)
{
    // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
    s.Reset();

    // Read the input as Latin1, even though we know it's UTF-8. This is terrible,
    // terrible thing to do, but gettext tools may sometimes output invalid UTF-8
    // (e.g. when using non-ASCII, non-UTF8 msgids) and wxTextInputStream logic
    // can't cope well with failing conversions. To make this work, we read the
    // input as Latin1 and later re-encode it back and re-parse as UTF-8.
    wxTextInputStream tis(s, " ", wxConvISO8859_1);

    while (true)
    {
        const wxString line = tis.ReadLine();
        if ( !line.empty() )
        {
            // reconstruct the UTF-8 text if we can
            wxString line2(line.mb_str(wxConvISO8859_1), wxConvUTF8);
            if (line2.empty())
                line2 = line;
            out.push_back(line2);
        }
        if (s.Eof())
            break;
        if ( !s )
            return false;
    }

    return true;
}

long DoExecuteGettext(const wxString& cmdline_, wxArrayString& gstderr)
{
    wxExecuteEnv env;
    wxString cmdline(cmdline_);

#if defined(__WXOSX__) || defined(__WXMSW__)
    wxString binary = cmdline.BeforeFirst(_T(' '));
    cmdline = GetPathToAuxBinary(binary) + cmdline.Mid(binary.length());
    wxGetEnvMap(&env.env);
    env.env["GETTEXTIOENCODING"] = "UTF-8";

    wxString lang = wxTranslations::Get()->GetBestTranslation("gettext-tools");
	if ( !lang.empty() )
        env.env["LANG"] = lang;
#endif // __WXOSX__ || __WXMSW__

#ifdef __WXOSX__
    // Hack alert! On Windows, relocation works, but building with it is too
    // messy/broken on macOS, so just use some custom hacks instead:
    auto sharedir = GetGettextPackagePath() + "/share";
    env.env["POEDIT_LOCALEDIR"] = sharedir + "/locale";
    env.env["GETTEXTDATADIR"] = sharedir + "/gettext";
#endif

    wxLogTrace("poedit.execute", "executing: %s", cmdline.c_str());

    wxScopedPtr<wxProcess> process(new wxProcess);
    process->Redirect();

    long retcode = wxExecute(cmdline, wxEXEC_BLOCK | wxEXEC_NODISABLE | wxEXEC_NOEVENTS, process.get(), &env);

	wxInputStream *std_err = process->GetErrorStream();
    if ( std_err && !ReadOutput(*std_err, gstderr) )
        retcode = -1;

    if ( retcode == -1 )
    {
        BOOST_THROW_EXCEPTION(Exception(wxString::Format(_("Cannot execute program: %s"), cmdline.c_str())));
    }

    return retcode;
}

} // anonymous namespace

bool ExecuteGettext(const wxString& cmdline)
{
    wxArrayString gstderr;
    long retcode = DoExecuteGettext(cmdline, gstderr);

    wxString pending;
    for (auto& ln: gstderr)
    {
        if (ln.empty())
            continue;

        // special handling of multiline errors
        if (ln[0] == ' ' || ln[0] == '\t')
        {
            pending += "\n\t" + ln.Strip(wxString::both);
        }
        else
        {
            if (!pending.empty())
                wxLogError("%s", pending);

            pending = ln;
        }
    }

    if (!pending.empty())
        wxLogError("%s", pending);

    return retcode == 0;
}

bool ExecuteGettextAndParseOutput(const wxString& cmdline, GettextErrors& errors)
{
    wxArrayString gstderr;
    long retcode = DoExecuteGettext(cmdline, gstderr);

    static const wregex RE_ERROR(L".*\\.po:([0-9]+)(:[0-9]+)?: (.*)");

    for (const auto& ewx: gstderr)
    {
        const auto e = ewx.ToStdWstring();
        wxLogTrace("poedit", "  stderr: %s", e.c_str());
        if ( e.empty() )
            continue;

        GettextError rec;

        wsmatch match;
        if (regex_match(e, match, RE_ERROR))
        {
            rec.line = std::stoi(match.str(1));
            rec.text = match.str(3);
            errors.push_back(rec);
            wxLogTrace("poedit.execute",
                       _T("        => parsed error = \"%s\" at %d"),
                       rec.text.c_str(), rec.line);
        }
        else
        {
            wxLogTrace("poedit.execute", "        (unrecognized line!)");
            // FIXME: handle the rest of output gracefully too
        }
    }

    return retcode == 0;
}

wxString QuoteCmdlineArg(const wxString& s)
{
    wxString s2(s);
#ifdef __UNIX__
    s2.Replace("\"", "\\\"");
#endif
    return "\"" + s2 + "\"";
}

#if defined(__WXOSX__) || defined(__WXMSW__)
wxString GetGettextPackagePath()
{
#if defined(__WXOSX__)
    return GetGettextPluginPath() + "/Contents/MacOS";
#elif defined(__WXMSW__)
    return wxStandardPaths::Get().GetDataDir() + wxFILE_SEP_PATH + "GettextTools";
#endif
}
#endif // __WXOSX__ || __WXMSW__

<|endoftext|>


<commit_before>#include "types.h"
#include "stat.h"
#include "user.h"
#include "mtrace.h"
#include "amd64.h"
#include "fcntl.h"

static const bool pinit = true;

enum { nloop = 100 };
enum { nfile = 10 };
enum { nlookup = 100 };

void
bench(u32 tid)
{
  char pn[MAXNAME];

  if (pinit)
    setaffinity(tid);

  for (u32 x = 0; x < nloop; x++) {
    for (u32 i = 0; i < nfile; i++) {
      snprintf(pn, sizeof(pn), "/dbx/f:%d:%d", tid, i);

      int fd = open(pn, O_CREATE | O_RDWR);
      if (fd < 0)
	die("create failed\n");

      close(fd);
    }

    for (u32 i = 0; i < nlookup; i++) {
      snprintf(pn, sizeof(pn), "/dbx/f:%d:%d", tid, (i % nfile));
      int fd = open(pn, O_RDWR);
      if (fd < 0)
        die("open failed\n");

      close(fd);
    }

    for (u32 i = 0; i < nfile; i++) {
      snprintf(pn, sizeof(pn), "/dbx/f:%d:%d", tid, i);
      if (unlink(pn) < 0)
	die("unlink failed\n");
    }
  }

  exit();
}

int
main(int ac, char** av)
{
  int nthread;

  if (ac < 2)
    die("usage: %s nthreads", av[0]);

  nthread = atoi(av[1]);

  mkdir("/dbx");

  u64 t0 = rdtsc();
  for(u32 i = 0; i < nthread; i++) {
    int pid = fork(0);
    if (pid == 0)
      bench(i);
    else if (pid < 0)
      die("fork");
  }

  for (u32 i = 0; i < nthread; i++)
    wait();
  u64 t1 = rdtsc();

  printf("dirbench: %lu\n", t1-t0);
  return 0;
}
<commit_msg>dirbench hack for qemu<commit_after>#include "types.h"
#include "stat.h"
#include "user.h"
#include "mtrace.h"
#include "amd64.h"
#include "fcntl.h"

static const bool pinit = true;

#ifdef HW_qemu
enum { nloop = 100 };
#else
enum { nloop = 1000 };
#endif

enum { nfile = 10 };
enum { nlookup = 100 };

void
bench(u32 tid)
{
  char pn[MAXNAME];

  if (pinit)
    setaffinity(tid);

  for (u32 x = 0; x < nloop; x++) {
    for (u32 i = 0; i < nfile; i++) {
      snprintf(pn, sizeof(pn), "/dbx/f:%d:%d", tid, i);

      int fd = open(pn, O_CREATE | O_RDWR);
      if (fd < 0)
	die("create failed\n");

      close(fd);
    }

    for (u32 i = 0; i < nlookup; i++) {
      snprintf(pn, sizeof(pn), "/dbx/f:%d:%d", tid, (i % nfile));
      int fd = open(pn, O_RDWR);
      if (fd < 0)
        die("open failed\n");

      close(fd);
    }

    for (u32 i = 0; i < nfile; i++) {
      snprintf(pn, sizeof(pn), "/dbx/f:%d:%d", tid, i);
      if (unlink(pn) < 0)
	die("unlink failed\n");
    }
  }

  exit();
}

int
main(int ac, char** av)
{
  int nthread;

  if (ac < 2)
    die("usage: %s nthreads", av[0]);

  nthread = atoi(av[1]);

  mkdir("/dbx");

  u64 t0 = rdtsc();
  for(u32 i = 0; i < nthread; i++) {
    int pid = fork(0);
    if (pid == 0)
      bench(i);
    else if (pid < 0)
      die("fork");
  }

  for (u32 i = 0; i < nthread; i++)
    wait();
  u64 t1 = rdtsc();

  printf("dirbench: %lu\n", t1-t0);
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/forms/ui_optionsdialog.h>
#include <qt/optionsdialog.h>

#include <interfaces/node.h>
#include <netbase.h>
#include <qt/bitcoinunits.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <txdb.h>       // for -dbcache defaults
#include <validation.h> // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS

#include <QDataWidgetMapper>
#include <QDir>
#include <QIntValidator>
#include <QLocale>
#include <QMessageBox>
#include <QSystemTrayIcon>
#include <QTimer>

OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet)
    : QDialog(parent), ui(new Ui::OptionsDialog), model(nullptr),
      mapper(nullptr) {
    ui->setupUi(this);

    /* Main elements init */
    ui->databaseCache->setMinimum(nMinDbCache);
    ui->databaseCache->setMaximum(nMaxDbCache);
    ui->threadsScriptVerif->setMinimum(-GetNumCores());
    ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS);
    ui->pruneWarning->setVisible(false);
    ui->pruneWarning->setStyleSheet("QLabel { color: red; }");

    ui->pruneSize->setEnabled(false);
    connect(ui->prune, &QPushButton::toggled, ui->pruneSize,
            &QWidget::setEnabled);

/* Network elements init */
#ifndef USE_UPNP
    ui->mapPortUpnp->setEnabled(false);
#endif

    ui->proxyIp->setEnabled(false);
    ui->proxyPort->setEnabled(false);
    ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));

    ui->proxyIpTor->setEnabled(false);
    ui->proxyPortTor->setEnabled(false);
    ui->proxyPortTor->setValidator(new QIntValidator(1, 65535, this));

    connect(ui->connectSocks, &QPushButton::toggled, ui->proxyIp,
            &QWidget::setEnabled);
    connect(ui->connectSocks, &QPushButton::toggled, ui->proxyPort,
            &QWidget::setEnabled);
    connect(ui->connectSocks, &QPushButton::toggled, this,
            &OptionsDialog::updateProxyValidationState);

    connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyIpTor,
            &QWidget::setEnabled);
    connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyPortTor,
            &QWidget::setEnabled);
    connect(ui->connectSocksTor, &QPushButton::toggled, this,
            &OptionsDialog::updateProxyValidationState);

    /* Window elements init */
#ifdef Q_OS_MAC
    /* remove Window tab on Mac */
    ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow));
    /* hide launch at startup option on macOS */
    ui->bitcoinAtStartup->setVisible(false);
    ui->verticalLayout_Main->removeWidget(ui->bitcoinAtStartup);
    ui->verticalLayout_Main->removeItem(ui->horizontalSpacer_0_Main);
#endif

    /* remove Wallet tab in case of -disablewallet */
    if (!enableWallet) {
        ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWallet));
    }

    /* Display elements init */
    QDir translations(":translations");

    ui->bitcoinAtStartup->setToolTip(
        ui->bitcoinAtStartup->toolTip().arg(PACKAGE_NAME));
    ui->bitcoinAtStartup->setText(
        ui->bitcoinAtStartup->text().arg(PACKAGE_NAME));

    ui->openBitcoinConfButton->setToolTip(
        ui->openBitcoinConfButton->toolTip().arg(PACKAGE_NAME));

    ui->lang->setToolTip(ui->lang->toolTip().arg(PACKAGE_NAME));
    ui->lang->addItem(QString("(") + tr("default") + QString(")"),
                      QVariant(""));
    for (const QString &langStr : translations.entryList()) {
        QLocale locale(langStr);

        /** check if the locale name consists of 2 parts (language_country) */
        if (langStr.contains("_")) {
            /** display language strings as "native language - native country
             * (locale name)", e.g. "Deutsch - Deutschland (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") +
                                  locale.nativeCountryName() + QString(" (") +
                                  langStr + QString(")"),
                              QVariant(langStr));
        } else {
            /** display language strings as "native language (locale name)",
             * e.g. "Deutsch (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" (") +
                                  langStr + QString(")"),
                              QVariant(langStr));
        }
    }
    ui->unit->setModel(new BitcoinUnits(this));

    /* Widget-to-option mapper */
    mapper = new QDataWidgetMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);

    GUIUtil::ItemDelegate *delegate = new GUIUtil::ItemDelegate(mapper);
    connect(delegate, &GUIUtil::ItemDelegate::keyEscapePressed, this,
            &OptionsDialog::reject);
    mapper->setItemDelegate(delegate);

    /* setup/change UI elements when proxy IPs are invalid/valid */
    ui->proxyIp->setCheckValidator(new ProxyAddressValidator(parent));
    ui->proxyIpTor->setCheckValidator(new ProxyAddressValidator(parent));
    connect(ui->proxyIp, &QValidatedLineEdit::validationDidChange, this,
            &OptionsDialog::updateProxyValidationState);
    connect(ui->proxyIpTor, &QValidatedLineEdit::validationDidChange, this,
            &OptionsDialog::updateProxyValidationState);
    connect(ui->proxyPort, &QLineEdit::textChanged, this,
            &OptionsDialog::updateProxyValidationState);
    connect(ui->proxyPortTor, &QLineEdit::textChanged, this,
            &OptionsDialog::updateProxyValidationState);

    if (!QSystemTrayIcon::isSystemTrayAvailable()) {
        ui->hideTrayIcon->setChecked(true);
        ui->hideTrayIcon->setEnabled(false);
        ui->minimizeToTray->setChecked(false);
        ui->minimizeToTray->setEnabled(false);
    }
}

OptionsDialog::~OptionsDialog() {
    delete ui;
}

void OptionsDialog::setModel(OptionsModel *_model) {
    this->model = _model;

    if (_model) {
        /* check if client restart is needed and show persistent message */
        if (_model->isRestartRequired()) {
            showRestartWarning(true);
        }

        // Prune values are in GB to be consistent with intro.cpp
        static constexpr uint64_t nMinDiskSpace =
            (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) +
                    (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES)
                ? 1
                : 0;
        ui->pruneSize->setRange(nMinDiskSpace, std::numeric_limits<int>::max());

        QString strLabel = _model->getOverriddenByCommandLine();
        if (strLabel.isEmpty()) {
            strLabel = tr("none");
        }
        ui->overriddenByCommandLineLabel->setText(strLabel);

        mapper->setModel(_model);
        setMapper();
        mapper->toFirst();

        updateDefaultProxyNets();
    }

    /* warn when one of the following settings changes by user action (placed
     * here so init via mapper doesn't trigger them) */

    /* Main */
    connect(ui->prune, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    connect(ui->prune, &QCheckBox::clicked, this,
            &OptionsDialog::togglePruneWarning);
    connect(ui->pruneSize,
            static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
            &OptionsDialog::showRestartWarning);
    connect(ui->databaseCache,
            static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
            &OptionsDialog::showRestartWarning);
    connect(ui->threadsScriptVerif,
            static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
            &OptionsDialog::showRestartWarning);
    /* Wallet */
    connect(ui->spendZeroConfChange, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    /* Network */
    connect(ui->allowIncoming, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    connect(ui->connectSocks, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    connect(ui->connectSocksTor, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    /* Display */
    connect(
        ui->lang,
        static_cast<void (QValueComboBox::*)()>(&QValueComboBox::valueChanged),
        [this] { showRestartWarning(); });
    connect(ui->thirdPartyTxUrls, &QLineEdit::textChanged,
            [this] { showRestartWarning(); });
}

void OptionsDialog::setCurrentTab(OptionsDialog::Tab tab) {
    QWidget *tab_widget = nullptr;
    if (tab == OptionsDialog::Tab::TAB_NETWORK) {
        tab_widget = ui->tabNetwork;
    }
    if (tab == OptionsDialog::Tab::TAB_MAIN) {
        tab_widget = ui->tabMain;
    }
    if (tab_widget && ui->tabWidget->currentWidget() != tab_widget) {
        ui->tabWidget->setCurrentWidget(tab_widget);
    }
}

void OptionsDialog::setMapper() {
    /* Main */
    mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup);
    mapper->addMapping(ui->threadsScriptVerif,
                       OptionsModel::ThreadsScriptVerif);
    mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache);
    mapper->addMapping(ui->prune, OptionsModel::Prune);
    mapper->addMapping(ui->pruneSize, OptionsModel::PruneSize);

    /* Wallet */
    mapper->addMapping(ui->spendZeroConfChange,
                       OptionsModel::SpendZeroConfChange);
    mapper->addMapping(ui->coinControlFeatures,
                       OptionsModel::CoinControlFeatures);

    /* Network */
    mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);
    mapper->addMapping(ui->allowIncoming, OptionsModel::Listen);

    mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
    mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
    mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);

    mapper->addMapping(ui->connectSocksTor, OptionsModel::ProxyUseTor);
    mapper->addMapping(ui->proxyIpTor, OptionsModel::ProxyIPTor);
    mapper->addMapping(ui->proxyPortTor, OptionsModel::ProxyPortTor);

/* Window */
#ifndef Q_OS_MAC
    if (QSystemTrayIcon::isSystemTrayAvailable()) {
        mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
        mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
    }
    mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
#endif

    /* Display */
    mapper->addMapping(ui->lang, OptionsModel::Language);
    mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
    mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
}

void OptionsDialog::setOkButtonState(bool fState) {
    ui->okButton->setEnabled(fState);
}

void OptionsDialog::on_resetButton_clicked() {
    if (model) {
        // confirmation dialog
        QMessageBox::StandardButton btnRetVal = QMessageBox::question(
            this, tr("Confirm options reset"),
            tr("Client restart required to activate changes.") + "

" +
                tr("Client will be shut down. Do you want to proceed?"),
            QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);

        if (btnRetVal == QMessageBox::Cancel) {
            return;
        }

        /* reset all options and close GUI */
        model->Reset();
        QApplication::quit();
    }
}

void OptionsDialog::on_openBitcoinConfButton_clicked() {
    /* explain the purpose of the config file */
    QMessageBox::information(
        this, tr("Configuration options"),
        tr("The configuration file is used to specify advanced user options "
           "which override GUI settings. Additionally, any command-line "
           "options will override this configuration file."));

    /* show an error if there was some problem opening the file */
    if (!GUIUtil::openBitcoinConf()) {
        QMessageBox::critical(
            this, tr("Error"),
            tr("The configuration file could not be opened."));
    }
}

void OptionsDialog::on_okButton_clicked() {
    mapper->submit();
    accept();
    updateDefaultProxyNets();
}

void OptionsDialog::on_cancelButton_clicked() {
    reject();
}

void OptionsDialog::on_hideTrayIcon_stateChanged(int fState) {
    if (fState) {
        ui->minimizeToTray->setChecked(false);
        ui->minimizeToTray->setEnabled(false);
    } else {
        ui->minimizeToTray->setEnabled(true);
    }
}

void OptionsDialog::togglePruneWarning(bool enabled) {
    ui->pruneWarning->setVisible(!ui->pruneWarning->isVisible());
}

void OptionsDialog::showRestartWarning(bool fPersistent) {
    ui->statusLabel->setStyleSheet("QLabel { color: red; }");

    if (fPersistent) {
        ui->statusLabel->setText(
            tr("Client restart required to activate changes."));
    } else {
        ui->statusLabel->setText(
            tr("This change would require a client restart."));
        // clear non-persistent status label after 10 seconds
        // TODO: should perhaps be a class attribute, if we extend the use of
        // statusLabel
        QTimer::singleShot(10000, this, &OptionsDialog::clearStatusLabel);
    }
}

void OptionsDialog::clearStatusLabel() {
    ui->statusLabel->clear();
    if (model && model->isRestartRequired()) {
        showRestartWarning(true);
    }
}

void OptionsDialog::updateProxyValidationState() {
    QValidatedLineEdit *pUiProxyIp = ui->proxyIp;
    QValidatedLineEdit *otherProxyWidget =
        (pUiProxyIp == ui->proxyIpTor) ? ui->proxyIp : ui->proxyIpTor;
    if (pUiProxyIp->isValid() &&
        (!ui->proxyPort->isEnabled() || ui->proxyPort->text().toInt() > 0) &&
        (!ui->proxyPortTor->isEnabled() ||
         ui->proxyPortTor->text().toInt() > 0)) {
        // Only enable ok button if both proxys are valid
        setOkButtonState(otherProxyWidget->isValid());
        clearStatusLabel();
    } else {
        setOkButtonState(false);
        ui->statusLabel->setStyleSheet("QLabel { color: red; }");
        ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
    }
}

void OptionsDialog::updateDefaultProxyNets() {
    proxyType proxy;
    std::string strProxy;
    QString strDefaultProxyGUI;

    model->node().getProxy(NET_IPV4, proxy);
    strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
    strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
    (strProxy == strDefaultProxyGUI.toStdString())
        ? ui->proxyReachIPv4->setChecked(true)
        : ui->proxyReachIPv4->setChecked(false);

    model->node().getProxy(NET_IPV6, proxy);
    strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
    strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
    (strProxy == strDefaultProxyGUI.toStdString())
        ? ui->proxyReachIPv6->setChecked(true)
        : ui->proxyReachIPv6->setChecked(false);

    model->node().getProxy(NET_ONION, proxy);
    strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
    strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
    (strProxy == strDefaultProxyGUI.toStdString())
        ? ui->proxyReachTor->setChecked(true)
        : ui->proxyReachTor->setChecked(false);
}

ProxyAddressValidator::ProxyAddressValidator(QObject *parent)
    : QValidator(parent) {}

QValidator::State ProxyAddressValidator::validate(QString &input,
                                                  int &pos) const {
    Q_UNUSED(pos);
    // Validate the proxy
    CService serv(
        LookupNumeric(input.toStdString().c_str(), DEFAULT_GUI_PROXY_PORT));
    proxyType addrProxy = proxyType(serv, true);
    if (addrProxy.IsValid()) {
        return QValidator::Acceptable;
    }

    return QValidator::Invalid;
}
<commit_msg>ui: disable 3rd-party tx-urls when wallet disabled<commit_after>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <qt/forms/ui_optionsdialog.h>
#include <qt/optionsdialog.h>

#include <interfaces/node.h>
#include <netbase.h>
#include <qt/bitcoinunits.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <txdb.h>       // for -dbcache defaults
#include <validation.h> // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS

#include <QDataWidgetMapper>
#include <QDir>
#include <QIntValidator>
#include <QLocale>
#include <QMessageBox>
#include <QSystemTrayIcon>
#include <QTimer>

OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet)
    : QDialog(parent), ui(new Ui::OptionsDialog), model(nullptr),
      mapper(nullptr) {
    ui->setupUi(this);

    /* Main elements init */
    ui->databaseCache->setMinimum(nMinDbCache);
    ui->databaseCache->setMaximum(nMaxDbCache);
    ui->threadsScriptVerif->setMinimum(-GetNumCores());
    ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS);
    ui->pruneWarning->setVisible(false);
    ui->pruneWarning->setStyleSheet("QLabel { color: red; }");

    ui->pruneSize->setEnabled(false);
    connect(ui->prune, &QPushButton::toggled, ui->pruneSize,
            &QWidget::setEnabled);

/* Network elements init */
#ifndef USE_UPNP
    ui->mapPortUpnp->setEnabled(false);
#endif

    ui->proxyIp->setEnabled(false);
    ui->proxyPort->setEnabled(false);
    ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));

    ui->proxyIpTor->setEnabled(false);
    ui->proxyPortTor->setEnabled(false);
    ui->proxyPortTor->setValidator(new QIntValidator(1, 65535, this));

    connect(ui->connectSocks, &QPushButton::toggled, ui->proxyIp,
            &QWidget::setEnabled);
    connect(ui->connectSocks, &QPushButton::toggled, ui->proxyPort,
            &QWidget::setEnabled);
    connect(ui->connectSocks, &QPushButton::toggled, this,
            &OptionsDialog::updateProxyValidationState);

    connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyIpTor,
            &QWidget::setEnabled);
    connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyPortTor,
            &QWidget::setEnabled);
    connect(ui->connectSocksTor, &QPushButton::toggled, this,
            &OptionsDialog::updateProxyValidationState);

    /* Window elements init */
#ifdef Q_OS_MAC
    /* remove Window tab on Mac */
    ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow));
    /* hide launch at startup option on macOS */
    ui->bitcoinAtStartup->setVisible(false);
    ui->verticalLayout_Main->removeWidget(ui->bitcoinAtStartup);
    ui->verticalLayout_Main->removeItem(ui->horizontalSpacer_0_Main);
#endif

    /* remove Wallet tab and 3rd party-URL textbox in case of -disablewallet */
    if (!enableWallet) {
        ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWallet));
        ui->thirdPartyTxUrlsLabel->setVisible(false);
        ui->thirdPartyTxUrls->setVisible(false);
    }

    /* Display elements init */
    QDir translations(":translations");

    ui->bitcoinAtStartup->setToolTip(
        ui->bitcoinAtStartup->toolTip().arg(PACKAGE_NAME));
    ui->bitcoinAtStartup->setText(
        ui->bitcoinAtStartup->text().arg(PACKAGE_NAME));

    ui->openBitcoinConfButton->setToolTip(
        ui->openBitcoinConfButton->toolTip().arg(PACKAGE_NAME));

    ui->lang->setToolTip(ui->lang->toolTip().arg(PACKAGE_NAME));
    ui->lang->addItem(QString("(") + tr("default") + QString(")"),
                      QVariant(""));
    for (const QString &langStr : translations.entryList()) {
        QLocale locale(langStr);

        /** check if the locale name consists of 2 parts (language_country) */
        if (langStr.contains("_")) {
            /** display language strings as "native language - native country
             * (locale name)", e.g. "Deutsch - Deutschland (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") +
                                  locale.nativeCountryName() + QString(" (") +
                                  langStr + QString(")"),
                              QVariant(langStr));
        } else {
            /** display language strings as "native language (locale name)",
             * e.g. "Deutsch (de)" */
            ui->lang->addItem(locale.nativeLanguageName() + QString(" (") +
                                  langStr + QString(")"),
                              QVariant(langStr));
        }
    }
    ui->unit->setModel(new BitcoinUnits(this));

    /* Widget-to-option mapper */
    mapper = new QDataWidgetMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);

    GUIUtil::ItemDelegate *delegate = new GUIUtil::ItemDelegate(mapper);
    connect(delegate, &GUIUtil::ItemDelegate::keyEscapePressed, this,
            &OptionsDialog::reject);
    mapper->setItemDelegate(delegate);

    /* setup/change UI elements when proxy IPs are invalid/valid */
    ui->proxyIp->setCheckValidator(new ProxyAddressValidator(parent));
    ui->proxyIpTor->setCheckValidator(new ProxyAddressValidator(parent));
    connect(ui->proxyIp, &QValidatedLineEdit::validationDidChange, this,
            &OptionsDialog::updateProxyValidationState);
    connect(ui->proxyIpTor, &QValidatedLineEdit::validationDidChange, this,
            &OptionsDialog::updateProxyValidationState);
    connect(ui->proxyPort, &QLineEdit::textChanged, this,
            &OptionsDialog::updateProxyValidationState);
    connect(ui->proxyPortTor, &QLineEdit::textChanged, this,
            &OptionsDialog::updateProxyValidationState);

    if (!QSystemTrayIcon::isSystemTrayAvailable()) {
        ui->hideTrayIcon->setChecked(true);
        ui->hideTrayIcon->setEnabled(false);
        ui->minimizeToTray->setChecked(false);
        ui->minimizeToTray->setEnabled(false);
    }
}

OptionsDialog::~OptionsDialog() {
    delete ui;
}

void OptionsDialog::setModel(OptionsModel *_model) {
    this->model = _model;

    if (_model) {
        /* check if client restart is needed and show persistent message */
        if (_model->isRestartRequired()) {
            showRestartWarning(true);
        }

        // Prune values are in GB to be consistent with intro.cpp
        static constexpr uint64_t nMinDiskSpace =
            (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) +
                    (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES)
                ? 1
                : 0;
        ui->pruneSize->setRange(nMinDiskSpace, std::numeric_limits<int>::max());

        QString strLabel = _model->getOverriddenByCommandLine();
        if (strLabel.isEmpty()) {
            strLabel = tr("none");
        }
        ui->overriddenByCommandLineLabel->setText(strLabel);

        mapper->setModel(_model);
        setMapper();
        mapper->toFirst();

        updateDefaultProxyNets();
    }

    /* warn when one of the following settings changes by user action (placed
     * here so init via mapper doesn't trigger them) */

    /* Main */
    connect(ui->prune, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    connect(ui->prune, &QCheckBox::clicked, this,
            &OptionsDialog::togglePruneWarning);
    connect(ui->pruneSize,
            static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
            &OptionsDialog::showRestartWarning);
    connect(ui->databaseCache,
            static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
            &OptionsDialog::showRestartWarning);
    connect(ui->threadsScriptVerif,
            static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
            &OptionsDialog::showRestartWarning);
    /* Wallet */
    connect(ui->spendZeroConfChange, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    /* Network */
    connect(ui->allowIncoming, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    connect(ui->connectSocks, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    connect(ui->connectSocksTor, &QCheckBox::clicked, this,
            &OptionsDialog::showRestartWarning);
    /* Display */
    connect(
        ui->lang,
        static_cast<void (QValueComboBox::*)()>(&QValueComboBox::valueChanged),
        [this] { showRestartWarning(); });
    connect(ui->thirdPartyTxUrls, &QLineEdit::textChanged,
            [this] { showRestartWarning(); });
}

void OptionsDialog::setCurrentTab(OptionsDialog::Tab tab) {
    QWidget *tab_widget = nullptr;
    if (tab == OptionsDialog::Tab::TAB_NETWORK) {
        tab_widget = ui->tabNetwork;
    }
    if (tab == OptionsDialog::Tab::TAB_MAIN) {
        tab_widget = ui->tabMain;
    }
    if (tab_widget && ui->tabWidget->currentWidget() != tab_widget) {
        ui->tabWidget->setCurrentWidget(tab_widget);
    }
}

void OptionsDialog::setMapper() {
    /* Main */
    mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup);
    mapper->addMapping(ui->threadsScriptVerif,
                       OptionsModel::ThreadsScriptVerif);
    mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache);
    mapper->addMapping(ui->prune, OptionsModel::Prune);
    mapper->addMapping(ui->pruneSize, OptionsModel::PruneSize);

    /* Wallet */
    mapper->addMapping(ui->spendZeroConfChange,
                       OptionsModel::SpendZeroConfChange);
    mapper->addMapping(ui->coinControlFeatures,
                       OptionsModel::CoinControlFeatures);

    /* Network */
    mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);
    mapper->addMapping(ui->allowIncoming, OptionsModel::Listen);

    mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
    mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
    mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);

    mapper->addMapping(ui->connectSocksTor, OptionsModel::ProxyUseTor);
    mapper->addMapping(ui->proxyIpTor, OptionsModel::ProxyIPTor);
    mapper->addMapping(ui->proxyPortTor, OptionsModel::ProxyPortTor);

/* Window */
#ifndef Q_OS_MAC
    if (QSystemTrayIcon::isSystemTrayAvailable()) {
        mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
        mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
    }
    mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
#endif

    /* Display */
    mapper->addMapping(ui->lang, OptionsModel::Language);
    mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
    mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
}

void OptionsDialog::setOkButtonState(bool fState) {
    ui->okButton->setEnabled(fState);
}

void OptionsDialog::on_resetButton_clicked() {
    if (model) {
        // confirmation dialog
        QMessageBox::StandardButton btnRetVal = QMessageBox::question(
            this, tr("Confirm options reset"),
            tr("Client restart required to activate changes.") + "

" +
                tr("Client will be shut down. Do you want to proceed?"),
            QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);

        if (btnRetVal == QMessageBox::Cancel) {
            return;
        }

        /* reset all options and close GUI */
        model->Reset();
        QApplication::quit();
    }
}

void OptionsDialog::on_openBitcoinConfButton_clicked() {
    /* explain the purpose of the config file */
    QMessageBox::information(
        this, tr("Configuration options"),
        tr("The configuration file is used to specify advanced user options "
           "which override GUI settings. Additionally, any command-line "
           "options will override this configuration file."));

    /* show an error if there was some problem opening the file */
    if (!GUIUtil::openBitcoinConf()) {
        QMessageBox::critical(
            this, tr("Error"),
            tr("The configuration file could not be opened."));
    }
}

void OptionsDialog::on_okButton_clicked() {
    mapper->submit();
    accept();
    updateDefaultProxyNets();
}

void OptionsDialog::on_cancelButton_clicked() {
    reject();
}

void OptionsDialog::on_hideTrayIcon_stateChanged(int fState) {
    if (fState) {
        ui->minimizeToTray->setChecked(false);
        ui->minimizeToTray->setEnabled(false);
    } else {
        ui->minimizeToTray->setEnabled(true);
    }
}

void OptionsDialog::togglePruneWarning(bool enabled) {
    ui->pruneWarning->setVisible(!ui->pruneWarning->isVisible());
}

void OptionsDialog::showRestartWarning(bool fPersistent) {
    ui->statusLabel->setStyleSheet("QLabel { color: red; }");

    if (fPersistent) {
        ui->statusLabel->setText(
            tr("Client restart required to activate changes."));
    } else {
        ui->statusLabel->setText(
            tr("This change would require a client restart."));
        // clear non-persistent status label after 10 seconds
        // TODO: should perhaps be a class attribute, if we extend the use of
        // statusLabel
        QTimer::singleShot(10000, this, &OptionsDialog::clearStatusLabel);
    }
}

void OptionsDialog::clearStatusLabel() {
    ui->statusLabel->clear();
    if (model && model->isRestartRequired()) {
        showRestartWarning(true);
    }
}

void OptionsDialog::updateProxyValidationState() {
    QValidatedLineEdit *pUiProxyIp = ui->proxyIp;
    QValidatedLineEdit *otherProxyWidget =
        (pUiProxyIp == ui->proxyIpTor) ? ui->proxyIp : ui->proxyIpTor;
    if (pUiProxyIp->isValid() &&
        (!ui->proxyPort->isEnabled() || ui->proxyPort->text().toInt() > 0) &&
        (!ui->proxyPortTor->isEnabled() ||
         ui->proxyPortTor->text().toInt() > 0)) {
        // Only enable ok button if both proxys are valid
        setOkButtonState(otherProxyWidget->isValid());
        clearStatusLabel();
    } else {
        setOkButtonState(false);
        ui->statusLabel->setStyleSheet("QLabel { color: red; }");
        ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
    }
}

void OptionsDialog::updateDefaultProxyNets() {
    proxyType proxy;
    std::string strProxy;
    QString strDefaultProxyGUI;

    model->node().getProxy(NET_IPV4, proxy);
    strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
    strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
    (strProxy == strDefaultProxyGUI.toStdString())
        ? ui->proxyReachIPv4->setChecked(true)
        : ui->proxyReachIPv4->setChecked(false);

    model->node().getProxy(NET_IPV6, proxy);
    strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
    strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
    (strProxy == strDefaultProxyGUI.toStdString())
        ? ui->proxyReachIPv6->setChecked(true)
        : ui->proxyReachIPv6->setChecked(false);

    model->node().getProxy(NET_ONION, proxy);
    strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
    strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
    (strProxy == strDefaultProxyGUI.toStdString())
        ? ui->proxyReachTor->setChecked(true)
        : ui->proxyReachTor->setChecked(false);
}

ProxyAddressValidator::ProxyAddressValidator(QObject *parent)
    : QValidator(parent) {}

QValidator::State ProxyAddressValidator::validate(QString &input,
                                                  int &pos) const {
    Q_UNUSED(pos);
    // Validate the proxy
    CService serv(
        LookupNumeric(input.toStdString().c_str(), DEFAULT_GUI_PROXY_PORT));
    proxyType addrProxy = proxyType(serv, true);
    if (addrProxy.IsValid()) {
        return QValidator::Acceptable;
    }

    return QValidator::Invalid;
}
<|endoftext|>


<commit_before>#include "rotocoinunits.h"

#include <QStringList>

RotocoinUnits::RotocoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<RotocoinUnits::Unit> RotocoinUnits::availableUnits()
{
    QList<RotocoinUnits::Unit> unitlist;
    unitlist.append(Rt2);
    unitlist.append(mRt2);
    unitlist.append(uRt2);
    unitlist.append(ilitris);
    return unitlist;
}

bool RotocoinUnits::valid(int unit)
{
    switch(unit)
    {
    case Rt2:
    case mRt2:
    case uRt2:
    case ilitris:
        return true;
    default:
        return false;
    }
}

QString RotocoinUnits::name(int unit)
{
    switch(unit)
    {
    case Rt2: return QString("Rt2");
    case mRt2: return QString("mRt2");
    case uRt2: return QString::fromUtf8("μRt2");
    case ilitris: return QString::fromUtf8("ilitris");
    default: return QString("???");
    }
}

QString RotocoinUnits::description(int unit)
{
    switch(unit)
    {
    case Rt2: return QString("Rotocoins");
    case mRt2: return QString("Milli-Rotocoins (0.001 Rt2)");       // ( 1 / 1,000 )
    case uRt2: return QString("Micro-Rotocoins (0.000001 Rt2)");    // ( 1 / 1,000,000 )
    case ilitris: return QString("ilitris (0.00000001 Rt2)");       // ( 1 / 100,000,000 )

    default: return QString("???");
    }
}

qint64 RotocoinUnits::factor(int unit)
{
    switch(unit)
    {
    case Rt2:  return 100000000;
    case mRt2: return 100000;
    case uRt2: return 100;
    case ilitris: return 1;
    default:   return 100000000;
    }
}

int RotocoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case Rt2: return 6; // 288,000 (# digits, without commas)
    case mRt2: return 9; // 288,000,000
    case uRt2: return 12; // 288,000,000,000
    case ilitris: return 14; // 28,800,000,000,000
    default: return 0;
    }
}

int RotocoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case Rt2: return 8;
    case mRt2: return 5;
    case uRt2: return 2;
    case ilitris: return 0;
    default: return 0;
    }
}

QString RotocoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');

    if (unit != ilitris)
        return quotient_str + QString(".") + remainder_str;
    else
        return quotient_str;
}

QString RotocoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool RotocoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int RotocoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant RotocoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<commit_msg>prettify units displaying<commit_after>#include "rotocoinunits.h"

#include <QStringList>

RotocoinUnits::RotocoinUnits(QObject *parent):
QAbstractListModel(parent),
unitlist(availableUnits())
{
}

QList<RotocoinUnits::Unit> RotocoinUnits::availableUnits()
{
    QList<RotocoinUnits::Unit> unitlist;
    unitlist.append(Rt2);
    unitlist.append(mRt2);
    unitlist.append(uRt2);
    unitlist.append(ilitris);
    return unitlist;
}

bool RotocoinUnits::valid(int unit)
{
    switch(unit)
    {
        case Rt2:
        case mRt2:
        case uRt2:
        case ilitris:
        return true;
        default:
        return false;
    }
}

QString RotocoinUnits::name(int unit)
{
    switch(unit)
    {
        case Rt2: return QString("Rt2");
        case mRt2: return QString("mRt2");
        case uRt2: return QString::fromUtf8("μRt2");
        case ilitris: return QString::fromUtf8("ilitris");
        default: return QString("???");
    }
}

QString RotocoinUnits::description(int unit)
{
    switch(unit)
    {
        case Rt2: return QString("Rotocoins");
    case mRt2: return QString("Milli-Rotocoins (0.001 Rt2)");       // ( 1 / 1,000 )
    case uRt2: return QString("Micro-Rotocoins (0.000001 Rt2)");    // ( 1 / 1,000,000 )
    case ilitris: return QString("ilitris (0.00000001 Rt2)");       // ( 1 / 100,000,000 )

    default: return QString("???");
}
}

qint64 RotocoinUnits::factor(int unit)
{
    switch(unit)
    {
        case Rt2:  return 100000000;
        case mRt2: return 100000;
        case uRt2: return 100;
        case ilitris: return 1;
        default:   return 100000000;
    }
}

int RotocoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case Rt2: return 6; // 288,000 (# digits, without commas)
    case mRt2: return 9; // 288,000,000
    case uRt2: return 12; // 288,000,000,000
    case ilitris: return 14; // 28,800,000,000,000
    default: return 0;
}
}

int RotocoinUnits::decimals(int unit)
{
    switch(unit)
    {
        case Rt2: return 8;
        case mRt2: return 5;
        case uRt2: return 2;
        case ilitris: return 0;
        default: return 0;
    }
}

QString RotocoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);

    // Dirty hack - TODO: prettify
    int qnum = quotient_str.size();
    for (int i = qnum; i>0 ; i=i-3)
        quotient_str.insert(i, " ");

    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');

    if (unit != ilitris)
        return quotient_str + QString(".") + remainder_str;
    else
        return quotient_str;
}

QString RotocoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool RotocoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int RotocoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant RotocoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
            case Qt::EditRole:
            case Qt::DisplayRole:
            return QVariant(name(unit));
            case Qt::ToolTipRole:
            return QVariant(description(unit));
            case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File FilterEnergy.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Output kinetic energy and enstrophy.
//
///////////////////////////////////////////////////////////////////////////////

#include <iomanip>

#include <SolverUtils/Filters/FilterEnergy.h>

namespace Nektar
{
    namespace SolverUtils
    {
        std::string FilterEnergy::className = GetFilterFactory().
            RegisterCreatorFunction("Energy", FilterEnergy::create);

        FilterEnergy::FilterEnergy(
            const LibUtilities::SessionReaderSharedPtr &pSession,
            const std::map<std::string, std::string> &pParams) :
            Filter(pSession), m_planes(), m_index(0), m_homogeneous(false)
        {
            std::string outName;
            if (pParams.find("OutputFile") == pParams.end())
            {
                outName = m_session->GetSessionName();
            }
            else
            {
                ASSERTL0(!(pParams.find("OutputFile")->second.empty()),
                         "Missing parameter 'OutputFile'.");
                outName = pParams.find("OutputFile")->second;
            }

            m_comm = pSession->GetComm();
            outName += ".eny";
            if (m_comm->GetRank() == 0)
            {
                m_outFile.open(outName.c_str());
                ASSERTL0(m_outFile.good(), "Unable to open: '" + outName + "'");
            }

            ASSERTL0(pParams.find("OutputFrequency") != pParams.end(),
                     "Missing parameter 'OutputFrequency'.");
            m_outputFrequency = atoi(pParams.find("OutputFrequency")->second.c_str());

            if (pSession->DefinesSolverInfo("HOMOGENEOUS"))
            {
                std::string HomoStr = m_session->GetSolverInfo("HOMOGENEOUS");
                if (HomoStr == "HOMOGENEOUS1D" || HomoStr == "Homogeneous1D" ||
                    HomoStr == "1D"            || HomoStr == "Homo1D")
                {
                    m_homogeneous = true;
                    pSession->LoadParameter("LZ", m_homogeneousLength);
                }
                else
                {
                    ASSERTL0(false, "The energy filter only supports 1D "
                                    "homogeneous expansions.");
                }
            }
        }

        FilterEnergy::~FilterEnergy()
        {

        }

        void FilterEnergy::v_Initialise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
        {
            m_index = 0;
            MultiRegions::ExpListSharedPtr areaField;

            // Calculate area/volume of domain.
            if (m_homogeneous)
            {
                m_planes = pFields[0]->GetZIDs();
                areaField = pFields[0]->GetPlane(0);
            }
            else
            {
                areaField = pFields[0];
            }

            Array<OneD, NekDouble> inarray(areaField->GetNpoints(), 1.0);
            m_area = areaField->Integral(inarray);

            if (m_homogeneous)
            {
                m_area *= m_homogeneousLength;
            }

            v_Update(pFields, time);
        }

        void FilterEnergy::v_Update(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
        {
            int i, n, nPoints = pFields[0]->GetNpoints(), nPlanePts = 0;

            if (m_homogeneous)
            {
                nPlanePts = pFields[0]->GetPlane(0)->GetNpoints();
            }

            m_index++;
            if (m_index % m_outputFrequency > 0)
            {
                return;
            }

            // Calculate kinetic energy.
            NekDouble Ek = 0.0;
            Array<OneD, NekDouble> tmp(nPoints);
            Array<OneD, Array<OneD, NekDouble> > u(3);
            for (i = 0; i < 3; ++i)
            {
                if (m_homogeneous)
                {
                    pFields[i]->HomogeneousBwdTrans(pFields[i]->GetPhys(), tmp);
                }

                u[i] = Array<OneD, NekDouble>(nPoints);
                Vmath::Vcopy(nPoints, tmp, 1, u[i], 1);
                Vmath::Vmul (nPoints, tmp, 1, tmp, 1, tmp, 1);

                if (m_homogeneous)
                {
                    pFields[i]->HomogeneousFwdTrans(tmp, tmp);
                    Ek += pFields[i]->GetPlane(0)->Integral(tmp) * 2.0 * M_PI;
                }
                else
                {
                    Ek += pFields[i]->Integral(tmp);
                }
            }

            Ek /= 2.0*m_area;

            if (m_comm->GetRank() == 0)
            {
                m_outFile << setw(10) << time << setw(20) << Ek;
            }

            bool waveSpace[3] = {
                pFields[0]->GetWaveSpace(),
                pFields[1]->GetWaveSpace(),
                pFields[2]->GetWaveSpace()
            };

            if (m_homogeneous)
            {
                for (i = 0; i < 3; ++i)
                {
                    pFields[i]->SetWaveSpace(false);
                }
            }

            // First calculate vorticity field.
            Array<OneD, NekDouble> tmp2(nPoints), tmp3(nPoints);
            Vmath::Zero(nPoints, tmp, 1);
            for (i = 0; i < 3; ++i)
            {
                int f1 = (i+2) % 3, c2 = f1;
                int c1 = (i+1) % 3, f2 = c1;
                pFields[f1]->PhysDeriv(c1, u[f1], tmp2);
                pFields[f2]->PhysDeriv(c2, u[f2], tmp3);
                Vmath::Vsub (nPoints, tmp2, 1, tmp3, 1, tmp2, 1);
                Vmath::Vvtvp(nPoints, tmp2, 1, tmp2, 1, tmp, 1, tmp, 1);
            }

            if (m_homogeneous)
            {
                for (i = 0; i < 3; ++i)
                {
                    pFields[i]->SetWaveSpace(waveSpace[i]);
                }
                pFields[0]->HomogeneousFwdTrans(tmp, tmp);
                Ek = pFields[0]->GetPlane(0)->Integral(tmp) * 2 * M_PI;
            }
            else
            {
                Ek = pFields[0]->Integral(tmp);
            }

            Ek /= 2.0*m_area;

            if (m_comm->GetRank() == 0)
            {
                m_outFile << setw(20) << Ek << endl;
            }
        }

        void FilterEnergy::v_Finalise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
        {
            m_outFile.close();
        }

        bool FilterEnergy::v_IsTimeDependent()
        {
            return true;
        }
    }
}
<commit_msg>Fix energy filter for full 3D simulation.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File FilterEnergy.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Output kinetic energy and enstrophy.
//
///////////////////////////////////////////////////////////////////////////////

#include <iomanip>

#include <SolverUtils/Filters/FilterEnergy.h>

namespace Nektar
{
    namespace SolverUtils
    {
        std::string FilterEnergy::className = GetFilterFactory().
            RegisterCreatorFunction("Energy", FilterEnergy::create);

        FilterEnergy::FilterEnergy(
            const LibUtilities::SessionReaderSharedPtr &pSession,
            const std::map<std::string, std::string> &pParams) :
            Filter(pSession), m_planes(), m_index(0), m_homogeneous(false)
        {
            std::string outName;
            if (pParams.find("OutputFile") == pParams.end())
            {
                outName = m_session->GetSessionName();
            }
            else
            {
                ASSERTL0(!(pParams.find("OutputFile")->second.empty()),
                         "Missing parameter 'OutputFile'.");
                outName = pParams.find("OutputFile")->second;
            }

            m_comm = pSession->GetComm();
            outName += ".eny";
            if (m_comm->GetRank() == 0)
            {
                m_outFile.open(outName.c_str());
                ASSERTL0(m_outFile.good(), "Unable to open: '" + outName + "'");
            }

            ASSERTL0(pParams.find("OutputFrequency") != pParams.end(),
                     "Missing parameter 'OutputFrequency'.");
            m_outputFrequency = atoi(pParams.find("OutputFrequency")->second.c_str());

            if (pSession->DefinesSolverInfo("HOMOGENEOUS"))
            {
                std::string HomoStr = m_session->GetSolverInfo("HOMOGENEOUS");
                if (HomoStr == "HOMOGENEOUS1D" || HomoStr == "Homogeneous1D" ||
                    HomoStr == "1D"            || HomoStr == "Homo1D")
                {
                    m_homogeneous = true;
                    pSession->LoadParameter("LZ", m_homogeneousLength);
                }
                else
                {
                    ASSERTL0(false, "The energy filter only supports 1D "
                                    "homogeneous expansions.");
                }
            }
        }

        FilterEnergy::~FilterEnergy()
        {

        }

        void FilterEnergy::v_Initialise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
        {
            m_index = 0;
            MultiRegions::ExpListSharedPtr areaField;

            // Calculate area/volume of domain.
            if (m_homogeneous)
            {
                m_planes  = pFields[0]->GetZIDs();
                areaField = pFields[0]->GetPlane(0);
            }
            else
            {
                areaField = pFields[0];
            }

            Array<OneD, NekDouble> inarray(areaField->GetNpoints(), 1.0);
            m_area = areaField->Integral(inarray);

            if (m_homogeneous)
            {
                m_area *= m_homogeneousLength;
            }

            // Output values at initial time.
            v_Update(pFields, time);
        }

        void FilterEnergy::v_Update(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
        {
            int i, n, nPoints = pFields[0]->GetNpoints(), nPlanePts = 0;

            if (m_homogeneous)
            {
                nPlanePts = pFields[0]->GetPlane(0)->GetNpoints();
            }

            m_index++;
            if (m_index % m_outputFrequency > 0)
            {
                return;
            }

            // Calculate kinetic energy.
            NekDouble Ek = 0.0;
            Array<OneD, NekDouble> tmp(nPoints);
            Array<OneD, Array<OneD, NekDouble> > u(3);
            for (i = 0; i < 3; ++i)
            {
                if (m_homogeneous)
                {
                    pFields[i]->HomogeneousBwdTrans(pFields[i]->GetPhys(), tmp);
                }
                else
                {
                    tmp = pFields[i]->GetPhys();
                }

                u[i] = Array<OneD, NekDouble>(nPoints);
                Vmath::Vcopy(nPoints, tmp, 1, u[i], 1);
                Vmath::Vmul (nPoints, tmp, 1, tmp, 1, tmp, 1);

                if (m_homogeneous)
                {
                    pFields[i]->HomogeneousFwdTrans(tmp, tmp);
                    Ek += pFields[i]->GetPlane(0)->Integral(tmp) * 2.0 * M_PI;
                }
                else
                {
                    Ek += pFields[i]->Integral(tmp);
                }
            }

            Ek /= 2.0*m_area;

            if (m_comm->GetRank() == 0)
            {
                m_outFile << setw(10) << time << setw(20) << Ek;
            }

            bool waveSpace[3] = {
                pFields[0]->GetWaveSpace(),
                pFields[1]->GetWaveSpace(),
                pFields[2]->GetWaveSpace()
            };

            if (m_homogeneous)
            {
                for (i = 0; i < 3; ++i)
                {
                    pFields[i]->SetWaveSpace(false);
                }
            }

            // First calculate vorticity field.
            Array<OneD, NekDouble> tmp2(nPoints), tmp3(nPoints);
            Vmath::Zero(nPoints, tmp, 1);
            for (i = 0; i < 3; ++i)
            {
                int f1 = (i+2) % 3, c2 = f1;
                int c1 = (i+1) % 3, f2 = c1;
                pFields[f1]->PhysDeriv(c1, u[f1], tmp2);
                pFields[f2]->PhysDeriv(c2, u[f2], tmp3);
                Vmath::Vsub (nPoints, tmp2, 1, tmp3, 1, tmp2, 1);
                Vmath::Vvtvp(nPoints, tmp2, 1, tmp2, 1, tmp, 1, tmp, 1);
            }

            if (m_homogeneous)
            {
                for (i = 0; i < 3; ++i)
                {
                    pFields[i]->SetWaveSpace(waveSpace[i]);
                }
                pFields[0]->HomogeneousFwdTrans(tmp, tmp);
                Ek = pFields[0]->GetPlane(0)->Integral(tmp) * 2 * M_PI;
            }
            else
            {
                Ek = pFields[0]->Integral(tmp);
            }

            Ek /= 2.0*m_area;

            if (m_comm->GetRank() == 0)
            {
                m_outFile << setw(20) << Ek << endl;
            }
        }

        void FilterEnergy::v_Finalise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
        {
            m_outFile.close();
        }

        bool FilterEnergy::v_IsTimeDependent()
        {
            return true;
        }
    }
}
<|endoftext|>