<commit_before>/* Copyright (c) 2008-2017 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 http://www.mrtrix.org/.
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
    + "Denoise DWI data and estimate the noise level based on the optimal threshold for PCA."

    + "DWI data denoising and noise map estimation by exploiting data redundancy in the PCA domain "
    "using the prior knowledge that the eigenspectrum of random covariance matrices is described by "
    "the universal Marchenko Pastur distribution."

    + "Important note: image denoising must be performed as the first step of the image processing pipeline. "
    "The routine will fail if interpolation or smoothing has been applied to the data prior to denoising."

    + "Note that this function does not correct for non-Gaussian noise biases.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier@gmail.com)";

  REFERENCES
    + "Veraart, J.; Novikov, D.S.; Christiaens, D.; Ades-aron, B.; Sijbers, J. & Fieremans, E. " // Internal
    "Denoising of diffusion MRI using random matrix theory. "
    "NeuroImage, 2016, in press, doi: 10.1016/j.neuroimage.2016.08.016"

    + "Veraart, J.; Fieremans, E. & Novikov, D.S. " // Internal
    "Diffusion MRI noise mapping using random matrix theory. "
    "Magn. Res. Med., 2016, early view, doi: 10.1002/mrm.26059";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
    + Option ("mask", "only perform computation within the specified binary brain mask image.")
    +   Argument ("image").type_image_in()

    + Option ("extent", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + "," + str(DEFAULT_SIZE) + "," + str(DEFAULT_SIZE) + ")")
    +   Argument ("window").type_sequence_int ()

    + Option ("noise", "the output noise map.")
    +   Argument ("level").type_image_out();

  COPYRIGHT = "Copyright (c) 2016 New York University, University of Antwerp, and the MRtrix3 contributors \n \n"
      "Permission is hereby granted, free of charge, to any non-commercial entity ('Recipient') obtaining a copy of this software and "
      "associated documentation files (the 'Software'), to the Software solely for non-commercial research, including the rights to "
      "use, copy and modify the Software, subject to the following conditions: \n \n"
      "\t 1. The above copyright notice and this permission notice shall be included by Recipient in all copies or substantial portions of "
      "the Software. \n \n"
      "\t 2. 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. \n \n"
      "\t 3. In no event shall NYU be liable for direct, indirect, special, incidental or consequential damages in connection with the Software. "
      "Recipient will defend, indemnify and hold NYU harmless from any claims or liability resulting from the use of the Software by recipient. \n \n"
      "\t 4. Neither anything contained herein nor the delivery of the Software to recipient shall be deemed to grant the Recipient any right or "
      "licenses under any patents or patent application owned by NYU. \n \n"
      "\t 5. The Software may only be used for non-commercial research and may not be used for clinical care. \n \n"
      "\t 6. Any publication by Recipient of research involving the Software shall cite the references listed below.";

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor { MEMALIGN(DenoisingFunctor)
  public:
  DenoisingFunctor (ImageType& dwi, vector<int> extent, Image<bool>& mask, ImageType& noise)
    : extent {{extent[0]/2, extent[1]/2, extent[2]/2}},
      m (dwi.size(3)),
      n (extent[0]*extent[1]*extent[2]),
      r ((m<n) ? m : n),
      X (m,n),
      pos {{0, 0, 0}},
      mask (mask),
      noise (noise)
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    if (mask.valid()) {
      assign_pos_of (dwi).to (mask);
      if (!mask.value())
        return;
    }

    // Load data in local window
    load_data (dwi);

    // Compute Eigendecomposition:
    Eigen::MatrixXf XtX (r,r);
    if (m <= n)
      XtX.template triangularView<Eigen::Lower>() = X * X.transpose();
    else
      XtX.template triangularView<Eigen::Lower>() = X.transpose() * X;
    Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eig (XtX);
    // eigenvalues provide squared singular values:
    Eigen::VectorXf s = eig.eigenvalues();

    // Marchenko-Pastur optimal threshold
    const double lam_r = s[0] / n;
    double clam = 0.0;
    sigma2 = NaN;
    ssize_t cutoff_p = 0;
    for (ssize_t p = 0; p < r; ++p)
    {
      double lam = s[p] / n;
      clam += lam;
      double gam = double(m-r+p+1) / double(n);
      double sigsq1 = clam / (p+1) / std::max (gam, 1.0);
      double sigsq2 = (lam - lam_r) / 4 / std::sqrt(gam);
      // sigsq2 > sigsq1 if signal else noise
      if (sigsq2 < sigsq1) {
        sigma2 = sigsq1;
        cutoff_p = p+1;
      }
    }

    if (cutoff_p > 0) {
      // recombine data using only eigenvectors above threshold:
      s.head (cutoff_p).setZero();
      s.tail (r-cutoff_p).setOnes();
      if (m <= n)
        X.col (n/2) = eig.eigenvectors() * ( s.asDiagonal() * ( eig.eigenvectors().adjoint() * X.col(n/2) ));
      else
        X.col (n/2) = X * ( eig.eigenvectors() * ( s.asDiagonal() * eig.eigenvectors().adjoint().col(n/2) ));
    }

    // Store output
    assign_pos_of(dwi).to(out);
    for (auto l = Loop (3) (out); l; ++l)
      out.value() = X(out.index(3), n/2);

    // store noise map if requested:
    if (noise.valid()) {
      assign_pos_of(dwi).to(noise);
      noise.value() = value_type (std::sqrt(sigma2));
    }
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent[2]; dwi.index(2) <= pos[2]+extent[2]; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent[1]; dwi.index(1) <= pos[1]+extent[1]; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent[0]; dwi.index(0) <= pos[0]+extent[0]; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi,0,3))
            X.col(k) = dwi.row(3);
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  const std::array<ssize_t, 3> extent;
  const ssize_t m, n, r;
  Eigen::MatrixXf X;
  std::array<ssize_t, 3> pos;
  double sigma2;
  Image<bool> mask;
  ImageType noise;

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  Image<bool> mask;
  auto opt = get_options ("mask");
  if (opt.size()) {
    mask = Image<bool>::open (opt[0][0]);
    check_dimensions (mask, dwi_in, 0, 3);
  }

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  opt = get_options("extent");
  vector<int> extent = { DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE };
  if (opt.size()) {
    extent = parse_ints(opt[0][0]);
    if (extent.size() == 1)
      extent = {extent[0], extent[0], extent[0]};
    if (extent.size() != 3)
      throw Exception ("-extent must be either a scalar or a list of length 3");
    for (auto &e : extent)
      if (!(e & 1))
        throw Exception ("-extent must be a (list of) odd numbers");
  }

  Image<value_type> noise;
  opt = get_options("noise");
  if (opt.size()) {
    header.ndim() = 3;
    noise = Image<value_type>::create (opt[0][0], header);
  }

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent, mask, noise);
  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);
}

<commit_msg>dwidenoise: update citation.<commit_after>/* Copyright (c) 2008-2017 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 http://www.mrtrix.org/.
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
    + "Denoise DWI data and estimate the noise level based on the optimal threshold for PCA."

    + "DWI data denoising and noise map estimation by exploiting data redundancy in the PCA domain "
    "using the prior knowledge that the eigenspectrum of random covariance matrices is described by "
    "the universal Marchenko Pastur distribution."

    + "Important note: image denoising must be performed as the first step of the image processing pipeline. "
    "The routine will fail if interpolation or smoothing has been applied to the data prior to denoising."

    + "Note that this function does not correct for non-Gaussian noise biases.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier@gmail.com)";

  REFERENCES
    + "Veraart, J.; Novikov, D.S.; Christiaens, D.; Ades-aron, B.; Sijbers, J. & Fieremans, E. " // Internal
    "Denoising of diffusion MRI using random matrix theory. "
    "NeuroImage, 2016, 142, 394-406, doi: 10.1016/j.neuroimage.2016.08.016"

    + "Veraart, J.; Fieremans, E. & Novikov, D.S. " // Internal
    "Diffusion MRI noise mapping using random matrix theory. "
    "Magn. Res. Med., 2016, early view, doi: 10.1002/mrm.26059";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
    + Option ("mask", "only perform computation within the specified binary brain mask image.")
    +   Argument ("image").type_image_in()

    + Option ("extent", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + "," + str(DEFAULT_SIZE) + "," + str(DEFAULT_SIZE) + ")")
    +   Argument ("window").type_sequence_int ()

    + Option ("noise", "the output noise map.")
    +   Argument ("level").type_image_out();

  COPYRIGHT = "Copyright (c) 2016 New York University, University of Antwerp, and the MRtrix3 contributors \n \n"
      "Permission is hereby granted, free of charge, to any non-commercial entity ('Recipient') obtaining a copy of this software and "
      "associated documentation files (the 'Software'), to the Software solely for non-commercial research, including the rights to "
      "use, copy and modify the Software, subject to the following conditions: \n \n"
      "\t 1. The above copyright notice and this permission notice shall be included by Recipient in all copies or substantial portions of "
      "the Software. \n \n"
      "\t 2. 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. \n \n"
      "\t 3. In no event shall NYU be liable for direct, indirect, special, incidental or consequential damages in connection with the Software. "
      "Recipient will defend, indemnify and hold NYU harmless from any claims or liability resulting from the use of the Software by recipient. \n \n"
      "\t 4. Neither anything contained herein nor the delivery of the Software to recipient shall be deemed to grant the Recipient any right or "
      "licenses under any patents or patent application owned by NYU. \n \n"
      "\t 5. The Software may only be used for non-commercial research and may not be used for clinical care. \n \n"
      "\t 6. Any publication by Recipient of research involving the Software shall cite the references listed below.";

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor { MEMALIGN(DenoisingFunctor)
  public:
  DenoisingFunctor (ImageType& dwi, vector<int> extent, Image<bool>& mask, ImageType& noise)
    : extent {{extent[0]/2, extent[1]/2, extent[2]/2}},
      m (dwi.size(3)),
      n (extent[0]*extent[1]*extent[2]),
      r ((m<n) ? m : n),
      X (m,n),
      pos {{0, 0, 0}},
      mask (mask),
      noise (noise)
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    if (mask.valid()) {
      assign_pos_of (dwi).to (mask);
      if (!mask.value())
        return;
    }

    // Load data in local window
    load_data (dwi);

    // Compute Eigendecomposition:
    Eigen::MatrixXf XtX (r,r);
    if (m <= n)
      XtX.template triangularView<Eigen::Lower>() = X * X.transpose();
    else
      XtX.template triangularView<Eigen::Lower>() = X.transpose() * X;
    Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eig (XtX);
    // eigenvalues provide squared singular values:
    Eigen::VectorXf s = eig.eigenvalues();

    // Marchenko-Pastur optimal threshold
    const double lam_r = s[0] / n;
    double clam = 0.0;
    sigma2 = NaN;
    ssize_t cutoff_p = 0;
    for (ssize_t p = 0; p < r; ++p)
    {
      double lam = s[p] / n;
      clam += lam;
      double gam = double(m-r+p+1) / double(n);
      double sigsq1 = clam / (p+1) / std::max (gam, 1.0);
      double sigsq2 = (lam - lam_r) / 4 / std::sqrt(gam);
      // sigsq2 > sigsq1 if signal else noise
      if (sigsq2 < sigsq1) {
        sigma2 = sigsq1;
        cutoff_p = p+1;
      }
    }

    if (cutoff_p > 0) {
      // recombine data using only eigenvectors above threshold:
      s.head (cutoff_p).setZero();
      s.tail (r-cutoff_p).setOnes();
      if (m <= n)
        X.col (n/2) = eig.eigenvectors() * ( s.asDiagonal() * ( eig.eigenvectors().adjoint() * X.col(n/2) ));
      else
        X.col (n/2) = X * ( eig.eigenvectors() * ( s.asDiagonal() * eig.eigenvectors().adjoint().col(n/2) ));
    }

    // Store output
    assign_pos_of(dwi).to(out);
    for (auto l = Loop (3) (out); l; ++l)
      out.value() = X(out.index(3), n/2);

    // store noise map if requested:
    if (noise.valid()) {
      assign_pos_of(dwi).to(noise);
      noise.value() = value_type (std::sqrt(sigma2));
    }
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent[2]; dwi.index(2) <= pos[2]+extent[2]; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent[1]; dwi.index(1) <= pos[1]+extent[1]; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent[0]; dwi.index(0) <= pos[0]+extent[0]; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi,0,3))
            X.col(k) = dwi.row(3);
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  const std::array<ssize_t, 3> extent;
  const ssize_t m, n, r;
  Eigen::MatrixXf X;
  std::array<ssize_t, 3> pos;
  double sigma2;
  Image<bool> mask;
  ImageType noise;

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  Image<bool> mask;
  auto opt = get_options ("mask");
  if (opt.size()) {
    mask = Image<bool>::open (opt[0][0]);
    check_dimensions (mask, dwi_in, 0, 3);
  }

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  opt = get_options("extent");
  vector<int> extent = { DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE };
  if (opt.size()) {
    extent = parse_ints(opt[0][0]);
    if (extent.size() == 1)
      extent = {extent[0], extent[0], extent[0]};
    if (extent.size() != 3)
      throw Exception ("-extent must be either a scalar or a list of length 3");
    for (auto &e : extent)
      if (!(e & 1))
        throw Exception ("-extent must be a (list of) odd numbers");
  }

  Image<value_type> noise;
  opt = get_options("noise");
  if (opt.size()) {
    header.ndim() = 3;
    noise = Image<value_type>::create (opt[0][0], header);
  }

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent, mask, noise);
  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);
}

<|endoftext|>


<commit_before>#ifndef AURACLE_HH
#define AURACLE_HH

#include <string>
#include <vector>

#include "aur/aur.hh"
#include "package_cache.hh"
#include "pacman.hh"
#include "sort.hh"

namespace auracle {

class Auracle {
 public:
  struct Options {
    Options& set_aur_baseurl(std::string aur_baseurl) {
      this->aur_baseurl = aur_baseurl;
      return *this;
    }

    Options& set_pacman(Pacman* pacman) {
      this->pacman = pacman;
      return *this;
    }

    Options& set_max_connections(int max_connections) {
      this->max_connections = max_connections;
      return *this;
    }

    Options& set_connection_timeout(int connection_timeout) {
      this->connection_timeout = connection_timeout;
      return *this;
    }

    Options& set_quiet(bool quiet) {
      this->quiet = quiet;
      return *this;
    }

    std::string aur_baseurl;
    Pacman* pacman = nullptr;
    bool quiet = false;
    int max_connections = 0;
    int connection_timeout = 0;
  };

  explicit Auracle(Options options)
      : aur_(options.aur_baseurl), pacman_(options.pacman) {
    aur_.SetMaxConnections(options.max_connections);
    aur_.SetConnectTimeout(options.connection_timeout);
  }

  ~Auracle() = default;

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

  Auracle(Auracle&&) = default;
  Auracle& operator=(Auracle&&) = default;

  struct CommandOptions {
    aur::SearchRequest::SearchBy search_by =
        aur::SearchRequest::SearchBy::NAME_DESC;
    std::string directory;
    bool recurse = false;
    bool allow_regex = true;
    bool quiet = false;
    std::string show_file = "PKGBUILD";
    sort::Sorter sorter =
        sort::MakePackageSorter("name", sort::OrderBy::ORDER_ASC);
    std::string format;
  };

  int BuildOrder(const std::vector<std::string>& args,
                 const CommandOptions& options);
  int Clone(const std::vector<std::string>& args,
            const CommandOptions& options);
  int Download(const std::vector<std::string>& args,
               const CommandOptions& options);
  int Info(const std::vector<std::string>& args, const CommandOptions& options);
  int Show(const std::vector<std::string>& args, const CommandOptions& options);
  int RawInfo(const std::vector<std::string>& args,
              const CommandOptions& options);
  int RawSearch(const std::vector<std::string>& args,
                const CommandOptions& options);
  int Search(const std::vector<std::string>& args,
             const CommandOptions& options);
  int Sync(const std::vector<std::string>& args, const CommandOptions& options);

 private:
  struct PackageIterator {
    using PackageCallback = std::function<void(const aur::Package&)>;

    PackageIterator(bool recurse, PackageCallback callback)
        : recurse(recurse), callback(std::move(callback)) {}

    bool recurse;

    const PackageCallback callback;
    PackageCache package_cache;
  };

  int SendRawRpc(const aur::RpcRequest* request);

  void IteratePackages(std::vector<std::string> args, PackageIterator* state);

  aur::Aur aur_;
  Pacman* pacman_;
};

}  // namespace auracle

#endif  // AURACLE_HH
<commit_msg>Drop unused function prototype<commit_after>#ifndef AURACLE_HH
#define AURACLE_HH

#include <string>
#include <vector>

#include "aur/aur.hh"
#include "package_cache.hh"
#include "pacman.hh"
#include "sort.hh"

namespace auracle {

class Auracle {
 public:
  struct Options {
    Options& set_aur_baseurl(std::string aur_baseurl) {
      this->aur_baseurl = aur_baseurl;
      return *this;
    }

    Options& set_pacman(Pacman* pacman) {
      this->pacman = pacman;
      return *this;
    }

    Options& set_max_connections(int max_connections) {
      this->max_connections = max_connections;
      return *this;
    }

    Options& set_connection_timeout(int connection_timeout) {
      this->connection_timeout = connection_timeout;
      return *this;
    }

    Options& set_quiet(bool quiet) {
      this->quiet = quiet;
      return *this;
    }

    std::string aur_baseurl;
    Pacman* pacman = nullptr;
    bool quiet = false;
    int max_connections = 0;
    int connection_timeout = 0;
  };

  explicit Auracle(Options options)
      : aur_(options.aur_baseurl), pacman_(options.pacman) {
    aur_.SetMaxConnections(options.max_connections);
    aur_.SetConnectTimeout(options.connection_timeout);
  }

  ~Auracle() = default;

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

  Auracle(Auracle&&) = default;
  Auracle& operator=(Auracle&&) = default;

  struct CommandOptions {
    aur::SearchRequest::SearchBy search_by =
        aur::SearchRequest::SearchBy::NAME_DESC;
    std::string directory;
    bool recurse = false;
    bool allow_regex = true;
    bool quiet = false;
    std::string show_file = "PKGBUILD";
    sort::Sorter sorter =
        sort::MakePackageSorter("name", sort::OrderBy::ORDER_ASC);
    std::string format;
  };

  int BuildOrder(const std::vector<std::string>& args,
                 const CommandOptions& options);
  int Clone(const std::vector<std::string>& args,
            const CommandOptions& options);
  int Download(const std::vector<std::string>& args,
               const CommandOptions& options);
  int Info(const std::vector<std::string>& args, const CommandOptions& options);
  int Show(const std::vector<std::string>& args, const CommandOptions& options);
  int RawInfo(const std::vector<std::string>& args,
              const CommandOptions& options);
  int RawSearch(const std::vector<std::string>& args,
                const CommandOptions& options);
  int Search(const std::vector<std::string>& args,
             const CommandOptions& options);
  int Sync(const std::vector<std::string>& args, const CommandOptions& options);

 private:
  struct PackageIterator {
    using PackageCallback = std::function<void(const aur::Package&)>;

    PackageIterator(bool recurse, PackageCallback callback)
        : recurse(recurse), callback(std::move(callback)) {}

    bool recurse;

    const PackageCallback callback;
    PackageCache package_cache;
  };

  void IteratePackages(std::vector<std::string> args, PackageIterator* state);

  aur::Aur aur_;
  Pacman* pacman_;
};

}  // namespace auracle

#endif  // AURACLE_HH
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      process.cpp
// Purpose:   Implementation of class wxExProcess
// Author:    Anton van Wezenbeek
// Copyright: (c) 2014 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/timer.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/process.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/defs.h>
#include <wx/extension/shell.h>
#include <wx/extension/stcdlg.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess(wxWindow* parent)
  : wxProcess(wxPROCESS_REDIRECT)
  , m_Parent(parent)
  , m_Timer(new wxTimer(this))
  , m_Busy(false)
  , m_Error(false)
  , m_HasStdError(false)
  , m_Sync(false)
  , m_Dialog(NULL)
{
  m_Command = wxExConfigFirstOf(_("Process"));
}

wxExProcess::~wxExProcess()
{
  delete m_Timer;
}

wxExProcess::wxExProcess(const wxExProcess& process)
  : m_Timer(NULL)
{
  *this = process;
}

wxExProcess& wxExProcess::operator=(const wxExProcess& p)
{
  if (this != &p)
  {
    if (m_Timer != NULL)
    {
      delete m_Timer;
    }

    m_Timer = new wxTimer(this);

    m_Busy = p.m_Busy;
    m_Command = p.m_Command;
    m_Error = p.m_Error;
    m_HasStdError = p.m_HasStdError;
    m_Output = p.m_Output;
    m_Sync = p.m_Sync;
  }

  return *this;
}

bool wxExProcess::CheckInput(const wxString& command)
{
  if (m_Busy)
  {
    return false;
  }

  m_Busy = true;

  wxString output;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());

    while (IsInputAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());

    while (IsErrorAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  m_Busy = false;

  if (!output.empty())
  {
    if (!command.empty() && output.StartsWith(command))
    {
      m_Dialog->GetSTCShell()->AppendText(output.substr(command.length()));
    }
    else
    {
      m_Dialog->GetSTCShell()->AppendText(output);
    }

    return true;
  }
  else
  {
    return false;
  }
}

bool wxExProcess::Command(int id, const wxString& command)
{
  switch (id)
  {
  case ID_SHELL_COMMAND:
    m_Timer->Stop();
    m_Dialog->GetSTCShell()->LineEnd();

    if (
      m_Command != "cmd" &&
      m_Command != "cmd.exe" &&
      m_Command != "powershell")
    {
      m_Dialog->GetSTCShell()->AppendText(m_Dialog->GetSTCShell()->GetEOL());
    }

    if (IsRunning())
    {
      // send command to process
      wxOutputStream* os = GetOutputStream();

      if (os != NULL)
      {
        wxTextOutputStream os(*GetOutputStream());

        if (HandleCommand(command))
        {
          os.WriteString(command + "\n");

          wxMilliSleep(10);

          if (!CheckInput(command))
          {
            m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
          }

          m_Timer->Start();
        }
      }
    }
    else
    {
      wxLogStatus("Process is not running");
      return false;
    }
    break;

  case ID_SHELL_COMMAND_STOP:
    if (IsRunning())
    {
      if (Kill() == wxKILL_OK)
      {
        wxBell();
      }
    }
    break;

  default: wxFAIL;
    return false;
    break;
  }

  return true;
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title,
  bool modal)
{
  std::vector<wxExConfigItem> v;

  wxExConfigItem ci(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString,
    true);

  wxTextValidator validator(wxFILTER_EXCLUDE_CHAR_LIST);
  validator.SetCharExcludes("/\\?%*:|\"<>");
  ci.SetValidator(&validator);

  v.push_back(ci);

  // adding this to initializer list, causes error
  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1005));

  if (modal)
  {
    return wxExConfigDialog(parent,
      v,
      title).ShowModal();
  }
  else
  {
    wxExConfigDialog* dlg = new wxExConfigDialog(
      parent,
      v,
      title);

    return dlg->Show();
  }
}

bool wxExProcess::Execute(
  const wxString& command_to_execute,
  int flags,
  const wxString& wd)
{
  m_Error = false;

  struct wxExecuteEnv env;

  if (command_to_execute.empty())
  {
    if (wxExConfigFirstOf(_("Process")).empty())
    {
      if (!wd.empty())
      {
        wxLogStatus("Ignored specified working directory");
      }

      if (ConfigDialog(wxTheApp->GetTopWindow()) == wxID_CANCEL)
      {
        return false;
      }
    }

    m_Command = wxExConfigFirstOf(_("Process"));
    env.cwd = wxExConfigFirstOf(m_WorkingDirKey);
  }
  else
  {
    m_Command = command_to_execute;
    env.cwd = wd;
  }

  if (!env.cwd.empty() && env.cwd != wxGetCwd())
  {
    if (!wxSetWorkingDirectory(env.cwd))
    {
      wxLogStatus("Working directory invalid");
      return false;
    }
  }

  m_Sync = (flags & wxEXEC_SYNC);

  // Construct the dialog.
  // This is necessary both in sync and async mode,
  // as for sync mode the dialog is used for presenting the
  // output member.
  if (m_Dialog == NULL)
  {
    m_Dialog = new wxExSTCEntryDialog(
      m_Parent,
      wxEmptyString,
      wxEmptyString,
      wxEmptyString,
      wxOK,
      true); // use_shell to force STCShell

    m_Dialog->SetEscapeId(wxID_NONE);
  }

  m_Dialog->SetProcess(this);
  m_Dialog->GetSTCShell()->EnableShell(!m_Sync);
  m_Dialog->GetSTCShell()->SetProcess(this);

  m_HasStdError = false;

  if (!m_Sync)
  {
    m_Dialog->SetTitle(m_Command);
    m_Dialog->GetSTCShell()->ClearAll();

    // If we have entered a shell, then the shell
    // itself has no prompt. So put one here.
    if (m_Command == "bash" ||
        m_Command == "csh" ||
        m_Command == "ksh" ||
        m_Command == "tcsh" ||
        m_Command == "sh")
    {
      m_Dialog->GetSTCShell()->SetPrompt(">", false);
      m_Dialog->SetLexer(m_Command);
    }
    else
    {
      m_Dialog->GetSTCShell()->SetPrompt("");

      if (m_Command == "cmd")
      {
        m_Dialog->SetLexer("batch");
      }
      else if (m_Command == "powershell")
      {
        m_Dialog->SetLexer("powershell");
      }
    }

    // For asynchronous execution the return value is the process id and zero
    // value indicates that the command could not be executed.
    if (wxExecute(m_Command, flags, this, &env) > 0)
    {
      m_Dialog->Show();

      if (!CheckInput())
      {
        m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
      }

      wxTheApp->Yield();
      wxMilliSleep(100);

      if (IsRunning())
      {
        m_Timer->Start(100); // each 100 milliseconds
        m_Dialog->GetSTCShell()->SetFocus();
      }
    }
    else
    {
      m_Dialog->Hide();

      m_Error = true;
    }
  }
  else
  {
    wxArrayString output;
    wxArrayString errors;

    // Call wxExecute to execute the command and
    // collect the output and the errors.
    if (wxExecute(
      m_Command,
      output,
      errors,
      flags,
      &env) == -1)
    {
      m_Output.clear();
      m_Error = true;
    }
    else
    {
      m_HasStdError = !errors.empty();

      // Set output by converting array strings into normal strings.
      m_Output = wxJoin(errors, '\n', '\n') + wxJoin(output, '\n', '\n');
    }
  }

  return !m_Error;
}

wxExSTCShell* wxExProcess::GetShell()
{
  return m_Dialog != NULL ? m_Dialog->GetSTCShell(): NULL;
}

wxExSTC* wxExProcess::GetSTC() const
{
  return m_Dialog != NULL ? m_Dialog->GetSTC(): NULL;
}

bool wxExProcess::HandleCommand(const wxString& command)
{
  wxString rest;

  if (
         command.StartsWith("cd", &rest)
#ifdef __WXMSW__
      || command.StartsWith("chdir", &rest)
#endif
     )
  {
    // Always return true, so you get a new line,
    // whether or not setworkingdir succeeded.
    wxLogNull logNo;
    rest.Trim(false);
    rest.Trim(true);

    if (rest.empty() || rest == "~")
    {
#ifdef __WXMSW__
      return true;
#else
      wxSetWorkingDirectory(wxGetHomeDir());
#endif
    }
    else
    {
      wxSetWorkingDirectory(rest);
    }
  }
  else if (
    command == "exit" &&
    m_Dialog->GetSTC()->GetLexer().IsKeyword("exit"))
  {
    Kill();
    return false;
  }

  return true;
}

bool wxExProcess::IsRunning() const
{
  if (
    // If we executed a sync process, then it always ended,
    // so it is not running.
    m_Sync ||
    // If we have not yet run Execute, process is not running
    m_Dialog == NULL ||
    GetPid() <= 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  const wxKillError result = wxProcess::Kill(GetPid(), sig);

  switch (result)
  {
    case wxKILL_OK:
      wxLogStatus(_("Stopped"));
      DeletePendingEvents();
      m_Timer->Stop();
      m_Dialog->Hide();
      m_Parent->SetFocus();
      break;

    case wxKILL_BAD_SIGNAL:
      wxLogStatus("no such signal");
      break;

    case wxKILL_ACCESS_DENIED:
    	wxLogStatus("permission denied");
      break;

    case wxKILL_NO_PROCESS:
      wxLogStatus("no such process");
      break;

    case wxKILL_ERROR:
      wxLogStatus("another, unspecified error");
      break;

    default: wxFAIL;
  }

  return result;
}

void wxExProcess::OnTerminate(int pid, int status)
{
  m_Timer->Stop();

  wxLogStatus(_("Ready"));

  // Collect remaining input.
  CheckInput();
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  CheckInput();
}

#if wxUSE_GUI
void wxExProcess::ShowOutput(const wxString& caption) const
{
  if (!m_Sync)
  {
    wxLogStatus("Output only available for sync processes");
  }
  else if (!m_Error)
  {
    if (m_Dialog != NULL)
    {
      m_Dialog->GetSTC()->SetText(m_Output);
      m_Dialog->SetTitle(caption.empty() ? m_Command: caption);
      m_Dialog->Show();
    }
    else if (!m_Output.empty())
    {
      wxLogMessage(m_Output);
    }
    else
    {
      wxLogStatus("No output available");
    }
  }
  else
  {
    // Executing command failed, so no output,
    // show failing command.
    wxLogError("Could not execute: " + m_Command);
  }
}
#endif
<commit_msg>fixed dialog initialization<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      process.cpp
// Purpose:   Implementation of class wxExProcess
// Author:    Anton van Wezenbeek
// Copyright: (c) 2014 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/timer.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/process.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/defs.h>
#include <wx/extension/shell.h>
#include <wx/extension/stcdlg.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess(wxWindow* parent)
  : wxProcess(wxPROCESS_REDIRECT)
  , m_Parent(parent)
  , m_Timer(new wxTimer(this))
  , m_Busy(false)
  , m_Error(false)
  , m_HasStdError(false)
  , m_Sync(false)
  , m_Dialog(NULL)
{
  m_Command = wxExConfigFirstOf(_("Process"));
}

wxExProcess::~wxExProcess()
{
  if (m_Parent == NULL)
  {
    if (m_Dialog != NULL)
    {
      m_Dialog->Destroy();
    }
  }

  delete m_Timer;
}

wxExProcess::wxExProcess(const wxExProcess& process)
  : m_Timer(NULL)
  , m_Dialog(NULL)
{
  *this = process;
}

wxExProcess& wxExProcess::operator=(const wxExProcess& p)
{
  if (this != &p)
  {
    if (m_Timer != NULL)
    {
      delete m_Timer;
    }

    m_Timer = new wxTimer(this);
    m_Dialog = NULL;

    m_Busy = p.m_Busy;
    m_Command = p.m_Command;
    m_Error = p.m_Error;
    m_HasStdError = p.m_HasStdError;
    m_Output = p.m_Output;
    m_Sync = p.m_Sync;
  }

  return *this;
}

bool wxExProcess::CheckInput(const wxString& command)
{
  if (m_Busy)
  {
    return false;
  }

  m_Busy = true;

  wxString output;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());

    while (IsInputAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());

    while (IsErrorAvailable())
    {
      const wxChar c = tis.GetChar();

      if (c != 0)
      {
        output << c;
      }
    }
  }

  m_Busy = false;

  if (!output.empty())
  {
    if (!command.empty() && output.StartsWith(command))
    {
      m_Dialog->GetSTCShell()->AppendText(output.substr(command.length()));
    }
    else
    {
      m_Dialog->GetSTCShell()->AppendText(output);
    }

    return true;
  }
  else
  {
    return false;
  }
}

bool wxExProcess::Command(int id, const wxString& command)
{
  switch (id)
  {
  case ID_SHELL_COMMAND:
    m_Timer->Stop();
    m_Dialog->GetSTCShell()->LineEnd();

    if (
      m_Command != "cmd" &&
      m_Command != "cmd.exe" &&
      m_Command != "powershell")
    {
      m_Dialog->GetSTCShell()->AppendText(m_Dialog->GetSTCShell()->GetEOL());
    }

    if (IsRunning())
    {
      // send command to process
      wxOutputStream* os = GetOutputStream();

      if (os != NULL)
      {
        wxTextOutputStream os(*GetOutputStream());

        if (HandleCommand(command))
        {
          os.WriteString(command + "\n");

          wxMilliSleep(10);

          if (!CheckInput(command))
          {
            m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
          }

          m_Timer->Start();
        }
      }
    }
    else
    {
      wxLogStatus("Process is not running");
      return false;
    }
    break;

  case ID_SHELL_COMMAND_STOP:
    if (IsRunning())
    {
      if (Kill() == wxKILL_OK)
      {
        wxBell();
      }
    }
    break;

  default: wxFAIL;
    return false;
    break;
  }

  return true;
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title,
  bool modal)
{
  std::vector<wxExConfigItem> v;

  wxExConfigItem ci(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString,
    true);

  wxTextValidator validator(wxFILTER_EXCLUDE_CHAR_LIST);
  validator.SetCharExcludes("/\\?%*:|\"<>");
  ci.SetValidator(&validator);

  v.push_back(ci);

  // adding this to initializer list, causes error
  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1005));

  if (modal)
  {
    return wxExConfigDialog(parent,
      v,
      title).ShowModal();
  }
  else
  {
    wxExConfigDialog* dlg = new wxExConfigDialog(
      parent,
      v,
      title);

    return dlg->Show();
  }
}

bool wxExProcess::Execute(
  const wxString& command_to_execute,
  int flags,
  const wxString& wd)
{
  m_Error = false;

  struct wxExecuteEnv env;

  if (command_to_execute.empty())
  {
    if (wxExConfigFirstOf(_("Process")).empty())
    {
      if (!wd.empty())
      {
        wxLogStatus("Ignored specified working directory");
      }

      if (ConfigDialog(wxTheApp->GetTopWindow()) == wxID_CANCEL)
      {
        return false;
      }
    }

    m_Command = wxExConfigFirstOf(_("Process"));
    env.cwd = wxExConfigFirstOf(m_WorkingDirKey);
  }
  else
  {
    m_Command = command_to_execute;
    env.cwd = wd;
  }

  if (!env.cwd.empty() && env.cwd != wxGetCwd())
  {
    if (!wxSetWorkingDirectory(env.cwd))
    {
      wxLogStatus("Working directory invalid");
      return false;
    }
  }

  m_Sync = (flags & wxEXEC_SYNC);

  // Construct the dialog.
  // This is necessary both in sync and async mode,
  // as for sync mode the dialog is used for presenting the
  // output member.
  if (m_Dialog == NULL)
  {
    m_Dialog = new wxExSTCEntryDialog(
      m_Parent,
      wxEmptyString,
      wxEmptyString,
      wxEmptyString,
      wxOK,
      true); // use_shell to force STCShell

    m_Dialog->SetEscapeId(wxID_NONE);
  }

  m_Dialog->SetProcess(this);
  m_Dialog->GetSTCShell()->EnableShell(!m_Sync);
  m_Dialog->GetSTCShell()->SetProcess(this);

  m_HasStdError = false;

  if (!m_Sync)
  {
    m_Dialog->SetTitle(m_Command);
    m_Dialog->GetSTCShell()->ClearAll();

    // If we have entered a shell, then the shell
    // itself has no prompt. So put one here.
    if (m_Command == "bash" ||
        m_Command == "csh" ||
        m_Command == "ksh" ||
        m_Command == "tcsh" ||
        m_Command == "sh")
    {
      m_Dialog->GetSTCShell()->SetPrompt(">", false);
      m_Dialog->SetLexer(m_Command);
    }
    else
    {
      m_Dialog->GetSTCShell()->SetPrompt("");

      if (m_Command == "cmd")
      {
        m_Dialog->SetLexer("batch");
      }
      else if (m_Command == "powershell")
      {
        m_Dialog->SetLexer("powershell");
      }
    }

    // For asynchronous execution the return value is the process id and zero
    // value indicates that the command could not be executed.
    if (wxExecute(m_Command, flags, this, &env) > 0)
    {
      m_Dialog->Show();

      if (!CheckInput())
      {
        m_Dialog->GetSTCShell()->Prompt(wxEmptyString, false);
      }

      wxTheApp->Yield();
      wxMilliSleep(100);

      if (IsRunning())
      {
        m_Timer->Start(100); // each 100 milliseconds
        m_Dialog->GetSTCShell()->SetFocus();
      }
    }
    else
    {
      m_Dialog->Hide();

      m_Error = true;
    }
  }
  else
  {
    wxArrayString output;
    wxArrayString errors;

    // Call wxExecute to execute the command and
    // collect the output and the errors.
    if (wxExecute(
      m_Command,
      output,
      errors,
      flags,
      &env) == -1)
    {
      m_Output.clear();
      m_Error = true;
    }
    else
    {
      m_HasStdError = !errors.empty();

      // Set output by converting array strings into normal strings.
      m_Output = wxJoin(errors, '\n', '\n') + wxJoin(output, '\n', '\n');
    }
  }

  return !m_Error;
}

wxExSTCShell* wxExProcess::GetShell()
{
  return m_Dialog != NULL ? m_Dialog->GetSTCShell(): NULL;
}

wxExSTC* wxExProcess::GetSTC() const
{
  return m_Dialog != NULL ? m_Dialog->GetSTC(): NULL;
}

bool wxExProcess::HandleCommand(const wxString& command)
{
  wxString rest;

  if (
         command.StartsWith("cd", &rest)
#ifdef __WXMSW__
      || command.StartsWith("chdir", &rest)
#endif
     )
  {
    // Always return true, so you get a new line,
    // whether or not setworkingdir succeeded.
    wxLogNull logNo;
    rest.Trim(false);
    rest.Trim(true);

    if (rest.empty() || rest == "~")
    {
#ifdef __WXMSW__
      return true;
#else
      wxSetWorkingDirectory(wxGetHomeDir());
#endif
    }
    else
    {
      wxSetWorkingDirectory(rest);
    }
  }
  else if (
    command == "exit" &&
    m_Dialog->GetSTC()->GetLexer().IsKeyword("exit"))
  {
    Kill();
    return false;
  }

  return true;
}

bool wxExProcess::IsRunning() const
{
  if (
    // If we executed a sync process, then it always ended,
    // so it is not running.
    m_Sync ||
    // If we have not yet run Execute, process is not running
    m_Dialog == NULL ||
    GetPid() <= 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  const wxKillError result = wxProcess::Kill(GetPid(), sig);

  switch (result)
  {
    case wxKILL_OK:
      wxLogStatus(_("Stopped"));
      DeletePendingEvents();
      m_Timer->Stop();
      m_Dialog->Hide();
      m_Parent->SetFocus();
      break;

    case wxKILL_BAD_SIGNAL:
      wxLogStatus("no such signal");
      break;

    case wxKILL_ACCESS_DENIED:
    	wxLogStatus("permission denied");
      break;

    case wxKILL_NO_PROCESS:
      wxLogStatus("no such process");
      break;

    case wxKILL_ERROR:
      wxLogStatus("another, unspecified error");
      break;

    default: wxFAIL;
  }

  return result;
}

void wxExProcess::OnTerminate(int pid, int status)
{
  m_Timer->Stop();

  wxLogStatus(_("Ready"));

  // Collect remaining input.
  CheckInput();
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  CheckInput();
}

#if wxUSE_GUI
void wxExProcess::ShowOutput(const wxString& caption) const
{
  if (!m_Sync)
  {
    wxLogStatus("Output only available for sync processes");
  }
  else if (!m_Error)
  {
    if (m_Dialog != NULL)
    {
      m_Dialog->GetSTC()->SetText(m_Output);
      m_Dialog->SetTitle(caption.empty() ? m_Command: caption);
      m_Dialog->Show();
    }
    else if (!m_Output.empty())
    {
      wxLogMessage(m_Output);
    }
    else
    {
      wxLogStatus("No output available");
    }
  }
  else
  {
    // Executing command failed, so no output,
    // show failing command.
    wxLogError("Could not execute: " + m_Command);
  }
}
#endif
<|endoftext|>


<commit_before>#ifndef NEU_LAYER_TRAITS_HPP
#define NEU_LAYER_TRAITS_HPP
//20151025
#include <type_traits>
#include <yaml-cpp/yaml.h>

namespace neu {
	namespace layer {
		enum class rank_id : std::size_t {
			dim = 0,
			width = 0,
			height = 1,
			channel_num = 2
		};

		//
		// input_rank
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class input_rank {
			public:
				static decltype(auto) call(Layer const& l) {
					return l.input_rank();
				}
			};
		}
		template<typename Layer>
		decltype(auto) input_rank(Layer const& l) {
			return ::neu::layer::traits::input_rank<std::decay_t<Layer>>::call(l);
		}

		//
		// output_rank
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class output_rank {
			public:
				static decltype(auto) call(Layer const& l) {
					return l.output_rank();
				}
			};
		}
		template<typename Layer>
		decltype(auto) output_rank(Layer const& l) {
			return ::neu::layer::traits::output_rank<std::decay_t<Layer>>::call(l);
		}

		//
		// input_size
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class input_size {
			public:
				static decltype(auto) call(Layer const& l, rank_id ri) {
					return l.input_size(ri);
				}
			};
		}
		template<typename Layer>
		decltype(auto) input_size(Layer const& l, rank_id ri) {
			if(static_cast<int>(ri) >= input_rank(l)) {
				throw "out of range of input rank";
			}
			return ::neu::layer::traits::input_size<std::decay_t<Layer>>::call(l, ri);
		}

		// helper for geometric layers
		template<typename Layer>
		decltype(auto) input_width(Layer const& l) {
			if(input_rank(l) <= 1) {
				throw "input rank should be greater than 1";
			}
			return ::neu::layer::input_size(l, rank_id::width);
		}

		//
		// output_size
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class output_size {
			public:
				static decltype(auto) call(Layer const& l, rank_id ri) {
					return l.output_size(ri);
				}
			};
		}
		template<typename Layer>
		decltype(auto) output_size(Layer const& l, rank_id ri) {
			if(static_cast<int>(ri) >= output_rank(l)) {
				throw "out of range of output rank";
			}
			return ::neu::layer::traits::output_size<std::decay_t<Layer>>::call(l, ri);
		}

		// helper for geometric layers
		template<typename Layer>
		decltype(auto) output_width(Layer const& l) {
			if(output_rank(l) <= 1) {
				throw "output rank should be greater than 1";
			}
			return ::neu::layer::output_size(l, rank_id::width);
		}

		// input_dim
		template<typename Layer>
		decltype(auto) input_dim(Layer const& l) {
			auto dim = 1;
			for(auto i = 0; i < static_cast<int>(::neu::layer::input_rank(l)); ++i) {
				dim *= input_size(l, static_cast<rank_id>(i));
			}
			return dim;
		}

		// output_dim
		template<typename Layer>
		decltype(auto) output_dim(Layer const& l) {
			auto dim = 1;
			for(auto i = 0; i < static_cast<int>(::neu::layer::output_rank(l)); ++i) {
				dim *= output_size(l, static_cast<rank_id>(i));
			}
			return dim;
		}

		//
		// batch_size
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class batch_size {
			public:
				static decltype(auto) call(Layer const& l) {
					return l.batch_size();
				}
			};
		}
		template<typename Layer>
		decltype(auto) batch_size(Layer const& l) {
			return ::neu::layer::traits::batch_size<std::decay_t<Layer>>::call(l);
		}

		// input_size
		template<typename Layer>
		decltype(auto) whole_input_size(Layer const& l) {
			return ::neu::layer::input_dim(l)*::neu::layer::batch_size(l);
		}

		// output_size
		template<typename Layer>
		decltype(auto) whole_output_size(Layer const& l) {
			return ::neu::layer::output_dim(l)*::neu::layer::batch_size(l);
		}

		//
		// test_forward
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class test_forward {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(Layer& l, std::size_t batch_size,
						InputRange const& input, OutputRange& output,
						boost::compute::command_queue& queue) {
					l.test_forward(batch_size, input, output, queue);
				}
			};
		}
		template<typename Layer, typename InputRange, typename OutputRange>
		decltype(auto) test_forward(Layer& l, std::size_t batch_size,
				InputRange const& input, OutputRange& output,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::test_forward<std::decay_t<Layer>>::call(
				l, batch_size, input, output, queue);
		}

		//
		// forward
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class forward {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(Layer& l,
						InputRange const& input, OutputRange& output,
						boost::compute::command_queue& queue) {
					l.forward(input, output, queue);
				}
			};
		}
		template<typename Layer, typename InputRange, typename OutputRange>
		decltype(auto) forward(Layer& l,
				InputRange const& input, OutputRange& output,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::forward<std::decay_t<Layer>>::call(
				l, input, output, queue);
		}

		//
		// backward_top
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class backward_top {
			public:
				template<typename InputRange>
				static decltype(auto) call(Layer& l,
						InputRange const& delta,
						boost::compute::command_queue& queue) {
					l.backward_top(delta, queue);
				}
			};
		}
		template<typename Layer, typename InputRange>
		decltype(auto) backward_top(Layer& l,
				InputRange const& delta,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::backward_top<std::decay_t<Layer>>::call(
				l, delta, queue);
		}

		//
		// backward
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class backward {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(Layer& l,
						InputRange const& delta, OutputRange& prev_delta,
						boost::compute::command_queue& queue) {
					l.backward(delta, prev_delta, queue);
				}
			};
		}
		template<typename Layer, typename InputRange, typename OutputRange>
		decltype(auto) backward(Layer& l,
				InputRange const& delta, OutputRange& prev_delta,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::backward<std::decay_t<Layer>>::call(
				l, delta, prev_delta, queue);
		}

		//
		// update
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class update {
			public:
				static decltype(auto) call(Layer& l,
						boost::compute::command_queue& queue) {
					l.update(queue);
				}
			};
		}
		template<typename Layer>
		decltype(auto) update(Layer& l,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::update<std::decay_t<Layer>>::call(l, queue);
		}

		//
		// serialize
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class serialize {
			public:
				static decltype(auto) call(Layer const& l,
						YAML::Emitter& emitter,
						boost::compute::command_queue& queue) {
					l.serialize(emitter, queue);
				}
			};
		}
		template<typename Layer>
		decltype(auto) serialize(Layer const& l,
				YAML::Emitter& emitter,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::serialize<std::decay_t<Layer>>::call(l, emitter, queue);
		}
	}
}
#endif //NEU_LAYER_TRAITS_HPP
<commit_msg>add output_channel<commit_after>#ifndef NEU_LAYER_TRAITS_HPP
#define NEU_LAYER_TRAITS_HPP
//20151025
#include <type_traits>
#include <yaml-cpp/yaml.h>

namespace neu {
	namespace layer {
		enum class rank_id : std::size_t {
			dim = 0,
			width = 0,
			height = 1,
			channel_num = 2
		};

		//
		// input_rank
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class input_rank {
			public:
				static decltype(auto) call(Layer const& l) {
					return l.input_rank();
				}
			};
		}
		template<typename Layer>
		decltype(auto) input_rank(Layer const& l) {
			return ::neu::layer::traits::input_rank<std::decay_t<Layer>>::call(l);
		}

		//
		// output_rank
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class output_rank {
			public:
				static decltype(auto) call(Layer const& l) {
					return l.output_rank();
				}
			};
		}
		template<typename Layer>
		decltype(auto) output_rank(Layer const& l) {
			return ::neu::layer::traits::output_rank<std::decay_t<Layer>>::call(l);
		}

		//
		// input_size
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class input_size {
			public:
				static decltype(auto) call(Layer const& l, rank_id ri) {
					return l.input_size(ri);
				}
			};
		}
		template<typename Layer>
		decltype(auto) input_size(Layer const& l, rank_id ri) {
			if(static_cast<int>(ri) >= input_rank(l)) {
				throw "out of range of input rank";
			}
			return ::neu::layer::traits::input_size<std::decay_t<Layer>>::call(l, ri);
		}

		// helper for geometric layers
		template<typename Layer>
		decltype(auto) input_width(Layer const& l) {
			if(input_rank(l) <= 1) {
				throw "input rank should be greater than 1";
			}
			return ::neu::layer::input_size(l, rank_id::width);
		}

		//
		// output_size
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class output_size {
			public:
				static decltype(auto) call(Layer const& l, rank_id ri) {
					return l.output_size(ri);
				}
			};
		}
		template<typename Layer>
		decltype(auto) output_size(Layer const& l, rank_id ri) {
			if(static_cast<int>(ri) >= output_rank(l)) {
				throw "out of range of output rank";
			}
			return ::neu::layer::traits::output_size<std::decay_t<Layer>>::call(l, ri);
		}

		// helper for geometric layers
		template<typename Layer>
		decltype(auto) output_width(Layer const& l) {
			if(output_rank(l) <= 1) {
				throw "output rank should be greater than 1";
			}
			return ::neu::layer::output_size(l, rank_id::width);
		}

		template<typename Layer>
		decltype(auto) output_channel_num(Layer const& l) {
			if(output_rank(l) <= 2) {
				throw "output rank should be greater than 1";
			}
			return ::neu::layer::output_size(l, rank_id::channel_num);
		}

		// input_dim
		template<typename Layer>
		decltype(auto) input_dim(Layer const& l) {
			auto dim = 1;
			for(auto i = 0; i < static_cast<int>(::neu::layer::input_rank(l)); ++i) {
				dim *= input_size(l, static_cast<rank_id>(i));
			}
			return dim;
		}

		// output_dim
		template<typename Layer>
		decltype(auto) output_dim(Layer const& l) {
			auto dim = 1;
			for(auto i = 0; i < static_cast<int>(::neu::layer::output_rank(l)); ++i) {
				dim *= output_size(l, static_cast<rank_id>(i));
			}
			return dim;
		}

		//
		// batch_size
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class batch_size {
			public:
				static decltype(auto) call(Layer const& l) {
					return l.batch_size();
				}
			};
		}
		template<typename Layer>
		decltype(auto) batch_size(Layer const& l) {
			return ::neu::layer::traits::batch_size<std::decay_t<Layer>>::call(l);
		}

		// input_size
		template<typename Layer>
		decltype(auto) whole_input_size(Layer const& l) {
			return ::neu::layer::input_dim(l)*::neu::layer::batch_size(l);
		}

		// output_size
		template<typename Layer>
		decltype(auto) whole_output_size(Layer const& l) {
			return ::neu::layer::output_dim(l)*::neu::layer::batch_size(l);
		}

		//
		// test_forward
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class test_forward {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(Layer& l, std::size_t batch_size,
						InputRange const& input, OutputRange& output,
						boost::compute::command_queue& queue) {
					l.test_forward(batch_size, input, output, queue);
				}
			};
		}
		template<typename Layer, typename InputRange, typename OutputRange>
		decltype(auto) test_forward(Layer& l, std::size_t batch_size,
				InputRange const& input, OutputRange& output,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::test_forward<std::decay_t<Layer>>::call(
				l, batch_size, input, output, queue);
		}

		//
		// forward
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class forward {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(Layer& l,
						InputRange const& input, OutputRange& output,
						boost::compute::command_queue& queue) {
					l.forward(input, output, queue);
				}
			};
		}
		template<typename Layer, typename InputRange, typename OutputRange>
		decltype(auto) forward(Layer& l,
				InputRange const& input, OutputRange& output,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::forward<std::decay_t<Layer>>::call(
				l, input, output, queue);
		}

		//
		// backward_top
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class backward_top {
			public:
				template<typename InputRange>
				static decltype(auto) call(Layer& l,
						InputRange const& delta,
						boost::compute::command_queue& queue) {
					l.backward_top(delta, queue);
				}
			};
		}
		template<typename Layer, typename InputRange>
		decltype(auto) backward_top(Layer& l,
				InputRange const& delta,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::backward_top<std::decay_t<Layer>>::call(
				l, delta, queue);
		}

		//
		// backward
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class backward {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(Layer& l,
						InputRange const& delta, OutputRange& prev_delta,
						boost::compute::command_queue& queue) {
					l.backward(delta, prev_delta, queue);
				}
			};
		}
		template<typename Layer, typename InputRange, typename OutputRange>
		decltype(auto) backward(Layer& l,
				InputRange const& delta, OutputRange& prev_delta,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::backward<std::decay_t<Layer>>::call(
				l, delta, prev_delta, queue);
		}

		//
		// update
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class update {
			public:
				static decltype(auto) call(Layer& l,
						boost::compute::command_queue& queue) {
					l.update(queue);
				}
			};
		}
		template<typename Layer>
		decltype(auto) update(Layer& l,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::update<std::decay_t<Layer>>::call(l, queue);
		}

		//
		// serialize
		//
		namespace traits {
			// default implementation (call member function)
			template<typename Layer>
			class serialize {
			public:
				static decltype(auto) call(Layer const& l,
						YAML::Emitter& emitter,
						boost::compute::command_queue& queue) {
					l.serialize(emitter, queue);
				}
			};
		}
		template<typename Layer>
		decltype(auto) serialize(Layer const& l,
				YAML::Emitter& emitter,
				boost::compute::command_queue& queue) {
			::neu::layer::traits::serialize<std::decay_t<Layer>>::call(l, emitter, queue);
		}
	}
}
#endif //NEU_LAYER_TRAITS_HPP
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
#include "ExecutorService.h"

#include <boost/asio.hpp>
#include <functional>
#include <memory>

namespace pulsar {

ExecutorService::ExecutorService()
    : io_service_(new boost::asio::io_service()),
      work_(new BackgroundWork(*io_service_)),
      worker_(std::bind(&ExecutorService::startWorker, this, io_service_)) {}

ExecutorService::~ExecutorService() {
    close();
    // If the worker_ is still not joinable at this point just detach
    // the thread so its destructor does not terminate the app
    if (worker_.joinable()) {
        worker_.detach();
    }
}

void ExecutorService::startWorker(std::shared_ptr<boost::asio::io_service> io_service) { io_service_->run(); }

/*
 *  factory method of boost::asio::ip::tcp::socket associated with io_service_ instance
 *  @ returns shared_ptr to this socket
 */
SocketPtr ExecutorService::createSocket() {
    return SocketPtr(new boost::asio::ip::tcp::socket(*io_service_));
}

TlsSocketPtr ExecutorService::createTlsSocket(SocketPtr &socket, boost::asio::ssl::context &ctx) {
    return std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket &> >(
        new boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>(*socket, ctx));
}

/*
 *  factory method of Resolver object associated with io_service_ instance
 *  @returns shraed_ptr to resolver object
 */
TcpResolverPtr ExecutorService::createTcpResolver() {
    return TcpResolverPtr(new boost::asio::ip::tcp::resolver(*io_service_));
}

DeadlineTimerPtr ExecutorService::createDeadlineTimer() {
    return DeadlineTimerPtr(new boost::asio::deadline_timer(*io_service_));
}

void ExecutorService::close() {
    bool expectedState = false;
    if (!closed_.compare_exchange_strong(expectedState, true)) {
        return;
    }

    io_service_->stop();
    work_.reset();
    // Detach the worker thread instead of join to avoid potential deadlock
    if (worker_.joinable()) {
        worker_.detach();
    }
}

void ExecutorService::postWork(std::function<void(void)> task) { io_service_->post(task); }

/////////////////////

ExecutorServiceProvider::ExecutorServiceProvider(int nthreads)
    : executors_(nthreads), executorIdx_(0), mutex_() {}

ExecutorServicePtr ExecutorServiceProvider::get() {
    Lock lock(mutex_);

    int idx = executorIdx_++ % executors_.size();
    if (!executors_[idx]) {
        executors_[idx] = std::make_shared<ExecutorService>();
    }

    return executors_[idx];
}

void ExecutorServiceProvider::close() {
    Lock lock(mutex_);

    for (ExecutorList::iterator it = executors_.begin(); it != executors_.end(); ++it) {
        if (*it != NULL) {
            (*it)->close();
        }
        it->reset();
    }
}
}  // namespace pulsar
<commit_msg>[C++] Handle error when shutting down client after forks (#11954)<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
#include "ExecutorService.h"

#include <boost/asio.hpp>
#include <functional>
#include <memory>

#include "LogUtils.h"
DECLARE_LOG_OBJECT()

namespace pulsar {

ExecutorService::ExecutorService()
    : io_service_(new boost::asio::io_service()),
      work_(new BackgroundWork(*io_service_)),
      worker_(std::bind(&ExecutorService::startWorker, this, io_service_)) {}

ExecutorService::~ExecutorService() { close(); }

void ExecutorService::startWorker(std::shared_ptr<boost::asio::io_service> io_service) { io_service_->run(); }

/*
 *  factory method of boost::asio::ip::tcp::socket associated with io_service_ instance
 *  @ returns shared_ptr to this socket
 */
SocketPtr ExecutorService::createSocket() {
    return SocketPtr(new boost::asio::ip::tcp::socket(*io_service_));
}

TlsSocketPtr ExecutorService::createTlsSocket(SocketPtr &socket, boost::asio::ssl::context &ctx) {
    return std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket &> >(
        new boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>(*socket, ctx));
}

/*
 *  factory method of Resolver object associated with io_service_ instance
 *  @returns shraed_ptr to resolver object
 */
TcpResolverPtr ExecutorService::createTcpResolver() {
    return TcpResolverPtr(new boost::asio::ip::tcp::resolver(*io_service_));
}

DeadlineTimerPtr ExecutorService::createDeadlineTimer() {
    return DeadlineTimerPtr(new boost::asio::deadline_timer(*io_service_));
}

void ExecutorService::close() {
    bool expectedState = false;
    if (!closed_.compare_exchange_strong(expectedState, true)) {
        return;
    }

    io_service_->stop();
    work_.reset();
    // Detach the worker thread instead of join to avoid potential deadlock
    if (worker_.joinable()) {
        try {
            worker_.detach();
        } catch (const std::system_error &e) {
            // This condition will happen if we're forking the process, therefore the thread was not ported to
            // the child side of the fork and the detach would be failing.
            LOG_DEBUG("Failed to detach thread: " << e.what());
        }
    }
}

void ExecutorService::postWork(std::function<void(void)> task) { io_service_->post(task); }

/////////////////////

ExecutorServiceProvider::ExecutorServiceProvider(int nthreads)
    : executors_(nthreads), executorIdx_(0), mutex_() {}

ExecutorServicePtr ExecutorServiceProvider::get() {
    Lock lock(mutex_);

    int idx = executorIdx_++ % executors_.size();
    if (!executors_[idx]) {
        executors_[idx] = std::make_shared<ExecutorService>();
    }

    return executors_[idx];
}

void ExecutorServiceProvider::close() {
    Lock lock(mutex_);

    for (ExecutorList::iterator it = executors_.begin(); it != executors_.end(); ++it) {
        if (*it != NULL) {
            (*it)->close();
        }
        it->reset();
    }
}
}  // namespace pulsar
<|endoftext|>


<commit_before><commit_msg>posix: don't complain when stat() fails with ENOENT<commit_after><|endoftext|>


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

#ifndef CONFIGMGR_AUTOOBJECT_HXX
#define CONFIGMGR_AUTOOBJECT_HXX

#ifndef CONFIGMGR_UTILITY_HXX_
#include "utility.hxx"
#endif

namespace configmgr
{
////////////////////////////////////////////////////////////////////////////////
    using ::rtl::OUString;

//-----------------------------------------------------------------------------
    template < class Object >
    class AutoObject : Noncopyable
    {
    public:
        typedef Object      object_type;
        typedef Object *    Ptr;
    public:
        AutoObject() : m_pObject(NULL) {}
        AutoObject(Object * _obj) : m_pObject(_obj) {}
        ~AutoObject() { delete m_pObject; }

        bool is()   const;
        Ptr get()   const;
        Ptr getOrCreate();
    private:
        Ptr internalCreate();
    private:
        Ptr  m_pObject;
    };
//-----------------------------------------------------------------------------

    template < class Object >
    inline
    Object * AutoObject<Object>::get() const
    {
        return m_pObject;
    }
//-----------------------------------------------------------------------------

    template < class Object >
    inline
    bool AutoObject<Object>::is() const
    {
        return get() != NULL;
    }
//-----------------------------------------------------------------------------

    template < class Object >
    Object * AutoObject<Object>::getOrCreate()
    {
        Object * p = get();
        return p ? p : internalCreate();
    }
//-----------------------------------------------------------------------------

    template < class Object >
    Object * AutoObject<Object>::internalCreate()
    {
        if (m_pObject == NULL)
            m_pObject = new Object();
        return m_pObject;

    }
//-----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////

} // namespace configmgr

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.3.16); FILE MERGED 2008/04/01 12:27:21 thb 1.3.16.2: #i85898# Stripping all external header guards 2008/03/31 12:22:43 rt 1.3.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: autoobject.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef CONFIGMGR_AUTOOBJECT_HXX
#define CONFIGMGR_AUTOOBJECT_HXX

#include "utility.hxx"

namespace configmgr
{
////////////////////////////////////////////////////////////////////////////////
    using ::rtl::OUString;

//-----------------------------------------------------------------------------
    template < class Object >
    class AutoObject : Noncopyable
    {
    public:
        typedef Object      object_type;
        typedef Object *    Ptr;
    public:
        AutoObject() : m_pObject(NULL) {}
        AutoObject(Object * _obj) : m_pObject(_obj) {}
        ~AutoObject() { delete m_pObject; }

        bool is()   const;
        Ptr get()   const;
        Ptr getOrCreate();
    private:
        Ptr internalCreate();
    private:
        Ptr  m_pObject;
    };
//-----------------------------------------------------------------------------

    template < class Object >
    inline
    Object * AutoObject<Object>::get() const
    {
        return m_pObject;
    }
//-----------------------------------------------------------------------------

    template < class Object >
    inline
    bool AutoObject<Object>::is() const
    {
        return get() != NULL;
    }
//-----------------------------------------------------------------------------

    template < class Object >
    Object * AutoObject<Object>::getOrCreate()
    {
        Object * p = get();
        return p ? p : internalCreate();
    }
//-----------------------------------------------------------------------------

    template < class Object >
    Object * AutoObject<Object>::internalCreate()
    {
        if (m_pObject == NULL)
            m_pObject = new Object();
        return m_pObject;

    }
//-----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////

} // namespace configmgr

#endif

<|endoftext|>